sync with NetBSD 970112 -moj
authormaja <maja@openbsd.org>
Wed, 15 Jan 1997 23:24:12 +0000 (23:24 +0000)
committermaja <maja@openbsd.org>
Wed, 15 Jan 1997 23:24:12 +0000 (23:24 +0000)
157 files changed:
sys/arch/vax/bi/bi.c [new file with mode: 0644]
sys/arch/vax/bi/bireg.h [new file with mode: 0644]
sys/arch/vax/bi/bivar.h [new file with mode: 0644]
sys/arch/vax/bi/kdb.c [new file with mode: 0644]
sys/arch/vax/bi/kdbreg.h [new file with mode: 0644]
sys/arch/vax/boot/Makefile
sys/arch/vax/boot/autoconf.c
sys/arch/vax/boot/boot.c
sys/arch/vax/boot/bootxx.c
sys/arch/vax/boot/conf.c
sys/arch/vax/boot/consio.c
sys/arch/vax/boot/copy.c
sys/arch/vax/boot/devopen.c
sys/arch/vax/boot/edlabel.c
sys/arch/vax/boot/init.c [deleted file]
sys/arch/vax/boot/ka410.h [new file with mode: 0644]
sys/arch/vax/boot/mfm.c [new file with mode: 0644]
sys/arch/vax/boot/ra.c
sys/arch/vax/boot/rom.c [new file with mode: 0644]
sys/arch/vax/boot/romread.s
sys/arch/vax/boot/samachdep.h [new file with mode: 0644]
sys/arch/vax/boot/scsi_hi.c [new file with mode: 0644]
sys/arch/vax/boot/scsi_low.c [new file with mode: 0644]
sys/arch/vax/boot/sd.c [new file with mode: 0644]
sys/arch/vax/boot/so.h [new file with mode: 0644]
sys/arch/vax/boot/srt0.s
sys/arch/vax/boot/start.s
sys/arch/vax/boot/str.s [new file with mode: 0644]
sys/arch/vax/boot/tmscp.c
sys/arch/vax/boot/vaxstand.h
sys/arch/vax/conf/EVERYTHING [deleted file]
sys/arch/vax/conf/GENERIC
sys/arch/vax/conf/Makefile.vax
sys/arch/vax/conf/files.vax
sys/arch/vax/conf/mkoldconf.awk [deleted file]
sys/arch/vax/conf/std.vax [deleted file]
sys/arch/vax/if/if_de.c
sys/arch/vax/if/if_le.c [new file with mode: 0644]
sys/arch/vax/if/if_qe.c
sys/arch/vax/if/if_uba.c
sys/arch/vax/if/if_uba.h
sys/arch/vax/include/ansi.h
sys/arch/vax/include/aout_machdep.h [new file with mode: 0644]
sys/arch/vax/include/asm.h
sys/arch/vax/include/clock.h [new file with mode: 0644]
sys/arch/vax/include/cpu.h
sys/arch/vax/include/endian.h
sys/arch/vax/include/ka410.h [new file with mode: 0644]
sys/arch/vax/include/ka420.h [new file with mode: 0644]
sys/arch/vax/include/ka43.h [new file with mode: 0644]
sys/arch/vax/include/ka630.h [new file with mode: 0644]
sys/arch/vax/include/ka750.h
sys/arch/vax/include/ka820.h [new file with mode: 0644]
sys/arch/vax/include/macros.h
sys/arch/vax/include/mtpr.h
sys/arch/vax/include/nexus.h
sys/arch/vax/include/param.h
sys/arch/vax/include/pmap.h
sys/arch/vax/include/sid.h
sys/arch/vax/include/trap.h
sys/arch/vax/include/types.h
sys/arch/vax/include/uvax.h [new file with mode: 0644]
sys/arch/vax/include/uvaxII.h [deleted file]
sys/arch/vax/include/vmparam.h
sys/arch/vax/include/vsbus.h [new file with mode: 0644]
sys/arch/vax/mba/hp.c
sys/arch/vax/mba/mba.c
sys/arch/vax/mscp/files.mscp [new file with mode: 0644]
sys/arch/vax/mscp/mscp.c [new file with mode: 0644]
sys/arch/vax/mscp/mscp.h [new file with mode: 0644]
sys/arch/vax/mscp/mscp_disk.c [new file with mode: 0644]
sys/arch/vax/mscp/mscp_subr.c [new file with mode: 0644]
sys/arch/vax/mscp/mscp_tape.c [new file with mode: 0644]
sys/arch/vax/mscp/mscpreg.h [new file with mode: 0644]
sys/arch/vax/mscp/mscpvar.h [new file with mode: 0644]
sys/arch/vax/stand/Makefile
sys/arch/vax/stand/autoconf.c
sys/arch/vax/stand/boot.c
sys/arch/vax/stand/bootxx.c
sys/arch/vax/stand/conf.c
sys/arch/vax/stand/consio.c
sys/arch/vax/stand/copy.c
sys/arch/vax/stand/devopen.c
sys/arch/vax/stand/edlabel.c
sys/arch/vax/stand/init.c [deleted file]
sys/arch/vax/stand/ka410.h [new file with mode: 0644]
sys/arch/vax/stand/mfm.c [new file with mode: 0644]
sys/arch/vax/stand/ra.c
sys/arch/vax/stand/rom.c [new file with mode: 0644]
sys/arch/vax/stand/romread.s
sys/arch/vax/stand/samachdep.h [new file with mode: 0644]
sys/arch/vax/stand/scsi_hi.c [new file with mode: 0644]
sys/arch/vax/stand/scsi_low.c [new file with mode: 0644]
sys/arch/vax/stand/sd.c [new file with mode: 0644]
sys/arch/vax/stand/so.h [new file with mode: 0644]
sys/arch/vax/stand/srt0.s
sys/arch/vax/stand/start.s
sys/arch/vax/stand/str.s [new file with mode: 0644]
sys/arch/vax/stand/tmscp.c
sys/arch/vax/stand/vaxstand.h
sys/arch/vax/uba/dhu.c
sys/arch/vax/uba/dz.c
sys/arch/vax/uba/qd.c [new file with mode: 0644]
sys/arch/vax/uba/qv.c [new file with mode: 0644]
sys/arch/vax/uba/tmscp.c [deleted file]
sys/arch/vax/uba/tmscpreg.h [deleted file]
sys/arch/vax/uba/ts.c
sys/arch/vax/uba/uba.c
sys/arch/vax/uba/ubareg.h
sys/arch/vax/uba/ubavar.h
sys/arch/vax/uba/uda.c
sys/arch/vax/uba/udareg.h
sys/arch/vax/vax/autoconf.c
sys/arch/vax/vax/clock.c
sys/arch/vax/vax/conf.c
sys/arch/vax/vax/crl.c
sys/arch/vax/vax/ctu.c
sys/arch/vax/vax/db_disasm.c
sys/arch/vax/vax/db_machdep.c
sys/arch/vax/vax/disksubr.c
sys/arch/vax/vax/dzcons.c [new file with mode: 0644]
sys/arch/vax/vax/gencons.c
sys/arch/vax/vax/in_cksum.c
sys/arch/vax/vax/intvec.s
sys/arch/vax/vax/ka410.c [new file with mode: 0644]
sys/arch/vax/vax/ka43.c [new file with mode: 0644]
sys/arch/vax/vax/ka630.c [new file with mode: 0644]
sys/arch/vax/vax/ka650.c
sys/arch/vax/vax/ka750.c
sys/arch/vax/vax/ka780.c
sys/arch/vax/vax/ka820.c [new file with mode: 0644]
sys/arch/vax/vax/ka860.c
sys/arch/vax/vax/locore.c
sys/arch/vax/vax/machdep.c
sys/arch/vax/vax/mscp.c [deleted file]
sys/arch/vax/vax/mscp.h [deleted file]
sys/arch/vax/vax/mscpvar.h [deleted file]
sys/arch/vax/vax/ns_cksum.c
sys/arch/vax/vax/pmap.c
sys/arch/vax/vax/random.s
sys/arch/vax/vax/rootfil.c
sys/arch/vax/vax/sbi.c
sys/arch/vax/vax/swapgeneric.c
sys/arch/vax/vax/tmscpinf.h [deleted file]
sys/arch/vax/vax/trap.c
sys/arch/vax/vax/uvax.c [new file with mode: 0644]
sys/arch/vax/vax/uvaxII.c
sys/arch/vax/vax/uvax_proto.c [new file with mode: 0644]
sys/arch/vax/vax/vm_machdep.c
sys/arch/vax/vsa/dc.c [new file with mode: 0644]
sys/arch/vax/vsa/dc7085cons.h [new file with mode: 0644]
sys/arch/vax/vsa/hdc9224.c [new file with mode: 0644]
sys/arch/vax/vsa/hdc9224.h [new file with mode: 0644]
sys/arch/vax/vsa/lk201.c [new file with mode: 0644]
sys/arch/vax/vsa/ncr.c [new file with mode: 0644]
sys/arch/vax/vsa/ncr.h [new file with mode: 0644]
sys/arch/vax/vsa/vsbus.c [new file with mode: 0644]

diff --git a/sys/arch/vax/bi/bi.c b/sys/arch/vax/bi/bi.c
new file mode 100644 (file)
index 0000000..cfb0171
--- /dev/null
@@ -0,0 +1,148 @@
+/*     $NetBSD: bi.c,v 1.4 1996/10/13 03:34:44 christos Exp $ */
+/*
+ * Copyright (c) 1996 Ludd, University of Lule}, Sweden.
+ * 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 at Ludd, University of 
+ *      Lule}, Sweden and its contributors.
+ * 4. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+
+/*
+ * VAXBI specific routines.
+ */
+/*
+ * TODO
+ *   handle BIbus errors more gracefully.
+ */
+
+#include <sys/param.h>
+#include <sys/device.h>
+
+#include <machine/mtpr.h>
+#include <machine/nexus.h>
+#include <machine/cpu.h>
+
+#include <arch/vax/bi/bireg.h>
+#include <arch/vax/bi/bivar.h>
+
+static int bi_match __P((struct device *, void *, void *));
+static void bi_attach __P((struct device *, struct device *, void*));
+static int bi_print __P((void *, const char *));
+
+struct cfdriver bi_cd = {
+       NULL, "bi", DV_DULL
+};
+
+struct cfattach bi_ca = {
+       sizeof(struct bi_softc), bi_match, bi_attach
+};
+
+struct bi_list bi_list[] = {
+       {BIDT_MS820, 1, "ms820"},
+       {BIDT_DRB32, 0, "drb32"},
+       {BIDT_DWBUA, 0, "dwbua"},
+       {BIDT_KLESI, 0, "klesi"},
+       {BIDT_KA820, 1, "ka820"},
+       {BIDT_DB88,  0, "db88"},
+       {BIDT_CIBCA, 0, "cibca"},
+       {BIDT_DMB32, 0, "dmb32"},
+       {BIDT_CIBCI, 0, "cibci"},
+       {BIDT_KA800, 0, "ka800"},
+       {BIDT_KDB50, 0, "kdb50"},
+       {BIDT_DWMBA, 0, "dwmba"},
+       {BIDT_KFBTA, 0, "kfbta"},
+       {BIDT_DEBNK, 0, "debnk"},
+       {BIDT_DEBNA, 0, "debna"},
+       {0,0,0}
+};
+
+int
+bi_print(aux, name)
+       void *aux;
+       const char *name;
+{
+       struct bi_attach_args *ba = aux;
+       struct bi_list *bl;
+
+       if (name) {
+               for (bl = &bi_list[0]; bl->bl_nr; bl++)
+                       if (bl->bl_nr == ba->ba_node->biic.bi_dtype) {
+                               printf(bl->bl_name);
+                               break;
+                       }
+               if (bl->bl_nr == 0)
+                       printf("unknown device 0x%x",
+                           ba->ba_node->biic.bi_dtype);
+               printf(" at %s", name);
+       }
+       printf(" node %d", ba->ba_nodenr);
+       return bl->bl_havedriver ? UNCONF : UNSUPP;
+}
+
+int
+bi_match(parent, match, aux)
+       struct device *parent;
+       void *match, *aux;
+{
+       struct bp_conf *bp = aux;
+
+       if (strcmp(bp->type, "bi"))
+               return 0;
+       return 1;
+}
+
+void
+bi_attach(parent, self, aux)
+       struct device  *parent, *self;
+       void *aux;
+{
+       struct bp_conf *bp = aux;
+       struct bi_softc *bi = (void *)self;
+       struct bi_node *binode;
+       struct bi_attach_args ba;
+       int nodenr;
+
+       printf("\n");
+       binode = bi->bi_base = (struct bi_node *)bp->bp_addr;
+
+       ba.ba_intcpu = 1 << mastercpu;
+       for (nodenr = 0; nodenr < NNODEBI; nodenr++) {
+               if (badaddr((caddr_t)&binode[nodenr], 4))
+                       continue;
+
+               ba.ba_node = &binode[nodenr];
+               ba.ba_nodenr = nodenr;
+               config_found(self, &ba, bi_print);
+       }
+}
+
+void
+bi_buserr()
+{
+       panic("bi_buserr");
+}
diff --git a/sys/arch/vax/bi/bireg.h b/sys/arch/vax/bi/bireg.h
new file mode 100644 (file)
index 0000000..1663e16
--- /dev/null
@@ -0,0 +1,245 @@
+/*     $NetBSD: bireg.h,v 1.1 1996/07/19 14:26:53 ragge Exp $  */
+/*
+ * Copyright (c) 1988 Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * 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.
+ *
+ *     @(#)bireg.h     7.3 (Berkeley) 6/28/90
+ */
+
+/*
+ * VAXBI node definitions.
+ */
+
+/*
+ * BI node addresses
+ */
+#define        BI_BASE(bi)     (0x20000000 + (bi) * 0x2000000)
+#define        MAXNBI          16      /* Spec says there can be 16 anyway */
+#define        NNODEBI         16      /* 16 nodes per BI */
+
+#define        BI_PROBE        0x80000 /* CPU on 8200, NBIA on 8800 */
+/*
+ * BI nodes all start with BI interface registers (those on the BIIC chip).
+ * These are followed with interface-specific registers.
+ *
+ * NB: This structure does NOT include the four GPRs (not anymore!)
+ */
+struct biiregs {
+       u_short bi_dtype;       /* device type */
+       u_short bi_revs;        /* revisions */
+       u_long  bi_csr;         /* control and status register */
+       u_long  bi_ber;         /* bus error register */
+       u_long  bi_eintrcsr;    /* error interrupt control register */
+       u_long  bi_intrdes;     /* interrupt destination register */
+                               /* the rest are not required for all nodes */
+       u_long  bi_ipintrmsk;   /* IP interrupt mask register */
+       u_long  bi_fipsdes;     /* Force-Bit IPINTR/STOP destination reg */
+       u_long  bi_ipintrsrc;   /* IPINTR source register */
+       u_long  bi_sadr;        /* starting address register */
+       u_long  bi_eadr;        /* ending address register */
+       u_long  bi_bcicsr;      /* BCI control and status register */
+       u_long  bi_wstat;       /* write status register */
+       u_long  bi_fipscmd;     /* Force-Bit IPINTR/STOP command reg */
+       u_long  bi_xxx1[3];     /* unused */
+       u_long  bi_uintrcsr;    /* user interface interrupt control reg */
+       u_long  bi_xxx2[43];    /* unused */
+/* although these are on the BIIC, their interpretation varies */
+/*     u_long  bi_gpr[4]; */   /* general purpose registers */
+};
+
+/*
+ * A generic BI node.
+ */
+struct bi_node {
+       struct  biiregs biic;   /* interface */
+       u_long  bi_xxx[1988];   /* pad to 8K */
+};
+
+/*
+ * A cpu node.
+ */
+struct bi_cpu {
+       struct  biiregs biic;   /* interface chip */
+       u_long  bi_gpr[4];      /* gprs (unused) */
+       u_long  bi_sosr;        /* slave only status register */
+       u_long  bi_xxx[63];     /* pad */
+       u_long  bi_rxcd;        /* receive console data register */
+};
+
+/* device types */
+#define        BIDT_MS820      0x0001  /* MS820 memory board */
+#define        BIDT_DRB32      0x0101  /* DRB32 Supercomputer gateway */
+#define        BIDT_DWBUA      0x0102  /* DWBUA Unibus adapter */
+#define        BIDT_KLESI      0x0103  /* KLESI-B adapter */
+#define        BIDT_KA820      0x0105  /* KA820 cpu */
+#define        BIDT_DB88       0x0106  /* DB88 adapter */
+#define        BIDT_CIBCA      0x0108  /* Computer Interconnect adapter */
+#define        BIDT_DMB32      0x0109  /* DMB32 adapter */
+#define        BIDT_CIBCI      0x010b  /* Computer Interconnect adapter (old) */
+#define        BIDT_KA800      0x010c  /* KA800 slave processor */
+#define        BIDT_KDB50      0x010e  /* KDB50 disk controller */
+#define        BIDT_DWMBA      0x2107  /* XMI - BI adapter */
+#define        BIDT_KFBTA      0x410d  /* RD/RX disk controller */
+#define        BIDT_DEBNK      0x410e  /* BI Ethernet (Lance) + TK50 */
+#define        BIDT_DEBNA      0x410f  /* BI Ethernet (Lance) adapter */
+
+/* bits in bi_csr */
+#define        BICSR_IREV(x)   ((u_char)((x) >> 24))   /* VAXBI interface rev */
+#define        BICSR_TYPE(x)   ((u_char)((x) >> 16))   /* BIIC type */
+#define        BICSR_HES       0x8000          /* hard error summary */
+#define        BICSR_SES       0x4000          /* soft error summary */
+#define        BICSR_INIT      0x2000          /* initialise node */
+#define        BICSR_BROKE     0x1000          /* broke */
+#define        BICSR_STS       0x0800          /* self test status */
+#define        BICSR_NRST      0x0400          /* node reset */
+#define        BICSR_UWP       0x0100          /* unlock write pending */
+#define        BICSR_HEIE      0x0080          /* hard error interrupt enable */
+#define        BICSR_SEIE      0x0040          /* soft error interrupt enable */
+#define        BICSR_ARB_MASK  0x0030          /* mask to get arbitration codes */
+#define        BICSR_ARB_NONE  0x0030          /* no arbitration */
+#define        BICSR_ARB_LOG   0x0020          /* low priority */
+#define        BICSR_ARB_HIGH  0x0010          /* high priority */
+#define        BICSR_ARB_RR    0x0000          /* round robin */
+#define        BICSR_NODEMASK  0x000f          /* node ID */
+
+#define        BICSR_BITS \
+"\20\20HES\17SES\16INIT\15BROKE\14STS\13NRST\11UWP\10HEIE\7SEIE"
+
+/* bits in bi_ber */
+#define        BIBER_MBZ       0x8000fff0
+#define        BIBER_NMR       0x40000000      /* no ack to multi-responder command */
+#define        BIBER_MTCE      0x20000000      /* master transmit check error */
+#define        BIBER_CTE       0x10000000      /* control transmit error */
+#define        BIBER_MPE       0x08000000      /* master parity error */
+#define        BIBER_ISE       0x04000000      /* interlock sequence error */
+#define        BIBER_TDF       0x02000000      /* transmitter during fault */
+#define        BIBER_IVE       0x01000000      /* ident vector error */
+#define        BIBER_CPE       0x00800000      /* command parity error */
+#define        BIBER_SPE       0x00400000      /* slave parity error */
+#define        BIBER_RDS       0x00200000      /* read data substitute */
+#define        BIBER_RTO       0x00100000      /* retry timeout */
+#define        BIBER_STO       0x00080000      /* stall timeout */
+#define        BIBER_BTO       0x00040000      /* bus timeout */
+#define        BIBER_NEX       0x00020000      /* nonexistent address */
+#define        BIBER_ICE       0x00010000      /* illegal confirmation error */
+#define        BIBER_UPEN      0x00000008      /* user parity enable */
+#define        BIBER_IPE       0x00000004      /* ID parity error */
+#define        BIBER_CRD       0x00000002      /* corrected read data */
+#define        BIBER_NPE       0x00000001      /* null bus parity error */
+#define        BIBER_HARD      0x4fff0000
+
+#define        BIBER_BITS \
+"\20\37NMR\36MTCE\35CTE\34MPE\33ISE\32TDF\31IVE\30CPE\
+\27SPE\26RDS\25RTO\24STO\23BTO\22NEX\21ICE\4UPEN\3IPE\2CRD\1NPE"
+
+/* bits in bi_eintrcsr */
+#define        BIEIC_INTRAB    0x01000000      /* interrupt abort */
+#define        BIEIC_INTRC     0x00800000      /* interrupt complete */
+#define        BIEIC_INTRSENT  0x00200000      /* interrupt command sent */
+#define        BIEIC_INTRFORCE 0x00100000      /* interrupt force */
+#define        BIEIC_LEVELMASK 0x000f0000      /* mask for interrupt levels */
+#define        BIEIC_IPL17     0x00080000      /* ipl 0x17 */
+#define        BIEIC_IPL16     0x00040000      /* ipl 0x16 */
+#define        BIEIC_IPL15     0x00020000      /* ipl 0x15 */
+#define        BIEIC_IPL14     0x00010000      /* ipl 0x14 */
+#define        BIEIC_VECMASK   0x00003ffc      /* vector mask for error intr */
+
+/* bits in bi_intrdes */
+#define        BIDEST_MASK     0x0000ffff      /* one bit per node to be intr'ed */
+
+/* bits in bi_ipintrmsk */
+#define        BIIPINTR_MASK   0xffff0000      /* one per node to allow to ipintr */
+
+/* bits in bi_fipsdes */
+#define        BIFIPSD_MASK    0x0000ffff
+
+/* bits in bi_ipintrsrc */
+#define        BIIPSRC_MASK    0xffff0000
+
+/* sadr and eadr are simple addresses */
+
+/* bits in bi_bcicsr */
+#define        BCI_BURSTEN     0x00020000      /* burst mode enable */
+#define        BCI_IPSTOP_FRC  0x00010000      /* ipintr/stop force */
+#define        BCI_MCASTEN     0x00008000      /* multicast space enable */
+#define        BCI_BCASTEN     0x00004000      /* broadcast enable */
+#define        BCI_STOPEN      0x00002000      /* stop enable */
+#define        BCI_RSRVDEN     0x00001000      /* reserved enable */
+#define        BCI_IDENTEN     0x00000800      /* ident enable */
+#define        BCI_INVALEN     0x00000400      /* inval enable */
+#define        BCI_WINVEN      0x00000200      /* write invalidate enable */
+#define        BCI_UINTEN      0x00000100      /* user interface csr space enable */
+#define        BCI_BIICEN      0x00000080      /* BIIC csr space enable */
+#define        BCI_INTEN       0x00000040      /* interrupt enable */
+#define        BCI_IPINTEN     0x00000020      /* ipintr enable */
+#define        BCI_PIPEEN      0x00000010      /* pipeline NXT enable */
+#define        BCI_RTOEVEN     0x00000008      /* read timeout EV enable */
+
+#define        BCI_BITS \
+"\20\22BURSTEN\21IPSTOP_FRC\20MCASTEN\
+\17BCASTEN\16STOPEN\15RSRVDEN\14IDENTEN\13INVALEN\12WINVEN\11UINTEN\
+\10BIICEN\7INTEN\6IPINTEN\5PIPEEN\4RTOEVEN"
+
+/* bits in bi_wstat */
+#define        BIW_GPR3        0x80000000      /* gpr 3 was written */
+#define        BIW_GPR2        0x40000000      /* gpr 2 was written */
+#define        BIW_GPR1        0x20000000      /* gpr 1 was written */
+#define        BIW_GPR0        0x10000000      /* gpr 0 was written */
+
+/* bits in force-bit ipintr/stop command register 8/
+#define        BIFIPSC_CMDMASK 0x0000f000      /* command */
+#define        BIFIPSC_MIDEN   0x00000800      /* master ID enable */
+
+/* bits in bi_uintcsr */
+#define        BIUI_INTAB      0xf0000000      /* interrupt abort level */
+#define        BIUI_INTC       0x0f000000      /* interrupt complete bits */
+#define        BIUI_SENT       0x00f00000      /* interrupt sent bits */
+#define        BIUI_FORCE      0x000f0000      /* force interrupt level */
+#define        BIUI_EVECEN     0x00008000      /* external vector enable */
+#define        BIUI_VEC        0x00003ffc      /* interrupt vector */
+
+/* tell if a bi device is a slave (hence has SOSR) */
+#define        BIDT_ISSLAVE(x) (((x) & 0x7f00) == 0)
+
+/* bits in bi_sosr */
+#define        BISOSR_MEMSIZE  0x1ffc0000      /* memory size */
+#define        BISOSR_BROKE    0x00001000      /* broke */
+
+/* bits in bi_rxcd */
+#define        BIRXCD_BUSY2    0x80000000      /* busy 2 */
+#define        BIRXCD_NODE2    0x0f000000      /* node id 2 */
+#define        BIRXCD_CHAR2    0x00ff0000      /* character 2 */
+#define        BIRXCD_BUSY1    0x00008000      /* busy 1 */
+#define        BIRXCD_NODE1    0x00000f00      /* node id 1 */
+#define        BIRXCD_CHAR1    0x000000ff      /* character 1 */
diff --git a/sys/arch/vax/bi/bivar.h b/sys/arch/vax/bi/bivar.h
new file mode 100644 (file)
index 0000000..bb6d397
--- /dev/null
@@ -0,0 +1,59 @@
+/*     $NetBSD: bivar.h,v 1.1 1996/07/19 14:26:54 ragge Exp $ */
+/*
+ * Copyright (c) 1996 Ludd, University of Lule}, Sweden.
+ * 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 at Ludd, University of 
+ *      Lule}, Sweden and its contributors.
+ * 4. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+
+/*
+ * per-BI-adapter state.
+ */
+struct bi_softc {
+        struct device bi_dev;
+        struct bi_node *bi_base;
+};
+
+/*
+ * Struct used for autoconfiguration; attaching of BI nodes.
+ */
+struct bi_attach_args {
+        struct bi_node *ba_node;
+        int ba_nodenr;
+       int ba_intcpu;  /* Mask of which cpus to interrupt */
+};
+
+/*
+ * BI node list.
+ */
+struct bi_list {
+       u_short bl_nr;          /* Unit ID# */
+       u_short bl_havedriver;  /* Have device driver */
+       char *bl_name;          /* DEC name */
+};
diff --git a/sys/arch/vax/bi/kdb.c b/sys/arch/vax/bi/kdb.c
new file mode 100644 (file)
index 0000000..13f8f4f
--- /dev/null
@@ -0,0 +1,313 @@
+/*     $NetBSD: kdb.c,v 1.5 1997/01/11 11:34:39 ragge Exp $ */
+/*
+ * Copyright (c) 1996 Ludd, University of Lule}, Sweden.
+ * 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 at Ludd, University of 
+ *      Lule}, Sweden and its contributors.
+ * 4. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * KDB50 disk device driver
+ */
+/*
+ * TODO
+ *   Implement node reset routine.
+ *   Nices hardware error handling.
+ */
+
+#include <sys/param.h>
+#include <sys/kernel.h>
+#include <sys/buf.h>
+#include <sys/device.h>
+#include <sys/proc.h>
+#include <sys/malloc.h>
+
+#include <vm/vm.h>
+#include <vm/vm_kern.h>
+
+#include <machine/sid.h>
+#include <machine/pte.h>
+#include <machine/pcb.h>
+#include <machine/trap.h>
+#include <machine/scb.h>
+
+#include <vax/bi/bireg.h>
+#include <vax/bi/bivar.h>
+#include <vax/bi/kdbreg.h>
+
+#include <vax/mscp/mscp.h>
+#include <vax/mscp/mscpvar.h>
+#include <vax/mscp/mscpreg.h>
+
+#define     b_forw  b_hash.le_next
+/*
+ * Software status, per controller.
+ */
+struct kdb_softc {
+       struct  device sc_dev;          /* Autoconfig info */
+       struct  ivec_dsp sc_ivec;       /* Interrupt vector handler */
+       struct  mscp_pack sc_kdb;       /* Struct for kdb communication */
+       struct  mscp_softc *sc_softc;   /* MSCP info (per mscpvar.h) */
+       struct  kdb_regs *sc_kr;        /* KDB controller registers */
+       struct  mscp *sc_mscp;          /* Keep pointer to active mscp */
+};
+
+int    kdbmatch __P((struct device *, void *, void *));
+void   kdbattach __P((struct device *, struct device *, void *));
+void   kdbreset __P((int));
+void   kdbintr __P((int));
+void   kdbctlrdone __P((struct device *, int));
+int    kdbprint __P((void *, const char *));
+void   kdbsaerror __P((struct device *, int));
+int    kdbgo __P((struct device *, struct buf *));
+
+struct cfdriver kdb_cd = {
+       NULL, "kdb", DV_DULL
+};
+
+struct cfattach kdb_ca = {
+       sizeof(struct kdb_softc), kdbmatch, kdbattach
+};
+
+/*
+ * More driver definitions, for generic MSCP code.
+ */
+struct mscp_ctlr kdb_mscp_ctlr = {
+       kdbctlrdone,
+       kdbgo,
+       kdbsaerror,
+};
+
+int
+kdbprint(aux, name)
+       void    *aux;
+       const char      *name;
+{
+       if (name)
+               printf("%s: mscpbus", name);
+       return UNCONF;
+}
+
+/*
+ * Poke at a supposed KDB to see if it is there.
+ */
+int
+kdbmatch(parent, match, aux)
+       struct  device *parent;
+       void    *match, *aux;
+{
+       struct  cfdata *cf = match;
+       struct bi_attach_args *ba = aux;
+
+        if (ba->ba_node->biic.bi_dtype != BIDT_KDB50)
+                return 0;
+
+        if (cf->cf_loc[0] != -1 && cf->cf_loc[0] != ba->ba_nodenr)
+                return 0;
+
+        return 1;
+}
+
+void
+kdbattach(parent, self, aux)
+       struct device *parent, *self;
+       void *aux;
+{
+       struct  kdb_softc *sc = (void *)self;
+       struct  bi_attach_args *ba = aux;
+       struct  mscp_attach_args ma;
+       extern  struct ivec_dsp idsptch;
+       volatile int i = 10000;
+
+       printf("\n");
+       bcopy(&idsptch, &sc->sc_ivec, sizeof(struct ivec_dsp));
+       scb->scb_nexvec[1][ba->ba_nodenr] = &sc->sc_ivec;
+       sc->sc_ivec.hoppaddr = kdbintr;
+       sc->sc_ivec.pushlarg = self->dv_unit;
+       sc->sc_kr = (void *)ba->ba_node;
+
+       bzero(&sc->sc_kdb, sizeof (struct mscp_pack));
+
+       ma.ma_mc = &kdb_mscp_ctlr;
+       ma.ma_type = MSCPBUS_DISK|MSCPBUS_KDB;
+       ma.ma_uuda = (struct mscp_pack *)kvtophys(&sc->sc_kdb);
+       ma.ma_uda = &sc->sc_kdb;
+       ma.ma_ip = &sc->sc_kr->kdb_ip;
+       ma.ma_sa = &sc->sc_kr->kdb_sa;
+       ma.ma_sw = &sc->sc_kr->kdb_sw;
+       ma.ma_softc = &sc->sc_softc;
+       ma.ma_ivec = (int)&scb->scb_nexvec[1][ba->ba_nodenr] - (int)scb;
+       ma.ma_ctlrnr = ba->ba_nodenr;
+       sc->sc_kr->kdb_bi.bi_csr |= BICSR_NRST;
+       while (i--) /* Need delay??? */
+               ;
+       sc->sc_kr->kdb_bi.bi_intrdes = ba->ba_intcpu;
+       sc->sc_kr->kdb_bi.bi_bcicsr |= BCI_STOPEN | BCI_IDENTEN | BCI_UINTEN |
+           BCI_INTEN;
+       sc->sc_kr->kdb_bi.bi_uintrcsr = ma.ma_ivec;
+       config_found(&sc->sc_dev, &ma, kdbprint);
+}
+
+int
+kdbgo(usc, bp)
+       struct device *usc;
+       struct buf *bp;
+{
+       struct kdb_softc *sc = (void *)usc;
+       struct mscp_softc *mi = sc->sc_softc;
+       struct mscp *mp = (void *)bp->b_actb;
+        struct  pcb *pcb;
+        pt_entry_t *pte;
+        int     pfnum, npf, o, i;
+       unsigned info = 0;
+        caddr_t addr;
+
+       o = (int)bp->b_un.b_addr & PGOFSET;
+       npf = btoc(bp->b_bcount + o) + 1;
+       addr = bp->b_un.b_addr;
+
+        /*
+         * Get a pointer to the pte pointing out the first virtual address.
+         * Use different ways in kernel and user space.
+         */
+        if ((bp->b_flags & B_PHYS) == 0) {
+                pte = kvtopte(addr);
+        } else {
+                pcb = bp->b_proc->p_vmspace->vm_pmap.pm_pcb;
+                pte = uvtopte(addr, pcb);
+        }
+
+        /*
+         * When we are doing DMA to user space, be sure that all pages
+         * we want to transfer to is mapped. WHY DO WE NEED THIS???
+         * SHOULDN'T THEY ALWAYS BE MAPPED WHEN DOING THIS???
+         */
+        for (i = 0; i < (npf - 1); i++) {
+                if ((pte + i)->pg_pfn == 0) {
+                        int rv;
+                        rv = vm_fault(&bp->b_proc->p_vmspace->vm_map,
+                            (unsigned)addr + i * NBPG,
+                            VM_PROT_READ|VM_PROT_WRITE, FALSE);
+                        if (rv)
+                                panic("KDB DMA to nonexistent page, %d", rv);
+                }
+        }
+       /*
+        * pte's for userspace isn't necessary positioned
+        * in consecutive physical pages. We check if they 
+        * are, otherwise we need to copy the pte's to a
+        * physically contigouos page area.
+        * XXX some copying here may be unneccessary. Subject to fix.
+        */
+       if (bp->b_flags & B_PHYS) {
+               int i = kvtophys(pte);
+               unsigned k;
+
+               if (trunc_page(i) != trunc_page(kvtophys(pte) + npf * 4)) {
+                       info = (unsigned)malloc(2 * NBPG, M_DEVBUF, M_WAITOK);
+                       k = (info + PGOFSET) & ~PGOFSET;
+                       bcopy(pte, (void *)k, NBPG);
+                       i = kvtophys(k);
+               }
+               mp->mscp_seq.seq_mapbase = i;
+       } else
+               mp->mscp_seq.seq_mapbase = (unsigned)pte;
+       mscp_dgo(mi, KDB_MAP | o, info, bp);
+       return 1;
+}
+
+void
+kdbsaerror(usc, doreset)
+       struct device *usc;
+       int doreset;
+{
+       struct  kdb_softc *sc = (void *)usc;
+       register int code = sc->sc_kr->kdb_sa;
+
+       if ((code & MP_ERR) == 0)
+               return;
+       printf("%s: controller error, sa=0x%x\n", sc->sc_dev.dv_xname, code);
+       /* What to do now??? */
+}
+
+/*
+ * Interrupt routine.  Depending on the state of the controller,
+ * continue initialisation, or acknowledge command and response
+ * interrupts, and process responses.
+ */
+void
+kdbintr(ctlr)
+       int     ctlr;
+{
+       struct kdb_softc *sc = kdb_cd.cd_devs[ctlr];
+       struct  uba_softc *uh;
+       struct mscp_pack *ud;
+
+       if (sc->sc_kr->kdb_sa & MP_ERR) {       /* ctlr fatal error */
+               kdbsaerror(&sc->sc_dev, 1);
+               return;
+       }
+       mscp_intr(sc->sc_softc);
+}
+
+#ifdef notyet
+/*
+ * The KDB50 has been reset.  Reinitialise the controller
+ * and requeue outstanding I/O.
+ */
+void
+kdbreset(ctlr)
+       int ctlr;
+{
+       register struct kdb_softc *sc;
+
+       sc = kdb_cd.cd_devs[ctlr];
+       printf(" kdb%d", ctlr);
+
+
+       /* reset queues and requeue pending transfers */
+       mscp_requeue(sc->sc_softc);
+
+       /*
+        * If it fails to initialise we will notice later and
+        * try again (and again...).  Do not call kdbstart()
+        * here; it will be done after the controller finishes
+        * initialisation.
+        */
+       if (kdbinit(sc))
+               printf(" (hung)");
+}
+#endif
+
+void
+kdbctlrdone(usc, info)
+       struct device *usc;
+       int info;
+{
+       if (info)
+               free((void *)info, NBPG * 2);
+}
diff --git a/sys/arch/vax/bi/kdbreg.h b/sys/arch/vax/bi/kdbreg.h
new file mode 100644 (file)
index 0000000..95ed954
--- /dev/null
@@ -0,0 +1,64 @@
+/*     $NetBSD: kdbreg.h,v 1.1 1996/07/19 14:26:56 ragge Exp $ */
+/*
+ * Copyright (c) 1988 Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * 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.
+ *
+ *     @(#)kdbreg.h    7.3 (Berkeley) 6/28/90
+ */
+
+/*
+ * The KDB50 registers are embedded inside the bi interface
+ * general-purpose registers.
+ */
+struct kdb_regs {
+       struct  biiregs kdb_bi;
+       short   kdb_xxx;        /* first half of GPR 0 unused */
+       short   kdb_ip;         /* initialisation and polling */
+       short   kdb_sa;         /* status & address (r/o half) */
+       short   kdb_sw;         /* status & address (w/o half) */
+};
+
+#define KDBSR_BITS \
+"\20\20ERR\17STEP4\16STEP3\15STEP2\14STEP1\13oldNV\12oldQB\11DI\10IE\1GO"
+
+/*
+ * Asserting KDB_MAP in values placed in mscp_seq.seq_buffer tells
+ * the KDB to use mscp_seq.seq_mapbase as a set of PTEs and seq_buffer
+ * as an offset value.  Hence we need no mappings; the KDB50 reads
+ * the hardware page tables directly.  (Without KDB_MAP, seq_bufer
+ * represents the physical memory address instead, and seq_mapbase is
+ * unused.)
+ */
+#define        KDB_MAP         0x80000000
+#define        KDB_PHYS        0               /* pseudo flag */
index f2ac372..b9a0cb4 100644 (file)
@@ -1,28 +1,29 @@
-#      $OpenBSD: Makefile,v 1.6 1996/09/27 18:38:04 maja Exp $
-#      $NetBSD: Makefile,v 1.9 1996/03/16 11:03:12 ragge Exp $
+#      $OpenBSD: Makefile,v 1.7 1997/01/15 23:24:15 maja Exp $
+#      $NetBSD: Makefile,v 1.11 1996/10/18 06:10:18 thorpej Exp $
 #
 
 INCPATH=-I. -I../../.. -I../.. -I../../../lib/libsa
-.PATH: ${.CURDIR}/../../../lib/libkern
 
 CC=    cc
 AS=    as
 
 S=      ../../..
 RELOC= 100000
-CFLAGS+=-O ${INCPATH} -DSTANDALONE -DRELOC=0x${RELOC} -D_VAX_INLINE_
+XXRPB= 0F4240
+CFLAGS+=-O ${INCPATH} -DSTANDALONE -DRELOC=0x${RELOC} \
+       -D_VAX_INLINE_ -DXXRPB=0x$(XXRPB)
 
-DEVS=  autoconf.o hp.o ra.o tmscp.o ctu.o
-
-LIBKERN=libkern.a
-KERNOBJ=__main.o strlen.o strcmp.o strncmp.o strncpy.o min.o strcpy.o
+DEVS=  autoconf.o hp.o ra.o tmscp.o ctu.o mfm.o rom.o romread.o \
+       scsi_low.o scsi_hi.o sd.o
 
 .include "$S/lib/libsa/Makefile.inc"
 LIBSA=         ${SALIB}
 
-all:   xxboot boot copy edlabel
+SVAX=  consio.o urem.o udiv.o str.o
+
+all:   ${LIBSA} xxboot boot copy edlabel
 
-libsvax.a: consio.o urem.o udiv.o
+libsvax.a: ${SVAX}
        ar crv $@ $?
        ranlib $@
 
@@ -32,6 +33,9 @@ urem.o:       ../vax/urem.s
 udiv.o:        ../vax/udiv.s
        ${CC} -x assembler-with-cpp -E ../vax/udiv.s | as -o udiv.o
 
+str.o: str.s
+       ${CC} -x assembler-with-cpp -E str.s | as -o str.o
+
 # startups
 
 start.o: start.s
@@ -42,29 +46,29 @@ srt0.o:     srt0.s
 
 # 
 
-xxboot:        start.o bootxx.o romread.o ${LIBSA} ${LIBKERN} libsvax.a 
+xxboot:        start.o bootxx.o romread.o libsvax.a 
        ld -N -Ttext ${RELOC} -o a.out start.o bootxx.o romread.o \
-       ${LIBSA} ${LIBKERN} libsvax.a
+       ${LIBSA} libsvax.a
        @strip a.out
        @size a.out
        @dd if=a.out of=xxboot bs=32 skip=1
        @rm -f a.out
 
-boot:  boot.o srt0.o devopen.o conf.o ${DEVS} ${LIBKERN} ${LIBSA} libsvax.a
+boot:  boot.o srt0.o devopen.o conf.o ${DEVS} libsvax.a
        ld -N -Ttext ${RELOC} -e nisse -o $@ srt0.o devopen.o boot.o \
-       conf.o ${DEVS} ${LIBSA} ${LIBKERN} libsvax.a
+       conf.o ${DEVS} ${LIBSA} libsvax.a
        @strip boot
        @size boot
 
-edlabel: edlabel.o srt0.o devopen.o conf.o ${DEVS} ${LIBKERN} ${LIBSA} libsvax.a
+edlabel: edlabel.o srt0.o devopen.o conf.o ${DEVS} libsvax.a
        ld -N -Ttext ${RELOC} -e nisse -o $@ srt0.o devopen.o edlabel.o\
-       conf.o ${DEVS} ${LIBSA} ${LIBKERN} libsvax.a
+       conf.o ${DEVS} ${LIBSA} libsvax.a
        @strip edlabel
        @size edlabel
 
-copy:  copy.o srt0.o devopen.o conf.o ${DEVS} ${LIBKERN} ${LIBSA} libsvax.a
+copy:  copy.o srt0.o devopen.o conf.o ${DEVS} libsvax.a
        ld -N -Ttext ${RELOC} -e nisse -o $@ srt0.o devopen.o copy.o \
-       conf.o ${DEVS} ${LIBSA} ${LIBKERN} libsvax.a
+       conf.o ${DEVS} ${LIBSA} libsvax.a
        @strip copy
        @size copy
 
@@ -97,15 +101,11 @@ init.o:    init.c
 bootxx.o: bootxx.c 
        ${CC} -c ${CFLAGS} $*.c
 
-#
-libkern.a: ${KERNOBJ}
-       @echo Creating standalone kern library
-       @ar rv libkern.a `lorder ${KERNOBJ} | tsort`
-
 #
 install: boot xxboot
-       install -c -o ${BINOWN} -g ${BINGRP} -m 444 boot ${DESTDIR}/
-       install -c -o ${BINOWN} -g ${BINGRP} -m 444 xxboot ${DESTDIR}/usr/mdec
+       ${INSTALL} -c -o ${BINOWN} -g ${BINGRP} -m 444 boot ${DESTDIR}/
+       ${INSTALL} -c -o ${BINOWN} -g ${BINGRP} -m 444 xxboot \
+           ${DESTDIR}/usr/mdec
        rm -f ${DESTDIR}/usr/mdec/raboot
        ln ${DESTDIR}/usr/mdec/xxboot ${DESTDIR}/usr/mdec/raboot
        rm -f ${DESTDIR}/usr/mdec/hpboot
@@ -115,7 +115,7 @@ clean::
        rm -f start.o romread.o bootxx.o init.o xxboot boot racopy \
        libsvax.a udiv.o urem.o consio.o ${DEVS} edlabel edlabel.o
        rm -f conf.o boot.o rom.o racopy.o srt0.o devopen.o rootcopy.o \
-       copy copy.o
+       copy copy.o init.o
 
 .include <bsd.prog.mk>
 
index ca08f01..d3b2d2b 100644 (file)
@@ -1,4 +1,4 @@
-/*     $NetBSD: autoconf.c,v 1.5 1996/03/07 23:27:06 ragge Exp $ */
+/*     $NetBSD: autoconf.c,v 1.6 1996/08/02 11:21:46 ragge Exp $ */
 /*
  * Copyright (c) 1994 Ludd, University of Lule}, Sweden.
  * All rights reserved.
@@ -39,8 +39,8 @@
 #include "vaxstand.h"
 
 int    nmba=0, nuba=0, nbi=0,nsbi=0,nuda=0;
-int    *mbaaddr, *ubaaddr;
-int    *udaaddr, *uioaddr, tmsaddr;
+int    *mbaaddr, *ubaaddr, *biaddr;
+int    *udaaddr, *uioaddr, tmsaddr, *bioaddr;
 
 static int mba750[]={0xf28000,0xf2a000,0xf2c000};
 static int uba750[]={0xf30000,0xf32000};
@@ -55,6 +55,10 @@ static int uba780[]={0x20006000,0x20008000,0x2000a000,0x2000c000,
 static int uio780[]={0x20100000,0x20140000,0x20180000,0x201c0000,
        0x22100000,0x22140000,0x22180000,0x221c0000};
 
+static int bi8200[]={0x20000000, 0x22000000, 0x24000000, 0x26000000,
+       0x28000000, 0x2a000000};
+static int bio8200[]={0x20400000};
+
 static int uba630[]={0x20087800};
 static int uio630[]={0x30000000};
 #define qbdev(csr) (((csr) & 017777)-0x10000000)
@@ -67,12 +71,11 @@ static int uda630[]={qbdev(0772150),qbdev(0760334)};
 
 autoconf()
 {
-       int i = MACHID(mfpr(PR_SID));
 
-       switch (i) {
+       switch (vax_cputype) {
 
        default:
-               printf("CPU type %d not supported by boot\n",i);
+               printf("CPU type %d not supported by boot\n",vax_cputype);
                asm("halt");
 
        case VAX_8600:
@@ -117,6 +120,11 @@ autoconf()
                uioaddr = uio630;
                tmsaddr = qbdev(0774500);
                break;
+
+       case VAX_8200:
+               nbi = 1;
+               biaddr = bi8200;
+               bioaddr = bio8200;
        }
 }
 
index 206db3d..7fd5422 100644 (file)
@@ -1,4 +1,5 @@
-/*     $NetBSD: boot.c,v 1.4 1995/09/16 15:54:20 ragge Exp $ */
+/*     $OpenBSD: boot.c,v 1.3 1997/01/15 23:24:16 maja Exp $ */
+/*     $NetBSD: boot.c,v 1.5 1996/08/02 11:21:49 ragge Exp $ */
 /*-
  * Copyright (c) 1982, 1986 The Regents of the University of California.
  * All rights reserved.
@@ -38,6 +39,8 @@
 #include "sys/reboot.h"
 #include "lib/libsa/stand.h"
 
+#define V750UCODE(x)    ((x>>8)&255)
+
 #include <a.out.h>
 
 /*
@@ -49,8 +52,9 @@
 char line[100];
 volatile u_int devtype, bootdev;
 extern unsigned opendev;
+extern  unsigned *bootregs;
 
-main()
+Xmain()
 {
        register howto asm("r11");
        register bdev  asm("r10");
@@ -149,7 +153,7 @@ copyunix(howto, devtype, aio)
        hoppabort((x.a_entry&0x7fffffff),howto, devtype, esym);
        return;
 shread:
-       printf("Short read\n");
+       printf("\nShort read\n\n");
        return;
 }
 
@@ -191,7 +195,7 @@ loadpcs()
                if (*cp == ')' || *cp == ':')
                        break;
        if (*cp) {
-               strncpy(pcs, line, 99);
+               bcopy(line, pcs, 99);
                pcs[99] = 0;
                i = cp - line + 1;
        } else
index 4a1b34f..e7464b8 100644 (file)
@@ -1,4 +1,4 @@
-/* $NetBSD: bootxx.c,v 1.5 1996/02/17 18:23:21 ragge Exp $ */
+/* $NetBSD: bootxx.c,v 1.7 1996/08/02 11:21:53 ragge Exp $ */
 /*-
  * Copyright (c) 1982, 1986 The Regents of the University of California.
  * All rights reserved.
 #include "../mba/mbareg.h"
 #include "../mba/hpreg.h"
 
-#define NRSP 0 /* Kludge */
-#define NCMD 0 /* Kludge */
+#define NRSP 1 /* Kludge */
+#define NCMD 1 /* Kludge */
+
 #include "../uba/ubareg.h"
 #include "../uba/udareg.h"
-#include "../vax/mscp.h"
+
+#include "../mscp/mscp.h"
+#include "../mscp/mscpreg.h"
 
 #include "data.h"
 #include "vaxstand.h"
 
 #include <a.out.h>
 
-int             romstrategy(), romopen();
+int     romstrategy(), romopen();
 int    command(int, int);
 
 /*
@@ -71,39 +74,45 @@ int command(int, int);
 
 volatile u_int  devtype, bootdev;
 unsigned        opendev, boothowto, bootset;
-int             cpu_type, cpunumber;
-unsigned *bootregs;
-int is_750 = 0, is_mvax = 0, is_tmscp = 0;
-struct rpb *rpb;
 
-main()
+extern unsigned *bootregs;
+extern struct  rpb *rpb;
+
+Xmain()
 {
        int io;
+       char *scbb;
+       char *new;
        char *hej = "/boot";
 
-        cpu_type = mfpr(PR_SID);
-        cpunumber = (mfpr(PR_SID) >> 24) & 0xFF;
-
-        switch (cpunumber) {
+        switch (vax_cputype) {
 
         case VAX_78032:
         case VAX_650:
-        {
-                int    cpu_sie;        /* sid-extension */
-
-                is_mvax = 1;
-                cpu_sie = *((int *) 0x20040004) >> 24;
-                cpu_type |= cpu_sie;
-               rpb = (struct rpb *)bootregs[11];
                bootdev = rpb->devtyp;
 
+               /*
+                * now relocate rpb/bqo (which are used by ROM-routines)
+                */
+               rpb = (void*)XXRPB;
+               bcopy ((void*)bootregs[11], rpb, 512);
+               rpb->rpb_base = rpb;
+               bqo = (void*)(512+(int)rpb);
+               bcopy ((void*)rpb->iovec, bqo, rpb->iovecsz);
+               rpb->iovec = (int)bqo;
+               bootregs[11] = (int)rpb;
+
                 break;
-        }
+       case VAX_8200:
         case VAX_750:
-                is_750 = 1;
                bootdev = bootregs[10];
 
                 break;
+       default:
+               printf("unknown cpu type %d\nRegister dump:\n", vax_cputype);
+               for (io = 0; io < 16; io++)
+                       printf("r%d 0x%x\n", io, bootregs[io]);
+               asm("halt");
         }
 
        bootset = getbootdev();
@@ -114,7 +123,7 @@ main()
        if (io >= 0 && io < SOPEN_MAX) {
                copyunix(io);
        } else {
-               printf("Boot failed. errno %d (%s)\n", errno, strerror(errno));
+               printf("Boot failed, saerrno %d\n", errno);
        }
 }
 
@@ -127,7 +136,7 @@ copyunix(aio)
 
        i = read(io, (char *) &x, sizeof(x));
        if (i != sizeof(x) || N_BADMAG(x)) {
-               printf("Bad format: errno %s\n", strerror(errno));
+               printf("Bad format\n");
                return;
        }
        printf("%d", x.a_text);
@@ -163,7 +172,7 @@ getbootdev()
        int     i, major, adaptor, controller, unit, partition;
 
 
-       switch (cpunumber) {
+       switch (vax_cputype) {
        case VAX_78032:
        case VAX_650:
                adaptor = 0;
@@ -172,6 +181,7 @@ getbootdev()
                
                break;
 
+       case VAX_8200:
        case VAX_750:
                controller = 0; /* XXX Actually massbuss can be on 3 ctlr's */
                unit = bootregs[3];
@@ -181,23 +191,28 @@ getbootdev()
        partition = 0;
 
        switch (bootdev) {
-       case 0:                 /* massbuss boot */
+       case BDEV_MBA:                  /* massbuss boot */
                major = 0;      /* hp / ...  */
                adaptor = (bootregs[1] & 0x6000) >> 17;
                break;
 
-       case 17:                /* UDA50 boot */
+       case BDEV_UDA:          /* UDA50 boot */
                major = 9;      /* ra / mscp  */
-               if (is_750)
+               if (vax_cputype == VAX_750)
                        adaptor = (bootregs[1] & 0x40000 ? 0 : 1);
                break;
 
-       case 18:                /* TK50 boot */
+       case BDEV_TK50:         /* TK50 boot */
                major = 15;     /* tms / tmscp  */
-               is_tmscp = 1;   /* use tape spec in mscp routines */
                break;
 
-       case 64:
+       case 36:                /* VS2000/KA410 ST506 disk */
+       case 37:                /* VS2000/KA410 SCSI tape */
+       case 42:                /* VS3100/76 SCSI-floppy(?) */
+               major = 17;     /* 17 is assigned to the ROM-drivers */
+               break;
+
+       case BDEV_CONSOLE:
                major = 8;
                break;
 
@@ -224,7 +239,7 @@ struct disklabel lp;
 int part_off = 0;              /* offset into partition holding /boot */
 char io_buf[MAXBSIZE];
 volatile struct uda {
-       struct  uda1ca uda_ca;           /* communications area */
+       struct  mscp_1ca uda_ca;           /* communications area */
        struct  mscp uda_rsp;     /* response packets */
        struct  mscp uda_cmd;     /* command packets */
 } uda;
@@ -245,27 +260,27 @@ devopen(f, fname, file)
        /*
         * On uVAX we need to init [T]MSCP ctlr to be able to use it.
         */
-       if (is_mvax) {
+       if (vax_cputype == VAX_78032 || vax_cputype == VAX_650) {
                switch (bootdev) {
-               case 17:        /* MSCP */
-               case 18:        /* TMSCP */
+               case BDEV_UDA:  /* MSCP */
+               case BDEV_TK50: /* TMSCP */
                        csr = (struct udadevice *)rpb->csrphy;
 
                        csr->udaip = 0; /* Start init */
-                       while((csr->udasa & UDA_STEP1) == 0);
+                       while((csr->udasa & MP_STEP1) == 0);
                        csr->udasa = 0x8000;
-                       while((csr->udasa & UDA_STEP2) == 0);
+                       while((csr->udasa & MP_STEP2) == 0);
                        csr->udasa = (short)(((u_int)&uda)&0xffff) + 8;
-                       while((csr->udasa & UDA_STEP3) == 0);
+                       while((csr->udasa & MP_STEP3) == 0);
                        csr->udasa = 0x10;
-                       while((csr->udasa & UDA_STEP4) == 0);
+                       while((csr->udasa & MP_STEP4) == 0);
                        csr->udasa = 0x0001;
 
                        uda.uda_ca.ca_rspdsc =
                            (int) &uda.uda_rsp.mscp_cmdref;
                        uda.uda_ca.ca_cmddsc =
                            (int) &uda.uda_cmd.mscp_cmdref;
-                       if (is_tmscp)
+                       if (bootdev == BDEV_TK50)
                                uda.uda_cmd.mscp_vcid = 1;
                        command(M_OP_SETCTLRC, 0);
                        uda.uda_cmd.mscp_unit = rpb->unit;
@@ -279,11 +294,10 @@ devopen(f, fname, file)
         * Actually disklabel is only needed when using hp disks,
         * but it doesn't hurt to always get it.
         */
-       if (!is_tmscp) {
+       if ((bootdev != BDEV_TK50) && (bootdev != BDEV_CONSOLE)) {
                msg = getdisklabel((void *)LABELOFFSET + RELOC, &lp);
-               if (msg) {
+               if (msg)
                        printf("getdisklabel: %s\n", msg);
-               }
        }
        return 0;
 }
@@ -317,13 +331,13 @@ romstrategy(sc, func, dblk, size, buf, rsize)
        int     block = dblk;
        int     nsize = size;
 
-       switch (cpunumber) {
+       switch (vax_cputype) {
 
        case VAX_650:
        case VAX_78032:
                switch (bootdev) {
 
-               case 17: /* MSCP */
+               case BDEV_UDA: /* MSCP */
                        uda.uda_cmd.mscp_seq.seq_lbn = dblk;
                        uda.uda_cmd.mscp_seq.seq_bytecount = size;
                        uda.uda_cmd.mscp_seq.seq_buffer = (int)buf;
@@ -331,7 +345,7 @@ romstrategy(sc, func, dblk, size, buf, rsize)
                        command(M_OP_READ, 0);
                        break;
 
-               case 18: /* TMSCP */
+               case BDEV_TK50: /* TMSCP */
                        if (dblk < curblock) {
                                uda.uda_cmd.mscp_seq.seq_bytecount =
                                    curblock - dblk;
@@ -351,16 +365,21 @@ romstrategy(sc, func, dblk, size, buf, rsize)
                                command(M_OP_READ, 0);
                        }
                        break;
+               case 36:
+               case 37:
+               default:
+                       romread_uvax(block, size, buf, bootregs);
+                       break;
 
                }
                break;
 
+       case VAX_8200:
        case VAX_750:
-               if (bootdev) {
+               if (bootdev != BDEV_MBA) {
                        while (size > 0) {
-                               if ((read750(block, bootregs) & 0x01) == 0)
-                                       return 1;
-
+                               while ((read750(block, bootregs) & 0x01) == 0)
+                                       printf("Retrying read bn# %d\n", block);
                                bcopy(0, buf, 512);
                                size -= 512;
                                buf += 512;
index f516c4d..72b7f44 100644 (file)
@@ -1,4 +1,4 @@
-/*     $NetBSD: conf.c,v 1.5 1996/02/17 18:23:18 ragge Exp $ */
+/*     $NetBSD: conf.c,v 1.6 1996/08/02 11:21:56 ragge Exp $ */
 /*
  * Copyright (c) 1994 Ludd, University of Lule}, Sweden.
  * All rights reserved.
@@ -42,25 +42,33 @@ int raopen(),  rastrategy();
 int    hpopen(),  hpstrategy();
 int    ctuopen(),  ctustrategy();
 int     tmscpopen(), tmscpstrategy();
+int     romopen(), romstrategy();
+int     mfmopen(), mfmstrategy();
+int     sdopen(), sdstrategy();
+
 
 struct devsw devsw[]={
        SADEV("hp",hpstrategy, hpopen, nullsys, noioctl),
-       SADEV("ht",nullsys, nodev, nullsys, noioctl),
-       SADEV("up",nullsys, nodev, nullsys, noioctl),
-       SADEV("hk",nullsys, nodev, nullsys, noioctl),
+       SADEV(0 ,nullsys, nodev, nullsys, noioctl), /* ht */
+       SADEV(0 ,nullsys, nodev, nullsys, noioctl), /* up */
+       SADEV(0 ,nullsys, nodev, nullsys, noioctl), /* hk */
        SADEV( 0  ,nullsys, nodev, nullsys, noioctl),
-       SADEV("tm",nullsys, nodev, nullsys, noioctl),
-       SADEV("ts",nullsys, nodev, nullsys, noioctl),
-       SADEV("mt",nullsys, nodev, nullsys, noioctl),
+       SADEV(0 ,nullsys, nodev, nullsys, noioctl), /* tm */
+       SADEV(0 ,nullsys, nodev, nullsys, noioctl), /* ts */
+       SADEV(0 ,nullsys, nodev, nullsys, noioctl), /* mt */
        SADEV("ctu",ctustrategy, ctuopen, nullsys, noioctl),
        SADEV("ra",rastrategy, raopen, nullsys, noioctl),
-       SADEV("ut",nullsys, nodev, nullsys, noioctl),
-       SADEV("id",nullsys, nodev, nullsys, noioctl),
-       SADEV("rx",nullsys, nodev, nullsys, noioctl),
-       SADEV("uu",nullsys, nodev, nullsys, noioctl),
-       SADEV("rl",nullsys, nodev, nullsys, noioctl),
-       SADEV("tms",tmscpstrategy, tmscpopen, nullsys, noioctl),
-       SADEV("kra",nullsys, nodev, nullsys, noioctl),
+       SADEV(0 ,nullsys, nodev, nullsys, noioctl), /* ut */
+       SADEV(0 ,nullsys, nodev, nullsys, noioctl), /* id */
+       SADEV(0 ,nullsys, nodev, nullsys, noioctl), /* rx */
+       SADEV(0 ,nullsys, nodev, nullsys, noioctl), /* uu */
+       SADEV(0 ,nullsys, nodev, nullsys, noioctl), /* rl */
+       SADEV("mt",tmscpstrategy, tmscpopen, nullsys, noioctl),
+       SADEV(0 ,nullsys, nodev, nullsys, noioctl), /* crx */
+        SADEV("rom",romstrategy, romopen, nullsys, noioctl),    /* 17 */
+        SADEV("mfm",mfmstrategy, mfmopen, nullsys, noioctl),    /* 18 */
+        SADEV("sd",sdstrategy, sdopen, nullsys, noioctl),       /* 18 */
+       SADEV("st",sdstrategy, sdopen, nullsys, noioctl),
 };
 
 int     ndevs = (sizeof(devsw)/sizeof(devsw[0]));
index 39402cc..94db46d 100644 (file)
@@ -1,4 +1,4 @@
-/*     $NetBSD: consio.c,v 1.3 1995/09/16 15:48:49 ragge Exp $ */
+/*     $NetBSD: consio.c,v 1.4 1996/08/02 11:22:00 ragge Exp $ */
 /*
  * Copyright (c) 1994 Ludd, University of Lule}, Sweden.
  * All rights reserved.
 #include "../vax/gencons.h"
 
 #include "../include/mtpr.h"
+#include "../include/sid.h"
+#include "../include/rpb.h"
 
-putchar(ch)
-        int     ch;
+#include "data.h"
+
+void setup __P((void));
+
+int    vax_cputype;
+int    vax_boardtype;
+
+int    is_750;
+int    is_mvax;
+
+unsigned       *bootregs;
+struct rpb     *rpb;
+struct bqo     *bqo;
+
+static int (*put_fp) __P((int))  = NULL;
+static int (*get_fp) __P((void)) = NULL;
+
+int pr_putchar __P((int c));   /* putchar() using mtpr/mfpr */
+int pr_getchar __P((void));
+
+int rom_putchar __P((int c));  /* putchar() using ROM routines */
+int rom_getchar __P((void));
+
+static int rom_putc;           /* ROM-address of put-routine */
+static int rom_getc;           /* ROM-address of get-routine */
+
+putchar(c)
+       int c;
+{
+       (*put_fp)(c);
+       if (c == 10)
+               (*put_fp)(13);          /* CR/LF */
+}
+
+getchar() 
+{
+       int c;
+
+       do
+               c = (*get_fp)() & 0177;
+       while (c == 17 || c == 19);             /* ignore XON/XOFF */
+       return c;
+}
+
+
+/*
+ * setup() is called out of the startup files (start.s, srt0.s) and
+ * initializes data which are globally used and is called before main().
+ */
+void 
+setup()
 {
-        while ((mfpr(PR_TXCS) & GC_RDY) == 0); /* Wait until xmit ready */
-        mtpr(ch, PR_TXDB);       /* xmit character */
-        if (ch == 10)
-                putchar(13); /* CR/LF */
+       vax_cputype = (mfpr(PR_SID) >> 24) & 0xFF;
+
+       put_fp = pr_putchar;
+       get_fp = pr_getchar;
+       /*
+        * according to vax_cputype we initialize vax_boardtype.
+        */
+        switch (vax_cputype) {
 
+       case VAX_650:
+       case VAX_78032:
+               is_mvax = 1;
+               vax_boardtype = (vax_cputype << 24) |
+                   ((*(int*)0x20040004 >> 24) & 0377);
+               rpb = (struct rpb *)bootregs[11];       /* bertram: ??? */
+               break;
+        }
+
+       /*
+        * According to the vax_boardtype (vax_cputype is not specific
+        * enough to do that) we decide which method/routines to use
+        * for console I/O. 
+        * mtpr/mfpr are restricted to serial consoles, ROM-based routines
+        * support both serial and graphical consoles, thus we use that
+        * as fallthrough/default.
+        */
+       switch (vax_boardtype) {        /* ROM-based is default !!! */
+
+       case VAX_BTYP_650:
+       case VAX_BTYP_660:
+       case VAX_BTYP_670:
+       case VAX_BTYP_690:
+       case VAX_BTYP_1303:
+               put_fp = rom_putchar;
+               get_fp = rom_getchar;
+               rom_putc = 0x20040058;          /* 537133144 */
+               rom_getc = 0x20040008;          /* 537133064 */
+               break;
+
+       case VAX_BTYP_43:
+       case VAX_BTYP_46:
+       case VAX_BTYP_49:
+       case VAX_BTYP_410:        
+               put_fp = rom_putchar;
+               get_fp = rom_getchar;
+               rom_putc = 0x20040058;          /* 537133144 */
+               rom_getc = 0x20040044;          /* 537133124 */
+               break;
+
+       default:
+               break;
+       }
+
+       return;
 }
 
-getchar()
+/*
+ * putchar() using MTPR
+ */
+pr_putchar(c)
+        int     c;
 {
-       int ch;
+       int     timeout = 1<<15;        /* don't hang the machine! */
+        while ((mfpr(PR_TXCS) & GC_RDY) == 0)  /* Wait until xmit ready */
+               if (--timeout < 0)
+                       break;
+        mtpr(c, PR_TXDB);              /* xmit character */
+}
 
-       do {
-               while ((mfpr(PR_RXCS) & GC_DON) == 0);  /* wait for char */
-               ch = mfpr(PR_RXDB);                     /* now get it */
-       } while (ch == 17 || ch == 19);
-       return ch;
+/*
+ * getchar() using MFPR
+ */
+pr_getchar()
+{
+       while ((mfpr(PR_RXCS) & GC_DON) == 0);  /* wait for char */
+       return (mfpr(PR_RXDB));                 /* now get it */
 }
+
+/*
+ * int rom_putchar (int c)     ==> putchar() using ROM-routines
+ */
+asm("
+       .globl _rom_putchar
+       _rom_putchar:
+               .word 0x04              # save-mask: R2
+               movl    4(ap), r2       # move argument to R2
+               jsb     *_rom_putc      # write it
+               ret                     # that's all
+");
+
+
+/*
+ * int rom_getchar (void)      ==> getchar() using ROM-routines
+ */
+asm("
+       .globl _rom_getchar
+       _rom_getchar:
+               .word 0x02              # save-mask: R1
+       loop:                           # do {
+               jsb     *_rom_getc      #   call the getc-routine
+               tstl    r0              #   check if char ready
+               beql    loop            # } while (R0 == 0)
+               movl    r1, r0          # R1 holds char
+               ret                     # we're done
+");
+
+
index a67721d..c46ba56 100644 (file)
@@ -1,4 +1,4 @@
-/*     $NetBSD: copy.c,v 1.2 1995/09/29 16:35:00 ragge Exp $ */
+/*     $NetBSD: copy.c,v 1.3 1996/08/02 11:22:03 ragge Exp $ */
 /*-
  * Copyright (c) 1982, 1986 The Regents of the University of California.
  * All rights reserved.
@@ -38,6 +38,8 @@
 #include "sys/reboot.h"
 #include "lib/libsa/stand.h"
 
+#include "vaxstand.h"
+
 #include <a.out.h>
 
 char line[100];
@@ -53,7 +55,7 @@ static int    partlist[8];
 int fill_buffer (void);
 int write_disk (void);
 
-main()
+Xmain()
 {
        int adapt, ctlr, unit, part;
        int res, i, loops;
index d3468b4..8d58b77 100644 (file)
@@ -1,4 +1,4 @@
-/*     $NetBSD: devopen.c,v 1.4 1996/03/16 11:02:28 ragge Exp $ */
+/*     $NetBSD: devopen.c,v 1.6 1996/08/02 16:18:39 ragge Exp $ */
 /*-
  *  Copyright (c) 1993 John Brezak
  *  All rights reserved.
@@ -52,7 +52,7 @@ usage()
 {
        printf("\
            Usage: device(adaptor, controller, drive, partition)file\n\
-            <device><unit><partitonletter>:file\n\
+           <device><unit><partitonletter>:file\n\
            ");
 }
 
@@ -62,15 +62,15 @@ devlookup(d,len)
 {
        struct devsw *dp = devsw;
        int i;
-    
+
        for (i = 0; i < ndevs; i++, dp++)
                if (dp->dv_name && strncmp(dp->dv_name, d, len) == 0)
-                       return(i);
+                       return(i);
 
        printf("No such device - Configured devices are:\n");
        for (dp = devsw, i = 0; i < ndevs; i++, dp++)
                if (dp->dv_name)
-                       printf(" %s", dp->dv_name);
+                       printf(" %s", dp->dv_name);
        printf("\n");
        errno = ENODEV;
        return(-1);
@@ -90,7 +90,7 @@ devparse(fname, dev, adapt, ctlr, unit, part, file)
 {
        int *argp, i;
        char *s, *args[4];
-    
+
        /* get device name and make lower case */
        for(s = fname; *s && *s != '/' && *s != ':' && *s != '('; s++)
                if(isupper(*s))
@@ -117,19 +117,19 @@ devparse(fname, dev, adapt, ctlr, unit, part, file)
                        *part  = atoi(args[3]);
                        break;
                case 3:
-                       *ctlr  = atoi(args[0]);
-                       *unit  = atoi(args[1]);
-                       *part  = atoi(args[2]);
-                       break;
+                       *ctlr  = atoi(args[0]);
+                       *unit  = atoi(args[1]);
+                       *part  = atoi(args[2]);
+                       break;
                case 2:
-                       *unit  = atoi(args[0]);
-                       *part  = atoi(args[1]);
-                       break;
+                       *unit  = atoi(args[0]);
+                       *part  = atoi(args[1]);
+                       break;
                case 1:
-                       *part  = atoi(args[0]);
-                       break;
+                       *part  = atoi(args[0]);
+                       break;
                case 0:
-                       break;
+                       break;
                }
                *file = ++s;
 
@@ -142,25 +142,25 @@ devparse(fname, dev, adapt, ctlr, unit, part, file)
        
                /* lookup device and get index */
                if ((*dev = devlookup(fname, s - fname)) < 0)
-                       goto baddev;
+                       goto baddev;
 
                /* isolate unit */
                if ((*unit = atoi(s)) > sizeof(char))
-                       goto bad;
+                       goto bad;
                for (; isdigit(*s); s++)
                        ;
        
                /* translate partition */
                if(!ispart(*s))
-                       goto bad;
+                       goto bad;
        
                *part = *s++ - 'a';
                if(*s != ':')
-                       goto bad;
+                       goto bad;
                *file = ++s;
 
        /* no device present */
-       } else
+       } else
                *file = fname;
     
        /* return the remaining unparsed part as the file to boot */
@@ -176,8 +176,8 @@ bad:
 extern int bootdev;
 
 devopen(f, fname, file)
-        struct open_file *f;
-        const char *fname;
+       struct open_file *f;
+       const char *fname;
        char **file;
 {
        int n, error;
@@ -190,12 +190,12 @@ devopen(f, fname, file)
        unit  = B_UNIT(bootdev);
        part  = B_PARTITION(bootdev);
        adapt = B_ADAPTOR(bootdev);
-       
+
        if (error = devparse(fname, &dev, &adapt, &ctlr, &unit, &part, file))
                return(error);
-       
+
        dp = &devsw[dev];
-       
+
        if (!dp->dv_open)
                return(ENODEV);
 
index 0984418..a5af6ab 100644 (file)
@@ -1,4 +1,4 @@
-/*     $NetBSD: edlabel.c,v 1.1 1995/09/16 12:56:03 ragge Exp $ */
+/*     $NetBSD: edlabel.c,v 1.2 1996/08/02 11:22:11 ragge Exp $ */
 /*
  * Copyright (c) 1995 Ludd, University of Lule}, Sweden.
  * All rights reserved.
@@ -88,7 +88,7 @@ setdefaultlabel()
 #define GETNUM2(out, num1, num) printf(out, num1, num);gets(store); \
        if (*store) num = atoi(store);
 #define        GETSTR(out, str) printf(out, str);gets(store); \
-       if (*store) strcpy(str, store);
+       if (*store) bcopy(store, str, strlen(store));
 #define        FLAGS(out, flag) printf(out, lp->d_flags & flag?'y':'n');gets(store); \
        if (*store == 'y' || *store == 'Y') lp->d_flags |= flag; \
        else lp->d_flags &= ~flag;
@@ -121,9 +121,11 @@ editlabel()
        GETNUM("drivedata 2? [%d] ", lp->d_drivedata[2]);
        GETNUM("drivedata 3? [%d] ", lp->d_drivedata[3]);
        GETNUM("drivedata 4? [%d] ", lp->d_drivedata[4]);
+       lp->d_secsize = 512;
        GETNUM("\nbytes/sector? [%d] ", lp->d_secsize);
        GETNUM("sectors/track? [%d] ", lp->d_nsectors);
        GETNUM("tracks/cylinder? [%d] ", lp->d_ntracks);
+       lp->d_secpercyl = lp->d_nsectors * lp->d_ntracks;
        GETNUM("sectors/cylinder? [%d] ", lp->d_secpercyl);
        GETNUM("cylinders? [%d] ", lp->d_ncylinders);
        lp->d_npartitions = MAXPARTITIONS;
@@ -137,7 +139,7 @@ editlabel()
 int bootdev;
 
 void 
-main()
+Xmain()
 {
        register bdev  asm("r10");
 
diff --git a/sys/arch/vax/boot/init.c b/sys/arch/vax/boot/init.c
deleted file mode 100644 (file)
index 94c7ad6..0000000
+++ /dev/null
@@ -1,82 +0,0 @@
-/* $NetBSD: init.c,v 1.3 1995/09/16 13:34:21 ragge Exp $ */
-/*
- * Copyright (c) 1995 Ludd, University of Lule}, Sweden. All rights reserved.
- * 
- * This code is derived from software contributed to Ludd by Bertram Barth.
- * 
- * 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 at
- * Ludd, University of Lule}, Sweden and its contributors. 4. The name of the
- * author may not be used to endorse or promote products derived from this
- * software without specific prior written permission
- * 
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
- * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
- * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/* All bugs are subject to removal without further notice */
-
-
-
-#include "lib/libsa/stand.h"
-
-#include "../include/mtpr.h"   /* mfpr(), mtpr() */
-#include "../include/sid.h"    /* cpu_type, cpu_number */
-
-#define NRSP 0                 /* Kludge, must be done before udareg.h */
-#define NCMD 0                 /* includes */
-
-#include "../uba/udareg.h"     /* struct udadevice */
-
-#include "data.h"              /* bootregs[], rpb, bqo */
-
-struct rpb     *rpb;
-struct bqo     *bqo;
-
-int    is_750 = 0, is_mvax = 0;
-
-/*
- * initdata() sets up data gotten from start routines, mostly for uVAX.
- */
-int
-initdata()
-{
-       int i, *tmp;
-
-       cpu_type = mfpr(PR_SID);
-       cpunumber = (mfpr(PR_SID) >> 24) & 0xFF;
-
-       switch (cpunumber) {
-
-       case VAX_78032:
-       case VAX_650:
-       {
-               int             cpu_sie;        /* sid-extension */
-
-               is_mvax = 1;
-               cpu_sie = *((int *) 0x20040004) >> 24;
-               cpu_type |= cpu_sie;
-
-               break;
-       }
-       case VAX_750:
-               is_750 = 1;
-               break;
-       }
-       return 0;
-}
diff --git a/sys/arch/vax/boot/ka410.h b/sys/arch/vax/boot/ka410.h
new file mode 100644 (file)
index 0000000..a022362
--- /dev/null
@@ -0,0 +1,82 @@
+/*     $NetBSD: ka410.h,v 1.1 1996/08/02 11:22:13 ragge Exp $ */
+/*
+ * Copyright (c) 1996 Ludd, University of Lule}, Sweden.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Ludd by
+ * Bertram Barth.
+ *
+ * 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 at Ludd, University of 
+ *      Lule}, Sweden and its contributors.
+ * 4. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+
+/* 
+ * interrupt request-, clear-, and mask register 
+ */
+extern volatile unsigned char *ka410_intreq;
+extern volatile unsigned char *ka410_intclr;
+extern volatile unsigned char *ka410_intmsk;
+
+#define INTR_SR        (1<<7)  /* Serial line receiver or silo full */
+#define INTR_ST        (1<<6)  /* Serial line transmitter done */
+#define INTR_NP        (1<<5)  /* Network controller primary */
+#define INTR_NS        (1<<4)  /* Network controller secondary */
+#define INTR_VF        (1<<3)  /* Video end of frame */
+#define INTR_VS        (1<<2)  /* Video secondary */
+#define INTR_SC        (1<<1)  /* SCSI controller */
+#define INTR_DC        (1<<0)  /* Disk controller */
+
+/*
+ * interrupt vector numbers
+ */
+#define IVEC_BASE      0x20040020
+#define IVEC_SR                0x000002C0
+#define IVEC_ST                0x000002C4
+#define IVEC_NP                0x00000250
+#define IVEC_NS                0x00000254
+#define IVEC_VF                0x00000244
+#define IVEC_VS                0x00000248
+#define IVEC_SC                0x000003F8
+#define IVEC_DC                0x000003FC
+
+/*
+ * Clock-Chip data in NVRAM
+ */
+#define KA410_CPMBX    0x200B0038      /* Console Mailbox (1 byte) */
+#define KA410_CPFLG    0x200B003C      /* Console Program Flags (1 byte) */
+#define KA410_LK201_ID 0x200B0040      /* Keyboard Variation (1 byte) */
+#define KA410_CONS_ID  0x200B0044      /* Console Device Type (1 byte) */
+#define KA410_SCR      0x200B0048      /* Console Scratch RAM */
+#define KA410_TEMP     0x200B0058      /* Used by System Firmware */
+#define KA410_BAT_CHK  0x200B0088      /* Battery Check Data */
+#define KA410_BOOTDEV  0x200B0098      /* Default Boot Device (4 bytes) */
+#define KA410_BOOTFLG  0x200B00A8      /* Default Boot Flags (4 bytes) */
+#define KA410_SCRLEN   0x200B00B8      /* Number of pages of SCR (1 byte) */
+#define KA410_SCSIPORT 0x200B00BC      /* Tape Controller Port Data */
+#define KA410_RESERVED 0x200B00C0      /* Reserved (16 bytes) */
+
diff --git a/sys/arch/vax/boot/mfm.c b/sys/arch/vax/boot/mfm.c
new file mode 100644 (file)
index 0000000..bd27153
--- /dev/null
@@ -0,0 +1,640 @@
+/*     $NetBSD: mfm.c,v 1.1 1996/08/02 11:22:16 ragge Exp $    */
+/*
+ * Copyright (c) 1996 Ludd, University of Lule}, Sweden.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Ludd by
+ * Bertram Barth.
+ *
+ * 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 at Ludd, University of
+ *     Lule}, Sweden and its contributors.
+ * 4. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * ToDo:
+ *
+ * - insert appropriate delays for diskette-drive where needed
+ * - allow more than one sector per diskette-read
+ * - check for and handle bad sectors
+ * - ???
+ */
+
+#include "sys/param.h"
+#include "sys/reboot.h"
+#include "sys/disklabel.h"
+
+#include "lib/libsa/stand.h"
+#include "lib/libsa/ufs.h"
+
+#include "../include/pte.h"
+#include "../include/sid.h"
+#include "../include/mtpr.h"
+#include "../include/reg.h"
+#include "../include/rpb.h"
+
+#include "ka410.h"
+#include "../vsa/hdc9224.h"
+
+#include "data.h"
+#include "vaxstand.h"
+
+#define MAX_WAIT       (1000*1000)     /* # of loop-instructions in seconds */
+
+struct mfm_softc {
+       int             part;
+       int             unit;
+};
+
+int    mfmstrategy(), mfmopen();
+struct disklabel mfmlabel;
+struct mfm_softc mfm_softc;
+char           io_buf[MAXBSIZE];
+
+/*
+ * These should probably be somewhere else, but ka410 is the only
+ * one with mfm disks anyway...
+ */
+volatile unsigned char *ka410_intreq = (void*)0x2008000f;
+volatile unsigned char *ka410_intclr = (void*)0x2008000f;
+volatile unsigned char *ka410_intmsk = (void*)0x2008000c;
+
+static volatile struct hdc9224_DKCreg *dkc = (void *) 0x200c0000;
+static volatile struct hdc9224_UDCreg sreg;    /* input */
+static volatile struct hdc9224_UDCreg creg;    /* output */
+
+/*
+ * we have to wait 0.7 usec between two accesses to any of the
+ * dkc-registers, on a VS2000 with 1 MIPS, this is roughly one
+ * instruction. Thus the loop-overhead will be enough...
+ */
+static int
+sreg_read()
+{
+       int     i;
+       char    *p;
+
+       dkc->dkc_cmd = 0x40;    /* set internal counter to zero */
+       p = (void *) &sreg;
+       for (i = 0; i < 10; i++)
+               *p++ = dkc->dkc_reg;    /* dkc_reg auto-increments */
+}
+
+static int
+creg_write()
+{
+       int     i;
+       char    *p;
+
+       dkc->dkc_cmd = 0x40;    /* set internal counter to zero */
+       p = (void *) &creg;
+       for (i = 0; i < 10; i++)
+               dkc->dkc_reg = *p++;    /* dkc_reg auto-increments */
+}
+
+/*
+ * floppies are handled in a quite strange way by this controller...
+ *
+ * before reading/writing a sector from/to floppy, we use the SEEK/READ_ID
+ * command to place the head at the desired location. Then we wait some
+ * time before issueing the real command in order to let the drive become
+ * ready...
+ */
+int
+mfm_rxprepare()
+{
+       int     error;
+
+       error = mfm_command(DKC_CMD_SEEKREADID | 0x04); /* step=1, verify=0 */
+       if (error) {
+               printf("error while stepping to position %d/%d/%x. Retry...\n",
+                   creg.udc_dsect, creg.udc_dhead, creg.udc_dcyl);
+               error = mfm_command(DKC_CMD_SEEKREADID | 0x04);
+       }
+       return error;
+}
+
+int
+mfm_rxselect(unit)
+       int     unit;
+{
+       int     error;
+
+       /*
+        * bring "creg" in some known-to-work state and
+        * select the drive with the DRIVE SELECT command.
+        */
+       creg.udc_dma7 = 0;
+       creg.udc_dma15 = 0;
+       creg.udc_dma23 = 0;
+       creg.udc_dsect = 1;     /* sectors are numbered 1..15 !!! */
+       creg.udc_dhead = 0;
+       creg.udc_dcyl = 0;
+       creg.udc_scnt = 0;
+
+       creg.udc_rtcnt = UDC_RC_RX33READ;
+       creg.udc_mode = UDC_MD_RX33;
+       creg.udc_term = UDC_TC_FDD;
+
+       /*
+        * this is ...
+        */
+       error = mfm_command(DKC_CMD_DRSEL_RX33 | unit);
+
+       if ((error != 0) || (sreg.udc_dstat & UDC_DS_READY == 0)) {
+               printf("\nfloppy-drive not ready (new floppy inserted?)\n\n");
+
+               creg.udc_rtcnt &= ~UDC_RC_INVRDY;       /* clear INVRDY-flag */
+               error = mfm_command(DKC_CMD_DRSEL_RX33 | unit);
+               if ((error != 0) || (sreg.udc_dstat & UDC_DS_READY == 0)) {
+                       printf("diskette not ready(1): %x/%x\n",
+                              error, sreg.udc_dstat);
+                       printf("floppy-drive offline?\n");
+                       return (-1);
+               }
+               if (sreg.udc_dstat & UDC_DS_TRK00)
+                       error = mfm_command(DKC_CMD_STEPIN_FDD);
+               else
+                       error = mfm_command(DKC_CMD_STEPOUT_FDD);
+
+               /*
+                * now ready should be 0, cause INVRDY is not set
+                * (retrying a command makes this fail...)
+                */
+               if ((error != 0) || (sreg.udc_dstat & UDC_DS_READY == 1)) {
+                       printf("diskette not ready(2): %x/%x\n",
+                              error, sreg.udc_dstat);
+               }
+               creg.udc_rtcnt |= UDC_RC_INVRDY;
+               error = mfm_command(DKC_CMD_DRSEL_RX33 | unit);
+
+               if ((error != 0) || (sreg.udc_dstat & UDC_DS_READY == 0)) {
+                       printf("diskette not ready(3): %x/%x\n",
+                              error, sreg.udc_dstat);
+                       printf("no floppy inserted or floppy-door open\n");
+                       return (-1);
+               }
+               printf("floppy-drive reselected.\n");
+       }
+       return (error);
+}
+
+int
+mfm_rdselect(unit)
+       int     unit;
+{
+       int     error;
+
+       /*
+        * bring "creg" in some known-to-work state and
+        * select the drive with the DRIVE SELECT command.
+        */
+       creg.udc_dma7 = 0;
+       creg.udc_dma15 = 0;
+       creg.udc_dma23 = 0;
+       creg.udc_dsect = 0;     /* sectors are numbered 0..16 */
+       creg.udc_dhead = 0;
+       creg.udc_dcyl = 0;
+       creg.udc_scnt = 0;
+
+       creg.udc_rtcnt = UDC_RC_HDD_READ;
+       creg.udc_mode = UDC_MD_HDD;
+       creg.udc_term = UDC_TC_HDD;
+
+       error = mfm_command(DKC_CMD_DRSEL_HDD | unit);
+
+       return (error);
+}
+
+static int     mfm_retry = 0;
+
+int
+mfm_command(cmd)
+       int     cmd;
+{
+       int     termcode, ready, i;
+
+       creg_write();           /* write command-registers */
+       *ka410_intclr = INTR_DC;
+       dkc->dkc_cmd = cmd;     /* issue command */
+       for (i = 0; i < MAX_WAIT; i++) {
+               if (*ka410_intreq & INTR_DC)    /* wait for interrupt */
+                       break;
+       }
+       if ((*ka410_intreq & INTR_DC) == 0)
+               printf("timeout in mfm_command...\n");
+
+       sreg_read();            /* read status-registers */
+
+       if (dkc->dkc_stat == (DKC_ST_DONE | DKC_TC_SUCCESS))
+               return (0);
+
+       if (sreg.udc_cstat & UDC_CS_ECCERR) {
+               printf(
+"\nspurious(?) ECC/CRC error at s%d/t%d/c%d [s%d/t%d/c%d(%d)]\n",
+                  sreg.udc_csect, sreg.udc_chead, sreg.udc_ccyl,
+                  creg.udc_dsect, creg.udc_dhead, creg.udc_dcyl,creg.udc_scnt);
+               if (sreg.udc_csect != creg.udc_dsect + creg.udc_scnt - 1) {
+                       printf("DMA: %x %x %x [%x]\n",
+                           sreg.udc_dma23, sreg.udc_dma15,
+                           sreg.udc_dma7, 512 * (sreg.udc_csect -
+                           creg.udc_dsect));
+                       creg.udc_scnt = creg.udc_scnt -
+                           (sreg.udc_csect - creg.udc_dsect) - 1;
+                       creg.udc_dsect = sreg.udc_csect + 1;
+                       creg.udc_dma23 = sreg.udc_dma23;
+                       creg.udc_dma15 = sreg.udc_dma15 + 2;
+                       creg.udc_dma7 = 0;
+                       printf("Retry starting from s%d/t%d/c%d (%d). ",
+                           creg.udc_dsect, creg.udc_dhead, creg.udc_dcyl,
+                           creg.udc_scnt);
+               }
+               goto retry;
+       }
+       termcode = (dkc->dkc_stat & DKC_ST_TERMCOD) >> 3;
+       ready = sreg.udc_dstat & UDC_DS_READY;
+
+       printf("cmd:0x%x: termcode=0x%x, status=0x%x, cstat=0x%x, dstat=0x%x\n",
+              cmd, termcode, dkc->dkc_stat, sreg.udc_cstat, sreg.udc_dstat);
+
+       if (dkc->dkc_stat & DKC_ST_BADSECT)
+               printf("bad sector found: s%d/t%d/c%d\n", creg.udc_dsect,
+                      creg.udc_dhead, creg.udc_dcyl);
+retry:
+       if ((mfm_retry == 0) && (sreg.udc_cstat & UDC_CS_RETREQ)) {
+               mfm_retry = 1;
+               printf("Retrying... ");
+               mfm_command(cmd);
+               printf("Retry done.\n");
+               mfm_retry = 0;
+       }
+       return ((dkc->dkc_stat & DKC_ST_TERMCOD) >> 3);
+}
+
+/*
+ * on-disk geometry block
+ */
+#define _aP    __attribute__ ((packed))        /* force byte-alignment */
+
+volatile struct mfm_xbn {
+       char            mbz[10];/* 10 bytes of zero */
+       long xbn_count  _aP;    /* number of XBNs */
+       long dbn_count  _aP;    /* number of DBNs */
+       long lbn_count  _aP;    /* number of LBNs (Logical-Block-Numbers) */
+       long rbn_count  _aP;    /* number of RBNs (Replacement-Block-Numbers) */
+       short           nspt;   /* number of sectors per track */
+       short           ntracks;/* number of tracks */
+       short           ncylinders;     /* number of cylinders */
+       short           precomp;/* first cylinder for write precompensation */
+       short           reduced;/* first cylinder for reduced write current */
+       short           seek_rate;      /* seek rate or zero for buffered
+                                        * seeks */
+       short           crc_eec;/* 0 if CRC is being used or 1 if ECC is
+                                * being used */
+       short           rct;    /* "replacement control table" (RCT) */
+       short           rct_ncopies;    /* number of copies of the RCT */
+       long media_id   _aP;    /* media identifier */
+       short           interleave;     /* sector-to-sector interleave */
+       short           headskew;       /* head-to-head skew */
+       short           cylskew;/* cylinder-to-cylinder skew */
+       short           gap0_size;      /* size of GAP 0 in the MFM format */
+       short           gap1_size;      /* size of GAP 1 in the MFM format */
+       short           gap2_size;      /* size of GAP 2 in the MFM format */
+       short           gap3_size;      /* size of GAP 3 in the MFM format */
+       short           sync_value;     /* sync value used to start a track
+                                        * when formatting */
+       char            reserved[32];   /* reserved for use by the RQDX1/2/3
+                                        * formatter */
+       short           serial_number;  /* serial number */
+       char            fill[412];      /* Filler bytes to the end of the
+                                        * block */
+       short           checksum;       /* checksum over the XBN */
+} mfm_xbn;
+
+display_xbn(p)
+       struct mfm_xbn *p;
+{
+       printf("**DiskData**    XBNs: %d, DBNs: %d, LBNs: %d, RBNs: %d\n",
+           p->xbn_count, p->dbn_count, p->lbn_count, p->rbn_count);
+       printf("sect/track: %d, tracks: %d, cyl: %d, precomp/reduced: %d/%d\n",
+           p->nspt, p->ntracks, p->ncylinders, p->precomp, p->reduced);
+       printf("seek-rate: %d, crc/eec: %s, RCT: %d, RCT-copies: %d\n",
+           p->seek_rate, p->crc_eec ? "EEC" : "CRC", p->rct, p->rct_ncopies);
+       printf("media-ID: 0x%x, interleave: %d, headskew: %d, cylskew: %d\n",
+           &p->media_id, p->interleave, p->headskew, p->cylskew);
+       printf("gap0: %d, gap1: %d, gap2: %d, gap3: %d, sync-value: %d\n",
+           p->gap0_size, p->gap1_size, p->gap2_size, p->gap3_size,
+           p->sync_value);
+       printf("serial: %d, checksum: %d, size: %d, reserved: %32c\n",
+           p->serial_number, p->checksum, sizeof(*p), p->reserved);
+}
+
+mfmopen(f, adapt, ctlr, unit, part)
+       struct open_file *f;
+       int    ctlr, unit, part;
+{
+       char *msg;
+       struct disklabel *lp = &mfmlabel;
+       volatile struct mfm_softc *msc = &mfm_softc;
+       int  i, err;
+
+       bzero(lp, sizeof(struct disklabel));
+       msc->unit = unit;
+       msc->part = part;
+
+       err = mfmstrategy(msc, F_READ, LABELSECTOR, DEV_BSIZE, io_buf, &i);
+       if (err) {
+               printf("reading disklabel: %s\n", strerror(err));
+               return 0;
+       }
+       msg = getdisklabel(io_buf + LABELOFFSET, lp);
+       if (msg)
+               printf("getdisklabel: %s\n", msg);
+
+       f->f_devdata = (void *) msc;
+
+       {
+               int             k;
+               unsigned char  *ucp;
+               struct mfm_xbn *xp;
+
+               /* mfmstrategy(msc, F_READ, -16, 8192, io_buf, &i); */
+               mfmstrategy(msc, F_READ, -16, 512, io_buf, &i);
+               printf("dumping raw disk-block #0:\n");
+               ucp = io_buf;
+               for (k = 0; k < 128; k++) {
+                       if (ucp[k] < 0x10)
+                               printf("0");
+                       printf("%x ", ucp[k]);
+                       if (k % 8 == 7)
+                               printf("  ");
+                       if (k % 16 == 15)
+                               printf("\n");
+               }
+               printf("\n");
+
+               xp = (void *) io_buf;
+               display_xbn(xp);
+               printf("\n");
+
+       }
+
+       if (unit == 2) {        /* floppy! */
+               if (lp->d_ntracks != 2) {
+                       printf("changing number of tracks from %d to %d.\n",
+                              lp->d_ntracks, 2);
+                       lp->d_ntracks = 2;
+               }
+       } else {                /* hard-disk */
+               unsigned short *usp = (void *) io_buf;
+               printf("label says: s/t/c = %d/%d/%d\n",
+                      lp->d_nsectors, lp->d_ntracks, lp->d_ncylinders);
+
+               if (lp->d_nsectors != usp[13]) {
+                       printf("changing number of sectors from %d to %d.\n",
+                              lp->d_nsectors, usp[13]);
+                       lp->d_nsectors = usp[13];
+               }
+               if (lp->d_ntracks != usp[14]) {
+                       printf("changing number of heads/tracks from %d to %d.\n",
+                              lp->d_ntracks, usp[14]);
+                       lp->d_ntracks = usp[14];
+               }
+               if (lp->d_ncylinders != usp[15]) {
+                       printf("changing number of cylinders from %d to %d.\n",
+                              lp->d_ncylinders, usp[15]);
+                       lp->d_ncylinders = usp[15];
+               }
+               lp->d_secpercyl = lp->d_nsectors * lp->d_ntracks;
+       }
+
+       return (0);
+}
+
+mfm_rxstrategy(msc, func, dblk, size, buf, rsize)
+       struct mfm_softc *msc;
+       int     func;
+       daddr_t dblk;
+       char    *buf;
+       int     size, *rsize;
+{
+       struct disklabel *lp;
+       int     block, sect, head, cyl, scount, i, cmd, res, sval;
+
+       lp = &mfmlabel;
+       block = (dblk < 0 ? 0 : dblk + lp->d_partitions[msc->part].p_offset);
+
+       mfm_rxselect(msc->unit);
+
+       /*
+        * if label is empty, assume RX33
+        */
+       if (lp->d_nsectors == 0)
+               lp->d_nsectors = 15;
+       if (lp->d_ntracks == 0)
+               lp->d_ntracks = 2;
+       if (lp->d_secpercyl == 0)
+               lp->d_secpercyl = 30;
+
+       bzero((void *) 0x200D0000, size);
+       scount = size / 512;
+
+       while (scount) {
+               /*
+                * prepare drive/operation parameter
+                */
+               cyl = block / lp->d_secpercyl;
+               sect = block % lp->d_secpercyl;
+               head = sect / lp->d_nsectors;
+               sect = sect % lp->d_nsectors;
+
+               /*
+                * *rsize = 512;                /* one sector after the other
+                * ...
+                */
+               *rsize = 512 * min(scount, lp->d_nsectors - sect);
+
+               /*
+                * now initialize the register values ...
+                */
+               creg.udc_dma7 = 0;
+               creg.udc_dma15 = 0;
+               creg.udc_dma23 = 0;
+
+               creg.udc_dsect = sect + 1;      /* sectors are numbered 1..15
+                                                * !!! */
+               head |= (cyl >> 4) & 0x70;
+               creg.udc_dhead = head;
+               creg.udc_dcyl = cyl;
+
+               creg.udc_scnt = *rsize / 512;
+
+               if (func == F_WRITE) {
+                       creg.udc_rtcnt = UDC_RC_RX33WRT;
+                       creg.udc_mode = UDC_MD_RX33;
+                       creg.udc_term = UDC_TC_FDD;
+
+                       mfm_rxprepare();
+                       /* copy from buf */
+                       bcopy(buf, (void *) 0x200D0000, *rsize);
+                       res = mfm_command(DKC_CMD_WRITE_RX33);
+               } else {
+                       creg.udc_rtcnt = UDC_RC_RX33READ;
+                       creg.udc_mode = UDC_MD_RX33;
+                       creg.udc_term = UDC_TC_FDD;
+
+                       mfm_rxprepare();
+                       /* clear disk buffer */
+                       bzero((void *) 0x200D0000, *rsize);
+                       res = mfm_command(DKC_CMD_READ_RX33);
+                       /* copy to buf */
+                       bcopy((void *) 0x200D0000, buf, *rsize);
+               }
+
+               scount -= *rsize / 512;
+               block += *rsize / 512;
+               buf += *rsize;
+       }
+
+       *rsize = size;
+       return 0;
+}
+
+mfm_rdstrategy(msc, func, dblk, size, buf, rsize)
+       struct mfm_softc *msc;
+       int     func;
+       daddr_t dblk;
+       char    *buf;
+       int     size, *rsize;
+{
+       struct disklabel *lp;
+       int     block, sect, head, cyl, scount, i, cmd, res, sval;
+
+       lp = &mfmlabel;
+       block = (dblk < 0 ? 0 : dblk + lp->d_partitions[msc->part].p_offset);
+
+       /*
+        * if label is empty, assume RD32 (XXX this must go away!!!)
+        */
+       if (lp->d_nsectors == 0)
+               lp->d_nsectors = 17;
+       if (lp->d_ntracks == 0)
+               lp->d_ntracks = 6;
+       if (lp->d_secpercyl == 0)
+               lp->d_secpercyl = 102;
+
+       mfm_rdselect(msc->unit);
+
+       bzero((void *) 0x200D0000, size);
+       scount = size / 512;
+
+       while (scount) {
+               /*
+                * prepare drive/operation parameter
+                */
+               cyl = block / lp->d_secpercyl;
+               sect = block % lp->d_secpercyl;
+               head = sect / lp->d_nsectors;
+               sect = sect % lp->d_nsectors;
+
+               if (dblk < 0) {
+                       printf("using raw diskblock-data!\n");
+                       printf("block %d, dblk %d ==> cyl %d, head %d, sect %d\n",
+                              block, dblk, cyl, sect, head);
+               } else
+                       cyl += 1;       /* first cylinder is reserved for
+                                        * controller! */
+
+               *rsize = 512 * min(scount, lp->d_nsectors - sect);
+               /*
+                * now re-initialize the register values ...
+                */
+               creg.udc_dma7 = 0;
+               creg.udc_dma15 = 0;
+               creg.udc_dma23 = 0;
+
+               creg.udc_dsect = sect;
+               head |= (cyl >> 4) & 0x70;
+               creg.udc_dhead = head;
+               creg.udc_dcyl = cyl;
+
+               creg.udc_scnt = *rsize / 512;
+
+               if (func == F_WRITE) {
+                       creg.udc_rtcnt = UDC_RC_HDD_WRT;
+                       creg.udc_mode = UDC_MD_HDD;
+                       creg.udc_term = UDC_TC_HDD;
+                       cmd = DKC_CMD_WRITE_HDD;
+
+                       bcopy(buf, (void *) 0x200D0000, *rsize);
+                       res = mfm_command(cmd);
+               } else {
+                       creg.udc_rtcnt = UDC_RC_HDD_READ;
+                       creg.udc_mode = UDC_MD_HDD;
+                       creg.udc_term = UDC_TC_HDD;
+                       cmd = DKC_CMD_READ_HDD;
+
+                       bzero((void *) 0x200D0000, *rsize);
+                       res = mfm_command(cmd);
+                       bcopy((void *) 0x200D0000, buf, *rsize);
+               }
+
+               scount -= *rsize / 512;
+               block += *rsize / 512;
+               buf += *rsize;
+       }
+
+       /*
+        * unselect the drive ...
+        */
+       mfm_command(DKC_CMD_DRDESELECT);
+
+       *rsize = size;
+       return 0;
+}
+
+int
+mfmstrategy(msc, func, dblk, size, buf, rsize)
+       struct mfm_softc *msc;
+       int     func;
+       daddr_t dblk;
+       char    *buf;
+       int     size, *rsize;
+{
+       int     res = -1;
+
+       switch (msc->unit) {
+       case 0:
+       case 1:
+               res = mfm_rdstrategy(msc, func, dblk, size, buf, rsize);
+               break;
+       case 2:
+               res = mfm_rxstrategy(msc, func, dblk, size, buf, rsize);
+               break;
+       default:
+               printf("invalid unit %d in mfmstrategy()\n");
+       }
+       return (res);
+}
index 43e368f..722b19d 100644 (file)
@@ -1,4 +1,4 @@
-/*     $NetBSD: ra.c,v 1.4 1996/02/17 18:23:23 ragge Exp $ */
+/*     $NetBSD: ra.c,v 1.5 1996/08/02 11:22:18 ragge Exp $ */
 /*
  * Copyright (c) 1995 Ludd, University of Lule}, Sweden.
  * All rights reserved.
@@ -31,8 +31,8 @@
 
  /* All bugs are subject to removal without further notice */
                
-#define NRSP 0 /* Kludge */
-#define NCMD 0 /* Kludge */
+#define NRSP 1 /* Kludge */
+#define NCMD 1 /* Kludge */
 
 #include "sys/param.h"
 #include "sys/disklabel.h"
 
 #include "../include/pte.h"
 #include "../include/macros.h"
+#include "../include/sid.h"
+
 #include "../uba/ubareg.h"
 #include "../uba/udareg.h"
-#include "../vax/mscp.h"
+
+#include "../mscp/mscp.h"
+#include "../mscp/mscpreg.h"
+
+#include "../bi/bireg.h"
+#include "../bi/kdbreg.h"
 
 #include "vaxstand.h"
 
@@ -62,10 +69,13 @@ struct ra_softc {
        int ubaddr;
        int part;
        int unit;
+       unsigned short *ra_ip;
+       unsigned short *ra_sa;
+       unsigned short *ra_sw;
 };
 
 volatile struct uda {
-        struct  uda1ca uda_ca;           /* communications area */
+        struct  mscp_1ca uda_ca;           /* communications area */
         struct  mscp uda_rsp;     /* response packets */
         struct  mscp uda_cmd;     /* command packets */
 } uda;
@@ -81,53 +91,84 @@ raopen(f, adapt, ctlr, unit, part)
         int ctlr, unit, part;
 {
        char *msg;
-       struct disklabel *lp=&ralabel;
-       volatile struct ra_softc *ra=&ra_softc;
-       volatile struct uba_regs *mr=(void *)ubaaddr[adapt];
+       struct disklabel *lp = &ralabel;
+       volatile struct ra_softc *ra = &ra_softc;
+       volatile struct uba_regs *mr = (void *)ubaaddr[adapt];
        volatile u_int *nisse;
-       unsigned short johan;
+       unsigned short johan, johan2;
        int i,err;
 
-       if(adapt>nuba) return(EADAPT);
-       if(ctlr>nuda) return(ECTLR);
        bzero(lp, sizeof(struct disklabel));
-       ra->udaddr=uioaddr[adapt]+udaaddr[ctlr];
-       ra->ubaddr=(int)mr;
-       ra->unit=unit;
+       ra->unit = unit;
        ra->part = part;
-       udacsr=(void*)ra->udaddr;
-       nisse=(u_int *)&mr->uba_map[0];
-       nisse[494]=PG_V|(((u_int)&uda)>>9);
-       nisse[495]=nisse[494]+1;
-       ubauda=(void*)0x3dc00+(((u_int)(&uda))&0x1ff);
+       if (vax_cputype != VAX_8200) {
+               if (adapt > nuba)
+                       return(EADAPT);
+               if (ctlr > nuda)
+                       return(ECTLR);
+               nisse = (u_int *)&mr->uba_map[0];
+               nisse[494] = PG_V | (((u_int)&uda) >> 9);
+               nisse[495] = nisse[494] + 1;
+               udacsr = (void*)uioaddr[adapt] + udaaddr[ctlr];
+               ubauda = (void*)0x3dc00 + (((u_int)(&uda))&0x1ff);
+               johan = (((u_int)ubauda) & 0xffff) + 8;
+               johan2 = 3;
+               ra->ra_ip = (short *)&udacsr->udaip;
+               ra->ra_sa = ra->ra_sw = (short *)&udacsr->udasa;
+               ra->udaddr = uioaddr[adapt] + udaaddr[ctlr];
+               ra->ubaddr = (int)mr;
+               *ra->ra_ip = 0; /* Start init */
+       } else {
+               struct bi_node *bi = (void *)biaddr[adapt];
+               struct kdb_regs *kb = (void *)&bi[ctlr];
+               volatile int i = 10000;
+
+               ra->ra_ip = &kb->kdb_ip;
+               ra->ra_sa = &kb->kdb_sa;
+               ra->ra_sw = &kb->kdb_sw;
+               johan = ((u_int)&uda.uda_ca.ca_rspdsc) & 0xffff;
+               johan2 = (((u_int)&uda.uda_ca.ca_rspdsc) & 0xffff0000) >> 16;
+               kb->kdb_bi.bi_csr |= BICSR_NRST;
+               while (i--) /* Need delay??? */
+                       ;
+               kb->kdb_bi.bi_ber = ~(BIBER_MBZ|BIBER_NMR|BIBER_UPEN);/* ??? */
+               ubauda = &uda;
+       }
+
        /* Init of this uda */
-       udacsr->udaip=0; /* Start init */
-       while((udacsr->udasa&UDA_STEP1) == 0);
-       udacsr->udasa=0x8000;
-       while((udacsr->udasa&UDA_STEP2) == 0);
-       johan=(((u_int)ubauda)&0xffff)+8;
-       udacsr->udasa=johan;
-       while((udacsr->udasa&UDA_STEP3) == 0);
-       udacsr->udasa=3;
-       while((udacsr->udasa&UDA_STEP4) == 0);
-       udacsr->udasa=0x0001;
-       uda.uda_ca.ca_rspdsc=(int)&ubauda->uda_rsp.mscp_cmdref;
-       uda.uda_ca.ca_cmddsc=(int)&ubauda->uda_cmd.mscp_cmdref;
+       while ((*ra->ra_sa & MP_STEP1) == 0)
+               ;
+
+       *ra->ra_sw = 0x8000;
+       while ((*ra->ra_sa & MP_STEP2) == 0)
+               ;
+
+       *ra->ra_sw = johan;
+       while ((*ra->ra_sa & MP_STEP3) == 0)
+               ;
+
+       *ra->ra_sw = johan2;
+       while ((*ra->ra_sa & MP_STEP4) == 0)
+               ;
+
+       *ra->ra_sw = 0x0001;
+       uda.uda_ca.ca_rspdsc = (int)&ubauda->uda_rsp.mscp_cmdref;
+       uda.uda_ca.ca_cmddsc = (int)&ubauda->uda_cmd.mscp_cmdref;
+
        command(M_OP_SETCTLRC);
-       uda.uda_cmd.mscp_unit=ra->unit;
+       uda.uda_cmd.mscp_unit = ra->unit;
        command(M_OP_ONLINE);
 
-       err=rastrategy(ra,F_READ, LABELSECTOR, DEV_BSIZE, io_buf, &i);
+       err = rastrategy(ra,F_READ, LABELSECTOR, DEV_BSIZE, io_buf, &i);
        if(err){
                printf("reading disklabel: %s\n",strerror(err));
                return 0;
        }
 
-       msg=getdisklabel(io_buf+LABELOFFSET, lp);
-       if(msg) {
-               printf("getdisklabel: %s\n",msg);
-       }
-       f->f_devdata=(void *)ra;
+       msg = getdisklabel(io_buf+LABELOFFSET, lp);
+       if (msg)
+               printf("getdisklabel: %s\n", msg);
+       f->f_devdata = (void *)ra;
        return(0);
 }
 
@@ -136,13 +177,14 @@ command(cmd)
 {
        volatile int hej;
 
-       uda.uda_cmd.mscp_opcode=cmd;
-       uda.uda_cmd.mscp_msglen=MSCP_MSGLEN;
-       uda.uda_rsp.mscp_msglen=MSCP_MSGLEN;
+       uda.uda_cmd.mscp_opcode = cmd;
+       uda.uda_cmd.mscp_msglen = MSCP_MSGLEN;
+       uda.uda_rsp.mscp_msglen = MSCP_MSGLEN;
        uda.uda_ca.ca_rspdsc |= MSCP_OWN|MSCP_INT;
        uda.uda_ca.ca_cmddsc |= MSCP_OWN|MSCP_INT;
-       hej=udacsr->udaip;
-       while(uda.uda_ca.ca_rspdsc<0);
+       hej = *ra_softc.ra_ip;
+       while(uda.uda_ca.ca_rspdsc<0)
+               ;
 
 }
 
@@ -161,20 +203,23 @@ rastrategy(ra, func, dblk, size, buf, rsize)
        volatile int hej;
 
 
-       ur = (void *)ra->ubaddr;
-       udadev = (void*)ra->udaddr;
-       ptmapp = (u_int *)&ur->uba_map[0];
-       lp = &ralabel;
+       if (vax_cputype != VAX_8200) {
+               ur = (void *)ra->ubaddr;
+               udadev = (void*)ra->udaddr;
+               ptmapp = (u_int *)&ur->uba_map[0];
 
-       pfnum = (u_int)buf >> PGSHIFT;
+               pfnum = (u_int)buf >> PGSHIFT;
 
-       for(mapnr = 0, nsize = size; (nsize + NBPG) > 0; nsize -= NBPG)
-               ptmapp[mapnr++] = PG_V | pfnum++;
+               for(mapnr = 0, nsize = size; (nsize + NBPG) > 0; nsize -= NBPG)
+                       ptmapp[mapnr++] = PG_V | pfnum++;
+               uda.uda_cmd.mscp_seq.seq_buffer = ((u_int)buf) & 0x1ff;
+       } else
+               uda.uda_cmd.mscp_seq.seq_buffer = ((u_int)buf);
 
+       lp = &ralabel;
        uda.uda_cmd.mscp_seq.seq_lbn =
            dblk + lp->d_partitions[ra->part].p_offset;
        uda.uda_cmd.mscp_seq.seq_bytecount = size;
-       uda.uda_cmd.mscp_seq.seq_buffer = ((u_int)buf) & 0x1ff;
        uda.uda_cmd.mscp_unit = ra->unit;
        if (func == F_WRITE)
                command(M_OP_WRITE);
diff --git a/sys/arch/vax/boot/rom.c b/sys/arch/vax/boot/rom.c
new file mode 100644 (file)
index 0000000..f299f50
--- /dev/null
@@ -0,0 +1,123 @@
+/*     $NetBSD: rom.c,v 1.1 1996/08/02 11:22:21 ragge Exp $ */
+/*
+ * Copyright (c) 1996 Ludd, University of Lule}, Sweden.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Ludd by
+ * Bertram Barth.
+ *
+ * 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 at Ludd, University of 
+ *      Lule}, Sweden and its contributors.
+ * 4. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "sys/param.h"
+#include "sys/reboot.h"
+#include "sys/disklabel.h"
+
+#include "lib/libsa/stand.h"
+#include "lib/libsa/ufs.h"
+
+#include "../include/pte.h"
+#include "../include/sid.h"
+#include "../include/mtpr.h"
+#include "../include/reg.h"
+#include "../include/rpb.h"
+
+#include "data.h"
+#include "vaxstand.h"
+
+extern unsigned *bootregs;
+extern struct rpb *rpb;
+
+struct rom_softc {
+       int part;
+       int unit;
+};
+
+int    romstrategy(), romopen();
+struct disklabel romlabel;
+struct  rom_softc rom_softc;
+char   io_buf[MAXBSIZE];
+
+romopen(f, adapt, ctlr, unit, part)
+       struct open_file *f;
+        int ctlr, unit, part;
+{
+       char *msg;
+       struct disklabel *lp = &romlabel;
+       volatile struct rom_softc *rsc = &rom_softc;
+       int i,err;
+
+       bootregs[11] = XXRPB;
+       rpb = (void*)XXRPB;
+       bqo = (void*)rpb->iovec;
+
+       if (rpb->unit > 0 && (rpb->unit % 100) == 0) {
+               printf ("changing rpb->unit from %d ", rpb->unit);
+               rpb->unit /= 100;
+               printf ("to %d\n", rpb->unit);
+       }
+
+       bzero(lp, sizeof(struct disklabel));
+       rsc->unit = unit;
+       rsc->part = part;
+
+       err = romstrategy(rsc, F_READ, LABELSECTOR, DEV_BSIZE, io_buf, &i);
+       if (err) {
+               printf("reading disklabel: %s\n",strerror(err));
+               return 0;
+       }
+       msg = getdisklabel(io_buf+LABELOFFSET, lp);
+       if (msg)
+               printf("getdisklabel: %s\n",msg);
+       f->f_devdata = (void*)rsc;
+       return(0);
+}
+
+romstrategy (rsc, func, dblk, size, buf, rsize)
+       struct  rom_softc *rsc;
+       int     func;
+       daddr_t dblk;
+       char    *buf;
+       int     size, *rsize;
+{
+       struct  disklabel *lp;
+       int     block;
+
+       lp = &romlabel;
+       block = dblk + lp->d_partitions[rsc->part].p_offset;
+       if (rsc->unit >= 0 && rsc->unit < 10)
+               rpb->unit = rsc->unit;
+
+       if (func == F_WRITE)
+               romwrite_uvax(block, size, buf, bootregs);
+       else
+               romread_uvax(block, size, buf, bootregs);
+
+       *rsize = size;
+       return 0;
+}
+
index 9662807..ff893c4 100644 (file)
@@ -1,4 +1,4 @@
-/*     $NetBSD: romread.s,v 1.3 1995/09/16 16:20:18 ragge Exp $ */
+/*     $NetBSD: romread.s,v 1.4 1996/08/02 11:22:24 ragge Exp $ */
 /*
  * Copyright (c) 1995 Ludd, University of Lule}, Sweden.
  * All rights reserved.
 
 #include "../include/asm.h"
 
-/*
- * read630 (int block, int *regs)
- */
-ENTRY(read630, 0xFFE)
-       pushl   $0                      # base of rpb
-       pushl   $0                      # virtual-flag 
-       pushl   $33                     # read-logical-block
-       pushl   12(ap)                  # lbn to start reading
-       pushl   8(ap)                   # number of bytes to read
-       pushl   4(ap)                   # buffer-address 
-       calls   $6, (r6)        # call the qio-routine
-       halt
-       ret                     # r0 holds the result
-
 /*
  * read750 (int block, int *regs)
  */
@@ -72,9 +58,9 @@ ENTRY(read750, 0xFFE)
        ret
 
 /*
- * bulkread630 (int lbn, int size, void *buf, int *regs)
+ * romread_uvax (int lbn, int size, void *buf, int *regs)
  */
-ENTRY(bulkread630, 0xFFE)
+ENTRY(romread_uvax, 0xFFE)
        movl    16(ap), r11     # array of bootregs
        movl    44(r11), r11    # restore boot-contents of r11 (rpb)
        movl    52(r11), r7     # load iovec/bqo into r7
@@ -87,3 +73,21 @@ ENTRY(bulkread630, 0xFFE)
        pushl   12(ap)                  # buffer-address 
        calls   $6, (r6)        # call the qio-routine
        ret                     # r0 holds the result
+
+/*
+ * romwrite_uvax (int lbn, int size, void *buf, int *regs)
+ */
+ENTRY(romwrite_uvax, 0xFFE)
+       movl    16(ap), r11     # array of bootregs
+       movl    44(r11), r11    # restore boot-contents of r11 (rpb)
+       movl    52(r11), r7     # load iovec/bqo into r7
+       addl3   (r7), r7, r6    # load qio into r6
+       pushl   r11                     # base of rpb
+       pushl   $0                      # virtual-flag 
+       pushl   $32                     # write-logical-block
+       pushl   4(ap)                   # lbn to start reading
+       pushl   8(ap)                   # number of bytes to read
+       pushl   12(ap)                  # buffer-address 
+       calls   $6, (r6)        # call the qio-routine
+       ret                     # r0 holds the result
+
diff --git a/sys/arch/vax/boot/samachdep.h b/sys/arch/vax/boot/samachdep.h
new file mode 100644 (file)
index 0000000..829a17d
--- /dev/null
@@ -0,0 +1,42 @@
+/*     $NetBSD: samachdep.h,v 1.1 1996/08/02 11:22:28 ragge Exp $      */
+
+/*
+ * Copyright (c) 1982, 1990, 1993
+ *     The Regents of the University of California.  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.
+ *
+ *     @(#)samachdep.h 8.1 (Berkeley) 6/10/93
+ */
+
+#define        NSCSI           1
+#define NSD            8
+
+extern int howto;
+extern unsigned int bootdev;
diff --git a/sys/arch/vax/boot/scsi_hi.c b/sys/arch/vax/boot/scsi_hi.c
new file mode 100644 (file)
index 0000000..0102123
--- /dev/null
@@ -0,0 +1,297 @@
+/*     $NetBSD: scsi_hi.c,v 1.1 1996/08/02 11:22:31 ragge Exp $        */
+
+/****************************************************************************
+ * NS32K Monitor SCSI high-level driver
+ * Bruce Culbertson
+ * 8 March 1990
+ * (This source is public domain source)
+ *
+ * There are three monitor SCSI commands.  "Read" and "write" I think are
+ * fairly self explanatory once you read the help messages.  They, in fact,
+ * execute the "extended read", "extended write", and "request sense"
+ * commands from the SCSI standard.
+ * 
+ * "Raw" lets you execute any SCSI command but you need a SCSI reference to
+ * know what the commands are and what their formats are.  The SCSI
+ * standard specifies that there are six buffers which, for example, hold a
+ * SCSI command or are the source or destination for data.  You provide
+ * "raw" with an array of pointers to the six buffers.  Using "edit", you
+ * can enter a SCSI command somewhere in memory and you can create the
+ * array of pointers.  The array must actually be eight entries long; two
+ * entries are not used.  By typing "raw <array address>", the SCSI command
+ * is executed.
+ * 
+ * By the way, "read", "write", and "raw" talk only to the DP8490 SCSI
+ * controller.  I have not had time to read the Adaptec data sheet and
+ * write a driver for it.
+ ****************************************************************************/
+#include "so.h"
+
+#define OK                     0
+#define NOT_OK                 OK+1
+#define        PRIVATE
+#define PUBLIC
+#define U8                     unsigned char
+
+long   scsiAdr = DEFAULT_SCSI_ADR,     /* default SCSI address */
+       scsiLun = DEFAULT_SCSI_LUN;
+
+struct cmd_desc {                      /* SCSI command description */
+  const U8     *cmd;                   /* command string */
+  const U8     *odata;                 /* data to output, if any */
+  const struct cmd_desc *chain;                /* next command */
+};
+
+struct drive {                         /* SCSI drive description */
+  U8   adr, lun;                       /* SCSI address and LUN */
+  U8   flags;                          /* drive characteristics */
+  U8   stat;                           /* drive state */
+  const struct cmd_desc *init;         /* list of initialize commands */
+};
+/* for drive.flags */
+#define EXTENDED_RDWR          1       /* device does extended read, write */
+#define EXTENDED_SENSE         2       /* device does extended sense */
+/* for drive.stat */
+#define INITIALIZED            1       /* device is initialized */
+
+PRIVATE struct drive drive_tbl[] = {
+#if 1
+  {0, 0, 0, 1, 0},
+  {1, 0, 0, 1, 0},
+  {2, 0, 0, 1, 0},
+  {3, 0, 0, 1, 0},
+  {4, 0, 0, 1, 0},
+  {5, 0, 0, 1, 0},
+  {6, 0, 0, 1, 0},
+  {7, 0, 0, 1, 0},
+#else
+  {0, 0, EXTENDED_RDWR | EXTENDED_SENSE, 1, 0},
+  {1, 0, EXTENDED_RDWR | EXTENDED_SENSE, 1, 0},
+  {2, 0, EXTENDED_RDWR | EXTENDED_SENSE, 1, 0},
+  {3, 0, EXTENDED_RDWR | EXTENDED_SENSE, 1, 0},
+  {4, 0, EXTENDED_RDWR | EXTENDED_SENSE, 1, 0},
+  {5, 0, EXTENDED_RDWR | EXTENDED_SENSE, 1, 0},
+  {6, 0, EXTENDED_RDWR | EXTENDED_SENSE, 1, 0},
+  {7, 0, EXTENDED_RDWR | EXTENDED_SENSE, 1, 0},
+#endif
+};
+#define DRV_TBL_SZ (sizeof (drive_tbl) / sizeof (struct drive))
+
+/* Round up to multiple of four since SCSI transfers are always multiples
+ * of four bytes.
+ */
+#define CMD_LEN                12              /* longest SCSI command */
+#define SENSE_LEN      24              /* extended sense length */
+#define MSG_LEN                4
+#define STAT_LEN       4
+
+#define MAX_SCSI_RETRIES       6
+#define CMD_IX         2
+#define CMD_SENSE      0x03
+#define CMD_READ       0x08
+#define CMD_WRITE      0x0a
+#define CMD_XREAD      0x28
+#define CMD_XWRITE     0x2a
+PRIVATE U8             cmd_buf[CMD_LEN];
+
+#define SENSE_KEY      2
+#define NO_SENSE       0
+#define RECOVERY_ERR   1
+#define UNIT_ATTN      6
+#define ADD_SENSE_CODE 12
+#define SENSE_RST      0x29
+PRIVATE        U8              sense_buf[SENSE_LEN];
+
+#define CHECK_CONDITION        2
+#define STAT_IX                3
+#define STAT_MASK      0x1f
+PRIVATE U8             stat_buf[STAT_LEN];
+#define IMSG_IX                7
+PRIVATE U8             msg_buf[MSG_LEN];
+
+#define ODATA_IX       0
+#define IDATA_IX       1
+PRIVATE struct scsi_args scsi_args;
+
+/*===========================================================================*
+ *                             sc_rdwt                                      * 
+ *===========================================================================*/
+/* Carry out a read or write request for the SCSI disk. */
+PRIVATE int
+sc_rdwt(op, block, ram_adr, len, sc_adr, lun)
+long block, ram_adr, len, sc_adr, lun;
+{
+  int retries, ret;
+  U8 *p;
+  struct drive *dp;
+
+  printf ("sc_rdwt: op %x, block %d, ram %x, len %d, sc_adr %d, lun %d\n",
+         op, block, ram_adr, len, sc_adr, lun);
+
+  /* get drive characteristics */
+  for (dp = drive_tbl; dp < drive_tbl + DRV_TBL_SZ - 1; ++dp)
+    if (dp->adr == sc_adr && dp->lun == lun) break;
+  if (dp == drive_tbl + DRV_TBL_SZ - 1) {
+    dp->adr = sc_adr;                  /* have default, set adr, lun */
+    dp->lun = lun;
+  }
+  for (retries = 0; retries < MAX_SCSI_RETRIES; ++retries) {
+    if (dp->init && !(dp->stat & INITIALIZED))
+      if (OK != sc_initialize (dp)) {
+       printf("SCSI cannot initialize device\n");
+       return NOT_OK;
+      }
+    p = cmd_buf;                       /* build SCSI command */
+    if (dp->flags & EXTENDED_RDWR) {   /* use extended commands */
+      *p++ = (op == DISK_READ)? CMD_XREAD: CMD_XWRITE;
+      *p++ = lun << 5;
+      *p++ = (block >> 24) & 0xff;
+      *p++ = (block >> 16) & 0xff;
+      *p++ = (block >> 8) & 0xff;
+      *p++ = (block >> 0) & 0xff;
+      *p++ = 0;
+      *p++ = (len >> 8) & 0xff;
+      *p++ = (len >> 0) & 0xff;
+      *p = 0;
+    } else {                           /* use short (SASI) commands */
+      *p++ = (op == DISK_READ)? CMD_READ: CMD_WRITE;
+      *p++ = (lun << 5) | ((block >> 16) & 0x1f);
+      *p++ = (block >> 8) & 0xff;
+      *p++ = (block >> 0) & 0xff;
+      *p++ = len;
+      *p = 0;
+    }
+    if (op == DISK_READ)
+      ret = exec_scsi_hi (cmd_buf, (U8 *)ram_adr, (U8 *)0, dp);
+    else
+      ret = exec_scsi_hi (cmd_buf, (U8 *)0, (U8 *)ram_adr, dp);
+    if (OK == ret) return OK;
+    dp->stat &= ~INITIALIZED;
+  }
+  printf("SCSI %s, block %d failed even after retries\n",
+    op == DISK_READ? "READ": "WRITE", block);
+  return NOT_OK;
+}
+
+/*===========================================================================*
+ *                             sc_initialize                                *
+ *===========================================================================*/
+/* Execute the list of initialization commands for the given drive.
+ */
+int
+sc_initialize (dp)
+struct drive *dp;
+{
+  const struct cmd_desc *cp;
+
+  for (cp = dp->init; cp != 0; cp = cp->chain)
+    if (OK != exec_scsi_hi (cp->cmd, 0, cp->odata, dp)) {
+      dp->stat &= ~INITIALIZED;
+      return NOT_OK;
+    }
+  dp->stat |= INITIALIZED;
+  return OK;
+}
+
+/*===========================================================================*
+ *                             exec_scsi_hi                                 * 
+ *===========================================================================*/
+/* Execute a "high-level" SCSI command.  This means execute a low level
+ * command and, if it fails, execute a request sense to find out why.
+ */
+PRIVATE int
+exec_scsi_hi(cmd, data_in, data_out, dp)
+U8 *cmd, *data_out, *data_in;
+struct drive *dp;
+{
+  scsi_args.ptr[CMD_IX] = (long)cmd;
+  scsi_args.ptr[STAT_IX] = (long)stat_buf;
+  scsi_args.ptr[IMSG_IX] = (long)msg_buf;
+  scsi_args.ptr[IDATA_IX] = (long)data_in;
+  scsi_args.ptr[ODATA_IX] = (long)data_out;
+  if (OK != exec_scsi_low (&scsi_args, dp->adr))
+    return NOT_OK;
+  *stat_buf &= STAT_MASK;              /* strip off lun */
+  if (*stat_buf == 0)
+    /* Success -- this should be the usual case */
+    return OK;
+  if (*stat_buf != CHECK_CONDITION) {
+    /* do not know how to handle this so return error */
+    printf("SCSI device returned unknown status: %d\n", *stat_buf);
+    return NOT_OK;
+  }
+  /* Something funny happened, need to execute request-sense command
+   * to learn more.
+   */
+  if (OK == get_sense(dp))
+    /* Something funny happened, but the device recovered from it and
+     * the command succeeded.
+     */
+    return OK;
+  return NOT_OK;
+}
+
+/*===========================================================================*
+ *                             get_sense                                    * 
+ *===========================================================================*/
+/* Execute a "request sense" SCSI command and check results.  When a SCSI
+ * command returns CHECK_CONDITION, a request-sense command must be executed.
+ * A request-sense command provides information about the original command.
+ * The original command might have succeeded, in which case it does not
+ * need to be retried and OK is returned.  Examples: read error corrected
+ * with error correction code, or error corrected by retries performed by
+ * the SCSI device.  The original command also could have failed, in
+ * which case NOT_OK is returned.
+ */
+#define XLOGICAL_ADR   \
+  (sense_buf[3]<<24 | sense_buf[4]<<16 | sense_buf[5]<<8 | sense_buf[6])
+#define LOGICAL_ADR    \
+  (sense_buf[1]<<16 | sense_buf[2]<<8 | sense_buf[3])
+
+PRIVATE int
+get_sense (dp)
+struct drive *dp;
+{
+  U8 *p;
+
+  p = cmd_buf;                         /* build SCSI command */
+  *p++ = CMD_SENSE;
+  *p++ = dp->lun << 5;
+  *p++ = 0;
+  *p++ = 0;
+  *p++ = (dp->flags & EXTENDED_SENSE)? SENSE_LEN: 0;
+  *p = 0;
+  scsi_args.ptr[IDATA_IX] = (long)sense_buf;
+  scsi_args.ptr[ODATA_IX] = 0;
+  scsi_args.ptr[CMD_IX] = (long)cmd_buf;
+  scsi_args.ptr[STAT_IX] = (long)stat_buf;
+  scsi_args.ptr[IMSG_IX] = (long)msg_buf;
+  if (OK != exec_scsi_low (&scsi_args, dp->adr)) {
+    printf("SCSI SENSE command failed\n");
+    return NOT_OK;
+  }
+  if ((*stat_buf & STAT_MASK) != 0) {
+    printf("SCSI SENSE returned wrong status %d\n", *stat_buf);
+    return NOT_OK;
+  }
+  if (0 == (dp->flags & EXTENDED_SENSE)) {
+    printf("SCSI request sense, code 0x%x, log_adr 0x%x\n",
+      sense_buf[0], LOGICAL_ADR);
+    return NOT_OK;
+  }
+  switch (sense_buf[SENSE_KEY] & 0xf) {
+    case NO_SENSE:
+    case UNIT_ATTN:                    /* reset */
+      return NOT_OK;                   /* must retry command */
+    case RECOVERY_ERR:
+      /* eventually, we probably do not want to hear about these. */
+      printf("SCSI ok with recovery, code 0x%x, logical address 0x%x\n",
+            sense_buf[ADD_SENSE_CODE], XLOGICAL_ADR);
+      return OK;                       /* orig command was ok with recovery */
+    default:
+      printf("SCSI failure: key 0x%x code 0x%x log adr 0x%x sense buf 0x%x\n",
+            sense_buf[SENSE_KEY], sense_buf[ADD_SENSE_CODE],
+       XLOGICAL_ADR, sense_buf);
+      return NOT_OK;                   /* orig command failed */
+  }
+}
diff --git a/sys/arch/vax/boot/scsi_low.c b/sys/arch/vax/boot/scsi_low.c
new file mode 100644 (file)
index 0000000..a86a82d
--- /dev/null
@@ -0,0 +1,479 @@
+/*     $NetBSD: scsi_low.c,v 1.1 1996/08/02 11:22:34 ragge Exp $       */
+
+/****************************************************************************
+ * NS32K Monitor SCSI low-level driver
+ * Bruce Culbertson
+ * 8 March 1990
+ * (This source is public domain source.)
+ *
+ * Originally written by Bruce Culbertson for a ns32016 port of Minix.
+ * Adapted from that for the pc532 (ns32632) monitor.
+ * Adapted from that for NetBSD/pc532 by Philip L. Bunde.
+ *
+ * Do not use DMA -- makes 32016 and pc532 versions compatible.
+ * Do not use interrupts -- makes it harder for the user code to bomb
+ * this code.
+ ****************************************************************************/
+
+#include "so.h"
+#include "ka410.h"
+
+#define BB_DEBUG(x)    printf x
+#define CLEAR_INTR()   *ka410_intclr=INTR_SC
+#define CHECK_INTR()   *ka410_intreq&INTR_SC
+
+#define OK             0
+#define NOT_OK         OK+1
+#define        PRIVATE
+#define PUBLIC
+#define WR_ADR(adr,val)        (*((volatile unsigned char *)(adr))=(val))
+#define RD_ADR(adr)    (*((volatile unsigned char *)(adr)))
+/* #define AIC6250             0 */
+/* #define DP8490              1 */
+#define MAX_CACHE      0x4000
+
+/* SCSI bus phases
+ */
+#define PH_ODATA       0
+#define PH_IDATA       1
+#define PH_CMD         2
+#define PH_STAT                3
+#define PH_IMSG                7
+#define PH_NONE                8
+#define PH_IN(phase)   ((phase) & 1)
+
+/* NCR5380 SCSI controller registers
+ */
+#define SC_CTL         0x200C0080      /* base for control registers */
+#define SC_DMA         0x200D0000      /* base for data registers (8/16K) */
+#define SC_CURDATA     SC_CTL+(4*0)
+#define SC_OUTDATA     SC_CTL+(4*0)
+#define SC_ICMD                SC_CTL+(4*1)
+#define SC_MODE                SC_CTL+(4*2)
+#define SC_TCMD                SC_CTL+(4*3)
+#define SC_STAT1       SC_CTL+(4*4)
+#define SC_STAT2       SC_CTL+(4*5)
+#define SC_START_SEND  SC_CTL+(4*5)
+#define SC_INDATA      SC_CTL+(4*6)
+#define SC_RESETIP     SC_CTL+(4*7)
+#define SC_START_RCV   SC_CTL+(4*7)
+
+/* Bits in NCR5380 registers
+ */
+#define SC_A_RST       0x80
+#define SC_A_SEL       0x04
+#define SC_S_SEL       0x02
+#define SC_S_REQ       0x20
+#define SC_S_BSY       0x40
+#define SC_S_BSYERR    0x04
+#define SC_S_PHASE     0x08
+#define SC_S_IRQ       0x10
+#define SC_S_DRQ       0x40
+#define SC_M_DMA       0x02
+#define SC_M_BSY       0x04
+#define SC_ENABLE_DB   0x01
+
+/* Status of interrupt routine, returned in m1_i1 field of message.
+ */
+#define ISR_NOTDONE    0
+#define ISR_OK         1
+#define ISR_BSYERR     2
+#define ISR_RSTERR     3
+#define ISR_BADPHASE   4
+#define ISR_TIMEOUT    5
+
+#define ICU_ADR                0xfffffe00
+#define ICU_IO         (ICU_ADR+20)
+#define ICU_DIR                (ICU_ADR+21)
+#define ICU_DATA       (ICU_ADR+19)
+#define ICU_SCSI_BIT   0x80
+
+/* Miscellaneous
+ */
+#define MAX_WAIT       (1000*1000)
+#define SC_LOG_LEN     32
+
+PRIVATE struct scsi_args       *sc_ptrs;
+PRIVATE char                   sc_cur_phase,
+                               sc_reset_done = 1,
+                               sc_have_msg,
+                               sc_accept_int,
+                               sc_dma_dir;
+
+long   sc_dma_port = SC_DMA,
+       sc_dma_adr;
+
+#ifdef DEBUG
+struct sc_log {
+  unsigned char stat1, stat2;
+}                              sc_log [SC_LOG_LEN],
+                               *sc_log_head = sc_log;
+int                            sc_spurious_int;
+#endif
+unsigned char
+       sc_watchdog_error;              /* watch dog error */
+
+/* error messages */
+char *scsi_errors[] = {
+  0,                                   /* ISR_NOTDONE */
+  0,                                   /* ISR_OK */
+  "busy error",                                /* ISR_BSYERR */
+  "reset error",                       /* ISR_RSTERR */
+  "NULL pointer for current phase",    /* ISR_BADPHASE */
+  "timeout",                           /* ISR_TIMEOUT */
+};
+
+/*===========================================================================*
+ *                             exec_scsi_low                                * 
+ *===========================================================================*/
+/* Execute a generic SCSI command.  Passed pointers to eight buffers:
+ * data-out, data-in, command, status, dummy, dummy, message-out, message-in.
+ */
+PUBLIC
+int
+exec_scsi_low (args, scsi_adr)
+struct scsi_args *args;
+long scsi_adr;
+{
+  int ret;
+
+  BB_DEBUG (("exec_scsi_low(0x%x, %d)\n", args, scsi_adr));
+
+  sc_ptrs = args;                      /* make pointers globally accessible */
+  /* bertram ??? scCtlrSelect (DP8490); */
+  if (!sc_reset_done) sc_reset();
+  /* TCMD has some undocumented behavior in initiator mode.  I think the
+   * data bus cannot be enabled if i/o is asserted.
+   */
+  WR_ADR (SC_TCMD, 0);
+  if (OK != sc_wait_bus_free ()) {     /* bus-free phase */
+    printf("SCSI: bus not free\n");
+    return NOT_OK;
+  }
+  sc_cur_phase = PH_NONE;
+  sc_have_msg = 0;
+  if (OK != sc_select (scsi_adr))      /* select phase */
+    return NOT_OK;
+  sc_watchdog_error = 0;
+  ret = sc_receive ();                 /* isr does the rest */
+  if (ret == ISR_OK) return OK;
+  else {
+    sc_reset();
+    printf("SCSI: %s\n", scsi_errors[ret]);
+    return NOT_OK;
+  }
+}
+
+/*===========================================================================*
+ *                             sc_reset                                     * 
+ *===========================================================================*/
+/*
+ * Reset SCSI bus.
+ */
+PRIVATE
+sc_reset()
+{
+  volatile int i;
+  
+  BB_DEBUG (("sc_reset()\n"));
+
+  WR_ADR (SC_MODE, 0);                 /* get into harmless state */
+  WR_ADR (SC_OUTDATA, 0);
+  WR_ADR (SC_ICMD, SC_A_RST);          /* assert RST on SCSI bus */
+  i = 200;                             /* wait 25 usec */
+  while (i--);
+  WR_ADR (SC_ICMD, 0);                 /* deassert RST, get off bus */
+  sc_reset_done = 1;
+}
+
+/*===========================================================================*
+ *                             sc_wait_bus_free                             * 
+ *===========================================================================*/
+PRIVATE int
+sc_wait_bus_free()
+{
+  int i = MAX_WAIT;
+  volatile int j;
+
+  BB_DEBUG (("sc_wait_bus_free()\n"));
+
+  while (i--) {
+    /* Must be clear for 2 usec, so read twice */
+    if (RD_ADR (SC_STAT1) & (SC_S_BSY | SC_S_SEL)) continue;
+    for (j = 0; j < 25; ++j);
+    if (RD_ADR (SC_STAT1) & (SC_S_BSY | SC_S_SEL)) continue;
+    return OK;
+  }
+  sc_reset_done = 0;
+  return NOT_OK;
+}
+
+/*===========================================================================*
+ *                             sc_select                                    * 
+ *===========================================================================*/
+/* This duplicates much of the work that the interrupt routine would do on a
+ * phase mismatch and, in fact, the original plan was to just do the select,
+ * let a phase mismatch occur, and let the interrupt routine do the rest.
+ * That didn't work because the 5380 did not reliably generate the phase
+ * mismatch interrupt after selection.
+ */
+PRIVATE int
+sc_select(adr)
+long adr;
+{
+  int i, stat1;
+  long new_ptr;
+
+  BB_DEBUG (("sc_select(%d)\n", adr));
+
+  CLEAR_INTR();
+  WR_ADR (SC_OUTDATA, adr);            /* SCSI bus address */
+  WR_ADR (SC_ICMD, SC_A_SEL | SC_ENABLE_DB);
+  for (i = 0;; ++i) {                  /* wait for target to assert SEL */
+    if (CHECK_INTR() == 0)
+      continue;
+    stat1 = RD_ADR (SC_STAT1);
+    if (stat1 & SC_S_BSY) break;       /* select successful */
+    if (i > MAX_WAIT) {                        /* timeout */
+      printf("SCSI: SELECT timeout\n");
+      sc_reset();
+      return NOT_OK;
+    }
+  }
+  CLEAR_INTR();
+  WR_ADR (SC_ICMD, 0);                 /* clear SEL, disable data out */
+  WR_ADR (SC_OUTDATA, 0);
+  for (i = 0;; ++i) {                  /* wait for target to assert REQ */
+    if (CHECK_INTR() == 0)
+      continue;
+    if (stat1 & SC_S_REQ) break;       /* target requesting transfer */
+    if (i > MAX_WAIT) {                        /* timeout */
+      printf("SCSI: REQ timeout\n");
+      sc_reset();
+      return NOT_OK;
+    }
+    stat1 = RD_ADR (SC_STAT1);
+  }
+  sc_cur_phase = (stat1 >> 2) & 7;     /* get new phase from controller */
+  if (sc_cur_phase != PH_CMD) {
+    printf("SCSI: bad phase = %d\n", sc_cur_phase);
+    sc_reset();
+    return NOT_OK;
+  }
+  new_ptr = sc_ptrs->ptr[PH_CMD];
+  if (new_ptr == 0) {
+    printf("SCSI: NULL command pointer\n");
+    sc_reset();
+    return NOT_OK;
+  }
+  sc_accept_int = 1;
+  sc_dma_setup (DISK_WRITE, new_ptr);
+  CLEAR_INTR();
+  WR_ADR (SC_TCMD, PH_CMD);
+  WR_ADR (SC_ICMD, SC_ENABLE_DB);
+  WR_ADR (SC_MODE, SC_M_BSY | SC_M_DMA);
+  WR_ADR (SC_START_SEND, 0);
+  return OK;
+}
+
+/*===========================================================================*
+ *                             scsi_interrupt                               *
+ *===========================================================================*/
+/* SCSI interrupt handler.
+ */
+PUBLIC
+int
+scsi_interrupt()
+{
+  unsigned char stat2, dummy;
+  long new_ptr;
+  int ret = ISR_NOTDONE;
+
+  BB_DEBUG (("scsi_interrupt()\n"));
+
+  stat2 = RD_ADR (SC_STAT2);           /* get status before clearing request */
+
+# ifdef DEBUG                          /* debugging log of interrupts */
+  sc_log_head->stat1 = RD_ADR (SC_STAT1);
+  sc_log_head->stat2 = stat2;
+  if (++sc_log_head >= sc_log + SC_LOG_LEN) sc_log_head = sc_log;
+  sc_log_head->stat1 = sc_log_head->stat2 = 0xff;
+# endif
+
+  for (;;) {
+    dummy = RD_ADR (SC_RESETIP);       /* clear interrupt request */
+    if (!sc_accept_int ||              /* return if spurious interrupt */
+        (!sc_watchdog_error &&
+         (stat2 & SC_S_BSYERR) == 0 && (stat2 & SC_S_PHASE) != 0))
+      {
+#     ifdef DEBUG
+        ++sc_spurious_int;
+#     endif
+       printf ("sc_spurious_int\n");
+       return ret;
+    }
+    RD_ADR (SC_MODE) &= ~SC_M_DMA;     /* clear DMA mode */
+    WR_ADR (SC_ICMD, 0);               /* disable data bus */
+    if (sc_cur_phase != PH_NONE) {     /* if did DMA, save the new pointer */
+      new_ptr = sc_dma_adr;            /* fetch new pointer from DMA cntlr */
+      if (sc_cur_phase == PH_IMSG &&   /* have message? */
+        new_ptr != sc_ptrs->ptr[PH_IMSG]) sc_have_msg = 1;
+      sc_ptrs->ptr[sc_cur_phase] =     /* save pointer */
+        new_ptr;
+    }
+    if (sc_watchdog_error) ret = ISR_TIMEOUT;
+    else if (stat2 & SC_S_BSYERR) {    /* target deasserted BSY? */
+      printf ("target deasserted BSY?\n");
+      if (sc_have_msg) ret = ISR_OK;
+      else ret = ISR_BSYERR;
+    } else if (!(stat2 & SC_S_PHASE)) {/* if phase mismatch, setup new phase */
+      printf ("phase mismatch\n");
+      sc_cur_phase =                   /* get new phase from controller */
+        (RD_ADR (SC_STAT1) >> 2) & 7;
+      new_ptr = sc_ptrs->ptr[sc_cur_phase];
+      if (new_ptr == 0) ret = ISR_BADPHASE;
+      else {
+        WR_ADR (SC_TCMD, sc_cur_phase);        /* write new phase into TCMD */
+        if (PH_IN (sc_cur_phase)) {    /* set DMA controller */
+          sc_dma_setup (DISK_READ, new_ptr);
+          RD_ADR (SC_MODE) |= SC_M_DMA;
+         CLEAR_INTR();
+          WR_ADR (SC_START_RCV, 0);    /* tell SCSI to start DMA */
+       } else {
+          sc_dma_setup (DISK_WRITE, new_ptr);
+         RD_ADR (SC_MODE) |= SC_M_DMA;
+         WR_ADR (SC_ICMD, SC_ENABLE_DB);
+         CLEAR_INTR();
+         WR_ADR (SC_START_SEND, 0);
+       }
+      }
+    } else ret = ISR_RSTERR;
+    if (ret != ISR_NOTDONE) {          /* if done, send message to task */
+      sc_watchdog_error = 0;
+      sc_accept_int = 0;
+      WR_ADR (SC_MODE, 0);             /* clear monbsy, dma */
+      break;                           /* reti re-enables ints */
+    }
+    if (0 == ((stat2 =                 /* check for another interrupt */
+      RD_ADR (SC_STAT2)) & SC_S_IRQ)) 
+    {
+      break;
+    }
+  }
+  return ret;
+}
+
+/*===========================================================================*
+ *                             sc_dma_setup                                 *
+ *===========================================================================*/
+/* Fake DMA setup.  Just store pointers and direction in global variables.
+ *
+ * The pseudo-DMA is subtler than it looks because of the cache.
+ *
+ * 1)  When accessing I/O devices through a cache, some mechanism is
+ *     necessary to ensure you access the device rather than the cache.
+ *     On the 32532, the IODEC signal is supposed to be asserted for I/O
+ *     addresses to accomplish this.  However, a bug makes this much
+ *     slower than necessary and severely hurts pseudo-DMA performance.
+ *     Hence, IODEC is not asserted for the SCSI DMA port.
+ *
+ * 2)  Because of (1), we must devise our own method of forcing the
+ *     SCSI DMA port to be read.  0x8000000 addresses have been decoded
+ *     to all access this port.  By always using new addresses to access
+ *     the DMA port (wrapping only after reading MAX_CACHE bytes), we
+ *     force cache misses and, hence, device reads.  Since the cache
+ *     is write-through, we do not need to worry about writes.
+ *
+ * 3)  It is possible to miss the last few bytes of a transfer if
+ *     bus transfer size is not considered.  The loop in sc_receive()
+ *     transfers data until the interrupt signal is asserted.  If
+ *     bytes are transferred, the attempt to move the first byte of a
+ *     double word causes the whole word to be read into the cache.
+ *     Then the byte is transferred.  If reading the double word
+ *     completed the SCSI transfer, then the loop exits since
+ *     interrupt is asserted.  However, the last few bytes have only
+ *     been moved into the cache -- they have not been moved to the
+ *     DMA destination.
+ *
+ * 4)  It is also possible to miss the first few bytes of a transfer.
+ *     If the address used to access pseudo-dma port is not double word
+ *     aligned, the whole double word is read into the cache, and then
+ *     data is moved from the middle of the word (i.e. something other
+ *     than the first bytes read from the SCSI controller) by the
+ *     pseudo-dma loop in sc_receive().
+ */
+sc_dma_setup (dir, adr)
+int dir;
+long adr;
+{
+  BB_DEBUG (("sc_dma_setup(%d, %d)\n", dir, adr));
+
+  CLEAR_INTR();
+  /* if (sc_dma_port > SC_DMA + MAX_CACHE) */
+  sc_dma_port = SC_DMA;
+  sc_dma_dir = dir;
+  sc_dma_adr = adr;
+}
+
+/*===========================================================================*
+ *                             sc_receive                                   *
+ *===========================================================================*/
+/* Replacement for Minix receive(), which waits for a message.  This code
+ * spins, waiting for data to transfer or interrupt requests to handle.
+ * See sc_dma_setup for details.
+ */
+int
+sc_receive()
+{
+  int stat2, isr_ret;
+  int i, c;
+
+  BB_DEBUG (("sc_receive()\n"));
+
+  /*
+   * check the interrupt-flag and wait if it reappears...
+   */
+  c = *ka410_intreq;
+  printf ("begin: %x/%x ", c, *ka410_intreq);
+  for (i=0; i<100; i++) {
+    if ((c = *ka410_intreq) & INTR_SC)
+      break;
+    printf (" %x ", c);
+  }
+  if (i==100)
+    printf ("timeout in sc_receive.\n");
+
+#if 1
+  for (;;) {
+    stat2 = RD_ADR (SC_STAT2);
+    if (stat2 & SC_S_IRQ) {
+      if (ISR_NOTDONE != (isr_ret = scsi_interrupt())) break;
+    } else if (stat2 & SC_S_DRQ) {     /* test really not necessary on pc532 */
+      if (sc_dma_dir == DISK_READ)
+       *((long *)sc_dma_adr)++ = *((volatile long *)sc_dma_port)++;
+      else *((volatile long *)sc_dma_port)++ = *((long *)sc_dma_adr)++;
+    }
+  }
+#endif
+  printf ("isr_ret: %d (ISR_NOTDONE: %d)\n", isr_ret, ISR_NOTDONE);
+  return isr_ret;
+}
+
+/*===========================================================================*
+ *                             scCtlrSelect
+ *===========================================================================*/
+/* Select a SCSI device.
+ */
+scCtlrSelect (ctlr)
+int ctlr;
+{
+  BB_DEBUG (("scCtlrSelect()\n"));
+#if 0
+  RD_ADR (ICU_IO) &= ~ICU_SCSI_BIT;    /* i/o, not port */
+  RD_ADR (ICU_DIR) &= ~ICU_SCSI_BIT;   /* output */
+  if (ctlr == DP8490)
+    RD_ADR (ICU_DATA) &= ~ICU_SCSI_BIT;        /* select = 0 for 8490 */
+  else
+    RD_ADR (ICU_DATA) |= ICU_SCSI_BIT; /* select = 1 for AIC6250 */
+#endif
+}
diff --git a/sys/arch/vax/boot/sd.c b/sys/arch/vax/boot/sd.c
new file mode 100644 (file)
index 0000000..30b08c3
--- /dev/null
@@ -0,0 +1,247 @@
+/*     $NetBSD: sd.c,v 1.1 1996/08/02 11:22:36 ragge Exp $     */
+
+/*
+ * Copyright (c) 1988 University of Utah.
+ * Copyright (c) 1990, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Van Jacobson of Lawrence Berkeley Laboratory and the Systems
+ * Programming Group of the University of Utah Computer Science Department.
+ *
+ * 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.
+ *
+ * from: Utah $Hdr: sd.c 1.9 92/12/21$
+ *
+ *     @(#)sd.c        8.1 (Berkeley) 6/10/93
+ */
+
+/*
+ * SCSI CCS disk driver
+ */
+
+#include <sys/param.h>
+#include <sys/disklabel.h>
+#include "stand.h"
+#include "samachdep.h"
+
+#define SC_DEBUG       1       /* bertram */
+#define SD_DEBUG       1       /* bertram */
+
+/*----------------------------------------------------------------------*/
+int
+scsialive(int ctlr)
+{
+       return 1;               /* controller always alive! */
+}
+
+/* call functions in scsi_hi.c */
+#include "so.h"
+
+int
+scsi_tt_read(ctlr, slave, buf, len, blk, nblk)
+       int ctlr, slave;
+       u_char *buf;
+       u_int len;
+       daddr_t blk;
+       u_int nblk;
+{
+#ifdef SC_DEBUG
+printf("scsi_tt_read: ctlr %d, slave %d, len %d, blk %d, nblk %d\n",
+       ctlr, slave, len, blk, nblk );
+#endif
+       if (sc_rdwt(DISK_READ, blk, buf, nblk, 1<<slave, 0) == 0)
+               return 0;
+       return -2;
+}
+
+int
+scsi_tt_write(ctlr, slave, buf, len, blk, nblk)
+       int ctlr, slave;
+       u_char *buf;
+       u_int len;
+       daddr_t blk;
+       u_int nblk;
+{
+#ifdef SC_DEBUG
+printf("scsi_tt_write: ctlr %d, slave %d, len %d, blk %d, nblk %d\n",
+       ctlr, slave, len, blk, nblk );
+#endif
+#if 0
+       if (sc_rdwt(DISK_WRITE, blk, buf, nblk, 1<<slave, 0) == 0)
+               return 0;
+#endif
+       return -2;
+}
+
+/*----------------------------------------------------------------------*/
+
+struct sd_softc {
+       int     sc_ctlr;
+       int     sc_unit;
+       int     sc_part;
+       char    sc_retry;
+       char    sc_alive;
+       struct  disklabel sc_label;
+} sd_softc[NSCSI][NSD];
+
+#ifdef SD_DEBUG
+int debug = SD_DEBUG;
+#endif
+
+#define        SDRETRY         2
+
+sdinit(ctlr, unit)
+       int ctlr, unit;
+{
+       register struct sd_softc *ss = &sd_softc[ctlr][unit];
+
+       /* HP version does test_unit_ready
+        * followed by read_capacity to get blocksize
+        */
+       ss->sc_alive = 1;
+       return (1);
+}
+
+sdreset(ctlr, unit)
+       int ctlr, unit;
+{
+}
+
+char io_buf[MAXBSIZE];
+
+sdgetinfo(ss)
+       register struct sd_softc *ss;
+{
+       register struct disklabel *lp;
+       char *msg, *getdisklabel();
+       int sdstrategy(), i, err;
+
+       lp = &sd_softc[ss->sc_ctlr][ss->sc_unit].sc_label;
+       bzero((caddr_t)lp, sizeof *lp);
+       lp->d_secsize = DEV_BSIZE;
+       lp->d_secpercyl = 1;
+       lp->d_npartitions = MAXPARTITIONS;
+       lp->d_partitions[ss->sc_part].p_offset = 0;
+       lp->d_partitions[ss->sc_part].p_size = 0x7fffffff;
+
+       if (err = sdstrategy(ss, F_READ,
+                      LABELSECTOR, DEV_BSIZE, io_buf, &i) < 0) {
+           printf("sdgetinfo: sdstrategy error %d\n", err);
+           return 0;
+       }
+       
+       msg = getdisklabel(io_buf, lp);
+       if (msg) {
+               printf("sd(%d,%d,%d): %s\n",
+                      ss->sc_ctlr, ss->sc_unit, ss->sc_part, msg);
+               return 0;
+       }
+       return(1);
+}
+
+sdopen(f, ctlr, unit, part)
+       struct open_file *f;
+       int ctlr, unit, part;
+{
+       register struct sd_softc *ss;
+       register struct disklabel *lp;
+
+#ifdef SD_DEBUG
+       if (debug)
+       printf("sdopen: ctlr=%d unit=%d part=%d\n",
+           ctlr, unit, part);
+#endif
+       
+       if (ctlr >= NSCSI || !scsialive(ctlr))
+               return (EADAPT);
+       if (unit >= NSD)
+               return (ECTLR);
+       ss = &sd_softc[ctlr][unit];     /* XXX alloc()? keep pointers? */
+       ss->sc_part = part;
+       ss->sc_unit = unit;
+       ss->sc_ctlr = ctlr;
+       if (!ss->sc_alive) {
+               if (!sdinit(ctlr, unit))
+                       return (ENXIO);
+               if (!sdgetinfo(ss))
+                       return (ERDLAB);
+       }
+       lp = &sd_softc[ctlr][unit].sc_label;
+       if (part >= lp->d_npartitions || lp->d_partitions[part].p_size == 0)
+               return (EPART);
+
+       f->f_devdata = (void *)ss;
+       return (0);
+}
+
+int
+sdstrategy(ss, func, dblk, size, buf, rsize)
+       register struct sd_softc *ss;
+       int func;
+       daddr_t dblk;           /* block number */
+       u_int size;             /* request size in bytes */
+       char *buf;
+       u_int *rsize;           /* out: bytes transferred */
+{
+       register int ctlr = ss->sc_ctlr;
+       register int unit = ss->sc_unit;
+       register int part = ss->sc_part;
+       register struct partition *pp = &ss->sc_label.d_partitions[part];
+       u_int nblk = size >> DEV_BSHIFT;
+       u_int blk = dblk + pp->p_offset;
+       char stat;
+
+       if (size == 0)
+               return(0);
+
+       ss->sc_retry = 0;
+
+#ifdef SD_DEBUG
+       if (debug)
+           printf("sdstrategy(%d,%d): size=%d blk=%d nblk=%d\n",
+               ctlr, unit, size, blk, nblk);
+#endif
+
+retry:
+       if (func == F_READ)
+               stat = scsi_tt_read(ctlr, unit, buf, size, blk, nblk);
+       else
+               stat = scsi_tt_write(ctlr, unit, buf, size, blk, nblk);
+       if (stat) {
+               printf("sd(%d,%d,%d): block=%x, error=0x%x\n",
+                      ctlr, unit, ss->sc_part, blk, stat);
+               if (++ss->sc_retry > SDRETRY)
+                       return(EIO);
+               goto retry;
+       }
+       *rsize = size;
+       
+       return(0);
+}
diff --git a/sys/arch/vax/boot/so.h b/sys/arch/vax/boot/so.h
new file mode 100644 (file)
index 0000000..3ead2c8
--- /dev/null
@@ -0,0 +1,57 @@
+/*     $NetBSD: so.h,v 1.1 1996/08/02 11:22:41 ragge Exp $     */
+
+#ifndef _SO_H_INCLUDE
+#define _SO_H_INCLUDE
+
+/* Definitions for standalone I/O lib */
+
+/* #define SCSI_POLLED 0x200C0080 */
+#define SCSI_DMA       0x200D0000
+
+/* Which SCSI device to use by default */
+#define DEFAULT_SCSI_ADR       1
+#define DEFAULT_SCSI_LUN       0
+
+/* Low level scsi operation codes */
+#define DISK_READ      3
+#define DISK_WRITE     4
+
+/* The size of a disk block */
+#define DBLKSIZE       512
+
+/* Some disk address that will never be used */
+#define INSANE_BADDR   0x800000
+
+struct scsi_args {
+  long ptr [8];
+};
+
+#ifndef NULL
+#define NULL           0L
+#endif
+
+/*
+ * The next macro defines where the "break" area in memory ends for
+ * malloc() and friends. The area between edata and this address will
+ * then be reserved and should not be used for anything else (or you will
+ * no doubt have big problems). Depending on where your program's end-of-data
+ * is, you may wish to locate this in such a way as to usurp a minimum
+ * amount of memory.
+ */
+#define BREAK_END_ADDR         ((char *)0x400000)      /* to   4MB */
+
+/* Selectivly enable inline functions */
+#ifndef NO_INLINE
+#define Inline inline
+#else
+#define Inline
+#endif
+extern void fatal(), warn();
+extern long ulimit(int, long);
+extern int brk(char *);
+extern char *sbrk(int);
+
+extern int sc_rdwt();
+
+#endif /* _SO_H_INCLUDE */
index 1fc8dfc..bfe5aca 100644 (file)
@@ -1,4 +1,4 @@
-/*     $NetBSD: srt0.s,v 1.5 1996/03/07 23:27:10 ragge Exp $ */
+/*     $NetBSD: srt0.s,v 1.6 1996/08/02 11:22:44 ragge Exp $ */
 /*
  * Copyright (c) 1994 Ludd, University of Lule}, Sweden.
  * All rights reserved.
@@ -58,7 +58,9 @@ _start:       .globl  _start
 1:     movl    $relocated, (sp)   # return-address on top of stack
        rsb                        # can be replaced with new address
 relocated:                        # now relocation is done !!!
-       calls   $0,_main        # Were here!
+       movl    sp, _bootregs
+       calls   $0, _setup
+       calls   $0, _Xmain      # Were here!
        halt                    # no return
 
        
index 55b2fc0..51edf00 100644 (file)
@@ -1,4 +1,4 @@
-/*     $NetBSD: start.s,v 1.7 1996/02/02 19:08:33 mycroft Exp $ */
+/*     $NetBSD: start.s,v 1.8 1996/08/02 11:22:47 ragge Exp $ */
 /*
  * Copyright (c) 1995 Ludd, University of Lule}, Sweden.
  * All rights reserved.
@@ -172,7 +172,8 @@ start_all:
 relocated:                             # now relocation is done !!!
        movl    sp, _bootregs
        movl    ap, _boothowto
-       calls   $0, _main               # call main() which is 
+       calls   $0, _setup
+       calls   $0, _Xmain              # call Xmain (gcc workaround)which is 
        halt                            # not intended to return ...
 
 /*
diff --git a/sys/arch/vax/boot/str.s b/sys/arch/vax/boot/str.s
new file mode 100644 (file)
index 0000000..685574e
--- /dev/null
@@ -0,0 +1,70 @@
+/*     $NetBSD: str.s,v 1.2 1996/08/02 16:18:40 ragge Exp $ */
+/*
+ * Copyright (c) 1996 Ludd, University of Lule}, Sweden.
+ * 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 at Ludd, University of 
+ *      Lule}, Sweden and its contributors.
+ * 4. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * Small versions of the most common string functions not using any
+ * emulated instructions.
+ */
+
+#include "../include/asm.h"
+
+ENTRY(strlen, 0);
+       movl    4(ap), r0
+1:     tstb    (r0)+
+       bneq    1b
+       decl    r0
+       subl2   4(ap), r0
+       ret
+
+ENTRY(strncmp, 0)
+       movl    12(ap), r3
+       brb     5f
+
+ENTRY(strcmp, 0)
+       movl    $250, r3        # max string len to compare
+5:     movl    4(ap), r2
+       movl    8(ap), r1
+       movl    $1, r0
+
+2:     cmpb    (r2),(r1)+
+       bneq    1f              # something differ
+       tstb    (r2)+
+       beql    4f              # continue, strings unequal
+       decl    r3              # max string len encountered?
+       bneq    2b
+
+4:     clrl    r0              # We are done, strings equal.
+       ret
+
+1:     bgtr    3f
+       mnegl   r0, r0
+3:     ret
index f5d0fe1..b630222 100644 (file)
@@ -1,4 +1,4 @@
-/*     $NetBSD: tmscp.c,v 1.2 1996/02/17 18:23:24 ragge Exp $ */
+/*     $NetBSD: tmscp.c,v 1.3 1996/08/02 11:22:53 ragge Exp $ */
 /*
  * Copyright (c) 1995 Ludd, University of Lule}, Sweden.
  * All rights reserved.
@@ -43,7 +43,8 @@
 #include "../include/macros.h"
 #include "../uba/ubareg.h"
 #include "../uba/udareg.h"
-#include "../vax/mscp.h"
+#include "../mscp/mscp.h"
+#include "../mscp/mscpreg.h"
 
 #include "vaxstand.h"
 
@@ -63,7 +64,7 @@ struct ra_softc {
 };
 
 static volatile struct uda {
-        struct  uda1ca uda_ca;           /* communications area */
+        struct  mscp_1ca uda_ca;           /* communications area */
         struct  mscp uda_rsp;     /* response packets */
         struct  mscp uda_cmd;     /* command packets */
 } uda;
@@ -100,14 +101,14 @@ tmscpopen(f, adapt, ctlr, unit, part)
         * Init of this tmscp ctlr.
         */
        udacsr->udaip=0; /* Start init */
-       while((udacsr->udasa&UDA_STEP1) == 0);
+       while((udacsr->udasa&MP_STEP1) == 0);
        udacsr->udasa=0x8000;
-       while((udacsr->udasa&UDA_STEP2) == 0);
+       while((udacsr->udasa&MP_STEP2) == 0);
        johan=(((u_int)ubauda)&0xffff)+8;
        udacsr->udasa=johan;
-       while((udacsr->udasa&UDA_STEP3) == 0);
+       while((udacsr->udasa&MP_STEP3) == 0);
        udacsr->udasa=3;
-       while((udacsr->udasa&UDA_STEP4) == 0);
+       while((udacsr->udasa&MP_STEP4) == 0);
        udacsr->udasa=0x0001;
 
        uda.uda_ca.ca_rspdsc=(int)&ubauda->uda_rsp.mscp_cmdref;
index f3217fd..2d068b9 100644 (file)
@@ -1,4 +1,4 @@
-/*     $NetBSD: vaxstand.h,v 1.4 1996/02/17 18:23:25 ragge Exp $ */
+/*     $NetBSD: vaxstand.h,v 1.5 1996/08/02 11:22:56 ragge Exp $ */
 /*
  * Copyright (c) 1994 Ludd, University of Lule}, Sweden.
  * All rights reserved.
 
 #define MAXNMBA 8 /* Massbussadapters */
 #define MAXNUBA 8 /* Unibusadapters */
-#define MAXNBI  4 /* Bi-bussadapters */
 #define        MAXMBAU 8 /* Units on an mba */
-#define        MAXBIN  16 /* Bi-nodes */
 
 /* Variables used in autoconf */
 extern int nmba, nuba, nbi, nsbi, nuda;
-extern int *ubaaddr, *mbaaddr, *udaaddr, *uioaddr;
+extern int *ubaaddr, *mbaaddr, *udaaddr, *uioaddr, *biaddr;
+extern int cpunumber;
 
 /* devsw type definitions, used in bootxx and conf */
 #define SADEV(name,strategy,open,close,ioctl) \
@@ -50,3 +49,17 @@ extern int *ubaaddr, *mbaaddr, *udaaddr, *uioaddr;
          (int(*)(struct open_file *))close, \
          (int(*)(struct open_file *,u_long, void *))ioctl}
 
+/*
+ * Easy-to-use definitions
+ */
+#define        min(x,y) (x < y ? x : y)
+
+/*
+ * Device numbers gotten from boot prom.
+ */
+#define        BDEV_MBA                0
+#define        BDEV_RK06               1
+#define        BDEV_RL02               2
+#define        BDEV_UDA                17
+#define        BDEV_TK50               18
+#define        BDEV_CONSOLE            64
diff --git a/sys/arch/vax/conf/EVERYTHING b/sys/arch/vax/conf/EVERYTHING
deleted file mode 100644 (file)
index 101d475..0000000
+++ /dev/null
@@ -1,93 +0,0 @@
-#      $OpenBSD: EVERYTHING,v 1.4 1996/09/20 06:45:26 deraadt Exp $
-#      $NetBSD: EVERYTHING,v 1.1 1995/03/29 22:54:02 ragge Exp $
-#
-# This file contains everything that is known to be compiled
-# without errors. Some things may not be tested, like NETISO.
-#
-
-include "std.vax"
-
-# Here are all different supported CPU types listed.
-options         "VAX750"
-options         "VAX630"
-
-# Kernel identification
-options         EVERYTHING
-
-# Max users on system; this is just a hint
-maxusers       16
-
-# Paging system, we always have them all.
-options                SWAPPAGER, DEVPAGER
-
-# Kernel compiled-in symbolic debugger
-#options               DDB
-
-# System V shared memory
-options                SYSVMSG         # Message passing
-options                SYSVSEM         # Semaphores
-options                SYSVSHM         # Shared memory
-options                SHMMAXPGS=1024
-
-# Network support
-options         INET           # Internet protocol, (almost) mandatory
-options         ETHER          # Ethernet, probably needed
-options                NS              # Xerox Network system, untested
-options                ISO,TPIP        # ISO network, untested
-options                EON
-options                CCITT,LLC,HDLC
-
-# All supported filesystem types
-options                FFS,QUOTA       # Normal fast filesystem, mandatory
-options                LFS             # Log-structured file system
-options                MFS             # Memory filesystem
-options                NFSCLIENT       # Network filesystem client
-options                NFSSERVER       # Network filesystem server
-options                CD9660          # CDRom filesystem
-options                FDESC           # Filedescriptors, /dev/fd
-options                FIFO
-options                KERNFS          # Kernel info filesystems
-options                NULLFS
-options                PORTAL
-options                PROCFS          # Process filesystem
-options                UMAPFS
-options                UNION
-
-# Old compat stuff; needed to run 4.3BSD Reno programs
-options                COMPAT_43
-options                COMPAT_09
-options                COMPAT_10
-options                COMPAT_RENO
-#options               TCP_COMPAT_42   # Bug compat with 4.2BSD systems (like NDIX)
-
-# loadable kernel modules.
-options                LKM
-
-
-# Kernel(s) to compile
-config          bsd          root on hp0 swap on hp0
-
-# All supported CPU:s
-cpu0           at backplane0
-
-# Main buses at backplane
-sbi*           at backplane0
-
-# Devices connected at sbi
-mem*           at sbi? tr?     # Memory subsystems
-uba0           at sbi? tr?     # Unibus adapters
-
-# Disk controllers at Unibus
-uda0           at uba? csr 0172150     # UDA50/KDA50/RQDX3
-ra0            at uda0 drive 0         # RA??/RD??
-
-# Ethernet cards
-de0            at uba? csr 0174510     # DEUNA/DELUA
-qe0            at uba? csr 0174440     # DEQNA/DELQA
-
-# Tape drivers
-tmscp0         at uba? csr 0174500
-tms0           at tmscp0 drive ?       # TK50/TU81
-
-pseudo-device   loop
-pseudo-device   pty    48
index 6a181c4..400d4a8 100644 (file)
@@ -1,16 +1,20 @@
-#      $NetBSD: GENERIC,v 1.13 1996/05/19 16:25:23 ragge Exp $
+#      $OpenBSD: GENERIC,v 1.7 1997/01/15 23:24:29 maja Exp $
+#      $NetBSD: GENERIC,v 1.19 1997/01/11 11:15:38 ragge Exp $
 #
 # GENERIC VAX configuration file; all supported devices.
 #
 
-include "std.vax"
+machine        vax
 
 # Here are all different supported CPU types listed.
 options         "VAX8600"
+options         "VAX8200"
 options         "VAX780"
 options         "VAX750"
-options         "VAX630"
-options         "VAX650"
+options         "VAX630"       # MV II
+options         "VAX650"       # MV III, 3600, 3800, 3900
+options                "VAX410"        # VS 2000
+options                "VAX43"         # VS 3100/76
 
 # Kernel identification
 options         GENERIC
@@ -49,6 +53,10 @@ options              SYSVMSG
 options                SYSVSEM
 options                SYSVSHM
 
+# What executables to look for.
+options                EXEC_AOUT
+options                EXEC_SCRIPT
+
 # Old compat stuff; needed to run 4.3BSD Reno programs.
 # Note that if COMPAT_ULTRIX is set, you lose compatibility with
 # 4.3BSD Reno programs and get Ultrix compatibility instead.
@@ -56,19 +64,38 @@ options             SYSVSHM
 options                COMPAT_43
 options                COMPAT_09
 options                COMPAT_10
+options                COMPAT_11
+options                COMPAT_12
 #options               COMPAT_ULTRIX
 #options               TCP_COMPAT_42
 
 options                LKM
 
-
 # Kernel(s) to compile
 config          bsd          swap generic
 
+backplane0     at root
+
 # Devices directly attached to backplane.
 cpu0           at backplane0   # Only one CPU so far.
 sbi*           at backplane0   # SBI's are always at backplane (Abus).
 mem*           at backplane0   # Some machines have memory at backplane.
+bi*            at backplane0   # VAXBI bus
+cmi0           at backplane0   # 11/750 internal bus.
+uba0           at backplane0   # MicroVAXen only have QBUS.
+vsbus0         at backplane0   # Internal "virtual" VAXstation bus
+
+# Devices connected at VAXBI
+cpu0           at bi? node?    # KA820/KA825 cpu
+mem*           at bi? node?    # Memory subsystems
+#ni*           at bi? node?    # DEBNA/DEBNT ethernet adapter
+kdb*           at bi? node?    # KDB50 MSCP disk ctlr
+mscpbus*       at kdb?
+
+# Devices connected at cmi
+mem*           at cmi? tr?     # Memory subsystems
+uba*           at cmi? tr?     # Unibus adapters
+mba*           at cmi? tr?     # Massbus adapters
 
 # Devices connected at sbi
 mem*           at sbi? tr?     # Memory subsystems
@@ -79,26 +106,38 @@ mba*               at sbi? tr?     # Massbus adapters
 hp*            at mba? drive?  # RM/RP disk drives
 
 # Disk controllers at Unibus
-uda0           at uba? csr 0172150
-ra0            at uda0 drive 0
-ra1            at uda0 drive 1
-ra2            at uda0 drive 2
-ra3            at uda0 drive 3
-
+uda0           at uba? csr 0172150     # UDA50/RQDX?
 uda1           at uba? csr 0160334
-ra4            at uda1 drive 0
-ra5            at uda1 drive 1
-ra6            at uda1 drive 2
-ra7            at uda1 drive 3
+mscpbus*       at uda?
+
+# Tape drivers
+mtc0           at uba? csr 0174500     # Tape MSCP ctlr
+mscpbus*       at mtc?
+
+# MSCP devices
+ra*            at mscpbus? drive?      # MSCP disk
+mt*            at mscpbus? drive?      # MSCP tape
+
+# Unibus tapes
+#ts0           at uba? csr 0172520     # TS11/TSV05 tape.
+
+# VS2000 builtin MFM controller (HDC9224)
+hdc0           at vsbus0               # The strange builtin MFM controller
+rd*            at hdc0 drive?          # The RD disk subsystem on VS2000
+
+# VAXstation builtin SCSI-controller (NCR5380)
+ncr0           at vsbus0               # 1st built-in SCSI interface
+ncr1           at vsbus0               # 2nd built-in SCSI interface
+scsibus*       at ncr?
+
+sd*            at scsibus? target? lun?
+st*            at scsibus? target? lun?
+
 
 # Ethernet cards
 de0            at uba? csr 0174510     # DELUA/DEUNA
 qe0            at uba? csr 0174440     # DEQNA/DELQA
-
-# Tape drivers
-tmscp0         at uba? csr 0174500     # TMSCP ctlr
-tms0           at tmscp0 drive ?       # TMSCP tape
-ts0            at uba? csr 0172520     # TS11/TSV05 tape.
+le0            at vsbus0               # LANCE
 
 # Terminal lines
 dhu0           at uba? csr 0160440     # DHU-11
@@ -106,9 +145,10 @@ dz0                at uba? csr 0160100     # DZ-11
 
 pseudo-device   loop   1
 pseudo-device   pty    48
-pseudo-device  bpfilter 8
+pseudo-device  bpfilter 8      # Not supported by de or qe yet.
 pseudo-device  sl      2
 pseudo-device  ppp     2
 pseudo-device  tun     2
 pseudo-device  tb      1
 pseudo-device  vnd     4
+pseudo-device  ccd     4
index 4d8b0ef..4167eab 100644 (file)
@@ -1,6 +1,7 @@
-#      $Bsd: Makefile.vax,v 1.21 1996/05/11 16:13:17 mycroft Exp $
+#      $OpenBSD: Makefile.vax,v 1.5 1997/01/15 23:24:30 maja Exp $
+#      $NetBSD: Makefile.vax,v 1.28 1996/12/01 06:12:39 jonathan Exp $
 
-# Makefile for Bsd
+# Makefile for NetBSD
 #
 # This makefile is constructed from a machine description:
 #      config machineid
 #
 # -DTRACE      compile in kernel tracing hooks
 # -DQUOTA      compile in file system quotas
-# -DUUDMA      compile in unibus tu58 pseudo-dma code
 
 # DEBUG is set to -g if debugging.
 # PROF is set to -pg if profiling.
 
-AS?=   as
 CC?=   cc
-CPP?=  cpp
 LD?=   ld
-STRIP?=        strip -d
-TOUCH?=        touch -f -c
+MKDEP?=        mkdep
+STRIP?=        strip
+COPTS?=        -O2
 
 # source tree is located via $S relative to the compilation directory
-S=     ../../../..
-VAX=   ../..
+.ifndef S
+S!=    cd ../../../..; pwd
+.endif
+VAX=   $S/arch/vax
 
-INCLUDES=      -I. -I$S/arch -I$S
-CPPFLAGS=      ${INCLUDES} ${IDENT} -D_KERNEL -D_VAX_INLINE_
-CFLAGS=                ${DEBUG} -O2 -Werror
+INCLUDES=      -I. -I$S/arch -I$S -nostdinc
+CPPFLAGS=      ${INCLUDES} ${IDENT} ${PARAM} -D_KERNEL \
+               -D_VAX_INLINE_
+CWARNFLAGS=    -Werror
+CFLAGS=                ${DEBUG} ${COPTS} ${CWARNFLAGS}
 AFLAGS=                -x assembler-with-cpp -traditional-cpp -D_LOCORE
 LINKFLAGS=     -Z -Ttext 80000000 -e _start
+STRIPFLAGS=    -d
+
+HOSTED_CC=     ${CC}
+HOSTED_CPPFLAGS=${CPPFLAGS:S/^-nostdinc$//}
+HOSTED_CFLAGS= ${CFLAGS}
 
 ### find out what to use for libkern
 .include "$S/lib/libkern/Makefile.inc"
@@ -55,19 +63,13 @@ LIBCOMPAT=      ${COMPATLIB}
 LIBCOMPAT=      ${COMPATLIB_PROF}
 .endif
 
-# compile rules: rules are named ${TYPE}_${SUFFIX}${CONFIG_DEP}
-# where TYPE is NORMAL, DRIVER, or PROFILE}; SUFFIX is the file suffix,
-# capitalized (e.g. C for a .c file), and CONFIG_DEP is _C if the file
-# is marked as config-dependent.
+# compile rules: rules are named ${TYPE}_${SUFFIX} where TYPE is NORMAL or
+# HOSTED}, and SUFFIX is the file suffix, capitalized (e.g. C for a .c file).
 
 NORMAL_C=      ${CC} ${CFLAGS} ${CPPFLAGS} ${PROF} -c $<
-NORMAL_C_C=    ${CC} ${CFLAGS} ${CPPFLAGS} ${PROF} ${PARAM} -c $<
-
-DRIVER_C=      ${CC} ${CFLAGS} ${CPPFLAGS} ${PROF} -c $<
-DRIVER_C_C=    ${CC} ${CFLAGS} ${CPPFLAGS} ${PROF} ${PARAM} -c $<
-
 NORMAL_S=      ${CC} ${AFLAGS} ${CPPFLAGS} -c $<
-NORMAL_S_C=    ${CC} ${AFLAGS} ${CPPFLAGS} ${PARAM} -c $<
+
+HOSTED_C=      ${HOSTED_CC} ${HOSTED_CFLAGS} ${HOSTED_CPPFLAGS} -c $<
 
 %OBJS
 
@@ -80,7 +82,7 @@ NORMAL_S_C=   ${CC} ${AFLAGS} ${CPPFLAGS} ${PARAM} -c $<
 #      ${SYSTEM_LD_HEAD}
 #      ${SYSTEM_LD} swapxxx.o
 #      ${SYSTEM_LD_TAIL}
-SYSTEM_OBJ=    intvec.o subr.o lim.o \
+SYSTEM_OBJ=    intvec.o subr.o \
                param.o ioconf.o ${OBJS} ${LIBKERN} ${LIBCOMPAT}
 SYSTEM_DEP=    Makefile ${SYSTEM_OBJ}
 SYSTEM_LD_HEAD=        @rm -f $@
@@ -93,9 +95,9 @@ DEBUG?=
 LINKFLAGS+=    -X
 SYSTEM_LD_TAIL+=; \
                echo cp $@ $@.gdb; rm -f $@.gdb; cp $@ $@.gdb; \
-               echo ${STRIP} $@; ${STRIP} $@
+               echo ${STRIP} ${STRIPFLAGS} $@; ${STRIP} ${STRIPFLAGS} $@
 .else
-LINKFLAGS+=    -x
+LINKFLAGS+=    -S
 .endif
 
 %LOAD
@@ -105,7 +107,7 @@ param.c: $S/conf/param.c
        cp $S/conf/param.c .
 
 param.o: param.c Makefile
-       ${NORMAL_C_C}
+       ${NORMAL_C}
 
 ioconf.o: ioconf.c
        ${NORMAL_C}
@@ -120,7 +122,7 @@ clean::
            [Ee]rrs linterrs makelinks
 
 lint:
-       @lint -hbxncez -DGENERIC -Dvolatile= ${CPPFLAGS} ${PARAM} -UKGDB \
+       @lint -hbxncez -DGENERIC -Dvolatile= ${CPPFLAGS} -UKGDB \
            ${VAX}/vax/Locore.c ${CFILES} ${VAX}/vax/swapgeneric.c \
            ioconf.c param.c | \
            grep -v 'static function .* unused'
@@ -136,14 +138,13 @@ links:
          sed 's,../.*/\(.*.o\),rm -f \1; ln -s ../GENERIC/\1 \1,' > makelinks
        sh makelinks && rm -f dontlink
 
-SRCS=  ${VAX}/vax/intvec.s ${VAX}/vax/subr.s lim.c \
+SRCS=  ${VAX}/vax/intvec.s ${VAX}/vax/subr.s \
        param.c ioconf.c ${CFILES} ${SFILES}
 depend:: .depend
 .depend: ${SRCS} param.c
-       mkdep ${AFLAGS} ${CPPFLAGS} ${VAX}/vax/intvec.s ${VAX}/vax/subr.s
-       mkdep -a ${CFLAGS} ${CPPFLAGS} lim.c
-       mkdep -a ${CFLAGS} ${CPPFLAGS} param.c ioconf.c ${CFILES}
-       mkdep -a ${AFLAGS} ${CPPFLAGS} ${SFILES}
+       ${MKDEP} ${AFLAGS} ${CPPFLAGS} ${VAX}/vax/intvec.s ${VAX}/vax/subr.s
+       ${MKDEP} -a ${CFLAGS} ${CPPFLAGS} param.c ioconf.c ${CFILES}
+       ${MKDEP} -a ${AFLAGS} ${CPPFLAGS} ${SFILES}
 
 
 # depend on root or device configuration
@@ -166,10 +167,4 @@ intvec.o: ${VAX}/vax/intvec.s
 subr.o: ${VAX}/vax/subr.s
        ${NORMAL_S}
 
-lim.c: ioconf.c
-       ../../conf/mkoldconf.awk < ioconf.c > lim.c
-
-lim.o: lim.c
-       ${NORMAL_C_C}
-
 %RULES
index b9176ea..61bd0f4 100644 (file)
@@ -1,4 +1,4 @@
-#       $NetBSD: files.vax,v 1.19 1996/05/19 16:25:29 ragge Exp $
+#       $NetBSD: files.vax,v 1.23 1997/01/05 18:50:27 ragge Exp $
 #
 # new style config file for vax architecture
 #
@@ -13,22 +13,32 @@ attach      backplane at root
 
 device sbi { tr=-1 }
 attach sbi at backplane
+file   arch/vax/vax/sbi.c              sbi needs-flag
+
+device cmi { tr=-1 }
+attach cmi at backplane
+
 device bi { node=-1 }
 attach bi at backplane
+file   arch/vax/bi/bi.c                bi needs-flag
+
+device vsbus { }
+attach vsbus at backplane
+file   arch/vax/vsa/vsbus.c            vsbus
 
 device cpu
 attach cpu at backplane with cpu_backplane
 attach cpu at bi with cpu_bi
+
 device mem
 attach mem at backplane with mem_backplane
 attach mem at bi with mem_bi
 attach mem at sbi with mem_sbi
-
-file   arch/vax/vax/sbi.c              sbi needs-flag
-file   arch/vax/vax/bi.c               bi needs-flag
+attach mem at cmi with mem_cmi
 
 device mba { drive = -1 }
-attach mba at sbi
+attach mba at sbi with mba_sbi
+attach mba at cmi with mba_cmi
 file   arch/vax/mba/mba.c              mba needs-flag
 
 device  hp: disk
@@ -40,35 +50,43 @@ device      ht
 attach ht at mba
 file   arch/vax/mba/ht.c               ht needs-flag
 
+# MSCP device drivers
+include "arch/vax/mscp/files.mscp"
+major  {ra = 9}
+major  {mt = 16}
+
+# KDB50 on BI
+device kdb: mscp
+attach kdb at bi
+file   arch/vax/bi/kdb.c               kdb
+
 device uba { csr }
-attach uba at sbi, bi
+attach uba at backplane with uba_backplane
+attach uba at sbi with uba_sbi
+attach uba at cmi with uba_cmi
+attach uba at bi with uba_bi
 file   arch/vax/uba/uba.c              uba
 
-device uda { drive=-1 }
+device mtc: mscp
+attach mtc at uba
+device uda: mscp
 attach uda at uba
-file    arch/vax/uba/uda.c             uda needs-count
+file    arch/vax/uba/uda.c             uda | mtc
 
 device de:ifnet, ether
 attach de at uba
 file   arch/vax/if/if_de.c             de
 
-device ra: disk
-attach ra at uda       
-file   arch/vax/vax/mscp.c             ra needs-count
-major  {ra = 9}
-
-# TK50/TU81 at UBA
-device tmscp {drive = -1}
-attach tmscp at uba
-device tms
-attach tms at tmscp
-file   arch/vax/uba/tmscp.c            tmscp needs-count
-
 # DEQNA/DELQA used on Qbus
 device qe:ifnet, ether
 attach qe at uba
 file   arch/vax/if/if_qe.c             qe
 
+# DEBNA/DEBNT Ethernet Adapter
+device ni:ifnet, ether
+attach ni at bi
+file   arch/vax/bi/ni.c                ni
+
 # TS11 at UBA
 device ts
 attach ts at uba
@@ -84,6 +102,50 @@ device      dz
 attach dz at uba
 file   arch/vax/uba/dz.c               dz needs-count
 
+# RD-type disks at VS2000's onboard MFM-controller
+device hdc { drive = -1 }
+attach hdc at vsbus
+file   arch/vax/vsa/hdc9224.c          hdc needs-flag
+
+device rd: disk
+attach rd at hdc
+major  {rd = 19}
+
+#
+# Machine-independent SCSI driver.
+#
+include "../../../scsi/files.scsi"
+major  { sd = 20 }
+major  { st = 21 }
+major  { cd = 22 }
+
+# Memory Disk for install floppy
+pseudo-device md
+file   dev/md.c                        md needs-flag
+major  { md = 23 }
+
+# builtin NCR5380 SCSI-controller on VAXstation 
+device ncr: scsi, ncr5380sbc
+attach ncr at vsbus
+file   arch/vax/vsa/ncr.c              ncr needs-flag
+
+# LANCE ethernet controller on VAXstation
+attach le at vsbus
+file   arch/vax/if/if_le.c             le
+
+# DC367-B in VAXstation 2000/3100 (DZ-like 4-port serial line controller,
+# controls keyboard, mouse, modem, and printer/console)
+device dc
+attach dc at vsbus
+file   arch/vax/vsa/dc.c               dc needs-flag
+file   arch/vax/vsa/lk201.c            dc
+
+# PM Framebuffer in VAXstation 2000/3100
+device pm
+attach pm at vsbus
+file   arch/vax/vsa/pm.c               pm needs-flag
+
+
 # These devices aren't tested (or even compiled!)
 # They are just included here to make some files happy ;)
 #
@@ -112,12 +174,6 @@ device     mu
 attach mu at mba
 file   arch/vax/mba/mt.c               mu needs-count
 
-# KDB50 on BI
-device kdb { drive=-1 }
-attach kdb at bi
-file   arch/vax/bi/kdb.c               kdb needs-count
-
-
 # DMF32 on UBA
 device dmf
 attach dmf at uba
@@ -244,17 +300,23 @@ file      dev/cninit.c
 file   arch/vax/vax/locore.c
 file   arch/vax/vax/mem.c
 file   arch/vax/vax/clock.c
-file   arch/vax/vax/gencons.c
+file   arch/vax/vax/gencons.c  vax8600|vax8200|vax780|vax750|vax630|ka650
+file   arch/vax/vax/dzcons.c           vax410 | vax43
 file   arch/vax/vax/pmap.c
 file   arch/vax/vax/machdep.c
 file   arch/vax/vax/ka750.c            vax750
-file   arch/vax/vax/ka780.c            vax780
 file   arch/vax/vax/ctu.c              vax750
-file   arch/vax/vax/uvaxII.c           vax630
-file   arch/vax/vax/emulate.s          vax630 | ka650
-file   arch/vax/vax/ka650.c            vax650
+file   arch/vax/vax/ka780.c            vax780
+file   arch/vax/vax/cfl.c              vax780
+file   arch/vax/vax/ka820.c            vax8200
 file   arch/vax/vax/ka860.c            vax8600
 file   arch/vax/vax/crl.c              vax8600
+file   arch/vax/vax/uvax.c             vax630 | vax410 | vax43
+file   arch/vax/vax/ka630.c            vax630
+file   arch/vax/vax/ka410.c            vax410
+file   arch/vax/vax/ka43.c             vax43
+file   arch/vax/vax/emulate.s          vax630 | ka650
+file   arch/vax/vax/ka650.c            vax650
 file   arch/vax/vax/conf.c
 file   arch/vax/vax/urem.s
 file   arch/vax/vax/udiv.s
@@ -266,7 +328,7 @@ file        arch/vax/vax/autoconf.c
 file   arch/vax/vax/random.s           inet
 file   arch/vax/vax/in_cksum.c         inet
 file   arch/vax/vax/ns_cksum.c         ns
-file   arch/vax/vax/disksubr.c         ffs
+file   arch/vax/vax/disksubr.c         disk | tape
 file   arch/vax/if/if_uba.c            de | qe
 file   arch/vax/vax/db_machdep.c       ddb
 file   arch/vax/vax/db_disasm.c        ddb
@@ -275,9 +337,7 @@ include "../../../compat/ultrix/files.ultrix"
 
 # Dom h{ra f}r vara kvar s} l{nge f}r vi se vilka vi beh|ver...
 #arch/vax/vax/dkbad.c         standard
-#arch/vax/vax/flp.c           standard
 #arch/vax/vax/ka730.c         standard
-#arch/vax/vax/ka820.c         standard
 #arch/vax/vax/rx50.c          standard
 #arch/vax/vax/iidr.o          optional ii
 #arch/vax/vax/iidrsys.o       optional ii
diff --git a/sys/arch/vax/conf/mkoldconf.awk b/sys/arch/vax/conf/mkoldconf.awk
deleted file mode 100644 (file)
index 81b2cb1..0000000
+++ /dev/null
@@ -1,151 +0,0 @@
-#!/usr/bin/awk -f
-#
-# $NetBSD: mkoldconf.awk,v 1.7 1996/03/17 22:56:31 ragge Exp $
-#
-
-/tms_cd/{
-       tmsplats[ntms]=$3;
-       tmsaddr[ntms]=$6;
-       ntms++;
-}
-
-/ts_cd/{
-       tsplats[nts]=$3;
-       tsaddr[nts]=$6;
-       nts++;
-}
-
-/ra_cd/{
-       raplats[nra]=$3;
-       raaddr[nra]=$6;
-       nra++;
-}
-
-{
-       if(savenext==1){
-               l=sprintf("%d",$3)
-               udanummer[l-1]=nuda-1
-               savenext=0;
-       }
-}
-
-
-{
-       if(tmssavenext==1){
-               l=sprintf("%d",$3)
-               tmsnummer[l-1]=ntmscp-1
-               tmssavenext=0;
-       }
-       if(tssavenext==1){
-               l=sprintf("%d",$3)
-               tsnummer[l-1]=nts-1
-               tssavenext=0;
-       }
-}
-
-/tmscp_cd/{
-       tmscpplats[ntmscp]=$3;
-       tmscpaddr[ntmscp]=$6;
-       ntmscp++;
-       tmssavenext=1;
-}
-               
-/uda_cd/{
-       udaplats[nuda]=$3;
-       udaddr[nuda]=$6;
-       nuda++;
-       savenext=1;
-}
-               
-
-/};/{
-       k=0;
-       m=0;
-}
-
-{
-       if (k==1){
-               for(i=1;i<NF+1;i++){
-                       loc[loccnt+i]=$i;
-               }
-               loccnt+=NF;
-       }
-}
-
-/static int loc/{
-       k=1;
-       loccnt=0;
-}
-
-{
-       if(m==1){
-               for(i=1;i<NF+1;i++){
-                       pv[i]=$i;
-               }
-       }
-}
-
-/static short pv/{
-       m=1;
-}
-
-END{
-
-printf "#include <sys/param.h>\n"
-printf "#include <machine/pte.h>\n"
-printf "#include <sys/buf.h>\n"
-printf "#include <sys/map.h>\n"
-
-printf "#include <vax/uba/ubavar.h>\n"
-
-printf "int antal_ra=%d;\n",nra-1
-printf "int antal_uda=%d;\n",nuda-1
-printf "int antal_ts=%d;\n",nts-1
-printf "int antal_tms=%d;\n",ntms-1
-printf "int antal_tmscp=%d;\n",ntmscp-1
-
-printf "extern struct uba_driver udadriver;\n"
-if(nts) printf "extern struct uba_driver tsdriver;\n"
-if(nts) printf "void tsintr();\n"
-if(ntms) printf "extern struct uba_driver tmscpdriver;\n"
-if(ntms) printf "void tmscpintr();\n"
-printf "void udaintr();\n"
-printf "int ra_cd=0, ra_ca=0, tms_cd=0, tms_ca=0;\n"
-printf "#define C (caddr_t)\n"
-
-printf "struct uba_ctlr ubminit[]={\n"
-for(i=1;i<nuda;i++){
-       k=sprintf("%d",udaddr[i])
-       printf "        { &udadriver, %d,'?',0,udaintr,C %s},\n",
-               udaplats[i],loc[k+1]
-}
-for(i=1;i<nts;i++){
-       k=sprintf("%d",tsaddr[i])
-if(nts)printf "        { &tsdriver, %d,'?',0,tsintr,C %s},\n",
-       tsplats[i],loc[k+1]
-}
-for(i=1;i<ntmscp;i++){
-       k=sprintf("%d",tmscpaddr[i])
-if(ntms)printf "        { &tmscpdriver, %d,'?',0,tmscpintr,C %s},\n",
-       tmscpplats[i],loc[k+1]
-}
-printf "0};\n"
-
-printf "struct uba_device ubdinit[]={\n"
-for(i=1;i<nra;i++){
-       k=sprintf("%d",raaddr[i])
-       printf "        { &udadriver,%d,%d,'?',%d,0,0,1,0},\n",raplats[i],
-               rr++/4,loc[k+1]
-}
-for(i=1;i<nts;i++){
-       k=sprintf("%d",tsaddr[i])
-       printf "        {&tsdriver,%d,0,'?',0,0,C 0,1,0},\n",tsplats[i]
-}
-for(i=1;i<ntms;i++){
-       k=sprintf("%d",tmsaddr[i])
-       printf "        {&tmscpdriver,%d,0,'?',0,0,C 0,1,0},\n",tmsplats[i]
-}
-printf "0};\n"
-
-}
-
diff --git a/sys/arch/vax/conf/std.vax b/sys/arch/vax/conf/std.vax
deleted file mode 100644 (file)
index ba605d9..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-#      $NetBSD: std.vax,v 1.3 1995/02/13 00:41:59 ragge Exp $
-#
-# Std vaxfiles
-#
-machine        vax
-
-backplane0     at root
-
-options        MAXFDESCS=2048
-options        TIMEZONE=-60, DST=1
index 32098cb..c6ffce3 100644 (file)
@@ -1,4 +1,4 @@
-/*     $NetBSD: if_de.c,v 1.21 1996/05/19 16:43:02 ragge Exp $ */
+/*     $NetBSD: if_de.c,v 1.25 1996/11/15 03:11:19 thorpej Exp $       */
 
 /*
  * Copyright (c) 1982, 1986, 1989 Regents of the University of California.
@@ -206,7 +206,7 @@ deattach(parent, self, aux)
        addr->pcsr0 = PCSR0_RSET;
        (void)dewait(ds, "reset");
 
-       ds->ds_ubaddr = uballoc(ds->ds_dev.dv_parent->dv_unit,
+       ds->ds_ubaddr = uballoc((void *)ds->ds_dev.dv_parent,
            (char *)&ds->ds_pcbb, sizeof (struct de_pcbb), 0);
        addr->pcsr2 = ds->ds_ubaddr & 0xffff;
        addr->pcsr3 = (ds->ds_ubaddr >> 16) & 0x3;
@@ -217,7 +217,7 @@ deattach(parent, self, aux)
        addr->pclow = CMD_GETCMD;
        (void)dewait(ds, "read addr ");
 
-       ubarelse(ds->ds_dev.dv_parent->dv_unit, &ds->ds_ubaddr);
+       ubarelse((void *)ds->ds_dev.dv_parent, &ds->ds_ubaddr);
        bcopy((caddr_t)&ds->ds_pcbb.pcbb2, (caddr_t)ds->ds_addr,
            sizeof (ds->ds_addr));
        printf("%s: hardware address %s\n", ds->ds_dev.dv_xname,
@@ -273,14 +273,14 @@ deinit(ds)
        if (ds->ds_flags & DSF_RUNNING)
                return;
        if ((ifp->if_flags & IFF_RUNNING) == 0) {
-               if (if_ubaminit(&ds->ds_deuba, ds->ds_dev.dv_parent->dv_unit,
+               if (if_ubaminit(&ds->ds_deuba, (void *)ds->ds_dev.dv_parent,
                    sizeof (struct ether_header), (int)btoc(ETHERMTU),
                    ds->ds_ifr, NRCV, ds->ds_ifw, NXMT) == 0) { 
                        printf("%s: can't initialize\n", ds->ds_dev.dv_xname);
                        ds->ds_if.if_flags &= ~IFF_UP;
                        return;
                }
-               ds->ds_ubaddr = uballoc(ds->ds_dev.dv_parent->dv_unit,
+               ds->ds_ubaddr = uballoc((void *)ds->ds_dev.dv_parent,
                    INCORE_BASE(ds), INCORE_SIZE(ds), 0);
        }
        addr = ds->ds_vaddr;
@@ -383,9 +383,13 @@ destart(ifp)
                if (rp->r_flags & XFLG_OWN)
                        panic("deuna xmit in progress");
                len = if_ubaput(&ds->ds_deuba, &ds->ds_ifw[ds->ds_xfree], m);
-               if (ds->ds_deuba.iff_flags & UBA_NEEDBDP)
-                       UBAPURGE(ds->ds_deuba.iff_uba,
-                       ds->ds_ifw[ds->ds_xfree].ifw_bdp);
+               if (ds->ds_deuba.iff_flags & UBA_NEEDBDP) {
+                       struct uba_softc *uh = (void *)ds->ds_dev.dv_parent;
+
+                       if (uh->uh_ubapurge)
+                               (*uh->uh_ubapurge)
+                                       (uh, ds->ds_ifw[ds->ds_xfree].ifw_bdp);
+               }
                rp->r_slen = len;
                rp->r_tdrerr = 0;
                rp->r_flags = XFLG_STP|XFLG_ENP|XFLG_OWN;
@@ -447,10 +451,15 @@ deintr(unit)
                        if (rp->r_flags & XFLG_ERRS) {
                                /* output error */
                                ds->ds_if.if_oerrors++;
-                               if (dedebug)
-                       printf("de%d: oerror, flags=%b tdrerr=%b (len=%d)\n",
-                                   unit, rp->r_flags, XFLG_BITS,
-                                   rp->r_tdrerr, XERR_BITS, rp->r_slen);
+                               if (dedebug) {
+                                       char bits[64];
+                                       printf("de%d: oerror, flags=%s ",
+                                           unit, bitmask_snprintf(rp->r_flags,
+                                           XFLG_BITS, bits, sizeof(bits)));
+                                       printf("tdrerr%s (len=%d)\n",
+                                           rp->r_tdrerr, XERR_BITS,
+                                           bits, sizeof(bits));
+                               }
                        } else if (rp->r_flags & XFLG_ONE) {
                                /* one collision */
                                ds->ds_if.if_collisions++;
@@ -503,9 +512,13 @@ derecv(unit)
        rp = &ds->ds_rrent[ds->ds_rindex];
        while ((rp->r_flags & RFLG_OWN) == 0) {
                ds->ds_if.if_ipackets++;
-               if (ds->ds_deuba.iff_flags & UBA_NEEDBDP)
-                       UBAPURGE(ds->ds_deuba.iff_uba,
-                       ds->ds_ifr[ds->ds_rindex].ifrw_bdp);
+               if (ds->ds_deuba.iff_flags & UBA_NEEDBDP) {
+                       struct uba_softc *uh = (void *)ds->ds_dev.dv_parent;
+
+                       if (uh->uh_ubapurge)
+                               (*uh->uh_ubapurge)
+                                       (uh,ds->ds_ifr[ds->ds_rindex].ifrw_bdp);
+               }
                len = (rp->r_lenerr&RERR_MLEN) - sizeof (struct ether_header)
                        - 4;    /* don't forget checksum! */
                /* check for errors */
@@ -514,10 +527,16 @@ derecv(unit)
                    (rp->r_lenerr & (RERR_BUFL|RERR_UBTO|RERR_NCHN)) ||
                    len < ETHERMIN || len > ETHERMTU) {
                        ds->ds_if.if_ierrors++;
-                       if (dedebug)
-                       printf("de%d: ierror, flags=%b lenerr=%b (len=%d)\n",
-                               unit, rp->r_flags, RFLG_BITS, rp->r_lenerr,
-                               RERR_BITS, len);
+                       if (dedebug) {
+                               char bits[64];
+                               printf("de%d: ierror, flags=%s ",
+                                   unit, bitmask_snprintf(rp->r_flags,
+                                   RFLG_BITS, bits, sizeof(bits)));
+                               printf("lenerr=%s (len=%d)\n",
+                                   bitmask_snprintf(rp->r_lenerr,
+                                   RERR_BITS, bits, sizeof(bits)),
+                                   len);
+                       }
                } else
                        deread(ds, &ds->ds_ifr[ds->ds_rindex], len);
 
@@ -662,10 +681,13 @@ dewait(ds, fn)
                ;
        csr0 = addr->pcsr0;
        addr->pchigh = csr0 >> 8;
-       if (csr0 & PCSR0_PCEI)
-               printf("de%d: %s failed, csr0=%b csr1=%b\n", 
-                   ds->ds_dev.dv_unit, fn, csr0, PCSR0_BITS, 
-                   addr->pcsr1, PCSR1_BITS);
+       if (csr0 & PCSR0_PCEI) {
+               char bits[64];
+               printf("de%d: %s failed, csr0=%s ", ds->ds_dev.dv_unit, fn,
+                   bitmask_snprintf(csr0, PCSR0_BITS, bits, sizeof(bits)));
+               printf("csr1=%s\n", bitmask_snprintf(addr->pcsr1, PCSR1_BITS,
+                   bits, sizeof(bits)));
+       }
        return (csr0 & PCSR0_PCEI);
 }
 
diff --git a/sys/arch/vax/if/if_le.c b/sys/arch/vax/if/if_le.c
new file mode 100644 (file)
index 0000000..a41d5db
--- /dev/null
@@ -0,0 +1,238 @@
+/*     $NetBSD: if_le.c,v 1.3 1996/10/13 03:34:53 christos Exp $       */
+
+#define LEDEBUG         1              /* debug-level: 0 or 1 */
+/* #define LE_CHIP_IS_POKEY    /* does VS2000 need this ??? */
+
+/*-
+ * Copyright (c) 1995 Charles M. Hannum.  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.
+ *
+ *     @(#)if_le.c     8.2 (Berkeley) 11/16/93
+ */
+
+#include "bpfilter.h"
+
+#include <sys/param.h>
+#include <sys/syslog.h>
+#include <sys/socket.h>
+#include <sys/device.h>
+
+#include <net/if.h>
+
+#if INET
+#include <netinet/in.h>
+#include <netinet/if_ether.h>
+#endif
+
+/*
+ * This would be nice, but it's not yet there...
+ *
+ * #include <machine/autoconf.h>
+ */
+
+#include <machine/pte.h>
+#include <machine/cpu.h>
+#include <machine/mtpr.h>
+#include <machine/uvax.h>
+#include <machine/ka410.h>
+#include <machine/vsbus.h>
+
+#include <dev/ic/am7990reg.h>
+#define LE_NEED_BUF_CONTIG
+#include <dev/ic/am7990var.h>
+
+#include <dev/tc/if_levar.h>
+
+#define xdebug(x)
+
+#ifdef LE_CHIP_IS_POKEY
+/* 
+ * access LANCE registers and double-check their contents
+ */
+#define wbflush()      /* do nothing */
+void lewritereg();
+#define LERDWR(cntl, src, dst) { (dst) = (src); wbflush(); }
+#define LEWREG(src, dst)       lewritereg(&(dst), (src))
+#endif
+
+#define LE_IOSIZE 64*1024      /* 64K of real-mem are reserved and already */
+extern void *le_iomem;         /* mapped into virt-mem by cpu_steal_pages */
+extern u_long le_ioaddr;       /* le_iomem is virt, le_ioaddr is phys */
+
+#define LE_SOFTC(unit) le_cd.cd_devs[unit]
+#define LE_DELAY(x)    DELAY(x)
+
+int lematch __P((struct device *, void *, void *));
+void leattach __P((struct device *, struct device *, void *));
+
+int leintr __P((void *sc));
+
+struct cfattach le_ca = {
+       sizeof(struct le_softc), lematch, leattach
+};
+
+integrate void
+lewrcsr(sc, port, val)
+       struct le_softc *sc;
+       u_int16_t port, val;
+{
+       struct lereg1 *ler1 = sc->sc_r1;
+
+#ifdef LE_CHIP_IS_POKEY
+       LEWREG(port, ler1->ler1_rap);
+       LERDWR(port, val, ler1->ler1_rdp);
+#else
+       ler1->ler1_rap = port;
+       ler1->ler1_rdp = val;
+#endif
+}
+
+integrate u_int16_t
+lerdcsr(sc, port)
+       struct le_softc *sc;
+       u_int16_t port;
+{
+       struct lereg1 *ler1 = sc->sc_r1;
+       u_int16_t val;
+
+#ifdef LE_CHIP_IS_POKEY
+       LEWREG(port, ler1->ler1_rap);
+       LERDWR(0, ler1->ler1_rdp, val);
+#else
+       ler1->ler1_rap = port;
+       val = ler1->ler1_rdp;
+#endif
+       return (val);
+}
+
+int
+lematch(parent, match, aux)
+       struct device *parent;
+       void *match, *aux;
+{
+       struct cfdata *cf = match;
+       struct confargs *ca = aux;
+
+       /*
+        * There could/should be more checks, but for now...
+        */
+       if (strcmp(ca->ca_name, "le") &&
+           strcmp(ca->ca_name, "am7990") &&
+           strcmp(ca->ca_name, "AM7990"))
+               return (0);
+
+       return (1);
+}
+
+/*
+ *
+ */
+void
+leattach(parent, self, aux)
+       struct device *parent, *self;
+       void *aux;
+{
+       register struct le_softc *sc = (void *)self;
+       struct confargs *ca = aux;
+       u_char *cp;     /* pointer to MAC address */
+       int i;
+
+       sc->sc_r1  = (void*)uvax_phys2virt(ca->ca_ioaddr);
+
+       sc->sc_am7990.sc_conf3 = 0;
+       sc->sc_am7990.sc_mem = le_iomem;
+       sc->sc_am7990.sc_addr = le_ioaddr;
+       sc->sc_am7990.sc_memsize = LE_IOSIZE;
+
+       xdebug(("leattach: mem=%x, addr=%x, size=%x (%d)\n",
+           sc->sc_am7990.sc_mem, sc->sc_am7990.sc_addr,
+           sc->sc_am7990.sc_memsize, sc->sc_am7990.sc_memsize));
+
+       sc->sc_am7990.sc_copytodesc = am7990_copytobuf_contig;
+       sc->sc_am7990.sc_copyfromdesc = am7990_copyfrombuf_contig;
+       sc->sc_am7990.sc_copytobuf = am7990_copytobuf_contig;
+       sc->sc_am7990.sc_copyfrombuf = am7990_copyfrombuf_contig;
+       sc->sc_am7990.sc_zerobuf = am7990_zerobuf_contig;
+
+       /*
+        * Get the ethernet address out of rom
+        */
+       for (i = 0; i < sizeof(sc->sc_am7990.sc_arpcom.ac_enaddr); i++) {
+               int *eaddr = (void*)uvax_phys2virt(ca->ca_enaddr);
+               sc->sc_am7990.sc_arpcom.ac_enaddr[i] = (u_char)eaddr[i];
+       }
+
+       bcopy(self->dv_xname, sc->sc_am7990.sc_arpcom.ac_if.if_xname, IFNAMSIZ);
+       am7990_config(&sc->sc_am7990);
+
+#ifdef LEDEBUG
+       sc->sc_am7990.sc_debug = LEDEBUG;
+#endif
+
+       vsbus_intr_register(ca, am7990_intr, &sc->sc_am7990);
+       vsbus_intr_enable(ca);
+}
+
+integrate void
+lehwinit(sc)
+       struct le_softc *sc;
+{
+}
+
+#ifdef LE_CHIP_IS_POKEY
+/*
+ * Write a lance register port, reading it back to ensure success. This seems
+ * to be necessary during initialization, since the chip appears to be a bit
+ * pokey sometimes.
+ */
+void
+lewritereg(regptr, val)
+       register volatile u_short *regptr;
+       register u_short val;
+{
+       register int i = 0;
+
+       while (*regptr != val) {
+               *regptr = val;
+               wbflush();
+               if (++i > 10000) {
+                       printf("le: Reg did not settle (to x%x): x%x\n", val,
+                           *regptr);
+                       return;
+               }
+               DELAY(100);
+       }
+}
+#endif
index cb5fedd..8c150fb 100644 (file)
@@ -1,4 +1,4 @@
-/*     $NetBSD: if_qe.c,v 1.15 1996/05/19 16:43:07 ragge Exp $ */
+/*     $NetBSD: if_qe.c,v 1.18 1996/10/13 03:34:55 christos Exp $ */
 
 /*
  * Copyright (c) 1988 Regents of the University of California.
@@ -290,8 +290,8 @@ qematch(parent, match, aux)
         * Map the communications area and the setup packet.
         */
        sc->setupaddr =
-           uballoc(0, (caddr_t)sc->setup_pkt, sizeof(sc->setup_pkt), 0);
-       sc->rringaddr = (struct qe_ring *) uballoc(0, (caddr_t)sc->rring,
+           uballoc(ubasc, (caddr_t)sc->setup_pkt, sizeof(sc->setup_pkt), 0);
+       sc->rringaddr = (struct qe_ring *) uballoc(ubasc, (caddr_t)sc->rring,
            sizeof(struct qe_ring) * (NTOT+2), 0);
        prp = (struct qe_ring *)UBAI_ADDR((int)sc->rringaddr);
 
@@ -338,8 +338,8 @@ qematch(parent, match, aux)
        /*
         * All done with the bus resources.
         */
-       ubarelse(0, &sc->setupaddr);
-       ubarelse(0, (int *)&sc->rringaddr);
+       ubarelse(ubasc, &sc->setupaddr);
+       ubarelse(ubasc, (int *)&sc->rringaddr);
        sc->ipl = 0x15;
        ua->ua_ivec = qeintr;
        return 1;
@@ -418,6 +418,7 @@ qeinit(sc)
        struct qe_softc *sc;
 {
        struct qedevice *addr = sc->qe_vaddr;
+       struct uba_softc *ubasc = (void *)sc->qe_dev.dv_parent;
        struct ifnet *ifp = (struct ifnet *)&sc->qe_if;
        int i;
        int s;
@@ -432,13 +433,13 @@ qeinit(sc)
                /*
                 * map the communications area onto the device
                 */
-               i = uballoc(0, (caddr_t)sc->rring,
+               i = uballoc(ubasc, (caddr_t)sc->rring,
                    sizeof(struct qe_ring) * (NTOT+2), 0);
                if (i == 0)
                        goto fail;
                sc->rringaddr = (struct qe_ring *)UBAI_ADDR(i);
                sc->tringaddr = sc->rringaddr + NRCV + 1;
-               i = uballoc(0, (caddr_t)sc->setup_pkt,
+               i = uballoc(ubasc, (caddr_t)sc->setup_pkt,
                    sizeof(sc->setup_pkt), 0);
                if (i == 0)
                        goto fail;
@@ -446,7 +447,7 @@ qeinit(sc)
                /*
                 * init buffers and maps
                 */
-               if (if_ubaminit(&sc->qe_uba, sc->qe_dev.dv_parent->dv_unit,
+               if (if_ubaminit(&sc->qe_uba, (void *)sc->qe_dev.dv_parent,
                    sizeof (struct ether_header), (int)btoc(MAXPACKETSIZE),
                    sc->qe_ifr, NRCV, sc->qe_ifw, NXMT) == 0) {
        fail:
index 5c793de..4b02356 100644 (file)
@@ -1,4 +1,4 @@
-/*     $NetBSD: if_uba.c,v 1.11 1996/03/17 22:56:36 ragge Exp $        */
+/*     $NetBSD: if_uba.c,v 1.12 1996/08/20 14:07:46 ragge Exp $        */
 
 /*
  * Copyright (c) 1982, 1986, 1988 Regents of the University of California.
@@ -50,7 +50,7 @@
 #include <machine/pte.h>
 #include <machine/mtpr.h>
 #include <machine/vmparam.h>
-#include <machine/macros.h>
+#include <machine/cpu.h>
 
 #include <vax/if/if_uba.h>
 #include <vax/uba/ubareg.h>
@@ -68,20 +68,20 @@ static      void restor_xmtbuf __P((struct ifxmt *));
  */
 
 /*
- * Init UNIBUS for interface on uban whose headers of size hlen are to
+ * Init UNIBUS for interface whose headers of size hlen are to
  * end on a page boundary.  We allocate a UNIBUS map register for the page
  * with the header, and nmr more UNIBUS map registers for i/o on the adapter,
  * doing this once for each read and once for each write buffer.  We also
  * allocate page frames in the mbuffer pool for these pages.
  */
 int
-if_ubaminit(ifu, uban, hlen, nmr, ifr, nr, ifw, nw)
+if_ubaminit(ifu, uh, hlen, nmr, ifr, nr, ifw, nw)
        register struct ifubinfo *ifu;
-       int uban, hlen, nmr, nr, nw;
+       struct uba_softc *uh;
+       int hlen, nmr, nr, nw;
        register struct ifrw *ifr;
        register struct ifxmt *ifw;
 {
-       struct  uba_softc *ubasc;
        register caddr_t p;
        caddr_t cp;
        int i, nclbytes, off;
@@ -111,10 +111,9 @@ if_ubaminit(ifu, uban, hlen, nmr, ifr, nr, ifw, nw)
                        p += nclbytes;
                }
                ifu->iff_hlen = hlen;
-               ifu->iff_uban = uban;
-               ubasc = uba_cd.cd_devs[uban];
-               ifu->iff_uba = ubasc->uh_uba;
-               ifu->iff_ubamr = ubasc->uh_mr;
+               ifu->iff_softc = uh;
+               ifu->iff_uba = uh->uh_uba;
+               ifu->iff_ubamr = uh->uh_mr;
        }
        for (i = 0; i < nr; i++)
                if (if_ubaalloc(ifu, &ifr[i], nmr) == 0) {
@@ -137,9 +136,9 @@ if_ubaminit(ifu, uban, hlen, nmr, ifr, nr, ifw, nw)
        return (1);
 bad:
        while (--nw >= 0)
-               ubarelse(ifu->iff_uban, &ifw[nw].ifw_info);
+               ubarelse(ifu->iff_softc, &ifw[nw].ifw_info);
        while (--nr >= 0)
-               ubarelse(ifu->iff_uban, &ifr[nr].ifrw_info);
+               ubarelse(ifu->iff_softc, &ifr[nr].ifrw_info);
        free(cp, M_DEVBUF);
        ifr[0].ifrw_addr = 0;
        return (0);
@@ -159,7 +158,7 @@ if_ubaalloc(ifu, ifrw, nmr)
        register int info;
 
        info =
-           uballoc(ifu->iff_uban, ifrw->ifrw_addr, nmr*NBPG + ifu->iff_hlen,
+           uballoc(ifu->iff_softc, ifrw->ifrw_addr, nmr*NBPG + ifu->iff_hlen,
                ifu->iff_flags);
        if (info == 0)
                return (0);
index 8b425fd..5ae8c51 100644 (file)
@@ -1,4 +1,4 @@
-/*     $NetBSD: if_uba.h,v 1.5 1996/04/08 18:34:57 ragge Exp $ */
+/*     $NetBSD: if_uba.h,v 1.6 1996/08/20 14:07:50 ragge Exp $ */
 
 /*
  * Copyright (c) 1982, 1986 Regents of the University of California.
  * Information per interface.
  */
 struct ifubinfo {
-       short   iff_uban;                       /* uba number */
+       short   iff_flags;                      /* used during uballoc's */
        short   iff_hlen;                       /* local net header length */
        struct  uba_regs *iff_uba;              /* uba adaptor regs, in vm */
        struct  pte *iff_ubamr;                 /* uba map regs, in vm */
-       short   iff_flags;                      /* used during uballoc's */
+       struct  uba_softc *iff_softc;           /* uba */
 };
 
 /*
@@ -116,7 +116,7 @@ struct ifuba {
        struct  ifxmt ifu_xmt;
 };
 
-#define        ifu_uban        ifu_info.iff_uban
+#define        ifu_softc       ifu_info.iff_softc
 #define        ifu_hlen        ifu_info.iff_hlen
 #define        ifu_uba         ifu_info.iff_uba
 #define        ifu_ubamr       ifu_info.iff_ubamr
@@ -134,7 +134,7 @@ struct ifuba {
                if_ubaput(&(ifu)->ifu_info, &(ifu)->ifu_xmt, m)
 
 /* Prototypes */
-int    if_ubaminit __P((struct ifubinfo *, int, int, int,
+int    if_ubaminit __P((struct ifubinfo *, struct uba_softc *, int, int,
            struct ifrw *, int, struct ifxmt *, int));
 int    if_ubaput __P((struct ifubinfo *, struct ifxmt *, struct mbuf *));
 struct mbuf *if_ubaget __P((struct ifubinfo *, struct ifrw *, int,
index 088f4a3..a9ded0b 100644 (file)
@@ -1,4 +1,4 @@
-/*     $NetBSD: ansi.h,v 1.4 1996/03/16 01:32:03 jtc Exp $     */
+/*     $NetBSD: ansi.h,v 1.5 1996/11/15 22:39:01 jtc Exp $     */
 
 /*-
  * Copyright (c) 1990 The Regents of the University of California.
@@ -57,5 +57,8 @@
 #define _BSD_VA_LIST_   char *                  /* va_list */
 #define        _BSD_WCHAR_T_   int                     /* wchar_t */
 #define _BSD_WINT_T_   int                     /* wint_t */
+#define _BSD_CLOCKID_T_        int
+#define _BSD_TIMER_T_  int
+
 
 #endif  /* _ANSI_H_ */
diff --git a/sys/arch/vax/include/aout_machdep.h b/sys/arch/vax/include/aout_machdep.h
new file mode 100644 (file)
index 0000000..3d34ccc
--- /dev/null
@@ -0,0 +1,49 @@
+/*     $NetBSD: aout_machdep.h,v 1.4 1995/09/23 14:57:40 ragge Exp $   */
+
+/*
+ * Copyright (c) 1993 Christopher G. Demetriou
+ * 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. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _VAX_EXEC_H_
+#define _VAX_EXEC_H_
+
+#define __LDPGSZ       1024
+
+/* Relocation format. */
+struct relocation_info_vax {
+       int r_address;                  /* offset in text or data segment */
+       unsigned int r_symbolnum : 24,  /* ordinal number of add symbol */
+                        r_pcrel :  1,  /* 1 if value should be pc-relative */
+                       r_length :  2,  /* log base 2 of value's width */
+                       r_extern :  1,  /* 1 if need to add symbol to value */
+                      r_baserel :  1,  /* linkage table relative */
+                     r_jmptable :  1,  /* relocate to jump table */
+                     r_relative :  1,  /* load address relative */
+                         r_copy :  1;  /* run time copy */
+};
+#define relocation_info        relocation_info_vax
+
+#endif  /* _VAX_EXEC_H_ */
index b77cf3d..b97107d 100644 (file)
@@ -1,4 +1,4 @@
-/*     $NetBSD: asm.h,v 1.4 1996/01/06 18:37:35 ragge Exp $ */
+/*     $NetBSD: asm.h,v 1.5 1996/11/30 02:49:06 jtc Exp $ */
 /*
  * Copyright (c) 1982, 1993
  *     The Regents of the University of California.  All rights reserved.
@@ -51,7 +51,7 @@
 #define        R11     0x800
 
 #ifdef __STDC__
-#ifdef PROF
+#ifdef GPROF
 #define        ENTRY(x, regs) \
        .globl _ ## x ## ; .align 2; _ ## x ## : .word regs; \
        .data; 1:; .long 0; .text; moval 1b,r0; jsb mcount
@@ -65,7 +65,7 @@
        .globl x; .align 2; x ## : .word regs
 #endif
 # else
-#ifdef PROF
+#ifdef GPROF
 #define ENTRY(x, regs) \
        .globl _/**/x; .align 2; _/**/x: .word regs; \
        .data; 1:; .long 0; .text; moval 1b,r0; jsb mcount
diff --git a/sys/arch/vax/include/clock.h b/sys/arch/vax/include/clock.h
new file mode 100644 (file)
index 0000000..28bffbe
--- /dev/null
@@ -0,0 +1,69 @@
+/*     $NetBSD: clock.h,v 1.1 1996/07/20 17:35:42 ragge Exp $ */
+/*
+ * Copyright (c) 1996 Ludd, University of Lule}, Sweden.
+ * 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 at Ludd, University of 
+ *     Lule}, Sweden and its contributors.
+ * 4. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+/*
+ * Conversion structure.
+ */
+struct chiptime {
+       long    sec;
+       long    min;
+       long    hour;
+       long    day;
+       long    mon;
+       long    year;
+};
+
+/*
+ * Time constants. These are unlikely to change.
+ */
+#define IS_LEAPYEAR(y) (((y % 4) == 0) && (y % 100))
+
+#define SEC_PER_MIN    (60)
+#define SEC_PER_HOUR   (SEC_PER_MIN * 60)
+#define SEC_PER_DAY    (SEC_PER_HOUR * 24)
+#define DAYSPERYEAR(y) (IS_LEAPYEAR(y) ? 366 : 365)
+#define SECPERYEAR(y)  (DAYSPERYEAR(y) * SEC_PER_DAY)
+
+#define CLKREAD_OK     0
+#define CLKREAD_BAD    -1
+#define CLKREAD_WARN   -2
+
+#define TODRBASE       (1 << 28) /* Rumours says it comes from VMS */
+
+/* Prototypes */
+long   chiptotime __P((struct chiptime *));
+void   timetochip __P((struct chiptime *));
+void   generic_clock __P((void));
+void   no_nicr_clock __P((void));
+int    generic_clkread __P((time_t));
+void   generic_clkwrite __P((void));
index a99710b..b928a64 100644 (file)
@@ -1,4 +1,4 @@
-/*      $NetBSD: cpu.h,v 1.17 1996/05/19 16:43:16 ragge Exp $      */
+/*      $NetBSD: cpu.h,v 1.19 1996/07/20 17:58:12 ragge Exp $      */
 
 /*
  * Copyright (c) 1994 Ludd, University of Lule}, Sweden
 #define        cpu_wait(p)
 #define        cpu_swapout(p)
 
-
-extern int cpunumber, cpu_type;
 extern struct cpu_dep cpu_calls[];
 
 struct cpu_dep {
        void    (*cpu_steal_pages) __P((void)); /* pmap init before mm is on */
-       int     (*cpu_clock) __P((void)); /* CPU dependent clock handling */
+       void    (*cpu_clock) __P((void)); /* CPU dep RT clock start */
        int     (*cpu_mchk) __P((caddr_t));   /* Machine check handling */
        void    (*cpu_memerr) __P((void)); /* Memory subsystem errors */
            /* Autoconfiguration */
        void    (*cpu_conf) __P((struct device *, struct device *, void *));
+       int     (*cpu_clkread) __P((time_t));   /* Read cpu clock time */
+       void    (*cpu_clkwrite) __P((void));    /* Write system time to cpu */
 };
 
 struct clockframe {
@@ -60,9 +60,12 @@ struct clockframe {
         int     ps;
 };
 
+extern int cold;
+extern int mastercpu;
+
 #define        setsoftnet()    mtpr(12,PR_SIRR)
 #define setsoftclock() mtpr(8,PR_SIRR)
-
+#define        todr()          mfpr(PR_TODR)
 /*
  * Preempt the current process if in interrupt from user mode,
  * or after the current trap/syscall if in system mode.
@@ -93,7 +96,8 @@ extern        int     want_resched;   /* resched() was called */
 int    badaddr __P((caddr_t, int));
 void   cpu_set_kpc __P((struct proc *, void (*)(struct proc *)));
 void   cpu_swapin __P((struct proc *));
-int    hp_getdev __P((int, int));
+int    hp_getdev __P((int, int, char **));
+int    ra_getdev __P((int, int, int, char **));
 void   configure __P((void));
 void   dumpconf __P((void));
 void   dumpsys __P((void));
index ac0699c..02e1fee 100644 (file)
@@ -1,5 +1,5 @@
-/*     $OpenBSD: endian.h,v 1.3 1996/11/25 13:11:40 niklas Exp $       */
-/*     $NetBSD: endian.h,v 1.7 1996/04/08 18:35:48 ragge Exp $ */
+/*     $OpenBSD: endian.h,v 1.4 1997/01/15 23:24:37 maja Exp $ */
+/*     $NetBSD: endian.h,v 1.8 1996/10/13 03:28:00 christos Exp $      */
 
 /*
  * Copyright (c) 1987, 1991 Regents of the University of California.
diff --git a/sys/arch/vax/include/ka410.h b/sys/arch/vax/include/ka410.h
new file mode 100644 (file)
index 0000000..379cf98
--- /dev/null
@@ -0,0 +1,212 @@
+/*     $NetBSD: ka410.h,v 1.1 1996/07/20 17:58:14 ragge Exp $ */
+/*
+ * Copyright (c) 1996 Ludd, University of Lule}, Sweden.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Ludd by Bertram Barth.
+ *
+ * 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 at Ludd, University of 
+ *      Lule}, Sweden and its contributors.
+ * 4. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * Definition for  I/O addresses of
+ *
+ *     MicroVAX 2000   (TeamMate)
+ *     VAXstation 2000 (VAXstar)
+ */
+
+#define KA410_SIDEX    0x20040004      /* SID extension register */
+
+#define KA410_CFGTST   0x20020000      /* Configuration and Test register */
+#define KA410_IORESET  0x20020000      /* I/O Reset register */
+
+#define KA410_ROM_BASE 0x20040000      /* System module ROM */
+#define KA410_ROM_END  0x2007FFFF
+#define KA410_ROM_SIZE    0x40000
+
+#define KA410_IVN_BASE 0x20040020      /* Interrupt Vector Numbers */
+#define KA410_IVN_END  0x2004003F
+#define KA410_IVN_SIZE       0x20
+
+#define KA410_HLTCOD   0x20080000      /* Halt Code Register */
+#define KA410_MSER     0x20080004      /* Memory System Error register */
+#define KA410_MEAR     0x20080008      /* Memory Error Address register */
+#define KA410_INTMSK   0x2008000C      /* Interrupt Mask register */
+#define KA410_VDCORG   0x2008000D      /* Video Controller Origin Register */
+#define KA410_VDCSEL   0x2008000E      /* Video Controller Select Register */
+#define KA410_INTREQ   0x2008000F      /* Interrupt Request register */
+#define KA410_INTCLR   0x2008000F      /* Interrupt Request clear register */
+
+/*
+ * Other fixed addresses which should be mapped
+ */
+#define KA410_CPU_BASE 0x20080000
+#define KA410_CPU_END  0x200800FF
+#define KA410_CPU_SIZE      0x100
+#define KA410_NWA_BASE 0x20090000      /* Network Address ROM */
+#define KA410_NWA_END  0x2009007F
+#define KA410_NWA_SIZE       0x80
+#define KA410_SER_BASE 0x200A0000      /* Serial line controller */
+#define KA410_SER_END  0x200A000F
+#define KA410_SER_SIZE        0x10
+#define KA410_WAT_BASE 0x200B0000      /* TOY clock and NV-RAM */
+#define KA410_WAT_END  0x200B00FF
+#define KA410_WAT_SIZE      0x100
+#define KA410_DKC_BASE 0x200C0000      /* Disk Controller Ports */
+#define KA410_DKC_END  0x200C0007
+#define KA410_DKC_SIZE       0x08
+#define KA410_SCS_BASE 0x200C0080      /* Tape (SCSI) Controller Chip */
+#define KA410_SCS_END  0x200C009F
+#define KA410_SCS_SIZE       0x20
+#define KA410_DMA_BASE 0x200D0000      /* Disk Data buffer RAM */
+#define KA410_DMA_END  0x200D3FFF
+#define KA410_DMA_SIZE     0x4000
+#define KA410_LAN_BASE 0x200E0000      /* LANCE chip registers */
+#define KA410_LAN_END  0x200E0007
+#define KA410_LAN_SIZE       0x08
+#define KA410_CUR_BASE 0x200F0000      /* Monochrome video cursor chip */
+#define KA410_CUR_END  0x200F0007
+#define KA410_CUR_SIZE       0x08
+
+#define KA410_SCS_DADR 0x200C00A0      /* Tape(SCSI) DMA address register */
+#define KA410_SCS_DCNT 0x200C00C0      /* Tape(SCSI) DMA byte count reg. */
+#define KA410_SCS_DDIR 0x200C00C4      /* Tape(SCSI) DMA transfer direction */
+
+#define KA410_CUR_CMD  0x200F0000      /* Cursor Command Register */
+#define KA410_CUR_XPOS 0x200F0004      /* Cursor X position */
+#define KA410_CUR_YPOS 0x200F0008      /* Cursor Y position */
+
+#define KA410_CUR_XMIN1        0x200F000C      /* Region 1 left edge */
+#define KA410_CUR_XMAX1        0x200F0010      /* Region 1 right edge */
+#define KA410_CUR_YMIN1        0x200F0014      /* Region 1 top edge */
+#define KA410_CUR_YMAX1        0x200F0018      /* Region 1 bottom edge */
+
+#define KA410_CUR_XMIN2        0x200F002C      /* Region 2 left edge */
+#define KA410_CUR_XMAX2        0x200F0030      /* Region 2 right edge */
+#define KA410_CUR_YMIN2        0x200F0034      /* Region 2 top edge */
+#define KA410_CUR_YMAX2        0x200F0038      /* Region 2 bottom edge */
+
+/*
+ * Definitions for the Configuration and Test Register
+ */
+#define KA410_CFG_MULTU                0x80    /* MicroVAX or VAXstation */
+#define KA410_CFG_NETOPT       0x40    /* Network option present */
+#define KA410_CFG_L3CON                0x20    /* Console on line #3 of dc */
+#define KA410_CFG_CURTEST      0x10    /* Cursor Test (monochrom) */
+#define KA410_CFG_VIDOPT       0x08    /* Video option present */
+#define KA410_CFG_MEMSZ                0x07    /* Memory option type/size */
+
+#define KA410_CFG_0MB          0x00    /* No additional Memory board */
+#define KA410_CFG_1MB          0x01
+#define KA410_CFG_2MB          0x02
+#define KA410_CFG_4MB          0x03
+#define KA410_CFG_6MB          0x04
+#define KA410_CFG_8MB          0x05
+#define KA410_CFG_12MB         0x06
+#define KA410_CFG_14MB         0x07
+
+
+/* 
+ * interrupt request-, clear-, and mask register 
+ */
+extern volatile unsigned char *ka410_intreq;
+extern volatile unsigned char *ka410_intclr;
+extern volatile unsigned char *ka410_intmsk;
+
+#define INTR_SR        (1<<7)  /* Serial line receiver or silo full */
+#define INTR_ST        (1<<6)  /* Serial line transmitter done */
+#define INTR_NP        (1<<5)  /* Network controller primary */
+#define INTR_NS        (1<<4)  /* Network controller secondary */
+#define INTR_VF        (1<<3)  /* Video end of frame */
+#define INTR_VS        (1<<2)  /* Video secondary */
+#define INTR_SC        (1<<1)  /* SCSI controller */
+#define INTR_DC        (1<<0)  /* Disk controller */
+
+/*
+ * interrupt vector numbers
+ */
+#define IVEC_BASE      0x20040020
+#define IVEC_SR                0x000002C0
+#define IVEC_ST                0x000002C4
+#define IVEC_NP                0x00000250
+#define IVEC_NS                0x00000254
+#define IVEC_VF                0x00000244
+#define IVEC_VS                0x00000248
+#define IVEC_SC                0x000003F8
+#define IVEC_DC                0x000003FC
+
+/*
+ * Clock-Chip data in NVRAM
+ */
+#define KA410_CPMBX    0x200B0038      /* Console Mailbox (1 byte) */
+#define KA410_CPFLG    0x200B003C      /* Console Program Flags (1 byte) */
+#define KA410_LK201_ID 0x200B0040      /* Keyboard Variation (1 byte) */
+#define KA410_CONS_ID  0x200B0044      /* Console Device Type (1 byte) */
+#define KA410_SCR      0x200B0048      /* Console Scratch RAM */
+#define KA410_TEMP     0x200B0058      /* Used by System Firmware */
+#define KA410_BAT_CHK  0x200B0088      /* Battery Check Data */
+#define KA410_BOOTDEV  0x200B0098      /* Default Boot Device (4 bytes) */
+#define KA410_BOOTFLG  0x200B00A8      /* Default Boot Flags (4 bytes) */
+#define KA410_SCRLEN   0x200B00B8      /* Number of pages of SCR (1 byte) */
+#define KA410_SCSIPORT 0x200B00BC      /* Tape Controller Port Data */
+#define KA410_RESERVED 0x200B00C0      /* Reserved (16 bytes) */
+
+
+struct ka410_cpu {
+       u_long  ka410_hltcod;
+       u_long  ka410_mser;
+       u_long  ka410_cear;
+       u_long  ka410_intmsk;
+};
+
+/*
+ * KA410 uses bits 2-9 of longwords to store single bytes in NVRAM, 
+ * thus we declare the clock as an struct of bit-fields, so that the
+ * generic clock-routines work for KA410...
+ */
+struct ka410_clock {
+       u_long  :2;     u_long  sec     :8;     u_long  :22;
+       u_long  :2;     u_long  secalrm :8;     u_long  :22;
+       u_long  :2;     u_long  min     :8;     u_long  :22;
+       u_long  :2;     u_long  minalrm :8;     u_long  :22;
+       u_long  :2;     u_long  hr      :8;     u_long  :22;
+       u_long  :2;     u_long  hralrm  :8;     u_long  :22;
+       u_long  :2;     u_long  dayofwk :8;     u_long  :22;
+       u_long  :2;     u_long  day     :8;     u_long  :22;
+       u_long  :2;     u_long  mon     :8;     u_long  :22;
+       u_long  :2;     u_long  yr      :8;     u_long  :22;
+       u_long  :2;     u_long  csr0    :8;     u_long  :22;
+       u_long  :2;     u_long  csr1    :8;     u_long  :22;
+       u_long  :2;     u_long  csr2    :8;     u_long  :22;
+       u_long  :2;     u_long  csr3    :8;     u_long  :22;
+       u_long  :2;     u_long  cpmbx   :8;     u_long  :22;
+};
+
+/* Prototypes */
+int ka410_setup __P((struct uvax_calls *p, int flags));
+static int ka410_clkread __P((time_t));
+static void ka410_clkwrite __P((void));
diff --git a/sys/arch/vax/include/ka420.h b/sys/arch/vax/include/ka420.h
new file mode 100644 (file)
index 0000000..ed1fa24
--- /dev/null
@@ -0,0 +1,140 @@
+/*     $NetBSD: ka420.h,v 1.1 1996/07/20 17:58:15 ragge Exp $ */
+/*
+ * Copyright (c) 1996 Ludd, University of Lule}, Sweden.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Ludd by Bertram Barth.
+ *
+ * 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 at Ludd, University of 
+ *      Lule}, Sweden and its contributors.
+ * 4. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * Definitions for I/O addresses of
+ *
+ *     VAXstation 3100 models 30, 40   (PVAX)
+ *     MicroVAX 3100 models 10, 20     (Teammate II)
+ *     MicroVAX 3100 models 10e, 20e   (Teammate II)
+ *     VAXstation 3100 models 38, 48   (PVAX rev#7)
+ */
+
+#define KA420_SIDEX    0x20040004      /* SID extension register */
+
+#define KA420_CH2_BASE 0x10000000      /* 2nd level cache data area */
+#define KA420_CH2_END  0x10007FFF
+#define KA420_CH2_SIZE     0x8000
+#define KA420_CT2_BASE 0x10010000      /* 2nd level cache tag area */
+#define KA420_CT2_END  0x10017FFF
+#define KA420_CT2_SIZE     0x8000
+#define KA420_CH2_CREG 0x20084000      /* 2nd level cache control register */
+
+#define KA420_CFGTST   0x20020000      /* Configuration and Test register */
+#define KA420_IORESET  0x20020000      /* I/O Reset register */
+
+#define KA420_ROM_BASE 0x20040000      /* System module ROM */
+#define KA420_ROM_END  0x2007FFFF
+#define KA420_ROM_SIZE    0x40000      /* ??? */
+
+#define KA420_IVN_BASE 0x20040020      /* Interrupt Vector Numbers */
+#define KA420_IVN_END  0x2004003F
+#define KA420_IVN_SIZE       0x20
+
+#define KA420_HLTCOD   0x20080000      /* Halt Code Register */
+#define KA420_MSER     0x20080004      /* Memory System Error register */
+#define KA420_MEAR     0x20080008      /* Memory Error Address register */
+#define KA420_INTMSK   0x2008000C      /* Interrupt Mask register */
+#define KA420_VDCORG   0x2008000D      /* Video Controller Origin Register */
+#define KA420_VDCSEL   0x2008000E      /* Video Controller Select Register */
+#define KA420_INTREQ   0x2008000F      /* Interrupt Request register */
+#define KA420_INTCLR   0x2008000F      /* Interrupt Request clear register */
+
+/*
+ * Other fixed addresses which should be mapped
+ */
+#define KA420_NWA_BASE 0x20090000      /* Network Address ROM */
+#define KA420_NWA_END  0x2009007F
+#define KA420_NWA_SIZE       0x80
+#define KA420_SER_BASE 0x200A0000      /* Serial line controller */
+#define KA420_SER_END  0x200A000F
+#define KA420_SER_SIZE        0x10
+#define KA420_WAT_BASE 0x200B0000      /* TOY clock and NV-RAM */
+#define KA420_WAT_END  0x200B00FF
+#define KA420_WAT_SIZE      0x100
+#define KA420_DKC_BASE 0x200C0000      /* Disk Controller Ports */
+#define KA420_DKC_END  0x200C0007
+#define KA420_DKC_SIZE       0x08
+#define KA420_SCS_BASE 0x200C0080      /* Tape (SCSI) Controller Chip */
+#define KA420_SCS_END  0x200C009F
+#define KA420_SCS_SIZE       0x20
+#define KA420_D16_BASE 0x200D0000      /* 16KB (compatibility) Data Buffer */
+#define KA420_D16_END  0x200D3FFF
+#define KA420_D16_SIZE     0x4000
+#define KA420_LAN_BASE 0x200E0000      /* LANCE chip registers */
+#define KA420_LAN_END  0x200E0007
+#define KA420_LAN_SIZE       0x08
+#define KA420_CUR_BASE 0x200F0000      /* Monochrome video cursor chip */
+#define KA420_CUR_END  0x200F0007
+#define KA420_CUR_SIZE       0x08
+#define KA420_DMA_BASE 0x202D0000      /* 128KB Data Buffer */
+#define KA420_DMA_END  0x202EFFFF
+#define KA420_DMA_SIZE     0x20000
+
+#define KA420_SCD_DADR 0x200C00A0      /* Tape(SCSI) DMA address register */
+#define KA420_SCD_DCNT 0x200C00C0      /* Tape(SCSI) DMA byte count reg. */
+#define KA420_SCD_DDIR 0x200C00C4      /* Tape(SCSI) DMA transfer direction */
+
+#define KA420_STC_MODE 0x200C00E0      /* Storage Controller Mode register */
+
+#define KA420_CUR_CMD  0x200F0000      /* Cursor Command Register */
+#define KA420_CUR_XPOS 0x200F0004      /* Cursor X position */
+#define KA420_CUR_YPOS 0x200F0008      /* Cursor Y position */
+
+#define KA420_CUR_XMIN1        0x200F000C      /* Region 1 left edge */
+#define KA420_CUR_XMAX1        0x200F0010      /* Region 1 right edge */
+#define KA420_CUR_YMIN1        0x200F0014      /* Region 1 top edge */
+#define KA420_CUR_YMAX1        0x200F0018      /* Region 1 bottom edge */
+
+#define KA420_CUR_XMIN2        0x200F002C      /* Region 2 left edge */
+#define KA420_CUR_XMAX2        0x200F0030      /* Region 2 right edge */
+#define KA420_CUR_YMIN2        0x200F0034      /* Region 2 top edge */
+#define KA420_CUR_YMAX2        0x200F0038      /* Region 2 bottom edge */
+
+/*
+ * Clock-Chip data in NVRAM
+ */
+#define KA420_CPMBX    0x200B0038      /* Console Mailbox (1 byte) */
+#define KA420_CPFLG    0x200B003C      /* Console Program Flags (1 byte) */
+#define KA420_LK201_ID 0x200B0040      /* Keyboard Variation (1 byte) */
+#define KA420_CONS_ID  0x200B0044      /* Console Device Type (1 byte) */
+#define KA420_SCR      0x200B0048      /* Console Scratch RAM */
+#define KA420_TEMP     0x200B0058      /* Used by System Firmware */
+#define KA420_BAT_CHK  0x200B0088      /* Battery Check Data */
+#define KA420_BOOTDEV  0x200B0098      /* Default Boot Device (4 bytes) */
+#define KA420_BOOTFLG  0x200B00A8      /* Default Boot Flags (4 bytes) */
+#define KA420_SCRLEN   0x200B00B8      /* Number of pages of SCR (1 byte) */
+#define KA420_SCSIPORT 0x200B00BC      /* Tape Controller Port Data */
+#define KA420_RESERVED 0x200B00C0      /* Reserved (16 bytes) */
+
diff --git a/sys/arch/vax/include/ka43.h b/sys/arch/vax/include/ka43.h
new file mode 100644 (file)
index 0000000..41981eb
--- /dev/null
@@ -0,0 +1,209 @@
+/*     $NetBSD: ka43.h,v 1.1 1996/07/20 17:58:16 ragge Exp $ */
+/*
+ * Copyright (c) 1996 Ludd, University of Lule}, Sweden.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Ludd by Bertram Barth.
+ *
+ * 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 at Ludd, University of 
+ *      Lule}, Sweden and its contributors.
+ * 4. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * Definitions for I/O addresses of
+ *
+ *     VAXstation 3100 model 76        (RigelMAX)
+ */
+
+#define KA43_SIDEX     0x20040004      /* SID extension register */
+
+#define KA43_CFGTST    0x20020000      /* Configuration and Test register */
+#define KA43_IORESET   0x20020000      /* I/O Reset register */
+
+#define KA43_ROMGETC   0x20040044
+#define KA43_ROMPUTC   0x20040058
+#define KA43_ROMPUTS   0x2004004C
+
+#define KA43_CH2_BASE  0x10000000      /* 2nd level cache data area */
+#define KA43_CH2_END   0x1FFFFFFF
+#define KA43_CH2_SIZE  0x10000000
+#define KA43_CT2_BASE  0x21000000      /* 2nd level cache tag area */
+#define KA43_CT2_END   0x2101FFFF
+#define KA43_CT2_SIZE     0x20000
+#define KA43_CH2_CREG  0x21100000      /* 2nd level cache control register */
+#define KA43_SESR      0x21100000      /* ??? */
+
+#define KA43_ROM_BASE  0x20040000      /* System module ROM */
+#define KA43_ROM_END   0x2007FFFF
+#define KA43_ROM_SIZE     0x40000      /* ??? */
+
+#define KA43_IVN_BASE  0x20040020      /* Interrupt Vector Numbers */
+#define KA43_IVN_END   0x2004003F
+#define KA43_IVN_SIZE        0x20
+
+#define KA43_HLTCOD    0x20080000      /* Halt Code Register */
+#define KA43_MSER      0x20080004      /* Memory System Error register */
+#define KA43_MEAR      0x20080008      /* Memory Error Address register */
+#define KA43_INTMSK    0x2008000C      /* Interrupt Mask register */
+#define KA43_VDCORG    0x2008000D      /* Video Controller Origin Register */
+#define KA43_VDCSEL    0x2008000E      /* Video Controller Select Register */
+#define KA43_INTREQ    0x2008000F      /* Interrupt Request register */
+#define KA43_INTCLR    0x2008000F      /* Interrupt Request clear register */
+#define KA43_DIAGDSP   0x20080010
+#define KA43_PARCTL    0x20080014      /* Parity Control Register */
+#define KA43_DIAGTME   0x2008001E
+
+#define KA43_PCTL_DPEN 0x00000001      /* DMA parity enable (bit 0) */
+#define KA43_PCTL_CPEN 0x00000002      /* CPU Parity enable (bit 1) */
+#define KA43_PCTL_DMA  0x01000000      /* LANCE DMA control (bit 24) */
+
+#define KA43_SESR_CENB 0x00000001
+#define KA43_SESR_SERR  0x00000002
+#define KA43_SESR_LERR 0x00000004
+#define KA43_SESR_CERR 0x00000008
+#define KA43_SESR_DIRTY        0x00000010
+#define KA43_SESR_MISS 0x00000020
+#define KA43_SESR_DPE  0x00000040
+#define KA43_SESR_TPE  0x00000080
+#define KA43_SESR_WSB  0x00010000
+#define KA43_SESR_CIEA 0x7FFC0000
+
+#define KA43_PCS_FORCEHIT      (1<<0)  /* Force hit */
+#define KA43_PCS_ENABLE                (1<<1)  /* Enable primary cache */
+#define KA43_PCS_FLUSH         (1<<2)  /* Flush cache */
+#define KA43_PCS_REFRESH       (1<<3)  /* Enable refresh */
+#define KA43_PCS_HIT           (1<<4)  /* Cache hit */
+#define KA43_PCS_INTERRUPT     (1<<5)  /* Interrupt pending */
+#define KA43_PCS_TRAP2         (1<<6)  /* Trap while trap */
+#define KA43_PCS_TRAP1         (1<<7)  /* Micro trap / machine check */
+#define KA43_PCS_TPERR         (1<<8)  /* Tag parity error */
+#define KA43_PCS_DPERR         (1<<9)  /* Dal data parity error */
+#define KA43_PCS_PPERR         (1<<10) /* P data parity error */
+#define KA43_PCS_BUSERR                (1<<11) /* Bus error */
+#define KA43_PCS_BCHIT         (1<<12) /* B cache hit */
+
+/*
+ * Other fixed addresses which should be mapped
+ */
+#define KA43_CPU_BASE  0x20080000      /* so called "CPU registers" */
+#define KA43_CPU_END   0x200800FF
+#define KA43_CPU_SIZE       0x100
+#define KA43_NWA_BASE  0x20090000      /* Network Address ROM */
+#define KA43_NWA_END   0x2009007F
+#define KA43_NWA_SIZE        0x80
+#define KA43_SER_BASE  0x200A0000      /* Serial line controller */
+#define KA43_SER_END   0x200A000F
+#define KA43_SER_SIZE         0x10
+#define KA43_WAT_BASE  0x200B0000      /* TOY clock and NV-RAM */
+#define KA43_WAT_END   0x200B00FF
+#define KA43_WAT_SIZE       0x100
+#define KA43_SC1_BASE  0x200C0080      /* 1st SCSI Controller Chip */
+#define KA43_SC1_END   0x200C009F
+#define KA43_SC1_SIZE        0x20
+#define KA43_SC2_BASE  0x200C0180      /* 2nd SCSI Controller Chip */
+#define KA43_SC2_END   0x200C019F
+#define KA43_SC2_SIZE        0x20
+#define KA43_SCS_BASE  0x200C0000      /* area occupied by SCSI 1+2 */
+#define KA43_SCS_END   0x200C01FF
+#define KA43_SCS_SIZE       0x200
+#define KA43_LAN_BASE  0x200E0000      /* LANCE chip registers */
+#define KA43_LAN_END   0x200E0007
+#define KA43_LAN_SIZE        0x08
+#define KA43_CUR_BASE  0x200F0000      /* Monochrome video cursor chip */
+#define KA43_CUR_END   0x200F003C
+#define KA43_CUR_SIZE        0x40
+#define KA43_DMA_BASE  0x202D0000      /* 128KB Data Buffer */
+#define KA43_DMA_END   0x202EFFFF
+#define KA43_DMA_SIZE      0x20000
+#define KA43_VME_BASE  0x30000000
+#define KA43_VME_END   0x3003FFFF
+#define KA43_VME_SIZE     0x40000
+
+#define KA43_SC1_DADR  0x200C00A0      /* (1st SCSI) DMA address register */
+#define KA43_SC1_DCNT  0x200C00C0      /* (1st SCSI) DMA byte count reg. */
+#define KA43_SC1_DDIR  0x200C00C4      /* (1st SCSI) DMA transfer direction */
+#define KA43_SC2_DADR  0x200C01A0
+#define KA43_SC2_DCNT  0x200C01C0
+#define KA43_SC2_DDIR  0x200C01C4
+
+#define KA43_CUR_CMD   0x200F0000      /* Cursor Command Register */
+#define KA43_CUR_XPOS  0x200F0004      /* Cursor X position */
+#define KA43_CUR_YPOS  0x200F0008      /* Cursor Y position */
+
+#define KA43_CUR_XMIN1 0x200F000C      /* Region 1 left edge */
+#define KA43_CUR_XMAX1 0x200F0010      /* Region 1 right edge */
+#define KA43_CUR_YMIN1 0x200F0014      /* Region 1 top edge */
+#define KA43_CUR_YMAX1 0x200F0018      /* Region 1 bottom edge */
+
+#define KA43_CUR_XMIN2 0x200F002C      /* Region 2 left edge */
+#define KA43_CUR_XMAX2 0x200F0030      /* Region 2 right edge */
+#define KA43_CUR_YMIN2 0x200F0034      /* Region 2 top edge */
+#define KA43_CUR_YMAX2 0x200F0038      /* Region 2 bottom edge */
+
+/*
+ * Clock-Chip data in NVRAM
+ */
+#define KA43_CPMBX     0x200B0038      /* Console Mailbox (1 byte) */
+#define KA43_CPFLG     0x200B003C      /* Console Program Flags (1 byte) */
+#define KA43_LK201_ID  0x200B0040      /* Keyboard Variation (1 byte) */
+#define KA43_CONS_ID   0x200B0044      /* Console Device Type (1 byte) */
+#define KA43_SCR       0x200B0048      /* Console Scratch RAM */
+#define KA43_TEMP      0x200B0058      /* Used by System Firmware */
+#define KA43_BAT_CHK   0x200B0088      /* Battery Check Data */
+#define KA43_PASSWD    0x200B0098      /* ??? */
+#define KA43_BOOTFLG   0x200B00A8      /* Default Boot Flags (4 bytes) */
+#define KA43_SCRLEN    0x200B00B8      /* Number of pages of SCR (1 byte) */
+#define KA43_SCSIPORT  0x200B00BC      /* Tape Controller Port Data */
+#define KA43_RESERVED  0x200B00C0      /* Reserved (16 bytes) */
+
+struct ka43_cpu {
+       u_long  ka43_hltcod;
+       u_long  ka43_mser;
+       u_long  ka43_cear;
+       u_long  ka43_intmsk;
+};
+
+struct ka43_clock {
+       u_long  :2;     u_long  sec     :8;     u_long  :22;
+       u_long  :2;     u_long  secalrm :8;     u_long  :22;
+       u_long  :2;     u_long  min     :8;     u_long  :22;
+       u_long  :2;     u_long  minalrm :8;     u_long  :22;
+       u_long  :2;     u_long  hr      :8;     u_long  :22;
+       u_long  :2;     u_long  hralrm  :8;     u_long  :22;
+       u_long  :2;     u_long  dayofwk :8;     u_long  :22;
+       u_long  :2;     u_long  day     :8;     u_long  :22;
+       u_long  :2;     u_long  mon     :8;     u_long  :22;
+       u_long  :2;     u_long  yr      :8;     u_long  :22;
+       u_long  :2;     u_long  csr0    :8;     u_long  :22;
+       u_long  :2;     u_long  csr1    :8;     u_long  :22;
+       u_long  :2;     u_long  csr2    :8;     u_long  :22;
+       u_long  :2;     u_long  csr3    :8;     u_long  :22;
+       u_long  :2;     u_long  cpmbx   :8;     u_long  :22;
+};
+
+int ka43_setup __P((struct uvax_calls *p, int flags));
+static int ka43_clkread __P((time_t));
+static void ka43_clkwrite __P((void));
diff --git a/sys/arch/vax/include/ka630.h b/sys/arch/vax/include/ka630.h
new file mode 100644 (file)
index 0000000..0987511
--- /dev/null
@@ -0,0 +1,125 @@
+/*     $NetBSD: ka630.h,v 1.1 1996/07/20 17:58:17 ragge Exp $ */
+/*-
+ * Copyright (c) 1986, 1988 The Regents of the University of California.
+ * 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.
+ *
+ *     @(#)uvaxII.h    7.4 (Berkeley) 5/9/91
+ */
+
+#if VAX630 || VAX410
+#define UVAXIISID      ((u_long *)0x20040004)
+#define UVAXIICPU      ((struct uvaxIIcpu *)0x20080000)
+
+struct uvaxIIcpu {
+       u_short uvaxII_bdr;
+       u_short uvaxII_xxx;
+       u_long  uvaxII_mser;
+       u_long  uvaxII_cear;
+       u_long  uvaxII_dear;
+};
+
+/* Memory system err reg. */
+#define        UVAXIIMSER_CD   0x00000300
+#define        UVAXIIMSER_NXM  0x00000080
+#define        UVAXIIMSER_LPE  0x00000040
+#define        UVAXIIMSER_QPE  0x00000020
+#define        UVAXIIMSER_MERR 0x000000f0
+#define        UVAXIIMSER_CPUE 0x00000060
+#define        UVAXIIMSER_DQPE 0x00000010
+#define        UVAXIIMSER_LEB  0x00000008
+#define        UVAXIIMSER_WRWP 0x00000002
+#define        UVAXIIMSER_PEN  0x00000001
+
+/* Mem. error address regs. */
+#define        UVAXIICEAR_PG   0x00007fff
+#define        UVAXIIDEAR_PG   0x00007fff
+#endif
+
+/*
+ * Definitions specific to the ka630 MicroVAXII Q22 bus cpu card. Includes the
+ * tod clock chip and the cpu registers.
+ */
+#if VAX630
+#define KA630CLK       ((struct ka630clock *)0x200b8000)
+
+/* Bdr register bits */
+#define        KA630BDR_PWROK  0x8000
+#define        KA630BDR_HLTENB 0x4000
+#define        KA630BDR_CPU    0x0c00
+#define        KA630BDR_BDG    0x0300
+#define        KA630BDR_DSPL   0x000f
+
+/* Clock registers and constants */
+#define        MINSEC  60
+#define        HRSEC   3600
+#define DAYSEC (HRSEC * 24)
+#define YEARSEC        (DAYSEC * 365)
+
+#define        KA630CLK_VRT    0200
+#define        KA630CLK_UIP    0200
+#define        KA630CLK_RATE   040
+#define        KA630CLK_ENABLE 06
+#define        KA630CLK_SET    0206
+/* cpmbx bits */
+#define        KA630CLK_HLTACT 03
+/* halt action values */
+#define        KA630CLK_RESTRT 01
+#define        KA630CLK_REBOOT 02
+#define        KA630CLK_HALT   03
+/* in progress flags */
+#define        KA630CLK_BOOT   04
+#define        KA630CLK_RSTRT  010
+#define        KA630CLK_LANG   0360
+
+#ifndef _LOCORE
+struct ka630clock {
+       u_short sec;
+       u_short secalrm;
+       u_short min;
+       u_short minalrm;
+       u_short hr;
+       u_short hralrm;
+       u_short dayofwk;
+       u_short day;
+       u_short mon;
+       u_short yr;
+       u_short csr0;
+       u_short csr1;
+       u_short csr2;
+       u_short csr3;
+       u_short cpmbx;  /* CPMBX is used by the boot rom. see ka630-ug-3.3.3 */
+};
+
+#endif
+static int ka630_clkread __P((time_t));
+static void ka630_clkwrite __P((void));
+
+#endif
index 9c6e108..c8cce51 100644 (file)
@@ -1,4 +1,4 @@
-/*     $NetBSD: ka750.h,v 1.6 1996/05/19 16:43:23 ragge Exp $  */
+/*     $NetBSD: ka750.h,v 1.7 1996/07/20 17:58:17 ragge Exp $  */
 
 /*
  * Copyright (c) 1994 Ludd, University of Lule}, Sweden.
@@ -44,7 +44,6 @@
 
 /* 11/750 specific prototypes */
 void   ka750_conf __P((struct device *, struct device *, void *));
-int    ka750_clock __P((void));
 void   ka750_memenable __P((struct sbi_attach_args *, struct device *));
 void   ka750_memerr __P((void));
 int    ka750_mchk __P((caddr_t));
diff --git a/sys/arch/vax/include/ka820.h b/sys/arch/vax/include/ka820.h
new file mode 100644 (file)
index 0000000..10d285c
--- /dev/null
@@ -0,0 +1,148 @@
+/*     $NetBSD: ka820.h,v 1.1 1996/07/20 17:33:09 ragge Exp $  */
+/*
+ * Copyright (c) 1988 Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * 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.
+ *
+ *     @(#)ka820.h     7.3 (Berkeley) 6/28/90
+ */
+
+/*
+ * Definitions specific to the ka820 cpu.
+ */
+
+/*
+ * Device addresses.
+ */
+#define KA820_PORTADDR         0x20088000      /* port controller */
+#define KA820_BRAMADDR         0x20090000      /* boot ram */
+#define KA820_EEPROMADDR       0x20098000      /* eeprom */
+#define KA820_RX50ADDR         0x200b0000      /* rcx50 */
+#define KA820_CLOCKADDR                0x200b8000      /* watch chip */
+
+/*
+ * Sizes.  The port controller, RCX50, and watch chip are all one page.
+ */
+#define KA820_BRPAGES          16              /* 8K */
+#define KA820_EEPAGES          64              /* 32K */
+
+/* port controller CSR bit values */
+#define KA820PORT_RSTHALT      0x80000000      /* restart halt */
+#define KA820PORT_LCONS                0x40000000      /* logical console */
+#define KA820PORT_LCONSEN      0x20000000      /* logical console enable */
+#define KA820PORT_BIRESET      0x10000000      /* BI reset */
+#define KA820PORT_BISTF                0x08000000      /* ??? */
+#define KA820PORT_ENBAPT       0x04000000      /* ??? */
+#define KA820PORT_STPASS       0x02000000      /* self test pass */
+#define KA820PORT_RUN          0x01000000      /* run */
+#define KA820PORT_WWPE         0x00800000      /* ??? parity even? */
+#define KA820PORT_EVLCK                0x00400000      /* event lock */
+#define KA820PORT_WMEM         0x00200000      /* write mem */
+#define KA820PORT_EV4          0x00100000      /* event 4 */
+#define KA820PORT_EV3          0x00080000      /* event 3 */
+#define KA820PORT_EV2          0x00040000      /* event 2 */
+#define KA820PORT_EV1          0x00020000      /* event 1 */
+#define KA820PORT_EV0          0x00010000      /* event 0 */
+#define KA820PORT_WWPO         0x00008000      /* ??? parity odd? */
+#define KA820PORT_PERH         0x00004000      /* parity error H */
+#define KA820PORT_ENBPIPE      0x00002000      /* enable? pipe */
+#define KA820PORT_TIMEOUT      0x00001000      /* timeout */
+#define KA820PORT_RSVD         0x00000800      /* reserved */
+#define KA820PORT_CONSEN       0x00000400      /* console interrupt enable */
+#define KA820PORT_CONSCLR      0x00000200      /* clear console interrupt */
+#define KA820PORT_CONSINTR     0x00000100      /* console interrupt req */
+#define KA820PORT_RXIE         0x00000080      /* RX50 interrupt enable */
+#define KA820PORT_RXCLR                0x00000040      /* clear RX50 interrupt */
+#define KA820PORT_RXIRQ                0x00000020      /* RX50 interrupt request */
+#define KA820PORT_IPCLR                0x00000010      /* clear IP interrupt */
+#define KA820PORT_IPINTR       0x00000008      /* IP interrupt request */
+#define KA820PORT_CRDEN                0x00000004      /* enable CRD interrupts */
+#define KA820PORT_CRDCLR       0x00000002      /* clear CRD interrupt */
+#define KA820PORT_CRDINTR      0x00000001      /* CRD interrupt request */
+
+/* what the heck */
+#define KA820PORT_BITS \
+"\20\40RSTHALT\37LCONS\36LCONSEN\35BIRESET\34BISTF\33ENBAPT\32STPASS\31RUN\
+\30WWPE\27EVLCK\26WMEM\25EV4\24EV3\23EV2\22EV1\21EV\20WWPO\17PERH\16ENBPIPE\
+\15TIMEOUT\13CONSEN\12CONSCLR\11CONSINTR\10RXIE\7RXCLR\6RXIRQ\5IPCLR\4IPINTR\
+\3CRDEN\2CLRCLR\1CRDINTR"
+
+/* clock CSR bit values, per csr */
+#define KA820CLK_0_BUSY                0x01            /* busy (time changing) */
+#define KA820CLK_1_GO          0x0c            /* run */
+#define KA820CLK_1_SET         0x0d            /* set the time */
+#define KA820CLK_3_VALID       0x01            /* clock is valid */
+
+#ifndef LOCORE
+struct ka820port {
+       u_long  csr;
+       /* that seems to be all.... */
+};
+
+struct ka820clock {
+       u_char  sec;
+       u_char  pad0;
+       u_char  secalrm;
+       u_char  pad1;
+       u_char  min;
+       u_char  pad2;
+       u_char  minalrm;
+       u_char  pad3;
+       u_char  hr;
+       u_char  pad4;
+       u_char  hralrm;
+       u_char  pad5;
+       u_char  dayofwk;
+       u_char  pad6;
+       u_char  day;
+       u_char  pad7;
+       u_char  mon;
+       u_char  pad8;
+       u_char  yr;
+       u_char  pad9;
+       u_short csr0;
+       u_short csr1;
+       u_short csr2;
+       u_short csr3;
+};
+
+/*
+ * Prototypes.
+ */
+void   ka820_conf __P((struct device *, struct device *, void *));
+void   ka820_memerr __P((void));
+int    ka820_mchk __P((caddr_t));
+void   ka820_steal_pages __P((void));
+int    ka820_clkread __P((time_t));
+void   ka820_clkwrite __P((void));
+#endif
index b08881f..1d863e9 100644 (file)
@@ -1,4 +1,4 @@
-/*     $NetBSD: macros.h,v 1.8 1996/03/17 22:44:50 ragge Exp $ */
+/*     $NetBSD: macros.h,v 1.10 1997/01/11 11:07:52 ragge Exp $        */
 
 /*
  * Copyright (c) 1994 Ludd, University of Lule}, Sweden.
@@ -117,6 +117,7 @@ static __inline__ int bcmp(const void *b1, const void *b2, size_t len){
        return ret;
 }
 
+#if 0 /* unused, but no point in deleting it since it _is_ an instruction */
 static __inline__ int locc(int mask, char *cp,u_int size){
        register ret;
 
@@ -126,8 +127,10 @@ static __inline__ int locc(int mask, char *cp,u_int size){
                        : "r0","r1" );
        return  ret;
 }
+#endif
 
-static __inline__ int scanc(u_int size, u_char *cp,u_char *table, int mask){
+static __inline__ int
+scanc(u_int size, const u_char *cp, const u_char *table, int mask){
        register ret;
 
        asm __volatile("scanc   %1,(%2),(%3),%4;movl r0,%0"
index 0ee73aa..f106ab6 100644 (file)
@@ -1,4 +1,4 @@
-/*      $NetBSD: mtpr.h,v 1.8 1996/03/07 23:23:59 ragge Exp $     */
+/*      $NetBSD: mtpr.h,v 1.9 1996/07/20 17:58:18 ragge Exp $     */
 
 /*
  * Copyright (c) 1994 Ludd, University of Lule}, Sweden.
 #define PR_ESPA   78 /* EBOX Scratchpad Address (KA86) */
 #define PR_ESPD   79 /* EBOX Scratchpad Data (KA86) */
 
+#define        PR_RXCS1  80 /* Serial-Line Unit 1 Receive CSR (KA820) */
+#define        PR_RXDB1  81 /* Serial-Line Unit 1 Receive Data Buffer (KA820) */
+#define        PR_TXCS1  82 /* Serial-Line Unit 1 Transmit CSR (KA820) */
+#define        PR_TXDB1  83 /* Serial-Line Unit 1 Transmit Data Buffer (KA820) */
+#define        PR_RXCS2  84 /* Serial-Line Unit 2 Receive CSR (KA820) */
+#define        PR_RXDB2  85 /* Serial-Line Unit 2 Receive Data Buffer (KA820) */
+#define        PR_TXCS2  86 /* Serial-Line Unit 2 Transmit CSR (KA820) */
+#define        PR_TXDB2  87 /* Serial-Line Unit 2 Transmit Data Buffer (KA820) */
+#define        PR_RXCS3  88 /* Serial-Line Unit 3 Receive CSR (KA820) */
+#define        PR_RXDB3  89 /* Serial-Line Unit 3 Receive Data Buffer (KA820) */
+#define        PR_TXCS3  90 /* Serial-Line Unit 3 Transmit CSR (KA820) */
+#define        PR_TXDB3  91 /* Serial-Line Unit 3 Transmit Data Buffer (KA820) */
+#define        PR_RXCD   92 /* Receive Console Data from another cpu (KA820) */
+#define        PR_CACHEX 93 /* Cache invalidate Register (KA820) */
+#define        PR_BINID  94 /* VAXBI node ID Register (KA820) */
+#define        PR_BISTOP 95 /* VAXBI Stop Register (KA820) */
+
+#define        PR_VINTSR 123 /* vector i/f error status (KA43/KA46) */
+#define PR_PCTAG  124 /* primary cache tag store (KA43/KA46) */
+#define PR_PCIDX  125 /* primary cache index (KA43/KA46) */
+#define PR_PCERR  126 /* primary cache error address (KA43/KA46) */
+#define PR_PCSTS  127 /* primary cache status (KA43/KA46) */
+
 /* Definitions for AST */
 #define        AST_NO    4
 #define        AST_OK    3
index fe9a2fb..6f15874 100644 (file)
@@ -1,4 +1,4 @@
-/*     $NetBSD: nexus.h,v 1.10 1996/03/02 14:27:53 ragge Exp $ */
+/*     $NetBSD: nexus.h,v 1.12 1996/08/20 14:19:43 ragge Exp $ */
 
 /*-
  * Copyright (c) 1982, 1986 The Regents of the University of California.
 
 #ifndef _VAX_NEXUS_H_
 #define _VAX_NEXUS_H_
+/*
+ * Different definitions for nicer autoconf probing.
+ */
+#define VAX_SBIBUS      1       /* SBI parent; 780/790 */
+#define VAX_CPUBUS      2       /* Has backplane CPU */
+#define VAX_MEMBUS      4       /* Has backplane memory */ 
+#define VAX_UNIBUS      8       /* Directly attached (630/650) */
+#define VAX_VSBUS       16      /* VAXstation board */
+#define VAX_BIBUS       32      /* BI bus expansions: 8200/8800 */ 
+#define VAX_CMIBUS     64      /* CMI backplane (750) */
+
 /*
  * Information about nexus's.
  *
 #define        NNEX730 NNEXSBI
 #define        NEX730  ((struct nexus *)0xf20000)
 #endif
-#if VAX630
-#define NNEX630 1
-#define NEX630  ((struct nexus *)0x20088000)
-#endif
 #define        NEXSIZE 0x2000
 
 #if VAX8600
@@ -102,20 +109,11 @@ struct mem_softc {
        int     sc_memnr;
 };
 
-struct iobus {
-        int io_type;
-        int io_addr;
-        int io_size;
-        int io_details;
-};
-
-struct nexusconnect {
-        int psb_nnexus;
-        struct nexus *psb_nexbase;
-       int psb_ubatype;
-       int psb_nubabdp;
-       caddr_t *psb_umaddr;
-        int *psb_nextype;
+struct bp_conf {
+       char *type;
+       int num;
+       int partyp;
+       int bp_addr;
 };
 
 extern caddr_t *nex_vec;
index ec5d9c6..a50abd5 100644 (file)
@@ -1,4 +1,5 @@
-/*      $NetBSD: param.h,v 1.19 1996/03/04 05:04:43 cgd Exp $    */
+/*     $OpenBSD: param.h,v 1.6 1997/01/15 23:24:42 maja Exp $ */
+/*      $NetBSD: param.h,v 1.22 1997/01/11 11:06:17 ragge Exp $    */
 /*-
  * Copyright (c) 1990 The Regents of the University of California.
  * All rights reserved.
@@ -74,7 +75,8 @@
 #define        DEV_BSIZE    (1 << DEV_BSHIFT)
 
 #define BLKDEV_IOSIZE 2048
-#define        MAXPHYS       (63 * 1024)     /* max raw I/O transfer size */
+#define        MAXPHYS         (63 * 1024)     /* max raw I/O transfer size */
+#define        MAXBSIZE        0x4000          /* max FS block size - XXX */
 
 #define        CLSIZELOG2    1
 #define        CLSIZE        2
 #define splsoftclock()  splx(8)                /* IPL08 */
 #define splsoftnet()    splx(0xc)      /* IPL0C */
 #define        splddb()        splx(0xf)       /* IPL0F */
-#define spl4()          splx(0x14)     /* IPL14 */
 #define splbio()        splx(0x15)     /* IPL15 */
 #define splnet()        splx(0x15)     /* IPL15 */
 #define spltty()        splx(0x15)     /* IPL15 */
 #define splhigh()       splx(0x1f)     /* IPL1F */
 #define        splstatclock()  splclock()
 
+/* These are better to use when playing with VAX buses */
+#define        spl4()          splx(0x14)
+#define        spl5()          splx(0x15)
+#define        spl6()          splx(0x16)
+#define        spl7()          splx(0x17)
+
 #define        ovbcopy(x,y,z)  bcopy(x,y,z)
 
+#if !defined(VAX410) && !defined(VAX43)
 #define vmapbuf(p,q)
 #define vunmapbuf(p,q)
+#endif
 
 /* Prototype needed for delay() */
 #ifndef        _LOCORE
index 870776d..a4f22ce 100644 (file)
@@ -1,4 +1,4 @@
-/*      $NetBSD: pmap.h,v 1.16 1996/04/08 18:35:51 ragge Exp $     */
+/*      $NetBSD: pmap.h,v 1.17 1996/07/20 17:58:22 ragge Exp $     */
 
 /* 
  * Copyright (c) 1987 Carnegie-Mellon University
@@ -85,6 +85,7 @@ typedef struct pv_entry {
 
 /* ROUND_PAGE used before vm system is initialized */
 #define ROUND_PAGE(x)   (((uint)(x) + PAGE_SIZE-1)& ~(PAGE_SIZE - 1))
+#define        TRUNC_PAGE(x)   ((uint)(x) & ~(PAGE_SIZE - 1))
 
 /* Mapping macros used when allocating SPT */
 #define        MAPVIRT(ptr, count)                                     \
index 2888b90..4270623 100644 (file)
@@ -1,4 +1,4 @@
-/*     $NetBSD: sid.h,v 1.6 1995/11/12 14:37:18 ragge Exp $    */
+/*     $NetBSD: sid.h,v 1.8 1996/08/20 14:19:41 ragge Exp $    */
 
 /*
  * Copyright (c) 1994 Ludd, University of Lule}, Sweden.
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
- /* All bugs are subject to removal without further notice */
-               
+/*
+ * Board-Type (?_BTYP_?) and Sub-Type (?_STYP_?) are synonima.
+ * other synonima are:
+ */
+#define cpudata            vax_cpudata
+#define cputype            vax_cputype
+#define cpusubtype  vax_boardtype
 
+/*
+ * Chip CPU types / chip CPU Subtypes
+ *
+ * The type of a VAX is given by the high-order byte of the System
+ * identification register (SID) and describes families or series of VAXen.
+ * Board-Types/Sub-Types within series are described by the SIED register.
+ */
 
-#define        VAX_780 1
-#define VAX_750        2
-#define        VAX_730 3
-#define VAX_8600 4
-#define VAX_8200 5
-#define VAX_8800 6
-#define VAX_610 7
-#define VAX_78032 8
-#define VAX_650 10
-#define        VAX_MAX 10
+/*
+ * 700 series (1977)
+ */
+#define VAX_TYP_780    1       /* VAX-11/780, 785, 782 */
+#define VAX_TYP_750    2       /* VAX-11/750 */
+#define VAX_TYP_730    3       /* VAX-11/730, 725 */
+#define VAX_TYP_790    4       /* VAX 8600, 8650 */
+#define VAX_BTYP_780   0x01000000      /* generic 11/780 */
+#define VAX_BTYP_750   0x02000000      /* generic 11/750 */
+#define VAX_BTYP_730   0x03000000      /* generic 11/730 */
+#define VAX_BTYP_790   0x04000000      /* generic 11/790 */
 
-#define MACHID(x)       ((x>>24)&255)
+/*
+ * 8000 series (1986)
+ */
+#define VAX_TYP_8SS    5       /* VAX 8200, 8300, 8250, 8350, VS 8000 */
+#define VAX_TYP_8NN    6       /* VAX 8530, 8550, 8700, 8800 */
+#define VAX_BTYP_8000  0x05000000      /* generic VAX 8000 */
+#define VAX_BTYP_8800  0x06000000      /* generic Nautilus */
+#define VAX_BTYP_8700  0x06000001
+#define VAX_BTYP_8550  0x06000006
+#define VAX_BTYP_8500  0x06000007
 
-#define V750UCODE(x)    ((x>>8)&255)
+/*
+ * MicroVAX I (1984)
+ */
+#define VAX_TYP_UV1    7       /* MicroVAX I, VAXstation I */
+     /* VAX_TYP_610    7 */
+#define VAX_BTYP_610   0x70000000      /* generic MicroVAX-I */
+/*
+ * MicroVAX II series (1985)
+ */
+#define VAX_TYP_UV2    8
+     /* VAX_TYP_78032  8 */
+#define VAX_BTYP_630   0x08000001      /* MicroVAX II, VAXstation II */
+#define VAX_BTYP_410   0x08000004      /* MicroVAX 2000, VAXstation 2000 */
+/*
+ * CVAX chip series (1987)
+ */
+#define VAX_TYP_CVAX   10
+     /* VAX_TYP_650    10 */
 
+#define VAX_BTYP_650   0x0A000001      /* MicroVAX 3500, 3600 */
+     /* VAX_BTYP_65D   0x0A000001         VAXstation 3200, 3500 */
+     /* VAX_BTYP_640   0x0A000001         MicroVAX 3300, 3400 */
+     /* VAX_BTYP_655   0x0A000001         MicroVAX 3800, 3900 */
+#define VAX_BTYP_9CC   0x0A000002      /* VAX 6000 model 210/310 */
+#define VAX_BTYP_60    0x0A000003      /* VAXstation 3520, 3540 */
+#define VAX_BTYP_420   0x0A000004      /* VAXstation 3100 models 10 - 48 */
+#define VAX_BTYP_510   0x0A000007      /* VAXft model 110 */
+     /* VAX_BTYP_520   0x0A000007         VAXft model 310 */
+/*
+ * Rigel chip series (1990)
+ */
+#define VAX_TYP_RIGEL  11
+     /* VAX_TYP_9RR    11 */
+#define VAX_BTYP_670   0x0B000001      /* VAX 4000 model 300 */
+#define VAX_BTYP_9RR   0x0B000002      /* VAX 6000 model 410-460 */
+#define VAX_BTYP_43    0x0B000004      /* VAXstation 3100 model 76 */
+/*
+ * Aquarius series (1990)
+ */
+#define VAX_TYP_9000   14
+#define VAX_BTYP_9AR   0x0E00000?      /* VAX 9000 models 210, 410-440 */
+#define VAX_BTYP_9AQ   0x0E00000?      /* VAX 9000 models 400-800 */
+/*
+ * Polarstar series (1988)
+ */
+#define VAX_TYP_8PS    17
+#define VAX_BTYP_8PS   0x11000000      /* VAX 8810 to 8840 */
+/*
+ * Mariah chip series (1991)
+ */
+#define VAX_TYP_MARIAH 18
+#define VAX_TYP_V12    18
+#define VAX_BTYP_690   0x12000001      /* VAX 4000 model 400 */
+#define VAX_BTYP_1202  0x12000002      /* VAX 6000 model 510-560 */
+#define VAX_BTYP_46    0x12000004      /* VAXstation 4000/60, 3100/80 */
+/*
+ * NVAX chip series (1991)
+ */
+#define VAX_TYP_NVAX   19
+#define VAX_TYP_V13    19
+#define VAX_BTYP_69D   0x13000001      /* VAX 4000 model 500 */
+#define VAX_BTYP_1301  0x13000001      /* VAX 4000 model 100 */
+#define VAX_BTYP_1302  0x13000002
+#define VAX_BTYP_1303  0x13000003
+#define VAX_BTYP_49    0x13000004      /* MicroVAX 3100 model 90 */
+
+/*
+ * SOC chip series (1991)
+ */
+#define VAX_TYP_SOC    20
+#define VAX_TYP_V14    20
+#define VAX_BTYP_660   0x14000001      /* VAX 4000 model 200 */
+#define VAX_BTYP_440   0x14000004      /* VS 4000/30, 3100/30, 3100/40 */
+#define VAX_BTYP_550   0x14000007      /* VAXft model 410, 610 */
+/*
+ * NVAX+ chip series (1991)
+ */
+#define VAX_TYP_NVPLUS 23
+#define VAX_TYP_V17    23
+#define VAX_BTYP_1701  0x17000001
+/*
+ * Highest Number supported by NetBSD/VAX
+ */
+#define VAX_TYP_MAX    VAX_TYP_RIGEL
+
+/*
+ * compatibility with old names:
+ */
+#define VAX_780                VAX_TYP_780
+#define VAX_750                VAX_TYP_750
+#define VAX_730                VAX_TYP_730
+#define VAX_8600       VAX_TYP_790
+#define VAX_8200       VAX_TYP_8SS
+#define VAX_8800       VAX_TYP_8NN
+#define VAX_610                VAX_TYP_UV1
+#define VAX_78032      VAX_TYP_UV2
+#define VAX_650                VAX_TYP_CVAX
 /*
- * The MicroVAXII CPU chip (78032) is used on more than one type of system
- * that are differentiated by the low order 8 bits of cpu_type. (Filled in
- * from the System Identification Extension Register.) To test for the cpu
- * chip, compare cpunumber == VAX_78032, but to test for a Qbus MicroVAXII
- * compare cpu_type == VAX_630.
+ * Some common-used external variables.
  */
-#define VAX_630       0x8000001
-#define VAX_410       0x8000002
+extern int vax_cputype;        /* general, highest byte of the SID-register */
+extern int vax_cpudata;        /* general, the contents of the SID-register */
+extern int vax_siedata;        /* contents of the SIE register */
+extern int vax_bustype;        /* HW-dep., setup at consinit() in ka???.c */
+extern int vax_boardtype;      /* HW-dep., msb of SID | SIE (SID-extension) */
+extern int vax_confdata;       /* HW-dep., hardware dependent config-data   */
 
-extern int cpu_type, cpunumber;
index ff7f89c..619b2d9 100644 (file)
@@ -1,4 +1,4 @@
-/*      $NetBSD: trap.h,v 1.13 1996/04/08 18:35:52 ragge Exp $     */
+/*      $NetBSD: trap.h,v 1.14 1997/01/11 11:46:43 ragge Exp $     */
 
 /*-
  * Copyright (c) 1990 The Regents of the University of California.
@@ -110,6 +110,8 @@ struct ivec_dsp {
        char    pad;            /* sizeof(struct ivec_dsp) == 16 */
 };
 
+extern struct ivec_dsp idsptch;
+
 #endif /* _LOCORE */
 
 #endif _VAX_TRAP_H_
index 09118fd..e44feb1 100644 (file)
@@ -1,4 +1,4 @@
-/*     $NetBSD: types.h,v 1.9 1996/04/08 18:35:53 ragge Exp $  */
+/*     $NetBSD: types.h,v 1.10 1996/12/05 00:14:00 cgd Exp $   */
 
 /*-
  * Copyright (c) 1990 The Regents of the University of California.
@@ -70,4 +70,6 @@ typedef unsigned long long      u_int64_t;
 
 typedef int32_t                 register_t;
 
+#define        __BROKEN_INDIRECT_CONFIG
+
 #endif /* _MACHTYPES_H_ */
diff --git a/sys/arch/vax/include/uvax.h b/sys/arch/vax/include/uvax.h
new file mode 100644 (file)
index 0000000..df7bc81
--- /dev/null
@@ -0,0 +1,115 @@
+/*     $NetBSD: uvax.h,v 1.1 1996/07/20 17:58:24 ragge Exp $ */
+/*
+ * Copyright (c) 1996 Ludd, University of Lule}, Sweden.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Ludd by Bertram Barth.
+ *
+ * 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 at Ludd, University of 
+ *      Lule}, Sweden and its contributors.
+ * 4. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * generic(?) MicroVAX and VAXstation support
+ *
+ * There are similarities to struct cpu_calls[] in autoconf.c
+ */
+
+/* 
+ * Prototypes for autoconf.c
+ */
+struct device;
+void   uvax_conf __P((struct device*, struct device*, void*));
+int    uvax_clock __P((void));
+void   uvax_memerr __P((void));
+int    uvax_mchk __P((caddr_t));
+void   uvax_steal_pages __P((void));
+
+int    uvax_setup __P((int mapen));
+
+struct uvax_calls {
+       u_long  (*uc_phys2virt) __P((u_long));  /* most often used! */
+       u_long  (*uc_memsize) __P((void));
+       void    (*uc_steal_pages) __P((void));
+       void    (*uc_conf) __P((struct device*, struct device*, void*));
+       void    (*uc_memerr) __P((void));
+       int     (*uc_mchk) __P((caddr_t));
+       int     (*uc_clkread) __P((time_t));
+       void    (*uc_clkwrite) __P((void));
+
+       char    *uc_name;
+       u_char  *uc_intreq;
+       u_char  *uc_intclr;
+       u_char  *uc_intmsk;
+
+       void    *le_iomem;              /* base addr of RAM -- CPU's view */
+       u_long  *le_ioaddr;             /* base addr of RAM -- LANCE's view */
+       int     *le_memsize;            /* size of RAM reserved for LANCE */
+
+       void    *uc_physmap;
+       int     uc_busTypes;
+       int     uc_vups;                /* used by delay() */
+
+       int     uv_flags;
+       int     vs_flags;
+};             
+
+extern struct uvax_calls guc;          /* Generic uVAX Calls */
+extern struct uvax_calls *ucp;
+
+struct uc_map {
+       u_long  um_base;
+       u_long  um_end;
+       u_long  um_size;
+       u_long  um_virt;
+};
+extern struct uc_map *uc_physmap;
+
+/*
+ * Generic definitions common on all MicroVAXen clock chip.
+ */
+#define        uVAX_CLKVRT     0200
+#define        uVAX_CLKUIP     0200
+#define        uVAX_CLKRATE    040
+#define        uVAX_CLKENABLE  06
+#define        uVAX_CLKSET     0206
+
+/* cpmbx bits  */
+#define        uVAX_CLKHLTACT  03
+
+/* halt action values */
+#define        uVAX_CLKRESTRT  01
+#define        uVAX_CLKREBOOT  02
+#define        uVAX_CLKHALT    03
+
+/* in progress flags */
+#define        uVAX_CLKBOOT    04
+#define        uVAX_CLKRSTRT   010
+#define        uVAX_CLKLANG    0360
+
+/* Prototypes */
+int    uvax_clkread __P((time_t));
+void   uvax_clkwrite __P((void));
diff --git a/sys/arch/vax/include/uvaxII.h b/sys/arch/vax/include/uvaxII.h
deleted file mode 100644 (file)
index db6227c..0000000
+++ /dev/null
@@ -1,134 +0,0 @@
-/*     $NetBSD: uvaxII.h,v 1.4 1996/05/19 16:43:28 ragge Exp $ */
-/*-
- * Copyright (c) 1986, 1988 The Regents of the University of California.
- * 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.
- *
- *     @(#)uvaxII.h    7.4 (Berkeley) 5/9/91
- */
-
-#if VAX630 || VAX410
-#define UVAXIISID      ((u_long *)0x20040004)
-#define UVAXIICPU      ((struct uvaxIIcpu *)0x20080000)
-
-struct uvaxIIcpu {
-       u_short uvaxII_bdr;
-       u_short uvaxII_xxx;
-       u_long  uvaxII_mser;
-       u_long  uvaxII_cear;
-       u_long  uvaxII_dear;
-};
-
-/* Memory system err reg. */
-#define        UVAXIIMSER_CD   0x00000300
-#define        UVAXIIMSER_NXM  0x00000080
-#define        UVAXIIMSER_LPE  0x00000040
-#define        UVAXIIMSER_QPE  0x00000020
-#define        UVAXIIMSER_MERR 0x000000f0
-#define        UVAXIIMSER_CPUE 0x00000060
-#define        UVAXIIMSER_DQPE 0x00000010
-#define        UVAXIIMSER_LEB  0x00000008
-#define        UVAXIIMSER_WRWP 0x00000002
-#define        UVAXIIMSER_PEN  0x00000001
-
-/* Mem. error address regs. */
-#define        UVAXIICEAR_PG   0x00007fff
-#define        UVAXIIDEAR_PG   0x00007fff
-
-u_long uvaxII_gettodr __P((int *));
-void   uvaxII_settodr __P((time_t));
-#endif
-
-/*
- * Definitions specific to the ka630 MicroVAXII Q22 bus cpu card. Includes the
- * tod clock chip and the cpu registers.
- */
-#if VAX630
-#define KA630CLK       ((struct ka630clock *)0x200b8000)
-
-/* Bdr register bits */
-#define        KA630BDR_PWROK  0x8000
-#define        KA630BDR_HLTENB 0x4000
-#define        KA630BDR_CPU    0x0c00
-#define        KA630BDR_BDG    0x0300
-#define        KA630BDR_DSPL   0x000f
-
-/* Clock registers and constants */
-#define        MINSEC  60
-#define        HRSEC   3600
-#define DAYSEC (HRSEC * 24)
-#define YEARSEC        (DAYSEC * 365)
-
-#define        KA630CLK_VRT    0200
-#define        KA630CLK_UIP    0200
-#define        KA630CLK_RATE   040
-#define        KA630CLK_ENABLE 06
-#define        KA630CLK_SET    0206
-/* cpmbx bits */
-#define        KA630CLK_HLTACT 03
-/* halt action values */
-#define        KA630CLK_RESTRT 01
-#define        KA630CLK_REBOOT 02
-#define        KA630CLK_HALT   03
-/* in progress flags */
-#define        KA630CLK_BOOT   04
-#define        KA630CLK_RSTRT  010
-#define        KA630CLK_LANG   0360
-
-#ifndef _LOCORE
-struct ka630clock {
-       u_short sec;
-       u_short secalrm;
-       u_short min;
-       u_short minalrm;
-       u_short hr;
-       u_short hralrm;
-       u_short dayofwk;
-       u_short day;
-       u_short mon;
-       u_short yr;
-       u_short csr0;
-       u_short csr1;
-       u_short csr2;
-       u_short csr3;
-       u_short cpmbx;  /* CPMBX is used by the boot rom. see ka630-ug-3.3.3 */
-};
-
-#endif
-struct sbi_attach_args;
-
-/* Prototypes */
-void   uvaxII_conf __P((struct device *, struct device *, void *));
-int    uvaxII_clock __P((void));
-void   uvaxII_memenable __P((struct sbi_attach_args *, struct device *));
-void   uvaxII_memerr __P((void));
-int    uvaxII_mchk __P((caddr_t));
-void   uvaxII_steal_pages __P((void));
-#endif
index 36d52b2..459c120 100644 (file)
@@ -1,4 +1,4 @@
-/*     $NetBSD: vmparam.h,v 1.11 1996/02/02 19:08:43 mycroft Exp $     */
+/*     $NetBSD: vmparam.h,v 1.12 1996/07/20 17:58:26 ragge Exp $       */
 
 /*-
  * Copyright (c) 1990 The Regents of the University of California.
 #define SHMMAXPGS      64              /* XXXX should be 1024 */
 #endif
 
+/*
+ * Size of User Raw I/O map
+ */
+#define        USRIOSIZE       300
+
 /*
  * Sizes of the system and user portions of the system page table.
  * USRPTSIZE is maximum possible user virtual memory to be used.
diff --git a/sys/arch/vax/include/vsbus.h b/sys/arch/vax/include/vsbus.h
new file mode 100644 (file)
index 0000000..81257f5
--- /dev/null
@@ -0,0 +1,86 @@
+/*     $NetBSD: vsbus.h,v 1.1 1996/07/20 17:58:28 ragge Exp $ */
+/*
+ * Copyright (c) 1996 Ludd, University of Lule}, Sweden.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Ludd by Bertram Barth.
+ *
+ * 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 at Ludd, University of 
+ *      Lule}, Sweden and its contributors.
+ * 4. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * Generic definitions for the (virtual) vsbus. contains common info
+ * used by all VAXstations.
+ */
+struct confargs {
+       char    ca_name[16];            /* device name */
+       int     ca_intslot;             /* device interrupt-slot */
+       int     ca_intpri;              /* device interrupt "priority" */
+       int     ca_intvec;              /* interrup-vector offset */
+       int     ca_intbit;              /* bit in interrupt-register */
+       int     ca_ioaddr;              /* device hardware I/O address */
+
+       int     ca_aux1;                /* additional info (DMA, etc.) */
+       int     ca_aux2;
+       int     ca_aux3;
+       int     ca_aux4;
+       int     ca_aux5;
+       int     ca_aux6;
+       int     ca_aux7;
+       int     ca_aux8;
+
+#define ca_recvslot    ca_intslot      /* DC/DZ: Receiver configuration */
+#define ca_recvpri     ca_intpri
+#define ca_recvvec     ca_intvec
+#define ca_recvbit     ca_intbit
+#define ca_xmitslot    ca_aux1         /* DC/DZ: transmitter configuration */
+#define ca_xmitpri     ca_aux2         /* DC/DZ:  */
+#define ca_xmitvec     ca_aux3
+#define ca_xmitbit     ca_aux4
+#define ca_dcflags     ca_aux5
+
+#define ca_dareg       ca_aux1         /* SCSI: DMA address register */
+#define ca_dcreg       ca_aux2         /* SCSI: DMA byte count register */
+#define ca_ddreg       ca_aux3         /* SCSI: DMA transfer direction */
+#define ca_dbase       ca_aux4         /* SCSI: DMA buffer address */
+#define ca_dsize       ca_aux5         /* SCSI: DMA buffer size */
+#define ca_dflag       ca_aux6         /* SCSI: DMA flags (eg. shared) */
+#define ca_idval       ca_aux7         /* SCSI: host-ID to use/set */
+#define ca_idreg       ca_aux8         /* SCSI: host-ID port register */
+
+#define ca_enaddr      ca_aux1         /* LANCE: Ethernet address in ROM */
+#define ca_leflags     ca_aux2
+};
+
+int vsbus_intr_register __P((struct confargs *, int(*)(void*), void*));
+int vsbus_intr_enable __P((struct confargs *));
+int vsbus_intr_disable  __P((struct confargs *));
+int vsbus_intr_unregister __P((struct confargs *));
+
+int vsbus_lockDMA __P((struct confargs *));
+int vsbus_unlockDMA __P((struct confargs *));
+
index 65c3374..6bc9955 100644 (file)
@@ -1,4 +1,4 @@
-/*     $NetBSD: hp.c,v 1.9 1996/05/19 16:43:34 ragge Exp $ */
+/*     $NetBSD: hp.c,v 1.12 1996/10/13 03:34:58 christos Exp $ */
 /*
  * Copyright (c) 1996 Ludd, University of Lule}, Sweden.
  * All rights reserved.
@@ -471,8 +471,9 @@ hpwrite(dev, uio)
  * Convert physical adapternr and unit to the unit number used by kernel.
  */
 int
-hp_getdev(mbanr, unit)
+hp_getdev(mbanr, unit, uname)
        int     mbanr, unit;
+       char **uname;
 {
        struct  mba_softc *ms;
        struct  hp_softc *sc;
@@ -484,8 +485,10 @@ hp_getdev(mbanr, unit)
 
                sc = hp_cd.cd_devs[i];
                ms = (void *)sc->sc_dev.dv_parent;
-               if (ms->sc_physnr == mbanr && sc->sc_physnr == unit)
+               if (ms->sc_physnr == mbanr && sc->sc_physnr == unit) {
+                       *uname = sc->sc_dev.dv_xname;
                        return i;
+               }
        }
        return -1;
 }
index 17ea88a..40cce61 100644 (file)
@@ -1,4 +1,4 @@
-/*     $NetBSD: mba.c,v 1.6 1996/04/08 18:38:59 ragge Exp $ */
+/*     $NetBSD: mba.c,v 1.10 1996/10/13 03:35:00 christos Exp $ */
 /*
  * Copyright (c) 1994, 1996 Ludd, University of Lule}, Sweden.
  * All rights reserved.
@@ -81,7 +81,11 @@ struct       cfdriver mba_cd = {
        NULL, "mba", DV_DULL
 };
 
-struct cfattach mba_ca = {
+struct cfattach mba_cmi_ca = {
+       sizeof(struct mba_softc), mbamatch, mbaattach
+};
+
+struct cfattach mba_sbi_ca = {
        sizeof(struct mba_softc), mbamatch, mbaattach
 };
 
@@ -134,7 +138,7 @@ mbaattach(parent, self, aux)
 
        sc->sc_physnr = sa->nexnum - 8; /* MBA's have TR between 8 - 11... */
 #ifdef VAX750
-       if (cpunumber == VAX_750)
+       if (vax_cputype == VAX_750)
                sc->sc_physnr += 4;     /* ...but not on 11/750 */
 #endif
        sc->sc_first = 0;
@@ -238,7 +242,7 @@ mbaintr(mba)
 
 int
 mbaprint(aux, mbaname)
-       void            *aux;
+       void    *aux;
        const char      *mbaname;
 {
        struct  mba_attach_args *ma = aux;
@@ -284,71 +288,10 @@ mbastart(sc)
        volatile struct mba_regs *mr = sc->sc_mbareg;
        struct  buf *bp = md->md_q.b_actf;
 
-       mbamapregs(sc);
+       disk_reallymapin(md->md_q.b_actf, sc->sc_mbareg->mba_map, 0, PG_V);
 
        sc->sc_state = SC_ACTIVE;
        mr->mba_var = ((u_int)bp->b_un.b_addr & PGOFSET);
        mr->mba_bc = (~bp->b_bcount) + 1;
        (*md->md_start)(md);            /* machine-dependent start */
 }
-
-/*
- * Setup map registers for a dma transfer.
- * This routine could be synced with the other adapter map routines!
- */
-void
-mbamapregs(sc)
-       struct  mba_softc *sc;
-{
-       struct  mba_device *md = sc->sc_first;
-       volatile struct mba_regs *mr = sc->sc_mbareg;
-       struct  buf *bp = md->md_q.b_actf;
-       struct  pcb *pcb;
-       pt_entry_t *pte;
-       volatile pt_entry_t *io;
-       int     pfnum, npf, o, i;
-       caddr_t addr;
-
-       o = (int)bp->b_un.b_addr & PGOFSET;
-       npf = btoc(bp->b_bcount + o) + 1;
-       addr = bp->b_un.b_addr;
-
-       /*
-        * Get a pointer to the pte pointing out the first virtual address.
-        * Use different ways in kernel and user space.
-        */
-       if ((bp->b_flags & B_PHYS) == 0) {
-               pte = kvtopte(addr);
-       } else {
-               pcb = bp->b_proc->p_vmspace->vm_pmap.pm_pcb;
-               pte = uvtopte(addr, pcb);
-       }
-
-       /*
-        * When we are doing DMA to user space, be sure that all pages
-        * we want to transfer to is mapped. WHY DO WE NEED THIS???
-        * SHOULDN'T THEY ALWAYS BE MAPPED WHEN DOING THIS???
-        */
-       for (i = 0; i < (npf - 1); i++) {
-               if ((pte + i)->pg_pfn == 0) {
-                       int rv;
-                       rv = vm_fault(&bp->b_proc->p_vmspace->vm_map,
-                           (unsigned)addr + i * NBPG,
-                           VM_PROT_READ|VM_PROT_WRITE, FALSE);
-                       if (rv)
-                               panic("MBA DMA to nonexistent page, %d", rv);
-               }
-       }
-
-       io = &mr->mba_map[0];
-       while (--npf > 0) {
-               pfnum = pte->pg_pfn;
-               if (pfnum == 0)
-                       panic("mba zero entry");
-               pte++;
-               *(int *)io++ = pfnum | PG_V;
-       }
-       *(int *)io = 0;
-}
-
-
diff --git a/sys/arch/vax/mscp/files.mscp b/sys/arch/vax/mscp/files.mscp
new file mode 100644 (file)
index 0000000..ad85bcb
--- /dev/null
@@ -0,0 +1,20 @@
+#      $NetBSD: files.mscp,v 1.1 1996/07/01 20:41:30 ragge Exp $
+#
+# File and device description for MSCP devices.
+#
+
+define mscp {}
+file   arch/vax/mscp/mscp.c
+file   arch/vax/mscp/mscp_subr.c
+
+device mscpbus {drive = -1}
+attach mscpbus at mscp
+
+device ra: disk
+attach ra at mscpbus
+file   arch/vax/mscp/mscp_disk.c       ra needs-flag
+
+device mt: tape
+attach mt at mscpbus
+file   arch/vax/mscp/mscp_tape.c       mt needs-flag
+
diff --git a/sys/arch/vax/mscp/mscp.c b/sys/arch/vax/mscp/mscp.c
new file mode 100644 (file)
index 0000000..e8cb619
--- /dev/null
@@ -0,0 +1,508 @@
+/*     $NetBSD: mscp.c,v 1.5 1997/01/11 11:20:31 ragge Exp $   */
+
+/*
+ * Copyright (c) 1996 Ludd, University of Lule}, Sweden.
+ * Copyright (c) 1988 Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * 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.
+ *
+ *     @(#)mscp.c      7.5 (Berkeley) 12/16/90
+ */
+
+/*
+ * MSCP generic driver routines
+ */
+
+#include <sys/param.h>
+#include <sys/buf.h>
+#include <sys/malloc.h>
+#include <sys/device.h>
+
+#include <vax/mscp/mscp.h>
+#include <vax/mscp/mscpvar.h>
+
+#define        PCMD    PSWP            /* priority for command packet waits */
+
+/*
+ * During transfers, mapping info is saved in the buffer's b_resid.
+ */
+#define        b_info b_resid
+
+/*
+ * Get a command packet.  Second argument is true iff we are
+ * to wait if necessary.  Return NULL if none are available and
+ * we cannot wait.
+ */
+struct mscp *
+mscp_getcp(mi, canwait)
+       register struct mscp_softc *mi;
+       int canwait;
+{
+#define        mri     (&mi->mi_cmd)
+       register struct mscp *mp;
+       register int i;
+       int s = splbio();
+
+again:
+       /*
+        * Ensure that we have some command credits, and
+        * that the next command packet is free.
+        */
+       if (mi->mi_credits <= MSCP_MINCREDITS) {
+               if (!canwait) {
+                       splx(s);
+                       return (NULL);
+               }
+               mi->mi_wantcredits = 1;
+               sleep((caddr_t) &mi->mi_wantcredits, PCMD);
+               goto again;
+       }
+       i = mri->mri_next;
+       if (mri->mri_desc[i] & MSCP_OWN) {
+               if (!canwait) {
+                       splx(s);
+                       return (NULL);
+               }
+               mi->mi_wantcmd = 1;
+               sleep((caddr_t) &mi->mi_wantcmd, PCMD);
+               goto again;
+       }
+       mi->mi_credits--;
+       mri->mri_desc[i] &= ~MSCP_INT;
+       mri->mri_next = (mri->mri_next + 1) % mri->mri_size;
+       splx(s);
+       mp = &mri->mri_ring[i];
+
+       /*
+        * Initialise some often-zero fields.
+        * ARE THE LAST TWO NECESSARY IN GENERAL?  IT SURE WOULD BE
+        * NICE IF DEC SOLD DOCUMENTATION FOR THEIR OWN CONTROLLERS.
+        */
+       mp->mscp_msglen = MSCP_MSGLEN;
+       mp->mscp_flags = 0;
+       mp->mscp_modifier = 0;
+       mp->mscp_seq.seq_bytecount = 0;
+       mp->mscp_seq.seq_buffer = 0;
+       mp->mscp_seq.seq_mapbase = 0;
+/*???*/        mp->mscp_sccc.sccc_errlgfl = 0;
+/*???*/        mp->mscp_sccc.sccc_copyspd = 0;
+       return (mp);
+#undef mri
+}
+
+#ifdef AVOID_EMULEX_BUG
+int    mscp_aeb_xor = 0x8000bb80;
+#endif
+
+/*
+ * Handle a response ring transition.
+ */
+void
+mscp_dorsp(mi)
+       register struct mscp_softc *mi;
+{
+       struct device *drive;
+       struct mscp_device *me = mi->mi_me;
+       struct mscp_ctlr *mc = mi->mi_mc;
+       register struct buf *bp;
+       register struct mscp *mp;
+       register int nextrsp;
+       int st, error, info;
+       extern int cold;
+       extern struct mscp slavereply;
+
+       nextrsp = mi->mi_rsp.mri_next;
+loop:
+       if (mi->mi_rsp.mri_desc[nextrsp] & MSCP_OWN) {
+               /*
+                * No more responses.  Remember the next expected
+                * response index.  Check to see if we have some
+                * credits back, and wake up sleepers if so.
+                */
+               mi->mi_rsp.mri_next = nextrsp;
+               if (mi->mi_wantcredits && mi->mi_credits > MSCP_MINCREDITS) {
+                       mi->mi_wantcredits = 0;
+                       wakeup((caddr_t) &mi->mi_wantcredits);
+               }
+               return;
+       }
+
+       mp = &mi->mi_rsp.mri_ring[nextrsp];
+       mi->mi_credits += MSCP_CREDITS(mp->mscp_msgtc);
+       /*
+        * Controllers are allowed to interrupt as any drive, so we
+        * must check the command before checking for a drive.
+        */
+       if (mp->mscp_opcode == (M_OP_SETCTLRC | M_OP_END)) {
+               if ((mp->mscp_status & M_ST_MASK) == M_ST_SUCCESS) {
+                       mi->mi_flags |= MSC_READY;
+               } else {
+                       printf("%s: SETCTLRC failed: %d ",
+                           mi->mi_dev.dv_xname, mp->mscp_status);
+                       mscp_printevent(mp);
+               }
+               goto done;
+       }
+
+       /*
+        * Found a response.  Update credit information.  If there is
+        * nothing else to do, jump to `done' to get the next response.
+        */
+       if (mp->mscp_unit >= mi->mi_driveno) { /* Must expand drive table */
+               int tmpno = ((mp->mscp_unit + 32) & 0xffe0) * sizeof(void *);
+               struct device **tmp = (struct device **)
+                   malloc(tmpno, M_DEVBUF, M_NOWAIT);
+               bzero(tmp, tmpno);
+               if (mi->mi_driveno) {
+                       bcopy(mi->mi_dp, tmp, mi->mi_driveno);
+                       free(mi->mi_dp, mi->mi_driveno);
+               }
+               mi->mi_driveno = tmpno;
+               mi->mi_dp = tmp;
+       }
+
+       drive = mi->mi_dp[mp->mscp_unit];
+
+       switch (MSCP_MSGTYPE(mp->mscp_msgtc)) {
+
+       case MSCPT_SEQ:
+               break;
+
+       case MSCPT_DATAGRAM:
+               (*me->me_dgram)(drive, mp, mi);
+               goto done;
+
+       case MSCPT_CREDITS:
+               goto done;
+
+       case MSCPT_MAINTENANCE:
+       default:
+               printf("%s: unit %d: unknown message type 0x%x ignored\n",
+                       mi->mi_dev.dv_xname, mp->mscp_unit,
+                       MSCP_MSGTYPE(mp->mscp_msgtc));
+               goto done;
+       }
+
+       /*
+        * Handle individual responses.
+        */
+       st = mp->mscp_status & M_ST_MASK;
+       error = 0;
+       switch (mp->mscp_opcode) {
+
+       case M_OP_END:
+               /*
+                * The controller presents a bogus END packet when
+                * a read/write command is given with an illegal
+                * block number.  This is contrary to the MSCP
+                * specification (ENDs are to be given only for
+                * invalid commands), but that is the way of it.
+                */
+               if (st == M_ST_INVALCMD && mp->mscp_cmdref != 0) {
+                       printf("%s: bad lbn (%d)?\n", drive->dv_xname,
+                               (int)mp->mscp_seq.seq_lbn);
+                       error = EIO;
+                       goto rwend;
+               }
+               goto unknown;
+
+       case M_OP_ONLINE | M_OP_END:
+               /*
+                * Finished an ON LINE request.  Call the driver to
+                * find out whether it succeeded.  If so, mark it on
+                * line.
+                */
+               (*me->me_online)(drive, mp);
+               break;
+
+       case M_OP_GETUNITST | M_OP_END:
+               /*
+                * Got unit status.  If we are autoconfiguring, save
+                * the mscp struct so that mscp_attach know what to do.
+                * If the drive isn't configured, call config_found()
+                * to set it up, otherwise it's just a "normal" unit
+                * status.
+                */
+               if (cold)
+                       bcopy(mp, &slavereply, sizeof(struct mscp));
+
+               if (mp->mscp_status == (M_ST_OFFLINE|M_OFFLINE_UNKNOWN))
+                       break;
+
+               if (drive == 0) {
+                       struct  drive_attach_args da;
+
+                       da.da_mp = (struct mscp *)mp;
+                       da.da_typ = mi->mi_type;
+                       config_found(&mi->mi_dev, (void *)&da, mscp_print);
+               } else
+                       /* Hack to avoid complaints */
+                       if (!(((mp->mscp_event & M_ST_MASK) == M_ST_AVAILABLE)
+                           && cold))
+                               (*me->me_gotstatus)(drive, mp);
+               break;
+
+       case M_OP_AVAILATTN:
+               /*
+                * The drive went offline and we did not notice.
+                * Mark it off line now, to force an on line request
+                * next, so we can make sure it is still the same
+                * drive.
+                *
+                * IF THE UDA DRIVER HAS A COMMAND AWAITING UNIBUS
+                * RESOURCES, THAT COMMAND MAY GO OUT BEFORE THE ON
+                * LINE.  IS IT WORTH FIXING??
+                */
+#ifdef notyet
+               (*md->md_offline)(ui, mp);
+#endif
+               break;
+
+       case M_OP_POS | M_OP_END:
+       case M_OP_WRITM | M_OP_END:
+               /*
+                * A non-data transfer operation completed.
+                */
+               (*me->me_cmddone)(drive, mp);
+               break;
+
+       case M_OP_READ | M_OP_END:
+       case M_OP_WRITE | M_OP_END:
+               /*
+                * A transfer finished.  Get the buffer, and release its
+                * map registers via ubadone().  If the command finished
+                * with an off line or available status, the drive went
+                * off line (the idiot controller does not tell us until
+                * it comes back *on* line, or until we try to use it).
+                */
+#ifdef DIAGNOSTIC
+               if (mp->mscp_cmdref == 0) {
+                       /*
+                        * No buffer means there is a bug somewhere!
+                        */
+                       printf("%s: io done, but no buffer?\n",
+                           drive->dv_xname);
+                       mscp_hexdump(mp);
+                       break;
+               }
+#endif
+rwend:
+               bp = (struct buf *) mp->mscp_cmdref;
+
+               /*
+                * Mark any error-due-to-bad-LBN (via `goto rwend').
+                * WHAT STATUS WILL THESE HAVE?  IT SURE WOULD BE NICE
+                * IF DEC SOLD DOCUMENTATION FOR THEIR OWN CONTROLLERS.
+                */
+               if (error) {
+                       bp->b_flags |= B_ERROR;
+                       bp->b_error = error;
+               }
+               if (st == M_ST_OFFLINE || st == M_ST_AVAILABLE) {
+#ifdef notyet
+                       (*md->md_offline)(ui, mp);
+#endif
+               }
+
+               /*
+                * Unlink the transfer from the wait queue.
+                */
+               _remque(&bp->b_actf);
+
+               /*
+                * If the transfer has something to do with bad
+                * block forwarding, let the driver handle the
+                * rest.
+                */
+               if ((bp->b_flags & B_BAD) != 0 && me->me_bb != NULL) {
+                       (*me->me_bb)(drive, mp, bp);
+                       goto out;
+               }
+
+               /*
+                * If the transfer failed, give the driver a crack
+                * at fixing things up.
+                */
+               if (st != M_ST_SUCCESS) {
+                       switch ((*me->me_ioerr)(drive, mp, bp)) {
+
+                       case MSCP_DONE:         /* fixed */
+                               break;
+
+                       case MSCP_RESTARTED:    /* still working on it */
+                               goto out;
+
+                       case MSCP_FAILED:       /* no luck */
+                               /* XXX must move to ra.c */
+                               mscp_printevent(mp);
+                               break;
+                       }
+               }
+
+               /*
+                * Set the residual count and mark the transfer as
+                * done.  If the I/O wait queue is now empty, release
+                * the shared BDP, if any.
+                */
+               info = bp->b_info;      /* we are about to clobber it */
+               bp->b_resid = bp->b_bcount - mp->mscp_seq.seq_bytecount;
+
+               (*mc->mc_ctlrdone)(mi->mi_dev.dv_parent, info);
+               (*me->me_iodone)(drive, bp);
+out:
+               break;
+               
+       case M_OP_REPLACE | M_OP_END:
+               /*
+                * A replace operation finished.  Just let the driver
+                * handle it (if it does replaces).
+                */
+               if (me->me_replace == NULL)
+                       printf("%s: bogus REPLACE end\n", drive->dv_xname);
+               else
+                       (*me->me_replace)(drive, mp);
+               break;
+
+       default:
+               /*
+                * If it is not one of the above, we cannot handle it.
+                * (And we should not have received it, for that matter.)
+                */
+unknown:
+               printf("%s: unknown opcode 0x%x status 0x%x ignored\n",
+                       drive->dv_xname, mp->mscp_opcode, mp->mscp_status);
+#ifdef DIAGNOSTIC
+               mscp_hexdump(mp);
+#endif
+               break;
+       }
+
+       /*
+        * If the drive needs to be put back in the controller queue,
+        * do that now.  (`bp' below ought to be `dp', but they are all
+        * struct buf *.)  Note that b_active was cleared in the driver;
+        * we presume that there is something to be done, hence reassert it.
+        */
+#ifdef notyet /* XXX */
+       if (ui->ui_flags & UNIT_REQUEUE) {
+               bp = &md->md_utab[ui->ui_unit];
+               if (bp->b_active) panic("mscp_dorsp requeue");
+               MSCP_APPEND(bp, mi->mi_XXXtab, b_hash.le_next);
+/* Was:                MSCP_APPEND(bp, mi->mi_XXXtab, b_forw); */
+               bp->b_active = 1;
+               ui->ui_flags &= ~UNIT_REQUEUE;
+       }
+#endif
+done:
+       /*
+        * Give back the response packet, and take a look at the next.
+        */
+       mp->mscp_msglen = MSCP_MSGLEN;
+       mi->mi_rsp.mri_desc[nextrsp] |= MSCP_OWN;
+       nextrsp = (nextrsp + 1) % mi->mi_rsp.mri_size;
+       goto loop;
+}
+
+/*
+ * Requeue outstanding transfers, e.g., after bus reset.
+ * Also requeue any drives that have on line or unit status
+ * info pending.
+ */
+void
+mscp_requeue(mi)
+       struct mscp_softc *mi;
+{
+       register struct mscp_device *me = mi->mi_me;
+       register struct buf *bp, *dp;
+       register int unit;
+       struct buf *nextbp;
+
+panic("mscp_requeue");
+       /*
+        * Clear the controller chain.  Mark everything un-busy; we
+        * will soon fix any that are in fact busy.
+        */
+#ifdef notyet /* XXX */
+       mi->mi_XXXtab->b_actf = NULL;
+       mi->mi_XXXtab->b_active = 0;
+       for (unit = 0, dp = md->md_utab; unit < md->md_nunits; unit++, dp++) {
+               ui = md->md_dinfo[unit];
+               if (ui == NULL || !ui->ui_alive || ui->ui_ctlr != mi->mi_ctlr)
+                       continue;       /* not ours */
+               dp->b_hash.le_next = NULL;
+               dp->b_active = 0;
+       }
+       /*
+        * Scan the wait queue, linking buffers onto drive queues.
+        * Note that these must be put at the front of the drive queue,
+        * lest we reorder I/O operations.
+        */
+       for (bp = *mi->mi_XXXwtab.b_actb; bp != &mi->mi_XXXwtab; bp = nextbp) {
+               nextbp = *bp->b_actb;
+               dp = &md->md_utab[minor(bp->b_dev) >> md->md_unitshift];
+               bp->b_actf = dp->b_actf;
+               if (dp->b_actf == NULL)
+                       dp->b_actb = (void *)bp;
+               dp->b_actf = bp;
+       }
+       mi->mi_XXXwtab.b_actf = *mi->mi_XXXwtab.b_actb = &mi->mi_XXXwtab;
+
+       /*
+        * Scan for drives waiting for on line or status responses,
+        * and for drives with pending transfers.  Put these on the
+        * controller queue, and mark the controller busy.
+        */
+       for (unit = 0, dp = md->md_utab; unit < md->md_nunits; unit++, dp++) {
+               ui = md->md_dinfo[unit];
+               if (ui == NULL || !ui->ui_alive || ui->ui_ctlr != mi->mi_ctlr)
+                       continue;
+               ui->ui_flags &= ~(UNIT_HAVESTATUS | UNIT_ONLINE);
+               if ((ui->ui_flags & UNIT_REQUEUE) == 0 && dp->b_actf == NULL)
+                       continue;
+               ui->ui_flags &= ~UNIT_REQUEUE;
+               MSCP_APPEND(dp, mi->mi_XXXtab, b_hash.le_next);
+
+               dp->b_active = 1;
+               mi->mi_XXXtab->b_active = 1;
+       }
+
+#endif
+#ifdef AVOID_EMULEX_BUG
+       /*
+        * ... and clear the index-to-buffer table.
+        */
+       for (unit = 0; unit < AEB_MAX_BP; unit++)
+               mi->mi_bp[unit] = 0;
+#endif
+}
+
diff --git a/sys/arch/vax/mscp/mscp.h b/sys/arch/vax/mscp/mscp.h
new file mode 100644 (file)
index 0000000..64d5031
--- /dev/null
@@ -0,0 +1,493 @@
+/*     $NetBSD: mscp.h,v 1.2 1996/07/10 23:35:59 ragge Exp $   */
+
+/*
+ * Copyright (c) 1988 Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * 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.
+ *
+ *     @(#)mscp.h      7.5 (Berkeley) 6/28/90
+ */
+
+/*
+ * Definitions for the Mass Storage Control Protocol
+ * I WISH I KNEW WHAT MORE OF THESE WERE.  IT SURE WOULD BE NICE
+ * IF DEC SOLD DOCUMENTATION FOR THEIR OWN CONTROLLERS.
+ */
+
+/*
+ * Control message opcodes
+ */
+#define        M_OP_ABORT      0x01    /* Abort command */
+#define        M_OP_GETCMDST   0x02    /* Get command status command */
+#define        M_OP_GETUNITST  0x03    /* Get unit status command */
+#define        M_OP_SETCTLRC   0x04    /* Set controller characteristics command */
+#define        M_OP_SEREX      0x07    /* Serious exception end message */
+#define        M_OP_AVAILABLE  0x08    /* Available command */
+#define        M_OP_ONLINE     0x09    /* Online command */
+#define        M_OP_SETUNITC   0x0a    /* Set unit characteristics command */
+#define        M_OP_DTACCPATH  0x0b    /* Determine access paths command */
+#define        M_OP_ACCESS     0x10    /* Access command */
+#define        M_OP_COMPCD     0x11    /* Compare controller data command */
+#define        M_OP_ERASE      0x12    /* Erase command */
+#define        M_OP_FLUSH      0x13    /* Flush command */
+#define        M_OP_REPLACE    0x14    /* Replace command */
+#define        M_OP_COMPHD     0x20    /* Compare host data command */
+#define        M_OP_READ       0x21    /* Read command */
+#define        M_OP_WRITE      0x22    /* Write command */
+#define        M_OP_WRITM      0x23    /* Write mark command */
+#define        M_OP_POS        0x25    /* Positioning command */
+#define        M_OP_AVAILATTN  0x40    /* Available attention message */
+#define        M_OP_DUPUNIT    0x41    /* Duplicate unit number attention message */
+#define        M_OP_ACCPATH    0x42    /* Access path attention message */
+#define        M_OP_END        0x80    /* End message flag */
+
+
+/*
+ * Generic command modifiers
+ */
+#define        M_MD_EXPRS      0x8000  /* Express request */
+#define        M_MD_COMP       0x4000  /* Compare */
+#define        M_MD_CLSEX      0x2000  /* Clear serious exception */
+#define        M_MD_ERROR      0x1000  /* Force error */
+#define        M_MD_SCCHH      0x0800  /* Suppress caching (high speed) */
+#define        M_MD_SCCHL      0x0400  /* Suppress caching (low speed) */
+#define        M_MD_SECOR      0x0200  /* Suppress error correction */
+#define        M_MD_SEREC      0x0100  /* Suppress error recovery */
+#define        M_MD_SSHDW      0x0080  /* Suppress shadowing */
+#define        M_MD_WBKNV      0x0040  /* Write back (non-volatile) */
+#define        M_MD_WBKVL      0x0020  /* Write back (volatile) */
+#define        M_MD_WRSEQ      0x0010  /* Write shadow set one unit at a time */
+
+/*
+ * tape command modifiers
+ */
+#define        M_MD_IMMEDIATE  0x0040  /* Immediate completion */
+#define        M_MD_UNLOAD     0x0010  /* Unload tape */
+#define        M_MD_REVERSE    0x0008  /* Reverse action */
+#define        M_MD_OBJCOUNT   0x0004  /* Object count */
+#define        M_MD_REWIND     0x0002  /* Rewind */
+
+/*
+ * AVAILABLE command modifiers
+ */
+#define        M_AVM_ALLCD     0x0002  /* All class drivers */
+#define        M_AVM_SPINDOWN  0x0001  /* Spin down */
+
+/*
+ * FLUSH command modifiers
+ */
+#define        M_FLM_FLUSHENU  0x0001  /* Flush entire unit */
+#define        M_FLM_VOLATILE  0x0002  /* Volatile only */
+
+/*
+ * GET UNIT STATUS command modifiers
+ */
+#define        M_GUM_NEXTUNIT  0x0001  /* Next unit */
+
+/*
+ * ONLINE command modifiers
+ */
+#define        M_OLM_RIP       0x0001  /* Allow self destruction */
+#define        M_OLM_IGNMF     0x0002  /* Ignore media format error */
+
+/*
+ * ONLINE and SET UNIT CHARACTERISTICS command modifiers
+ */
+#define        M_OSM_ALTERHI   0x0020  /* Alter host identifier */
+#define        M_OSM_SHADOWSP  0x0010  /* Shadow unit specified */
+#define        M_OSM_CLEARWBL  0x0008  /* Clear write-back data lost */
+#define        M_OSM_SETWRPROT 0x0004  /* Set write protect */
+
+/*
+ * REPLACE command modifiers
+ */
+#define        M_RPM_PRIMARY   0x0001  /* Primary replacement block */
+
+/*
+ * End message flags
+ */
+#define        M_EF_BBLKR      0x80    /* Bad block reported */
+#define        M_EF_BBLKU      0x40    /* Bad block unreported */
+#define        M_EF_ERLOG      0x20    /* Error log generated */
+#define        M_EF_SEREX      0x10    /* Serious exception */
+#define        M_EF_EOT        0x08    /* at end-of-tape */
+#define        M_EF_POSLOST    0x04    /* position lost */
+
+/*
+ * Controller flags
+ */
+#define        M_CF_ATTN       0x80    /* Enable attention messages */
+#define        M_CF_MISC       0x40    /* Enable miscellaneous error log messages */
+#define        M_CF_OTHER      0x20    /* Enable other host's error log messages */
+#define        M_CF_THIS       0x10    /* Enable this host's error log messages */
+#define        M_CF_MLTHS      0x04    /* Multi-host */
+#define        M_CF_SHADW      0x02    /* Shadowing */
+#define        M_CF_576        0x01    /* 576 byte sectors */
+
+/*
+ * Unit flags
+ */
+#define        M_UF_REPLC      0x8000  /* Controller initiated bad block replacement */
+#define        M_UF_INACT      0x4000  /* Inactive shadow set unit */
+#define        M_UF_WRTPH      0x2000  /* Write protect (hardware) */
+#define        M_UF_WRTPS      0x1000  /* Write protect (software or volume) */
+#define        M_UF_SCCHH      0x8000  /* Suppress caching (high speed) */
+#define        M_UF_SCCHL      0x4000  /* Suppress caching (low speed) */
+#define        M_UF_RMVBL      0x0080  /* Removable media */
+#define        M_UF_WBKNV      0x0040  /* Write back (non-volatile) */
+#define        M_UF_576        0x0004  /* 576 byte sectors */
+#define        M_UF_CMPWR      0x0002  /* Compare writes */
+#define        M_UF_CMPRD      0x0001  /* Compare reads */
+
+/*
+ * Error Log message format codes
+ */
+#define        M_FM_CTLRERR    0x00    /* Controller error */
+#define        M_FM_BUSADDR    0x01    /* Host memory access error */
+#define        M_FM_DISKTRN    0x02    /* Disk transfer error */
+#define        M_FM_SDI        0x03    /* SDI error */
+#define        M_FM_SMLDSK     0x04    /* Small disk error */
+#define        M_FM_TAPETRN    0x05    /* Tape transfer error */
+#define        M_FM_STIERR     0x06    /* STI communication or command failure */
+#define        M_FM_STIDEL     0x07    /* STI drive error log */
+#define        M_FM_STIFEL     0x08    /* STI formatter error log */
+
+/*
+ * Error Log message flags
+ */
+#define        M_LF_SUCC       0x80    /* Operation successful */
+#define        M_LF_CONT       0x40    /* Operation continuing */
+#define        M_LF_SQNRS      0x01    /* Sequence number reset */
+
+/*
+ * Status codes
+ */
+#define        M_ST_MASK       0x1f    /* Status code mask */
+#define        M_ST_SUCCESS    0x00    /* Success */
+#define        M_ST_INVALCMD   0x01    /* Invalid command */
+#define        M_ST_ABORTED    0x02    /* Command aborted */
+#define        M_ST_OFFLINE    0x03    /* Unit offline */
+#define        M_ST_AVAILABLE  0x04    /* Unit available */
+#define        M_ST_MFMTERR    0x05    /* Media format error */
+#define        M_ST_WRPROT     0x06    /* Write protected */
+#define        M_ST_COMPERR    0x07    /* Compare error */
+#define        M_ST_DATAERR    0x08    /* Data error */
+#define        M_ST_HOSTBUFERR 0x09    /* Host buffer access error */
+#define        M_ST_CTLRERR    0x0a    /* Controller error */
+#define        M_ST_DRIVEERR   0x0b    /* Drive error */
+#define        M_ST_FORMATTERR 0x0c    /* Formatter error */
+#define        M_ST_BOT        0x0d    /* Beginning-of-tape */
+#define        M_ST_TAPEMARK   0x0e    /* Tape mark encountered */
+#define        M_ST_RDTRUNC    0x10    /* Record data truncated */
+#define        M_ST_DIAG       0x1f    /* Message from an internal diagnostic */
+
+/*
+ * Subcodes of M_ST_OFFLINE
+ */
+#define        M_OFFLINE_UNKNOWN       (0 << 5) /* unknown or on other ctlr */
+#define        M_OFFLINE_UNMOUNTED     (1 << 5) /* unmounted or RUN/STOP at STOP */
+#define        M_OFFLINE_INOPERATIVE   (2 << 5) /* inoperative? */
+#define        M_OFFLINE_DUPLICATE     (4 << 5) /* duplicate unit number */
+#define        M_OFFLINE_INDIAGNOSTIC  (8 << 5) /* disabled by FS or diagnostic */
+
+/*
+ * An MSCP packet begins with a header giving the length of
+ * the entire packet (including the header itself)(?), two bytes
+ * of device specific data, and the a whole bunch of variants
+ * depending on message type.
+ *
+ * N.B.:  In most cases we distinguish between a `command' and
+ * an `end' variant as well.  The command variant is that which
+ * is given to the controller; the `end' variant is its response.
+ */
+
+/*
+ * Generic sequential message variant (command and response).
+ */
+struct mscpv_seq {
+       long    seq_bytecount;          /* byte count */
+#define        seq_rbn         seq_bytecount   /* aka RBN (replace) */
+#define        seq_outref      seq_bytecount   /* aka outref (abort/get cmd status) */
+       long    seq_buffer;             /* buffer descriptor */
+       long    seq_mapbase;            /* page map (first PTE) phys address */
+       long    seq_xxx1;       /* ? */ /* unused */
+       long    seq_lbn;                /* logical block number */
+       long    seq_xxx2;       /* ? */ /* unused */
+       long    *seq_addr;              /* pointer to cmd descriptor */
+       long    seq_software[4];        /* reserved to software; unused */
+};
+
+/*
+ * Set Controller Characteristics command variant
+ */
+struct mscpv_sccc {
+       u_short sccc_version;           /* MSCP version number */
+       u_short sccc_ctlrflags;         /* controller flags */
+       u_short sccc_hosttimo;          /* host timeout */
+       u_short sccc_usefrac;           /* use fraction */
+       long    sccc_time;              /* time and date */
+       long    sccc_time1;             /* it's a quad field */
+       long    sccc_errlgfl;   /* ? */
+       short   sccc_xxx2;      /* ? */
+       short   sccc_copyspd;   /* ? */
+};
+
+/*
+ * Set Controller Characteristics end variant
+ */
+struct mscpv_scce {
+       u_short scce_version;           /* MSCP version number */
+       u_short scce_ctlrflags;         /* controller flags */
+       u_short scce_ctlrtimo;          /* controller timeout */
+       u_short scce_ctlrcmdl;          /* ??? */
+       quad_t  scce_ctlrid;            /* controller ID */
+       long    scce_xxx[3];    /* ? */
+       long    scce_volser;            /* volume serial number */
+};
+
+/*
+ * On Line command variant
+ */
+struct mscpv_onlc {
+       long    onlc_xxx1[4];   /* ? */
+       long    onlc_errlgfl;           /* error log flag? */
+       short   onlc_xxx2;      /* ? */
+       short   onlc_copyspd;           /* copy speed? */
+};
+
+/*
+ * On Line end variant
+ */
+struct mscpv_onle {
+       long    onle_xxx1[3];   /* ? */
+/*???*/        short   onle_xxx2;      /* ? */
+       u_char  onle_drivetype;         /* drive type index (same in guse) */
+       char    onle_xxx3;      /* ? */
+       long    onle_mediaid;           /* media type id (same in guse) */
+       long    onle_xxx4;      /* ? */
+       long    onle_unitsize;          /* unit size in sectors */
+       long    onle_volser;            /* volume serial number */
+};
+
+/*
+ * Get Unit Status end variant (and Avail Attn?)
+ */
+struct mscpv_guse {
+       u_short guse_multunit;          /* multi-unit code */
+       u_short guse_unitflags;         /* unit flags */
+       long    guse_hostid;            /* host id */
+       long    guse_unitid0;   /*???*/
+       short   guse_unitid1;   /*???*/
+       u_char  guse_drivetype;         /* drive type index */
+       u_char  guse_unitid2;   /*???*/
+       long    guse_mediaid;           /* media type id (encoded) */
+       short   guse_shadowunit;        /* shadow unit */
+       short   guse_shadowstat;        /* shadow status */
+       u_short guse_nspt;              /* sectors per track */
+       u_short guse_group;             /* track group size */
+       u_short guse_ngpc;              /* groups per cylinder */
+       u_short guse_xxx;               /* reserved */
+       u_short guse_rctsize;           /* RCT size (sectors) */
+       u_char  guse_nrpt;              /* RBNs per track */
+       u_char  guse_nrct;              /* number of RCTs */
+};
+
+/*
+ * Macros to break up and build media IDs.  An ID encodes the port
+ * type in the top 10 bits, and the drive type in the remaining 22.
+ * The 10 bits, and 15 of the 22, are in groups of 5, with the value
+ * 0 representing space and values 1..26 representing A..Z.  The low
+ * 7 bits represent a number in 0..127.  Hence an RA81 on a UDA50
+ * is <D><U><R><A>< >81, or 0x25641051.  This encoding scheme is known
+ * in part in uda.c.
+ *
+ * The casts below are just to make pcc generate better code.
+ */
+#define        MSCP_MEDIA_PORT(id)     (((long)(id) >> 22) & 0x3ff)    /* port */
+#define        MSCP_MEDIA_DRIVE(id)    ((long)(id) & 0x003fffff)       /* drive */
+#define        MSCP_MID_ECH(n, id)     (((long)(id) >> ((n) * 5 + 7)) & 0x1f)
+#define        MSCP_MID_CHAR(n, id) \
+       (MSCP_MID_ECH(n, id) ? MSCP_MID_ECH(n, id) + '@' : ' ')
+#define        MSCP_MID_NUM(id)        ((id) & 0x7f)
+/* for, e.g., RA81 */
+#define        MSCP_MKDRIVE2(a, b, n) \
+       (((a) - '@') << 17 | ((b) - '@') << 12 | (n))
+/* for, e.g., RRD50 */
+#define        MSCP_MKDRIVE3(a, b, c, n) \
+       (((a) - '@') << 17 | ((b) - '@') << 12 | ((c) - '@') << 7 | (n))
+
+/*
+ * Error datagram variant.
+ */
+struct mscpv_erd {
+       quad_t  erd_ctlrid;             /* controller ID */
+       u_char  erd_ctlrsoftware;       /* controller software version */
+       u_char  erd_ctlrhardware;       /* controller hardware version */
+       u_short erd_multiunit;          /* multi-unit code (?) */
+       union {
+               u_long  un_busaddr;     /* bus address, if mem access err */
+               quad_t  un_unitid;      /* unit id, otherwise */
+       } erd_un1;
+#define        erd_busaddr     erd_un1.un_busaddr
+#define        erd_unitid      erd_un1.un_unitid
+       u_char  erd_unitsoftware;       /* unit software version */
+       u_char  erd_unithardware;       /* unit hardware version */
+       union {
+               u_char  un_b[2];        /* level, retry (if disk xfer err) */
+               u_short un_s;           /* cylinder (if small disk error) */
+       } erd_un2;
+#define        erd_level       erd_un2.un_b[0]
+#define        erd_retry       erd_un2.un_b[1]
+#define        erd_sdecyl      erd_un2.un_s
+       long    erd_volser;             /* volume serial number */
+       u_long  erd_hdr;                /* `header' (block number) */
+       u_char  erd_sdistat[12];        /* SDI status information (?) */
+};
+
+/*
+ * I am making brash assumptions about the first four bytes of all
+ * MSCP packets.  These appear to be true for both UDA50s and TMSCP
+ * devices (TU81, TA81, TK50).  DEC claim that these four bytes are
+ * not part of MSCP itself, yet at least the length is necessary
+ * for, e.g., error checking.
+ */
+struct mscp {
+       u_short mscp_msglen;            /* length in bytes */
+       u_char  mscp_msgtc;             /* type (high 4 bits) and credits */
+       u_char  mscp_vcid;              /* virtual circuit ID */
+       long    mscp_cmdref;            /* command reference number */
+       u_short mscp_unit;              /* unit number */
+       u_short mscp_seqnum;            /* sequence number */
+       u_char  mscp_opcode;            /* opcode */
+#define        mscp_format     mscp_opcode     /* aka format (datagrams) */
+       u_char  mscp_flags;             /* flags */
+       u_short mscp_modifier;          /* modifier (commands) */
+#define        mscp_status     mscp_modifier   /* aka status (ends) */
+#define        mscp_event      mscp_modifier   /* aka event (datagrams) */
+       union {
+               struct  mscpv_seq un_seq;       /* generic sequential msg */
+               struct  mscpv_sccc un_sccc;     /* SCC command */
+               struct  mscpv_scce un_scce;     /* SCC end */
+               struct  mscpv_onlc un_onlc;     /* on line command */
+               struct  mscpv_onle un_onle;     /* on line end */
+               struct  mscpv_guse un_guse;     /* get unit status */
+               struct  mscpv_erd un_erd;       /* error datagram */
+       } mscp_un;
+/*???*/        long    mscp_xxx;               /* pad to 64 bytes */
+};
+
+/*
+ * Define message length according to the DEC specifications by dropping
+ * the four byte header.
+ */
+#define        MSCP_MSGLEN     (sizeof (struct mscp) - 4)
+
+/*
+ * Shorthand
+ */
+
+/*
+ * Generic packet
+ */
+#define        mscp_seq        mscp_un.un_seq
+
+/*
+ * Set Controller Characteristics packet
+ */
+#define        mscp_sccc       mscp_un.un_sccc
+
+/*
+ * Set Controller Characteristics end packet
+ */
+#define        mscp_scce       mscp_un.un_scce
+
+/*
+ * Online / Set Unit Characteristics command packet
+ */
+#define        mscp_onlc       mscp_un.un_onlc
+
+/*
+ * Online end packet
+ */
+#define        mscp_onle       mscp_un.un_onle
+
+/*
+ * Get Unit Status end packet
+ */
+#define        mscp_guse       mscp_un.un_guse
+
+/*
+ * MSCP Error Log packet
+ */
+#define        mscp_erd        mscp_un.un_erd
+
+/*
+ * MSCP seq_addr field actually belongs to overall packet.
+ */
+#define        mscp_addr       mscp_seq.seq_addr
+
+/*
+ * Macros to break up mscp_msgtc, and types.
+ */
+#define        MSCP_MSGTYPE(m) ((m) & 0xf0)
+#define        MSCP_CREDITS(m) ((m) & 0x0f)
+
+#define        MSCPT_SEQ               0x00    /* sequential message */
+#define        MSCPT_DATAGRAM          0x10    /* error datagram */
+#define        MSCPT_CREDITS           0x20    /* credit notification */
+#define        MSCPT_MAINTENANCE       0xf0    /* who knows */
+
+
+/*
+ * Here begin more perhaps brash assumptions about MSCP devices...
+ */
+
+/*
+ * MSCP controllers have `command rings' and `response rings'.  A
+ * command ring is a pool of MSCP packets that the host uses to give
+ * commands to the controller; a response ring is a pool of MSCP
+ * packets that the controller uses to give back responses.  Entries
+ * in the command and response rings are `owned' by either the host
+ * or the controller; only the owner is allowed to alter any of the
+ * fields in the MSCP packet.  Thus, free command packets are owned
+ * by the host, and free response packets by the controller.  When
+ * the host gives a packet to the controller, it tells the controller
+ * by touching a device register; when the controller gives a response
+ * to the host, it generates an interrupt if enabled, and sets
+ * a device register as well.
+ *
+ * The pool is `described' by a set of pointers to the packets, along
+ * with the two flags below.
+ */
+#define        MSCP_OWN        0x80000000      /* controller owns this packet */
+#define        MSCP_INT        0x40000000      /* controller should interrupt */
diff --git a/sys/arch/vax/mscp/mscp_disk.c b/sys/arch/vax/mscp/mscp_disk.c
new file mode 100644 (file)
index 0000000..394e1ed
--- /dev/null
@@ -0,0 +1,966 @@
+/*     $NetBSD: mscp_disk.c,v 1.7 1997/01/11 11:20:32 ragge Exp $      */
+/*
+ * Copyright (c) 1996 Ludd, University of Lule}, Sweden.
+ * Copyright (c) 1988 Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * 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.
+ *
+ *     @(#)uda.c       7.32 (Berkeley) 2/13/91
+ */
+
+/*
+ * RA disk device driver
+ */
+
+/*
+ * TODO
+ *     write bad block forwarding code
+ */
+
+#include <sys/param.h>
+#include <sys/buf.h>
+#include <sys/device.h>
+#include <sys/disk.h>
+#include <sys/disklabel.h>
+#include <sys/ioctl.h>
+#include <sys/stat.h>
+#include <sys/fcntl.h>
+#include <sys/proc.h>
+#include <sys/systm.h>
+
+#include <ufs/ffs/fs.h> /* For some disklabel stuff */
+
+#include <vax/mscp/mscp.h>
+#include <vax/mscp/mscpvar.h>
+
+/*
+ * Drive status, per drive
+ */
+struct ra_softc {
+       struct  device ra_dev;  /* Autoconf struct */
+       struct  disk ra_disk;
+       int     ra_state;       /* open/closed state */
+       u_long  ra_mediaid;     /* media id */
+       int     ra_hwunit;      /* Hardware unit number */
+       int     ra_havelabel;   /* true if we have a label */
+       int     ra_wlabel;      /* label sector is currently writable */
+       int     ra_isafloppy;   /* unit is a floppy disk */
+};
+
+int    ramatch __P((struct device *, void *, void *));
+void   raattach __P((struct device *, struct device *, void *));
+void   radgram __P((struct device *, struct mscp *, struct mscp_softc *));
+void   raiodone __P((struct device *, struct buf *));
+int    raonline __P((struct device *, struct mscp *));
+int    ragotstatus __P((struct device *, struct mscp *));
+void   rareplace __P((struct device *, struct mscp *));
+int    raioerror __P((struct device *, struct mscp *, struct buf *));
+void   rafillin __P((struct buf *, struct mscp *));
+void   rabb __P((struct device *, struct mscp *, struct buf *));
+int    raopen __P((dev_t, int, int, struct proc *));
+int    raclose __P((dev_t, int, int, struct proc *));
+void   rastrategy __P((struct buf *));
+void   rastrat1 __P((struct buf *));
+int    raread __P((dev_t, struct uio *));
+int    rawrite __P((dev_t, struct uio *));
+int    raioctl __P((dev_t, int, caddr_t, int, struct proc *));
+int    radump __P((dev_t, daddr_t, caddr_t, size_t));
+int    rasize __P((dev_t));
+int    ra_putonline __P((struct ra_softc *));
+
+
+struct mscp_device ra_device = {
+       radgram,
+       raiodone,
+       raonline,
+       ragotstatus,
+       rareplace,
+       raioerror,
+       rabb,
+       rafillin,
+};
+
+/*
+ * Device to unit number and partition and back
+ */
+#define        UNITSHIFT       3
+#define        UNITMASK        7
+#define        raunit(dev)     (minor(dev) >> UNITSHIFT)
+#define        rapart(dev)     (minor(dev) & UNITMASK)
+#define        raminor(u, p)   (((u) << UNITSHIFT) | (p))
+
+struct cfdriver ra_cd = {
+       NULL, "ra", DV_DULL
+};
+
+struct cfattach ra_ca = {
+       sizeof(struct ra_softc), ramatch, raattach
+};
+
+/*
+ * Software state, per drive
+ */
+#define        RA_OFFLINE      0
+#define        RA_WANTOPEN     1
+#define        RA_ONLINE       3
+
+/*
+ * More driver definitions, for generic MSCP code.
+ */
+extern int cold;
+
+int
+ramatch(parent, match, aux)
+       struct  device *parent;
+       void    *match, *aux;
+{
+       struct  cfdata *cf = match;
+       struct  drive_attach_args *da = aux;
+       struct  mscp *mp = da->da_mp;
+
+       if ((da->da_typ & MSCPBUS_DISK) == 0)
+               return 0;
+       if (cf->cf_loc[0] != -1 && cf->cf_loc[0] != mp->mscp_unit)
+               return 0;
+       return 1;
+}
+
+/*
+ * The attach routine only checks and prints drive type.
+ * Bringing the disk online is done when the disk is accessed
+ * the first time. 
+ */
+void
+raattach(parent, self, aux)
+       struct  device *parent, *self;
+       void    *aux; 
+{
+       struct  ra_softc *ra = (void *)self;
+       struct  drive_attach_args *da = aux;
+       struct  mscp *mp = da->da_mp;
+       struct  mscp_softc *mi = (void *)parent;
+       struct  disklabel *dl;
+
+       ra->ra_mediaid = mp->mscp_guse.guse_mediaid;
+       ra->ra_state = RA_OFFLINE;
+       ra->ra_havelabel = 0;
+       ra->ra_hwunit = mp->mscp_unit;
+       mi->mi_dp[mp->mscp_unit] = self;
+       disk_attach((struct disk *)&ra->ra_disk);
+
+       /* Fill in what we know. The actual size is gotten later */
+       dl = ra->ra_disk.dk_label;
+
+       dl->d_secsize = DEV_BSIZE;
+       dl->d_nsectors = mp->mscp_guse.guse_nspt;
+       dl->d_ntracks = mp->mscp_guse.guse_ngpc;
+       dl->d_secpercyl = dl->d_nsectors * dl->d_ntracks;
+       disk_printtype(mp->mscp_unit, mp->mscp_guse.guse_mediaid);
+}
+
+/* 
+ * (Try to) put the drive online. This is done the first time the
+ * drive is opened, or if it har fallen offline.
+ */
+int
+ra_putonline(ra)
+       struct ra_softc *ra;
+{
+       struct  mscp *mp;
+       struct  mscp_softc *mi = (struct mscp_softc *)ra->ra_dev.dv_parent;
+       struct  disklabel *dl;
+       volatile int i;
+       char *msg;
+
+       dl = ra->ra_disk.dk_label;
+
+       ra->ra_state = RA_WANTOPEN;
+       mp = mscp_getcp(mi, MSCP_WAIT);
+       mp->mscp_opcode = M_OP_ONLINE;
+       mp->mscp_unit = ra->ra_hwunit;
+       mp->mscp_cmdref = (long)&ra->ra_state;
+       *mp->mscp_addr |= MSCP_OWN | MSCP_INT;
+
+       /* Poll away */
+       i = *mi->mi_ip;
+       if (tsleep(&ra->ra_state, PRIBIO, "raonline", 100*100)) {
+               ra->ra_state = RA_OFFLINE;
+               return MSCP_FAILED;
+       }
+
+       if (ra->ra_state == RA_OFFLINE)
+               return MSCP_FAILED;
+       if (ra->ra_isafloppy)
+               return MSCP_DONE;
+       dl->d_partitions[0].p_size = dl->d_partitions[2].p_size =
+           dl->d_secperunit;
+       dl->d_partitions[0].p_offset = dl->d_partitions[2].p_offset = 0;
+
+       printf("%s", ra->ra_dev.dv_xname);
+       if ((msg = readdisklabel(raminor(ra->ra_dev.dv_unit, 0),
+           rastrategy, dl, NULL)) != NULL)
+               printf(": %s", msg);
+       else
+               ra->ra_havelabel = 1;
+       ra->ra_state = RA_ONLINE;
+
+       printf(": size %d sectors\n", dl->d_secperunit);
+
+       return MSCP_DONE;
+}
+/*
+ * Open a drive.
+ */
+/*ARGSUSED*/
+int
+raopen(dev, flag, fmt, p)
+       dev_t dev;
+       int flag, fmt;
+       struct  proc *p;
+{
+       register struct ra_softc *ra;
+       int part, unit, mask;
+
+       /*
+        * Make sure this is a reasonable open request.
+        */
+       unit = raunit(dev);
+       if (unit >= ra_cd.cd_ndevs)
+               return ENXIO;
+       ra = ra_cd.cd_devs[unit];
+       if (ra == 0)
+               return ENXIO;
+
+       /*
+        * If this is the first open; we must first try to put
+        * the disk online (and read the label).
+        */
+       if (ra->ra_state == RA_OFFLINE)
+               if (ra_putonline(ra) == MSCP_FAILED)
+                       return EIO;
+
+       part = raunit(dev);
+       if (ra->ra_isafloppy == 0)
+               if (part >= ra->ra_disk.dk_label->d_npartitions)
+                       return ENXIO;
+
+       /*
+        * Wait for the state to settle
+        */
+#if notyet
+       while (ra->ra_state != RA_ONLINE)
+               if ((error = tsleep((caddr_t)ra, (PZERO + 1) | PCATCH,
+                   devopn, 0))) {
+                       splx(s);
+                       return (error);
+               }
+#endif
+
+       mask = 1 << part;
+
+       switch (fmt) {
+       case S_IFCHR:
+               ra->ra_disk.dk_copenmask |= mask;
+               break;
+       case S_IFBLK:
+               ra->ra_disk.dk_bopenmask |= mask;
+               break;
+       }
+       ra->ra_disk.dk_openmask |= mask;
+       return 0;
+}
+
+/* ARGSUSED */
+int
+raclose(dev, flags, fmt, p)
+       dev_t dev;
+       int flags, fmt;
+       struct  proc *p;
+{
+       register int unit = raunit(dev);
+       register struct ra_softc *ra = ra_cd.cd_devs[unit];
+       int mask = (1 << rapart(dev));
+
+       switch (fmt) {
+       case S_IFCHR:
+               ra->ra_disk.dk_copenmask &= ~mask;
+               break;
+       case S_IFBLK:
+               ra->ra_disk.dk_bopenmask &= ~mask;
+               break;
+       }
+       ra->ra_disk.dk_openmask =
+           ra->ra_disk.dk_copenmask | ra->ra_disk.dk_bopenmask;
+
+       /*
+        * Should wait for I/O to complete on this partition even if
+        * others are open, but wait for work on blkflush().
+        */
+#if 0
+       if (ra->ra_openpart == 0) {
+               s = splbio();
+               while (udautab[unit].b_actf)
+                       sleep((caddr_t)&udautab[unit], PZERO - 1);
+               splx(s);
+               ra->ra_state = CLOSED;
+               ra->ra_wlabel = 0;
+       }
+#endif
+       return (0);
+}
+
+/*
+ * Queue a transfer request, and if possible, hand it to the controller.
+ *
+ * This routine is broken into two so that the internal version
+ * udastrat1() can be called by the (nonexistent, as yet) bad block
+ * revectoring routine.
+ */
+void
+rastrategy(bp)
+       register struct buf *bp;
+{
+       register int unit;
+       register struct ra_softc *ra;
+       int p;
+       /*
+        * Make sure this is a reasonable drive to use.
+        */
+       unit = raunit(bp->b_dev);
+       if (unit > ra_cd.cd_ndevs || (ra = ra_cd.cd_devs[unit]) == NULL) {
+               bp->b_error = ENXIO;
+               goto bad;
+       }
+       /*
+        * If drive is open `raw' or reading label, let it at it.
+        */
+       if (ra->ra_state < RA_ONLINE) {
+               mscp_strategy(bp, ra->ra_dev.dv_parent);
+               return;
+       }
+       p = rapart(bp->b_dev);
+
+       /*
+        * Determine the size of the transfer, and make sure it is
+        * within the boundaries of the partition.
+        */
+       if (ra->ra_isafloppy) {
+               if (bp->b_blkno >= ra->ra_disk.dk_label->d_secperunit) {
+                       bp->b_resid = bp->b_bcount;
+                       goto done;
+               }
+       } else
+               if (bounds_check_with_label(bp, ra->ra_disk.dk_label,
+                   ra->ra_wlabel) <= 0) {
+                       bp->b_error = ENXIO;
+                       goto bad;
+               }
+
+       mscp_strategy(bp, ra->ra_dev.dv_parent);
+       return;
+
+bad:
+       bp->b_flags |= B_ERROR;
+done:
+       biodone(bp);
+}
+
+int
+raread(dev, uio)
+        dev_t dev;
+        struct uio *uio;
+{
+
+        return (physio(rastrategy, NULL, dev, B_READ, minphys, uio));
+}
+
+int
+rawrite(dev, uio)
+        dev_t dev;
+        struct uio *uio;
+{
+
+        return (physio(rastrategy, NULL, dev, B_WRITE, minphys, uio));
+}
+
+void
+raiodone(usc, bp)
+       struct device *usc;
+       struct buf *bp;
+{
+
+       biodone(bp);
+}
+
+/*
+ * Fill in disk addresses in a mscp packet waiting for transfer.
+ */
+void
+rafillin(bp, mp)
+       struct buf *bp;
+       struct mscp *mp;
+{
+       int unit = raunit(bp->b_dev);
+       int part = rapart(bp->b_dev);
+       struct ra_softc *ra = ra_cd.cd_devs[unit];
+       struct disklabel *lp = ra->ra_disk.dk_label;
+
+       
+       /* XXX more checks needed */
+       mp->mscp_unit = ra->ra_hwunit;
+       mp->mscp_seq.seq_lbn = bp->b_blkno + lp->d_partitions[part].p_offset;
+       mp->mscp_seq.seq_bytecount = bp->b_bcount;
+}
+
+/*
+ * Handle an error datagram.
+ * This can come from an unconfigured drive as well.
+ */
+void
+radgram(usc, mp, mi)
+       struct device *usc;
+       struct mscp *mp;
+       struct mscp_softc *mi;
+{
+       if (mscp_decodeerror(usc == NULL?"unconf ra" : usc->dv_xname, mp, mi))
+               return;
+       /*
+        * SDI status information bytes 10 and 11 are the microprocessor
+        * error code and front panel code respectively.  These vary per
+        * drive type and are printed purely for field service information.
+        */
+       if (mp->mscp_format == M_FM_SDI)
+               printf("\tsdi uproc error code 0x%x, front panel code 0x%x\n",
+                       mp->mscp_erd.erd_sdistat[10],
+                       mp->mscp_erd.erd_sdistat[11]);
+}
+
+/*
+ * A drive came on line.  Check its type and size.  Return DONE if
+ * we think the drive is truly on line.  In any case, awaken anyone
+ * sleeping on the drive on-line-ness.
+ */
+int
+raonline(usc, mp)
+       struct device *usc;
+       struct mscp *mp;
+{
+       register struct ra_softc *ra = (void *)usc;
+       struct disklabel *dl;
+       int p = 0, d, n;
+
+       wakeup((caddr_t)&ra->ra_state);
+       if ((mp->mscp_status & M_ST_MASK) != M_ST_SUCCESS) {
+               printf("%s: attempt to bring on line failed: ", 
+                   ra->ra_dev.dv_xname);
+               mscp_printevent(mp);
+               ra->ra_state = RA_OFFLINE;
+               return (MSCP_FAILED);
+       }
+
+       /*
+        * Fill in the rest of disk size.
+        */
+       ra->ra_state = RA_WANTOPEN;
+       dl = ra->ra_disk.dk_label;
+       dl->d_secperunit = (daddr_t)mp->mscp_onle.onle_unitsize;
+
+       if (dl->d_secpercyl != 0)
+               dl->d_ncylinders = dl->d_secperunit/dl->d_secpercyl;
+       else
+               ra->ra_isafloppy = 1;
+       dl->d_type = DTYPE_MSCP;
+       dl->d_rpm = 3600;
+       dl->d_bbsize = BBSIZE;
+       dl->d_sbsize = SBSIZE;
+
+       /* Create the disk name for disklabel. Phew... */
+       d = ra->ra_mediaid;
+       dl->d_typename[p++] = MSCP_MID_CHAR(2, d);
+       dl->d_typename[p++] = MSCP_MID_CHAR(1, d);
+       if (MSCP_MID_ECH(0, d))
+               dl->d_typename[p++] = MSCP_MID_CHAR(0, d);
+       n = MSCP_MID_NUM(d);
+       if (n > 99) {
+               dl->d_typename[p++] = '1';
+               n -= 100;
+       }
+       if (n > 9) {
+               dl->d_typename[p++] = (n / 10) + '0';
+               n %= 10;
+       }
+       dl->d_typename[p++] = n + '0';
+       dl->d_typename[p] = 0;
+       dl->d_npartitions = MAXPARTITIONS;
+
+       return (MSCP_DONE);
+}
+
+/*
+ * We got some (configured) unit's status.  Return DONE if it succeeded.
+ */
+int
+ragotstatus(usc, mp)
+       register struct device *usc;
+       register struct mscp *mp;
+{
+       if ((mp->mscp_status & M_ST_MASK) != M_ST_SUCCESS) {
+               printf("%s: attempt to get status failed: ", usc->dv_xname);
+               mscp_printevent(mp);
+               return (MSCP_FAILED);
+       }
+       /* record for (future) bad block forwarding and whatever else */
+#ifdef notyet
+       uda_rasave(ui->ui_unit, mp, 1);
+#endif
+       return (MSCP_DONE);
+}
+
+/*
+ * A transfer failed.  We get a chance to fix or restart it.
+ * Need to write the bad block forwaring code first....
+ */
+/*ARGSUSED*/
+int
+raioerror(usc, mp, bp)
+       register struct device *usc;
+       register struct mscp *mp;
+       struct buf *bp;
+{
+printf("raioerror\n");
+#if 0
+       if (mp->mscp_flags & M_EF_BBLKR) {
+               /*
+                * A bad block report.  Eventually we will
+                * restart this transfer, but for now, just
+                * log it and give up.
+                */
+               log(LOG_ERR, "ra%d: bad block report: %d%s\n",
+                       ui->ui_unit, (int)mp->mscp_seq.seq_lbn,
+                       mp->mscp_flags & M_EF_BBLKU ? " + others" : "");
+       } else {
+               /*
+                * What the heck IS a `serious exception' anyway?
+                * IT SURE WOULD BE NICE IF DEC SOLD DOCUMENTATION
+                * FOR THEIR OWN CONTROLLERS.
+                */
+               if (mp->mscp_flags & M_EF_SEREX)
+                       log(LOG_ERR, "ra%d: serious exception reported\n",
+                               ui->ui_unit);
+       }
+#endif
+       return (MSCP_FAILED);
+}
+
+/*
+ * A replace operation finished.
+ */
+/*ARGSUSED*/
+void
+rareplace(usc, mp)
+       struct device *usc;
+       struct mscp *mp;
+{
+
+       panic("udareplace");
+}
+
+/*
+ * A bad block related operation finished.
+ */
+/*ARGSUSED*/
+void
+rabb(usc, mp, bp)
+       struct device *usc;
+       struct mscp *mp;
+       struct buf *bp;
+{
+
+       panic("udabb");
+}
+
+
+/*
+ * I/O controls.
+ */
+int
+raioctl(dev, cmd, data, flag, p)
+       dev_t dev;
+       int cmd;
+       caddr_t data;
+       int flag;
+       struct proc *p;
+{
+       register int unit = raunit(dev);
+       register struct disklabel *lp;
+       register struct ra_softc *ra = ra_cd.cd_devs[unit];
+       int error = 0;
+
+       lp = ra->ra_disk.dk_label;
+
+       switch (cmd) {
+
+       case DIOCGDINFO:
+               bcopy(lp, data, sizeof (struct disklabel));
+               break;
+
+       case DIOCGPART:
+               ((struct partinfo *)data)->disklab = lp;
+               ((struct partinfo *)data)->part =
+                   &lp->d_partitions[rapart(dev)];
+               break;
+
+       case DIOCSDINFO:
+               if ((flag & FWRITE) == 0)
+                       error = EBADF;
+               else
+                       error = setdisklabel(lp, (struct disklabel *)data,0,0);
+               break;
+
+       case DIOCWLABEL:
+               if ((flag & FWRITE) == 0)
+                       error = EBADF;
+               else
+                       ra->ra_wlabel = 1;
+               break;
+
+       case DIOCWDINFO:
+               if ((flag & FWRITE) == 0)
+                       error = EBADF;
+               else {
+                       ra->ra_wlabel = 1;
+                       error = writedisklabel(dev, rastrategy, lp,0);
+                       ra->ra_wlabel = 0;
+               }
+               break;
+
+       default:
+               error = ENOTTY;
+               break;
+       }
+       return (error);
+}
+
+#if 0
+/*
+ * Do a panic dump.  We set up the controller for one command packet
+ * and one response packet, for which we use `struct uda1'.
+ */
+struct uda1 {
+       struct  uda1ca uda1_ca; /* communications area */
+       struct  mscp uda1_rsp;  /* response packet */
+       struct  mscp uda1_cmd;  /* command packet */
+} uda1;
+#endif
+
+#define        DBSIZE  32              /* dump 16K at a time */
+
+int
+radump(dev, blkno, va, size)
+       dev_t   dev;
+       daddr_t blkno;
+       caddr_t va;
+       size_t  size;
+{
+#if 0
+       struct udadevice *udaddr;
+       struct uda1 *ud_ubaddr;
+       char *start;
+       int num, blk, unit, maxsz, blkoff, reg;
+       struct partition *pp;
+       struct uba_regs *uba;
+       struct uba_device *ui;
+       struct uda1 *ud;
+       struct pte *io;
+       int i;
+
+       /*
+        * Make sure the device is a reasonable place on which to dump.
+        */
+       unit = udaunit(dev);
+       if (unit >= NRA)
+               return (ENXIO);
+#define        phys(cast, addr)        ((cast) ((int)addr & 0x7fffffff))
+       ui = phys(struct uba_device *, udadinfo[unit]);
+       if (ui == NULL || ui->ui_alive == 0)
+               return (ENXIO);
+
+       /*
+        * Find and initialise the UBA; get the physical address of the
+        * device registers, and of communications area and command and
+        * response packet.
+        */
+       uba = phys(struct uba_softc *, ui->ui_hd)->uh_physuba;
+       ubainit(ui->ui_hd);
+       udaddr = (struct udadevice *)ui->ui_physaddr;
+       ud = phys(struct uda1 *, &uda1);
+       /*
+        * Map the ca+packets into Unibus I/O space so the UDA50 can get
+        * at them.  Use the registers at the end of the Unibus map (since
+        * we will use the registers at the beginning to map the memory
+        * we are dumping).
+        */
+       num = btoc(sizeof(struct uda1)) + 1;
+       reg = NUBMREG - num;
+       io = (void *)&uba->uba_map[reg];
+       for (i = 0; i < num; i++)
+               *(int *)io++ = UBAMR_MRV | (btop(ud) + i);
+       ud_ubaddr = (struct uda1 *)(((int)ud & PGOFSET) | (reg << 9));
+
+       /*
+        * Initialise the controller, with one command and one response
+        * packet.
+        */
+       udaddr->udaip = 0;
+       if (udadumpwait(udaddr, UDA_STEP1))
+               return (EFAULT);
+       udaddr->udasa = UDA_ERR;
+       if (udadumpwait(udaddr, UDA_STEP2))
+               return (EFAULT);
+       udaddr->udasa = (int)&ud_ubaddr->uda1_ca.ca_rspdsc;
+       if (udadumpwait(udaddr, UDA_STEP3))
+               return (EFAULT);
+       udaddr->udasa = ((int)&ud_ubaddr->uda1_ca.ca_rspdsc) >> 16;
+       if (udadumpwait(udaddr, UDA_STEP4))
+               return (EFAULT);
+       ((struct uda_softc *)uda_cd.cd_devs[ui->ui_ctlr])->sc_micro = udaddr->udasa & 0xff;
+       udaddr->udasa = UDA_GO;
+
+       /*
+        * Set up the command and response descriptor, then set the
+        * controller characteristics and bring the drive on line.
+        * Note that all uninitialised locations in uda1_cmd are zero.
+        */
+       ud->uda1_ca.ca_rspdsc = (long)&ud_ubaddr->uda1_rsp.mscp_cmdref;
+       ud->uda1_ca.ca_cmddsc = (long)&ud_ubaddr->uda1_cmd.mscp_cmdref;
+       /* ud->uda1_cmd.mscp_sccc.sccc_ctlrflags = 0; */
+       /* ud->uda1_cmd.mscp_sccc.sccc_version = 0; */
+       if (udadumpcmd(M_OP_SETCTLRC, ud, ui))
+               return (EFAULT);
+       ud->uda1_cmd.mscp_unit = ui->ui_slave;
+       if (udadumpcmd(M_OP_ONLINE, ud, ui))
+               return (EFAULT);
+
+       pp = phys(struct partition *,
+           &udalabel[unit].d_partitions[udapart(dev)]);
+       maxsz = pp->p_size;
+       blkoff = pp->p_offset;
+
+       /*
+        * Dump all of physical memory, or as much as will fit in the
+        * space provided.
+        */
+       start = 0;
+       printf("Dumpar {r inte implementerade {n :) \n");
+       asm("halt");
+/*     num = maxfree; */
+       if (dumplo + num >= maxsz)
+               num = maxsz - dumplo;
+       blkoff += dumplo;
+
+       /*
+        * Write out memory, DBSIZE pages at a time.
+        * N.B.: this code depends on the fact that the sector
+        * size == the page size.
+        */
+       while (num > 0) {
+               blk = num > DBSIZE ? DBSIZE : num;
+               io = (void *)uba->uba_map;
+               /*
+                * Map in the pages to write, leaving an invalid entry
+                * at the end to guard against wild Unibus transfers.
+                * Then do the write.
+                */
+               for (i = 0; i < blk; i++)
+                       *(int *)io++ = UBAMR_MRV | (btop(start) + i);
+               *(int *)io = 0;
+               ud->uda1_cmd.mscp_unit = ui->ui_slave;
+               ud->uda1_cmd.mscp_seq.seq_lbn = btop(start) + blkoff;
+               ud->uda1_cmd.mscp_seq.seq_bytecount = blk << PGSHIFT;
+               if (udadumpcmd(M_OP_WRITE, ud, ui))
+                       return (EIO);
+               start += blk << PGSHIFT;
+               num -= blk;
+       }
+       return (0);             /* made it! */
+}
+
+/*
+ * Wait for some of the bits in `bits' to come on.  If the error bit
+ * comes on, or ten seconds pass without response, return true (error).
+ */
+int
+udadumpwait(udaddr, bits)
+       struct udadevice *udaddr;
+       register int bits;
+{
+       register int timo = todr() + 1000;
+
+       while ((udaddr->udasa & bits) == 0) {
+               if (udaddr->udasa & UDA_ERR) {
+                       char bits[64];
+                       printf("udasa=%s\ndump ",
+                           bitmask_snprintf(udaddr->udasa, udasr_bits,
+                           bits, sizeof(bits)));
+                       return (1);
+               }
+               if (todr() >= timo) {
+                       printf("timeout\ndump ");
+                       return (1);
+               }
+       }
+       return (0);
+}
+
+/*
+ * Feed a command to the UDA50, wait for its response, and return
+ * true iff something went wrong.
+ */
+int
+udadumpcmd(op, ud, ui)
+       int op;
+       struct uda1 *ud;
+       struct uba_device *ui;
+{
+       volatile struct udadevice *udaddr;
+       volatile int n;
+#define mp (&ud->uda1_rsp)
+
+       udaddr = (struct udadevice *)ui->ui_physaddr;
+       ud->uda1_cmd.mscp_opcode = op;
+       ud->uda1_cmd.mscp_msglen = MSCP_MSGLEN;
+       ud->uda1_rsp.mscp_msglen = MSCP_MSGLEN;
+       ud->uda1_ca.ca_rspdsc |= MSCP_OWN | MSCP_INT;
+       ud->uda1_ca.ca_cmddsc |= MSCP_OWN | MSCP_INT;
+       if (udaddr->udasa & UDA_ERR) {
+               char bits[64];
+               printf("udasa=%s\ndump ", bitmask_snprintf(udaddr->udasa,
+                   udasr_bits, bits, sizeof(bits)));
+               return (1);
+       }
+       n = udaddr->udaip;
+       n = todr() + 1000;
+       for (;;) {
+               if (todr() > n) {
+                       printf("timeout\ndump ");
+                       return (1);
+               }
+               if (ud->uda1_ca.ca_cmdint)
+                       ud->uda1_ca.ca_cmdint = 0;
+               if (ud->uda1_ca.ca_rspint == 0)
+                       continue;
+               ud->uda1_ca.ca_rspint = 0;
+               if (mp->mscp_opcode == (op | M_OP_END))
+                       break;
+               printf("\n");
+               switch (MSCP_MSGTYPE(mp->mscp_msgtc)) {
+
+               case MSCPT_SEQ:
+                       printf("sequential");
+                       break;
+
+               case MSCPT_DATAGRAM:
+                       mscp_decodeerror("uda", ui->ui_ctlr, mp);
+                       printf("datagram");
+                       break;
+
+               case MSCPT_CREDITS:
+                       printf("credits");
+                       break;
+
+               case MSCPT_MAINTENANCE:
+                       printf("maintenance");
+                       break;
+
+               default:
+                       printf("unknown (type 0x%x)",
+                               MSCP_MSGTYPE(mp->mscp_msgtc));
+                       break;
+               }
+               printf(" ignored\ndump ");
+               ud->uda1_ca.ca_rspdsc |= MSCP_OWN | MSCP_INT;
+       }
+       if ((mp->mscp_status & M_ST_MASK) != M_ST_SUCCESS) {
+               printf("error: op 0x%x => 0x%x status 0x%x\ndump ", op,
+                       mp->mscp_opcode, mp->mscp_status);
+               return (1);
+       }
+#endif
+       return (0);
+#undef mp
+}
+
+/*
+ * Return the size of a partition, if known, or -1 if not.
+ */
+int
+rasize(dev)
+       dev_t dev;
+{
+       register int unit = raunit(dev);
+       struct ra_softc *ra;
+
+       if (unit >= ra_cd.cd_ndevs || ra_cd.cd_devs[unit] == 0)
+               return -1;
+
+       ra = ra_cd.cd_devs[unit];
+
+       if (ra->ra_state == RA_OFFLINE)
+               if (ra_putonline(ra) == MSCP_FAILED)
+                        return -1;
+
+       return ra->ra_disk.dk_label->d_partitions[rapart(dev)].p_size;
+}
+
+int
+ra_getdev(adaptor, controller, unit, uname)
+       int adaptor, controller, unit;
+       char **uname;
+{
+       struct mscp_softc *mi;
+       struct ra_softc *ra;
+       int i;
+
+       for (i = 0; i < ra_cd.cd_ndevs; i++) {
+               if ((ra = ra_cd.cd_devs[i]) == 0)
+                       continue;
+
+               mi = (void *)ra->ra_dev.dv_parent;
+               if (mi->mi_ctlrnr == controller && mi->mi_adapnr == adaptor &&
+                   ra->ra_hwunit == unit) {
+                       *uname = ra->ra_dev.dv_xname;
+                       return i;
+               }
+       }
+       return -1;
+}
diff --git a/sys/arch/vax/mscp/mscp_subr.c b/sys/arch/vax/mscp/mscp_subr.c
new file mode 100644 (file)
index 0000000..8634a33
--- /dev/null
@@ -0,0 +1,836 @@
+/*     $NetBSD: mscp_subr.c,v 1.6 1997/01/11 11:20:34 ragge Exp $      */
+/*
+ * Copyright (c) 1996 Ludd, University of Lule}, Sweden.
+ * Copyright (c) 1988 Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * 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.
+ *
+ *     @(#)mscp.c      7.5 (Berkeley) 12/16/90
+ */
+
+/*
+ * MSCP generic driver routines
+ */
+
+#include <sys/param.h>
+#include <sys/device.h>
+#include <sys/buf.h>
+#include <sys/systm.h>
+#include <sys/proc.h>
+
+#include <machine/sid.h>
+
+#include <vax/mscp/mscp.h>
+#include <vax/mscp/mscpreg.h>
+#include <vax/mscp/mscpvar.h>
+
+#include "ra.h"
+#include "mt.h"
+
+#define        b_forw  b_hash.le_next
+
+int    mscp_match __P((struct device *, void *, void *));
+void   mscp_attach __P((struct device *, struct device *, void *));
+void    mscp_start __P((struct  mscp_softc *));
+int    mscp_init __P((struct  mscp_softc *));
+void   mscp_initds __P((struct mscp_softc *));
+int    mscp_waitstep __P((struct mscp_softc *, int, int));
+
+struct cfattach mscpbus_ca = {
+       sizeof(struct mscp_softc), mscp_match, mscp_attach
+};
+
+struct cfdriver mscpbus_cd = {
+       NULL, "mscpbus", DV_DULL
+};
+
+struct mscp slavereply;
+
+/*
+ * This function is for delay during init. Some MSCP clone card (Dilog)
+ * can't handle fast read from its registers, and therefore need
+ * a delay between them.
+ */
+
+#define DELAYTEN 1000
+int
+mscp_waitstep(mi, mask, result)
+       struct mscp_softc *mi;
+       int mask, result;
+{
+       int     status = 1;
+
+       if ((*mi->mi_sa & mask) != result) {
+               volatile int count = 0;
+               while ((*mi->mi_sa & mask) != result) {
+                       DELAY(10000);
+                       count += 1;
+                       if (count > DELAYTEN)
+                               break;
+               }
+               if (count > DELAYTEN)
+                       status = 0;
+       }
+       return status;
+}
+
+int
+mscp_match(parent, match, aux)
+       struct device *parent;
+       void *match, *aux;
+{
+       struct  mscp_attach_args *ma = aux;
+
+#if NRA
+       if (ma->ma_type & MSCPBUS_DISK)
+               return 1;
+#endif
+#if NMT
+       if (ma->ma_type & MSCPBUS_TAPE)
+               return 1;
+#endif
+       return 0;
+};
+
+void
+mscp_attach(parent, self, aux)
+       struct device *parent, *self;
+       void *aux;
+{
+       struct  mscp_attach_args *ma = aux;
+       struct  mscp_softc *mi = (void *)self;
+       volatile struct mscp *mp;
+       volatile int i;
+       int     timeout, next = 0;
+
+       mi->mi_mc = ma->ma_mc;
+       mi->mi_me = NULL;
+       mi->mi_type = ma->ma_type;
+       mi->mi_uuda = ma->ma_uuda;
+       mi->mi_uda = ma->ma_uda;
+       mi->mi_ip = ma->ma_ip;
+       mi->mi_sa = ma->ma_sa;
+       mi->mi_sw = ma->ma_sw;
+       mi->mi_ivec = ma->ma_ivec;
+       mi->mi_adapnr = ma->ma_adapnr;
+       mi->mi_ctlrnr = ma->ma_ctlrnr;
+       *ma->ma_softc = mi;
+       /*
+        * Go out to init the bus, so that we can give commands
+        * to its devices.
+        */
+        mi->mi_cmd.mri_size = NCMD;
+        mi->mi_cmd.mri_desc = mi->mi_uda->mp_ca.ca_cmddsc;
+        mi->mi_cmd.mri_ring = mi->mi_uda->mp_cmd;
+        mi->mi_rsp.mri_size = NRSP;
+        mi->mi_rsp.mri_desc = mi->mi_uda->mp_ca.ca_rspdsc;
+        mi->mi_rsp.mri_ring = mi->mi_uda->mp_rsp;
+       mi->mi_actf = (void *)&mi->mi_actf; /* Circular wait queue */
+       mi->mi_actb = (void *)&mi->mi_actf;
+
+       if (mscp_init(mi)) {
+               printf("%s: can't init, controller hung\n",
+                   mi->mi_dev.dv_xname);
+               return;
+       }
+
+#if NRA
+       if (ma->ma_type & MSCPBUS_DISK) {
+               extern  struct mscp_device ra_device;
+
+               mi->mi_me = &ra_device;
+       }
+#endif
+#if NMT
+       if (ma->ma_type & MSCPBUS_TAPE) {
+               extern  struct mscp_device mt_device;
+
+               mi->mi_me = &mt_device;
+       }
+#endif
+       /*
+        * Go out and search for sub-units on this MSCP bus,
+        * and call config_found for each found.
+        */
+findunit:
+       mp = mscp_getcp(mi, MSCP_DONTWAIT);
+       if (mp == NULL)
+               panic("mscpattach: no packets");
+       mp->mscp_opcode = M_OP_GETUNITST;
+       mp->mscp_unit = next;
+       mp->mscp_modifier = M_GUM_NEXTUNIT;
+       *mp->mscp_addr |= MSCP_OWN | MSCP_INT;
+       slavereply.mscp_opcode = 0;
+
+       i = *mi->mi_ip;  /* Kick off polling */
+       mp = &slavereply;
+       timeout = 1000;
+       while (timeout-- > 0) {
+               DELAY(10000);
+               if (mp->mscp_opcode)
+                       goto gotit;
+       }
+       printf("%s: no response to Get Unit Status request\n",
+           mi->mi_dev.dv_xname);
+       return;
+
+gotit: /*
+        * Got a slave response.  If the unit is there, use it.
+        */
+       switch (mp->mscp_status & M_ST_MASK) {
+
+       case M_ST_SUCCESS:      /* worked */
+       case M_ST_AVAILABLE:    /* found another drive */
+               break;          /* use it */
+
+       case M_ST_OFFLINE:
+               /*
+                * Figure out why it is off line.  It may be because
+                 * it is nonexistent, or because it is spun down, or
+                 * for some other reason.
+                 */
+                switch (mp->mscp_status & ~M_ST_MASK) {
+
+                case M_OFFLINE_UNKNOWN:
+                        /*
+                         * No such drive, and there are none with
+                         * higher unit numbers either, if we are
+                         * using M_GUM_NEXTUNIT.
+                         */
+                       mi->mi_ierr = 3;
+                        return;
+
+                case M_OFFLINE_UNMOUNTED:
+                        /*
+                         * The drive is not spun up.  Use it anyway.
+                         *
+                         * N.B.: this seems to be a common occurrance
+                         * after a power failure.  The first attempt
+                         * to bring it on line seems to spin it up
+                         * (and thus takes several minutes).  Perhaps
+                         * we should note here that the on-line may
+                         * take longer than usual.
+                         */
+                        break;
+
+                default:
+                        /*
+                         * In service, or something else equally unusable.
+                         */
+                        printf("%s: unit %d off line: ", mi->mi_dev.dv_xname,
+                                mp->mscp_unit);
+                        mscp_printevent((struct mscp *)mp);
+                       next++;
+                        goto findunit;
+                }
+                break;
+
+        default:
+                printf("%s: unable to get unit status: ", mi->mi_dev.dv_xname);
+                mscp_printevent((struct mscp *)mp);
+                return;
+        }
+
+        /*
+         * If we get a lower number, we have circulated around all
+        * devices and are finished, otherwise try to find next unit.
+        * We shouldn't ever get this, it's a workaround.
+         */
+        if (mp->mscp_unit < next)
+                return;
+
+       next = mp->mscp_unit + 1;
+       goto findunit;
+}
+
+
+/*
+ * The ctlr gets initialised, normally after boot but may also be 
+ * done if the ctlr gets in an unknown state. Returns 1 if init
+ * fails, 0 otherwise.
+ */
+int
+mscp_init(mi)
+       struct  mscp_softc *mi;
+{
+       struct  mscp *mp;
+       volatile int i;
+       int     status, count;
+       unsigned int j = 0;
+
+        /*
+         * While we are thinking about it, reset the next command
+         * and response indicies.
+         */
+       mi->mi_cmd.mri_next = 0;
+       mi->mi_rsp.mri_next = 0;
+
+       mi->mi_flags |= MSC_IGNOREINTR;
+
+       if ((mi->mi_type & MSCPBUS_KDB) == 0)
+               *mi->mi_ip = 0; /* Kick off */
+
+       status = mscp_waitstep(mi, MP_STEP1, MP_STEP1);/* Wait to it wakes up */
+       if (status == 0)
+               return 1; /* Init failed */
+       if (*mi->mi_sa & MP_ERR) {
+               (*mi->mi_mc->mc_saerror)(mi->mi_dev.dv_parent, 0);
+               return 1;
+       }
+
+       /* step1 */
+       *mi->mi_sw = MP_ERR | (NCMDL2 << 11) | (NRSPL2 << 8) |
+           MP_IE | (mi->mi_ivec >> 2);
+       status = mscp_waitstep(mi, STEP1MASK, STEP1GOOD);
+       if (status == 0) {
+               (*mi->mi_mc->mc_saerror)(mi->mi_dev.dv_parent, 0);
+               return 1;
+       }
+
+       /* step2 */
+       *mi->mi_sw = (int)&mi->mi_uuda->mp_ca.ca_rspdsc[0] | 
+           (vax_cputype == VAX_780 || vax_cputype == VAX_8600 ? MP_PI : 0);
+       status = mscp_waitstep(mi, STEP2MASK, STEP2GOOD(mi->mi_ivec >> 2));
+        if (status == 0) {
+                (*mi->mi_mc->mc_saerror)(mi->mi_dev.dv_parent, 0);
+                return 1;
+        }
+
+       /* step3 */
+       *mi->mi_sw = ((int)&mi->mi_uuda->mp_ca.ca_rspdsc[0]) >> 16;
+       status = mscp_waitstep(mi, STEP3MASK, STEP3GOOD);
+        if (status == 0) { 
+                (*mi->mi_mc->mc_saerror)(mi->mi_dev.dv_parent, 0);
+                return 1;
+        }
+       i = *mi->mi_sa & 0377;
+       printf(": version %d model %d\n", i & 15, i >> 4);
+
+#define        BURST 4 /* XXX */
+       if (mi->mi_type & MSCPBUS_UDA) {
+               *mi->mi_sw = MP_GO | (BURST - 1) << 2;
+               printf("%s: DMA burst size set to %d\n", 
+                   mi->mi_dev.dv_xname, BURST);
+       }
+       *mi->mi_sw = MP_GO;
+
+       mscp_initds(mi);
+       mi->mi_flags &= ~MSC_IGNOREINTR;
+
+       /*
+        * Set up all necessary info in the bus softc struct, get a
+        * mscp packet and set characteristics for this controller.
+        */
+       mi->mi_credits = MSCP_MINCREDITS + 1;
+       mp = mscp_getcp(mi, MSCP_DONTWAIT);
+
+       mi->mi_credits = 0;
+       mp->mscp_opcode = M_OP_SETCTLRC;
+       mp->mscp_unit = mp->mscp_modifier = mp->mscp_flags =
+           mp->mscp_sccc.sccc_version = mp->mscp_sccc.sccc_hosttimo = 
+           mp->mscp_sccc.sccc_time = mp->mscp_sccc.sccc_time1 =
+           mp->mscp_sccc.sccc_errlgfl = 0;
+       mp->mscp_sccc.sccc_ctlrflags = M_CF_ATTN | M_CF_MISC | M_CF_THIS;
+       *mp->mscp_addr |= MSCP_OWN | MSCP_INT;
+       i = *mi->mi_ip;
+
+        count = 0;
+        while (count < DELAYTEN) {
+                if (((volatile)mi->mi_flags & MSC_READY) != 0)
+                        break;
+               if ((j = *mi->mi_sa) & MP_ERR)
+                       goto out;
+                DELAY(10000);
+                count += 1;
+        }
+       if (count == DELAYTEN) {
+out:
+               printf("%s: couldn't set ctlr characteristics, sa=%x\n", 
+                   mi->mi_dev.dv_xname, j);
+               return 1;
+       }
+       return 0;
+}
+
+/*
+ * Initialise the various data structures that control the mscp protocol.
+ */
+void
+mscp_initds(mi)
+       struct mscp_softc *mi;
+{
+       struct mscp_pack *uud = mi->mi_uuda;
+       struct mscp_pack *ud = mi->mi_uda;
+       struct mscp *mp;
+       int i;
+
+       for (i = 0, mp = ud->mp_rsp; i < NRSP; i++, mp++) {
+               ud->mp_ca.ca_rspdsc[i] = MSCP_OWN | MSCP_INT |
+                   (long)&uud->mp_rsp[i].mscp_cmdref;
+               mp->mscp_addr = &ud->mp_ca.ca_rspdsc[i];
+               mp->mscp_msglen = MSCP_MSGLEN;
+       }
+       for (i = 0, mp = ud->mp_cmd; i < NCMD; i++, mp++) {
+               ud->mp_ca.ca_cmddsc[i] = MSCP_INT |
+                   (long)&uud->mp_cmd[i].mscp_cmdref;
+               mp->mscp_addr = &ud->mp_ca.ca_cmddsc[i];
+               mp->mscp_msglen = MSCP_MSGLEN;
+               if (mi->mi_type & MSCPBUS_TAPE)
+                       mp->mscp_vcid = 1;
+       }
+}
+
+void
+mscp_intr(mi)
+       struct mscp_softc *mi;
+{
+       struct mscp_pack *ud = mi->mi_uda;
+
+       if (mi->mi_flags & MSC_IGNOREINTR)
+               return;
+        /*
+         * Check for response and command ring transitions.
+         */
+        if (ud->mp_ca.ca_rspint) {
+                ud->mp_ca.ca_rspint = 0;
+                mscp_dorsp(mi);
+        }
+        if (ud->mp_ca.ca_cmdint) {
+                ud->mp_ca.ca_cmdint = 0;
+                MSCP_DOCMD(mi);
+        }
+
+       /*
+        * If there are any not-yet-handled requeset, try them now.
+        * XXX - We handles them (erroneous) in last-in first-handled order.
+        * Must we fix this???
+        */
+       while (mi->mi_w) {
+               struct buf *bp = mi->mi_w;
+
+               mi->mi_w = (void *)bp->b_actb;
+               mscp_strategy(bp, (struct device *)mi);
+               if (mi->mi_w == bp)
+                       break;
+       }
+}
+
+int
+mscp_print(aux, name)
+       void *aux;
+       const char *name;
+{
+       return UNCONF;
+}
+
+/*
+ * common strategy routine for all types of MSCP devices.
+ * bp is the current buf, dp is the drive queue.
+ */
+void
+mscp_strategy(bp, usc)
+       struct buf *bp;
+       struct device *usc;
+{
+       struct  mscp_softc *mi = (void *)usc;
+       struct  mscp *mp;
+       int s = spl6();
+
+       /*
+        * Ok; we are ready to try to start a xfer. Get a MSCP packet
+        * and try to start...
+        */
+       if ((mp = mscp_getcp(mi, MSCP_DONTWAIT)) == NULL) {
+               if (mi->mi_credits > MSCP_MINCREDITS)
+                       printf("%s: command ring too small\n",
+                           mi->mi_dev.dv_parent->dv_xname);
+               /*
+                * By some (strange) reason we didn't get a MSCP packet.
+                * Put it on queue and wait for free packets.
+                */
+               (void *)bp->b_actb = mi->mi_w;
+               mi->mi_w = bp;
+               splx(s);
+               return;
+       }
+
+       /*
+        * Set up the MSCP packet and ask the ctlr to start.
+        */
+       mp->mscp_opcode = (bp->b_flags & B_READ) ? M_OP_READ : M_OP_WRITE;
+       (*mi->mi_me->me_fillin)(bp, mp);
+       (void *)bp->b_actb = mp; /* b_actb is unused, save mscp packet here */
+       (*mi->mi_mc->mc_go)(mi->mi_dev.dv_parent, bp);
+       splx(s);
+}
+
+void
+mscp_dgo(mi, buffer, info, bp)
+       struct mscp_softc *mi;
+       long buffer, info;
+       struct buf *bp;
+{
+       volatile int i;
+       struct  mscp *mp;
+
+        /*
+         * Fill in the MSCP packet and move the buffer to the I/O wait queue.
+         */
+       mp = (void *)bp->b_actb;
+
+       mp->mscp_seq.seq_buffer = buffer;
+
+       _insque(&bp->b_actf, &mi->mi_actf);
+
+       bp->b_resid = info;
+       mp->mscp_cmdref = (long) bp;
+       *mp->mscp_addr |= MSCP_OWN | MSCP_INT;
+
+       i = *mi->mi_ip;
+}
+
+#ifdef DIAGNOSTIC
+/*
+ * Dump the entire contents of an MSCP packet in hex.  Mainly useful
+ * for debugging....
+ */
+void
+mscp_hexdump(mp)
+       register struct mscp *mp;
+{
+       register long *p = (long *) mp;
+       register int i = mp->mscp_msglen;
+
+       if (i > 256)            /* sanity */
+               i = 256;
+       i /= sizeof (*p);       /* ASSUMES MULTIPLE OF sizeof(long) */
+       while (--i >= 0)
+               printf("0x%x ", (int)*p++);
+       printf("\n");
+}
+#endif
+
+/*
+ * MSCP error reporting
+ */
+
+/*
+ * Messages for the various subcodes.
+ */
+static char unknown_msg[] = "unknown subcode";
+
+/*
+ * Subcodes for Success (0)
+ */
+static char *succ_msgs[] = {
+       "normal",               /* 0 */
+       "spin down ignored",    /* 1 = Spin-Down Ignored */
+       "still connected",      /* 2 = Still Connected */
+       unknown_msg,
+       "dup. unit #",          /* 4 = Duplicate Unit Number */
+       unknown_msg,
+       unknown_msg,
+       unknown_msg,
+       "already online",       /* 8 = Already Online */
+       unknown_msg,
+       unknown_msg,
+       unknown_msg,
+       unknown_msg,
+       unknown_msg,
+       unknown_msg,
+       unknown_msg,
+       "still online",         /* 16 = Still Online */
+};
+
+/*
+ * Subcodes for Invalid Command (1)
+ */
+static char *icmd_msgs[] = {
+       "invalid msg length",   /* 0 = Invalid Message Length */
+};
+
+/*
+ * Subcodes for Command Aborted (2)
+ */
+/* none known */
+
+/*
+ * Subcodes for Unit Offline (3)
+ */
+static char *offl_msgs[] = {
+       "unknown drive",        /* 0 = Unknown, or online to other ctlr */
+       "not mounted",          /* 1 = Unmounted, or RUN/STOP at STOP */
+       "inoperative",          /* 2 = Unit Inoperative */
+       unknown_msg,
+       "duplicate",            /* 4 = Duplicate Unit Number */
+       unknown_msg,
+       unknown_msg,
+       unknown_msg,
+       "in diagnosis",         /* 8 = Disabled by FS or diagnostic */
+};
+
+/*
+ * Subcodes for Unit Available (4)
+ */
+/* none known */
+
+/*
+ * Subcodes for Media Format Error (5)
+ */
+static char *media_fmt_msgs[] = {
+       "fct unread - edc",     /* 0 = FCT unreadable */
+       "invalid sector header",/* 1 = Invalid Sector Header */
+       "not 512 sectors",      /* 2 = Not 512 Byte Sectors */
+       "not formatted",        /* 3 = Not Formatted */
+       "fct ecc",              /* 4 = FCT ECC */
+};
+
+/*
+ * Subcodes for Write Protected (6)
+ * N.B.:  Code 6 subcodes are 7 bits higher than other subcodes
+ * (i.e., bits 12-15).
+ */
+static char *wrprot_msgs[] = {
+       unknown_msg,
+       "software",             /* 1 = Software Write Protect */
+       "hardware",             /* 2 = Hardware Write Protect */
+};
+
+/*
+ * Subcodes for Compare Error (7)
+ */
+/* none known */
+
+/*
+ * Subcodes for Data Error (8)
+ */
+static char *data_msgs[] = {
+       "forced error",         /* 0 = Forced Error (software) */
+       unknown_msg,
+       "header compare",       /* 2 = Header Compare Error */
+       "sync timeout",         /* 3 = Sync Timeout Error */
+       unknown_msg,
+       unknown_msg,
+       unknown_msg,
+       "uncorrectable ecc",    /* 7 = Uncorrectable ECC */
+       "1 symbol ecc",         /* 8 = 1 bit ECC */
+       "2 symbol ecc",         /* 9 = 2 bit ECC */
+       "3 symbol ecc",         /* 10 = 3 bit ECC */
+       "4 symbol ecc",         /* 11 = 4 bit ECC */
+       "5 symbol ecc",         /* 12 = 5 bit ECC */
+       "6 symbol ecc",         /* 13 = 6 bit ECC */
+       "7 symbol ecc",         /* 14 = 7 bit ECC */
+       "8 symbol ecc",         /* 15 = 8 bit ECC */
+};
+
+/*
+ * Subcodes for Host Buffer Access Error (9)
+ */
+static char *host_buffer_msgs[] = {
+       unknown_msg,
+       "odd xfer addr",        /* 1 = Odd Transfer Address */
+       "odd xfer count",       /* 2 = Odd Transfer Count */
+       "non-exist. memory",    /* 3 = Non-Existent Memory */
+       "memory parity",        /* 4 = Memory Parity Error */
+};
+
+/*
+ * Subcodes for Controller Error (10)
+ */
+static char *cntlr_msgs[] = {
+       unknown_msg,
+       "serdes overrun",       /* 1 = Serialiser/Deserialiser Overrun */
+       "edc",                  /* 2 = Error Detection Code? */
+       "inconsistant internal data struct",/* 3 = Internal Error */
+};
+
+/*
+ * Subcodes for Drive Error (11)
+ */
+static char *drive_msgs[] = {
+       unknown_msg,
+       "sdi command timeout",  /* 1 = SDI Command Timeout */
+       "ctlr detected protocol",/* 2 = Controller Detected Protocol Error */
+       "positioner",           /* 3 = Positioner Error */
+       "lost rd/wr ready",     /* 4 = Lost R/W Ready Error */
+       "drive clock dropout",  /* 5 = Lost Drive Clock */
+       "lost recvr ready",     /* 6 = Lost Receiver Ready */
+       "drive detected error", /* 7 = Drive Error */
+       "ctlr detected pulse or parity",/* 8 = Pulse or Parity Error */
+};
+
+/*
+ * The following table correlates message codes with the
+ * decoding strings.
+ */
+struct code_decode {
+       char    *cdc_msg;
+       int     cdc_nsubcodes;
+       char    **cdc_submsgs;
+} code_decode[] = {
+#define        SC(m)   sizeof (m) / sizeof (m[0]), m
+       {"success",                     SC(succ_msgs)},
+       {"invalid command",             SC(icmd_msgs)},
+       {"command aborted",             0, 0},
+       {"unit offline",                SC(offl_msgs)},
+       {"unit available",              0, 0},
+       {"media format error",          SC(media_fmt_msgs)},
+       {"write protected",             SC(wrprot_msgs)},
+       {"compare error",               0, 0},
+       {"data error",                  SC(data_msgs)},
+       {"host buffer access error",    SC(host_buffer_msgs)},
+       {"controller error",            SC(cntlr_msgs)},
+       {"drive error",                 SC(drive_msgs)},
+#undef SC
+};
+
+/*
+ * Print the decoded error event from an MSCP error datagram.
+ */
+void
+mscp_printevent(mp)
+       struct mscp *mp;
+{
+       register int event = mp->mscp_event;
+       register struct code_decode *cdc;
+       int c, sc;
+       char *cm, *scm;
+
+       /*
+        * The code is the lower six bits of the event number (aka
+        * status).  If that is 6 (write protect), the subcode is in
+        * bits 12-15; otherwise, it is in bits 5-11.
+        * I WONDER WHAT THE OTHER BITS ARE FOR.  IT SURE WOULD BE
+        * NICE IF DEC SOLD DOCUMENTATION FOR THEIR OWN CONTROLLERS.
+        */
+       c = event & M_ST_MASK;
+       sc = (c != 6 ? event >> 5 : event >> 12) & 0x7ff;
+       if (c >= sizeof code_decode / sizeof code_decode[0])
+               cm = "- unknown code", scm = "??";
+       else {
+               cdc = &code_decode[c];
+               cm = cdc->cdc_msg;
+               if (sc >= cdc->cdc_nsubcodes)
+                       scm = unknown_msg;
+               else
+                       scm = cdc->cdc_submsgs[sc];
+       }
+       printf(" %s (%s) (code %d, subcode %d)\n", cm, scm, c, sc);
+}
+
+static char *codemsg[16] = {
+       "lbn", "code 1", "code 2", "code 3",
+       "code 4", "code 5", "rbn", "code 7",
+       "code 8", "code 9", "code 10", "code 11",
+       "code 12", "code 13", "code 14", "code 15"
+};
+/*
+ * Print the code and logical block number for an error packet.
+ * THIS IS PROBABLY PECULIAR TO DISK DRIVES.  IT SURE WOULD BE
+ * NICE IF DEC SOLD DOCUMENTATION FOR THEIR OWN CONTROLLERS.
+ */
+int
+mscp_decodeerror(name, mp, mi)
+       char *name;
+       register struct mscp *mp;
+       struct mscp_softc *mi;
+{
+       int issoft;
+       /* 
+        * We will get three sdi errors of type 11 after autoconfig
+        * is finished; depending of searching for non-existing units.
+        * How can we avoid this???
+        */
+       if (((mp->mscp_event & M_ST_MASK) == 11) && (mi->mi_ierr++ < 3))
+               return 1;
+       /*
+        * For bad blocks, mp->mscp_erd.erd_hdr identifies a code and
+        * the logical block number.  Code 0 is a regular block; code 6
+        * is a replacement block.  The remaining codes are currently
+        * undefined.  The code is in the upper four bits of the header
+        * (bits 0-27 are the lbn).
+        */
+       issoft = mp->mscp_flags & (M_LF_SUCC | M_LF_CONT);
+#define BADCODE(h)     (codemsg[(unsigned)(h) >> 28])
+#define BADLBN(h)      ((h) & 0xfffffff)
+
+       printf("%s: drive %d %s error datagram%s:", name, mp->mscp_unit,
+               issoft ? "soft" : "hard",
+               mp->mscp_flags & M_LF_CONT ? " (continuing)" : "");
+       switch (mp->mscp_format & 0377) {
+
+       case M_FM_CTLRERR:      /* controller error */
+               break;
+
+       case M_FM_BUSADDR:      /* host memory access error */
+               printf(" memory addr 0x%x:", (int)mp->mscp_erd.erd_busaddr);
+               break;
+
+       case M_FM_DISKTRN:
+               printf(" unit %d: level %d retry %d, %s %d:",
+                       mp->mscp_unit,
+                       mp->mscp_erd.erd_level, mp->mscp_erd.erd_retry,
+                       BADCODE(mp->mscp_erd.erd_hdr),
+                       (int)BADLBN(mp->mscp_erd.erd_hdr));
+               break;
+
+       case M_FM_SDI:
+               printf(" unit %d: %s %d:", mp->mscp_unit,
+                       BADCODE(mp->mscp_erd.erd_hdr),
+                       (int)BADLBN(mp->mscp_erd.erd_hdr));
+               break;
+
+       case M_FM_SMLDSK:
+               printf(" unit %d: small disk error, cyl %d:",
+                       mp->mscp_unit, mp->mscp_erd.erd_sdecyl);
+               break;
+
+       case M_FM_TAPETRN:
+               printf(" unit %d: tape transfer error, grp 0x%x event 0%o:",
+                   mp->mscp_unit, mp->mscp_erd.erd_sdecyl, mp->mscp_event);
+               break;
+
+       case M_FM_STIERR:
+               printf(" unit %d: STI error, event 0%o:", mp->mscp_unit,
+                   mp->mscp_event);
+               break;
+
+       default:
+               printf(" unit %d: unknown error, format 0x%x:",
+                       mp->mscp_unit, mp->mscp_format);
+       }
+       mscp_printevent(mp);
+       return 0;
+#undef BADCODE
+#undef BADLBN
+}
diff --git a/sys/arch/vax/mscp/mscp_tape.c b/sys/arch/vax/mscp/mscp_tape.c
new file mode 100644 (file)
index 0000000..85470b5
--- /dev/null
@@ -0,0 +1,535 @@
+/*     $NetBSD: mscp_tape.c,v 1.4 1997/01/11 11:20:35 ragge Exp $ */
+/*
+ * Copyright (c) 1996 Ludd, University of Lule}, Sweden.
+ * 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 at Ludd, University of 
+ *      Lule}, Sweden and its contributors.
+ * 4. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+/*
+ * MSCP tape device driver
+ */
+
+/*
+ * TODO
+ *     Write status handling code.
+ */
+
+#include <sys/param.h>
+#include <sys/device.h>
+#include <sys/kernel.h>
+#include <sys/buf.h>
+#include <sys/ioccom.h>
+#include <sys/mtio.h>
+#include <sys/fcntl.h>
+#include <sys/malloc.h>
+#include <sys/systm.h>
+#include <sys/proc.h>
+
+#include <vax/mscp/mscp.h>
+#include <vax/mscp/mscpvar.h>
+
+/*
+ * Drive status, per drive
+ */
+struct mt_softc {
+       struct  device mt_dev;  /* Autoconf struct */
+       int     mt_state;       /* open/closed state */
+       int     mt_hwunit;      /* Hardware unit number */
+       int     mt_inuse;       /* Locks the tape drive for others */
+       int     mt_waswrite;    /* Last operation was a write op */
+       int     mt_serex;       /* Got serious exception */
+};
+
+#define        MT_OFFLINE      0
+#define        MT_ONLINE       1
+
+int    mtmatch __P((struct device *, void *, void *));
+void   mtattach __P((struct device *, struct device *, void *));
+void   mtdgram __P((struct device *, struct mscp *, struct mscp_softc *));
+void   mtiodone __P((struct device *, struct buf *));
+int    mtonline __P((struct device *, struct mscp *));
+int    mtgotstatus __P((struct device *, struct mscp *));
+int    mtioerror __P((struct device *, struct mscp *, struct buf *));
+void   mtfillin __P((struct buf *, struct mscp *));
+int    mtopen __P((dev_t, int, int, struct proc *));
+int    mtclose __P((dev_t, int, int, struct proc *));
+void   mtstrategy __P((struct buf *));
+int    mtread __P((dev_t, struct uio *));
+int    mtwrite __P((dev_t, struct uio *));
+int    mtioctl __P((dev_t, int, caddr_t, int, struct proc *));
+int    mtdump __P((dev_t, daddr_t, caddr_t, size_t));
+void   mtcmd __P((struct mt_softc *, int));
+void   mtcmddone __P((struct device *, struct mscp *));
+
+struct mscp_device mt_device = {
+       mtdgram,
+       mtiodone,
+       mtonline,
+       mtgotstatus,
+       0,
+       mtioerror,
+       0,
+       mtfillin,
+       mtcmddone,
+};
+
+/* This is not good, should allow more than 4 tapes/device type */
+#define        mtunit(dev)     (minor(dev) & T_UNIT)
+#define        mtnorewind(dev) (dev & T_NOREWIND)
+#define        mthdensity(dev) (dev & T_1600BPI)
+
+struct cfdriver mt_cd = {
+       NULL, "mt", DV_DULL
+};
+
+struct cfattach mt_ca = {
+       sizeof(struct mt_softc), mtmatch, mtattach
+};
+
+/*
+ * More driver definitions, for generic MSCP code.
+ */
+
+int
+mtmatch(parent, match, aux)
+       struct  device *parent;
+       void    *match, *aux;
+{
+       struct  cfdata *cf = match;
+       struct  drive_attach_args *da = aux;
+       struct  mscp *mp = da->da_mp;
+
+       if ((da->da_typ & MSCPBUS_TAPE) == 0)
+               return 0;
+       if (cf->cf_loc[0] != -1 && cf->cf_loc[0] != mp->mscp_unit)
+               return 0;
+       return 1;
+}
+
+/*
+ * The attach routine only checks and prints drive type.
+ */
+void
+mtattach(parent, self, aux)
+       struct  device *parent, *self;
+       void    *aux; 
+{
+       struct  mt_softc *mt = (void *)self;
+       struct  drive_attach_args *da = aux;
+       struct  mscp *mp = da->da_mp;
+       struct  mscp_softc *mi = (void *)parent;
+
+       mt->mt_hwunit = mp->mscp_unit;
+       mi->mi_dp[mp->mscp_unit] = self;
+
+       disk_printtype(mp->mscp_unit, mp->mscp_guse.guse_mediaid);
+}
+
+/* 
+ * (Try to) put the drive online. This is done the first time the
+ * drive is opened, or if it has fallen offline.
+ */
+int
+mt_putonline(mt)
+       struct mt_softc *mt;
+{
+       struct  mscp *mp;
+       struct  mscp_softc *mi = (struct mscp_softc *)mt->mt_dev.dv_parent;
+       volatile int i;
+
+       (volatile)mt->mt_state = MT_OFFLINE;
+       mp = mscp_getcp(mi, MSCP_WAIT);
+       mp->mscp_opcode = M_OP_ONLINE;
+       mp->mscp_unit = mt->mt_hwunit;
+       mp->mscp_cmdref = (long)&mt->mt_state;
+       *mp->mscp_addr |= MSCP_OWN | MSCP_INT;
+
+       /* Poll away */
+       i = *mi->mi_ip;
+       if (tsleep(&mt->mt_state, PRIBIO, "mtonline", 240 * hz))
+               return MSCP_FAILED;
+
+       if ((volatile)mt->mt_state != MT_ONLINE)
+               return MSCP_FAILED;
+
+       return MSCP_DONE;
+}
+/*
+ * Open a drive.
+ */
+/*ARGSUSED*/
+int
+mtopen(dev, flag, fmt, p)
+       dev_t dev;
+       int flag, fmt;
+       struct  proc *p;
+{
+       register struct mt_softc *mt;
+       int unit;
+
+       /*
+        * Make sure this is a reasonable open request.
+        */
+       unit = mtunit(dev);
+       if (unit >= mt_cd.cd_ndevs)
+               return ENXIO;
+       mt = mt_cd.cd_devs[unit];
+       if (mt == 0)
+               return ENXIO;
+
+       if (mt->mt_inuse)
+                       return EBUSY;
+       mt->mt_inuse = 1;
+
+       if (mt_putonline(mt) == MSCP_FAILED)
+               return EIO;
+
+       return 0;
+}
+
+/* ARGSUSED */
+int
+mtclose(dev, flags, fmt, p)
+       dev_t dev;
+       int flags, fmt;
+       struct  proc *p;
+{
+       int unit = mtunit(dev);
+       struct mt_softc *mt = mt_cd.cd_devs[unit];
+
+       /*
+        * If we just have finished a writing, write EOT marks.
+        */
+       if ((flags & FWRITE) && mt->mt_waswrite) {
+               mtcmd(mt, MTWEOF);
+               mtcmd(mt, MTWEOF);
+               mtcmd(mt, MTBSR);
+       }
+       if (mtnorewind(dev) == 0)
+               mtcmd(mt, MTREW);
+       if (mt->mt_serex)
+               mtcmd(mt, -1);
+
+       mt->mt_inuse = 0; /* Release the tape */
+       return 0;
+}
+
+void
+mtstrategy(bp)
+       register struct buf *bp;
+{
+       register int unit;
+       register struct mt_softc *mt;
+
+       /*
+        * Make sure this is a reasonable drive to use.
+        */
+       unit = mtunit(bp->b_dev);
+       if (unit > mt_cd.cd_ndevs || (mt = mt_cd.cd_devs[unit]) == NULL) {
+               bp->b_error = ENXIO;
+               goto bad;
+       }
+
+       mscp_strategy(bp, mt->mt_dev.dv_parent);
+       return;
+
+bad:
+       bp->b_flags |= B_ERROR;
+       biodone(bp);
+}
+
+int
+mtread(dev, uio)
+        dev_t dev;
+        struct uio *uio;
+{
+
+        return (physio(mtstrategy, NULL, dev, B_READ, minphys, uio));
+}
+
+int
+mtwrite(dev, uio)
+        dev_t dev;
+        struct uio *uio;
+{
+
+        return (physio(mtstrategy, NULL, dev, B_WRITE, minphys, uio));
+}
+
+void
+mtiodone(usc, bp)
+       struct device *usc;
+       struct buf *bp;
+{
+
+       biodone(bp);
+}
+
+/*
+ * Fill in drive addresses in a mscp packet waiting for transfer.
+ */
+void
+mtfillin(bp, mp)
+       struct buf *bp;
+       struct mscp *mp;
+{
+       int unit = mtunit(bp->b_dev);
+       struct mt_softc *mt = mt_cd.cd_devs[unit];
+
+       mp->mscp_unit = mt->mt_hwunit;
+       if (mt->mt_serex == 2) {
+               mp->mscp_modifier = M_MD_CLSEX;
+               mt->mt_serex = 0;
+       } else
+               mp->mscp_modifier = 0;
+
+       mp->mscp_seq.seq_bytecount = bp->b_bcount;
+}
+
+/*
+ * Handle an error datagram.
+ */
+void
+mtdgram(usc, mp, mi)
+       struct device *usc;
+       struct mscp *mp;
+       struct mscp_softc *mi;
+{
+       if (mscp_decodeerror(usc == NULL?"unconf mt" : usc->dv_xname, mp, mi))
+               return;
+}
+
+/*
+ * A drive came on line, make sure it really _is_ on line before
+ * trying to use it.
+ */
+int
+mtonline(usc, mp)
+       struct device *usc;
+       struct mscp *mp;
+{
+       register struct mt_softc *mt = (void *)usc;
+
+       wakeup((caddr_t)&mt->mt_state);
+       if ((mp->mscp_status & M_ST_MASK) == M_ST_SUCCESS) 
+               mt->mt_state = MT_ONLINE;
+
+       return (MSCP_DONE);
+}
+
+/*
+ * We got some (configured) unit's status.  Return DONE.
+ */
+int
+mtgotstatus(usc, mp)
+       register struct device *usc;
+       register struct mscp *mp;
+{
+       return (MSCP_DONE);
+}
+
+static char *mt_ioerrs[] = {
+       "invalid command",      /* 1 M_ST_INVALCMD */
+       "command aborted",      /* 2 M_ST_ABORTED */
+       "unit offline",         /* 3 M_ST_OFFLINE */
+       "unknown",              /* 4 M_ST_AVAILABLE */
+       "unknown",              /* 5 M_ST_MFMTERR */
+       "unit write protected", /* 6 M_ST_WRPROT */
+       "compare error",        /* 7 M_ST_COMPERR */
+       "data error",           /* 8 M_ST_DATAERR */
+       "host buffer access error",     /* 9 M_ST_HOSTBUFERR */
+       "controller error",     /* 10 M_ST_CTLRERR */
+       "drive error",          /* 11 M_ST_DRIVEERR */
+       "formatter error",      /* 12 M_ST_FORMATTERR */
+       "BOT encountered",      /* 13 M_ST_BOT */
+       "tape mark encountered",/* 14 M_ST_TAPEMARK */
+       "unknown",              /* 15 */
+       "record data truncated",/* 16 M_ST_RDTRUNC */
+};
+
+/*
+ * An I/O error, may be because of a tapemark encountered.
+ * Check that before failing.
+ */
+/*ARGSUSED*/
+int
+mtioerror(usc, mp, bp)
+       register struct device *usc;
+       register struct mscp *mp;
+       struct buf *bp;
+{
+       struct mt_softc *mt = (void *)usc;
+       int st = mp->mscp_status & M_ST_MASK;
+
+       if (mp->mscp_flags & M_EF_SEREX)
+               mt->mt_serex = 1;
+       if (st == M_ST_TAPEMARK)
+               mt->mt_serex = 2;
+       else {
+               if (st && st < 17)
+                       printf("%s: error %d (%s)\n", mt->mt_dev.dv_xname, st,
+                           mt_ioerrs[st-1]);
+               else
+                       printf("%s: error %d\n", mt->mt_dev.dv_xname, st);
+               bp->b_flags |= B_ERROR;
+       }
+
+       return (MSCP_DONE);
+}
+
+/*
+ * I/O controls.
+ */
+int
+mtioctl(dev, cmd, data, flag, p)
+       dev_t dev;
+       int cmd;
+       caddr_t data;
+       int flag;
+       struct proc *p;
+{
+       register int unit = mtunit(dev);
+       register struct mt_softc *mt = mt_cd.cd_devs[unit];
+       struct  mtop *mtop;
+       struct  mtget *mtget;
+       int error = 0, i;
+
+
+       switch (cmd) {
+
+       case MTIOCTOP:
+               mtop = (void *)data;
+               i = mtop->mt_count;
+               while (i-- > 0)
+                       mtcmd(mt, mtop->mt_op);
+               break;
+
+       case MTIOCGET:
+               mtget = (void *)data;
+               mtget->mt_type = MT_ISTMSCP;
+               /* XXX we need to fill in more fields here */
+               break;
+
+       default:
+               error = ENXIO;
+               break;
+       }
+       return (error);
+}
+
+/*
+ * No crash dump support...
+ */
+int
+mtdump(dev, blkno, va, size)
+       dev_t   dev;
+       daddr_t blkno;
+       caddr_t va;
+       size_t  size;
+{
+       return -1;
+}
+
+/*
+ * Send a command to the tape drive. Wait until the command is
+ * finished before returning.
+ */
+void
+mtcmd(mt, cmd)
+       struct mt_softc *mt;
+       int cmd;
+{
+       struct mscp *mp;
+       struct mscp_softc *mi = (void *)mt->mt_dev.dv_parent;
+       volatile int i;
+
+       mp = mscp_getcp(mi, MSCP_WAIT);
+
+       mp->mscp_unit = mt->mt_hwunit;
+       mp->mscp_cmdref = -1;
+       *mp->mscp_addr |= MSCP_OWN | MSCP_INT;
+
+       switch (cmd) {
+       case MTWEOF:
+               mp->mscp_opcode = M_OP_WRITM;
+               break;
+
+       case MTBSF:
+               mp->mscp_modifier = M_MD_REVERSE;
+       case MTFSF:
+               mp->mscp_opcode = M_OP_POS;
+               mp->mscp_modifier |= M_MD_OBJCOUNT;
+               mp->mscp_seq.seq_buffer = 1;
+               break;
+
+       case MTBSR:
+               mp->mscp_modifier = M_MD_REVERSE;
+       case MTFSR:
+               mp->mscp_opcode = M_OP_POS;
+               mp->mscp_modifier |= M_MD_OBJCOUNT;
+               mp->mscp_seq.seq_bytecount = 1;
+               break;
+
+       case MTREW:
+               mp->mscp_opcode = M_OP_POS;
+               mp->mscp_modifier = M_MD_REWIND | M_MD_CLSEX;
+               mt->mt_serex = 0;
+               break;
+
+       case -1: /* Clear serious exception only */
+               mp->mscp_opcode = M_OP_POS;
+               mp->mscp_modifier = M_MD_CLSEX;
+               mt->mt_serex = 0;
+               break;
+
+       default:
+               printf("Bad ioctl %x\n", cmd);
+               mp->mscp_opcode = M_OP_POS;
+               break;
+       }
+
+       i = *mi->mi_ip;
+       tsleep(&mt->mt_inuse, PRIBIO, "mtioctl", 0);
+}
+
+/*
+ * Called from bus routines whenever a non-data transfer is finished.
+ */
+void
+mtcmddone(usc, mp)
+       struct device *usc;
+       struct mscp *mp;
+{
+       struct mt_softc *mt = (void *)usc;
+
+       if (mp->mscp_status)
+               printf("%s: bad status %x\n", mt->mt_dev.dv_xname,
+                   mp->mscp_status);
+       wakeup(&mt->mt_inuse);
+}
diff --git a/sys/arch/vax/mscp/mscpreg.h b/sys/arch/vax/mscp/mscpreg.h
new file mode 100644 (file)
index 0000000..a5c6993
--- /dev/null
@@ -0,0 +1,123 @@
+/*     $NetBSD: mscpreg.h,v 1.1 1996/07/01 20:41:37 ragge Exp $        */
+/*
+ * Copyright (c) 1996 Ludd, University of Lule}, Sweden.
+ * Copyright (c) 1988 Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * 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.
+ *
+ *     @(#)udareg.h    7.3 (Berkeley) 5/8/91
+ */
+
+/*
+ * NRSPL2 and NCMDL2 control the number of response and command
+ * packets respectively.  They may be any value from 0 to 7, though
+ * setting them higher than 5 is unlikely to be of any value.
+ * If you get warnings about your command ring being too small,
+ * try increasing the values by one.
+ */
+#define        NRSPL2  5
+#define        NCMDL2  5
+#define        NRSP    (1 << NRSPL2)
+#define        NCMD    (1 << NCMDL2)
+
+/*
+ * Communication area definition. This seems to be the same for
+ * all types of MSCP controllers.
+ */
+
+struct mscp_ca {
+       short   ca_xxx1;        /* unused */
+       char    ca_xxx2;        /* unused */
+       char    ca_bdp;         /* BDP to purge */
+       short   ca_cmdint;      /* command ring transition flag */
+       short   ca_rspint;      /* response ring transition flag */
+       long    ca_rspdsc[NRSP];/* response descriptors */
+       long    ca_cmddsc[NCMD];/* command descriptors */
+};
+
+/*
+ * Simplified routines (e.g., uddump) reprogram the UDA50 for one command
+ * and one response at a time; uda1ca is like udaca except that it provides
+ * exactly one command and response descriptor.
+ */
+struct mscp_1ca {
+       short   ca_xxx1;
+       char    ca_xxx2;
+       char    ca_bdp;
+       short   ca_cmdint;
+       short   ca_rspint;
+       long    ca_rspdsc;
+       long    ca_cmddsc;
+};
+
+/*
+ * Combined communications area and MSCP packet pools, per controller.
+ * NRSP and NCMD must be defined before this struct is used.
+ */
+
+struct mscp_pack {
+       struct  mscp_ca mp_ca;          /* communications area */
+       struct  mscp mp_rsp[NRSP];      /* response packets */
+       struct  mscp mp_cmd[NCMD];      /* command packets */
+};
+
+/*
+ * Bits in UDA status register during initialisation
+ */
+#define MP_ERR         0x8000  /* error */
+#define MP_STEP4       0x4000  /* step 4 has started */
+#define MP_STEP3       0x2000  /* step 3 has started */
+#define MP_STEP2       0x1000  /* step 2 has started */
+#define MP_STEP1       0x0800  /* step 1 has started */
+#define MP_NV          0x0400  /* no host settable interrupt vector */
+#define MP_QB          0x0200  /* controller supports Q22 bus */
+#define MP_DI          0x0100  /* controller implements diagnostics */
+#define MP_IE          0x0080  /* interrupt enable */
+#define MP_NCNRMASK    0x003f  /* in STEP1, bits 0-2=NCMDL2, 3-5=NRSPL2 */
+#define MP_IVECMASK    0x007f  /* in STEP2, bits 0-6 are interruptvec / 4 */
+#define MP_PI          0x0001  /* host requests adapter purge interrupts */
+#define        MP_GO           0x0001  /* Go command to ctlr */
+
+#define ALLSTEPS       (MP_ERR | MP_STEP4 | MP_STEP3 | MP_STEP2 | MP_STEP1)
+
+#define STEP0MASK      (ALLSTEPS | MP_NV)
+
+#define STEP1MASK       (ALLSTEPS | MP_IE | MP_NCNRMASK) 
+#define STEP1GOOD       (MP_STEP2 | MP_IE | (NCMDL2 << 3) | NRSPL2)
+#define STEP2MASK       (ALLSTEPS | MP_IE | MP_IVECMASK)
+#define STEP2GOOD(iv)   (MP_STEP3 | MP_IE | (iv))
+#define STEP3MASK       ALLSTEPS
+#define STEP3GOOD       MP_STEP4
+
diff --git a/sys/arch/vax/mscp/mscpvar.h b/sys/arch/vax/mscp/mscpvar.h
new file mode 100644 (file)
index 0000000..8871f96
--- /dev/null
@@ -0,0 +1,254 @@
+/*     $NetBSD: mscpvar.h,v 1.4 1997/01/11 11:20:36 ragge Exp $        */
+/*
+ * Copyright (c) 1996 Ludd, University of Lule}, Sweden.
+ * Copyright (c) 1988 Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * 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.
+ *
+ *     @(#)mscpvar.h   7.3 (Berkeley) 6/28/90
+ */
+
+/*
+ * MSCP generic driver configuration
+ */
+
+/*
+ * Enabling MSCP_PARANOIA makes the response code perform various checks
+ * on the hardware.  (Right now it verifies only the buffer pointer in
+ * mscp_cmdref.)
+ *
+ * Enabling AVOID_EMULEX_BUG selects an alternative method of identifying
+ * transfers in progress, which gets around a rather peculiar bug in the
+ * SC41/MS.  Enabling MSCP_PARANOIA instead should work, but will cause
+ * `extra' Unibus resets.
+ *
+ * Either of these flags can simply be included as an `options' line in
+ * your configuration file.
+ */
+
+/* #define MSCP_PARANOIA */
+/* #define AVOID_EMULEX_BUG */
+
+/*
+ * Ring information, per ring (one each for commands and responses).
+ */
+struct mscp_ri {
+       int     mri_size;               /* ring size */
+       int     mri_next;               /* next (expected|free) */
+       long    *mri_desc;              /* base address of descriptors */
+       struct  mscp *mri_ring;         /* base address of packets */
+};
+
+struct mscp_ctlr {
+       void    (*mc_ctlrdone)          /* controller operation complete */
+           __P((struct device *, int));
+       int     (*mc_go)                /* device-specific start routine */
+           __P((struct device *, struct buf *));
+       void    (*mc_saerror)           /* ctlr error handling */
+           __P((struct device *, int));
+};
+
+struct mscp_softc;
+
+struct mscp_device {
+       void    (*me_dgram)     /* error datagram */
+           __P((struct device *, struct mscp *, struct mscp_softc *));
+       void    (*me_iodone)    /* normal I/O is done */
+           __P((struct device *, struct buf *));
+       int     (*me_online)    /* drive on line */
+           __P((struct device *, struct mscp *));
+       int     (*me_gotstatus) /* got unit status */
+           __P((struct device *, struct mscp *));
+       void    (*me_replace)   /* replace done */
+           __P((struct device *, struct mscp *));
+       int     (*me_ioerr)     /* read or write failed */
+           __P((struct device *, struct mscp *, struct buf *));
+       void    (*me_bb)        /* B_BAD io done */
+           __P((struct device *, struct mscp *, struct buf *));
+       void    (*me_fillin)    /* Fill in mscp info for this drive */
+           __P((struct buf *,struct mscp *));
+       void    (*me_cmddone)   /* Non-data transfer operation is done */
+           __P((struct device *, struct mscp *));
+};
+
+/*
+ * This struct is used when attaching a mscpbus.
+ */
+struct mscp_attach_args {
+       struct  mscp_ctlr *ma_mc;       /* Pointer to ctlr's mscp_ctlr */
+       int     ma_type;                /* disk/tape bus type */
+       struct  mscp_pack *ma_uda;      /* comm area virtual */
+       struct  mscp_pack *ma_uuda;     /* comm area on bus */
+       struct  mscp_softc **ma_softc;  /* backpointer to bus softc */
+       short   *ma_ip;                 /* initialisation and polling */
+       short   *ma_sa;                 /* status & address (read part) */
+       short   *ma_sw;                 /* status & address (write part) */
+       short   ma_ivec;                /* Interrupt vector to use */
+       char    ma_ctlrnr;              /* Phys ctlr nr */
+       char    ma_adapnr;              /* Phys adapter nr */
+};
+#define MSCPBUS_DISK   001     /* Bus is used for disk mounts */
+#define MSCPBUS_TAPE   002     /* Bus is used for tape mounts */
+#define        MSCPBUS_UDA     004     /* ctlr is disk on unibus/qbus */
+#define        MSCPBUS_KDB     010     /* ctlr is disk on BI */
+#define        MSCPBUS_KLE     020     /* ctlr is tape on unibus/qbus */
+
+/*
+ * Used when going for child devices.
+ */
+struct drive_attach_args {
+       struct  mscp *da_mp;    /* this devices response struct */
+       int     da_typ;         /* Parent of type */
+};
+
+/*
+ * Return values from functions.
+ * MSCP_RESTARTED is peculiar to I/O errors.
+ */
+#define MSCP_DONE      0               /* all ok */
+#define MSCP_FAILED    1               /* no go */
+#define MSCP_RESTARTED 2               /* transfer restarted */
+
+/*
+ * Per device information.
+ *
+ * mi_ip is a pointer to the inverting pointers (things that get `ui's
+ * given unit numbers) FOR THIS CONTROLLER (NOT the whole set!).
+ *
+ * b_actf holds a queue of those transfers that were started but have
+ * not yet finished.  Other Unibus drivers do not need this as they hand
+ * out requests one at a time. MSCP devices, however, take a slew of
+ * requests and pick their own order to execute them.  This means that
+ * we have to have a place to move transfers that were given to the
+ * controller, so we can tell those apart from those that have not yet
+ * been handed out; b_actf is that place.
+ */
+struct mscp_softc {
+       struct  device mi_dev;          /* Autoconf stuff */
+       struct  mscp_ri mi_cmd;         /* MSCP command ring info */
+       struct  mscp_ri mi_rsp;         /* MSCP response ring info */
+       short   mi_credits;             /* transfer credits */
+       char    mi_wantcmd;             /* waiting for command packet */
+       char    mi_wantcredits;         /* waiting for transfer credits */
+       struct  buf *mi_actf;           /* Pointer to buffers in */
+       struct  buf *mi_actb;           /*  circular wait queue */
+       struct  mscp_ctlr *mi_mc;       /* Pointer to parent's mscp_ctlr */
+       struct  mscp_device *mi_me;     /* Pointer to child's mscp_device */
+       struct  device **mi_dp;         /* array of backpointers */
+       int     mi_driveno;             /* Max physical drive number found */
+       char    mi_ctlrnr;              /* Phys ctlr nr */
+       char    mi_adapnr;              /* Phys adapter nr */
+       int     mi_flags;
+       struct  mscp_pack *mi_uda;      /* virtual address */
+       struct  mscp_pack *mi_uuda;     /* (device-specific) address */
+       int     mi_type;
+       short   mi_ivec;                /* Interrupt vector to use */
+       short   mi_ierr;                /* Init err counter */
+       volatile short *mi_ip;          /* initialisation and polling */
+       volatile short *mi_sa;          /* status & address (read part) */
+       volatile short *mi_sw;          /* status & address (write part) */
+       struct  buf *mi_w;              /* While waiting for packets */
+};
+
+/* mi_flags */
+#define        MSC_STARTPOLL   1
+#define        MSC_INSTART     2
+#define        MSC_IGNOREINTR  4
+#define        MSC_READY       8
+
+/*
+ * We have run out of credits when mi_credits is <= MSCP_MINCREDITS.
+ * It is still possible to issue one command in this case, but it must
+ * not be a data transfer.  E.g., `get command status' or `abort command'
+ * is legal, while `read' is not.
+ */
+#define MSCP_MINCREDITS 1
+
+/*
+ * Flags for mscp_getcp().
+ */
+#define MSCP_WAIT      1
+#define MSCP_DONTWAIT  0
+
+       /* get a command packet */
+
+/*
+ * Unit flags
+ */
+#define UNIT_ONLINE    0x01    /* drive is on line */
+#define UNIT_HAVESTATUS 0x02   /* got unit status */
+#define UNIT_REQUEUE   0x04    /* requeue after response */
+
+/*
+ * Handle a command ring transition: wake up sleepers for command packets.
+ * This is too simple to bother with a function call.
+ */
+#define MSCP_DOCMD(mi) { \
+       if ((mi)->mi_wantcmd) { \
+               (mi)->mi_wantcmd = 0; \
+               wakeup((caddr_t) &(mi)->mi_wantcmd); \
+       } \
+}
+
+/*
+ * The following macro appends a buffer to a drive queue or a drive to
+ * a controller queue, given the name of the forward link.  Use as
+ * `APPEND(dp, &um->um_tab, b_forw)' or `APPEND(bp, dp, av_forw)',
+ * where `bp' is a transfer request, `dp' is a drive queue, and `um_tab'
+ * is a controller queue.  (That is, the forward link for controller
+ * queues is `b_forw'; for drive queues, it is `av_forw'.)
+ */
+
+#define        MSCP_APPEND(bp, queue, link) {                  \
+       (bp)->link = NULL;                              \
+       if ((queue)->link == NULL)                      \
+               (queue)->link = (bp);                   \
+       else                                            \
+               *(queue)->b_actb = (bp);                \
+       (queue)->b_actb = &(bp)->link;                  \
+}
+
+/* Prototypes */
+struct mscp *mscp_getcp __P((struct mscp_softc *, int));
+void   mscp_printevent __P((struct mscp *));
+void   mscp_go __P((struct mscp_softc *, struct mscp *, int));
+void   mscp_requeue __P((struct mscp_softc *));
+void   mscp_dorsp __P((struct mscp_softc *));
+int    mscp_decodeerror __P((char *, struct mscp *, struct mscp_softc *));
+int    mscp_print __P((void *, const char *));
+void   mscp_hexdump __P((struct mscp *));
+void   mscp_strategy __P((struct buf *, struct device *));
+void   mscp_printtype __P((int, int));
+int    mscp_waitstep __P((struct mscp_softc *, int, int));
+void   mscp_dgo __P((struct mscp_softc *, long, long, struct buf *));
+void   mscp_intr __P((struct mscp_softc *));
index f2ac372..b9a0cb4 100644 (file)
@@ -1,28 +1,29 @@
-#      $OpenBSD: Makefile,v 1.6 1996/09/27 18:38:04 maja Exp $
-#      $NetBSD: Makefile,v 1.9 1996/03/16 11:03:12 ragge Exp $
+#      $OpenBSD: Makefile,v 1.7 1997/01/15 23:24:15 maja Exp $
+#      $NetBSD: Makefile,v 1.11 1996/10/18 06:10:18 thorpej Exp $
 #
 
 INCPATH=-I. -I../../.. -I../.. -I../../../lib/libsa
-.PATH: ${.CURDIR}/../../../lib/libkern
 
 CC=    cc
 AS=    as
 
 S=      ../../..
 RELOC= 100000
-CFLAGS+=-O ${INCPATH} -DSTANDALONE -DRELOC=0x${RELOC} -D_VAX_INLINE_
+XXRPB= 0F4240
+CFLAGS+=-O ${INCPATH} -DSTANDALONE -DRELOC=0x${RELOC} \
+       -D_VAX_INLINE_ -DXXRPB=0x$(XXRPB)
 
-DEVS=  autoconf.o hp.o ra.o tmscp.o ctu.o
-
-LIBKERN=libkern.a
-KERNOBJ=__main.o strlen.o strcmp.o strncmp.o strncpy.o min.o strcpy.o
+DEVS=  autoconf.o hp.o ra.o tmscp.o ctu.o mfm.o rom.o romread.o \
+       scsi_low.o scsi_hi.o sd.o
 
 .include "$S/lib/libsa/Makefile.inc"
 LIBSA=         ${SALIB}
 
-all:   xxboot boot copy edlabel
+SVAX=  consio.o urem.o udiv.o str.o
+
+all:   ${LIBSA} xxboot boot copy edlabel
 
-libsvax.a: consio.o urem.o udiv.o
+libsvax.a: ${SVAX}
        ar crv $@ $?
        ranlib $@
 
@@ -32,6 +33,9 @@ urem.o:       ../vax/urem.s
 udiv.o:        ../vax/udiv.s
        ${CC} -x assembler-with-cpp -E ../vax/udiv.s | as -o udiv.o
 
+str.o: str.s
+       ${CC} -x assembler-with-cpp -E str.s | as -o str.o
+
 # startups
 
 start.o: start.s
@@ -42,29 +46,29 @@ srt0.o:     srt0.s
 
 # 
 
-xxboot:        start.o bootxx.o romread.o ${LIBSA} ${LIBKERN} libsvax.a 
+xxboot:        start.o bootxx.o romread.o libsvax.a 
        ld -N -Ttext ${RELOC} -o a.out start.o bootxx.o romread.o \
-       ${LIBSA} ${LIBKERN} libsvax.a
+       ${LIBSA} libsvax.a
        @strip a.out
        @size a.out
        @dd if=a.out of=xxboot bs=32 skip=1
        @rm -f a.out
 
-boot:  boot.o srt0.o devopen.o conf.o ${DEVS} ${LIBKERN} ${LIBSA} libsvax.a
+boot:  boot.o srt0.o devopen.o conf.o ${DEVS} libsvax.a
        ld -N -Ttext ${RELOC} -e nisse -o $@ srt0.o devopen.o boot.o \
-       conf.o ${DEVS} ${LIBSA} ${LIBKERN} libsvax.a
+       conf.o ${DEVS} ${LIBSA} libsvax.a
        @strip boot
        @size boot
 
-edlabel: edlabel.o srt0.o devopen.o conf.o ${DEVS} ${LIBKERN} ${LIBSA} libsvax.a
+edlabel: edlabel.o srt0.o devopen.o conf.o ${DEVS} libsvax.a
        ld -N -Ttext ${RELOC} -e nisse -o $@ srt0.o devopen.o edlabel.o\
-       conf.o ${DEVS} ${LIBSA} ${LIBKERN} libsvax.a
+       conf.o ${DEVS} ${LIBSA} libsvax.a
        @strip edlabel
        @size edlabel
 
-copy:  copy.o srt0.o devopen.o conf.o ${DEVS} ${LIBKERN} ${LIBSA} libsvax.a
+copy:  copy.o srt0.o devopen.o conf.o ${DEVS} libsvax.a
        ld -N -Ttext ${RELOC} -e nisse -o $@ srt0.o devopen.o copy.o \
-       conf.o ${DEVS} ${LIBSA} ${LIBKERN} libsvax.a
+       conf.o ${DEVS} ${LIBSA} libsvax.a
        @strip copy
        @size copy
 
@@ -97,15 +101,11 @@ init.o:    init.c
 bootxx.o: bootxx.c 
        ${CC} -c ${CFLAGS} $*.c
 
-#
-libkern.a: ${KERNOBJ}
-       @echo Creating standalone kern library
-       @ar rv libkern.a `lorder ${KERNOBJ} | tsort`
-
 #
 install: boot xxboot
-       install -c -o ${BINOWN} -g ${BINGRP} -m 444 boot ${DESTDIR}/
-       install -c -o ${BINOWN} -g ${BINGRP} -m 444 xxboot ${DESTDIR}/usr/mdec
+       ${INSTALL} -c -o ${BINOWN} -g ${BINGRP} -m 444 boot ${DESTDIR}/
+       ${INSTALL} -c -o ${BINOWN} -g ${BINGRP} -m 444 xxboot \
+           ${DESTDIR}/usr/mdec
        rm -f ${DESTDIR}/usr/mdec/raboot
        ln ${DESTDIR}/usr/mdec/xxboot ${DESTDIR}/usr/mdec/raboot
        rm -f ${DESTDIR}/usr/mdec/hpboot
@@ -115,7 +115,7 @@ clean::
        rm -f start.o romread.o bootxx.o init.o xxboot boot racopy \
        libsvax.a udiv.o urem.o consio.o ${DEVS} edlabel edlabel.o
        rm -f conf.o boot.o rom.o racopy.o srt0.o devopen.o rootcopy.o \
-       copy copy.o
+       copy copy.o init.o
 
 .include <bsd.prog.mk>
 
index ca08f01..d3b2d2b 100644 (file)
@@ -1,4 +1,4 @@
-/*     $NetBSD: autoconf.c,v 1.5 1996/03/07 23:27:06 ragge Exp $ */
+/*     $NetBSD: autoconf.c,v 1.6 1996/08/02 11:21:46 ragge Exp $ */
 /*
  * Copyright (c) 1994 Ludd, University of Lule}, Sweden.
  * All rights reserved.
@@ -39,8 +39,8 @@
 #include "vaxstand.h"
 
 int    nmba=0, nuba=0, nbi=0,nsbi=0,nuda=0;
-int    *mbaaddr, *ubaaddr;
-int    *udaaddr, *uioaddr, tmsaddr;
+int    *mbaaddr, *ubaaddr, *biaddr;
+int    *udaaddr, *uioaddr, tmsaddr, *bioaddr;
 
 static int mba750[]={0xf28000,0xf2a000,0xf2c000};
 static int uba750[]={0xf30000,0xf32000};
@@ -55,6 +55,10 @@ static int uba780[]={0x20006000,0x20008000,0x2000a000,0x2000c000,
 static int uio780[]={0x20100000,0x20140000,0x20180000,0x201c0000,
        0x22100000,0x22140000,0x22180000,0x221c0000};
 
+static int bi8200[]={0x20000000, 0x22000000, 0x24000000, 0x26000000,
+       0x28000000, 0x2a000000};
+static int bio8200[]={0x20400000};
+
 static int uba630[]={0x20087800};
 static int uio630[]={0x30000000};
 #define qbdev(csr) (((csr) & 017777)-0x10000000)
@@ -67,12 +71,11 @@ static int uda630[]={qbdev(0772150),qbdev(0760334)};
 
 autoconf()
 {
-       int i = MACHID(mfpr(PR_SID));
 
-       switch (i) {
+       switch (vax_cputype) {
 
        default:
-               printf("CPU type %d not supported by boot\n",i);
+               printf("CPU type %d not supported by boot\n",vax_cputype);
                asm("halt");
 
        case VAX_8600:
@@ -117,6 +120,11 @@ autoconf()
                uioaddr = uio630;
                tmsaddr = qbdev(0774500);
                break;
+
+       case VAX_8200:
+               nbi = 1;
+               biaddr = bi8200;
+               bioaddr = bio8200;
        }
 }
 
index 206db3d..7fd5422 100644 (file)
@@ -1,4 +1,5 @@
-/*     $NetBSD: boot.c,v 1.4 1995/09/16 15:54:20 ragge Exp $ */
+/*     $OpenBSD: boot.c,v 1.3 1997/01/15 23:24:16 maja Exp $ */
+/*     $NetBSD: boot.c,v 1.5 1996/08/02 11:21:49 ragge Exp $ */
 /*-
  * Copyright (c) 1982, 1986 The Regents of the University of California.
  * All rights reserved.
@@ -38,6 +39,8 @@
 #include "sys/reboot.h"
 #include "lib/libsa/stand.h"
 
+#define V750UCODE(x)    ((x>>8)&255)
+
 #include <a.out.h>
 
 /*
@@ -49,8 +52,9 @@
 char line[100];
 volatile u_int devtype, bootdev;
 extern unsigned opendev;
+extern  unsigned *bootregs;
 
-main()
+Xmain()
 {
        register howto asm("r11");
        register bdev  asm("r10");
@@ -149,7 +153,7 @@ copyunix(howto, devtype, aio)
        hoppabort((x.a_entry&0x7fffffff),howto, devtype, esym);
        return;
 shread:
-       printf("Short read\n");
+       printf("\nShort read\n\n");
        return;
 }
 
@@ -191,7 +195,7 @@ loadpcs()
                if (*cp == ')' || *cp == ':')
                        break;
        if (*cp) {
-               strncpy(pcs, line, 99);
+               bcopy(line, pcs, 99);
                pcs[99] = 0;
                i = cp - line + 1;
        } else
index 4a1b34f..e7464b8 100644 (file)
@@ -1,4 +1,4 @@
-/* $NetBSD: bootxx.c,v 1.5 1996/02/17 18:23:21 ragge Exp $ */
+/* $NetBSD: bootxx.c,v 1.7 1996/08/02 11:21:53 ragge Exp $ */
 /*-
  * Copyright (c) 1982, 1986 The Regents of the University of California.
  * All rights reserved.
 #include "../mba/mbareg.h"
 #include "../mba/hpreg.h"
 
-#define NRSP 0 /* Kludge */
-#define NCMD 0 /* Kludge */
+#define NRSP 1 /* Kludge */
+#define NCMD 1 /* Kludge */
+
 #include "../uba/ubareg.h"
 #include "../uba/udareg.h"
-#include "../vax/mscp.h"
+
+#include "../mscp/mscp.h"
+#include "../mscp/mscpreg.h"
 
 #include "data.h"
 #include "vaxstand.h"
 
 #include <a.out.h>
 
-int             romstrategy(), romopen();
+int     romstrategy(), romopen();
 int    command(int, int);
 
 /*
@@ -71,39 +74,45 @@ int command(int, int);
 
 volatile u_int  devtype, bootdev;
 unsigned        opendev, boothowto, bootset;
-int             cpu_type, cpunumber;
-unsigned *bootregs;
-int is_750 = 0, is_mvax = 0, is_tmscp = 0;
-struct rpb *rpb;
 
-main()
+extern unsigned *bootregs;
+extern struct  rpb *rpb;
+
+Xmain()
 {
        int io;
+       char *scbb;
+       char *new;
        char *hej = "/boot";
 
-        cpu_type = mfpr(PR_SID);
-        cpunumber = (mfpr(PR_SID) >> 24) & 0xFF;
-
-        switch (cpunumber) {
+        switch (vax_cputype) {
 
         case VAX_78032:
         case VAX_650:
-        {
-                int    cpu_sie;        /* sid-extension */
-
-                is_mvax = 1;
-                cpu_sie = *((int *) 0x20040004) >> 24;
-                cpu_type |= cpu_sie;
-               rpb = (struct rpb *)bootregs[11];
                bootdev = rpb->devtyp;
 
+               /*
+                * now relocate rpb/bqo (which are used by ROM-routines)
+                */
+               rpb = (void*)XXRPB;
+               bcopy ((void*)bootregs[11], rpb, 512);
+               rpb->rpb_base = rpb;
+               bqo = (void*)(512+(int)rpb);
+               bcopy ((void*)rpb->iovec, bqo, rpb->iovecsz);
+               rpb->iovec = (int)bqo;
+               bootregs[11] = (int)rpb;
+
                 break;
-        }
+       case VAX_8200:
         case VAX_750:
-                is_750 = 1;
                bootdev = bootregs[10];
 
                 break;
+       default:
+               printf("unknown cpu type %d\nRegister dump:\n", vax_cputype);
+               for (io = 0; io < 16; io++)
+                       printf("r%d 0x%x\n", io, bootregs[io]);
+               asm("halt");
         }
 
        bootset = getbootdev();
@@ -114,7 +123,7 @@ main()
        if (io >= 0 && io < SOPEN_MAX) {
                copyunix(io);
        } else {
-               printf("Boot failed. errno %d (%s)\n", errno, strerror(errno));
+               printf("Boot failed, saerrno %d\n", errno);
        }
 }
 
@@ -127,7 +136,7 @@ copyunix(aio)
 
        i = read(io, (char *) &x, sizeof(x));
        if (i != sizeof(x) || N_BADMAG(x)) {
-               printf("Bad format: errno %s\n", strerror(errno));
+               printf("Bad format\n");
                return;
        }
        printf("%d", x.a_text);
@@ -163,7 +172,7 @@ getbootdev()
        int     i, major, adaptor, controller, unit, partition;
 
 
-       switch (cpunumber) {
+       switch (vax_cputype) {
        case VAX_78032:
        case VAX_650:
                adaptor = 0;
@@ -172,6 +181,7 @@ getbootdev()
                
                break;
 
+       case VAX_8200:
        case VAX_750:
                controller = 0; /* XXX Actually massbuss can be on 3 ctlr's */
                unit = bootregs[3];
@@ -181,23 +191,28 @@ getbootdev()
        partition = 0;
 
        switch (bootdev) {
-       case 0:                 /* massbuss boot */
+       case BDEV_MBA:                  /* massbuss boot */
                major = 0;      /* hp / ...  */
                adaptor = (bootregs[1] & 0x6000) >> 17;
                break;
 
-       case 17:                /* UDA50 boot */
+       case BDEV_UDA:          /* UDA50 boot */
                major = 9;      /* ra / mscp  */
-               if (is_750)
+               if (vax_cputype == VAX_750)
                        adaptor = (bootregs[1] & 0x40000 ? 0 : 1);
                break;
 
-       case 18:                /* TK50 boot */
+       case BDEV_TK50:         /* TK50 boot */
                major = 15;     /* tms / tmscp  */
-               is_tmscp = 1;   /* use tape spec in mscp routines */
                break;
 
-       case 64:
+       case 36:                /* VS2000/KA410 ST506 disk */
+       case 37:                /* VS2000/KA410 SCSI tape */
+       case 42:                /* VS3100/76 SCSI-floppy(?) */
+               major = 17;     /* 17 is assigned to the ROM-drivers */
+               break;
+
+       case BDEV_CONSOLE:
                major = 8;
                break;
 
@@ -224,7 +239,7 @@ struct disklabel lp;
 int part_off = 0;              /* offset into partition holding /boot */
 char io_buf[MAXBSIZE];
 volatile struct uda {
-       struct  uda1ca uda_ca;           /* communications area */
+       struct  mscp_1ca uda_ca;           /* communications area */
        struct  mscp uda_rsp;     /* response packets */
        struct  mscp uda_cmd;     /* command packets */
 } uda;
@@ -245,27 +260,27 @@ devopen(f, fname, file)
        /*
         * On uVAX we need to init [T]MSCP ctlr to be able to use it.
         */
-       if (is_mvax) {
+       if (vax_cputype == VAX_78032 || vax_cputype == VAX_650) {
                switch (bootdev) {
-               case 17:        /* MSCP */
-               case 18:        /* TMSCP */
+               case BDEV_UDA:  /* MSCP */
+               case BDEV_TK50: /* TMSCP */
                        csr = (struct udadevice *)rpb->csrphy;
 
                        csr->udaip = 0; /* Start init */
-                       while((csr->udasa & UDA_STEP1) == 0);
+                       while((csr->udasa & MP_STEP1) == 0);
                        csr->udasa = 0x8000;
-                       while((csr->udasa & UDA_STEP2) == 0);
+                       while((csr->udasa & MP_STEP2) == 0);
                        csr->udasa = (short)(((u_int)&uda)&0xffff) + 8;
-                       while((csr->udasa & UDA_STEP3) == 0);
+                       while((csr->udasa & MP_STEP3) == 0);
                        csr->udasa = 0x10;
-                       while((csr->udasa & UDA_STEP4) == 0);
+                       while((csr->udasa & MP_STEP4) == 0);
                        csr->udasa = 0x0001;
 
                        uda.uda_ca.ca_rspdsc =
                            (int) &uda.uda_rsp.mscp_cmdref;
                        uda.uda_ca.ca_cmddsc =
                            (int) &uda.uda_cmd.mscp_cmdref;
-                       if (is_tmscp)
+                       if (bootdev == BDEV_TK50)
                                uda.uda_cmd.mscp_vcid = 1;
                        command(M_OP_SETCTLRC, 0);
                        uda.uda_cmd.mscp_unit = rpb->unit;
@@ -279,11 +294,10 @@ devopen(f, fname, file)
         * Actually disklabel is only needed when using hp disks,
         * but it doesn't hurt to always get it.
         */
-       if (!is_tmscp) {
+       if ((bootdev != BDEV_TK50) && (bootdev != BDEV_CONSOLE)) {
                msg = getdisklabel((void *)LABELOFFSET + RELOC, &lp);
-               if (msg) {
+               if (msg)
                        printf("getdisklabel: %s\n", msg);
-               }
        }
        return 0;
 }
@@ -317,13 +331,13 @@ romstrategy(sc, func, dblk, size, buf, rsize)
        int     block = dblk;
        int     nsize = size;
 
-       switch (cpunumber) {
+       switch (vax_cputype) {
 
        case VAX_650:
        case VAX_78032:
                switch (bootdev) {
 
-               case 17: /* MSCP */
+               case BDEV_UDA: /* MSCP */
                        uda.uda_cmd.mscp_seq.seq_lbn = dblk;
                        uda.uda_cmd.mscp_seq.seq_bytecount = size;
                        uda.uda_cmd.mscp_seq.seq_buffer = (int)buf;
@@ -331,7 +345,7 @@ romstrategy(sc, func, dblk, size, buf, rsize)
                        command(M_OP_READ, 0);
                        break;
 
-               case 18: /* TMSCP */
+               case BDEV_TK50: /* TMSCP */
                        if (dblk < curblock) {
                                uda.uda_cmd.mscp_seq.seq_bytecount =
                                    curblock - dblk;
@@ -351,16 +365,21 @@ romstrategy(sc, func, dblk, size, buf, rsize)
                                command(M_OP_READ, 0);
                        }
                        break;
+               case 36:
+               case 37:
+               default:
+                       romread_uvax(block, size, buf, bootregs);
+                       break;
 
                }
                break;
 
+       case VAX_8200:
        case VAX_750:
-               if (bootdev) {
+               if (bootdev != BDEV_MBA) {
                        while (size > 0) {
-                               if ((read750(block, bootregs) & 0x01) == 0)
-                                       return 1;
-
+                               while ((read750(block, bootregs) & 0x01) == 0)
+                                       printf("Retrying read bn# %d\n", block);
                                bcopy(0, buf, 512);
                                size -= 512;
                                buf += 512;
index f516c4d..72b7f44 100644 (file)
@@ -1,4 +1,4 @@
-/*     $NetBSD: conf.c,v 1.5 1996/02/17 18:23:18 ragge Exp $ */
+/*     $NetBSD: conf.c,v 1.6 1996/08/02 11:21:56 ragge Exp $ */
 /*
  * Copyright (c) 1994 Ludd, University of Lule}, Sweden.
  * All rights reserved.
@@ -42,25 +42,33 @@ int raopen(),  rastrategy();
 int    hpopen(),  hpstrategy();
 int    ctuopen(),  ctustrategy();
 int     tmscpopen(), tmscpstrategy();
+int     romopen(), romstrategy();
+int     mfmopen(), mfmstrategy();
+int     sdopen(), sdstrategy();
+
 
 struct devsw devsw[]={
        SADEV("hp",hpstrategy, hpopen, nullsys, noioctl),
-       SADEV("ht",nullsys, nodev, nullsys, noioctl),
-       SADEV("up",nullsys, nodev, nullsys, noioctl),
-       SADEV("hk",nullsys, nodev, nullsys, noioctl),
+       SADEV(0 ,nullsys, nodev, nullsys, noioctl), /* ht */
+       SADEV(0 ,nullsys, nodev, nullsys, noioctl), /* up */
+       SADEV(0 ,nullsys, nodev, nullsys, noioctl), /* hk */
        SADEV( 0  ,nullsys, nodev, nullsys, noioctl),
-       SADEV("tm",nullsys, nodev, nullsys, noioctl),
-       SADEV("ts",nullsys, nodev, nullsys, noioctl),
-       SADEV("mt",nullsys, nodev, nullsys, noioctl),
+       SADEV(0 ,nullsys, nodev, nullsys, noioctl), /* tm */
+       SADEV(0 ,nullsys, nodev, nullsys, noioctl), /* ts */
+       SADEV(0 ,nullsys, nodev, nullsys, noioctl), /* mt */
        SADEV("ctu",ctustrategy, ctuopen, nullsys, noioctl),
        SADEV("ra",rastrategy, raopen, nullsys, noioctl),
-       SADEV("ut",nullsys, nodev, nullsys, noioctl),
-       SADEV("id",nullsys, nodev, nullsys, noioctl),
-       SADEV("rx",nullsys, nodev, nullsys, noioctl),
-       SADEV("uu",nullsys, nodev, nullsys, noioctl),
-       SADEV("rl",nullsys, nodev, nullsys, noioctl),
-       SADEV("tms",tmscpstrategy, tmscpopen, nullsys, noioctl),
-       SADEV("kra",nullsys, nodev, nullsys, noioctl),
+       SADEV(0 ,nullsys, nodev, nullsys, noioctl), /* ut */
+       SADEV(0 ,nullsys, nodev, nullsys, noioctl), /* id */
+       SADEV(0 ,nullsys, nodev, nullsys, noioctl), /* rx */
+       SADEV(0 ,nullsys, nodev, nullsys, noioctl), /* uu */
+       SADEV(0 ,nullsys, nodev, nullsys, noioctl), /* rl */
+       SADEV("mt",tmscpstrategy, tmscpopen, nullsys, noioctl),
+       SADEV(0 ,nullsys, nodev, nullsys, noioctl), /* crx */
+        SADEV("rom",romstrategy, romopen, nullsys, noioctl),    /* 17 */
+        SADEV("mfm",mfmstrategy, mfmopen, nullsys, noioctl),    /* 18 */
+        SADEV("sd",sdstrategy, sdopen, nullsys, noioctl),       /* 18 */
+       SADEV("st",sdstrategy, sdopen, nullsys, noioctl),
 };
 
 int     ndevs = (sizeof(devsw)/sizeof(devsw[0]));
index 39402cc..94db46d 100644 (file)
@@ -1,4 +1,4 @@
-/*     $NetBSD: consio.c,v 1.3 1995/09/16 15:48:49 ragge Exp $ */
+/*     $NetBSD: consio.c,v 1.4 1996/08/02 11:22:00 ragge Exp $ */
 /*
  * Copyright (c) 1994 Ludd, University of Lule}, Sweden.
  * All rights reserved.
 #include "../vax/gencons.h"
 
 #include "../include/mtpr.h"
+#include "../include/sid.h"
+#include "../include/rpb.h"
 
-putchar(ch)
-        int     ch;
+#include "data.h"
+
+void setup __P((void));
+
+int    vax_cputype;
+int    vax_boardtype;
+
+int    is_750;
+int    is_mvax;
+
+unsigned       *bootregs;
+struct rpb     *rpb;
+struct bqo     *bqo;
+
+static int (*put_fp) __P((int))  = NULL;
+static int (*get_fp) __P((void)) = NULL;
+
+int pr_putchar __P((int c));   /* putchar() using mtpr/mfpr */
+int pr_getchar __P((void));
+
+int rom_putchar __P((int c));  /* putchar() using ROM routines */
+int rom_getchar __P((void));
+
+static int rom_putc;           /* ROM-address of put-routine */
+static int rom_getc;           /* ROM-address of get-routine */
+
+putchar(c)
+       int c;
+{
+       (*put_fp)(c);
+       if (c == 10)
+               (*put_fp)(13);          /* CR/LF */
+}
+
+getchar() 
+{
+       int c;
+
+       do
+               c = (*get_fp)() & 0177;
+       while (c == 17 || c == 19);             /* ignore XON/XOFF */
+       return c;
+}
+
+
+/*
+ * setup() is called out of the startup files (start.s, srt0.s) and
+ * initializes data which are globally used and is called before main().
+ */
+void 
+setup()
 {
-        while ((mfpr(PR_TXCS) & GC_RDY) == 0); /* Wait until xmit ready */
-        mtpr(ch, PR_TXDB);       /* xmit character */
-        if (ch == 10)
-                putchar(13); /* CR/LF */
+       vax_cputype = (mfpr(PR_SID) >> 24) & 0xFF;
+
+       put_fp = pr_putchar;
+       get_fp = pr_getchar;
+       /*
+        * according to vax_cputype we initialize vax_boardtype.
+        */
+        switch (vax_cputype) {
 
+       case VAX_650:
+       case VAX_78032:
+               is_mvax = 1;
+               vax_boardtype = (vax_cputype << 24) |
+                   ((*(int*)0x20040004 >> 24) & 0377);
+               rpb = (struct rpb *)bootregs[11];       /* bertram: ??? */
+               break;
+        }
+
+       /*
+        * According to the vax_boardtype (vax_cputype is not specific
+        * enough to do that) we decide which method/routines to use
+        * for console I/O. 
+        * mtpr/mfpr are restricted to serial consoles, ROM-based routines
+        * support both serial and graphical consoles, thus we use that
+        * as fallthrough/default.
+        */
+       switch (vax_boardtype) {        /* ROM-based is default !!! */
+
+       case VAX_BTYP_650:
+       case VAX_BTYP_660:
+       case VAX_BTYP_670:
+       case VAX_BTYP_690:
+       case VAX_BTYP_1303:
+               put_fp = rom_putchar;
+               get_fp = rom_getchar;
+               rom_putc = 0x20040058;          /* 537133144 */
+               rom_getc = 0x20040008;          /* 537133064 */
+               break;
+
+       case VAX_BTYP_43:
+       case VAX_BTYP_46:
+       case VAX_BTYP_49:
+       case VAX_BTYP_410:        
+               put_fp = rom_putchar;
+               get_fp = rom_getchar;
+               rom_putc = 0x20040058;          /* 537133144 */
+               rom_getc = 0x20040044;          /* 537133124 */
+               break;
+
+       default:
+               break;
+       }
+
+       return;
 }
 
-getchar()
+/*
+ * putchar() using MTPR
+ */
+pr_putchar(c)
+        int     c;
 {
-       int ch;
+       int     timeout = 1<<15;        /* don't hang the machine! */
+        while ((mfpr(PR_TXCS) & GC_RDY) == 0)  /* Wait until xmit ready */
+               if (--timeout < 0)
+                       break;
+        mtpr(c, PR_TXDB);              /* xmit character */
+}
 
-       do {
-               while ((mfpr(PR_RXCS) & GC_DON) == 0);  /* wait for char */
-               ch = mfpr(PR_RXDB);                     /* now get it */
-       } while (ch == 17 || ch == 19);
-       return ch;
+/*
+ * getchar() using MFPR
+ */
+pr_getchar()
+{
+       while ((mfpr(PR_RXCS) & GC_DON) == 0);  /* wait for char */
+       return (mfpr(PR_RXDB));                 /* now get it */
 }
+
+/*
+ * int rom_putchar (int c)     ==> putchar() using ROM-routines
+ */
+asm("
+       .globl _rom_putchar
+       _rom_putchar:
+               .word 0x04              # save-mask: R2
+               movl    4(ap), r2       # move argument to R2
+               jsb     *_rom_putc      # write it
+               ret                     # that's all
+");
+
+
+/*
+ * int rom_getchar (void)      ==> getchar() using ROM-routines
+ */
+asm("
+       .globl _rom_getchar
+       _rom_getchar:
+               .word 0x02              # save-mask: R1
+       loop:                           # do {
+               jsb     *_rom_getc      #   call the getc-routine
+               tstl    r0              #   check if char ready
+               beql    loop            # } while (R0 == 0)
+               movl    r1, r0          # R1 holds char
+               ret                     # we're done
+");
+
+
index a67721d..c46ba56 100644 (file)
@@ -1,4 +1,4 @@
-/*     $NetBSD: copy.c,v 1.2 1995/09/29 16:35:00 ragge Exp $ */
+/*     $NetBSD: copy.c,v 1.3 1996/08/02 11:22:03 ragge Exp $ */
 /*-
  * Copyright (c) 1982, 1986 The Regents of the University of California.
  * All rights reserved.
@@ -38,6 +38,8 @@
 #include "sys/reboot.h"
 #include "lib/libsa/stand.h"
 
+#include "vaxstand.h"
+
 #include <a.out.h>
 
 char line[100];
@@ -53,7 +55,7 @@ static int    partlist[8];
 int fill_buffer (void);
 int write_disk (void);
 
-main()
+Xmain()
 {
        int adapt, ctlr, unit, part;
        int res, i, loops;
index d3468b4..8d58b77 100644 (file)
@@ -1,4 +1,4 @@
-/*     $NetBSD: devopen.c,v 1.4 1996/03/16 11:02:28 ragge Exp $ */
+/*     $NetBSD: devopen.c,v 1.6 1996/08/02 16:18:39 ragge Exp $ */
 /*-
  *  Copyright (c) 1993 John Brezak
  *  All rights reserved.
@@ -52,7 +52,7 @@ usage()
 {
        printf("\
            Usage: device(adaptor, controller, drive, partition)file\n\
-            <device><unit><partitonletter>:file\n\
+           <device><unit><partitonletter>:file\n\
            ");
 }
 
@@ -62,15 +62,15 @@ devlookup(d,len)
 {
        struct devsw *dp = devsw;
        int i;
-    
+
        for (i = 0; i < ndevs; i++, dp++)
                if (dp->dv_name && strncmp(dp->dv_name, d, len) == 0)
-                       return(i);
+                       return(i);
 
        printf("No such device - Configured devices are:\n");
        for (dp = devsw, i = 0; i < ndevs; i++, dp++)
                if (dp->dv_name)
-                       printf(" %s", dp->dv_name);
+                       printf(" %s", dp->dv_name);
        printf("\n");
        errno = ENODEV;
        return(-1);
@@ -90,7 +90,7 @@ devparse(fname, dev, adapt, ctlr, unit, part, file)
 {
        int *argp, i;
        char *s, *args[4];
-    
+
        /* get device name and make lower case */
        for(s = fname; *s && *s != '/' && *s != ':' && *s != '('; s++)
                if(isupper(*s))
@@ -117,19 +117,19 @@ devparse(fname, dev, adapt, ctlr, unit, part, file)
                        *part  = atoi(args[3]);
                        break;
                case 3:
-                       *ctlr  = atoi(args[0]);
-                       *unit  = atoi(args[1]);
-                       *part  = atoi(args[2]);
-                       break;
+                       *ctlr  = atoi(args[0]);
+                       *unit  = atoi(args[1]);
+                       *part  = atoi(args[2]);
+                       break;
                case 2:
-                       *unit  = atoi(args[0]);
-                       *part  = atoi(args[1]);
-                       break;
+                       *unit  = atoi(args[0]);
+                       *part  = atoi(args[1]);
+                       break;
                case 1:
-                       *part  = atoi(args[0]);
-                       break;
+                       *part  = atoi(args[0]);
+                       break;
                case 0:
-                       break;
+                       break;
                }
                *file = ++s;
 
@@ -142,25 +142,25 @@ devparse(fname, dev, adapt, ctlr, unit, part, file)
        
                /* lookup device and get index */
                if ((*dev = devlookup(fname, s - fname)) < 0)
-                       goto baddev;
+                       goto baddev;
 
                /* isolate unit */
                if ((*unit = atoi(s)) > sizeof(char))
-                       goto bad;
+                       goto bad;
                for (; isdigit(*s); s++)
                        ;
        
                /* translate partition */
                if(!ispart(*s))
-                       goto bad;
+                       goto bad;
        
                *part = *s++ - 'a';
                if(*s != ':')
-                       goto bad;
+                       goto bad;
                *file = ++s;
 
        /* no device present */
-       } else
+       } else
                *file = fname;
     
        /* return the remaining unparsed part as the file to boot */
@@ -176,8 +176,8 @@ bad:
 extern int bootdev;
 
 devopen(f, fname, file)
-        struct open_file *f;
-        const char *fname;
+       struct open_file *f;
+       const char *fname;
        char **file;
 {
        int n, error;
@@ -190,12 +190,12 @@ devopen(f, fname, file)
        unit  = B_UNIT(bootdev);
        part  = B_PARTITION(bootdev);
        adapt = B_ADAPTOR(bootdev);
-       
+
        if (error = devparse(fname, &dev, &adapt, &ctlr, &unit, &part, file))
                return(error);
-       
+
        dp = &devsw[dev];
-       
+
        if (!dp->dv_open)
                return(ENODEV);
 
index 0984418..a5af6ab 100644 (file)
@@ -1,4 +1,4 @@
-/*     $NetBSD: edlabel.c,v 1.1 1995/09/16 12:56:03 ragge Exp $ */
+/*     $NetBSD: edlabel.c,v 1.2 1996/08/02 11:22:11 ragge Exp $ */
 /*
  * Copyright (c) 1995 Ludd, University of Lule}, Sweden.
  * All rights reserved.
@@ -88,7 +88,7 @@ setdefaultlabel()
 #define GETNUM2(out, num1, num) printf(out, num1, num);gets(store); \
        if (*store) num = atoi(store);
 #define        GETSTR(out, str) printf(out, str);gets(store); \
-       if (*store) strcpy(str, store);
+       if (*store) bcopy(store, str, strlen(store));
 #define        FLAGS(out, flag) printf(out, lp->d_flags & flag?'y':'n');gets(store); \
        if (*store == 'y' || *store == 'Y') lp->d_flags |= flag; \
        else lp->d_flags &= ~flag;
@@ -121,9 +121,11 @@ editlabel()
        GETNUM("drivedata 2? [%d] ", lp->d_drivedata[2]);
        GETNUM("drivedata 3? [%d] ", lp->d_drivedata[3]);
        GETNUM("drivedata 4? [%d] ", lp->d_drivedata[4]);
+       lp->d_secsize = 512;
        GETNUM("\nbytes/sector? [%d] ", lp->d_secsize);
        GETNUM("sectors/track? [%d] ", lp->d_nsectors);
        GETNUM("tracks/cylinder? [%d] ", lp->d_ntracks);
+       lp->d_secpercyl = lp->d_nsectors * lp->d_ntracks;
        GETNUM("sectors/cylinder? [%d] ", lp->d_secpercyl);
        GETNUM("cylinders? [%d] ", lp->d_ncylinders);
        lp->d_npartitions = MAXPARTITIONS;
@@ -137,7 +139,7 @@ editlabel()
 int bootdev;
 
 void 
-main()
+Xmain()
 {
        register bdev  asm("r10");
 
diff --git a/sys/arch/vax/stand/init.c b/sys/arch/vax/stand/init.c
deleted file mode 100644 (file)
index 94c7ad6..0000000
+++ /dev/null
@@ -1,82 +0,0 @@
-/* $NetBSD: init.c,v 1.3 1995/09/16 13:34:21 ragge Exp $ */
-/*
- * Copyright (c) 1995 Ludd, University of Lule}, Sweden. All rights reserved.
- * 
- * This code is derived from software contributed to Ludd by Bertram Barth.
- * 
- * 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 at
- * Ludd, University of Lule}, Sweden and its contributors. 4. The name of the
- * author may not be used to endorse or promote products derived from this
- * software without specific prior written permission
- * 
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
- * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
- * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/* All bugs are subject to removal without further notice */
-
-
-
-#include "lib/libsa/stand.h"
-
-#include "../include/mtpr.h"   /* mfpr(), mtpr() */
-#include "../include/sid.h"    /* cpu_type, cpu_number */
-
-#define NRSP 0                 /* Kludge, must be done before udareg.h */
-#define NCMD 0                 /* includes */
-
-#include "../uba/udareg.h"     /* struct udadevice */
-
-#include "data.h"              /* bootregs[], rpb, bqo */
-
-struct rpb     *rpb;
-struct bqo     *bqo;
-
-int    is_750 = 0, is_mvax = 0;
-
-/*
- * initdata() sets up data gotten from start routines, mostly for uVAX.
- */
-int
-initdata()
-{
-       int i, *tmp;
-
-       cpu_type = mfpr(PR_SID);
-       cpunumber = (mfpr(PR_SID) >> 24) & 0xFF;
-
-       switch (cpunumber) {
-
-       case VAX_78032:
-       case VAX_650:
-       {
-               int             cpu_sie;        /* sid-extension */
-
-               is_mvax = 1;
-               cpu_sie = *((int *) 0x20040004) >> 24;
-               cpu_type |= cpu_sie;
-
-               break;
-       }
-       case VAX_750:
-               is_750 = 1;
-               break;
-       }
-       return 0;
-}
diff --git a/sys/arch/vax/stand/ka410.h b/sys/arch/vax/stand/ka410.h
new file mode 100644 (file)
index 0000000..a022362
--- /dev/null
@@ -0,0 +1,82 @@
+/*     $NetBSD: ka410.h,v 1.1 1996/08/02 11:22:13 ragge Exp $ */
+/*
+ * Copyright (c) 1996 Ludd, University of Lule}, Sweden.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Ludd by
+ * Bertram Barth.
+ *
+ * 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 at Ludd, University of 
+ *      Lule}, Sweden and its contributors.
+ * 4. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+
+/* 
+ * interrupt request-, clear-, and mask register 
+ */
+extern volatile unsigned char *ka410_intreq;
+extern volatile unsigned char *ka410_intclr;
+extern volatile unsigned char *ka410_intmsk;
+
+#define INTR_SR        (1<<7)  /* Serial line receiver or silo full */
+#define INTR_ST        (1<<6)  /* Serial line transmitter done */
+#define INTR_NP        (1<<5)  /* Network controller primary */
+#define INTR_NS        (1<<4)  /* Network controller secondary */
+#define INTR_VF        (1<<3)  /* Video end of frame */
+#define INTR_VS        (1<<2)  /* Video secondary */
+#define INTR_SC        (1<<1)  /* SCSI controller */
+#define INTR_DC        (1<<0)  /* Disk controller */
+
+/*
+ * interrupt vector numbers
+ */
+#define IVEC_BASE      0x20040020
+#define IVEC_SR                0x000002C0
+#define IVEC_ST                0x000002C4
+#define IVEC_NP                0x00000250
+#define IVEC_NS                0x00000254
+#define IVEC_VF                0x00000244
+#define IVEC_VS                0x00000248
+#define IVEC_SC                0x000003F8
+#define IVEC_DC                0x000003FC
+
+/*
+ * Clock-Chip data in NVRAM
+ */
+#define KA410_CPMBX    0x200B0038      /* Console Mailbox (1 byte) */
+#define KA410_CPFLG    0x200B003C      /* Console Program Flags (1 byte) */
+#define KA410_LK201_ID 0x200B0040      /* Keyboard Variation (1 byte) */
+#define KA410_CONS_ID  0x200B0044      /* Console Device Type (1 byte) */
+#define KA410_SCR      0x200B0048      /* Console Scratch RAM */
+#define KA410_TEMP     0x200B0058      /* Used by System Firmware */
+#define KA410_BAT_CHK  0x200B0088      /* Battery Check Data */
+#define KA410_BOOTDEV  0x200B0098      /* Default Boot Device (4 bytes) */
+#define KA410_BOOTFLG  0x200B00A8      /* Default Boot Flags (4 bytes) */
+#define KA410_SCRLEN   0x200B00B8      /* Number of pages of SCR (1 byte) */
+#define KA410_SCSIPORT 0x200B00BC      /* Tape Controller Port Data */
+#define KA410_RESERVED 0x200B00C0      /* Reserved (16 bytes) */
+
diff --git a/sys/arch/vax/stand/mfm.c b/sys/arch/vax/stand/mfm.c
new file mode 100644 (file)
index 0000000..bd27153
--- /dev/null
@@ -0,0 +1,640 @@
+/*     $NetBSD: mfm.c,v 1.1 1996/08/02 11:22:16 ragge Exp $    */
+/*
+ * Copyright (c) 1996 Ludd, University of Lule}, Sweden.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Ludd by
+ * Bertram Barth.
+ *
+ * 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 at Ludd, University of
+ *     Lule}, Sweden and its contributors.
+ * 4. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * ToDo:
+ *
+ * - insert appropriate delays for diskette-drive where needed
+ * - allow more than one sector per diskette-read
+ * - check for and handle bad sectors
+ * - ???
+ */
+
+#include "sys/param.h"
+#include "sys/reboot.h"
+#include "sys/disklabel.h"
+
+#include "lib/libsa/stand.h"
+#include "lib/libsa/ufs.h"
+
+#include "../include/pte.h"
+#include "../include/sid.h"
+#include "../include/mtpr.h"
+#include "../include/reg.h"
+#include "../include/rpb.h"
+
+#include "ka410.h"
+#include "../vsa/hdc9224.h"
+
+#include "data.h"
+#include "vaxstand.h"
+
+#define MAX_WAIT       (1000*1000)     /* # of loop-instructions in seconds */
+
+struct mfm_softc {
+       int             part;
+       int             unit;
+};
+
+int    mfmstrategy(), mfmopen();
+struct disklabel mfmlabel;
+struct mfm_softc mfm_softc;
+char           io_buf[MAXBSIZE];
+
+/*
+ * These should probably be somewhere else, but ka410 is the only
+ * one with mfm disks anyway...
+ */
+volatile unsigned char *ka410_intreq = (void*)0x2008000f;
+volatile unsigned char *ka410_intclr = (void*)0x2008000f;
+volatile unsigned char *ka410_intmsk = (void*)0x2008000c;
+
+static volatile struct hdc9224_DKCreg *dkc = (void *) 0x200c0000;
+static volatile struct hdc9224_UDCreg sreg;    /* input */
+static volatile struct hdc9224_UDCreg creg;    /* output */
+
+/*
+ * we have to wait 0.7 usec between two accesses to any of the
+ * dkc-registers, on a VS2000 with 1 MIPS, this is roughly one
+ * instruction. Thus the loop-overhead will be enough...
+ */
+static int
+sreg_read()
+{
+       int     i;
+       char    *p;
+
+       dkc->dkc_cmd = 0x40;    /* set internal counter to zero */
+       p = (void *) &sreg;
+       for (i = 0; i < 10; i++)
+               *p++ = dkc->dkc_reg;    /* dkc_reg auto-increments */
+}
+
+static int
+creg_write()
+{
+       int     i;
+       char    *p;
+
+       dkc->dkc_cmd = 0x40;    /* set internal counter to zero */
+       p = (void *) &creg;
+       for (i = 0; i < 10; i++)
+               dkc->dkc_reg = *p++;    /* dkc_reg auto-increments */
+}
+
+/*
+ * floppies are handled in a quite strange way by this controller...
+ *
+ * before reading/writing a sector from/to floppy, we use the SEEK/READ_ID
+ * command to place the head at the desired location. Then we wait some
+ * time before issueing the real command in order to let the drive become
+ * ready...
+ */
+int
+mfm_rxprepare()
+{
+       int     error;
+
+       error = mfm_command(DKC_CMD_SEEKREADID | 0x04); /* step=1, verify=0 */
+       if (error) {
+               printf("error while stepping to position %d/%d/%x. Retry...\n",
+                   creg.udc_dsect, creg.udc_dhead, creg.udc_dcyl);
+               error = mfm_command(DKC_CMD_SEEKREADID | 0x04);
+       }
+       return error;
+}
+
+int
+mfm_rxselect(unit)
+       int     unit;
+{
+       int     error;
+
+       /*
+        * bring "creg" in some known-to-work state and
+        * select the drive with the DRIVE SELECT command.
+        */
+       creg.udc_dma7 = 0;
+       creg.udc_dma15 = 0;
+       creg.udc_dma23 = 0;
+       creg.udc_dsect = 1;     /* sectors are numbered 1..15 !!! */
+       creg.udc_dhead = 0;
+       creg.udc_dcyl = 0;
+       creg.udc_scnt = 0;
+
+       creg.udc_rtcnt = UDC_RC_RX33READ;
+       creg.udc_mode = UDC_MD_RX33;
+       creg.udc_term = UDC_TC_FDD;
+
+       /*
+        * this is ...
+        */
+       error = mfm_command(DKC_CMD_DRSEL_RX33 | unit);
+
+       if ((error != 0) || (sreg.udc_dstat & UDC_DS_READY == 0)) {
+               printf("\nfloppy-drive not ready (new floppy inserted?)\n\n");
+
+               creg.udc_rtcnt &= ~UDC_RC_INVRDY;       /* clear INVRDY-flag */
+               error = mfm_command(DKC_CMD_DRSEL_RX33 | unit);
+               if ((error != 0) || (sreg.udc_dstat & UDC_DS_READY == 0)) {
+                       printf("diskette not ready(1): %x/%x\n",
+                              error, sreg.udc_dstat);
+                       printf("floppy-drive offline?\n");
+                       return (-1);
+               }
+               if (sreg.udc_dstat & UDC_DS_TRK00)
+                       error = mfm_command(DKC_CMD_STEPIN_FDD);
+               else
+                       error = mfm_command(DKC_CMD_STEPOUT_FDD);
+
+               /*
+                * now ready should be 0, cause INVRDY is not set
+                * (retrying a command makes this fail...)
+                */
+               if ((error != 0) || (sreg.udc_dstat & UDC_DS_READY == 1)) {
+                       printf("diskette not ready(2): %x/%x\n",
+                              error, sreg.udc_dstat);
+               }
+               creg.udc_rtcnt |= UDC_RC_INVRDY;
+               error = mfm_command(DKC_CMD_DRSEL_RX33 | unit);
+
+               if ((error != 0) || (sreg.udc_dstat & UDC_DS_READY == 0)) {
+                       printf("diskette not ready(3): %x/%x\n",
+                              error, sreg.udc_dstat);
+                       printf("no floppy inserted or floppy-door open\n");
+                       return (-1);
+               }
+               printf("floppy-drive reselected.\n");
+       }
+       return (error);
+}
+
+int
+mfm_rdselect(unit)
+       int     unit;
+{
+       int     error;
+
+       /*
+        * bring "creg" in some known-to-work state and
+        * select the drive with the DRIVE SELECT command.
+        */
+       creg.udc_dma7 = 0;
+       creg.udc_dma15 = 0;
+       creg.udc_dma23 = 0;
+       creg.udc_dsect = 0;     /* sectors are numbered 0..16 */
+       creg.udc_dhead = 0;
+       creg.udc_dcyl = 0;
+       creg.udc_scnt = 0;
+
+       creg.udc_rtcnt = UDC_RC_HDD_READ;
+       creg.udc_mode = UDC_MD_HDD;
+       creg.udc_term = UDC_TC_HDD;
+
+       error = mfm_command(DKC_CMD_DRSEL_HDD | unit);
+
+       return (error);
+}
+
+static int     mfm_retry = 0;
+
+int
+mfm_command(cmd)
+       int     cmd;
+{
+       int     termcode, ready, i;
+
+       creg_write();           /* write command-registers */
+       *ka410_intclr = INTR_DC;
+       dkc->dkc_cmd = cmd;     /* issue command */
+       for (i = 0; i < MAX_WAIT; i++) {
+               if (*ka410_intreq & INTR_DC)    /* wait for interrupt */
+                       break;
+       }
+       if ((*ka410_intreq & INTR_DC) == 0)
+               printf("timeout in mfm_command...\n");
+
+       sreg_read();            /* read status-registers */
+
+       if (dkc->dkc_stat == (DKC_ST_DONE | DKC_TC_SUCCESS))
+               return (0);
+
+       if (sreg.udc_cstat & UDC_CS_ECCERR) {
+               printf(
+"\nspurious(?) ECC/CRC error at s%d/t%d/c%d [s%d/t%d/c%d(%d)]\n",
+                  sreg.udc_csect, sreg.udc_chead, sreg.udc_ccyl,
+                  creg.udc_dsect, creg.udc_dhead, creg.udc_dcyl,creg.udc_scnt);
+               if (sreg.udc_csect != creg.udc_dsect + creg.udc_scnt - 1) {
+                       printf("DMA: %x %x %x [%x]\n",
+                           sreg.udc_dma23, sreg.udc_dma15,
+                           sreg.udc_dma7, 512 * (sreg.udc_csect -
+                           creg.udc_dsect));
+                       creg.udc_scnt = creg.udc_scnt -
+                           (sreg.udc_csect - creg.udc_dsect) - 1;
+                       creg.udc_dsect = sreg.udc_csect + 1;
+                       creg.udc_dma23 = sreg.udc_dma23;
+                       creg.udc_dma15 = sreg.udc_dma15 + 2;
+                       creg.udc_dma7 = 0;
+                       printf("Retry starting from s%d/t%d/c%d (%d). ",
+                           creg.udc_dsect, creg.udc_dhead, creg.udc_dcyl,
+                           creg.udc_scnt);
+               }
+               goto retry;
+       }
+       termcode = (dkc->dkc_stat & DKC_ST_TERMCOD) >> 3;
+       ready = sreg.udc_dstat & UDC_DS_READY;
+
+       printf("cmd:0x%x: termcode=0x%x, status=0x%x, cstat=0x%x, dstat=0x%x\n",
+              cmd, termcode, dkc->dkc_stat, sreg.udc_cstat, sreg.udc_dstat);
+
+       if (dkc->dkc_stat & DKC_ST_BADSECT)
+               printf("bad sector found: s%d/t%d/c%d\n", creg.udc_dsect,
+                      creg.udc_dhead, creg.udc_dcyl);
+retry:
+       if ((mfm_retry == 0) && (sreg.udc_cstat & UDC_CS_RETREQ)) {
+               mfm_retry = 1;
+               printf("Retrying... ");
+               mfm_command(cmd);
+               printf("Retry done.\n");
+               mfm_retry = 0;
+       }
+       return ((dkc->dkc_stat & DKC_ST_TERMCOD) >> 3);
+}
+
+/*
+ * on-disk geometry block
+ */
+#define _aP    __attribute__ ((packed))        /* force byte-alignment */
+
+volatile struct mfm_xbn {
+       char            mbz[10];/* 10 bytes of zero */
+       long xbn_count  _aP;    /* number of XBNs */
+       long dbn_count  _aP;    /* number of DBNs */
+       long lbn_count  _aP;    /* number of LBNs (Logical-Block-Numbers) */
+       long rbn_count  _aP;    /* number of RBNs (Replacement-Block-Numbers) */
+       short           nspt;   /* number of sectors per track */
+       short           ntracks;/* number of tracks */
+       short           ncylinders;     /* number of cylinders */
+       short           precomp;/* first cylinder for write precompensation */
+       short           reduced;/* first cylinder for reduced write current */
+       short           seek_rate;      /* seek rate or zero for buffered
+                                        * seeks */
+       short           crc_eec;/* 0 if CRC is being used or 1 if ECC is
+                                * being used */
+       short           rct;    /* "replacement control table" (RCT) */
+       short           rct_ncopies;    /* number of copies of the RCT */
+       long media_id   _aP;    /* media identifier */
+       short           interleave;     /* sector-to-sector interleave */
+       short           headskew;       /* head-to-head skew */
+       short           cylskew;/* cylinder-to-cylinder skew */
+       short           gap0_size;      /* size of GAP 0 in the MFM format */
+       short           gap1_size;      /* size of GAP 1 in the MFM format */
+       short           gap2_size;      /* size of GAP 2 in the MFM format */
+       short           gap3_size;      /* size of GAP 3 in the MFM format */
+       short           sync_value;     /* sync value used to start a track
+                                        * when formatting */
+       char            reserved[32];   /* reserved for use by the RQDX1/2/3
+                                        * formatter */
+       short           serial_number;  /* serial number */
+       char            fill[412];      /* Filler bytes to the end of the
+                                        * block */
+       short           checksum;       /* checksum over the XBN */
+} mfm_xbn;
+
+display_xbn(p)
+       struct mfm_xbn *p;
+{
+       printf("**DiskData**    XBNs: %d, DBNs: %d, LBNs: %d, RBNs: %d\n",
+           p->xbn_count, p->dbn_count, p->lbn_count, p->rbn_count);
+       printf("sect/track: %d, tracks: %d, cyl: %d, precomp/reduced: %d/%d\n",
+           p->nspt, p->ntracks, p->ncylinders, p->precomp, p->reduced);
+       printf("seek-rate: %d, crc/eec: %s, RCT: %d, RCT-copies: %d\n",
+           p->seek_rate, p->crc_eec ? "EEC" : "CRC", p->rct, p->rct_ncopies);
+       printf("media-ID: 0x%x, interleave: %d, headskew: %d, cylskew: %d\n",
+           &p->media_id, p->interleave, p->headskew, p->cylskew);
+       printf("gap0: %d, gap1: %d, gap2: %d, gap3: %d, sync-value: %d\n",
+           p->gap0_size, p->gap1_size, p->gap2_size, p->gap3_size,
+           p->sync_value);
+       printf("serial: %d, checksum: %d, size: %d, reserved: %32c\n",
+           p->serial_number, p->checksum, sizeof(*p), p->reserved);
+}
+
+mfmopen(f, adapt, ctlr, unit, part)
+       struct open_file *f;
+       int    ctlr, unit, part;
+{
+       char *msg;
+       struct disklabel *lp = &mfmlabel;
+       volatile struct mfm_softc *msc = &mfm_softc;
+       int  i, err;
+
+       bzero(lp, sizeof(struct disklabel));
+       msc->unit = unit;
+       msc->part = part;
+
+       err = mfmstrategy(msc, F_READ, LABELSECTOR, DEV_BSIZE, io_buf, &i);
+       if (err) {
+               printf("reading disklabel: %s\n", strerror(err));
+               return 0;
+       }
+       msg = getdisklabel(io_buf + LABELOFFSET, lp);
+       if (msg)
+               printf("getdisklabel: %s\n", msg);
+
+       f->f_devdata = (void *) msc;
+
+       {
+               int             k;
+               unsigned char  *ucp;
+               struct mfm_xbn *xp;
+
+               /* mfmstrategy(msc, F_READ, -16, 8192, io_buf, &i); */
+               mfmstrategy(msc, F_READ, -16, 512, io_buf, &i);
+               printf("dumping raw disk-block #0:\n");
+               ucp = io_buf;
+               for (k = 0; k < 128; k++) {
+                       if (ucp[k] < 0x10)
+                               printf("0");
+                       printf("%x ", ucp[k]);
+                       if (k % 8 == 7)
+                               printf("  ");
+                       if (k % 16 == 15)
+                               printf("\n");
+               }
+               printf("\n");
+
+               xp = (void *) io_buf;
+               display_xbn(xp);
+               printf("\n");
+
+       }
+
+       if (unit == 2) {        /* floppy! */
+               if (lp->d_ntracks != 2) {
+                       printf("changing number of tracks from %d to %d.\n",
+                              lp->d_ntracks, 2);
+                       lp->d_ntracks = 2;
+               }
+       } else {                /* hard-disk */
+               unsigned short *usp = (void *) io_buf;
+               printf("label says: s/t/c = %d/%d/%d\n",
+                      lp->d_nsectors, lp->d_ntracks, lp->d_ncylinders);
+
+               if (lp->d_nsectors != usp[13]) {
+                       printf("changing number of sectors from %d to %d.\n",
+                              lp->d_nsectors, usp[13]);
+                       lp->d_nsectors = usp[13];
+               }
+               if (lp->d_ntracks != usp[14]) {
+                       printf("changing number of heads/tracks from %d to %d.\n",
+                              lp->d_ntracks, usp[14]);
+                       lp->d_ntracks = usp[14];
+               }
+               if (lp->d_ncylinders != usp[15]) {
+                       printf("changing number of cylinders from %d to %d.\n",
+                              lp->d_ncylinders, usp[15]);
+                       lp->d_ncylinders = usp[15];
+               }
+               lp->d_secpercyl = lp->d_nsectors * lp->d_ntracks;
+       }
+
+       return (0);
+}
+
+mfm_rxstrategy(msc, func, dblk, size, buf, rsize)
+       struct mfm_softc *msc;
+       int     func;
+       daddr_t dblk;
+       char    *buf;
+       int     size, *rsize;
+{
+       struct disklabel *lp;
+       int     block, sect, head, cyl, scount, i, cmd, res, sval;
+
+       lp = &mfmlabel;
+       block = (dblk < 0 ? 0 : dblk + lp->d_partitions[msc->part].p_offset);
+
+       mfm_rxselect(msc->unit);
+
+       /*
+        * if label is empty, assume RX33
+        */
+       if (lp->d_nsectors == 0)
+               lp->d_nsectors = 15;
+       if (lp->d_ntracks == 0)
+               lp->d_ntracks = 2;
+       if (lp->d_secpercyl == 0)
+               lp->d_secpercyl = 30;
+
+       bzero((void *) 0x200D0000, size);
+       scount = size / 512;
+
+       while (scount) {
+               /*
+                * prepare drive/operation parameter
+                */
+               cyl = block / lp->d_secpercyl;
+               sect = block % lp->d_secpercyl;
+               head = sect / lp->d_nsectors;
+               sect = sect % lp->d_nsectors;
+
+               /*
+                * *rsize = 512;                /* one sector after the other
+                * ...
+                */
+               *rsize = 512 * min(scount, lp->d_nsectors - sect);
+
+               /*
+                * now initialize the register values ...
+                */
+               creg.udc_dma7 = 0;
+               creg.udc_dma15 = 0;
+               creg.udc_dma23 = 0;
+
+               creg.udc_dsect = sect + 1;      /* sectors are numbered 1..15
+                                                * !!! */
+               head |= (cyl >> 4) & 0x70;
+               creg.udc_dhead = head;
+               creg.udc_dcyl = cyl;
+
+               creg.udc_scnt = *rsize / 512;
+
+               if (func == F_WRITE) {
+                       creg.udc_rtcnt = UDC_RC_RX33WRT;
+                       creg.udc_mode = UDC_MD_RX33;
+                       creg.udc_term = UDC_TC_FDD;
+
+                       mfm_rxprepare();
+                       /* copy from buf */
+                       bcopy(buf, (void *) 0x200D0000, *rsize);
+                       res = mfm_command(DKC_CMD_WRITE_RX33);
+               } else {
+                       creg.udc_rtcnt = UDC_RC_RX33READ;
+                       creg.udc_mode = UDC_MD_RX33;
+                       creg.udc_term = UDC_TC_FDD;
+
+                       mfm_rxprepare();
+                       /* clear disk buffer */
+                       bzero((void *) 0x200D0000, *rsize);
+                       res = mfm_command(DKC_CMD_READ_RX33);
+                       /* copy to buf */
+                       bcopy((void *) 0x200D0000, buf, *rsize);
+               }
+
+               scount -= *rsize / 512;
+               block += *rsize / 512;
+               buf += *rsize;
+       }
+
+       *rsize = size;
+       return 0;
+}
+
+mfm_rdstrategy(msc, func, dblk, size, buf, rsize)
+       struct mfm_softc *msc;
+       int     func;
+       daddr_t dblk;
+       char    *buf;
+       int     size, *rsize;
+{
+       struct disklabel *lp;
+       int     block, sect, head, cyl, scount, i, cmd, res, sval;
+
+       lp = &mfmlabel;
+       block = (dblk < 0 ? 0 : dblk + lp->d_partitions[msc->part].p_offset);
+
+       /*
+        * if label is empty, assume RD32 (XXX this must go away!!!)
+        */
+       if (lp->d_nsectors == 0)
+               lp->d_nsectors = 17;
+       if (lp->d_ntracks == 0)
+               lp->d_ntracks = 6;
+       if (lp->d_secpercyl == 0)
+               lp->d_secpercyl = 102;
+
+       mfm_rdselect(msc->unit);
+
+       bzero((void *) 0x200D0000, size);
+       scount = size / 512;
+
+       while (scount) {
+               /*
+                * prepare drive/operation parameter
+                */
+               cyl = block / lp->d_secpercyl;
+               sect = block % lp->d_secpercyl;
+               head = sect / lp->d_nsectors;
+               sect = sect % lp->d_nsectors;
+
+               if (dblk < 0) {
+                       printf("using raw diskblock-data!\n");
+                       printf("block %d, dblk %d ==> cyl %d, head %d, sect %d\n",
+                              block, dblk, cyl, sect, head);
+               } else
+                       cyl += 1;       /* first cylinder is reserved for
+                                        * controller! */
+
+               *rsize = 512 * min(scount, lp->d_nsectors - sect);
+               /*
+                * now re-initialize the register values ...
+                */
+               creg.udc_dma7 = 0;
+               creg.udc_dma15 = 0;
+               creg.udc_dma23 = 0;
+
+               creg.udc_dsect = sect;
+               head |= (cyl >> 4) & 0x70;
+               creg.udc_dhead = head;
+               creg.udc_dcyl = cyl;
+
+               creg.udc_scnt = *rsize / 512;
+
+               if (func == F_WRITE) {
+                       creg.udc_rtcnt = UDC_RC_HDD_WRT;
+                       creg.udc_mode = UDC_MD_HDD;
+                       creg.udc_term = UDC_TC_HDD;
+                       cmd = DKC_CMD_WRITE_HDD;
+
+                       bcopy(buf, (void *) 0x200D0000, *rsize);
+                       res = mfm_command(cmd);
+               } else {
+                       creg.udc_rtcnt = UDC_RC_HDD_READ;
+                       creg.udc_mode = UDC_MD_HDD;
+                       creg.udc_term = UDC_TC_HDD;
+                       cmd = DKC_CMD_READ_HDD;
+
+                       bzero((void *) 0x200D0000, *rsize);
+                       res = mfm_command(cmd);
+                       bcopy((void *) 0x200D0000, buf, *rsize);
+               }
+
+               scount -= *rsize / 512;
+               block += *rsize / 512;
+               buf += *rsize;
+       }
+
+       /*
+        * unselect the drive ...
+        */
+       mfm_command(DKC_CMD_DRDESELECT);
+
+       *rsize = size;
+       return 0;
+}
+
+int
+mfmstrategy(msc, func, dblk, size, buf, rsize)
+       struct mfm_softc *msc;
+       int     func;
+       daddr_t dblk;
+       char    *buf;
+       int     size, *rsize;
+{
+       int     res = -1;
+
+       switch (msc->unit) {
+       case 0:
+       case 1:
+               res = mfm_rdstrategy(msc, func, dblk, size, buf, rsize);
+               break;
+       case 2:
+               res = mfm_rxstrategy(msc, func, dblk, size, buf, rsize);
+               break;
+       default:
+               printf("invalid unit %d in mfmstrategy()\n");
+       }
+       return (res);
+}
index 43e368f..722b19d 100644 (file)
@@ -1,4 +1,4 @@
-/*     $NetBSD: ra.c,v 1.4 1996/02/17 18:23:23 ragge Exp $ */
+/*     $NetBSD: ra.c,v 1.5 1996/08/02 11:22:18 ragge Exp $ */
 /*
  * Copyright (c) 1995 Ludd, University of Lule}, Sweden.
  * All rights reserved.
@@ -31,8 +31,8 @@
 
  /* All bugs are subject to removal without further notice */
                
-#define NRSP 0 /* Kludge */
-#define NCMD 0 /* Kludge */
+#define NRSP 1 /* Kludge */
+#define NCMD 1 /* Kludge */
 
 #include "sys/param.h"
 #include "sys/disklabel.h"
 
 #include "../include/pte.h"
 #include "../include/macros.h"
+#include "../include/sid.h"
+
 #include "../uba/ubareg.h"
 #include "../uba/udareg.h"
-#include "../vax/mscp.h"
+
+#include "../mscp/mscp.h"
+#include "../mscp/mscpreg.h"
+
+#include "../bi/bireg.h"
+#include "../bi/kdbreg.h"
 
 #include "vaxstand.h"
 
@@ -62,10 +69,13 @@ struct ra_softc {
        int ubaddr;
        int part;
        int unit;
+       unsigned short *ra_ip;
+       unsigned short *ra_sa;
+       unsigned short *ra_sw;
 };
 
 volatile struct uda {
-        struct  uda1ca uda_ca;           /* communications area */
+        struct  mscp_1ca uda_ca;           /* communications area */
         struct  mscp uda_rsp;     /* response packets */
         struct  mscp uda_cmd;     /* command packets */
 } uda;
@@ -81,53 +91,84 @@ raopen(f, adapt, ctlr, unit, part)
         int ctlr, unit, part;
 {
        char *msg;
-       struct disklabel *lp=&ralabel;
-       volatile struct ra_softc *ra=&ra_softc;
-       volatile struct uba_regs *mr=(void *)ubaaddr[adapt];
+       struct disklabel *lp = &ralabel;
+       volatile struct ra_softc *ra = &ra_softc;
+       volatile struct uba_regs *mr = (void *)ubaaddr[adapt];
        volatile u_int *nisse;
-       unsigned short johan;
+       unsigned short johan, johan2;
        int i,err;
 
-       if(adapt>nuba) return(EADAPT);
-       if(ctlr>nuda) return(ECTLR);
        bzero(lp, sizeof(struct disklabel));
-       ra->udaddr=uioaddr[adapt]+udaaddr[ctlr];
-       ra->ubaddr=(int)mr;
-       ra->unit=unit;
+       ra->unit = unit;
        ra->part = part;
-       udacsr=(void*)ra->udaddr;
-       nisse=(u_int *)&mr->uba_map[0];
-       nisse[494]=PG_V|(((u_int)&uda)>>9);
-       nisse[495]=nisse[494]+1;
-       ubauda=(void*)0x3dc00+(((u_int)(&uda))&0x1ff);
+       if (vax_cputype != VAX_8200) {
+               if (adapt > nuba)
+                       return(EADAPT);
+               if (ctlr > nuda)
+                       return(ECTLR);
+               nisse = (u_int *)&mr->uba_map[0];
+               nisse[494] = PG_V | (((u_int)&uda) >> 9);
+               nisse[495] = nisse[494] + 1;
+               udacsr = (void*)uioaddr[adapt] + udaaddr[ctlr];
+               ubauda = (void*)0x3dc00 + (((u_int)(&uda))&0x1ff);
+               johan = (((u_int)ubauda) & 0xffff) + 8;
+               johan2 = 3;
+               ra->ra_ip = (short *)&udacsr->udaip;
+               ra->ra_sa = ra->ra_sw = (short *)&udacsr->udasa;
+               ra->udaddr = uioaddr[adapt] + udaaddr[ctlr];
+               ra->ubaddr = (int)mr;
+               *ra->ra_ip = 0; /* Start init */
+       } else {
+               struct bi_node *bi = (void *)biaddr[adapt];
+               struct kdb_regs *kb = (void *)&bi[ctlr];
+               volatile int i = 10000;
+
+               ra->ra_ip = &kb->kdb_ip;
+               ra->ra_sa = &kb->kdb_sa;
+               ra->ra_sw = &kb->kdb_sw;
+               johan = ((u_int)&uda.uda_ca.ca_rspdsc) & 0xffff;
+               johan2 = (((u_int)&uda.uda_ca.ca_rspdsc) & 0xffff0000) >> 16;
+               kb->kdb_bi.bi_csr |= BICSR_NRST;
+               while (i--) /* Need delay??? */
+                       ;
+               kb->kdb_bi.bi_ber = ~(BIBER_MBZ|BIBER_NMR|BIBER_UPEN);/* ??? */
+               ubauda = &uda;
+       }
+
        /* Init of this uda */
-       udacsr->udaip=0; /* Start init */
-       while((udacsr->udasa&UDA_STEP1) == 0);
-       udacsr->udasa=0x8000;
-       while((udacsr->udasa&UDA_STEP2) == 0);
-       johan=(((u_int)ubauda)&0xffff)+8;
-       udacsr->udasa=johan;
-       while((udacsr->udasa&UDA_STEP3) == 0);
-       udacsr->udasa=3;
-       while((udacsr->udasa&UDA_STEP4) == 0);
-       udacsr->udasa=0x0001;
-       uda.uda_ca.ca_rspdsc=(int)&ubauda->uda_rsp.mscp_cmdref;
-       uda.uda_ca.ca_cmddsc=(int)&ubauda->uda_cmd.mscp_cmdref;
+       while ((*ra->ra_sa & MP_STEP1) == 0)
+               ;
+
+       *ra->ra_sw = 0x8000;
+       while ((*ra->ra_sa & MP_STEP2) == 0)
+               ;
+
+       *ra->ra_sw = johan;
+       while ((*ra->ra_sa & MP_STEP3) == 0)
+               ;
+
+       *ra->ra_sw = johan2;
+       while ((*ra->ra_sa & MP_STEP4) == 0)
+               ;
+
+       *ra->ra_sw = 0x0001;
+       uda.uda_ca.ca_rspdsc = (int)&ubauda->uda_rsp.mscp_cmdref;
+       uda.uda_ca.ca_cmddsc = (int)&ubauda->uda_cmd.mscp_cmdref;
+
        command(M_OP_SETCTLRC);
-       uda.uda_cmd.mscp_unit=ra->unit;
+       uda.uda_cmd.mscp_unit = ra->unit;
        command(M_OP_ONLINE);
 
-       err=rastrategy(ra,F_READ, LABELSECTOR, DEV_BSIZE, io_buf, &i);
+       err = rastrategy(ra,F_READ, LABELSECTOR, DEV_BSIZE, io_buf, &i);
        if(err){
                printf("reading disklabel: %s\n",strerror(err));
                return 0;
        }
 
-       msg=getdisklabel(io_buf+LABELOFFSET, lp);
-       if(msg) {
-               printf("getdisklabel: %s\n",msg);
-       }
-       f->f_devdata=(void *)ra;
+       msg = getdisklabel(io_buf+LABELOFFSET, lp);
+       if (msg)
+               printf("getdisklabel: %s\n", msg);
+       f->f_devdata = (void *)ra;
        return(0);
 }
 
@@ -136,13 +177,14 @@ command(cmd)
 {
        volatile int hej;
 
-       uda.uda_cmd.mscp_opcode=cmd;
-       uda.uda_cmd.mscp_msglen=MSCP_MSGLEN;
-       uda.uda_rsp.mscp_msglen=MSCP_MSGLEN;
+       uda.uda_cmd.mscp_opcode = cmd;
+       uda.uda_cmd.mscp_msglen = MSCP_MSGLEN;
+       uda.uda_rsp.mscp_msglen = MSCP_MSGLEN;
        uda.uda_ca.ca_rspdsc |= MSCP_OWN|MSCP_INT;
        uda.uda_ca.ca_cmddsc |= MSCP_OWN|MSCP_INT;
-       hej=udacsr->udaip;
-       while(uda.uda_ca.ca_rspdsc<0);
+       hej = *ra_softc.ra_ip;
+       while(uda.uda_ca.ca_rspdsc<0)
+               ;
 
 }
 
@@ -161,20 +203,23 @@ rastrategy(ra, func, dblk, size, buf, rsize)
        volatile int hej;
 
 
-       ur = (void *)ra->ubaddr;
-       udadev = (void*)ra->udaddr;
-       ptmapp = (u_int *)&ur->uba_map[0];
-       lp = &ralabel;
+       if (vax_cputype != VAX_8200) {
+               ur = (void *)ra->ubaddr;
+               udadev = (void*)ra->udaddr;
+               ptmapp = (u_int *)&ur->uba_map[0];
 
-       pfnum = (u_int)buf >> PGSHIFT;
+               pfnum = (u_int)buf >> PGSHIFT;
 
-       for(mapnr = 0, nsize = size; (nsize + NBPG) > 0; nsize -= NBPG)
-               ptmapp[mapnr++] = PG_V | pfnum++;
+               for(mapnr = 0, nsize = size; (nsize + NBPG) > 0; nsize -= NBPG)
+                       ptmapp[mapnr++] = PG_V | pfnum++;
+               uda.uda_cmd.mscp_seq.seq_buffer = ((u_int)buf) & 0x1ff;
+       } else
+               uda.uda_cmd.mscp_seq.seq_buffer = ((u_int)buf);
 
+       lp = &ralabel;
        uda.uda_cmd.mscp_seq.seq_lbn =
            dblk + lp->d_partitions[ra->part].p_offset;
        uda.uda_cmd.mscp_seq.seq_bytecount = size;
-       uda.uda_cmd.mscp_seq.seq_buffer = ((u_int)buf) & 0x1ff;
        uda.uda_cmd.mscp_unit = ra->unit;
        if (func == F_WRITE)
                command(M_OP_WRITE);
diff --git a/sys/arch/vax/stand/rom.c b/sys/arch/vax/stand/rom.c
new file mode 100644 (file)
index 0000000..f299f50
--- /dev/null
@@ -0,0 +1,123 @@
+/*     $NetBSD: rom.c,v 1.1 1996/08/02 11:22:21 ragge Exp $ */
+/*
+ * Copyright (c) 1996 Ludd, University of Lule}, Sweden.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Ludd by
+ * Bertram Barth.
+ *
+ * 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 at Ludd, University of 
+ *      Lule}, Sweden and its contributors.
+ * 4. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "sys/param.h"
+#include "sys/reboot.h"
+#include "sys/disklabel.h"
+
+#include "lib/libsa/stand.h"
+#include "lib/libsa/ufs.h"
+
+#include "../include/pte.h"
+#include "../include/sid.h"
+#include "../include/mtpr.h"
+#include "../include/reg.h"
+#include "../include/rpb.h"
+
+#include "data.h"
+#include "vaxstand.h"
+
+extern unsigned *bootregs;
+extern struct rpb *rpb;
+
+struct rom_softc {
+       int part;
+       int unit;
+};
+
+int    romstrategy(), romopen();
+struct disklabel romlabel;
+struct  rom_softc rom_softc;
+char   io_buf[MAXBSIZE];
+
+romopen(f, adapt, ctlr, unit, part)
+       struct open_file *f;
+        int ctlr, unit, part;
+{
+       char *msg;
+       struct disklabel *lp = &romlabel;
+       volatile struct rom_softc *rsc = &rom_softc;
+       int i,err;
+
+       bootregs[11] = XXRPB;
+       rpb = (void*)XXRPB;
+       bqo = (void*)rpb->iovec;
+
+       if (rpb->unit > 0 && (rpb->unit % 100) == 0) {
+               printf ("changing rpb->unit from %d ", rpb->unit);
+               rpb->unit /= 100;
+               printf ("to %d\n", rpb->unit);
+       }
+
+       bzero(lp, sizeof(struct disklabel));
+       rsc->unit = unit;
+       rsc->part = part;
+
+       err = romstrategy(rsc, F_READ, LABELSECTOR, DEV_BSIZE, io_buf, &i);
+       if (err) {
+               printf("reading disklabel: %s\n",strerror(err));
+               return 0;
+       }
+       msg = getdisklabel(io_buf+LABELOFFSET, lp);
+       if (msg)
+               printf("getdisklabel: %s\n",msg);
+       f->f_devdata = (void*)rsc;
+       return(0);
+}
+
+romstrategy (rsc, func, dblk, size, buf, rsize)
+       struct  rom_softc *rsc;
+       int     func;
+       daddr_t dblk;
+       char    *buf;
+       int     size, *rsize;
+{
+       struct  disklabel *lp;
+       int     block;
+
+       lp = &romlabel;
+       block = dblk + lp->d_partitions[rsc->part].p_offset;
+       if (rsc->unit >= 0 && rsc->unit < 10)
+               rpb->unit = rsc->unit;
+
+       if (func == F_WRITE)
+               romwrite_uvax(block, size, buf, bootregs);
+       else
+               romread_uvax(block, size, buf, bootregs);
+
+       *rsize = size;
+       return 0;
+}
+
index 9662807..ff893c4 100644 (file)
@@ -1,4 +1,4 @@
-/*     $NetBSD: romread.s,v 1.3 1995/09/16 16:20:18 ragge Exp $ */
+/*     $NetBSD: romread.s,v 1.4 1996/08/02 11:22:24 ragge Exp $ */
 /*
  * Copyright (c) 1995 Ludd, University of Lule}, Sweden.
  * All rights reserved.
 
 #include "../include/asm.h"
 
-/*
- * read630 (int block, int *regs)
- */
-ENTRY(read630, 0xFFE)
-       pushl   $0                      # base of rpb
-       pushl   $0                      # virtual-flag 
-       pushl   $33                     # read-logical-block
-       pushl   12(ap)                  # lbn to start reading
-       pushl   8(ap)                   # number of bytes to read
-       pushl   4(ap)                   # buffer-address 
-       calls   $6, (r6)        # call the qio-routine
-       halt
-       ret                     # r0 holds the result
-
 /*
  * read750 (int block, int *regs)
  */
@@ -72,9 +58,9 @@ ENTRY(read750, 0xFFE)
        ret
 
 /*
- * bulkread630 (int lbn, int size, void *buf, int *regs)
+ * romread_uvax (int lbn, int size, void *buf, int *regs)
  */
-ENTRY(bulkread630, 0xFFE)
+ENTRY(romread_uvax, 0xFFE)
        movl    16(ap), r11     # array of bootregs
        movl    44(r11), r11    # restore boot-contents of r11 (rpb)
        movl    52(r11), r7     # load iovec/bqo into r7
@@ -87,3 +73,21 @@ ENTRY(bulkread630, 0xFFE)
        pushl   12(ap)                  # buffer-address 
        calls   $6, (r6)        # call the qio-routine
        ret                     # r0 holds the result
+
+/*
+ * romwrite_uvax (int lbn, int size, void *buf, int *regs)
+ */
+ENTRY(romwrite_uvax, 0xFFE)
+       movl    16(ap), r11     # array of bootregs
+       movl    44(r11), r11    # restore boot-contents of r11 (rpb)
+       movl    52(r11), r7     # load iovec/bqo into r7
+       addl3   (r7), r7, r6    # load qio into r6
+       pushl   r11                     # base of rpb
+       pushl   $0                      # virtual-flag 
+       pushl   $32                     # write-logical-block
+       pushl   4(ap)                   # lbn to start reading
+       pushl   8(ap)                   # number of bytes to read
+       pushl   12(ap)                  # buffer-address 
+       calls   $6, (r6)        # call the qio-routine
+       ret                     # r0 holds the result
+
diff --git a/sys/arch/vax/stand/samachdep.h b/sys/arch/vax/stand/samachdep.h
new file mode 100644 (file)
index 0000000..829a17d
--- /dev/null
@@ -0,0 +1,42 @@
+/*     $NetBSD: samachdep.h,v 1.1 1996/08/02 11:22:28 ragge Exp $      */
+
+/*
+ * Copyright (c) 1982, 1990, 1993
+ *     The Regents of the University of California.  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.
+ *
+ *     @(#)samachdep.h 8.1 (Berkeley) 6/10/93
+ */
+
+#define        NSCSI           1
+#define NSD            8
+
+extern int howto;
+extern unsigned int bootdev;
diff --git a/sys/arch/vax/stand/scsi_hi.c b/sys/arch/vax/stand/scsi_hi.c
new file mode 100644 (file)
index 0000000..0102123
--- /dev/null
@@ -0,0 +1,297 @@
+/*     $NetBSD: scsi_hi.c,v 1.1 1996/08/02 11:22:31 ragge Exp $        */
+
+/****************************************************************************
+ * NS32K Monitor SCSI high-level driver
+ * Bruce Culbertson
+ * 8 March 1990
+ * (This source is public domain source)
+ *
+ * There are three monitor SCSI commands.  "Read" and "write" I think are
+ * fairly self explanatory once you read the help messages.  They, in fact,
+ * execute the "extended read", "extended write", and "request sense"
+ * commands from the SCSI standard.
+ * 
+ * "Raw" lets you execute any SCSI command but you need a SCSI reference to
+ * know what the commands are and what their formats are.  The SCSI
+ * standard specifies that there are six buffers which, for example, hold a
+ * SCSI command or are the source or destination for data.  You provide
+ * "raw" with an array of pointers to the six buffers.  Using "edit", you
+ * can enter a SCSI command somewhere in memory and you can create the
+ * array of pointers.  The array must actually be eight entries long; two
+ * entries are not used.  By typing "raw <array address>", the SCSI command
+ * is executed.
+ * 
+ * By the way, "read", "write", and "raw" talk only to the DP8490 SCSI
+ * controller.  I have not had time to read the Adaptec data sheet and
+ * write a driver for it.
+ ****************************************************************************/
+#include "so.h"
+
+#define OK                     0
+#define NOT_OK                 OK+1
+#define        PRIVATE
+#define PUBLIC
+#define U8                     unsigned char
+
+long   scsiAdr = DEFAULT_SCSI_ADR,     /* default SCSI address */
+       scsiLun = DEFAULT_SCSI_LUN;
+
+struct cmd_desc {                      /* SCSI command description */
+  const U8     *cmd;                   /* command string */
+  const U8     *odata;                 /* data to output, if any */
+  const struct cmd_desc *chain;                /* next command */
+};
+
+struct drive {                         /* SCSI drive description */
+  U8   adr, lun;                       /* SCSI address and LUN */
+  U8   flags;                          /* drive characteristics */
+  U8   stat;                           /* drive state */
+  const struct cmd_desc *init;         /* list of initialize commands */
+};
+/* for drive.flags */
+#define EXTENDED_RDWR          1       /* device does extended read, write */
+#define EXTENDED_SENSE         2       /* device does extended sense */
+/* for drive.stat */
+#define INITIALIZED            1       /* device is initialized */
+
+PRIVATE struct drive drive_tbl[] = {
+#if 1
+  {0, 0, 0, 1, 0},
+  {1, 0, 0, 1, 0},
+  {2, 0, 0, 1, 0},
+  {3, 0, 0, 1, 0},
+  {4, 0, 0, 1, 0},
+  {5, 0, 0, 1, 0},
+  {6, 0, 0, 1, 0},
+  {7, 0, 0, 1, 0},
+#else
+  {0, 0, EXTENDED_RDWR | EXTENDED_SENSE, 1, 0},
+  {1, 0, EXTENDED_RDWR | EXTENDED_SENSE, 1, 0},
+  {2, 0, EXTENDED_RDWR | EXTENDED_SENSE, 1, 0},
+  {3, 0, EXTENDED_RDWR | EXTENDED_SENSE, 1, 0},
+  {4, 0, EXTENDED_RDWR | EXTENDED_SENSE, 1, 0},
+  {5, 0, EXTENDED_RDWR | EXTENDED_SENSE, 1, 0},
+  {6, 0, EXTENDED_RDWR | EXTENDED_SENSE, 1, 0},
+  {7, 0, EXTENDED_RDWR | EXTENDED_SENSE, 1, 0},
+#endif
+};
+#define DRV_TBL_SZ (sizeof (drive_tbl) / sizeof (struct drive))
+
+/* Round up to multiple of four since SCSI transfers are always multiples
+ * of four bytes.
+ */
+#define CMD_LEN                12              /* longest SCSI command */
+#define SENSE_LEN      24              /* extended sense length */
+#define MSG_LEN                4
+#define STAT_LEN       4
+
+#define MAX_SCSI_RETRIES       6
+#define CMD_IX         2
+#define CMD_SENSE      0x03
+#define CMD_READ       0x08
+#define CMD_WRITE      0x0a
+#define CMD_XREAD      0x28
+#define CMD_XWRITE     0x2a
+PRIVATE U8             cmd_buf[CMD_LEN];
+
+#define SENSE_KEY      2
+#define NO_SENSE       0
+#define RECOVERY_ERR   1
+#define UNIT_ATTN      6
+#define ADD_SENSE_CODE 12
+#define SENSE_RST      0x29
+PRIVATE        U8              sense_buf[SENSE_LEN];
+
+#define CHECK_CONDITION        2
+#define STAT_IX                3
+#define STAT_MASK      0x1f
+PRIVATE U8             stat_buf[STAT_LEN];
+#define IMSG_IX                7
+PRIVATE U8             msg_buf[MSG_LEN];
+
+#define ODATA_IX       0
+#define IDATA_IX       1
+PRIVATE struct scsi_args scsi_args;
+
+/*===========================================================================*
+ *                             sc_rdwt                                      * 
+ *===========================================================================*/
+/* Carry out a read or write request for the SCSI disk. */
+PRIVATE int
+sc_rdwt(op, block, ram_adr, len, sc_adr, lun)
+long block, ram_adr, len, sc_adr, lun;
+{
+  int retries, ret;
+  U8 *p;
+  struct drive *dp;
+
+  printf ("sc_rdwt: op %x, block %d, ram %x, len %d, sc_adr %d, lun %d\n",
+         op, block, ram_adr, len, sc_adr, lun);
+
+  /* get drive characteristics */
+  for (dp = drive_tbl; dp < drive_tbl + DRV_TBL_SZ - 1; ++dp)
+    if (dp->adr == sc_adr && dp->lun == lun) break;
+  if (dp == drive_tbl + DRV_TBL_SZ - 1) {
+    dp->adr = sc_adr;                  /* have default, set adr, lun */
+    dp->lun = lun;
+  }
+  for (retries = 0; retries < MAX_SCSI_RETRIES; ++retries) {
+    if (dp->init && !(dp->stat & INITIALIZED))
+      if (OK != sc_initialize (dp)) {
+       printf("SCSI cannot initialize device\n");
+       return NOT_OK;
+      }
+    p = cmd_buf;                       /* build SCSI command */
+    if (dp->flags & EXTENDED_RDWR) {   /* use extended commands */
+      *p++ = (op == DISK_READ)? CMD_XREAD: CMD_XWRITE;
+      *p++ = lun << 5;
+      *p++ = (block >> 24) & 0xff;
+      *p++ = (block >> 16) & 0xff;
+      *p++ = (block >> 8) & 0xff;
+      *p++ = (block >> 0) & 0xff;
+      *p++ = 0;
+      *p++ = (len >> 8) & 0xff;
+      *p++ = (len >> 0) & 0xff;
+      *p = 0;
+    } else {                           /* use short (SASI) commands */
+      *p++ = (op == DISK_READ)? CMD_READ: CMD_WRITE;
+      *p++ = (lun << 5) | ((block >> 16) & 0x1f);
+      *p++ = (block >> 8) & 0xff;
+      *p++ = (block >> 0) & 0xff;
+      *p++ = len;
+      *p = 0;
+    }
+    if (op == DISK_READ)
+      ret = exec_scsi_hi (cmd_buf, (U8 *)ram_adr, (U8 *)0, dp);
+    else
+      ret = exec_scsi_hi (cmd_buf, (U8 *)0, (U8 *)ram_adr, dp);
+    if (OK == ret) return OK;
+    dp->stat &= ~INITIALIZED;
+  }
+  printf("SCSI %s, block %d failed even after retries\n",
+    op == DISK_READ? "READ": "WRITE", block);
+  return NOT_OK;
+}
+
+/*===========================================================================*
+ *                             sc_initialize                                *
+ *===========================================================================*/
+/* Execute the list of initialization commands for the given drive.
+ */
+int
+sc_initialize (dp)
+struct drive *dp;
+{
+  const struct cmd_desc *cp;
+
+  for (cp = dp->init; cp != 0; cp = cp->chain)
+    if (OK != exec_scsi_hi (cp->cmd, 0, cp->odata, dp)) {
+      dp->stat &= ~INITIALIZED;
+      return NOT_OK;
+    }
+  dp->stat |= INITIALIZED;
+  return OK;
+}
+
+/*===========================================================================*
+ *                             exec_scsi_hi                                 * 
+ *===========================================================================*/
+/* Execute a "high-level" SCSI command.  This means execute a low level
+ * command and, if it fails, execute a request sense to find out why.
+ */
+PRIVATE int
+exec_scsi_hi(cmd, data_in, data_out, dp)
+U8 *cmd, *data_out, *data_in;
+struct drive *dp;
+{
+  scsi_args.ptr[CMD_IX] = (long)cmd;
+  scsi_args.ptr[STAT_IX] = (long)stat_buf;
+  scsi_args.ptr[IMSG_IX] = (long)msg_buf;
+  scsi_args.ptr[IDATA_IX] = (long)data_in;
+  scsi_args.ptr[ODATA_IX] = (long)data_out;
+  if (OK != exec_scsi_low (&scsi_args, dp->adr))
+    return NOT_OK;
+  *stat_buf &= STAT_MASK;              /* strip off lun */
+  if (*stat_buf == 0)
+    /* Success -- this should be the usual case */
+    return OK;
+  if (*stat_buf != CHECK_CONDITION) {
+    /* do not know how to handle this so return error */
+    printf("SCSI device returned unknown status: %d\n", *stat_buf);
+    return NOT_OK;
+  }
+  /* Something funny happened, need to execute request-sense command
+   * to learn more.
+   */
+  if (OK == get_sense(dp))
+    /* Something funny happened, but the device recovered from it and
+     * the command succeeded.
+     */
+    return OK;
+  return NOT_OK;
+}
+
+/*===========================================================================*
+ *                             get_sense                                    * 
+ *===========================================================================*/
+/* Execute a "request sense" SCSI command and check results.  When a SCSI
+ * command returns CHECK_CONDITION, a request-sense command must be executed.
+ * A request-sense command provides information about the original command.
+ * The original command might have succeeded, in which case it does not
+ * need to be retried and OK is returned.  Examples: read error corrected
+ * with error correction code, or error corrected by retries performed by
+ * the SCSI device.  The original command also could have failed, in
+ * which case NOT_OK is returned.
+ */
+#define XLOGICAL_ADR   \
+  (sense_buf[3]<<24 | sense_buf[4]<<16 | sense_buf[5]<<8 | sense_buf[6])
+#define LOGICAL_ADR    \
+  (sense_buf[1]<<16 | sense_buf[2]<<8 | sense_buf[3])
+
+PRIVATE int
+get_sense (dp)
+struct drive *dp;
+{
+  U8 *p;
+
+  p = cmd_buf;                         /* build SCSI command */
+  *p++ = CMD_SENSE;
+  *p++ = dp->lun << 5;
+  *p++ = 0;
+  *p++ = 0;
+  *p++ = (dp->flags & EXTENDED_SENSE)? SENSE_LEN: 0;
+  *p = 0;
+  scsi_args.ptr[IDATA_IX] = (long)sense_buf;
+  scsi_args.ptr[ODATA_IX] = 0;
+  scsi_args.ptr[CMD_IX] = (long)cmd_buf;
+  scsi_args.ptr[STAT_IX] = (long)stat_buf;
+  scsi_args.ptr[IMSG_IX] = (long)msg_buf;
+  if (OK != exec_scsi_low (&scsi_args, dp->adr)) {
+    printf("SCSI SENSE command failed\n");
+    return NOT_OK;
+  }
+  if ((*stat_buf & STAT_MASK) != 0) {
+    printf("SCSI SENSE returned wrong status %d\n", *stat_buf);
+    return NOT_OK;
+  }
+  if (0 == (dp->flags & EXTENDED_SENSE)) {
+    printf("SCSI request sense, code 0x%x, log_adr 0x%x\n",
+      sense_buf[0], LOGICAL_ADR);
+    return NOT_OK;
+  }
+  switch (sense_buf[SENSE_KEY] & 0xf) {
+    case NO_SENSE:
+    case UNIT_ATTN:                    /* reset */
+      return NOT_OK;                   /* must retry command */
+    case RECOVERY_ERR:
+      /* eventually, we probably do not want to hear about these. */
+      printf("SCSI ok with recovery, code 0x%x, logical address 0x%x\n",
+            sense_buf[ADD_SENSE_CODE], XLOGICAL_ADR);
+      return OK;                       /* orig command was ok with recovery */
+    default:
+      printf("SCSI failure: key 0x%x code 0x%x log adr 0x%x sense buf 0x%x\n",
+            sense_buf[SENSE_KEY], sense_buf[ADD_SENSE_CODE],
+       XLOGICAL_ADR, sense_buf);
+      return NOT_OK;                   /* orig command failed */
+  }
+}
diff --git a/sys/arch/vax/stand/scsi_low.c b/sys/arch/vax/stand/scsi_low.c
new file mode 100644 (file)
index 0000000..a86a82d
--- /dev/null
@@ -0,0 +1,479 @@
+/*     $NetBSD: scsi_low.c,v 1.1 1996/08/02 11:22:34 ragge Exp $       */
+
+/****************************************************************************
+ * NS32K Monitor SCSI low-level driver
+ * Bruce Culbertson
+ * 8 March 1990
+ * (This source is public domain source.)
+ *
+ * Originally written by Bruce Culbertson for a ns32016 port of Minix.
+ * Adapted from that for the pc532 (ns32632) monitor.
+ * Adapted from that for NetBSD/pc532 by Philip L. Bunde.
+ *
+ * Do not use DMA -- makes 32016 and pc532 versions compatible.
+ * Do not use interrupts -- makes it harder for the user code to bomb
+ * this code.
+ ****************************************************************************/
+
+#include "so.h"
+#include "ka410.h"
+
+#define BB_DEBUG(x)    printf x
+#define CLEAR_INTR()   *ka410_intclr=INTR_SC
+#define CHECK_INTR()   *ka410_intreq&INTR_SC
+
+#define OK             0
+#define NOT_OK         OK+1
+#define        PRIVATE
+#define PUBLIC
+#define WR_ADR(adr,val)        (*((volatile unsigned char *)(adr))=(val))
+#define RD_ADR(adr)    (*((volatile unsigned char *)(adr)))
+/* #define AIC6250             0 */
+/* #define DP8490              1 */
+#define MAX_CACHE      0x4000
+
+/* SCSI bus phases
+ */
+#define PH_ODATA       0
+#define PH_IDATA       1
+#define PH_CMD         2
+#define PH_STAT                3
+#define PH_IMSG                7
+#define PH_NONE                8
+#define PH_IN(phase)   ((phase) & 1)
+
+/* NCR5380 SCSI controller registers
+ */
+#define SC_CTL         0x200C0080      /* base for control registers */
+#define SC_DMA         0x200D0000      /* base for data registers (8/16K) */
+#define SC_CURDATA     SC_CTL+(4*0)
+#define SC_OUTDATA     SC_CTL+(4*0)
+#define SC_ICMD                SC_CTL+(4*1)
+#define SC_MODE                SC_CTL+(4*2)
+#define SC_TCMD                SC_CTL+(4*3)
+#define SC_STAT1       SC_CTL+(4*4)
+#define SC_STAT2       SC_CTL+(4*5)
+#define SC_START_SEND  SC_CTL+(4*5)
+#define SC_INDATA      SC_CTL+(4*6)
+#define SC_RESETIP     SC_CTL+(4*7)
+#define SC_START_RCV   SC_CTL+(4*7)
+
+/* Bits in NCR5380 registers
+ */
+#define SC_A_RST       0x80
+#define SC_A_SEL       0x04
+#define SC_S_SEL       0x02
+#define SC_S_REQ       0x20
+#define SC_S_BSY       0x40
+#define SC_S_BSYERR    0x04
+#define SC_S_PHASE     0x08
+#define SC_S_IRQ       0x10
+#define SC_S_DRQ       0x40
+#define SC_M_DMA       0x02
+#define SC_M_BSY       0x04
+#define SC_ENABLE_DB   0x01
+
+/* Status of interrupt routine, returned in m1_i1 field of message.
+ */
+#define ISR_NOTDONE    0
+#define ISR_OK         1
+#define ISR_BSYERR     2
+#define ISR_RSTERR     3
+#define ISR_BADPHASE   4
+#define ISR_TIMEOUT    5
+
+#define ICU_ADR                0xfffffe00
+#define ICU_IO         (ICU_ADR+20)
+#define ICU_DIR                (ICU_ADR+21)
+#define ICU_DATA       (ICU_ADR+19)
+#define ICU_SCSI_BIT   0x80
+
+/* Miscellaneous
+ */
+#define MAX_WAIT       (1000*1000)
+#define SC_LOG_LEN     32
+
+PRIVATE struct scsi_args       *sc_ptrs;
+PRIVATE char                   sc_cur_phase,
+                               sc_reset_done = 1,
+                               sc_have_msg,
+                               sc_accept_int,
+                               sc_dma_dir;
+
+long   sc_dma_port = SC_DMA,
+       sc_dma_adr;
+
+#ifdef DEBUG
+struct sc_log {
+  unsigned char stat1, stat2;
+}                              sc_log [SC_LOG_LEN],
+                               *sc_log_head = sc_log;
+int                            sc_spurious_int;
+#endif
+unsigned char
+       sc_watchdog_error;              /* watch dog error */
+
+/* error messages */
+char *scsi_errors[] = {
+  0,                                   /* ISR_NOTDONE */
+  0,                                   /* ISR_OK */
+  "busy error",                                /* ISR_BSYERR */
+  "reset error",                       /* ISR_RSTERR */
+  "NULL pointer for current phase",    /* ISR_BADPHASE */
+  "timeout",                           /* ISR_TIMEOUT */
+};
+
+/*===========================================================================*
+ *                             exec_scsi_low                                * 
+ *===========================================================================*/
+/* Execute a generic SCSI command.  Passed pointers to eight buffers:
+ * data-out, data-in, command, status, dummy, dummy, message-out, message-in.
+ */
+PUBLIC
+int
+exec_scsi_low (args, scsi_adr)
+struct scsi_args *args;
+long scsi_adr;
+{
+  int ret;
+
+  BB_DEBUG (("exec_scsi_low(0x%x, %d)\n", args, scsi_adr));
+
+  sc_ptrs = args;                      /* make pointers globally accessible */
+  /* bertram ??? scCtlrSelect (DP8490); */
+  if (!sc_reset_done) sc_reset();
+  /* TCMD has some undocumented behavior in initiator mode.  I think the
+   * data bus cannot be enabled if i/o is asserted.
+   */
+  WR_ADR (SC_TCMD, 0);
+  if (OK != sc_wait_bus_free ()) {     /* bus-free phase */
+    printf("SCSI: bus not free\n");
+    return NOT_OK;
+  }
+  sc_cur_phase = PH_NONE;
+  sc_have_msg = 0;
+  if (OK != sc_select (scsi_adr))      /* select phase */
+    return NOT_OK;
+  sc_watchdog_error = 0;
+  ret = sc_receive ();                 /* isr does the rest */
+  if (ret == ISR_OK) return OK;
+  else {
+    sc_reset();
+    printf("SCSI: %s\n", scsi_errors[ret]);
+    return NOT_OK;
+  }
+}
+
+/*===========================================================================*
+ *                             sc_reset                                     * 
+ *===========================================================================*/
+/*
+ * Reset SCSI bus.
+ */
+PRIVATE
+sc_reset()
+{
+  volatile int i;
+  
+  BB_DEBUG (("sc_reset()\n"));
+
+  WR_ADR (SC_MODE, 0);                 /* get into harmless state */
+  WR_ADR (SC_OUTDATA, 0);
+  WR_ADR (SC_ICMD, SC_A_RST);          /* assert RST on SCSI bus */
+  i = 200;                             /* wait 25 usec */
+  while (i--);
+  WR_ADR (SC_ICMD, 0);                 /* deassert RST, get off bus */
+  sc_reset_done = 1;
+}
+
+/*===========================================================================*
+ *                             sc_wait_bus_free                             * 
+ *===========================================================================*/
+PRIVATE int
+sc_wait_bus_free()
+{
+  int i = MAX_WAIT;
+  volatile int j;
+
+  BB_DEBUG (("sc_wait_bus_free()\n"));
+
+  while (i--) {
+    /* Must be clear for 2 usec, so read twice */
+    if (RD_ADR (SC_STAT1) & (SC_S_BSY | SC_S_SEL)) continue;
+    for (j = 0; j < 25; ++j);
+    if (RD_ADR (SC_STAT1) & (SC_S_BSY | SC_S_SEL)) continue;
+    return OK;
+  }
+  sc_reset_done = 0;
+  return NOT_OK;
+}
+
+/*===========================================================================*
+ *                             sc_select                                    * 
+ *===========================================================================*/
+/* This duplicates much of the work that the interrupt routine would do on a
+ * phase mismatch and, in fact, the original plan was to just do the select,
+ * let a phase mismatch occur, and let the interrupt routine do the rest.
+ * That didn't work because the 5380 did not reliably generate the phase
+ * mismatch interrupt after selection.
+ */
+PRIVATE int
+sc_select(adr)
+long adr;
+{
+  int i, stat1;
+  long new_ptr;
+
+  BB_DEBUG (("sc_select(%d)\n", adr));
+
+  CLEAR_INTR();
+  WR_ADR (SC_OUTDATA, adr);            /* SCSI bus address */
+  WR_ADR (SC_ICMD, SC_A_SEL | SC_ENABLE_DB);
+  for (i = 0;; ++i) {                  /* wait for target to assert SEL */
+    if (CHECK_INTR() == 0)
+      continue;
+    stat1 = RD_ADR (SC_STAT1);
+    if (stat1 & SC_S_BSY) break;       /* select successful */
+    if (i > MAX_WAIT) {                        /* timeout */
+      printf("SCSI: SELECT timeout\n");
+      sc_reset();
+      return NOT_OK;
+    }
+  }
+  CLEAR_INTR();
+  WR_ADR (SC_ICMD, 0);                 /* clear SEL, disable data out */
+  WR_ADR (SC_OUTDATA, 0);
+  for (i = 0;; ++i) {                  /* wait for target to assert REQ */
+    if (CHECK_INTR() == 0)
+      continue;
+    if (stat1 & SC_S_REQ) break;       /* target requesting transfer */
+    if (i > MAX_WAIT) {                        /* timeout */
+      printf("SCSI: REQ timeout\n");
+      sc_reset();
+      return NOT_OK;
+    }
+    stat1 = RD_ADR (SC_STAT1);
+  }
+  sc_cur_phase = (stat1 >> 2) & 7;     /* get new phase from controller */
+  if (sc_cur_phase != PH_CMD) {
+    printf("SCSI: bad phase = %d\n", sc_cur_phase);
+    sc_reset();
+    return NOT_OK;
+  }
+  new_ptr = sc_ptrs->ptr[PH_CMD];
+  if (new_ptr == 0) {
+    printf("SCSI: NULL command pointer\n");
+    sc_reset();
+    return NOT_OK;
+  }
+  sc_accept_int = 1;
+  sc_dma_setup (DISK_WRITE, new_ptr);
+  CLEAR_INTR();
+  WR_ADR (SC_TCMD, PH_CMD);
+  WR_ADR (SC_ICMD, SC_ENABLE_DB);
+  WR_ADR (SC_MODE, SC_M_BSY | SC_M_DMA);
+  WR_ADR (SC_START_SEND, 0);
+  return OK;
+}
+
+/*===========================================================================*
+ *                             scsi_interrupt                               *
+ *===========================================================================*/
+/* SCSI interrupt handler.
+ */
+PUBLIC
+int
+scsi_interrupt()
+{
+  unsigned char stat2, dummy;
+  long new_ptr;
+  int ret = ISR_NOTDONE;
+
+  BB_DEBUG (("scsi_interrupt()\n"));
+
+  stat2 = RD_ADR (SC_STAT2);           /* get status before clearing request */
+
+# ifdef DEBUG                          /* debugging log of interrupts */
+  sc_log_head->stat1 = RD_ADR (SC_STAT1);
+  sc_log_head->stat2 = stat2;
+  if (++sc_log_head >= sc_log + SC_LOG_LEN) sc_log_head = sc_log;
+  sc_log_head->stat1 = sc_log_head->stat2 = 0xff;
+# endif
+
+  for (;;) {
+    dummy = RD_ADR (SC_RESETIP);       /* clear interrupt request */
+    if (!sc_accept_int ||              /* return if spurious interrupt */
+        (!sc_watchdog_error &&
+         (stat2 & SC_S_BSYERR) == 0 && (stat2 & SC_S_PHASE) != 0))
+      {
+#     ifdef DEBUG
+        ++sc_spurious_int;
+#     endif
+       printf ("sc_spurious_int\n");
+       return ret;
+    }
+    RD_ADR (SC_MODE) &= ~SC_M_DMA;     /* clear DMA mode */
+    WR_ADR (SC_ICMD, 0);               /* disable data bus */
+    if (sc_cur_phase != PH_NONE) {     /* if did DMA, save the new pointer */
+      new_ptr = sc_dma_adr;            /* fetch new pointer from DMA cntlr */
+      if (sc_cur_phase == PH_IMSG &&   /* have message? */
+        new_ptr != sc_ptrs->ptr[PH_IMSG]) sc_have_msg = 1;
+      sc_ptrs->ptr[sc_cur_phase] =     /* save pointer */
+        new_ptr;
+    }
+    if (sc_watchdog_error) ret = ISR_TIMEOUT;
+    else if (stat2 & SC_S_BSYERR) {    /* target deasserted BSY? */
+      printf ("target deasserted BSY?\n");
+      if (sc_have_msg) ret = ISR_OK;
+      else ret = ISR_BSYERR;
+    } else if (!(stat2 & SC_S_PHASE)) {/* if phase mismatch, setup new phase */
+      printf ("phase mismatch\n");
+      sc_cur_phase =                   /* get new phase from controller */
+        (RD_ADR (SC_STAT1) >> 2) & 7;
+      new_ptr = sc_ptrs->ptr[sc_cur_phase];
+      if (new_ptr == 0) ret = ISR_BADPHASE;
+      else {
+        WR_ADR (SC_TCMD, sc_cur_phase);        /* write new phase into TCMD */
+        if (PH_IN (sc_cur_phase)) {    /* set DMA controller */
+          sc_dma_setup (DISK_READ, new_ptr);
+          RD_ADR (SC_MODE) |= SC_M_DMA;
+         CLEAR_INTR();
+          WR_ADR (SC_START_RCV, 0);    /* tell SCSI to start DMA */
+       } else {
+          sc_dma_setup (DISK_WRITE, new_ptr);
+         RD_ADR (SC_MODE) |= SC_M_DMA;
+         WR_ADR (SC_ICMD, SC_ENABLE_DB);
+         CLEAR_INTR();
+         WR_ADR (SC_START_SEND, 0);
+       }
+      }
+    } else ret = ISR_RSTERR;
+    if (ret != ISR_NOTDONE) {          /* if done, send message to task */
+      sc_watchdog_error = 0;
+      sc_accept_int = 0;
+      WR_ADR (SC_MODE, 0);             /* clear monbsy, dma */
+      break;                           /* reti re-enables ints */
+    }
+    if (0 == ((stat2 =                 /* check for another interrupt */
+      RD_ADR (SC_STAT2)) & SC_S_IRQ)) 
+    {
+      break;
+    }
+  }
+  return ret;
+}
+
+/*===========================================================================*
+ *                             sc_dma_setup                                 *
+ *===========================================================================*/
+/* Fake DMA setup.  Just store pointers and direction in global variables.
+ *
+ * The pseudo-DMA is subtler than it looks because of the cache.
+ *
+ * 1)  When accessing I/O devices through a cache, some mechanism is
+ *     necessary to ensure you access the device rather than the cache.
+ *     On the 32532, the IODEC signal is supposed to be asserted for I/O
+ *     addresses to accomplish this.  However, a bug makes this much
+ *     slower than necessary and severely hurts pseudo-DMA performance.
+ *     Hence, IODEC is not asserted for the SCSI DMA port.
+ *
+ * 2)  Because of (1), we must devise our own method of forcing the
+ *     SCSI DMA port to be read.  0x8000000 addresses have been decoded
+ *     to all access this port.  By always using new addresses to access
+ *     the DMA port (wrapping only after reading MAX_CACHE bytes), we
+ *     force cache misses and, hence, device reads.  Since the cache
+ *     is write-through, we do not need to worry about writes.
+ *
+ * 3)  It is possible to miss the last few bytes of a transfer if
+ *     bus transfer size is not considered.  The loop in sc_receive()
+ *     transfers data until the interrupt signal is asserted.  If
+ *     bytes are transferred, the attempt to move the first byte of a
+ *     double word causes the whole word to be read into the cache.
+ *     Then the byte is transferred.  If reading the double word
+ *     completed the SCSI transfer, then the loop exits since
+ *     interrupt is asserted.  However, the last few bytes have only
+ *     been moved into the cache -- they have not been moved to the
+ *     DMA destination.
+ *
+ * 4)  It is also possible to miss the first few bytes of a transfer.
+ *     If the address used to access pseudo-dma port is not double word
+ *     aligned, the whole double word is read into the cache, and then
+ *     data is moved from the middle of the word (i.e. something other
+ *     than the first bytes read from the SCSI controller) by the
+ *     pseudo-dma loop in sc_receive().
+ */
+sc_dma_setup (dir, adr)
+int dir;
+long adr;
+{
+  BB_DEBUG (("sc_dma_setup(%d, %d)\n", dir, adr));
+
+  CLEAR_INTR();
+  /* if (sc_dma_port > SC_DMA + MAX_CACHE) */
+  sc_dma_port = SC_DMA;
+  sc_dma_dir = dir;
+  sc_dma_adr = adr;
+}
+
+/*===========================================================================*
+ *                             sc_receive                                   *
+ *===========================================================================*/
+/* Replacement for Minix receive(), which waits for a message.  This code
+ * spins, waiting for data to transfer or interrupt requests to handle.
+ * See sc_dma_setup for details.
+ */
+int
+sc_receive()
+{
+  int stat2, isr_ret;
+  int i, c;
+
+  BB_DEBUG (("sc_receive()\n"));
+
+  /*
+   * check the interrupt-flag and wait if it reappears...
+   */
+  c = *ka410_intreq;
+  printf ("begin: %x/%x ", c, *ka410_intreq);
+  for (i=0; i<100; i++) {
+    if ((c = *ka410_intreq) & INTR_SC)
+      break;
+    printf (" %x ", c);
+  }
+  if (i==100)
+    printf ("timeout in sc_receive.\n");
+
+#if 1
+  for (;;) {
+    stat2 = RD_ADR (SC_STAT2);
+    if (stat2 & SC_S_IRQ) {
+      if (ISR_NOTDONE != (isr_ret = scsi_interrupt())) break;
+    } else if (stat2 & SC_S_DRQ) {     /* test really not necessary on pc532 */
+      if (sc_dma_dir == DISK_READ)
+       *((long *)sc_dma_adr)++ = *((volatile long *)sc_dma_port)++;
+      else *((volatile long *)sc_dma_port)++ = *((long *)sc_dma_adr)++;
+    }
+  }
+#endif
+  printf ("isr_ret: %d (ISR_NOTDONE: %d)\n", isr_ret, ISR_NOTDONE);
+  return isr_ret;
+}
+
+/*===========================================================================*
+ *                             scCtlrSelect
+ *===========================================================================*/
+/* Select a SCSI device.
+ */
+scCtlrSelect (ctlr)
+int ctlr;
+{
+  BB_DEBUG (("scCtlrSelect()\n"));
+#if 0
+  RD_ADR (ICU_IO) &= ~ICU_SCSI_BIT;    /* i/o, not port */
+  RD_ADR (ICU_DIR) &= ~ICU_SCSI_BIT;   /* output */
+  if (ctlr == DP8490)
+    RD_ADR (ICU_DATA) &= ~ICU_SCSI_BIT;        /* select = 0 for 8490 */
+  else
+    RD_ADR (ICU_DATA) |= ICU_SCSI_BIT; /* select = 1 for AIC6250 */
+#endif
+}
diff --git a/sys/arch/vax/stand/sd.c b/sys/arch/vax/stand/sd.c
new file mode 100644 (file)
index 0000000..30b08c3
--- /dev/null
@@ -0,0 +1,247 @@
+/*     $NetBSD: sd.c,v 1.1 1996/08/02 11:22:36 ragge Exp $     */
+
+/*
+ * Copyright (c) 1988 University of Utah.
+ * Copyright (c) 1990, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Van Jacobson of Lawrence Berkeley Laboratory and the Systems
+ * Programming Group of the University of Utah Computer Science Department.
+ *
+ * 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.
+ *
+ * from: Utah $Hdr: sd.c 1.9 92/12/21$
+ *
+ *     @(#)sd.c        8.1 (Berkeley) 6/10/93
+ */
+
+/*
+ * SCSI CCS disk driver
+ */
+
+#include <sys/param.h>
+#include <sys/disklabel.h>
+#include "stand.h"
+#include "samachdep.h"
+
+#define SC_DEBUG       1       /* bertram */
+#define SD_DEBUG       1       /* bertram */
+
+/*----------------------------------------------------------------------*/
+int
+scsialive(int ctlr)
+{
+       return 1;               /* controller always alive! */
+}
+
+/* call functions in scsi_hi.c */
+#include "so.h"
+
+int
+scsi_tt_read(ctlr, slave, buf, len, blk, nblk)
+       int ctlr, slave;
+       u_char *buf;
+       u_int len;
+       daddr_t blk;
+       u_int nblk;
+{
+#ifdef SC_DEBUG
+printf("scsi_tt_read: ctlr %d, slave %d, len %d, blk %d, nblk %d\n",
+       ctlr, slave, len, blk, nblk );
+#endif
+       if (sc_rdwt(DISK_READ, blk, buf, nblk, 1<<slave, 0) == 0)
+               return 0;
+       return -2;
+}
+
+int
+scsi_tt_write(ctlr, slave, buf, len, blk, nblk)
+       int ctlr, slave;
+       u_char *buf;
+       u_int len;
+       daddr_t blk;
+       u_int nblk;
+{
+#ifdef SC_DEBUG
+printf("scsi_tt_write: ctlr %d, slave %d, len %d, blk %d, nblk %d\n",
+       ctlr, slave, len, blk, nblk );
+#endif
+#if 0
+       if (sc_rdwt(DISK_WRITE, blk, buf, nblk, 1<<slave, 0) == 0)
+               return 0;
+#endif
+       return -2;
+}
+
+/*----------------------------------------------------------------------*/
+
+struct sd_softc {
+       int     sc_ctlr;
+       int     sc_unit;
+       int     sc_part;
+       char    sc_retry;
+       char    sc_alive;
+       struct  disklabel sc_label;
+} sd_softc[NSCSI][NSD];
+
+#ifdef SD_DEBUG
+int debug = SD_DEBUG;
+#endif
+
+#define        SDRETRY         2
+
+sdinit(ctlr, unit)
+       int ctlr, unit;
+{
+       register struct sd_softc *ss = &sd_softc[ctlr][unit];
+
+       /* HP version does test_unit_ready
+        * followed by read_capacity to get blocksize
+        */
+       ss->sc_alive = 1;
+       return (1);
+}
+
+sdreset(ctlr, unit)
+       int ctlr, unit;
+{
+}
+
+char io_buf[MAXBSIZE];
+
+sdgetinfo(ss)
+       register struct sd_softc *ss;
+{
+       register struct disklabel *lp;
+       char *msg, *getdisklabel();
+       int sdstrategy(), i, err;
+
+       lp = &sd_softc[ss->sc_ctlr][ss->sc_unit].sc_label;
+       bzero((caddr_t)lp, sizeof *lp);
+       lp->d_secsize = DEV_BSIZE;
+       lp->d_secpercyl = 1;
+       lp->d_npartitions = MAXPARTITIONS;
+       lp->d_partitions[ss->sc_part].p_offset = 0;
+       lp->d_partitions[ss->sc_part].p_size = 0x7fffffff;
+
+       if (err = sdstrategy(ss, F_READ,
+                      LABELSECTOR, DEV_BSIZE, io_buf, &i) < 0) {
+           printf("sdgetinfo: sdstrategy error %d\n", err);
+           return 0;
+       }
+       
+       msg = getdisklabel(io_buf, lp);
+       if (msg) {
+               printf("sd(%d,%d,%d): %s\n",
+                      ss->sc_ctlr, ss->sc_unit, ss->sc_part, msg);
+               return 0;
+       }
+       return(1);
+}
+
+sdopen(f, ctlr, unit, part)
+       struct open_file *f;
+       int ctlr, unit, part;
+{
+       register struct sd_softc *ss;
+       register struct disklabel *lp;
+
+#ifdef SD_DEBUG
+       if (debug)
+       printf("sdopen: ctlr=%d unit=%d part=%d\n",
+           ctlr, unit, part);
+#endif
+       
+       if (ctlr >= NSCSI || !scsialive(ctlr))
+               return (EADAPT);
+       if (unit >= NSD)
+               return (ECTLR);
+       ss = &sd_softc[ctlr][unit];     /* XXX alloc()? keep pointers? */
+       ss->sc_part = part;
+       ss->sc_unit = unit;
+       ss->sc_ctlr = ctlr;
+       if (!ss->sc_alive) {
+               if (!sdinit(ctlr, unit))
+                       return (ENXIO);
+               if (!sdgetinfo(ss))
+                       return (ERDLAB);
+       }
+       lp = &sd_softc[ctlr][unit].sc_label;
+       if (part >= lp->d_npartitions || lp->d_partitions[part].p_size == 0)
+               return (EPART);
+
+       f->f_devdata = (void *)ss;
+       return (0);
+}
+
+int
+sdstrategy(ss, func, dblk, size, buf, rsize)
+       register struct sd_softc *ss;
+       int func;
+       daddr_t dblk;           /* block number */
+       u_int size;             /* request size in bytes */
+       char *buf;
+       u_int *rsize;           /* out: bytes transferred */
+{
+       register int ctlr = ss->sc_ctlr;
+       register int unit = ss->sc_unit;
+       register int part = ss->sc_part;
+       register struct partition *pp = &ss->sc_label.d_partitions[part];
+       u_int nblk = size >> DEV_BSHIFT;
+       u_int blk = dblk + pp->p_offset;
+       char stat;
+
+       if (size == 0)
+               return(0);
+
+       ss->sc_retry = 0;
+
+#ifdef SD_DEBUG
+       if (debug)
+           printf("sdstrategy(%d,%d): size=%d blk=%d nblk=%d\n",
+               ctlr, unit, size, blk, nblk);
+#endif
+
+retry:
+       if (func == F_READ)
+               stat = scsi_tt_read(ctlr, unit, buf, size, blk, nblk);
+       else
+               stat = scsi_tt_write(ctlr, unit, buf, size, blk, nblk);
+       if (stat) {
+               printf("sd(%d,%d,%d): block=%x, error=0x%x\n",
+                      ctlr, unit, ss->sc_part, blk, stat);
+               if (++ss->sc_retry > SDRETRY)
+                       return(EIO);
+               goto retry;
+       }
+       *rsize = size;
+       
+       return(0);
+}
diff --git a/sys/arch/vax/stand/so.h b/sys/arch/vax/stand/so.h
new file mode 100644 (file)
index 0000000..3ead2c8
--- /dev/null
@@ -0,0 +1,57 @@
+/*     $NetBSD: so.h,v 1.1 1996/08/02 11:22:41 ragge Exp $     */
+
+#ifndef _SO_H_INCLUDE
+#define _SO_H_INCLUDE
+
+/* Definitions for standalone I/O lib */
+
+/* #define SCSI_POLLED 0x200C0080 */
+#define SCSI_DMA       0x200D0000
+
+/* Which SCSI device to use by default */
+#define DEFAULT_SCSI_ADR       1
+#define DEFAULT_SCSI_LUN       0
+
+/* Low level scsi operation codes */
+#define DISK_READ      3
+#define DISK_WRITE     4
+
+/* The size of a disk block */
+#define DBLKSIZE       512
+
+/* Some disk address that will never be used */
+#define INSANE_BADDR   0x800000
+
+struct scsi_args {
+  long ptr [8];
+};
+
+#ifndef NULL
+#define NULL           0L
+#endif
+
+/*
+ * The next macro defines where the "break" area in memory ends for
+ * malloc() and friends. The area between edata and this address will
+ * then be reserved and should not be used for anything else (or you will
+ * no doubt have big problems). Depending on where your program's end-of-data
+ * is, you may wish to locate this in such a way as to usurp a minimum
+ * amount of memory.
+ */
+#define BREAK_END_ADDR         ((char *)0x400000)      /* to   4MB */
+
+/* Selectivly enable inline functions */
+#ifndef NO_INLINE
+#define Inline inline
+#else
+#define Inline
+#endif
+extern void fatal(), warn();
+extern long ulimit(int, long);
+extern int brk(char *);
+extern char *sbrk(int);
+
+extern int sc_rdwt();
+
+#endif /* _SO_H_INCLUDE */
index 1fc8dfc..bfe5aca 100644 (file)
@@ -1,4 +1,4 @@
-/*     $NetBSD: srt0.s,v 1.5 1996/03/07 23:27:10 ragge Exp $ */
+/*     $NetBSD: srt0.s,v 1.6 1996/08/02 11:22:44 ragge Exp $ */
 /*
  * Copyright (c) 1994 Ludd, University of Lule}, Sweden.
  * All rights reserved.
@@ -58,7 +58,9 @@ _start:       .globl  _start
 1:     movl    $relocated, (sp)   # return-address on top of stack
        rsb                        # can be replaced with new address
 relocated:                        # now relocation is done !!!
-       calls   $0,_main        # Were here!
+       movl    sp, _bootregs
+       calls   $0, _setup
+       calls   $0, _Xmain      # Were here!
        halt                    # no return
 
        
index 55b2fc0..51edf00 100644 (file)
@@ -1,4 +1,4 @@
-/*     $NetBSD: start.s,v 1.7 1996/02/02 19:08:33 mycroft Exp $ */
+/*     $NetBSD: start.s,v 1.8 1996/08/02 11:22:47 ragge Exp $ */
 /*
  * Copyright (c) 1995 Ludd, University of Lule}, Sweden.
  * All rights reserved.
@@ -172,7 +172,8 @@ start_all:
 relocated:                             # now relocation is done !!!
        movl    sp, _bootregs
        movl    ap, _boothowto
-       calls   $0, _main               # call main() which is 
+       calls   $0, _setup
+       calls   $0, _Xmain              # call Xmain (gcc workaround)which is 
        halt                            # not intended to return ...
 
 /*
diff --git a/sys/arch/vax/stand/str.s b/sys/arch/vax/stand/str.s
new file mode 100644 (file)
index 0000000..685574e
--- /dev/null
@@ -0,0 +1,70 @@
+/*     $NetBSD: str.s,v 1.2 1996/08/02 16:18:40 ragge Exp $ */
+/*
+ * Copyright (c) 1996 Ludd, University of Lule}, Sweden.
+ * 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 at Ludd, University of 
+ *      Lule}, Sweden and its contributors.
+ * 4. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * Small versions of the most common string functions not using any
+ * emulated instructions.
+ */
+
+#include "../include/asm.h"
+
+ENTRY(strlen, 0);
+       movl    4(ap), r0
+1:     tstb    (r0)+
+       bneq    1b
+       decl    r0
+       subl2   4(ap), r0
+       ret
+
+ENTRY(strncmp, 0)
+       movl    12(ap), r3
+       brb     5f
+
+ENTRY(strcmp, 0)
+       movl    $250, r3        # max string len to compare
+5:     movl    4(ap), r2
+       movl    8(ap), r1
+       movl    $1, r0
+
+2:     cmpb    (r2),(r1)+
+       bneq    1f              # something differ
+       tstb    (r2)+
+       beql    4f              # continue, strings unequal
+       decl    r3              # max string len encountered?
+       bneq    2b
+
+4:     clrl    r0              # We are done, strings equal.
+       ret
+
+1:     bgtr    3f
+       mnegl   r0, r0
+3:     ret
index f5d0fe1..b630222 100644 (file)
@@ -1,4 +1,4 @@
-/*     $NetBSD: tmscp.c,v 1.2 1996/02/17 18:23:24 ragge Exp $ */
+/*     $NetBSD: tmscp.c,v 1.3 1996/08/02 11:22:53 ragge Exp $ */
 /*
  * Copyright (c) 1995 Ludd, University of Lule}, Sweden.
  * All rights reserved.
@@ -43,7 +43,8 @@
 #include "../include/macros.h"
 #include "../uba/ubareg.h"
 #include "../uba/udareg.h"
-#include "../vax/mscp.h"
+#include "../mscp/mscp.h"
+#include "../mscp/mscpreg.h"
 
 #include "vaxstand.h"
 
@@ -63,7 +64,7 @@ struct ra_softc {
 };
 
 static volatile struct uda {
-        struct  uda1ca uda_ca;           /* communications area */
+        struct  mscp_1ca uda_ca;           /* communications area */
         struct  mscp uda_rsp;     /* response packets */
         struct  mscp uda_cmd;     /* command packets */
 } uda;
@@ -100,14 +101,14 @@ tmscpopen(f, adapt, ctlr, unit, part)
         * Init of this tmscp ctlr.
         */
        udacsr->udaip=0; /* Start init */
-       while((udacsr->udasa&UDA_STEP1) == 0);
+       while((udacsr->udasa&MP_STEP1) == 0);
        udacsr->udasa=0x8000;
-       while((udacsr->udasa&UDA_STEP2) == 0);
+       while((udacsr->udasa&MP_STEP2) == 0);
        johan=(((u_int)ubauda)&0xffff)+8;
        udacsr->udasa=johan;
-       while((udacsr->udasa&UDA_STEP3) == 0);
+       while((udacsr->udasa&MP_STEP3) == 0);
        udacsr->udasa=3;
-       while((udacsr->udasa&UDA_STEP4) == 0);
+       while((udacsr->udasa&MP_STEP4) == 0);
        udacsr->udasa=0x0001;
 
        uda.uda_ca.ca_rspdsc=(int)&ubauda->uda_rsp.mscp_cmdref;
index f3217fd..2d068b9 100644 (file)
@@ -1,4 +1,4 @@
-/*     $NetBSD: vaxstand.h,v 1.4 1996/02/17 18:23:25 ragge Exp $ */
+/*     $NetBSD: vaxstand.h,v 1.5 1996/08/02 11:22:56 ragge Exp $ */
 /*
  * Copyright (c) 1994 Ludd, University of Lule}, Sweden.
  * All rights reserved.
 
 #define MAXNMBA 8 /* Massbussadapters */
 #define MAXNUBA 8 /* Unibusadapters */
-#define MAXNBI  4 /* Bi-bussadapters */
 #define        MAXMBAU 8 /* Units on an mba */
-#define        MAXBIN  16 /* Bi-nodes */
 
 /* Variables used in autoconf */
 extern int nmba, nuba, nbi, nsbi, nuda;
-extern int *ubaaddr, *mbaaddr, *udaaddr, *uioaddr;
+extern int *ubaaddr, *mbaaddr, *udaaddr, *uioaddr, *biaddr;
+extern int cpunumber;
 
 /* devsw type definitions, used in bootxx and conf */
 #define SADEV(name,strategy,open,close,ioctl) \
@@ -50,3 +49,17 @@ extern int *ubaaddr, *mbaaddr, *udaaddr, *uioaddr;
          (int(*)(struct open_file *))close, \
          (int(*)(struct open_file *,u_long, void *))ioctl}
 
+/*
+ * Easy-to-use definitions
+ */
+#define        min(x,y) (x < y ? x : y)
+
+/*
+ * Device numbers gotten from boot prom.
+ */
+#define        BDEV_MBA                0
+#define        BDEV_RK06               1
+#define        BDEV_RL02               2
+#define        BDEV_UDA                17
+#define        BDEV_TK50               18
+#define        BDEV_CONSOLE            64
index 8dcf623..10ade80 100644 (file)
@@ -1,4 +1,4 @@
-/*     $NetBSD: dhu.c,v 1.5 1996/05/19 16:27:02 ragge Exp $    */
+/*     $NetBSD: dhu.c,v 1.9 1997/01/11 11:34:41 ragge Exp $    */
 /*
  * Copyright (c) 1996  Ken C. Wellsch.  All rights reserved.
  * Copyright (c) 1992, 1993
@@ -132,7 +132,7 @@ static unsigned     dhumctl __P((struct dhu_softc *,int, int, int));
        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 *));
-       int     dhustop __P((struct tty *, int));
+       void    dhustop __P((struct tty *, int));
 struct tty *   dhutty __P((dev_t));
 
 struct cfdriver dhu_cd = {
@@ -376,9 +376,9 @@ dhuopen(dev, flag, mode, p)
 
                sc->sc_dhu[line].dhu_state = STATE_IDLE;
 
-               sc->sc_dhu[line].dhu_txaddr = uballoc(
-                                       sc->sc_dev.dv_parent->dv_unit,
-                                       tp->t_outq.c_cs, tp->t_outq.c_cn, 0);
+               sc->sc_dhu[line].dhu_txaddr =
+                   uballoc((struct uba_softc *)sc->sc_dev.dv_parent,
+                   tp->t_outq.c_cs, tp->t_outq.c_cn, 0);
 
                dhuaddr = sc->sc_addr;
 
@@ -561,7 +561,7 @@ dhutty(dev)
 }
 
 /*ARGSUSED*/
-int
+void
 dhustop(tp, flag)
        register struct tty *tp;
 {
@@ -590,7 +590,6 @@ dhustop(tp, flag)
                        tp->t_state |= TS_FLUSH;
        }
        (void) splx(s);
-       return 0;
 }
 
 static void
index f1636b7..bc583be 100644 (file)
@@ -1,4 +1,4 @@
-/*     $NetBSD: dz.c,v 1.1 1996/04/08 17:22:20 ragge Exp $     */
+/*     $NetBSD: dz.c,v 1.4 1996/10/13 03:35:15 christos Exp $  */
 /*
  * Copyright (c) 1996  Ken C. Wellsch.  All rights reserved.
  * Copyright (c) 1992, 1993
@@ -121,7 +121,7 @@ struct      tty *   dztty __P((dev_t));
        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));
+       void    dzstop __P((struct tty *, int));
 
 struct cfdriver dz_cd = {
        NULL, "dz", DV_TTY
@@ -547,8 +547,8 @@ dztty (dev)
 }
 
 /*ARGSUSED*/
-int
-dzstop (tp, flag)
+void
+dzstop(tp, flag)
        register struct tty *tp;
 {
        register struct dz_softc *sc;
@@ -560,14 +560,12 @@ dzstop (tp, flag)
 
        s = spltty();
 
-       if (tp->t_state & TS_BUSY)
-       {
+       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
diff --git a/sys/arch/vax/uba/qd.c b/sys/arch/vax/uba/qd.c
new file mode 100644 (file)
index 0000000..71acc07
--- /dev/null
@@ -0,0 +1,3611 @@
+/*     $NetBSD: qd.c,v 1.4 1996/10/13 03:35:17 christos Exp $  */
+
+/*-
+ * Copyright (c) 1988 Regents of the University of California.
+ * 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.
+ *
+ *     @(#)qd.c        7.1 (Berkeley) 6/28/91
+ */
+
+/************************************************************************
+*                                                                      *
+*                      Copyright (c) 1985-1988 by                      *
+*              Digital Equipment Corporation, Maynard, MA              *
+*                      All rights reserved.                            *
+*                                                                      *
+*   This software is furnished under a license and may be used and     *
+*   copied  only  in accordance with the terms of such license and     *
+*   with the  inclusion  of  the  above  copyright  notice.   This     *
+*   software  or  any  other copies thereof may not be provided or     *
+*   otherwise made available to any other person.  No title to and     *
+*   ownership of the software is hereby transferred.                   *
+*                                                                      *
+*   The information in this software is subject to change  without     *
+*   notice  and should not be construed as a commitment by Digital     *
+*   Equipment Corporation.                                             *
+*                                                                      *
+*   Digital assumes no responsibility for the use  or  reliability     *
+*   of its software on equipment which is not supplied by Digital.     *
+*                                                                      *
+*************************************************************************/
+
+/*
+ * qd.c - QDSS display driver for VAXSTATION-II GPX workstation
+ */
+
+#include "qd.h"
+
+#if NQD > 0
+#include "../include/pte.h"
+#include "../include/mtpr.h"
+#include "sys/param.h"
+#include "../include/cpu.h"
+#include "sys/conf.h"
+#include "sys/user.h"
+#include "qdioctl.h"
+#include "sys/tty.h"
+#include "sys/map.h"
+#include "sys/buf.h"
+#include "sys/vm.h"
+#include "sys/clist.h"
+#include "sys/file.h"
+#include "sys/uio.h"
+#include "sys/kernel.h"
+#include "sys/exec.h"
+#include "sys/proc.h"
+#include "ubareg.h"
+#include "ubavar.h"
+#include "sys/syslog.h"
+#include "qduser.h"    /* definitions shared with user level client */
+#include "qdreg.h"     /* QDSS device register structures */
+
+/*
+ * QDSS driver status flags for tracking operational state 
+ */
+struct qdflags {
+       u_int inuse;            /* which minor dev's are in use now */
+       u_int config;           /* I/O page register content */
+       u_int mapped;           /* user mapping status word */
+       u_int kernel_loop;      /* if kernel console is redirected */
+       u_int user_dma;         /* DMA from user space in progress */
+       u_short pntr_id;        /* type code of pointing device */
+       u_short duart_imask;    /* shadowing for duart intrpt mask reg */
+       u_short adder_ie;       /* shadowing for adder intrpt enbl reg */
+       u_short curs_acc;       /* cursor acceleration factor */
+       u_short curs_thr;       /* cursor acceleration threshold level */
+       u_short tab_res;        /* tablet resolution factor */
+       u_short selmask;        /* mask for active qd select entries */
+};
+
+/*
+ * bit definitions for 'inuse' entry  
+ */
+#define CONS_DEV       0x01
+#define GRAPHIC_DEV    0x04
+
+/*
+ * bit definitions for 'mapped' member of flag structure 
+ */
+#define MAPDEV         0x01            /* hardware is mapped */
+#define MAPDMA         0x02            /* DMA buffer mapped */
+#define MAPEQ          0x04            /* event queue buffer mapped */
+#define MAPSCR         0x08            /* scroll param area mapped */
+#define MAPCOLOR       0x10            /* color map writing buffer mapped */
+
+/*
+ * bit definitions for 'selmask' member of qdflag structure 
+ */
+#define SEL_READ       0x01            /* read select is active */
+#define SEL_WRITE      0x02            /* write select is active */
+
+/*
+ * constants used in shared memory operations 
+ */
+#define EVENT_BUFSIZE  1024    /* # of bytes per device's event buffer */
+#define MAXEVENTS  ( (EVENT_BUFSIZE - sizeof(struct qdinput))   \
+       / sizeof(struct _vs_event) )
+#define DMA_BUFSIZ     (1024 * 10)
+#define COLOR_BUFSIZ  ((sizeof(struct color_buf) + 512) & ~0x01FF)
+
+/*
+ * reference to an array of "uba_device" structures built by the auto
+ * configuration program.  The uba_device structure decribes the device
+ * sufficiently for the driver to talk to it.  The auto configuration code
+ * fills in the uba_device structures (located in ioconf.c) from user
+ * maintained info.  
+ */
+struct uba_device *qdinfo[NQD];  /* array of pntrs to each QDSS's */
+struct tty qd_tty[NQD*4];      /* teletype structures for each.. */
+extern char qvmem[][128*NBPG];
+extern struct pte QVmap[][128];
+#define CHUNK    (64 * 1024)
+#define QMEMSIZE  (1024 * 1024 * 4)    /* 4 meg */
+
+/*
+ * static storage used by multiple functions in this code  
+ */
+int Qbus_unmap[NQD];           /* Qbus mapper release code */
+struct qdflags qdflags[NQD];   /* QDSS device status flags */
+struct qdmap qdmap[NQD];       /* QDSS register map structure */
+caddr_t qdbase[NQD];           /* base address of each QDSS unit */
+struct buf qdbuf[NQD];         /* buf structs used by strategy */
+short qdopened[NQD];           /* graphics device is open exclusive use */
+
+/*
+ * the array "event_shared[]" is made up of a number of event queue buffers
+ * equal to the number of QDSS's configured into the running kernel (NQD).
+ * Each event queue buffer begins with an event queue header (struct qdinput)
+ * followed by a group of event queue entries (struct _vs_event).  The array
+ * "*eq_header[]" is an array of pointers to the start of each event queue
+ * buffer in "event_shared[]".  
+ */
+#define EQSIZE ((EVENT_BUFSIZE * NQD) + 512)
+
+char event_shared[EQSIZE];         /* reserve space for event bufs */
+struct qdinput *eq_header[NQD];     /* event queue header pntrs */
+
+/*
+ * This allocation method reserves enough memory pages for NQD shared DMA I/O
+ * buffers.  Each buffer must consume an integral number of memory pages to
+ * guarantee that a following buffer will begin on a page boundary.  Also,
+ * enough space is allocated so that the FIRST I/O buffer can start at the
+ * 1st page boundary after "&DMA_shared".  Page boundaries are used so that
+ * memory protections can be turned on/off for individual buffers. 
+ */
+#define IOBUFSIZE  ((DMA_BUFSIZ * NQD) + 512)
+
+char DMA_shared[IOBUFSIZE];        /* reserve I/O buffer space */
+struct DMAreq_header *DMAheader[NQD];  /* DMA buffer header pntrs */
+
+/*
+ * The driver assists a client in scroll operations by loading dragon
+ * registers from an interrupt service routine.        The loading is done using
+ * parameters found in memory shrade between the driver and it's client.
+ * The scroll parameter structures are ALL loacted in the same memory page
+ * for reasons of memory economy.  
+ */
+char scroll_shared[2 * 512];   /* reserve space for scroll structs */
+struct scroll *scroll[NQD];    /* pointers to scroll structures */
+
+/*
+ * the driver is programmable to provide the user with color map write
+ * services at VSYNC interrupt time.  At interrupt time the driver loads
+ * the color map with any user-requested load data found in shared memory 
+ */
+#define COLOR_SHARED  ((COLOR_BUFSIZ * NQD) + 512)
+
+char color_shared[COLOR_SHARED];      /* reserve space: color bufs */
+struct color_buf *color_buf[NQD];     /* pointers to color bufs */
+
+/*
+ * mouse input event structures 
+ */
+struct mouse_report last_rep[NQD];
+struct mouse_report current_rep[NQD];
+
+struct proc *qdrsel[NQD];      /* process waiting for select */
+struct _vs_cursor cursor[NQD]; /* console cursor */
+int qdcount = 0;               /* count of successfully probed qd's */
+int nNQD = NQD;
+int DMAbuf_size = DMA_BUFSIZ;
+int QDlast_DMAtype;             /* type of the last DMA operation */
+
+#define QDSSMAJOR      41      /* QDSS major device number */
+/*
+ * macro to get system time.  Used to time stamp event queue entries 
+ */
+#define TOY ((time.tv_sec * 100) + (time.tv_usec / 10000))
+
+int qdprobe();
+int qdattach();
+int qddint();                  /* DMA gate array intrpt service */
+int qdaint();                  /* Dragon ADDER intrpt service */
+int qdiint();
+
+u_short qdstd[] = { 0 };
+
+struct uba_driver qddriver = {
+       qdprobe,                /* device probe entry */
+       0,                      /* no slave device */
+       qdattach,               /* device attach entry */
+       0,                      /* no "fill csr/ba to start" */
+       qdstd,                  /* device addresses */
+       "qd",                   /* device name string */
+       qdinfo                  /* ptr to QDSS's uba_device struct */
+};
+
+#define QDPRIOR (PZERO-1)              /* must be negative */
+#define FALSE  0
+#define TRUE   ~FALSE
+#define BAD    -1
+#define GOOD   0
+
+/*
+ * macro to create a system virtual page number from system virtual adrs 
+ */
+#define VTOP(x)  (((int)x & ~0xC0000000) >> PGSHIFT)
+
+/*
+ * QDSS register address offsets from start of QDSS address space 
+ */
+#define QDSIZE  (52 * 1024)    /* size of entire QDSS foot print */
+#define TMPSIZE  (16 * 1024)   /* template RAM is 8k SHORT WORDS */
+#define TMPSTART 0x8000        /* offset of template RAM from base adrs */
+#define REGSIZE  (5 * 512)     /* regs touch 2.5k (5 pages) of addr space */
+#define REGSTART 0xC000        /* offset of reg pages from base adrs */
+#define ADDER  (REGSTART+0x000)
+#define DGA    (REGSTART+0x200)
+#define DUART  (REGSTART+0x400)
+#define MEMCSR (REGSTART+0x800)
+#define CLRSIZE  (3 * 512)             /* color map size */
+#define CLRSTART (REGSTART+0xA00)      /* color map start offset from base */
+/*  0x0C00 really */
+#define RED    (CLRSTART+0x000)
+#define BLUE   (CLRSTART+0x200)
+#define GREEN  (CLRSTART+0x400)
+
+
+/*
+ * QDSS minor device numbers.  The *real* minor device numbers are in
+ * the bottom two bits of the major/minor device spec.  Bits 2 and up are
+ * used to specify the QDSS device number (ie: which one?) 
+ */
+
+#define CONS           0
+#define GRAPHIC        2
+
+/*
+ * console cursor bitmap (white block cursor)  
+ */
+short cons_cursor[32] = {
+       /* A */ 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF,
+       0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF,
+       /* B */ 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF,
+       0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF
+};
+
+/*
+ * constants used in font operations 
+ */
+#define CHARS          190                     /* # of chars in the font */
+#define CHAR_HEIGHT    15                      /* char height in pixels */
+#define CHAR_WIDTH     8                       /* char width in pixels*/
+#define FONT_WIDTH     (CHAR_WIDTH * CHARS)    /* font width in pixels */
+#define ROWS           CHAR_HEIGHT
+#define FONT_X         0                       /* font's off screen adrs */
+#define FONT_Y         (2048 - CHAR_HEIGHT)
+
+/* Offset to second row characters (XXX - should remove) */
+#define FONT_OFFSET    ((MAX_SCREEN_X/CHAR_WIDTH)*CHAR_HEIGHT)
+
+extern char q_font[];          /* reference font object code */
+extern u_short q_key[];        /* reference key xlation tables */
+extern u_short q_shift_key[];
+extern char *q_special[];
+
+/*
+ * definitions for cursor acceleration reporting  
+ */
+#define ACC_OFF        0x01            /* acceleration is inactive */
+
+/*
+ * virtual console support.
+ */
+extern (*v_putc)();
+#ifdef KADB
+extern (*v_getc)();
+extern (*v_poll)();
+#endif
+extern struct cdevsw *consops;
+int qdputc();
+int qdgetc();
+int qdpoll();
+int qdstart();
+int qdpolling = 0;
+
+/*
+ * LK-201 state storage for input console keyboard conversion to ASCII 
+ */
+struct q_keyboard {
+       int shift;                      /* state variables      */
+       int cntrl;
+       int lock;
+       int lastcode;                   /* last keycode typed   */
+       unsigned kup[8];                /* bits for each keycode*/
+       unsigned dkeys[8];              /* down/up mode keys    */
+       char last;                      /* last character       */
+} q_keyboard;
+
+/*
+ * tty settings on first open
+ */
+#define IFLAG (BRKINT|ISTRIP|IXON|IXANY|ICRNL|IMAXBEL)
+#define OFLAG (OPOST|OXTABS|ONLCR)
+#define LFLAG (ISIG|ICANON|ECHO|IEXTEN)
+#define CFLAG (PARENB|CREAD|CS7|CLOCAL)
+
+/*
+ * Init QDSS as console (before probe routine)
+ */
+
+qdcons_init()
+{
+       register unit;
+       caddr_t phys_adr;               /* physical QDSS base adrs */
+       u_int mapix;                    /* index into QVmap[] array */
+       struct percpu *pcpu;            /* pointer to cpusw structure  */
+       register struct qbus *qb;
+       u_short *qdaddr;                /* address of QDSS IO page CSR */
+       u_short *devptr;                /* vitual device space */
+       extern cnputc();
+
+#define QDSSCSR 0x1F00
+
+       if (v_putc != cnputc)
+           return 0;
+
+       unit = 0;
+
+       /*
+        * find the cpusw entry that matches this machine. 
+        */
+       for (pcpu = percpu; pcpu && pcpu->pc_cputype != cpu; pcpu++)
+               ;
+       if (pcpu == NULL)
+           return 0;
+       if (pcpu->pc_io->io_type != IO_QBUS)
+           return 0;
+
+       /*
+        * Map device registers - the last 8K of qvmem.
+        */
+       qb = (struct qbus *)pcpu->pc_io->io_details;
+       ioaccess(qb->qb_iopage, UMEMmap[0] + qb->qb_memsize,
+                UBAIOPAGES * NBPG);
+       devptr = (u_short *)((char *)umem[0]+(qb->qb_memsize * NBPG));
+       qdaddr = (u_short *)((u_int)devptr + ubdevreg(QDSSCSR));
+       if (badaddr((caddr_t)qdaddr, sizeof(short)))
+               return 0;
+
+       /*
+        * Map q-bus memory used by qdss. (separate map)
+        */
+       mapix = QMEMSIZE - (CHUNK * (unit + 1));
+       phys_adr = qb->qb_maddr + mapix;
+       ioaccess(phys_adr, QVmap[0], (CHUNK*NQD));
+
+       /*
+        * tell QDSS which Q memory address base to decode 
+        * (shifted right 16 bits - its in 64K units)
+        */
+       *qdaddr = (u_short)((int)mapix >> 16);
+       qdflags[unit].config = *(u_short *)qdaddr;
+
+       /*
+        * load qdmap struct with the virtual addresses of the QDSS elements 
+        */
+       qdbase[unit] = (caddr_t) (qvmem[0]);
+       qdmap[unit].template = qdbase[unit] + TMPSTART;
+       qdmap[unit].adder = qdbase[unit] + ADDER;
+       qdmap[unit].dga = qdbase[unit] + DGA;
+       qdmap[unit].duart = qdbase[unit] + DUART;
+       qdmap[unit].memcsr = qdbase[unit] + MEMCSR;
+       qdmap[unit].red = qdbase[unit] + RED;
+       qdmap[unit].blue = qdbase[unit] + BLUE;
+       qdmap[unit].green = qdbase[unit] + GREEN;
+
+       qdflags[unit].duart_imask = 0;  /* init shadow variables */
+
+       /*
+        * init the QDSS  
+        */
+       /* 
+       printf("qdbase[0] = %x, qdmap[0].memcsr = %x\n",
+               (char *)qdbase[0], qdmap[0].memcsr);
+       */
+
+       *(short *)qdmap[unit].memcsr |= SYNC_ON; /* once only: turn on sync */
+
+       cursor[unit].x = 0;
+       cursor[unit].y = 0;
+       init_shared(unit);              /* init shared memory */
+       setup_dragon(unit);             /* init the ADDER/VIPER stuff */
+       clear_qd_screen(unit);          /* clear the screen */
+       ldfont(unit);                   /* load the console font */
+       ldcursor(unit, cons_cursor);    /* load default cursor map */
+       setup_input(unit);              /* init the DUART */
+       v_putc = qdputc;                /* kernel console output to qdss */
+#ifdef KADB
+       v_getc = qdgetc;                /* kernel console input from qdss */
+       v_poll = qdpoll;                /* kdb hook to disable char intr */
+#endif
+       consops = &cdevsw[QDSSMAJOR];   /* virtual console is qdss */
+       return 1;
+
+} /* qdcons_init */
+
+/*
+ *  Configure QDSS into Q memory and make it intrpt.
+ *
+ *  side effects: QDSS gets mapped into Qbus memory space at the first
+ *              vacant 64kb boundary counting back from the top of
+ *              Qbus memory space (qvmem+4mb)
+ *
+ *  return: QDSS bus request level and vector address returned in
+ *        registers by UNIX convention.
+ *
+ */
+qdprobe(reg)
+       caddr_t reg;    /* character pointer to the QDSS I/O page register */
+{
+       register int br, cvec;
+       register int unit;
+       struct dga *dga;                /* pointer to gate array structure */
+       int vector;
+#ifdef notdef
+       int *ptep;                      /* page table entry pointer */
+       caddr_t phys_adr;               /* physical QDSS base adrs */
+       u_int mapix;
+#endif
+
+#ifdef lint
+       br = 0; cvec = br; br = cvec; nNQD = br; br = nNQD;
+       qddint(0); qdaint(0); qdiint(0); (void)qdgetc();
+#endif
+
+       /*
+        * calculate board unit number from I/O page register address  
+        */
+       unit = (int) (((int)reg >> 1) & 0x0007);
+
+       /*
+        * QDSS regs must be mapped to Qbus memory space at a 64kb
+        * physical boundary.  The Qbus memory space is mapped into
+        * the system memory space at config time.  After config
+        * runs, "qvmem[0]" (ubavar.h) holds the system virtual adrs
+        * of the start of Qbus memory.   The Qbus memory page table
+        * is found via an array of pte ptrs called "QVmap[]" (ubavar.h)
+        * which is also loaded at config time.   These are the
+        * variables used below to find a vacant 64kb boundary in
+        * Qbus memory, and load it's corresponding physical adrs
+        * into the QDSS's I/O page CSR.  
+        */
+
+       /*
+        * Only if QD is the graphics device.
+        */
+
+       /* if this QDSS is NOT the console, then do init here.. */
+
+       if (unit != 0) {
+               printf("qd: can't support two qdss's (yet)\n");
+#ifdef notdef  /* can't test */
+               if (v_consputc != qdputc  ||  unit != 0) {
+
+                       /*
+                       * read QDSS config info 
+                       */
+                       qdflags[unit].config = *(u_short *)reg;
+
+                       /*
+                       * find an empty 64kb adrs boundary 
+                       */
+
+                       qdbase[unit] = (caddr_t) (qvmem[0] + QMEMSIZE - CHUNK);
+
+                       /*
+                       * find the cpusw entry that matches this machine. 
+                       */
+                       cpup = &cpusw[cpu];
+                       while (!(BADADDR(qdbase[unit], sizeof(short))))
+                               qdbase[unit] -= CHUNK;
+
+                       /*
+                       * tell QDSS which Q memory address base to decode 
+                       */
+                       mapix = (int) (VTOP(qdbase[unit]) - VTOP(qvmem[0]));
+                       ptep = (int *) QVmap[0] + mapix;
+                       phys_adr = (caddr_t)(((int)*ptep&0x001FFFFF)<<PGSHIFT);
+                       *(u_short *)reg = (u_short) ((int)phys_adr >> 16);
+
+                       /*
+                       * load QDSS adrs map with system addresses 
+                       * of device regs 
+                       */
+                       qdmap[unit].template = qdbase[unit] + TMPSTART;
+                       qdmap[unit].adder = qdbase[unit] + ADDER;
+                       qdmap[unit].dga = qdbase[unit] + DGA;
+                       qdmap[unit].duart = qdbase[unit] + DUART;
+                       qdmap[unit].memcsr = qdbase[unit] + MEMCSR;
+                       qdmap[unit].red = qdbase[unit] + RED;
+                       qdmap[unit].blue = qdbase[unit] + BLUE;
+                       qdmap[unit].green = qdbase[unit] + GREEN;
+
+                       /* device init */
+
+                       cursor[unit].x = 0;
+                       cursor[unit].y = 0;
+                       init_shared(unit);              /* init shared memory */
+                       setup_dragon(unit);     /* init the ADDER/VIPER stuff */
+                       ldcursor(unit, cons_cursor);    /* load default cursor map */
+                       setup_input(unit);              /* init the DUART */
+                       clear_qd_screen(unit);
+                       ldfont(unit);                   /* load the console font */
+
+                       /* once only: turn on sync */
+
+                       *(short *)qdmap[unit].memcsr |= SYNC_ON;
+               }
+#endif /*notdef*/
+       }
+
+       /*
+       * The QDSS interrupts at HEX vectors xx0 (DMA) xx4
+       * (ADDER) and xx8 (DUART).  Therefore, we take three
+       * vectors from the vector pool, and then continue
+       * to take them until we get a xx0 HEX vector.  The
+       * pool provides vectors in contiguous decending
+       * order.  
+       */
+
+       vector = (uba_hd[0].uh_lastiv -= 4*3);  /* take three vectors */
+
+       while (vector & 0x0F) {            /* if lo nibble != 0.. */
+               /* ..take another vector */
+               vector = (uba_hd[0].uh_lastiv -= 4);  
+       }
+
+       /*
+       * setup DGA to do a DMA interrupt (transfer count = 0)  
+       */
+       dga = (struct dga *) qdmap[unit].dga;
+       dga->csr = (short) HALT;        /* disable everything */
+       dga->ivr = (short) vector;      /* load intrpt base vector */
+       dga->bytcnt_lo = (short) 0;     /* DMA xfer count = 0 */
+       dga->bytcnt_hi = (short) 0;
+
+       /* 
+       * turn on DMA interrupts 
+       */
+       dga->csr &= ~SET_DONE_FIFO;
+       dga->csr |= DMA_IE | DL_ENB;
+
+       DELAY(20000);                   /* wait for the intrpt */
+       dga->csr = HALT;                /* stop the wheels */
+
+       if (cvec != vector)             /* if vector != base vector.. */
+               return(0);              /* ..return = 'no device' */
+
+       /*
+       * score this as an existing qdss
+       */
+       qdcount++;
+
+       return(sizeof(short));      /* return size of QDSS I/O page reg */
+
+} /* qdprobe */
+
+qdattach(ui)
+       struct uba_device *ui;
+{
+       register unit;                  /* QDSS module # for this call */
+
+       unit = ui->ui_unit;             /* get QDSS number */
+
+       /*
+       * init "qdflags[]" for this QDSS 
+       */
+       qdflags[unit].inuse = 0;        /* init inuse variable EARLY! */
+       qdflags[unit].mapped = 0;
+       qdflags[unit].kernel_loop = -1;
+       qdflags[unit].user_dma = 0;
+       qdflags[unit].curs_acc = ACC_OFF;
+       qdflags[unit].curs_thr = 128;
+       qdflags[unit].tab_res = 2;      /* default tablet resolution factor */
+       qdflags[unit].duart_imask = 0;  /* init shadow variables */
+       qdflags[unit].adder_ie = 0;
+
+       /*
+       * init structures used in kbd/mouse interrupt service.  This code must
+       * come after the "init_shared()" routine has run since that routine 
+       * inits the eq_header[unit] structure used here.   
+       */
+
+       /*
+       * init the "latest mouse report" structure 
+       */
+       last_rep[unit].state = 0;
+       last_rep[unit].dx = 0;
+       last_rep[unit].dy = 0;
+       last_rep[unit].bytcnt = 0;
+
+       /*
+       * init the event queue (except mouse position) 
+       */
+       eq_header[unit]->header.events = 
+           (struct _vs_event *)((int)eq_header[unit] + sizeof(struct qdinput));
+
+       eq_header[unit]->header.size = MAXEVENTS;
+       eq_header[unit]->header.head = 0;
+       eq_header[unit]->header.tail = 0;
+
+       /*
+        * open exclusive for graphics device.
+        */
+       qdopened[unit] = 0;
+
+} /* qdattach */
+
+/*ARGSUSED*/
+qdopen(dev, flag)
+       dev_t dev;
+       int flag;
+{
+       register struct uba_device *ui; /* ptr to uba structures */
+       register struct dga *dga;       /* ptr to gate array struct */
+       register struct tty *tp;
+       struct duart *duart;
+       int unit;
+       int minor_dev;
+
+       minor_dev = minor(dev); /* get QDSS minor device number */
+       unit = minor_dev >> 2;
+
+       /*
+       * check for illegal conditions  
+       */
+       ui = qdinfo[unit];              /* get ptr to QDSS device struct */
+       if (ui == 0  || ui->ui_alive == 0)
+               return(ENXIO);          /* no such device or address */
+
+       duart = (struct duart *) qdmap[unit].duart;
+       dga = (struct dga *) qdmap[unit].dga;
+
+       if ((minor_dev & 0x03) == 2) {
+               /*
+               * this is the graphic device... 
+               */
+               if (qdopened[unit] != 0)
+                       return(EBUSY);
+               else
+                       qdopened[unit] = 1;
+               qdflags[unit].inuse |= GRAPHIC_DEV;  /* graphics dev is open */
+               /*
+                * enble kbd & mouse intrpts in DUART mask reg 
+                */
+               qdflags[unit].duart_imask |= 0x22;
+               duart->imask = qdflags[unit].duart_imask;
+       } else {
+               /*
+               * this is the console 
+               */
+               qdflags[unit].inuse |= CONS_DEV;  /* mark console as open */
+               dga->csr |= CURS_ENB;
+               qdflags[unit].duart_imask |= 0x02;
+               duart->imask = qdflags[unit].duart_imask;
+               /*
+               * some setup for tty handling 
+               */
+               tp = &qd_tty[minor_dev];
+               tp->t_addr = ui->ui_addr;
+               tp->t_oproc = qdstart;
+               if ((tp->t_state & TS_ISOPEN) == 0) {
+                       ttychars(tp);
+                       tp->t_ispeed = B9600;
+                       tp->t_ospeed = B9600;
+                       tp->t_state = TS_ISOPEN | TS_CARR_ON;
+                       tp->t_iflag = TTYDEF_IFLAG;
+                       tp->t_oflag = TTYDEF_OFLAG;
+                       tp->t_lflag = TTYDEF_LFLAG;
+                       tp->t_cflag = TTYDEF_CFLAG;
+               }
+               /*
+               * enable intrpts, open line discipline 
+               */
+               dga->csr |= GLOBAL_IE;  /* turn on the interrupts */
+               return ((*linesw[tp->t_line].l_open)(dev, tp));
+       }
+       dga->csr |= GLOBAL_IE;  /* turn on the interrupts */
+       return(0);
+
+} /* qdopen */
+
+/*ARGSUSED*/
+qdclose(dev, flag, mode, p)
+       dev_t dev;
+       int flag, mode;
+       struct proc *p;
+{
+       register struct tty *tp;
+       register struct qdmap *qd;
+       register int *ptep;
+       struct dga *dga;                /* gate array register map pointer */
+       struct duart *duart;
+       struct adder *adder;
+       int unit;
+       int minor_dev;
+       u_int mapix;
+       int i;                          /* SIGNED index */
+
+       minor_dev = minor(dev);         /* get minor device number */
+       unit = minor_dev >> 2;          /* get QDSS number */
+       qd = &qdmap[unit];
+
+       if ((minor_dev & 0x03) == 2) {
+               /*
+               * this is the graphic device... 
+               */
+               if (qdopened[unit] != 1)
+                       return(EBUSY);
+               else
+                       qdopened[unit] = 0;     /* allow it to be re-opened */
+               /*
+               * re-protect device memory 
+               */
+               if (qdflags[unit].mapped & MAPDEV) {
+                       /*
+                       * TEMPLATE RAM 
+                       */
+                       mapix = VTOP((int)qd->template) - VTOP(qvmem[0]);
+                       ptep = (int *)(QVmap[0] + mapix);
+                       for (i = 0; i < btop(TMPSIZE); i++, ptep++)
+                               *ptep = (*ptep & ~PG_PROT) | PG_V | PG_KW;
+                       /*
+                       * ADDER 
+                       */
+                       mapix = VTOP((int)qd->adder) - VTOP(qvmem[0]);
+                       ptep = (int *)(QVmap[0] + mapix);
+                       for (i = 0; i < btop(REGSIZE); i++, ptep++)
+                               *ptep = (*ptep & ~PG_PROT) | PG_V | PG_KW;
+                       /*
+                       * COLOR MAPS 
+                       */
+                       mapix = VTOP((int)qd->red) - VTOP(qvmem[0]);
+                       ptep = (int *)(QVmap[0] + mapix);
+                       for (i = 0; i < btop(CLRSIZE); i++, ptep++)
+                               *ptep = (*ptep & ~PG_PROT) | PG_V | PG_KW;
+               }
+
+               /*
+               * re-protect DMA buffer and free the map registers 
+               */
+               if (qdflags[unit].mapped & MAPDMA) {
+                       dga = (struct dga *) qdmap[unit].dga;
+                       adder = (struct adder *) qdmap[unit].adder;
+                       dga->csr &= ~DMA_IE;
+                       dga->csr &= ~0x0600;         /* kill DMA */
+                       adder->command = CANCEL;
+                       /* 
+                        * if DMA was running, flush spurious intrpt 
+                        */
+                       if (dga->bytcnt_lo != 0) {
+                               dga->bytcnt_lo = 0;
+                               dga->bytcnt_hi = 0;
+                               DMA_SETIGNORE(DMAheader[unit]);
+                               dga->csr |= DMA_IE;
+                               dga->csr &= ~DMA_IE;
+                       }
+                       ptep = (int *)
+                          ((VTOP(DMAheader[unit]*4)) + (mfpr(SBR)|0x80000000));
+                       for (i = 0; i < btop(DMAbuf_size); i++, ptep++)
+                               *ptep = (*ptep & ~PG_PROT) | PG_V | PG_KW;
+                       ubarelse(0, &Qbus_unmap[unit]);
+               }
+
+               /*
+               * re-protect 1K (2 pages) event queue 
+               */
+               if (qdflags[unit].mapped & MAPEQ) {
+                       ptep = (int *)
+                          ((VTOP(eq_header[unit])*4) + (mfpr(SBR)|0x80000000));
+                       *ptep = (*ptep & ~PG_PROT) | PG_KW | PG_V; ptep++;
+                       *ptep = (*ptep & ~PG_PROT) | PG_KW | PG_V;
+               }
+               /*
+               * re-protect scroll param area and disable scroll intrpts  
+               */
+               if (qdflags[unit].mapped & MAPSCR) {
+                       ptep = (int *) ((VTOP(scroll[unit]) * 4)
+                               + (mfpr(SBR) | 0x80000000));
+                       /*
+                        * re-protect 512 scroll param area 
+                        */
+                       *ptep = (*ptep & ~PG_PROT) | PG_KW | PG_V;
+                       adder = (struct adder *) qdmap[unit].adder;
+                       qdflags[unit].adder_ie &= ~FRAME_SYNC;
+                       adder->interrupt_enable = qdflags[unit].adder_ie;
+               }
+               /*
+               * re-protect color map write buffer area and kill intrpts 
+               */
+               if (qdflags[unit].mapped & MAPCOLOR) {
+                       ptep = (int *) ((VTOP(color_buf[unit]) * 4)
+                               + (mfpr(SBR) | 0x80000000));
+                       *ptep = (*ptep & ~PG_PROT) | PG_KW | PG_V; ptep++;
+                       *ptep = (*ptep & ~PG_PROT) | PG_KW | PG_V;
+                       color_buf[unit]->status = 0;
+                       adder = (struct adder *) qdmap[unit].adder;
+                       qdflags[unit].adder_ie &= ~VSYNC;
+                       adder->interrupt_enable = qdflags[unit].adder_ie;
+               }
+               mtpr(TBIA, 0);          
+               /* flag everything now unmapped */
+               qdflags[unit].mapped = 0;   
+               qdflags[unit].inuse &= ~GRAPHIC_DEV;
+               qdflags[unit].curs_acc = ACC_OFF;
+               qdflags[unit].curs_thr = 128;
+               /*
+               * restore the console 
+               */
+               dga = (struct dga *) qdmap[unit].dga;
+               adder = (struct adder *) qdmap[unit].adder;
+               dga->csr &= ~DMA_IE;
+               dga->csr &= ~0x0600;    /* halt the DMA! (just in case...) */
+               dga->csr |= DMA_ERR;    /* clear error condition */
+               adder->command = CANCEL;
+               /*
+                * if DMA was running, flush spurious intrpt 
+                */
+               if (dga->bytcnt_lo != 0) {
+                       dga->bytcnt_lo = 0;
+                       dga->bytcnt_hi = 0;
+                       DMA_SETIGNORE(DMAheader[unit]);
+                       dga->csr |= DMA_IE;
+                       dga->csr &= ~DMA_IE;
+               }
+               init_shared(unit);              /* init shared memory */
+               setup_dragon(unit);             /* init ADDER/VIPER */
+               ldcursor(unit, cons_cursor);    /* load default cursor map */
+               setup_input(unit);              /* init the DUART */
+               ldfont(unit);
+               cursor[unit].x = 0;
+               cursor[unit].y = 0;
+               /*
+                * shut off the mouse rcv intrpt and turn on kbd intrpts 
+                */
+               duart = (struct duart *) qdmap[unit].duart;
+               qdflags[unit].duart_imask &= ~(0x20);
+               qdflags[unit].duart_imask |= 0x02;
+               duart->imask = qdflags[unit].duart_imask;
+               /*
+               * shut off interrupts if all is closed  
+               */
+               if (!(qdflags[unit].inuse & CONS_DEV)) {
+                       dga = (struct dga *) qdmap[unit].dga;
+                       dga->csr &= ~(GLOBAL_IE | DMA_IE);
+               }
+       } else {
+               /*
+               * this is the console 
+               */
+               tp = &qd_tty[minor_dev];
+               (*linesw[tp->t_line].l_close)(tp, flag);
+               ttyclose(tp);
+               tp->t_state = 0;
+               qdflags[unit].inuse &= ~CONS_DEV;
+               /*
+               * if graphics device is closed, kill interrupts 
+               */
+               if (!(qdflags[unit].inuse & GRAPHIC_DEV)) {
+                       dga = (struct dga *) qdmap[unit].dga;
+                       dga->csr &= ~(GLOBAL_IE | DMA_IE);
+               }
+       }
+
+       return(0);
+
+} /* qdclose */
+
+qdioctl(dev, cmd, datap, flags)
+       dev_t dev;
+       int cmd;
+       register caddr_t datap;
+       int flags;
+{
+       register int *ptep;             /* page table entry pointer */
+       register int mapix;             /* QVmap[] page table index */
+       register struct _vs_event *event;
+       register struct tty *tp;
+       register i;
+       struct qdmap *qd;               /* pointer to device map struct */
+       struct dga *dga;                /* Gate Array reg structure pntr */
+       struct duart *duart;            /* DUART reg structure pointer */
+       struct adder *adder;            /* ADDER reg structure pointer */
+       struct prgkbd *cmdbuf;
+       struct prg_cursor *curs;
+       struct _vs_cursor *pos;
+       int unit = minor(dev) >> 2;     /* number of caller's QDSS */
+       u_int minor_dev = minor(dev);
+       int error;
+       int s;
+       short *temp;                    /* a pointer to template RAM */
+
+       /*
+       * service graphic device ioctl commands 
+       */
+       switch (cmd) {
+
+       case QD_GETEVENT:
+               /*
+               * extract the oldest event from the event queue 
+               */
+               if (ISEMPTY(eq_header[unit])) {
+                       event = (struct _vs_event *) datap;
+                       event->vse_device = VSE_NULL;
+                       break;
+               }
+               event = (struct _vs_event *) GETBEGIN(eq_header[unit]);
+               s = spl5();
+               GETEND(eq_header[unit]);
+               splx(s);
+               bcopy((caddr_t)event, datap, sizeof(struct _vs_event));
+               break;
+
+       case QD_RESET:
+               /*
+               * init the dragon stuff, DUART, and driver variables  
+               */
+               init_shared(unit);              /* init shared memory */
+               setup_dragon(unit);           /* init the ADDER/VIPER stuff */
+               clear_qd_screen(unit);
+               ldcursor(unit, cons_cursor);    /* load default cursor map */
+               ldfont(unit);                   /* load the console font */
+               setup_input(unit);              /* init the DUART */
+               break;
+
+       case QD_SET:
+               /*
+               * init the DUART and driver variables  
+               */
+               init_shared(unit);
+               setup_input(unit);
+               break;
+
+       case QD_CLRSCRN:
+               /*
+               * clear the QDSS screen.  (NOTE that this reinits the dragon) 
+               */
+#ifdef notdef  /* has caused problems and isn't necessary */
+               setup_dragon(unit);
+               clear_qd_screen(unit);
+#endif
+               break;
+
+       case QD_WTCURSOR:
+               /*
+               * load a cursor into template RAM  
+               */
+               ldcursor(unit, (short *)datap);
+               break;
+
+       case QD_RDCURSOR:
+
+               temp = (short *) qdmap[unit].template;
+               /*
+                * cursor is 32 WORDS from the end of the 8k WORD...
+                *  ...template space 
+                */
+               temp += (8 * 1024) - 32;
+               for (i = 0; i < 32; ++i, datap += sizeof(short))
+                       *(short *)datap = *temp++;
+               break;
+
+       case QD_POSCURSOR:
+               /*
+               * position the mouse cursor  
+               */
+               dga = (struct dga *) qdmap[unit].dga;
+               pos = (struct _vs_cursor *) datap;
+               s = spl5();
+               dga->x_cursor = TRANX(pos->x);
+               dga->y_cursor = TRANY(pos->y);
+               eq_header[unit]->curs_pos.x = pos->x;
+               eq_header[unit]->curs_pos.y = pos->y;
+               splx(s);
+               break;
+
+       case QD_PRGCURSOR:
+               /*
+               * set the cursor acceleration factor 
+               */
+               curs = (struct prg_cursor *) datap;
+               s = spl5();
+               qdflags[unit].curs_acc = curs->acc_factor;
+               qdflags[unit].curs_thr = curs->threshold;
+               splx(s);
+               break;
+
+       case QD_MAPDEVICE:
+               /*
+               * enable 'user write' to device pages 
+               */
+               qdflags[unit].mapped |= MAPDEV;
+               qd = (struct qdmap *) &qdmap[unit];
+               /*
+               * enable user write to template RAM 
+               */
+               mapix = VTOP((int)qd->template) - VTOP(qvmem[0]);
+               ptep = (int *)(QVmap[0] + mapix);
+               for (i = 0; i < btop(TMPSIZE); i++, ptep++)
+                       *ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V;
+               /*
+               * enable user write to registers 
+               */
+               mapix = VTOP((int)qd->adder) - VTOP(qvmem[0]);
+               ptep = (int *)(QVmap[0] + mapix);
+               for (i = 0; i < btop(REGSIZE); i++, ptep++)
+                       *ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V;
+               /*
+               * enable user write to color maps 
+               */
+               mapix = VTOP((int)qd->red) - VTOP(qvmem[0]);
+               ptep = (int *)(QVmap[0] + mapix);
+               for (i = 0; i < btop(CLRSIZE); i++, ptep++)
+                       *ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V;
+               /*
+               * enable user write to DUART 
+               */
+               mapix = VTOP((int)qd->duart) - VTOP(qvmem[0]);
+               ptep = (int *)(QVmap[0] + mapix);
+               *ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V; /* duart page */
+
+               mtpr(TBIA, 0);          /* invalidate translation buffer */
+
+               /*
+                * stuff qdmap structure in return buffer 
+                */
+               bcopy((caddr_t)qd, datap, sizeof(struct qdmap));
+               break;
+
+       case QD_MAPIOBUF:
+               /*
+                * do setup for DMA by user process     
+                *
+                * set 'user write enable' bits for DMA buffer  
+                */
+               qdflags[unit].mapped |= MAPDMA;
+               ptep = (int *) ((VTOP(DMAheader[unit]) * 4)
+                       + (mfpr(SBR) | 0x80000000));
+               for (i = 0; i < btop(DMAbuf_size); i++, ptep++)
+                       *ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V;
+               mtpr(TBIA, 0);          /* invalidate translation buffer */
+               /*
+               * set up QBUS map registers for DMA 
+               */
+               DMAheader[unit]->QBAreg =
+                   uballoc(0, (caddr_t)DMAheader[unit], DMAbuf_size, 0);
+               if (DMAheader[unit]->QBAreg == 0)
+                   printf("qd%d: qdioctl: QBA setup error\n", unit);
+               Qbus_unmap[unit] = DMAheader[unit]->QBAreg;
+               DMAheader[unit]->QBAreg &= 0x3FFFF;
+               /*
+               * return I/O buf adr 
+               */
+               *(int *)datap = (int) DMAheader[unit];
+               break;
+
+       case QD_MAPSCROLL:
+               /*
+               * map the shared scroll param area and enable scroll interpts  
+               */
+               qdflags[unit].mapped |= MAPSCR;
+               ptep = (int *) ((VTOP(scroll[unit]) * 4)
+                       + (mfpr(SBR) | 0x80000000));
+               /*
+                * allow user write to scroll area 
+                */
+               *ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V;
+               mtpr(TBIA, 0);                  /* invalidate translation buf */
+               scroll[unit]->status = 0;
+               adder = (struct adder *) qdmap[unit].adder;
+               qdflags[unit].adder_ie |= FRAME_SYNC;
+               adder->interrupt_enable = qdflags[unit].adder_ie;
+               *(int *)datap = (int) scroll[unit]; /* return scroll area */
+               break;
+
+       case QD_UNMAPSCROLL:
+               /*
+               * unmap shared scroll param area and disable scroll intrpts 
+               */
+               if (qdflags[unit].mapped & MAPSCR) {
+                       qdflags[unit].mapped &= ~MAPSCR;
+                       ptep = (int *) ((VTOP(scroll[unit]) * 4)
+                               + (mfpr(SBR) | 0x80000000));
+                       /*
+                        * re-protect 512 scroll param area 
+                        */
+                       *ptep = (*ptep & ~PG_PROT) | PG_KW | PG_V;
+                       mtpr(TBIA, 0);  /* smash CPU's translation buf */
+                       adder = (struct adder *) qdmap[unit].adder;
+                       qdflags[unit].adder_ie &= ~FRAME_SYNC;
+                       adder->interrupt_enable = qdflags[unit].adder_ie;
+               }
+               break;
+
+       case QD_MAPCOLOR:
+               /*
+               * map shared color map write buf and turn on vsync intrpt 
+               */
+               qdflags[unit].mapped |= MAPCOLOR;
+               ptep = (int *) ((VTOP(color_buf[unit]) * 4)
+                       + (mfpr(SBR) | 0x80000000));
+               /*
+                * allow user write to color map write buffer 
+                */
+               *ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V; ptep++;
+               *ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V;
+               mtpr(TBIA, 0);                  /* clr CPU translation buf */
+               adder = (struct adder *) qdmap[unit].adder;
+               qdflags[unit].adder_ie |= VSYNC;
+               adder->interrupt_enable = qdflags[unit].adder_ie;
+               /*
+                * return color area address 
+                */
+               *(int *)datap = (int) color_buf[unit];
+               break;
+
+       case QD_UNMAPCOLOR:
+               /*
+                * unmap shared color map write buffer and kill VSYNC intrpts 
+                */
+               if (qdflags[unit].mapped & MAPCOLOR) {
+                       qdflags[unit].mapped &= ~MAPCOLOR;
+                       ptep = (int *) ((VTOP(color_buf[unit]) * 4)
+                               + (mfpr(SBR) | 0x80000000));
+                       /*
+                        * re-protect color map write buffer 
+                        */
+                       *ptep = (*ptep & ~PG_PROT) | PG_KW | PG_V; ptep++;
+                       *ptep = (*ptep & ~PG_PROT) | PG_KW | PG_V;
+                       mtpr(TBIA, 0);
+                       adder = (struct adder *) qdmap[unit].adder;
+                       qdflags[unit].adder_ie &= ~VSYNC;
+                       adder->interrupt_enable = qdflags[unit].adder_ie;
+               }
+               break;
+
+       case QD_MAPEVENT:
+               /*
+               * give user write access to the event queue 
+               */
+               qdflags[unit].mapped |= MAPEQ;
+               ptep = (int *) ((VTOP(eq_header[unit]) * 4)
+                       + (mfpr(SBR) | 0x80000000));
+               /*
+                * allow user write to 1K event queue 
+                */
+               *ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V; ptep++;
+               *ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V;
+               mtpr(TBIA, 0);                  /* clr CPU translation buf */
+               /*
+                * return event queue address 
+                */
+               *(int *)datap = (int)eq_header[unit];
+               break;
+
+       case QD_PRGKBD:
+               /*
+               * pass caller's programming commands to LK201 
+               */
+               duart = (struct duart *)qdmap[unit].duart;
+               cmdbuf = (struct prgkbd *)datap;    /* pnt to kbd cmd buf */
+               /*
+               * send command 
+               */
+               for (i = 1000; i > 0; --i) {
+                       if (duart->statusA&XMT_RDY) {
+                               duart->dataA = cmdbuf->cmd;
+                               break;
+                       }
+               }
+               if (i == 0) {
+                       printf("qd%d: qdioctl: timeout on XMT_RDY [1]\n", unit);
+                       break;
+               }
+               /*
+               * send param1? 
+               */
+               if (cmdbuf->cmd & LAST_PARAM)
+                       break;
+               for (i = 1000; i > 0; --i) {
+                       if (duart->statusA&XMT_RDY) {
+                               duart->dataA = cmdbuf->param1;
+                               break;
+                       }
+               }
+               if (i == 0) {
+                       printf("qd%d: qdioctl: timeout on XMT_RDY [2]\n", unit);
+                       break;
+               }
+               /*
+               * send param2? 
+               */
+               if (cmdbuf->param1 & LAST_PARAM)
+                   break;
+               for (i = 1000; i > 0; --i) {
+                       if (duart->statusA&XMT_RDY) {
+                               duart->dataA = cmdbuf->param2;
+                               break;
+                       }
+               }
+               if (i == 0) {
+                       printf("qd%d: qdioctl: timeout on XMT_RDY [3]\n", unit);
+                       break;
+               }
+               break;
+
+       case QD_PRGMOUSE:
+               /*
+               * pass caller's programming commands to the mouse  
+               */
+               duart = (struct duart *) qdmap[unit].duart;
+               for (i = 1000; i > 0; --i) {
+                       if (duart->statusB&XMT_RDY) {
+                               duart->dataB = *datap;
+                               break;
+                       }
+               }
+               if (i == 0) {
+                       printf("qd%d: qdioctl: timeout on XMT_RDY [4]\n", unit);
+               }
+               break;
+
+       case QD_RDCONFIG:
+               /*
+               * get QDSS configuration word and return it  
+               */
+               *(short *)datap = qdflags[unit].config;
+               break;
+
+       case QD_KERN_LOOP:
+       case QD_KERN_UNLOOP:
+               /*
+                * vestige from ultrix.  BSD uses TIOCCONS to redirect
+                * kernel console output.
+                */
+               break;
+
+       case QD_PRGTABLET:
+               /*
+               * program the tablet 
+               */
+               duart = (struct duart *) qdmap[unit].duart;
+               for (i = 1000; i > 0; --i) {
+                       if (duart->statusB&XMT_RDY) {
+                               duart->dataB = *datap;
+                               break;
+                       }
+               }
+               if (i == 0) {
+                       printf("qd%d: qdioctl: timeout on XMT_RDY [5]\n", unit);
+               }
+               break;
+
+       case QD_PRGTABRES:
+               /*
+               * program the tablet report resolution factor 
+               */
+               qdflags[unit].tab_res = *(short *)datap;
+               break;
+
+       default:
+               /*
+               * service tty ioctl's  
+               */
+               if (!(minor_dev & 0x02)) {
+                       tp = &qd_tty[minor_dev];
+                       error = 
+                          (*linesw[tp->t_line].l_ioctl)(tp, cmd, datap, flags);
+                       if (error >= 0) {
+                               return(error);
+                       }
+                       error = ttioctl(tp, cmd, datap, flags);
+                       if (error >= 0) {
+                               return(error);
+                       }
+               }
+               break;
+       }
+
+       return(0);
+
+} /* qdioctl */
+
+qdselect(dev, rw)
+       dev_t dev;
+       int rw;
+{
+       register s;
+       register unit;
+       register struct tty *tp;
+       u_int minor_dev = minor(dev);
+
+       s = spl5();
+       unit = minor_dev >> 2;
+
+       switch (rw) {
+       case FREAD:
+               if ((minor_dev & 0x03) == 2) {
+                       /*
+                       * this is a graphics device, so check for events
+                       */
+                       if(!(ISEMPTY(eq_header[unit]))) {
+                               splx(s);
+                               return(1);
+                       }
+                       qdrsel[unit] = u.u_procp;
+                       qdflags[unit].selmask |= SEL_READ;
+                       splx(s);
+                       return(0);
+               } else {
+                       /*
+                       * this is a tty device
+                       */
+                       tp = &qd_tty[minor_dev];
+                       if (ttnread(tp))
+                           return(1);
+                       tp->t_rsel = u.u_procp;
+                       splx(s);
+                       return(0);
+               }
+
+       case FWRITE:
+               if ((minor(dev) & 0x03) == 2) {
+                       /*
+                       * this is a graphics device, so check for dma buffers
+                       */
+                       if (DMA_ISEMPTY(DMAheader[unit]))
+                           {
+                               splx(s);
+                               return(1);
+                       }
+                       qdrsel[unit] = u.u_procp;
+                       qdflags[unit].selmask |= SEL_WRITE;
+                       splx(s);
+                       return(0);
+               } else {
+                       /*
+                       * this is a tty device
+                       */
+                       tp = &qd_tty[minor_dev];
+                       if (tp->t_outq.c_cc <= tp->t_lowat)
+                           return(1);
+                       tp->t_wsel = u.u_procp;
+                       splx(s);
+                       return(0);
+               }
+       }
+       splx(s);
+       return(0);
+
+} /* qdselect() */
+
+extern qd_strategy();
+
+qdwrite(dev, uio)
+       dev_t dev;
+       struct uio *uio;
+{
+       register struct tty *tp;
+       register minor_dev;
+       register unit;
+
+       minor_dev = minor(dev);
+       unit = (minor_dev >> 2) & 0x07;
+
+       if (((minor_dev&0x03) != 0x02) && (qdflags[unit].inuse&CONS_DEV)) {
+               /*
+               * this is the console...  
+               */
+               tp = &qd_tty[minor_dev];
+               return ((*linesw[tp->t_line].l_write)(tp, uio));
+       } else if (qdflags[unit].inuse & GRAPHIC_DEV) {
+               /*
+               * this is a DMA xfer from user space 
+               */
+               return (physio(qd_strategy, &qdbuf[unit],
+               dev, B_WRITE, minphys, uio));
+       }
+       return (ENXIO);
+}
+
+qdread(dev, uio)
+       dev_t dev;
+       struct uio *uio;
+{
+       register struct tty *tp;
+       register minor_dev;
+       register unit;
+
+       minor_dev = minor(dev);
+       unit = (minor_dev >> 2) & 0x07;
+
+       if ((minor_dev & 0x03) != 0x02 && qdflags[unit].inuse & CONS_DEV) {
+               /*
+               * this is the console
+               */
+               tp = &qd_tty[minor_dev];
+               return ((*linesw[tp->t_line].l_read)(tp, uio));
+       } else if (qdflags[unit].inuse & GRAPHIC_DEV) {
+               /*
+               * this is a bitmap-to-processor xfer 
+               */
+               return (physio(qd_strategy, &qdbuf[unit],
+               dev, B_READ, minphys, uio));
+       }
+       return (ENXIO);
+}
+
+/***************************************************************
+*
+*      qd_strategy()... strategy routine to do DMA
+*
+***************************************************************/
+
+qd_strategy(bp)
+       register struct buf *bp;
+{
+       register struct dga *dga;
+       register struct adder *adder;
+       register unit;
+       int QBAreg;
+       int s;
+       int cookie;
+
+       unit = (minor(bp->b_dev) >> 2) & 0x07;
+
+       /*
+       * init pointers 
+       */
+       if ((QBAreg = ubasetup(0, bp, 0)) == 0) {
+               printf("qd%d: qd_strategy: QBA setup error\n", unit);
+               goto STRAT_ERR;
+       }
+       dga = (struct dga *) qdmap[unit].dga;
+       s = spl5();
+       qdflags[unit].user_dma = -1;
+       dga->csr |= DMA_IE;
+       cookie = QBAreg & 0x3FFFF;
+       dga->adrs_lo = (short) cookie;
+       dga->adrs_hi = (short) (cookie >> 16);
+       dga->bytcnt_lo = (short) bp->b_bcount;
+       dga->bytcnt_hi = (short) (bp->b_bcount >> 16);
+
+       while (qdflags[unit].user_dma) {
+               sleep((caddr_t)&qdflags[unit].user_dma, QDPRIOR);
+       }
+       splx(s);
+       ubarelse(0, &QBAreg);
+       if (!(dga->csr & DMA_ERR)) {
+               iodone(bp);
+               return;
+       }
+
+STRAT_ERR:
+       adder = (struct adder *) qdmap[unit].adder;
+       adder->command = CANCEL;        /* cancel adder activity */
+       dga->csr &= ~DMA_IE;
+       dga->csr &= ~0x0600;            /* halt DMA (reset fifo) */
+       dga->csr |= DMA_ERR;            /* clear error condition */
+       bp->b_flags |= B_ERROR;         /* flag an error to physio() */
+
+       /*
+        * if DMA was running, flush spurious intrpt 
+        */
+       if (dga->bytcnt_lo != 0) {
+               dga->bytcnt_lo = 0;
+               dga->bytcnt_hi = 0;
+               DMA_SETIGNORE(DMAheader[unit]);
+               dga->csr |= DMA_IE;
+       }
+       iodone(bp);
+
+} /* qd_strategy */
+
+/*
+ *  Start output to the console screen
+ */
+qdstart(tp)
+       register struct tty *tp;
+{
+       register which_unit, unit, c;
+       int s;
+
+       unit = minor(tp->t_dev);
+       which_unit = (unit >> 2) & 0x3;
+       unit &= 0x03;
+
+       s = spl5();
+
+       /*
+       * If it's currently active, or delaying, no need to do anything. 
+       */
+       if (tp->t_state & (TS_TIMEOUT|TS_BUSY|TS_TTSTOP))
+               goto out;
+
+       /*
+       * Display chars until the queue is empty.
+       * Drop input from anything but the console
+       * device on the floor.  
+       *
+       * XXX - this loop is done at spltty.
+       *
+       */
+       while (tp->t_outq.c_cc) {
+               c = getc(&tp->t_outq);
+               if (unit == 0)
+                       blitc(which_unit, (u_char)c);
+       }
+       /*
+       * If there are sleepers, and output has drained below low
+       * water mark, wake up the sleepers. 
+       */
+       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);
+               }
+       }
+
+       tp->t_state &= ~TS_BUSY;
+
+out:
+       splx(s);
+
+} /* qdstart */
+
+/*ARGSUSED*/
+void
+qdstop(tp, flag)
+       register struct tty *tp;
+       int flag;
+{
+       register int s;
+
+       s = spl5();     /* block intrpts during state modification */
+       if (tp->t_state & TS_BUSY)
+               if ((tp->t_state & TS_TTSTOP) == 0)
+                       tp->t_state |= TS_FLUSH;
+               else
+                       tp->t_state &= ~TS_BUSY;
+       splx(s);
+}
+
+/*
+ *  Output a character to the QDSS screen
+ */
+
+blitc(unit, chr)
+       register unit;
+       register u_char chr;
+{
+       register struct adder *adder;
+       register struct dga *dga;
+       register int i;
+       int nograph = !(qdflags[unit].inuse&GRAPHIC_DEV);
+       static short inescape[NQD];
+
+       adder = (struct adder *)qdmap[unit].adder;
+       dga = (struct dga *) qdmap[unit].dga;
+       /* 
+        * BSD comment: this (&=0177) defeats the extended character 
+        * set code for the glass tty, but if i had the time i would 
+        * spend it ripping out the code completely.  This driver
+        * is too big for its own good.
+        */
+       chr &= 0177;
+       /*
+        * Cursor addressing (so vi will work).
+        * Decode for "\E=%.%." cursor motion description.
+        * Corresponds to type "qdcons" in /etc/termcap:
+        *
+        *    qd|qdss|qdcons|qdss glass tty (4.4 BSD):\
+        *      :am:do=^J:le=^H:bs:cm=\E=%.%.:cl=1^Z:co#128:li#57::nd=^L:up=^K:
+        *
+        */
+       if (inescape[unit] && nograph) {        
+               switch (inescape[unit]++) {
+               case 1:
+                       if (chr != '=') {
+                               /* abort escape sequence */
+                               inescape[unit] = 0;
+                               blitc(unit, chr);
+                       }
+                       return;
+               case 2:
+                       /* position row */
+                       cursor[unit].y = CHAR_HEIGHT * chr;
+                       if (cursor[unit].y > 863 - CHAR_HEIGHT)
+                               cursor[unit].y = 863 - CHAR_HEIGHT;
+                       dga->y_cursor = TRANY(cursor[unit].y);
+                       return;
+               case 3:
+                       /* position column */
+                       cursor[unit].x = CHAR_WIDTH * chr;
+                       if (cursor[unit].x > 1024 - CHAR_WIDTH)
+                               cursor[unit].x = 1023 - CHAR_WIDTH;
+                       dga->x_cursor = TRANX(cursor[unit].x);
+                       inescape[unit] = 0;
+                       return;
+               default:
+                       inescape[unit] = 0;
+                       blitc(unit, chr);
+               }
+       }
+
+       switch (chr) {
+       case '\r':                      /* return char */
+               cursor[unit].x = 0;
+               if (nograph)
+                       dga->x_cursor = TRANX(cursor[unit].x);
+               return;
+
+       case '\t':                      /* tab char */
+               for (i = 8 - ((cursor[unit].x >> 3) & 0x07); i > 0; --i) {
+                       blitc(unit, ' ');
+               }
+               return;
+
+       case '\n':                      /* line feed char */
+               if ((cursor[unit].y += CHAR_HEIGHT) > (863 - CHAR_HEIGHT)) {
+                       if (nograph) {
+                               cursor[unit].y -= CHAR_HEIGHT;
+                               scroll_up(adder);
+                       } else
+                               cursor[unit].y = 0;
+               }
+               if (nograph)
+                       dga->y_cursor = TRANY(cursor[unit].y);
+               return;
+
+       case '\b':                      /* backspace char */
+               if (cursor[unit].x > 0) {
+                       cursor[unit].x -= CHAR_WIDTH;
+                       if (nograph)
+                               dga->x_cursor = TRANX(cursor[unit].x);
+               }
+               return;
+       case CTRL('k'):         /* cursor up */
+               if (nograph && cursor[unit].y > 0) {
+                       cursor[unit].y -= CHAR_HEIGHT;
+                       dga->y_cursor = TRANY(cursor[unit].y);
+               }
+               return;
+
+       case CTRL('^'):         /* home cursor */
+               if (nograph) {
+                       cursor[unit].x = 0;
+                       dga->x_cursor = TRANX(cursor[unit].x);
+                       cursor[unit].y = 0;
+                       dga->y_cursor = TRANY(cursor[unit].y);
+               }
+               return;
+
+       case CTRL('l'):         /* cursor right */
+               if (nograph && cursor[unit].x < 1023 - CHAR_WIDTH) {
+                       cursor[unit].x += CHAR_WIDTH;
+                       dga->x_cursor = TRANX(cursor[unit].x);
+               }
+               return;
+
+       case CTRL('z'):         /* clear screen */
+               if (nograph) {
+                       setup_dragon(unit);     
+                       clear_qd_screen(unit);
+                       /* home cursor - termcap seems to assume this */
+                       cursor[unit].x = 0;
+                       dga->x_cursor = TRANX(cursor[unit].x);
+                       cursor[unit].y = 0;
+                       dga->y_cursor = TRANY(cursor[unit].y);
+               }
+               return;
+
+       case '\033':            /* start escape sequence */
+               if (nograph)
+                       inescape[unit] = 1;
+               return;
+
+       default:
+               if ((chr < ' ') || (chr > '~'))
+                       return;
+       }
+       /*
+        * setup VIPER operand control registers  
+        */
+       write_ID(adder, CS_UPDATE_MASK, 0x0001);  /* select plane #0 */
+       write_ID(adder, SRC1_OCR_B,
+       EXT_NONE | INT_SOURCE | ID | BAR_SHIFT_DELAY);
+       write_ID(adder, CS_UPDATE_MASK, 0x00FE);  /* select other planes */
+       write_ID(adder, SRC1_OCR_B,
+       EXT_SOURCE | INT_NONE | NO_ID | BAR_SHIFT_DELAY);
+       write_ID(adder, CS_UPDATE_MASK, 0x00FF);  /* select all planes */
+       write_ID(adder, DST_OCR_B,
+       EXT_NONE | INT_NONE | NO_ID | NO_BAR_SHIFT_DELAY);
+       write_ID(adder, MASK_1, 0xFFFF);
+       write_ID(adder, VIPER_Z_LOAD | FOREGROUND_COLOR_Z, 1);
+       write_ID(adder, VIPER_Z_LOAD | BACKGROUND_COLOR_Z, 0);
+       adder->x_clip_min = 0;
+       adder->x_clip_max = 1024;
+       adder->y_clip_min = 0;
+       adder->y_clip_max = 864;
+       /*
+        * load DESTINATION origin and vectors  
+        */
+       adder->fast_dest_dy = 0;
+       adder->slow_dest_dx = 0;
+       adder->error_1 = 0;
+       adder->error_2 = 0;
+       adder->rasterop_mode = DST_WRITE_ENABLE | NORMAL;
+       (void)wait_status(adder, RASTEROP_COMPLETE);
+       adder->destination_x = cursor[unit].x;
+       adder->fast_dest_dx = CHAR_WIDTH;
+       adder->destination_y = cursor[unit].y;
+       adder->slow_dest_dy = CHAR_HEIGHT;
+       /*
+        * load SOURCE origin and vectors  
+        */
+       if ((chr - ' ') > (CHARS - 1))  {
+               printf("Invalid character (x)%x in blitc\n",chr);
+               chr = ' ';
+       }
+       /*
+        * X position is modulo the number of characters per line 
+        */
+       adder->source_1_x = FONT_X + 
+           (((chr - ' ') % (MAX_SCREEN_X/CHAR_WIDTH)) * CHAR_WIDTH);
+       /*
+        * Point to either first or second row 
+        */
+       adder->source_1_y = 2048 - 15 * 
+           (((chr - ' ')/(MAX_SCREEN_X/CHAR_WIDTH)) + 1);
+       adder->source_1_dx = CHAR_WIDTH;
+       adder->source_1_dy = CHAR_HEIGHT;
+       write_ID(adder, LU_FUNCTION_R1, FULL_SRC_RESOLUTION | LF_SOURCE);
+       adder->cmd = RASTEROP | OCRB | 0 | S1E | DTE;
+       /*
+        * update console cursor coordinates 
+        */
+       cursor[unit].x += CHAR_WIDTH;
+       if (nograph)
+               dga->x_cursor = TRANX(cursor[unit].x);
+       if (cursor[unit].x > (1024 - CHAR_WIDTH)) {
+               blitc(unit, '\r');
+               blitc(unit, '\n');
+       }
+
+} /* blitc */
+
+qdreset() { }
+
+/*
+ *  INTERRUPT SERVICE ROUTINES
+ */
+
+/*
+ *  Service "DMA DONE" interrupt condition
+ */
+qddint(qd)
+       register qd;
+{
+       register struct DMAreq_header *header;
+       register struct DMAreq *request;
+       register struct dga *dga;
+       struct adder *adder;
+       int cookie;                     /* DMA adrs for QDSS */
+
+       (void)spl4();                   /* allow interval timer in */
+
+       /*
+       * init pointers 
+       */
+       header = DMAheader[qd];             /* register for optimization */
+       dga = (struct dga *) qdmap[qd].dga;
+       adder = (struct adder *) qdmap[qd].adder;
+
+       /*
+       * if this interrupt flagged as bogus for interrupt flushing purposes.. 
+       */
+       if (DMA_ISIGNORE(header)) {
+               DMA_CLRIGNORE(header);
+               return;
+       }
+
+       /*
+       * dump a DMA hardware error message if appropriate
+       */
+       if (dga->csr & DMA_ERR) {
+
+               if (dga->csr & PARITY_ERR)
+                   printf("qd%d: qddint: DMA hardware parity fault.\n", qd);
+
+               if (dga->csr & BUS_ERR)
+                   printf("qd%d: qddint: DMA hardware bus error.\n", qd);
+       }
+
+       /*
+       * if this was a DMA from user space... 
+       */
+       if (qdflags[qd].user_dma) {
+               qdflags[qd].user_dma = 0;
+               wakeup((caddr_t)&qdflags[qd].user_dma);
+               return;
+       }
+
+       /*
+       * if we're doing DMA request queue services, field the error condition 
+       */
+       if (dga->csr & DMA_ERR) {
+
+               dga->csr &= ~0x0600;            /* halt DMA (reset fifo) */
+               dga->csr |= DMA_ERR;            /* clear error condition */
+               adder->command = CANCEL;        /* cancel adder activity */
+
+               DMA_SETERROR(header);   /* flag error in header status word */
+               DMA_CLRACTIVE(header);
+               header->DMAreq[header->oldest].DMAdone |= HARD_ERROR;
+               header->newest = header->oldest;
+               header->used = 0;
+
+               if (qdrsel[qd] && qdflags[qd].selmask & SEL_WRITE) {
+                       selwakeup(qdrsel[qd], 0);
+                       qdrsel[qd] = 0;
+                       qdflags[qd].selmask &= ~SEL_WRITE;
+               }
+
+               if (dga->bytcnt_lo != 0) {
+                       dga->bytcnt_lo = 0;
+                       dga->bytcnt_hi = 0;
+                       DMA_SETIGNORE(header);
+               }
+               return;
+       }
+
+       /*
+       * if the DMA request queue is now becoming non-full, 
+       * wakeup "select" client.
+       */
+       if (DMA_ISFULL(header)) {
+               if (qdrsel[qd] && qdflags[qd].selmask & SEL_WRITE) {
+                       selwakeup(qdrsel[qd], 0);
+                       qdrsel[qd] = 0;
+                       qdflags[qd].selmask &= ~SEL_WRITE;
+               }
+       }
+
+       header->DMAreq[header->oldest].DMAdone |= REQUEST_DONE;
+       QDlast_DMAtype = header->DMAreq[header->oldest].DMAtype;
+
+       /* check for unexpected interrupt */
+       if (DMA_ISEMPTY(header))
+           return;
+
+       DMA_GETEND(header);     /* update request queue indices */
+
+       /*
+       * if no more DMA pending, wake up "select" client and exit 
+       */
+       if (DMA_ISEMPTY(header)) {
+
+               if (qdrsel[qd] && qdflags[qd].selmask & SEL_WRITE) {
+                       selwakeup(qdrsel[qd], 0);
+                       qdrsel[qd] = 0;
+                       qdflags[qd].selmask &= ~SEL_WRITE;
+               }
+
+               DMA_CLRACTIVE(header);  /* flag DMA done */
+               return;
+       }
+
+       /*
+       * initiate next DMA xfer  
+       */
+       request = DMA_GETBEGIN(header);
+       if (request->DMAtype != QDlast_DMAtype) {
+               dga->csr &= ~0x0600;      /* halt DMA (reset fifo) */
+               adder->command = CANCEL;  /* cancel adder activity */
+       }
+
+
+       switch (request->DMAtype) {
+
+       case DISPLIST:
+               if (request->DMAtype != QDlast_DMAtype) {
+                       dga->csr |= DL_ENB;
+                       dga->csr &= ~(BTOP_ENB | BYTE_DMA);
+               }
+               break;
+
+       case PTOB:
+               if (request->DMAtype != QDlast_DMAtype) {
+                       if (request->DMAdone & BYTE_PACK)
+                           dga->csr |= (PTOB_ENB | BYTE_DMA);
+                       else {
+                               dga->csr |= PTOB_ENB;
+                               dga->csr &= ~BYTE_DMA;
+                       }
+               }
+               break;
+
+       case BTOP:
+               if (request->DMAtype != QDlast_DMAtype) {
+                       if (request->DMAdone & BYTE_PACK) {
+                               dga->csr &= ~DL_ENB;
+                               dga->csr |= (BTOP_ENB | BYTE_DMA);
+                       }
+                       else {
+                               dga->csr |= BTOP_ENB;
+                               dga->csr &= ~(BYTE_DMA | DL_ENB);
+                       }
+               }
+               break;
+       default:
+               printf("qd%d: qddint: illegal DMAtype parameter.\n", qd);
+               DMA_CLRACTIVE(header);  /* flag DMA done */
+               return;
+       }
+
+       if (request->DMAdone & COUNT_ZERO) {
+               dga->csr &= ~SET_DONE_FIFO;
+       } 
+       else if (request->DMAdone & FIFO_EMPTY) {
+               dga->csr |= SET_DONE_FIFO;
+       }
+
+       if (request->DMAdone & WORD_PACK)
+           dga->csr &= ~BYTE_DMA;
+       else if (request->DMAdone & BYTE_PACK)
+           dga->csr |= BYTE_DMA;
+
+       dga->csr |= DMA_IE;
+       QDlast_DMAtype = request->DMAtype;
+
+       cookie = ((int)request->bufp - (int)header) + (int)header->QBAreg;
+
+       dga->adrs_lo = (short) cookie;
+       dga->adrs_hi = (short) (cookie >> 16);
+
+       dga->bytcnt_lo = (short) request->length;
+       dga->bytcnt_hi = (short) (request->length >> 16);
+
+       return;
+}
+
+/*
+ * ADDER interrupt service routine
+ */
+qdaint(qd)
+       register qd;
+{
+       register struct adder *adder;
+       struct color_buf *cbuf;
+       int i;
+       register struct rgb *rgbp;
+       register short *red;
+       register short *green;
+       register short *blue;
+
+       (void)spl4();                   /* allow interval timer in */
+
+       adder = (struct adder *) qdmap[qd].adder;
+
+       /*
+       * service the vertical blank interrupt (VSYNC bit) by loading 
+       * any pending color map load request  
+       */
+       if (adder->status & VSYNC) {
+               adder->status &= ~VSYNC;        /* clear the interrupt */
+               cbuf = color_buf[qd];
+               if (cbuf->status & LOAD_COLOR_MAP) {
+
+                       red = (short *) qdmap[qd].red;
+                       green = (short *) qdmap[qd].green;
+                       blue = (short *) qdmap[qd].blue;
+
+                       for (i = cbuf->count, rgbp = cbuf->rgb;
+                            --i >= 0; rgbp++) {
+                               red[rgbp->offset] = (short) rgbp->red;
+                               green[rgbp->offset] = (short) rgbp->green;
+                               blue[rgbp->offset] = (short) rgbp->blue;
+                       }
+
+                       cbuf->status &= ~LOAD_COLOR_MAP;
+               }
+       }
+
+       /*
+       * service the scroll interrupt (FRAME_SYNC bit) 
+       */
+       if (adder->status & FRAME_SYNC) {
+               adder->status &= ~FRAME_SYNC;   /* clear the interrupt */
+
+               if (scroll[qd]->status & LOAD_REGS) {
+
+                       for (i = 1000, adder->status = 0; i > 0 && 
+                            !(adder->status&ID_SCROLL_READY); --i)
+                             ;
+
+                       if (i == 0) {
+                           printf("qd%d: qdaint: timeout on ID_SCROLL_READY\n",
+                               qd);
+                               return;
+                       }
+
+                       adder->ID_scroll_data = scroll[qd]->viper_constant;
+                       adder->ID_scroll_command = ID_LOAD | SCROLL_CONSTANT;
+
+                       adder->y_scroll_constant =
+                               scroll[qd]->y_scroll_constant;
+                       adder->y_offset_pending = scroll[qd]->y_offset;
+
+                       if (scroll[qd]->status & LOAD_INDEX) {
+
+                               adder->x_index_pending = 
+                                       scroll[qd]->x_index_pending;
+                               adder->y_index_pending = 
+                                       scroll[qd]->y_index_pending;
+                       }
+
+                       scroll[qd]->status = 0x00;
+               }
+       }
+}
+
+/*
+ *  DUART input interrupt service routine
+ *
+ *  XXX - this routine should be broken out - it is essentially
+ *           straight line code.
+ */
+
+qdiint(qd)
+       register qd;
+{
+       register struct _vs_event *event;
+       register struct qdinput *eqh;
+       struct dga *dga;
+       struct duart *duart;
+       struct mouse_report *new_rep;
+       struct uba_device *ui;
+       struct tty *tp;
+       u_short chr;
+       u_short status;
+       u_short data;
+       u_short key;
+       char do_wakeup = 0;             /* flag to do a select wakeup call */
+       char a, b, c;                   /* mouse button test variables */
+
+       (void)spl4();                   /* allow interval timer in */
+
+       eqh = eq_header[qd];            /* optimized as a register */
+       new_rep = &current_rep[qd];
+       duart = (struct duart *) qdmap[qd].duart;
+
+       /*
+       * if the graphic device is turned on..  
+       */
+       if (qdflags[qd].inuse & GRAPHIC_DEV) {
+               /*
+               * empty DUART 
+               */
+               while (duart->statusA&RCV_RDY || duart->statusB&RCV_RDY) {
+                       /*
+                        * pick up LK-201 input (if any) 
+                        */
+                       if (duart->statusA&RCV_RDY) {
+
+                               /* if error condition, then reset it */
+
+                               if (duart->statusA&0x70) {
+                                       duart->cmdA = 0x40;
+                                       continue;
+                               }
+
+                               /* event queue full now? (overflow condition) */
+
+                               if (ISFULL(eqh) == TRUE) {
+                                       printf(
+                                        "qd%d: qdiint: event queue overflow\n",
+                                          qd);
+                                       break;
+                               }
+
+                               /*
+                               * Check for various keyboard errors  */
+
+                               key = duart->dataA & 0xFF;
+
+                               if (key==LK_POWER_ERROR ||
+                                   key==LK_KDOWN_ERROR ||
+                                   key == LK_INPUT_ERROR || 
+                                   key == LK_OUTPUT_ERROR) {
+                                       printf(
+                                   "qd%d: qdiint: keyboard error, code = %x\n",
+                                       qd,key);
+                                       return;
+                               }
+
+                               if (key < LK_LOWEST)
+                                   return;
+
+                               ++do_wakeup;  /* request a select wakeup call */
+
+                               event = PUTBEGIN(eqh);
+                               PUTEND(eqh);
+
+                               event->vse_key = key;
+                               event->vse_key &= 0x00FF;
+                               event->vse_x = eqh->curs_pos.x;
+                               event->vse_y = eqh->curs_pos.y;
+                               event->vse_time = TOY;
+                               event->vse_type = VSE_BUTTON;
+                               event->vse_direction = VSE_KBTRAW;
+                               event->vse_device = VSE_DKB;
+                       }
+
+                       /*
+                       * pick up the mouse input (if any)  */
+
+                       if ((status = duart->statusB) & RCV_RDY  &&
+                           qdflags[qd].pntr_id == MOUSE_ID) {
+
+                               if (status & 0x70) {
+                                       duart->cmdB = 0x40;
+                                       continue;
+                               }
+
+                               /* event queue full now? (overflow condition) */
+
+                               if (ISFULL(eqh) == TRUE) {
+                                       printf(
+                                       "qd%d: qdiint: event queue overflow\n",
+                                            qd);
+                                       break;
+                               }
+
+                               data = duart->dataB;      /* get report byte */
+                               ++new_rep->bytcnt; /* bump report byte count */
+
+                               /*
+                               * if 1st byte of report.. */
+
+                               if ( data & START_FRAME) {
+                                       new_rep->state = data;
+                                       if (new_rep->bytcnt > 1) {
+                                               /* start of new frame */
+                                               new_rep->bytcnt = 1;    
+                                               /* ..continue looking */
+                                               continue;                   
+                                       }
+                               }
+
+                               /*
+                               * if 2nd byte of report.. */
+
+                               else if (new_rep->bytcnt == 2) {
+                                       new_rep->dx = data & 0x00FF;
+                               }
+
+                               /*
+                               * if 3rd byte of report, load input event queue */
+
+                               else if (new_rep->bytcnt == 3) {
+
+                                       new_rep->dy = data & 0x00FF;
+                                       new_rep->bytcnt = 0;
+
+                                       /*
+                                       * if mouse position has changed.. */
+
+                                       if (new_rep->dx != 0  ||  new_rep->dy != 0) {
+
+                                               /*
+                                               * calculate acceleration factor, if needed      */
+
+                                               if (qdflags[qd].curs_acc > ACC_OFF) {
+
+                                                       if (qdflags[qd].curs_thr <= new_rep->dx)
+                                                           new_rep->dx +=
+                                                           (new_rep->dx - qdflags[qd].curs_thr)
+                                                           * qdflags[qd].curs_acc;
+
+                                                       if (qdflags[qd].curs_thr <= new_rep->dy)
+                                                           new_rep->dy +=
+                                                           (new_rep->dy - qdflags[qd].curs_thr)
+                                                           * qdflags[qd].curs_acc;
+                                               }
+
+                                               /*
+                                               * update cursor position coordinates */
+
+                                               if (new_rep->state & X_SIGN) {
+                                                       eqh->curs_pos.x += new_rep->dx;
+                                                       if (eqh->curs_pos.x > 1023)
+                                                           eqh->curs_pos.x = 1023;
+                                               }
+                                               else {
+                                                       eqh->curs_pos.x -= new_rep->dx;
+                                                       if (eqh->curs_pos.x < -15)
+                                                           eqh->curs_pos.x = -15;
+                                               }
+
+                                               if (new_rep->state & Y_SIGN) {
+                                                       eqh->curs_pos.y -= new_rep->dy;
+                                                       if (eqh->curs_pos.y < -15)
+                                                           eqh->curs_pos.y = -15;
+                                               }
+                                               else {
+                                                       eqh->curs_pos.y += new_rep->dy;
+                                                       if (eqh->curs_pos.y > 863)
+                                                           eqh->curs_pos.y = 863;
+                                               }
+
+                                               /*
+                                               * update cursor screen position */
+
+                                               dga = (struct dga *) qdmap[qd].dga;
+                                               dga->x_cursor = TRANX(eqh->curs_pos.x);
+                                               dga->y_cursor = TRANY(eqh->curs_pos.y);
+
+                                               /*
+                                               * if cursor is in the box, no event report */
+
+                                               if (eqh->curs_pos.x <= eqh->curs_box.right      &&
+                                                   eqh->curs_pos.x >= eqh->curs_box.left  &&
+                                                   eqh->curs_pos.y >= eqh->curs_box.top  &&
+                                                   eqh->curs_pos.y <= eqh->curs_box.bottom ) {
+                                                       goto GET_MBUTTON;
+                                               }
+
+                                               /*
+                                               * report the mouse motion event */
+
+                                               event = PUTBEGIN(eqh);
+                                               PUTEND(eqh);
+
+                                               ++do_wakeup;   /* request a select wakeup call */
+
+                                               event->vse_x = eqh->curs_pos.x;
+                                               event->vse_y = eqh->curs_pos.y;
+
+                                               event->vse_device = VSE_MOUSE;  /* mouse */
+                                               event->vse_type = VSE_MMOTION;  /* pos changed */
+                                               event->vse_key = 0;
+                                               event->vse_direction = 0;
+                                               event->vse_time = TOY;  /* time stamp */
+                                       }
+
+GET_MBUTTON:
+                                       /*
+                                       * if button state has changed */
+
+                                       a = new_rep->state & 0x07;    /*mask nonbutton bits */
+                                       b = last_rep[qd].state & 0x07;
+
+                                       if (a ^ b) {
+
+                                               for ( c = 1;  c < 8; c <<= 1) {
+
+                                                       if (!( c & (a ^ b))) /* this button change? */
+                                                           continue;
+
+                                                       /* event queue full? (overflow condition) */
+
+                                                       if (ISFULL(eqh) == TRUE) {
+                                                               printf("qd%d: qdiint: event queue overflow\n", qd);
+                                                               break;
+                                                       }
+
+                                                       event = PUTBEGIN(eqh);  /* get new event */
+                                                       PUTEND(eqh);
+
+                                                       ++do_wakeup;   /* request select wakeup */
+
+                                                       event->vse_x = eqh->curs_pos.x;
+                                                       event->vse_y = eqh->curs_pos.y;
+
+                                                       event->vse_device = VSE_MOUSE;  /* mouse */
+                                                       event->vse_type = VSE_BUTTON; /* new button */
+                                                       event->vse_time = TOY;        /* time stamp */
+
+                                                       /* flag changed button and if up or down */
+
+                                                       if (c == RIGHT_BUTTON)
+                                                           event->vse_key = VSE_RIGHT_BUTTON;
+                                                       else if (c == MIDDLE_BUTTON)
+                                                           event->vse_key = VSE_MIDDLE_BUTTON;
+                                                       else if (c == LEFT_BUTTON)
+                                                           event->vse_key = VSE_LEFT_BUTTON;
+
+                                                       /* set bit = button depressed */
+
+                                                       if (c & a)
+                                                           event->vse_direction = VSE_KBTDOWN;
+                                                       else
+                                                               event->vse_direction = VSE_KBTUP;
+                                               }
+                                       }
+
+                                       /* refresh last report */
+
+                                       last_rep[qd] = current_rep[qd];
+
+                               }  /* get last byte of report */
+                       } else if ((status = duart->statusB)&RCV_RDY &&
+                                  qdflags[qd].pntr_id == TABLET_ID) {
+                               /*
+                               * pickup tablet input, if any  
+                               */
+                               if (status&0x70) {
+                                       duart->cmdB = 0x40;
+                                       continue;
+                               }
+                               /* 
+                                * event queue full now? (overflow condition) 
+                                */
+                               if (ISFULL(eqh) == TRUE) {
+                                       printf("qd%d: qdiint: event queue overflow\n", qd);
+                                       break;
+                               }
+
+                               data = duart->dataB;      /* get report byte */
+                               ++new_rep->bytcnt;            /* bump report byte count */
+
+                               /*
+                               * if 1st byte of report.. */
+
+                               if (data & START_FRAME) {
+                                       new_rep->state = data;
+                                       if (new_rep->bytcnt > 1) {
+                                               new_rep->bytcnt = 1;    /* start of new frame */
+                                               continue;                   /* ..continue looking */
+                                       }
+                               }
+
+                               /*
+                               * if 2nd byte of report.. */
+
+                               else if (new_rep->bytcnt == 2) {
+                                       new_rep->dx = data & 0x3F;
+                               }
+
+                               /*
+                               * if 3rd byte of report.. */
+
+                               else if (new_rep->bytcnt == 3) {
+                                       new_rep->dx |= (data & 0x3F) << 6;
+                               }
+
+                               /*
+                               * if 4th byte of report.. */
+
+                               else if (new_rep->bytcnt == 4) {
+                                       new_rep->dy = data & 0x3F;
+                               }
+
+                               /*
+                               * if 5th byte of report, load input event queue */
+
+                               else if (new_rep->bytcnt == 5) {
+
+                                       new_rep->dy |= (data & 0x3F) << 6;
+                                       new_rep->bytcnt = 0;
+
+                                       /*
+                                       * update cursor position coordinates */
+
+                                       new_rep->dx /= qdflags[qd].tab_res;
+                                       new_rep->dy = (2200 - new_rep->dy)
+                                           / qdflags[qd].tab_res;
+
+                                       if (new_rep->dx > 1023) {
+                                               new_rep->dx = 1023;
+                                       }
+                                       if (new_rep->dy > 863) {
+                                               new_rep->dy = 863;
+                                       }
+
+                                       /*
+                                       * report an event if the puck/stylus has moved
+                                       */
+
+                                       if (eqh->curs_pos.x != new_rep->dx ||
+                                           eqh->curs_pos.y != new_rep->dy) {
+
+                                               eqh->curs_pos.x = new_rep->dx;
+                                               eqh->curs_pos.y = new_rep->dy;
+
+                                               /*
+                                               * update cursor screen position */
+
+                                               dga = (struct dga *) qdmap[qd].dga;
+                                               dga->x_cursor = TRANX(eqh->curs_pos.x);
+                                               dga->y_cursor = TRANY(eqh->curs_pos.y);
+
+                                               /*
+                                               * if cursor is in the box, no event report
+                                               */
+
+                                               if (eqh->curs_pos.x <= eqh->curs_box.right      &&
+                                                   eqh->curs_pos.x >= eqh->curs_box.left  &&
+                                                   eqh->curs_pos.y >= eqh->curs_box.top  &&
+                                                   eqh->curs_pos.y <= eqh->curs_box.bottom ) {
+                                                       goto GET_TBUTTON;
+                                               }
+
+                                               /*
+                                               * report the tablet motion event */
+
+                                               event = PUTBEGIN(eqh);
+                                               PUTEND(eqh);
+
+                                               ++do_wakeup;   /* request a select wakeup call */
+
+                                               event->vse_x = eqh->curs_pos.x;
+                                               event->vse_y = eqh->curs_pos.y;
+
+                                               event->vse_device = VSE_TABLET;  /* tablet */
+                                               /*
+                                               * right now, X handles tablet motion the same
+                                               * as mouse motion
+                                               */
+                                               event->vse_type = VSE_MMOTION;   /* pos changed */
+                                               event->vse_key = 0;
+                                               event->vse_direction = 0;
+                                               event->vse_time = TOY;  /* time stamp */
+                                       }
+GET_TBUTTON:
+                                       /*
+                                       * if button state has changed */
+
+                                       a = new_rep->state & 0x1E;   /* mask nonbutton bits */
+                                       b = last_rep[qd].state & 0x1E;
+
+                                       if (a ^ b) {
+
+                                               /* event queue full now? (overflow condition) */
+
+                                               if (ISFULL(eqh) == TRUE) {
+                                                       printf("qd%d: qdiint: event queue overflow\n",qd);
+                                                       break;
+                                               }
+
+                                               event = PUTBEGIN(eqh);  /* get new event */
+                                               PUTEND(eqh);
+
+                                               ++do_wakeup;   /* request a select wakeup call */
+
+                                               event->vse_x = eqh->curs_pos.x;
+                                               event->vse_y = eqh->curs_pos.y;
+
+                                               event->vse_device = VSE_TABLET;  /* tablet */
+                                               event->vse_type = VSE_BUTTON; /* button changed */
+                                               event->vse_time = TOY;     /* time stamp */
+
+                                               /* define the changed button and if up or down */
+
+                                               for ( c = 1;  c <= 0x10; c <<= 1) {
+                                                       if (c & (a ^ b)) {
+                                                               if (c == T_LEFT_BUTTON)
+                                                                   event->vse_key = VSE_T_LEFT_BUTTON;
+                                                               else if (c == T_FRONT_BUTTON)
+                                                                   event->vse_key = VSE_T_FRONT_BUTTON;
+                                                               else if (c == T_RIGHT_BUTTON)
+                                                                   event->vse_key = VSE_T_RIGHT_BUTTON;
+                                                               else if (c == T_BACK_BUTTON)
+                                                                   event->vse_key = VSE_T_BACK_BUTTON;
+                                                               break;
+                                                       }
+                                               }
+
+                                               /* set bit = button depressed */
+
+                                               if (c & a)
+                                                   event->vse_direction = VSE_KBTDOWN;
+                                               else
+                                                       event->vse_direction = VSE_KBTUP;
+                                       }
+
+                                       /* refresh last report */
+
+                                       last_rep[qd] = current_rep[qd];
+
+                               } /* get last byte of report */
+                       } /* pick up tablet input */
+
+               } /* while input available.. */
+
+               /*
+               * do select wakeup      
+               */
+               if (qdrsel[qd] && do_wakeup && qdflags[qd].selmask & SEL_READ) {
+                       selwakeup(qdrsel[qd], 0);
+                       qdrsel[qd] = 0;
+                       qdflags[qd].selmask &= ~SEL_READ;
+                       do_wakeup = 0;
+               }
+       } else {
+               /*
+                * if the graphic device is not turned on, this is console input
+                */
+               if (qdpolling)
+                       return;
+               ui = qdinfo[qd];
+               if (ui == 0 || ui->ui_alive == 0)
+                       return;
+
+               tp = &qd_tty[qd << 2];
+
+               /*
+                * Get a character from the keyboard. 
+                */
+               while (duart->statusA&RCV_RDY) {
+                       key = duart->dataA;
+                       key &= 0xFF;
+                       /*
+                       * Check for various keyboard errors  
+                       */
+                       if (key == LK_POWER_ERROR || key == LK_KDOWN_ERROR ||
+                           key == LK_INPUT_ERROR || key == LK_OUTPUT_ERROR) {
+                               printf("qd%d: qdiint: Keyboard error, code = %x\n",qd,key);
+                               return;
+                       }
+
+                       if (key < LK_LOWEST)
+                           return;
+
+                       /*
+                       * See if its a state change key */
+
+                       switch (key) {
+
+                       case LOCK:
+                               q_keyboard.lock ^= 0xffff;      /* toggle */
+                               if (q_keyboard.lock)
+                                       (void)led_control(qd, LK_LED_ENABLE,
+                                                         LK_LED_LOCK);
+                               else
+                                       (void)led_control(qd, LK_LED_DISABLE,
+                                                         LK_LED_LOCK);
+                               return;
+
+                       case SHIFT:
+                               q_keyboard.shift ^= 0xFFFF;
+                               return;
+
+                       case CNTRL:
+                               q_keyboard.cntrl ^= 0xFFFF;
+                               return;
+
+                       case ALLUP:
+                               q_keyboard.cntrl = 0;
+                               q_keyboard.shift = 0;
+                               return;
+
+                       case REPEAT:
+                               chr = q_keyboard.last;
+                               break;
+
+                               /*
+                               * Test for cntrl characters. If set, see if the character
+                               * is elligible to become a control character. */
+
+                       default:
+
+                               if (q_keyboard.cntrl) {
+                                       chr = q_key[key];
+                                       if (chr >= ' ' && chr <= '~')
+                                           chr &= 0x1F;
+                                       else if (chr >= 0xA1 && chr <= 0xFE)
+                                           chr &= 0x9F;
+                               }
+                               else if( q_keyboard.lock || q_keyboard.shift )
+                                   chr = q_shift_key[key];
+                               else
+                                       chr = q_key[key];
+                               break;
+                       }
+
+                       q_keyboard.last = chr;
+
+                       /*
+                       * Check for special function keys */
+
+                       if (chr & 0x100) {
+                               char *string;
+                               string = q_special[chr & 0x7F];
+                               while(*string)
+                                   (*linesw[tp->t_line].l_rint)(*string++, tp);
+                       }
+                       else {
+#ifdef KADB
+                               if (!kdbrintr(chr&0177, tp))
+#endif
+                               (*linesw[tp->t_line].l_rint)(chr&0177, tp);
+                       }
+               }
+       }
+} /* qdiint */
+
+/*
+ *
+ * Clear the QDSS screen
+ *
+ *                          >>> NOTE <<<
+ *
+ *   This code requires that certain adder initialization be valid.  To
+ *   assure that this requirement is satisfied, this routine should be
+ *   called only after calling the "setup_dragon()" function.
+ *
+ *   Clear the bitmap a piece at a time. Since the fast scroll clear
+ *   only clears the current displayed portion of the bitmap put a
+ *   temporary value in the y limit register so we can access whole
+ *   bitmap
+ *
+ */
+clear_qd_screen(unit)
+       int unit;
+{
+       register struct adder *adder;
+       adder = (struct adder *) qdmap[unit].adder;
+
+       adder->x_limit = 1024;
+       adder->y_limit = 2048 - CHAR_HEIGHT;
+       adder->y_offset_pending = 0;
+#define WSV  (void)wait_status(adder, VSYNC); (void)wait_status(adder, VSYNC)
+       WSV;
+       adder->y_scroll_constant = SCROLL_ERASE;
+       WSV;
+       adder->y_offset_pending = 864;
+       WSV;
+       adder->y_scroll_constant = SCROLL_ERASE;
+       WSV;
+       adder->y_offset_pending = 1728;
+       WSV;
+       adder->y_scroll_constant = SCROLL_ERASE;
+       WSV;
+       adder->y_offset_pending = 0;     /* back to normal */
+       WSV;
+       adder->x_limit = MAX_SCREEN_X;
+       adder->y_limit = MAX_SCREEN_Y + FONT_HEIGHT;
+#undef WSV
+
+} /* clear_qd_screen */
+
+/*
+ *  kernel console output to the glass tty
+ */
+qdputc(chr)
+       register char chr;
+{
+
+       /*
+        * if system is now physical, forget it (ie: crash DUMP) 
+        */
+       if ((mfpr(MAPEN) & 1) == 0)
+               return;
+
+       blitc(0, (u_char)(chr & 0xff));
+       if ((chr & 0177) == '\n')
+               blitc(0, '\r');
+
+} /* qdputc */
+
+/*
+ *  load the mouse cursor's template RAM bitmap
+ */
+ldcursor(unit, bitmap)
+       int unit;
+       register short *bitmap;
+{
+       register struct dga *dga;
+       register short *temp;
+       register int i;
+       int curs;
+
+       dga = (struct dga *) qdmap[unit].dga;
+       temp = (short *) qdmap[unit].template;
+
+       if (dga->csr & CURS_ENB) {      /* if the cursor is enabled.. */
+               curs = -1;              /* ..note that.. */
+               dga->csr &= ~CURS_ENB;  /* ..and shut it off */
+       } else 
+               curs = 0;
+
+       dga->csr &= ~CURS_ENB;          /* shut off the cursor */
+
+       temp += (8 * 1024) - 32;        /* cursor is 32 WORDS from the end */
+       /* ..of the 8k WORD template space */
+       for (i = 0; i < 32; ++i)
+               *temp++ = *bitmap++;
+
+       if (curs) {                     /* if cursor was enabled.. */
+               dga->csr |= CURS_ENB;   /* ..turn it back on */
+       }
+
+} /* ldcursor */
+
+/*
+ *  Put the console font in the QDSS off-screen memory
+ */
+ldfont(unit)
+       int unit;
+{
+       register struct adder *adder;
+
+       register i, j, k, max_chars_line;
+       register short packed;
+
+       adder = (struct adder *) qdmap[unit].adder;
+
+       /*
+       * setup VIPER operand control registers  
+       */
+       write_ID(adder, MASK_1, 0xFFFF);
+       write_ID(adder, VIPER_Z_LOAD | FOREGROUND_COLOR_Z, 255);
+       write_ID(adder, VIPER_Z_LOAD | BACKGROUND_COLOR_Z, 0);
+
+       write_ID(adder, SRC1_OCR_B,
+       EXT_NONE | INT_NONE | ID | BAR_SHIFT_DELAY);
+       write_ID(adder, SRC2_OCR_B,
+       EXT_NONE | INT_NONE | ID | BAR_SHIFT_DELAY);
+       write_ID(adder, DST_OCR_B,
+       EXT_SOURCE | INT_NONE | NO_ID | NO_BAR_SHIFT_DELAY);
+
+       adder->rasterop_mode = DST_WRITE_ENABLE | DST_INDEX_ENABLE | NORMAL;
+
+       /*
+       * load destination data  
+       */
+       (void)wait_status(adder, RASTEROP_COMPLETE);
+
+       adder->destination_x = FONT_X;
+       adder->destination_y = FONT_Y;
+#if FONT_WIDTH > MAX_SCREEN_X
+       adder->fast_dest_dx = MAX_SCREEN_X;
+#else
+       adder->fast_dest_dx = FONT_WIDTH;
+#endif
+       adder->slow_dest_dy = CHAR_HEIGHT;
+
+       /*
+       * setup for processor to bitmap xfer  */
+
+       write_ID(adder, CS_UPDATE_MASK, 0x0001);
+       adder->cmd = PBT | OCRB | 2 | DTE | 2;
+
+       /*
+       * Figure out how many characters can be stored on one "line" of 
+       * offscreen memory.
+       */
+       max_chars_line = MAX_SCREEN_X/(CHAR_WIDTH*2);
+       if ((CHARS/2 + CHARS%2) < max_chars_line)
+           max_chars_line = CHARS/2 + CHARS%2;
+
+       /*
+       * iteratively do the processor to bitmap xfer */
+
+       for (i = 0; i < ROWS; ++i) {
+
+               /* PTOB a scan line */
+
+               for (j = 0, k = i; j < max_chars_line; ++j) {
+                       /* PTOB one scan of a char cell */
+
+                       packed = q_font[k];
+                       k += ROWS;
+                       packed |= ((short)q_font[k] << 8);
+                       k += ROWS;
+
+                       (void)wait_status(adder, TX_READY);
+                       adder->id_data = packed;
+               }
+       }
+
+       /*
+        * (XXX XXX XXX - should remove)
+        *
+        * Copy the second row of characters.  Subtract the first
+        * row from the total number.  Divide this quantity by 2
+        * because 2 chars are stored in a short in the PTOB loop
+        * below.  Figure out how many characters can be stored on
+        * one "line" of offscreen memory 
+        */
+
+       max_chars_line = MAX_SCREEN_X/(CHAR_WIDTH*2);
+       if ((CHARS/2 + CHARS%2) < max_chars_line)
+           return;
+       max_chars_line = (CHARS/2 + CHARS%2) - max_chars_line; /* 95 - 64 */
+       /* Paranoia check to see if 3rd row may be needed */
+       if (max_chars_line > (MAX_SCREEN_X/(CHAR_WIDTH*2)))
+           max_chars_line = MAX_SCREEN_X/(CHAR_WIDTH*2);
+
+       adder->destination_x = FONT_X;
+       adder->destination_y = FONT_Y - CHAR_HEIGHT;
+       adder->fast_dest_dx = max_chars_line * CHAR_WIDTH * 2;
+       adder->slow_dest_dy = CHAR_HEIGHT;
+
+       /*
+       * setup for processor to bitmap xfer  
+       */
+       write_ID(adder, CS_UPDATE_MASK, 0x0001);
+       adder->cmd = PBT | OCRB | 2 | DTE | 2;
+
+       /*
+       * iteratively do the processor to bitmap xfer 
+       */
+       for (i = 0; i < ROWS; ++i) {
+               /* 
+                * PTOB a scan line 
+                */
+               for (j = 0, k = i; j < max_chars_line; ++j) {
+                       /*
+                        * PTOB one scan of a char cell 
+                        */
+                       packed = q_font[k + FONT_OFFSET];
+                       k += ROWS;
+                       packed |= ((short)q_font[k + FONT_OFFSET] << 8);
+                       k += ROWS;
+                       (void)wait_status(adder, TX_READY);
+                       adder->id_data = packed;
+               }
+       }
+
+}  /* ldfont */
+
+qdpoll(onoff)
+{
+       qdpolling = onoff;
+}
+
+/*
+ *  Get a character from the LK201 (polled)
+ */
+qdgetc()
+{
+       register short key;
+       register char chr;
+       register struct duart *duart;
+
+       duart = (struct duart *) qdmap[0].duart;
+
+       /*
+       * Get a character from the keyboard. 
+       */
+LOOP:
+       while (!(duart->statusA&RCV_RDY))
+               ;
+
+       key = duart->dataA;
+       key &= 0xFF;
+
+       /*
+       * Check for various keyboard errors  */
+
+       if (key == LK_POWER_ERROR || key == LK_KDOWN_ERROR ||
+           key == LK_INPUT_ERROR || key == LK_OUTPUT_ERROR) {
+               printf("Keyboard error, code = %x\n", key);
+               return(0);
+       }
+
+       if (key < LK_LOWEST)
+               return(0);
+
+       /*
+        * See if its a state change key 
+        */
+       switch (key) {
+
+       case LOCK:
+               q_keyboard.lock ^= 0xffff;      /* toggle */
+               if (q_keyboard.lock)
+                       (void)led_control(0, LK_LED_ENABLE, LK_LED_LOCK);
+               else
+                       (void)led_control(0, LK_LED_DISABLE, LK_LED_LOCK);
+               goto LOOP;
+
+       case SHIFT:
+               q_keyboard.shift ^= 0xFFFF;
+               goto LOOP;
+
+       case CNTRL:
+               q_keyboard.cntrl ^= 0xFFFF;
+               goto LOOP;
+
+       case ALLUP:
+               q_keyboard.cntrl = 0;
+               q_keyboard.shift = 0;
+               goto LOOP;
+
+       case REPEAT:
+               chr = q_keyboard.last;
+               break;
+
+               /*
+               * Test for cntrl characters. If set, see if the character
+               * is elligible to become a control character. 
+               */
+       default:
+
+               if (q_keyboard.cntrl) {
+                       chr = q_key[key];
+                       if (chr >= ' ' && chr <= '~')
+                           chr &= 0x1F;
+               }
+               else if ( q_keyboard.lock || q_keyboard.shift )
+                   chr = q_shift_key[key];
+               else
+                       chr = q_key[key];
+               break;
+       }
+
+       if (chr < ' ' && chr > '~')     /* if input is non-displayable */
+               return(0);              /* ..then pitch it! */
+
+       q_keyboard.last = chr;
+
+       /*
+       * Check for special function keys */
+
+       if (chr & 0x80)                 /* pitch the function keys */
+               return(0);
+       else
+               return(chr);
+
+} /* qdgetc */
+
+/*
+ *  led_control()... twiddle LK-201 LED's
+ */
+led_control(unit, cmd, led_mask)
+       int unit, cmd, led_mask;
+{
+       register i;
+       register struct duart *duart;
+
+       duart = (struct duart *)qdmap[unit].duart;
+
+       for (i = 1000; i > 0; --i) {
+               if (duart->statusA&XMT_RDY) {
+                       duart->dataA = cmd;
+                       break;
+               }
+       }
+       for (i = 1000; i > 0; --i) {
+               if (duart->statusA&XMT_RDY) {
+                       duart->dataA = led_mask;
+                       break;
+               }
+       }
+       if (i == 0)
+               return(BAD);
+       return(GOOD);
+
+} /* led_control */
+
+/*
+ *  scroll_up()... move the screen up one character height
+ */
+scroll_up(adder)
+       register struct adder *adder;
+{
+       /*
+       * setup VIPER operand control registers  
+       */
+       (void)wait_status(adder, ADDRESS_COMPLETE);
+       write_ID(adder, CS_UPDATE_MASK, 0x00FF);  /* select all planes */
+       write_ID(adder, MASK_1, 0xFFFF);
+       write_ID(adder, VIPER_Z_LOAD | FOREGROUND_COLOR_Z, 255);
+       write_ID(adder, VIPER_Z_LOAD | BACKGROUND_COLOR_Z, 0);
+       write_ID(adder, SRC1_OCR_B,
+       EXT_NONE | INT_SOURCE | ID | BAR_SHIFT_DELAY);
+       write_ID(adder, DST_OCR_B,
+       EXT_NONE | INT_NONE | NO_ID | NO_BAR_SHIFT_DELAY);
+       /*
+        * load DESTINATION origin and vectors  
+        */
+       adder->fast_dest_dy = 0;
+       adder->slow_dest_dx = 0;
+       adder->error_1 = 0;
+       adder->error_2 = 0;
+       adder->rasterop_mode = DST_WRITE_ENABLE | NORMAL;
+       adder->destination_x = 0;
+       adder->fast_dest_dx = 1024;
+       adder->destination_y = 0;
+       adder->slow_dest_dy = 864 - CHAR_HEIGHT;
+       /*
+        * load SOURCE origin and vectors  
+        */
+       adder->source_1_x = 0;
+       adder->source_1_dx = 1024;
+       adder->source_1_y = 0 + CHAR_HEIGHT;
+       adder->source_1_dy = 864 - CHAR_HEIGHT;
+       write_ID(adder, LU_FUNCTION_R1, FULL_SRC_RESOLUTION | LF_SOURCE);
+       adder->cmd = RASTEROP | OCRB | 0 | S1E | DTE;
+       /*
+        * do a rectangle clear of last screen line 
+        */
+       write_ID(adder, MASK_1, 0xffff);
+       write_ID(adder, SOURCE, 0xffff);
+       write_ID(adder,DST_OCR_B,
+       (EXT_NONE | INT_NONE | NO_ID | NO_BAR_SHIFT_DELAY));
+       write_ID(adder, VIPER_Z_LOAD | FOREGROUND_COLOR_Z, 0);
+       adder->error_1 = 0;
+       adder->error_2 = 0;
+       adder->slow_dest_dx = 0;                /* set up the width of  */
+       adder->slow_dest_dy = CHAR_HEIGHT;      /* rectangle */
+       adder->rasterop_mode = (NORMAL | DST_WRITE_ENABLE) ;
+       (void)wait_status(adder, RASTEROP_COMPLETE);
+       adder->destination_x = 0;
+       adder->destination_y = 864 - CHAR_HEIGHT;
+       adder->fast_dest_dx = 1024;     /* set up the height    */
+       adder->fast_dest_dy = 0;        /* of rectangle         */
+       write_ID(adder, LU_FUNCTION_R2, (FULL_SRC_RESOLUTION | LF_SOURCE));
+       adder->cmd = (RASTEROP | OCRB | LF_R2 | DTE ) ;
+
+} /* scroll_up */
+
+/*
+ *  init shared memory pointers and structures
+ */
+init_shared(unit)
+       register unit;
+{
+       register struct dga *dga;
+
+       dga = (struct dga *) qdmap[unit].dga;
+
+       /*
+       * initialize the event queue pointers and header */
+
+       eq_header[unit] = (struct qdinput *)
+           ((((int)event_shared & ~(0x01FF)) + 512)
+               + (EVENT_BUFSIZE * unit));
+       eq_header[unit]->curs_pos.x = 0;
+       eq_header[unit]->curs_pos.y = 0;
+       dga->x_cursor = TRANX(eq_header[unit]->curs_pos.x);
+       dga->y_cursor = TRANY(eq_header[unit]->curs_pos.y);
+       eq_header[unit]->curs_box.left = 0;
+       eq_header[unit]->curs_box.right = 0;
+       eq_header[unit]->curs_box.top = 0;
+       eq_header[unit]->curs_box.bottom = 0;
+       /*
+        * assign a pointer to the DMA I/O buffer for this QDSS. 
+        */
+       DMAheader[unit] = (struct DMAreq_header *)
+           (((int)(&DMA_shared[0] + 512) & ~0x1FF)
+               + (DMAbuf_size * unit));
+       DMAheader[unit]->DMAreq = (struct DMAreq *) ((int)DMAheader[unit]
+           + sizeof(struct DMAreq_header));
+       DMAheader[unit]->QBAreg = 0;
+       DMAheader[unit]->status = 0;
+       DMAheader[unit]->shared_size = DMAbuf_size;
+       DMAheader[unit]->used = 0;
+       DMAheader[unit]->size = 10;     /* default = 10 requests */
+       DMAheader[unit]->oldest = 0;
+       DMAheader[unit]->newest = 0;
+       /*
+       * assign a pointer to the scroll structure for this QDSS. 
+       */
+       scroll[unit] = (struct scroll *)
+           (((int)(&scroll_shared[0] + 512) & ~0x1FF)
+               + (sizeof(struct scroll) * unit));
+       scroll[unit]->status = 0;
+       scroll[unit]->viper_constant = 0;
+       scroll[unit]->y_scroll_constant = 0;
+       scroll[unit]->y_offset = 0;
+       scroll[unit]->x_index_pending = 0;
+       scroll[unit]->y_index_pending = 0;
+       /*
+       * assign a pointer to the color map write buffer for this QDSS 
+       */
+       color_buf[unit] = (struct color_buf *)
+           (((int)(&color_shared[0] + 512) & ~0x1FF)
+               + (COLOR_BUFSIZ * unit));
+       color_buf[unit]->status = 0;
+       color_buf[unit]->count = 0;
+
+} /* init_shared */
+
+/*
+ * init the ADDER, VIPER, bitmaps, & color map
+ */
+setup_dragon(unit)
+       int unit;
+{
+
+       register struct adder *adder;
+       register struct dga *dga;
+       short *memcsr;
+       register i;
+       short top;              /* clipping/scrolling boundaries */
+       short bottom;
+       short right;
+       short left;
+       short *red;             /* color map pointers */
+       short *green;
+       short *blue;
+
+       /*
+       * init for setup 
+       */
+       adder = (struct adder *) qdmap[unit].adder;
+       dga = (struct dga *) qdmap[unit].dga;
+       memcsr = (short *) qdmap[unit].memcsr;
+       dga->csr &= ~(DMA_IE | 0x700);  /* halt DMA and kill the intrpts */
+       *memcsr = SYNC_ON;              /* blank screen and turn off LED's */
+       adder->command = CANCEL;
+       /*
+       * set monitor timing 
+       */
+       adder->x_scan_count_0 = 0x2800;
+       adder->x_scan_count_1 = 0x1020;
+       adder->x_scan_count_2 = 0x003A;
+       adder->x_scan_count_3 = 0x38F0;
+       adder->x_scan_count_4 = 0x6128;
+       adder->x_scan_count_5 = 0x093A;
+       adder->x_scan_count_6 = 0x313C;
+       adder->sync_phase_adj = 0x0100;
+       adder->x_scan_conf = 0x00C8;
+       /*
+        * got a bug in secound pass ADDER! lets take care of it 
+        *
+        * normally, just use the code in the following bug fix code, but to
+        * make repeated demos look pretty, load the registers as if there was
+        * no bug and then test to see if we are getting sync 
+        */
+       adder->y_scan_count_0 = 0x135F;
+       adder->y_scan_count_1 = 0x3363;
+       adder->y_scan_count_2 = 0x2366;
+       adder->y_scan_count_3 = 0x0388;
+       /*
+        * if no sync, do the bug fix code 
+        */
+       if (wait_status(adder, VSYNC) == BAD) {
+               /* first load all Y scan registers with very short frame and
+                * wait for scroll service.  This guarantees at least one SYNC
+                * to fix the pass 2 Adder initialization bug (synchronizes
+                * XCINCH with DMSEEDH) 
+                */
+               adder->y_scan_count_0 = 0x01;
+               adder->y_scan_count_1 = 0x01;
+               adder->y_scan_count_2 = 0x01;
+               adder->y_scan_count_3 = 0x01;
+               /*
+                * delay at least 1 full frame time 
+                */
+               (void)wait_status(adder, VSYNC);        
+               (void)wait_status(adder, VSYNC);
+               /*
+                * now load the REAL sync values (in reverse order just to
+                * be safe.  
+                */
+               adder->y_scan_count_3 = 0x0388;
+               adder->y_scan_count_2 = 0x2366;
+               adder->y_scan_count_1 = 0x3363;
+               adder->y_scan_count_0 = 0x135F;
+       }
+       *memcsr = SYNC_ON | UNBLANK;    /* turn off leds and turn on video */
+       /*
+        * zero the index registers 
+        */
+       adder->x_index_pending = 0;
+       adder->y_index_pending = 0;
+       adder->x_index_new = 0;
+       adder->y_index_new = 0;
+       adder->x_index_old = 0;
+       adder->y_index_old = 0;
+       adder->pause = 0;
+       /*
+        * set rasterop mode to normal pen down 
+        */
+       adder->rasterop_mode = DST_WRITE_ENABLE | DST_INDEX_ENABLE | NORMAL;
+       /*
+        * set the rasterop registers to a default values 
+        */
+       adder->source_1_dx = 1;
+       adder->source_1_dy = 1;
+       adder->source_1_x = 0;
+       adder->source_1_y = 0;
+       adder->destination_x = 0;
+       adder->destination_y = 0;
+       adder->fast_dest_dx = 1;
+       adder->fast_dest_dy = 0;
+       adder->slow_dest_dx = 0;
+       adder->slow_dest_dy = 1;
+       adder->error_1 = 0;
+       adder->error_2 = 0;
+       /*
+        * scale factor = UNITY 
+        */
+       adder->fast_scale = UNITY;
+       adder->slow_scale = UNITY;
+       /*
+        * set the source 2 parameters 
+        */
+       adder->source_2_x = 0;
+       adder->source_2_y = 0;
+       adder->source_2_size = 0x0022;
+       /*
+       * initialize plane addresses for eight vipers 
+       */
+       write_ID(adder, CS_UPDATE_MASK, 0x0001);
+       write_ID(adder, PLANE_ADDRESS, 0x0000);
+       write_ID(adder, CS_UPDATE_MASK, 0x0002);
+       write_ID(adder, PLANE_ADDRESS, 0x0001);
+       write_ID(adder, CS_UPDATE_MASK, 0x0004);
+       write_ID(adder, PLANE_ADDRESS, 0x0002);
+       write_ID(adder, CS_UPDATE_MASK, 0x0008);
+       write_ID(adder, PLANE_ADDRESS, 0x0003);
+       write_ID(adder, CS_UPDATE_MASK, 0x0010);
+       write_ID(adder, PLANE_ADDRESS, 0x0004);
+       write_ID(adder, CS_UPDATE_MASK, 0x0020);
+       write_ID(adder, PLANE_ADDRESS, 0x0005);
+       write_ID(adder, CS_UPDATE_MASK, 0x0040);
+       write_ID(adder, PLANE_ADDRESS, 0x0006);
+       write_ID(adder, CS_UPDATE_MASK, 0x0080);
+       write_ID(adder, PLANE_ADDRESS, 0x0007);
+       /*
+        * initialize the external registers. 
+        */
+       write_ID(adder, CS_UPDATE_MASK, 0x00FF);
+       write_ID(adder, CS_SCROLL_MASK, 0x00FF);
+       /*
+        * initialize resolution mode 
+        */
+       write_ID(adder, MEMORY_BUS_WIDTH, 0x000C);     /* bus width = 16 */
+       write_ID(adder, RESOLUTION_MODE, 0x0000);      /* one bit/pixel */
+       /*
+        * initialize viper registers 
+        */
+       write_ID(adder, SCROLL_CONSTANT, SCROLL_ENABLE|VIPER_LEFT|VIPER_UP);
+       write_ID(adder, SCROLL_FILL, 0x0000);
+       /*
+        * set clipping and scrolling limits to full screen 
+        */
+       for (i = 1000, adder->status = 0; 
+            i > 0 && !(adder->status&ADDRESS_COMPLETE); --i)
+               ;
+       if (i == 0)
+           printf("qd%d: setup_dragon: timeout on ADDRESS_COMPLETE\n",unit);
+       top = 0;
+       bottom = 2048;
+       left = 0;
+       right = 1024;
+       adder->x_clip_min = left;
+       adder->x_clip_max = right;
+       adder->y_clip_min = top;
+       adder->y_clip_max = bottom;
+       adder->scroll_x_min = left;
+       adder->scroll_x_max = right;
+       adder->scroll_y_min = top;
+       adder->scroll_y_max = bottom;
+       (void)wait_status(adder, VSYNC);        /* wait at LEAST 1 full frame */
+       (void)wait_status(adder, VSYNC);
+       adder->x_index_pending = left;
+       adder->y_index_pending = top;
+       adder->x_index_new = left;
+       adder->y_index_new = top;
+       adder->x_index_old = left;
+       adder->y_index_old = top;
+
+       for (i = 1000, adder->status = 0; i > 0 && 
+            !(adder->status&ADDRESS_COMPLETE) ; --i)
+               ;
+       if (i == 0)
+              printf("qd%d: setup_dragon: timeout on ADDRESS_COMPLETE\n",unit);
+
+       write_ID(adder, LEFT_SCROLL_MASK, 0x0000);
+       write_ID(adder, RIGHT_SCROLL_MASK, 0x0000);
+       /*
+       * set source and the mask register to all ones (ie: white) o
+       */
+       write_ID(adder, SOURCE, 0xFFFF);
+       write_ID(adder, MASK_1, 0xFFFF);
+       write_ID(adder, VIPER_Z_LOAD | FOREGROUND_COLOR_Z, 255);
+       write_ID(adder, VIPER_Z_LOAD | BACKGROUND_COLOR_Z, 0);
+       /*
+       * initialize Operand Control Register banks for fill command 
+       */
+       write_ID(adder, SRC1_OCR_A, EXT_NONE | INT_M1_M2  | NO_ID | WAIT);
+       write_ID(adder, SRC2_OCR_A, EXT_NONE | INT_SOURCE | NO_ID | NO_WAIT);
+       write_ID(adder, DST_OCR_A, EXT_NONE | INT_NONE   | NO_ID | NO_WAIT);
+       write_ID(adder, SRC1_OCR_B, EXT_NONE | INT_SOURCE | NO_ID | WAIT);
+       write_ID(adder, SRC2_OCR_B, EXT_NONE | INT_M1_M2  | NO_ID | NO_WAIT);
+       write_ID(adder, DST_OCR_B, EXT_NONE | INT_NONE | NO_ID | NO_WAIT);
+       /*
+       * init Logic Unit Function registers, (these are just common values,
+       * and may be changed as required).  
+       */
+       write_ID(adder, LU_FUNCTION_R1, FULL_SRC_RESOLUTION | LF_SOURCE);
+       write_ID(adder, LU_FUNCTION_R2, FULL_SRC_RESOLUTION | LF_SOURCE |
+                INV_M1_M2);
+       write_ID(adder, LU_FUNCTION_R3, FULL_SRC_RESOLUTION | LF_D_OR_S);
+       write_ID(adder, LU_FUNCTION_R4, FULL_SRC_RESOLUTION | LF_D_XOR_S);
+       /*
+       * load the color map for black & white 
+       */
+       for (i = 0, adder->status = 0; i < 10000 && !(adder->status&VSYNC); ++i)
+               ;
+
+       if (i == 0)
+               printf("qd%d: setup_dragon: timeout on VSYNC\n", unit);
+
+       red = (short *) qdmap[unit].red;
+       green = (short *) qdmap[unit].green;
+       blue = (short *) qdmap[unit].blue;
+
+       *red++ = 0x00;                  /* black */
+       *green++ = 0x00;
+       *blue++ = 0x00;
+
+       *red-- = 0xFF;                  /* white */
+       *green-- = 0xFF;
+       *blue-- = 0xFF;
+
+       /*
+       * set color map for mouse cursor 
+       */
+
+       red += 254;
+       green += 254;
+       blue += 254;
+
+       *red++ = 0x00;                  /* black */
+       *green++ = 0x00;
+       *blue++ = 0x00;
+
+       *red = 0xFF;                    /* white */
+       *green = 0xFF;
+       *blue = 0xFF;
+
+} /* setup_dragon */
+
+/*
+ * Init the DUART and set defaults in input
+ */
+setup_input(unit)
+       int unit;
+{
+       register struct duart *duart;   /* DUART register structure pointer */
+       register i, bits;
+       char id_byte;
+
+       duart = (struct duart *) qdmap[unit].duart;
+       duart->imask = 0;
+
+       /*
+       * setup the DUART for kbd & pointing device 
+       */
+       duart->cmdA = RESET_M;  /* reset mode reg ptr for kbd */
+       duart->modeA = 0x13;    /* 8 bits, no parity, rcv IE, */
+                               /* no RTS control,char error mode */
+       duart->modeA = 0x07;    /* 1 stop bit,CTS does not IE XMT */
+                               /* no RTS control,no echo or loop */
+       duart->cmdB = RESET_M;  /* reset mode reg pntr for host */
+       duart->modeB = 0x07;    /* 8 bits, odd parity, rcv IE.. */
+                               /* ..no RTS cntrl, char error mode */
+       duart->modeB = 0x07;    /* 1 stop bit,CTS does not IE XMT */
+                               /* no RTS control,no echo or loop */
+       duart->auxctl = 0x00;   /* baud rate set 1 */
+       duart->clkselA = 0x99;  /* 4800 baud for kbd */
+       duart->clkselB = 0x99;  /* 4800 baud for mouse */
+
+       /* reset everything for keyboard */
+
+       for (bits = RESET_M; bits < START_BREAK; bits += 0x10)
+               duart->cmdA = bits;
+
+       /* reset everything for host */
+
+       for (bits = RESET_M; bits < START_BREAK; bits += 0x10)
+               duart->cmdB = bits;
+
+       duart->cmdA = EN_RCV | EN_XMT; /* enbl xmt & rcv for kbd */
+       duart->cmdB = EN_RCV | EN_XMT; /* enbl xmt & rcv for pointer device */
+
+       /*
+       * init keyboard defaults (DUART channel A) 
+       */
+       for (i = 500; i > 0; --i) {
+               if (duart->statusA&XMT_RDY) {
+                       duart->dataA = LK_DEFAULTS;
+                       break;
+               }
+       }
+
+       for (i = 100000; i > 0; --i) {
+               if (duart->statusA&RCV_RDY) {
+                       break;
+               }
+       }
+
+       if (duart->dataA)       /* flush the ACK */
+               ;               
+
+       /*
+       * identify the pointing device 
+       */
+       for (i = 500; i > 0; --i) {
+               if (duart->statusB&XMT_RDY) {
+                       duart->dataB = SELF_TEST;
+                       break;
+               }
+       }
+
+       /*
+       * wait for 1st byte of self test report */
+
+       for (i = 100000; i > 0; --i) {
+               if (duart->statusB&RCV_RDY) {
+                       break;
+               }
+       }
+
+       if (i == 0) {
+               printf("qd[%d]: setup_input: timeout on 1st byte of self test\n"
+                      ,unit);
+               goto OUT;
+       }
+
+       if (duart->dataB)
+               ;
+
+       /*
+       * wait for ID byte of self test report  
+       */
+       for (i = 100000; i > 0; --i) {
+               if (duart->statusB&RCV_RDY) {
+                       break;
+               }
+       }
+
+       if (i == 0) {
+               printf("qd[%d]: setup_input: timeout on 2nd byte of self test\n", unit);
+               goto OUT;
+       }
+
+       id_byte = duart->dataB;
+
+       /*
+       * wait for other bytes to come in  
+       */
+       for (i = 100000; i > 0; --i) {
+               if (duart->statusB & RCV_RDY) {
+                       if (duart->dataB)
+                               ;
+                       break;
+               }
+       }
+       if (i == 0) {
+               printf("qd[%d]: setup_input: timeout on 3rd byte of self test\n", unit);
+               goto OUT;
+       }
+       for (i = 100000; i > 0; --i) {
+               if (duart->statusB&RCV_RDY) {
+                       if (duart->dataB)
+                               ;
+                       break;
+               }
+       }
+       if (i == 0) {
+               printf("qd[%d]: setup_input: timeout on 4th byte of self test\n", unit);
+               goto OUT;
+       }
+       /*
+       * flag pointing device type and set defaults 
+       */
+       for (i=100000; i>0; --i)
+               ;               /*XXX*/
+
+       if ((id_byte & 0x0F) != TABLET_ID) {
+               qdflags[unit].pntr_id = MOUSE_ID;
+
+               for (i = 500; i > 0; --i) {
+                       if (duart->statusB&XMT_RDY) {
+                               duart->dataB = INC_STREAM_MODE;
+                               break;
+                       }
+               }
+       } 
+       else {
+               qdflags[unit].pntr_id = TABLET_ID;
+
+               for (i = 500; i > 0; --i) {
+                       if (duart->statusB&XMT_RDY) {
+                               duart->dataB = T_STREAM;
+                               break;
+                       }
+               }
+       }
+OUT:
+       duart->imask = qdflags[unit].duart_imask;
+
+} /* setup_input */
+
+/*
+ * delay for at least one display frame time
+ *
+ *     return: BAD means that we timed out without ever seeing the
+ *                   vertical sync status bit
+ *             GOOD otherwise
+ */
+wait_status(adder, mask)
+       register struct adder *adder;
+       register int mask;
+{
+       register i;
+
+       for (i = 10000, adder->status = 0 ; i > 0  &&  
+            !(adder->status&mask) ; --i)
+               ;
+
+       if (i == 0) {
+               printf("wait_status: timeout polling for 0x%x in adder->status\n", mask);
+               return(BAD);
+       }
+
+       return(GOOD);
+
+} /* wait_status */
+
+/*
+ * write out onto the ID bus
+ */
+write_ID(adder, adrs, data)
+       register struct adder *adder;
+       register short adrs;
+       register short data;
+{
+       register i;
+
+       for (i = 100000, adder->status = 0 ; 
+             i > 0  &&  !(adder->status&ADDRESS_COMPLETE) ; --i)
+               ;
+
+       if (i == 0)
+               goto ERR;
+
+       for (i = 100000, adder->status = 0 ; 
+             i > 0  &&  !(adder->status&TX_READY) ; --i)
+               ;
+
+       if (i > 0) {
+               adder->id_data = data;
+               adder->command = ID_LOAD | adrs;
+               return ;
+       }
+
+ERR:
+       printf("write_ID: timeout trying to write to VIPER\n");
+       return ;
+
+} /* write_ID */
+#endif
diff --git a/sys/arch/vax/uba/qv.c b/sys/arch/vax/uba/qv.c
new file mode 100644 (file)
index 0000000..650487d
--- /dev/null
@@ -0,0 +1,1323 @@
+/*     $NetBSD: qv.c,v 1.2 1996/09/02 06:44:28 mycroft Exp $   */
+
+/*-
+ * Copyright (c) 1988
+ *     The Regents of the University of California.  All rights reserved.
+ * (c) UNIX System Laboratories, Inc.
+ * All or some portions of this file are derived from material licensed
+ * to the University of California by American Telephone and Telegraph
+ * Co. or Unix System Laboratories, Inc. and are reproduced herein with
+ * the permission of UNIX System Laboratories, Inc.
+ *
+ * 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.
+ *
+ *     @(#)qv.c        7.2 (Berkeley) 1/21/94
+ */
+
+/*
+ *     derived from: @(#)qv.c  1.8 (ULTRIX) 8/21/85
+ */
+
+/************************************************************************
+ *                                                                     *
+ *                     Copyright (c) 1985 by                           *
+ *             Digital Equipment Corporation, Maynard, MA              *
+ *                     All rights reserved.                            *
+ *                                                                     *
+ *   This software is furnished under a license and may be used and    *
+ *   copied  only  in accordance with the terms of such license and    *
+ *   with the  inclusion  of  the  above  copyright  notice.   This    *
+ *   software  or  any  other copies thereof may not be provided or    *
+ *   otherwise made available to any other person.  No title to and    *
+ *   ownership of the software is hereby transferred.                  *
+ *                                                                     *
+ *   This software is  derived  from  software  received  from  the    *
+ *   University    of   California,   Berkeley,   and   from   Bell    *
+ *   Laboratories.  Use, duplication, or disclosure is  subject  to    *
+ *   restrictions  under  license  agreements  with  University  of    *
+ *   California and with AT&T.                                         *
+ *                                                                     *
+ *   The information in this software is subject to change  without    *
+ *   notice  and should not be construed as a commitment by Digital    *
+ *   Equipment Corporation.                                            *
+ *                                                                     *
+ *   Digital assumes no responsibility for the use  or  reliability    *
+ *   of its software on equipment which is not supplied by Digital.    *
+ *                                                                     *
+ ************************************************************************
+ *
+ * This driver provides glass tty functionality to the qvss. It is a strange
+ * device in that it supports three subchannels. The first being the asr,
+ * the second being a channel that intercepts the chars headed for the screen
+ * ( like a pseudo tty ) and the third being a source of mouse state changes.
+ * NOTE: the second is conditional on #ifdef CONS_HACK in this version
+ * of the driver, as it's a total crock.
+ *
+ * There may be one and only one qvss in the system.  This restriction is based
+ * on the inability to map more than one at a time.  This restriction will
+ * exist until the kernel has shared memory services. This driver therefore
+ * support a single unit. No attempt was made to have it service more.
+ *
+ * (this belongs in sccs - not here)
+ *
+ * 02 Aug 85 -- rjl
+ *     Changed the names of the special setup routines so that the system
+ *     can have a qvss or a qdss system console.
+ *
+ * 03 Jul 85 -- rjl
+ *     Added a check for virtual mode in qvputc so that the driver
+ *     doesn't crash while in a dump which is done in physical mode.
+ *
+ * 10 Apr 85 -- jg
+ *     Well, our theory about keyboard handling was wrong; most of the 
+ *     keyboard is in autorepeat, down mode.  These changes are to make
+ *     the qvss work the same as the Vs100, which is not necessarily
+ *     completely correct, as some chord usage may fail.  But since we
+ *     can't easily change the Vs100, we might as well propagate the
+ *     problem to another device.  There are also changes for screen and
+ *     mouse accellaration.
+ *
+ * 27 Mar 85 -- rjl
+ *     MicroVAX-II systems have interval timers that interrupt at ipl4.
+ *     Everything else is higher and thus causes us to miss clock ticks. The
+ *     problem isn't severe except in the case of a device like this one that
+ *     generates lots of interrupts. We aren't willing to make this change to
+ *     all device drivers but it seems acceptable in this case.
+ *
+ *  3 Dec 84 -- jg
+ *     To continue the tradition of building a better mouse trap,  this
+ *     driver has been extended to form Vs100 style event queues.  If the
+ *     mouse device is open, the keyboard events are intercepted and put
+ *     into the shared memory queue.  Unfortunately, we are ending up with
+ *     one of the longest Unix device drivers.  Sigh....
+ *
+ * 20 Nov 84 -- rjl
+ *      As a further complication this driver is required to function as the
+ *      virtual system console. This code runs before and during auto-
+ *      configuration and therefore is require to have a second path for setup.
+ *      It is futher constrained to have a character output routine that
+ *      is not dependant on the interrupt system.
+ *
+ */
+
+
+#include "qv.h"
+#if NQV > 0
+
+#include "../include/pte.h"
+
+#include "sys/param.h"
+#include "sys/conf.h"
+#include "sys/user.h"
+#include "qvioctl.h"
+#include "sys/tty.h"
+#include "sys/map.h"
+#include "sys/buf.h"
+#include "sys/vm.h"
+#include "sys/clist.h"
+#include "sys/file.h"
+#include "sys/uio.h"
+#include "sys/kernel.h"
+#include "sys/syslog.h"
+#include "../include/cpu.h"
+#include "../include/mtpr.h"
+#include "ubareg.h"
+#include "ubavar.h"
+
+#define CONS_HACK
+
+struct uba_device *qvinfo[NQV];
+
+struct tty qv_tty[NQV*4];
+
+#define        nNQV  NQV
+int    nqv = NQV*4;
+
+/*
+ * Definition of the driver for the auto-configuration program.
+ */
+int    qvprobe(), qvattach(), qvkint(), qvvint();
+u_short        qvstd[] = { 0 };
+struct uba_driver qvdriver =
+       { qvprobe, 0, qvattach, 0, qvstd, "qv", qvinfo };
+
+extern char qvmem[][512*NBPG];
+extern struct pte QVmap[][512];
+
+/*
+ * Local variables for the driver. Initialized for 15' screen
+ * so that it can be used during the boot process.
+ */
+
+#define QVWAITPRI      (PZERO+1)
+#define QVSSMAJOR      40
+
+#define QVKEYBOARD     0       /* minor 0, keyboard/glass tty */
+#define QVPCONS        1       /* minor 1, console interceptor XXX */
+#define QVMOUSECHAN    2       /* minor 2, mouse */
+#define        QVSPARE         3       /* unused */
+#define QVCHAN(unit)   ((unit) & 03)
+/*
+ * v_putc is the switch that is used to redirect the console cnputc to the
+ * virtual console vputc.  consops is used to redirect the console
+ * device to the qvss console.
+ */
+extern (*v_putc)();
+extern struct cdevsw *consops;
+/*
+ * qv_def_scrn is used to select the appropriate tables. 0=15 inch 1=19 inch,
+ * 2 = uVAXII.
+ */
+int qv_def_scrn = 2;
+
+#define QVMAXEVQ       64      /* must be power of 2 */
+#define EVROUND(x)     ((x) & (QVMAXEVQ - 1))
+
+/*
+ * Screen parameters 15 & 19 inch monitors. These determine the max size in
+ * pixel and character units for the display and cursor positions.
+ * Notice that the mouse defaults to original square algorithm, but X
+ * will change to its defaults once implemented.
+ */
+struct qv_info *qv_scn;
+struct qv_info qv_scn_defaults[] = {
+       {0, {0, 0}, 0, {0, 0}, 0, 0, 30, 80, 768, 480, 768-16, 480-16,
+        0, 0, 0, 0, 0, QVMAXEVQ, 0, 0, {0, 0}, {0, 0, 0, 0}, 2, 4},
+       {0, {0, 0}, 0, {0, 0}, 0, 0, 55, 120, 960, 864, 960-16, 864-16,
+        0, 0, 0, 0, 0, QVMAXEVQ, 0, 0, {0, 0}, {0, 0, 0, 0}, 2, 4},
+       {0, {0, 0}, 0, {0, 0}, 0, 0, 56, 120,1024, 864,1024-16, 864-16,
+        0, 0, 0, 0, 0, QVMAXEVQ, 0, 0, {0, 0}, {0, 0, 0, 0}, 2, 4}
+};
+
+/*
+ * Screen controller initialization parameters. The definations and use
+ * of these parameters can be found in the Motorola 68045 crtc specs. In
+ * essence they set the display parameters for the chip. The first set is
+ * for the 15" screen and the second is for the 19" seperate sync. There
+ * is also a third set for a 19" composite sync monitor which we have not
+ * tested and which is not supported.
+ */
+static short qv_crt_parms[][16] = {
+           { 31, 25, 27, 0142, 31, 13, 30, 31, 4, 15, 040, 0, 0, 0, 0, 0 },
+/* VR100*/ { 39, 30, 32, 0262, 55, 5, 54, 54, 4, 15, 040, 0, 0, 0, 0, 0 },
+/* VR260*/ { 39, 32, 33, 0264, 56, 5, 54, 54, 4, 15, 040, 0, 0, 0, 0, 0},
+};
+
+/*
+ * Screen parameters
+ */
+struct qv_info  *qv_scn;
+int maxqvmem = 254*1024 - sizeof(struct qv_info) - QVMAXEVQ*sizeof(vsEvent);
+       
+/*
+ * Keyboard state
+ */
+struct qv_keyboard {
+       int shift;                      /* state variables      */
+       int cntrl;
+       int lock;
+       char last;                      /* last character       */
+} qv_keyboard;
+
+short divdefaults[15] = { LK_DOWN,     /* 0 doesn't exist */
+       LK_AUTODOWN, LK_AUTODOWN, LK_AUTODOWN, LK_DOWN,
+       LK_UPDOWN,   LK_UPDOWN,   LK_AUTODOWN, LK_AUTODOWN, 
+       LK_AUTODOWN, LK_AUTODOWN, LK_AUTODOWN, LK_AUTODOWN, 
+       LK_DOWN, LK_AUTODOWN };
+
+short kbdinitstring[] = {              /* reset any random keyboard stuff */
+       LK_AR_ENABLE,                   /* we want autorepeat by default */
+       LK_CL_ENABLE,                   /* keyclick */
+       0x84,                           /* keyclick volume */
+       LK_KBD_ENABLE,                  /* the keyboard itself */
+       LK_BELL_ENABLE,                 /* keyboard bell */
+       0x84,                           /* bell volume */
+       LK_LED_DISABLE,                 /* keyboard leds */
+       LED_ALL };
+#define KBD_INIT_LENGTH        sizeof(kbdinitstring)/sizeof(short)
+
+#define TOY ((time.tv_sec * 100) + (time.tv_usec / 10000))
+
+int    qv_ipl_lo = 1;                  /* IPL low flag                 */
+int    mouseon = 0;                    /* mouse channel is enabled when 1*/
+struct proc *qvrsel;                   /* process waiting for select */
+
+int    qvstart(), qvputc(),  ttrstrt();
+
+/*
+ * Keyboard translation and font tables
+ */
+extern u_short q_key[], q_shift_key[], q_cursor[];
+extern char *q_special[], q_font[];
+
+/*
+ * See if the qvss will interrupt.
+ */
+
+/*ARGSUSED*/
+qvprobe(reg, ctlr)
+       caddr_t reg;
+       int ctlr;
+{
+       register int br, cvec;          /* these are ``value-result'' */
+       register struct qvdevice *qvaddr = (struct qvdevice *)reg;
+       static int tvec, ovec;
+
+#ifdef lint
+       br = 0; cvec = br; br = cvec;
+       qvkint(0); qvvint(0);
+#endif
+       /*
+        * Allocate the next two vectors
+        */
+       tvec = 0360;
+       ovec = cvec;
+       /*
+        * Turn on the keyboard and vertical interrupt vectors.
+        */
+       qvaddr->qv_intcsr = 0;          /* init the interrupt controler */
+       qvaddr->qv_intcsr = 0x40;       /* reset irr                    */
+       qvaddr->qv_intcsr = 0x80;       /* specify individual vectors   */
+       qvaddr->qv_intcsr = 0xc0;       /* preset autoclear data        */
+       qvaddr->qv_intdata = 0xff;      /* all setup as autoclear       */
+
+       qvaddr->qv_intcsr = 0xe0;       /* preset vector address 1      */
+       qvaddr->qv_intdata = tvec;      /* give it the keyboard vector  */
+       qvaddr->qv_intcsr = 0x28;       /* enable tx/rx interrupt       */
+
+       qvaddr->qv_intcsr = 0xe1;       /* preset vector address 2      */
+       qvaddr->qv_intdata = tvec+4;    /* give it the vertical sysnc   */
+       qvaddr->qv_intcsr = 0x29;       /* enable                       */
+
+       qvaddr->qv_intcsr = 0xa1;       /* arm the interrupt ctrl       */
+
+       qvaddr->qv_uartcmd = 0x15;      /* set mode pntr/enable rx/tx   */
+       qvaddr->qv_uartmode = 0x17;     /* noparity, 8-bit              */
+       qvaddr->qv_uartmode = 0x07;     /* 1 stop bit                   */
+       qvaddr->qv_uartstatus = 0x99;   /* 4800 baud xmit/recv          */
+       qvaddr->qv_uartintstatus = 2;   /* enable recv interrupts       */
+
+       qvaddr->qv_csr |= QV_INT_ENABLE | QV_CUR_MODE;
+
+       DELAY(10000);
+
+       qvaddr->qv_csr &= ~QV_INT_ENABLE;
+
+       /*
+        * If the qvss did interrupt it was the second vector not
+        * the first so we have to return the first so that they
+        * will be setup properly
+        */
+       if( ovec == cvec ) {
+               return 0;
+       } else
+               cvec -= 4;
+       return (sizeof (struct qvdevice));
+}
+
+/*
+ * Routine called to attach a qv.
+ */
+qvattach(ui)
+        struct uba_device *ui;
+{
+
+        /*
+         * If not the console then we have to setup the screen
+         */
+        if (v_putc != qvputc || ui->ui_unit != 0)
+                (void)qv_setup((struct qvdevice *)ui->ui_addr, ui->ui_unit, 1);
+       else
+               qv_scn->qvaddr = (struct qvdevice *)ui->ui_addr;
+}
+
+
+/*ARGSUSED*/
+qvopen(dev, flag)
+       dev_t dev;
+{
+       register struct tty *tp;
+       register int unit, qv;
+       register struct qvdevice *qvaddr;
+       register struct uba_device *ui;
+       register struct qv_info *qp = qv_scn;
+
+       unit = minor(dev);
+       qv = unit >> 2;
+       if (unit >= nqv || (ui = qvinfo[qv])== 0 || ui->ui_alive == 0)
+               return (ENXIO);
+       if (QVCHAN(unit) == QVSPARE
+#ifndef CONS_HACK
+          || QVCHAN(unit) == QVPCONS
+#endif
+          )
+               return (ENODEV);
+       tp = &qv_tty[unit];
+       if (tp->t_state&TS_XCLUDE && u.u_uid!=0)
+               return (EBUSY);
+       qvaddr = (struct qvdevice *)ui->ui_addr;
+        qv_scn->qvaddr = qvaddr;
+       tp->t_addr = (caddr_t)qvaddr;
+       tp->t_oproc = qvstart;
+
+       if ((tp->t_state&TS_ISOPEN) == 0) {
+               ttychars(tp);
+               tp->t_state = TS_ISOPEN|TS_CARR_ON;
+               tp->t_ispeed = B9600;
+               tp->t_ospeed = B9600;
+               if( QVCHAN(unit) == QVKEYBOARD ) {
+                       /* make sure keyboard is always back to default */
+                       qvkbdreset();
+                       qvaddr->qv_csr |= QV_INT_ENABLE;
+                       tp->t_iflag = TTYDEF_IFLAG;
+                       tp->t_oflag = TTYDEF_OFLAG;
+                       tp->t_lflag = TTYDEF_LFLAG;
+                       tp->t_cflag = TTYDEF_CFLAG;
+               }
+               /* XXX ?why?  else 
+                       tp->t_flags = RAW;
+               */
+       }
+       /*
+        * Process line discipline specific open if its not the
+        * mouse channel. For the mouse we init the ring ptr's.
+        */
+       if( QVCHAN(unit) != QVMOUSECHAN )
+               return ((*linesw[tp->t_line].l_open)(dev, tp));
+       else {
+               mouseon = 1;
+               /* set up event queue for later */
+               qp->ibuff = (vsEvent *)qp - QVMAXEVQ;
+               qp->iqsize = QVMAXEVQ;
+               qp->ihead = qp->itail = 0;
+               return 0;
+       }
+}
+
+/*
+ * Close a QVSS line.
+ */
+/*ARGSUSED*/
+qvclose(dev, flag, mode, p)
+       dev_t dev;
+       int flag, mode;
+       struct proc *p;
+{
+       register struct tty *tp;
+       register unit;
+       register struct qvdevice *qvaddr;
+       int error;
+
+       unit = minor(dev);
+       tp = &qv_tty[unit];
+
+       /*
+        * If this is the keyboard unit (0) shutdown the
+        * interface.
+        */
+       qvaddr = (struct qvdevice *)tp->t_addr;
+       if (QVCHAN(unit) == QVKEYBOARD )
+               qvaddr->qv_csr &= ~QV_INT_ENABLE;
+
+       /*
+        * If unit is not the mouse channel call the line disc.
+        * otherwise clear the state flag, and put the keyboard into down/up.
+        */
+       if (QVCHAN(unit) != QVMOUSECHAN) {
+               (*linesw[tp->t_line].l_close)(tp, flag);
+               error = ttyclose(tp);
+       } else {
+               mouseon = 0;
+               qv_init( qvaddr );
+               error = 0;
+       }
+       tp->t_state = 0;
+       return (error);
+}
+
+qvread(dev, uio)
+       dev_t dev;
+       struct uio *uio;
+{
+       register struct tty *tp;
+       int unit = minor( dev );
+
+       if (QVCHAN(unit) != QVMOUSECHAN) {
+               tp = &qv_tty[unit];
+               return ((*linesw[tp->t_line].l_read)(tp, uio));
+       }
+       return (ENXIO);
+}
+
+qvwrite(dev, uio)
+       dev_t dev;
+       struct uio *uio;
+{
+       register struct tty *tp;
+       int unit = minor( dev );
+
+       /*
+        * If this is the mouse we simply fake the i/o, otherwise
+        * we let the line disp. handle it.
+        */
+       if (QVCHAN(unit) == QVMOUSECHAN) {
+               uio->uio_offset = uio->uio_resid;
+               uio->uio_resid = 0;
+               return 0;
+       }
+       tp = &qv_tty[unit];
+       return ((*linesw[tp->t_line].l_write)(tp, uio));
+}
+
+
+/*
+ * Mouse activity select routine
+ */
+qvselect(dev, rw)
+dev_t dev;
+{
+       register int s = spl5();
+       register struct qv_info *qp = qv_scn;
+
+       if( QVCHAN(minor(dev)) == QVMOUSECHAN )
+               switch(rw) {
+               case FREAD:                     /* if events okay */
+                       if(qp->ihead != qp->itail) {
+                               splx(s);
+                               return(1);
+                       }
+                       qvrsel = u.u_procp;
+                       splx(s);
+                       return(0);
+               default:                        /* can never write */
+                       splx(s);
+                       return(0);
+               }
+       else {
+               splx(s);
+               return( ttselect(dev, rw) );
+       }
+       /*NOTREACHED*/
+}
+               
+/*
+ * QVSS keyboard interrupt.
+ */
+qvkint(qv)
+       int qv;
+{
+       struct tty *tp;
+       register c;
+       struct uba_device *ui;
+       register int key;
+       register int i;
+
+       ui = qvinfo[qv];
+       if (ui == 0 || ui->ui_alive == 0)
+               return;
+       tp = &qv_tty[qv<<2];
+       /*
+        * Get a character from the keyboard.
+        */
+       key = ((struct qvdevice *)ui->ui_addr)->qv_uartdata & 0xff;
+       if( mouseon == 0) {
+               /*
+                * Check for various keyboard errors
+                */
+               if( key == LK_POWER_ERROR || key == LK_KDOWN_ERROR ||
+                   key == LK_INPUT_ERROR || key == LK_OUTPUT_ERROR) {
+                       log(LOG_ERR,
+                           "qv%d: Keyboard error, code = %x\n",qv,key);
+                       return;
+               }
+               if( key < LK_LOWEST ) return;
+               /*
+                * See if its a state change key
+                */
+               switch ( key ) {
+               case LOCK:
+                       qv_keyboard.lock ^= 0xffff;     /* toggle */
+                       if( qv_keyboard.lock )
+                               qv_key_out( LK_LED_ENABLE );
+                       else
+                               qv_key_out( LK_LED_DISABLE );
+                       qv_key_out( LED_3 );
+                       return;
+               case SHIFT:
+                       qv_keyboard.shift ^= 0xffff;
+                       return; 
+               case CNTRL:
+                       qv_keyboard.cntrl ^= 0xffff;
+                       return;
+               case ALLUP:
+                       qv_keyboard.cntrl = qv_keyboard.shift = 0;
+                       return;
+               case REPEAT:
+                       c = qv_keyboard.last;
+                       break;
+               default:
+               /*
+                * Test for control characters. If set, see if the character
+                * is elligible to become a control character.
+                */
+                       if( qv_keyboard.cntrl ) {
+                               c = q_key[ key ];
+                               if( c >= ' ' && c <= '~' )
+                                       c &= 0x1f;
+                       } else if( qv_keyboard.lock || qv_keyboard.shift )
+                               c = q_shift_key[ key ];
+                               else
+                               c = q_key[ key ];
+                       break;  
+               }
+
+               qv_keyboard.last = c;
+
+               /*
+                * Check for special function keys
+                */
+               if( c & 0x80 ) {
+                       register char *string;
+                       string = q_special[ c & 0x7f ];
+                       while( *string )
+                       (*linesw[tp->t_line].l_rint)(*string++, tp);
+               } else
+                       (*linesw[tp->t_line].l_rint)(c, tp);
+       } else {
+               /*
+                * Mouse channel is open put it into the event queue
+                * instead.
+                */
+               register struct qv_info *qp = qv_scn;
+               register vsEvent *vep;
+
+               if ((i = EVROUND(qp->itail+1)) == qp->ihead) 
+                       return;
+               vep = &qp->ibuff[qp->itail];
+               vep->vse_direction = VSE_KBTRAW;
+               vep->vse_type = VSE_BUTTON;
+               vep->vse_device = VSE_DKB;
+               vep->vse_x = qp->mouse.x;
+               vep->vse_y = qp->mouse.y;
+               vep->vse_time = TOY;
+               vep->vse_key = key;
+               qp->itail = i;
+               if(qvrsel) {
+                       selwakeup(qvrsel,0);
+                       qvrsel = 0;
+               }
+       }
+}
+
+/*
+ * Ioctl for QVSS.
+ */
+/*ARGSUSED*/
+qvioctl(dev, cmd, data, flag)
+       dev_t dev;
+       register caddr_t data;
+{
+       register struct tty *tp;
+       register int unit = minor(dev);
+       register struct qv_info *qp = qv_scn;
+       register struct qv_kpcmd *qk;
+       register unsigned char *cp;
+       int error;
+       /*
+        * Check for and process qvss specific ioctl's
+        */
+       switch( cmd ) {
+       case QIOCGINFO:                                 /* return screen info */
+               bcopy((caddr_t)qp, data, sizeof (struct qv_info));
+               break;
+
+       case QIOCSMSTATE:                               /* set mouse state */
+               qp->mouse = *((vsCursor *)data);
+               qv_pos_cur( qp->mouse.x, qp->mouse.y );
+               break;
+
+       case QIOCINIT:                                  /* init screen  */
+               qv_init( qp->qvaddr );
+               break;
+
+       case QIOCKPCMD:
+               qk = (struct qv_kpcmd *)data;
+               if(qk->nbytes == 0) qk->cmd |= 0200;
+               if(mouseon == 0) qk->cmd |= 1;  /* no mode changes */
+               qv_key_out(qk->cmd);
+               cp = &qk->par[0];
+               while(qk->nbytes-- > 0) {       /* terminate parameters */
+                       if(qk->nbytes <= 0) *cp |= 0200;
+                       qv_key_out(*cp++);
+               }
+               break;
+       case QIOCADDR:                                  /* get struct addr */
+               *(struct qv_info **) data = qp;
+               break;
+       default:                                        /* not ours ??  */
+               tp = &qv_tty[unit];
+               error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag);
+               if (error >= 0)
+                       return (error);
+               error = ttioctl(tp, cmd, data, flag);
+               if (error >= 0) {
+                       return (error);
+               }
+               break;
+       }
+       return (0);
+}
+/*
+ * Initialize the screen and the scanmap
+ */
+qv_init(qvaddr)
+struct qvdevice *qvaddr;
+{
+       register short *scanline;
+       register int i;
+       register short scan;
+       register char *ptr;
+       register struct qv_info *qp = qv_scn;
+
+       /*
+        * Clear the bit map
+        */
+       for( i=0 , ptr = qp->bitmap ; i<240 ; i += 2 , ptr += 2048)
+               bzero( ptr, 2048 );
+       /*
+        * Reinitialize the scanmap
+        */
+        scan = qvaddr->qv_csr & QV_MEM_BANK;
+        scanline = qp->scanmap;
+        for(i = 0 ; i < qp->max_y ; i++ )
+                *scanline++ = scan++;
+
+       /*
+        * Home the cursor
+        */
+       qp->row = qp->col = 0;
+
+       /*
+        * Reset the cursor to the default type.
+        */
+       for( i=0 ; i<16 ; i++ )
+               qp->cursorbits[i] = q_cursor[i];
+       qvaddr->qv_csr |= QV_CUR_MODE;
+       /*
+        * Reset keyboard to default state.
+        */
+       qvkbdreset();
+}
+
+qvreset()
+{
+}
+qvkbdreset()
+{
+       register int i;
+       qv_key_out(LK_DEFAULTS);
+       for( i=1 ; i < 15 ; i++ )
+               qv_key_out( divdefaults[i] | (i<<3));
+       for (i = 0; i < KBD_INIT_LENGTH; i++)
+               qv_key_out(kbdinitstring[i]);
+}
+
+#define abs(x) (((x) > 0) ? (x) : (-(x)))
+/*
+ * QVSS vertical sync interrupt
+ */
+qvvint(qv)
+       int qv;
+{
+       extern int selwait;
+       register struct qvdevice *qvaddr;
+       struct uba_device *ui;
+       register struct qv_info *qp = qv_scn;
+       int unit;
+       struct tty *tp0;
+       int i;
+       register int j;
+       /*
+        * Mouse state info
+        */
+       static ushort omouse = 0, nmouse = 0;
+       static char omx=0, omy=0, mx=0, my=0, om_switch=0, m_switch=0;
+       register int dx, dy;
+
+       /*
+        * Test and set the qv_ipl_lo flag. If the result is not zero then
+        * someone else must have already gotten here.
+        */
+       if( --qv_ipl_lo )
+               return;
+       (void)spl4();
+       ui = qvinfo[qv];
+       unit = qv<<2;
+       qvaddr = (struct qvdevice *)ui->ui_addr;
+       tp0 = &qv_tty[QVCHAN(unit) + QVMOUSECHAN];
+       /*
+        * See if the mouse has moved.
+        */
+       if( omouse != (nmouse = qvaddr->qv_mouse) ) {
+               omouse = nmouse;
+               mx = nmouse & 0xff;
+               my = nmouse >> 8;
+               dy = my - omy; omy = my;
+               dx = mx - omx; omx = mx;
+               if( dy < 50 && dy > -50 && dx < 50 && dx > -50 ) {
+                       register vsEvent *vep;
+                       if( qp->mscale < 0 ) {  /* Ray Lanza's original */
+                               if( dy < 0 )
+                                       dy = -( dy * dy );
+                               else
+                                       dy *= dy;
+                               if( dx < 0 )
+                                       dx = -( dx * dx );
+                               else
+                                       dx *= dx;
+                       }
+                       else {                  /* Vs100 style, see WGA spec */
+                           int thresh = qp->mthreshold;
+                           int scale  = qp->mscale;
+                           if( abs(dx) > thresh ) {
+                               if ( dx < 0 )
+                                   dx = (dx + thresh)*scale - thresh;
+                               else
+                                   dx = (dx - thresh)*scale + thresh;
+                           }
+                           if( abs(dy) > thresh ) {
+                               if ( dy < 0 )
+                                   dy = (dy + thresh)*scale - thresh;
+                               else
+                                   dy = (dy - thresh)*scale + thresh;
+                           }
+                       }
+                       qp->mouse.x += dx;
+                       qp->mouse.y -= dy;
+                       if( qp->mouse.x < 0 )
+                               qp->mouse.x = 0;
+                       if( qp->mouse.y < 0 )
+                               qp->mouse.y = 0;
+                       if( qp->mouse.x > qp->max_cur_x )
+                               qp->mouse.x = qp->max_cur_x;
+                       if( qp->mouse.y > qp->max_cur_y )
+                               qp->mouse.y = qp->max_cur_y;
+                       if( tp0->t_state & TS_ISOPEN )
+                               qv_pos_cur( qp->mouse.x, qp->mouse.y );
+                       if (qp->mouse.y < qp->mbox.bottom &&
+                           qp->mouse.y >=  qp->mbox.top &&
+                           qp->mouse.x < qp->mbox.right &&
+                           qp->mouse.x >=  qp->mbox.left) goto switches;
+                       qp->mbox.bottom = 0;    /* trash box */
+                       if (EVROUND(qp->itail+1) == qp->ihead)
+                               goto switches;
+                       i = EVROUND(qp->itail - 1);
+                       if ((qp->itail != qp->ihead) && (i != qp->ihead)) {
+                               vep = & qp->ibuff[i];
+                               if(vep->vse_type == VSE_MMOTION) {
+                                       vep->vse_x = qp->mouse.x;
+                                       vep->vse_y = qp->mouse.y;
+                                       goto switches;
+                               }
+                       }
+                       /* put event into queue and do select */
+                       vep = & qp->ibuff[qp->itail];
+                       vep->vse_type = VSE_MMOTION;
+                       vep->vse_time = TOY;
+                       vep->vse_x = qp->mouse.x;
+                       vep->vse_y = qp->mouse.y;
+                       qp->itail = EVROUND(qp->itail+1);
+               }
+       }
+       /*
+        * See if mouse switches have changed.
+        */
+switches:if( om_switch != ( m_switch = (qvaddr->qv_csr & QV_MOUSE_ANY) >> 8 ) ) {
+               qp->mswitches = ~m_switch & 0x7;
+               for (j = 0; j < 3; j++) {       /* check each switch */
+                       register vsEvent *vep;
+                       if ( ((om_switch>>j) & 1) == ((m_switch>>j) & 1) )
+                               continue;
+                       /* check for room in the queue */
+                       if ((i = EVROUND(qp->itail+1)) == qp->ihead) return;
+                       /* put event into queue and do select */
+                       vep = &qp->ibuff[qp->itail];
+                       vep->vse_type = VSE_BUTTON;
+                       vep->vse_key = 2 - j;
+                       vep->vse_direction = VSE_KBTDOWN;
+                       if ( (m_switch >> j) & 1)
+                               vep->vse_direction = VSE_KBTUP;
+                       vep->vse_device = VSE_MOUSE;
+                       vep->vse_time = TOY;
+                       vep->vse_x = qp->mouse.x;
+                       vep->vse_y = qp->mouse.y;
+               }
+               qp->itail =  i;
+               om_switch = m_switch;
+               qp->mswitches = m_switch;
+       }
+       /* if we have proc waiting, and event has happened, wake him up */
+       if(qvrsel && (qp->ihead != qp->itail)) {
+               selwakeup(qvrsel,0);
+               qvrsel = 0;
+       }
+       /*
+        * Okay we can take another hit now
+        */
+       qv_ipl_lo = 1;
+}
+
+/*
+ * Start  transmission
+ */
+qvstart(tp)
+       register struct tty *tp;
+{
+       register int unit, c;
+       register struct tty *tp0;
+       int s;
+
+       unit = minor(tp->t_dev);
+#ifdef CONS_HACK
+       tp0 = &qv_tty[(unit&0xfc)+QVPCONS];
+#endif
+       unit = QVCHAN(unit);
+
+       s = spl5();
+       /*
+        * If it's currently active, or delaying, no need to do anything.
+        */
+       if (tp->t_state&(TS_TIMEOUT|TS_BUSY|TS_TTSTOP))
+               goto out;
+       /*
+        * Display chars until the queue is empty, if the second subchannel
+        * is open direct them there. Drop characters from subchannels other
+        * than 0 on the floor.
+        */
+
+       while( tp->t_outq.c_cc ) {
+               c = getc(&tp->t_outq);
+               if (unit == QVKEYBOARD)
+#ifdef CONS_HACK
+                       if( tp0->t_state & TS_ISOPEN ){
+                               (*linesw[tp0->t_line].l_rint)(c, tp0);
+                       } else
+#endif
+                               qvputchar( c & 0xff );
+       }
+       /*
+        * Position the cursor to the next character location.
+        */
+       qv_pos_cur( qv_scn->col*8, qv_scn->row*15 );
+
+       /*
+        * If there are sleepers, and output has drained below low
+        * water mark, wake up the sleepers.
+        */
+       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);
+               }
+       }
+       tp->t_state &= ~TS_BUSY;
+out:
+       splx(s);
+}
+
+/*
+ * Stop output on a line, e.g. for ^S/^Q or output flush.
+ */
+/*ARGSUSED*/
+void
+qvstop(tp, flag)
+       register struct tty *tp;
+       int flag;
+{
+       register int s;
+
+       /*
+        * Block input/output interrupts while messing with state.
+        */
+       s = spl5();
+       if (tp->t_state & TS_BUSY) {
+               if ((tp->t_state&TS_TTSTOP)==0) {
+                       tp->t_state |= TS_FLUSH;
+               } else
+                       tp->t_state &= ~TS_BUSY;
+       }
+       splx(s);
+}
+
+qvputc(c)
+char c;
+{
+       qvputchar(c);
+       if (c == '\n')
+               qvputchar('\r');
+}
+
+/*
+ * Routine to display a character on the screen.  The model used is a 
+ * glass tty.  It is assummed that the user will only use this emulation
+ * during system boot and that the screen will be eventually controlled
+ * by a window manager.
+ *
+ */
+qvputchar( c )
+register char c;
+{
+
+       register char *b_row, *f_row;
+       register int i;
+       register short *scanline;
+       register int ote = 128;
+       register struct qv_info *qp = qv_scn;
+
+       /*
+        * This routine may be called in physical mode by the dump code
+        * so we check and punt if that's the case.
+        */
+       if( (mfpr(MAPEN) & 1) == 0 )
+               return;
+
+       c &= 0x7f;
+
+       switch ( c ) {
+       case '\t':                              /* tab          */
+               for( i = 8 - (qp->col & 0x7) ; i > 0 ; i-- )
+                       qvputchar( ' ' );
+               break;
+
+       case '\r':                              /* return       */
+               qp->col = 0;
+               break;
+
+       case '\010':                            /* backspace    */
+               if( --qp->col < 0 )
+                       qp->col = 0;
+               break;
+
+       case '\n':                              /* linefeed     */
+               if( qp->row+1 >= qp->max_row )
+                       qvscroll();
+               else
+                       qp->row++;
+               /*
+               * Position the cursor to the next character location.
+               */
+               qv_pos_cur( qp->col*8, qp->row*15 );
+               break;
+
+       case '\007':                            /* bell         */
+                /*
+                 * We don't do anything to the keyboard until after
+                 * autoconfigure.
+                 */
+               if( qp->qvaddr )
+                       qv_key_out( LK_RING_BELL );
+               return;
+
+       default:
+               if( c >= ' ' && c <= '~' ) {
+                        scanline = qp->scanmap;
+                        b_row = qp->bitmap+(scanline[qp->row*15]&0x3ff)*128+qp->col;
+                       i = c - ' ';
+                       if( i < 0 || i > 95 )
+                               i = 0;
+                       else
+                               i *= 15;
+                       f_row = (char *)((int)q_font + i);
+               
+/*                     for( i=0 ; i<15 ; i++ , b_row += 128, f_row++ )
+                               *b_row = *f_row;*/
+                       /* inline expansion for speed */
+                       *b_row = *f_row++; b_row += ote;
+                       *b_row = *f_row++; b_row += ote;
+                       *b_row = *f_row++; b_row += ote;
+                       *b_row = *f_row++; b_row += ote;
+                       *b_row = *f_row++; b_row += ote;
+                       *b_row = *f_row++; b_row += ote;
+                       *b_row = *f_row++; b_row += ote;
+                       *b_row = *f_row++; b_row += ote;
+                       *b_row = *f_row++; b_row += ote;
+                       *b_row = *f_row++; b_row += ote;
+                       *b_row = *f_row++; b_row += ote;
+                       *b_row = *f_row++; b_row += ote;
+                       *b_row = *f_row++; b_row += ote;
+                       *b_row = *f_row++; b_row += ote;
+                       *b_row = *f_row++; b_row += ote;
+
+                       if( ++qp->col >= qp->max_col ) {
+                               qp->col = 0 ;
+                               if( qp->row+1 >= qp->max_row )
+                                       qvscroll();
+                               else
+                                       qp->row++;
+                       }
+               }
+               break;
+       }
+}
+
+/*
+ * Position the cursor to a particular spot.
+ */
+qv_pos_cur( x, y)
+register int x,y;
+{
+       register struct qvdevice *qvaddr;
+       register struct qv_info *qp = qv_scn;
+       register index;
+
+       if( qvaddr = qp->qvaddr ) {
+               if( y < 0 || y > qp->max_cur_y )
+                       y = qp->max_cur_y;
+               if( x < 0 || x > qp->max_cur_x )
+                       x = qp->max_cur_x;
+               qp->cursor.x = x;               /* keep track of real cursor*/
+               qp->cursor.y = y;               /* position, indep. of mouse*/
+
+               qvaddr->qv_crtaddr = 10;        /* select cursor start reg */
+               qvaddr->qv_crtdata = y & 0xf;
+               qvaddr->qv_crtaddr = 11;        /* select cursor end reg */
+               qvaddr->qv_crtdata = y & 0xf;
+               qvaddr->qv_crtaddr = 14;        /* select cursor y pos. */
+               qvaddr->qv_crtdata = y >> 4;
+               qvaddr->qv_xcur = x;            /* pos x axis   */
+               /*
+                * If the mouse is being used then we change the mode of
+                * cursor display based on the pixels under the cursor
+                */
+               if( mouseon ) {
+                       index = y*128 + x/8;
+                       if( qp->bitmap[ index ] && qp->bitmap[ index+128 ] )
+                               qvaddr->qv_csr &= ~QV_CUR_MODE;
+                       else
+                               qvaddr->qv_csr |=  QV_CUR_MODE;
+               }
+       }
+}
+/*
+ * Scroll the bitmap by moving the scanline map words. This could
+ * be done by moving the bitmap but it's much too slow for a full screen.
+ * The only drawback is that the scanline map must be reset when the user 
+ * wants to do graphics.
+ */
+qvscroll()
+{
+       short tmpscanlines[15];
+       register char *b_row;
+       register short *scanline;
+       register struct qv_info *qp = qv_scn;
+
+       /*
+        * If the mouse is on we don't scroll so that the bit map
+        * remains sane.
+        */
+       if( mouseon ) {
+               qp->row = 0;
+               return;
+       }
+       /*
+        * Save the first 15 scanlines so that we can put them at
+        * the bottom when done.
+        */
+       bcopy((caddr_t)qp->scanmap, (caddr_t)tmpscanlines, sizeof tmpscanlines);
+
+       /*
+        * Clear the wrapping line so that it won't flash on the bottom
+        * of the screen.
+        */
+        scanline = qp->scanmap;
+        b_row = qp->bitmap+(*scanline&0x3ff)*128;
+       bzero( b_row, 1920 );
+
+       /*
+        * Now move the scanlines down 
+        */
+       bcopy((caddr_t)(qp->scanmap+15), (caddr_t)qp->scanmap,
+             (qp->row * 15) * sizeof (short) );
+
+       /*
+        * Now put the other lines back
+        */
+       bcopy((caddr_t)tmpscanlines, (caddr_t)(qp->scanmap+(qp->row * 15)),
+             sizeof (tmpscanlines) );
+
+}
+
+/*
+ * Output to the keyboard. This routine status polls the transmitter on the
+ * keyboard to output a code. The timer is to avoid hanging on a bad device.
+ */
+qv_key_out(c)
+       u_short c;
+{
+       int timer = 30000;
+       register struct qv_info *qp = qv_scn;
+
+       if (qp->qvaddr) {
+               while ((qp->qvaddr->qv_uartstatus & 0x4) == 0  && timer--)
+                       ;
+               qp->qvaddr->qv_uartdata = c;
+       }
+}
+/*
+ * Virtual console initialization. This routine sets up the qvss so that it can
+ * be used as the system console. It is invoked before autoconfig and has to do
+ * everything necessary to allow the device to serve as the system console. 
+ * In this case it must map the q-bus and device areas and initialize the qvss 
+ * screen.
+ */
+qvcons_init()
+{
+        struct percpu *pcpu;            /* pointer to percpu structure  */
+       register struct qbus *qb;
+        struct qvdevice *qvaddr;        /* device pointer               */
+        short *devptr;                  /* virtual device space         */
+       extern cnputc();                /* standard serial console putc */
+#define QVSSCSR 017200
+
+       /*
+        * If secondary console already configured,
+        * don't override the previous one.
+        */
+       if (v_putc != cnputc)
+               return 0;
+        /*
+         * find the percpu entry that matches this machine.
+         */
+        for( pcpu = percpu ; pcpu && pcpu->pc_cputype != cpu ; pcpu++ )
+                ;
+        if( pcpu == NULL )
+                return 0;
+       if (pcpu->pc_io->io_type != IO_QBUS)
+               return 0;
+
+        /*
+         * Found an entry for this cpu. Because this device is Microvax specific
+         * we assume that there is a single q-bus and don't have to worry about
+         * multiple adapters.
+         *
+         * Map the device registers.
+         */
+       qb = (struct qbus *)pcpu->pc_io->io_details;
+       ioaccess(qb->qb_iopage, UMEMmap[0] + qb->qb_memsize, UBAIOPAGES * NBPG);
+
+        /*
+         * See if the qvss is there.
+         */
+        devptr = (short *)((char *)umem[0] + (qb->qb_memsize * NBPG));
+        qvaddr = (struct qvdevice *)((u_int)devptr + ubdevreg(QVSSCSR));
+        if (badaddr((caddr_t)qvaddr, sizeof(short)))
+                return 0;
+        /*
+         * Okay the device is there lets set it up
+         */
+        if (!qv_setup(qvaddr, 0, 0))
+               return 0;
+       v_putc = qvputc;
+        consops = &cdevsw[QVSSMAJOR];
+       return 1;
+}
+/*
+ * Do the board specific setup
+ */
+qv_setup(qvaddr, unit, probed)
+struct qvdevice *qvaddr;
+int unit;
+int probed;
+{
+        caddr_t qvssmem;               /* pointer to the display mem   */
+        register i;                    /* simple index                 */
+       register struct qv_info *qp;
+        register int *pte;
+        struct percpu *pcpu;            /* pointer to percpu structure  */
+       register struct qbus *qb;
+
+        /*
+         * find the percpu entry that matches this machine.
+         */
+        for( pcpu = percpu ; pcpu && pcpu->pc_cputype != cpu ; pcpu++ )
+                ;
+        if( pcpu == NULL )
+                return(0);
+
+        /*
+         * Found an entry for this cpu. Because this device is Microvax specific
+         * we assume that there is a single q-bus and don't have to worry about
+         * multiple adapters.
+         *
+         * Map the device memory.
+         */
+       qb = (struct qbus *)pcpu->pc_io->io_details;
+
+        i = (u_int)(qvaddr->qv_csr & QV_MEM_BANK) << 7;
+       ioaccess(qb->qb_maddr + i, QVmap[unit], 512 * NBPG);
+       qvssmem = qvmem[unit];
+        pte = (int *)(QVmap[unit]);
+        for (i=0; i < 512; i++, pte++)
+                *pte = (*pte & ~PG_PROT) | PG_UW | PG_V;
+
+        qv_scn = (struct qv_info *)((u_int)qvssmem + 251*1024);
+       qp = qv_scn;
+        if( (qvaddr->qv_csr & QV_19INCH) && qv_def_scrn == 0)
+                qv_def_scrn = 1;
+        *qv_scn = qv_scn_defaults[ qv_def_scrn ];
+       if (probed)
+               qp->qvaddr = qvaddr;
+       qp->bitmap = qvssmem;
+        qp->scanmap = (short *)((u_int)qvssmem + 254*1024);
+        qp->cursorbits = (short *)((u_int)qvssmem + 256*1024-32);
+       /* set up event queue for later */
+       qp->ibuff = (vsEvent *)qp - QVMAXEVQ;
+       qp->iqsize = QVMAXEVQ;
+       qp->ihead = qp->itail = 0;
+
+        /*
+         * Setup the crt controller chip.
+         */
+        for( i=0 ; i<16 ; i++ ) {
+                qvaddr->qv_crtaddr = i;
+                qvaddr->qv_crtdata = qv_crt_parms[ qv_def_scrn ][ i ];
+        }
+        /*
+         * Setup the display.
+         */
+        qv_init( qvaddr );
+
+        /*
+         * Turn on the video
+         */
+        qvaddr->qv_csr |= QV_VIDEO_ENA ;
+       return 1;
+}
+#endif
diff --git a/sys/arch/vax/uba/tmscp.c b/sys/arch/vax/uba/tmscp.c
deleted file mode 100644 (file)
index ef490d9..0000000
+++ /dev/null
@@ -1,2211 +0,0 @@
-/*     $NetBSD: tmscp.c,v 1.12 1996/04/08 18:37:30 ragge Exp $ */
-
-/*-
- * Copyright (c) 1991 The Regents of the University of California.
- * 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.
- *
- *     @(#)tmscp.c     7.16 (Berkeley) 5/9/91
- */
-
-/*
- * sccsid = "@(#)tmscp.c       1.24    (ULTRIX)        1/21/86";
- */
-
-/************************************************************************
- *                                                                     *
- *        Licensed from Digital Equipment Corporation                  *
- *                       Copyright (c)                                         *
- *               Digital Equipment Corporation                         *
- *                   Maynard, Massachusetts                            *
- *                         1985, 1986                                  *
- *                    All rights reserved.                             *
- *                                                                     *
- *        The Information in this software is subject to change        *
- *   without notice and should not be construed as a commitment        *
- *   by  Digital  Equipment  Corporation.   Digital   makes  no        *
- *   representations about the suitability of this software for        *
- *   any purpose.  It is supplied "As Is" without expressed  or        *
- *   implied  warranty.                                                *
- *                                                                     *
- *        If the Regents of the University of California or its        *
- *   licensees modify the software in a manner creating                *
- *   diriviative copyright rights, appropriate copyright               *
- *   legends may be placed on  the drivative work in addition                  *
- *   to that set forth above.                                          *
- *                                                                     *
- ************************************************************************
- * 
- * tmscp.c - TMSCP (TK50/TU81) tape device driver
- * 
- * Modification History:
- *
- * 06-Jan-86 - afd
- *     Changed the probe routine to use DELAY (not TODR).  This now
- *     works for MicroVAXen as well.  This eliminates the busy-wait
- *     for MicroVAXen so a dead TK50 controller will not hang autoconf.
- *
- * 06-Dec-85 - afd
- *     Fixed a bug in density selection.  The "set unit characteristics"
- *     command to select density, was clearing the "unit flags" field
- *     where the CACHE bit was for TU81-E.  Now the unit's "format" and
- *     "unitflgs" are saved in tms_info struct.  And are used on STUNT
- *     commands.
- *
- * 19-Oct-85 - afd
- *     Added support to the open routine to allow drives to be opened
- *     for low density (800 or 1600 bpi) use.  When the slave routine
- *     initiates a "get-unit-char" cmd, the format menu for the unit
- *     is saved in the tms_info structure. The format menu is used in the
- *     start routine to select the proper low density.
- *
- * 02-Oct-85 - afd
- *     When a tmscp-type controller is initializing, it is possible for
- *     the sa reg to become 0 between states.  Thus the init code in
- *     the interrupt routine had to be modified to reflect this.
- *
- * 21-Sep-85 - afd
- *     The TK50 declares a serious exception when a tape mark is encountered.
- *     This causes problems to dd (& other UN*X utilities).  So a flag
- *     is set in the rsp() routine when a tape mark is encountered.  If
- *     this flag is set, the start() routine appends the Clear Serious
- *     Exception modifier to the next command.
- *
- * 03-Sep-85 -- jaw
- *     messed up previous edit..
- *
- * 29-Aug-85 - jaw
- *     fixed bugs in 8200 and 750 buffered datapath handling.
- *
- * 06-Aug-85 - afd
- *   1. When repositioning records or files, the count of items skipped
- *     does NOT HAVE to be returned by controllers (& the TU81 doesn't).
- *     So tmscprsp() had to be modified to stop reporting
- *     residual count errors on reposition commands.
- *
- *   2. Fixed bug in the open routine which allowed multiple opens.
- *
- * 18-Jul-85 - afd
- *   1. Need to return status when mt status (or corresponding ioctl) is done.
- *     Save resid, flags, endcode & status in tmscprsp() routine (except on
- *     clear serious exception no-op).  Return these fields when status
- *     ioctl is done (in tmscpcommand()).  How they are returned:
- *             mt_resid = resid
- *             mt_dsreg = flags|endcode
- *             mt_erreg = status
- *
- *   2. Added latent support for enabling/disabling caching.  This is
- *     handled along with all other ioctl commands.
- *
- *   3. Need to issue a no-op on unrecognized ioctl in tmscpstart(), since
- *     we have already commited to issuing a command at that point.
- *
- *   4. In tmscprsp() routine if encode is 0200 (invalid command issued);
- *     We need to: Unlink the buffer from the I/O wait queue,
- *     and signal iodone, so the higher level command can exit!
- *     Just as if it were a valid command.
- *
- * 11-jul-85 -- jaw
- *     fix bua/bda map registers.
- *
- * 19-Jun-85 -- jaw
- *     VAX8200 name change.
- *
- * 06-Jun-85 - jaw
- *     fixes for 8200.
- *
- * 9-Apr-85 - afd
- *     Added timeout code to the probe routine, so if the controller
- *     fails to init in 10 seconds we return failed status.
- *
- * 13-Mar-85 -jaw
- *     Changes for support of the VAX8200 were merged in.
- *
- * 27-Feb-85 -tresvik
- *     Changes for support of the VAX8600 were merged in.
- *
- */
-
-#define NTMS 2 /* XXX - This is _wery_ kludgy! /ragge */
-
-#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 <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
-
-#define NRSPL2  3               /* log2 number of response packets */
-#define NCMDL2  3               /* log2 number of command packets */
-#define NRSP    (1<<NRSPL2)
-#define NCMD    (1<<NCMDL2)
-
-#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 tmscp_cd = {
-       NULL, "tmscp", DV_DULL
-};
-
-struct cfattach tmscp_ca = {
-       sizeof(struct device), tmscp_match, tmscp_attach
-};
-
-/* Software state per controller */
-
-struct tmscp_softc {
-       short   sc_state;       /* state of controller */
-       short   sc_mapped;      /* Unibus map allocated for tmscp struct? */
-       int     sc_ubainfo;     /* Unibus mapping info */
-       struct  tmscp *sc_tmscp;   /* Unibus address of tmscp struct */
-       int     sc_ivec;        /* interrupt vector address */
-       short   sc_credits;     /* transfer credits */
-       short   sc_lastcmd;     /* pointer into command ring */
-       short   sc_lastrsp;     /* pointer into response ring */
-       short   sc_ipl;         /* interrupt priority (Q-bus) */
-} tmscp_softc[NTMSCP];
-
-struct tmscp {
-       struct tmscpca  tmscp_ca;         /* communications area */
-       struct mscp     tmscp_rsp[NRSP];  /* response packets */
-       struct mscp     tmscp_cmd[NCMD];  /* command packets */
-} tmscp[NTMSCP];
-
-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
- */
-struct tms_info {
-       daddr_t         tms_dsize;      /* Max user size from online pkt */
-       unsigned        tms_type;       /* Drive type int field  */
-       int             tms_resid;      /* residual from last xfer */
-       u_char          tms_endcode;    /* last command endcode */
-       u_char          tms_flags;      /* last command end flags */
-       unsigned        tms_status;     /* Command status from last command */
-       char            tms_openf;      /* lock against multiple opens */
-       char            tms_lastiow;    /* last op was a write */
-       char            tms_serex;      /* set when serious exception occurs */
-       char            tms_clserex;    /* set when serex being cleared by no-op */
-       short           tms_fmtmenu;    /* the unit's format (density) menu */
-       short           tms_unitflgs;   /* unit flag parameters */
-       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];
-/* 
- * ifdef other tmscp devices here if they allow more than 1 unit/controller
- */
-struct uba_device *tmscpip[NTMSCP][1];
-struct buf ctmscpbuf[NTMSCP];          /* internal cmd buffer (for ioctls) */
-struct buf tmsutab[NTMS];              /* Drive queue */
-struct buf tmscpwtab[NTMSCP];          /* I/O wait queue, per controller */
-int    tmscpmicro[NTMSCP];             /* to store microcode level */
-short  utoctlr[NTMS];                  /* Slave unit to controller mapping */
-                                       /* filled in by the slave routine */
-
-/* Bits in minor device */
-#define        TMSUNIT(dev)    (minor(dev)&03)
-#define        T_HIDENSITY     010
-
-/* Slave unit to controller mapping */
-#define TMSCPCTLR(dev) (utoctlr[TMSUNIT(dev)])
-
-/*
- * Internal (ioctl) command codes (these must also be declared in the
- * tmscpioctl routine).  These correspond to ioctls in mtio.h
- */
-#define TMS_WRITM      0               /* write tape mark */
-#define TMS_FSF                1               /* forward space file */
-#define TMS_BSF                2               /* backward space file */
-#define TMS_FSR                3               /* forward space record */
-#define TMS_BSR                4               /* backward space record */
-#define TMS_REW                5               /* rewind tape */
-#define TMS_OFFL       6               /* rewind tape & mark unit offline */
-#define TMS_SENSE      7               /* noop - do a get unit status */
-#define TMS_CACHE      8               /* enable cache */
-#define TMS_NOCACHE    9               /* disable cache */
-/* These go last: after all real mt cmds, just bump the numbers up */
-#define TMS_CSE                10              /* clear serious exception */
-#define TMS_LOWDENSITY 11              /* set unit to low density */
-#define TMS_HIDENSITY  12              /* set unit to high density */
-
-/*
- * Controller states
- */
-#define S_IDLE  0               /* hasn't been initialized */
-#define S_STEP1 1               /* doing step 1 init */
-#define S_STEP2 2               /* doing step 2 init */
-#define S_STEP3 3               /* doing step 3 init */
-#define S_SCHAR 4               /* doing "set controller characteristics" */
-#define S_RUN   5               /* running */
-
-int     tmscperror = 0;                /* causes hex dump of packets */
-int    tmscp_cp_wait = 0;      /* Something to wait on for command */
-                               /* packets and or credits. */
-extern int     hz;             /* Should find the right include */
-
-#ifdef DEBUG
-#define printd if (tmscpdebug) printf
-int tmscpdebug = 1;
-#define        printd10 if(tmscpdebug >= 10) printf
-#endif 
-
-#define DRVNAME "tms"
-#define CTRLNAME "tmscp"
-
-u_short tmscpstd[] = { 0174504, 0 };
-struct  uba_driver tmscpdriver =
-{ tmscpprobe, tmscpslave, tmscpattach, 0, tmscpstd, DRVNAME, tmsdinfo, CTRLNAME
-, tmscpminfo, 0};
-
-#define b_qsize         b_resid         /* queue size per drive, in tmsutab */
-#define b_ubinfo        b_resid         /* Unibus mapping info, per buffer */
-
-
-/*************************************************************************/
-
-#define DELAYTEN 1000
-extern struct cfdriver uba_cd;
-
-/*
- * Unfortunately qbgetpri can't be used because the TK50 doesn't flip the
- * TMSCP_STEP2 flag in the tmscpsa register until after the pending interrupt
- * has been acknowledged by the cpu. If you are at spl6(), the TMSCP_STEP2
- * flag never gets set and you return (0).
- */
-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];
-                               /* ptr to software controller structure */
-       volatile struct tmscpdevice *tmscpaddr;
-       int count;              /* for probe delay time out */
-       struct  uba_softc *ubasc;
-
-#      ifdef lint
-       br = 0; cvec = br; br = cvec; reg = reg;
-       tmscpreset(0); tmscpintr(0);
-#      endif
-
-       tmscpminfo[ctlr] = um;
-       tmscpaddr = (struct tmscpdevice *) reg;
-       /* 
-        * Set host-settable interrupt vector.
-        * Assign 0 to the ip register to start the tmscp-device initialization.
-        * The device is not really initialized at this point, this is just to
-        * find out if the device exists.
-        */
-       ubasc = uba_cd.cd_devs[0]; /* XXX */
-       sc->sc_ivec = (ubasc->uh_lastiv -= 4);
-       tmscpaddr->tmscpip = 0;
-
-       count=0;
-       while(count < DELAYTEN)
-               {       /* wait for at most 10 secs */
-               if((tmscpaddr->tmscpsa & TMSCP_STEP1) != 0)
-                       break;
-               DELAY(10000);
-               count=count+1;
-               }
-       if (count == DELAYTEN)
-               return(0);              
-
-       tmscpaddr->tmscpsa = TMSCP_ERR|(NCMDL2<<11)|(NRSPL2<<8)|TMSCP_IE|(sc->sc_ivec/4);
-
-       count=0;
-       while(count < DELAYTEN)
-               {
-               if((tmscpaddr->tmscpsa & TMSCP_STEP2) != 0)
-                       break;
-               DELAY(10000);
-               count = count+1;
-               }
-       if (count == DELAYTEN)
-               return(0);
-
-#ifdef QBA
-       sc->sc_ipl = 0x15;
-#endif
-       return(sizeof (struct tmscpdevice));
-}
-
-/*
- * 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];
-       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 */
-                                       /* the tmscp polling */
-
-#      ifdef lint
-       reg = reg;
-#      endif
-       tmscpaddr = (struct tmscpdevice *)um->um_addr;
-       /* 
-        * If its not in the run state, start the initialization process
-        * (tmscpintr will complete it);  if the initialization doesn't start;
-        * then return.
-        */
-       if(sc->sc_state != S_RUN)
-               {
-#              ifdef DEBUG
-               printd("tmscpslave: ctlr not running: calling init \n");
-#              endif   
-               if(!tmscpinit(ui->ui_ctlr))
-                       return(0);
-               }
-       /*
-        * Wait for the controller to come into the run state or go idle.
-        * If it goes idle return.
-        */
-#      ifdef DEBUG
-       i=1;
-#      endif   
-       while(sc->sc_state != S_RUN && sc->sc_state != S_IDLE)
-#              ifdef DEBUG
-               if (tmscpaddr->tmscpsa & TMSCP_ERR && i)
-                       {
-                       printd("tmscp-device: fatal error (%o)\n", tmscpaddr->tmscpsa&0xffff);
-                       i=0;
-                        }
-#              endif   
-               ;       /* wait */
-       if(sc->sc_state == S_IDLE)
-               {       /* The tmscp device failed to initialize */
-               printf("tmscp controller failed to init\n");
-               return(0);
-               }
-       /* The controller is up so see if the drive is there */
-       if(0 == (mp = tmscpgetcp(um)))
-               {
-               printf("tmscp can't get command packet\n");
-               return(0);
-               }
-       /* Need to determine the drive type for generic driver */
-       mp->mscp_opcode = M_OP_GTUNT;   /* This should give us the device type */
-       mp->mscp_unit = ui->ui_slave;
-       mp->mscp_cmdref = (long) ui->ui_slave;
-       tms->tms_status = 0;    /* set to zero */
-       tmscpip[ui->ui_ctlr][ui->ui_slave] = ui;
-       *((long *) mp->mscp_dscptr ) |= TMSCP_OWN | TMSCP_INT;/* maybe we should poll*/
-       i = tmscpaddr->tmscpip;
-#ifdef lint
-       i = i;
-#endif
-       while(!tms->tms_status)
-               ;                               /* Wait for some status */
-#      ifdef DEBUG
-       printd("tmscpslave: status = %o\n",tms->tms_status & M_ST_MASK);
-#      endif
-       tmscpip[ui->ui_ctlr][ui->ui_slave] = 0;
-       if(!tms->tms_type)                      /* packet from a GTUNT */
-               return(0);                      /* Failed No such drive */
-       else
-               return(1);                      /* Got it and it is there */
-}
-
-
-/* 
- * Set ui flags to zero to show device is not online & set tmscpip.
- * 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 */
-{
-
-       ui->ui_flags = 0;
-       tmscpip[ui->ui_ctlr][ui->ui_slave] = ui;
-#      ifdef DEBUG
-       /* 
-        * Check to see if the drive is available.
-        * If not then just print debug.
-        */
-       if(tms_info[ui->ui_unit].tms_status != M_ST_AVLBL)
-               printd("tmscpattach: unavailable \n");
-#      endif   
-       utoctlr[ui->ui_unit] = ui->ui_ctlr;
-}
-
-
-/*
- * TMSCP interrupt routine.
- */
-void
-tmscpintr(d)
-       int d;
-{
-       volatile struct uba_ctlr *um = tmscpminfo[d];
-       volatile struct tmscpdevice *tmscpaddr =
-               (struct tmscpdevice *)um->um_addr;
-       struct buf *bp;
-       volatile int i;
-       volatile struct tmscp_softc *sc = &tmscp_softc[d];
-       struct tmscp *tm = &tmscp[d];
-       struct tmscp *ttm;
-       volatile struct mscp *mp;
-
-#      ifdef DEBUG
-       printd10("tmscpintr: state %d, tmscpsa %o\n", sc->sc_state, tmscpaddr->tmscpsa);
-#      endif   
-
-#ifdef QBA
-       if (cpunumber == VAX_78032)
-               splx(sc->sc_ipl);
-#endif
-       /*
-        * How the interrupt is handled depends on the state of the controller.
-        */
-       switch (sc->sc_state) {
-
-       case S_IDLE:
-               printf("tmscp%d: random interrupt ignored\n", d);
-               return;
-
-       /* Controller was in step 1 last, see if its gone to step 2 */
-       case S_STEP1:
-#              define STEP1MASK 0174377
-#              define STEP1GOOD (TMSCP_STEP2|TMSCP_IE|(NCMDL2<<3)|NRSPL2)
-               for (i = 0; i < 150; i++)
-                       {
-                       if ((tmscpaddr->tmscpsa&STEP1MASK) != STEP1GOOD)
-                               { /* still in step 1 (wait 1/100 sec) */
-                               DELAY(10000);
-#                              ifdef DEBUG
-                               printd("still in step 1, delaying\n");
-#                              endif DEBUG
-                               }
-                       else
-                               break;
-                       }
-               if (i > 149)
-                       {
-                       sc->sc_state = S_IDLE;
-                       printf("failed to initialize, in step1: sa 0x%x", tmscpaddr->tmscpsa);
-                       wakeup((caddr_t)um);
-                       return;
-                       }
-               tmscpaddr->tmscpsa = ((int)&sc->sc_tmscp->tmscp_ca.ca_ringbase)
-                       | ((cpunumber == VAX_780 || cpunumber == VAX_8600) ?
-                        TMSCP_PI : 0);
-               sc->sc_state = S_STEP2;
-               return;
-
-       /* Controller was in step 2 last, see if its gone to step 3 */
-       case S_STEP2:
-#              define STEP2MASK 0174377
-#              define STEP2GOOD (TMSCP_STEP3|TMSCP_IE|(sc->sc_ivec/4))
-               for (i = 0; i < 150; i++)
-                       {
-                       if ((tmscpaddr->tmscpsa&STEP2MASK) != STEP2GOOD)
-                               { /* still in step 2 (wait 1/100 sec) */
-                               DELAY(10000);
-#                              ifdef DEBUG
-                               printd("still in step 2, delaying\n");
-#                              endif DEBUG
-                               }
-                       else
-                               break;
-                       }
-               if (i > 149)
-                       {
-                       sc->sc_state = S_IDLE;
-                       printf("failed to initialize, in step2: sa 0x%x", tmscpaddr->tmscpsa);
-                       wakeup((caddr_t)um);
-                       return;
-                       }
-               tmscpaddr->tmscpsa = ((int)&sc->sc_tmscp->tmscp_ca.ca_ringbase)>>16;
-               sc->sc_state = S_STEP3;
-               return;
-
-       /* Controller was in step 3 last, see if its gone to step 4 */
-       case S_STEP3:
-#              define STEP3MASK 0174000
-#              define STEP3GOOD TMSCP_STEP4
-               for (i = 0; i < 150; i++)
-                       {
-                       if ((tmscpaddr->tmscpsa&STEP3MASK) != STEP3GOOD)
-                               { /* still in step 3 (wait 1/100 sec) */
-                               DELAY(10000);
-#                              ifdef DEBUG
-                               printd("still in step 3, delaying\n");
-#                              endif DEBUG
-                               }
-                       else
-                               break;
-                       }
-               if (i > 149)
-                       {
-                       sc->sc_state = S_IDLE;
-                       printf("failed to initialize, in step3: sa 0x%x", tmscpaddr->tmscpsa);
-                       wakeup((caddr_t)um);
-                       return;
-                       }
-               /*
-                * Get microcode version and model number of controller;
-                * Signal initialization complete (_GO) (to the controller);
-                *    ask for Last Fail response if tmscperror is set;
-                * Set state to "set controller characteristics".
-                */
-               tmscpmicro[d] = tmscpaddr->tmscpsa;
-               tmscpaddr->tmscpsa = TMSCP_GO | (tmscperror? TMSCP_LF : 0);
-               sc->sc_state = S_SCHAR;
-#              ifdef DEBUG
-               printd("tmscpintr: completed state %d \n", sc->sc_state);
-               printd("tmscp%d Version %d model %d\n",d,tmscpmicro[d]&0xF,
-                       (tmscpmicro[d]>>4) & 0xF);
-#              endif
-
-           /*
-            * Initialize the data structures (response and command queues).
-            */
-           ttm = sc->sc_tmscp;
-           for (i = 0; i < NRSP; i++)
-                   {
-                   tm->tmscp_ca.ca_rspdsc[i] = TMSCP_OWN | TMSCP_INT | 
-                          (long)&ttm->tmscp_rsp[i].mscp_cmdref;
-                   tm->tmscp_rsp[i].mscp_dscptr = &tm->tmscp_ca.ca_rspdsc[i];
-                   tm->tmscp_rsp[i].mscp_header.tmscp_msglen = mscp_msglen;
-                   }
-           for (i = 0; i < NCMD; i++)
-                   {
-                   tm->tmscp_ca.ca_cmddsc[i] = TMSCP_INT | 
-                                       (long)&ttm->tmscp_cmd[i].mscp_cmdref;
-                   tm->tmscp_cmd[i].mscp_dscptr = &tm->tmscp_ca.ca_cmddsc[i];
-                   tm->tmscp_cmd[i].mscp_header.tmscp_msglen = mscp_msglen;
-                   tm->tmscp_cmd[i].mscp_header.tmscp_vcid = 1;
-                   }
-           bp = &tmscpwtab[d];
-           bp->b_actf = NULL;
-           sc->sc_lastcmd = 1;
-           sc->sc_lastrsp = 0;
-           mp = &tmscp[d].tmscp_cmd[0];
-           mp->mscp_unit = mp->mscp_modifier = 0;
-           mp->mscp_flags = 0;
-           mp->mscp_version = 0;
-           mp->mscp_cntflgs = M_CF_ATTN|M_CF_MISC|M_CF_THIS;
-           /*
-            * A host time out value of 0 means that the controller will not
-            * time out.  This is ok for the TK50.
-            */
-           mp->mscp_hsttmo = 0;
-           mp->mscp_time = 0;
-           mp->mscp_cntdep = 0;
-           mp->mscp_opcode = M_OP_STCON;
-           *((long *)mp->mscp_dscptr) |= TMSCP_OWN|TMSCP_INT;
-           i = tmscpaddr->tmscpip;      /* initiate polling */
-           return;
-
-       case S_SCHAR:
-       case S_RUN:
-               break;
-
-       default:
-           printf("tmscp%d: interrupt in unknown state %d ignored\n",d,sc->sc_state);
-           return;
-       }       /* end switch */
-
-       /*
-        * The controller state is S_SCHAR or S_RUN
-        */
-
-       /*
-        * If the error bit is set in the SA register then print an error
-        * message and reinitialize the controller.
-        */
-       if (tmscpaddr->tmscpsa&TMSCP_ERR)
-               {
-               printf("tmscp%d: fatal error (%o)\n", d, tmscpaddr->tmscpsa&0xffff);
-               tmscpaddr->tmscpip = 0;
-               wakeup((caddr_t)um);
-               }
-       /*
-        * Check for a buffer purge request. (Won't happen w/ TK50 on Q22 bus)
-        */
-       if (tm->tmscp_ca.ca_bdp)
-               {
-               UBAPURGE(um->um_hd->uh_uba, tm->tmscp_ca.ca_bdp);
-               tm->tmscp_ca.ca_bdp = 0;
-               tmscpaddr->tmscpsa = 0;      /* signal purge complete */
-               }
-
-       /*
-        * Check for response ring transition.
-        */
-       if (tm->tmscp_ca.ca_rspint)
-               {
-               tm->tmscp_ca.ca_rspint = 0;
-               for (i = sc->sc_lastrsp;; i++)
-                       {
-                       i %= NRSP;
-                       if (tm->tmscp_ca.ca_rspdsc[i]&TMSCP_OWN)
-                           break;
-                       tmscprsp((struct uba_ctlr *)um, tm,
-                           (struct tmscp_softc *)sc, i);
-                       tm->tmscp_ca.ca_rspdsc[i] |= TMSCP_OWN;
-                       }
-               sc->sc_lastrsp = i;
-               }
-
-       /*
-        * Check for command ring transition.
-        */
-       if (tm->tmscp_ca.ca_cmdint)
-               {
-#              ifdef DEBUG
-               printd("tmscpintr: command ring transition\n");
-#              endif           
-               tm->tmscp_ca.ca_cmdint = 0;
-               }
-       if(tmscp_cp_wait)
-               wakeup((caddr_t)&tmscp_cp_wait);
-       (void) tmscpstart((struct uba_ctlr *)um);
-}
-
-
-/*
- * Open a tmscp device and set the unit online.  If the controller is not 
- * in the run state, call init to initialize the tmscp controller first.
- */
-
-/* ARGSUSED */
-int
-tmscpopen(dev, flag, type, p)
-       dev_t dev;
-       int flag, type;
-       struct proc *p;
-{
-       register int unit;
-       register struct uba_device *ui;
-       register struct tmscp_softc *sc;
-       register struct tms_info *tms;
-       register volatile struct mscp *mp;
-       register struct uba_ctlr *um;
-       volatile struct tmscpdevice *tmscpaddr;
-       volatile int i;
-       int s;
-       
-       unit = TMSUNIT(dev);
-#      ifdef DEBUG
-       printd("tmscpopen unit %d\n",unit);
-       if(tmscpdebug)DELAY(10000);
-#      endif
-       if (unit >= NTMS || (ui = tmsdinfo[unit]) == 0 || ui->ui_alive == 0)
-               return (ENXIO);
-       tms = &tms_info[ui->ui_unit];
-       if (tms->tms_openf)
-               return (EBUSY);
-       sc = &tmscp_softc[ui->ui_ctlr];
-       tms->tms_openf = 1;
-       tms->tms_tpr = tprintf_open(curproc);
-       s = splbio();
-       if (sc->sc_state != S_RUN)
-               {
-               if (sc->sc_state == S_IDLE)
-                       if(!tmscpinit(ui->ui_ctlr))
-                               {
-                               printf("tmscp controller failed to init\n");
-                               (void) splx(s);
-                               tms->tms_openf = 0;
-                               return(ENXIO);
-                               }
-               /* 
-                * Wait for initialization to complete
-                */
-               timeout(wakeup,(caddr_t)ui->ui_mi,11*hz);       /* to be sure*/
-               sleep((caddr_t)ui->ui_mi, 0);
-               if (sc->sc_state != S_RUN)
-                       {
-                       (void) splx(s);
-                       tms->tms_openf = 0;
-                       return (EIO);
-                       }
-               }
-       /*
-        * Check to see if the device is really there.
-        * this code was taken from Fred Canters 11 driver
-        */
-       um = ui->ui_mi;
-       tmscpaddr = (struct tmscpdevice *) um->um_addr;
-       (void) splx(s);
-       if(ui->ui_flags == 0)
-               {
-               s = splbio();
-               while(0 ==(mp = tmscpgetcp(um)))
-                       {
-                       tmscp_cp_wait++;
-                       sleep((caddr_t)&tmscp_cp_wait,PSWP+1);
-                       tmscp_cp_wait--;
-                       }
-               (void) splx(s);
-               mp->mscp_opcode = M_OP_ONLIN;
-               mp->mscp_unit = ui->ui_slave;
-               mp->mscp_cmdref = (long) & tms->tms_type;
-                                           /* need to sleep on something */
-#              ifdef DEBUG
-               printd("tmscpopen: bring unit %d online\n",ui->ui_unit);
-#              endif   
-               *((long *) mp->mscp_dscptr ) |= TMSCP_OWN | TMSCP_INT;
-               i = tmscpaddr->tmscpip;
-#ifdef lint
-               i = i;
-#endif
-               /* 
-                * To make sure we wake up, timeout in 240 seconds.
-                * Wakeup in tmscprsp routine.
-                * 240 seconds (4 minutes) is necessary since a rewind
-                * can take a few minutes.
-                */
-               timeout(wakeup,(caddr_t) mp->mscp_cmdref,240 * hz);
-               sleep((caddr_t) mp->mscp_cmdref,PSWP+1);
-               }
-       if(ui->ui_flags == 0) {
-               tms->tms_openf = 0;
-               return(ENXIO);  /* Didn't go online */
-       }
-       tms->tms_lastiow = 0;
-       /*
-        * If the high density device is not specified, set unit to low
-        * density.  This is done as an "internal" ioctl command so
-        * that the command setup and response handling
-        * is done thru "regular" command routines.
-        */
-       if ((minor(dev) & T_HIDENSITY) == 0)
-               tmscpcommand(dev, TMS_LOWDENSITY, 1);
-       else
-               tmscpcommand(dev, TMS_HIDENSITY, 1);
-       return (0);
-}
-
-
-/*
- * Close tape device.
- *
- * If tape was open for writing or last operation was
- * a write, then write two EOF's and backspace over the last one.
- * Unless this is a non-rewinding special file, rewind the tape.
- *
- * NOTE:
- *     We want to be sure that any serious exception is cleared on the
- *     close. A Clear Serious Exception (CSE) modifier is always done on
- *     the rewind command.  For the non-rewind case we check to see if the
- *     "serex" field is set in the softc struct; if it is then issue a noop
- *     command with the CSE modifier.
- * Make the tape available to others, by clearing openf flag.
- */
-int
-tmscpclose(dev, flag, type, p)
-       register dev_t dev;
-       register flag, type;
-       struct proc *p;
-{
-       register struct tms_info *tms;
-       register struct uba_device *ui;
-
-       ui = tmsdinfo[TMSUNIT(dev)];
-#      ifdef DEBUG
-       printd("tmscpclose: ctlr =  %d\n",TMSCPCTLR(dev));
-       printd("tmscpclose: unit = %d\n",TMSUNIT(dev));
-       if(tmscpdebug)DELAY(10000);
-#      endif
-       tms = &tms_info[ui->ui_unit];
-       if (flag == FWRITE || ((flag&FWRITE) && tms->tms_lastiow))
-               {
-               /*         device, command, count */
-               tmscpcommand (dev, TMS_WRITM, 1);
-               tmscpcommand (dev, TMS_WRITM, 1);
-               tmscpcommand (dev, TMS_BSR, 1);
-               }
-       if ((minor(dev)&T_NOREWIND) == 0)
-               /*
-                * Don't hang waiting for rewind complete.
-                */
-               tmscpcommand(dev, TMS_REW, 0);
-       else
-               if (tms->tms_serex)
-                       {
-#                      ifdef DEBUG
-                       printd("tmscpclose: clearing serex\n");
-                       if(tmscpdebug)DELAY(10000);
-#                      endif
-                       tmscpcommand(dev, TMS_CSE, 1);
-                       }
-       tprintf_close(tms->tms_tpr);
-       tms->tms_openf = 0;
-       return (0);
-}
-
-
-/*
- * Execute a command on the tape drive a specified number of times.
- * This routine sets up a buffer and calls the strategy routine which
- * links the buffer onto the drive's buffer queue.
- * The start routine will take care of creating a tmscp command packet
- * 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;
-{
-       register struct uba_device *ui;
-       register struct buf *bp;
-       register int s;
-       int unit = TMSUNIT(dev);
-
-       ui = tmsdinfo[unit];
-       bp = &ctmscpbuf[ui->ui_ctlr];
-
-       s = splbio();
-       while (bp->b_flags&B_BUSY)
-               {
-               /*
-                * This special check is because B_BUSY never
-                * gets cleared in the non-waiting rewind case.
-                */
-               if (bp->b_bcount == 0 && (bp->b_flags&B_DONE))
-                       break;
-               bp->b_flags |= B_WANTED;
-               sleep((caddr_t)bp, PRIBIO);
-               }
-       bp->b_flags = B_BUSY|B_READ;
-       splx(s);
-       /*
-        * Load the buffer.  The b_count field gets used to hold the command
-        * count.  the b_resid field gets used to hold the command mneumonic.
-        * These 2 fields are "known" to be "safe" to use for this purpose.
-        * (Most other drivers also use these fields in this way.)
-        */
-       bp->b_dev = dev;
-       bp->b_bcount = count;
-       bp->b_resid = com;
-       bp->b_blkno = 0;
-       tmscpstrategy(bp);
-       /*
-        * In case of rewind from close, don't wait.
-        * This is the only case where count can be 0.
-        */
-       if (count == 0)
-               return;
-       iowait(bp);
-       if (bp->b_flags&B_WANTED)
-               wakeup((caddr_t)bp);
-       bp->b_flags &= B_ERROR;
-}
-
-/*
- * Find an unused command packet
- */
-struct mscp *
-tmscpgetcp(um)
-       struct uba_ctlr *um;
-{
-       register volatile struct mscp *mp;
-       register volatile struct tmscpca *cp;
-       register struct tmscp_softc *sc;
-       register int i;
-       int     s;
-
-       s = splbio();
-       cp = &tmscp[um->um_ctlr].tmscp_ca;
-       sc = &tmscp_softc[um->um_ctlr];
-       /*
-        * If no credits, can't issue any commands
-        * until some outstanding commands complete.
-        */
-       i = sc->sc_lastcmd;
-#      ifdef DEBUG
-       printd10("tmscpgetcp: %d credits remain\n", sc->sc_credits);
-#      endif
-       if(((cp->ca_cmddsc[i]&(TMSCP_OWN|TMSCP_INT))==TMSCP_INT) &&
-         (sc->sc_credits >= 2))
-               {
-               sc->sc_credits--;       /* This commits to issuing a command */
-               cp->ca_cmddsc[i] &= ~TMSCP_INT;
-               mp = &tmscp[um->um_ctlr].tmscp_cmd[i];
-               mp->mscp_unit = mp->mscp_modifier = 0;
-               mp->mscp_opcode = mp->mscp_flags = 0;
-               mp->mscp_bytecnt = mp->mscp_buffer = 0;
-               sc->sc_lastcmd = (i + 1) % NCMD;
-               (void) splx(s);
-               return((struct mscp *)mp);
-               }
-       (void) splx(s);
-       return(NULL);
-}
-
-
-/*
- * Initialize a TMSCP device.  Set up UBA mapping registers,
- * initialize data structures, and start hardware
- * initialization sequence.
- */
-int
-tmscpinit (d)
-       int d;                  /* index to the controller */
-{
-       register struct tmscp_softc *sc;
-       register struct tmscp *t;
-       volatile struct tmscpdevice *tmscpaddr;
-       struct uba_ctlr *um;
-
-       sc = &tmscp_softc[d];
-       um = tmscpminfo[d];
-       um->um_tab.b_active++;
-       t = &tmscp[d];
-       tmscpaddr = (struct tmscpdevice *)um->um_addr;
-       if (sc->sc_mapped == 0)
-               {
-               /*
-                * Map the communications area and command
-                * and response packets into Unibus address
-                * space.
-                */
-               sc->sc_ubainfo = uballoc(um->um_ubanum, (caddr_t)t, sizeof (struct tmscp), 0);
-               sc->sc_tmscp = (struct tmscp *)(UBAI_ADDR(sc->sc_ubainfo));
-               sc->sc_mapped = 1;
-               }
-
-       /*
-        * Start the hardware initialization sequence.
-        */
-       tmscpaddr->tmscpip = 0;              /* start initialization */
-
-       while((tmscpaddr->tmscpsa & TMSCP_STEP1) == 0)
-               {
-#              ifdef DEBUG
-               printd("tmscpinit: tmscpsa = 0%o\n",tmscpaddr->tmscpsa);
-               DELAY(100000);
-#              endif
-               if(tmscpaddr->tmscpsa & TMSCP_ERR)
-                       return(0);      /* CHECK */
-               }
-       tmscpaddr->tmscpsa=TMSCP_ERR|(NCMDL2<<11)|(NRSPL2<<8)|TMSCP_IE|(sc->sc_ivec/4);
-       /*
-        * Initialization continues in the interrupt routine.
-        */
-       sc->sc_state = S_STEP1;
-       sc->sc_credits = 0;
-       return(1);
-}
-
-
-/*
- * 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;
-{
-       register struct buf *bp, *dp;
-       register volatile struct mscp *mp;
-       register struct tmscp_softc *sc;
-       register struct tms_info *tms;
-       register struct uba_device *ui;
-       volatile struct tmscpdevice *tmscpaddr;
-       volatile struct tmscp *tm = &tmscp[um->um_ctlr];
-       volatile int i;
-       int tempi;
-       char ioctl;             /* flag: set true if its an IOCTL command */
-
-       sc = &tmscp_softc[um->um_ctlr];
-       
-    for(;;)
-       {
-       if ((dp = um->um_tab.b_actf) == NULL)
-               {
-               /*
-                * Release unneeded UBA resources and return
-                * (drive was inactive)
-                */
-               um->um_tab.b_active = 0;
-               break;
-               }
-       if ((bp = dp->b_actf) == NULL)
-               {
-               /*
-                * No more requests for this drive, remove
-                * from controller queue and look at next drive.
-                * We know we're at the head of the controller queue.
-                */
-               dp->b_active = 0;
-               um->um_tab.b_actf = dp->b_hash.le_next;
-               continue;               /* Need to check for loop */
-               }
-       um->um_tab.b_active++;
-       tmscpaddr = (struct tmscpdevice *)um->um_addr;
-       ui = tmsdinfo[(TMSUNIT(bp->b_dev))];
-       tms = &tms_info[ui->ui_unit];
-       if ((tmscpaddr->tmscpsa&TMSCP_ERR) || sc->sc_state != S_RUN)
-               {
-               tprintf(tms->tms_tpr,
-                   "tms%d: hard error bn%d\n",
-                   minor(bp->b_dev)&03, bp->b_blkno);
-               log(TMS_PRI, "tmscp%d: sa 0%o, state %d\n",um->um_ctlr,
-                               tmscpaddr->tmscpsa&0xffff, sc->sc_state);
-               (void)tmscpinit(um->um_ctlr);
-               /* SHOULD REQUEUE OUTSTANDING REQUESTS, LIKE TMSCPRESET */
-               break;
-               }
-       /*
-        * Default is that last command was NOT a write command;
-        * if a write command is done it will be detected in tmscprsp.
-        */
-       tms->tms_lastiow = 0;
-       if (ui->ui_flags == 0)
-               {        /* not online */
-               if ((mp = tmscpgetcp(um)) == NULL)
-                       break;
-               mp->mscp_opcode = M_OP_ONLIN;
-               mp->mscp_unit = ui->ui_slave;
-               dp->b_active = 2;
-               um->um_tab.b_actf = dp->b_hash.le_next; /* remove from controller q */
-               *((long *)mp->mscp_dscptr) |= TMSCP_OWN|TMSCP_INT;
-               if (tmscpaddr->tmscpsa&TMSCP_ERR)
-                       printf("tmscp%d fatal error (0%o)\n",um->um_ctlr,
-                                       tmscpaddr->tmscpsa&0xffff);
-               i = tmscpaddr->tmscpip;
-               continue;
-               }
-       switch (cpunumber) {
-
-       case VAX_8600:
-       case VAX_780:
-               i = UBA_NEEDBDP|UBA_CANTWAIT;
-               break;
-       case VAX_750:
-               i = um->um_ubinfo|UBA_HAVEBDP|UBA_CANTWAIT;
-               break;
-       case VAX_730:
-       case VAX_78032:
-               i = UBA_CANTWAIT;
-               break;
-       }   /* end switch (cpunumber) */
-       /*
-        * If command is an ioctl command then set the ioctl flag for later use.
-        * If not (i.e. it is a read or write) then attempt
-        * to set up a buffer pointer.
-        */
-       ioctl = 0;
-       if (bp == &ctmscpbuf[um->um_ctlr])
-               ioctl = 1;
-       else
-               if ((i = ubasetup(um->um_ubanum, bp, i)) == 0)
-                       {
-                       if(dp->b_qsize != 0)
-                               break; /* When a command completes and */
-                                    /* frees a bdp tmscpstart will be called */
-                       if ((mp = tmscpgetcp(um)) == NULL)
-                               break;
-#                      ifdef DEBUG
-                       printd("tmscpstart: GTUNT %d ubasetup = %d\n",ui->ui_unit, i);
-                       if(tmscpdebug)DELAY(10000);
-#                      endif
-                       mp->mscp_opcode = M_OP_GTUNT;
-                       mp->mscp_unit = ui->ui_slave;
-                       *((long *)mp->mscp_dscptr) |= TMSCP_OWN|TMSCP_INT;
-                       if (tmscpaddr->tmscpsa&TMSCP_ERR)
-                               printf("tmscp%d: fatal error (0%o)\n",um->um_ctlr,
-                                           tmscpaddr->tmscpsa&0xffff);
-                       i = tmscpaddr->tmscpip; /* initiate polling */
-                       break;
-                       }
-#      if defined(VAX750)
-       if (cpunumber == VAX_750)
-               tempi = i & 0xfffffff;                  /* mask off bdp */
-       else
-#      endif
-               tempi = i;
-       if ((mp = tmscpgetcp(um)) == NULL)
-               {
-               if (!ioctl)             /* only need to release if NOT ioctl */
-                       ubarelse(um->um_ubanum,&tempi);
-               break;
-               }
-       mp->mscp_cmdref = (long)bp;             /* pointer to get back */
-       mp->mscp_unit = ui->ui_slave;
-       /*
-        * If its an ioctl-type command then set up the appropriate
-        * tmscp command;  by doing a switch on the "b_resid" field where
-        * the command mneumonic is stored.
-        */
-       if (ioctl)
-               {
-#              ifdef DEBUG
-               printd("tmscpstart: doing ioctl cmd %d\n", bp->b_resid);
-#              endif
-               /*
-                * The reccnt and tmkcnt fields are set to zero by the getcp
-                * routine (as bytecnt and buffer fields).  Thus reccnt and
-                * tmkcnt are only modified here if they need to be set to
-                * a non-zero value.
-                */
-               switch ((int)bp->b_resid) {
-
-               case TMS_WRITM:
-                       mp->mscp_opcode = M_OP_WRITM;
-                       break;
-               case TMS_FSF:
-                       mp->mscp_opcode = M_OP_REPOS;
-                       mp->mscp_tmkcnt = bp->b_bcount;
-                       break;
-               case TMS_BSF:
-                       mp->mscp_opcode = M_OP_REPOS;
-                       mp->mscp_modifier = M_MD_REVRS;
-                       mp->mscp_tmkcnt = bp->b_bcount;
-                       break;
-               case TMS_FSR:
-                       mp->mscp_opcode = M_OP_REPOS;
-                       mp->mscp_modifier = M_MD_OBJCT;
-                       mp->mscp_reccnt = bp->b_bcount;
-                       break;
-               case TMS_BSR:
-                       mp->mscp_opcode = M_OP_REPOS;
-                       mp->mscp_modifier = M_MD_REVRS | M_MD_OBJCT;
-                       mp->mscp_reccnt = bp->b_bcount;
-                       break;
-               /*
-                * Clear serious exception is done for Rewind & Available cmds
-                */
-               case TMS_REW:
-                       mp->mscp_opcode = M_OP_REPOS;
-                       mp->mscp_modifier = M_MD_REWND | M_MD_CLSEX;
-                       if (bp->b_bcount == 0)
-                               mp->mscp_modifier |= M_MD_IMMED;
-                       tms->tms_serex = 0;
-                       break;
-               case TMS_OFFL:
-                       mp->mscp_opcode = M_OP_AVAIL;
-                       mp->mscp_modifier = M_MD_UNLOD | M_MD_CLSEX;
-                       tms->tms_serex = 0;
-                       break;
-               case TMS_SENSE:
-                       mp->mscp_opcode = M_OP_GTUNT;
-                       break;
-               case TMS_CACHE:
-                       mp->mscp_opcode = M_OP_STUNT;
-                       tms->tms_unitflgs |= M_UF_WBKNV;
-                       mp->mscp_unitflgs = tms->tms_unitflgs;
-                       mp->mscp_format = tms->tms_format;
-                       /* default device dependant parameters */
-                       mp->mscp_mediaid = 0;
-                       break;
-               case TMS_NOCACHE:
-                       mp->mscp_opcode = M_OP_STUNT;
-                       tms->tms_unitflgs &= ~(M_UF_WBKNV);
-                       mp->mscp_unitflgs = tms->tms_unitflgs;
-                       mp->mscp_format = tms->tms_format;
-                       /* default device dependant parameters */
-                       mp->mscp_mediaid = 0;
-                       break;
-               case TMS_CSE:
-                       /*
-                        * This is a no-op command. It performs a 
-                        * clear serious exception only.  (Done on a
-                        * non-rewinding close after a serious exception.)
-                        */
-                       mp->mscp_opcode = M_OP_REPOS;
-                       mp->mscp_modifier = M_MD_CLSEX;
-                       tms->tms_serex = 0;
-                       tms->tms_clserex = 1;
-                       break;
-               case TMS_LOWDENSITY:
-                       /*
-                        * Set the unit to low density
-                        */
-                       mp->mscp_opcode = M_OP_STUNT;
-                       mp->mscp_unitflgs = tms->tms_unitflgs;
-                       mp->mscp_mediaid = 0;   /* default device dependant parameters */
-                       if ((tms->tms_fmtmenu & M_TF_800) != 0)
-                               mp->mscp_format = M_TF_800;
-                       else
-                               mp->mscp_format = M_TF_PE & tms->tms_fmtmenu;
-                       tms->tms_format = mp->mscp_format;
-                       break;
-               case TMS_HIDENSITY:
-                       /*
-                        * Set the unit to high density (format == 0)
-                        */
-                       mp->mscp_opcode = M_OP_STUNT;
-                       mp->mscp_unitflgs = tms->tms_unitflgs;
-                       mp->mscp_mediaid = 0;   /* default device dependant parameters */
-                       mp->mscp_format = 0;
-                       tms->tms_format = 0;
-                       break;
-               default:
-                       printf("Bad ioctl on tms unit %d\n", ui->ui_unit);
-                       /* Need a no-op. Reposition no amount */
-                       mp->mscp_opcode = M_OP_REPOS;
-                       break;
-               }   /* end switch (bp->b_resid) */
-               }
-       else    /* Its a read/write command (not an ioctl) */
-               {
-               mp->mscp_opcode = bp->b_flags&B_READ ? M_OP_READ : M_OP_WRITE;
-               mp->mscp_bytecnt = bp->b_bcount;
-               mp->mscp_buffer = UBAI_ADDR(i) | (UBAI_BDP(i) << 24);
-
-               bp->b_ubinfo = tempi;                   /* save mapping info */
-               }
-       if (tms->tms_serex == 2)                        /* if tape mark read */
-               {
-               mp->mscp_modifier |= M_MD_CLSEX;        /*  clear serious exc */
-               tms->tms_serex = 0;
-               }
-       *((long *)mp->mscp_dscptr) |= TMSCP_OWN|TMSCP_INT;
-#      ifdef DEBUG
-       printd("tmscpstart: opcode 0%o mod %o unit %d cnt %d\n",mp->mscp_opcode,mp->mscp_modifier,mp->mscp_unit,mp->mscp_bytecnt);
-       if(tmscpdebug)DELAY(100000);
-#      endif
-       i = tmscpaddr->tmscpip;              /* initiate polling */
-       dp->b_qsize++;
-       /*
-        * Move drive to the end of the controller queue
-        */
-       if (dp->b_hash.le_next != NULL)
-               {
-               um->um_tab.b_actf = dp->b_hash.le_next;
-               MSCP_APPEND(dp, &um->um_tab, b_hash.le_next);
-               }
-       /*
-        * Move buffer to I/O wait queue
-        */
-       dp->b_actf = bp->b_actf;
-       dp = &tmscpwtab[um->um_ctlr];
-       MSCP_APPEND(bp, dp, b_actf);
-       if (tmscpaddr->tmscpsa&TMSCP_ERR)
-               {
-               printf("tmscp%d: fatal error (0%o)\n", um->um_ctlr, tmscpaddr->tmscpsa&0xffff);
-               (void)tmscpinit(um->um_ctlr);
-               break;
-               }
-    }   /* end for */
-    /*
-     * Check for response ring transitions lost in the
-     * Race condition
-     */
-    for (i = sc->sc_lastrsp;; i++)
-           {
-           i %= NRSP;
-           if (tm->tmscp_ca.ca_rspdsc[i]&TMSCP_OWN)
-                   break;
-           tmscprsp(um, (struct tmscp *)tm, sc, i);
-           tm->tmscp_ca.ca_rspdsc[i] |= TMSCP_OWN;
-           }
-    sc->sc_lastrsp = i;
-}
-
-
-/*
- * Process a response packet
- */
-void
-tmscprsp(um, tm, sc, i)
-       register struct uba_ctlr *um;
-       struct tmscp *tm;
-       register struct tmscp_softc *sc;
-       int i;
-{
-       register volatile struct mscp *mp;
-       register struct tms_info *tms;
-       struct uba_device *ui;
-       struct buf *dp, *bp;
-       int st;
-       struct  uba_softc *ubasc;
-
-       mp = &tm->tmscp_rsp[i];
-       mp->mscp_header.tmscp_msglen = mscp_msglen;
-       sc->sc_credits += mp->mscp_header.tmscp_credits & 0xf;  /* low 4 bits */
-       if ((mp->mscp_header.tmscp_credits & 0xf0) > 0x10)      /* Check */
-               return;
-#      ifdef DEBUG
-       printd("tmscprsp, opcode 0%o status 0%o\n",mp->mscp_opcode,mp->mscp_status&M_ST_MASK);
-#      endif   
-       /*
-        * If it's an error log message (datagram),
-        * pass it on for more extensive processing.
-        */
-       if ((mp->mscp_header.tmscp_credits & 0xf0) == 0x10)
-               {       /* check */
-               tmserror(um, (struct mslg *)mp);
-               return;
-               }
-       st = mp->mscp_status&M_ST_MASK;
-       /*
-        * The controller interrupts as drive 0.
-        * This means that you must check for controller interrupts
-        * before you check to see if there is a drive 0.
-        */
-       if((M_OP_STCON|M_OP_END) == mp->mscp_opcode)
-               {
-               if (st == M_ST_SUCC)
-                       {
-#                      ifdef DEBUG
-                       printd("ctlr has %d credits\n", mp->mscp_header.tmscp_credits & 0xf);
-                       printd("ctlr timeout = %d\n", mp->mscp_cnttmo);
-#                      endif
-                       sc->sc_state = S_RUN;
-                       }
-               else
-                       sc->sc_state = S_IDLE;
-               um->um_tab.b_active = 0;
-               wakeup((caddr_t)um);
-               return;
-               }
-       if (mp->mscp_unit >= NTMS)
-               return;
-       if ((ui = tmscpip[um->um_ctlr][mp->mscp_unit]) == 0)
-               return;
-       tms = &tms_info[ui->ui_unit];
-       /*
-        * Save endcode, endflags, and status for mtioctl get unit status.
-        * NOTE: Don't do this on Clear serious exception (reposition no-op);
-        *    which is done on close since this would
-        *    overwrite the real status we want.
-        */
-       if (tms->tms_clserex != 1)
-               {
-               tms->tms_endcode = mp->mscp_opcode;
-               tms->tms_flags = mp->mscp_flags;
-               tms->tms_status = st;
-               }
-       else tms->tms_clserex = 0;
-
-       switch (mp->mscp_opcode) {
-       case M_OP_ONLIN|M_OP_END:
-               tms->tms_type = mp->mscp_mediaid;
-               dp = &tmsutab[ui->ui_unit];
-               if (st == M_ST_SUCC)
-                       {
-                       /*
-                        * Link the drive onto the controller queue
-                        */
-                       MSCP_APPEND(dp, &um->um_tab, b_hash.le_next);
-                       ui->ui_flags = 1;       /* mark it online */
-                       tms->tms_dsize=(daddr_t)mp->mscp_maxwrt;
-#                      ifdef DEBUG
-                       printd("tmscprsp: unit %d online\n", mp->mscp_unit);
-#                      endif                   
-                       /* 
-                        * This define decodes the Media type identifier
-                        */
-#                      define F_to_C(x,i)     ( ((x)->mscp_mediaid) >> (i*5+7) & 0x1f ? ( ( (((x)->mscp_mediaid) >>( i*5 + 7)) & 0x1f) + 'A' - 1): ' ')
-#                      ifdef DEBUG
-                       printd("tmscprsp: unit %d online %x %c%c %c%c%c%d\n"
-                               ,mp->mscp_unit, mp->mscp_mediaid ,F_to_C(mp,4)
-                               ,F_to_C(mp,3), F_to_C(mp,2)
-                               ,F_to_C(mp,1), F_to_C(mp,0), mp->mscp_mediaid & 0x7f);
-#                      endif                           
-                       dp->b_active = 1;
-                       }       /* end if st == M_ST_SUCC */
-               else 
-                       {
-                       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);
-                       else
-                               tprintf(tms->tms_tpr,
-                                   "tms%d: hard error: OFFLINE\n",
-                                   ui->ui_unit);
-                       while ((bp = dp->b_actf))
-                               {
-                               dp->b_actf = bp->b_actf;
-                               bp->b_flags |= B_ERROR;
-                               iodone(bp);
-                               }
-                       }
-               if(mp->mscp_cmdref!=NULL)
-                       /* Seems to get lost sometimes in uda */
-                       wakeup((caddr_t)mp->mscp_cmdref);
-               break;
-       /*
-        * The AVAILABLE ATTENTION message occurs when the
-        * unit becomes available after loading,
-        * marking the unit offline (ui_flags = 0) will force an
-        * online command prior to using the unit.
-        */
-       case M_OP_AVATN:
-               ui->ui_flags = 0;
-               tms->tms_type = mp->mscp_mediaid;
-               break;
-       case M_OP_END:
-               /*
-                * An endcode without an opcode (0200) is an invalid command.
-                * The mscp specification states that this would be a protocol
-                * type error, such as illegal opcodes. The mscp spec. also
-                * states that parameter error type of invalid commands should
-                * return the normal end message for the command. This does not appear
-                * to be the case. An invalid logical block number returned an endcode
-                * of 0200 instead of the 0241 (read) that was expected.
-                */
-                       
-               printf("tmscp%d: invalid cmd, endcode = %o, status=%o\n",
-                       um->um_ctlr, mp->mscp_opcode, st);
-               bp = (struct buf *)mp->mscp_cmdref;
-               /*
-                * Unlink buffer from I/O wait queue.
-                * And signal iodone, so the higher level command can exit!
-                *
-                */
-               dp = &tmscpwtab[um->um_ctlr];
-               while (dp && dp->b_actf != bp)
-                       dp = dp->b_actf;
-               if (dp == NULL)
-                       panic("tmscp: don't work1!");
-               dp->b_actf = bp->b_actf;
-               dp = &tmsutab[ui->ui_unit];
-               dp->b_qsize--;
-               iodone(bp);
-               break;
-       case M_OP_WRITE|M_OP_END:
-               /* mark the last io op as a write */
-               tms->tms_lastiow = 1;
-       case M_OP_READ|M_OP_END:
-       case M_OP_WRITM|M_OP_END:
-       case M_OP_REPOS|M_OP_END:
-       case M_OP_STUNT|M_OP_END:
-       /*
-        * The AVAILABLE message occurs when the mt ioctl "rewoffl" is
-        * issued.  For the ioctl, "rewoffl", a tmscp AVAILABLE command is
-        * done with the UNLOAD modifier.  This performs a rewind, followed
-        * by marking the unit offline.  So mark the unit offline
-        * software wise as well (ui_flags = 0 and 
-        * tms->tms_openf = 0).
-        */
-       case M_OP_AVAIL|M_OP_END:
-#              ifdef DEBUG
-               printd("tmscprsp: position = %d\n", mp->mscp_lbn);
-#              endif
-               bp = (struct buf *)mp->mscp_cmdref;
-               /*
-                * Only need to release buffer if the command was read or write.
-                * No ubasetup was done in "tmscpstart" if it was an ioctl cmd.
-                */
-               if (mp->mscp_opcode == (M_OP_READ|M_OP_END) || 
-                   mp->mscp_opcode == (M_OP_WRITE|M_OP_END))
-                       ubarelse(um->um_ubanum, (int *)&bp->b_ubinfo);
-               /*
-                * Unlink buffer from I/O wait queue.
-                */
-               dp = &tmscpwtab[um->um_ctlr];
-               while (dp && dp->b_actf != bp)
-                       dp = dp->b_actf;
-               if (dp == NULL)
-                       panic("tmscp: don't work2!");
-               dp->b_actf = bp->b_actf;
-#              if defined(VAX750)
-               ubasc = uba_cd.cd_devs[um->um_ubanum];
-               if (cpunumber == VAX_750) { 
-                   if ((tmscpwtab[um->um_ctlr].b_actf == NULL) &&
-                                       (um->um_ubinfo != 0)) {
-                       ubarelse(um->um_ubanum, &um->um_ubinfo);
-                   }
-                   else {
-                       if (mp->mscp_opcode == (M_OP_READ|M_OP_END) ||
-                           mp->mscp_opcode == (M_OP_WRITE|M_OP_END))
-                               UBAPURGE(ubasc->uh_uba,(um->um_ubinfo >>28) & 0x0f);
-                   }
-               }
-#              endif
-               dp = &tmsutab[ui->ui_unit];
-               dp->b_qsize--;
-               if (st == M_ST_OFFLN || st == M_ST_AVLBL)
-                       {
-                       ui->ui_flags = 0;       /* mark unit offline */
-                       tms->tms_openf = 0;
-                       tms->tms_type = mp->mscp_mediaid;
-                       /*
-                        * Link the buffer onto the front of the drive queue
-                        */
-                       bp->b_actf = dp->b_actf;
-                       dp->b_actf = bp;
-                       /*
-                        * Link the drive onto the controller queue
-                        */
-                       if (dp->b_active == 0)
-                               {
-                               MSCP_APPEND(dp, &um->um_tab, b_hash.le_next);
-                               dp->b_active = 1;
-                               }
-#                      if defined(VAX750)
-                       if (cpunumber == VAX_750 && um->um_ubinfo == 0)
-                               um->um_ubinfo = uballoc(um->um_ubanum, (caddr_t)0, 0, UBA_NEEDBDP);
-#                      endif
-                       return;
-                       }
-               if (st != M_ST_SUCC)
-                       {
-                       if (mp->mscp_flags & M_EF_SEREX)
-                               tms->tms_serex = 1;
-                       if (st != M_ST_TAPEM)
-                               {
-                               tprintf(tms->tms_tpr,
-                                   "tms%d: hard error bn%d\n",
-                                   minor(bp->b_dev)&03, bp->b_blkno);
-                               errinfo(st);            /* produces more info */
-#                              ifdef DEBUG
-                               printd("tmscprsp: error; status sub-code = 0%o, flags = 0%o\n",
-                                       (mp->mscp_status & 177740)>>5, mp->mscp_flags);
-#                              endif
-                               bp->b_flags |= B_ERROR;
-                               }
-                       else
-                               /* Hit a tape mark - Set serex flag to
-                                * a special value so we can clear the
-                                * serious exception on the next command.
-                                */
-                               tms->tms_serex = 2;
-                       }
-               /*
-                * The tmscp spec states that controllers do not have to
-                * report the number of records or files skipped.  So on
-                * reposition commands we go strictly by cmd status.
-                */
-               if (mp->mscp_opcode != (M_OP_REPOS|M_OP_END))
-                       bp->b_resid = bp->b_bcount - mp->mscp_bytecnt;
-               else
-                       bp->b_resid = 0;
-               tms->tms_resid = bp->b_resid;
-               iodone(bp);
-               break;
-
-       case M_OP_GTUNT|M_OP_END:
-#              ifdef DEBUG
-               printd("tmscprsp: GTUNT end packet status = 0%o\n",st);
-               printd("tmscprsp: unit %d mediaid %x %c%c %c%c%c%d %x %x t=%d\n"
-                   ,mp->mscp_unit, mp->mscp_mediaid
-                   ,F_to_C(mp,4),F_to_C(mp,3),F_to_C(mp,2)
-                   ,F_to_C(mp,1),F_to_C(mp,0)
-                   ,mp->mscp_mediaid & 0x7f
-                   ,mp->mscp_unitid.val[0]
-                   ,mp->mscp_unitid.val[1]
-                   ,mp->mscp_format);
-#              endif           
-               tms->tms_type = mp->mscp_mediaid;
-               tms->tms_fmtmenu = mp->mscp_fmtmenu;
-               tms->tms_unitflgs = mp->mscp_unitflgs;
-               break;
-
-       default:
-               printf("tmscp unknown packet\n");
-               tmserror(um, (struct mslg *)mp);
-       }       /* end switch mp->mscp_opcode */
-}
-
-
-/* 
- * Give a meaningful error when the mscp_status field returns an error code.
- */
-
-void
-errinfo(st)
-       int st;                 /* the status code */
-{
-       switch(st) {
-       case M_ST_ICMD:
-               printf("invalid command\n");
-               break;
-       case M_ST_ABRTD:
-               printf("command aborted\n");
-               break;
-       case M_ST_OFFLN:
-               printf("unit offline\n");
-               break;
-       case M_ST_WRTPR:
-               printf("unit write protected\n");
-               break;
-       case M_ST_COMP:
-               printf("compare error\n");
-               break;
-       case M_ST_DATA:
-               printf("data error\n");
-               break;
-       case M_ST_HSTBF:
-               printf("host buffer access error\n");
-               break;
-       case M_ST_CNTLR:
-               printf("controller error\n");
-               break;
-       case M_ST_DRIVE:
-               printf("drive error\n");
-               break;
-       case M_ST_FMTER:
-               printf("formatter error\n");
-               break;
-       case M_ST_BOT:
-               printf("BOT encountered\n");
-               break;
-       case M_ST_TAPEM:
-               printf("tape mark encountered\n");
-               break;
-       case M_ST_RDTRN:
-               printf("record data truncated\n");
-               break;
-       case M_ST_PLOST:
-               printf("position lost\n");
-               break;
-       case M_ST_SEX:
-               printf("serious exception\n");
-               break;
-       case M_ST_LED:
-               printf("LEOT detected\n");
-               break;
-       }
-}
-
-
-/*
- * Manage buffers and perform block mode read and write operations.
- */
-void
-tmscpstrategy (bp)
-       register struct buf *bp;
-{
-       register struct uba_device *ui;
-       register struct uba_ctlr *um;
-       register struct buf *dp;
-       register int unit = TMSUNIT(bp->b_dev);
-       int s;
-
-       if (unit >= NTMS)
-               {
-#              ifdef DEBUG
-               printd ("tmscpstrategy: bad unit # %d\n",unit);
-#              endif
-               bp->b_flags |= B_ERROR;
-               iodone(bp);
-               return;
-               }
-       ui = tmsdinfo[unit];
-       um = ui->ui_mi;
-       if (ui == 0 || ui->ui_alive == 0)
-               {
-               bp->b_flags |= B_ERROR;
-               iodone(bp);
-               return;
-               }
-       s = splbio();
-       /*
-        * Link the buffer onto the drive queue
-        */
-       dp = &tmsutab[ui->ui_unit];
-       MSCP_APPEND(bp, dp, b_actf);
-       /*
-        * Link the drive onto the controller queue
-        */
-       if (dp->b_active == 0)
-               {
-               MSCP_APPEND(dp, &um->um_tab, b_hash.le_next);
-               dp->b_active = 1;
-               }
-       /*
-        * If the controller is not active, start it.
-        */
-       if (um->um_tab.b_active == 0)
-               {
-#              if defined(VAX750)
-               if (cpunumber == VAX_750
-                                && tmscpwtab[um->um_ctlr].b_actf == NULL)
-                       {
-                       if (um->um_ubinfo != 0)
-                               log(TMS_PRI, "tmscpstrategy: ubinfo 0x%x\n",
-                                   um->um_ubinfo);
-                       else
-                               um->um_ubinfo = uballoc(um->um_ubanum, (caddr_t)0, 0, UBA_NEEDBDP);
-                       }
-#              endif
-#              ifdef DEBUG
-               printd10("tmscpstrategy: Controller not active, starting it\n");
-#              endif
-               (void) tmscpstart(um);
-               }
-       splx(s);
-       return;
-}
-
-int
-tmscpread(dev, uio)
-       dev_t dev;
-       struct uio *uio;
-{
-
-       return (physio(tmscpstrategy, NULL, dev, B_READ, minphys, uio));
-}
-
-int
-tmscpwrite(dev, uio)
-       dev_t dev;
-       struct uio *uio;
-{
-
-       return (physio(tmscpstrategy, NULL, dev, B_WRITE, minphys, uio));
-}
-
-#define DBSIZE 32
-
-#define ca_Rspdsc       ca_rspdsc[0]
-#define ca_Cmddsc       ca_rspdsc[1]
-#define tmscp_Rsp       tmscp_rsp[0]
-#define tmscp_Cmd       tmscp_cmd[0]
-
-struct  tmscp     tmscpd[NTMSCP];
-
-int
-tmscpdump(dev, blkno, va, size)
-       dev_t dev;
-       daddr_t blkno;
-       caddr_t va;
-       size_t size;
-{
-#ifdef notyet
-       volatile struct tmscpdevice *tmscpaddr;
-       volatile struct tmscp *tmscp_ubaddr;
-       char *start;
-       int num, blk, unit;
-       register struct uba_regs *uba;
-       register struct uba_device *ui;
-       register volatile struct tmscp *tmscpp;
-       register struct pte *io;
-       register int i;
-
-       unit = minor(dev) & 03;
-       if (unit >= NTMS)
-               return (ENXIO);
-#      define phys(cast, addr) ((cast)((int)addr & 0x7fffffff))
-       ui = phys(struct uba_device *, tmsdinfo[unit]);
-       if (ui->ui_alive == 0)
-               return (ENXIO);
-       uba = phys(struct uba_softc *, ui->ui_hd)->uh_physuba;
-       ubainit(uba);
-       tmscpaddr = (struct tmscpdevice *)ui->ui_physaddr;
-       DELAY(2000000);
-       tmscpp = phys(struct tmscp *, &tmscpd[ui->ui_ctlr]);
-
-       num = btoc(sizeof(struct tmscp)) + 1;
-       io = (struct pte *)&uba->uba_map[NUBMREG-num];
-       for(i = 0; i<num; i++)
-               *(int *)io++ = UBAMR_MRV|(btop(tmscpp)+i);
-       tmscp_ubaddr = (struct tmscp *)(((int)tmscpp & PGOFSET)|((NUBMREG-num)<<9));
-
-       tmscpaddr->tmscpip = 0;
-       while ((tmscpaddr->tmscpsa & TMSCP_STEP1) == 0)
-               if(tmscpaddr->tmscpsa & TMSCP_ERR) return(EFAULT);
-       tmscpaddr->tmscpsa = TMSCP_ERR;
-       while ((tmscpaddr->tmscpsa & TMSCP_STEP2) == 0)
-               if(tmscpaddr->tmscpsa & TMSCP_ERR) return(EFAULT);
-       tmscpaddr->tmscpsa = (short)((int)&tmscp_ubaddr->tmscp_ca.ca_ringbase);
-       while ((tmscpaddr->tmscpsa & TMSCP_STEP3) == 0)
-               if(tmscpaddr->tmscpsa & TMSCP_ERR) return(EFAULT);
-       tmscpaddr->tmscpsa = (short)(((int)&tmscp_ubaddr->tmscp_ca.ca_ringbase) >> 16);
-       while ((tmscpaddr->tmscpsa & TMSCP_STEP4) == 0)
-               if(tmscpaddr->tmscpsa & TMSCP_ERR) return(EFAULT);
-       tmscpaddr->tmscpsa = TMSCP_GO;
-       tmscpp->tmscp_ca.ca_Rspdsc = (long)&tmscp_ubaddr->tmscp_Rsp.mscp_cmdref;
-       tmscpp->tmscp_ca.ca_Cmddsc = (long)&tmscp_ubaddr->tmscp_Cmd.mscp_cmdref;
-       tmscpp->tmscp_Cmd.mscp_header.tmscp_vcid = 1;   /* for tape */
-       tmscpp->tmscp_Cmd.mscp_cntflgs = 0;
-       tmscpp->tmscp_Cmd.mscp_version = 0;
-       if (tmscpcmd(M_OP_STCON, tmscpp, tmscpaddr) == 0) {
-               return(EFAULT);
-       }
-       tmscpp->tmscp_Cmd.mscp_unit = ui->ui_slave;
-       if (tmscpcmd(M_OP_ONLIN, tmscpp, tmscpaddr) == 0) {
-               return(EFAULT);
-       }
-
-       num = maxfree;
-       start = 0;
-       while (num > 0)
-               {
-               blk = num > DBSIZE ? DBSIZE : num;
-               io = (struct pte *)uba->uba_map;
-               for (i = 0; i < blk; i++)
-                       *(int *)io++ = (btop(start)+i) | UBAMR_MRV;
-               *(int *)io = 0;
-               tmscpp->tmscp_Cmd.mscp_lbn = btop(start);
-               tmscpp->tmscp_Cmd.mscp_unit = ui->ui_slave;
-               tmscpp->tmscp_Cmd.mscp_bytecnt = blk*NBPG;
-#              ifdef   MVAX
-               if( cpu == MVAX_I )
-                       tmscpp->tmscp_Cmd.mscp_buffer = (long) start;
-               else
-#              endif   MVAX
-                       tmscpp->tmscp_Cmd.mscp_buffer = 0;
-               if (tmscpcmd(M_OP_WRITE, tmscpp, tmscpaddr) == 0)
-                       return(EIO);
-               start += blk*NBPG;
-               num -= blk;
-               }
-#endif
-       return (0);
-}
-
-
-/*
- * Perform a standalone tmscp command.  This routine is only used by tmscpdump.
- */
-
-int
-tmscpcmd(op, tmscpp, tmscpaddr)
-       int op;
-       struct tmscp *tmscpp;
-       struct tmscpdevice *tmscpaddr;
-{
-       volatile int i;
-
-
-       tmscpp->tmscp_Cmd.mscp_opcode = op;
-       tmscpp->tmscp_Rsp.mscp_header.tmscp_msglen = mscp_msglen;
-       tmscpp->tmscp_Cmd.mscp_header.tmscp_msglen = mscp_msglen;
-       tmscpp->tmscp_ca.ca_Rspdsc |= TMSCP_OWN|TMSCP_INT;
-       tmscpp->tmscp_ca.ca_Cmddsc |= TMSCP_OWN|TMSCP_INT;
-       if (tmscpaddr->tmscpsa&TMSCP_ERR)
-               printf("tmscp fatal error (0%o)\n", tmscpaddr->tmscpsa&0xffff);
-       i = tmscpaddr->tmscpip;
-#ifdef lint
-       i = i;
-#endif
-       for (;;)
-               {
-               if (tmscpp->tmscp_ca.ca_cmdint)
-                       tmscpp->tmscp_ca.ca_cmdint = 0;
-               if (tmscpp->tmscp_ca.ca_rspint)
-                       break;
-               }
-       tmscpp->tmscp_ca.ca_rspint = 0;
-       if (tmscpp->tmscp_Rsp.mscp_opcode != (op|M_OP_END) ||
-           (tmscpp->tmscp_Rsp.mscp_status&M_ST_MASK) != M_ST_SUCC)
-               {
-               printf("error: com %d opc 0x%x stat 0x%x\ndump ", op,
-                       tmscpp->tmscp_Rsp.mscp_opcode, tmscpp->tmscp_Rsp.mscp_status);
-               return(0);
-               }
-       return(1);
-}
-
-/*
- * Catch ioctl commands, and call the "command" routine to do them.
- */
-
-/* ARGSUSED */
-int
-tmscpioctl(dev, cmd, data, flag, p)
-       dev_t dev;
-       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 */
-       register struct uba_device *ui;
-       register struct tms_info *tms;
-       int fcount;             /* number of files (or records) to space */
-       int error = 0;
-       register struct mtop *mtop;     /* mag tape cmd op to perform */
-       register struct mtget *mtget;   /* mag tape struct to get info in */
-
-       /* we depend of the values and order of the TMS ioctl codes here */
-       static tmsops[] =
-        {TMS_WRITM,TMS_FSF,TMS_BSF,TMS_FSR,TMS_BSR,TMS_REW,TMS_OFFL,TMS_SENSE,
-         TMS_CACHE,TMS_NOCACHE};
-
-       switch (cmd) {
-       case MTIOCTOP:  /* tape operation */
-               mtop = (struct mtop *)data;
-               switch (mtop->mt_op) {
-
-               case MTWEOF:
-                       callcount = mtop->mt_count;
-                       fcount = 1;
-                       break;
-               case MTFSF: case MTBSF:
-               case MTFSR: case MTBSR:
-                       callcount = 1;
-                       fcount = mtop->mt_count;
-                       break;
-               case MTREW: case MTOFFL: case MTNOP:
-               case MTCACHE: case MTNOCACHE:
-                       callcount = 1;
-                       fcount = 1;             /* wait for this rewind */
-                       break;
-               default:
-                       return (ENXIO);
-               }       /* end switch mtop->mt_op */
-
-               if (callcount <= 0 || fcount <= 0)
-                       return (EINVAL);
-               while (--callcount >= 0)
-                       {
-                       tmscpcommand(dev, tmsops[mtop->mt_op], fcount);
-                       if ((mtop->mt_op == MTFSR || mtop->mt_op == MTBSR) &&
-                           bp->b_resid)
-                               return (EIO);
-                       if (bp->b_flags & B_ERROR)      /* like hitting BOT */
-                               break;
-                       }
-               if (bp->b_flags&B_ERROR)
-                       if ((error = bp->b_error)==0)
-                               return (EIO);
-               return (error);
-
-       case MTIOCGET:
-               /*
-                * Return status info associated with the particular UNIT.
-                */
-               ui = tmsdinfo[TMSUNIT(dev)];
-               tms = &tms_info[ui->ui_unit];
-               mtget = (struct mtget *)data;
-               mtget->mt_type = MT_ISTMSCP;
-               mtget->mt_dsreg = tms->tms_flags << 8;
-               mtget->mt_dsreg |= tms->tms_endcode;
-               mtget->mt_erreg = tms->tms_status;
-               mtget->mt_resid = tms->tms_resid;
-               break;
-
-       default:
-               return (ENXIO);
-       }
-       return (0);
-}
-
-
-/*
- * Reset (for raw mode use only).
- */
-void
-tmscpreset (uban)
-       int uban;
-{
-       register struct uba_ctlr *um;
-       register struct uba_device *ui;
-       register struct buf *bp, *dp;
-       register int unit;
-       struct buf *nbp;
-       int d;
-
-       for (d = 0; d < NTMSCP; d++)
-               {
-               if ((um = tmscpminfo[d]) == 0 || um->um_ubanum != uban ||
-                   um->um_alive == 0)
-                       continue;
-               printf(" tmscp%d", d);
-               um->um_tab.b_active = 0;
-               um->um_tab.b_actf = 0;
-               tmscp_softc[d].sc_state = S_IDLE;
-               tmscp_softc[d].sc_mapped = 0;
-               for (unit = 0; unit < NTMS; unit++)
-                       {
-                       if ((ui = tmsdinfo[unit]) == 0)
-                               continue;
-                       if (ui->ui_alive == 0 || ui->ui_mi != um)
-                               continue;
-                       tmsutab[unit].b_active = 0;
-                       tmsutab[unit].b_qsize = 0;
-                       }
-               for (bp = tmscpwtab[d].b_actf; bp; bp = nbp)
-                       {
-                       nbp = bp->b_actf;
-                       bp->b_ubinfo = 0;
-                       /*
-                        * Link the buffer onto the drive queue
-                        */
-                       dp = &tmsutab[TMSUNIT(bp->b_dev)];
-                       MSCP_APPEND(bp, dp, b_actf);
-                       /*
-                        * Link the drive onto the controller queue
-                        */
-                       if (dp->b_active == 0)
-                               {
-                               MSCP_APPEND(dp, &um->um_tab, b_hash.le_next);
-                               dp->b_active = 1;
-                               }
-                       }
-               (void)tmscpinit(d);
-               }
-}
-
-
-/*
- * Process an error log message
- *
- * Only minimal decoding is done, only "useful"
- * information is printed.  Eventually should
- * send message to an error logger.
- */
-void
-tmserror(um, mp)
-       register struct uba_ctlr *um;
-       register struct mslg *mp;
-{
-       register i;
-
-#      ifdef DEBUG
-       printd("tmserror:\n");
-#      endif
-       if(!(mp->mslg_flags & (M_LF_SUCC | M_LF_CONT)))
-               log(TMS_PRI, "tmscp%d: %s error, ", um->um_ctlr,
-               mp->mslg_flags & ( M_LF_SUCC | M_LF_CONT ) ? "soft" : "hard");
-
-       switch (mp->mslg_format) {
-
-       case M_FM_CNTERR:
-               log(TMS_PRI, "controller error, event 0%o\n", mp->mslg_event);
-               break;
-       case M_FM_BUSADDR:
-               log(TMS_PRI, "host memory access error, event 0%o, addr 0%o\n",
-                   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",
-                       mp->mslg_unit, mp->mslg_group, mp->mslg_event);
-               break;
-       case M_FM_STIERR:
-               log(TMS_PRI, "STI error, unit %d, event 0%o\n",
-                       mp->mslg_unit, mp->mslg_event);
-#ifdef notdef
-               /* too painful to do with log() */
-               for(i = 0; i < 62;i++)
-                       mprintf("\t0x%x",mp->mslg_stiunsucc[i] & 0xff);
-               mprintf("\n");
-#endif
-               break;
-       case M_FM_STIDEL:
-               log(TMS_PRI, "STI Drive Error Log, unit %d, event 0%o\n",
-                       mp->mslg_unit, mp->mslg_event);
-               break;
-       case M_FM_STIFEL:
-               log(TMS_PRI, "STI Formatter Error Log, unit %d, event 0%o\n",
-                       mp->mslg_unit, mp->mslg_event);
-               break;
-       default:
-               log(TMS_PRI, "unknown error, unit %d, format 0%o, event 0%o\n",
-                       mp->mslg_unit, mp->mslg_format, mp->mslg_event);
-       }
-
-       if (tmscperror)
-               {
-               register long *p = (long *)mp;
-
-               for (i = 0; i < mp->mslg_header.tmscp_msglen; i += sizeof(*p))
-                       printf("%x ", (unsigned int)*p++);
-               printf("\n");
-               }
-}
-
-int
-tmscp_match(parent, match, aux)
-        struct device *parent;
-        void *match, *aux;
-{
-        return 0;
-}
-
-void
-tmscp_attach(parent, self, aux)
-        struct device *parent, *self;
-        void *aux;
-{
-}
-
-#endif
diff --git a/sys/arch/vax/uba/tmscpreg.h b/sys/arch/vax/uba/tmscpreg.h
deleted file mode 100644 (file)
index de806fc..0000000
+++ /dev/null
@@ -1,120 +0,0 @@
-/*     $NetBSD: tmscpreg.h,v 1.1 1995/02/23 17:53:19 ragge Exp $ */
-
-/*-
- * Copyright (c) 1991 The Regents of the University of California.
- * 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.
- *
- *     @(#)tmscpreg.h  7.2 (Berkeley) 5/9/91
- */
-
-/*     @(#)tmscpreg.h  1.1     11/2/84 84/09/25        */
-
-/****************************************************************
- *                                                             *
- *        Licensed from Digital Equipment Corporation          *
- *                       Copyright (c)                                 *
- *               Digital Equipment Corporation                 *
- *                   Maynard, Massachusetts                    *
- *                         1985, 1986                          *
- *                    All rights reserved.                     *
- *                                                             *
- *        The Information in this software is subject to change *
- *   without notice and should not be construed as a commitment *
- *   by  Digital  Equipment  Corporation.   Digital   makes  no *
- *   representations about the suitability of this software for *
- *   any purpose.  It is supplied "As Is" without expressed  or *
- *   implied  warranty.                                        *
- *                                                             *
- *        If the Regents of the University of California or its *
- *   licensees modify the software in a manner creating        *
- *   diriviative copyright rights, appropriate copyright       *
- *   legends may be placed on  the drivative work in addition   *
- *   to that set forth above.                                  *
- *                                                             *
- ****************************************************************/
-/*
- * TMSCP registers and structures
- */
-#ifndef _UBA_TMSCPREG_
-#define _UBA_TMSCPREG_
-struct tmscpdevice {
-       short   tmscpip;        /* initialization and polling */
-       short   tmscpsa;        /* status and address */
-};
-#define        TMSCP_ERR               0100000 /* error bit */
-#define        TMSCP_STEP4     0040000 /* step 4 has started */
-#define        TMSCP_STEP3     0020000 /* step 3 has started */
-#define        TMSCP_STEP2     0010000 /* step 2 has started */
-#define        TMSCP_STEP1     0004000 /* step 1 has started */
-#define        TMSCP_NV                0002000 /* no host settable interrupt vector */
-#define        TMSCP_QB                0001000 /* controller supports Q22 bus */
-#define        TMSCP_DI                0000400 /* controller implements diagnostics */
-#define        TMSCP_OD                0000200 /* port allows odd host addr's in the buffer descriptor */
-#define        TMSCP_IE                0000200 /* interrupt enable */
-#define        TMSCP_MP                0000100 /* port supports address mapping */
-#define        TMSCP_LF                0000002 /* host requests last fail response packet */
-#define        TMSCP_PI                0000001 /* host requests adapter purge interrupts */
-#define        TMSCP_GO                0000001 /* start operation, after init */
-/*
- * TMSCP Communications Area
- */
-struct tmscpca {
-       short   ca_xxx1;        /* unused */
-       char    ca_xxx2;        /* unused */
-       char    ca_bdp;         /* BDP to purge */
-       short   ca_cmdint;      /* command queue transition interrupt flag */
-       short   ca_rspint;      /* response queue transition interrupt flag */
-       long    ca_rspdsc[NRSP];/* response descriptors */
-       long    ca_cmddsc[NCMD];/* command descriptors */
-};
-#define        ca_ringbase     ca_rspdsc[0]
-#define        TMSCP_OWN       0x80000000      /* port owns this descriptor (else host
- owns it) */
-#define        TMSCP_INT       0x40000000      /* allow interrupt on ring transition */
-#define        TMSCP_MAP       0x80000000      /* modifier for mapped buffer descriptors */
-/*
- * TMSCP packet info (same as MSCP)
- */
-struct mscp_header {
-       short   tmscp_msglen;   /* length of MSCP packet */
-       char    tmscp_credits;  /* low 4 bits: credits, high 4 bits: msgtype */
-       char    tmscp_vcid;     /* virtual circuit id (connection id) */
-};
-#endif
index c2bb299..cdb14f6 100644 (file)
@@ -1,4 +1,4 @@
-/*      $NetBSD: ts.c,v 1.6 1996/04/08 18:37:32 ragge Exp $ */
+/*     $NetBSD: ts.c,v 1.11 1997/01/11 11:34:43 ragge Exp $ */
 
 /*-
  * Copyright (c) 1991 The Regents of the University of California.
@@ -14,8 +14,8 @@
  *    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.
+ *     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.
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- *      @(#)tmscp.c     7.16 (Berkeley) 5/9/91
+ *     @(#)tmscp.c     7.16 (Berkeley) 5/9/91
  */
 
 /*
- * sccsid = "@(#)tmscp.c        1.24    (ULTRIX)        1/21/86";
+ * sccsid = "@(#)tmscp.c       1.24    (ULTRIX)        1/21/86";
  */
 
 /************************************************************************
- *                                                                      *
- *        Licensed from Digital Equipment Corporation                   *
- *                       Copyright (c)                                  *
- *               Digital Equipment Corporation                          *
- *                   Maynard, Massachusetts                             *
- *                         1985, 1986                                   *
- *                    All rights reserved.                              *
- *                                                                      *
- *        The Information in this software is subject to change         *
- *   without notice and should not be construed as a commitment         *
- *   by  Digital  Equipment  Corporation.   Digital   makes  no         *
- *   representations about the suitability of this software for         *
- *   any purpose.  It is supplied "As Is" without expressed  or         *
- *   implied  warranty.                                                 *
- *                                                                      *
- *        If the Regents of the University of California or its         *
- *   licensees modify the software in a manner creating                 *
- *   diriviative copyright rights, appropriate copyright                *
- *   legends may be placed on  the drivative work in addition           *
- *   to that set forth above.                                           *
- *                                                                      *
+ *                                                                     *
+ *       Licensed from Digital Equipment Corporation                   *
+ *                      Copyright (c)                                  *
+ *              Digital Equipment Corporation                          *
+ *                  Maynard, Massachusetts                             *
+ *                        1985, 1986                                   *
+ *                   All rights reserved.                              *
+ *                                                                     *
+ *       The Information in this software is subject to change         *
+ *   without notice and should not be construed as a commitment                *
+ *   by         Digital  Equipment  Corporation.   Digital   makes  no         *
+ *   representations about the suitability of this software for                *
+ *   any purpose.  It is supplied "As Is" without expressed  or                *
+ *   implied  warranty.                                                        *
+ *                                                                     *
+ *       If the Regents of the University of California or its         *
+ *   licensees modify the software in a manner creating                        *
+ *   diriviative copyright rights, appropriate copyright               *
+ *   legends may be placed on  the drivative work in addition          *
+ *   to that set forth above.                                          *
+ *                                                                     *
  ************************************************************************/
 
 /*
  * should be TS11 compatible (untested)
  */
 
-#define NCMD   1
-#define NMSG   1
-
-#if 0
-# define DEBUG
-# define TRACE
-#else
-# undef  DEBUG
-# undef  TRACE
-#endif
-
 #define TS11_COMPAT    /* don't use extended features provided by TS05 */
 
-#ifdef  NEED_18BIT
+#ifdef NEED_18BIT
 #define TS_UBAFLAGS    UBA_NEED16
 #else
 #define TS_UBAFLAGS    0
 #define ENABLE_END
 
 #define ENABLE_EAI     /* enable Attention-Interrupts */
-#undef  ENABLE_EAI
+#undef ENABLE_EAI
 
 #define ENABLE_ERI     /* Enable Release Buffer Interrupts */
-#undef  ENABLE_ERI
+#undef ENABLE_ERI
 
 #ifdef DEBUG
 int tsdebug = 1;
@@ -129,11 +118,6 @@ int tstrace = 1;
  */
 
 
-#include "ts.h"
-
-#if NTS > 0
-
-
 #include <sys/param.h>
 #include <sys/systm.h>
 #include <sys/kernel.h>
@@ -147,7 +131,6 @@ int tstrace = 1;
 #include <sys/mtio.h>
 #include <sys/uio.h>
 #include <sys/proc.h>
-#include <sys/tprintf.h>
 
 #include <machine/pte.h>
 #include <machine/sid.h>
@@ -159,24 +142,14 @@ int tstrace = 1;
 
 #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 ts_cd = {
-       NULL, "ts", DV_DULL
-};
-
-struct cfattach ts_ca = {
-       sizeof(struct device), ts_match, ts_attach
-};
+#include "ts.h"
 
 /*
  * ts command packets and communication area (per controller)
  */
-struct         ts {
+struct ts {
        struct  tsdevice *reg;          /* address of i/o-registers */
-       struct  tscmd     cmd;          /* command packet(s) */
+       struct  tscmd     cmd;          /* command packet(s) */
        struct  tsmsg     msg;          /* message packet(s) */
 } ts[NTS];
 
@@ -186,37 +159,38 @@ struct    ts {
  * (thus we have no struct ts_info)
  */
 struct ts_softc {
-       struct  ts *sc_ts;      /* Unibus address of uda struct */
-        short   sc_mapped;             /* Unibus map allocated ? */
-        int     sc_ubainfo;            /* Unibus mapping info */
-       short   sc_state;               /* see below: ST_xxx */
-       short   sc_flags;               /* see below: FL_xxx */
+       struct  device sc_dev;          /* Autoconf ... */
+       struct  uba_unit sc_unit;       /* Struct common for UBA to talk */
+       struct  ts *sc_ts;              /* Unibus address of uda struct */
+       short   sc_mapped;              /* Unibus map allocated ? */
+       int     sc_ubainfo;             /* Unibus mapping info */
+       short   sc_state;               /* see below: ST_xxx */
+       short   sc_flags;               /* see below: FL_xxx */
        short   sc_lcmd;                /* last command word */
        short   sc_rtc;                 /* retry count for lcmd */
        short   sc_lssr;                /* last status register */
        short   sc_lmsgh;               /* last message header */
        short   sc_lxst0;               /* last status word */
        short   sc_cmdf;                /* command flags (ack,cvc,ie) */
-       short   sc_openf;               /* lock against multiple opens */
+       short   sc_openf;               /* lock against multiple opens */
        short   sc_liowf;               /* last operation was write */
-       int     sc_micro;               /* microcode revision */
-       int     sc_ivec;                /* interrupt vector address */
-       short   sc_ipl;                 /* interrupt priority, Q-bus */
-       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 *));
+       int     sc_micro;               /* microcode revision */
+       int     sc_ivec;                /* interrupt vector address */
+       short   sc_ipl;                 /* interrupt priority, Q-bus */
+};
+
 void   tsintr __P((int));
-int    tsinit __P((int));
+int    tsinit __P((struct ts_softc *));
 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    tsstart __P((struct ts_softc *, struct buf *));
 int    tswchar __P((int));
 void   tsreset __P((int));
 void   tsxstatus __P((struct tsmsg *));
+int    tsmatch __P((struct device *, void *, void *));
+void   tsattach __P((struct device *, struct device *, void *));
+void   tsstrategy __P((struct buf *));
 
 int    tsopen __P((dev_t, int, int, struct proc *));
 int    tsclose __P((dev_t, int, int, struct proc *));
@@ -225,37 +199,30 @@ 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));
 
+struct cfdriver ts_cd = {
+       NULL, "ts", DV_DULL
+};
+
+struct cfattach ts_ca = {
+       sizeof(struct ts_softc), tsmatch, tsattach
+};
+
 
 #define ST_INVALID     0       /* uninitialized, before probe */
 #define ST_PROBE       1       /* during tsprobe(), not used */
 #define ST_SLAVE       2       /* in tsslave(), init almost complete */
 #define ST_ATTACH      3       /* during tsattach(), not used */
-#define ST_INITIALIZED  4      /* init completed, set by tsintr() */
+#define ST_INITIALIZED       /* init completed, set by tsintr() */
 #define ST_RUNNING     5
 #define ST_IDLE                6
 #define ST_BUSY                7
 
 /* Bits in minor device */ 
 #define TS_UNIT(dev)   (minor(dev)&03)
-#define TS_CTLR(dev)   (TS_UNIT(dev))
 #define TS_HIDENSITY   010
 
-#define TS_PRI  LOG_INFO
-
-/*
- * Definition of the driver for autoconf.
- */
-#define CTLRNAME  "zs"         /* ts/zs ??? */
-#define UNITNAME  "ts"
-
-struct  uba_ctlr       *zsinfo[NTS];           /* controller-info */
-struct  uba_device     *tsinfo[NTS];           /* unit(tape)-info */
+#define TS_PRI LOG_INFO
 
-u_short tsstd[] = { 0172520, 0172524,          /* standart csr for ts */
-                   0172530, 0172534, 0 };      /* standart csr for ts */
-
-struct  uba_driver tsdriver = { tsprobe, tsslave, tsattach, 0, tsstd, 
-                               UNITNAME, tsinfo, CTLRNAME, zsinfo, 0 };
 
 /*
  * Since we don't have credits and thus only one operation per time,
@@ -274,30 +241,25 @@ struct buf        *ts_wtab[NTS];          /* dummy I/O wait queue */
  * initialize data structures, what else ???
  */
 int 
-tsinit (unit)
-       int unit;
+tsinit (sc)
+       struct ts_softc *sc;
 {
-       register struct ts_softc *sc;
        volatile struct tsdevice *tsregs;
-       struct uba_ctlr *um;
+       int unit = sc->sc_dev.dv_unit;
+       struct uba_unit *uu;
        
-       trace (("tsinit: unit = %d\n", unit));
-
-       sc = &ts_softc[unit];
-       um = zsinfo[unit];
-       um->um_tab.b_active++;                  /* ??? */
-       tsregs = (struct tsdevice *)um->um_addr;
+       uu = &sc->sc_unit;
+       tsregs = (struct tsdevice *)ts[unit].reg;
        if (sc->sc_mapped == 0) {
                /*
                 * Map the communications area and command and message
                 * buffer into Unibus address space.
                 */
-               sc->sc_ubainfo = uballoc (um->um_ubanum, (caddr_t)&ts[unit],
-                       sizeof (struct ts), TS_UBAFLAGS);
+               sc->sc_ubainfo = uballoc((struct uba_softc *)
+                   sc->sc_dev.dv_parent,
+                   (caddr_t)&ts[unit], sizeof (struct ts), TS_UBAFLAGS);
                sc->sc_ts = (struct ts *)(UBAI_ADDR(sc->sc_ubainfo));
                sc->sc_mapped = 1;
-               debug (("sc_mapped: %d [%x, %x]\n", sc->sc_mapped,
-                       sc->sc_ubainfo, sc->sc_ts));
        }
 
        /*
@@ -320,7 +282,7 @@ tsexec (ctlr, cmd)
        int ctlr;
        int cmd;
 {
-       register struct ts_softc *sc = &ts_softc[ctlr];
+       register struct ts_softc *sc = ts_cd.cd_devs[ctlr];
        register struct tscmd *tscmdp = &ts[ctlr].cmd;
        register long tscmdma = (long)&sc->sc_ts->cmd;  /* mapped address */
        volatile struct tsdevice *tsreg = ts[ctlr].reg;
@@ -349,13 +311,12 @@ tsexec (ctlr, cmd)
        case TS_CMD_STAT:       cmdName = "Get Status (END)";           break;
        default:                cmdName = "unexptected Command";        break;
        }
-       debug (("tsexec: cmd = 0x%x (%s)\n", tscmdp->cmdr, cmdName));
 #endif
 
        sr = tsreg->tssr;
        if ((sr & TS_SSR) == 0) {       /* subsystem NOT ready */
                printf ("%s%d: subsystem not ready [%x]\n", 
-                       CTLRNAME, ctlr, sr);
+                   sc->sc_dev.dv_xname, sr);
                return (-1);
        }
        dbx = ((char*)tsreg) + 3;       /* dbx is located at the fourth byte */
@@ -375,7 +336,7 @@ tsexec (ctlr, cmd)
         * wait for SSR or RMR to show up
         */
        sr = tsreg->tssr;
-       if ((sr & TS_SSR) != 0) {       /* something went wrong .. */
+       if ((sr & TS_SSR) != 0) {       /* something went wrong .. */
                if (sr & TS_RMR) {
                        printf ("ts: error writing TSDB (RMR)\n");
                        return (-1);
@@ -404,15 +365,14 @@ tscommand (dev, cmd, count)
        int count;
 {
        register struct buf *bp;
-       register int s;  
+       register int s;  
 
        trace (("tscommand (%d, %x, %d)\n", TS_UNIT(dev), cmd, count));
 
        s = splbio();
        bp = &ts_cbuf[TS_UNIT(dev)];
-#if 1
+
        while (bp->b_flags & B_BUSY) {
-               debug (("looping 'cause B_BUSY\n"));
                /*
                 * This special check is because B_BUSY never
                 * gets cleared in the non-waiting rewind case. ???
@@ -420,12 +380,11 @@ tscommand (dev, cmd, count)
                if (bp->b_bcount == 0 && (bp->b_flags & B_DONE))
                        break;
                bp->b_flags |= B_WANTED;
-               debug (("sleeping ...\n"));;
                sleep ((caddr_t)bp, PRIBIO);
                /* check MOT-flag !!! */
        }
        bp->b_flags = B_BUSY | B_READ;
-#endif
+
        splx(s);
 
        /*
@@ -438,7 +397,6 @@ tscommand (dev, cmd, count)
        bp->b_bcount = count;
        bp->b_resid = cmd;
        bp->b_blkno = 0;
-       debug (("tscommand: calling tsstrategy ...\n"));
        tsstrategy (bp);
        /*
         * In case of rewind from close, don't wait.
@@ -459,42 +417,34 @@ tscommand (dev, cmd, count)
  * Start an I/O operation on TS05 controller
  */
 int
-tsstart (um, bp)
-       register struct uba_ctlr *um;
+tsstart (sc, bp)
+       register struct ts_softc *sc;
        register struct buf *bp;
 {
-       register struct ts_softc *sc = &ts_softc[um->um_ctlr];
-       volatile struct tsdevice *tsreg = ts[um->um_ctlr].reg;
-       register struct tscmd *tscmdp = &ts[um->um_ctlr].cmd;
+       int ctlr = sc->sc_dev.dv_unit;
+       volatile struct tsdevice *tsreg = ts[ctlr].reg;
+       register struct tscmd *tscmdp = &ts[ctlr].cmd;
        register struct buf *dp;
        volatile int i, itmp;
-       int unit;
        int ioctl;
        int cmd;
 
-       unit = um->um_ctlr;
-       trace (("tsstart (unit = %d)\n", unit));
-       sc = &ts_softc[unit];
-
-       if ((dp = ts_wtab[unit]) != NULL) {
+       if ((dp = ts_wtab[ctlr]) != NULL) {
                /*
                 * There's already a command pending ...
                 * Either we are called by tsintr or we have missed
                 * something important (race condition).
                 */
-               debug (("tsstart: I/O queue not empty.\n"));
 
                /* bertram: ubarelse ??? */
-               ts_wtab[um->um_ctlr] = NULL;
+               ts_wtab[ctlr] = NULL;
                dp->b_flags |= B_ERROR;
                iodone (dp);
 
                if (tsreg->tssr & TS_SC) {      /* Special Condition; Error */
-                       tprintf (sc->sc_tpr, "%s%d: error at bn%d\n",
-                               UNITNAME, unit, dp->b_blkno);
-                       log (TS_PRI, "%s%d: tssr 0x%x, state %d\n",
-                               CTLRNAME, unit, tsreg->tssr, sc->sc_state);
-                       tsinit (unit);
+                       log (TS_PRI, "%s: tssr 0x%x, state %d\n",
+                               sc->sc_dev.dv_xname, tsreg->tssr, sc->sc_state);
+                       tsinit (sc);
                        return (-1);
                }
                /* XXX */
@@ -505,47 +455,43 @@ tsstart (um, bp)
         * If it's an ioctl then just set the flags for later use;
         * For other commands attempt to setup a buffer pointer.
         */
-       if (bp == &ts_cbuf[um->um_ctlr]) {
+       if (bp == &ts_cbuf[ctlr]) {
                ioctl = 1;
-               debug (("tsstart(ioctl): unit %d\n", um->um_ctlr));
        } else {
                ioctl = 0;
-               debug (("tsstart(rw): unit %d\n", um->um_ctlr));
 
                /*
                 * now we try to map the buffer into uba map space (???)
                 */
                i = TS_UBAFLAGS;
-               switch (cpunumber) {
+               switch (vax_cputype) {
                case VAX_8600:
                case VAX_780:
                        i |= UBA_CANTWAIT;
                        break;
                case VAX_750:
-                       i |= um->um_ubinfo | UBA_CANTWAIT;
+                       i |= sc->sc_unit.uu_ubinfo | UBA_CANTWAIT;
                        break;
                case VAX_730:
                case VAX_78032:
                        i |= UBA_CANTWAIT;
                        break;
                default:
-                       printf ("unsupported cpu %d in tsstart.\n", cpunumber);
-               } /* end switch (cpunumber) */
+                       printf ("unsupported cpu %d in tsstart.\n", vax_cputype);
+               } /* end switch (vax_cputype) */
 
-               debug (("ubasetup (%x, %x, %x)\n", um->um_ubanum, bp, i));
-               if ((i = ubasetup (um->um_ubanum, bp, i)) == 0) {
+               if ((i = ubasetup(sc->sc_dev.dv_parent->dv_unit, bp, i)) == 0) {
                        /*
                         * For some reasons which I don't (yet? :) understand,
                         * tmscp.c initiates in this situation a GET-UNIT
                         * command. (Because no data-buffers are neccess. ??)
                         */
-                       debug (("tsstart: %d, ubasetup = 0\n", um->um_ctlr));
                        cmd = TS_CMD_STAT;
                        goto do_cmd;
                        return (-1);    /* ??? */
                }
 #if defined(VAX750)
-               if (cpunumber == VAX_750)
+               if (vax_cputype == VAX_750)
                        itmp = i & 0xfffffff;           /* mask off bdp */
                else
 #endif
@@ -553,7 +499,6 @@ tsstart (um, bp)
 
                /* XXX */
        }
-       debug (("ubasetup done. [%x, %x, %d]\n", i, itmp, ioctl));
 
        /*
         * If it's an ioctl command, then assemble the command.
@@ -561,7 +506,6 @@ tsstart (um, bp)
         * in <sys/mtio.h>
         */
        if (ioctl) {
-               debug (("tsstart: doing ioctl %d\n", bp->b_resid));
                switch ((int)bp->b_resid) {
                case MTWEOF:
                        cmd = TS_CMD_WTM;
@@ -597,24 +541,20 @@ tsstart (um, bp)
                        cmd = TS_CMD_STAT;
                        break;
                default:
-                       printf ("%s%d: bad ioctl %d\n", 
-                               CTLRNAME, unit, (int)bp->b_resid);
+                       printf ("%s: bad ioctl %d\n", sc->sc_dev.dv_xname,
+                               (int)bp->b_resid);
                        /* Need a no-op. get status */
                        cmd = TS_CMD_STAT;
                } /* end switch (bp->b_resid) */
        } else {        /* Its a read/write command (not an ioctl) */ 
-               debug (("tsstart: non-ioctl [%x, %xi, %x]\n", 
-                       tscmdp, UBAI_ADDR(i), bp));
                tscmdp->cw1 = UBAI_ADDR(i) & 0xffff;
                tscmdp->cw2 = (UBAI_ADDR(i) >> 16) & 0x3f;
                tscmdp->cw3 = bp->b_bcount;
 
                if (bp->b_flags & B_READ) {
-                       debug (("read-command(%d)\n", tscmdp->cw3));
                        cmd = TS_CMD_RNF;
                }
                else {
-                       debug (("write-command(%d)\n", tscmdp->cw3));
                        cmd = TS_CMD_WD;
                }
                bp->b_ubinfo = itmp;                    /* save mapping info */
@@ -623,22 +563,20 @@ tsstart (um, bp)
        /*
         * Move buffer to I/O wait pseudo-queue
         */
-       if (ts_wtab[um->um_ctlr]) {
+       if (ts_wtab[ctlr]) {
                /*
                 * we are already waiting for something ...
                 * this should not happen, so we have a problem now.
                 * bertram: set error-flag and call iodone() ???
                 */
-               debug (("tsstart: already waiting for something ...\n"));
        }
-       ts_wtab[um->um_ctlr] = bp;
+       ts_wtab[ctlr] = bp;
 
        /*
         * Now that the command-buffer is setup, give it to the controller
         */
 do_cmd:
-       debug (("tsstart: calling tsexec(%d, %d)\n", unit, cmd));
-       return (tsexec (unit, cmd));
+       return (tsexec(ctlr, cmd));
 }
 
 /*
@@ -650,6 +588,7 @@ int
 tswchar (ctlr)
        int ctlr;
 {
+       struct ts_softc *sc = ts_cd.cd_devs[ctlr];
        volatile struct tsdevice *tsregs = ts[ctlr].reg;
        volatile struct tscmd *tscmdp = &ts[ctlr].cmd;
        volatile struct tsmsg *tsmsgp = &ts[ctlr].msg;
@@ -658,17 +597,17 @@ tswchar (ctlr)
        /*
         * assemble and send "WRITE CHARACTERISTICS" command
         */
-        ma = (long)tsmsgp;
-        if (ma & 0x7FC00001) { /* address must be even and 22-bit */
-                printf ("invalid address 0x%0x for msg-buffer.\n", ma);
-                return (-1);
-        }
-
-        tsmsgp->hdr = ma & 0xFFFF;             /* low order addr. bits */
-        tsmsgp->dfl = (ma >> 16) & 0x003F;     /* high order addr. bits */
-        tsmsgp->rbpcr = 16;                    /* size of message-buffer */
-        tsmsgp->xst0 = 0;                      /* chacacteristics mode word */
-        tsmsgp->xst1 = 0;                      /* control word (ext.feat.) */
+       ma = (long)tsmsgp;
+       if (ma & 0x7FC00001) {  /* address must be even and 22-bit */
+               printf ("invalid address 0x%0x for msg-buffer.\n", ma);
+               return (-1);
+       }
+
+       tsmsgp->hdr = ma & 0xFFFF;              /* low order addr. bits */
+       tsmsgp->dfl = (ma >> 16) & 0x003F;      /* high order addr. bits */
+       tsmsgp->rbpcr = 16;                     /* size of message-buffer */
+       tsmsgp->xst0 = 0;                       /* chacacteristics mode word */
+       tsmsgp->xst1 = 0;                       /* control word (ext.feat.) */
 
 #ifdef TS11_COMPAT
        tsmsgp->rbpcr = 14;             /* size of message-buffer */
@@ -695,29 +634,29 @@ tswchar (ctlr)
 #endif
 #endif
 
-        tscmdp->cmdr = TS_CF_ACK | TS_CF_IE | TS_CMD_WCHAR;    /* obsolete */
-        tscmdp->cw1  = ma & 0xFFFF;
-        tscmdp->cw2  = (ma >> 16) & 0x003F;
-        tscmdp->cw3  = 10;                 /* size of charact.-data */
+       tscmdp->cmdr = TS_CF_ACK | TS_CF_IE | TS_CMD_WCHAR;     /* obsolete */
+       tscmdp->cw1  = ma & 0xFFFF;
+       tscmdp->cw2  = (ma >> 16) & 0x003F;
+       tscmdp->cw3  = 10;                 /* size of charact.-data */
 
-        if (tsexec (ctlr, TS_CMD_WCHAR) < 0) {
-               printf ("%s%d: write characteristics command failed [%x]\n",
-                       CTLRNAME, ctlr, tsregs->tssr);
-                return (-1);
+       if (tsexec (ctlr, TS_CMD_WCHAR) < 0) {
+               printf ("%s: write characteristics command failed [%x]\n",
+                   sc->sc_dev.dv_xname, tsregs->tssr);
+               return (-1);
        }
 
-        timeout = 1000;                /* timeout in 10 seconds */
-        do {
+       timeout = 1000;                /* timeout in 10 seconds */
+       do {
                DELAY(10000);
-                sr = tsregs->tssr;
-                debug10 (("\ttssr: 0x%x\n", sr));
-                if (timeout-- > 0) {
-                        printf ("timeout during initialize.");
-                        tsstatus (sr);
-                        return (-1);
-                }
-        } while ((sr & TS_SSR) == 0);
-        tsstatus (sr);
+               sr = tsregs->tssr;
+               debug10 (("\ttssr: 0x%x\n", sr));
+               if (timeout-- > 0) {
+                       printf ("timeout during initialize.");
+                       tsstatus (sr);
+                       return (-1);
+               }
+       } while ((sr & TS_SSR) == 0);
+       tsstatus (sr);
 
        return (0);
 }
@@ -729,101 +668,95 @@ void
 tsreset(ctlr) 
        int ctlr;
 {
+       struct ts_softc *sc = ts_cd.cd_devs[ctlr];
        volatile struct tsdevice *tsreg = ts[ctlr].reg;
        volatile unsigned int sr, timeout;
 
-       trace (("tsreset (%d)\n", ctlr));
-
        /*
         * reset ctlr by writing into TSSR, then write characteristics
         */
-        timeout = 1000;                /* timeout in 10 seconds */     
-        tsreg->tssr = 0;                       /* start initialization */
-        do {
+       timeout = 1000;         /* timeout in 10 seconds */     
+       tsreg->tssr = 0;                        /* start initialization */
+       do {
                DELAY(10000);
-                sr = tsreg->tssr;
-                debug10 (("\ttssr: 0x%x\n", sr));
-                if (timeout-- > 0) {
-                        if (sr != 0)
-                                printf ("%s%d: timeout waiting for TS_SSR\n",
-                                        CTLRNAME, ctlr);
-                        tsstatus (sr);
+               sr = tsreg->tssr;
+               debug10 (("\ttssr: 0x%x\n", sr));
+               if (timeout-- > 0) {
+                       if (sr != 0)
+                               printf ("%s: timeout waiting for TS_SSR\n",
+                                       sc->sc_dev.dv_xname);
+                       tsstatus (sr);
                        return;
-                }
-        } while ((sr & TS_SSR) == 0);   /* wait until subsystem ready */
-        tsstatus (sr);
+               }
+       } while ((sr & TS_SSR) == 0);   /* wait until subsystem ready */
+       tsstatus (sr);
 
        return;
 }
 
-extern struct cfdriver uba_cd;
 /*
  * probe for device. If found, try to raise an interrupt.
+ * XXX - most of this should be done in the attach routine.
  */
-int 
-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;
+int
+tsmatch(parent, match, aux)
+       struct  device *parent;
+       void    *match, *aux;
 {
-       register struct ts_softc *sc;
-       register struct tsdevice *tsregs = (struct tsdevice*) reg;
+       struct ts_softc *sc = match;
+       struct uba_softc *uh = (void *)parent;
+       struct uba_attach_args *ua = aux;
+       struct tsdevice *tsregs = (struct tsdevice*)ua->ua_addr;
        volatile unsigned int sr, timeout, count;
-       struct uba_softc *ubasc;
-
-       trace (("tsprobe (%x, %d, %x)\n", reg, ctlr, um));
+       int ctlr = sc->sc_dev.dv_unit;
 
        ts_wtab[ctlr] = NULL;
-       sc = &ts_softc[ctlr];
        sc->sc_ts = &ts[ctlr];
        sc->sc_state = ST_PROBE;
        sc->sc_flags = 0;
-       zsinfo[ctlr] = um;
-       ts[ctlr].reg = (struct tsdevice*) reg;
+       ts[ctlr].reg = (struct tsdevice*)ua->ua_addr;
 
        /*
-         * Set host-settable interrupt vector.
-         * Assign 0 to the TSSR register to start the ts-device initialization.
-         * The device is not really initialized at this point, this is just to
-         * find out if the device exists. 
-         */
-       ubasc = uba_cd.cd_devs[0]; /* XXX */
-        sc->sc_ivec = (ubasc->uh_lastiv -= 4);
+        * Set host-settable interrupt vector.
+        * Assign 0 to the TSSR register to start the ts-device initialization.
+        * The device is not really initialized at this point, this is just to
+        * find out if the device exists. 
+        */
+       sc->sc_ivec = (uh->uh_lastiv -= 4);
 
        count = 0;
 again:
        timeout = 1000;         /* timeout in 10 seconds */     
-        tsregs->tssr = 0;                      /* start initialization */
+       tsregs->tssr = 0;                       /* start initialization */
        do {
                DELAY(10000);
                sr = tsregs->tssr;
                debug10 (("\ttssr-1: 0x%x\n", sr));
                if (timeout-- > 0) {
                        if (sr != 0)    /* the device exists !!! */
-                               printf ("%s%d: timeout waiting for TS_SSR\n",
-                                       CTLRNAME, ctlr);
+                               printf ("%s: timeout waiting for TS_SSR\n",
+                                       sc->sc_dev.dv_xname);
                        tsstatus (sr);
                        goto bad;
                }
        } while ((sr & TS_SSR) == 0);   /* wait until subsystem ready */
        tsstatus (sr);
 
-       tswchar (ctlr);         /* write charact. to enable interrupts */
+       tswchar (ctlr);         /* write charact. to enable interrupts */
                                /* completion of this will raise the intr. */
 
 #ifdef notyet
-        sc->sc_ipl = br = qbgetpri();
+       sc->sc_ipl = br = qbgetpri();
 #else
-        sc->sc_ipl = 0x15;
+       sc->sc_ipl = 0x15;
 #endif
-        return (sizeof (struct tsdevice));
+       return (sizeof (struct tsdevice));
 
 bad:   if (++count < 3)
                goto again;
 
 #ifdef notyet
-        splx(s);
+       splx(s);
 #endif
        return (0);
 }
@@ -834,14 +767,14 @@ bad:      if (++count < 3)
  * Since there's only one drive per controller there's nothing to do.
  * (we could check the status of the drive (online/offline/...)
  */
-int
-tsslave (ui, reg)
-       struct uba_device *ui;  /* ptr to the uba device structure */
-        caddr_t reg;            /* addr of the device controller */
+void
+tsattach(parent, self, aux)
+       struct device *parent, *self;
+       void *aux;
 {
-       register int ctlr = ui->ui_ctlr;
-       register struct ts_softc *sc = &ts_softc[ctlr];
-       register struct tsmsg *tsmsgp = &ts[ctlr].msg;
+       struct ts_softc *sc = (void *)self;
+       int ctlr = sc->sc_dev.dv_unit;
+       struct tsmsg *tsmsgp = &ts[ctlr].msg;
 
        trace (("tsslave (%x, %x)\n", ui, reg));
        
@@ -852,34 +785,18 @@ tsslave (ui, reg)
         */
        sc->sc_state = ST_SLAVE;        /* tsintr() checks this ... */
        if (tswchar (ctlr) < 0) {
-               printf ("%s%d: cannot initialize", CTLRNAME, ctlr);
-               return (0);             /* ??? XXX ??? */
+               printf ("%s: cannot initialize", sc->sc_dev.dv_xname);
        }
        sc->sc_micro = (tsmsgp->xst2 & TS_SF_MCRL) >> 2;
-       printf ("%s%d: rev %d, extended features %s, transport %s\n",
-               CTLRNAME, ctlr, sc->sc_micro,
+       printf ("%s: rev %d, extended features %s, transport %s\n",
+               sc->sc_dev.dv_xname, sc->sc_micro,
                (tsmsgp->xst2 & TS_SF_EFES ? "enabled" : "disabled"),
                (ts[ctlr].reg->tssr & TS_OFL ? "offline" : "online"));
 
-       tsinit (ctlr);          /* must be called once, why not here ? */
-
-       return (1);
+       tsinit (sc);            /* must be called once, why not here ? */
 }
 
 
-/*
- * Open routine will issue the online command, later.
- * Just reset the flags and do nothing ...
- */
-void
-tsattach (ui)
-       struct uba_device *ui;
-{
-       trace (("\ntsattach (%x)", ui));
-       ui->ui_flags = 0;       /* mark unit offline */
-}      
-
-
 /*
  * TSV05/TS05 interrupt routine
  */
@@ -887,11 +804,11 @@ void
 tsintr(ctlr)
        int ctlr;
 {
-       register struct ts_softc *sc = &ts_softc[ctlr];
+       register struct ts_softc *sc = ts_cd.cd_devs[ctlr];
        register struct tsmsg *tsmsgp = &ts[ctlr].msg;
        register struct tscmd *tscmdp = &ts[ctlr].cmd;
        volatile struct tsdevice *tsreg = ts[ctlr].reg;
-       struct uba_ctlr *um = zsinfo[ctlr];
+       struct uba_unit *um = &sc->sc_unit;
        register struct buf *bp;
 
        unsigned short sr = tsreg->tssr;        /* save TSSR */
@@ -902,12 +819,16 @@ tsintr(ctlr)
        short cmask = tscmdp->cmdr & TS_CF_CMASK;
 
 #ifdef DEBUG
-       printf ("TSSR: %b, MSG: %x ", sr, TS_TSSR_BITS, mh);
+       {
+               char bits[64];
+               printf ("TSSR: %s, MSG: %x ", bitmask_snprintf(sr,
+                   TS_TSSR_BITS, bits, sizeof(bits)), mh);
+       }
        switch (tsmsgp->hdr & 0x001F) {
        case 16:        printf ("(End)");       break;
        case 17:        printf ("(Fail)");      break;
        case 18:        printf ("(Error)");     break;
-       case 19:        printf ("(Attention)"); break;
+       case 19:        printf ("(Attention)"); break;
        }
 #endif
 
@@ -917,8 +838,8 @@ tsintr(ctlr)
                sc->sc_cmdf |= TS_CF_CVC;
 
 #ifdef QBA                             /* copied from uda.c */
-        if(cpunumber == VAX_78032)
-                splx(sc->sc_ipl);       /* Qbus interrupt protocol is odd */
+       if(vax_cputype == VAX_78032)
+               splx(sc->sc_ipl);       /* Qbus interrupt protocol is odd */
 #endif
 
        /*
@@ -935,14 +856,12 @@ tsintr(ctlr)
        switch (sc->sc_state) {
 
        case ST_INVALID:
-                /*
-                 * Ignore unsolicited interrupts.
-                 */
-               debug (("%s%d: intr in state ST_INVALID [%x,%x]\n", 
-                       CTLRNAME, ctlr, sr, mh));
-                log (LOG_WARNING, "%s%d: stray intr [%x,%x]\n", 
-                       CTLRNAME, ctlr, sr, mh);
-                return;
+               /*
+                * Ignore unsolicited interrupts.
+                */
+               log (LOG_WARNING, "%s: stray intr [%x,%x]\n", 
+                       sc->sc_dev.dv_xname, sr, mh);
+               return;
 
        case ST_SLAVE:
                /*
@@ -950,11 +869,9 @@ tsintr(ctlr)
                 * issued by tsslave() and indicates the end of the
                 * initialization phase. Just ignore it ...
                 */
-               debug (("%s%d: intr in state ST_SLAVE [%x,%x]\n", 
-                       CTLRNAME, ctlr, sr, mh));
                if ((sr & TS_SC) != 0 || (sr & TS_TC) != TS_TC_NORM) {
-                       printf ("%s%d: problem during init [%x,%x]\n",
-                               CTLRNAME, ctlr, sr, mh);
+                       printf("%s: problem during init [%x,%x]\n",
+                               sc->sc_dev.dv_xname, sr, mh);
                        /* return here ??? */
                        /* break and check the error outside switch ??? */
                        break;
@@ -968,23 +885,18 @@ tsintr(ctlr)
                 * Here we expect interrupts indicating the end of
                 * commands or indicating problems.
                 */
-               debug (("%s%d: intr ST_RUN (%s) [%x,%x]\n", 
-                       CTLRNAME, ctlr, ((tsmsgp->xst0 & TS_SF_ONL) ? 
-                       "online" : "offline"), sr, mh));
                /*
                 * Anything else is handled outside this switch ...
                 */
                break;
 
        case ST_IDLE:
-               debug (("%s%d: intr ST_IDLE [%x,%x]\n", 
-                       CTLRNAME, ctlr, sr, mh));
                break;
 
 
        default:
-               printf ("%s%d: unexpected interrupt during state %d [%x,%x]\n", 
-                       CTLRNAME, ctlr, sc->sc_state, sr, mh);
+               printf ("%s: unexpected interrupt during state %d [%x,%x]\n", 
+                       sc->sc_dev.dv_xname, sc->sc_state, sr, mh);
                return;
        }
 
@@ -998,7 +910,6 @@ tsintr(ctlr)
                 * Normal termination -- The operation is completed
                 * witout incident.
                 */
-               debug (("%s%d: Normal Termination\n", CTLRNAME, ctlr));
                sc->sc_state = ST_IDLE;         /* XXX ??? */
                sc->sc_state = ST_RUNNING;
                sc->sc_liowf = (ccode == TS_CC_WRITE);
@@ -1006,12 +917,16 @@ tsintr(ctlr)
                if ((bp = ts_wtab[ctlr]) != NULL) {
                        ts_wtab[ctlr] = NULL;   /* pseudo-unlink */
 
-                       if (bp != &ts_cbuf[ctlr]) {     /* no ioctl */
-                               debug (("ubarelse\n"));
-                               ubarelse (um->um_ubanum, (int *)&bp->b_ubinfo);
+                       if (bp != &ts_cbuf[ctlr]) {     /* no ioctl */
+                               ubarelse((struct uba_softc *)
+                                   sc->sc_dev.dv_parent,
+                                   (int *)&bp->b_ubinfo);
 #if defined(VAX750)
-                               if (cpunumber == VAX_750 && um->um_ubinfo != 0)
-                                       ubarelse(um->um_ubanum, &um->um_ubinfo);
+                               if (vax_cputype == VAX_750 &&
+                                   sc->sc_unit.uu_ubinfo != 0)
+                                       ubarelse((struct uba_softc *)
+                                           sc->sc_dev.dv_parent,
+                                           &sc->sc_unit.uu_ubinfo);
                                        /* XXX */
 #endif
                        }
@@ -1030,10 +945,9 @@ tsintr(ctlr)
                 * (Without EAI enabled, no Attention interrupts occur.
                 * drive status changes are signaled by the VCK flag.)
                 */
-               debug (("%s%d: Attention\n", CTLRNAME, ctlr));
                return;
 
-        case TS_TC_TSA:
+       case TS_TC_TSA:
                /* 
                 * Tape Status Alert -- A status condition is encountered
                 * that may have significance to the program. Bits of
@@ -1050,7 +964,7 @@ tsintr(ctlr)
                }
                break;
 
-        case TS_TC_FR: 
+       case TS_TC_FR: 
                /*
                 * Function Reject -- The specified function was not
                 * initiated. Bits of interest include OFL, VCK, BOT,
@@ -1075,7 +989,7 @@ tsintr(ctlr)
                }
                break;
 
-        case TS_TC_TPD:
+       case TS_TC_TPD:
                /*
                 * Recoverable Error -- Tape position is a record beyond
                 * what its position was when the function was initiated.
@@ -1096,7 +1010,7 @@ tsintr(ctlr)
                        return;
                case TS_CMD_WD:         /* Write Data (Next) */
                        debug (("retry write data ...\n"));
-                       sc->sc_rtc = 1;         
+                       sc->sc_rtc = 1;         
                        tsexec (ctlr, TS_CMD_WDR);
                        return;
                case TS_CMD_WTM:
@@ -1109,7 +1023,7 @@ tsintr(ctlr)
                }
                break;
 
-        case TS_TC_TNM:
+       case TS_TC_TNM:
                /*
                 * Recoverable Error -- Tape position has not changed.
                 * Suggested recovery procedure is to log the error and
@@ -1126,7 +1040,7 @@ tsintr(ctlr)
                }
                break;
 
-        case TS_TC_TPL:
+       case TS_TC_TPL:
                /*
                 * Unrecoverable Error -- Tape position has been lost.
                 * No valid recovery procedures exist unless the tape
@@ -1135,7 +1049,7 @@ tsintr(ctlr)
                printf ("Tape position lost\n"); 
                break;
 
-        case TS_TC_FCE:
+       case TS_TC_FCE:
                /*
                 * Fatal subsytem Error -- The subsytem is incapable
                 * of properly performing commands, or at least its
@@ -1146,8 +1060,8 @@ tsintr(ctlr)
                printf ("Fatal Controller Error\n"); 
 
        default:
-               printf ("%s%d: error 0x%x, resetting controller\n", 
-                       CTLRNAME, ctlr, sr & TS_TC);
+               printf ("%s: error 0x%x, resetting controller\n", 
+                       sc->sc_dev.dv_xname, sr & TS_TC);
                tsreset (ctlr);
        }
 
@@ -1157,14 +1071,13 @@ tsintr(ctlr)
        if ((bp = ts_wtab[ctlr]) != NULL) {
                ts_wtab[ctlr] = NULL;           /* pseudo unlink */
 
-               if (bp != &ts_cbuf[ctlr]) {     /* no ioctl */
-                       debug (("ubarelse-2\n"));
-                       ubarelse(um->um_ubanum, (int *)&bp->b_ubinfo);
-               }
-               if ((sr & TS_TC) != TS_TC_NORM) {
+               if (bp != &ts_cbuf[ctlr])       /* no ioctl */
+                       ubarelse((struct uba_softc *)sc->sc_dev.dv_parent,
+                           (int *)&bp->b_ubinfo);
+
+               if ((sr & TS_TC) != TS_TC_NORM)
                        bp->b_flags |= B_ERROR;
-                       debug (("tsintr: bp->b_flags |= B_ERROR\n"));
-               }
+
                debug (("resid:%d, count:%d, rbpcr:%d\n",
                        bp->b_resid, bp->b_bcount, tsmsgp->rbpcr));
                bp->b_resid = tsmsgp->rbpcr; /* XXX */
@@ -1196,27 +1109,27 @@ tsopen (dev, flag, type, p)
 
        trace (("tsopen (%x, %x)\n", dev, flag));
        
-       if (unit >= NTS || (ui = tsinfo[unit]) == 0 || ui->ui_alive == 0) {
-               debug (("ui->ui_alive == 0\n"));
-               return (ENXIO);
-       }
-       sc = &ts_softc[ui->ui_ctlr];    /* unit ??? */
-       if (sc->sc_openf) {
-               debug (("sc->sc_openf\n"));
-               return (EBUSY);
-       }
+       if (unit >= ts_cd.cd_ndevs)
+               return ENXIO;
+
+       sc = ts_cd.cd_devs[unit];
+       if (sc == 0)
+               return ENXIO;
+
+       if (sc->sc_openf)
+               return EBUSY;
+
        sc->sc_openf = 1;
-       sc->sc_tpr = tprintf_open (curproc);
+
        s = splbio ();
        if (sc->sc_state < ST_RUNNING) {                /* XXX */
-               printf ("ts%d not running.\n", ui->ui_ctlr);
+               printf ("%s not running.\n", sc->sc_dev.dv_xname);
                (void) splx (s);
                sc->sc_openf = 0;
                return (ENXIO);
        }
-       um = ui->ui_mi;
        (void) splx (s);
-#if 1
+
        /*
         * check if transport is really online.
         * (without attention-interrupts enabled, we really don't know
@@ -1224,14 +1137,14 @@ tsopen (dev, flag, type, p)
         * (ie. MTNOP) once and check the actual status.)
         */
        tscommand (dev, MTNOP, 1);
-       if (ts[TS_CTLR(dev)].reg->tssr & TS_OFL) {
-               printf ("ts%d: transport is offline.\n", ui->ui_ctlr);
+       if (ts[unit].reg->tssr & TS_OFL) {
+               printf ("%s: transport is offline.\n", sc->sc_dev.dv_xname);
                sc->sc_openf = 0;
-               return (EIO);           /* transport is offline */
+               return EIO;             /* transport is offline */
        }
-#endif
+
        sc->sc_liowf = 0;
-       return (0);
+       return 0;
 }
 
 
@@ -1246,16 +1159,13 @@ tsopen (dev, flag, type, p)
  */
 int
 tsclose (dev, flag, type, p)
-        dev_t dev;
-        int flag, type;
+       dev_t dev;
+       int flag, type;
        struct proc *p;
 {
-       register struct ts_softc *sc = &ts_softc[TS_UNIT(dev)];
-
-        trace (("tsclose (%x, %d)\n", dev, flag));
+       register struct ts_softc *sc = ts_cd.cd_devs[TS_UNIT(dev)];
 
        if (flag == FWRITE || ((flag & FWRITE) && sc->sc_liowf)) {
-               debug (("tsclose: writing eot\n"));
                /* 
                 * We are writing two tape marks (EOT), but place the tape
                 * before the second one, so that another write operation
@@ -1263,18 +1173,15 @@ tsclose (dev, flag, type, p)
                 */
                tscommand (dev, MTWEOF, 1);     /* Write Tape Mark */
                tscommand (dev, MTWEOF, 1);     /* Write Tape Mark */
-               tscommand (dev, MTBSF,  1);     /* Skip Tape Marks Reverse */
+               tscommand (dev, MTBSF,  1);     /* Skip Tape Marks Reverse */
        }
 
-       if ((minor(dev)&T_NOREWIND) == 0) {
-               debug (("tsclose: rewinding\n"));
+       if ((dev & T_NOREWIND) == 0)
                tscommand (dev, MTREW, 0);
-       }
 
-       tprintf_close (sc->sc_tpr);
        sc->sc_openf = 0;
        sc->sc_liowf = 0;
-       return (0);
+       return 0;
 }
 
 
@@ -1283,51 +1190,20 @@ tsclose (dev, flag, type, p)
  */
 void
 tsstrategy (bp)
-        register struct buf *bp;
+       register struct buf *bp;
 {
-       register struct uba_device *ui;
-       register struct uba_ctlr *um;
        register int unit = TS_UNIT(bp->b_dev);
+       struct ts_softc *sc = (void *)ts_cd.cd_devs[unit];
        int s;
 
-       trace (("tsstrategy (...)\n"));
-       if (unit >= NTS) {
-               debug (("tsstrategy: bad unit # %d\n",unit));
-               bp->b_flags |= B_ERROR;
-               iodone(bp);
-               return;
-       }
-       ui = tsinfo[unit];
-       if (ui == 0 || ui->ui_alive == 0) {
-               debug (("tsstrategy: ui_alive == 0\n"));
-               bp->b_flags |= B_ERROR;
-               iodone(bp);
-               return;
-       }
-
        s = splbio ();
        /*
         * we have only one command at one time, no credits.
         * thus we don't need buffer management and controller queue
         * just try to execute the command ...
         */
-#if 0
-       if (ts_wtab[unit] != NULL) {
-               debug (("tsstrategy: already waiting for something\n"));
-               ts_wtab[unit]->b_flags |= B_ERROR;
-               iodone (ts_wtab[unit]);
-       }
-       ts_wtab[unit] = bp;
-#endif
 
-       um = ui->ui_mi;
-       if (um->um_tab.b_active == 0) {
-               /*
-                * If the controller is not active, start it.
-                */
-       }
-
-       tsstart (um, bp);
+       tsstart (sc, bp);
        splx(s);
        return;
 }
@@ -1338,10 +1214,10 @@ tsstrategy (bp)
  */
 int
 tsioctl (dev, cmd, data, flag, p)
-        dev_t dev;
+       dev_t dev;
        u_long cmd;
-        caddr_t data;
-        int flag;
+       caddr_t data;
+       int flag;
        struct proc *p;
 {
        register struct buf *bp = &ts_cbuf[TS_UNIT(dev)];
@@ -1413,11 +1289,11 @@ tsioctl (dev, cmd, data, flag, p)
                return (error);         
 
        case MTIOCGET:                  /* get tape status */
-               sc = &ts_softc[TS_CTLR(dev)];
+               sc = ts_cd.cd_devs[TS_UNIT(dev)];
                mtget = (struct mtget *)data;
                mtget->mt_type = MT_ISTS;
-               mtget->mt_dsreg = (unsigned)(ts[TS_CTLR(dev)].reg->tssr);
-               mtget->mt_erreg = (unsigned)(ts[TS_CTLR(dev)].msg.hdr);
+               mtget->mt_dsreg = (unsigned)(ts[TS_UNIT(dev)].reg->tssr);
+               mtget->mt_erreg = (unsigned)(ts[TS_UNIT(dev)].msg.hdr);
                mtget->mt_resid = 0;            /* ??? */
                mtget->mt_density = 0;          /* ??? */
                break;
@@ -1482,7 +1358,10 @@ tsstatus (sr)
        int sr;
 {
 #ifdef DEBUG
-       debug (("status: TSSR=%b\n", sr, TS_TSSR_BITS));
+       char bits[64];
+
+       debug (("status: TSSR=%s\n", bitmask_snprintf(sr, TS_TSSR_BITS,
+           bits, sizeof(bits))));
 
        if (tsdebug < 5)
                return (0);
@@ -1496,7 +1375,7 @@ tsstatus (sr)
        if (sr & TS_A11)        printf ("Address Bits 17-16\n");
        if (sr & TS_SSR)        printf ("Subsystem Ready\n");
        if (sr & TS_OFL)        printf ("Off Line\n");
-       if (sr & TS_FTC)        printf ("Fatal Termination Class Code\n");
+       if (sr & TS_FTC)        printf ("Fatal Termination Class Code\n");
        switch (sr & TS_TC) {
        case TS_TC_NORM:        printf ("Normal Termination\n"); break;
        case TS_TC_ATTN:        printf ("Attention Condition\n"); break;
@@ -1516,10 +1395,18 @@ tsxstatus (mp)
        struct tsmsg *mp;
 {
 #ifdef DEBUG
-       debug (("tsxstatus: xst0=%b, xst1=%b, xst2=%b, xst3=%b, xst4=%b\n",
-               mp->xst0, TS_XST0_BITS, mp->xst1, TS_XST1_BITS,
-               mp->xst2, TS_XST2_BITS, mp->xst3, TS_XST3_BITS,
-               mp->xst4, "\20"));
+       char bits[64];
+
+       debug (("tsxstatus: xst0=%s, ", bitmask_snprintf(mp->xst0,
+           TS_XST0_BITS, bits, sizeof(bits))));
+       debug (("xst1=%s, ", bitmask_snprintf(mp->xst1, TS_XST1_BITS,
+           bits, sizeof(bits))));
+       debug (("xst2=%s, ", bitmask_snprintf(mp->xst2, TS_XST2_BITS, 
+           bits, sizeof(bits))));
+       debug (("xst3=%s, ", bitmask_snprintf(mp->xst3, TS_XST3_BITS,
+           bits, sizeof(bits))));
+       debug (("xst4=%s\n", bitmask_snprintf(mp->xst4, "\20",
+           bits, sizeof(bits))));
 
        if (tsdebug < 10)
                return (0);
@@ -1566,23 +1453,3 @@ tsxstatus (mp)
        if (mp->xst4 & TS_SF_RCX)       printf ("Retry Count Exceeded\n");
 #endif
 }
-
-int
-ts_match(parent, match, aux)
-        struct device *parent;
-        void *match, *aux;
-{
-        return 0;
-}
-
-void
-ts_attach(parent, self, aux)
-        struct device *parent, *self;
-        void *aux;
-{
-}
-
-
-
-#endif /* #if NTS > 0 */
-
index 2018c4a..fd1a2ea 100644 (file)
@@ -1,8 +1,8 @@
-/*      $NetBSD: uba.c,v 1.22 1996/04/08 18:37:34 ragge Exp $      */
-
+/*     $NetBSD: uba.c,v 1.29 1996/10/13 03:35:24 christos Exp $           */
 /*
+ * Copyright (c) 1996 Jonathan Stone.
+ * Copyright (c) 1994, 1996 Ludd, University of Lule}, Sweden.
  * Copyright (c) 1982, 1986 The Regents of the University of California.
- * Copyright (c) 1994 Ludd, University of Lule}, Sweden.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -34,7 +34,7 @@
  * SUCH DAMAGE.
  *
  *     @(#)uba.c       7.10 (Berkeley) 12/16/90
- *      @(#)autoconf.c  7.20 (Berkeley) 5/9/91
+ *     @(#)autoconf.c  7.20 (Berkeley) 5/9/91
  */
 
 #include <sys/param.h>
 #include <vax/uba/ubareg.h>
 #include <vax/uba/ubavar.h>
 
-extern int cold;
-
-volatile int rbr,rcvec;
+volatile int rbr, rcvec, svec;
 
-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 *, const char *));
-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));
+static void ubascan __P((struct device *, void *));
+static int ubaprint __P((void *, const char *));
+static void ubastray __P((int));
+static void ubainitmaps __P((struct uba_softc *));
+static void uba_attach __P((struct uba_softc *, unsigned long));
+static int ubasetup __P((struct uba_softc *, struct buf *, int));
 
 
 struct cfdriver uba_cd = {
        NULL, "uba", DV_DULL, 1
 };
 
-struct cfattach uba_ca = {
-       sizeof(struct uba_softc), uba_match, uba_attach
+#define spluba spl7
+
+#if defined(DW780) || defined(DW750)
+
+int    dw_match __P((struct device *, void *, void *));
+
+int
+dw_match(parent, vcf, aux)
+       struct  device *parent;
+       void *vcf, *aux;
+{
+       struct sbi_attach_args *sa = (struct sbi_attach_args *)aux;
+       struct cfdata *cf = vcf;
+
+       if ((cf->cf_loc[0] != sa->nexnum) && (cf->cf_loc[0] > -1 ))
+               return 0;
+
+       /*
+        * The uba type is actually only telling where the uba 
+        * space is in nexus space.
+        */
+       if ((sa->type & ~3) != NEX_UBA0)
+               return 0;
+
+       return 1;
+}
+#endif
+
+#ifdef DW780
+/*
+ * The DW780 are directly connected to the SBI on 11/780 and 8600.
+ */
+void   dw780_attach __P((struct device *, struct device *, void *));
+void   dw780_beforescan __P((struct uba_softc *));
+void   dw780_afterscan __P((struct uba_softc *));
+int    dw780_errchk __P((struct uba_softc *));
+void   dw780_init __P((struct uba_softc *));
+void   dw780_purge __P((struct uba_softc *, int));
+void   uba_dw780int __P((int));
+static void ubaerror __P((struct uba_softc *, int *, int *));
+
+struct cfattach uba_sbi_ca = {
+       sizeof(struct uba_softc), dw_match, dw780_attach
 };
 
+char   ubasr_bits[] = UBASR_BITS;
+
+void
+dw780_attach(parent, self, aux)
+       struct device *parent, *self;
+       void *aux;
+{
+       struct uba_softc *sc = (void *)self;
+       struct sbi_attach_args *sa = aux;
+       int ubaddr = sa->type & 3;
+
+       printf(": DW780\n");
+
+       /*
+        * Fill in bus specific data.
+        */
+       sc->uh_uba = (void *)sa->nexaddr;
+       sc->uh_nbdp = NBDP780;
+       sc->uh_nr = sa->nexnum * (parent->dv_unit + 1);
+       sc->uh_beforescan = dw780_beforescan;
+       sc->uh_afterscan = dw780_afterscan;
+       sc->uh_errchk = dw780_errchk;
+       sc->uh_ubapurge = dw780_purge;
+       sc->uh_ubainit = dw780_init;
+       sc->uh_type = DW780;
+       sc->uh_memsize = UBAPAGES;
+       sc->uh_iarea = (void *)scb + NBPG + ubaddr * NBPG;
+       sc->uh_mr = sc->uh_uba->uba_map;
+
+       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;
+
+       uba_attach(sc, (parent->dv_unit ? UMEMB8600(ubaddr) :
+           UMEMA8600(ubaddr)) + (UBAPAGES * NBPG));
+}
+
+void
+dw780_beforescan(sc)
+       struct uba_softc *sc;
+{
+       volatile int *hej = &sc->uh_uba->uba_sr;
+
+       if (sc->uh_type == DW780) {
+               *hej = *hej;
+               sc->uh_uba->uba_cr = UBACR_IFS|UBACR_BRIE;
+       }
+}
+
+void
+dw780_afterscan(sc)
+       struct uba_softc *sc;
+{
+       if (sc->uh_type == DW780)
+               sc->uh_uba->uba_cr = UBACR_IFS | UBACR_BRIE |
+                   UBACR_USEFIE | UBACR_SUEFIE |
+                   (sc->uh_uba->uba_cr & 0x7c000000);
+}
+
+/*
+ * On DW780 badaddr() in uba space sets a bit in uba_sr instead of
+ * doing a machine check.
+ */
+int
+dw780_errchk(sc)
+       struct uba_softc *sc;
+{
+       volatile int *hej = &sc->uh_uba->uba_sr;
+
+       if (sc->uh_type == DW780 && *hej) {
+               *hej = *hej;
+               return 1;
+       }
+       return 0;
+}
+
+void
+uba_dw780int(uba)
+       int     uba;
+{
+       int     br, 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(sc, &br, (int *)&svec);
+               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);
+}
+
+void
+dw780_init(sc)
+       struct uba_softc *sc;
+{
+       sc->uh_uba->uba_cr = UBACR_ADINIT;
+       sc->uh_uba->uba_cr = UBACR_IFS|UBACR_BRIE|UBACR_USEFIE|UBACR_SUEFIE;
+       while ((sc->uh_uba->uba_cnfgr & UBACNFGR_UBIC) == 0)
+               ;
+}
+
+void
+dw780_purge(sc, bdp)
+       struct uba_softc *sc;
+       int bdp;
+{
+       sc->uh_uba->uba_dpr[bdp] |= UBADPR_BNE;
+}
+
+int    ubawedgecnt = 10;
+int    ubacrazy = 500;
+int    zvcnt_max = 5000;       /* in 8 sec */
+int    ubaerrcnt;
+/*
+ * This routine is called by the locore code to process a UBA
+ * error on an 11/780 or 8600. The arguments are passed
+ * on the stack, and value-result (through some trickery).
+ * In particular, the uvec argument is used for further
+ * uba processing so the result aspect of it is very important.
+ * It must not be declared register.
+ */
+/*ARGSUSED*/
+void
+ubaerror(uh, ipl, uvec)
+       register struct uba_softc *uh;
+       int *ipl, *uvec;
+{
+       struct  uba_regs *uba = uh->uh_uba;
+       register sr, s;
+
+       if (*uvec == 0) {
+               /*
+                * Declare dt as unsigned so that negative values
+                * are handled as >8 below, in case time was set back.
+                */
+               u_long  dt = time.tv_sec - uh->uh_zvtime;
+
+               uh->uh_zvtotal++;
+               if (dt > 8) {
+                       uh->uh_zvtime = time.tv_sec;
+                       uh->uh_zvcnt = 0;
+               }
+               if (++uh->uh_zvcnt > zvcnt_max) {
+                       printf("%s: too many zero vectors (%d in <%d sec)\n",
+                               uh->uh_dev.dv_xname, 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,
+                               uba->uba_cnfgr&0xff);
+                       printf("\tsr: %b\n\tdcr: %x (MIC %sOK)\n",
+                               uba->uba_sr, ubasr_bits, uba->uba_dcr,
+                               (uba->uba_dcr&0x8000000)?"":"NOT ");
+                       ubareset(uh->uh_dev.dv_unit);
+               }
+               return;
+       }
+       if (uba->uba_cnfgr & NEX_CFGFLT) {
+               printf("%s: sbi fault sr=%b cnfgr=%b\n",
+                   uh->uh_dev.dv_xname, uba->uba_sr, ubasr_bits,
+                   uba->uba_cnfgr, NEXFLT_BITS);
+               ubareset(uh->uh_dev.dv_unit);
+               *uvec = 0;
+               return;
+       }
+       sr = uba->uba_sr;
+       s = spluba();
+       printf("%s: uba error sr=%b fmer=%x fubar=%o\n", uh->uh_dev.dv_xname,
+           uba->uba_sr, ubasr_bits, uba->uba_fmer, 4*uba->uba_fubar);
+       splx(s);
+       uba->uba_sr = sr;
+       *uvec &= UBABRRVR_DIV;
+       if (++ubaerrcnt % ubawedgecnt == 0) {
+               if (ubaerrcnt > ubacrazy)
+                       panic("uba crazy");
+               printf("ERROR LIMIT ");
+               ubareset(uh->uh_dev.dv_unit);
+               *uvec = 0;
+               return;
+       }
+       return;
+}
+#endif
+
+#ifdef DW750
+/*
+ * The DW780 and DW750 are quite similar to their function from
+ * a programmers point of view. Differencies are number of BDP's
+ * and bus status/command registers, the latter are (partly) IPR's
+ * on 750.
+ */
+void   dw750_attach __P((struct device *, struct device *, void *));
+void   dw750_init __P((struct uba_softc *));
+void   dw750_purge __P((struct uba_softc *, int));
+
+struct cfattach uba_cmi_ca = {
+       sizeof(struct uba_softc), dw_match, dw750_attach
+};
+
+void
+dw750_attach(parent, self, aux)
+       struct device *parent, *self;
+       void *aux;
+{
+       struct uba_softc *sc = (void *)self;
+       struct sbi_attach_args *sa = aux;
+       int ubaddr = sa->nexinfo & 1;
+
+       printf(": DW750\n");
+
+       /*
+        * Fill in bus specific data.
+        */
+       sc->uh_uba = (void *)sa->nexaddr;
+       sc->uh_nbdp = NBDP750;
+       sc->uh_nr = sa->nexnum;
+       sc->uh_ubapurge = dw750_purge;
+       sc->uh_ubainit = dw750_init;
+       sc->uh_type = DW750;
+       sc->uh_memsize = UBAPAGES;
+       sc->uh_iarea = (void *)scb + NBPG + ubaddr * NBPG;
+       sc->uh_mr = sc->uh_uba->uba_map;
+
+       uba_attach(sc, UMEM750(ubaddr) + (UBAPAGES * NBPG));
+}
+
+void
+dw750_init(sc)
+       struct uba_softc *sc;
+{
+       mtpr(0, PR_IUR);
+       DELAY(500000);
+}
+
+void
+dw750_purge(sc, bdp)
+       struct uba_softc *sc;
+       int bdp;
+{
+       sc->uh_uba->uba_dpr[bdp] |= UBADPR_PURGE | UBADPR_NXM | UBADPR_UCE;
+}
+#endif
+
+#ifdef QBA
+/*
+ * The Q22 bus is the main IO bus on MicroVAX II/MicroVAX III systems.
+ * It has an address space of 4MB (22 address bits), therefore the name,
+ * and is hardware compatible with all 16 and 18 bits Q-bus devices.
+ * This driver can only handle map registers up to 1MB due to map info
+ * storage, but that should be enough for normal purposes.
+ */
+int    qba_match __P((struct device *, void *, void *));
+void   qba_attach __P((struct device *, struct device *, void *));
+void   qba_beforescan __P((struct uba_softc*));
+void   qba_init __P((struct uba_softc*));
+
+struct cfattach uba_backplane_ca = {
+       sizeof(struct uba_softc), qba_match, qba_attach
+};
+
+int
+qba_match(parent, vcf, aux)
+       struct device *parent;
+       void *vcf, *aux;
+{
+       struct  bp_conf *bp = aux;
+
+       if (strcmp(bp->type, "uba"))
+               return 0;
+
+       return 1;
+}
+
+void
+qba_attach(parent, self, aux)
+       struct device *parent, *self;
+       void *aux;
+{
+       struct uba_softc *sc = (void *)self;
+       vm_offset_t mini, maxi;
+
+       printf(": Q22\n");
+
+
+       /*
+        * Fill in bus specific data.
+        */
+/*     sc->uh_uba not used; no regs */
+/*     sc->uh_nbdp is 0; Qbus has no BDP's */
+/*     sc->uh_nr is 0; there can be only one! */
+/*     sc->uh_afterscan; not used */
+/*     sc->uh_errchk; not used */
+       sc->uh_beforescan = qba_beforescan;
+       sc->uh_ubainit = qba_init;
+       sc->uh_type = QBA;
+       sc->uh_memsize = QBAPAGES;
+       sc->uh_iarea = (void *)scb + NBPG;
+       /*
+        * Map in the UBA page map into kernel space. On other UBAs,
+        * the map registers are in the bus IO space.
+        */
+       (void)kmem_suballoc(kernel_map, &mini, &maxi,
+           QBAPAGES * sizeof(struct pte), FALSE);
+       pmap_map(mini,  QBAMAP, QBAMAP + QBAPAGES * sizeof(struct pte),
+           VM_PROT_READ | VM_PROT_WRITE);
+       sc->uh_mr = (void *)mini;
+
+       uba_attach(sc, QIOPAGE);
+}
+
+/*
+ * Called when the QBA is set up; to enable DMA access from
+ * QBA devices to main memory.
+ */
+void
+qba_beforescan(sc)
+       struct uba_softc *sc;
+{
+       *((u_short *)(sc->uh_iopage + QIPCR)) = Q_LMEAE;
+}
+
+void
+qba_init(sc)
+       struct uba_softc *sc;
+{
+       mtpr(0, PR_IUR);
+       DELAY(500000);
+       qba_beforescan(sc);
+}
+#endif
+#ifdef DWBUA
+int    bua_match __P((struct device *, void *, void *));
+void   bua_attach __P((struct device *, struct device *, void *));
+
+struct cfattach uba_bi_ca = {
+       sizeof(struct uba_softc), bua_match, bua_attach
+};
+
+bua_beforescan(sc)
+       struct uba_softc *sc;
+{
+       if (sc->uh_type == DWBUA)
+               BUA(ubar)->bua_offset = (int)sc->uh_vec - (int)&scb[0];
+}
+
+void
+bua_init(sc)
+       struct uba_softc *sc;
+{
+       BUA(uba)->bua_csr |= BUACSR_UPI;
+       /* give devices time to recover from power fail */
+       DELAY(500000);
+       break;
+}
+#endif
+#ifdef DW730
+struct cfattach uba_dw730_ca = {
+       sizeof(struct uba_softc), dw730_match, dw730_attach
+};
+#endif
 /* 
  * Stray interrupt vector handler, used when nowhere else to go to.
  */
@@ -104,13 +504,12 @@ ubastray(arg)
 {
        struct  callsframe *cf = FRAMEOFFSET(arg);
        struct  uba_softc *sc = uba_cd.cd_devs[arg];
-       struct  uba_regs *ur = sc->uh_uba;
        int     vektor;
 
        rbr = mfpr(PR_IPL);
 #ifdef DW780
        if (sc->uh_type == DW780)
-               vektor = ur->uba_brrvr[rbr - 0x14] >> 2;
+               vektor = svec >> 2;
        else
 #endif
                vektor = (cf->ca_pc - (unsigned)&sc->uh_idsp[0]) >> 4;
@@ -121,131 +520,10 @@ ubastray(arg)
 #endif
                        rcvec = vektor;
        } else 
-               printf("uba%d: unexpected interrupt, vector %o, br %d\n",
-                   arg, vektor << 2, rbr - 20);
+               printf("uba%d: unexpected interrupt, vector 0x%x, br 0x%x\n",
+                   arg, svec, rbr);
 }
 
-/*
- * Find devices on a UNIBUS.
- * Uses per-driver routine to set <br,cvec> into <r11,r10>,
- * 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;
-{
-       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;
-       volatile extern int rbr, rcvec;
-
-#define        ubaddr(uhp, off)    (u_short *)((int)(uhp)->uh_iopage + ubdevreg(off))
-       /*
-        * Check each unibus mass storage controller.
-        * For each one which is potentially on this uba,
-        * 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)
-                       continue;
-               addr = (u_short)(u_long)um->um_addr;
-               /*
-                * use the particular address specified first,
-                * or if it is given as "0", of there is no device
-                * at that address, try all the standard addresses
-                * in the driver til we find it
-                */
-           for (ap = udp->ud_addr; addr || (addr = *ap++); addr = 0) {
-               reg = ubaddr(uhp, addr);
-               if (badaddr((caddr_t)reg, 2))
-                       continue;
-
-#if DW780
-               if (uhp->uh_type == DW780 && ubar->uba_sr) {
-                       ubar->uba_sr = ubar->uba_sr;
-                       continue;
-               }
-#endif
-               rcvec = 0x200;
-               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
-               if (i == 0)
-                       continue;
-               printf("%s%d at uba%d csr %o ",
-                   udp->ud_mname, um->um_ctlr, uhp->uh_dev.dv_unit, addr);
-               if (rcvec == 0) {
-                       printf("zero vector\n");
-                       continue;
-               }
-               if (rcvec == 0x200) {
-                       printf("didn't interrupt\n");
-                       continue;
-               }
-               printf("vec %o, ipl %x\n", rcvec << 2, rbr);
-               um->um_alive = 1;
-               um->um_ubanum = uhp->uh_dev.dv_unit;
-               um->um_hd = uhp;
-               um->um_addr = (caddr_t)reg;
-               udp->ud_minfo[um->um_ctlr] = um;
-               uhp->uh_idsp[rcvec].hoppaddr = um->um_intr;
-               uhp->uh_idsp[rcvec].pushlarg = um->um_ctlr;
-               for (ui = ubdinit; ui->ui_driver; ui++) {
-                       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 != '?'))
-                               continue;
-                       t = ui->ui_ctlr;
-                       ui->ui_ctlr = um->um_ctlr;
-                       if ((*udp->ud_slave)(ui, (caddr_t)reg) == 0)
-                               ui->ui_ctlr = t;
-                       else {
-                               ui->ui_alive = 1;
-                               ui->ui_ubanum = uhp->uh_dev.dv_unit;
-                               ui->ui_hd = uhp;
-                               ui->ui_addr = (caddr_t)reg;
-                               ui->ui_physaddr = pumem + ubdevreg(addr);
-                               if (ui->ui_dk && dkn < DK_NDRIVE)
-                                       ui->ui_dk = dkn++;
-                               else
-                                       ui->ui_dk = -1;
-                               ui->ui_mi = um;
-                               /* ui_type comes from driver */
-                               udp->ud_dinfo[ui->ui_unit] = ui;
-                               printf("%s%d at %s%d slave %d",
-                                   udp->ud_dname, ui->ui_unit,
-                                   udp->ud_mname, um->um_ctlr, ui->ui_slave);
-                               (*udp->ud_attach)(ui);
-                               printf("\n");
-                       }
-               }
-               break;
-           }
-       }
-}
-
-
-#ifdef DW780
-char   ubasr_bits[] = UBASR_BITS;
-#endif
-
-#define        spluba  splbio          /* IPL 17 */
-
 /*
  * Do transfer on device argument.  The controller
  * and uba involved are implied by the device.
@@ -253,7 +531,7 @@ char        ubasr_bits[] = UBASR_BITS;
  * We return 1 if the transfer was started, 0 if it was not.
  *
  * The onq argument must be zero iff the device is not on the
- * queue for this UBA.  If onq is set, the device must be at the
+ * queue for this UBA. If onq is set, the device must be at the
  * head of the queue.  In any case, if the transfer is started,
  * the device will be off the queue, and if not, it will be on.
  *
@@ -263,82 +541,64 @@ char      ubasr_bits[] = UBASR_BITS;
  * does not now have a BDP.
  */
 int
-ubaqueue(ui, onq)
-       register struct uba_device *ui;
-       int onq;
+ubaqueue(uu, bp)
+       register struct uba_unit *uu;
+       struct buf *bp;
 {
-       register struct uba_ctlr *um = ui->ui_mi;
        register struct uba_softc *uh;
-       register struct uba_driver *ud;
-       register int s, unit;
+       register int s;
 
-       uh = uba_cd.cd_devs[um->um_ubanum];
-       ud = um->um_driver;
+       uh = (void *)((struct device *)(uu->uu_softc))->dv_parent;
        s = spluba();
        /*
         * Honor exclusive BDP use requests.
         */
-       if ((ud->ud_xclu && uh->uh_users > 0) || uh->uh_xclu)
+       if ((uu->uu_xclu && uh->uh_users > 0) || uh->uh_xclu)
                goto rwait;
-       if (ud->ud_keepbdp) {
+       if (uu->uu_keepbdp) {
                /*
                 * First get just a BDP (though in fact it comes with
                 * one map register too).
                 */
-               if (um->um_bdp == 0) {
-                       um->um_bdp = uballoc(um->um_ubanum,
-                               (caddr_t)0, 0, UBA_NEEDBDP|UBA_CANTWAIT);
-                       if (um->um_bdp == 0)
+               if (uu->uu_bdp == 0) {
+                       uu->uu_bdp = uballoc(uh, (caddr_t)0, 0,
+                           UBA_NEEDBDP|UBA_CANTWAIT);
+                       if (uu->uu_bdp == 0)
                                goto rwait;
                }
                /* now share it with this transfer */
-               um->um_ubinfo = ubasetup(um->um_ubanum,
-                       um->um_tab.b_actf->b_actf,
-                       um->um_bdp|UBA_HAVEBDP|UBA_CANTWAIT);
+               uu->uu_ubinfo = ubasetup(uh, bp,
+                   uu->uu_bdp|UBA_HAVEBDP|UBA_CANTWAIT);
        } else
-               um->um_ubinfo = ubasetup(um->um_ubanum,
-                       um->um_tab.b_actf->b_actf, UBA_NEEDBDP|UBA_CANTWAIT);
-       if (um->um_ubinfo == 0)
+               uu->uu_ubinfo = ubasetup(uh, bp, UBA_NEEDBDP|UBA_CANTWAIT);
+       if (uu->uu_ubinfo == 0)
                goto rwait;
        uh->uh_users++;
-       if (ud->ud_xclu)
+       if (uu->uu_xclu)
                uh->uh_xclu = 1;
+
        splx(s);
-       if (ui->ui_dk >= 0) {
-               unit = ui->ui_dk;
-               dk_busy |= 1<<unit;
-               dk_xfer[unit]++;
-               dk_wds[unit] += um->um_tab.b_actf->b_actf->b_bcount>>6;
-       }
-       if (onq)
-               uh->uh_actf = ui->ui_forw;
-       (*ud->ud_dgo)(um);
        return (1);
+
 rwait:
-       if (!onq) {
-               ui->ui_forw = NULL;
-               if (uh->uh_actf == NULL)
-                       uh->uh_actf = ui;
-               else
-                       uh->uh_actl->ui_forw = ui;
-               uh->uh_actl = ui;
-       }
+       SIMPLEQ_INSERT_TAIL(&uh->uh_resq, uu, uu_resq);
        splx(s);
        return (0);
 }
 
 void
-ubadone(um)
-       struct uba_ctlr *um;
+ubadone(uu)
+       struct uba_unit *uu;
 {
-       struct uba_softc *uh = uba_cd.cd_devs[um->um_ubanum];
+       struct uba_softc *uh = (void *)((struct device *)
+           (uu->uu_softc))->dv_parent;
 
-       if (um->um_driver->ud_xclu)
+       if (uu->uu_xclu)
                uh->uh_xclu = 0;
        uh->uh_users--;
-       if (um->um_driver->ud_keepbdp)
-               um->um_ubinfo &= ~BDPMASK;      /* keep BDP for misers */
-       ubarelse(um->um_ubanum, &um->um_ubinfo);
+       if (uu->uu_keepbdp)
+               uu->uu_ubinfo &= ~BDPMASK;      /* keep BDP for misers */
+       ubarelse(uh, &uu->uu_ubinfo);
 }
 
 /*
@@ -349,27 +609,19 @@ ubadone(um)
  * bdp number and number of map registers.
  */
 int
-ubasetup(uban, bp, flags)
+ubasetup(uh, bp, flags)
+       struct  uba_softc *uh;
        struct  buf *bp;
-       int     uban, flags;
+       int     flags;
 {
-       struct uba_softc *uh = uba_cd.cd_devs[uban];
-       struct pte *pte, *io;
        int npf;
-       int pfnum, temp;
+       int temp;
        int reg, bdp;
-       unsigned v;
-       struct proc *rp;
        int a, o, ubinfo;
 
-#ifdef DW730
-       if (uh->uh_type == DW730)
+       if (uh->uh_nbdp == 0)
                flags &= ~UBA_NEEDBDP;
-#endif
-#ifdef QBA
-       if (uh->uh_type == QBA)
-               flags &= ~UBA_NEEDBDP;
-#endif
+
        o = (int)bp->b_un.b_addr & PGOFSET;
        npf = btoc(bp->b_bcount + o) + 1;
        if (npf > UBA_MAXNMR)
@@ -412,47 +664,9 @@ ubasetup(uban, bp, flags)
        temp = (bdp << 21) | UBAMR_MRV;
        if (bdp && (o & 01))
                temp |= UBAMR_BO;
-       if ((bp->b_flags & B_PHYS) == 0)
-               pte = (struct pte *)kvtopte(bp->b_un.b_addr);
-       else {
-               struct  pte *hej;
-               int     i;
 
-               rp = bp->b_proc;
-               v = btop((u_int)bp->b_un.b_addr&0x3fffffff);
+       disk_reallymapin(bp, uh->uh_mr, reg, temp | PG_V);
 
-               /*
-                * It may be better to use pmap_extract() here
-                * somewhere, but so far we do it "the hard way" :)
-                */
-               if (((u_int)bp->b_un.b_addr < 0x40000000) ||
-                   ((u_int)bp->b_un.b_addr > 0x7fffffff))
-                       hej = rp->p_vmspace->vm_pmap.pm_pcb->P0BR;
-               else
-                       hej = rp->p_vmspace->vm_pmap.pm_pcb->P1BR;
-
-               pte = &hej[v];
-               for (i = 0; i < (npf - 1); i++) {
-                       if ((pte + i)->pg_pfn == 0) {
-                               int rv;
-
-                               rv = vm_fault(&rp->p_vmspace->vm_map,
-                                   (u_int)bp->b_un.b_addr + i * NBPG,
-                                   VM_PROT_READ, FALSE);
-                               if (rv)
-                                       panic("DMA to nonexistent page");
-                       }
-               }
-       }
-       io = &uh->uh_mr[reg];
-       while (--npf > 0) {
-               pfnum = pte->pg_pfn;
-               if (pfnum == 0)
-                       panic("uba zero uentry");
-               pte++;
-               *(int *)io++ = pfnum | temp;
-       }
-       *(int *)io = 0;
        return (ubinfo);
 }
 
@@ -460,9 +674,10 @@ ubasetup(uban, bp, flags)
  * Non buffer setup interface... set up a buffer and call ubasetup.
  */
 int
-uballoc(uban, addr, bcnt, flags)
+uballoc(uh, addr, bcnt, flags)
+       struct  uba_softc *uh;
        caddr_t addr;
-       int     uban, bcnt, flags;
+       int     bcnt, flags;
 {
        struct buf ubabuf;
 
@@ -470,7 +685,7 @@ uballoc(uban, addr, bcnt, flags)
        ubabuf.b_flags = B_BUSY;
        ubabuf.b_bcount = bcnt;
        /* that's all the fields ubasetup() needs */
-       return (ubasetup(uban, &ubabuf, flags));
+       return (ubasetup(uh, &ubabuf, flags));
 }
  
 /*
@@ -479,10 +694,11 @@ uballoc(uban, addr, bcnt, flags)
  * against uba resets on 11/780's.
  */
 void
-ubarelse(uban, amr)
-       int uban, *amr;
+ubarelse(uh, amr)
+       struct  uba_softc *uh;
+       int     *amr;
 {
-       register struct uba_softc *uh = uba_cd.cd_devs[uban];
+       struct uba_unit *uu;
        register int bdp, reg, npf, s;
        int mr;
  
@@ -494,35 +710,18 @@ ubarelse(uban, amr)
        mr = *amr;
        if (mr == 0) {
                /*
-                * A ubareset() occurred before we got around
-                * to releasing the space... no need to bother.
-                */
-               splx(s);
-               return;
-       }
-       *amr = 0;
-       bdp = UBAI_BDP(mr);
-       if (bdp) {
-               switch (uh->uh_type) {
-#ifdef DWBUA
-               case DWBUA:
-                       BUA(uh->uh_uba)->bua_dpr[bdp] |= BUADPR_PURGE;
-                       break;
-#endif
-#ifdef DW780
-               case DW780:
-                       uh->uh_uba->uba_dpr[bdp] |= UBADPR_BNE;
-                       break;
-#endif
-#ifdef DW750
-               case DW750:
-                       uh->uh_uba->uba_dpr[bdp] |=
-                           UBADPR_PURGE|UBADPR_NXM|UBADPR_UCE;
-                       break;
-#endif
-               default:
-                       break;
-               }
+                * A ubareset() occurred before we got around
+                * to releasing the space... no need to bother.
+                */
+               splx(s);
+               return;
+       }
+       *amr = 0;
+       bdp = UBAI_BDP(mr);
+       if (bdp) {
+               if (uh->uh_ubapurge)
+                       (*uh->uh_ubapurge)(uh, bdp);
+
                uh->uh_bdpfree |= 1 << (bdp-1);         /* atomic */
                if (uh->uh_bdpwant) {
                        uh->uh_bdpwant = 0;
@@ -549,35 +748,10 @@ ubarelse(uban, amr)
                uh->uh_mrwant = 0;
                wakeup((caddr_t)&uh->uh_mrwant);
        }
-       while (uh->uh_actf && ubaqueue(uh->uh_actf, 1))
-               ;
-}
-
-void
-ubapurge(um)
-       register struct uba_ctlr *um;
-{
-       register struct uba_softc *uh = um->um_hd;
-       register int bdp = UBAI_BDP(um->um_ubinfo);
-
-       switch (uh->uh_type) {
-#ifdef DWBUA
-       case DWBUA:
-               BUA(uh->uh_uba)->bua_dpr[bdp] |= BUADPR_PURGE;
-               break;
-#endif
-#ifdef DW780
-       case DW780:
-               uh->uh_uba->uba_dpr[bdp] |= UBADPR_BNE;
-               break;
-#endif
-#ifdef DW750
-       case DW750:
-               uh->uh_uba->uba_dpr[bdp] |= UBADPR_PURGE|UBADPR_NXM|UBADPR_UCE;
-               break;
-#endif
-       default:
-               break;
+       while ((uu = uh->uh_resq.sqh_first)) {
+               SIMPLEQ_REMOVE_HEAD(&uh->uh_resq, uu, uu_resq);
+               if ((*uu->uu_ready)(uu) == 0)
+                       break;
        }
 }
 
@@ -589,29 +763,11 @@ ubainitmaps(uhp)
        if (uhp->uh_memsize > UBA_MAXMR)
                uhp->uh_memsize = UBA_MAXMR;
        rminit(uhp->uh_map, (long)uhp->uh_memsize, (long)1, "uba", UAMSIZ);
-       switch (uhp->uh_type) {
-#ifdef DWBUA
-       case DWBUA:
-               uhp->uh_bdpfree = (1<<NBDPBUA) - 1;
-               break;
-#endif
-#ifdef DW780
-       case DW780:
-               uhp->uh_bdpfree = (1<<NBDP780) - 1;
-               break;
-#endif
-#ifdef DW750
-       case DW750:
-               uhp->uh_bdpfree = (1<<NBDP750) - 1;
-               break;
-#endif
-       default:
-               break;
-       }
+       uhp->uh_bdpfree = (1 << uhp->uh_nbdp) - 1;
 }
 
 /*
- * Generate a reset on uba number uban.  Then
+ * Generate a reset on uba number uban.         Then
  * call each device that asked to be called during attach,
  * giving it a chance to clean up so as to be able to continue.
  */
@@ -626,82 +782,25 @@ ubareset(uban)
        uh->uh_users = 0;
        uh->uh_zvcnt = 0;
        uh->uh_xclu = 0;
-       uh->uh_actf = uh->uh_actl = 0;
+       SIMPLEQ_INIT(&uh->uh_resq);
        uh->uh_bdpwant = 0;
        uh->uh_mrwant = 0;
        ubainitmaps(uh);
        wakeup((caddr_t)&uh->uh_bdpwant);
        wakeup((caddr_t)&uh->uh_mrwant);
        printf("%s: reset", uh->uh_dev.dv_xname);
-       ubainit(uh);
-#ifdef notyet
-       ubameminit(uban);
-#endif
+       (*uh->uh_ubainit)(uh);
+
        for (i = 0; i < uh->uh_resno; i++)
                (*uh->uh_reset[i])(uh->uh_resarg[i]);
        printf("\n");
        splx(s);
 }
 
-/*
- * 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:
-               BUA(uba)->bua_csr |= BUACSR_UPI;
-               /* give devices time to recover from power fail */
-               DELAY(500000);
-               break;
-#endif
-#if DW780
-       case DW780:
-               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
-#ifdef DW750
-       case DW750:
-#endif
-#ifdef DW730
-       case DW730:
-#endif
-#ifdef QBA
-       case QBA:
-#endif
-#if DW750 || DW730 || QBA
-               mtpr(0, PR_IUR);
-               /* give devices time to recover from power fail */
-
-/* THIS IS PROBABLY UNNECESSARY */
-               DELAY(500000);
-/* END PROBABLY UNNECESSARY */
-
-#ifdef QBA
-               /*
-                * Re-enable local memory access
-                * from the Q-bus.
-                */
-               if (uhp->uh_type == QBA)
-                       *((u_short *)(uhp->uh_iopage + QIPCR)) = Q_LMEAE;
-#endif QBA
-               break;
-#endif DW750 || DW730 || QBA
-       }
-}
-
-#ifdef QBA
+#ifdef notyet
 /*
  * Determine the interrupt priority of a Q-bus
- * peripheral.  The device probe routine must spl6(),
+ * peripheral. The device probe routine must spl6(),
  * attempt to make the device request an interrupt,
  * delaying as necessary, then call this routine
  * before resetting the device.
@@ -709,329 +808,45 @@ ubainit(uhp)
 int
 qbgetpri()
 {
-#ifdef notyet
        int pri;
-       extern int cvec;
 
-       panic("qbgetpri");
        for (pri = 0x17; pri > 0x14; ) {
-               if (cvec && cvec != 0x200)      /* interrupted at pri */
+               if (rcvec && rcvec != 0x200)    /* interrupted at pri */
                        break;
                pri--;
                splx(pri - 1);
        }
-       (void) spl0();
+       spl0();
        return (pri);
-#else
-       return 0x17;
-#endif
-}
-#endif
-
-#ifdef DW780
-int    ubawedgecnt = 10;
-int    ubacrazy = 500;
-int    zvcnt_max = 5000;       /* in 8 sec */
-/*
- * This routine is called by the locore code to process a UBA
- * error on an 11/780 or 8600.  The arguments are passed
- * on the stack, and value-result (through some trickery).
- * In particular, the uvec argument is used for further
- * uba processing so the result aspect of it is very important.
- * 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;
-       register struct uba_regs *uba;
-{
-       register sr, s;
-
-       if (*uvec == 0) {
-               /*
-                * Declare dt as unsigned so that negative values
-                * are handled as >8 below, in case time was set back.
-                */
-               u_long  dt = time.tv_sec - uh->uh_zvtime;
-
-               uh->uh_zvtotal++;
-               if (dt > 8) {
-                       uh->uh_zvtime = time.tv_sec;
-                       uh->uh_zvcnt = 0;
-               }
-               if (++uh->uh_zvcnt > zvcnt_max) {
-                       printf("uba%d: too many zero vectors (%d in <%d sec)\n",
-                               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,
-                               uba->uba_cnfgr&0xff);
-                       printf("\tsr: %b\n\tdcr: %x (MIC %sOK)\n",
-                               uba->uba_sr, ubasr_bits, uba->uba_dcr,
-                               (uba->uba_dcr&0x8000000)?"":"NOT ");
-                       ubareset(uban);
-               }
-               return;
-       }
-       if (uba->uba_cnfgr & NEX_CFGFLT) {
-               printf("uba%d: sbi fault sr=%b cnfgr=%b\n",
-                   uban, uba->uba_sr, ubasr_bits,
-                   uba->uba_cnfgr, NEXFLT_BITS);
-               ubareset(uban);
-               *uvec = 0;
-               return;
-       }
-       sr = uba->uba_sr;
-       s = spluba();
-       printf("uba%d: uba error sr=%b fmer=%x fubar=%o\n",
-           uban, uba->uba_sr, ubasr_bits, uba->uba_fmer, 4*uba->uba_fubar);
-       splx(s);
-       uba->uba_sr = sr;
-       *uvec &= UBABRRVR_DIV;
-       if (++uh->uh_errcnt % ubawedgecnt == 0) {
-               if (uh->uh_errcnt > ubacrazy)
-                       panic("uba crazy");
-               printf("ERROR LIMIT ");
-               ubareset(uban);
-               *uvec = 0;
-               return;
-       }
-       return;
-}
-#endif
-
-/*
- * Look for devices with unibus memory, allow them to configure, then disable
- * map registers as necessary.  Called during autoconfiguration and ubareset.
- * The device ubamem routine returns 0 on success, 1 on success if it is fully
- * configured (has no csr or interrupt, so doesn't need to be probed),
- * and -1 on failure.
- */
-#ifdef notyet
-ubameminit(uban)
-{
-       register struct uba_device *ui;
-       register struct uba_softc *uh = uba_cd.cd_devs[uban];
-       caddr_t umembase, addr;
-#define        ubaoff(off)     ((int)(off) & 0x1fff)
-
-       umembase = uh->uh_iopage;
-       uh->uh_lastmem = 0;
-       for (ui = ubdinit; ui->ui_driver; ui++) {
-               if (ui->ui_ubanum != uban && ui->ui_ubanum != '?')
-                       continue;
-               if (ui->ui_driver->ud_ubamem) {
-                       /*
-                        * During autoconfiguration, need to fudge ui_addr.
-                        */
-                       addr = ui->ui_addr;
-                       ui->ui_addr = umembase + ubaoff(addr);
-                       switch ((*ui->ui_driver->ud_ubamem)(ui, uban)) {
-                       case 1:
-                               ui->ui_alive = 1;
-                               /* FALLTHROUGH */
-                       case 0:
-                               ui->ui_ubanum = uban;
-                               break;
-                       }
-                       ui->ui_addr = addr;
-               }
-       }
-#ifdef DW780
-jdhfgsjdkfhgsdjkfghak
-       /*
-        * On a DW780, throw away any map registers disabled by rounding
-        * the map disable in the configuration register
-        * up to the next 8K boundary, or below the last unibus memory.
-        */
-       if (uh->uh_type == DW780) {
-               register i;
-
-               i = btop(((uh->uh_lastmem + 8191) / 8192) * 8192);
-               while (i)
-                       (void) rmget(uh->uh_map, 1, i--);
-       }
-#endif
-}
-#endif
-
-/*
- * Allocate UNIBUS memory.  Allocates and initializes
- * sufficient mapping registers for access.  On a 780,
- * the configuration register is setup to disable UBA
- * response on DMA transfers to addresses controlled
- * by the disabled mapping registers.
- * On a DW780, should only be called from ubameminit, or in ascending order
- * from 0 with 8K-sized and -aligned addresses; freeing memory that isn't
- * 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 = uba_cd.cd_devs[uban];
-       register int a;
-       int s;
-
-       a = (addr >> 9) + 1;
-       s = spluba();
-       if (doalloc)
-               panic("uba: rmget");
-/*             a = rmget(uh->uh_map, npg, a); */
-       else
-               rmfree(uh->uh_map, (long)npg, (long)a);
-       splx(s);
-       if (a) {
-               register int i, *m;
-
-               m = (int *)&uh->uh_mr[a - 1];
-               for (i = 0; i < npg; i++)
-                       *m++ = 0;       /* All off, especially 'valid' */
-               i = addr + npg * 512;
-               if (doalloc && i > uh->uh_lastmem)
-                       uh->uh_lastmem = i;
-               else if (doalloc == 0 && i == uh->uh_lastmem)
-                       uh->uh_lastmem = addr;
-#ifdef DW780
-               /*
-                * On a 780, set up the map register disable
-                * field in the configuration register.  Beware
-                * of callers that request memory ``out of order''
-                * or in sections other than 8K multiples.
-                * Ubameminit handles such requests properly, however.
-                */
-               if (uh->uh_type == DW780) {
-                       i = uh->uh_uba->uba_cr &~ 0x7c000000;
-                       i |= ((uh->uh_lastmem + 8191) / 8192) << 26;
-                       uh->uh_uba->uba_cr = i;
-               }
-#endif
-       }
-       return (a);
-}
-
-#include "ik.h"
-#include "vs.h"
-#if NIK > 0 || NVS > 0
-/*
- * Map a virtual address into users address space. Actually all we
- * do is turn on the user mode write protection bits for the particular
- * page of memory involved.
- */
-maptouser(vaddress)
-       caddr_t vaddress;
-{
-
-       kvtopte(vaddress)->pg_prot = (PG_UW >> 27);
-}
-
-unmaptouser(vaddress)
-       caddr_t vaddress;
-{
-
-       kvtopte(vaddress)->pg_prot = (PG_KW >> 27);
-}
-#endif
-
-#ifdef DW780
-void
-uba_dw780int(uba)
-       int     uba;
-{
-       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;
-       void *vcf, *aux;
-{
-       struct sbi_attach_args *sa = (struct sbi_attach_args *)aux;
-       struct cfdata *cf = vcf;
-
-       if ((cf->cf_loc[0] != sa->nexnum) && (cf->cf_loc[0] > -1 ))
-               return 0;
-
-       switch (sa->type) {
-       case NEX_UBA0:
-               sa->nexinfo = 0;
-               break;
-       case NEX_UBA1:
-               sa->nexinfo = 1;
-               break;
-       case NEX_UBA2:
-               sa->nexinfo = 2;
-               break;
-       case NEX_UBA3:
-               sa->nexinfo = 3;
-               break;
-       
-       default:
-               return 0;
-       }
-       return 1;
-}
-
-/*
- * The attach routines:
+ * The common attach routines:
  *   Allocates interrupt vectors.
- *   Puts correct (cpu-specific) addresses in uba_softc.
+ *   Puts correct values in uba_softc.
  *   Calls the scan routine to search for uba devices.
  */
 void
-uba_attach(parent, self, aux)
-       struct device *parent, *self;
-       void *aux;
+uba_attach(sc, iopagephys)
+       struct uba_softc *sc;
+       unsigned long iopagephys;
 {
-       struct sbi_attach_args *sa = (struct sbi_attach_args *)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;
+       vm_offset_t     mini, maxi;
        extern  struct  ivec_dsp idsptch;
 
-       printf("\n");
        /*
-        * Allocate place for unibus memory in virtual space.
-        * This is done with kmem_suballoc() but after that
-        * never used in the vm system. Is it OK to do so?
+        * Set last free interrupt vector for devices with
+        * programmable interrupt vectors.  Use is to decrement
+        * this number and use result as interrupt vector.
         */
-       (void)kmem_suballoc(kernel_map, &min, &max,
-           (UBAPAGES + UBAIOPAGES) * NBPG, FALSE);
-       sc->uh_mem = (caddr_t)min;
-       sc->uh_uba = (void*)ubar;
-       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;
+       sc->uh_lastiv = 0x200;
+       SIMPLEQ_INIT(&sc->uh_resq);
+
        /*
         * Create interrupt dispatchers for this uba.
         */
-#define        NO_IVEC 128
+#define NO_IVEC 128
        {
                vm_offset_t     iarea;
                int     i;
@@ -1048,81 +863,15 @@ uba_attach(parent, self, aux)
                        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;
-               sc->uh_type = DW750;
-               sc->uh_physuba = (struct uba_regs *)kvtophys(sa->nexaddr);
-               ubaphys = UMEM750(sa->nexinfo);
-               ubaiophys = UMEM750(sa->nexinfo) + (UBAPAGES * NBPG);
-               break;
-#endif
-#if VAX630 || VAX410
-       case VAX_78032:
-               switch (cpu_type) {
-#if VAX630
-               case VAX_630:
-                       sc->uh_mr = (void *)sa->nexaddr;
-                       sc->uh_type = QBA;
-                       sc->uh_physuba = (void*)QBAMAP630;
-                       ubaphys = QMEM630;
-                       ubaiophys = QIOPAGE630;
-                       break;
-#endif
-               default:
-                       ubaphys = QMEM630;
-                       ubaiophys = QIOPAGE630;
-               };
-               break;
-#endif
-#if VAX650
-       case VAX_650:
-               sc->uh_mr = (void *)sa->nexaddr;
-               sc->uh_type = QBA;
-               sc->uh_physuba = (void*)QBAMAP630; /* XXX */
-               ubaphys = QMEM630; /* XXX */
-               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.
+        * Allocate place for unibus memory in virtual space.
+        * This is done with kmem_suballoc() but after that
+        * never used in the vm system. Is it OK to do so?
         */
-       pmap_map(min, ubaphys, ubaphys + (UBAPAGES * NBPG),
+       (void)kmem_suballoc(kernel_map, &mini, &maxi, UBAIOPAGES * NBPG, FALSE);
+       pmap_map(mini, iopagephys, iopagephys + UBAIOPAGES * NBPG,
            VM_PROT_READ|VM_PROT_WRITE);
-       pmap_map(min + (UBAPAGES * NBPG), ubaiophys, ubaiophys + 
-           (UBAIOPAGES * NBPG), VM_PROT_READ|VM_PROT_WRITE);
-#if VAX630 || VAX650
-       /* Enable access to local memory. */
-       if (cpu_type == VAX_630 || cpunumber == VAX_650)
-               *((u_short *)(sc->uh_iopage + QIPCR)) = Q_LMEAE;
-#endif
+       sc->uh_iopage = (void *)mini;
        /*
         * Initialize the UNIBUS, by freeing the map
         * registers and the buffered data path registers
@@ -1132,51 +881,21 @@ uba_attach(parent, self, aux)
        bzero((caddr_t)sc->uh_map, (unsigned)(UAMSIZ * sizeof (struct map)));
        ubainitmaps(sc);
 
-       /*
-        * Set last free interrupt vector for devices with
-        * programmable interrupt vectors.  Use is to decrement
-        * this number and use result as interrupt vector.
-        */
-       sc->uh_lastiv = 0x200;
-
-#ifdef DWBUA
-        if (sc->uh_type == DWBUA)
-                BUA(ubar)->bua_offset = (int)sc->uh_vec - (int)&scb[0];
-#endif
-
-#ifdef DW780
-        if (sc->uh_type == DW780) {
-                ubar->uba_sr = ubar->uba_sr;
-                ubar->uba_cr = UBACR_IFS|UBACR_BRIE;
-        }
-#endif
-#ifdef notyet
-       /*
-        * First configure devices that have unibus memory,
-        * allowing them to allocate the correct map registers.
-        */
-       ubameminit(uhp->uh_dev.dv_unit);
-#endif
        /*
         * 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.
-        * ??? - Why? This is rpb page... /ragge
+        * for devices which will need to dma to produce an interrupt.
         */
        *(int *)(&sc->uh_mr[0]) = UBAMR_MRV;
 
+       if (sc->uh_beforescan)
+               (*sc->uh_beforescan)(sc);
        /*
         * Now start searching for devices.
         */
-       unifind(sc, (caddr_t)ubaiophys);/* Some devices are not yet converted */
-       config_scan(ubascan,self);
-
-#ifdef DW780
-       if (sc->uh_type == DW780)
-               ubar->uba_cr = UBACR_IFS | UBACR_BRIE |
-                   UBACR_USEFIE | UBACR_SUEFIE |
-                   (ubar->uba_cr & 0x7c000000);
-#endif
+       config_scan(ubascan,(struct device *)sc);
 
+       if (sc->uh_afterscan)
+               (*sc->uh_afterscan)(sc);
 }
 
 void
@@ -1187,31 +906,21 @@ 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_addr = (caddr_t)((int)sc->uh_iopage + ubdevreg(cf->cf_loc[0]));
        ua.ua_reset = NULL;
 
-       if (badaddr(ua.ua_addr, 2))
+       if (badaddr(ua.ua_addr, 2) || (sc->uh_errchk ? (*sc->uh_errchk)(sc):0))
                goto forgetit;
 
-#ifdef DW780
-       if (sc->uh_type == DW780 && ubar->uba_sr) {
-               ubar->uba_sr = ubar->uba_sr;
-               goto forgetit;
-       }
-#endif
        rcvec = 0x200;
        i = (*cf->cf_attach->ca_match) (parent, dev, &ua);
 
-#ifdef DW780
-       if (sc->uh_type == DW780 && ubar->uba_sr) {
-               ubar->uba_sr = ubar->uba_sr;
-               goto forgetit;
-       }
-#endif
+       if (sc->uh_errchk)
+               if ((*sc->uh_errchk)(sc))
+                       goto forgetit;
        if (i == 0)
                goto forgetit;
 
@@ -1220,13 +929,21 @@ ubascan(parent, match)
                
        sc->uh_idsp[rcvec].hoppaddr = ua.ua_ivec;
        sc->uh_idsp[rcvec].pushlarg = dev->dv_unit;
-       if (ua.ua_reset) { /* device wants ubaeset */
+       if (ua.ua_reset) { /* device wants ubraeset */
                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 = (int *)sc->uh_reset + 128;
+               }
+#ifdef DIAGNOSTIC
+               if (sc->uh_resno > 127) {
+                       printf("%s: Expand reset table, skipping reset %s\n",
+                           sc->uh_dev.dv_xname, dev->dv_xname);
+               } else
+#endif
+               {
+                       sc->uh_resarg[sc->uh_resno] = dev->dv_unit;
+                       sc->uh_reset[sc->uh_resno++] = ua.ua_reset;
                }
-               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;
index d63093e..823ae52 100644 (file)
@@ -1,4 +1,4 @@
-/*     $NetBSD: ubareg.h,v 1.7 1996/04/08 18:37:35 ragge Exp $ */
+/*     $NetBSD: ubareg.h,v 1.9 1996/08/20 13:38:02 ragge Exp $ */
 
 /*-
  * Copyright (c) 1982, 1986 The Regents of the University of California.
  */
 
 #if VAX780 || VAX8600
-#define        DW780   1               /* has adaptor regs, sr: 780/785/8600 */
+#define DW780  1               /* has adaptor regs, sr: 780/785/8600 */
 #else
 #undef DW780
 #endif
 
 
 #if VAX750
-#define        DW750   2               /* has adaptor regs, no sr: 750, 730 */
+#define DW750  2               /* has adaptor regs, no sr: 750, 730 */
 #endif
 
 #if VAX730
-#define        DW730   3               /* has adaptor regs, no sr: 750, 730 */
+#define DW730  3               /* has adaptor regs, no sr: 750, 730 */
 #endif
 
 #if VAX630 || VAX650
-#define        QBA     4               /* 22-bit Q-bus, no adaptor regs: uVAX II */
+#define QBA    4               /* 22-bit Q-bus, no adaptor regs: uVAX II */
 #endif
 
-#if VAX8200 || VAX8500 || VAX8800
-#define        DWBUA   5               /* BI UNIBUS adaptor: 8200/8500/8800 */
+#if 0 /* XXX  VAX8200 || VAX8500 || VAX8800 */
+#define DWBUA  5               /* BI UNIBUS adaptor: 8200/8500/8800 */
 #endif
 
 /*
  * QBAPAGES should be 8192, but we don't need nearly that much
  * address space, and the return from the allocation routine
  * can accommodate at most 2047 (ubavar.h: UBA_MAXMR);
- * QBAPAGES must be at least UBAPAGES.  Choose pragmatically.
+ * QBAPAGES must be at least UBAPAGES. Choose pragmatically.
  * 
  * Is there ever any need to have QBAPAGES != UBAPAGES???
  * Wont work now anyway, QBAPAGES _must_ be .eq. UBAPAGES.
  */
-#define        UBAPAGES        496
-#define        NUBMREG         496
-/* #if defined(GATEWAY) && !defined(QNIVERT) */
-/* #define     QBAPAGES        1024 */
-/* #else */
-#define        QBAPAGES        UBAPAGES
-/* #endif */
-#define        UBAIOADDR       0760000         /* start of I/O page */
-#define        UBAIOPAGES      16
+#define UBAPAGES       496
+#define NUBMREG                496
+#define        QBAPAGES        1024
+#define UBAIOADDR      0760000         /* start of I/O page */
+#define UBAIOPAGES     16
 
 #ifndef _LOCORE
 /*
@@ -112,39 +108,39 @@ struct dwbua_regs {
        int     pad3[10];
        int     bua_bdps[20];           /* buffered data path space *//*???*/
        int     pad4[8];
-       pt_entry_t bua_map[UBAPAGES];   /* unibus map registers */
+       struct pte bua_map[UBAPAGES];   /* unibus map registers */
        int     pad5[UBAIOPAGES];       /* no maps for device address space */
 };
 
 #ifdef DWBUA
 /* bua_csr */
-#define        BUACSR_ERR      0x80000000      /* composite error */
-#define        BUACSR_BIF      0x10000000      /* BI failure */
-#define        BUACSR_SSYNTO   0x08000000      /* slave sync timeout */
-#define        BUACSR_UIE      0x04000000      /* unibus interlock error */
-#define        BUACSR_IVMR     0x02000000      /* invalid map register */
-#define        BUACSR_BADBDP   0x01000000      /* bad BDP select */
-#define        BUACSR_BUAEIE   0x00100000      /* bua error interrupt enable (?) */
-#define        BUACSR_UPI      0x00020000      /* unibus power init */
-#define        BUACSR_UREGDUMP 0x00010000      /* microdiag register dump */
-#define        BUACSR_IERRNO   0x000000ff      /* mask for internal errror number */
+#define BUACSR_ERR     0x80000000      /* composite error */
+#define BUACSR_BIF     0x10000000      /* BI failure */
+#define BUACSR_SSYNTO  0x08000000      /* slave sync timeout */
+#define BUACSR_UIE     0x04000000      /* unibus interlock error */
+#define BUACSR_IVMR    0x02000000      /* invalid map register */
+#define BUACSR_BADBDP  0x01000000      /* bad BDP select */
+#define BUACSR_BUAEIE  0x00100000      /* bua error interrupt enable (?) */
+#define BUACSR_UPI     0x00020000      /* unibus power init */
+#define BUACSR_UREGDUMP 0x00010000     /* microdiag register dump */
+#define BUACSR_IERRNO  0x000000ff      /* mask for internal errror number */
 
 /* bua_offset */
-#define        BUAOFFSET_MASK  0x00003e00      /* hence max offset = 15872 */
+#define BUAOFFSET_MASK 0x00003e00      /* hence max offset = 15872 */
 
 /* bua_dpr */
-#define        BUADPR_DPSEL    0x00e00000      /* data path select (?) */
-#define        BUADPR_PURGE    0x00000001      /* purge bdp */
+#define BUADPR_DPSEL   0x00e00000      /* data path select (?) */
+#define BUADPR_PURGE   0x00000001      /* purge bdp */
 
 /* bua_map -- in particular, those bits that are not in DW780s & DW750s */
-#define        BUAMR_IOADR     0x40000000      /* I/O address space */
-#define        BUAMR_LAE       0x04000000      /* longword access enable */
+#define BUAMR_IOADR    0x40000000      /* I/O address space */
+#define BUAMR_LAE      0x04000000      /* longword access enable */
        /* I see no reason to use either one, though ... act 6 Aug 1987 */
 
-#define        UBA_PURGEBUA(uba, bdp) \
+#define UBA_PURGEBUA(uba, bdp) \
        (((struct dwbua_regs *)(uba))->bua_dpr[bdp] |= BUADPR_PURGE)
 #else
-#define        UBA_PURGEBUA(uba, bdp)
+#define UBA_PURGEBUA(uba, bdp)
 #endif
 
 /*
@@ -162,164 +158,131 @@ struct uba_regs {
        int     uba_brrvr[4];           /* receive vector registers */
        int     uba_dpr[16];            /* buffered data path register */
        int     pad2[480];
-       pt_entry_t uba_map[UBAPAGES];   /* unibus map register */
+       struct pte uba_map[UBAPAGES];   /* unibus map register */
        int     pad3[UBAIOPAGES];       /* no maps for device address space */
 };
 #endif
 
 #ifdef DW780
 /* uba_cnfgr */
-#define        UBACNFGR_UBINIT 0x00040000      /* unibus init asserted */
-#define        UBACNFGR_UBPDN  0x00020000      /* unibus power down */
-#define        UBACNFGR_UBIC   0x00010000      /* unibus init complete */
+#define UBACNFGR_UBINIT 0x00040000     /* unibus init asserted */
+#define UBACNFGR_UBPDN 0x00020000      /* unibus power down */
+#define UBACNFGR_UBIC  0x00010000      /* unibus init complete */
 
 #define UBACNFGR_BITS \
 "\40\40PARFLT\37WSQFLT\36URDFLT\35ISQFLT\34MXTFLT\33XMTFLT\30ADPDN\27ADPUP\23UBINIT\22UBPDN\21UBIC"
 
 /* uba_cr */
-#define        UBACR_MRD16     0x40000000      /* map reg disable bit 4 */
-#define        UBACR_MRD8      0x20000000      /* map reg disable bit 3 */
-#define        UBACR_MRD4      0x10000000      /* map reg disable bit 2 */
-#define        UBACR_MRD2      0x08000000      /* map reg disable bit 1 */
-#define        UBACR_MRD1      0x04000000      /* map reg disable bit 0 */
-#define        UBACR_IFS       0x00000040      /* interrupt field switch */
-#define        UBACR_BRIE      0x00000020      /* BR interrupt enable */
-#define        UBACR_USEFIE    0x00000010      /* UNIBUS to SBI error field IE */
-#define        UBACR_SUEFIE    0x00000008      /* SBI to UNIBUS error field IE */
-#define        UBACR_CNFIE     0x00000004      /* configuration IE */
-#define        UBACR_UPF       0x00000002      /* UNIBUS power fail */
-#define        UBACR_ADINIT    0x00000001      /* adapter init */
+#define UBACR_MRD16    0x40000000      /* map reg disable bit 4 */
+#define UBACR_MRD8     0x20000000      /* map reg disable bit 3 */
+#define UBACR_MRD4     0x10000000      /* map reg disable bit 2 */
+#define UBACR_MRD2     0x08000000      /* map reg disable bit 1 */
+#define UBACR_MRD1     0x04000000      /* map reg disable bit 0 */
+#define UBACR_IFS      0x00000040      /* interrupt field switch */
+#define UBACR_BRIE     0x00000020      /* BR interrupt enable */
+#define UBACR_USEFIE   0x00000010      /* UNIBUS to SBI error field IE */
+#define UBACR_SUEFIE   0x00000008      /* SBI to UNIBUS error field IE */
+#define UBACR_CNFIE    0x00000004      /* configuration IE */
+#define UBACR_UPF      0x00000002      /* UNIBUS power fail */
+#define UBACR_ADINIT   0x00000001      /* adapter init */
 
 /* uba_sr */
-#define        UBASR_BR7FULL   0x08000000      /* BR7 receive vector reg full */
-#define        UBASR_BR6FULL   0x04000000      /* BR6 receive vector reg full */
-#define        UBASR_BR5FULL   0x02000000      /* BR5 receive vector reg full */
-#define        UBASR_BR4FULL   0x01000000      /* BR4 receive vector reg full */
-#define        UBASR_RDTO      0x00000400      /* UNIBUS to SBI read data timeout */
-#define        UBASR_RDS       0x00000200      /* read data substitute */
-#define        UBASR_CRD       0x00000100      /* corrected read data */
-#define        UBASR_CXTER     0x00000080      /* command transmit error */
-#define        UBASR_CXTMO     0x00000040      /* command transmit timeout */
-#define        UBASR_DPPE      0x00000020      /* data path parity error */
-#define        UBASR_IVMR      0x00000010      /* invalid map register */
-#define        UBASR_MRPF      0x00000008      /* map register parity failure */
-#define        UBASR_LEB       0x00000004      /* lost error */
-#define        UBASR_UBSTO     0x00000002      /* UNIBUS select timeout */
-#define        UBASR_UBSSYNTO  0x00000001      /* UNIBUS slave sync timeout */
-
-#define        UBASR_BITS \
+#define UBASR_BR7FULL  0x08000000      /* BR7 receive vector reg full */
+#define UBASR_BR6FULL  0x04000000      /* BR6 receive vector reg full */
+#define UBASR_BR5FULL  0x02000000      /* BR5 receive vector reg full */
+#define UBASR_BR4FULL  0x01000000      /* BR4 receive vector reg full */
+#define UBASR_RDTO     0x00000400      /* UNIBUS to SBI read data timeout */
+#define UBASR_RDS      0x00000200      /* read data substitute */
+#define UBASR_CRD      0x00000100      /* corrected read data */
+#define UBASR_CXTER    0x00000080      /* command transmit error */
+#define UBASR_CXTMO    0x00000040      /* command transmit timeout */
+#define UBASR_DPPE     0x00000020      /* data path parity error */
+#define UBASR_IVMR     0x00000010      /* invalid map register */
+#define UBASR_MRPF     0x00000008      /* map register parity failure */
+#define UBASR_LEB      0x00000004      /* lost error */
+#define UBASR_UBSTO    0x00000002      /* UNIBUS select timeout */
+#define UBASR_UBSSYNTO 0x00000001      /* UNIBUS slave sync timeout */
+
+#define UBASR_BITS \
 "\20\13RDTO\12RDS\11CRD\10CXTER\7CXTMO\6DPPE\5IVMR\4MRPF\3LEB\2UBSTO\1UBSSYNTO"
 
 /* uba_brrvr[] */
-#define        UBABRRVR_AIRI   0x80000000      /* adapter interrupt request */
-#define        UBABRRVR_DIV    0x0000ffff      /* device interrupt vector field */
+#define UBABRRVR_AIRI  0x80000000      /* adapter interrupt request */
+#define UBABRRVR_DIV   0x0000ffff      /* device interrupt vector field */
 #endif
  
 /* uba_dpr */
 #ifdef DW780
-#define        UBADPR_BNE      0x80000000      /* buffer not empty - purge */
-#define        UBADPR_BTE      0x40000000      /* buffer transfer error */
-#define        UBADPR_DPF      0x20000000      /* DP function (RO) */
-#define        UBADPR_BS       0x007f0000      /* buffer state field */
-#define        UBADPR_BUBA     0x0000ffff      /* buffered UNIBUS address */
-#define        UBA_PURGE780(uba, bdp) \
-    ((uba)->uba_dpr[(int)bdp] |= UBADPR_BNE)
-#else
-#define UBA_PURGE780(uba, bdp)
+#define UBADPR_BNE     0x80000000      /* buffer not empty - purge */
+#define UBADPR_BTE     0x40000000      /* buffer transfer error */
+#define UBADPR_DPF     0x20000000      /* DP function (RO) */
+#define UBADPR_BS      0x007f0000      /* buffer state field */
+#define UBADPR_BUBA    0x0000ffff      /* buffered UNIBUS address */
 #endif
 #ifdef DW750
-#define        UBADPR_ERROR    0x80000000      /* error occurred */
-#define        UBADPR_NXM      0x40000000      /* nxm from memory */
-#define        UBADPR_UCE      0x20000000      /* uncorrectable error */
-#define        UBADPR_PURGE    0x00000001      /* purge bdp */
-/* the DELAY is for a hardware problem */
-#define        UBA_PURGE750(uba, bdp) { \
-    ((uba)->uba_dpr[(int)bdp] |= (UBADPR_PURGE|UBADPR_NXM|UBADPR_UCE)); \
-    {volatile int N=8;while(N--);} \
-}
-#else
-#define UBA_PURGE750(uba, bdp)
+#define UBADPR_ERROR   0x80000000      /* error occurred */
+#define UBADPR_NXM     0x40000000      /* nxm from memory */
+#define UBADPR_UCE     0x20000000      /* uncorrectable error */
+#define UBADPR_PURGE   0x00000001      /* purge bdp */
 #endif
 
-/*
- * Macros for fast buffered data path purging in time-critical routines.
- *
- * Too bad C pre-processor doesn't have the power of LISP in macro
- * expansion...
- */
-
-/* THIS IS WRONG, should use pointer to uba_hd */
-#if DWBUA || DW780 || DW750
-#define        UBAPURGE(uba, bdp) { \
-       switch (MACHID(cpu_type)) { \
-       case VAX_8200: UBA_PURGEBUA(uba, bdp); break; \
-       case VAX_8600: case VAX_780: UBA_PURGE780((uba), (bdp)); break; \
-       case VAX_750: UBA_PURGE750((uba), (bdp)); break; \
-       } \
-}
-#else
-#define        UBAPURGE(uba, bdp)
-#endif
-
-
-
 /* uba_mr[] */
-#define        UBAMR_MRV       0x80000000      /* map register valid */
-#define        UBAMR_BO        0x02000000      /* byte offset bit */
-#define        UBAMR_DPDB      0x01e00000      /* data path designator field */
-#define        UBAMR_SBIPFN    0x001fffff      /* SBI page address field */
+#define UBAMR_MRV      0x80000000      /* map register valid */
+#define UBAMR_BO       0x02000000      /* byte offset bit */
+#define UBAMR_DPDB     0x01e00000      /* data path designator field */
+#define UBAMR_SBIPFN   0x001fffff      /* SBI page address field */
 
-#define        UBAMR_DPSHIFT   21              /* shift to data path designator */
+#define UBAMR_DPSHIFT  21              /* shift to data path designator */
 
 /*
  * Number of unibus buffered data paths and possible uba's per cpu type.
  */
-#define        NBDP8600        15
-#define        NBDP780         15
-#define        NBDPBUA         5
-#define        NBDP750         3
-#define        NBDP730         0
-#define        MAXNBDP         15
+#define NBDP8600       15
+#define NBDP780                15
+#define NBDPBUA                5
+#define NBDP750                3
+#define NBDP730                0
+#define MAXNBDP                15
 
 /*
  * Symbolic BUS addresses for UBAs.
  */
 
 #if VAX630 || VAX650
-#define        QBAMAP630       ((struct pte *)0x20088000)
-#define        QMEM630         0x30000000
-#define        QIOPAGE630      0x20000000
+#define QBAMAP 0x20088000
+#define QMEM   0x30000000
+#define QIOPAGE        0x20000000
 /*
  * Q-bus control registers
  */
-#define        QIPCR           0x1f40          /* from start of iopage */
+#define QIPCR          0x1f40          /* from start of iopage */
 /* bits in QIPCR */
-#define        Q_DBIRQ         0x0001          /* doorbell interrupt request */
-#define        Q_LMEAE         0x0020          /* local mem external access enable */
-#define        Q_DBIIE         0x0040          /* doorbell interrupt enable */
-#define        Q_AUXHLT        0x0100          /* auxiliary processor halt */
-#define        Q_DMAQPE        0x8000          /* Q22 bus address space parity error */
+#define Q_DBIRQ                0x0001          /* doorbell interrupt request */
+#define Q_LMEAE                0x0020          /* local mem external access enable */
+#define Q_DBIIE                0x0040          /* doorbell interrupt enable */
+#define Q_AUXHLT       0x0100          /* auxiliary processor halt */
+#define Q_DMAQPE       0x8000          /* Q22 bus address space parity error */
 #endif
 
 #if VAX730
-#define        UMEM730         0xfc0000
+#define UMEM730                0xfc0000
 #endif
 
 #if VAX750
-#define        UMEM750(i)      (0xfc0000-(i)*0x40000)
+#define UMEM750(i)     (0xfc0000-(i)*0x40000)
 #endif
 
 #if VAX780
-#define        UMEM780(i)      (0x20100000+(i)*0x40000)
+#define UMEM780(i)     (0x20100000+(i)*0x40000)
 #endif
 
 #if VAX8200            /* BEWARE, argument is node, not ubanum */
-#define        UMEM8200(i)     (0x20400000+(i)*0x40000)
+#define UMEM8200(i)    (0x20400000+(i)*0x40000)
 #endif
 
 #if VAX8600 || VAX780
-#define        UMEMA8600(i)    (0x20100000+(i)*0x40000)
-#define        UMEMB8600(i)    (0x22100000+(i)*0x40000)
+#define UMEMA8600(i)   (0x20100000+(i)*0x40000)
+#define UMEMB8600(i)   (0x22100000+(i)*0x40000)
 #endif
 
 /*
@@ -327,4 +290,4 @@ struct uba_regs {
  * something like 0172520, by forcing it into the last 8K
  * of UNIBUS memory space.
  */
-#define        ubdevreg(addr)  ((addr) & 017777)
+#define ubdevreg(addr) ((addr) & 017777)
index c179cb4..50b84a0 100644 (file)
@@ -1,4 +1,4 @@
-/*     $NetBSD: ubavar.h,v 1.15 1996/04/08 18:37:36 ragge Exp $        */
+/*     $NetBSD: ubavar.h,v 1.18 1996/08/20 13:38:04 ragge Exp $        */
 
 /*
  * Copyright (c) 1982, 1986 Regents of the University of California.
  */
 struct uba_softc {
        struct  device uh_dev;          /* Device struct, autoconfig */
+       SIMPLEQ_HEAD(, uba_unit) uh_resq;       /* resource wait chain */
        int     uh_type;                /* type of adaptor */
        struct  uba_regs *uh_uba;       /* virt addr of uba adaptor regs */
-       struct  uba_regs *uh_physuba;   /* phys addr of uba adaptor regs */
        struct  pte *uh_mr;             /* start of page map */
        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    (**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 */
-       struct  uba_device *uh_actl;    /* tail of queue to transfer */
        short   uh_mrwant;              /* someone is waiting for map reg */
        short   uh_bdpwant;             /* someone awaits bdp's */
        int     uh_bdpfree;             /* free bdp's */
-       int     uh_hangcnt;             /* number of ticks hung */
        int     uh_zvcnt;               /* number of recent 0 vectors */
        long    uh_zvtime;              /* time over which zvcnt accumulated */
        int     uh_zvtotal;             /* total number of 0 vectors */
-       int     uh_errcnt;              /* number of errors */
        int     uh_lastiv;              /* last free interrupt vector */
        short   uh_users;               /* transient bdp use count */
        short   uh_xclu;                /* an rk07 is using this uba! */
        int     uh_lastmem;             /* limit of any unibus memory */
-#define        UAMSIZ  100
        struct  map *uh_map;            /* register free map */
+       int     (*uh_errchk) __P((struct uba_softc *));
+       void    (*uh_beforescan) __P((struct uba_softc *));
+       void    (*uh_afterscan) __P((struct uba_softc *));
+       void    (*uh_ubainit) __P((struct uba_softc *));
+       void    (*uh_ubapurge) __P((struct uba_softc *, int));
+#ifdef DW780
        struct  ivec_dsp uh_dw780;      /* Interrupt handles for DW780 */
+#endif
+       short   uh_nr;                  /* Unibus sequential number */
+       short   uh_nbdp;                /* # of BDP's */
 };
 
+#define        UAMSIZ  100
+
 /* given a pointer to uba_regs, find DWBUA registers */
 /* this should be replaced with a union in uba_softc */
 #define        BUA(uba)        ((struct dwbua_regs *)(uba))
 
 /*
  * Per-controller structure.
- * (E.g. one for each disk and tape controller, and other things
- * which use and release buffered data paths.)
- *
- * If a controller has devices attached, then there are
- * cross-referenced uba_drive structures.
- * This structure is the one which is queued in unibus resource wait,
- * and saves the information about unibus resources which are used.
- * The queue of devices waiting to transfer is also attached here.
+ * The unit struct is common to both the adapter and the controller
+ * to which it belongs. It is only used on controllers that handles
+ * BDP's, and calls the adapter queueing subroutines.
  */
-struct uba_ctlr {
-       struct  uba_driver *um_driver;
-       short   um_ctlr;        /* controller index in driver */
-       short   um_ubanum;      /* the uba it is on */
-       short   um_alive;       /* controller exists */
-       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 */
-       int     um_cmd;         /* communication to dgo() */
-       int     um_ubinfo;      /* save unibus registers, etc */
-       int     um_bdp;         /* for controllers that hang on to bdp's */
-       struct  buf um_tab;     /* queue of devices for this controller */
-};
-
-/*
- * Per ``device'' structure.
- * (A controller has devices or uses and releases buffered data paths).
- * (Everything else is a ``device''.)
- *
- * If a controller has many drives attached, then there will
- * be several uba_device structures associated with a single uba_ctlr
- * structure.
- *
- * This structure contains all the information necessary to run
- * a unibus device such as a dz or a dh.  It also contains information
- * for slaves of unibus controllers as to which device on the slave
- * this is.  A flags field here can also be given in the system specification
- * and is used to tell which dz lines are hard wired or other device
- * specific parameters.
- */
-struct uba_device {
-       struct  uba_driver *ui_driver;
-       short   ui_unit;        /* unit number on the system */
-       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) __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 */
-       short   ui_alive;       /* device exists */
-       short   ui_type;        /* driver specific type information */
-       caddr_t ui_physaddr;    /* phys addr, for standalone (dump) code */
-/* this is the forward link in a list of devices on a controller */
-       struct  uba_device *ui_forw;
-/* if the device is connected to a controller, this is the controller */
-       struct  uba_ctlr *ui_mi;
-       struct  uba_softc *ui_hd;
-};
-
-/*
- * Per-driver structure.
- *
- * Each unibus driver defines entries for a set of routines
- * as well as an array of types which are acceptable to it.
- * These are used at boot time by the configuration program.
- */
-struct uba_driver {
-           /* 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 */
-       char    *ud_mname;              /* name of a controller */
-       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) __P((struct uba_device *, int));
-           /* see if dedicated memory is present */
+struct uba_unit {
+       SIMPLEQ_ENTRY(uba_unit) uu_resq;/* Queue while waiting for resources */
+       void    *uu_softc;      /* Pointer to units softc */
+       int     uu_ubinfo;      /* save unibus registers, etc */
+       int     uu_bdp;         /* for controllers that hang on to bdp's */
+       int    (*uu_ready) __P((struct uba_unit *));
+       short   uu_xclu;        /* want exclusive use of bdp's */
+       short   uu_keepbdp;     /* hang on to bdp's once allocated */
 };
 
 /*
@@ -246,25 +177,17 @@ struct ubinfo {
 
 #ifndef _LOCORE
 #ifdef _KERNEL
-#define        ubago(ui)       ubaqueue(ui, 0)
-
-/*
- * Ubminit and ubdinit initialize the mass storage controller and
- * device tables specifying possible devices.
- */
-extern struct  uba_ctlr ubminit[];
-extern struct  uba_device ubdinit[];
+#define        ubago(ui)       ubaqueue(ui)
+#define b_forw  b_hash.le_next /* Nice to have when handling uba queues */
 
 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 *));
+int    uballoc __P((struct uba_softc *, caddr_t, int, int));
+void   ubarelse __P((struct uba_softc *, int *));
+int    ubaqueue __P((struct uba_unit *, struct buf *));
+void   ubadone __P((struct uba_unit *));
 void   ubareset __P((int));
-int    ubasetup __P((int, struct buf *, int));
 
 #endif /* _KERNEL */
 #endif !_LOCORE
index c911d3a..86fa0c2 100644 (file)
@@ -1,5 +1,6 @@
-/*     $NetBSD: uda.c,v 1.16 1996/05/19 16:43:42 ragge Exp $   */
+/*     $NetBSD: uda.c,v 1.23 1996/10/13 03:35:26 christos Exp $        */
 /*
+ * Copyright (c) 1996 Ludd, University of Lule}, Sweden.
  * Copyright (c) 1988 Regents of the University of California.
  * All rights reserved.
  *
  */
 
 /*
- * UDA50/MSCP device driver
+ * UDA50 disk device driver
  */
 
-#define        POLLSTATS
-
-/*
- * TODO
- *     write bad block forwarding code
- */
-
-#include "uda.h"
-#include "ra.h"
-
-/*
- * CONFIGURATION OPTIONS.  The next three defines are tunable -- tune away!
- *
- * COMPAT_42 enables 4.2/4.3 compatibility (label mapping)
- *
- * NRSPL2 and NCMDL2 control the number of response and command
- * packets respectively.  They may be any value from 0 to 7, though
- * setting them higher than 5 is unlikely to be of any value.
- * If you get warnings about your command ring being too small,
- * try increasing the values by one.
- *
- * MAXUNIT controls the maximum unit number (number of drives per
- * controller) we are prepared to handle.
- *
- * DEFAULT_BURST must be at least 1.
- */
-#define        COMPAT_42
-#define        todr()  0       /* XXX */
-#define        NRSPL2  5               /* log2 number of response packets */
-#define NCMDL2 5               /* log2 number of command packets */
-#define        MAXUNIT 8               /* maximum allowed unit number */
-#define        DEFAULT_BURST   4       /* default DMA burst size */
-
-#define        ALLSTEPS        (UDA_ERR|UDA_STEP4|UDA_STEP3|UDA_STEP2|UDA_STEP1)
-
-#define        STEP1MASK       (ALLSTEPS | UDA_IE | UDA_NCNRMASK)
-#define        STEP1GOOD       (UDA_STEP2 | UDA_IE | (NCMDL2 << 3) | NRSPL2)
-
-#define        STEP2MASK       (ALLSTEPS | UDA_IE | UDA_IVECMASK)
-#define        STEP2GOOD       (UDA_STEP3 | UDA_IE | (sc->sc_ivec >> 2))
-
-#define        STEP3MASK       ALLSTEPS
-#define        STEP3GOOD       UDA_STEP4
-
 #include <sys/param.h>
+#include <sys/kernel.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/pte.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/ubareg.h>
 #include <vax/uba/udareg.h>
-#include <vax/vax/mscp.h>
-#include <vax/vax/mscpvar.h>
-#include <machine/mtpr.h>
 
-extern int cold;
+#include <vax/mscp/mscp.h>
+#include <vax/mscp/mscpvar.h>
+#include <vax/mscp/mscpreg.h>
 
 /*
- * This macro is for delay during init. Some MSCP clone card (Dilog)
- * can't handle fast read from its registers, and therefore need
- * a delay between them.
+ * Variants of SIMPLEQ macros for use with buf structs.
  */
-#define DELAYTEN 1000
-#define Wait_step( mask, result, status ) {                            \
-               status = 1;                                             \
-               if ((udaddr->udasa & mask) != result) {                 \
-                       volatile int count = 0;                         \
-                       while ((udaddr->udasa & mask) != result) {      \
-                               DELAY(10000);                           \
-                               count += 1;                             \
-                               if (count > DELAYTEN)                   \
-                                       break;                          \
-                       }                                               \
-                       if (count > DELAYTEN)                           \
-                               status = 0;                             \
-               }                                                       \
-       }
+#define BUFQ_INSERT_TAIL(head, elm) {                                  \
+       (elm)->b_actf = NULL;                                           \
+       *(head)->sqh_last = (elm);                                      \
+       (head)->sqh_last = &(elm)->b_actf;                              \
+}
 
-/*
- * UDA communications area and MSCP packet pools, per controller.
- */
-struct uda {
-       struct  udaca uda_ca;           /* communications area */
-       struct  mscp uda_rsp[NRSP];     /* response packets */
-       struct  mscp uda_cmd[NCMD];     /* command packets */
-};
+#define BUFQ_REMOVE_HEAD(head, elm) {                                  \
+       if (((head)->sqh_first = (elm)->b_actf) == NULL)                \
+               (head)->sqh_last = &(head)->sqh_first;                  \
+}
 
 /*
  * Software status, per controller.
  */
 struct uda_softc {
-       struct  uda *sc_uuda;   /* Unibus address of uda struct */
-       struct  uda sc_uda;     /* Struct for uda communication */
-       short   sc_state;       /* UDA50 state; see below */
-       short   sc_flags;       /* flags; see below */
-       int     sc_micro;       /* microcode revision */
-       int     sc_ivec;        /* interrupt vector address */
+       struct  device sc_dev;  /* Autoconfig info */
+       struct  uba_unit sc_unit; /* Struct common for UBA to communicate */
+       SIMPLEQ_HEAD(, buf) sc_bufq;    /* bufs awaiting for resources */
+       struct  mscp_pack *sc_uuda;     /* Unibus address of uda struct */
+       struct  mscp_pack sc_uda;       /* Struct for uda communication */
+       struct  udadevice *sc_udadev;   /* pointer to ip/sa regs */
+       struct  mscp *sc_mscp;          /* Keep pointer to active mscp */
        short   sc_ipl;         /* interrupt priority, Q-bus */
-       struct  mscp_info sc_mi;/* MSCP info (per mscpvar.h) */
-#ifndef POLLSTATS
+       struct  mscp_softc *sc_softc;   /* MSCP info (per mscpvar.h) */
        int     sc_wticks;      /* watchdog timer ticks */
-#else
-       short   sc_wticks;
-       short   sc_ncmd;
-#endif
-} uda_softc[NUDA];
+};
 
-#ifdef POLLSTATS
-struct udastats {
-       int     ncmd;
-       int     cmd[NCMD + 1];
-} udastats = { NCMD + 1 };
-#endif
+static int     udamatch __P((struct device *, void *, void *));
+static void    udaattach __P((struct device *, struct device *, void *));
+static void    udareset __P((int));
+static void    mtcreset __P((int));
+static void    reset __P((struct uda_softc *));
+static void    udaintr __P((int));
+static void    mtcintr __P((int));
+static void    intr __P((struct uda_softc *));
+int    udaready __P((struct uba_unit *));
+void   udactlrdone __P((struct device *, int));
+int    udaprint __P((void *, const char *));
+void   udasaerror __P((struct device *, int));
+int    udago __P((struct device *, struct buf *));
+
+struct cfdriver mtc_cd = {
+       NULL, "mtc", DV_DULL
+};
 
-int    udamatch __P((struct device *, void *, void *));
-void   uda_attach __P((struct device *, struct device *, void *));
+struct cfattach mtc_ca = {
+       sizeof(struct uda_softc), udamatch, udaattach
+};
 
 struct cfdriver uda_cd = {
        NULL, "uda", DV_DULL
 };
 
 struct cfattach uda_ca = {
-       sizeof(struct device), udamatch, uda_attach
+       sizeof(struct uda_softc), udamatch, udaattach
 };
 
-/*
- * Controller states
- */
-#define        ST_IDLE         0       /* uninitialised */
-#define        ST_STEP1        1       /* in `STEP 1' */
-#define        ST_STEP2        2       /* in `STEP 2' */
-#define        ST_STEP3        3       /* in `STEP 3' */
-#define        ST_SETCHAR      4       /* in `Set Controller Characteristics' */
-#define        ST_RUN          5       /* up and running */
-
-/*
- * Flags
- */
-#define        SC_MAPPED       0x01    /* mapped in Unibus I/O space */
-#define        SC_INSTART      0x02    /* inside udastart() */
-#define        SC_GRIPED       0x04    /* griped about cmd ring too small */
-#define        SC_INSLAVE      0x08    /* inside udaslave() */
-#define        SC_DOWAKE       0x10    /* wakeup when ctlr init done */
-#define        SC_STARTPOLL    0x20    /* need to initiate polling */
-
-/*
- * Device to unit number and partition and back
- */
-#define        UNITSHIFT       3
-#define        UNITMASK        7
-#define        udaunit(dev)    (minor(dev) >> UNITSHIFT)
-#define        udapart(dev)    (minor(dev) & UNITMASK)
-#define        udaminor(u, p)  (((u) << UNITSHIFT) | (p))
-
-/*
- * Drive status, per drive
- */
-struct ra_info {
-       daddr_t ra_dsize;       /* size in sectors */
-/*     u_long  ra_type;        /* drive type */
-       u_long  ra_mediaid;     /* media id */
-       int     ra_state;       /* open/closed state */
-       struct  ra_geom {       /* geometry information */
-               u_short rg_nsectors;    /* sectors/track */
-               u_short rg_ngroups;     /* track groups */
-               u_short rg_ngpc;        /* groups/cylinder */
-               u_short rg_ntracks;     /* ngroups*ngpc */
-               u_short rg_ncyl;        /* ra_dsize/ntracks/nsectors */
-#ifdef notyet
-               u_short rg_rctsize;     /* size of rct */
-               u_short rg_rbns;        /* replacement blocks per track */
-               u_short rg_nrct;        /* number of rct copies */
-#endif
-       } ra_geom;
-       int     ra_wlabel;      /* label sector is currently writable */
-       u_long  ra_openpart;    /* partitions open */
-       u_long  ra_bopenpart;   /* block partitions open */
-       u_long  ra_copenpart;   /* character partitions open */
-} ra_info[NRA];
-
-/*
- * Software state, per drive
- */
-#define        CLOSED          0
-#define        WANTOPEN        1
-#define        RDLABEL         2
-#define        OPEN            3
-#define        OPENRAW         4
-
-/*
- * Definition of the driver for autoconf.
- */
-int    udaprobe __P((caddr_t, int, struct uba_ctlr *, struct uba_softc *));
-int    udaslave __P((struct uba_device *, caddr_t));
-void   udaattach __P((struct uba_device *));
-void   udadgo __P((struct uba_ctlr *));
-void   udaintr __P((int));
-
-struct uba_ctlr *udaminfo[NUDA];
-struct uba_device *udadinfo[NRA];
-struct disklabel udalabel[NRA];
-
-u_short        udastd[] = { 0 };
-struct uba_driver udadriver =
- { udaprobe, udaslave, udaattach, udadgo, udastd, "ra", udadinfo, "uda",
-   udaminfo };
-
 /*
  * More driver definitions, for generic MSCP code.
  */
-void    udadgram __P((struct mscp_info *, struct mscp *));
-void    udactlrdone __P((struct mscp_info *, struct mscp *));
-int     udaunconf __P((struct mscp_info *, struct mscp *));
-void    udaiodone __P((struct mscp_info *, struct buf *, int)); 
-int     udaonline __P((struct uba_device *, struct mscp *));
-int     udagotstatus __P((struct uba_device *, struct mscp *));
-void    udareplace __P((struct uba_device *, struct mscp *));
-int     udaioerror __P((struct uba_device *, struct mscp *, struct buf *));
-void    udabb __P((struct uba_device *, struct mscp *, struct buf *));
-
-struct buf udautab[NRA];       /* per drive transfer queue */
-
-struct mscp_driver udamscpdriver =
- { MAXUNIT, NRA, UNITSHIFT, udautab, udalabel, udadinfo,
-   udadgram, udactlrdone, udaunconf, udaiodone,
-   udaonline, udagotstatus, udareplace, udaioerror, udabb,
-   "uda", "ra" };
+struct mscp_ctlr uda_mscp_ctlr = {
+       udactlrdone,
+       udago,
+       udasaerror,
+};
 
 /*
  * Miscellaneous private variables.
  */
-char   udasr_bits[] = UDASR_BITS;
+static int     ivec_no;
 
-struct uba_device *udaip[NUDA][MAXUNIT];
-                               /* inverting pointers: ctlr & unit => Unibus
-                                  device pointer */
-
-int    udaburst[NUDA] = { 0 }; /* burst size, per UDA50, zero => default;
-                                  in data space so patchable via adb */
-
-struct mscp udaslavereply;     /* get unit status response packet, set
-                                  for udaslave by udaunconf, via udaintr */
-
-static struct uba_ctlr *probeum;/* this is a hack---autoconf should pass ctlr
-                                  info to slave routine; instead, we remember
-                                  the last ctlr argument to probe */
-
-int    udawstart;
-void   udawatch();     /* watchdog timer */
-
-/*
- * Externals
- */
-int    hz;
+int
+udaprint(aux, name)
+       void    *aux;
+       const char      *name;
+{
+       if (name)
+               printf("%s: mscpbus", name);
+       return UNCONF;
+}
 
 /*
  * Poke at a supposed UDA50 to see if it is there.
- * This routine duplicates some of the code in udainit() only
- * because autoconf has not set up the right information yet.
- * We have to do everything `by hand'.
  */
 int
 udamatch(parent, match, aux)
-       struct device *parent;
-       void *match, *aux;
-{
-       return 0;
-}
-
-void
-uda_attach(parent, self, aux)
-       struct device *parent, *self;
-       void *aux;
-{
-}
-
-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;
-       struct mscp_info *mi;
-       struct uba_softc *ubasc;
-       extern int cpu_type;
-       int timeout, tries, count;
-#ifdef notyet
+       struct  device *parent;
+       void    *match, *aux;
+{
+       struct  uba_attach_args *ua = aux;
+       struct  device *dev = match;
+       struct  mscp_softc mi;  /* Nice hack */
+       struct  uba_softc *ubasc;
+       int     tries;
+#if QBA && notyet
+       extern volatile int rbr;
        int s;
 #endif
 
-#ifdef VAX750
-       /*
-        * The UDA50 wants to share BDPs on 750s, but not on 780s or
-        * 8600s.  (730s have no BDPs anyway.)  Toward this end, we
-        * here set the `keep bdp' flag in the per-driver information
-        * if this is a 750.  (We just need to do it once, but it is
-        * easiest to do it now, for each UDA50.)
-        */
-       if (MACHID(cpu_type) == VAX_750)
-               udadriver.ud_keepbdp = 1;
-#endif
-       probeum = um;                   /* remember for udaslave() */
-       /*
-        * Set up the controller-specific generic MSCP driver info.
-        * Note that this should really be done in the (nonexistent)
-        * controller attach routine.
-        */
-       sc = &uda_softc[ctlr];
-       mi = &sc->sc_mi;
-       mi->mi_md = &udamscpdriver;
-       mi->mi_ctlr = um->um_ctlr;
-       mi->mi_tab = (void*)&um->um_tab;
-       mi->mi_ip = udaip[ctlr];
-       mi->mi_cmd.mri_size = NCMD;
-       mi->mi_cmd.mri_desc = sc->sc_uda.uda_ca.ca_cmddsc;
-       mi->mi_cmd.mri_ring = sc->sc_uda.uda_cmd;
-       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;
-       mi->mi_wtab.b_actf = &mi->mi_wtab;
+       /* Get an interrupt vector. */
+       ubasc = (void *)parent;
+       ivec_no = ubasc->uh_lastiv - 4;
 
-       /*
-        * More controller specific variables.  Again, this should
-        * be in the controller attach routine.
-        */
-       if (udaburst[ctlr] == 0)
-               udaburst[ctlr] = DEFAULT_BURST;
-               
-       /*
-        * Get an interrupt vector.  Note that even if the controller
-        * does not respond, we keep the vector.  This is not a serious
-        * problem; but it would be easily fixed if we had a controller
-        * attach routine.  Sigh.
-        */
-       ubasc = uhp;
-       sc->sc_ivec = ubasc->uh_lastiv -= 4;
-       udaddr = (struct udadevice *) reg;
+       mi.mi_sa = &((struct udadevice *)ua->ua_addr)->udasa;
+       mi.mi_ip = &((struct udadevice *)ua->ua_addr)->udaip;
 
        /*
         * Initialise the controller (partially).  The UDA50 programmer's
@@ -408,961 +175,165 @@ udaprobe(reg, ctlr, um, uhp)
         * initialise within ten seconds.  Or so I hear; I have not seen
         * this manual myself.
         */
-#ifdef notyet
+#if 0
        s = spl6();
 #endif
        tries = 0;
 again:
-       udaddr->udaip = 0;              /* start initialisation */
 
-       count = 0;
-       while ( count < DELAYTEN ) {
-               if ( (udaddr->udasa & UDA_STEP1) != 0 )
-                       break;
-               DELAY(10000);
-               count += 1;
-       }
+       *mi.mi_ip = 0;
+       if (mscp_waitstep(&mi, MP_STEP1, MP_STEP1) == 0)
+               return 0; /* Nothing here... */
 
-       /* nothing there */
-       if ( count == DELAYTEN )
-               return(0);
+       *mi.mi_sa = MP_ERR | (NCMDL2 << 11) | (NRSPL2 << 8) | MP_IE |
+               (ivec_no >> 2);
 
-       udaddr->udasa = UDA_ERR | (NCMDL2 << 11) | (NRSPL2 << 8) | UDA_IE |
-               (sc->sc_ivec >> 2);
-
-       count = 0;
-       while (count < DELAYTEN) {
-               if ((udaddr->udasa & UDA_STEP2 ) != 0)
-                   break;
-               DELAY(10000);
-               count += 1;
-       }
-
-       if (count == DELAYTEN) {
-               printf("udaprobe: uda%d: init step2 no change.\n",
-                   um->um_ctlr);
+       if (mscp_waitstep(&mi, MP_STEP2, MP_STEP2) == 0) {
+               printf("udaprobe: init step2 no change. sa=%x\n", *mi.mi_sa);
                goto bad;
        }
 
        /* should have interrupted by now */
-#ifdef notyet
-       sc->sc_ipl = br = qbgetpri();
-#else
-       sc->sc_ipl = 0x15;
-#endif
-       return (sizeof (struct udadevice));
-bad:
-       if (++tries < 2)
-               goto again;
-#ifdef notyet
-       splx(s);
-#endif
-       return (0);
-}
-
-/*
- * Find a slave.  We allow wildcard slave numbers (something autoconf
- * is not really prepared to deal with); and we need to know the
- * controller number to talk to the UDA.  For the latter, we keep
- * track of the last controller probed, since a controller probe
- * immediately precedes all slave probes for that controller.  For the
- * former, we simply put the unit number into ui->ui_slave after we
- * have found one.
- *
- * Note that by the time udaslave is called, the interrupt vector
- * for the UDA50 has been set up (so that udaunconf() will be called).
- */
-udaslave(ui, reg)
-       register struct uba_device *ui;
-       caddr_t reg;
-{
-       register struct uba_ctlr *um = probeum;
-       volatile struct mscp *mp;
-       volatile struct uda_softc *sc;
-       int next = 0, timeout, tries;
-       volatile int i;
-
-#ifdef lint
-       i = 0; i = i;
+#if 0
+       rbr = qbgetpri();
 #endif
-       /*
-        * Make sure the controller is fully initialised, by waiting
-        * for it if necessary.
-        */
-       sc = &uda_softc[um->um_ctlr];
-       if (sc->sc_state == ST_RUN)
-               goto findunit;
-       tries = 0;
-again:
-       if (udainit(ui->ui_ctlr))
-               return (0);
-       timeout = 1000;
-       while (timeout-- > 0) {
-               DELAY(10000);
-               if (sc->sc_state == ST_RUN)
-                       goto findunit;
+       if (strcmp(dev->dv_cfdata->cf_driver->cd_name, mtc_cd.cd_name)) {
+               ua->ua_ivec = udaintr;
+               ua->ua_reset = udareset;
+       } else {
+               ua->ua_ivec = mtcintr;
+               ua->ua_reset = mtcreset;
        }
 
+       return 1;
+bad:
        if (++tries < 2)
                goto again;
-       printf("uda%d: controller hung\n", um->um_ctlr);
-       return (0);
-
-       /*
-        * The controller is all set; go find the unit.  Grab an
-        * MSCP packet and send out a Get Unit Status command, with
-        * the `next unit' modifier if we are looking for a generic
-        * unit.  We set the `in slave' flag so that udaunconf()
-        * knows to copy the response to `udaslavereply'.
-        */
-findunit:
-       udaslavereply.mscp_opcode = 0;
-       sc->sc_flags |= SC_INSLAVE;
-       if ((mp = mscp_getcp((void *)&sc->sc_mi, MSCP_DONTWAIT)) == NULL)
-               panic("udaslave");              /* `cannot happen' */
-       mp->mscp_opcode = M_OP_GETUNITST;
-       if (ui->ui_slave == '?') {
-               mp->mscp_unit = next;
-               mp->mscp_modifier = M_GUM_NEXTUNIT;
-       } else {
-               mp->mscp_unit = ui->ui_slave;
-               mp->mscp_modifier = 0;
-       }
-       *mp->mscp_addr |= MSCP_OWN | MSCP_INT;
-       i = ((struct udadevice *) reg)->udaip;  /* initiate polling */
-       mp = &udaslavereply;
-       timeout = 1000;
-       while (timeout-- > 0) {
-               DELAY(10000);
-               if (mp->mscp_opcode)
-                       goto gotit;
-       }
-       printf("uda%d: no response to Get Unit Status request\n",
-           um->um_ctlr);
-       sc->sc_flags &= ~SC_INSLAVE;
-       return (0);
-
-gotit:
-       sc->sc_flags &= ~SC_INSLAVE;
-
-       /*
-        * Got a slave response.  If the unit is there, use it.
-        */
-       switch (mp->mscp_status & M_ST_MASK) {
-
-       case M_ST_SUCCESS:      /* worked */
-       case M_ST_AVAILABLE:    /* found another drive */
-               break;          /* use it */
-
-       case M_ST_OFFLINE:
-               /*
-                * Figure out why it is off line.  It may be because
-                * it is nonexistent, or because it is spun down, or
-                * for some other reason.
-                */
-               switch (mp->mscp_status & ~M_ST_MASK) {
-
-               case M_OFFLINE_UNKNOWN:
-                       /*
-                        * No such drive, and there are none with
-                        * higher unit numbers either, if we are
-                        * using M_GUM_NEXTUNIT.
-                        */
-                       return (0);
-
-               case M_OFFLINE_UNMOUNTED:
-                       /*
-                        * The drive is not spun up.  Use it anyway.
-                        *
-                        * N.B.: this seems to be a common occurrance
-                        * after a power failure.  The first attempt
-                        * to bring it on line seems to spin it up
-                        * (and thus takes several minutes).  Perhaps
-                        * we should note here that the on-line may
-                        * take longer than usual.
-                        */
-                       break;
-
-               default:
-                       /*
-                        * In service, or something else equally unusable.
-                        */
-                       printf("uda%d: unit %d off line: ", um->um_ctlr,
-                               mp->mscp_unit);
-                       mscp_printevent((void *)mp);
-                       goto try_another;
-               }
-               break;
-
-       default:
-               printf("uda%d: unable to get unit status: ", um->um_ctlr);
-               mscp_printevent((void *)mp);
-               return (0);
-       }
-
-       /*
-        * Does this ever happen?  What (if anything) does it mean?
-        */
-       if (mp->mscp_unit < next) {
-               printf("uda%d: unit %d, next %d\n",
-                       um->um_ctlr, mp->mscp_unit, next);
-               return (0);
-       }
-
-       if (mp->mscp_unit >= MAXUNIT) {
-               printf("uda%d: cannot handle unit number %d (max is %d)\n",
-                       um->um_ctlr, mp->mscp_unit, MAXUNIT - 1);
-               return (0);
-       }
-
-       /*
-        * See if we already handle this drive.
-        * (Only likely if ui->ui_slave=='?'.)
-        */
-       if (udaip[um->um_ctlr][mp->mscp_unit] != NULL) {
-try_another:
-               if (ui->ui_slave != '?')
-                       return (0);
-               next = mp->mscp_unit + 1;
-               goto findunit;
-       }
-
-       /*
-        * Voila!
-        */
-       uda_rasave(ui->ui_unit, mp, 0);
-       ui->ui_flags = 0;       /* not on line, nor anything else */
-       ui->ui_slave = mp->mscp_unit;
-       return (1);
-}
-
-/*
- * Attach a found slave.  Make sure the watchdog timer is running.
- * If this disk is being profiled, fill in the `wpms' value (used by
- * what?).  Set up the inverting pointer, and attempt to bring the
- * drive on line and read its label.
- */
-void
-udaattach(ui)
-       register struct uba_device *ui;
-{
-       register int unit = ui->ui_unit;
-
-       if (udawstart == 0) {
-               timeout(udawatch, (caddr_t) 0, hz);
-               udawstart++;
-       }
-
-       /*
-        * Floppies cannot be brought on line unless there is
-        * a disk in the drive.  Since an ONLINE while cold
-        * takes ten seconds to fail, and (when notyet becomes now)
-        * no sensible person will swap to one, we just
-        * defer the ONLINE until someone tries to use the drive.
-        *
-        * THIS ASSUMES THAT DRIVE TYPES ?X? ARE FLOPPIES
-        */
-       if (MSCP_MID_ECH(1, ra_info[unit].ra_mediaid) == 'X' - '@') {
-               printf(": floppy");
-               return;
-       }
-       if (ui->ui_dk >= 0)
-               dk_wpms[ui->ui_dk] = (60 * 31 * 256);   /* approx */
-       udaip[ui->ui_ctlr][ui->ui_slave] = ui;
-
-       if (uda_rainit(ui, 0))
-               printf(": offline");
-       else if (ra_info[unit].ra_state == OPEN) {
-               printf(": %s, size = %d sectors",
-                   udalabel[unit].d_typename, ra_info[unit].ra_dsize);
-#ifdef notyet
-               addswap(makedev(UDADEVNUM, udaminor(unit, 0)), &udalabel[unit]);
-#endif
-       }
-}
-
-/*
- * Initialise a UDA50.  Return true iff something goes wrong.
- */
-udainit(ctlr)
-       int ctlr;
-{
-       register struct uda_softc *sc;
-       volatile struct udadevice *udaddr;
-       struct uba_ctlr *um;
-       int timo, ubinfo, count, i, wait_status;
-       unsigned short hej;
-/* printf("udainit\n"); */
-       sc = &uda_softc[ctlr];
-       um = udaminfo[ctlr];
-       if ((sc->sc_flags & SC_MAPPED) == 0) {
-               /*
-                * Map the communication area and command and
-                * response packets into Unibus space.
-                */
-               ubinfo = uballoc(um->um_ubanum, (caddr_t) &sc->sc_uda,
-                       sizeof (struct uda), UBA_CANTWAIT);
-               if (ubinfo == 0) {
-                       printf("uda%d: uballoc map failed\n", ctlr);
-                       return (-1);
-               }
-               sc->sc_uuda = (struct uda *) UBAI_ADDR(ubinfo);
-               sc->sc_flags |= SC_MAPPED;
-       }
-       bzero(&sc->sc_uda, sizeof (struct uda));
-
-       /*
-        * While we are thinking about it, reset the next command
-        * and response indicies.
-        */
-       sc->sc_mi.mi_cmd.mri_next = 0;
-       sc->sc_mi.mi_rsp.mri_next = 0;
-
-       /*
-        * Start up the hardware initialisation sequence.
-        */
-#define        STEP0MASK       (UDA_ERR | UDA_STEP4 | UDA_STEP3 | UDA_STEP2 | \
-                        UDA_STEP1 | UDA_NV)
-
-       sc->sc_state = ST_IDLE; /* in case init fails */
-       udaddr = (struct udadevice *)um->um_addr;
-       udaddr->udaip = 0;
-       count = 0;
-       while (count < DELAYTEN) {
-               if ((udaddr->udasa & UDA_STEP1) != 0)
-                       break;
-               DELAY(10000);
-               count += 1;
-       }
-       if (count == DELAYTEN) {
-               printf("uda%d: timeout during init\n", ctlr);
-               return (-1);
-       }
-
-       if ((udaddr->udasa & STEP0MASK) != UDA_STEP1) {
-               printf("uda%d: init failed, sa=%b\n", ctlr,
-                       udaddr->udasa, udasr_bits);
-               udasaerror(um, 0);
-               return (-1);
-       }
-
-       /*
-        * Success!  Record new state, and start step 1 initialisation.
-        * The rest is done in the interrupt handler.
-        */
-       sc->sc_state = ST_STEP1;
-       udaddr->udasa = UDA_ERR | (NCMDL2 << 11) | (NRSPL2 << 8) | UDA_IE |
-           (sc->sc_ivec >> 2);
-
-       return (0);
-}
-
-/*
- * Open a drive.
- */
-/*ARGSUSED*/
-udaopen(dev, flag, fmt)
-       dev_t dev;
-       int flag, fmt;
-{
-       register int unit;
-       register struct uba_device *ui;
-       register struct uda_softc *sc;
-       register struct disklabel *lp;
-       register struct partition *pp;
-       register struct ra_info *ra;
-       int s, i, part, mask, error = 0;
-       daddr_t start, end;
-/* printf("udaopen\n"); */
-       /*
-        * Make sure this is a reasonable open request.
-        */
-       unit = udaunit(dev);
-       if (unit >= NRA || (ui = udadinfo[unit]) == 0 || ui->ui_alive == 0)
-               return (ENXIO);
-
-       /*
-        * Make sure the controller is running, by (re)initialising it if
-        * necessary.
-        */
-       sc = &uda_softc[ui->ui_ctlr];
-       s = splbio();
-       if (sc->sc_state != ST_RUN) {
-               if (sc->sc_state == ST_IDLE && udainit(ui->ui_ctlr)) {
-                       splx(s);
-                       return (EIO);
-               }
-               /*
-                * In case it does not come up, make sure we will be
-                * restarted in 10 seconds.  This corresponds to the
-                * 10 second timeouts in udaprobe() and udaslave().
-                */
-               sc->sc_flags |= SC_DOWAKE;
-               timeout(wakeup, (caddr_t) sc, 10 * hz);
-               sleep((caddr_t) sc, PRIBIO);
-               if (sc->sc_state != ST_RUN) {
-                       splx(s);
-                       printf("uda%d: controller hung\n", ui->ui_ctlr);
-                       return (EIO);
-               }
-               untimeout(wakeup, (caddr_t) sc);
-       }
-
-       /*
-        * Wait for the state to settle
-        */
-       ra = &ra_info[unit];
-       while (ra->ra_state != OPEN && ra->ra_state != OPENRAW &&
-           ra->ra_state != CLOSED)
-               if (error = tsleep((caddr_t)ra, (PZERO + 1) | PCATCH,
-                   devopn, 0)) {
-                       splx(s);
-                       return (error);
-               }
-
-       /*
-        * If not on line, or we are not sure of the label, reinitialise
-        * the drive.
-        */
-       if ((ui->ui_flags & UNIT_ONLINE) == 0 ||
-           (ra->ra_state != OPEN && ra->ra_state != OPENRAW))
-               error = uda_rainit(ui, flag);
+#if 0
        splx(s);
-       if (error)
-               return (error);
-
-       part = udapart(dev);
-       lp = &udalabel[unit];
-       if (part >= lp->d_npartitions)
-               return (ENXIO);
-       /*
-        * Warn if a partition is opened that overlaps another
-        * already open, unless either is the `raw' partition
-        * (whole disk).
-        */
-#define        RAWPART         2       /* 'c' partition */     /* XXX */
-       mask = 1 << part;
-       if ((ra->ra_openpart & mask) == 0 && part != RAWPART) {
-               pp = &lp->d_partitions[part];
-               start = pp->p_offset;
-               end = pp->p_offset + pp->p_size;
-               for (pp = lp->d_partitions, i = 0;
-                    i < lp->d_npartitions; pp++, i++) {
-                       if (pp->p_offset + pp->p_size <= start ||
-                           pp->p_offset >= end || i == RAWPART)
-                               continue;
-                       if (ra->ra_openpart & (1 << i))
-                               log(LOG_WARNING,
-                                   "ra%d%c: overlaps open partition (%c)\n",
-                                   unit, part + 'a', i + 'a');
-               }
-       }
-       switch (fmt) {
-       case S_IFCHR:
-               ra->ra_copenpart |= mask;
-               break;
-       case S_IFBLK:
-               ra->ra_bopenpart |= mask;
-               break;
-       }
-       ra->ra_openpart |= mask;
-       return (0);
-}
-
-/* ARGSUSED */
-udaclose(dev, flags, fmt)
-       dev_t dev;
-       int flags, fmt;
-{
-       register int unit = udaunit(dev);
-       register struct ra_info *ra = &ra_info[unit];
-       int s, mask = (1 << udapart(dev));
-/* printf("udaclose\n"); */
-       switch (fmt) {
-       case S_IFCHR:
-               ra->ra_copenpart &= ~mask;
-               break;
-       case S_IFBLK:
-               ra->ra_bopenpart &= ~mask;
-               break;
-       }
-       ra->ra_openpart = ra->ra_copenpart | ra->ra_bopenpart;
-
-       /*
-        * Should wait for I/O to complete on this partition even if
-        * others are open, but wait for work on blkflush().
-        */
-       if (ra->ra_openpart == 0) {
-               s = splbio();
-               while (udautab[unit].b_actf)
-                       sleep((caddr_t)&udautab[unit], PZERO - 1);
-               splx(s);
-               ra->ra_state = CLOSED;
-               ra->ra_wlabel = 0;
-       }
-       return (0);
-}
-
-/*
- * Initialise a drive.  If it is not already, bring it on line,
- * and set a timeout on it in case it fails to respond.
- * When on line, read in the pack label.
- */
-uda_rainit(ui, flags)
-       volatile struct uba_device *ui;
-       int flags;
-{
-       register struct uda_softc *sc = &uda_softc[ui->ui_ctlr];
-       register struct disklabel *lp;
-       register struct mscp *mp;
-       register int unit = ui->ui_unit;
-       register struct ra_info *ra;
-       char *msg, *readdisklabel();
-       int s, i;
-       volatile int hej;
-       void udastrategy();
-       extern int cold;
-
-       ra = &ra_info[unit];
-       if ((ui->ui_flags & UNIT_ONLINE) == 0) {
-               mp = mscp_getcp(&sc->sc_mi, MSCP_WAIT);
-               mp->mscp_opcode = M_OP_ONLINE;
-               mp->mscp_unit = ui->ui_slave;
-               mp->mscp_cmdref = (long)&ui->ui_flags;
-               *mp->mscp_addr |= MSCP_OWN | MSCP_INT;
-               ra->ra_state = WANTOPEN;
-               if (!cold)
-                       s = splbio();
-               hej = ((struct udadevice *)ui->ui_addr)->udaip;
-
-               if (cold) {
-                       i = 1000;
-                       while ((ui->ui_flags & UNIT_ONLINE) == 0) {
-                               DELAY(10000);
-                               if (i-- < 0)
-                                       break;
-                       }
-               } else {
-                       timeout(wakeup, (caddr_t)&ui->ui_flags, 10 * hz);
-                       sleep((caddr_t)&ui->ui_flags, PSWP + 1);
-                       splx(s);
-                       untimeout(wakeup, (caddr_t)&ui->ui_flags);
-               }
-               if (ra->ra_state != OPENRAW) {
-                       ra->ra_state = CLOSED;
-                       wakeup((caddr_t)ra);
-                       return (EIO);
-               }
-       }
-
-       lp = &udalabel[unit];
-       lp->d_secsize = DEV_BSIZE;
-       lp->d_secperunit = ra->ra_dsize;
-
-       if (flags & O_NDELAY)
-               return (0);
-       ra->ra_state = RDLABEL;
-       /*
-        * Set up default sizes until we have the label, or longer
-        * if there is none.  Set secpercyl, as readdisklabel wants
-        * to compute b_cylin (although we do not need it), and set
-        * nsectors in case diskerr is called.
-        */
-       lp->d_secpercyl = 1;
-       lp->d_npartitions = 1;
-       lp->d_secsize = 512;
-       lp->d_secperunit = ra->ra_dsize;
-       lp->d_nsectors = ra->ra_geom.rg_nsectors;
-       lp->d_partitions[0].p_size = lp->d_secperunit;
-       lp->d_partitions[0].p_offset = 0;
-
-       /*
-        * Read pack label.
-        */
-       if ((msg = readdisklabel(udaminor(unit, 0), udastrategy, lp,NULL))
-                       != NULL) {
-               if (cold)
-                       printf(": %s", msg);
-               else
-                       log(LOG_ERR, "ra%d: %s", unit, msg);
-#ifdef COMPAT_42
-               if (udamaptype(unit, lp))
-                       ra->ra_state = OPEN;
-               else
-                       ra->ra_state = OPENRAW;
-#else
-               ra->ra_state = OPENRAW;
-               uda_makefakelabel(ra, lp);
 #endif
-       } else
-               ra->ra_state = OPEN;
-       wakeup((caddr_t)ra);
-       return (0);
-}
-
-/*
- * Copy the geometry information for the given ra from a
- * GET UNIT STATUS response.  If check, see if it changed.
- */
-uda_rasave(unit, mp, check)
-       int unit;
-       register struct mscp *mp;
-       int check;
-{
-       register struct ra_info *ra = &ra_info[unit];
-/* printf("uda_rasave\n"); */
-       if (check && ra->ra_mediaid != mp->mscp_guse.guse_mediaid) {
-               printf("ra%d: changed types! was %d now %d\n", unit,
-                       ra->ra_mediaid, mp->mscp_guse.guse_mediaid);
-               ra->ra_state = CLOSED;  /* ??? */
-       }
-       /* ra->ra_type = mp->mscp_guse.guse_drivetype; */
-       ra->ra_mediaid = mp->mscp_guse.guse_mediaid;
-       ra->ra_geom.rg_nsectors = mp->mscp_guse.guse_nspt;
-       ra->ra_geom.rg_ngroups = mp->mscp_guse.guse_group;
-       ra->ra_geom.rg_ngpc = mp->mscp_guse.guse_ngpc;
-       ra->ra_geom.rg_ntracks = ra->ra_geom.rg_ngroups * ra->ra_geom.rg_ngpc;
-       /* ra_geom.rg_ncyl cannot be computed until we have ra_dsize */
-#ifdef notyet
-       ra->ra_geom.rg_rctsize = mp->mscp_guse.guse_rctsize;
-       ra->ra_geom.rg_rbns = mp->mscp_guse.guse_nrpt;
-       ra->ra_geom.rg_nrct = mp->mscp_guse.guse_nrct;
-#endif
-}
-
-/*
- * Queue a transfer request, and if possible, hand it to the controller.
- *
- * This routine is broken into two so that the internal version
- * udastrat1() can be called by the (nonexistent, as yet) bad block
- * revectoring routine.
- */
-void
-udastrategy(bp)
-       register struct buf *bp;
-{
-       register int unit;
-       register struct uba_device *ui;
-       register struct ra_info *ra;
-       struct partition *pp;
-       int p;
-       daddr_t sz, maxsz;
-/* printf("udastrategy\n"); */
-       /*
-        * Make sure this is a reasonable drive to use.
-        */
-       if ((unit = udaunit(bp->b_dev)) >= NRA ||
-           (ui = udadinfo[unit]) == NULL || ui->ui_alive == 0 ||
-           (ra = &ra_info[unit])->ra_state == CLOSED) {
-               bp->b_error = ENXIO;
-               goto bad;
-       }
-
-       /*
-        * If drive is open `raw' or reading label, let it at it.
-        */
-       if (ra->ra_state < OPEN) {
-               udastrat1(bp);
-               return;
-       }
-       p = udapart(bp->b_dev);
-       if ((ra->ra_openpart & (1 << p)) == 0) {
-               bp->b_error = ENODEV;
-               goto bad;
-       }
-
-       /*
-        * Determine the size of the transfer, and make sure it is
-        * within the boundaries of the partition.
-        */
-       pp = &udalabel[unit].d_partitions[p];
-       maxsz = pp->p_size;
-       if (pp->p_offset + pp->p_size > ra->ra_dsize)
-               maxsz = ra->ra_dsize - pp->p_offset;
-       sz = (bp->b_bcount + DEV_BSIZE - 1) >> DEV_BSHIFT;
-       if (bp->b_blkno + pp->p_offset <= LABELSECTOR &&
-#if LABELSECTOR != 0
-           bp->b_blkno + pp->p_offset + sz > LABELSECTOR &&
-#endif
-           (bp->b_flags & B_READ) == 0 && ra->ra_wlabel == 0) {
-               bp->b_error = EROFS;
-               goto bad;
-       }
-       if (bp->b_blkno < 0 || bp->b_blkno + sz > maxsz) {
-               /* if exactly at end of disk, return an EOF */
-               if (bp->b_blkno == maxsz) {
-                       bp->b_resid = bp->b_bcount;
-                       biodone(bp);
-                       return;
-               }
-               /* or truncate if part of it fits */
-               sz = maxsz - bp->b_blkno;
-               if (sz <= 0) {
-                       bp->b_error = EINVAL;   /* or hang it up */
-                       goto bad;
-               }
-               bp->b_bcount = sz << DEV_BSHIFT;
-       }
-       udastrat1(bp);
-       return;
-bad:
-       bp->b_flags |= B_ERROR;
-       biodone(bp);
-}
-
-/*
- * Work routine for udastrategy.
- */
-udastrat1(bp)
-       register struct buf *bp;
-{
-       register int unit = udaunit(bp->b_dev);
-       register struct uba_ctlr *um;
-       register struct buf *dp;
-       struct uba_device *ui;
-       int s = splbio();
-/* printf("udastrat1\n"); */
-       /*
-        * Append the buffer to the drive queue, and if it is not
-        * already there, the drive to the controller queue.  (However,
-        * if the drive queue is marked to be requeued, we must be
-        * awaiting an on line or get unit status command; in this
-        * case, leave it off the controller queue.)
-        */
-       um = (ui = udadinfo[unit])->ui_mi;
-       dp = &udautab[unit];
-       MSCP_APPEND(bp, dp, b_actf);
-       if (dp->b_active == 0 && (ui->ui_flags & UNIT_REQUEUE) == 0) {
-               MSCP_APPEND(dp, &um->um_tab, b_hash.le_next);
-               dp->b_active++;
-       }
-/* Was:  MSCP_APPEND(bp, dp, av_forw);
-        if (dp->b_active == 0 && (ui->ui_flags & UNIT_REQUEUE) == 0) {
-                MSCP_APPEND(dp, &um->um_tab, b_forw);
-                dp->b_active++;
-        }
-*/
-       /*
-        * Start activity on the controller.  Note that unlike other
-        * Unibus drivers, we must always do this, not just when the
-        * controller is not active.
-        */
-       udastart(um);
-       splx(s);
-}
-
-int
-udaread(dev, uio)
-        dev_t dev;
-        struct uio *uio;
-{
-
-        return (physio(udastrategy, NULL, dev, B_READ, minphys, uio));
-}
-
-int
-udawrite(dev, uio)
-        dev_t dev;
-        struct uio *uio;
-{
-
-        return (physio(udastrategy, NULL, dev, B_WRITE, minphys, uio));
+       return 0;
 }
 
-/*
- * Start up whatever transfers we can find.
- * Note that udastart() must be called at splbio().
- */
-udastart(um)
-       register struct uba_ctlr *um;
-{
-       volatile struct uda_softc *sc = &uda_softc[um->um_ctlr];
-       register struct buf *bp, *dp;
-       register struct mscp *mp;
-       struct uba_device *ui;
-       volatile struct udadevice *udaddr;
-       struct partition *pp;
-       int sz;
-       volatile int i;
-/* printf("udastart\n"); */
-#ifdef lint
-       i = 0; i = i;
-#endif
-       /*
-        * If it is not running, try (again and again...) to initialise
-        * it.  If it is currently initialising just ignore it for now.
-        */
-       if (sc->sc_state != ST_RUN) {
-               if (sc->sc_state == ST_IDLE && udainit(um->um_ctlr))
-                       printf("uda%d: still hung\n", um->um_ctlr);
-               return;
-       }
-
-       /*
-        * If um_cmd is nonzero, this controller is on the Unibus
-        * resource wait queue.  It will not help to try more requests;
-        * instead, when the Unibus unblocks and calls udadgo(), we
-        * will call udastart() again.
-        */
-       if (um->um_cmd)
-               return;
+void
+udaattach(parent, self, aux)
+       struct device *parent, *self;
+       void *aux;
+{
+       struct  uda_softc *sc = (void *)self;
+       struct  uba_attach_args *ua = aux;
+       struct  uba_softc *uh = (void *)parent;
+       struct  mscp_attach_args ma;
+       int     ctlr, ubinfo;
 
-       sc->sc_flags |= SC_INSTART;
-       udaddr = (struct udadevice *) um->um_addr;
+       printf("\n");
 
-loop:
-       /*
-        * Service the drive at the head of the queue.  It may not
-        * need anything, in which case it might be shutting down
-        * in udaclose().
-        */
-       if ((dp = um->um_tab.b_actf) == NULL)
-               goto out;
-       if ((bp = dp->b_actf) == NULL) {
-               dp->b_active = 0;
-               um->um_tab.b_actf = dp->b_hash.le_next;
-/* Was:                um->um_tab.b_actf = dp->b_forw; */
-               if (ra_info[dp - udautab].ra_openpart == 0)
-                       wakeup((caddr_t)dp); /* finish close protocol */
-               goto loop;
-       }
+       uh->uh_lastiv -= 4;     /* remove dynamic interrupt vector */
+#ifdef QBA
+       sc->sc_ipl = ua->ua_br;
+#endif
 
-       if (udaddr->udasa & UDA_ERR) {  /* ctlr fatal error */
-               udasaerror(um, 1);
-               goto out;
-       }
+       ctlr = sc->sc_dev.dv_unit;
+       sc->sc_udadev = (struct udadevice *)ua->ua_addr;
+       SIMPLEQ_INIT(&sc->sc_bufq);
 
        /*
-        * Get an MSCP packet, then figure out what to do.  If
-        * we cannot get a command packet, the command ring may
-        * be too small:  We should have at least as many command
-        * packets as credits, for best performance.
+        * Fill in the uba_unit struct, so we can communicate with the uba.
         */
-       if ((mp = mscp_getcp((void*)&sc->sc_mi, MSCP_DONTWAIT)) == NULL) {
-               if (sc->sc_mi.mi_credits > MSCP_MINCREDITS &&
-                   (sc->sc_flags & SC_GRIPED) == 0) {
-                       log(LOG_NOTICE, "uda%d: command ring too small\n",
-                               um->um_ctlr);
-                       sc->sc_flags |= SC_GRIPED;/* complain only once */
-               }
-               goto out;
-       }
+       sc->sc_unit.uu_softc = sc;      /* Backpointer to softc */
+       sc->sc_unit.uu_ready = udaready;/* go routine called from adapter */
+       sc->sc_unit.uu_keepbdp = vax_cputype == VAX_750 ? 1 : 0;
 
        /*
-        * Bring the drive on line if it is not already.  Get its status
-        * if we do not already have it.  Otherwise just start the transfer.
+        * Map the communication area and command and
+        * response packets into Unibus space.
         */
-       ui = udadinfo[udaunit(bp->b_dev)];
-       if ((ui->ui_flags & UNIT_ONLINE) == 0) {
-               mp->mscp_opcode = M_OP_ONLINE;
-               goto common;
+       ubinfo = uballoc((struct uba_softc *)sc->sc_dev.dv_parent,
+           (caddr_t) &sc->sc_uda, sizeof (struct mscp_pack), UBA_CANTWAIT);
+
+#ifdef DIAGNOSTIC
+       if (ubinfo == 0) {
+               printf("%s: uballoc map failed\n", sc->sc_dev.dv_xname);
+               return;
        }
-       if ((ui->ui_flags & UNIT_HAVESTATUS) == 0) {
-               mp->mscp_opcode = M_OP_GETUNITST;
-common:
-if (ui->ui_flags & UNIT_REQUEUE) panic("udastart");
-               /*
-                * Take the drive off the controller queue.  When the
-                * command finishes, make sure the drive is requeued.
-                */
-               um->um_tab.b_actf = dp->b_hash.le_next;
-/* Was:                um->um_tab.b_actf = dp->b_forw; */
-               dp->b_active = 0;
-               ui->ui_flags |= UNIT_REQUEUE;
-               mp->mscp_unit = ui->ui_slave;
-               *mp->mscp_addr |= MSCP_OWN | MSCP_INT;
-               sc->sc_flags |= SC_STARTPOLL;
-#ifdef POLLSTATS
-               sc->sc_ncmd++;
 #endif
-               goto loop;
-       }
+       sc->sc_uuda = (struct mscp_pack *) UBAI_ADDR(ubinfo);
 
-       pp = &udalabel[ui->ui_unit].d_partitions[udapart(bp->b_dev)];
-       mp->mscp_opcode = (bp->b_flags & B_READ) ? M_OP_READ : M_OP_WRITE;
-       mp->mscp_unit = ui->ui_slave;
-       mp->mscp_seq.seq_lbn = bp->b_blkno + pp->p_offset;
-       sz = (bp->b_bcount + DEV_BSIZE - 1) >> DEV_BSHIFT;
-       mp->mscp_seq.seq_bytecount = bp->b_blkno + sz > pp->p_size ?
-               (pp->p_size - bp->b_blkno) >> DEV_BSHIFT : bp->b_bcount;
-       /* mscp_cmdref is filled in by mscp_go() */
+       bzero(&sc->sc_uda, sizeof (struct mscp_pack));
 
        /*
-        * Drop the packet pointer into the `command' field so udadgo()
-        * can tell what to start.  If ubago returns 1, we can do another
-        * transfer.  If not, um_cmd will still point at mp, so we will
-        * know that we are waiting for resources.
+        * The only thing that differ UDA's and Tape ctlr's is
+        * their vcid. Beacuse there are no way to determine which
+        * ctlr type it is, we check what is generated and later
+        * set the correct vcid.
         */
-       um->um_cmd = (int)mp;
-       if (ubago(ui))
-               goto loop;
+       ma.ma_type = (strcmp(self->dv_cfdata->cf_driver->cd_name,
+           mtc_cd.cd_name) ? MSCPBUS_DISK : MSCPBUS_TAPE);
 
-       /*
-        * All done, or blocked in ubago().  If we managed to
-        * issue some commands, start up the beast.
-        */
-out:
-       if (sc->sc_flags & SC_STARTPOLL) {
-#ifdef POLLSTATS
-               udastats.cmd[sc->sc_ncmd]++;
-               sc->sc_ncmd = 0;
-#endif
-               i = ((struct udadevice *)um->um_addr)->udaip;
-       }
-       sc->sc_flags &= ~(SC_INSTART | SC_STARTPOLL);
+       ma.ma_mc = &uda_mscp_ctlr;
+       ma.ma_type |= MSCPBUS_UDA;
+       ma.ma_uuda = sc->sc_uuda;
+       ma.ma_uda = &sc->sc_uda;
+       ma.ma_softc = &sc->sc_softc;
+       ma.ma_ip = &sc->sc_udadev->udaip;
+       ma.ma_sa = ma.ma_sw = &sc->sc_udadev->udasa;
+       ma.ma_ivec = ivec_no;
+       ma.ma_ctlrnr = (ua->ua_iaddr == 0772150 ? 0 : 1);       /* XXX */
+       ma.ma_adapnr = uh->uh_nr;
+       config_found(&sc->sc_dev, &ma, udaprint);
 }
 
 /*
- * Start a transfer.
- *
- * If we are not called from within udastart(), we must have been
- * blocked, so call udastart to do more requests (if any).  If
- * this calls us again immediately we will not recurse, because
- * that time we will be in udastart().  Clever....
+ * Start a transfer if there are free resources available, otherwise
+ * let it go in udaready, forget it for now.
  */
-void
-udadgo(um)
-       register struct uba_ctlr *um;
+int
+udago(usc, bp)
+       struct device *usc;
+       struct buf *bp;
 {
-       struct uda_softc *sc = &uda_softc[um->um_ctlr];
-       struct mscp *mp = (struct mscp *)um->um_cmd;
-/* printf("udago\n"); */
-       um->um_tab.b_active++;  /* another transfer going */
+       struct uda_softc *sc = (void *)usc;
+       struct uba_unit *uu = &sc->sc_unit;
 
        /*
-        * Fill in the MSCP packet and move the buffer to the
-        * I/O wait queue.  Mark the controller as no longer on
-        * the resource queue, and remember to initiate polling.
+        * If we already are queued for resources, don't call ubaqueue
+        * again. (Then we would trash the wait queue). Just queue the
+        * buf and let the rest be done in udaready.
         */
-       mp->mscp_seq.seq_buffer = UBAI_ADDR(um->um_ubinfo) |
-               (UBAI_BDP(um->um_ubinfo) << 24);
-       mscp_go(&sc->sc_mi, mp, um->um_ubinfo);
-       um->um_cmd = 0; 
-       um->um_ubinfo = 0;      /* tyke it awye */
-       sc->sc_flags |= SC_STARTPOLL;
-#ifdef POLLSTATS
-       sc->sc_ncmd++;
-#endif
-       if ((sc->sc_flags & SC_INSTART) == 0)
-               udastart(um);
+       if (sc->sc_bufq.sqh_first)
+               BUFQ_INSERT_TAIL(&sc->sc_bufq, bp)
+       else {
+               if (ubaqueue(uu, bp))
+                       mscp_dgo(sc->sc_softc, (UBAI_ADDR(uu->uu_ubinfo) |
+                           (UBAI_BDP(uu->uu_ubinfo) << 24)),uu->uu_ubinfo,bp);
+               else
+                       BUFQ_INSERT_TAIL(&sc->sc_bufq, bp)
+       }
+               
+       return 0;
 }
 
-void
-udaiodone(mi, bp, info)
-       register struct mscp_info *mi;
-       struct buf *bp;
-       int info;
+/*
+ * Called if we have been blocked for resources, and resources
+ * have been freed again. Return 1 if we could start all 
+ * transfers again, 0 if we still are waiting.
+ */
+int
+udaready(uu)
+       struct uba_unit *uu;
 {
-       register struct uba_ctlr *um = udaminfo[mi->mi_ctlr];
-/* printf("udaiodone\n"); */
-       um->um_ubinfo = info;
-       ubadone(um);
-       biodone(bp);
-       if (um->um_bdp && mi->mi_wtab.b_actf == &mi->mi_wtab)
-               ubarelse(um->um_ubanum, &um->um_bdp);
-/* Was:        if (um->um_bdp && mi->mi_wtab.av_forw == &mi->mi_wtab)
-               ubarelse(um->um_ubanum, &um->um_bdp); */
-       um->um_tab.b_active--;  /* another transfer done */
+       struct uda_softc *sc = uu->uu_softc;
+       struct buf *bp;
+
+       while ((bp = sc->sc_bufq.sqh_first)) {
+               if (ubaqueue(uu, bp)) {
+                       BUFQ_REMOVE_HEAD(&sc->sc_bufq, bp);
+                       mscp_dgo(sc->sc_softc, (UBAI_ADDR(uu->uu_ubinfo) |
+                           (UBAI_BDP(uu->uu_ubinfo) << 24)),uu->uu_ubinfo,bp);
+               } else
+                       return 0;
+       }
+       return 1;
 }
 
 static struct saerr {
@@ -1414,24 +385,26 @@ static struct saerr {
  * If the error bit was set in the controller status register, gripe,
  * then (optionally) reset the controller and requeue pending transfers.
  */
-udasaerror(um, doreset)
-       register struct uba_ctlr *um;
+void
+udasaerror(usc, doreset)
+       struct device *usc;
        int doreset;
 {
-       register int code = ((struct udadevice *)um->um_addr)->udasa;
+       struct  uda_softc *sc = (void *)usc;
+       register int code = sc->sc_udadev->udasa;
        register struct saerr *e;
-/*printf("udasaerror\n"); */
-       if ((code & UDA_ERR) == 0)
+
+       if ((code & MP_ERR) == 0)
                return;
        for (e = saerr; e->code; e++)
                if (e->code == code)
                        break;
-       printf("uda%d: controller error, sa=0%o (%s%s)\n",
-               um->um_ctlr, code, e->desc + 1,
+       printf("%s: controller error, sa=0%o (%s%s)\n",
+               sc->sc_dev.dv_xname, code, e->desc + 1,
                *e->desc == 'E' ? " error" : "");
        if (doreset) {
-               mscp_requeue(&uda_softc[um->um_ctlr].sc_mi);
-               (void) udainit(um->um_ctlr);
+               mscp_requeue(sc->sc_softc);
+/*             (void) udainit(sc);     XXX */
        }
 }
 
@@ -1440,1034 +413,110 @@ udasaerror(um, doreset)
  * continue initialisation, or acknowledge command and response
  * interrupts, and process responses.
  */
-void
+static void
 udaintr(ctlr)
        int ctlr;
 {
-       struct uba_ctlr *um = udaminfo[ctlr];
-       struct uda_softc *sc = &uda_softc[ctlr];
-       volatile struct udadevice *udaddr = (struct udadevice *)um->um_addr;
-       struct uda *ud;
-       struct mscp *mp;
-       volatile int i, wait_status;
-       extern int cpu_type;
+       intr(uda_cd.cd_devs[ctlr]);
+}
+
+static void
+mtcintr(ctlr)
+       int ctlr;
+{
+       intr(mtc_cd.cd_devs[ctlr]);
+}
+
+static void
+intr(sc)
+       struct uda_softc *sc;
+{
+       volatile struct udadevice *udaddr = sc->sc_udadev;
+       struct  uba_softc *uh;
+       struct mscp_pack *ud;
 
 #ifdef QBA
-       if(cpunumber == VAX_78032)
+       if(vax_cputype == VAX_TYP_UV2)
                splx(sc->sc_ipl);       /* Qbus interrupt protocol is odd */
 #endif
        sc->sc_wticks = 0;      /* reset interrupt watchdog */
 
-       /*
-        * Combinations during steps 1, 2, and 3: STEPnMASK
-        * corresponds to which bits should be tested;
-        * STEPnGOOD corresponds to the pattern that should
-        * appear after the interrupt from STEPn initialisation.
-        * All steps test the bits in ALLSTEPS.
-        */
-
-       switch (sc->sc_state) {
-
-       case ST_IDLE:
-               /*
-                * Ignore unsolicited interrupts.
-                */
-               log(LOG_WARNING, "uda%d: stray intr\n", ctlr);
-               return;
-
-       case ST_STEP1:
-               /*
-                * Begin step two initialisation.
-                */
-               i = 0;
-               Wait_step(STEP1MASK, STEP1GOOD, wait_status);
-               if (!wait_status) {
-initfailed:
-                       printf("uda%d: init step %d failed, sa=%b\n",
-                               ctlr, i, udaddr->udasa, udasr_bits);
-                       udasaerror(um, 0);
-                       sc->sc_state = ST_IDLE;
-                       if (sc->sc_flags & SC_DOWAKE) {
-                               sc->sc_flags &= ~SC_DOWAKE;
-                               wakeup((caddr_t)sc);
-                       }
-                       return;
-               }
-               udaddr->udasa = (int)&sc->sc_uuda->uda_ca.ca_rspdsc[0] |
-                       (MACHID(cpu_type) == VAX_780 || MACHID(cpu_type) 
-                       == VAX_8600 ? UDA_PI : 0);
-               sc->sc_state = ST_STEP2;
-               return;
-
-       case ST_STEP2:
-               /*
-                * Begin step 3 initialisation.
-                */
-               i = 2;
-               Wait_step(STEP2MASK, STEP2GOOD, wait_status);
-               if (!wait_status)
-                       goto initfailed;
-
-               udaddr->udasa = ((int)&sc->sc_uuda->uda_ca.ca_rspdsc[0]) >> 16;
-               sc->sc_state = ST_STEP3;
-               return;
-
-       case ST_STEP3:
-               /*
-                * Set controller characteristics (finish initialisation).
-                */
-               i = 3;
-               Wait_step(STEP3MASK, STEP3GOOD, wait_status);
-               if (!wait_status)
-                       goto initfailed;
-
-               i = udaddr->udasa & 0xff;
-               if (i != sc->sc_micro) {
-                       sc->sc_micro = i;
-                       printf("uda%d: version %d model %d\n",
-                               ctlr, i & 0xf, i >> 4);
-               }
-
-               /*
-                * Present the burst size, then remove it.  Why this
-                * should be done this way, I have no idea.
-                *
-                * Note that this assumes udaburst[ctlr] > 0.
-                */
-               udaddr->udasa = UDA_GO | (udaburst[ctlr] - 1) << 2;
-               udaddr->udasa = UDA_GO;
-               printf("uda%d: DMA burst size set to %d\n",
-                       ctlr, udaburst[ctlr]);
-
-               udainitds(ctlr);        /* initialise data structures */
-
-               /*
-                * Before we can get a command packet, we need some
-                * credits.  Fake some up to keep mscp_getcp() happy,
-                * get a packet, and cancel all credits (the right
-                * number should come back in the response to the
-                * SCC packet).
-                */
-               sc->sc_mi.mi_credits = MSCP_MINCREDITS + 1;
-               mp = mscp_getcp(&sc->sc_mi, MSCP_DONTWAIT);
-               if (mp == NULL) /* `cannot happen' */
-                       panic("udaintr");
-               sc->sc_mi.mi_credits = 0;
-               mp->mscp_opcode = M_OP_SETCTLRC;
-               mp->mscp_unit = 0;
-               mp->mscp_sccc.sccc_ctlrflags = M_CF_ATTN | M_CF_MISC |
-                       M_CF_THIS;
-               *mp->mscp_addr |= MSCP_OWN | MSCP_INT;
-               i = udaddr->udaip;
-               sc->sc_state = ST_SETCHAR;
-               return;
-
-       case ST_SETCHAR:
-       case ST_RUN:
-               /*
-                * Handle Set Ctlr Characteristics responses and operational
-                * responses (via mscp_dorsp).
-                */
-               break;
-
-       default:
-               printf("uda%d: driver bug, state %d\n", ctlr, sc->sc_state);
-               panic("udastate");
-       }
-
-       if (udaddr->udasa & UDA_ERR) {  /* ctlr fatal error */
-               udasaerror(um, 1);
+       if (udaddr->udasa & MP_ERR) {   /* ctlr fatal error */
+               udasaerror(&sc->sc_dev, 1);
                return;
        }
-
        ud = &sc->sc_uda;
-
        /*
         * Handle buffer purge requests.
         */
-       if (ud->uda_ca.ca_bdp) {
-               UBAPURGE(um->um_hd->uh_uba, ud->uda_ca.ca_bdp);
-               ud->uda_ca.ca_bdp = 0;
+       uh = (void *)sc->sc_dev.dv_parent;
+       if (ud->mp_ca.ca_bdp) {
+               if (uh->uh_ubapurge)
+                       (*uh->uh_ubapurge)(uh, ud->mp_ca.ca_bdp);
+               ud->mp_ca.ca_bdp = 0;
                udaddr->udasa = 0;      /* signal purge complete */
        }
 
-       /*
-        * Check for response and command ring transitions.
-        */
-       if (ud->uda_ca.ca_rspint) {
-               ud->uda_ca.ca_rspint = 0;
-               mscp_dorsp(&sc->sc_mi);
-       }
-       if (ud->uda_ca.ca_cmdint) {
-               ud->uda_ca.ca_cmdint = 0;
-               MSCP_DOCMD(&sc->sc_mi);
-       }
-       udastart(um);
-}
-
-/*
- * Initialise the various data structures that control the UDA50.
- */
-udainitds(ctlr)
-       int ctlr;
-{
-       register struct uda *uud = uda_softc[ctlr].sc_uuda;
-       register struct uda *ud = &uda_softc[ctlr].sc_uda;
-       register struct mscp *mp;
-       register int i;
-/* printf("udainitds\n"); */
-       for (i = 0, mp = ud->uda_rsp; i < NRSP; i++, mp++) {
-               ud->uda_ca.ca_rspdsc[i] = MSCP_OWN | MSCP_INT |
-                       (long)&uud->uda_rsp[i].mscp_cmdref;
-               mp->mscp_addr = &ud->uda_ca.ca_rspdsc[i];
-               mp->mscp_msglen = MSCP_MSGLEN;
-       }
-       for (i = 0, mp = ud->uda_cmd; i < NCMD; i++, mp++) {
-               ud->uda_ca.ca_cmddsc[i] = MSCP_INT |
-                       (long)&uud->uda_cmd[i].mscp_cmdref;
-               mp->mscp_addr = &ud->uda_ca.ca_cmddsc[i];
-               mp->mscp_msglen = MSCP_MSGLEN;
-       }
-}
-
-/*
- * Handle an error datagram.
- */
-void
-udadgram(mi, mp)
-       struct mscp_info *mi;
-       struct mscp *mp;
-{
-/* printf("udadgram\n"); */
-       mscp_decodeerror(mi->mi_md->md_mname, mi->mi_ctlr, mp);
-       /*
-        * SDI status information bytes 10 and 11 are the microprocessor
-        * error code and front panel code respectively.  These vary per
-        * drive type and are printed purely for field service information.
-        */
-       if (mp->mscp_format == M_FM_SDI)
-               printf("\tsdi uproc error code 0x%x, front panel code 0x%x\n",
-                       mp->mscp_erd.erd_sdistat[10],
-                       mp->mscp_erd.erd_sdistat[11]);
-}
-
-/*
- * The Set Controller Characteristics command finished.
- * Record the new state of the controller.
- */
-void
-udactlrdone(mi, mp)
-       register struct mscp_info *mi;
-       struct mscp *mp;
-{
-       register struct uda_softc *sc = &uda_softc[mi->mi_ctlr];
-/* printf("udactlrdone\n"); */
-       if ((mp->mscp_status & M_ST_MASK) == M_ST_SUCCESS)
-               sc->sc_state = ST_RUN;
-       else {
-               printf("uda%d: SETCTLRC failed: ",
-                       mi->mi_ctlr, mp->mscp_status);
-               mscp_printevent(mp);
-               sc->sc_state = ST_IDLE;
-       }
-       if (sc->sc_flags & SC_DOWAKE) {
-               sc->sc_flags &= ~SC_DOWAKE;
-               wakeup((caddr_t)sc);
-       }
-}
-
-/*
- * Received a response from an as-yet unconfigured drive.  Configure it
- * in, if possible.
- */
-udaunconf(mi, mp)
-       struct mscp_info *mi;
-       register struct mscp *mp;
-{
-/* printf("udaunconf\n"); */
-       /*
-        * If it is a slave response, copy it to udaslavereply for
-        * udaslave() to look at.
-        */
-       if (mp->mscp_opcode == (M_OP_GETUNITST | M_OP_END) &&
-           (uda_softc[mi->mi_ctlr].sc_flags & SC_INSLAVE) != 0) {
-               bcopy(mp, &udaslavereply, sizeof(struct mscp));
-/*             udaslavereply = *mp; */
-               return (MSCP_DONE);
-       }
-
-       /*
-        * Otherwise, it had better be an available attention response.
-        */
-       if (mp->mscp_opcode != M_OP_AVAILATTN)
-               return (MSCP_FAILED);
-
-       /* do what autoconf does */
-       return (MSCP_FAILED);   /* not yet, arwhite, not yet */
-}
-
-/*
- * A drive came on line.  Check its type and size.  Return DONE if
- * we think the drive is truly on line.  In any case, awaken anyone
- * sleeping on the drive on-line-ness.
- */
-udaonline(ui, mp)
-       register struct uba_device *ui;
-       struct mscp *mp;
-{
-       register struct ra_info *ra = &ra_info[ui->ui_unit];
-/* printf("udaonline\n"); */
-       wakeup((caddr_t)&ui->ui_flags);
-       if ((mp->mscp_status & M_ST_MASK) != M_ST_SUCCESS) {
-               if (!cold)
-                       printf("uda%d: ra%d", ui->ui_ctlr, ui->ui_unit);
-               printf(": attempt to bring on line failed: ");
-               mscp_printevent(mp);
-               ra->ra_state = CLOSED;
-               return (MSCP_FAILED);
-       }
-
-       ra->ra_state = OPENRAW;
-       ra->ra_dsize = (daddr_t)mp->mscp_onle.onle_unitsize;
-       if (!cold)
-               printf("ra%d: uda%d, unit %d, size = %d sectors\n", ui->ui_unit,
-                   ui->ui_ctlr, mp->mscp_unit, ra->ra_dsize);
-       /* can now compute ncyl */
-       ra->ra_geom.rg_ncyl = ra->ra_dsize / ra->ra_geom.rg_ntracks /
-               ra->ra_geom.rg_nsectors;
-       return (MSCP_DONE);
-}
-
-/*
- * We got some (configured) unit's status.  Return DONE if it succeeded.
- */
-udagotstatus(ui, mp)
-       register struct uba_device *ui;
-       register struct mscp *mp;
-{
-/* printf("udagotstatus\n"); */
-       if ((mp->mscp_status & M_ST_MASK) != M_ST_SUCCESS) {
-               printf("uda%d: attempt to get status for ra%d failed: ",
-                       ui->ui_ctlr, ui->ui_unit);
-               mscp_printevent(mp);
-               return (MSCP_FAILED);
-       }
-       /* record for (future) bad block forwarding and whatever else */
-       uda_rasave(ui->ui_unit, mp, 1);
-       return (MSCP_DONE);
-}
-
-/*
- * A transfer failed.  We get a chance to fix or restart it.
- * Need to write the bad block forwaring code first....
- */
-/*ARGSUSED*/
-udaioerror(ui, mp, bp)
-       register struct uba_device *ui;
-       register struct mscp *mp;
-       struct buf *bp;
-{
-/* printf("udaioerror\n"); */
-       if (mp->mscp_flags & M_EF_BBLKR) {
-               /*
-                * A bad block report.  Eventually we will
-                * restart this transfer, but for now, just
-                * log it and give up.
-                */
-               log(LOG_ERR, "ra%d: bad block report: %d%s\n",
-                       ui->ui_unit, mp->mscp_seq.seq_lbn,
-                       mp->mscp_flags & M_EF_BBLKU ? " + others" : "");
-       } else {
-               /*
-                * What the heck IS a `serious exception' anyway?
-                * IT SURE WOULD BE NICE IF DEC SOLD DOCUMENTATION
-                * FOR THEIR OWN CONTROLLERS.
-                */
-               if (mp->mscp_flags & M_EF_SEREX)
-                       log(LOG_ERR, "ra%d: serious exception reported\n",
-                               ui->ui_unit);
-       }
-       return (MSCP_FAILED);
-}
-
-/*
- * A replace operation finished.
- */
-/*ARGSUSED*/
-void
-udareplace(ui, mp)
-       struct uba_device *ui;
-       struct mscp *mp;
-{
-
-       panic("udareplace");
-}
-
-/*
- * A bad block related operation finished.
- */
-/*ARGSUSED*/
-void
-udabb(ui, mp, bp)
-       struct uba_device *ui;
-       struct mscp *mp;
-       struct buf *bp;
-{
-
-       panic("udabb");
-}
-
-
-/*
- * I/O controls.
- */
-udaioctl(dev, cmd, data, flag)
-       dev_t dev;
-       int cmd;
-       caddr_t data;
-       int flag;
-{
-       register int unit = udaunit(dev);
-       register struct disklabel *lp;
-       register struct ra_info *ra = &ra_info[unit];
-       int error = 0;
-/* printf("udaioctl\n"); */
-       lp = &udalabel[unit];
-
-       switch (cmd) {
-
-       case DIOCGDINFO:
-               *(struct disklabel *)data = *lp;
-               break;
-
-       case DIOCGPART:
-               ((struct partinfo *)data)->disklab = lp;
-               ((struct partinfo *)data)->part =
-                   &lp->d_partitions[udapart(dev)];
-               break;
-
-       case DIOCSDINFO:
-               if ((flag & FWRITE) == 0)
-                       error = EBADF;
-               else
-                       error = setdisklabel(lp, (struct disklabel *)data,
-                           (ra->ra_state == OPENRAW) ? 0 : ra->ra_openpart,0);
-               break;
-
-       case DIOCWLABEL:
-               if ((flag & FWRITE) == 0)
-                       error = EBADF;
-               else
-                       ra->ra_wlabel = *(int *)data;
-               break;
-
-       case DIOCWDINFO:
-               if ((flag & FWRITE) == 0)
-                       error = EBADF;
-               else if ((error = setdisklabel(lp, (struct disklabel *)data,
-                   (ra->ra_state == OPENRAW) ? 0 : ra->ra_openpart,0)) == 0) {
-                       int wlab;
-
-                       ra->ra_state = OPEN;
-                       /* simulate opening partition 0 so write succeeds */
-                       ra->ra_openpart |= (1 << 0);            /* XXX */
-                       wlab = ra->ra_wlabel;
-                       ra->ra_wlabel = 1;
-                       error = writedisklabel(dev, udastrategy, lp,0);
-                       ra->ra_openpart = ra->ra_copenpart | ra->ra_bopenpart;
-                       ra->ra_wlabel = wlab;
-               }
-               break;
-
-#ifdef notyet
-       case UDAIOCREPLACE:
-               /*
-                * Initiate bad block replacement for the given LBN.
-                * (Should we allow modifiers?)
-                */
-               error = EOPNOTSUPP;
-               break;
-
-       case UDAIOCGMICRO:
-               /*
-                * Return the microcode revision for the UDA50 running
-                * this drive.
-                */
-               *(int *)data = uda_softc[uddinfo[unit]->ui_ctlr].sc_micro;
-               break;
-#endif
-
-       default:
-               error = ENOTTY;
-               break;
-       }
-       return (error);
+       mscp_intr(sc->sc_softc);
 }
 
 /*
  * A Unibus reset has occurred on UBA uban.  Reinitialise the controller(s)
  * on that Unibus, and requeue outstanding I/O.
  */
-udareset(uban)
-       int uban;
+void
+udareset(ctlr)
+       int ctlr;
 {
-       register struct uba_ctlr *um;
-       register struct uda_softc *sc;
-       register int ctlr;
-/* printf("udareset\n"); */
-       for (ctlr = 0, sc = uda_softc; ctlr < NUDA; ctlr++, sc++) {
-               if ((um = udaminfo[ctlr]) == NULL || um->um_ubanum != uban ||
-                   um->um_alive == 0)
-                       continue;
-               printf(" uda%d", ctlr);
-
-               /*
-                * Our BDP (if any) is gone; our command (if any) is
-                * flushed; the device is no longer mapped; and the
-                * UDA50 is not yet initialised.
-                */
-               if (um->um_bdp) {
-                       printf("<%d>", UBAI_BDP(um->um_bdp));
-                       um->um_bdp = 0;
-               }
-               um->um_ubinfo = 0;
-               um->um_cmd = 0;
-               sc->sc_flags &= ~SC_MAPPED;
-               sc->sc_state = ST_IDLE;
-
-               /* reset queues and requeue pending transfers */
-               mscp_requeue(&sc->sc_mi);
-
-               /*
-                * If it fails to initialise we will notice later and
-                * try again (and again...).  Do not call udastart()
-                * here; it will be done after the controller finishes
-                * initialisation.
-                */
-               if (udainit(ctlr))
-                       printf(" (hung)");
-       }
+       reset(uda_cd.cd_devs[ctlr]);
 }
 
-/*
- * Watchdog timer:  If the controller is active, and no interrupts
- * have occurred for 30 seconds, assume it has gone away.
- */
 void
-udawatch()
+mtcreset(ctlr)
+       int ctlr;
 {
-       register int i;
-       register struct uba_ctlr *um;
-       register struct uda_softc *sc;
-       timeout(udawatch, (caddr_t) 0, hz);     /* every second */
-       for (i = 0, sc = uda_softc; i < NUDA; i++, sc++) {
-               if ((um = udaminfo[i]) == 0 || !um->um_alive)
-                       continue;
-               if (sc->sc_state == ST_IDLE)
-                       continue;
-               if (sc->sc_state == ST_RUN && !um->um_tab.b_active)
-                       sc->sc_wticks = 0;
-               else if (++sc->sc_wticks >= 30) {
-                       sc->sc_wticks = 0;
-                       printf("uda%d: lost interrupt\n", i);
-                       ubareset(um->um_ubanum);
-               }
-       }
+       reset(mtc_cd.cd_devs[ctlr]);
 }
 
-/*
- * Do a panic dump.  We set up the controller for one command packet
- * and one response packet, for which we use `struct uda1'.
- */
-struct uda1 {
-       struct  uda1ca uda1_ca; /* communications area */
-       struct  mscp uda1_rsp;  /* response packet */
-       struct  mscp uda1_cmd;  /* command packet */
-} uda1;
-
-#define        DBSIZE  32              /* dump 16K at a time */
-
-udadump(dev)
-       dev_t dev;
+static void
+reset(sc)
+       struct uda_softc *sc;
 {
-       struct udadevice *udaddr;
-       struct uda1 *ud_ubaddr;
-       char *start;
-       int num, blk, unit, maxsz, blkoff, reg;
-       struct partition *pp;
-       struct uba_regs *uba;
-       struct uba_device *ui;
-       struct uda1 *ud;
-       struct pte *io;
-       int i;
-
-       /*
-        * Make sure the device is a reasonable place on which to dump.
-        */
-       unit = udaunit(dev);
-       if (unit >= NRA)
-               return (ENXIO);
-#define        phys(cast, addr)        ((cast) ((int)addr & 0x7fffffff))
-       ui = phys(struct uba_device *, udadinfo[unit]);
-       if (ui == NULL || ui->ui_alive == 0)
-               return (ENXIO);
-
-       /*
-        * Find and initialise the UBA; get the physical address of the
-        * device registers, and of communications area and command and
-        * response packet.
-        */
-       uba = phys(struct uba_softc *, ui->ui_hd)->uh_physuba;
-       ubainit(ui->ui_hd);
-       udaddr = (struct udadevice *)ui->ui_physaddr;
-       ud = phys(struct uda1 *, &uda1);
-       /*
-        * Map the ca+packets into Unibus I/O space so the UDA50 can get
-        * at them.  Use the registers at the end of the Unibus map (since
-        * we will use the registers at the beginning to map the memory
-        * we are dumping).
-        */
-       num = btoc(sizeof(struct uda1)) + 1;
-       reg = NUBMREG - num;
-       io = (void *)&uba->uba_map[reg];
-       for (i = 0; i < num; i++)
-               *(int *)io++ = UBAMR_MRV | (btop(ud) + i);
-       ud_ubaddr = (struct uda1 *)(((int)ud & PGOFSET) | (reg << 9));
-
-       /*
-        * Initialise the controller, with one command and one response
-        * packet.
-        */
-       udaddr->udaip = 0;
-       if (udadumpwait(udaddr, UDA_STEP1))
-               return (EFAULT);
-       udaddr->udasa = UDA_ERR;
-       if (udadumpwait(udaddr, UDA_STEP2))
-               return (EFAULT);
-       udaddr->udasa = (int)&ud_ubaddr->uda1_ca.ca_rspdsc;
-       if (udadumpwait(udaddr, UDA_STEP3))
-               return (EFAULT);
-       udaddr->udasa = ((int)&ud_ubaddr->uda1_ca.ca_rspdsc) >> 16;
-       if (udadumpwait(udaddr, UDA_STEP4))
-               return (EFAULT);
-       uda_softc[ui->ui_ctlr].sc_micro = udaddr->udasa & 0xff;
-       udaddr->udasa = UDA_GO;
+       printf(" %s", sc->sc_dev.dv_xname);
 
        /*
-        * Set up the command and response descriptor, then set the
-        * controller characteristics and bring the drive on line.
-        * Note that all uninitialised locations in uda1_cmd are zero.
+        * Our BDP (if any) is gone; our command (if any) is
+        * flushed; the device is no longer mapped; and the
+        * UDA50 is not yet initialised.
         */
-       ud->uda1_ca.ca_rspdsc = (long)&ud_ubaddr->uda1_rsp.mscp_cmdref;
-       ud->uda1_ca.ca_cmddsc = (long)&ud_ubaddr->uda1_cmd.mscp_cmdref;
-       /* ud->uda1_cmd.mscp_sccc.sccc_ctlrflags = 0; */
-       /* ud->uda1_cmd.mscp_sccc.sccc_version = 0; */
-       if (udadumpcmd(M_OP_SETCTLRC, ud, ui))
-               return (EFAULT);
-       ud->uda1_cmd.mscp_unit = ui->ui_slave;
-       if (udadumpcmd(M_OP_ONLINE, ud, ui))
-               return (EFAULT);
-
-       pp = phys(struct partition *,
-           &udalabel[unit].d_partitions[udapart(dev)]);
-       maxsz = pp->p_size;
-       blkoff = pp->p_offset;
+       if (sc->sc_unit.uu_bdp) {
+               printf("<%d>", UBAI_BDP(sc->sc_unit.uu_bdp));
+               sc->sc_unit.uu_bdp = 0;
+       }
+       sc->sc_unit.uu_ubinfo = 0;
+/*     sc->sc_unit.uu_cmd = 0; XXX */
 
-       /*
-        * Dump all of physical memory, or as much as will fit in the
-        * space provided.
-        */
-       start = 0;
-       printf("Dumpar {r inte implementerade {n :) \n");
-       asm("halt");
-/*     num = maxfree; */
-       if (dumplo + num >= maxsz)
-               num = maxsz - dumplo;
-       blkoff += dumplo;
+       /* reset queues and requeue pending transfers */
+       mscp_requeue(sc->sc_softc);
 
        /*
-        * Write out memory, DBSIZE pages at a time.
-        * N.B.: this code depends on the fact that the sector
-        * size == the page size.
+        * If it fails to initialise we will notice later and
+        * try again (and again...).  Do not call udastart()
+        * here; it will be done after the controller finishes
+        * initialisation.
         */
-       while (num > 0) {
-               blk = num > DBSIZE ? DBSIZE : num;
-               io = (void *)uba->uba_map;
-               /*
-                * Map in the pages to write, leaving an invalid entry
-                * at the end to guard against wild Unibus transfers.
-                * Then do the write.
-                */
-               for (i = 0; i < blk; i++)
-                       *(int *)io++ = UBAMR_MRV | (btop(start) + i);
-               *(int *)io = 0;
-               ud->uda1_cmd.mscp_unit = ui->ui_slave;
-               ud->uda1_cmd.mscp_seq.seq_lbn = btop(start) + blkoff;
-               ud->uda1_cmd.mscp_seq.seq_bytecount = blk << PGSHIFT;
-               if (udadumpcmd(M_OP_WRITE, ud, ui))
-                       return (EIO);
-               start += blk << PGSHIFT;
-               num -= blk;
-       }
-       return (0);             /* made it! */
-}
-
-/*
- * Wait for some of the bits in `bits' to come on.  If the error bit
- * comes on, or ten seconds pass without response, return true (error).
- */
-udadumpwait(udaddr, bits)
-       volatile struct udadevice *udaddr;
-       register int bits;
-{
-       register int timo = todr() + 1000;
-
-       while ((udaddr->udasa & bits) == 0) {
-               if (udaddr->udasa & UDA_ERR) {
-                       printf("udasa=%b\ndump ", udaddr->udasa, udasr_bits);
-                       return (1);
-               }
-               if (todr() >= timo) {
-                       printf("timeout\ndump ");
-                       return (1);
-               }
-       }
-       return (0);
-}
-
-/*
- * Feed a command to the UDA50, wait for its response, and return
- * true iff something went wrong.
- */
-udadumpcmd(op, ud, ui)
-       int op;
-       register struct uda1 *ud;
-       struct uba_device *ui;
-{
-       volatile struct udadevice *udaddr;
-       volatile int n;
-#define mp (&ud->uda1_rsp)
-
-       udaddr = (struct udadevice *)ui->ui_physaddr;
-       ud->uda1_cmd.mscp_opcode = op;
-       ud->uda1_cmd.mscp_msglen = MSCP_MSGLEN;
-       ud->uda1_rsp.mscp_msglen = MSCP_MSGLEN;
-       ud->uda1_ca.ca_rspdsc |= MSCP_OWN | MSCP_INT;
-       ud->uda1_ca.ca_cmddsc |= MSCP_OWN | MSCP_INT;
-       if (udaddr->udasa & UDA_ERR) {
-               printf("udasa=%b\ndump ", udaddr->udasa, udasr_bits);
-               return (1);
-       }
-       n = udaddr->udaip;
-       n = todr() + 1000;
-       for (;;) {
-               if (todr() > n) {
-                       printf("timeout\ndump ");
-                       return (1);
-               }
-               if (ud->uda1_ca.ca_cmdint)
-                       ud->uda1_ca.ca_cmdint = 0;
-               if (ud->uda1_ca.ca_rspint == 0)
-                       continue;
-               ud->uda1_ca.ca_rspint = 0;
-               if (mp->mscp_opcode == (op | M_OP_END))
-                       break;
-               printf("\n");
-               switch (MSCP_MSGTYPE(mp->mscp_msgtc)) {
-
-               case MSCPT_SEQ:
-                       printf("sequential");
-                       break;
-
-               case MSCPT_DATAGRAM:
-                       mscp_decodeerror("uda", ui->ui_ctlr, mp);
-                       printf("datagram");
-                       break;
-
-               case MSCPT_CREDITS:
-                       printf("credits");
-                       break;
-
-               case MSCPT_MAINTENANCE:
-                       printf("maintenance");
-                       break;
-
-               default:
-                       printf("unknown (type 0x%x)",
-                               MSCP_MSGTYPE(mp->mscp_msgtc));
-                       break;
-               }
-               printf(" ignored\ndump ");
-               ud->uda1_ca.ca_rspdsc |= MSCP_OWN | MSCP_INT;
-       }
-       if ((mp->mscp_status & M_ST_MASK) != M_ST_SUCCESS) {
-               printf("error: op 0x%x => 0x%x status 0x%x\ndump ", op,
-                       mp->mscp_opcode, mp->mscp_status);
-               return (1);
-       }
-       return (0);
-#undef mp
-}
-
-/*
- * Return the size of a partition, if known, or -1 if not.
- */
-udasize(dev)
-       dev_t dev;
-{
-       register int unit = udaunit(dev);
-       register struct uba_device *ui;
-
-       if (unit >= NRA || (ui = udadinfo[unit]) == NULL ||
-           ui->ui_alive == 0 || (ui->ui_flags & UNIT_ONLINE) == 0 ||
-           ra_info[unit].ra_state != OPEN)
-               return (-1);
-       return ((int)udalabel[unit].d_partitions[udapart(dev)].p_size);
+/* XXX if (udainit(sc)) */
+               printf(" (hung)");
 }
 
-#ifdef COMPAT_42
-/*
- * Tables mapping unlabelled drives.
- */
-struct size {
-       daddr_t nblocks;
-       daddr_t blkoff;
-} ra60_sizes[8] = {
-       15884,  0,              /* A=sectors 0 thru 15883 */
-       33440,  15884,          /* B=sectors 15884 thru 49323 */
-       400176, 0,              /* C=sectors 0 thru 400175 */
-       82080,  49324,          /* 4.2 G => D=sectors 49324 thru 131403 */
-       268772, 131404,         /* 4.2 H => E=sectors 131404 thru 400175 */
-       350852, 49324,          /* F=sectors 49324 thru 400175 */
-       157570, 242606,         /* UCB G => G=sectors 242606 thru 400175 */
-       193282, 49324,          /* UCB H => H=sectors 49324 thru 242605 */
-}, ra70_sizes[8] = {
-       15884,  0,              /* A=blk 0 thru 15883 */
-       33440,  15972,          /* B=blk 15972 thru 49323 */
-       -1,     0,              /* C=blk 0 thru end */
-       15884,  341220,         /* D=blk 341220 thru 357103 */
-       55936,  357192,         /* E=blk 357192 thru 413127 */
-       -1,     413457,         /* F=blk 413457 thru end */
-       -1,     341220,         /* G=blk 341220 thru end */
-       291346, 49731,          /* H=blk 49731 thru 341076 */
-}, ra80_sizes[8] = {
-       15884,  0,              /* A=sectors 0 thru 15883 */
-       33440,  15884,          /* B=sectors 15884 thru 49323 */
-       242606, 0,              /* C=sectors 0 thru 242605 */
-       0,      0,              /* D=unused */
-       193282, 49324,          /* UCB H => E=sectors 49324 thru 242605 */
-       82080,  49324,          /* 4.2 G => F=sectors 49324 thru 131403 */
-       192696, 49910,          /* G=sectors 49910 thru 242605 */
-       111202, 131404,         /* 4.2 H => H=sectors 131404 thru 242605 */
-}, ra81_sizes[8] ={
-/*
- * These are the new standard partition sizes for ra81's.
- * An RA_COMPAT system is compiled with D, E, and F corresponding
- * to the 4.2 partitions for G, H, and F respectively.
- */
-#ifndef        UCBRA
-       15884,  0,              /* A=sectors 0 thru 15883 */
-       66880,  16422,          /* B=sectors 16422 thru 83301 */
-       891072, 0,              /* C=sectors 0 thru 891071 */
-#ifdef RA_COMPAT
-       82080,  49324,          /* 4.2 G => D=sectors 49324 thru 131403 */
-       759668, 131404,         /* 4.2 H => E=sectors 131404 thru 891071 */
-       478582, 412490,         /* 4.2 F => F=sectors 412490 thru 891071 */
-#else
-       15884,  375564,         /* D=sectors 375564 thru 391447 */
-       307200, 391986,         /* E=sectors 391986 thru 699185 */
-       191352, 699720,         /* F=sectors 699720 thru 891071 */
-#endif RA_COMPAT
-       515508, 375564,         /* G=sectors 375564 thru 891071 */
-       291346, 83538,          /* H=sectors 83538 thru 374883 */
-
-/*
- * These partitions correspond to the sizes used by sites at Berkeley,
- * and by those sites that have received copies of the Berkeley driver
- * with deltas 6.2 or greater (11/15/83).
- */
-#else UCBRA
-
-       15884,  0,              /* A=sectors 0 thru 15883 */
-       33440,  15884,          /* B=sectors 15884 thru 49323 */
-       891072, 0,              /* C=sectors 0 thru 891071 */
-       15884,  242606,         /* D=sectors 242606 thru 258489 */
-       307200, 258490,         /* E=sectors 258490 thru 565689 */
-       325382, 565690,         /* F=sectors 565690 thru 891071 */
-       648466, 242606,         /* G=sectors 242606 thru 891071 */
-       193282, 49324,          /* H=sectors 49324 thru 242605 */
-
-#endif UCBRA
-}, ra82_sizes[8] = {
-       15884,  0,              /* A=blk 0 thru 15883 */
-       66880,  16245,          /* B=blk 16245 thru 83124 */
-       -1,     0,              /* C=blk 0 thru end */
-       15884,  375345,         /* D=blk 375345 thru 391228 */
-       307200, 391590,         /* E=blk 391590 thru 698789 */
-       -1,     699390,         /* F=blk 699390 thru end */
-       -1,     375345,         /* G=blk 375345 thru end */
-       291346, 83790,          /* H=blk 83790 thru 375135 */
-}, ra90_sizes[8] = {
-        15884,  0,              /* A=sectors 0 thru 15883 */
-        66880,  16146,          /* B=sectors 16146 thru 83025 */
-        2376153,0,              /* C=sectors 0 thru 2376152 */
-        15884,  374946,         /* D=sectors 374946 thru 390829 */
-        307200, 391092,         /* E=sectors 391092 thru 698291 */
-        1677390,698763,         /* F=sectors 698763 thru 2376152 */
-        2001207,374946,         /* G=sectors 374946 thru 2376152 */
-        291346, 83421,          /* H=sectors 83421 thru 374766 */
-}, ra92_sizes[8] = {
-        15884,  0,              /* A=sectors 0 thru 15883 */
-        66880,  16146,          /* B=sectors 16146 thru 83025 */
-        2941263,0,              /* C=sectors 0 thru 2941262 */
-        15884,  374946,         /* D=sectors 374946 thru 390829 */
-        307200, 391092,         /* E=sectors 391092 thru 698291 */
-        2242500,698763,         /* F=sectors 698763 thru 2941262 */
-        2566317,374946,         /* G=sectors 374946 thru 2941262 */
-        291346, 83421,          /* H=sectors 83421 thru 374766 */
-}, rc25_sizes[8] = {
-       15884,  0,              /* A=blk 0 thru 15883 */
-       10032,  15884,          /* B=blk 15884 thru 49323 */
-       -1,     0,              /* C=blk 0 thru end */
-       0,      0,              /* D=blk 340670 thru 356553 */
-       0,      0,              /* E=blk 356554 thru 412489 */
-       0,      0,              /* F=blk 412490 thru end */
-       -1,     25916,          /* G=blk 49324 thru 131403 */
-       0,      0,              /* H=blk 131404 thru end */
-}, rd52_sizes[8] = {
-       15884,  0,              /* A=blk 0 thru 15883 */
-       9766,   15884,          /* B=blk 15884 thru 25649 */
-       -1,     0,              /* C=blk 0 thru end */
-       0,      0,              /* D=unused */
-       0,      0,              /* E=unused */
-       0,      0,              /* F=unused */
-       -1,     25650,          /* G=blk 25650 thru end */
-       0,      0,              /* H=unused */
-}, rd53_sizes[8] = {
-       15884,  0,              /* A=blk 0 thru 15883 */
-       33440,  15884,          /* B=blk 15884 thru 49323 */
-       -1,     0,              /* C=blk 0 thru end */
-       0,      0,              /* D=unused */
-       33440,  0,              /* E=blk 0 thru 33439 */
-       -1,     33440,          /* F=blk 33440 thru end */
-       -1,     49324,          /* G=blk 49324 thru end */
-       -1,     15884,          /* H=blk 15884 thru end */
-}, rd54_sizes[8] = {
-       15884,  0,              /* A=blk 0 thru 15883 */
-       33440,  15884,          /* B=blk 15884 thru 49323 */
-       -1,     0,              /* C=blk 0 thru end */
-       130938, 49324,          /* D=blk 49324 thru 180261 */
-       130938, 180262,         /* E=blk 180262 thru 311199 (end) */
-       0,      0,              /* F=unused */
-       261876, 49324,          /* G=blk 49324 thru 311199 (end) */
-       0,      0,              /* H=unused */
-}, rx50_sizes[8] = {
-       800,    0,              /* A=blk 0 thru 799 */
-       0,      0,
-       -1,     0,              /* C=blk 0 thru end */
-       0,      0,
-       0,      0,
-       0,      0,
-       0,      0,
-       0,      0,
-};
-
-/*
- * Media ID decoding table.
- */
-struct udatypes {
-       u_long  ut_id;          /* media drive ID */
-       char    *ut_name;       /* drive type name */
-       struct  size *ut_sizes; /* partition tables */
-       int     ut_nsectors, ut_ntracks, ut_ncylinders;
-} udatypes[] = {
-       { MSCP_MKDRIVE2('R', 'A', 60), "ra60", ra60_sizes, 42, 4, 2382 },
-       { MSCP_MKDRIVE2('R', 'A', 70), "ra70", ra70_sizes, 33, 11, 1507 },
-       { MSCP_MKDRIVE2('R', 'A', 80), "ra80", ra80_sizes, 31, 14, 559 },
-       { MSCP_MKDRIVE2('R', 'A', 81), "ra81", ra81_sizes, 51, 14, 1248 },
-       { MSCP_MKDRIVE2('R', 'A', 82), "ra82", ra82_sizes, 57, 15, 1423 },
-       { MSCP_MKDRIVE2('R', 'A', 90), "ra90", ra90_sizes, 69, 13, 2649 },
-       { MSCP_MKDRIVE2('R', 'A', 92), "ra92", ra92_sizes, 69, 13, 3279 },
-       { MSCP_MKDRIVE2('R', 'C', 25), "rc25-removable",
-                                               rc25_sizes, 42, 4, 302 },
-       { MSCP_MKDRIVE3('R', 'C', 'F', 25), "rc25-fixed",
-                                               rc25_sizes, 42, 4, 302 },
-       { MSCP_MKDRIVE2('R', 'D', 52), "rd52", rd52_sizes, 18, 7, 480 },
-       { MSCP_MKDRIVE2('R', 'D', 53), "rd53", rd53_sizes, 17, 8, 1019 },
-       { MSCP_MKDRIVE2('R', 'D', 32), "rd54-from-rd32",
-                                               rd54_sizes, 17, 15, 1220 },
-       { MSCP_MKDRIVE2('R', 'D', 54), "rd54", rd54_sizes, 17, 15, 1220 },
-       { MSCP_MKDRIVE2('R', 'X', 50), "rx50", rx50_sizes, 10, 1, 80 },
-       0
-};
-
-#define NTYPES (sizeof(udatypes) / sizeof(*udatypes))
-
-udamaptype(unit, lp)
-       int unit;
-       register struct disklabel *lp;
+void
+udactlrdone(usc, info)
+       struct device *usc;
+       int info;
 {
-       register struct udatypes *ut;
-       register struct size *sz;
-       register struct partition *pp;
-       register char *p;
-       register int i;
-       register struct ra_info *ra = &ra_info[unit];
-
-       i = MSCP_MEDIA_DRIVE(ra->ra_mediaid);
-       for (ut = udatypes; ut->ut_id; ut++)
-               if (ut->ut_id == i &&
-                   ut->ut_nsectors == ra->ra_geom.rg_nsectors &&
-                   ut->ut_ntracks == ra->ra_geom.rg_ntracks &&
-                   ut->ut_ncylinders == ra->ra_geom.rg_ncyl)
-                       goto found;
-
-       /* not one we know; fake up a label for the whole drive */
-       uda_makefakelabel(ra, lp);
-       i = ra->ra_mediaid;     /* print the port type too */
-       addlog(": no partition table for %c%c %c%c%c%d, size %d;\n\
-using (s,t,c)=(%d,%d,%d)",
-               MSCP_MID_CHAR(4, i), MSCP_MID_CHAR(3, i),
-               MSCP_MID_CHAR(2, i), MSCP_MID_CHAR(1, i),
-               MSCP_MID_CHAR(0, i), MSCP_MID_NUM(i), lp->d_secperunit,
-               lp->d_nsectors, lp->d_ntracks, lp->d_ncylinders);
-       if (!cold)
-               addlog("\n");
-       return (0);
-found:
-       p = ut->ut_name;
-       for (i = 0; i < sizeof(lp->d_typename) - 1 && *p; i++)
-               lp->d_typename[i] = *p++;
-       lp->d_typename[i] = 0;
-       sz = ut->ut_sizes;
-       lp->d_nsectors = ut->ut_nsectors;
-       lp->d_ntracks = ut->ut_ntracks;
-       lp->d_ncylinders = ut->ut_ncylinders;
-       lp->d_npartitions = 8;
-       lp->d_secpercyl = lp->d_nsectors * lp->d_ntracks;
-       for (pp = lp->d_partitions; pp < &lp->d_partitions[8]; pp++, sz++) {
-               pp->p_offset = sz->blkoff;
-               if ((pp->p_size = sz->nblocks) == (u_long)-1)
-                       pp->p_size = ra->ra_dsize - sz->blkoff;
-       }
-       return (1);
-}
-#endif /* COMPAT_42 */
+       struct uda_softc *sc = (void *)usc;
 
-/*
- * Construct a label for a drive from geometry information
- * if we have no better information.
- */
-uda_makefakelabel(ra, lp)
-       register struct ra_info *ra;
-       register struct disklabel *lp;
-{
-       lp->d_nsectors = ra->ra_geom.rg_nsectors;
-       lp->d_ntracks = ra->ra_geom.rg_ntracks;
-       lp->d_ncylinders = ra->ra_geom.rg_ncyl;
-       lp->d_secpercyl = lp->d_nsectors * lp->d_ntracks;
-       bcopy("ra??", lp->d_typename, sizeof("ra??"));
-       lp->d_npartitions = 1;
-       lp->d_partitions[0].p_offset = 0;
-       lp->d_partitions[0].p_size = lp->d_secperunit;
+       /* XXX check if we shall release the BDP */
+       sc->sc_unit.uu_ubinfo = info;
+       ubadone(&sc->sc_unit);
 }
index f6107a4..ebada16 100644 (file)
@@ -1,4 +1,4 @@
-/*     $NetBSD: udareg.h,v 1.2 1994/10/26 08:02:51 cgd Exp $   */
+/*     $NetBSD: udareg.h,v 1.3 1996/07/01 21:24:50 ragge Exp $ */
 
 /*
  * Copyright (c) 1988 Regents of the University of California.
@@ -53,22 +53,6 @@ struct udadevice {
        u_short udasa;          /* status and address */
 };
 
-/*
- * Bits in UDA status register during initialisation
- */
-#define        UDA_ERR         0x8000  /* error */
-#define        UDA_STEP4       0x4000  /* step 4 has started */
-#define        UDA_STEP3       0x2000  /* step 3 has started */
-#define        UDA_STEP2       0x1000  /* step 2 has started */
-#define        UDA_STEP1       0x0800  /* step 1 has started */
-#define        UDA_NV          0x0400  /* no host settable interrupt vector */
-#define        UDA_QB          0x0200  /* controller supports Q22 bus */
-#define        UDA_DI          0x0100  /* controller implements diagnostics */
-#define        UDA_IE          0x0080  /* interrupt enable */
-#define        UDA_NCNRMASK    0x003f  /* in STEP1, bits 0-2=NCMDL2, 3-5=NRSPL2 */
-#define        UDA_IVECMASK    0x007f  /* in STEP2, bits 0-6 are interruptvec / 4 */
-#define        UDA_PI          0x0001  /* host requests adapter purge interrupts */
-
 /*
  * Bits in UDA status register after initialisation
  */
@@ -77,31 +61,3 @@ struct udadevice {
 #define        UDASR_BITS \
 "\20\20ERR\17STEP4\16STEP3\15STEP2\14STEP1\13NV\12QB\11DI\10IE\1GO"
 
-/*
- * UDA Communications Area.  Note that this structure definition
- * requires NRSP and NCMD to be defined already.
- */
-struct udaca {
-       short   ca_xxx1;        /* unused */
-       char    ca_xxx2;        /* unused */
-       char    ca_bdp;         /* BDP to purge */
-       short   ca_cmdint;      /* command ring transition flag */
-       short   ca_rspint;      /* response ring transition flag */
-       long    ca_rspdsc[NRSP];/* response descriptors */
-       long    ca_cmddsc[NCMD];/* command descriptors */
-};
-
-/*
- * Simplified routines (e.g., uddump) reprogram the UDA50 for one command
- * and one response at a time; uda1ca is like udaca except that it provides
- * exactly one command and response descriptor.
- */
-struct uda1ca {
-       short   ca_xxx1;
-       char    ca_xxx2;
-       char    ca_bdp;
-       short   ca_cmdint;
-       short   ca_rspint;
-       long    ca_rspdsc;
-       long    ca_cmddsc;
-};
index 78b42be..2968157 100644 (file)
@@ -1,4 +1,4 @@
-/*      $NetBSD: autoconf.c,v 1.13 1996/05/19 16:43:53 ragge Exp $      */
+/*     $NetBSD: autoconf.c,v 1.20 1997/01/11 13:50:20 ragge Exp $      */
 
 /*
  * Copyright (c) 1994 Ludd, University of Lule}, Sweden.
 #include <machine/vmparam.h>
 #include <machine/nexus.h>
 #include <machine/ioa.h>
+#include <machine/ka820.h>
 #include <machine/ka750.h>
 #include <machine/ka650.h>
-#include <machine/uvaxII.h>
+#include <machine/uvax.h>
+#include <machine/clock.h>
 
 #include <vax/vax/gencons.h>
 
 #include <vm/vm.h>
 
-#define        BACKPLANE       0
-#define        BIBUSS          1
-#define        SBIBUSS         2
+struct nexus *nexus;
 
-struct bp_conf {
-       char *type;
-       int num;
-       int partyp;
-};
-
-extern int cold;
+#define BACKPLANE      0
+#define BIBUSS         1
+#define SBIBUSS                2
+#define VSBUSS         4
 
-void    notsupp_steal_pages __P((void));
+int    mastercpu;      /* chief of the system */
 
+#if defined(VAX630) || defined(VAX410) || defined(VAX43) || defined(VAX46)
+#define VAX_uVAX
+#endif
 
 #ifdef VAX8600 /* XXX These are in ka860 also */
-void    ka86_conf __P((struct device *, struct device *, void *));
-int     ka86_clock __P((void));
-void    ka86_memenable __P((struct sbi_attach_args *, struct device *));
-void    ka86_memerr __P((void));
-int     ka86_mchk __P((caddr_t));
-void    ka86_steal_pages __P((void));
+void   ka86_conf __P((struct device *, struct device *, void *));
+void   ka86_memenable __P((struct sbi_attach_args *, struct device *));
+void   ka86_memerr __P((void));
+int    ka86_mchk __P((caddr_t));
+void   ka86_steal_pages __P((void));
 #endif
 #ifdef VAX780 /* XXX These are in ka780 also */
-void    ka780_conf __P((struct device *, struct device *, void *));
-int     ka780_clock __P((void));
-void    ka780_memenable __P((struct sbi_attach_args *, void *));
-void    ka780_memerr __P((void));
-int     ka780_mchk __P((caddr_t));
-void    ka780_steal_pages __P((void));
-#endif
-#ifdef VAX750
-int    nexty750[]={ NEX_MEM16, NEX_MEM16,      NEX_MEM16,      NEX_MEM16,
-               NEX_MBA,        NEX_MBA,        NEX_MBA,        NEX_MBA,
-               NEX_UBA0,       NEX_UBA1,       NEX_ANY,        NEX_ANY,
-               NEX_ANY,        NEX_ANY,        NEX_ANY,        NEX_ANY};
-#endif
-#if VAX730
-int   nexty730[NNEX730] = {
-       NEX_MEM16,      NEX_ANY,        NEX_ANY,        NEX_ANY,
-       NEX_ANY,        NEX_ANY,        NEX_ANY,        NEX_ANY,
-};
+void   ka780_conf __P((struct device *, struct device *, void *));
+void   ka780_memenable __P((struct sbi_attach_args *, void *));
+void   ka780_memerr __P((void));
+int    ka780_mchk __P((caddr_t));
+void   ka780_steal_pages __P((void));
 #endif
 
-struct cpu_dep cpu_calls[VAX_MAX+1]={
+struct cpu_dep cpu_calls[]={
                /* Type 0,noexist */
-       {notsupp_steal_pages, NULL, NULL, NULL, NULL },
+       {NULL, NULL, NULL, NULL, NULL },
 #ifdef VAX780  /* Type 1, 11/{780,782,785} */
-       {ka780_steal_pages, ka780_clock, ka780_mchk, ka780_memerr, ka780_conf},
+       {ka780_steal_pages,generic_clock, ka780_mchk, ka780_memerr, ka780_conf,
+           generic_clkread, generic_clkwrite},
 #else
-       {notsupp_steal_pages, NULL, NULL, NULL, NULL },
+       {NULL, NULL, NULL, NULL, NULL },
 #endif
-#ifdef  VAX750 /* Type 2, 11/750 */
-       {ka750_steal_pages, ka750_clock, ka750_mchk, ka750_memerr, ka750_conf},
+#ifdef VAX750  /* Type 2, 11/750 */
+       {ka750_steal_pages,generic_clock, ka750_mchk, ka750_memerr, ka750_conf,
+           generic_clkread, generic_clkwrite},
 #else
-       {notsupp_steal_pages, NULL, NULL, NULL, NULL },
+       {NULL, NULL, NULL, NULL, NULL },
 #endif
 #ifdef VAX730  /* Type 3, 11/{730,725}, ceauciesco-vax */
-       {notsupp_steal_pages, NULL, NULL, NULL, NULL },
+       {NULL, NULL, NULL, NULL, NULL },
 #else
-       {notsupp_steal_pages, NULL, NULL, NULL, NULL },
+       {NULL, NULL, NULL, NULL, NULL },
 #endif
-#ifdef VAX8600 /* Type 4, 8600/8650 (11/{790,795}) */
-       {ka86_steal_pages, ka86_clock, ka86_mchk, ka86_memerr, ka86_conf},
+#ifdef VAX8600 /* Type 4, 8600/8650 (11/{790,795}) */
+       {ka86_steal_pages, generic_clock, ka86_mchk, ka86_memerr, ka86_conf,
+           generic_clkread, generic_clkwrite},
 #else
-       {notsupp_steal_pages, NULL, NULL, NULL, NULL },
+       {NULL, NULL, NULL, NULL, NULL },
 #endif
-#ifdef VAX8200 /* Type 5, 8200, 8300, 8350 */
-       {notsupp_steal_pages, NULL, NULL, NULL, NULL },
+#ifdef VAX8200 /* Type 5, 8200, 8300, 8350 */
+       {ka820_steal_pages, generic_clock, ka820_mchk, ka820_memerr, NULL,
+           ka820_clkread, ka820_clkwrite},
 #else
-       {notsupp_steal_pages, NULL, NULL, NULL, NULL },
+       {NULL, NULL, NULL, NULL, NULL },
 #endif
-#ifdef VAX8800 /* Type 6, 85X0, 8700, 88X0 */
-       {notsupp_steal_pages, NULL, NULL, NULL, NULL },
+#ifdef VAX8800 /* Type 6, 85X0, 8700, 88X0 */
+       {NULL, generic_clock, NULL, NULL, NULL },
 #else
-       {notsupp_steal_pages, NULL, NULL, NULL, NULL },
+       {NULL, NULL, NULL, NULL, NULL },
 #endif
 #ifdef VAX610  /* Type 7, KA610 */
-       {notsupp_steal_pages, NULL, NULL, NULL, NULL },
+       {NULL, NULL, NULL, NULL, NULL },
 #else
-       {notsupp_steal_pages, NULL, NULL, NULL, NULL },
+       {NULL, NULL, NULL, NULL, NULL },
 #endif
-#ifdef  VAX630  /* Type 8, KA630 or KA410 (uVAX II) */
-       {uvaxII_steal_pages, uvaxII_clock, uvaxII_mchk, uvaxII_memerr,
-           uvaxII_conf},
+#ifdef VAX630  /* Type 8, KA630 or KA410 (uVAX II) */
+       {uvax_steal_pages, no_nicr_clock, uvax_mchk, uvax_memerr, uvax_conf,
+           uvax_clkread, uvax_clkwrite},
 #else
-       {notsupp_steal_pages, NULL, NULL, NULL, NULL },
+       {NULL, NULL, NULL, NULL, NULL },
 #endif
                /* Type 9, not used */
-       {notsupp_steal_pages, NULL, NULL, NULL, NULL },
-#ifdef VAX650  /* Type 10, KA65X (uVAX III) */
-       {uvaxIII_steal_pages, uvaxIII_clock, uvaxIII_mchk, uvaxIII_memerr,
-           uvaxIII_conf},
+       {NULL, NULL, NULL, NULL, NULL },
+#ifdef VAX650  /* Type 10, KA65X (uVAX III) */
+       {uvaxIII_steal_pages, no_nicr_clock, uvaxIII_mchk, uvaxIII_memerr,
+           uvaxIII_conf, generic_clkread, generic_clkwrite},
+#else
+       {NULL, NULL, NULL, NULL, NULL },
+#endif
+#ifdef VAX_uVAX /* Type 11, RIGEL */
+       {uvax_steal_pages, no_nicr_clock, uvax_mchk, uvax_memerr, uvax_conf,
+           uvax_clkread, uvax_clkwrite},
 #else
-       {notsupp_steal_pages, NULL, NULL, NULL, NULL },
+       {NULL, NULL, NULL, NULL, NULL },
 #endif
 };
 
-void
-notsupp_steal_pages()
-{
-       printf("This cputype not supported.\n");
-       asm("halt");
-}
-
 void   gencnslask __P((void));
 
 void
@@ -182,6 +171,9 @@ configure()
         * parameter based on device(s) used.
         */
        gencnslask(); /* XXX inte g|ras h{r */
+#if VAX410 || VAX43
+       dzcnslask(); /* XXX inte g|ras h{r */
+#endif
        swapconf();
        cold = 0;
        mtpr(GC_CCF, PR_TXDB);  /* Clear cold start flag in cpu */
@@ -206,7 +198,7 @@ backplane_match(parent, gcf, aux)
        struct  device  *parent;
        void    *gcf, *aux;
 {
-       struct  cfdata  *cf = gcf;
+       struct  cfdata  *cf = gcf;
 
        if (cf->cf_unit == 0 &&
            strcmp(cf->cf_driver->cd_name, "backplane") == 0)
@@ -215,8 +207,8 @@ backplane_match(parent, gcf, aux)
        return (0);
 }
 
-static  void find_sbi __P((struct device *, struct bp_conf *,
-           int (*) __P((void *, char *))));
+static void find_sbi __P((struct device *, struct bp_conf *,
+           int (*) __P((void *, const char *))));
 
 
 void
@@ -225,52 +217,78 @@ backplane_attach(parent, self, hej)
        void    *hej;
 {
        struct bp_conf bp;
-       int i, ccpu, cmem, cbi, csbi;
 
        printf("\n");
+       bp.partyp = BACKPLANE;
 
-       switch (cpunumber) {
-       case VAX_750:
-       case VAX_650:
-       case VAX_78032:
-       case VAX_780:
-               cmem = cbi = 0;
-               ccpu = csbi = 1;
-               break;
-
-       case VAX_8600:
-               cmem = ccpu = 1;
-               cbi = csbi = 0;
-               break;
-       default:
-               cmem = ccpu = cbi = csbi = 0;
+       if (vax_bustype & VAX_CPUBUS) {
+               bp.type = "cpu";
+               bp.num = 0;
+               config_found(self, &bp, printut);
        }
-
-       bp.partyp = BACKPLANE;
-       bp.type = "cpu";
-       for (i = 0; i < ccpu; i++) {
-               bp.num = i;
+       if (vax_bustype & VAX_VSBUS) {
+               bp.type = "vsbus";
+               bp.num = 0;
                config_found(self, &bp, printut);
        }
-       bp.type = "mem";
-       for (i = 0; i < cmem; i++) {
-               bp.num = i;
+       if (vax_bustype & VAX_SBIBUS) {
+               bp.type = "sbi";
+               bp.num = 0;
                config_found(self, &bp, printut);
        }
-       bp.type = "bi";
-       for (i = 0; i < cbi; i++) {
-               bp.num = i;
+       if (vax_bustype & VAX_CMIBUS) {
+               bp.type = "cmi";
+               bp.num = 0;
                config_found(self, &bp, printut);
        }
-       bp.type = "sbi";
-       for(i = 0; i < csbi; i++) {
-               bp.num = i;
+       if (vax_bustype & VAX_UNIBUS) {
+               bp.type = "uba";
+               bp.num = 0;
                config_found(self, &bp, printut);
        }
 #if VAX8600
-       if (cpunumber == VAX_8600)
+       if (vax_bustype & VAX_MEMBUS) {
+               bp.type = "mem";
+               bp.num = 0;
+               config_found(self, &bp, printut);
+       }
+       if (vax_cputype == VAX_8600)
                find_sbi(self, &bp, printut);
 #endif
+
+#if VAX8200 || VAX8800
+       bp.type = "bi";
+       if (vax_bustype & VAX_BIBUS) {
+
+               switch (vax_cputype) {
+#if VAX8200
+               case VAX_8200: {
+                       extern void *bi_nodebase;
+
+                       bp.bp_addr = (int)bi_nodebase;
+                       config_found(self, &bp, printut);
+                       break;
+               }
+#endif
+#ifdef notyet
+               case VAX_8800: {
+                       int bi, biaddr;
+
+                       for (bi = 0; bi < MAXNBI; bi++) {
+                               biaddr = BI_BASE(bi) + BI_PROBE;
+                               if (badaddr((caddr_t)biaddr, 4))
+                                       continue;
+
+                               bp.bp_addr = BI_BASE(bi);
+                               config_found(self, &bp, printut);
+                       }
+                       break;
+               }
+#endif
+               }
+       }
+#endif
+
 }
 
 #if VAX8600
@@ -278,10 +296,10 @@ void
 find_sbi(self, bp, print)
        struct  device *self;
        struct  bp_conf *bp;
-       int     (*print) __P((void *, char *));
+       int     (*print) __P((void *, const char *));
 {
        volatile int tmp;
-       volatile struct sbia_regs *sbiar;
+       volatile struct sbia_regs *sbiar;
        extern  struct ioa *ioa;
        int     type, i;
 
@@ -311,28 +329,29 @@ find_sbi(self, bp, print)
 }
 #endif
 
-int     cpu_match __P((struct  device  *, void *, void *));
-void   cpu_attach __P((struct  device  *, struct  device  *, void *));
+int    cpu_match __P((struct  device  *, void *, void *));
+void   cpu_attach __P((struct  device  *, struct  device  *, void *));
 
 
 int
 cpu_match(parent, gcf, aux)
-       struct  device  *parent;
-       void    *gcf, *aux;
+       struct  device  *parent;
+       void    *gcf, *aux;
 {
-       struct  cfdata  *cf = gcf;
+       struct  cfdata  *cf = gcf;
        struct bp_conf *bp = aux;
 
        if (strcmp(bp->type, "cpu"))
                return 0;
 
-       switch (cpunumber) {
-#if VAX750 || VAX630 || VAX650 || VAX780 || VAX8600
+       switch (vax_cputype) {
+#if VAX750 || VAX630 || VAX650 || VAX780 || VAX8600 || VAX410
        case VAX_750:
        case VAX_78032:
        case VAX_650:
        case VAX_780:
        case VAX_8600:
+       default:
                if(cf->cf_unit == 0 && bp->partyp == BACKPLANE)
                        return 1;
                break;
@@ -344,26 +363,26 @@ cpu_match(parent, gcf, aux)
 
 void
 cpu_attach(parent, self, aux)
-       struct  device  *parent, *self;
-       void    *aux;
+       struct  device  *parent, *self;
+       void    *aux;
 {
-       (*cpu_calls[cpunumber].cpu_conf)(parent, self, aux);
+       (*cpu_calls[vax_cputype].cpu_conf)(parent, self, aux);
 }
 
-int     mem_match __P((struct  device  *, void  *, void *));
-void   mem_attach __P((struct  device  *, struct  device  *, void *));
+int    mem_match __P((struct  device  *, void  *, void *));
+void   mem_attach __P((struct  device  *, struct  device  *, void *));
 
 int
 mem_match(parent, gcf, aux)
-       struct  device  *parent;
-       void    *gcf, *aux;
+       struct  device  *parent;
+       void    *gcf, *aux;
 {
-       struct  cfdata  *cf = gcf;
+       struct  cfdata  *cf = gcf;
        struct  sbi_attach_args *sa = (struct sbi_attach_args *)aux;
-       struct  bp_conf *bp = aux;
+       struct  bp_conf *bp = aux;
 
 #if VAX8600
-       if (cpunumber == VAX_8600 && !strcmp(parent->dv_xname, "backplane0")) {
+       if (vax_cputype == VAX_8600 && !strcmp(parent->dv_xname, "backplane0")) {
                if (strcmp(bp->type, "mem"))
                        return 0;
                return 1;
@@ -404,14 +423,14 @@ mem_match(parent, gcf, aux)
 
 void
 mem_attach(parent, self, aux)
-       struct  device  *parent, *self;
-       void    *aux;
+       struct  device  *parent, *self;
+       void    *aux;
 {
        struct  sbi_attach_args *sa = (struct sbi_attach_args *)aux;
        struct  mem_softc *sc = (void *)self;
 
 #if VAX8600
-       if (cpunumber == VAX_8600) {
+       if (vax_cputype == VAX_8600) {
                ka86_memenable(0, 0);
                printf("\n");
                return;
@@ -420,22 +439,9 @@ mem_attach(parent, self, aux)
        sc->sc_memaddr = sa->nexaddr;
        sc->sc_memtype = sa->nexinfo;
        sc->sc_memnr = sa->type;
-
-       switch (cpunumber) {
-#ifdef VAX750
-       case VAX_750:
-               ka750_memenable(sa, (void *)sc);
-               break;
-#endif
 #ifdef VAX780
-       case VAX_780:
-               ka780_memenable(sa, sc);
-               break;
+       ka780_memenable(sa, sc);
 #endif
-       default:
-               break;
-       }
-
 }
 
 struct cfdriver backplane_cd = {
@@ -454,14 +460,14 @@ struct    cfattach cpu_backplane_ca = {
        sizeof(struct device), cpu_match, cpu_attach
 };
 
-struct  cfdriver mem_cd = {
+struct cfdriver mem_cd = {
        NULL, "mem", DV_CPU
 };
 
 struct cfattach mem_backplane_ca = {
-       sizeof(struct device), mem_match, mem_attach
+       sizeof(struct mem_softc), mem_match, mem_attach
 };
 
 struct cfattach mem_sbi_ca = {
-       sizeof(struct device), mem_match, mem_attach
+       sizeof(struct mem_softc), mem_match, mem_attach
 };
index 3a1a717..f55c19f 100644 (file)
@@ -1,4 +1,4 @@
-/*      $NetBSD: clock.c,v 1.14 1996/05/19 16:43:57 ragge Exp $  */
+/*     $NetBSD: clock.c,v 1.18 1996/10/13 03:35:33 christos Exp $       */
 /*
  * Copyright (c) 1995 Ludd, University of Lule}, Sweden.
  * All rights reserved.
 
 #include <machine/mtpr.h>
 #include <machine/sid.h>
-#include <machine/uvaxII.h>
-
-#define SEC_PER_DAY (60*60*24)
-
-extern int todrstopped;
+#include <machine/uvax.h>
+#include <machine/clock.h>
+#include <machine/cpu.h>
 
 static unsigned long year;     /*  start of current year in seconds */
 static unsigned long year_len; /* length of current year in 100th of seconds */
@@ -62,10 +60,10 @@ microtime(tvp)
        s = splhigh();
        int_time = mfpr(PR_TODR);
 
-        asm ("movc3 %0,(%1),(%2)" 
-                :
-                : "r" (sizeof(struct timeval)),"r" (&time),"r"(tvp)
-                :"r0","r1","r2","r3","r4","r5"); 
+       asm ("movc3 %0,(%1),(%2)" 
+               :
+               : "r" (sizeof(struct timeval)),"r" (&time),"r"(tvp)
+               :"r0","r1","r2","r3","r4","r5"); 
 
        i = mfpr(PR_ICR) + tick; /* Get current interval count */
        tvp->tv_usec += i;
@@ -103,69 +101,34 @@ void
 inittodr(fs_time) 
        time_t fs_time;
 {
+       int rv;
 
-       unsigned long tmp_year, sluttid, year_ticks;
-       int clock_stopped = 0;
+       rv = (*cpu_calls[vax_cputype].cpu_clkread) (fs_time);
+       switch (rv) {
 
-       sluttid = fs_time;
-       year = (fs_time / SEC_PER_DAY / 365) * 365 * SEC_PER_DAY;
-       tmp_year = year / SEC_PER_DAY / 365 + 2;
-       year_len = 100 * SEC_PER_DAY *
-           ((tmp_year % 4 && tmp_year != 32) ? 365 : 366);
-
-       switch (cpunumber) {
-#if VAX750 || VAX650
-       case VAX_750:
-       case VAX_650:
-               year_ticks = mfpr(PR_TODR);
-               clock_stopped = todrstopped;
+       case CLKREAD_BAD: /* No useable information from system clock */
+               time.tv_sec = fs_time;
+               resettodr();
                break;
-#endif
-#if VAX630 || VAX410
-       case VAX_78032:
-               year_ticks = uvaxII_gettodr(&clock_stopped);
+
+       case CLKREAD_WARN: /* Just give the warning */
                break;
-#endif
-#if VAX780 || VAX8600
-       case VAX_780:
-       case VAX_8600:
-               year_ticks = mfpr(PR_TODR);
+
+       default: /* System clock OK, no warning if we don't want to. */
+               if (time.tv_sec > fs_time + 3 * SEC_PER_DAY) {
+                       printf("Clock has gained %d days",
+                           (time.tv_sec - fs_time) / SEC_PER_DAY);
+                       rv = CLKREAD_WARN;
+               } else if (time.tv_sec + SEC_PER_DAY < fs_time) {
+                       printf("Clock has lost %d day(s)",
+                           (fs_time - time.tv_sec) / SEC_PER_DAY);
+                       rv = CLKREAD_WARN;
+               }
                break;
-#endif
-       default:
-               year_ticks = 0;
-               clock_stopped = 1;
-       };
-
-       if (clock_stopped){
-               printf(
-       "Internal clock not started. Using time from file system.\n");
-               switch (cpunumber) {
-#if VAX750 || VAX650
-               case VAX_750:
-               case VAX_650:
-                       /* +1 so the clock won't be stopped */
-                       mtpr((fs_time - year) * 100 + 1, PR_TODR);
-                       break;
-#endif
-#if VAX630 || VAX410
-               case VAX_78032:
-                       uvaxII_settodr((fs_time - year) * 100 + 1);
-                       break;
-#endif
-               };
-               todrstopped = 0;
-       } else if (year_ticks / 100 > fs_time - year + SEC_PER_DAY * 3) {
-               printf(
-       "WARNING: Clock has gained %d days - CHECK AND RESET THE DATE.\n",
-                   (int)(year_ticks / 100 - (fs_time - year)) / SEC_PER_DAY);
-               sluttid = year + (year_ticks / 100);
-       } else if (year_ticks / 100 < fs_time - year) {
-               printf(
-               "WARNING: Clock has lost time - CHECK AND RESET THE DATE.\n");
-       } else
-               sluttid = year + (year_ticks / 100);
-       time.tv_sec = sluttid;
+       }
+
+       if (rv < CLKREAD_OK)
+               printf(" - CHECK AND RESET THE DATE.\n");
 }
 
 /*   
@@ -175,30 +138,8 @@ inittodr(fs_time)
 void
 resettodr()
 {
-
-       unsigned long tmp_year;
-
-       year = (time.tv_sec / SEC_PER_DAY / 365) * 365 * SEC_PER_DAY;
-       tmp_year = year / SEC_PER_DAY / 365 + 2;
-       year_len = 100 * SEC_PER_DAY *
-           ((tmp_year % 4 && tmp_year != 32) ? 365 : 366);
-       switch (cpunumber) {
-#if VAX750
-       case VAX_750:
-               mtpr((time.tv_sec - year) * 100 + 1, PR_TODR);
-               break;
-#endif
-#if VAX630 || VAX410
-       case VAX_78032:
-               uvaxII_settodr((time.tv_sec - year) * 100 + 1);
-               break;
-#endif
-       default:
-               mtpr((time.tv_sec - year) * 100, PR_TODR);
-       };
-       todrstopped = 0;
+       (*cpu_calls[vax_cputype].cpu_clkwrite)();
 }
-
 /*
  * A delayloop that delays about the number of milliseconds that is
  * given as argument.
@@ -209,14 +150,19 @@ delay(i)
 {
        int     mul;
 
-       switch (cpunumber) {
-#if VAX750 || VAX630 || VAX780
+       switch (vax_cputype) {
+#if VAX750 || VAX630 || VAX410
        case VAX_750:
        case VAX_78032:
-       case VAX_780:
                mul = 1; /* <= 1 VUPS */
                break;
 #endif
+#if VAX780 || VAX8200
+       case VAX_780:
+       case VAX_8200:
+               mul = 2; /* <= 2 VUPS */
+               break;
+#endif
 #if VAX650
        case VAX_650:
                mul = 3; /* <= 3 VUPS */
@@ -229,3 +175,168 @@ delay(i)
        }
        asm ("1: sobgtr %0, 1b" : : "r" (mul * i));
 }
+
+#if VAX750 || VAX780 || VAX8200 || VAX8600 || VAX8800
+/*
+ * On most VAXen there are a microsecond clock that should
+ * be used for interval interrupts. Have a generic version here.
+ */
+void
+generic_clock()
+{
+       mtpr(-10000, PR_NICR); /* Load in count register */
+       mtpr(0x800000d1, PR_ICCS); /* Start clock and enable interrupt */
+}
+#endif
+
+#if VAX650 || VAX630 || VAX410 || VAX43
+/*
+ * Most microvaxen don't have a interval count register.
+ */
+void
+no_nicr_clock()
+{
+       mtpr(0x800000d1, PR_ICCS); /* Start clock and enable interrupt */
+}
+#endif
+
+/*
+ * There are two types of real-time battery-backed up clocks on
+ * VAX computers, one with a register that counts up every 1/100 second,
+ * one with a clock chip that delivers time. For the register clock
+ * we have a generic version, and for the chip clock there are 
+ * support routines for time conversion.
+ */
+/*
+ * Converts a year to corresponding number of ticks.
+ */
+int
+yeartonum(y)
+       int y;
+{
+       int n;
+
+       for (n = 0, y -= 1; y > 69; y--)
+               n += SECPERYEAR(y);
+       return n;
+}
+
+/* 
+ * Converts tick number to a year 70 ->
+ */
+int
+numtoyear(num)
+       int num;
+{
+       int y = 70, j;
+       while(num >= (j = SECPERYEAR(y))) {
+               y++;
+               num -= j;
+       }
+       return y;
+}
+
+#if VAX750 || VAX780 || VAX8600 || VAX650
+/*
+ * Reads the TODR register; returns a (probably) true tick value,
+ * or CLKREAD_BAD if failed. The year is based on the argument
+ * year; the TODR doesn't hold years.
+ */
+int
+generic_clkread(base)
+       time_t base;
+{
+       unsigned klocka = mfpr(PR_TODR);
+
+       /*
+        * Sanity check.
+        */
+       if (klocka < TODRBASE) {
+               if (klocka == 0)
+                       printf("TODR stopped");
+               else
+                       printf("TODR too small");
+               return CLKREAD_BAD;
+       }
+
+       time.tv_sec = yeartonum(numtoyear(base)) + (klocka - TODRBASE) / 100;
+       return CLKREAD_OK;
+}
+
+/*
+ * Takes the current system time and writes it to the TODR.
+ */
+void
+generic_clkwrite()
+{
+       unsigned tid = time.tv_sec, bastid;
+
+       bastid = tid - yeartonum(numtoyear(tid));
+       mtpr((bastid * 100) + TODRBASE, PR_TODR);
+}
+#endif
+
+#if VAX630 || VAX410 || VAX43 || VAX8200
+
+static int dagar[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
+
+/*
+ * Returns the number of days in month based on the current year.
+ */
+int
+daysinmonth(m, y)
+       int m, y;
+{
+       if (m == 2 && IS_LEAPYEAR(y))
+               return 29;
+       else
+               return dagar[m - 1];
+}
+
+/*
+ * Converts chiptime (year/month/day/hour/min/sek) and returns ticks.
+ */
+long
+chiptotime(c)
+       struct chiptime *c;
+{
+       int num, i;
+
+       num = c->sec;
+       num += c->min * SEC_PER_MIN;
+       num += c->hour * SEC_PER_HOUR;
+       num += (c->day - 1) * SEC_PER_DAY;
+       for(i = c->mon - 1; i > 0; i--)
+               num += daysinmonth(i, c->year) * SEC_PER_DAY;
+       num += yeartonum(c->year);
+
+       return num;
+}
+
+/*
+ * Reads the system time and puts it into a chiptime struct.
+ */
+void
+timetochip(c)
+       struct chiptime *c;
+{
+       int tid = time.tv_sec, i, j;
+
+       c->year = numtoyear(tid);
+       tid -= yeartonum(c->year);
+
+       c->mon = 1;
+       while(tid >= (j = (daysinmonth(c->mon, c->year) * SEC_PER_DAY))) {
+               c->mon++;
+               tid -= j;
+       }
+       c->day = (tid / SEC_PER_DAY) + 1;
+       tid %= SEC_PER_DAY;
+
+       c->hour = tid / SEC_PER_HOUR;
+       tid %= SEC_PER_HOUR;
+
+       c->min = tid / SEC_PER_MIN;
+       c->sec = tid % SEC_PER_MIN;
+}
+#endif
index d78fe74..4abb4d7 100644 (file)
@@ -1,4 +1,5 @@
-/*     $NetBSD: conf.c,v 1.21 1996/04/08 18:32:29 ragge Exp $  */
+/*     $OpenBSD: conf.c,v 1.10 1997/01/15 23:25:06 maja Exp $ */
+/*     $NetBSD: conf.c,v 1.27 1997/01/07 11:35:20 mrg Exp $    */
 
 /*-
  * Copyright (c) 1982, 1986 The Regents of the University of California.
 #include <sys/conf.h>
 #include <sys/vnode.h>
 
-int    ttselect        __P((dev_t, int, struct proc *));
-
-#ifndef LKM
-#define lkmenodev       enodev
-#endif
-
 #include "hp.h" /* 0 */
 bdev_decl(hp);
 
@@ -63,27 +58,24 @@ bdev_decl(sw);
 #include "te.h"
 bdev_decl(tm);
 
-#include "tmscp.h"
-bdev_decl(tmscp);
+#include "mt.h"
+bdev_decl(mt);
 
 #include "ts.h"
 bdev_decl(ts);
 
 #include "mu.h"
-bdev_decl(mt);
+bdev_decl(mu);
 
 #if defined(VAX750)
-#define        NCTU    1
+#define NCTU   1
 #else
-#define        NCTU    0
+#define NCTU   0
 #endif
 bdev_decl(ctu);
 
-#include "uda.h"
-bdev_decl(uda);
-
-#include "kdb.h"
-bdev_decl(kdb);
+#include "ra.h"
+bdev_decl(ra);
 
 #include "up.h"
 bdev_decl(up);
@@ -109,6 +101,21 @@ bdev_decl(ccd);
 #include "vnd.h"
 bdev_decl(vnd);
 
+#include "hdc.h"
+bdev_decl(hdc);
+
+#include "sd.h"
+bdev_decl(sd);
+
+#include "st.h"
+bdev_decl(st);
+
+#include "cd.h"
+bdev_decl(cd);
+
+#include "md.h"
+bdev_decl(md);
+
 struct bdevsw  bdevsw[] =
 {
        bdev_disk_init(NHP,hp),         /* 0: RP0?/RM0? */
@@ -118,33 +125,53 @@ struct bdevsw     bdevsw[] =
        bdev_swap_init(1,sw),           /* 4: swap pseudo-device */
        bdev_tape_init(NTE,tm),         /* 5: TM11/TE10 */
        bdev_tape_init(NTS,ts),         /* 6: TS11 */
-       bdev_tape_init(NMU,mt),         /* 7: TU78 */
+       bdev_tape_init(NMU,mu),         /* 7: TU78 */
        bdev_tape_init(NCTU,ctu),       /* 8: Console TU58 on 730/750 */
-       bdev_disk_init(NUDA,uda),       /* 9: UDA50/RA?? */
+       bdev_disk_init(NRA,ra),         /* 9: MSCP disk */
        bdev_tape_init(NTJ,ut),         /* 10: TU45 */
        bdev_disk_init(NRB,idc),        /* 11: IDC (RB730) */
        bdev_disk_init(NRX,rx),         /* 12: RX01/02 on unibus */
        bdev_disk_init(NUU,uu),         /* 13: TU58 on DL11 */
        bdev_disk_init(NRL,rl),         /* 14: RL01/02 */
-       bdev_tape_init(NTMSCP,tmscp),   /* 15: TMSCP tape */
-       bdev_disk_init(NKDB,kdb),       /* 16: KDB50/RA?? */
+       bdev_tape_init(NMT,mt),         /* 15: MSCP tape */
+       bdev_notdef(),                  /* 16: was: KDB50/RA?? */
        bdev_disk_init(NCCD,ccd),       /* 17: concatenated disk driver */
        bdev_disk_init(NVND,vnd),       /* 18: vnode disk driver */
+       bdev_disk_init(NHDC,hdc),       /* 19: HDC9224/RD?? */
+       bdev_disk_init(NSD,sd),         /* 20: SCSI disk */
+       bdev_tape_init(NST,st),         /* 21: SCSI tape */
+       bdev_disk_init(NCD,cd),         /* 22: SCSI CD-ROM */
+       bdev_disk_init(NMD,md),         /* 23: memory disk driver */
 };
 int    nblkdev = sizeof(bdevsw) / sizeof(bdevsw[0]);
 
 /*
- * Console routines for VAX console. There are always an generic console,
- * but maybe we should care about RD, QDSS etc?
+ * Console routines for VAX console.
  */
 #include <dev/cons.h>
 
-#define gencnpollc      nullcnpollc
+#define gencnpollc     nullcnpollc
 cons_decl(gen);
+#define dzcnpollc      nullcnpollc
+cons_decl(dz);
 
-struct consdev constab[]={
-/* Generic console, should always be present */
-       cons_init(gen),
+struct consdev constab[]={
+#if VAX8600 || VAX780 || VAX750 || VAX650 || VAX630
+#define NGEN   1
+       cons_init(gen), /* Generic console type; mtpr/mfpr */
+#else
+#define NGEN   0
+#endif
+#if VAX410 || VAX43
+#define NDZCN  1
+       cons_init(dz),  /* DZ11-like serial console on VAXstations */
+#else
+#define NDZCN  0
+#endif
+#if 0 /* VAX410 || VAX43 || VAX650 || VAX630 */
+       cons_init(qv),  /* QVSS/QDSS bit-mapped console driver */
+       cons_init(qd),
+#endif
 
 #ifdef notyet
 /* We may not always use builtin console, sometimes RD */
@@ -156,76 +183,73 @@ struct    consdev constab[]={
 /* Special for console storage */
 #define dev_type_rw(n) int n __P((dev_t, int, int, struct proc *))
 
-/* plotters - open, close, write, ioctl, select */
+/* plotters - open, close, write, ioctl, poll */
 #define cdev_plotter_init(c,n) { \
        dev_init(c,n,open), dev_init(c,n,close), (dev_type_read((*))) enodev, \
        dev_init(c,n,write), dev_init(c,n,ioctl), (dev_type_stop((*))) enodev, \
-       0, dev_init(c,n,select), (dev_type_mmap((*))) enodev }
+       0, dev_init(c,n,poll), (dev_type_mmap((*))) enodev }
 
 /* console mass storage - open, close, read/write */
-#define        cdev_cnstore_init(c,n) { \
+#define cdev_cnstore_init(c,n) { \
        dev_init(c,n,open), dev_init(c,n,close), dev_init(c,n,read), \
        dev_init(c,n,write), (dev_type_ioctl((*))) enodev, \
-       (dev_type_stop((*))) enodev, 0, (dev_type_select((*))) enodev, \
+       (dev_type_stop((*))) enodev, 0, (dev_type_poll((*))) enodev, \
        (dev_type_mmap((*))) enodev }
 
-#define        cdev_lp_init(c,n) { \
+#define cdev_lp_init(c,n) { \
        dev_init(c,n,open), dev_init(c,n,close), (dev_type_read((*))) enodev, \
        dev_init(c,n,write), (dev_type_ioctl((*))) enodev, \
        (dev_type_stop((*))) enodev, 0, seltrue, (dev_type_mmap((*))) enodev }
 
 /* graphic display adapters */
-#define        cdev_graph_init(c,n) { \
+#define cdev_graph_init(c,n) { \
        dev_init(c,n,open), dev_init(c,n,close), dev_init(c,n,read), \
        dev_init(c,n,write), dev_init(c,n,ioctl), dev_init(c,n,stop), \
-       0, dev_init(c,n,select), (dev_type_mmap((*))) enodev }
+       0, dev_init(c,n,poll), (dev_type_mmap((*))) enodev }
 
 /* Ingres */
 #define cdev_ingres_init(c,n) { \
        dev_init(c,n,open), dev_init(c,n,close), (dev_type_read((*))) nullop, \
        (dev_type_write((*))) nullop, dev_init(c,n,ioctl), \
-       (dev_type_stop((*))) nullop, 0, (dev_type_select((*))) nullop, \
+       (dev_type_stop((*))) nullop, 0, (dev_type_poll((*))) nullop, \
        (dev_type_mmap((*))) enodev }
 
 
 
 cdev_decl(cn);
 cdev_decl(ctty);
-#define        mmread  mmrw
-#define        mmwrite mmrw
+#define mmread mmrw
+#define mmwrite mmrw
 cdev_decl(mm);
 cdev_decl(sw);
 #include "pty.h"
-#define        ptstty          ptytty
-#define        ptsioctl        ptyioctl
+#define ptstty         ptytty
+#define ptsioctl       ptyioctl
 cdev_decl(pts);
-#define        ptctty          ptytty
-#define        ptcioctl        ptyioctl
+#define ptctty         ptytty
+#define ptcioctl       ptyioctl
 cdev_decl(ptc);
 cdev_decl(log);
-#ifdef LKM
-#define        NLKM    1
-#else
-#define        NLKM    0
-#endif
-cdev_decl(lkm);
 
 cdev_decl(hp);
 cdev_decl(rk);
 cdev_decl(tm);
-cdev_decl(tmscp);
-cdev_decl(ts);
 cdev_decl(mt);
-cdev_decl(uda);
+cdev_decl(ts);
+cdev_decl(mu);
+cdev_decl(ra);
 cdev_decl(up);
 cdev_decl(ut);
 cdev_decl(idc);
 cdev_decl(fd);
 cdev_decl(gencn);
+cdev_decl(dzcn);
 cdev_decl(rx);
 cdev_decl(rl);
-cdev_decl(kdb);
 cdev_decl(ccd);
+cdev_decl(hdc);
+cdev_decl(sd);
+cdev_decl(st);
 
 #include "ct.h"
 cdev_decl(ct);
@@ -238,31 +262,31 @@ cdev_decl(dmf);
 cdev_decl(np);
 
 #if VAX8600
-#define        NCRL 1
+#define NCRL 1
 #else
 #define NCRL 0
 #endif
-#define        crlread crlrw
+#define crlread crlrw
 #define crlwrite crlrw
 cdev_decl(crl);
 
-#if VAX8200
+#if VAX8200 && 0
 #define NCRX 1
 #else
 #define NCRX 0
 #endif
-#define        crxread crxrw
-#define        crxwrite crxrw
+#define crxread crxrw
+#define crxwrite crxrw
 cdev_decl(crx);
 
-#if VAX780 && 0
-#define        NFL 1
+#if VAX780
+#define NCFL 1
 #else
-#define NFL 0
+#define NCFL 0
 #endif
-#define flread flrw
-#define flwrite flrw
-cdev_decl(fl);
+#define cflread cflrw
+#define cflwrite cflrw
+cdev_decl(cfl);
 
 #include "dz.h"
 cdev_decl(dz);
@@ -303,10 +327,15 @@ cdev_decl(qv);
 #include "qd.h"
 cdev_decl(qd);
 
+#ifdef 0
+#include "ipfilter.h"
+cdev_decl(ipl);
+#endif
+
 #if defined(INGRES)
-#define        NII 1
+#define NII 1
 #else
-#define        NII 0
+#define NII 0
 #endif
 cdev_decl(ii);
 
@@ -317,6 +346,14 @@ cdev_decl(bpf);
 
 #include "tun.h" 
 cdev_decl(tun);
+cdev_decl(cd);
+#include "ch.h"
+cdev_decl(ch);
+cdev_decl(md);
+#include "ss.h"
+cdev_decl(ss);
+#include "uk.h"
+cdev_decl(uk);
 
 cdev_decl(random);
 
@@ -332,8 +369,8 @@ struct cdevsw       cdevsw[] =
        cdev_notdef(),                  /* 5 */
        cdev_plotter_init(NVP,vp),      /* 6: Versatec plotter */
        cdev_swap_init(1,sw),           /* 7 */
-       cdev_cnstore_init(NFL,fl),      /* 8: 11/780 console floppy */
-       cdev_disk_init(NUDA,uda),       /* 9: MSCP disk interface */
+       cdev_cnstore_init(NCFL,cfl),    /* 8: 11/780 console floppy */
+       cdev_disk_init(NRA,ra),         /* 9: MSCP disk interface */
        cdev_plotter_init(NVA,va),      /* 10: Benson-Varian plotter */
        cdev_disk_init(NRK,rk),         /* 11: RK06/07 */
        cdev_tty_init(NDH,dh),          /* 12: DH-11/DM-11 */
@@ -343,13 +380,13 @@ struct cdevsw     cdevsw[] =
        cdev_tape_init(NTS,ts),         /* 16: TS11 */
        cdev_tape_init(NTJ,ut),         /* 17: TU45 */
        cdev_lp_init(NCT,ct),           /* 18: phototypesetter interface */
-       cdev_tape_init(NMU,mt),         /* 19: TU78 */
+       cdev_tape_init(NMU,mu),         /* 19: TU78 */
        cdev_tty_init(NPTY,pts),        /* 20: pseudo-tty slave */
        cdev_ptc_init(NPTY,ptc),        /* 21: pseudo-tty master */
        cdev_tty_init(NDMF,dmf),        /* 22: DMF32 */
        cdev_disk_init(NRB,idc),        /* 23: IDC (RB730) */
        cdev_lp_init(NDN,dn),           /* 24: DN-11 autocall unit */
-       cdev_tty_init(1,gencn),         /* 25: Generic console (mtpr...) */
+       cdev_tty_init(NGEN,gencn),      /* 25: Generic console (mtpr...) */
        cdev_audio_init(NLPA,lpa),      /* 26 ??? */
        cdev_graph_init(NPS,ps),        /* 27: E/S graphics device */
        cdev_lkm_init(NLKM,lkm),        /* 28: loadable module driver */
@@ -360,13 +397,17 @@ struct cdevsw     cdevsw[] =
        cdev_log_init(1,log),           /* 33: /dev/klog */
        cdev_tty_init(NDHU,dhu),        /* 34: DHU-11 */
        cdev_cnstore_init(NCRL,crl),    /* 35: Console RL02 on 8600 */
-       cdev_notdef(),                  /* 36: was vs100 interface. ??? */
+       cdev_tty_init(NDZCN,dzcn),      /* 36: DZ11-like console on VAXst. */
        cdev_tty_init(NDMZ,dmz),        /* 37: DMZ32 */
-       cdev_tape_init(NTMSCP,tmscp),   /* 38: TMSCP tape */
+       cdev_tape_init(NMT,mt),         /* 38: MSCP tape */
        cdev_audio_init(NNP,np),        /* 39: NP Intelligent Board */
        cdev_graph_init(NQV,qv),        /* 40: QVSS graphic display */
        cdev_graph_init(NQD,qd),        /* 41: QDSS graphic display */
-       cdev_notdef(),                  /* 42 */
+#ifdef 0
+       cdev_ipf_init(NIPFILTER,ipl),   /* 42: Packet filter */
+#else
+       cdev_notdef(),
+#endif
        cdev_ingres_init(NII,ii),       /* 43: Ingres device */
        cdev_notdef(),                  /* 44  was Datakit */
        cdev_notdef(),                  /* 45  was Datakit */
@@ -376,17 +417,25 @@ struct cdevsw     cdevsw[] =
        cdev_notdef(),                  /* 49 */
        cdev_notdef(),                  /* 50 */
        cdev_cnstore_init(NCRX,crx),    /* 51: Console RX50 at 8200 */
-       cdev_disk_init(NKDB,kdb),       /* 52: KDB50/RA?? */
+       cdev_notdef(),                  /* 52: was: KDB50/RA?? */
        cdev_fd_init(1,filedesc),       /* 53: file descriptor pseudo-device */
        cdev_disk_init(NCCD,ccd),       /* 54: concatenated disk driver */
        cdev_disk_init(NVND,vnd),       /* 55: vnode disk driver */
        cdev_bpftun_init(NBPFILTER,bpf),/* 56: berkeley packet filter */
        cdev_bpftun_init(NTUN,tun),     /* 57: tunnel filter */
-       cdev_random_init(1,random),     /* 58: random data source */
+       cdev_disk_init(NHDC,hdc),       /* 58: HDC9224/RD?? */
+       cdev_disk_init(NSD,sd),         /* 59: SCSI disk */
+       cdev_tape_init(NST,st),         /* 60: SCSI tape */
+       cdev_disk_init(NCD,cd),         /* 61: SCSI CD-ROM */
+       cdev_disk_init(NMD,md),         /* 62: memory disk driver */
+       cdev_ch_init(NCH,ch),           /* 63: SCSI autochanger */
+       cdev_scanner_init(NSS,ss),      /* 64: SCSI scanner */
+       cdev_uk_init(NUK,uk),           /* 65: SCSI unknown */
+       cdev_random_init(1,random),     /* 66: random data source */
 };
 int    nchrdev = sizeof(cdevsw) / sizeof(cdevsw[0]);
 
-int    mem_no = 3;     /* major device number of memory special file */
+int    mem_no = 3;     /* major device number of memory special file */
 
 /*
  * Swapdev is a fake device implemented
@@ -404,16 +453,16 @@ int       chrtoblktbl[] = {
        NODEV,  /* 1 */
        NODEV,  /* 2 */
        NODEV,  /* 3 */
-       0,      /* 4 */
-       1,      /* 5 */
+       0,      /* 4 */
+       1,      /* 5 */
        NODEV,  /* 6 */
        NODEV,  /* 7 */
        NODEV,  /* 8 */
-       9,      /* 9 */
+       9,      /* 9 */
        NODEV,  /* 10 */
-       3,      /* 11 */
+       3,      /* 11 */
        NODEV,  /* 12 */
-       2,      /* 13 */
+       2,      /* 13 */
        5,      /* 14 */
        NODEV,  /* 15 */
        6,      /* 16 */
@@ -451,11 +500,21 @@ int       chrtoblktbl[] = {
        NODEV,  /* 48 */
        NODEV,  /* 49 */
        NODEV,  /* 50 */
-       NODEV,  /* 51 */
+       NODEV,  /* 51 */
        16,     /* 52 */
        NODEV,  /* 53 */
        17,     /* 54 */
        18,     /* 55 */
+       NODEV,  /* 56 */
+       NODEV,  /* 57 */
+       19,     /* 58 */
+       20,     /* 59 */
+       21,     /* 60 */
+       22,     /* 61 */
+       23,     /* 62 */
+       NODEV,  /* 63 */
+       NODEV,  /* 64 */
+       NODEV,  /* 65 */
 };
 
 int
index c928997..9c2c687 100644 (file)
@@ -1,4 +1,4 @@
-/*     $NetBSD: crl.c,v 1.2 1996/04/08 18:32:30 ragge Exp $    */
+/*     $NetBSD: crl.c,v 1.5 1996/10/13 03:35:35 christos Exp $ */
 /*-
  * Copyright (c) 1982, 1986 The Regents of the University of California.
  * All rights reserved.
@@ -75,17 +75,17 @@ int crlclose __P((dev_t, int, struct proc *));
 int    crlrw __P((dev_t, struct uio *, int));
 
 
-struct  ivec_dsp crl_intr;
+struct ivec_dsp crl_intr;
 
 void
 crlattach()
 {
-       extern  struct ivec_dsp idsptch;
+       extern  struct ivec_dsp idsptch;
 
        bcopy(&idsptch, &crl_intr, sizeof(struct ivec_dsp));
        scb->scb_csrint = &crl_intr;
        crl_intr.hoppaddr = crlintr;
-}       
+}      
 
 /*ARGSUSED*/
 int
@@ -94,7 +94,7 @@ crlopen(dev, flag, p)
        int flag;
        struct proc *p;
 {
-       if (cpunumber != VAX_8600)
+       if (vax_cputype != VAX_8600)
                return (ENXIO);
        if (crltab.crl_state != CRL_IDLE)
                return (EALREADY);
index 2584aaa..1d5727a 100644 (file)
@@ -1,4 +1,4 @@
-/*     $NetBSD: ctu.c,v 1.3 1996/04/08 18:32:31 ragge Exp $ */
+/*     $NetBSD: ctu.c,v 1.5 1996/10/13 03:35:36 christos Exp $ */
 /*
  * Copyright (c) 1996 Ludd, University of Lule}, Sweden.
  * All rights reserved.
index 2695065..a985982 100644 (file)
@@ -1,4 +1,4 @@
-/*     $NetBSD: db_disasm.c,v 1.6 1996/04/08 18:32:32 ragge Exp $ */
+/*     $NetBSD: db_disasm.c,v 1.9 1996/10/13 03:35:38 christos Exp $ */
 /*
  * Copyright (c) 1996 Ludd, University of Lule}, Sweden.
  * All rights reserved.
@@ -16,8 +16,8 @@
  *    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 at Ludd, University of 
- *      Lule}, Sweden and its contributors.
+ *     This product includes software developed at Ludd, University of 
+ *     Lule}, Sweden and its contributors.
  * 4. The name of the author may not be used to endorse or promote products
  *    derived from this software without specific prior written permission
  *
 
 
 #include <sys/param.h>
-#include <sys/systm.h>
 #include <sys/proc.h>
 #include <sys/reboot.h>
 
 #include <machine/db_machdep.h>
 #include <ddb/db_sym.h>
-#include <ddb/db_output.h>
-#include <ddb/db_interface.h>
 #include <ddb/db_variables.h>
 
 #include <vax/vax/db_disasm.h>
 
 #ifdef VMS_MODE
 #define DEFERRED   '@'
-#define LITERAL    '#'
+#define LITERAL           '#'
 #else
 #define DEFERRED   '*'
-#define LITERAL    '$'
+#define LITERAL           '$'
 #endif
 /*
  * disassembling vax instructions works as follows:
  *
- * - get first byte as opcode (check for two-byte opcodes!)
- * - evaluate (variable length) argument list
- * - for each argument get type (byte, long, address etc.)
- * - evaluate addressing mode for this argument
- * - db_printf the opcode and the (value of the) arguments
- * - return the start of the next instruction
+ * 1.  get first byte as opcode (check for two-byte opcodes!)
+ * 2.  lookup in op-table for mnemonic and operand-list
+ * 2.a store the mnemonic
+ * 3.  for each operand in list: get the size/type
+ * 3.a evaluate addressing mode for this operand
+ * 3.b store each operand(s)
+ * 4.  db_printf the opcode and the (value of the) operands
+ * 5.  return the start of the next instruction
  *
  * - if jump/branch calculate (and display) the target-address
  */
 /* 
 #define BROKEN_DB_REGS
 */
-#ifdef  BROKEN_DB_REGS
-struct {                /* Due to order and contents of db_regs[], we can't */
-        char *name;     /* use this array to extract register-names. */
-        void *valuep;   /* eg. "psl" vs "pc", "pc" vs "sp" */
+#ifdef BROKEN_DB_REGS
+struct {               /* Due to order and contents of db_regs[], we can't */
+       char *name;     /* use this array to extract register-names. */
+       void *valuep;   /* eg. "psl" vs "pc", "pc" vs "sp" */
 } my_db_regs[16] = {
-        { "r0",         NULL },
-        { "r1",         NULL },
-        { "r2",         NULL },
-        { "r3",         NULL },
-        { "r4",         NULL },
-        { "r5",         NULL },
-        { "r6",         NULL },
-        { "r7",         NULL },
-        { "r8",         NULL },
-        { "r9",         NULL },
-        { "r10",        NULL },
-        { "r11",        NULL },
-        { "ap",         NULL },         /* aka "r12" */
-        { "fp",         NULL },         /* aka "r13" */
-        { "sp",         NULL },         /* aka "r14" */
-        { "pc",         NULL },         /* aka "r15" */
+       { "r0",         NULL },
+       { "r1",         NULL },
+       { "r2",         NULL },
+       { "r3",         NULL },
+       { "r4",         NULL },
+       { "r5",         NULL },
+       { "r6",         NULL },
+       { "r7",         NULL },
+       { "r8",         NULL },
+       { "r9",         NULL },
+       { "r10",        NULL },
+       { "r11",        NULL },
+       { "ap",         NULL },         /* aka "r12" */
+       { "fp",         NULL },         /* aka "r13" */
+       { "sp",         NULL },         /* aka "r14" */
+       { "pc",         NULL },         /* aka "r15" */
 };
 #else
 #define my_db_regs db_regs
 #endif
 
 typedef struct {
-       char            dasm[256];      /* disassebled instruction as text */
-       char           *curp;   /* pointer into result */
-       char           *ppc;    /* pseudo PC */
-       int             opc;    /* op-code */
-       char           *argp;   /* pointer into argument-list */
-       int             itype;  /* instruction-type, eg. branch, call, unspec */
-       int             atype;  /* argument-type, eg. byte, long, address */
-       int             off;    /* offset specified by last argument */
-       int             addr;   /* address specified by last argument */
-}       inst_buffer;
+       char            dasm[256];      /* disassebled instruction as text */
+       char           *curp;   /* pointer into result */
+       char           *ppc;    /* pseudo PC */
+       int             opc;    /* op-code */
+       char           *argp;   /* pointer into argument-list */
+       int             itype;  /* instruction-type, eg. branch, call, unspec */
+       int             atype;  /* argument-type, eg. byte, long, address */
+       int             off;    /* offset specified by last argument */
+       int             addr;   /* address specified by last argument */
+}      inst_buffer;
 
 #define ITYPE_INVALID  -1
-#define ITYPE_UNSPEC    0
-#define ITYPE_BRANCH    1
-#define ITYPE_CALL      2
+#define ITYPE_UNSPEC   0
+#define ITYPE_BRANCH   1
+#define ITYPE_CALL     2
 
-int get_byte    __P((inst_buffer * ib));
-int get_word    __P((inst_buffer * ib));
-int get_long    __P((inst_buffer * ib));
+int get_byte   __P((inst_buffer * ib));
+int get_word   __P((inst_buffer * ib));
+int get_long   __P((inst_buffer * ib));
 
-int get_opcode  __P((inst_buffer * ib));
+int get_opcode __P((inst_buffer * ib));
 int get_operands __P((inst_buffer * ib));
 int get_operand __P((inst_buffer * ib, int size));
 
-void add_char   __P((inst_buffer * ib, int c));
-void add_str    __P((inst_buffer * ib, char *s));
-void add_int    __P((inst_buffer * ib, int i));
-void add_xint   __P((inst_buffer * ib, int i));
-void add_sym    __P((inst_buffer * ib, int i));
-void add_off    __P((inst_buffer * ib, int i));
+void add_char  __P((inst_buffer * ib, int c));
+void add_str   __P((inst_buffer * ib, char *s));
+void add_int   __P((inst_buffer * ib, int i));
+void add_xint  __P((inst_buffer * ib, int i));
+void add_sym   __P((inst_buffer * ib, int i));
+void add_off   __P((inst_buffer * ib, int i));
 
 #define err_print  printf
 
@@ -141,14 +140,14 @@ void add_off    __P((inst_buffer * ib, int i));
  */
 db_addr_t
 db_disasm(loc, altfmt)
-       db_addr_t       loc;
-       boolean_t       altfmt;
+       db_addr_t       loc;
+       boolean_t       altfmt;
 {
-       db_expr_t       diff;
-       db_sym_t        sym;
-       char           *symname;
+       db_expr_t       diff;
+       db_sym_t        sym;
+       char           *symname;
 
-       inst_buffer     ib;
+       inst_buffer     ib;
 
        bzero(&ib, sizeof(ib));
        ib.ppc = (void *) loc;
@@ -160,7 +159,7 @@ db_disasm(loc, altfmt)
                sym = db_search_symbol(loc, DB_STGY_PROC, &diff);
                db_symbol_values(sym, &symname, 0);
 
-               if (symname && !diff) { /* symbol at loc */
+               if (symname && !diff) { /* symbol at loc */
                        db_printf("function \"%s()\", entry-mask 0x%x\n\t\t",
                                  symname, (unsigned short) get_word(&ib));
                        ib.ppc += 2;
@@ -210,8 +209,8 @@ int
 get_operands(ib)
        inst_buffer    *ib;
 {
-       int             aa = 0; /* absolute address mode ? */
-       int             size;
+       int             aa = 0; /* absolute address mode ? */
+       int             size;
 
        if (ib->opc < 0 || ib->opc > 0xFF) {
                /* invalid or two-byte opcode */
@@ -243,7 +242,7 @@ get_operands(ib)
                        break;
 
                case 'a':       /* absolute adressing mode */
-                       aa = 1; /* do not break here ! */
+                       aa = 1; /* do not break here ! */
 
                default:
                        switch (*(++ib->argp)) {
@@ -301,14 +300,14 @@ get_operands(ib)
 int
 get_operand(ib, size)
        inst_buffer    *ib;
-       int             size;
+       int             size;
 {
-       int             c = get_byte(ib);
-       int             mode = c >> 4;
-       int             reg = c & 0x0F;
-       int             lit = c & 0x3F;
-       int             tmp = 0;
-       char            buf[16];
+       int             c = get_byte(ib);
+       int             mode = c >> 4;
+       int             reg = c & 0x0F;
+       int             lit = c & 0x3F;
+       int             tmp = 0;
+       char            buf[16];
 
        switch (mode) {
        case 0:         /* literal */
@@ -348,6 +347,15 @@ get_operand(ib, size)
 
        case 9:         /* autoincrement deferred */
                add_char(ib, DEFERRED);
+               if (reg == 0x0F) {      /* pc: immediate deferred */
+                       /*
+                        * addresses are always longwords!
+                        */
+                       tmp = get_long(ib);
+                       add_off(ib, tmp);
+                       break;
+               }
+               /* fall through */
        case 8:         /* autoincrement */
                if (reg == 0x0F) {      /* pc: immediate ==> special syntax */
                        switch (size) {
@@ -439,8 +447,8 @@ int
 get_word(ib)
        inst_buffer    *ib;
 {
-       int             tmp;
-       char           *p = (void *) &tmp;
+       int             tmp;
+       char           *p = (void *) &tmp;
        *p++ = get_byte(ib);
        *p++ = get_byte(ib);
        return (tmp);
@@ -450,8 +458,8 @@ int
 get_long(ib)
        inst_buffer    *ib;
 {
-       int             tmp;
-       char           *p = (void *) &tmp;
+       int             tmp;
+       char           *p = (void *) &tmp;
        *p++ = get_byte(ib);
        *p++ = get_byte(ib);
        *p++ = get_byte(ib);
@@ -462,7 +470,7 @@ get_long(ib)
 void
 add_char(ib, c)
        inst_buffer    *ib;
-       int             c;
+       int             c;
 {
        *ib->curp++ = c;
 }
@@ -470,18 +478,18 @@ add_char(ib, c)
 void
 add_str(ib, s)
        inst_buffer    *ib;
-       char           *s;
+       char           *s;
 {
-       while ((*ib->curp++ = *s++));
+       while (*ib->curp++ = *s++);
        *--ib->curp = '\0';
 }
 
 void
 add_int(ib, i)
        inst_buffer    *ib;
-       int             i;
+       int             i;
 {
-       char            buf[32];
+       char            buf[32];
        if (i < 100 && i > -100)
                sprintf(buf, "%d", i);
        else
@@ -492,9 +500,9 @@ add_int(ib, i)
 void
 add_xint(ib, val)
        inst_buffer    *ib;
-       int             val;
+       int             val;
 {
-       char            buf[32];
+       char            buf[32];
        sprintf(buf, "0x%x", val);
        add_str(ib, buf);
 }
@@ -502,11 +510,11 @@ add_xint(ib, val)
 void
 add_sym(ib, loc)
        inst_buffer    *ib;
-       int             loc;
+       int             loc;
 {
-       db_expr_t       diff;
-       db_sym_t        sym;
-       char           *symname;
+       db_expr_t       diff;
+       db_sym_t        sym;
+       char           *symname;
 
        if (! loc)
                return;
@@ -528,11 +536,11 @@ add_sym(ib, loc)
 void
 add_off(ib, loc)
        inst_buffer    *ib;
-       int             loc;
+       int             loc;
 {
-       db_expr_t       diff;
-       db_sym_t        sym;
-       char           *symname;
+       db_expr_t       diff;
+       db_sym_t        sym;
+       char           *symname;
 
        if (!loc)
                return;
index 317e005..932683e 100644 (file)
@@ -1,4 +1,4 @@
-/*     $NetBSD: db_machdep.c,v 1.6 1996/04/08 18:32:33 ragge Exp $     */
+/*     $NetBSD: db_machdep.c,v 1.8 1996/10/13 03:35:39 christos Exp $  */
 
 /* 
  * Mach Operating System
index 411b5b3..ecb1b06 100644 (file)
@@ -1,4 +1,4 @@
-/*     $NetBSD: disksubr.c,v 1.10 1996/05/19 16:44:02 ragge Exp $      */
+/*     $NetBSD: disksubr.c,v 1.11 1997/01/11 11:24:51 ragge Exp $      */
 
 /*
  * Copyright (c) 1982, 1986, 1988 Regents of the University of California.
 #include <sys/dkbad.h>
 #include <sys/disklabel.h>
 #include <sys/syslog.h>
+#include <sys/proc.h>
+
+#include <vm/vm.h>
+#include <vm/vm_kern.h>
 
 #include <machine/macros.h>
+#include <machine/pte.h>
+#include <machine/pcb.h>
 
-/* XXX encoding of disk minor numbers, should be elsewhere... */
-#define dkunit(dev)            (minor(dev) >> 3)
-#define dkpart(dev)            (minor(dev) & 7)
-#define dkminor(unit, part)    (((unit) << 3) | (part))
+#include <arch/vax/mscp/mscp.h> /* For disk encoding scheme */
 
-#define        b_cylin b_resid
+#define b_cylin b_resid
 
 int    cpu_setdisklabel __P((struct disklabel *, struct disklabel *, u_long,
            struct cpu_disklabel *));
@@ -67,38 +70,38 @@ bounds_check_with_label(bp, lp, wlabel)
        struct  disklabel *lp;
        int     wlabel;
 {
-       struct partition *p = lp->d_partitions + dkpart(bp->b_dev);
+       struct partition *p = lp->d_partitions + DISKPART(bp->b_dev);
        int labelsect = lp->d_partitions[2].p_offset;
        int maxsz = p->p_size,
                sz = (bp->b_bcount + DEV_BSIZE - 1) >> DEV_BSHIFT;
        /* overwriting disk label ? */
-        if (bp->b_blkno + p->p_offset <= LABELSECTOR + labelsect &&
+       if (bp->b_blkno + p->p_offset <= LABELSECTOR + labelsect &&
 #if LABELSECTOR != 0
-            bp->b_blkno + p->p_offset + sz > LABELSECTOR + labelsect &&
+           bp->b_blkno + p->p_offset + sz > LABELSECTOR + labelsect &&
 #endif
-            (bp->b_flags & B_READ) == 0 && wlabel == 0) {
-                bp->b_error = EROFS;
-                goto bad;
-        }
+           (bp->b_flags & B_READ) == 0 && wlabel == 0) {
+               bp->b_error = EROFS;
+               goto bad;
+       }
 
        /* beyond partition? */
-        if (bp->b_blkno < 0 || bp->b_blkno + sz > maxsz) {
-                /* if exactly at end of disk, return an EOF */
-                if (bp->b_blkno == maxsz) {
-                        bp->b_resid = bp->b_bcount;
-                        return(0);
-                }
-                /* or truncate if part of it fits */
-                sz = maxsz - bp->b_blkno;
-                if (sz <= 0) {
+       if (bp->b_blkno < 0 || bp->b_blkno + sz > maxsz) {
+               /* if exactly at end of disk, return an EOF */
+               if (bp->b_blkno == maxsz) {
+                       bp->b_resid = bp->b_bcount;
+                       return(0);
+               }
+               /* or truncate if part of it fits */
+               sz = maxsz - bp->b_blkno;
+               if (sz <= 0) {
                        bp->b_error = EINVAL;
-                        goto bad;
+                       goto bad;
                }
-                bp->b_bcount = sz << DEV_BSHIFT;
-        }
+               bp->b_bcount = sz << DEV_BSHIFT;
+       }
 
        /* calculate cylinder for disksort to order transfers with */
-        bp->b_cylin = (bp->b_blkno + p->p_offset) / lp->d_secpercyl;
+       bp->b_cylin = (bp->b_blkno + p->p_offset) / lp->d_secpercyl;
        return(1);
 
 bad:
@@ -227,16 +230,12 @@ cpu_setdisklabel(olp, nlp, openmask, osdep)
                        npp->p_cpg = opp->p_cpg;
                }
        }
-       nlp->d_checksum = 0;
-       nlp->d_checksum = dkcksum(nlp);
+       nlp->d_checksum = 0;
+       nlp->d_checksum = dkcksum(nlp);
        *olp = *nlp;
        return (0);
 }
 
-/* encoding of disk minor numbers, should be elsewhere... */
-#define dkunit(dev)            (minor(dev) >> 3)
-#define dkminor(unit, part)    (((unit) << 3) | (part))
-
 /*
  * Write disk label back to device after modification.
  */
@@ -252,14 +251,14 @@ cpu_writedisklabel(dev, strat, lp, osdep)
        int labelpart;
        int error = 0;
 
-       labelpart = dkpart(dev);
+       labelpart = DISKPART(dev);
        if (lp->d_partitions[labelpart].p_offset != 0) {
                if (lp->d_partitions[0].p_offset != 0)
                        return (EXDEV);                 /* not quite right */
                labelpart = 0;
        }
        bp = geteblk((int)lp->d_secsize);
-       bp->b_dev = makedev(major(dev), dkminor(dkunit(dev), labelpart));
+       bp->b_dev = MAKEDISKDEV(major(dev), DISKUNIT(dev), labelpart);
        bp->b_blkno = LABELSECTOR;
        bp->b_bcount = lp->d_secsize;
        bp->b_flags = B_READ;
@@ -284,3 +283,78 @@ done:
        brelse(bp);
        return (error);
 }
+
+/*     
+ * Print out the name of the device; ex. TK50, RA80. DEC uses a common
+ * disk type encoding scheme for most of its disks.
+ */   
+void  
+disk_printtype(unit, type)
+       int unit, type;
+{
+       printf(" drive %d: %c%c", unit, MSCP_MID_CHAR(2, type),
+           MSCP_MID_CHAR(1, type));
+       if (MSCP_MID_ECH(0, type))
+               printf("%c", MSCP_MID_CHAR(0, type));
+       printf("%d\n", MSCP_MID_NUM(type));
+}
+
+/*
+ * Be sure that the pages we want to do DMA to is actually there
+ * by faking page-faults if necessary. If given a map-register address,
+ * also map it in.
+ */
+void
+disk_reallymapin(bp, map, reg, flag)
+       struct buf *bp;
+       struct pte *map;
+       int reg, flag;
+{
+       volatile pt_entry_t *io;
+       pt_entry_t *pte;
+       struct pcb *pcb;
+       int pfnum, npf, o, i;
+       caddr_t addr;
+
+       o = (int)bp->b_un.b_addr & PGOFSET;
+       npf = btoc(bp->b_bcount + o) + 1;
+       addr = bp->b_un.b_addr;
+
+       /*
+        * Get a pointer to the pte pointing out the first virtual address.
+        * Use different ways in kernel and user space.
+        */
+       if ((bp->b_flags & B_PHYS) == 0) {
+               pte = kvtopte(addr);
+       } else {
+               pcb = bp->b_proc->p_vmspace->vm_pmap.pm_pcb;
+               pte = uvtopte(addr, pcb);
+       }
+
+       /*
+        * When we are doing DMA to user space, be sure that all pages
+        * we want to transfer to is mapped. WHY DO WE NEED THIS???
+        * SHOULDN'T THEY ALWAYS BE MAPPED WHEN DOING THIS???
+        */
+       for (i = 0; i < (npf - 1); i++) {
+               if ((pte + i)->pg_pfn == 0) {
+                       int rv;
+                       rv = vm_fault(&bp->b_proc->p_vmspace->vm_map,
+                           (unsigned)addr + i * NBPG,
+                           VM_PROT_READ|VM_PROT_WRITE, FALSE);
+                       if (rv)
+                               panic("DMA to nonexistent page, %d", rv);
+               }
+       }
+       if (map) {
+               io = &map[reg];
+               while (--npf > 0) {
+                       pfnum = pte->pg_pfn;
+                       if (pfnum == 0)
+                               panic("mapin zero entry");
+                       pte++;
+                       *(int *)io++ = pfnum | flag;
+               }
+               *(int *)io = 0;
+       }
+}
diff --git a/sys/arch/vax/vax/dzcons.c b/sys/arch/vax/vax/dzcons.c
new file mode 100644 (file)
index 0000000..6002bfe
--- /dev/null
@@ -0,0 +1,345 @@
+/*     $NetBSD: dzcons.c,v 1.2 1996/09/02 06:44:30 mycroft Exp $       */
+/*
+ * Copyright (c) 1994 Gordon W. Ross
+ * Copyright (c) 1994 Ludd, University of Lule}, Sweden.
+ * 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 at Ludd, University of Lule}.
+ * 4. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *     kd.c,v 1.2 1994/05/05 04:46:51 gwr Exp $
+ */
+
+#include <sys/param.h>
+#include <sys/proc.h>
+#include <sys/systm.h>
+#include <sys/ioctl.h>
+#include <sys/tty.h>
+#include <sys/file.h>
+#include <sys/conf.h>
+#include <sys/device.h>
+#include <sys/reboot.h>
+
+#include <dev/cons.h>
+
+#include <machine/mtpr.h>
+#include <machine/sid.h>
+#include <machine/uvax.h>
+#include <machine/ka410.h>
+#include <machine/../vax/gencons.h>
+
+volatile unsigned char *ka410_intreq = (void*)KA410_INTREQ;
+volatile unsigned char *ka410_intclr = (void*)KA410_INTCLR;
+volatile unsigned char *ka410_intmsk = (void*)KA410_INTMSK;
+
+
+
+/*----------------------------------------------------------------------*/
+
+int
+dzcngetc(dev) 
+       dev_t dev;
+{
+       int c;
+       int mapen;
+       int imsk;
+
+       imsk = *ka410_intmsk;           /* save interrupt-mask */
+       *ka410_intmsk = 0;              /* disable console-receive interrupt! */
+
+#if 0
+       do {
+               c = get_fp() & 0xFF;            /* 0x7F ??? */
+       } while (c == 17 || c == 19);           /* ignore XON/XOFF */
+
+       *ka410_intclr = 0x80;           /* clear the interrupt request */
+       *ka410_intmsk = imsk;           /* restore interrupt-mask */
+#else
+       for (;;)
+               ;
+#endif
+
+       if (c == 13)
+               c = 10;
+       return (c);
+}
+
+#define REG(name)      short name; short X##name##X;
+static volatile struct {/* base address of DZ-controller: 0x200A0000 */
+  REG(csr);            /* 00 Csr: control/status register */
+  REG(rbuf);           /* 04 Rbuf/Lpr: receive buffer/line param reg. */
+  REG(tcr);            /* 08 Tcr: transmit console register */
+  REG(tdr);            /* 0C Msr/Tdr: modem status reg/transmit data reg */
+  REG(lpr0);           /* 10 Lpr0: */
+  REG(lpr1);           /* 14 Lpr0: */
+  REG(lpr2);           /* 18 Lpr0: */
+  REG(lpr3);           /* 1C Lpr0: */
+} *dz = (void*)0x200A0000; 
+#undef REG
+
+struct tty *dzcn_tty[1];
+
+int    dzcnparam();
+void   dzcnstart();
+
+int    ka410_consintr_enable __P((void));
+
+int
+dzcnopen(dev, flag, mode, p)
+       dev_t   dev;
+       int     flag, mode;
+       struct proc *p;
+{
+        int unit;
+        struct tty *tp;
+
+        unit = minor(dev);
+        if (unit) return ENXIO;
+
+       tp = dzcn_tty[0];
+
+        tp->t_oproc = dzcnstart;
+        tp->t_param = dzcnparam;
+        tp->t_dev = dev;
+        if ((tp->t_state & TS_ISOPEN) == 0) {
+                tp->t_state |= TS_WOPEN;
+                ttychars(tp);
+                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;
+                dzcnparam(tp, &tp->t_termios);
+                ttsetwater(tp);
+        } else if (tp->t_state & TS_XCLUDE && p->p_ucred->cr_uid != 0)
+                return EBUSY;
+        tp->t_state |= TS_CARR_ON;
+       ka410_consintr_enable();        /* Turn on interrupts */
+       
+
+        return ((*linesw[tp->t_line].l_open)(dev, tp));
+}
+
+int
+dzcnclose(dev, flag, mode, p)
+        dev_t dev;
+        int flag, mode;
+        struct proc *p;
+{
+        int unit = minor(dev);
+        struct tty *tp = dzcn_tty[0];
+
+        (*linesw[tp->t_line].l_close)(tp, flag);
+        ttyclose(tp);
+        return (0);
+}
+
+struct tty *
+dzcntty(dev)
+       dev_t dev;
+{
+
+       return dzcn_tty[0]; /* XXX */
+}
+
+int
+dzcnread(dev, uio, flag)
+        dev_t dev;
+        struct uio *uio;
+        int flag;
+{
+        int unit = minor(dev);
+        struct tty *tp = dzcn_tty[0];
+
+        return ((*linesw[tp->t_line].l_read)(tp, uio, flag));
+}
+
+int
+dzcnwrite(dev, uio, flag)
+        dev_t dev;
+        struct uio *uio;
+        int flag;
+{
+        int unit = minor(dev);
+        struct tty *tp = dzcn_tty[0];
+
+        return ((*linesw[tp->t_line].l_write)(tp, uio, flag));
+}
+
+int
+dzcnioctl(dev, cmd, data, flag, p)
+        dev_t dev;
+        int cmd;
+        caddr_t data;
+        int flag;
+        struct proc *p;
+{
+        int error;
+        int unit = minor(dev);
+        struct tty *tp = dzcn_tty[0];
+
+        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;
+       return ENOTTY;
+}
+
+void
+dzcnstart(tp)
+        struct tty *tp;
+{
+        struct clist *cl;
+        int s, ch;
+
+        s = spltty();
+        if (tp->t_state & (TS_BUSY|TS_TTSTOP|TS_TIMEOUT))
+                goto out;
+        cl = &tp->t_outq;
+
+       if(cl->c_cc){
+               tp->t_state |= TS_BUSY;
+               ch = getc(cl);
+               dz->tdr = ch;
+       } else {
+               if (tp->t_state & TS_ASLEEP) {
+                       tp->t_state &= ~TS_ASLEEP;
+                       wakeup((caddr_t)cl);
+               }
+               selwakeup(&tp->t_wsel);
+       }
+
+out:   splx(s);
+}
+
+dzcnrint()
+{
+       struct tty *tp;
+       int i, j;
+
+       tp = dzcn_tty[0];
+       i = dz->rbuf;
+
+#ifdef DDB
+       j = kdbrint(i);
+
+       if (j == 1)     /* Escape received, just return */
+               return;
+
+       if (j == 2)     /* Second char wasn't 'D' */
+               (*linesw[tp->t_line].l_rint)(27, tp);
+#endif
+
+       (*linesw[tp->t_line].l_rint)(i,tp);
+       return;
+}
+
+void
+dzcnstop(tp, flag)
+        struct tty *tp;
+        int flag;
+{
+
+}
+
+dzcntint()
+{
+       struct tty *tp;
+
+       tp = dzcn_tty[0];
+       tp->t_state &= ~TS_BUSY;
+
+       dzcnstart(tp);
+}
+
+int
+dzcnparam(tp, t)
+       struct tty *tp;
+       struct termios *t;
+{
+        /* XXX - These are ignored... */
+        tp->t_ispeed = t->c_ispeed;
+        tp->t_ospeed = t->c_ospeed;
+        tp->t_cflag = t->c_cflag;
+       return 0;
+}
+
+void
+dzcnprobe(cndev)
+       struct  consdev *cndev;
+{
+       int i;
+
+       switch (vax_boardtype) {
+       case VAX_BTYP_410:
+       case VAX_BTYP_43:
+               break;
+
+       default:
+               cndev->cn_pri = CN_DEAD;
+               return;
+       }
+
+       for (i = 0; i < nchrdev; i++)
+               if (cdevsw[i].d_open == dzcnopen) {
+                       cndev->cn_dev = makedev(i,0);
+                       cndev->cn_pri = CN_NORMAL;
+                       return;
+               }
+       cndev->cn_pri = CN_DEAD;
+       return;
+}
+
+int
+dzcninit(cndev)
+       struct  consdev *cndev;
+{
+}
+
+dzcnslask()
+{
+       dzcn_tty[0] = ttymalloc();
+}
+
+void
+dzcnputc(dev,ch)
+       dev_t   dev;
+       int     ch;
+{
+       int timeout = 1<<15;            /* don't hang the machine! */
+       while ((dz->csr & 0x8000) == 0) /* Wait until ready */
+               if (--timeout < 0)
+                       break;
+       dz->tdr = ch;                    /* Put the  character */
+}
+
+conout(str)
+       char *str;
+{
+       while (*str)
+               gencnputc(0, *str++);
+}
index 63bd67e..6139269 100644 (file)
@@ -1,4 +1,4 @@
-/*     $NetBSD: gencons.c,v 1.10 1996/04/08 18:32:36 ragge Exp $       */
+/*     $NetBSD: gencons.c,v 1.11 1996/09/02 06:44:32 mycroft Exp $     */
 
 /*
  * Copyright (c) 1994 Gordon W. Ross
@@ -68,7 +68,7 @@ void  gencninit __P((struct consdev *));
 struct tty *gencntty __P((dev_t));
 void   gencnrint __P((void));
 void   gencntint __P((void));
-int    gencnstop __P((struct tty *, int));
+void   gencnstop __P((struct tty *, int));
 void   gencnslask __P((void));
 
 int
@@ -218,12 +218,12 @@ gencnrint()
        return;
 }
 
-int
+void
 gencnstop(tp, flag)
         struct tty *tp;
         int flag;
 {
-       return 0;
+
 }
 
 void
index fa336ba..6d24740 100644 (file)
@@ -1,4 +1,4 @@
-/*     $NetBSD: in_cksum.c,v 1.2 1996/04/08 18:32:38 ragge Exp $       */
+/*     $NetBSD: in_cksum.c,v 1.4 1996/10/13 03:35:40 christos Exp $    */
 
 /*
  * Copyright (c) 1988, 1992, 1993
index 8c09393..333f7de 100644 (file)
@@ -1,4 +1,4 @@
-/*     $NetBSD: intvec.s,v 1.19 1996/03/09 23:36:40 ragge Exp $   */
+/*     $NetBSD: intvec.s,v 1.20 1996/07/20 18:20:44 ragge Exp $   */
 
 /*
  * Copyright (c) 1994 Ludd, University of Lule}, Sweden.
 #include <machine/pte.h>
 #include <machine/trap.h>
 
-#define        ENTRY(name) \
+#define ENTRY(name) \
        .text                   ; \
        .align 2                ; \
        .globl name             ; \
 name /**/:
 
-#define        TRAPCALL(namn, typ) \
+#define TRAPCALL(namn, typ) \
 ENTRY(namn)                    ; \
        pushl $0                ; \
        pushl $typ              ; \
        jbr trap
 
-#define        TRAPARGC(namn, typ) \
+#define TRAPARGC(namn, typ) \
 ENTRY(namn)                    ; \
        pushl $typ              ; \
        jbr trap
 
-#define        FASTINTR(namn, rutin) \
+#define FASTINTR(namn, rutin) \
 ENTRY(namn)                    ; \
        pushr $0x3f             ; \
        calls $0,_/**/rutin     ; \
        popr $0x3f              ; \
        rei
 
-#define        STRAY(scbnr, vecnr) \
+#define STRAY(scbnr, vecnr) \
 ENTRY(stray/**/vecnr)          ; \
        pushr $0x3f             ; \
        pushl $/**/0x/**/vecnr  ; \
@@ -71,7 +71,7 @@ ENTRY(stray/**/vecnr)         ; \
        popr $0x3f              ; \
        rei
 
-#define        KSTACK 0
+#define KSTACK 0
 #define ISTACK 1
 #define INTVEC(label,stack)    \
        .long   label+stack;
@@ -87,66 +87,66 @@ _rpb:
  * and move the SCB later to somewhere else.
  */
 
-       INTVEC(stray00, ISTACK) # Unused., 0
+       INTVEC(stray00, ISTACK) # Unused., 0
        INTVEC(mcheck, ISTACK)          # Machine Check., 4
-       INTVEC(invkstk, ISTACK) # Kernel Stack Invalid., 8
-       INTVEC(stray0C, ISTACK) # Power Failed., C
+       INTVEC(invkstk, ISTACK) # Kernel Stack Invalid., 8
+       INTVEC(stray0C, ISTACK) # Power Failed., C
        INTVEC(privinflt, KSTACK)       # Privileged/Reserved Instruction.
-       INTVEC(stray14, ISTACK) # Customer Reserved Instruction, 14
+       INTVEC(stray14, ISTACK) # Customer Reserved Instruction, 14
        INTVEC(resopflt, KSTACK)        # Reserved Operand/Boot Vector(?), 18
        INTVEC(resadflt, KSTACK)        # # Reserved Address Mode., 1C
        INTVEC(access_v, KSTACK)        # Access Control Violation, 20
        INTVEC(transl_v, KSTACK)        # Translation Invalid, 24
        INTVEC(tracep, KSTACK)  # Trace Pending, 28
        INTVEC(breakp, KSTACK)  # Breakpoint Instruction, 2C
-       INTVEC(stray30, ISTACK) # Compatibility Exception, 30
+       INTVEC(stray30, ISTACK) # Compatibility Exception, 30
        INTVEC(arithflt, KSTACK)        # Arithmetic Fault, 34
-       INTVEC(stray38, ISTACK) # Unused, 38
-       INTVEC(stray3C, ISTACK) # Unused, 3C
+       INTVEC(stray38, ISTACK) # Unused, 38
+       INTVEC(stray3C, ISTACK) # Unused, 3C
        INTVEC(syscall, KSTACK)         # main syscall trap, chmk, 40
        INTVEC(resopflt, KSTACK)        # chme, 44
        INTVEC(resopflt, KSTACK)        # chms, 48
        INTVEC(resopflt, KSTACK)        # chmu, 4C
-       INTVEC(stray50, ISTACK) # System Backplane Exception, 50
+       INTVEC(sbiexc, ISTACK)  # System Backplane Exception/BIerror, 50
        INTVEC(cmrerr, ISTACK)  # Corrected Memory Read, 54
-       INTVEC(stray58, ISTACK) # System Backplane Alert, 58
+       INTVEC(rxcs, ISTACK)    # System Backplane Alert/RXCD, 58
        INTVEC(sbiflt, ISTACK)  # System Backplane Fault, 5C
-       INTVEC(stray60, ISTACK) # Memory Write Timeout, 60
-       INTVEC(stray64, ISTACK) # Unused, 64
-       INTVEC(stray68, ISTACK) # Unused, 68
-       INTVEC(stray6C, ISTACK) # Unused, 6C
-       INTVEC(stray70, ISTACK) # Unused, 70
-       INTVEC(stray74, ISTACK) # Unused, 74
-       INTVEC(stray78, ISTACK) # Unused, 78
-       INTVEC(stray7C, ISTACK) # Unused, 7C
-       INTVEC(stray80, ISTACK) # Unused, 80
-       INTVEC(stray84, ISTACK) # Unused, 84
+       INTVEC(stray60, ISTACK) # Memory Write Timeout, 60
+       INTVEC(stray64, ISTACK) # Unused, 64
+       INTVEC(stray68, ISTACK) # Unused, 68
+       INTVEC(stray6C, ISTACK) # Unused, 6C
+       INTVEC(stray70, ISTACK) # Unused, 70
+       INTVEC(stray74, ISTACK) # Unused, 74
+       INTVEC(stray78, ISTACK) # Unused, 78
+       INTVEC(stray7C, ISTACK) # Unused, 7C
+       INTVEC(stray80, ISTACK) # Unused, 80
+       INTVEC(stray84, ISTACK) # Unused, 84
        INTVEC(astintr,  KSTACK)        # Asynchronous Sustem Trap, AST
-       INTVEC(stray8C, ISTACK) # Unused, 8C
-       INTVEC(stray90, ISTACK) # Unused, 90
-       INTVEC(stray94, ISTACK) # Unused, 94
-       INTVEC(stray98, ISTACK) # Unused, 98
-       INTVEC(stray9C, ISTACK) # Unused, 9C
+       INTVEC(stray8C, ISTACK) # Unused, 8C
+       INTVEC(stray90, ISTACK) # Unused, 90
+       INTVEC(stray94, ISTACK) # Unused, 94
+       INTVEC(stray98, ISTACK) # Unused, 98
+       INTVEC(stray9C, ISTACK) # Unused, 9C
        INTVEC(softclock,ISTACK)        # Software clock interrupt
-       INTVEC(strayA4, ISTACK) # Unused, A4
-       INTVEC(strayA8, ISTACK) # Unused, A8
-       INTVEC(strayAC, ISTACK) # Unused, AC
-       INTVEC(netint,   ISTACK)        # Network interrupt
-       INTVEC(strayB4, ISTACK) # Unused, B4
-       INTVEC(strayB8, ISTACK) # Unused, B8
-       INTVEC(ddbtrap, ISTACK) # Kernel debugger trap, BC
+       INTVEC(strayA4, ISTACK) # Unused, A4
+       INTVEC(strayA8, ISTACK) # Unused, A8
+       INTVEC(strayAC, ISTACK) # Unused, AC
+       INTVEC(netint,   ISTACK)        # Network interrupt
+       INTVEC(strayB4, ISTACK) # Unused, B4
+       INTVEC(strayB8, ISTACK) # Unused, B8
+       INTVEC(ddbtrap, ISTACK) # Kernel debugger trap, BC
        INTVEC(hardclock,ISTACK)        # Interval Timer
-       INTVEC(strayC4, ISTACK) # Unused, C4
+       INTVEC(strayC4, ISTACK) # Unused, C4
        INTVEC(emulate, KSTACK) # Subset instruction emulation
-       INTVEC(strayCC, ISTACK) # Unused, CC
-       INTVEC(strayD0, ISTACK) # Unused, D0
-       INTVEC(strayD4, ISTACK) # Unused, D4
-       INTVEC(strayD8, ISTACK) # Unused, D8
-       INTVEC(strayDC, ISTACK) # Unused, DC
-       INTVEC(strayE0, ISTACK) # Unused, E0
-       INTVEC(strayE4, ISTACK) # Unused, E4
-       INTVEC(strayE8, ISTACK) # Unused, E8
-       INTVEC(strayEC, ISTACK) # Unused, EC
+       INTVEC(strayCC, ISTACK) # Unused, CC
+       INTVEC(strayD0, ISTACK) # Unused, D0
+       INTVEC(strayD4, ISTACK) # Unused, D4
+       INTVEC(strayD8, ISTACK) # Unused, D8
+       INTVEC(strayDC, ISTACK) # Unused, DC
+       INTVEC(strayE0, ISTACK) # Unused, E0
+       INTVEC(strayE4, ISTACK) # Unused, E4
+       INTVEC(strayE8, ISTACK) # Unused, E8
+       INTVEC(strayEC, ISTACK) # Unused, EC
        INTVEC(strayF0, ISTACK)
        INTVEC(strayF4, ISTACK)
        INTVEC(consrint, ISTACK)        # Console Terminal Recieve Interrupt
@@ -164,7 +164,7 @@ _rpb:
 # _memtest (memtest in C) holds the address to continue execution
 # at when returning from a intentional test.
 #
-mcheck:        .globl  mcheck
+mcheck: .globl mcheck
        tstl    _cold           # Ar we still in coldstart?
        bneq    L4              # Yes.
 
@@ -174,16 +174,16 @@ mcheck:   .globl  mcheck
        popr    $0x3f
        addl2   (sp)+,sp
 
-        rei
+       rei
 
 L4:    addl2   (sp)+,sp        # remove info pushed on stack
-       cmpl    _cpunumber, $1  # Is it a 11/780?
+       cmpl    _vax_cputype,$1 # Is it a 11/780?
        bneq    1f              # No...
 
        mtpr    $0, $PR_SBIFS   # Clear SBI fault register
        brb     2f
 
-1:     cmpl    _cpunumber, $4  # Is it a 8600?
+1:     cmpl    _vax_cputype,$4 # Is it a 8600?
        bneq    3f
 
        mtpr    $0, $PR_EHSR    # Clear Error status register
@@ -213,13 +213,13 @@ L2:       movl    (sp), 4(sp)
        jbr     trap
 
 
-               .align  2
-access_v:.globl        access_v        # Access cntrl viol fault,      24
+               .align  2
+access_v:.globl access_v       # Access cntrl viol fault,      24
        blbs    (sp), ptelen
        pushl   $T_ACCFLT
        jbr     L3
 
-ptelen:        movl    $T_PTELEN, (sp)         # PTE must expand (or send segv)
+ptelen: movl   $T_PTELEN, (sp)         # PTE must expand (or send segv)
        jbr trap;
 
        TRAPCALL(tracep, T_TRCTRAP)
@@ -256,9 +256,33 @@ syscall:
        STRAY(0,44)
        STRAY(0,48)
        STRAY(0,4C)
-       STRAY(0,50)
+
+ENTRY(sbiexc)
+       tstl    _cold   /* Is it ok to get errs during boot??? */
+       bneq    1f
+       pushr   $0x3f
+       pushl   $0x50
+       pushl   $0
+       calls   $2,_stray
+       popr    $0x3f
+1:     rei
+
        FASTINTR(cmrerr,cmrerr)
-       STRAY(0,58)
+
+ENTRY(rxcs);   /* console interrupt from some other processor */
+       pushr   $0x3f
+#if VAX8200
+       cmpl    $5,_vax_cputype
+       bneq    1f
+       calls   $0,_rxcdintr
+       brb     2f
+#endif
+1:     pushl   $0x58
+       pushl   $0
+       calls   $2,_stray
+2:     popr    $0x3f
+       rei
+
        ENTRY(sbiflt);
        moval   sbifltmsg, -(sp)
        calls   $1, _panic
@@ -373,35 +397,35 @@ _emtable:
 /*
  * The following is called with the stack set up as follows:
  *
- *       (sp): Opcode
- *      4(sp): Instruction PC
- *      8(sp): Operand 1
- *     12(sp): Operand 2
- *     16(sp): Operand 3
- *     20(sp): Operand 4
- *     24(sp): Operand 5
- *     28(sp): Operand 6
- *     32(sp): Operand 7 (unused)
- *     36(sp): Operand 8 (unused)
- *     40(sp): Return PC
- *     44(sp): Return PSL
+ *       (sp): Opcode
+ *      4(sp): Instruction PC
+ *      8(sp): Operand 1
+ *     12(sp): Operand 2
+ *     16(sp): Operand 3
+ *     20(sp): Operand 4
+ *     24(sp): Operand 5
+ *     28(sp): Operand 6
+ *     32(sp): Operand 7 (unused)
+ *     36(sp): Operand 8 (unused)
+ *     40(sp): Return PC
+ *     44(sp): Return PSL
  *     48(sp): TOS before instruction
  *
  * Each individual routine is called with the stack set up as follows:
  *
- *       (sp): Return address of trap handler
- *      4(sp): Opcode (will get return PSL)
- *      8(sp): Instruction PC
- *     12(sp): Operand 1
- *     16(sp): Operand 2
- *     20(sp): Operand 3
- *     24(sp): Operand 4
- *     28(sp): Operand 5
- *     32(sp): Operand 6
- *     36(sp): saved register 11
- *     40(sp): saved register 10
- *     44(sp): Return PC
- *     48(sp): Return PSL
+ *       (sp): Return address of trap handler
+ *      4(sp): Opcode (will get return PSL)
+ *      8(sp): Instruction PC
+ *     12(sp): Operand 1
+ *     16(sp): Operand 2
+ *     20(sp): Operand 3
+ *     24(sp): Operand 4
+ *     28(sp): Operand 5
+ *     32(sp): Operand 6
+ *     36(sp): saved register 11
+ *     40(sp): saved register 10
+ *     44(sp): Return PC
+ *     48(sp): Return PSL
  *     52(sp): TOS before instruction
  *     See the VAX Architecture Reference Manual, Section B-5 for more
  *     information.
@@ -429,12 +453,12 @@ noemulate:
 #endif
        .word   0xffff                  # "reserved instruction fault"
 
-        .globl  _intrnames, _eintrnames, _intrcnt, _eintrcnt
+       .globl  _intrnames, _eintrnames, _intrcnt, _eintrcnt
 _intrnames:
-        .long   0
+       .long   0
 _eintrnames:
 _intrcnt:
-        .long   0
+       .long   0
 _eintrcnt:
 
        .data
diff --git a/sys/arch/vax/vax/ka410.c b/sys/arch/vax/vax/ka410.c
new file mode 100644 (file)
index 0000000..5824873
--- /dev/null
@@ -0,0 +1,249 @@
+/*     $NetBSD: ka410.c,v 1.3 1996/10/13 03:35:42 christos Exp $ */
+/*
+ * Copyright (c) 1996 Ludd, University of Lule}, Sweden.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Ludd by Bertram Barth.
+ *
+ * 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 at Ludd, University of 
+ *      Lule}, Sweden and its contributors.
+ * 4. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/device.h>
+#include <sys/kernel.h>
+#include <vm/vm.h>
+#include <vm/vm_kern.h>
+
+#include <machine/pte.h>
+#include <machine/mtpr.h>
+#include <machine/sid.h>
+#include <machine/pmap.h>
+#include <machine/nexus.h>
+#include <machine/uvax.h>
+#include <machine/ka410.h>
+#include <machine/clock.h>
+
+/*
+ * Maybe all these variables/functions should be static or "integrate"
+ */
+void   ka410_conf __P((struct device*, struct device*, void*));
+void   ka410_memenable __P((struct sbi_attach_args *, struct device *));
+void   ka410_steal_pages __P((void));
+
+#ifdef notyet
+void   ka410_memerr __P((void));
+int    ka410_mchk __P((caddr_t));
+#endif
+
+struct  ka410_cpu   *ka410_cpuptr = (void*)KA410_CPU_BASE;
+struct  ka410_clock *ka410_clkptr = (void*)KA410_WAT_BASE;
+
+extern int uVAX_fillmap __P((struct uc_map *));
+
+struct uc_map ka410_map[] = {
+       { KA410_CFGTST,         KA410_CFGTST+1023,      1024,   0 },
+       { KA410_ROM_BASE,       KA410_ROM_END,  KA410_ROM_SIZE, 0 },
+       { KA410_CPU_BASE,       KA410_CPU_END,  KA410_CPU_SIZE, 0 },
+       { KA410_NWA_BASE,       KA410_NWA_END,  KA410_NWA_SIZE, 0 },
+       { KA410_SER_BASE,       KA410_SER_END,  KA410_SER_SIZE, 0 },
+       { KA410_WAT_BASE,       KA410_WAT_END,  KA410_WAT_SIZE, 0 },
+#if 0
+       { KA410_SCS_BASE,       KA410_SCS_END,  KA410_SCS_SIZE, 0 },
+#else
+       { 0x200C0000,           0x200C01FF,     0x200,          0 },
+#endif
+       { KA410_LAN_BASE,       KA410_LAN_END,  KA410_LAN_SIZE, 0 },
+       { KA410_CUR_BASE,       KA410_CUR_END,  KA410_CUR_SIZE, 0 },
+       { KA410_DMA_BASE,       KA410_DMA_END,  KA410_DMA_SIZE, 0 },
+       /*
+        * there's more to come, eg. framebuffers (mono + GPX)
+        */
+       {0, 0, 0, 0},
+};
+
+int
+ka410_setup(uc,flags)
+       struct uvax_calls *uc;
+       int flags;
+{
+       uc->uc_name = "ka410";
+
+       uc->uc_phys2virt = NULL;        /* ka410_mapaddr; */
+       uc->uc_physmap = ka410_map;     /* ptv_map ? p2v_map */
+
+       uc->uc_steal_pages = ka410_steal_pages;
+       uc->uc_conf = ka410_conf;
+       uc->uc_clkread = ka410_clkread;
+       uc->uc_clkwrite = ka410_clkwrite;
+
+#ifdef notyet
+       uc->uc_memerr = ka410_memerr;
+       uc->uc_mchk = ka410_mchk;
+#endif
+
+       uc->uc_intreq = (void*)KA410_INTREQ;
+       uc->uc_intclr = (void*)KA410_INTCLR;
+       uc->uc_intmsk = (void*)KA410_INTMSK;
+
+       uc->uc_busTypes = VAX_VSBUS;
+}
+
+void
+ka410_conf(parent, self, aux)
+       struct  device *parent, *self;
+       void    *aux;
+{
+       extern char cpu_model[];
+
+       if (vax_confdata & 0x80)        /* MSB in CFGTST */
+               strcpy(cpu_model,"MicroVAX 2000");
+       else
+               strcpy(cpu_model,"VAXstation 2000");
+
+       printf(": %s\n", cpu_model);
+}
+
+
+/*
+ *
+ */
+u_long le_iomem;                       /* base addr of RAM -- CPU's view */
+u_long le_ioaddr;                      /* base addr of RAM -- LANCE's view */
+
+void
+ka410_steal_pages()
+{
+       extern  vm_offset_t avail_start, virtual_avail, avail_end;
+       int     junk;
+
+       int     i;
+       struct {
+         u_long     :2;
+         u_long data:8;
+         u_long     :22;
+       } *p;
+       int *srp;       /* Scratch Ram */
+       char *q = (void*)&srp;
+
+       srp = NULL;
+       p = (void*)KA410_SCR;
+       for (i=0; i<4; i++) {
+         printf("p[%d] = %x, ", i, p[i].data);
+         q[i]  = p[i].data;
+       }
+       p = (void*)KA410_SCRLEN;
+       printf("\nlen = %d\n", p->data);
+       printf("srp = 0x%x\n", srp);
+
+       for (i=0; i<0x2; i++) {
+         printf("%x:0x%x ", i*4, srp[i]);
+         if ((i & 0x07) == 0x07)
+           printf("\n");
+       }
+       printf("\n");
+
+       /* 
+        * SCB is already copied/initialized at addr avail_start
+        * by pmap_bootstrap(), but it's not yet mapped. Thus we use
+        * the MAPPHYS() macro to reserve these two pages and to
+        * perform the mapping. The mapped address is assigned to junk.
+        */
+       MAPPHYS(junk, 2, VM_PROT_READ|VM_PROT_WRITE);
+
+       /*
+        * At top of physical memory there are some console-prom and/or
+        * restart-specific data. Make this area unavailable.
+        */
+       avail_end -= 10 * NBPG;
+
+       /*
+        * If we need to map physical areas also, we can decrease avail_end
+        * (the highest available memory-address), copy the stuff into the
+        * gap between and use pmap_map to map it...
+        *
+        * Don't use the MAPPHYS macro here, since this uses and changes(!)
+        * the value of avail_start. Use MAPVIRT even if it's name misleads.
+        */
+       avail_end -= 10 * NBPG;         /* paranoid: has been done before */
+
+       avail_end = (int)srp;
+
+       avail_end &= ~0xffff;           /* make avail_end 64K-aligned */
+       avail_end -= (64 * 1024);       /* steal 64K for LANCE's iobuf */
+       le_ioaddr = avail_end;          /* ioaddr=phys, iomem=virt */
+       MAPVIRT(le_iomem, (64 * 1024)/NBPG);
+       pmap_map((vm_offset_t)le_iomem, le_ioaddr, le_ioaddr + 0xffff,
+                VM_PROT_READ|VM_PROT_WRITE);
+
+       printf("le_iomem: %x, le_ioaddr: %x, srp: %x, avail_end: %x\n",
+              le_iomem, le_ioaddr, srp, avail_end);
+
+       /*
+        * VAXstation 2000 and MicroVAX 2000: 
+        * since there's no bus, we have to map in anything which 
+        * could be neccessary/used/interesting...
+        * 
+        * MAPVIRT(ptr,count) reserves a virtual area with the requested size
+        *                      and initializes ptr to point at this location
+        * pmap_map(ptr,...)  inserts a pair of virtual/physical addresses
+        *                      into the system maptable (Sysmap)
+        */
+       uVAX_fillmap(ka410_map);
+
+       /*
+        * Clear restart and boot in progress flags
+        * in the CPMBX. (ie. clear bits 4 and 5)
+        */
+       ka410_clkptr->cpmbx = (ka410_clkptr->cpmbx & ~0x30);
+
+       /*
+        * Enable memory parity error detection and clear error bits.
+        */
+       ka410_cpuptr->ka410_mser = 1; 
+       /* (UVAXIIMSER_PEN | UVAXIIMSER_MERR | UVAXIIMSER_LEB); */
+
+       /*
+        * MM is not yet enabled, thus we still used the physical addresses,
+        * but before leaving this routine, we need to reset them to virtual.
+        */
+       ka410_cpuptr = (void*)uvax_phys2virt(KA410_CPU_BASE);
+       ka410_clkptr = (void*)uvax_phys2virt(KA410_WAT_BASE);
+
+}
+/*
+ * define what we need and overwrite the uVAX_??? names
+ */
+
+#define uVAX_clock     ka410_clock
+#define uVAX_clkptr    ka410_clkptr
+#define uVAX_clkread   ka410_clkread
+#define uVAX_clkwrite  ka410_clkwrite
+
+#include <arch/vax/vax/uvax_proto.c>
diff --git a/sys/arch/vax/vax/ka43.c b/sys/arch/vax/vax/ka43.c
new file mode 100644 (file)
index 0000000..814f8e8
--- /dev/null
@@ -0,0 +1,444 @@
+/*     $NetBSD: ka43.c,v 1.3 1996/10/13 03:35:43 christos Exp $ */
+/*
+ * Copyright (c) 1996 Ludd, University of Lule}, Sweden.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Ludd by Bertram Barth.
+ *
+ * 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 at Ludd, University of 
+ *      Lule}, Sweden and its contributors.
+ * 4. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/device.h>
+#include <sys/kernel.h>
+
+#include <vm/vm.h>
+#include <vm/vm_kern.h>
+
+#include <machine/pte.h>
+#include <machine/mtpr.h>
+#include <machine/sid.h>
+#include <machine/pmap.h>
+#include <machine/nexus.h>
+#include <machine/uvax.h>
+#include <machine/ka43.h>
+#include <machine/clock.h>
+#include <machine/ka650.h>     /* cache ??? */
+
+#define        xtrace(x)
+
+void   ka43_conf __P((struct device*, struct device*, void*));
+void   ka43_steal_pages __P((void));
+
+void   ka43_memerr __P((void));
+int    ka43_mchk __P((caddr_t));
+
+struct ka43_cpu   *ka43_cpuptr = (void*)KA43_CPU_BASE;
+struct ka43_clock *ka43_clkptr = (void*)KA43_WAT_BASE;
+
+extern int uVAX_fillmap __P((struct uc_map *));
+
+struct uc_map ka43_map[] = {
+       { KA43_CFGTST,          KA43_CFGTST,    4,              0 },
+       { KA43_ROM_BASE,        KA43_ROM_END,   KA43_ROM_SIZE,  0 },
+       { KA43_CPU_BASE,        KA43_CPU_END,   KA43_CPU_SIZE,  0 },
+       { KA43_CT2_BASE,        KA43_CT2_END,   KA43_CT2_SIZE,  0 },
+       { KA43_CH2_CREG,        KA43_CH2_CREG,  4,              0 },
+       { KA43_NWA_BASE,        KA43_NWA_END,   KA43_NWA_SIZE,  0 },
+       { KA43_SER_BASE,        KA43_SER_END,   KA43_SER_SIZE,  0 },
+       { KA43_WAT_BASE,        KA43_WAT_END,   KA43_WAT_SIZE,  0 },
+       { KA43_SCS_BASE,        KA43_SCS_END,   KA43_SCS_SIZE,  0 },
+       { KA43_LAN_BASE,        KA43_LAN_END,   KA43_LAN_SIZE,  0 },
+       { KA43_CUR_BASE,        KA43_CUR_END,   KA43_CUR_SIZE,  0 },
+       { KA43_DMA_BASE,        KA43_DMA_END,   KA43_DMA_SIZE,  0 },
+       { KA43_VME_BASE,        KA43_VME_END,   KA43_VME_SIZE,  0 },
+       /*
+        * there's more to come, eg. framebuffers (GPX/SPX)
+        */
+       {0, 0, 0, 0},
+};
+
+#define CH1_BITS \
+       "\020\015BCHIT\014BUSERR\013PPERR\012DPERR\011TPERR\010TRAP1" \
+       "\007TRAP2\006INTR\005HIT\004REFRESH\003FLUSH\002ENABLE\001FORCEHIT"
+
+#define CH2_BITS \
+       "\020\010TPE\007DPE\006MISS\005DIRTY\004CERR\003LERR\002SERR\001ENAB"
+
+void
+ka43_memerr()
+{
+       int mapen;
+       int *ch2reg;
+
+       printf("memory error!\n");
+       printf("primary cache status: %b\n", mfpr(PR_PCSTS), CH1_BITS);
+
+       mapen = mfpr(PR_MAPEN);
+       if (mapen) 
+               ch2reg = (void*)uvax_phys2virt(KA43_CH2_CREG);
+       else 
+               ch2reg = (void*)KA43_CH2_CREG;
+       printf("secondary cache status: %b\n", *ch2reg, CH2_BITS);
+}
+
+static char *mcc43[] = {
+       "no error (0)",
+       "FPA signalled protocoll error",
+       "FPA signalled illegal opcode",
+       "FPA detected parity error",
+       "FPA returned unknown status",
+       "FPA result has parity error",
+       "unused (6)",
+       "unused (7)",
+       "MMU error (TLB miss)",
+       "MMU error (TLB hit)",
+       "HW interrupt at unused IPL",
+       "impossible microcode state",
+       "undefined trap code (i-box)",
+       "undefined control store address",
+       "unused (14)",
+       "unused (15)",
+       "PC tag or data parity error",
+       "data bus parity error",
+       "data bus error (NXM)",
+       "undefined data bus state",
+};
+
+int
+ka43_mchk(addr)
+       caddr_t addr;
+{
+       struct {
+         int bcount;   /* byte count (0x18) */
+         int mcc;      /* "R"-flag and machine check code */
+         int mrva;     /* most recent virtual address */
+         int viba;     /* contents of VIBA register */
+         int sisr;     /* ICCS bit 6 and SISR bits 15:0 */
+         int isd;      /* internal state */
+         int scr;      /* shift count register */
+         int pc;       /* program counter */
+         int psl;      /* processor status longword */
+       } *p = (void*)addr;
+
+       printf("machine check: 0x%x\n", p->mcc);
+       printf("reason: %s\n", mcc43[p->mcc & 0xff]);
+
+       printf("bcount:0x%x, check-code:0x%x, virtaddr:0x%x\n",
+              p->bcount, p->mcc, p->mrva);
+       printf("pc:0x%x, psl:0x%x, viba: %x, state: %x\n",
+              p->pc, p->psl, p->viba, p->isd);
+
+       return (-1);
+}
+
+int
+ka43_setup(uc,flags)
+       struct uvax_calls *uc;
+       int flags;
+{
+       uc->uc_name = "ka43";
+
+       uc->uc_phys2virt = NULL;
+       uc->uc_physmap = ka43_map;
+
+       uc->uc_steal_pages = ka43_steal_pages;
+       uc->uc_conf = ka43_conf;
+       uc->uc_clkread = ka43_clkread;
+       uc->uc_clkwrite = ka43_clkwrite;
+
+       uc->uc_memerr = ka43_memerr;
+       uc->uc_mchk = ka43_mchk;
+
+       uc->uc_intreq = (void*)KA43_INTREQ;
+       uc->uc_intclr = (void*)KA43_INTCLR;
+       uc->uc_intmsk = (void*)KA43_INTMSK;
+
+       uc->uc_busTypes = VAX_VSBUS;
+}
+
+ka43_discache()
+{
+       int *ctag;
+       int *creg;
+       int mapen;
+       int i;
+
+       xtrace(("ka43_discache()\n"));
+       return (0);
+
+       /*
+        * first disable primary cache
+        */
+#if 0
+       mtpr(0, PR_PCSTS);
+       mtpr(0, PR_PCERR);
+       mtpr(0, PR_PCIDX);
+       mtpr(0, PR_PCTAG);
+#else
+       i = mfpr(PR_PCSTS);
+       mtpr((i & ~2), PR_PCSTS);
+       printf("pcsts: %x --> %x\n", i, mfpr(PR_PCSTS));
+#endif
+       /*
+        * now secondary cache
+        */
+       mapen = mfpr(PR_MAPEN);
+       if (mapen) {
+               ctag = (void*)uvax_phys2virt(KA43_CT2_BASE);
+               creg = (void*)uvax_phys2virt(KA43_CH2_CREG);
+       } else {
+               ctag = (void*)KA43_CT2_BASE;
+               creg = (void*)KA43_CH2_CREG;
+       }
+       i = *creg;
+       *creg = (i & ~1);
+       printf("creg: %x --> %x\n", i, *creg);
+       
+       xtrace(("ka43_discache() done.\n"));
+}
+
+ka43_encache()
+{
+       int *ctag;
+       int *creg;
+       int mapen;
+       int i;
+
+       xtrace(("ka43_encache()\n"));
+
+       ka43_discache();
+
+       /*
+        * first enable primary cache
+        */
+       printf("P-0");
+       i = mfpr(PR_PCSTS);
+       mtpr((i & ~2), PR_PCSTS);
+       mtpr(0, PR_PCSTS);
+       printf("P-1");
+#if 1
+       mtpr(KA43_PCS_ENABLE | KA43_PCS_FLUSH | KA43_PCS_REFRESH, PR_PCSTS);
+#else
+       mtpr(KA43_PCS_ENABLE, PR_PCSTS);
+#endif
+       printf("P-2");
+
+       /*
+        * now secondary cache
+        */
+       mapen = mfpr(PR_MAPEN);
+       if (mapen) {
+               ctag = (void*)uvax_phys2virt(KA43_CT2_BASE);
+               creg = (void*)uvax_phys2virt(KA43_CH2_CREG);
+       } else {
+               ctag = (void*)KA43_CT2_BASE;
+               creg = (void*)KA43_CH2_CREG;
+       }
+       printf("ctag: %x, creg: %x\n", ctag, creg);
+       printf("S-1");
+       i = *creg;
+       printf("creg=[%x] ", *creg);
+#if 0
+       *creg = (i & ~1);
+       printf("creg=[%x] ", *creg);
+       printf("S-2");
+       for (i = 0; i < KA43_CT2_SIZE; i += 4)          /* Quadword entries */
+               ctag[i/4] = 0;                          /* reset lower half */
+       printf("S-3");
+       i = *creg;
+       printf("creg=[%x] ", *creg);
+       *creg = (i & ~1);
+       printf("creg=[%x] ", *creg);
+       printf("S-4");
+       /* *creg = 1; */
+       printf("S-5");
+#endif
+       xtrace(("ka43_encache() done.\n"));
+
+       printf("primary cache status: %b\n", mfpr(PR_PCSTS), CH1_BITS);
+       printf("secondary cache status: %b\n", *creg, CH2_BITS);
+}
+
+void
+ka43_conf(parent, self, aux)
+       struct  device *parent, *self;
+       void    *aux;
+{
+       extern char cpu_model[];
+       extern int vax_siedata;
+
+       if (vax_siedata & 0x02)         /* "single-user" flag */
+               strcpy(cpu_model,"VAXstation 3100 model 76");
+       else if (vax_siedata & 0x01)    /* "multiuser" flag */
+               strcpy(cpu_model,"MicroVAX 3100 model 76(?)");
+       else
+               strcpy(cpu_model, "unknown KA43 board");
+
+       printf(": %s\n", cpu_model);
+
+       ka43_encache();
+}
+
+
+/*
+ *
+ */
+u_long le_iomem;               /* base addr of RAM -- CPU's view */
+u_long le_ioaddr;              /* base addr of RAM -- LANCE's view */
+
+void
+ka43_steal_pages()
+{
+       extern  vm_offset_t avail_start, virtual_avail, avail_end;
+       int     junk;
+       int     i;
+       struct {
+         u_long     :2;
+         u_long data:8;
+         u_long     :22;
+       } *p;
+       int *srp;       /* Scratch Ram */
+       int *pctl;      /* parity control register */
+       char *q = (void*)&srp;
+       char line[20];
+
+       ka43_encache();
+
+       pctl = (void*)KA43_PARCTL;
+       printf("parctl: 0x%x\n", *pctl);
+#if 0
+       *pctl = KA43_PCTL_DPEN | KA43_PCTL_CPEN;
+#else
+       *pctl = KA43_PCTL_CPEN;
+#endif
+       printf("new value for parctl: ");
+       gets(line);
+       *pctl = *line - '0';
+       printf("parctl: 0x%x\n", *pctl);
+
+       srp = NULL;
+       p = (void*)KA43_SCR;
+       for (i=0; i<4; i++) {
+         printf("p[%d] = %x, ", i, p[i].data);
+         q[i]  = p[i].data;
+       }
+       p = (void*)KA43_SCRLEN;
+       printf("\nlen = %d\n", p->data);
+       printf("srp = 0x%x\n", srp);
+
+       for (i=0; i<0x2; i++) {
+         printf("%x:0x%x ", i*4, srp[i]);
+         if ((i & 0x07) == 0x07)
+           printf("\n");
+       }
+       printf("\n");
+
+       printf ("ka43_steal_pages: avail_end=0x%x\n", avail_end);
+
+       /* 
+        * SCB is already copied/initialized at addr avail_start
+        * by pmap_bootstrap(), but it's not yet mapped. Thus we use
+        * the MAPPHYS() macro to reserve these two pages and to
+        * perform the mapping. The mapped address is assigned to junk.
+        */
+       MAPPHYS(junk, 2, VM_PROT_READ|VM_PROT_WRITE);
+
+       /*
+        * At top of physical memory there are some console-prom and/or
+        * restart-specific data. Make this area unavailable.
+        */
+#if 1
+       avail_end -= 10 * NBPG;
+#endif
+
+       /*
+        * If we need to map physical areas also, we can decrease avail_end
+        * (the highest available memory-address), copy the stuff into the
+        * gap between and use pmap_map to map it...
+        *
+        * Don't use the MAPPHYS macro here, since this uses and changes(!)
+        * the value of avail_start. Use MAPVIRT even if it's name misleads.
+        */
+       avail_end &= ~0xffff;
+       avail_end -= (64 * 1024);
+
+       avail_end = 0xf00000;
+       le_ioaddr = 0xf40000;
+
+       MAPVIRT(le_iomem, (64 * 1024)/NBPG);
+       pmap_map((vm_offset_t)le_iomem, le_ioaddr, le_ioaddr + 0xffff,
+                VM_PROT_READ|VM_PROT_WRITE);
+
+       if (1 || le_ioaddr > 0xffffff) {
+               le_ioaddr &= 0xffffff;
+               *pctl |= KA43_PCTL_DMA;
+       }
+       printf("le_iomem: %x, le_ioaddr: %x, parctl:%x\n",
+              le_iomem, le_ioaddr, *pctl);
+
+       /*
+        * now map in anything listed in ka43_map...
+        */
+       uVAX_fillmap(ka43_map);
+
+       /*
+        * Clear restart and boot in progress flags in the CPMBX. 
+        */
+       ka43_clkptr->cpmbx = ka43_clkptr->cpmbx & 0xF0;
+
+       /*
+        * Enable memory parity error detection and clear error bits.
+        */
+       ka43_cpuptr->ka43_mser = 0x01; 
+       /* (UVAXIIMSER_PEN | UVAXIIMSER_MERR | UVAXIIMSER_LEB); */
+
+       /*
+        * MM is not yet enabled, thus we still used the physical addresses,
+        * but before leaving this routine, we need to reset them to virtual.
+        */
+       ka43_cpuptr = (void*)uvax_phys2virt(KA43_CPU_BASE);
+       ka43_clkptr = (void*)uvax_phys2virt(KA43_WAT_BASE);
+
+       printf ("steal_pages done.\n");
+}
+
+/*
+ * define what we need and overwrite the uVAX_??? names
+ */
+
+#define NEED_UVAX_GENCLOCK
+#define NEED_UVAX_PROTOCLOCK
+
+#define uVAX_clock     ka43_clock
+#define uVAX_clkptr    ka43_clkptr
+#define uVAX_clkread   ka43_clkread
+#define uVAX_clkwrite  ka43_clkwrite
+#define uVAX_genclock  ka43_genclock
+
+#include <arch/vax/vax/uvax_proto.c>
diff --git a/sys/arch/vax/vax/ka630.c b/sys/arch/vax/vax/ka630.c
new file mode 100644 (file)
index 0000000..3212149
--- /dev/null
@@ -0,0 +1,193 @@
+/*     $NetBSD: ka630.c,v 1.4 1996/10/13 03:35:44 christos Exp $       */
+/*-
+ * Copyright (c) 1982, 1988, 1990, 1993
+ *     The Regents of the University of California.  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.
+ *
+ *      @(#)ka630.c     7.8 (Berkeley) 5/9/91
+ */
+
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/device.h>
+#include <sys/kernel.h>
+#include <sys/time.h>
+
+#include <vm/vm.h>
+#include <vm/vm_kern.h>
+
+#include <machine/pte.h>
+#include <machine/mtpr.h>
+#include <machine/sid.h>
+#include <machine/pmap.h>
+#include <machine/nexus.h>
+#include <machine/uvax.h>
+#include <machine/ka630.h>
+#include <machine/clock.h>
+
+struct uvaxIIcpu *uvaxIIcpu_ptr;
+
+struct ka630clock *ka630_clkptr = KA630CLK;
+
+static void ka630_conf __P((struct device *, struct device *, void *));
+static void ka630_memerr __P((void));
+static int ka630_mchk __P((caddr_t));
+static void ka630_steal_pages __P((void));
+
+
+int
+ka630_setup(uc,flags)
+        struct uvax_calls *uc;
+        int flags;
+{
+        uc->uc_name = "ka630";
+
+        uc->uc_phys2virt = NULL;
+        uc->uc_physmap = NULL;     /* ptv_map ? p2v_map */
+
+        uc->uc_steal_pages = ka630_steal_pages;
+        uc->uc_conf = ka630_conf;
+        uc->uc_clkread = ka630_clkread;
+        uc->uc_clkwrite = ka630_clkwrite;
+        
+#ifdef notyet
+        uc->uc_memerr = ka630_memerr;
+        uc->uc_mchk = ka630_mchk;
+#endif  
+        
+        uc->uc_busTypes = VAX_UNIBUS;
+} 
+
+/*
+ * uvaxII_conf() is called by cpu_attach to do the cpu_specific setup.
+ */
+void
+ka630_conf(parent, self, aux)
+       struct  device *parent, *self;
+       void    *aux;
+{
+       extern char cpu_model[];
+
+       strcpy(cpu_model,"MicroVAX II");
+       printf(": %s\n", cpu_model);
+}
+
+/* log crd errors */
+uvaxII_memerr()
+{
+       printf("memory err!\n");
+}
+
+#define NMC78032 10
+char *mc78032[] = {
+       0,              "immcr (fsd)",  "immcr (ssd)",  "fpu err 0",
+       "fpu err 7",    "mmu st(tb)",   "mmu st(m=0)",  "pte in p0",
+       "pte in p1",    "un intr id",
+};
+
+struct mc78032frame {
+       int     mc63_bcnt;              /* byte count == 0xc */
+       int     mc63_summary;           /* summary parameter */
+       int     mc63_mrvaddr;           /* most recent vad */
+       int     mc63_istate;            /* internal state */
+       int     mc63_pc;                /* trapped pc */
+       int     mc63_psl;               /* trapped psl */
+};
+
+uvaxII_mchk(cmcf)
+       caddr_t cmcf;
+{
+       register struct mc78032frame *mcf = (struct mc78032frame *)cmcf;
+       register u_int type = mcf->mc63_summary;
+
+       printf("machine check %x", type);
+       if (type < NMC78032 && mc78032[type])
+               printf(": %s", mc78032[type]);
+       printf("\n\tvap %x istate %x pc %x psl %x\n",
+           mcf->mc63_mrvaddr, mcf->mc63_istate,
+           mcf->mc63_pc, mcf->mc63_psl);
+       if (uvaxIIcpu_ptr && uvaxIIcpu_ptr->uvaxII_mser & UVAXIIMSER_MERR) {
+               printf("\tmser=0x%x ", uvaxIIcpu_ptr->uvaxII_mser);
+               if (uvaxIIcpu_ptr->uvaxII_mser & UVAXIIMSER_CPUE)
+                       printf("page=%d", uvaxIIcpu_ptr->uvaxII_cear);
+               if (uvaxIIcpu_ptr->uvaxII_mser & UVAXIIMSER_DQPE)
+                       printf("page=%d", uvaxIIcpu_ptr->uvaxII_dear);
+               printf("\n");
+       }
+       return (-1);
+}
+
+void
+ka630_steal_pages()
+{
+       extern  vm_offset_t avail_start, virtual_avail, avail_end;
+       int     junk;
+
+       /*
+        * MicroVAX II: get 10 pages from top of memory,
+        * map in Qbus map registers, cpu and clock registers.
+        */
+       avail_end -= 10;
+
+       MAPPHYS(junk, 2, VM_PROT_READ|VM_PROT_WRITE);
+       MAPVIRT(nexus, btoc(0x400000));
+       pmap_map((vm_offset_t)nexus, 0x20088000, 0x20090000,
+           VM_PROT_READ|VM_PROT_WRITE);
+
+       MAPVIRT(uvaxIIcpu_ptr, 1);
+       pmap_map((vm_offset_t)uvaxIIcpu_ptr, (vm_offset_t)UVAXIICPU,
+           (vm_offset_t)UVAXIICPU + NBPG, VM_PROT_READ|VM_PROT_WRITE);
+
+       MAPVIRT(ka630_clkptr, 1);
+       pmap_map((vm_offset_t)ka630_clkptr, (vm_offset_t)KA630CLK,
+           (vm_offset_t)KA630CLK + NBPG, VM_PROT_READ|VM_PROT_WRITE);
+
+       /*
+        * Clear restart and boot in progress flags
+        * in the CPMBX.
+        /
+       ka630clk_ptr->cpmbx = (ka630clk_ptr->cpmbx & KA630CLK_LANG);
+
+       /*
+        * Enable memory parity error detection and clear error bits.
+        */
+       uvaxIIcpu_ptr->uvaxII_mser = (UVAXIIMSER_PEN | UVAXIIMSER_MERR |
+           UVAXIIMSER_LEB);
+
+}
+#define uVAX_gettodr    ka630_gettodr
+#define uVAX_settodr    ka630_settodr
+#define        uVAX_clkptr     ka630_clkptr
+#define        uVAX_genclock   ka630_genclock
+#define        uVAX_clock      ka630clock
+#define        uVAX_clkread    ka630_clkread
+#define        uVAX_clkwrite   ka630_clkwrite
+
+#include <arch/vax/vax/uvax_proto.c>
index be70978..e4a798c 100644 (file)
@@ -1,4 +1,4 @@
-/*     $NetBSD: ka650.c,v 1.3 1996/04/08 18:32:41 ragge Exp $  */
+/*     $NetBSD: ka650.c,v 1.7 1997/01/11 11:31:57 ragge Exp $  */
 /*
  * Copyright (c) 1988 The Regents of the University of California.
  * All rights reserved.
@@ -80,6 +80,7 @@ uvaxIII_conf(parent, self, aux)
         * check which here. but that later...
         */
        strcpy(cpu_model,"MicroVAX III");
+       printf(": %s\n", cpu_model);
        ka650encache();
        if (ctob(physmem) > ka650merr_ptr->merr_qbmbr) {
                printf("physmem(0x%x) > qbmbr(0x%x)\n",
@@ -131,13 +132,6 @@ uvaxIII_steal_pages()
        subtyp = *jon;
 }
 
-int
-uvaxIII_clock()
-{
-       mtpr(0x40, PR_ICCS); /* Start clock and enable interrupt */
-       return 1;
-}
-
 void
 uvaxIII_memerr()
 {
@@ -241,9 +235,9 @@ uvaxIII_mchk(cmcf)
        }
        if (time.tv_sec - i < 7) {
                ka650discache();
-               printf(" parity error:  cacheing disabled\n");
+               printf(" parity error:  cacheing disabled\n");
        } else {
-               printf(" parity error:  flushing cache\n");
+               printf(" parity error:  flushing cache\n");
                ka650encache();
        }
        /*
index fbcf608..2224696 100644 (file)
@@ -1,4 +1,4 @@
-/*     $NetBSD: ka750.c,v 1.12 1996/04/08 18:32:42 ragge Exp $ */
+/*     $NetBSD: ka750.c,v 1.17 1996/10/13 03:35:48 christos Exp $ */
 
 /*-
  * Copyright (c) 1982, 1986, 1988 The Regents of the University of California.
@@ -34,7 +34,7 @@
  * SUCH DAMAGE.
  *
  *     @(#)ka750.c     7.4 (Berkeley) 5/9/91
- *      @(#)autoconf.c  7.20 (Berkeley) 5/9/91
+ *     @(#)autoconf.c  7.20 (Berkeley) 5/9/91
  */
 
 #include <sys/param.h>
 #include <machine/ka750.h>
 #include <machine/pte.h>
 #include <machine/cpu.h>
+#include <machine/sid.h>
 #include <machine/mtpr.h>
 #include <machine/scb.h>
+
 #include <vax/uba/ubavar.h>
 #include <vax/uba/ubareg.h>
 
@@ -60,14 +62,14 @@ void        ctuattach __P((void));
  */
 void
 ka750_conf(parent, self, aux)
-       struct  device *parent, *self;
-       void    *aux;
+       struct device *parent, *self;
+       void *aux;
 {
        extern  char cpu_model[];
 
        strcpy(cpu_model,"VAX 11/750");
        printf(": 11/750, hardware rev %d, ucode rev %d\n",
-           V750HARDW(cpu_type), V750UCODE(cpu_type));
+           V750HARDW(vax_cpudata), V750UCODE(vax_cpudata));
        printf("%s: ", self->dv_xname);
        if (mfpr(PR_ACCS) & 255) {
                printf("FPA present, enabling.\n");
@@ -79,28 +81,30 @@ ka750_conf(parent, self, aux)
        ctuattach();
 }
 
-/*
- * ka750_clock() makes the 11/750 interrupt clock and todr
- * register start counting.
- */
+static int ka750_memmatch __P((struct  device  *, void  *, void *));
+static void ka750_memenable __P((struct  device  *, struct  device  *, void *));
+
+struct  cfattach mem_cmi_ca = {
+        sizeof(struct device), ka750_memmatch, ka750_memenable
+};
+
 int
-ka750_clock()
+ka750_memmatch(parent, gcf, aux)
+        struct  device  *parent;
+        void    *gcf, *aux;
 {
+       struct  sbi_attach_args *sa = (struct sbi_attach_args *)aux;
+       struct  cfdata  *cf = gcf;
 
-       mtpr(-10000, PR_NICR); /* Load in count register */
-       mtpr(0x800000d1, PR_ICCS); /* Start clock and enable interrupt */
-       if (mfpr(PR_TODR)) {
-               /* todr running */
+        if ((cf->cf_loc[0] != sa->nexnum) && (cf->cf_loc[0] > -1))
+                return 0;
+
+       if (sa->type != NEX_MEM16)
                return 0;
-       } else {
-               /* Start TODR register. */
-               mtpr(1, PR_TODR);
-               return 1;
-       }
 
+       return 1;
 }
 
-
 extern volatile caddr_t mcraddr[];
 
 struct mcr750 {
@@ -109,26 +113,27 @@ struct    mcr750 {
        int     mc_inf;                 /* info bits */
 };
 
-#define        M750_ICRD       0x10000000      /* inhibit crd interrupts, in [1] */
-#define        M750_UNCORR     0xc0000000      /* uncorrectable error, in [0] */
-#define        M750_CORERR     0x20000000      /* correctable error, in [0] */
+#define M750_ICRD      0x10000000      /* inhibit crd interrupts, in [1] */
+#define M750_UNCORR    0xc0000000      /* uncorrectable error, in [0] */
+#define M750_CORERR    0x20000000      /* correctable error, in [0] */
 
-#define        M750_INH(mcr)   ((mcr)->mc_inh = 0)
-#define        M750_ENA(mcr)   ((mcr)->mc_err = (M750_UNCORR|M750_CORERR), \
+#define M750_INH(mcr)  ((mcr)->mc_inh = 0)
+#define M750_ENA(mcr)  ((mcr)->mc_err = (M750_UNCORR|M750_CORERR), \
                         (mcr)->mc_inh = M750_ICRD)
-#define        M750_ERR(mcr)   ((mcr)->mc_err & (M750_UNCORR|M750_CORERR))
+#define M750_ERR(mcr)  ((mcr)->mc_err & (M750_UNCORR|M750_CORERR))
 
-#define        M750_SYN(err)   ((err) & 0x7f)
-#define        M750_ADDR(err)  (((err) >> 9) & 0x7fff)
+#define M750_SYN(err)  ((err) & 0x7f)
+#define M750_ADDR(err) (((err) >> 9) & 0x7fff)
 
 /* enable crd interrupts */
 void
-ka750_memenable(sa,self)
-       struct sbi_attach_args *sa;
-       struct device *self;
+ka750_memenable(parent, self, aux)
+        struct  device  *parent, *self;
+        void    *aux;
 {
-       int k, l, m, cardinfo;
+       struct  sbi_attach_args *sa = (struct sbi_attach_args *)aux;
        struct mcr750 *mcr = (struct mcr750 *)sa->nexaddr;
+       int k, l, m, cardinfo;
        
        mcraddr[self->dv_unit] = (caddr_t)sa->nexaddr;
 
@@ -209,7 +214,7 @@ struct mc750frame {
 };
 
 #define MC750_TBERR    2               /* type code of cp tbuf par */
-#define        MC750_TBPAR     4               /* tbuf par bit in mcesr */
+#define MC750_TBPAR    4               /* tbuf par bit in mcesr */
 
 int
 ka750_mchk(cmcf)
@@ -241,7 +246,6 @@ void
 ka750_steal_pages()
 {
        extern  vm_offset_t avail_start, virtual_avail;
-       extern  struct nexus *nexus;
        int     junk;
 
        /*
@@ -255,3 +259,87 @@ ka750_steal_pages()
            VM_PROT_READ|VM_PROT_WRITE);
 }
 
+static  int cmi_print __P((void *, const char *));
+static  int cmi_match __P((struct device *, void *, void *));
+static  void cmi_attach __P((struct device *, struct device *, void*));
+
+struct  cfdriver cmi_cd = {
+        NULL, "cmi", DV_DULL
+};      
+
+struct  cfattach cmi_ca = {
+        sizeof(struct device), cmi_match, cmi_attach
+};
+
+int
+cmi_print(aux, name)
+        void *aux;
+        const char *name;
+{
+        struct sbi_attach_args *sa = (struct sbi_attach_args *)aux;
+
+        if (name)
+               printf("unknown device 0x%x at %s", sa->type, name);
+
+        printf(" tr%d", sa->nexnum);
+        return (UNCONF);
+}
+
+
+int
+cmi_match(parent, cf, aux)
+        struct  device  *parent;
+        void    *cf, *aux;
+{
+        struct bp_conf *bp = aux;
+
+        if (strcmp(bp->type, "cmi"))
+                return 0;
+        return 1;
+}
+
+void
+cmi_attach(parent, self, aux)
+        struct  device  *parent, *self;
+        void    *aux;
+{
+        u_int   nexnum, maxnex, minnex;
+        struct  sbi_attach_args sa;
+
+       printf("I\n");
+       /*
+        * Probe for memory, can be in the first 4 slots.
+        */
+       for (sa.nexnum = 0; sa.nexnum < 4; sa.nexnum++) {
+               if (badaddr((caddr_t)&nexus[sa.nexnum], 4))
+                       continue;
+
+               sa.nexaddr = nexus + sa.nexnum;
+               sa.type = NEX_MEM16;
+               config_found(self, (void*)&sa, cmi_print);
+       }
+
+       /*
+        * Probe for mba's, can be in slot 4 - 7.
+        */
+       for (sa.nexnum = 4; sa.nexnum < 7; sa.nexnum++) {
+               if (badaddr((caddr_t)&nexus[sa.nexnum], 4))
+                       continue;
+
+               sa.nexaddr = nexus + sa.nexnum;
+               sa.type = NEX_MBA;
+               config_found(self, (void*)&sa, cmi_print);
+       }
+
+       /*
+        * There are always one generic UBA, and maybe an optional.
+        */
+       sa.nexnum = 8;
+       sa.nexaddr = nexus + sa.nexnum;
+       sa.type = NEX_UBA0;
+       config_found(self, (void*)&sa, cmi_print);
+       sa.type = NEX_UBA1;
+       if (badaddr((caddr_t)&nexus[++sa.nexnum], 4) == 0)
+               config_found(self, (void*)&sa, cmi_print);
+
+}
index 7eb7e05..93b4711 100644 (file)
@@ -1,4 +1,4 @@
-/*     $NetBSD: ka780.c,v 1.3 1996/04/08 18:32:43 ragge Exp $  */
+/*     $NetBSD: ka780.c,v 1.6 1996/10/13 03:35:50 christos Exp $       */
 /*-
  * Copyright (c) 1982, 1986, 1988 The Regents of the University of California.
  * All rights reserved.
 #include <machine/mtpr.h>
 #include <machine/scb.h>
 #include <machine/nexus.h>
+#include <machine/sid.h>
+
 #include <vax/uba/ubavar.h>
 #include <vax/uba/ubareg.h>
 
 /* Prototypes. XXX These should be somewhere else */
 void   ka780_conf __P((struct device *, struct device *, void *));
-int    ka780_clock __P((void));
 void   ka780_memenable __P((struct sbi_attach_args *, void *));
 void   ka780_memerr __P((void));
 int    ka780_mchk __P((caddr_t));
@@ -69,45 +70,45 @@ struct      mcr780 {
        int     mc_reg[4];
 };
 
-#define        M780_ICRD       0x40000000      /* inhibit crd interrupts, in [2] */
-#define        M780_HIER       0x20000000      /* high error rate, in reg[2] */
-#define        M780_ERLOG      0x10000000      /* error log request, in reg[2] */
+#define M780_ICRD      0x40000000      /* inhibit crd interrupts, in [2] */
+#define M780_HIER      0x20000000      /* high error rate, in reg[2] */
+#define M780_ERLOG     0x10000000      /* error log request, in reg[2] */
 /* on a 780, memory crd's occur only when bit 15 is set in the SBIER */
 /* register; bit 14 there is an error bit which we also clear */
 /* these bits are in the back of the ``red book'' (or in the VMS code) */
 
-#define        M780C_INH(mcr)  \
+#define M780C_INH(mcr) \
        ((mcr)->mc_reg[2] = (M780_ICRD|M780_HIER|M780_ERLOG)); \
            mtpr(0, PR_SBIER);
-#define        M780C_ENA(mcr)  \
+#define M780C_ENA(mcr) \
        ((mcr)->mc_reg[2] = (M780_HIER|M780_ERLOG)); mtpr(3<<14, PR_SBIER);
-#define        M780C_ERR(mcr)  \
+#define M780C_ERR(mcr) \
        ((mcr)->mc_reg[2] & (M780_ERLOG))
 
-#define        M780C_SYN(mcr)  ((mcr)->mc_reg[2] & 0xff)
-#define        M780C_ADDR(mcr) (((mcr)->mc_reg[2] >> 8) & 0xfffff)
+#define M780C_SYN(mcr) ((mcr)->mc_reg[2] & 0xff)
+#define M780C_ADDR(mcr) (((mcr)->mc_reg[2] >> 8) & 0xfffff)
 
-#define        M780EL_INH(mcr) \
+#define M780EL_INH(mcr) \
        ((mcr)->mc_reg[2] = (M780_ICRD|M780_HIER|M780_ERLOG)); \
            mtpr(0, PR_SBIER);
-#define        M780EL_ENA(mcr) \
+#define M780EL_ENA(mcr) \
        ((mcr)->mc_reg[2] = (M780_HIER|M780_ERLOG)); mtpr(3<<14, PR_SBIER);
-#define        M780EL_ERR(mcr) \
+#define M780EL_ERR(mcr) \
        ((mcr)->mc_reg[2] & (M780_ERLOG))
 
-#define        M780EL_SYN(mcr)         ((mcr)->mc_reg[2] & 0x7f)
-#define        M780EL_ADDR(mcr)        (((mcr)->mc_reg[2] >> 11) & 0x1ffff)
+#define M780EL_SYN(mcr)                ((mcr)->mc_reg[2] & 0x7f)
+#define M780EL_ADDR(mcr)       (((mcr)->mc_reg[2] >> 11) & 0x1ffff)
 
-#define        M780EU_INH(mcr) \
+#define M780EU_INH(mcr) \
        ((mcr)->mc_reg[3] = (M780_ICRD|M780_HIER|M780_ERLOG)); \
            mtpr(0, PR_SBIER);
-#define        M780EU_ENA(mcr) \
+#define M780EU_ENA(mcr) \
        ((mcr)->mc_reg[3] = (M780_HIER|M780_ERLOG)); mtpr(3<<14, PR_SBIER);
-#define        M780EU_ERR(mcr) \
+#define M780EU_ERR(mcr) \
        ((mcr)->mc_reg[3] & (M780_ERLOG))
 
-#define        M780EU_SYN(mcr)         ((mcr)->mc_reg[3] & 0x7f)
-#define        M780EU_ADDR(mcr)        (((mcr)->mc_reg[3] >> 11) & 0x1ffff)
+#define M780EU_SYN(mcr)                ((mcr)->mc_reg[3] & 0x7f)
+#define M780EU_ADDR(mcr)       (((mcr)->mc_reg[3] >> 11) & 0x1ffff)
 
 /* enable crd interrrupts */
 void
@@ -213,8 +214,8 @@ struct {
        0x73,   "L19",  0x75,   "L21",  0x76,   "L22",  0x79,   "L25",
        0x7A,   "L26",  0x7C,   "L28",  0x7F,   "L31",  0x80,   "C07",
        0x89,   "U01",  0x8A,   "U02",  0x8C,   "U04",  0x8F,   "U07",
-       0x91,   "U09",  0x92,   "U10",  0x94,   "U12",  0x97,   "U15",
-       0x98,   "U16",  0x9B,   "U19",  0x9D,   "U21",  0x9E,   "U22",
+       0x91,   "U09",  0x92,   "U10",  0x94,   "U12",  0x97,   "U15",
+       0x98,   "U16",  0x9B,   "U19",  0x9D,   "U21",  0x9E,   "U22",
        0xA8,   "U00",  0xAB,   "U03",  0xAD,   "U05",  0xAE,   "U06",
        0xB0,   "U08",  0xB3,   "U11",  0xB5,   "U13",  0xB6,   "U14",
        0xB9,   "U17",  0xBA,   "U18",  0xBC,   "U20",  0xBF,   "U23",
@@ -244,7 +245,7 @@ memlog(m, mcr)
 #endif TRENDATA
 
 char *mc780[]={"0","1","2","3","4","5","6","7","8","9","10","11","12","13",
-        "14","15"};
+       "14","15"};
 
 struct mc780frame {
        int     mc8_bcnt;               /* byte count == 0x28 */
@@ -296,11 +297,11 @@ struct ka78x {
 
 void
 ka780_conf(parent, self, aux)
-       struct  device *parent, *self;
-       void    *aux;
+       struct  device *parent, *self;
+       void    *aux;
 {
-       extern  char cpu_model[];
-       struct  ka78x *ka78 = (void *)&cpu_type;
+       extern  char cpu_model[];
+       struct  ka78x *ka78 = (void *)&vax_cpudata;
 
        /* Enable cache */
        mtpr(0x200000, PR_SBIMT);
@@ -319,14 +320,6 @@ ka780_conf(parent, self, aux)
 
 }
 
-int
-ka780_clock()
-{
-       mtpr(-10000, PR_NICR); /* Load in count register */
-       mtpr(0x800000d1, PR_ICCS); /* Start clock and enable interrupt */
-       return 0;
-}
-
 void
 ka780_steal_pages()
 {
diff --git a/sys/arch/vax/vax/ka820.c b/sys/arch/vax/vax/ka820.c
new file mode 100644 (file)
index 0000000..b3122c8
--- /dev/null
@@ -0,0 +1,466 @@
+/*     $NetBSD: ka820.c,v 1.3 1996/10/13 03:35:51 christos Exp $       */
+/*
+ * Copyright (c) 1988 Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * 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.
+ *
+ *     @(#)ka820.c     7.4 (Berkeley) 12/16/90
+ */
+
+/*
+ * KA820 specific CPU code.  (Note that the VAX8200 uses a KA820, not
+ * a KA8200.  Sigh.)
+ */
+
+#include <sys/param.h>
+#include <sys/time.h>
+#include <sys/kernel.h>
+#include <sys/device.h>
+
+#include <vm/vm.h> 
+#include <vm/vm_kern.h>
+
+#include <machine/ka820.h>
+#include <machine/cpu.h>
+#include <machine/mtpr.h>
+#include <machine/nexus.h>
+#include <machine/clock.h>
+#include <machine/scb.h>
+
+#include <arch/vax/bi/bireg.h>
+#include <arch/vax/bi/bivar.h>
+
+struct ka820clock *ka820clock_ptr;
+struct ka820port *ka820port_ptr;
+struct rx50device *rx50device_ptr;
+void *bi_nodebase;     /* virtual base address for all possible bi nodes */
+
+static int ka820_match __P((struct device *, void *, void *));
+static void ka820_attach __P((struct device *, struct device *, void*));
+
+struct cfattach cpu_bi_ca = {
+       sizeof(struct device), ka820_match, ka820_attach
+};
+
+#ifdef notyet
+extern struct pte BRAMmap[];
+extern struct pte EEPROMmap[];
+char bootram[KA820_BRPAGES * NBPG];
+char eeprom[KA820_EEPAGES * NBPG];
+#endif
+
+struct ivec_dsp nollhanterare;
+
+static void
+hant(arg)
+       int arg;
+{
+       if (cold == 0)
+               printf("stray interrupt from vaxbi bus\n");
+}
+
+void
+ka820_steal_pages()
+{
+       extern  vm_offset_t avail_start, virtual_avail, avail_end;
+       extern  struct ivec_dsp idsptch;
+       struct scb *sb;
+       int     junk, i, j;
+
+       /*
+        * On the ka820, we map in the port CSR, the clock registers
+        * and the console RX50 register. We also map in the BI nodespace
+        * for all possible (16) nodes. It would only be needed with
+        * the existent nodes, but we only loose 1K so...
+        */
+       sb = (void *)avail_start;
+       MAPPHYS(junk, j, VM_PROT_READ|VM_PROT_WRITE); /* SCB & vectors */
+       MAPVIRT(ka820clock_ptr, 1);
+       pmap_map((vm_offset_t)ka820clock_ptr, (vm_offset_t)KA820_CLOCKADDR,
+           KA820_CLOCKADDR + NBPG, VM_PROT_READ|VM_PROT_WRITE);
+
+       MAPVIRT(ka820port_ptr, 1);
+       pmap_map((vm_offset_t)ka820port_ptr, (vm_offset_t)KA820_PORTADDR,
+           KA820_PORTADDR + NBPG, VM_PROT_READ|VM_PROT_WRITE);
+
+       MAPVIRT(rx50device_ptr, 1);
+       pmap_map((vm_offset_t)rx50device_ptr, (vm_offset_t)KA820_RX50ADDR,
+           KA820_RX50ADDR + NBPG, VM_PROT_READ|VM_PROT_WRITE);
+
+       MAPVIRT(bi_nodebase, NNODEBI * (sizeof(struct bi_node) / NBPG));
+       pmap_map((vm_offset_t)bi_nodebase, (vm_offset_t)BI_BASE(0),
+           BI_BASE(0) + sizeof(struct bi_node) * NNODEBI,
+           VM_PROT_READ|VM_PROT_WRITE);
+       bcopy(&idsptch, &nollhanterare, sizeof(struct ivec_dsp));
+       nollhanterare.hoppaddr = hant;
+       for (i = 0; i < 4; i++)
+               for (j = 0; j < 16; j++)
+                       sb->scb_nexvec[i][j] = &nollhanterare;
+
+}
+
+int
+ka820_match(parent, match, aux)
+       struct device *parent;
+       void    *match, *aux;
+{
+       struct  cfdata *cf = match;
+       struct bi_attach_args *ba = aux;
+
+       if (ba->ba_node->biic.bi_dtype != BIDT_KA820)
+               return 0;
+
+       if (ba->ba_nodenr != mastercpu)
+               return 0;
+
+       if (cf->cf_loc[0] != -1 && cf->cf_loc[0] != ba->ba_nodenr)
+               return 0;
+
+       return 1;
+}
+
+void
+ka820_attach(parent, self, aux)
+       struct  device *parent, *self;
+       void    *aux;
+{
+       struct bi_attach_args *ba = aux;
+       register int csr;
+       u_short rev = ba->ba_node->biic.bi_revs;
+       extern  char cpu_model[];
+
+       strcpy(cpu_model,"VAX 8200");
+       cpu_model[6] = rev & 0x8000 ? '5' : '0';
+       printf(": ka82%c (%s) cpu rev %d, u patch rev %d, sec patch %d\n",
+           cpu_model[6], mastercpu == ba->ba_nodenr ? "master" : "slave",
+           ((rev >> 11) & 15), ((rev >> 1) &1023), rev & 1);
+
+       /* reset the console and enable the RX50 */
+       csr = ka820port_ptr->csr;
+       csr &= ~KA820PORT_RSTHALT;      /* ??? */
+       csr |= KA820PORT_CONSCLR | KA820PORT_CRDCLR | KA820PORT_CONSEN |
+               KA820PORT_RXIE;
+       ka820port_ptr->csr = csr;
+       ba->ba_node->biic.bi_intrdes = ba->ba_intcpu;
+       ba->ba_node->biic.bi_csr |= BICSR_SEIE | BICSR_HEIE;
+}
+
+/* Set system time from clock */
+/* ARGSUSED */
+ka820_clkread(base)
+       time_t base;
+{
+       struct chiptime c;
+       int s, rv;
+
+       rv = CLKREAD_OK;
+       /* I wish I knew the differences between these */
+       if ((ka820clock_ptr->csr3 & KA820CLK_3_VALID) == 0) {
+               printf("WARNING: TOY clock not marked valid\n");
+               rv = CLKREAD_WARN;
+       }
+       if ((ka820clock_ptr->csr1 & KA820CLK_1_GO) != KA820CLK_1_GO) {
+               printf("WARNING: TOY clock stopped\n");
+               rv = CLKREAD_WARN;
+       }
+       /* THIS IS NOT RIGHT (clock may change on us) */
+       s = splhigh();
+       while (ka820clock_ptr->csr0 & KA820CLK_0_BUSY)
+               /* void */;
+       c.sec = ka820clock_ptr->sec;
+       c.min = ka820clock_ptr->min;
+       c.hour = ka820clock_ptr->hr;
+       c.day = ka820clock_ptr->day;
+       c.mon = ka820clock_ptr->mon;
+       c.year = ka820clock_ptr->yr;
+       splx(s);
+
+       /* the darn thing needs tweaking! */
+       c.sec >>= 1;            /* tweak */
+       c.min >>= 1;            /* tweak */
+       c.hour >>= 1;           /* tweak */
+       c.day >>= 1;            /* tweak */
+       c.mon >>= 1;            /* tweak */
+       c.year >>= 1;           /* tweak */
+
+       time.tv_sec = chiptotime(&c);
+       return (time.tv_sec ? rv : CLKREAD_BAD);
+}
+
+/* store time into clock */
+void
+ka820_clkwrite()
+{
+       struct chiptime c;
+       int s;
+
+       timetochip(&c);
+
+       /* play it again, sam (or mike or kirk or ...) */
+       c.sec <<= 1;            /* tweak */
+       c.min <<= 1;            /* tweak */
+       c.hour <<= 1;           /* tweak */
+       c.day <<= 1;            /* tweak */
+       c.mon <<= 1;            /* tweak */
+       c.year <<= 1;           /* tweak */
+
+       s = splhigh();
+       ka820clock_ptr->csr1 = KA820CLK_1_SET;
+       while (ka820clock_ptr->csr0 & KA820CLK_0_BUSY)
+               /* void */;
+       ka820clock_ptr->sec = c.sec;
+       ka820clock_ptr->min = c.min;
+       ka820clock_ptr->hr = c.hour;
+       ka820clock_ptr->day = c.day;
+       ka820clock_ptr->mon = c.mon;
+       ka820clock_ptr->yr = c.year;
+       /* should we set a `rate'? */
+       ka820clock_ptr->csr1 = KA820CLK_1_GO;
+       splx(s);
+}
+
+/*
+ * MS820 support.
+ */
+struct ms820regs {
+       struct  biiregs biic;           /* BI interface chip */
+       u_long  ms_gpr[4];              /* the four gprs (unused) */
+       int     ms_csr1;                /* control/status register 1 */
+       int     ms_csr2;                /* control/status register 2 */
+};
+
+/*
+ * Bits in CSR1.
+ */
+#define MS1_ERRSUM     0x80000000      /* error summary (ro) */
+#define MS1_ECCDIAG    0x40000000      /* ecc diagnostic (rw) */
+#define MS1_ECCDISABLE 0x20000000      /* ecc disable (rw) */
+#define MS1_MSIZEMASK  0x1ffc0000      /* mask for memory size (ro) */
+#define MS1_RAMTYMASK  0x00030000      /* mask for ram type (ro) */
+#define MS1_RAMTY64K   0x00000000      /* 64K chips */
+#define MS1_RAMTY256K  0x00010000      /* 256K chips */
+#define MS1_RAMTY1MB   0x00020000      /* 1MB chips */
+                                       /* type 3 reserved */
+#define MS1_CRDINH     0x00008000      /* inhibit crd interrupts (rw) */
+#define MS1_MEMVALID   0x00004000      /* memory has been written (ro) */
+#define MS1_INTLK      0x00002000      /* interlock flag (ro) */
+#define MS1_BROKE      0x00001000      /* broken (rw) */
+#define MS1_MBZ                0x00000880      /* zero */
+#define MS1_MWRITEERR  0x00000400      /* rds during masked write (rw) */
+#define MS1_CNTLERR    0x00000200      /* internal timing busted (rw) */
+#define MS1_INTLV      0x00000100      /* internally interleaved (ro) */
+#define MS1_DIAGC      0x0000007f      /* ecc diagnostic bits (rw) */
+
+/*
+ * Bits in CSR2.
+ */
+#define MS2_RDSERR     0x80000000      /* rds error (rw) */
+#define MS2_HIERR      0x40000000      /* high error rate (rw) */
+#define MS2_CRDERR     0x20000000      /* crd error (rw) */
+#define MS2_ADRSERR    0x10000000      /* rds due to addr par err (rw) */
+#define MS2_MBZ                0x0f000080      /* zero */
+#define MS2_ADDR       0x00fffe00      /* address in error (relative) (ro) */
+#define MS2_INTLVADDR  0x00000100      /* error was in bank 1 (ro) */
+#define MS2_SYN                0x0000007f      /* error syndrome (ro, rw diag) */
+
+static int ms820_match __P((struct device *, void *, void *));
+static void ms820_attach __P((struct device *, struct device *, void*));
+
+struct mem_bi_softc {
+       struct device mem_dev;
+       struct ms820regs *mem_regs;
+};
+
+struct cfattach mem_bi_ca = {
+       sizeof(struct mem_bi_softc), ms820_match, ms820_attach
+};
+
+static int
+ms820_match(parent, match, aux)
+       struct  device  *parent;
+       void    *match, *aux;
+{
+       struct  cfdata *cf = match;
+       struct bi_attach_args *ba = aux;
+
+       if (ba->ba_node->biic.bi_dtype != BIDT_MS820)
+               return 0;
+
+       if (cf->cf_loc[0] != -1 && cf->cf_loc[0] != ba->ba_nodenr)
+               return 0;
+
+       return 1;
+}
+
+static void
+ms820_attach(parent, self, aux)
+       struct  device  *parent, *self;
+       void    *aux;
+{
+       struct mem_bi_softc *ms = (void *)self;
+       struct bi_attach_args *ba = aux;
+
+       ms->mem_regs = (void *)ba->ba_node;
+
+       if ((ms->mem_regs->biic.bi_csr & BICSR_STS) == 0)
+               printf(": failed self test\n");
+       else
+               printf(": size %dMB, %s chips\n", ((ms->mem_regs->ms_csr1 & 
+                   MS1_MSIZEMASK) >> 20), (ms->mem_regs->ms_csr1&MS1_RAMTYMASK
+                   ?ms->mem_regs->ms_csr1 & MS1_RAMTY256K?"256K":"1M":"64K"));
+
+       ms->mem_regs->biic.bi_intrdes = ba->ba_intcpu;
+       ms->mem_regs->biic.bi_csr |= BICSR_SEIE | BICSR_HEIE;
+
+       ms->mem_regs->ms_csr1 = MS1_MWRITEERR | MS1_CNTLERR;
+       ms->mem_regs->ms_csr2 = MS2_RDSERR | MS2_HIERR |
+           MS2_CRDERR | MS2_ADRSERR;
+}
+
+void
+ka820_memerr()
+{
+       register struct ms820regs *mcr;
+       struct mem_bi_softc *mc;
+       extern struct cfdriver mem_cd;
+       register int m, hard;
+       register char *type;
+static char b1[] = "\20\40ERRSUM\37ECCDIAG\36ECCDISABLE\20CRDINH\17VALID\
+\16INTLK\15BROKE\13MWRITEERR\12CNTLERR\11INTLV";
+static char b2[] = "\20\40RDS\37HIERR\36CRD\35ADRS";
+
+       for (m = 0; m < mem_cd.cd_ndevs; m++) {
+               mc = mem_cd.cd_devs[m];
+               if (mc == NULL)
+                       continue;
+               mcr = mc->mem_regs;
+               printf("%s: csr1=%b csr2=%b\n", mc->mem_dev.dv_xname,
+                   mcr->ms_csr1, b1, mcr->ms_csr2, b2);
+               if ((mcr->ms_csr1 & MS1_ERRSUM) == 0)
+                       continue;
+               hard = 1;
+               if (mcr->ms_csr1 & MS1_BROKE)
+                       type = "broke";
+               else if (mcr->ms_csr1 & MS1_CNTLERR)
+                       type = "cntl err";
+               else if (mcr->ms_csr2 & MS2_ADRSERR)
+                       type = "address parity err";
+               else if (mcr->ms_csr2 & MS2_RDSERR)
+                       type = "rds err";
+               else if (mcr->ms_csr2 & MS2_CRDERR) {
+                       hard = 0;
+                       type = "";
+               } else
+                       type = "mysterious error";
+               printf("%s: %s%s%s addr %x bank %x syn %x\n",
+                   mc->mem_dev.dv_xname,
+                   hard ? "hard error: " : "soft ecc",
+                   type, mcr->ms_csr2 & MS2_HIERR ?
+                   " (+ other rds or crd err)" : "",
+                   ((mcr->ms_csr2 & MS2_ADDR) + mcr->biic.bi_sadr) >> 9,
+                   (mcr->ms_csr2 & MS2_INTLVADDR) != 0,
+                   mcr->ms_csr2 & MS2_SYN);
+               mcr->ms_csr1 = mcr->ms_csr1 | MS1_CRDINH;
+               mcr->ms_csr2 = mcr->ms_csr2;
+       }
+}
+
+/* these are bits 0 to 6 in the summary field */
+char *mc8200[] = {
+       "cpu bad ipl",          "ucode lost err",
+       "ucode par err",        "DAL par err",
+       "BI bus err",           "BTB tag par",
+       "cache tag par",
+};
+#define MC8200_BADIPL  0x01
+#define MC8200_UERR    0x02
+#define MC8200_UPAR    0x04
+#define MC8200_DPAR    0x08
+#define MC8200_BIERR   0x10
+#define MC8200_BTAGPAR 0x20
+#define MC8200_CTAGPAR 0x40
+
+struct mc8200frame {
+       int     mc82_bcnt;              /* byte count == 0x20 */
+       int     mc82_summary;           /* summary parameter */
+       int     mc82_param1;            /* parameter 1 */
+       int     mc82_va;                /* va register */
+       int     mc82_vap;               /* va prime register */
+       int     mc82_ma;                /* memory address */
+       int     mc82_status;            /* status word */
+       int     mc82_epc;               /* error pc */
+       int     mc82_upc;               /* micro pc */
+       int     mc82_pc;                /* current pc */
+       int     mc82_psl;               /* current psl */
+};
+
+int
+ka820_mchk(cmcf)
+       caddr_t cmcf;
+{
+       register struct mc8200frame *mcf = (struct mc8200frame *)cmcf;
+       register int i, type = mcf->mc82_summary;
+
+       /* ignore BI bus errors during configuration */
+       if (cold && type == MC8200_BIERR) {
+               mtpr(PR_MCESR, 0xf);
+               return (MCHK_RECOVERED);
+       }
+
+       /*
+        * SOME ERRORS ARE RECOVERABLE
+        * do it later
+        */
+       printf("machine check %x: ", type);
+       for (i = 0; i < sizeof (mc8200) / sizeof (mc8200[0]); i++)
+               if (type & (1 << i))
+                       printf(" %s,", mc8200[i]);
+       printf(" param1 %x\n", mcf->mc82_param1);
+       printf(
+"\tva %x va' %x ma %x pc %x psl %x\n\tstatus %x errpc %x upc %x\n",
+               mcf->mc82_va, mcf->mc82_vap, mcf->mc82_ma,
+               mcf->mc82_pc, mcf->mc82_psl,
+               mcf->mc82_status, mcf->mc82_epc, mcf->mc82_upc);
+       return (MCHK_PANIC);
+}
+
+/*
+ * Receive a character from logical console.
+ */
+rxcdintr()
+{
+       register int c = mfpr(PR_RXCD);
+
+       /* not sure what (if anything) to do with these */
+       printf("rxcd node %x c=0x%x\n", (c >> 8) & 0xf, c & 0xff);
+}
index b41b228..43cb009 100644 (file)
@@ -1,4 +1,4 @@
-/*     $NetBSD: ka860.c,v 1.3 1996/04/08 18:32:45 ragge Exp $  */
+/*     $NetBSD: ka860.c,v 1.6 1996/10/13 03:35:53 christos Exp $       */
 /*
  * Copyright (c) 1986, 1988 Regents of the University of California.
  * All rights reserved.
 #include <machine/mtpr.h>
 #include <machine/nexus.h>
 #include <machine/ioa.h>
+#include <machine/sid.h>
 
 struct ioa *ioa; 
 
 /* XXX These are in autoconf.c also */
 void   ka86_conf __P((struct device *, struct device *, void *));
-int    ka86_clock __P((void));
 void   ka86_memenable __P((struct sbi_attach_args *, struct device *));
 void   ka86_memerr __P((void));
 int    ka86_mchk __P((caddr_t));
-void    ka86_steal_pages __P((void));
+void   ka86_steal_pages __P((void));
 
 void   crlattach __P((void));
 
 /*
  * 8600 memory register (MERG) bit definitions
  */
-#define        M8600_ICRD      0x400           /* inhibit crd interrupts */
+#define M8600_ICRD     0x400           /* inhibit crd interrupts */
 #define M8600_TB_ERR   0xf00           /* translation buffer error mask */
 
 /*
  * MDECC register
  */
-#define        M8600_ADDR_PE   0x080000        /* address parity error */
+#define M8600_ADDR_PE  0x080000        /* address parity error */
 #define M8600_DBL_ERR  0x100000        /* data double bit error */
-#define        M8600_SNG_ERR   0x200000        /* data single bit error */
-#define        M8600_BDT_ERR   0x400000        /* bad data error */
+#define M8600_SNG_ERR  0x200000        /* data single bit error */
+#define M8600_BDT_ERR  0x400000        /* bad data error */
 
 /*
  * ESPA register is used to address scratch pad registers in the Ebox.
@@ -88,7 +88,7 @@ void  crlattach __P((void));
  * The scratchpad registers that are supplied for a single bit ECC 
  * error are:
  */
-#define        SPAD_MSTAT1     0x25            /* scratch pad mstat1 register  */
+#define SPAD_MSTAT1    0x25            /* scratch pad mstat1 register  */
 #define SPAD_MSTAT2    0x26            /* scratch pad mstat2 register  */
 #define SPAD_MDECC     0x27            /* scratch pad mdecc register   */
 #define SPAD_MEAR      0x2a            /* scratch pad mear register    */
@@ -124,7 +124,7 @@ ka86_memenable(sa, dev)
 void
 ka86_memerr()
 {
-       register int reg11 = 0; /* known to be r11 below */
+       register int reg11 = 0; /* known to be r11 below */
        int mdecc, mear, mstat1, mstat2, array;
 
        /*
@@ -161,25 +161,25 @@ ka86_memerr()
        }
 }
 
-#define NMC8600        7
+#define NMC8600 7
 char *mc8600[] = {
        "unkn type",    "fbox error",   "ebox error",   "ibox error",
        "mbox error",   "tbuf error",   "mbox 1D error"
 };
 /* codes for above */
-#define        MC_FBOX         1
-#define        MC_EBOX         2
-#define        MC_IBOX         3
-#define        MC_MBOX         4
-#define        MC_TBUF         5
-#define        MC_MBOX1D       6
+#define MC_FBOX                1
+#define MC_EBOX                2
+#define MC_IBOX                3
+#define MC_MBOX                4
+#define MC_TBUF                5
+#define MC_MBOX1D      6
 
 /* error bits */
-#define        MBOX_FE         0x8000          /* Mbox fatal error */
-#define        FBOX_SERV       0x10000000      /* Fbox service error */
-#define        IBOX_ERR        0x2000          /* Ibox error */
-#define        EBOX_ERR        0x1e00          /* Ebox error */
-#define        MBOX_1D         0x81d0000       /* Mbox 1D error */
+#define MBOX_FE                0x8000          /* Mbox fatal error */
+#define FBOX_SERV      0x10000000      /* Fbox service error */
+#define IBOX_ERR       0x2000          /* Ibox error */
+#define EBOX_ERR       0x1e00          /* Ebox error */
+#define MBOX_1D                0x81d0000       /* Mbox 1D error */
 #define EDP_PE         0x200
 
 struct mc8600frame {
@@ -257,9 +257,9 @@ ka86_mchk(cmcf)
 void
 ka86_steal_pages()
 {
-       extern  vm_offset_t avail_start, virtual_avail;
-       extern  struct nexus *nexus;
-       int     junk;
+       extern  vm_offset_t avail_start, virtual_avail;
+       extern  struct nexus *nexus;
+       int     junk;
  
        /* 8600 may have 2 SBI's == 4 pages */
        MAPPHYS(junk, 4, VM_PROT_READ|VM_PROT_WRITE);
@@ -293,11 +293,11 @@ struct ka86 {
 
 void
 ka86_conf(parent, self, aux)
-       struct  device *parent, *self;
-       void    *aux;
+       struct  device *parent, *self;
+       void    *aux;
 {
-       extern  char cpu_model[];
-       struct  ka86 *ka86 = (void *)&cpu_type;
+       extern  char cpu_model[];
+       struct  ka86 *ka86 = (void *)&vax_cpudata;
 
        /* Enable cache */
        mtpr(3, PR_CSWP);
@@ -316,12 +316,3 @@ ka86_conf(parent, self, aux)
                printf("no FPA\n");
        crlattach();
 }
-
-int   
-ka86_clock()
-{
-       mtpr(-10000, PR_NICR); /* Load in count register */
-       mtpr(0x800000d1, PR_ICCS); /* Start clock and enable interrupt */
-       return 0; 
-}
-
index 100dd6b..443f7b5 100644 (file)
@@ -1,5 +1,4 @@
-/*     $NetBSD: locore.c,v 1.15 1996/05/19 16:44:07 ragge Exp $        */
-
+/*     $NetBSD: locore.c,v 1.17 1996/08/20 14:13:54 ragge Exp $        */
 /*
  * Copyright (c) 1994 Ludd, University of Lule}, Sweden.
  * All rights reserved.
 #include <machine/vmparam.h>
 #include <machine/pcb.h>
 #include <machine/pmap.h>
+#include <machine/nexus.h>
 
 void   start __P((void));
 void   main __P((void));
 
 u_int  proc0paddr;
-int    cpunumber, *Sysmap, boothowto, cpu_type;
+int    *Sysmap, boothowto;
 char   *esym;
 extern int bootdev;
 
+/* 
+ * We set up some information about the machine we're
+ * running on and thus initializes/uses vax_cputype and vax_boardtype.
+ * There should be no need to change/reinitialize these variables
+ * outside of this routine, they should be read only!
+ */
+int vax_cputype;       /* highest byte of SID register */
+int vax_bustype;       /* holds/defines all busses on this machine */
+int vax_boardtype;     /* machine dependend, combination of SID and SIE */
+int vax_systype;       /* machine dependend identification of the system */
+int vax_cpudata;       /* contents of the SID register */
+int vax_siedata;       /* contents of the SIE register */
+int vax_confdata;      /* machine dependend, configuration/setup data */
+
 /*
  * Start is called from boot; the first routine that is called
  * in kernel. Kernel stack is setup somewhere in a safe place;
@@ -116,11 +131,11 @@ tokmem: movw      $0xfff, _panic
        Sysmap = (u_int *)ROUND_PAGE(mfpr(PR_KSP));
 
        /* Be sure some important internal registers have safe values */
-        ((struct pcb *)proc0paddr)->P0LR = 0;
-        ((struct pcb *)proc0paddr)->P0BR = (void *)0x80000000;
-        ((struct pcb *)proc0paddr)->P1LR = 0;
-        ((struct pcb *)proc0paddr)->P1BR = (void *)0x80000000;
-        ((struct pcb *)proc0paddr)->iftrap = NULL;
+       ((struct pcb *)proc0paddr)->P0LR = 0;
+       ((struct pcb *)proc0paddr)->P0BR = (void *)0x80000000;
+       ((struct pcb *)proc0paddr)->P1LR = 0;
+       ((struct pcb *)proc0paddr)->P1BR = (void *)0x80000000;
+       ((struct pcb *)proc0paddr)->iftrap = NULL;
        mtpr(0, PR_P0LR);
        mtpr(0x80000000, PR_P0BR);
        mtpr(0, PR_P1LR);
@@ -129,13 +144,73 @@ tokmem: movw      $0xfff, _panic
        mtpr(0, PR_SCBB); /* SCB at physical addr  */
        mtpr(0, PR_ESP); /* Must be zero, used in page fault routine */
        mtpr(AST_NO, PR_ASTLVL);
-       
-       cninit();
 
        /* Count up memory etc... early machine dependent routines */
-       if ((cpunumber = MACHID(mfpr(PR_SID))) > VAX_MAX)
-               cpunumber = 0;
-       cpu_type = mfpr(PR_SID);
+       vax_cputype = ((vax_cpudata = mfpr(PR_SID)) >> 24);
+
+       switch (vax_cputype) {
+#if VAX780
+       case VAX_TYP_780:
+               vax_bustype = VAX_SBIBUS | VAX_CPUBUS;
+               vax_boardtype = VAX_BTYP_780;
+               break;
+#endif
+#if VAX750
+       case VAX_TYP_750:
+               vax_bustype = VAX_CMIBUS | VAX_CPUBUS;
+               vax_boardtype = VAX_BTYP_750;
+               break;
+#endif
+#if VAX8600
+       case VAX_TYP_790:
+               vax_bustype = VAX_CPUBUS | VAX_MEMBUS;
+               vax_boardtype = VAX_BTYP_790;
+               break;
+#endif
+#if VAX630 || VAX650 || VAX410 || VAX43
+       case VAX_TYP_UV2:
+       case VAX_TYP_CVAX:
+       case VAX_TYP_RIGEL:
+               vax_siedata = *(int *)(0x20040004);     /* SIE address */
+               vax_boardtype = (vax_cputype<<24) | ((vax_siedata>>24)&0xFF);
+
+               switch (vax_boardtype) {
+               case VAX_BTYP_410:
+               case VAX_BTYP_43:
+                       vax_confdata = *(int *)(0x20020000);
+                       vax_bustype = VAX_VSBUS | VAX_CPUBUS;
+                       break;
+
+               case VAX_BTYP_630:
+               case VAX_BTYP_650:
+                       vax_bustype = VAX_UNIBUS | VAX_CPUBUS;
+                       break;
+
+               default:
+                       break;
+               }
+               break;
+#endif
+#if VAX8200
+       case VAX_TYP_8SS:
+               vax_boardtype = VAX_BTYP_8000;
+               vax_bustype = VAX_BIBUS;
+               mastercpu = mfpr(PR_BINID);
+               break;
+#endif
+       default:
+               /* CPU not supported, just give up */
+               asm("halt");
+       }
+
+       /*
+        * before doing anything else, we need to setup the console
+        * so that output (eg. debug and error messages) are visible.
+        * They way console-output is done is different for different
+        * VAXen, thus vax_cputype and vax_boardtype are setup/used.
+        */
+       cninit();
+
        pmap_bootstrap();
 
        ((struct pcb *)proc0paddr)->framep = scratch;
index 53cbc17..1935d85 100644 (file)
@@ -1,4 +1,5 @@
-/* $NetBSD: machdep.c,v 1.30 1996/05/19 16:44:13 ragge Exp $  */
+/* $OpenBSD: machdep.c,v 1.10 1997/01/15 23:25:17 maja Exp $ */
+/* $NetBSD: machdep.c,v 1.35 1997/01/11 11:31:26 ragge Exp $  */
 
 /*
  * Copyright (c) 1994 Ludd, University of Lule}, Sweden.
@@ -23,7 +24,7 @@
  * 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.
+ *     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.
@@ -119,45 +120,44 @@ extern int virtual_avail, virtual_end;
  * We do these external declarations here, maybe they should be done
  * somewhere else...
  */
-int             nmcr, nmba, numuba, cold = 1;
-caddr_t         mcraddr[MAXNMCR];
-int             astpending;
-int             want_resched;
-char            machine[] = "vax";
-char            cpu_model[100];
-int             msgbufmapped = 0;
+int            nmcr, nmba, numuba, cold = 1;
+caddr_t                mcraddr[MAXNMCR];
+int            astpending;
+int            want_resched;
+char           machine[] = "vax";
+char           cpu_model[100];
+int            msgbufmapped = 0;
 struct msgbuf  *msgbufp;
-int             physmem;
+int            physmem;
 struct cfdriver nexuscd;
-int             todrstopped = 0, glurg;
-int             dumpsize = 0;
+int            todrstopped = 0, glurg;
+int            dumpsize = 0;
 
 caddr_t allocsys __P((caddr_t));
 
 #define valloclim(name, type, num, lim) \
                (name) = (type *)v; v = (caddr_t)((lim) = ((name)+(num)))
 
-#ifdef  BUFPAGES
-int             bufpages = BUFPAGES;
+#ifdef BUFPAGES
+int            bufpages = BUFPAGES;
 #else
-int             bufpages = 0;
+int            bufpages = 0;
 #endif
-int             nswbuf = 0;
-#ifdef  NBUF
-int             nbuf = NBUF;
+int            nswbuf = 0;
+#ifdef NBUF
+int            nbuf = NBUF;
 #else
-int             nbuf = 0;
+int            nbuf = 0;
 #endif
 
 void
 cpu_startup()
 {
-       caddr_t         v;
-       extern char     version[];
-       int             base, residual, i, sz;
-       vm_offset_t     minaddr, maxaddr;
-       vm_size_t       size;
-       extern int      cpu_type, boothowto;
+       caddr_t         v;
+       extern char     version[];
+       int             base, residual, i, sz;
+       vm_offset_t     minaddr, maxaddr;
+       vm_size_t       size;
        extern unsigned int avail_end;
 
        /*
@@ -166,7 +166,7 @@ cpu_startup()
        msgbufmapped = 1;
 
 #if VAX750 || VAX650
-       if (cpunumber == VAX_750 || cpunumber == VAX_650)
+       if (vax_cputype == VAX_750 || vax_cputype == VAX_650)
                if (!mfpr(PR_TODR))
                        mtpr(todrstopped = 1, PR_TODR);
 #endif
@@ -194,7 +194,7 @@ cpu_startup()
                panic("startup: table size inconsistency");
 
        /*
-        * Now allocate buffers proper.  They are different than the above in
+        * Now allocate buffers proper.  They are different than the above in
         * that they usually occupy more virtual memory than physical.
         */
        size = MAXBSIZE * nbuf;
@@ -211,12 +211,12 @@ cpu_startup()
        base = bufpages / nbuf;
        residual = bufpages % nbuf;
        for (i = 0; i < nbuf; i++) {
-               vm_size_t       curbufsize;
-               vm_offset_t     curbuf;
+               vm_size_t       curbufsize;
+               vm_offset_t     curbuf;
 
                /*
                 * First <residual> buffers get (base+1) physical pages
-                * allocated for them.  The rest get (base) physical pages.
+                * allocated for them.  The rest get (base) physical pages.
                 * 
                 * The rest of each buffer occupies virtual space, but has no
                 * physical memory allocated for it.
@@ -235,7 +235,7 @@ cpu_startup()
                                 16 * NCARGS, TRUE);
 
        /*
-        * Finally, allocate mbuf pool.  Since mclrefcnt is an off-size we
+        * Finally, allocate mbuf pool.  Since mclrefcnt is an off-size we
         * use the more space efficient malloc in place of kmem_alloc.
         */
        mclrefcnt = (char *) malloc(NMBCLUSTERS + CLBYTES / MCLBYTES,
@@ -243,6 +243,13 @@ cpu_startup()
        bzero(mclrefcnt, NMBCLUSTERS + CLBYTES / MCLBYTES);
        mb_map = kmem_suballoc(kernel_map, (vm_offset_t *) & mbutl, &maxaddr,
                               VM_MBUF_SIZE, FALSE);
+
+       /*
+        * Allocate a submap for physio
+        */
+       phys_map = kmem_suballoc(kernel_map, &minaddr, &maxaddr,
+           VM_PHYS_SIZE, TRUE);
+
        /*
         * Initialize callouts
         */
@@ -290,7 +297,7 @@ allocsys(v)
 {
 
 #define valloc(name, type, num) \
-            v = (caddr_t)(((name) = (type *)v) + (num))
+           v = (caddr_t)(((name) = (type *)v) + (num))
 
 #ifdef REAL_CLISTS
        valloc(cfree, struct cblock, nclist);
@@ -338,14 +345,14 @@ allocsys(v)
        return v;
 }
 
-long    dumplo = 0;
+long   dumplo = 0;
 long   dumpmag = 0x8fca0101;
 
 void
 dumpconf()
 {
-       int             nblks;
-       extern int      dumpdev;
+       int             nblks;
+       extern int      dumpdev;
 
        /*
         * XXX include the final RAM page which is not included in physmem.
@@ -369,7 +376,7 @@ dumpconf()
 void
 cpu_initclocks()
 {
-       (cpu_calls[cpunumber].cpu_clock) ();
+       (cpu_calls[vax_cputype].cpu_clock) ();
 }
 
 int
@@ -380,7 +387,6 @@ cpu_sysctl(a, b, c, d, e, f, g)
        size_t  *d, f;
        struct  proc *g;
 {
-       printf("cpu_sysctl:\n");
        return (EOPNOTSUPP);
 }
 
@@ -443,7 +449,7 @@ struct trampframe {
        unsigned        sig;    /* Signal number */
        unsigned        code;   /* Info code */
        unsigned        scp;    /* Pointer to struct sigcontext */
-       unsigned        r0, r1, r2, r3, r4, r5; /* Registers saved when
+       unsigned        r0, r1, r2, r3, r4, r5; /* Registers saved when
                                                 * interrupt */
        unsigned        pc;     /* Address of signal handler */
        unsigned        arg;    /* Pointer to first (and only) sigreturn
@@ -452,17 +458,17 @@ struct trampframe {
 
 void
 sendsig(catcher, sig, mask, code)
-       sig_t           catcher;
-       int             sig, mask;
-       u_long          code;
+       sig_t           catcher;
+       int             sig, mask;
+       u_long          code;
 {
-       struct  proc    *p = curproc;
+       struct  proc    *p = curproc;
        struct  sigacts *psp = p->p_sigacts;
        struct  trapframe *syscf;
        struct  sigcontext *sigctx;
        struct  trampframe *trampf;
        unsigned        cursp;
-       int     oonstack = psp->ps_sigstk.ss_flags & SS_ONSTACK;
+       int     oonstack = psp->ps_sigstk.ss_flags & SS_ONSTACK;
        extern  char sigcode[], esigcode[];
        /*
         * Allocate and validate space for the signal handler context. Note
@@ -531,8 +537,9 @@ int waittime = -1;
 static volatile int showto; /* Must be volatile to survive MM on -> MM off */
 
 void
-boot(howto)
+boot(howto, bootstr)
        register howto;
+       char *bootstr;
 {
        showto = howto;
        if ((howto & RB_NOSYNC) == 0 && waittime < 0) {
@@ -574,14 +581,14 @@ boot(howto)
 
                asm("movl %0,r5":: "g" (showto)); /* How to boot */
 
-               switch (cpunumber) {
+               switch (vax_cputype) {
                        int     state;
 
 #if VAX750 || VAX780 || VAX630
                case VAX_780:
                case VAX_750:
-               case VAX_630:
-                       mtpr(GC_BOOT, PR_TXDB); /* boot command */
+               case VAX_TYP_UV2:
+                       mtpr(GC_BOOT, PR_TXDB); /* boot command */
                        break;
 #endif
 #if VAX8600
@@ -642,16 +649,16 @@ void
 machinecheck(frame)
        caddr_t frame;
 {
-       if ((*cpu_calls[cpunumber].cpu_mchk) (frame) == 0)
+       if ((*cpu_calls[vax_cputype].cpu_mchk) (frame) == 0)
                return;
-       (*cpu_calls[cpunumber].cpu_memerr) ();
+       (*cpu_calls[vax_cputype].cpu_memerr) ();
        panic("machine check");
 }
 
 void
 dumpsys()
 {
-       extern int      dumpdev;
+       extern int      dumpdev;
 
        msgbufmapped = 0;
        if (dumpdev == NODEV)
@@ -692,7 +699,7 @@ dumpsys()
 
 int
 fuswintr(addr)
-       caddr_t addr;
+       const void *addr;
 {
        panic("fuswintr: need to be implemented");
        return 0;
@@ -701,8 +708,8 @@ fuswintr(addr)
 
 int
 suibyte(base, byte)
-       int byte;
        void *base;
+       short byte;
 {
        panic("suibyte: need to be implemented");
        return 0;
@@ -710,8 +717,8 @@ suibyte(base, byte)
 
 int
 suswintr(addr, cnt)
-       caddr_t addr;
-       u_int   cnt;
+       void *addr;
+       short   cnt;
 {
        panic("suswintr: need to be implemented");
        return 0;
@@ -772,7 +779,7 @@ int
 process_sstep(p, sstep)
        struct proc    *p;
 {
-       void           *ptr;
+       void           *ptr;
        struct trapframe *tf;
 
        if ((p->p_flag & P_INMEM) == 0)
@@ -792,5 +799,5 @@ process_sstep(p, sstep)
 void
 cmrerr()
 {
-       (*cpu_calls[cpunumber].cpu_memerr) ();
+       (*cpu_calls[vax_cputype].cpu_memerr) ();
 }
diff --git a/sys/arch/vax/vax/mscp.c b/sys/arch/vax/vax/mscp.c
deleted file mode 100644 (file)
index 427c025..0000000
+++ /dev/null
@@ -1,980 +0,0 @@
-/*     $NetBSD: mscp.c,v 1.9 1996/04/08 18:32:50 ragge Exp $   */
-
-/*
- * Copyright (c) 1988 Regents of the University of California.
- * All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Chris Torek.
- *
- * 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.
- *
- *     @(#)mscp.c      7.5 (Berkeley) 12/16/90
- */
-
-/*
- * MSCP generic driver routines
- */
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/buf.h>
-#include <sys/errno.h>
-#include <sys/dkstat.h>
-#include <sys/ioctl.h>
-#include <sys/disklabel.h>
-#include <sys/syslog.h>
-#include <sys/proc.h>
-
-#include <vax/uba/ubavar.h>
-
-#include <vax/vax/mscp.h>
-#include <vax/vax/mscpvar.h>
-
-void   mscp_hexdump __P((struct mscp *));
-
-
-
-
-#define        PCMD    PSWP            /* priority for command packet waits */
-
-/*
- * During transfers, mapping info is saved in the buffer's b_resid.
- */
-#define        b_info b_resid
-
-/*
- * Get a command packet.  Second argument is true iff we are
- * to wait if necessary.  Return NULL if none are available and
- * we cannot wait.
- */
-struct mscp *
-mscp_getcp(mi, canwait)
-       register struct mscp_info *mi;
-       int canwait;
-{
-#define        mri     (&mi->mi_cmd)
-       register struct mscp *mp;
-       register int i;
-       int s = splbio();
-
-again:
-       /*
-        * Ensure that we have some command credits, and
-        * that the next command packet is free.
-        */
-       if (mi->mi_credits <= MSCP_MINCREDITS) {
-               if (!canwait) {
-                       splx(s);
-                       return (NULL);
-               }
-               mi->mi_wantcredits = 1;
-               sleep((caddr_t) &mi->mi_wantcredits, PCMD);
-               goto again;
-       }
-       i = mri->mri_next;
-       if (mri->mri_desc[i] & MSCP_OWN) {
-               if (!canwait) {
-                       splx(s);
-                       return (NULL);
-               }
-               mi->mi_wantcmd = 1;
-               sleep((caddr_t) &mi->mi_wantcmd, PCMD);
-               goto again;
-       }
-       mi->mi_credits--;
-       mri->mri_desc[i] &= ~MSCP_INT;
-       mri->mri_next = (mri->mri_next + 1) % mri->mri_size;
-       splx(s);
-       mp = &mri->mri_ring[i];
-
-       /*
-        * Initialise some often-zero fields.
-        * ARE THE LAST TWO NECESSARY IN GENERAL?  IT SURE WOULD BE
-        * NICE IF DEC SOLD DOCUMENTATION FOR THEIR OWN CONTROLLERS.
-        */
-       mp->mscp_msglen = MSCP_MSGLEN;
-       mp->mscp_flags = 0;
-       mp->mscp_modifier = 0;
-       mp->mscp_seq.seq_bytecount = 0;
-       mp->mscp_seq.seq_buffer = 0;
-       mp->mscp_seq.seq_mapbase = 0;
-/*???*/        mp->mscp_sccc.sccc_errlgfl = 0;
-/*???*/        mp->mscp_sccc.sccc_copyspd = 0;
-       return (mp);
-#undef mri
-}
-
-#ifdef AVOID_EMULEX_BUG
-int    mscp_aeb_xor = 0x8000bb80;
-#endif
-
-/*
- * Do a device go.  The driver calls this once it has allocated
- * resources for the transfer.  Save the resource information in
- * bp->b_ubinfo, and finish the MSCP packet.
- *
- * N.B.: If we were blocked for some time, the drive could have gone
- * off line and might still be that way.  We should probably handle
- * such a case by changing this command into an on line request and
- * not dequeuing the transfer after all.
- */
-void
-mscp_go(mi, mp, info)
-       register struct mscp_info *mi;
-       register struct mscp *mp;
-       int info;
-{
-       register struct buf *bp, *dp;
-
-       /*
-        * Now is also the time to move the transfer off the
-        * controller and drive queues, and shuffle the drive
-        * queue on the controller queue.  The idea is to try
-        * to keep as many drives busy as possible---to deal
-        * the controller's credits out to the drives in a `fair
-        * share' arrangement.  (To do this fully would be more
-        * trouble than it is worth, though.)
-        */
-       dp = mi->mi_tab->b_actf;
-       bp = dp->b_actf;
-       dp->b_actf = bp->b_actf;        /* transfer off drive queue */
-       mi->mi_tab->b_actf = dp->b_hash.le_next;/* drive off ctlr queue */
-       MSCP_APPEND(dp, mi->mi_tab, b_hash.le_next);    /* then back again */
-
-#ifdef oldway
-       dp->b_actf = bp->av_forw;        /* transfer off drive queue */
-       mi->mi_tab->b_actf = dp->b_forw; /* drive off ctlr queue */
-       MSCP_APPEND(dp, mi->mi_tab, b_forw);     /* then back again */
-#endif
-
-       /*
-        * Move the buffer to the I/O wait queue.
-        */
-       {
-       struct buf *tmp;
-
-       bp->b_actf=&mi->mi_wtab;
-       if(mi->mi_wtab.b_actf==&mi->mi_wtab){
-               mi->mi_wtab.b_actf=bp;
-       } else {
-               tmp=mi->mi_wtab.b_actf;
-               while(tmp->b_actf!=&mi->mi_wtab) tmp=tmp->b_actf;
-               tmp->b_actf=bp;
-       }}
-
-#ifdef oldway
-       bp->av_back = mi->mi_wtab.av_back;
-       bp->av_forw = &mi->mi_wtab;
-       mi->mi_wtab.av_back->av_forw = bp;
-       mi->mi_wtab.av_back = bp;
-#endif
-
-       /*
-        * Save the mapping info, finish the command packet, and give
-        * it to the device.  The device's dgo routine should then
-        * initiate polling.
-        */
-       bp->b_info = info;
-#ifdef AVOID_EMULEX_BUG
-       /*
-        * The Emulex SC41/MS will occasionally zero the lower half word
-        * of the command reference number.  The upper half word remains
-        * intact.  To keep running, we convert the buffer address into
-        * a small but nonzero integer that is unique over all pending
-        * transfers, and store that value in the upper half word.  To
-        * catch occurrances of the bug (so that we can gripe to Emulex),
-        * we also put a nonzero value in the lower word.
-        */
-       {
-               register u_int i = mi->mi_nextbp;
-
-               do {            /* find a free value */
-                       if (mi->mi_bp[i] == 0)
-                               goto found;
-                       i = (i + 1) % AEB_MAX_BP;
-               } while (i != mi->mi_nextbp);
-               panic("mscp_go: AEB_MAX_BP too small");
-found:
-               mi->mi_bp[i++] = bp;
-               mi->mi_nextbp = i % AEB_MAX_BP;
-               mp->mscp_cmdref = (i << 16) ^ mscp_aeb_xor;
-       }
-#else
-       mp->mscp_cmdref = (long) bp;
-#endif
-       *mp->mscp_addr |= MSCP_OWN | MSCP_INT;
-}
-
-/*
- * Handle a response ring transition.
- */
-void
-mscp_dorsp(mi)
-       register struct mscp_info *mi;
-{
-       register struct uba_device *ui;
-       register struct buf *bp;
-       register struct mscp *mp;
-       register int nextrsp;
-       struct mscp_driver *md = mi->mi_md;
-       char *ctlrname, *drivename;
-       int st, error, info;
-
-       ctlrname = md->md_mname;
-       drivename = md->md_dname;
-       nextrsp = mi->mi_rsp.mri_next;
-loop:
-       if (mi->mi_rsp.mri_desc[nextrsp] & MSCP_OWN) {
-               /*
-                * No more responses.  Remember the next expected
-                * response index.  Check to see if we have some
-                * credits back, and wake up sleepers if so.
-                */
-               mi->mi_rsp.mri_next = nextrsp;
-               if (mi->mi_wantcredits && mi->mi_credits > MSCP_MINCREDITS) {
-                       mi->mi_wantcredits = 0;
-                       wakeup((caddr_t) &mi->mi_wantcredits);
-               }
-               return;
-       }
-
-       /*
-        * Found a response.  Update credit information.  If there is
-        * nothing else to do, jump to `done' to get the next response.
-        */
-       mp = &mi->mi_rsp.mri_ring[nextrsp];
-       mi->mi_credits += MSCP_CREDITS(mp->mscp_msgtc);
-       switch (MSCP_MSGTYPE(mp->mscp_msgtc)) {
-
-       case MSCPT_SEQ:
-               break;
-
-       case MSCPT_DATAGRAM:
-               (*md->md_dgram)(mi, mp);
-               goto done;
-
-       case MSCPT_CREDITS:
-               goto done;
-
-       case MSCPT_MAINTENANCE:
-       default:
-               printf("%s%d: unit %d: unknown message type 0x%x ignored\n",
-                       ctlrname, mi->mi_ctlr, mp->mscp_unit,
-                       MSCP_MSGTYPE(mp->mscp_msgtc));
-               goto done;
-       }
-
-       /*
-        * Controllers are allowed to interrupt as any drive, so we
-        * must check the command before checking for a drive.
-        */
-       if (mp->mscp_opcode == (M_OP_SETCTLRC | M_OP_END)) {
-               (*md->md_ctlrdone)(mi, mp);
-               goto done;
-       }
-
-       /*
-        * Find the drive info.  If there is none, and this is an
-        * available attention response, try configuring a new drive.
-        */
-       if (mp->mscp_unit > md->md_ndpc) {
-               printf("%s%d: unit %d out of range\n",
-                       ctlrname, mi->mi_ctlr, mp->mscp_unit);
-               goto done;
-       }
-       if ((ui = mi->mi_ip[mp->mscp_unit]) == NULL) {
-               if ((*md->md_unconf)(mi, mp) != MSCP_DONE) {
-                       printf("%s%d: unit %d not configured, ",
-                               ctlrname, mi->mi_ctlr, mp->mscp_unit);
-                       if (mp->mscp_opcode == M_OP_AVAILATTN)
-                               printf("available attn");
-                       else
-                               printf("stray response op 0x%x status 0x%x",
-                                       mp->mscp_opcode, mp->mscp_status);
-                       printf(" ignored\n");
-               }
-               goto done;
-       }
-
-       /*
-        * Handle individual responses.
-        */
-       st = mp->mscp_status & M_ST_MASK;
-       error = 0;
-       switch (mp->mscp_opcode) {
-
-       case M_OP_END:
-               /*
-                * The controller presents a bogus END packet when
-                * a read/write command is given with an illegal
-                * block number.  This is contrary to the MSCP
-                * specification (ENDs are to be given only for
-                * invalid commands), but that is the way of it.
-                */
-               if (st == M_ST_INVALCMD && mp->mscp_cmdref != 0) {
-                       printf("%s%d: bad lbn (%d)?\n", drivename,
-                               ui->ui_unit, (int)mp->mscp_seq.seq_lbn);
-                       error = EIO;
-                       goto rwend;
-               }
-               goto unknown;
-
-       case M_OP_ONLINE | M_OP_END:
-               /*
-                * Finished an ON LINE request.  Call the driver to
-                * find out whether it succeeded.  If so, mark it on
-                * line.
-                */
-               if (ui->ui_flags & UNIT_ONLINE) {
-                       printf("%s%d: duplicate ONLINE ignored\n",
-                               drivename, ui->ui_unit);
-                       break;
-               }
-               if ((*md->md_online)(ui, mp) == MSCP_DONE)
-                       ui->ui_flags |= UNIT_ONLINE;
-               break;
-
-       case M_OP_GETUNITST | M_OP_END:
-               /*
-                * Got unit status.  Call the driver to find out
-                * whether it succeeded, and if so, mark it.
-                */
-               if ((*md->md_gotstatus)(ui, mp) == MSCP_DONE)
-                       ui->ui_flags |= UNIT_HAVESTATUS;
-               break;
-
-       case M_OP_AVAILATTN:
-               /*
-                * The drive went offline and we did not notice.
-                * Mark it off line now, to force an on line request
-                * next, so we can make sure it is still the same
-                * drive.
-                *
-                * IF THE UDA DRIVER HAS A COMMAND AWAITING UNIBUS
-                * RESOURCES, THAT COMMAND MAY GO OUT BEFORE THE ON
-                * LINE.  IS IT WORTH FIXING??
-                */
-               ui->ui_flags &= ~(UNIT_ONLINE | UNIT_HAVESTATUS);
-#ifdef notyet
-               (*md->md_offline)(ui, mp);
-#endif
-               break;
-
-       case M_OP_READ | M_OP_END:
-       case M_OP_WRITE | M_OP_END:
-               /*
-                * A transfer finished.  Get the buffer, and release its
-                * map registers via ubadone().  If the command finished
-                * with an off line or available status, the drive went
-                * off line (the idiot controller does not tell us until
-                * it comes back *on* line, or until we try to use it).
-                */
-               if (mp->mscp_cmdref == 0) {
-                       /*
-                        * No buffer means there is a bug somewhere!
-                        */
-                       printf("%s%d: io done, but no buffer?\n",
-                               drivename, ui->ui_unit);
-                       mscp_hexdump(mp);
-                       break;
-               }
-
-rwend:
-#ifdef AVOID_EMULEX_BUG
-               {
-                       register u_short *p = (u_short *) &mp->mscp_cmdref;
-
-                       /*
-                        * Note any errors on the part of the controller.
-                        * The lower word should be zero after exclusive
-                        * or'ing with mscp_aeb_xor, and the upper should
-                        * then be in the range [1..AEB_MAX_BP].
-                        */
-                       mp->mscp_cmdref ^= mscp_aeb_xor;
-                       p[1]--;
-                       if (p[1] >= AEB_MAX_BP)
-                               panic("unrecoverable Emulex screwup");
-                       if (p[0] == 0)
-                               mi->mi_ok++;
-                       else {
-                               /*
-                                * Calculate the expected response,
-                                * assuming p[1] is correct.  The
-                                * actual response is then the expected
-                                * response xor p[0].
-                                */
-                               int sb = ((p[1] + 1) << 16) ^ mscp_aeb_xor;
-
-                               log(LOG_WARNING, "\
-Emulex SC41/MS screwup: %s%d, got %d correct, then changed 0x%x to 0x%x\n",
-                                       ctlrname, mi->mi_ctlr,
-                                       mi->mi_ok, sb, sb ^ p[0]);
-                               mi->mi_ok = 0;
-                       }
-                       /* convert index back to buffer, and mark free */
-                       bp = mi->mi_bp[p[1]];
-                       mi->mi_bp[p[1]] = 0;
-               }
-#else
-               bp = (struct buf *) mp->mscp_cmdref;
-#ifdef MSCP_PARANOIA
-               {
-                       register struct buf *q = mi->mi_wtab.av_forw;
-
-                       /*
-                        * Ensure that this response corresponds to
-                        * some outstanding request.  If not, ignore
-                        * it entirely.  This will likely cause a
-                        * Unibus reset soon, after which the controller
-                        * just might behave.
-                        */
-                       while (q != bp && q != &mi->mi_wtab)
-                               q = q->av_forw;
-                       if (q != bp) {
-                               printf("%s%d: bad response packet ignored\n",
-                                       ctlrname, mi->mi_ctlr);
-                               mscp_hexdump(mp);
-                               goto out;
-                       }
-               }
-#endif MSCP_PARANOIA
-#endif AVOID_EMULEX_BUG
-
-               /*
-                * Mark any error-due-to-bad-LBN (via `goto rwend').
-                * WHAT STATUS WILL THESE HAVE?  IT SURE WOULD BE NICE
-                * IF DEC SOLD DOCUMENTATION FOR THEIR OWN CONTROLLERS.
-                */
-               if (error) {
-                       bp->b_flags |= B_ERROR;
-                       bp->b_error = error;
-               }
-               if (st == M_ST_OFFLINE || st == M_ST_AVAILABLE) {
-                       ui->ui_flags &= ~(UNIT_ONLINE | UNIT_HAVESTATUS);
-#ifdef notyet
-                       (*md->md_offline)(ui, mp);
-#endif
-               }
-
-               /*
-                * Unlink the transfer from the wait queue mi_wtab.
-                * If there are no more transfers on the drive queue
-                * for this drive, and it is a profiled disk, turn
-                * off its busy bit.
-                */
-
-
-               { /* Insane */
-               struct buf *tmp;
-
-               tmp=bp->b_actf;
-               if(!tmp){
-                       printf("Found 0 - bad!\n");
-                       asm("halt");
-               }
-               while(tmp->b_actf!=bp){
-                       if(!tmp){
-                               printf("Got lost in chains...\n");
-                               asm("halt");
-                       }
-                       tmp=tmp->b_actf;
-               }
-               tmp->b_actf=bp->b_actf;
-               }
-               if (ui->ui_dk >= 0 && md->md_utab[ui->ui_unit].b_hash.le_next == NULL)
-                       dk_busy &= ~(1 << ui->ui_dk);
-
-/* Was:                bp->av_back->av_forw = bp->av_forw;
-               bp->av_forw->av_back = bp->av_back;
-               if (ui->ui_dk >= 0 && md->md_utab[ui->ui_unit].b_forw == NULL)
-                       dk_busy &= ~(1 << ui->ui_dk);
-*/
-               /*
-                * If the transfer has something to do with bad
-                * block forwarding, let the driver handle the
-                * rest.
-                */
-               if ((bp->b_flags & B_BAD) != 0 && md->md_bb != NULL) {
-                       (*md->md_bb)(ui, mp, bp);
-                       goto out;
-               }
-
-               /*
-                * If the transfer failed, give the driver a crack
-                * at fixing things up.
-                */
-               if (st != M_ST_SUCCESS) {
-                       switch ((*md->md_ioerr)(ui, mp, bp)) {
-
-                       case MSCP_DONE:         /* fixed */
-                               break;
-
-                       case MSCP_RESTARTED:    /* still working on it */
-                               goto out;
-
-                       case MSCP_FAILED:       /* no luck */
-                               diskerr(bp, drivename, "hard error",
-                                   LOG_PRINTF, -1, md->md_lab ?
-                                   &md->md_lab[ui->ui_unit] : md->md_lab);
-                               mscp_printevent(mp);
-                               bp->b_flags |= B_ERROR;
-                               bp->b_error = EIO;
-                               break;
-                       }
-               }
-
-               /*
-                * Set the residual count and mark the transfer as
-                * done.  If the I/O wait queue is now empty, release
-                * the shared BDP, if any.
-                */
-               info = bp->b_info;      /* we are about to clobber it */
-               bp->b_resid = bp->b_bcount - mp->mscp_seq.seq_bytecount;
-               (*md->md_iodone)(mi, bp, info);
-out:
-               break;
-               
-       case M_OP_REPLACE | M_OP_END:
-               /*
-                * A replace operation finished.  Just let the driver
-                * handle it (if it does replaces).
-                */
-               if (md->md_replace == NULL)
-                       printf("%s%d: bogus REPLACE end\n",
-                               drivename, ui->ui_unit);
-               else
-                       (*md->md_replace)(ui, mp);
-               break;
-
-       default:
-               /*
-                * If it is not one of the above, we cannot handle it.
-                * (And we should not have received it, for that matter.)
-                */
-unknown:
-               printf("%s%d: unknown opcode 0x%x status 0x%x ignored\n",
-                       mi->mi_md->md_dname, ui->ui_unit,
-                       mp->mscp_opcode, mp->mscp_status);
-               mscp_hexdump(mp);
-               break;
-       }
-
-       /*
-        * If the drive needs to be put back in the controller queue,
-        * do that now.  (`bp' below ought to be `dp', but they are all
-        * struct buf *.)  Note that b_active was cleared in the driver;
-        * we presume that there is something to be done, hence reassert it.
-        */
-       if (ui->ui_flags & UNIT_REQUEUE) {
-               bp = &md->md_utab[ui->ui_unit];
-               if (bp->b_active) panic("mscp_dorsp requeue");
-               MSCP_APPEND(bp, mi->mi_tab, b_hash.le_next);
-/* Was:                MSCP_APPEND(bp, mi->mi_tab, b_forw); */
-               bp->b_active = 1;
-               ui->ui_flags &= ~UNIT_REQUEUE;
-       }
-
-done:
-       /*
-        * Give back the response packet, and take a look at the next.
-        */
-       mp->mscp_msglen = MSCP_MSGLEN;
-       mi->mi_rsp.mri_desc[nextrsp] |= MSCP_OWN;
-       nextrsp = (nextrsp + 1) % mi->mi_rsp.mri_size;
-       goto loop;
-}
-
-/*
- * Dump the entire contents of an MSCP packet in hex.  Mainly useful
- * for debugging....
- */
-void
-mscp_hexdump(mp)
-       register struct mscp *mp;
-{
-       register long *p = (long *) mp;
-       register int i = mp->mscp_msglen;
-
-       if (i > 256)            /* sanity */
-               i = 256;
-       i /= sizeof (*p);       /* ASSUMES MULTIPLE OF sizeof(long) */
-       while (--i >= 0)
-               printf("0x%x ", (int)*p++);
-       printf("\n");
-}
-
-/*
- * Requeue outstanding transfers, e.g., after bus reset.
- * Also requeue any drives that have on line or unit status
- * info pending.
- */
-void
-mscp_requeue(mi)
-       struct mscp_info *mi;
-{
-       register struct uba_device *ui;
-       register struct mscp_driver *md = mi->mi_md;
-       register struct buf *bp, *dp;
-       register int unit;
-       struct buf *nextbp;
-
-       /*
-        * Clear the controller chain.  Mark everything un-busy; we
-        * will soon fix any that are in fact busy.
-        */
-       mi->mi_tab->b_actf = NULL;
-       mi->mi_tab->b_active = 0;
-       for (unit = 0, dp = md->md_utab; unit < md->md_nunits; unit++, dp++) {
-               ui = md->md_dinfo[unit];
-               if (ui == NULL || !ui->ui_alive || ui->ui_ctlr != mi->mi_ctlr)
-                       continue;       /* not ours */
-               dp->b_hash.le_next = NULL;
-               dp->b_active = 0;
-       }
-
-       /*
-        * Scan the wait queue, linking buffers onto drive queues.
-        * Note that these must be put at the front of the drive queue,
-        * lest we reorder I/O operations.
-        */
-       for (bp = *mi->mi_wtab.b_actb; bp != &mi->mi_wtab; bp = nextbp) {
-               nextbp = *bp->b_actb;
-               dp = &md->md_utab[minor(bp->b_dev) >> md->md_unitshift];
-               bp->b_actf = dp->b_actf;
-               if (dp->b_actf == NULL)
-                       dp->b_actb = (void *)bp;
-               dp->b_actf = bp;
-       }
-       mi->mi_wtab.b_actf = *mi->mi_wtab.b_actb = &mi->mi_wtab;
-
-       /*
-        * Scan for drives waiting for on line or status responses,
-        * and for drives with pending transfers.  Put these on the
-        * controller queue, and mark the controller busy.
-        */
-       for (unit = 0, dp = md->md_utab; unit < md->md_nunits; unit++, dp++) {
-               ui = md->md_dinfo[unit];
-               if (ui == NULL || !ui->ui_alive || ui->ui_ctlr != mi->mi_ctlr)
-                       continue;
-               ui->ui_flags &= ~(UNIT_HAVESTATUS | UNIT_ONLINE);
-               if ((ui->ui_flags & UNIT_REQUEUE) == 0 && dp->b_actf == NULL)
-                       continue;
-               ui->ui_flags &= ~UNIT_REQUEUE;
-               MSCP_APPEND(dp, mi->mi_tab, b_hash.le_next);
-
-               dp->b_active = 1;
-               mi->mi_tab->b_active = 1;
-       }
-
-#ifdef AVOID_EMULEX_BUG
-       /*
-        * ... and clear the index-to-buffer table.
-        */
-       for (unit = 0; unit < AEB_MAX_BP; unit++)
-               mi->mi_bp[unit] = 0;
-#endif
-}
-
-
-/*
- * MSCP error reporting
- */
-
-/*
- * Messages for the various subcodes.
- */
-static char unknown_msg[] = "unknown subcode";
-
-/*
- * Subcodes for Success (0)
- */
-static char *succ_msgs[] = {
-       "normal",               /* 0 */
-       "spin down ignored",    /* 1 = Spin-Down Ignored */
-       "still connected",      /* 2 = Still Connected */
-       unknown_msg,
-       "dup. unit #",          /* 4 = Duplicate Unit Number */
-       unknown_msg,
-       unknown_msg,
-       unknown_msg,
-       "already online",       /* 8 = Already Online */
-       unknown_msg,
-       unknown_msg,
-       unknown_msg,
-       unknown_msg,
-       unknown_msg,
-       unknown_msg,
-       unknown_msg,
-       "still online",         /* 16 = Still Online */
-};
-
-/*
- * Subcodes for Invalid Command (1)
- */
-static char *icmd_msgs[] = {
-       "invalid msg length",   /* 0 = Invalid Message Length */
-};
-
-/*
- * Subcodes for Command Aborted (2)
- */
-/* none known */
-
-/*
- * Subcodes for Unit Offline (3)
- */
-static char *offl_msgs[] = {
-       "unknown drive",        /* 0 = Unknown, or online to other ctlr */
-       "not mounted",          /* 1 = Unmounted, or RUN/STOP at STOP */
-       "inoperative",          /* 2 = Unit Inoperative */
-       unknown_msg,
-       "duplicate",            /* 4 = Duplicate Unit Number */
-       unknown_msg,
-       unknown_msg,
-       unknown_msg,
-       "in diagnosis",         /* 8 = Disabled by FS or diagnostic */
-};
-
-/*
- * Subcodes for Unit Available (4)
- */
-/* none known */
-
-/*
- * Subcodes for Media Format Error (5)
- */
-static char *media_fmt_msgs[] = {
-       "fct unread - edc",     /* 0 = FCT unreadable */
-       "invalid sector header",/* 1 = Invalid Sector Header */
-       "not 512 sectors",      /* 2 = Not 512 Byte Sectors */
-       "not formatted",        /* 3 = Not Formatted */
-       "fct ecc",              /* 4 = FCT ECC */
-};
-
-/*
- * Subcodes for Write Protected (6)
- * N.B.:  Code 6 subcodes are 7 bits higher than other subcodes
- * (i.e., bits 12-15).
- */
-static char *wrprot_msgs[] = {
-       unknown_msg,
-       "software",             /* 1 = Software Write Protect */
-       "hardware",             /* 2 = Hardware Write Protect */
-};
-
-/*
- * Subcodes for Compare Error (7)
- */
-/* none known */
-
-/*
- * Subcodes for Data Error (8)
- */
-static char *data_msgs[] = {
-       "forced error",         /* 0 = Forced Error (software) */
-       unknown_msg,
-       "header compare",       /* 2 = Header Compare Error */
-       "sync timeout",         /* 3 = Sync Timeout Error */
-       unknown_msg,
-       unknown_msg,
-       unknown_msg,
-       "uncorrectable ecc",    /* 7 = Uncorrectable ECC */
-       "1 symbol ecc",         /* 8 = 1 bit ECC */
-       "2 symbol ecc",         /* 9 = 2 bit ECC */
-       "3 symbol ecc",         /* 10 = 3 bit ECC */
-       "4 symbol ecc",         /* 11 = 4 bit ECC */
-       "5 symbol ecc",         /* 12 = 5 bit ECC */
-       "6 symbol ecc",         /* 13 = 6 bit ECC */
-       "7 symbol ecc",         /* 14 = 7 bit ECC */
-       "8 symbol ecc",         /* 15 = 8 bit ECC */
-};
-
-/*
- * Subcodes for Host Buffer Access Error (9)
- */
-static char *host_buffer_msgs[] = {
-       unknown_msg,
-       "odd xfer addr",        /* 1 = Odd Transfer Address */
-       "odd xfer count",       /* 2 = Odd Transfer Count */
-       "non-exist. memory",    /* 3 = Non-Existent Memory */
-       "memory parity",        /* 4 = Memory Parity Error */
-};
-
-/*
- * Subcodes for Controller Error (10)
- */
-static char *cntlr_msgs[] = {
-       unknown_msg,
-       "serdes overrun",       /* 1 = Serialiser/Deserialiser Overrun */
-       "edc",                  /* 2 = Error Detection Code? */
-       "inconsistant internal data struct",/* 3 = Internal Error */
-};
-
-/*
- * Subcodes for Drive Error (11)
- */
-static char *drive_msgs[] = {
-       unknown_msg,
-       "sdi command timeout",  /* 1 = SDI Command Timeout */
-       "ctlr detected protocol",/* 2 = Controller Detected Protocol Error */
-       "positioner",           /* 3 = Positioner Error */
-       "lost rd/wr ready",     /* 4 = Lost R/W Ready Error */
-       "drive clock dropout",  /* 5 = Lost Drive Clock */
-       "lost recvr ready",     /* 6 = Lost Receiver Ready */
-       "drive detected error", /* 7 = Drive Error */
-       "ctlr detected pulse or parity",/* 8 = Pulse or Parity Error */
-};
-
-/*
- * The following table correlates message codes with the
- * decoding strings.
- */
-struct code_decode {
-       char    *cdc_msg;
-       int     cdc_nsubcodes;
-       char    **cdc_submsgs;
-} code_decode[] = {
-#define        SC(m)   sizeof (m) / sizeof (m[0]), m
-       {"success",                     SC(succ_msgs)},
-       {"invalid command",             SC(icmd_msgs)},
-       {"command aborted",             0, 0},
-       {"unit offline",                SC(offl_msgs)},
-       {"unit available",              0, 0},
-       {"media format error",          SC(media_fmt_msgs)},
-       {"write protected",             SC(wrprot_msgs)},
-       {"compare error",               0, 0},
-       {"data error",                  SC(data_msgs)},
-       {"host buffer access error",    SC(host_buffer_msgs)},
-       {"controller error",            SC(cntlr_msgs)},
-       {"drive error",                 SC(drive_msgs)},
-#undef SC
-};
-
-/*
- * Print the decoded error event from an MSCP error datagram.
- */
-void
-mscp_printevent(mp)
-       struct mscp *mp;
-{
-       register int event = mp->mscp_event;
-       register struct code_decode *cdc;
-       int c, sc;
-       char *cm, *scm;
-
-       /*
-        * The code is the lower six bits of the event number (aka
-        * status).  If that is 6 (write protect), the subcode is in
-        * bits 12-15; otherwise, it is in bits 5-11.
-        * I WONDER WHAT THE OTHER BITS ARE FOR.  IT SURE WOULD BE
-        * NICE IF DEC SOLD DOCUMENTATION FOR THEIR OWN CONTROLLERS.
-        */
-       c = event & M_ST_MASK;
-       sc = (c != 6 ? event >> 5 : event >> 12) & 0x7ff;
-       if (c >= sizeof code_decode / sizeof code_decode[0])
-               cm = "- unknown code", scm = "??";
-       else {
-               cdc = &code_decode[c];
-               cm = cdc->cdc_msg;
-               if (sc >= cdc->cdc_nsubcodes)
-                       scm = unknown_msg;
-               else
-                       scm = cdc->cdc_submsgs[sc];
-       }
-       printf(" %s (%s) (code %d, subcode %d)\n", cm, scm, c, sc);
-}
-
-/*
- * Print the code and logical block number for an error packet.
- * THIS IS PROBABLY PECULIAR TO DISK DRIVES.  IT SURE WOULD BE
- * NICE IF DEC SOLD DOCUMENTATION FOR THEIR OWN CONTROLLERS.
- */
-void
-mscp_decodeerror(name, ctlr, mp)
-       char *name;
-       int ctlr;
-       register struct mscp *mp;
-{
-       /*
-        * For bad blocks, mp->mscp_erd.erd_hdr identifies a code and
-        * the logical block number.  Code 0 is a regular block; code 6
-        * is a replacement block.  The remaining codes are currently
-        * undefined.  The code is in the upper four bits of the header
-        * (bits 0-27 are the lbn).
-        */
-       int issoft = mp->mscp_flags & (M_LF_SUCC | M_LF_CONT);
-       static char *codemsg[16] = {
-               "lbn", "code 1", "code 2", "code 3",
-               "code 4", "code 5", "rbn", "code 7",
-               "code 8", "code 9", "code 10", "code 11",
-               "code 12", "code 13", "code 14", "code 15"
-       };
-#define BADCODE(h)     (codemsg[(unsigned)(h) >> 28])
-#define BADLBN(h)      ((h) & 0xfffffff)
-
-       printf("%s%d: %s error datagram%s:", name, ctlr,
-               issoft ? "soft" : "hard",
-               mp->mscp_flags & M_LF_CONT ? " (continuing)" : "");
-       switch (mp->mscp_format & 0377) {
-
-       case M_FM_CTLRERR:      /* controller error */
-               break;
-
-       case M_FM_BUSADDR:      /* host memory access error */
-               printf(" memory addr 0x%x:", (int)mp->mscp_erd.erd_busaddr);
-               break;
-
-       case M_FM_DISKTRN:
-               printf(" unit %d: level %d retry %d, %s %d:",
-                       mp->mscp_unit,
-                       mp->mscp_erd.erd_level, mp->mscp_erd.erd_retry,
-                       BADCODE(mp->mscp_erd.erd_hdr),
-                       (int)BADLBN(mp->mscp_erd.erd_hdr));
-               break;
-
-       case M_FM_SDI:
-               printf(" unit %d: %s %d:", mp->mscp_unit,
-                       BADCODE(mp->mscp_erd.erd_hdr),
-                       (int)BADLBN(mp->mscp_erd.erd_hdr));
-               break;
-
-       case M_FM_SMLDSK:
-               printf(" unit %d: small disk error, cyl %d:",
-                       mp->mscp_unit, mp->mscp_erd.erd_sdecyl);
-               break;
-
-       default:
-               printf(" unit %d: unknown error, format 0x%x:",
-                       mp->mscp_unit, mp->mscp_format);
-       }
-       mscp_printevent(mp);
-#undef BADCODE
-#undef BADLBN
-}
diff --git a/sys/arch/vax/vax/mscp.h b/sys/arch/vax/vax/mscp.h
deleted file mode 100644 (file)
index 1f53838..0000000
+++ /dev/null
@@ -1,473 +0,0 @@
-/*     $NetBSD: mscp.h,v 1.3 1995/10/20 13:51:56 ragge Exp $   */
-
-/*
- * Copyright (c) 1988 Regents of the University of California.
- * All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Chris Torek.
- *
- * 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.
- *
- *     @(#)mscp.h      7.5 (Berkeley) 6/28/90
- */
-
-/*
- * Definitions for the Mass Storage Control Protocol
- * I WISH I KNEW WHAT MORE OF THESE WERE.  IT SURE WOULD BE NICE
- * IF DEC SOLD DOCUMENTATION FOR THEIR OWN CONTROLLERS.
- */
-
-/*
- * Control message opcodes
- */
-#define        M_OP_ABORT      0x01    /* Abort command */
-#define        M_OP_GETCMDST   0x02    /* Get command status command */
-#define        M_OP_GETUNITST  0x03    /* Get unit status command */
-#define        M_OP_SETCTLRC   0x04    /* Set controller characteristics command */
-#define        M_OP_SEREX      0x07    /* Serious exception end message */
-#define        M_OP_AVAILABLE  0x08    /* Available command */
-#define        M_OP_ONLINE     0x09    /* Online command */
-#define        M_OP_SETUNITC   0x0a    /* Set unit characteristics command */
-#define        M_OP_DTACCPATH  0x0b    /* Determine access paths command */
-#define        M_OP_ACCESS     0x10    /* Access command */
-#define        M_OP_COMPCD     0x11    /* Compare controller data command */
-#define        M_OP_ERASE      0x12    /* Erase command */
-#define        M_OP_FLUSH      0x13    /* Flush command */
-#define        M_OP_REPLACE    0x14    /* Replace command */
-#define        M_OP_COMPHD     0x20    /* Compare host data command */
-#define        M_OP_READ       0x21    /* Read command */
-#define        M_OP_WRITE      0x22    /* Write command */
-#define        M_OP_POS        0x25    /* Positioning command */
-#define        M_OP_AVAILATTN  0x40    /* Available attention message */
-#define        M_OP_DUPUNIT    0x41    /* Duplicate unit number attention message */
-#define        M_OP_ACCPATH    0x42    /* Access path attention message */
-#define        M_OP_END        0x80    /* End message flag */
-
-
-/*
- * Generic command modifiers
- */
-#define        M_MD_EXPRS      0x8000  /* Express request */
-#define        M_MD_COMP       0x4000  /* Compare */
-#define        M_MD_CLSEX      0x2000  /* Clear serious exception */
-#define        M_MD_ERROR      0x1000  /* Force error */
-#define        M_MD_SCCHH      0x0800  /* Suppress caching (high speed) */
-#define        M_MD_SCCHL      0x0400  /* Suppress caching (low speed) */
-#define        M_MD_SECOR      0x0200  /* Suppress error correction */
-#define        M_MD_SEREC      0x0100  /* Suppress error recovery */
-#define        M_MD_SSHDW      0x0080  /* Suppress shadowing */
-#define        M_MD_WBKNV      0x0040  /* Write back (non-volatile) */
-#define        M_MD_WBKVL      0x0020  /* Write back (volatile) */
-#define        M_MD_WRSEQ      0x0010  /* Write shadow set one unit at a time */
-
-/*
- * AVAILABLE command modifiers
- */
-#define        M_AVM_ALLCD     0x0002  /* All class drivers */
-#define        M_AVM_SPINDOWN  0x0001  /* Spin down */
-
-/*
- * FLUSH command modifiers
- */
-#define        M_FLM_FLUSHENU  0x0001  /* Flush entire unit */
-#define        M_FLM_VOLATILE  0x0002  /* Volatile only */
-
-/*
- * GET UNIT STATUS command modifiers
- */
-#define        M_GUM_NEXTUNIT  0x0001  /* Next unit */
-
-/*
- * ONLINE command modifiers
- */
-#define        M_OLM_RIP       0x0001  /* Allow self destruction */
-#define        M_OLM_IGNMF     0x0002  /* Ignore media format error */
-
-/*
- * ONLINE and SET UNIT CHARACTERISTICS command modifiers
- */
-#define        M_OSM_ALTERHI   0x0020  /* Alter host identifier */
-#define        M_OSM_SHADOWSP  0x0010  /* Shadow unit specified */
-#define        M_OSM_CLEARWBL  0x0008  /* Clear write-back data lost */
-#define        M_OSM_SETWRPROT 0x0004  /* Set write protect */
-
-/*
- * REPLACE command modifiers
- */
-#define        M_RPM_PRIMARY   0x0001  /* Primary replacement block */
-
-/*
- * End message flags
- */
-#define        M_EF_BBLKR      0x80    /* Bad block reported */
-#define        M_EF_BBLKU      0x40    /* Bad block unreported */
-#define        M_EF_ERLOG      0x20    /* Error log generated */
-#define        M_EF_SEREX      0x10    /* Serious exception */
-
-/*
- * Controller flags
- */
-#define        M_CF_ATTN       0x80    /* Enable attention messages */
-#define        M_CF_MISC       0x40    /* Enable miscellaneous error log messages */
-#define        M_CF_OTHER      0x20    /* Enable other host's error log messages */
-#define        M_CF_THIS       0x10    /* Enable this host's error log messages */
-#define        M_CF_MLTHS      0x04    /* Multi-host */
-#define        M_CF_SHADW      0x02    /* Shadowing */
-#define        M_CF_576        0x01    /* 576 byte sectors */
-
-/*
- * Unit flags
- */
-#define        M_UF_REPLC      0x8000  /* Controller initiated bad block replacement */
-#define        M_UF_INACT      0x4000  /* Inactive shadow set unit */
-#define        M_UF_WRTPH      0x2000  /* Write protect (hardware) */
-#define        M_UF_WRTPS      0x1000  /* Write protect (software or volume) */
-#define        M_UF_SCCHH      0x8000  /* Suppress caching (high speed) */
-#define        M_UF_SCCHL      0x4000  /* Suppress caching (low speed) */
-#define        M_UF_RMVBL      0x0080  /* Removable media */
-#define        M_UF_WBKNV      0x0040  /* Write back (non-volatile) */
-#define        M_UF_576        0x0004  /* 576 byte sectors */
-#define        M_UF_CMPWR      0x0002  /* Compare writes */
-#define        M_UF_CMPRD      0x0001  /* Compare reads */
-
-/*
- * Error Log message format codes
- */
-#define        M_FM_CTLRERR    0x00    /* Controller error */
-#define        M_FM_BUSADDR    0x01    /* Host memory access error */
-#define        M_FM_DISKTRN    0x02    /* Disk transfer error */
-#define        M_FM_SDI        0x03    /* SDI error */
-#define        M_FM_SMLDSK     0x04    /* Small disk error */
-
-/*
- * Error Log message flags
- */
-#define        M_LF_SUCC       0x80    /* Operation successful */
-#define        M_LF_CONT       0x40    /* Operation continuing */
-#define        M_LF_SQNRS      0x01    /* Sequence number reset */
-
-/*
- * Status codes
- */
-#define        M_ST_MASK       0x1f    /* Status code mask */
-#define        M_ST_SUCCESS    0x00    /* Success */
-#define        M_ST_INVALCMD   0x01    /* Invalid command */
-#define        M_ST_ABORTED    0x02    /* Command aborted */
-#define        M_ST_OFFLINE    0x03    /* Unit offline */
-#define        M_ST_AVAILABLE  0x04    /* Unit available */
-#define        M_ST_MFMTERR    0x05    /* Media format error */
-#define        M_ST_WRPROT     0x06    /* Write protected */
-#define        M_ST_COMPERR    0x07    /* Compare error */
-#define        M_ST_DATAERR    0x08    /* Data error */
-#define        M_ST_HOSTBUFERR 0x09    /* Host buffer access error */
-#define        M_ST_CTLRERR    0x0a    /* Controller error */
-#define        M_ST_DRIVEERR   0x0b    /* Drive error */
-#define        M_ST_DIAG       0x1f    /* Message from an internal diagnostic */
-
-/*
- * Subcodes of M_ST_OFFLINE
- */
-#define        M_OFFLINE_UNKNOWN       (0 << 5) /* unknown or on other ctlr */
-#define        M_OFFLINE_UNMOUNTED     (1 << 5) /* unmounted or RUN/STOP at STOP */
-#define        M_OFFLINE_INOPERATIVE   (2 << 5) /* inoperative? */
-#define        M_OFFLINE_DUPLICATE     (4 << 5) /* duplicate unit number */
-#define        M_OFFLINE_INDIAGNOSTIC  (8 << 5) /* disabled by FS or diagnostic */
-
-/*
- * An MSCP packet begins with a header giving the length of
- * the entire packet (including the header itself)(?), two bytes
- * of device specific data, and the a whole bunch of variants
- * depending on message type.
- *
- * N.B.:  In most cases we distinguish between a `command' and
- * an `end' variant as well.  The command variant is that which
- * is given to the controller; the `end' variant is its response.
- */
-
-/*
- * Generic sequential message variant (command and response).
- */
-struct mscpv_seq {
-       long    seq_bytecount;          /* byte count */
-#define        seq_rbn         seq_bytecount   /* aka RBN (replace) */
-#define        seq_outref      seq_bytecount   /* aka outref (abort/get cmd status) */
-       long    seq_buffer;             /* buffer descriptor */
-       long    seq_mapbase;            /* page map (first PTE) phys address */
-       long    seq_xxx1;       /* ? */ /* unused */
-       long    seq_lbn;                /* logical block number */
-       long    seq_xxx2;       /* ? */ /* unused */
-       long    *seq_addr;              /* pointer to cmd descriptor */
-       long    seq_software[4];        /* reserved to software; unused */
-};
-
-/*
- * Set Controller Characteristics command variant
- */
-struct mscpv_sccc {
-       u_short sccc_version;           /* MSCP version number */
-       u_short sccc_ctlrflags;         /* controller flags */
-       u_short sccc_hosttimo;          /* host timeout */
-       u_short sccc_usefrac;           /* use fraction */
-       long    sccc_time;              /* time and date */
-       long    sccc_xxx1;      /* ? */
-       long    sccc_errlgfl;   /* ? */
-       short   sccc_xxx2;      /* ? */
-       short   sccc_copyspd;   /* ? */
-};
-
-/*
- * Set Controller Characteristics end variant
- */
-struct mscpv_scce {
-       u_short scce_version;           /* MSCP version number */
-       u_short scce_ctlrflags;         /* controller flags */
-       u_short scce_ctlrtimo;          /* controller timeout */
-       u_short scce_ctlrcmdl;          /* ??? */
-       quad_t  scce_ctlrid;            /* controller ID */
-       long    scce_xxx[3];    /* ? */
-       long    scce_volser;            /* volume serial number */
-};
-
-/*
- * On Line command variant
- */
-struct mscpv_onlc {
-       long    onlc_xxx1[4];   /* ? */
-       long    onlc_errlgfl;           /* error log flag? */
-       short   onlc_xxx2;      /* ? */
-       short   onlc_copyspd;           /* copy speed? */
-};
-
-/*
- * On Line end variant
- */
-struct mscpv_onle {
-       long    onle_xxx1[3];   /* ? */
-/*???*/        short   onle_xxx2;      /* ? */
-       u_char  onle_drivetype;         /* drive type index (same in guse) */
-       char    onle_xxx3;      /* ? */
-       long    onle_mediaid;           /* media type id (same in guse) */
-       long    onle_xxx4;      /* ? */
-       long    onle_unitsize;          /* unit size in sectors */
-       long    onle_volser;            /* volume serial number */
-};
-
-/*
- * Get Unit Status end variant (and Avail Attn?)
- */
-struct mscpv_guse {
-       u_short guse_multunit;          /* multi-unit code */
-       u_short guse_unitflags;         /* unit flags */
-       long    guse_hostid;            /* host id */
-       long    guse_unitid0;   /*???*/
-       short   guse_unitid1;   /*???*/
-       u_char  guse_drivetype;         /* drive type index */
-       u_char  guse_unitid2;   /*???*/
-       long    guse_mediaid;           /* media type id (encoded) */
-       short   guse_shadowunit;        /* shadow unit */
-       short   guse_shadowstat;        /* shadow status */
-       u_short guse_nspt;              /* sectors per track */
-       u_short guse_group;             /* track group size */
-       u_short guse_ngpc;              /* groups per cylinder */
-       u_short guse_xxx;               /* reserved */
-       u_short guse_rctsize;           /* RCT size (sectors) */
-       u_char  guse_nrpt;              /* RBNs per track */
-       u_char  guse_nrct;              /* number of RCTs */
-};
-
-/*
- * Macros to break up and build media IDs.  An ID encodes the port
- * type in the top 10 bits, and the drive type in the remaining 22.
- * The 10 bits, and 15 of the 22, are in groups of 5, with the value
- * 0 representing space and values 1..26 representing A..Z.  The low
- * 7 bits represent a number in 0..127.  Hence an RA81 on a UDA50
- * is <D><U><R><A>< >81, or 0x25641051.  This encoding scheme is known
- * in part in uda.c.
- *
- * The casts below are just to make pcc generate better code.
- */
-#define        MSCP_MEDIA_PORT(id)     (((long)(id) >> 22) & 0x3ff)    /* port */
-#define        MSCP_MEDIA_DRIVE(id)    ((long)(id) & 0x003fffff)       /* drive */
-#define        MSCP_MID_ECH(n, id)     (((long)(id) >> ((n) * 5 + 7)) & 0x1f)
-#define        MSCP_MID_CHAR(n, id) \
-       (MSCP_MID_ECH(n, id) ? MSCP_MID_ECH(n, id) + '@' : ' ')
-#define        MSCP_MID_NUM(id)        ((id) & 0x7f)
-/* for, e.g., RA81 */
-#define        MSCP_MKDRIVE2(a, b, n) \
-       (((a) - '@') << 17 | ((b) - '@') << 12 | (n))
-/* for, e.g., RRD50 */
-#define        MSCP_MKDRIVE3(a, b, c, n) \
-       (((a) - '@') << 17 | ((b) - '@') << 12 | ((c) - '@') << 7 | (n))
-
-/*
- * Error datagram variant.
- */
-struct mscpv_erd {
-       quad_t  erd_ctlrid;             /* controller ID */
-       u_char  erd_ctlrsoftware;       /* controller software version */
-       u_char  erd_ctlrhardware;       /* controller hardware version */
-       u_short erd_multiunit;          /* multi-unit code (?) */
-       union {
-               u_long  un_busaddr;     /* bus address, if mem access err */
-               quad_t  un_unitid;      /* unit id, otherwise */
-       } erd_un1;
-#define        erd_busaddr     erd_un1.un_busaddr
-#define        erd_unitid      erd_un1.un_unitid
-       u_char  erd_unitsoftware;       /* unit software version */
-       u_char  erd_unithardware;       /* unit hardware version */
-       union {
-               u_char  un_b[2];        /* level, retry (if disk xfer err) */
-               u_short un_s;           /* cylinder (if small disk error) */
-       } erd_un2;
-#define        erd_level       erd_un2.un_b[0]
-#define        erd_retry       erd_un2.un_b[1]
-#define        erd_sdecyl      erd_un2.un_s
-       long    erd_volser;             /* volume serial number */
-       u_long  erd_hdr;                /* `header' (block number) */
-       u_char  erd_sdistat[12];        /* SDI status information (?) */
-};
-
-/*
- * I am making brash assumptions about the first four bytes of all
- * MSCP packets.  These appear to be true for both UDA50s and TMSCP
- * devices (TU81, TA81, TK50).  DEC claim that these four bytes are
- * not part of MSCP itself, yet at least the length is necessary
- * for, e.g., error checking.
- */
-struct mscp {
-       u_short mscp_msglen;            /* length in bytes */
-       u_char  mscp_msgtc;             /* type (high 4 bits) and credits */
-       u_char  mscp_vcid;              /* virtual circuit ID */
-       long    mscp_cmdref;            /* command reference number */
-       u_short mscp_unit;              /* unit number */
-       u_short mscp_seqnum;            /* sequence number */
-       u_char  mscp_opcode;            /* opcode */
-#define        mscp_format     mscp_opcode     /* aka format (datagrams) */
-       u_char  mscp_flags;             /* flags */
-       u_short mscp_modifier;          /* modifier (commands) */
-#define        mscp_status     mscp_modifier   /* aka status (ends) */
-#define        mscp_event      mscp_modifier   /* aka event (datagrams) */
-       union {
-               struct  mscpv_seq un_seq;       /* generic sequential msg */
-               struct  mscpv_sccc un_sccc;     /* SCC command */
-               struct  mscpv_scce un_scce;     /* SCC end */
-               struct  mscpv_onlc un_onlc;     /* on line command */
-               struct  mscpv_onle un_onle;     /* on line end */
-               struct  mscpv_guse un_guse;     /* get unit status */
-               struct  mscpv_erd un_erd;       /* error datagram */
-       } mscp_un;
-/*???*/        long    mscp_xxx;               /* pad to 64 bytes */
-};
-
-/*
- * Define message length according to the DEC specifications by dropping
- * the four byte header.
- */
-#define        MSCP_MSGLEN     (sizeof (struct mscp) - 4)
-
-/*
- * Shorthand
- */
-
-/*
- * Generic packet
- */
-#define        mscp_seq        mscp_un.un_seq
-
-/*
- * Set Controller Characteristics packet
- */
-#define        mscp_sccc       mscp_un.un_sccc
-
-/*
- * Set Controller Characteristics end packet
- */
-#define        mscp_scce       mscp_un.un_scce
-
-/*
- * Online / Set Unit Characteristics command packet
- */
-#define        mscp_onlc       mscp_un.un_onlc
-
-/*
- * Online end packet
- */
-#define        mscp_onle       mscp_un.un_onle
-
-/*
- * Get Unit Status end packet
- */
-#define        mscp_guse       mscp_un.un_guse
-
-/*
- * MSCP Error Log packet
- */
-#define        mscp_erd        mscp_un.un_erd
-
-/*
- * MSCP seq_addr field actually belongs to overall packet.
- */
-#define        mscp_addr       mscp_seq.seq_addr
-
-/*
- * Macros to break up mscp_msgtc, and types.
- */
-#define        MSCP_MSGTYPE(m) ((m) & 0xf0)
-#define        MSCP_CREDITS(m) ((m) & 0x0f)
-
-#define        MSCPT_SEQ               0x00    /* sequential message */
-#define        MSCPT_DATAGRAM          0x10    /* error datagram */
-#define        MSCPT_CREDITS           0x20    /* credit notification */
-#define        MSCPT_MAINTENANCE       0xf0    /* who knows */
-
-
-/*
- * Here begin more perhaps brash assumptions about MSCP devices...
- */
-
-/*
- * MSCP controllers have `command rings' and `response rings'.  A
- * command ring is a pool of MSCP packets that the host uses to give
- * commands to the controller; a response ring is a pool of MSCP
- * packets that the controller uses to give back responses.  Entries
- * in the command and response rings are `owned' by either the host
- * or the controller; only the owner is allowed to alter any of the
- * fields in the MSCP packet.  Thus, free command packets are owned
- * by the host, and free response packets by the controller.  When
- * the host gives a packet to the controller, it tells the controller
- * by touching a device register; when the controller gives a response
- * to the host, it generates an interrupt if enabled, and sets
- * a device register as well.
- *
- * The pool is `described' by a set of pointers to the packets, along
- * with the two flags below.
- */
-#define        MSCP_OWN        0x80000000      /* controller owns this packet */
-#define        MSCP_INT        0x40000000      /* controller should interrupt */
diff --git a/sys/arch/vax/vax/mscpvar.h b/sys/arch/vax/vax/mscpvar.h
deleted file mode 100644 (file)
index 52213fa..0000000
+++ /dev/null
@@ -1,242 +0,0 @@
-/*     $NetBSD: mscpvar.h,v 1.7 1996/04/08 18:32:51 ragge Exp $        */
-
-/*
- * Copyright (c) 1988 Regents of the University of California.
- * All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Chris Torek.
- *
- * 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.
- *
- *     @(#)mscpvar.h   7.3 (Berkeley) 6/28/90
- */
-
-/*
- * MSCP generic driver configuration
- */
-
-/*
- * Enabling MSCP_PARANOIA makes the response code perform various checks
- * on the hardware.  (Right now it verifies only the buffer pointer in
- * mscp_cmdref.)
- *
- * Enabling AVOID_EMULEX_BUG selects an alternative method of identifying
- * transfers in progress, which gets around a rather peculiar bug in the
- * SC41/MS.  Enabling MSCP_PARANOIA instead should work, but will cause
- * `extra' Unibus resets.
- *
- * Either of these flags can simply be included as an `options' line in
- * your configuration file.
- */
-
-/* #define MSCP_PARANOIA */
-/* #define AVOID_EMULEX_BUG */
-
-/*
- * Per driver information.
- *
- * md_ndpc sets the maximum unit number allowed in response packets.
- * md_nunits is the number of drives attached to all controllers.
- * md_unitshift is the divisor for converting a minor device number
- * to a unit index for the device queues in md_utab.
- *
- * The routines are called from the generic response dispatcher.
- * THE FOLLOWING IS OUT OF DATE
- * The first three (dgram, ctlrdone, and unconf) get passed a pointer
- * to the uba_ctlr and to the packet; the rest get a pointer to the
- * uba_device and to the packet (`um, mp' and `ui, mp' respectively).
- * The routines unconf, online, gotstatus, and ioerr are functions
- * and should return one of the values given below.  In addition,
- * the ioerr and bb routines get a third argument, `bp': a pointer
- * to the buffer describing the transfer in error.
- * END OUT OF DATE
- */
-struct mscp_info;
-
-struct mscp_driver {
-       int     md_ndpc;                /* number of drives per ctlr */
-       int     md_nunits;              /* total number drives (all ctlrs) */
-       int     md_unitshift;           /* device number to unit: >> count */
-       struct  buf *md_utab;           /* pointer to device queues */
-       struct  disklabel *md_lab;      /* pointer to devicee disklabels */
-       struct  uba_device **md_dinfo;  /* pointer to device info */
-           /* error datagram */
-       void    (*md_dgram) __P((struct mscp_info *, struct mscp *));
-           /* controller operation complete */
-       void    (*md_ctlrdone) __P((struct mscp_info *, struct mscp *));
-           /* response from unconfigured drive */
-       int     (*md_unconf) __P((struct mscp_info *, struct mscp *));  
-           /* normal I/O is done */
-       void    (*md_iodone) __P((struct mscp_info *, struct buf *, int));
-           /* drive on line */
-       int     (*md_online) __P((struct uba_device *, struct mscp *));/*XXX*/
-           /* got unit status */
-       int     (*md_gotstatus) __P((struct uba_device *, struct mscp *));
-           /* replace done */
-       void    (*md_replace) __P((struct uba_device *, struct mscp *));
-           /* read or write failed */
-       int     (*md_ioerr) __P((struct uba_device *, struct mscp *, 
-           struct buf *));     
-           /* B_BAD io done */
-       void    (*md_bb) __P((struct uba_device *, struct mscp *,
-           struct buf *));
-       char    *md_mname;              /* name of controllers */
-       char    *md_dname;              /* name of drives */
-};
-
-/*
- * Return values from functions.
- * MSCP_RESTARTED is peculiar to I/O errors.
- */
-#define        MSCP_DONE       0               /* all ok */
-#define        MSCP_FAILED     1               /* no go */
-#define        MSCP_RESTARTED  2               /* transfer restarted */
-
-/*
- * Ring information, per ring (one each for commands and responses).
- */
-struct mscp_ri {
-       int     mri_size;               /* ring size */
-       int     mri_next;               /* next (expected|free) */
-       long    *mri_desc;              /* base address of descriptors */
-       struct  mscp *mri_ring;         /* base address of packets */
-};
-
-/*
- * Per device information.
- *
- * mi_ip is a pointer to the inverting pointers (things that get `ui's
- * given unit numbers) FOR THIS CONTROLLER (NOT the whole set!).
- *
- * mi_wtab holds a queue of those transfers that were started but have
- * not yet finished.  Other Unibus drivers do not need this as they hand
- * out requests one at a time.  MSCP devices, however, take a slew of
- * requests and pick their own order to execute them.  This means that
- * we have to have a place to move transfers that were given to the
- * controller, so we can tell those apart from those that have not yet
- * been handed out; mi_wtab is that place.
- */
-struct mscp_info {
-       struct  mscp_driver *mi_md;     /* pointer to driver info */
-       int     mi_ctlr;                /* controller index */
-       struct  buf *mi_tab;            /* pointer to ctlr's drive queue */
-       struct  uba_device **mi_ip;     /* pointer to inverting pointers */
-       struct  mscp_ri mi_cmd;         /* MSCP command ring info */
-       struct  mscp_ri mi_rsp;         /* MSCP response ring info */
-       short   mi_credits;             /* transfer credits */
-       char    mi_wantcmd;             /* waiting for command packet */
-       char    mi_wantcredits;         /* waiting for transfer credits */
-       struct  buf mi_wtab;            /* transfer wait queue */
-#ifdef AVOID_EMULEX_BUG
-#define        AEB_MAX_BP      32              /* max pend xfers (power of 2) XXX */
-       volatile struct buf *mi_bp[AEB_MAX_BP]; /* xfer no. to buffer */
-       u_int   mi_nextbp;              /* generates unique xfer no's */
-       int     mi_ok;                  /* for error rate statistics */
-#endif AVOID_EMULEX_BUG
-};
-
-/*
- * We have run out of credits when mi_credits is <= MSCP_MINCREDITS.
- * It is still possible to issue one command in this case, but it must
- * not be a data transfer.  E.g., `get command status' or `abort command'
- * is legal, while `read' is not.
- */
-#define        MSCP_MINCREDITS 1
-
-/*
- * Flags for mscp_getcp().
- */
-#define        MSCP_WAIT       1
-#define        MSCP_DONTWAIT   0
-
-       /* get a command packet */
-struct mscp *mscp_getcp __P((struct mscp_info *, int));
-
-/*
- * Unit flags
- */
-#define        UNIT_ONLINE     0x01    /* drive is on line */
-#define        UNIT_HAVESTATUS 0x02    /* got unit status */
-#define        UNIT_REQUEUE    0x04    /* requeue after response */
-
-/*
- * Handle a command ring transition: wake up sleepers for command packets.
- * This is too simple to bother with a function call.
- */
-#define        MSCP_DOCMD(mi) { \
-       if ((mi)->mi_wantcmd) { \
-               (mi)->mi_wantcmd = 0; \
-               wakeup((caddr_t) &(mi)->mi_wantcmd); \
-       } \
-}
-
-/*
- * The following macro appends a buffer to a drive queue or a drive to
- * a controller queue, given the name of the forward link.  Use as
- * `APPEND(dp, &um->um_tab, b_forw)' or `APPEND(bp, dp, av_forw)',
- * where `bp' is a transfer request, `dp' is a drive queue, and `um_tab'
- * is a controller queue.  (That is, the forward link for controller
- * queues is `b_forw'; for drive queues, it is `av_forw'.)
- *
- * Changed to new buf structure 940605/Ragge
- */
-#define        MSCP_APPEND(bp, queue, link) { \
-       struct buf *tmp; \
-       \
-       (bp)->link = NULL; \
-       if ((queue)->b_actf == NULL) \
-               (queue)->b_actf = (bp); \
-       else { \
-               tmp=(queue)->b_actf; \
-               while(tmp->link) tmp=tmp->link; \
-               tmp->link = (bp); \
-       } \
-}
-
-/* Old APPEND macro */
-/*
-#define APPEND(bp, queue, link) { \
-        (bp)->link = NULL; \
-        if ((queue)->b_actf == NULL) \
-                (queue)->b_actf = (bp); \
-        else \
-                (queue)->b_actl->link = (bp); \
-        (queue)->b_actl = (bp); \
-}
-*/
-
-/* Prototypes */
-
-void   mscp_printevent __P((struct mscp *));
-void   mscp_go __P((struct mscp_info *, struct mscp *, int));
-void   mscp_requeue __P((struct mscp_info *));
-void   mscp_dorsp __P((struct mscp_info *));
-void   mscp_decodeerror __P((char *, int, struct mscp *));
-
index 0a7f59b..b6401f8 100644 (file)
@@ -1,4 +1,4 @@
-/*     $NetBSD: ns_cksum.c,v 1.1 1996/03/03 11:54:37 ragge Exp $       */
+/*     $NetBSD: ns_cksum.c,v 1.3 1996/10/13 03:35:55 christos Exp $    */
 /*
  * Copyright (c) 1985, 1986 Regents of the University of California.
  * All rights reserved.
index 1263ff1..4b3338b 100644 (file)
@@ -1,4 +1,5 @@
-/*      $NetBSD: pmap.c,v 1.27 1996/05/19 16:44:20 ragge Exp $     */
+/*     $OpenBSD: pmap.c,v 1.7 1997/01/15 23:25:20 maja Exp $ */
+/*     $NetBSD: pmap.c,v 1.30 1996/10/13 03:35:57 christos Exp $          */
 /*
  * Copyright (c) 1994 Ludd, University of Lule}, Sweden.
  * All rights reserved.
@@ -58,8 +59,8 @@ static        void    free_pv_entry __P((pv_entry_t));
 static int     remove_pmap_from_mapping __P((pv_entry_t, pmap_t));
 
 
-#define        ISTACK_SIZE (4 * NBPG)
-#define        PTE_TO_PV(pte)  (PHYS_TO_PV((pte&PG_FRAME)<<PGSHIFT))
+#define ISTACK_SIZE (4 * NBPG)
+#define PTE_TO_PV(pte) (PHYS_TO_PV((pte&PG_FRAME)<<PGSHIFT))
 
 struct pmap kernel_pmap_store;
 
@@ -71,21 +72,55 @@ static int kernel_prot[]={ PG_NONE, PG_KR, PG_KW, PG_KW,
 
 static pv_entry_t   pv_head = NULL;
 static unsigned int pv_count = 0;
-pv_entry_t      pv_table;               /* array of entries,
-                                           one per LOGICAL page */
+pv_entry_t     pv_table;               /* array of entries,
+                                          one per LOGICAL page */
 unsigned *pte_cmap;
-void   *scratch;
+void   *scratch;
 
 #ifdef PMAPDEBUG
 int    startpmapdebug = 0;
-extern int startsysc, faultdebug;
+/* extern      int startsysc, faultdebug; */
 #endif
 
 unsigned int vmmap;
 vm_map_t pte_map;
 
 vm_offset_t   avail_start, avail_end;
-vm_offset_t   virtual_avail, virtual_end; /* Available virtual memory   */
+vm_offset_t   virtual_avail, virtual_end; /* Available virtual memory  */
+
+/*
+ * badaddr() doesn't work on some VAXstations 
+ * (I've checked KA410 and KA43, don't know about others yet).
+ *
+ * Checking all pages of physical memory starting from address 0x0 and
+ * waiting for being trapped by badaddr() is not enough on these machines:
+ *
+ * on VS2000/KA410 physical memory appears more than once.
+ * eg. on a machine with 10MB memory (2MB base + 8MB extension)
+ * the extension memory is mapped to 0x200000, 0xA00000, and so on.
+ *
+ * On VS3100/KA43 writing to addresses above the available memory
+ * is implemented as a nop.
+ *
+ * On both of these machines the old check/count routine resulted in an
+ * endless loop. Thus while checking/counting the memory, we write a 
+ * pattern to all the pages we are visiting. (leaving a hole for kernel).
+ * If we access a page which already holds a valid pattern, then we've 
+ * seen this page already and thus reached the highest memory-address.
+ * If the page doesn't hold the pattern directly after having written
+ * it, then the page is bad or not available and we've reached the end.
+ * 
+ * VAXen can't have more than 512(?) MB of physical memory, so we also
+ * have an upper limit for how much pages to check. If we're not trapped
+ * within this address-range, something went wrong and we're assuming
+ * some save amount of physical memory. This might be paranoid, but...
+ */
+#ifndef MAX_PHYSMEM_AVAIL
+#define MAX_PHYSMEM_AVAIL     512*1024*1024
+#endif
+#ifndef MIN_PHYSMEM_AVAIL
+#define MIN_PHYSMEM_AVAIL      8*1024*1024
+#endif
 
 /*
  * pmap_bootstrap().
@@ -104,6 +139,31 @@ pmap_bootstrap()
        p0pmap = &vmspace0.vm_pmap;
 
        sysptsize = SYSPTSIZE;
+
+       /*
+        * Because of the badaddr() problem with some VAXstations we
+        * compare the first page of memory (the SCB) with the new
+        * counted up pages for equality. It's very unlikely that
+        * another page will hold the same info as the SCB.
+        * This is neccessary only if badaddr() doesn't work, but on other
+        * machines checking the pattern doesn't hurt anyway...
+        */
+
+       /* Kickoff for memory checking */
+       avail_end = 0x200000;   /* 2 MB */
+
+       while (badaddr((caddr_t)avail_end, 4) == 0) {
+#if VAX410 || VAX420 || VAX43 || VAX46 || VAX49 || VAX50
+               if (bcmp(0, (caddr_t)avail_end, NBPG) == 0)
+                       break;
+#endif
+               avail_end += NBPG * 128;/* Memory is checked in 64K hunks */
+       }
+
+#if VAX410 || VAX420 || VAX43 || VAX46 || VAX49 || VAX50
+       sysptsize += (16 * 1024) >> PGSHIFT;  /* guc->uc_sysptSpace ?? */
+#endif
+
        /*
         * Virtual_* and avail_* is used for mapping of system page table.
         * First set them to their max values and then decrement them.
@@ -112,8 +172,6 @@ pmap_bootstrap()
         * a variable here that is changed dependent of the physical
         * memory size.
         */
-       while (!badaddr((caddr_t)avail_end, 4)) /* Memory is in 64K hunks */
-               avail_end += NBPG * 128;
        sysptsize += avail_end >> PGSHIFT;
        virtual_avail = KERNBASE;
        virtual_end = KERNBASE + sysptsize * NBPG;
@@ -137,7 +195,7 @@ pmap_bootstrap()
            VM_PROT_READ|VM_PROT_WRITE);
 
        /* Map System Page Table and zero it,  Sysmap already set. */
-        mtpr(avail_start, PR_SBR);
+       mtpr(avail_start, PR_SBR);
        MAPPHYS(junk, (ROUND_PAGE(sysptsize * 4) >> PGSHIFT),
            VM_PROT_READ|VM_PROT_WRITE);
 
@@ -176,40 +234,42 @@ pmap_bootstrap()
        bcopy(0, (void *)avail_start, NBPG >> 1);
        mtpr(avail_start, PR_SCBB);
        bzero(0, NBPG >> 1);
-       (cpu_calls[cpunumber].cpu_steal_pages)();
+       (cpu_calls[vax_cputype].cpu_steal_pages)();
+       avail_start = ROUND_PAGE(avail_start);
+       virtual_avail = ROUND_PAGE(virtual_avail);
 
 #ifdef PMAPDEBUG
-        printf("Sysmap %x, istack %x, scratch %x\n",Sysmap,istack,scratch);
-        printf("etext %x\n", &etext);
-        printf("SYSPTSIZE %x, USRPTSIZE %x\n",sysptsize,USRPTSIZE);
-        printf("pv_table %x, vmmap %x, pte_cmap %x\n",
-                pv_table,vmmap,pte_cmap);
-        printf("avail_start %x, avail_end %x\n",avail_start,avail_end);
-        printf("virtual_avail %x,virtual_end %x\n",virtual_avail,virtual_end);
-        printf("clearomr: %x \n",(uint)vmmap-(uint)Sysmap);
-        printf("faultdebug %x, startsysc %x\n",&faultdebug, &startsysc);
-        printf("startpmapdebug %x\n",&startpmapdebug);
+       printf("Sysmap %x, istack %x, scratch %x\n",Sysmap,istack,scratch);
+       printf("etext %x\n", &etext);
+       printf("SYSPTSIZE %x, USRPTSIZE %x\n",sysptsize,USRPTSIZE);
+       printf("pv_table %x, vmmap %x, pte_cmap %x\n",
+               pv_table,vmmap,pte_cmap);
+       printf("avail_start %x, avail_end %x\n",avail_start,avail_end);
+       printf("virtual_avail %x,virtual_end %x\n",virtual_avail,virtual_end);
+       printf("clearomr: %x \n",(uint)vmmap-(uint)Sysmap);
+/*       printf("faultdebug %x, startsysc %x\n",&faultdebug, &startsysc);*/
+       printf("startpmapdebug %x\n",&startpmapdebug);
 #endif
 
 
-        /* Init kernel pmap */
-        pmap_kernel()->ref_count = 1;
-        simple_lock_init(&pmap_kernel()->pm_lock);
-        p0pmap->pm_pcb = (struct pcb *)proc0paddr;
+       /* Init kernel pmap */
+       pmap_kernel()->ref_count = 1;
+       simple_lock_init(&pmap_kernel()->pm_lock);
+       p0pmap->pm_pcb = (struct pcb *)proc0paddr;
 
-        p0pmap->pm_pcb->P1BR = (void *)0x80000000;
-        p0pmap->pm_pcb->P0BR = (void *)0x80000000;
-        p0pmap->pm_pcb->P1LR = 0x200000;
-        p0pmap->pm_pcb->P0LR = AST_PCB;
-        mtpr(0x80000000, PR_P1BR);
-        mtpr(0x80000000, PR_P0BR);
-        mtpr(0x200000, PR_P1LR);
-        mtpr(AST_PCB, PR_P0LR);
+       p0pmap->pm_pcb->P1BR = (void *)0x80000000;
+       p0pmap->pm_pcb->P0BR = (void *)0x80000000;
+       p0pmap->pm_pcb->P1LR = 0x200000;
+       p0pmap->pm_pcb->P0LR = AST_PCB;
+       mtpr(0x80000000, PR_P1BR);
+       mtpr(0x80000000, PR_P0BR);
+       mtpr(0x200000, PR_P1LR);
+       mtpr(AST_PCB, PR_P0LR);
        /*
         * Now everything should be complete, start virtual memory.
         */
-        mtpr(sysptsize, PR_SLR);
-        mtpr(1, PR_MAPEN);
+       mtpr(sysptsize, PR_SLR);
+       mtpr(1, PR_MAPEN);
 }
 
 
@@ -238,7 +298,7 @@ pmap_t
 pmap_create(phys_size)
        vm_size_t phys_size;
 {
-       pmap_t   pmap;
+       pmap_t   pmap;
 
 #ifdef PMAPDEBUG
 if(startpmapdebug)printf("pmap_create: phys_size %x\n",phys_size);
@@ -310,10 +370,10 @@ if(startpmapdebug)printf("pmap_destroy: pmap %x\n",pmap);
 void 
 pmap_enter(pmap, v, p, prot, wired)
        register pmap_t pmap;
-       vm_offset_t     v;
-       vm_offset_t     p;
-       vm_prot_t       prot;
-       boolean_t       wired;
+       vm_offset_t     v;
+       vm_offset_t     p;
+       vm_prot_t       prot;
+       boolean_t       wired;
 {
        u_int   i, pte, s, *patch;
        pv_entry_t pv, tmp;
@@ -398,6 +458,10 @@ pmap_bootstrap_alloc(size)
 {
        void *mem;
 
+#ifdef PMAPDEBUG
+if(startpmapdebug)
+printf("pmap_bootstrap_alloc: size 0x %x\n",size);
+#endif
        size = round_page(size);
        mem = (void *)virtual_avail;
        virtual_avail = pmap_map(virtual_avail, avail_start,
@@ -455,8 +519,8 @@ void
 pmap_protect(pmap, start, end, prot)
        pmap_t pmap;
        vm_offset_t start;
-       vm_offset_t     end;
-       vm_prot_t       prot;
+       vm_offset_t     end;
+       vm_prot_t       prot;
 {
        int pte, *patch, s;
 
@@ -690,7 +754,7 @@ free_pv_entry(entry)
 
 boolean_t
 pmap_is_referenced(pa)
-       vm_offset_t     pa;
+       vm_offset_t     pa;
 {
        struct pv_entry *pv;
        u_int *pte,spte=0;
@@ -717,9 +781,9 @@ pmap_is_modified(pa)
        pv=PHYS_TO_PV(pa);
        if(!pv->pv_pmap) return 0;
        do {
-                pte=(u_int *)pmap_virt2pte(pv->pv_pmap,pv->pv_va);
-                spte|=*pte++;
-                spte|=*pte;
+               pte=(u_int *)pmap_virt2pte(pv->pv_pmap,pv->pv_va);
+               spte|=*pte++;
+               spte|=*pte;
        } while((pv=pv->pv_next));
        return((spte&PG_M)?1:0);
 }
@@ -731,7 +795,7 @@ pmap_is_modified(pa)
 
 void 
 pmap_clear_reference(pa)
-       vm_offset_t     pa;
+       vm_offset_t     pa;
 {
        struct pv_entry *pv;
        int *pte;
@@ -758,7 +822,7 @@ if(startpmapdebug) printf("pmap_clear_reference: pa %x, pv %x\n",pa,pv);
 
 void 
 pmap_clear_modify(pa)
-       vm_offset_t     pa;
+       vm_offset_t     pa;
 {
        struct pv_entry *pv;
        u_int *pte;
@@ -775,8 +839,8 @@ pmap_clear_modify(pa)
 void 
 pmap_change_wiring(pmap, va, wired)
        register pmap_t pmap;
-       vm_offset_t     va;
-       boolean_t       wired;
+       vm_offset_t     va;
+       boolean_t       wired;
 {
        int *pte;
 #ifdef PMAPDEBUG
@@ -791,14 +855,14 @@ if(startpmapdebug) printf("pmap_change_wiring: pmap %x, va %x, wired %x\n",
 }
 
 /*
- *      pmap_page_protect:
+ *     pmap_page_protect:
  *
- *      Lower the permission for all mappings to a given page.
+ *     Lower the permission for all mappings to a given page.
  */
 void
 pmap_page_protect(pa, prot)
-       vm_offset_t     pa;
-       vm_prot_t       prot;
+       vm_offset_t     pa;
+       vm_prot_t       prot;
 {
        pv_entry_t pv,opv;
        u_int s,*pte,*pte1,nyprot,kprot;
@@ -859,10 +923,10 @@ if(startpmapdebug) printf("pmap_page_protect: pa %x, prot %x\n",pa, prot);
 }
 
 /*
- *      pmap_zero_page zeros the specified (machine independent)
- *      page by mapping the page into virtual memory and using
- *      bzero to clear its contents, one machine dependent page
- *      at a time.
+ *     pmap_zero_page zeros the specified (machine independent)
+ *     page by mapping the page into virtual memory and using
+ *     bzero to clear its contents, one machine dependent page
+ *     at a time.
  */
 void
 pmap_zero_page(phys)
index cf14bbd..865c9cd 100644 (file)
@@ -1,3 +1,4 @@
+/*     $OpenBSD: random.s,v 1.3 1997/01/15 23:25:21 maja Exp $ */
 /*     $NetBSD: random.s,v 1.2 1994/10/26 08:03:24 cgd Exp $   */
 
 /*
index 67fab58..c75e0da 100644 (file)
@@ -1,4 +1,4 @@
-/*     $NetBSD: rootfil.c,v 1.11 1996/04/08 18:32:54 ragge Exp $       */
+/*     $NetBSD: rootfil.c,v 1.14 1996/10/13 03:35:58 christos Exp $    */
 
 /*
  * Copyright (c) 1988 University of Utah.
 #include <machine/pte.h>
 #include <machine/cpu.h>
 
-#include <vax/uba/ubavar.h>
-
-#include "uda.h"
 #include "hp.h"
+#include "ra.h"
 
 #define DOSWAP                  /* Change swdevt, argdev, and dumpdev too */
 u_long  bootdev;                /* should be dev_t, but not until 32 bits */
 extern dev_t rootdev, dumpdev;
 
-static  char devname[][2] = {
-        {'h','p'},        /* 0 = hp */
-        {0,0},            /* 1 = ht */
-        {'u','p'},        /* 2 = up */
-        {'r','k'},        /* 3 = hk */
-        {0,0},            /* 4 = sw */
-        {0,0},            /* 5 = tm */
-        {0,0},            /* 6 = ts */
-        {0,0},            /* 7 = mt */
-        {0,0},            /* 8 = tu */
-        {'r','a'},        /* 9 = ra */
-        {0,0},            /* 10 = ut */
-        {'r','b'},        /* 11 = rb */
-        {0,0},            /* 12 = uu */
-        {0,0},            /* 13 = rx */
-        {'r','l'},        /* 14 = rl */
-        {0,0},            /* 15 = tmscp */
-        {'k','r'},        /* 16 = ra on kdb50 */
-};
-
 #define PARTITIONMASK   0x7
 #define PARTITIONSHIFT  3
 
@@ -100,45 +78,40 @@ setroot()
 {
         int  majdev, mindev, unit, part, controller, adaptor;
         dev_t temp = 0, orootdev;
-#if NUDA > 0
-       extern struct uba_device ubdinit[];
-#endif
         struct swdevt *swp;
        extern int boothowto;
+       char *uname;
 
         if (boothowto & RB_DFLTROOT ||
             (bootdev & B_MAGICMASK) != (u_long)B_DEVMAGIC)
                 return;
         majdev = B_TYPE(bootdev);
-        if (majdev >= sizeof(devname) / sizeof(devname[0]))
+        if (majdev >= nblkdev)
                 return;
         adaptor = B_ADAPTOR(bootdev);
         controller = B_CONTROLLER(bootdev);
         part = B_PARTITION(bootdev);
         unit = B_UNIT(bootdev);
-        if (majdev == 0) {      /* MBA device */
-#if NHP > 0
-               mindev = hp_getdev(adaptor, unit);
-               if (mindev < 0)
+
+       switch (majdev) {
+       case 0: /* MBA disk */
+#if NHP
+               if ((mindev = hp_getdev(adaptor, unit, &uname)) < 0)
+#endif
                        return;
-#else
-                return;
+               break;
+
+       case 9: /* MSCP disk */
+#if NRA
+               if ((mindev = ra_getdev(adaptor, controller, unit, &uname)) < 0)
 #endif
-        } else {
-                register struct uba_device *ubap;
-
-                for (ubap = ubdinit; ubap->ui_driver; ubap++){
-                        if (ubap->ui_alive && ubap->ui_slave == unit &&
-                           ubap->ui_ctlr == controller &&
-                           ubap->ui_ubanum == adaptor &&
-                           ubap->ui_driver->ud_dname[0] == devname[majdev][0] &&
-                           ubap->ui_driver->ud_dname[1] == devname[majdev][1])
-                                break;
-               }
-                if (ubap->ui_driver == 0)
-                        return;
-                mindev = ubap->ui_unit;
-        }
+                       return;
+               break;
+
+       default:
+               return;
+       }
+
         mindev = (mindev << PARTITIONSHIFT) + part;
         orootdev = rootdev;
         rootdev = makedev(majdev, mindev);
@@ -149,9 +122,7 @@ setroot()
         if (rootdev == orootdev)
                 return;
 
-        printf("Changing root device to %c%c%d%c\n",
-                devname[majdev][0], devname[majdev][1],
-                mindev >> PARTITIONSHIFT, part + 'a');
+        printf("Changing root device to %s%c\n", uname, part + 'a');
 
 #ifdef DOSWAP
         mindev &= ~PARTITIONMASK;
@@ -173,9 +144,6 @@ setroot()
          */
         if (temp == dumpdev)
                 dumpdev = swdevt[0].sw_dev;
-        panic("autoconf.c: argdev\n");
-/*      if (temp == argdev)
-                argdev = swdevt[0].sw_dev; */
 #endif
 }
 
index 486acc3..237087c 100644 (file)
@@ -1,4 +1,4 @@
-/*     $NetBSD: sbi.c,v 1.9 1996/04/08 18:32:55 ragge Exp $ */
+/*     $NetBSD: sbi.c,v 1.14 1996/10/13 03:36:00 christos Exp $ */
 /*
  * Copyright (c) 1994 Ludd, University of Lule}, Sweden.
  * All rights reserved.
 #include <sys/param.h>
 #include <sys/device.h>
 #include <sys/systm.h>
-#include <vm/vm.h>
-#include <vm/vm_kern.h>
-#include <vm/vm_page.h>
-#include <machine/ka750.h>
-#include <machine/pmap.h>
+
 #include <machine/sid.h>
 #include <machine/cpu.h>
-
-struct nexus *nexus;
+#include <machine/nexus.h>
 
 static int sbi_print __P((void *, const char *));
-       int sbi_match __P((struct device *, void *, void *));
-       void sbi_attach __P((struct device *, struct device *, void*));
-
-
-struct bp_conf {
-       char *type;
-       int num;
-       int partyp;
-};
+static int sbi_match __P((struct device *, void *, void *));
+static void sbi_attach __P((struct device *, struct device *, void*));
 
 int
 sbi_print(aux, name)
@@ -79,8 +67,8 @@ sbi_print(aux, name)
 
 int
 sbi_match(parent, cf, aux)
-       struct  device  *parent;
-       void    *cf, *aux;
+       struct  device  *parent;
+       void    *cf, *aux;
 {
        struct bp_conf *bp = aux;
 
@@ -91,99 +79,36 @@ sbi_match(parent, cf, aux)
 
 void
 sbi_attach(parent, self, aux)
-       struct  device  *parent, *self;
-       void    *aux;
+       struct  device  *parent, *self;
+       void    *aux;
 {
-       u_int   nexnum, maxnex, minnex;
+       u_int   nexnum, maxnex, minnex;
        struct  sbi_attach_args sa;
 
-       switch (cpunumber) {
-#ifdef VAX730
-       case VAX_730:
-               maxnex = NNEX730;
-               printf(": BL[730\n");
-               break;
-#endif
-#ifdef VAX750
-       case VAX_750:
-               maxnex = NNEX750;
-               printf(": CMI750\n");
-               break;
-#endif
-#ifdef VAX630
-       case VAX_78032:
-               switch (cpu_type) {
-               case VAX_630:
-                       maxnex = NNEX630;
-                       printf(": Q22\n");
-                       break;
-               default:
-                       panic("Microvax not supported");
-               };
-               break;
-#endif
-#ifdef VAX650
-       case VAX_650:
-               maxnex = NNEX630; /* XXX */
-               printf(": Q22\n");
-               break;
-#endif
-#if VAX780 || VAX8600
-       case VAX_780:
-       case VAX_8600:
-               maxnex = NNEXSBI;
-               printf(": SBI780\n");
-               break;
-#endif
-       default:
-               maxnex = 0; /* Leave it */
-               break;
-       }
+       printf("\n");
 
        /*
         * Now a problem: on different machines with SBI units identifies
         * in different ways (if they identifies themselves at all).
         * We have to fake identifying depending on different CPUs.
         */
-       minnex = self->dv_unit * maxnex;
-       for (nexnum = minnex; nexnum < minnex + maxnex; nexnum++) {
+       minnex = self->dv_unit * NNEXSBI;
+       for (nexnum = minnex; nexnum < minnex + NNEXSBI; nexnum++) {
                volatile int tmp;
 
                if (badaddr((caddr_t)&nexus[nexnum], 4))
                        continue;
 
-               switch (cpunumber) {
-#ifdef VAX750
-               case VAX_750:
-               {       extern  int nexty750[];
-                       sa.type = nexty750[nexnum];
-                       break;
-               }
-#endif
-#ifdef VAX730
-               case VAX_730:
-               {       extern  int nexty730[];
-                       sa.type = nexty730[nexnum];
-                       break;
-               }
-#endif
-#if VAX630 || VAX650
-               case VAX_78032:
-               case VAX_650:
-                       sa.type = NEX_UBA0;
-                       break;
-#endif
-               default:
-                       tmp = nexus[nexnum].nexcsr.nex_csr; /* no byte reads */
-                       sa.type = tmp & 255;
-               }
+               tmp = nexus[nexnum].nexcsr.nex_csr; /* no byte reads */
+               sa.type = tmp & 255;
+
                sa.nexnum = nexnum;
                sa.nexaddr = nexus + nexnum;
                config_found(self, (void*)&sa, sbi_print);
        }
 }
 
-struct  cfdriver sbi_cd = {
+struct cfdriver sbi_cd = {
        NULL, "sbi", DV_DULL
 };
 
index 88fc116..f2bec41 100644 (file)
@@ -1,4 +1,4 @@
-/*     $NetBSD: swapgeneric.c,v 1.9 1996/04/08 18:32:57 ragge Exp $    */
+/*     $NetBSD: swapgeneric.c,v 1.13 1996/10/13 03:36:01 christos Exp $        */
 
 /*-
  * Copyright (c) 1982, 1986 The Regents of the University of California.
@@ -35,9 +35,6 @@
  *     @(#)swapgeneric.c       7.11 (Berkeley) 5/9/91
  */
 
-#include "uda.h"
-#include "hp.h"
-
 #include <sys/param.h>
 #include <sys/conf.h>
 #include <sys/buf.h>
 #include <machine/mtpr.h>
 #include <machine/cpu.h>
 
-#include <vax/uba/ubareg.h>
-#include <vax/uba/ubavar.h>
-
+#include "hp.h"
+#include "ra.h"
+#include "hdc.h"
+#include "sd.h"
+#include "st.h"
 
 void   gets __P((char *));
 
@@ -77,14 +76,11 @@ int dmmin, dmmax, dmtext;
 
 int (*mountroot) __P((void)) = ffs_mountroot;
 
-extern struct uba_driver scdriver;
-extern struct uba_driver hkdriver;
-extern struct uba_driver idcdriver;
-extern struct uba_driver hldriver;
-extern struct uba_driver udadriver;
-extern struct uba_driver kdbdriver;
-
 extern struct cfdriver hp_cd;
+extern struct cfdriver ra_cd;
+extern struct cfdriver rd_cd;
+extern struct cfdriver sd_cd;
+extern struct cfdriver st_cd;
 
 struct ngcconf {
        struct  cfdriver *ng_cf;
@@ -93,34 +89,24 @@ struct      ngcconf {
 #if NHP > 0
        { &hp_cd,       makedev(0, 0), },
 #endif
-       { 0 },
-};
-
-struct genericconf {
-       caddr_t gc_driver;
-       char    *gc_name;
-       dev_t   gc_root;
-} genericconf[] = {
-/*     { (caddr_t)&hp_cd,      "hp",   makedev(0, 0),  },
-       { (caddr_t)&scdriver,   "up",   makedev(2, 0),  }, */
-#if NUDA > 0
-       { (caddr_t)&udadriver,  "ra",   makedev(9, 0),  },
+#if NRA > 0
+       { &ra_cd,       makedev(9, 0), },
+#endif
+#if NHDC > 0
+       { &rd_cd,       makedev(19, 0), },
+#endif
+#if NSD > 0
+       { &sd_cd,       makedev(20, 0), },
+#endif
+#if NST > 0
+       { &st_cd,       makedev(21, 0), },
 #endif
-/*     { (caddr_t)&idcdriver,  "rb",   makedev(11, 0), },
-       { (caddr_t)&hldriver,   "rl",   makedev(14, 0), },
-       { (caddr_t)&hkdriver,   "hk",   makedev(3, 0),  },
-       { (caddr_t)&hkdriver,   "rk",   makedev(3, 0),  },
-       { (caddr_t)&kdbdriver,  "kra",  makedev(16, 0), }, */
        { 0 },
 };
 
 void
 setconf()
 {
-#if NUDA > 0
-       register struct uba_device *ui;
-#endif
-       register struct genericconf *gc;
        struct  ngcconf *nc;
        register char *cp, *gp;
        int unit, swaponroot = 0, i;
@@ -145,13 +131,13 @@ nretry:
                                    strcmp(name, ((struct device *)
                                    (nc->ng_cf->cd_devs[i]))->dv_xname) == 0)
                                        goto ngotit;
-#ifdef notyet
+
                printf("Use one of ");
                for (nc = ngcconf; nc->ng_cf; nc++)
                        printf("%s%%d ", nc->ng_cf->cd_name);
                printf("\n");
-#endif
-               goto gc2;
+
+               goto nretry;
 ngotit:
                rootdev = makedev(major(nc->ng_root), i * 8);
                goto doswap;
@@ -169,50 +155,9 @@ ngotit:
 
        }
 
-       if (boothowto & RB_ASKNAME) {
-retry:
-               printf("root device? ");
-               gets(name);
-gc2:
-               for (gc = genericconf; gc->gc_driver; gc++)
-                   for (cp = name, gp = gc->gc_name; *cp == *gp; cp++)
-                       if (*++gp == 0)
-                               goto gotit;
-               printf(
-                 "use hp%%d, up%%d, ra%%d, rb%%d, rl%%d, hk%%d or kra%%d\n");
-               goto nretry;
-gotit:
-               if (*++cp < '0' || *cp > '9') {
-                       printf("bad/missing unit number\n");
-                       goto retry;
-               }
-               while (*cp >= '0' && *cp <= '9')
-                       unit = 10 * unit + *cp++ - '0';
-               if (*cp == '*')
-                       swaponroot++;
-               goto found;
-       }
-       for (gc = genericconf; gc->gc_driver; gc++) {
-#if NUDA > 0
-               for (ui = ubdinit; ui->ui_driver; ui++) {
-                       if (ui->ui_alive == 0)
-                               continue;
-                       if (ui->ui_unit == unit && ui->ui_driver ==
-                           (struct uba_driver *)gc->gc_driver) {
-                               printf("root on %s%d\n",
-                                   ui->ui_driver->ud_dname, unit);
-                               goto found;
-                       }
-               }
-#endif
-       }
-
        printf("no suitable root\n");
        asm("halt");
 
-found:
-       gc->gc_root = makedev(major(gc->gc_root), unit*8);
-       rootdev = gc->gc_root;
 doswap:
        swdevt[0].sw_dev = argdev = dumpdev =
            makedev(major(rootdev), minor(rootdev)+1);
diff --git a/sys/arch/vax/vax/tmscpinf.h b/sys/arch/vax/vax/tmscpinf.h
deleted file mode 100644 (file)
index 5d69899..0000000
+++ /dev/null
@@ -1,321 +0,0 @@
-/*     $NetBSD: tmscpinf.h,v 1.1 1995/02/23 17:54:06 ragge Exp $ */
-
-/*     @(#)tmscp.h     7.2 (Berkeley) 5/27/88 */
-/*
- *     @(#)tmscp.h     1.3     10/21/85
- * Definitions for the Tape Mass Storage Control Protocol
- */
-
-/****************************************************************
- *                                                              *
- *        Licensed from Digital Equipment Corporation           *
- *                       Copyright (c)                          *
- *               Digital Equipment Corporation                  *
- *                   Maynard, Massachusetts                     *
- *                         1985, 1986                           *
- *                    All rights reserved.                      *
- *                                                              *
- *        The Information in this software is subject to change *
- *   without notice and should not be construed as a commitment *
- *   by  Digital  Equipment  Corporation.   Digital   makes  no *
- *   representations about the suitability of this software for *
- *   any purpose.  It is supplied "As Is" without expressed  or *
- *   implied  warranty.                                        *
- *                                                             *
- *        If the Regents of the University of California or its *
- *   licensees modify the software in a manner creating        *
- *   diriviative copyright rights, appropriate copyright       *
- *   legends may be placed on  the drivative work in addition   *
- *   to that set forth above.                                  *
- *                                                             *
- ****************************************************************
- *
- * Modification history: /sys/vax/tmscp.h
- *
- * 18-Oct-85 - afd
- *     Added: defines for tape format (density) flag values.
- *
- * 18-Jul-85 - afd
- *     Added: #define  M_UF_WBKNV      0000100
- *             for write back (which enables cache).
- ************************************************************************/
-/*
- * Control message opcodes
- */
-#define        M_OP_ABORT      0001    /* Abort command */
-#define        M_OP_GTCMD      0002    /* Get command status command */
-#define        M_OP_GTUNT      0003    /* Get unit status command */
-#define        M_OP_STCON      0004    /* Set controller characteristics command */
-#define        M_OP_AVAIL      0010    /* Available command */
-#define        M_OP_ONLIN      0011    /* Online command */
-#define        M_OP_STUNT      0012    /* Set unit characteristics command */
-#define        M_OP_DTACP      0013    /* Determine access paths command */
-#define        M_OP_ACCES      0020    /* Access command */
-#define        M_OP_CMPCD      0021    /* Compare controller data command */
-#define        M_OP_ERASE      0022    /* Erase command */
-#define        M_OP_FLUSH      0023    /* Flush command */
-#define M_OP_ERGAP     0026    /* Erase gap command */
-#define        M_OP_COMP       0040    /* Compare host data command */
-#define        M_OP_READ       0041    /* Read command */
-#define        M_OP_WRITE      0042    /* Write command */
-#define        M_OP_WRITM      0044    /* Write tape mark command */
-#define        M_OP_REPOS      0045    /* Reposition command */
-#define        M_OP_AVATN      0100    /* Available attention message */
-#define        M_OP_DUPUN      0101    /* Duplicate unit number attention message */
-#define        M_OP_ACPTH      0102    /* Access path attention message */
-#define        M_OP_END        0200    /* End message flag */
-/*
- * Generic command modifiers
- */
-#define        M_MD_COMP       0040000         /* Compare */
-#define        M_MD_CLSEX      0020000         /* Clear serious exception */
-#define        M_MD_SECOR      0001000         /* Suppress error correction */
-#define        M_MD_SEREC      0000400         /* Suppress error recovery */
-#define        M_MD_STWRP      0000004         /* Set write protect */
-#define        M_MD_ALLCD      0000002         /* All class drivers */
-#define        M_MD_NXUNT      0000001         /* Next unit */
-/*
- * TMSCP command modifiers
- */
-#define        M_MD_DLEOT      0000200         /* Delete LEOT */
-#define        M_MD_IMMED      0000100         /* Immediate completion */
-#define        M_MD_EXCAC      0000040         /* Exclusive access */
-#define        M_MD_UNLOD      0000020         /* Unload */
-#define        M_MD_REVRS      0000010         /* reverse */
-#define        M_MD_OBJCT      0000004         /* object count */
-#define        M_MD_REWND      0000002         /* rewind */
-/*
- * End message flags
- */
-#define        M_EF_ERLOG      0040    /* Error log generated */
-#define        M_EF_SEREX      0020    /* Serious exception */
-#define        M_EF_EOT        0010    /* End of tape encountered */
-#define        M_EF_PLS        0004    /* Position lost */
-/*
- * Controller flags
- */
-#define        M_CF_ATTN       0200    /* Enable attention messages */
-#define        M_CF_MISC       0100    /* Enable miscellaneous error log messages */
-#define        M_CF_OTHER      0040    /* Enable other host's error log messages */
-#define        M_CF_THIS       0020    /* Enable this host's error log messages */
-/*
- * Unit flags
- */
-#define        M_UF_WRTPH      0020000         /* Write protect (hardware) */
-#define        M_UF_WRTPS      0010000         /* Write protect (software or volume) */
-#define        M_UF_WBKNV      0000100         /* Write back (enables cache) */
-#define        M_UF_VSMSU      0000040         /* Variable speed mode suppression */
-#define        M_UF_VARSP      0000020         /* Variable speed unit */
-#define        M_UF_CMPWR      0000002         /* Compare writes */
-#define        M_UF_CMPRD      0000001         /* Compare reads */
-/*
- * Status codes
- */
-#define        M_ST_MASK       037             /* Status code mask */
-#define        M_ST_SUCC       000             /* Success */
-#define        M_ST_ICMD       001             /* Invalid command */
-#define        M_ST_ABRTD      002             /* Command aborted */
-#define        M_ST_OFFLN      003             /* Unit offline */
-#define        M_ST_AVLBL      004             /* Unit available */
-#define        M_ST_WRTPR      006             /* Write protected */
-#define        M_ST_COMP       007             /* Compare error */
-#define        M_ST_DATA       010             /* Data error */
-#define        M_ST_HSTBF      011             /* Host buffer access error */
-#define        M_ST_CNTLR      012             /* Controller error */
-#define        M_ST_DRIVE      013             /* Drive error */
-#define        M_ST_FMTER      014             /* Formatter error */
-#define        M_ST_BOT        015             /* BOT encountered */
-#define        M_ST_TAPEM      016             /* Tape mark encountered */
-#define        M_ST_RDTRN      020             /* Record data truncated */
-#define        M_ST_PLOST      021             /* Position lost */
-#define        M_ST_SEX        022             /* Serious exception */
-#define        M_ST_LED        023             /* LEOT detected */
-#define        M_ST_DIAG       037             /* Message from an internal diagnostic */
-/*
- * An MSCP packet
- */
-struct mscp {
-       struct  mscp_header mscp_header;/* device specific header */
-       long    mscp_cmdref;            /* command reference number */
-       short   mscp_unit;              /* unit number */
-       short   mscp_xxx1;              /* unused */
-       u_char  mscp_opcode;            /* opcode */
-       u_char  mscp_flags;             /* end message flags */
-       short   mscp_modifier;          /* modifiers */
-       union {
-       struct {
-               long    Mscp_bytecnt;   /* byte count */
-               long    Mscp_buffer;    /* buffer descriptor */
-               long    Mscp_mapbase;   /* physical addr of map registers */
-               long    Mscp_xxx2;      /* unused */
-               long    Mscp_lbn;       /* logical block number */
-               long    Mscp_xxx4;      /* unused */
-               long    *Mscp_dscptr;   /* pointer to descriptor (software) */
-               long    Mscp_sftwds[17];/* software words, padding */
-       } mscp_generic;
-       struct {
-               short   Mscp_version;   /* MSCP version */
-               short   Mscp_cntflgs;   /* controller flags */
-               short   Mscp_hsttmo;    /* host timeout */
-               short   Mscp_usefrac;   /* use fraction */
-               quad_t  Mscp_time;      /* time and date */
-               long    Mscp_cntdep;    /* controller dependent parameters */
-       } mscp_setcntchar;
-       struct {
-               short   Mscp_multunt;   /* multi-unit code */
-               short   Mscp_unitflgs;  /* unit flags */
-               long    Mscp_hostid;    /* host identifier */
-               quad_t  Mscp_unitid;    /* unit identifier */
-               long    Mscp_mediaid;   /* media type identifier */
-               short   Mscp_format;    /* format (tape density) */
-               short   Mscp_speed;     /* tape speed = (ips * bpi) /1000 */
-               short   Mscp_fmtmenu;   /* format menu */
-               short   Mscp_group;     /* group size */
-               short   Mscp_cylinder;  /* cylinder size */
-               short   Mscp_xxx3;      /* reserved */
-               short   Mscp_rctsize;   /* RCT table size */
-               char    Mscp_rbns;      /* RBNs / track */
-               char    Mscp_rctcpys;   /* RCT copies */
-       } mscp_getunitsts;
-       } mscp_un;
-       short mscp_fil1;
-       short mscp_fil2;
-       short mscp_fil3;
-};
-#define mscp_msglen (sizeof (struct mscp) - sizeof(struct mscp_header))
-/*
- * generic packet
- */
-#define        mscp_bytecnt    mscp_un.mscp_generic.Mscp_bytecnt
-#define        mscp_buffer     mscp_un.mscp_generic.Mscp_buffer
-#define        mscp_mapbase    mscp_un.mscp_generic.Mscp_mapbase
-#define        mscp_lbn        mscp_un.mscp_generic.Mscp_lbn
-#define        mscp_dscptr     mscp_un.mscp_generic.Mscp_dscptr
-#define        mscp_sftwds     mscp_un.mscp_generic.Mscp_sftwds
-#define        mscp_status     mscp_modifier
-/*
- * Abort / Get Command Status packet
- */
-#define        mscp_outref     mscp_bytecnt
-/*
- * Set Controller Characteristics packet
- */
-#define        mscp_version    mscp_un.mscp_setcntchar.Mscp_version
-#define        mscp_cntflgs    mscp_un.mscp_setcntchar.Mscp_cntflgs
-#define        mscp_hsttmo     mscp_un.mscp_setcntchar.Mscp_hsttmo
-#define        mscp_usefrac    mscp_un.mscp_setcntchar.Mscp_usefrac
-#define        mscp_time       mscp_un.mscp_setcntchar.Mscp_time
-#define        mscp_cntdep     mscp_un.mscp_setcntchar.Mscp_cntdep
-/*
- * Reposition command packet fields
- */
-#define mscp_reccnt mscp_bytecnt       /* record/object count */
-#define mscp_tmkcnt mscp_buffer                /* tape mark count */
-/*
- * Get Unit Status end packet
- */
-#define        mscp_multunt    mscp_un.mscp_getunitsts.Mscp_multunt
-#define        mscp_unitflgs   mscp_un.mscp_getunitsts.Mscp_unitflgs
-#define        mscp_hostid     mscp_un.mscp_getunitsts.Mscp_hostid
-#define        mscp_unitid     mscp_un.mscp_getunitsts.Mscp_unitid
-#define        mscp_mediaid    mscp_un.mscp_getunitsts.Mscp_mediaid
-#define        mscp_format     mscp_un.mscp_getunitsts.Mscp_format /* density:0=high */
-#define        mscp_speed      mscp_un.mscp_getunitsts.Mscp_speed  /* (ips*bpi)/1000 */
-#define        mscp_fmtmenu    mscp_un.mscp_getunitsts.Mscp_fmtmenu
-/*
- * Online / Set Unit Characteristics end packet
- */
-#define        mscp_maxwrt     mscp_dscptr     /* max write byte count */
-#define        mscp_noiserec   mscp_cylinder   /* noise record */
-/*
- * Set Controller Characteristics end packet
- */
-#define        mscp_cnttmo     mscp_hsttmo     /* controller timeout */
-#define        mscp_cntcmdl    mscp_usefrac    /* controller soft & hardware version */
-#define        mscp_cntid      mscp_unitid     /* controller id */
-/*
- * Error Log message format codes
- */
-#define        M_FM_CNTERR     0       /* Controller error */
-#define        M_FM_BUSADDR    1       /* Host memory access error */
-#define        M_FM_TAPETRN    5       /* Tape transfer error */
-#define        M_FM_STIERR     6       /* STI communication or command failure */
-#define        M_FM_STIDEL     7       /* STI drive error log */
-#define        M_FM_STIFEL   010       /* STI formatter error log */
-/*
- * Error Log message flags
- */
-#define        M_LF_SUCC       0200    /* Operation successful */
-#define        M_LF_CONT       0100    /* Operation continuing */
-#define        M_LF_SQNRS      0001    /* Sequence number reset */
-/*
- * Tape Format Flag Values
- */
-#define        M_TF_800        001     /* NRZI 800 bpi */
-#define        M_TF_PE         002     /* Phase Encoded 1600 bpi */
-#define        M_TF_GCR        004     /* Group Code Recording 6250 bpi */
-#define        M_TF_BLK        010     /* Cartridge Block Mode */
-/*
- * MSCP Error Log packet
- *
- *     NOTE: MSCP packet must be padded to this size.
- */
-struct mslg {
-       struct  mscp_header mslg_header;/* device specific header */
-       long    mslg_cmdref;            /* command reference number */
-       short   mslg_unit;              /* unit number */
-       short   mslg_seqnum;            /* sequence number */
-       u_char  mslg_format;            /* format */
-       u_char  mslg_flags;             /* error log message flags */
-       short   mslg_event;             /* event code */
-       quad_t  mslg_cntid;             /* controller id */
-       u_char  mslg_cntsvr;            /* controller software version */
-       u_char  mslg_cnthvr;            /* controller hardware version */
-       short   mslg_multunt;           /* multi-unit code */
-       quad_t  mslg_unitid;            /* unit id */
-       u_char  mslg_unitsvr;           /* unit software version */
-       u_char  mslg_unithvr;           /* unit hardware version */
-       short   mslg_group;             /* group; retry + level */
-       long    mslg_position;          /* position (object count) */
-       u_char  mslg_fmtsvr;            /* formatter software version */
-       u_char  mslg_fmthvr;            /* formatter hardware version */
-       short   mslg_xxx2;              /* unused */
-       char    mslg_stiunsucc[62];     /* STI status information */
-};
-#define        mslg_sdecyl     mslg_group
-
index d81c18d..e574f21 100644 (file)
@@ -1,4 +1,4 @@
-/*      $NetBSD: trap.c,v 1.21 1996/05/19 16:44:27 ragge Exp $     */
+/*      $NetBSD: trap.c,v 1.24 1996/11/06 20:19:55 cgd Exp $     */
 
 /*
  * Copyright (c) 1994 Ludd, University of Lule}, Sweden.
@@ -89,8 +89,8 @@ userret(p, pc, psl)
                  * Since we are curproc, clock will normally just change
                  * our priority without moving us from one queue to another
                  * (since the running process is not on a queue.)
-                 * If that happened after we setrq ourselves but before we
-                 * swtch()'ed, we might not be on the queue indicated by
+                 * If that happened after we setrunqueue ourselves but before
+                * we swtch()'ed, we might not be on the queue indicated by
                  * our priority.
                  */
                 s=splstatclock();
diff --git a/sys/arch/vax/vax/uvax.c b/sys/arch/vax/vax/uvax.c
new file mode 100644 (file)
index 0000000..ce9df0e
--- /dev/null
@@ -0,0 +1,287 @@
+/*     $NetBSD: uvax.c,v 1.3 1996/10/13 03:36:03 christos Exp $ */
+/*
+ * Copyright (c) 1996 Ludd, University of Lule}, Sweden.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Ludd by Bertram Barth.
+ *
+ * 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 at Ludd, University of 
+ *      Lule}, Sweden and its contributors.
+ * 4. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * generic(?) MicroVAX and VAXstation support
+ *
+ * There are similarities to struct cpu_calls[] in autoconf.c
+ */
+
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/device.h>
+#include <vm/vm.h>
+#include <vm/vm_kern.h>
+
+#include <machine/pte.h>
+#include <machine/mtpr.h>
+#include <machine/sid.h>
+#include <machine/pmap.h>
+#include <machine/nexus.h>
+#include <machine/uvax.h>
+
+#define xtrace(x)
+#define xdebug(x)
+
+
+struct uvax_calls guc;                 /* Generic uVAX Calls */
+/* struct uvax_calls *ucp = &guc;      /* not yet public !!! */
+static int uvax_callsSetup = 0;                /* not yet setup */
+
+u_long uVAX_phys2virt __P((u_long, struct uc_map *));
+
+/* u_long      uVAX_physmap;   /* XXX  another ugly hack... */
+int 
+uvax_notavail(s)
+       char *s;
+{
+       printf("\"%s()\" not available for uVAX (%s)\n", s, guc.uc_name);
+       /*
+        * should we panic() here???
+        */
+       return(0);
+}
+
+int
+uvax_setup(flags)
+       int flags;
+{
+       /*
+        * insert some defaults here !!!
+        */
+
+       /*
+        * Now call the specific routines to overwrite these defaults
+        */
+       switch (vax_boardtype) {
+#ifdef VAX630
+       case VAX_BTYP_630:
+               ka630_setup(&guc, flags);
+               break;
+#endif
+#ifdef VAX410
+       case VAX_BTYP_410:
+               ka410_setup(&guc, flags);
+               break;
+#endif
+#ifdef VAX43
+       case VAX_BTYP_43:
+               ka43_setup(&guc, flags);
+               break;
+#endif
+       default:
+               printf("don't know how to handle 0x%x\n", vax_boardtype);
+               printf("Let's try using the defaults...\n");
+       }
+       uvax_callsSetup = 1;
+}
+
+/*
+ * XXX_steal_pages() is the first cpu/board specific function to be called.
+ * Thus we use this call to setup the dispatch structure for further use.
+ *
+ * We should have a special setup-routine !!!
+ */
+void
+uvax_steal_pages()
+{
+       if (uvax_callsSetup == 0)
+               uvax_setup(0);
+
+       /*
+        * now that specific functions are inserted, we can call 'em
+        */
+       if (guc.uc_steal_pages) {
+               (guc.uc_steal_pages)(); 
+               return;
+       }
+       uvax_notavail("uc_steal_pages");
+}
+
+u_long 
+uvax_phys2virt(paddr)
+       u_long paddr;
+{
+       if (guc.uc_phys2virt)
+               return ((guc.uc_phys2virt)(paddr));
+       if (guc.uc_physmap)
+               return (uVAX_phys2virt(paddr, guc.uc_physmap));
+       uvax_notavail("uc_phys2virt");
+       return (0);
+}
+
+void
+uvax_conf(parent, self, aux)
+       struct  device *parent, *self;
+       void    *aux;
+{
+       if (guc.uc_conf) {
+               (guc.uc_conf)(parent, self, aux);
+               return;
+       }
+       uvax_notavail("uc_conf");
+}
+
+void
+uvax_memerr()
+{
+       xtrace(("uvax_memerr()\n"));
+
+       if (guc.uc_memerr) {
+               (guc.uc_memerr)(); 
+               return;
+       }
+       uvax_notavail("uc_memerr");
+}
+
+int
+uvax_mchk(addr)
+       caddr_t addr;
+{
+       xtrace(("uvax_mchk(0x%x)\n", addr));
+
+       if (guc.uc_mchk)
+               return ((guc.uc_mchk)(addr));
+       uvax_notavail("uc_mchk");
+       return (-1);
+}
+
+int
+uvax_clkread(base)
+       time_t base;
+{
+       if (guc.uc_clkread)
+               return ((guc.uc_clkread)(base));
+       uvax_notavail("uc_clkread");
+}
+
+void
+uvax_clkwrite()
+{
+       if (guc.uc_clkwrite)
+               (guc.uc_clkwrite)();
+       else
+               uvax_notavail("uc_clkwrite");
+       return;
+}
+
+/*
+ * NB: mapping should/must be done in chunks of PAGE_SIZE (ie. 1024), 
+ *     while pmap_map() expects size to be in chunks of NBPG (ie. 512).
+ * 
+ * Thus we round down the start-address to be aligned wrt PAGE_SIZE and
+ * the end-address up to be just beyond the next multiple of PAGE_SIZE.
+ * size is the number of bytes between start and end expressed in NBPG.
+ */
+int 
+uVAX_old_fillmap(um)
+       struct uc_map *um;
+{
+       extern  vm_offset_t avail_start, virtual_avail, avail_end;
+       register struct uc_map *p;
+       register u_int base, end, size;
+
+       for (p = um; p->um_base != 0; p++) {
+               base = p->um_base & ~PAGE_SIZE;         /* round base down */
+               end = ROUND_PAGE(p->um_end + 1) - 1;    /* round end up */
+               size = (end - base + 1) / NBPG;         /* size in pages */
+               MAPVIRT(p->um_virt, size);
+               pmap_map((vm_offset_t)p->um_virt, base, end, 
+                        VM_PROT_READ|VM_PROT_WRITE);
+
+               xdebug(("uVAX_fillmap: %x:%x[%x] (%x:%x[%x]) --> %x\n", 
+                       p->um_base, p->um_end, p->um_size, 
+                       base, end, size, p->um_virt));
+
+       }
+}
+
+/*
+ * NB: mapping should/must be done in chunks of PAGE_SIZE (ie. 1024), 
+ *     while pmap_map() expects size to be in chunks of NBPG (ie. 512).
+ * 
+ * Thus we round down the start-address to be aligned wrt PAGE_SIZE and
+ * the end-address up to be just beyond the next multiple of PAGE_SIZE.
+ * size is the number of bytes between start and end expressed in NBPG.
+ */
+int 
+uVAX_fillmap(um)
+       struct uc_map *um;
+{
+       extern  vm_offset_t avail_start, virtual_avail, avail_end;
+       register struct uc_map *p;
+       register u_int base, end, off, size;
+
+       for (p = um; p->um_base != 0; p++) {
+               base = TRUNC_PAGE(p->um_base);          /* round base down */
+               off = p->um_base - base;
+               size = ROUND_PAGE(off + p->um_size);
+               if (size < PAGE_SIZE) {
+                       printf("invalid size %d in uVAX_fillmap\n", size);
+                       size = PAGE_SIZE;
+               }
+               end = base + size - 1;
+               MAPVIRT(p->um_virt, size/NBPG);
+               pmap_map((vm_offset_t)p->um_virt, base, end, 
+                        VM_PROT_READ|VM_PROT_WRITE);
+
+               xdebug(("uVAX_fillmap: %x:%x[%x] (%x:%x[%x]) --> %x\n", 
+                       p->um_base, p->um_end, p->um_size, 
+                       base, end, size, p->um_virt));
+
+       }
+}
+
+u_long
+uVAX_phys2virt(phys,um)
+       u_long phys;
+       struct uc_map *um;
+{
+       register struct uc_map *p;
+       u_long virt = 0;
+
+       for (p = um; p->um_base != 0; p++) {
+               if (p->um_base > phys || p->um_end < phys)
+                       continue;
+               virt = p->um_virt + (phys - trunc_page(p->um_base));
+               break;
+       }
+
+       if (virt == 0) {
+               printf("invalid argument 0x%x to uvax_phys2virt()\n", phys);
+               /* should we panic() here ??? */
+       }
+
+       return (virt);
+}
index fe11591..57eb4bc 100644 (file)
@@ -1,4 +1,4 @@
-/*     $NetBSD: uvaxII.c,v 1.8 1996/04/08 18:32:59 ragge Exp $ */
+/*     $NetBSD: uvaxII.c,v 1.10 1996/10/13 03:36:04 christos Exp $     */
 
 /*-
  * Copyright (c) 1994 Gordon W. Ross 
diff --git a/sys/arch/vax/vax/uvax_proto.c b/sys/arch/vax/vax/uvax_proto.c
new file mode 100644 (file)
index 0000000..4cf9e98
--- /dev/null
@@ -0,0 +1,142 @@
+/*     $NetBSD: uvax_proto.c,v 1.3 1996/10/13 03:36:06 christos Exp $  */
+/*-
+ * Copyright (c) 1982, 1988, 1990, 1993
+ *     The Regents of the University of California.  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.
+ *
+ */
+
+/*
+ * MicroVAX and VAXstation and their different models have many 
+ * similarities and also many very specific implementations/solutions.
+ * Thus this is a trial to have generic and prototypic routines
+ * which can be used instead of specific routines whenever possible.
+ *
+ * usually there are groups of machines using the same CPU chips, eg.
+ *     MicroVAX II
+ *     MicroVAX 2000
+ *     VAXstation 2000
+ * have the same CPU and thus can share the CPU dependent code.
+ *
+ * On the other hand the above machines are quite differnet wrt. the
+ * way the board-specific details (system-bus, NVRAM layout, etc.)
+ * and thus can't share this code. 
+ *
+ * It's also possible to find groups of machines which have enough
+ * similarities wrt. to board-specific implementations, to share some
+ * code between them. Eg.
+ *     VAXstation 2000
+ *     VAXstation 3100 (which models ???)
+ *     VAXstation 4000 (which models ???)
+ * use the same (nonexistent "virtual") system-bus and thus can share
+ * some pieces of code...
+ */
+
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/device.h>
+
+#include <machine/mtpr.h>
+
+static int
+uVAX_clkread(base)
+       time_t base;
+{
+       register struct uVAX_clock *claddr = uVAX_clkptr;
+       struct chiptime c;
+       int timeout = 1<<15, rv;
+
+       claddr->csr1 = uVAX_CLKSET;
+       while ((claddr->csr0 & uVAX_CLKUIP) != 0)
+               if (--timeout == 0) {
+                       printf ("TOY clock timed out");
+                       return CLKREAD_BAD;
+               }
+
+       c.sec = claddr->sec;
+       c.min = claddr->min;
+       c.hour = claddr->hr;
+       c.day = claddr->day;
+       c.mon = claddr->mon;
+       c.year = claddr->yr;
+
+       /* If the clock is valid, use it. */
+       if ((claddr->csr3 & uVAX_CLKVRT) != 0 &&
+           (claddr->csr1 & uVAX_CLKENABLE) == uVAX_CLKENABLE) {
+               /* simple sanity checks */
+               time.tv_sec = chiptotime(&c);
+               if (c.mon < 1 || c.mon > 12 ||
+                   c.day < 1 || c.day > 31) {
+                       printf("WARNING: preposterous clock chip time");
+                       rv = CLKREAD_WARN;
+               } else
+                       rv = CLKREAD_OK;
+
+               claddr->csr0 = uVAX_CLKRATE;
+               claddr->csr1 = uVAX_CLKENABLE;
+               return rv;
+       }
+
+       printf("WARNING: TOY clock invalid");
+       return CLKREAD_BAD;
+}
+
+/* Set the time of day clock, called via. stime system call.. */
+static void
+uVAX_clkwrite()
+{
+       register struct uVAX_clock *claddr = uVAX_clkptr;
+       struct chiptime c;
+       int timeout = 1<<15;
+       int s;
+
+       timetochip(&c);
+
+       s = splhigh();
+
+       claddr->csr1 = uVAX_CLKSET;
+       while ((claddr->csr0 & uVAX_CLKUIP) != 0)
+               if (--timeout == 0) {
+                       printf("Trouble saving date, TOY clock timed out\n");
+                       break;
+               }
+       claddr->sec = c.sec;
+       claddr->min = c.min;
+       claddr->hr  = c.hour;
+       claddr->day = c.day;
+       claddr->mon = c.mon;
+       claddr->yr  = c.year;
+
+       claddr->csr0 = uVAX_CLKRATE;
+       claddr->csr1 = uVAX_CLKENABLE;
+
+       splx(s);
+}
index 60a486b..c39957a 100644 (file)
@@ -1,4 +1,4 @@
-/*      $NetBSD: vm_machdep.c,v 1.25 1996/05/19 16:44:33 ragge Exp $       */
+/*      $NetBSD: vm_machdep.c,v 1.30 1997/01/11 11:23:09 ragge Exp $       */
 
 /*
  * Copyright (c) 1994 Ludd, University of Lule}, Sweden.
@@ -56,6 +56,7 @@
 #include <machine/pcb.h>
 #include <machine/frame.h>
 #include <machine/cpu.h>
+#include <machine/sid.h>
 
 #include <sys/syscallargs.h>
 
@@ -295,16 +296,19 @@ idle:
 /* Should check that values is in bounds XXX */
 int
 copyinstr(from, to, maxlen, lencopied)
-       void *from, *to;
-       u_int *lencopied,maxlen;
+       const void *from;
+       void *to;
+       size_t *lencopied;
+       size_t maxlen;
 {
        u_int i;
        void *addr=&curproc->p_addr->u_pcb.iftrap;
-       char *gfrom=from, *gto=to;
+       const char *gfrom = from;
+       char *gto = to;
 
        asm("movl $Lstr,(%0)":: "r"(addr));
        for(i=0;i<maxlen;i++){
-               *(gto+i)=*(gfrom+i);
+               *(gto +i )=*(gfrom + i);
                if(!(*(gto+i))) goto ok;
        }
 
@@ -319,11 +323,14 @@ asm("Lstr:        ret");
 /* Should check that values is in bounds XXX */
 int
 copyoutstr(from, to, maxlen, lencopied)
-       void *from, *to;
-       u_int *lencopied,maxlen;
+       const   void *from;
+       void    *to;
+       size_t  *lencopied;
+       size_t  maxlen;
 {
        u_int i;
-       char *gfrom=from, *gto=to;
+       const char *gfrom=from;
+       char *gto=to;
         void *addr=&curproc->p_addr->u_pcb.iftrap;
 
         asm("movl $Lstr,(%0)":: "r"(addr));
@@ -510,13 +517,14 @@ cpu_coredump(p, vp, cred, chdr)
         return error;
 }
 
-int    locopyout __P((void *, void *, size_t, void *));
-int    locopyin __P((void *, void *, size_t, void *));
+int    locopyout __P((const void *, void *, size_t, void *));
+int    locopyin __P((const void *, void *, size_t, void *));
 
 int
 copyout(from, to, len)
-       void *from, *to;
-       size_t len;
+       const   void *from;
+       void    *to;
+       size_t  len;
 {
        void *addr=&curproc->p_addr->u_pcb.iftrap;
 
@@ -525,8 +533,9 @@ copyout(from, to, len)
 
 int
 copyin(from, to, len)
-       void *from, *to;
-       size_t len;
+       const   void *from;
+       void    *to;
+       size_t  len;
 {
        void *addr = &curproc->p_addr->u_pcb.iftrap;
 
@@ -562,3 +571,60 @@ cpu_swapin(p)
        *j = 0; /* Set kernel stack red zone */
 #endif
 }
+
+#if VAX410 || VAX43
+/*
+ * vmapbuf()/vunmapbuf() only used on some vaxstations without
+ * any busadapter with MMU.
+ * XXX - This must be reworked to be effective.
+ */
+void
+vmapbuf(bp, len)
+        struct buf *bp;
+        vm_size_t len;
+{
+        vm_offset_t faddr, taddr, off, pa;
+        pmap_t fmap, tmap;
+
+       if ((vax_boardtype != VAX_BTYP_43) && (vax_boardtype != VAX_BTYP_410))
+               return;
+        faddr = trunc_page(bp->b_saveaddr = bp->b_data);
+        off = (vm_offset_t)bp->b_data - faddr;
+        len = round_page(off + len);
+        taddr = kmem_alloc_wait(phys_map, len);
+        bp->b_data = (caddr_t)(taddr + off);
+        fmap = vm_map_pmap(&bp->b_proc->p_vmspace->vm_map);
+        tmap = vm_map_pmap(phys_map);
+        len = len >> PGSHIFT;
+        while (len--) {
+                pa = pmap_extract(fmap, faddr);
+                if (pa == 0)
+                        panic("vmapbuf: null page frame for %x", faddr);
+                pmap_enter(tmap, taddr, pa & ~(NBPG - 1),
+                           VM_PROT_READ|VM_PROT_WRITE, TRUE);
+                faddr += NBPG;
+                taddr += NBPG;
+        }
+}
+
+/*
+ * Free the io map PTEs associated with this IO operation.
+ * We also invalidate the TLB entries and restore the original b_addr.
+ */
+void
+vunmapbuf(bp, len)
+        struct buf *bp;
+        vm_size_t len;
+{
+        vm_offset_t addr, off;
+
+       if ((vax_boardtype != VAX_BTYP_43) && (vax_boardtype != VAX_BTYP_410))
+               return;
+        addr = trunc_page(bp->b_data);
+        off = (vm_offset_t)bp->b_data - addr;
+        len = round_page(off + len);
+        kmem_free_wakeup(phys_map, addr, len);
+        bp->b_data = bp->b_saveaddr;
+        bp->b_saveaddr = 0;
+}
+#endif
diff --git a/sys/arch/vax/vsa/dc.c b/sys/arch/vax/vsa/dc.c
new file mode 100644 (file)
index 0000000..f9d5de9
--- /dev/null
@@ -0,0 +1,1026 @@
+/*     $NetBSD: dc.c,v 1.4 1996/10/13 03:36:10 christos Exp $  */
+/*-
+ * 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.
+ *
+ *     @(#)dc.c        8.2 (Berkeley) 11/30/93
+ */
+
+/*
+ * devDC7085.c --
+ *
+ *     This file contains machine-dependent routines that handle the
+ *     output queue for the serial lines.
+ *
+ *     Copyright (C) 1989 Digital Equipment Corporation.
+ *     Permission to use, copy, modify, and distribute this software and
+ *     its documentation for any purpose and without fee is hereby granted,
+ *     provided that the above copyright notice appears in all copies.
+ *     Digital Equipment Corporation makes no representations about the
+ *     suitability of this software for any purpose.  It is provided "as is"
+ *     without express or implied warranty.
+ *
+ * from: Header: /sprite/src/kernel/dev/ds3100.md/RCS/devDC7085.c,
+ *     v 1.4 89/08/29 11:55:30 nelson Exp  SPRITE (DECWRL)";
+ */
+
+#include "dc.h"
+#if NDC > 0
+/*
+ * DC7085 (DZ-11 look alike) Driver
+ *
+ * bertram 13-apr-1996: slightly modfied for DC367B in VS2000
+ */
+#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>
+
+/*
+ * bertram 17-apr-1996: we could use most of the include files directly
+ *                     from the pmax port, only some of the paddings need
+ *                     to be changed. For now we use modified copies...
+ *
+ * #include <pmax/include/dc7085cons.h>
+ * #include <pmax/include/pmioctl.h>
+ *
+ * #include <pmax/dev/pdma.h>
+ * #include <pmax/dev/lk201.h>
+ */
+#include "dc7085cons.h"                        /* this one is modified !!! */
+#include <pmax/include/pmioctl.h>
+#include <pmax/dev/pdma.h>
+#include <pmax/dev/lk201.h>
+
+#include <sys/device.h>
+
+/*
+ * here follow some pmax specific includes which we don't need...
+ */
+#ifdef pmax
+#include <machine/autoconf.h>
+#include <machine/machConst.h>
+#include <pmax/pmax/pmaxtype.h>
+#include <pmax/pmax/cons.h>
+#endif
+
+#ifdef vax
+#include <machine/sid.h>
+#include <machine/uvax.h>
+#include <machine/vsbus.h>
+#include <pmax/pmax/cons.h>    /* we need to modify this for VAXen */
+#define MachEmptyWriteBuffer() /* we don't need this for VAXstation */
+#endif
+
+#include <pmax/dev/dcvar.h>
+
+struct dc_softc {
+       struct device sc_dv;
+       struct pdma dc_pdma[4];
+       void    *xmit_cfargs;
+       void    *recv_cfargs;
+};
+
+/*
+ * Autoconfiguration data for config.
+ * 
+ * Use the statically-allocated softc until old autoconfig code and
+ * config.old are completely gone.
+ */
+int    dcmatch  __P((struct device * parent, void *cfdata, void *aux));
+void   dcattach __P((struct device *parent, struct device *self, void *aux));
+
+int    dc_doprobe __P((void *addr, int unit, int flags, int pri));
+int    dcintr __P((void * xxxunit));
+
+struct cfdriver dc_cd = {
+       NULL, "dc", DV_TTY
+};
+struct cfattach dc_ca = {
+       sizeof(struct dc_softc), dcmatch, dcattach
+};
+
+
+#define NDCLINE                (NDC*4)
+
+void dcstart   __P((struct tty *));
+void dcxint    __P((struct tty *));
+void dcPutc    __P((dev_t, int));
+void dcscan    __P((void *));
+extern void ttrstrt __P((void *));
+int dcGetc     __P((dev_t));
+int dcparam    __P((struct tty *, struct termios *));
+
+struct tty *dc_tty[NDCLINE];
+int    dc_cnt = NDCLINE;
+void   (*dcDivertXInput)();    /* X windows keyboard input routine */
+void   (*dcMouseEvent)();      /* X windows mouse motion event routine */
+void   (*dcMouseButtons)();    /* X windows mouse buttons event routine */
+#ifdef DEBUG
+int    debugChar;
+#endif
+
+/*
+ * Software copy of brk register since it isn't readable
+ */
+int    dc_brk[NDC];
+char   dcsoftCAR[NDC];         /* mask of dc's with carrier on (DSR) */
+
+/*
+ * The DC7085 doesn't interrupt on carrier transitions, so
+ * we have to use a timer to watch it.
+ */
+int    dc_timer;               /* true if timer started */
+
+/*
+ * Pdma structures for fast output code
+ */
+struct pdma dcpdma[NDCLINE];
+
+struct speedtab dcspeedtab[] = {
+       0,      0,
+       50,     LPR_B50,
+       75,     LPR_B75,
+       110,    LPR_B110,
+       134,    LPR_B134,
+       150,    LPR_B150,
+       300,    LPR_B300,
+       600,    LPR_B600,
+       1200,   LPR_B1200,
+       1800,   LPR_B1800,
+       2400,   LPR_B2400,
+       4800,   LPR_B4800,
+       9600,   LPR_B9600,
+       19200,  LPR_B19200,
+       -1,     -1
+};
+
+#ifndef PORTSELECTOR
+#define ISPEED TTYDEF_SPEED
+#define LFLAG  TTYDEF_LFLAG
+#else
+#define ISPEED B4800
+#define LFLAG  (TTYDEF_LFLAG & ~ECHO)
+#endif
+
+static struct {
+       void    *xmit_cfargs;
+       void    *recv_cfargs;
+} vs2000_hack = { NULL, NULL };
+
+/*
+ * Match driver based on name
+ */
+int
+dcmatch(parent, match, aux)
+       struct device *parent;
+       void *match;
+       void *aux;
+{
+       struct cfdata *cf = match;
+       struct confargs *ca = aux;
+
+       static int nunits = 0;
+
+       return (0);
+
+       if (strcmp(ca->ca_name, "dc") != 0 &&
+           strcmp(ca->ca_name, "mdc") != 0 &&
+           strcmp(ca->ca_name, "dc367") != 0 &&
+           strcmp(ca->ca_name, "dc7085") != 0)
+               return (0);
+
+       /*
+        * Use statically-allocated softc and attach code until
+        * old config is completely gone.  Don't  over-run softc.
+        */
+       if (nunits > NDC) {
+               printf("dc: too many units for old config\n");
+               return (0);
+       }
+       nunits++;
+       return (1);
+}
+
+void
+dcattach(parent, self, aux)
+       struct device *parent;
+       struct device *self;
+       void *aux;
+{
+       register struct confargs *ca = aux;
+       u_long dcaddr;
+
+       dcaddr = (u_long)ca->ca_ioaddr;
+       (void) dc_doprobe((void*)uvax_phys2virt(dcaddr),
+                         self->dv_unit, self->dv_cfdata->cf_flags,
+                         ca->ca_intslot);
+
+       /* tie pseudo-slot to device */
+#ifdef notyet
+       vsbus_intr_register(ca, dcintr, self);
+       vsbus_intr_enable(ca);
+#endif
+       printf("\n");
+}
+
+/*
+ * Is there a framebuffer console device using this serial driver?
+ * XXX used for ugly special-cased console input that should be redone
+ * more cleanly.
+ */
+static inline int
+raster_console()
+{
+       return (cn_tab->cn_pri == CN_INTERNAL ||
+               cn_tab->cn_pri == CN_NORMAL);
+}
+
+
+/*
+ * DC7085 (dz-11) probe routine from old-style config.
+ * This is only here out of intertia.
+ */
+int
+dc_doprobe(addr, unit, flags, priority)
+       void *addr;
+       int unit, flags, priority;
+{
+       register dcregs *dcaddr;
+       register struct pdma *pdp;
+       register struct tty *tp;
+       register int cntr;
+       int s;
+
+       if (unit >= NDC)
+               return (0);
+       if (badaddr(addr, 2))
+               return (0);
+
+       /*
+        * For a remote console, wait a while for previous output to
+        * complete.
+        */
+       if (major(cn_tab->cn_dev) == DCDEV && unit == 0 &&
+               cn_tab->cn_pri == CN_REMOTE)
+               DELAY(10000);
+
+       /* reset chip */
+       dcaddr = (dcregs *)addr;
+       dcaddr->dc_csr = CSR_CLR;
+       MachEmptyWriteBuffer();
+       while (dcaddr->dc_csr & CSR_CLR)
+               ;
+       dcaddr->dc_csr = CSR_MSE | CSR_TIE | CSR_RIE;
+
+       /* init pseudo DMA structures */
+       pdp = &dcpdma[unit * 4];
+       for (cntr = 0; cntr < 4; cntr++) {
+               pdp->p_addr = (void *)dcaddr;
+               tp = dc_tty[unit * 4 + cntr] = ttymalloc();
+               pdp->p_arg = (int) tp;
+               pdp->p_fcn = dcxint;
+               pdp++;
+       }
+       dcsoftCAR[unit] = flags | 0xB;
+
+       if (dc_timer == 0) {
+               dc_timer = 1;
+               timeout(dcscan, (void *)0, hz);
+       }
+
+       /*
+        * Special handling for consoles.
+        */
+       if (unit == 0) {
+               if (cn_tab->cn_pri == CN_INTERNAL ||
+                   cn_tab->cn_pri == CN_NORMAL) {
+                       s = spltty();
+                       dcaddr->dc_lpr = LPR_RXENAB | LPR_8_BIT_CHAR |
+                               LPR_B4800 | DCKBD_PORT;
+                       MachEmptyWriteBuffer();
+                       dcaddr->dc_lpr = LPR_RXENAB | LPR_B4800 | LPR_OPAR |
+                               LPR_PARENB | LPR_8_BIT_CHAR | DCMOUSE_PORT;
+                       MachEmptyWriteBuffer();
+                       DELAY(1000);
+                       KBDReset(makedev(DCDEV, DCKBD_PORT), dcPutc);
+                       MouseInit(makedev(DCDEV, DCMOUSE_PORT), dcPutc, dcGetc);
+                       splx(s);
+               } else if (major(cn_tab->cn_dev) == DCDEV) {
+                       s = spltty();
+                       dcaddr->dc_lpr = LPR_RXENAB | LPR_8_BIT_CHAR |
+                               LPR_B9600 | minor(cn_tab->cn_dev);
+                       MachEmptyWriteBuffer();
+                       DELAY(1000);
+                       /*cn_tab.cn_disabled = 0;*/ /* FIXME */
+                       splx(s);
+               }
+       }
+
+       return (1);
+}
+
+dcopen(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 >= dc_cnt || dcpdma[unit].p_addr == (void *)0)
+               return (ENXIO);
+       tp = dc_tty[unit];
+       if (tp == NULL)
+               tp = dc_tty[unit] = ttymalloc();
+       tp->t_oproc = dcstart;
+       tp->t_param = dcparam;
+       tp->t_dev = dev;
+       if ((tp->t_state & TS_ISOPEN) == 0) {
+               tp->t_state |= TS_WOPEN;
+               ttychars(tp);
+#ifndef PORTSELECTOR
+               if (tp->t_ispeed == 0) {
+#endif
+                       tp->t_iflag = TTYDEF_IFLAG;
+                       tp->t_oflag = TTYDEF_OFLAG;
+                       tp->t_cflag = TTYDEF_CFLAG;
+                       tp->t_lflag = LFLAG;
+                       tp->t_ispeed = tp->t_ospeed = ISPEED;
+#ifdef PORTSELECTOR
+                       tp->t_cflag |= HUPCL;
+#else
+               }
+#endif
+               (void) dcparam(tp, &tp->t_termios);
+               ttsetwater(tp);
+       } else if ((tp->t_state & TS_XCLUDE) && curproc->p_ucred->cr_uid != 0)
+               return (EBUSY);
+       (void) dcmctl(dev, DML_DTR, DMSET);
+       s = spltty();
+       while (!(flag & O_NONBLOCK) && !(tp->t_cflag & CLOCAL) &&
+              !(tp->t_state & TS_CARR_ON)) {
+               tp->t_state |= TS_WOPEN;
+               if (error = ttysleep(tp, (caddr_t)&tp->t_rawq, TTIPRI | PCATCH,
+                   ttopen, 0))
+                       break;
+       }
+       splx(s);
+       if (error)
+               return (error);
+       return ((*linesw[tp->t_line].l_open)(dev, tp));
+}
+
+/*ARGSUSED*/
+dcclose(dev, flag, mode, p)
+       dev_t dev;
+       int flag, mode;
+       struct proc *p;
+{
+       register struct tty *tp;
+       register int unit, bit;
+
+       unit = minor(dev);
+       tp = dc_tty[unit];
+       bit = 1 << ((unit & 03) + 8);
+       if (dc_brk[unit >> 2] & bit) {
+               dc_brk[unit >> 2] &= ~bit;
+               ttyoutput(0, tp);
+       }
+       (*linesw[tp->t_line].l_close)(tp, flag);
+       if ((tp->t_cflag & HUPCL) || (tp->t_state & TS_WOPEN) ||
+           !(tp->t_state & TS_ISOPEN))
+               (void) dcmctl(dev, 0, DMSET);
+       return (ttyclose(tp));
+}
+
+dcread(dev, uio, flag)
+       dev_t dev;
+       struct uio *uio;
+{
+       register struct tty *tp;
+
+       tp = dc_tty[minor(dev)];
+       return ((*linesw[tp->t_line].l_read)(tp, uio, flag));
+}
+
+dcwrite(dev, uio, flag)
+       dev_t dev;
+       struct uio *uio;
+{
+       register struct tty *tp;
+
+       tp = dc_tty[minor(dev)];
+       return ((*linesw[tp->t_line].l_write)(tp, uio, flag));
+}
+
+struct tty *
+dctty(dev)
+       dev_t dev;
+{
+       struct tty *tp = dc_tty [minor (dev)];
+       return (tp);
+}
+
+/*ARGSUSED*/
+dcioctl(dev, cmd, data, flag, p)
+       dev_t dev;
+       int cmd;
+       caddr_t data;
+       int flag;
+       struct proc *p;
+{
+       register struct tty *tp;
+       register int unit = minor(dev);
+       register int dc = unit >> 2;
+       int error;
+
+       tp = dc_tty[unit];
+       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:
+               dc_brk[dc] |= 1 << ((unit & 03) + 8);
+               ttyoutput(0, tp);
+               break;
+
+       case TIOCCBRK:
+               dc_brk[dc] &= ~(1 << ((unit & 03) + 8));
+               ttyoutput(0, tp);
+               break;
+
+       case TIOCSDTR:
+               (void) dcmctl(dev, DML_DTR|DML_RTS, DMBIS);
+               break;
+
+       case TIOCCDTR:
+               (void) dcmctl(dev, DML_DTR|DML_RTS, DMBIC);
+               break;
+
+       case TIOCMSET:
+               (void) dcmctl(dev, *(int *)data, DMSET);
+               break;
+
+       case TIOCMBIS:
+               (void) dcmctl(dev, *(int *)data, DMBIS);
+               break;
+
+       case TIOCMBIC:
+               (void) dcmctl(dev, *(int *)data, DMBIC);
+               break;
+
+       case TIOCMGET:
+               *(int *)data = dcmctl(dev, 0, DMGET);
+               break;
+
+       default:
+               return (ENOTTY);
+       }
+       return (0);
+}
+
+dcparam(tp, t)
+       register struct tty *tp;
+       register struct termios *t;
+{
+       register dcregs *dcaddr;
+       register int lpr;
+       register int cflag = t->c_cflag;
+       int unit = minor(tp->t_dev);
+       int ospeed = ttspeedtab(t->c_ospeed, dcspeedtab);
+
+       /* check requested parameters */
+       if (ospeed < 0 || (t->c_ispeed && t->c_ispeed != t->c_ospeed) ||
+           (cflag & CSIZE) == CS5 || (cflag & CSIZE) == CS6 ||
+           (vax_boardtype == -1 && t->c_ospeed == 19200))
+               return (EINVAL);
+       /* and copy to tty */
+       tp->t_ispeed = t->c_ispeed;
+       tp->t_ospeed = t->c_ospeed;
+       tp->t_cflag = cflag;
+
+       dcaddr = (dcregs *)dcpdma[unit].p_addr;
+
+       /*
+        * Handle console cases specially.
+        */
+       if (raster_console()) {
+               if (unit == DCKBD_PORT) {
+                       dcaddr->dc_lpr = LPR_RXENAB | LPR_8_BIT_CHAR |
+                               LPR_B4800 | DCKBD_PORT;
+                       MachEmptyWriteBuffer();
+                       return (0);
+               } else if (unit == DCMOUSE_PORT) {
+                       dcaddr->dc_lpr = LPR_RXENAB | LPR_B4800 | LPR_OPAR |
+                               LPR_PARENB | LPR_8_BIT_CHAR | DCMOUSE_PORT;
+                       MachEmptyWriteBuffer();
+                       return (0);
+               }
+       } else if (tp->t_dev == cn_tab->cn_dev) {
+               dcaddr->dc_lpr = LPR_RXENAB | LPR_8_BIT_CHAR |
+                       LPR_B9600 | unit;
+               MachEmptyWriteBuffer();
+               return (0);
+       }
+       if (ospeed == 0) {
+               (void) dcmctl(unit, 0, DMSET);  /* hang up line */
+               return (0);
+       }
+       lpr = LPR_RXENAB | ospeed | (unit & 03);
+       if ((cflag & CSIZE) == CS7)
+               lpr |= LPR_7_BIT_CHAR;
+       else
+               lpr |= LPR_8_BIT_CHAR;
+       if (cflag & PARENB)
+               lpr |= LPR_PARENB;
+       if (cflag & PARODD)
+               lpr |= LPR_OPAR;
+       if (cflag & CSTOPB)
+               lpr |= LPR_2_STOP;
+       dcaddr->dc_lpr = lpr;
+       MachEmptyWriteBuffer();
+       DELAY(10);
+       return (0);
+}
+
+/*
+ * Check for interrupts from all devices.
+ */
+int
+dcintr(xxxunit)
+       void *xxxunit;
+{
+       register struct dc_softc *sc = xxxunit;
+       register dcregs *dcaddr;
+       register unsigned csr;
+
+       register int unit = sc->sc_dv.dv_unit;
+
+       unit <<= 2;
+       dcaddr = (dcregs *)dcpdma[unit].p_addr;
+       while ((csr = dcaddr->dc_csr) & (CSR_RDONE | CSR_TRDY)) {
+               if (csr & CSR_RDONE)
+                       dcrint(unit);
+               if (csr & CSR_TRDY)
+                       dcxint(dc_tty[unit + ((csr >> 8) & 03)]);
+       }
+       /* XXX check for spurious interrupts */
+       return 0;
+}
+
+dcrint(unit)
+       register int unit;
+{
+       register dcregs *dcaddr;
+       register struct tty *tp;
+       register int c, cc;
+       int overrun = 0;
+
+       dcaddr = (dcregs *)dcpdma[unit].p_addr;
+       while ((c = dcaddr->dc_rbuf) < 0) {     /* char present */
+               cc = c & 0xff;
+               tp = dc_tty[unit + ((c >> 8) & 03)];
+               if ((c & RBUF_OERR) && overrun == 0) {
+                       log(LOG_WARNING, "dc%d,%d: silo overflow\n", unit >> 2,
+                               (c >> 8) & 03);
+                       overrun = 1;
+               }
+               /* the keyboard requires special translation */
+               if (tp == dc_tty[DCKBD_PORT] && raster_console()) {
+#ifdef KADB
+                       if (cc == LK_DO) {
+                               spl0();
+                               kdbpanic();
+                               return;
+                       }
+#endif
+#ifdef DEBUG
+                       debugChar = cc;
+#endif
+                       if (dcDivertXInput) {
+                               (*dcDivertXInput)(cc);
+                               return;
+                       }
+                       if ((cc = kbdMapChar(cc)) < 0)
+                               return;
+#ifdef notyet
+               } else if (tp == dc_tty[DCMOUSE_PORT] && dcMouseButtons) {
+                       mouseInput(cc);
+                       return;
+#endif
+               }
+               if (!(tp->t_state & TS_ISOPEN)) {
+                       wakeup((caddr_t)&tp->t_rawq);
+#ifdef PORTSELECTOR
+                       if (!(tp->t_state & TS_WOPEN))
+#endif
+                               return;
+               }
+               if (c & RBUF_FERR)
+                       cc |= TTY_FE;
+               if (c & RBUF_PERR)
+                       cc |= TTY_PE;
+               (*linesw[tp->t_line].l_rint)(cc, tp);
+       }
+       DELAY(10);
+}
+
+void
+dcxint(tp)
+       register struct tty *tp;
+{
+       register struct pdma *dp;
+       register dcregs *dcaddr;
+       int unit = minor(tp->t_dev);
+
+       dp = &dcpdma[unit];
+       if (dp->p_mem < dp->p_end) {
+               dcaddr = (dcregs *)dp->p_addr;
+               dcaddr->dc_tdr = dc_brk[unit >> 2] | *dp->p_mem++; 
+               MachEmptyWriteBuffer();
+               DELAY(10);
+               return;
+       }
+       tp->t_state &= ~TS_BUSY;
+       if (tp->t_state & TS_FLUSH)
+               tp->t_state &= ~TS_FLUSH;
+       else {
+               ndflush(&tp->t_outq, dp->p_mem - (caddr_t) tp->t_outq.c_cf);
+               dp->p_end = dp->p_mem = tp->t_outq.c_cf;
+       }
+       if (tp->t_line)
+               (*linesw[tp->t_line].l_start)(tp);
+       else
+               dcstart(tp);
+       if (tp->t_outq.c_cc == 0 || !(tp->t_state & TS_BUSY)) {
+               dcaddr = (dcregs *)dp->p_addr;
+               dcaddr->dc_tcr &= ~(1 << (unit & 03));
+               MachEmptyWriteBuffer();
+               DELAY(10);
+       }
+}
+
+void
+dcstart(tp)
+       register struct tty *tp;
+{
+       register struct pdma *dp;
+       register dcregs *dcaddr;
+       register int cc;
+       int s;
+
+       dp = &dcpdma[minor(tp->t_dev)];
+       dcaddr = (dcregs *)dp->p_addr;
+       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;
+       /* handle console specially */
+       if (tp == dc_tty[DCKBD_PORT] && raster_console()) {
+               while (tp->t_outq.c_cc > 0) {
+                       cc = getc(&tp->t_outq) & 0x7f;
+                       cnputc(cc);
+               }
+               /*
+                * After we flush the output queue we may need to wake
+                * up the process that made the output.
+                */
+               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);
+               }
+               goto out;
+       }
+       cc = ndqb(&tp->t_outq, 0);
+       if (cc == 0) 
+               goto out;
+
+       tp->t_state |= TS_BUSY;
+       dp->p_end = dp->p_mem = tp->t_outq.c_cf;
+       dp->p_end += cc;
+       dcaddr->dc_tcr |= 1 << (minor(tp->t_dev) & 03);
+       MachEmptyWriteBuffer();
+out:
+       splx(s);
+}
+
+/*
+ * Stop output on a line.
+ */
+/*ARGSUSED*/
+void
+dcstop(tp, flag)
+       register struct tty *tp;
+{
+       register struct pdma *dp;
+       register int s;
+
+       dp = &dcpdma[minor(tp->t_dev)];
+       s = spltty();
+       if (tp->t_state & TS_BUSY) {
+               dp->p_end = dp->p_mem;
+               if (!(tp->t_state & TS_TTSTOP))
+                       tp->t_state |= TS_FLUSH;
+       }
+       splx(s);
+}
+
+dcmctl(dev, bits, how)
+       dev_t dev;
+       int bits, how;
+{
+       register dcregs *dcaddr;
+       register int unit, mbits;
+       int b, s;
+       register int msr;
+
+       unit = minor(dev);
+       b = 1 << (unit & 03);
+       dcaddr = (dcregs *)dcpdma[unit].p_addr;
+       s = spltty();
+       /* only channel 2 has modem control (what about line 3?) */
+       mbits = DML_DTR | DML_DSR | DML_CAR;
+       switch (unit & 03) {
+       case 2:
+               mbits = 0;
+               if (dcaddr->dc_tcr & TCR_DTR2)
+                       mbits |= DML_DTR;
+               msr = dcaddr->dc_msr;
+               if (msr & MSR_CD2)
+                       mbits |= DML_CAR;
+               if (msr & MSR_DSR2) {
+                       if (vax_boardtype == -1)
+                               mbits |= DML_CAR | DML_DSR;
+                       else
+                               mbits |= DML_DSR;
+               }
+               break;
+
+       case 3:
+               if (vax_boardtype != -1) {
+                       mbits = 0;
+                       if (dcaddr->dc_tcr & TCR_DTR3)
+                               mbits |= DML_DTR;
+                       msr = dcaddr->dc_msr;
+                       if (msr & MSR_CD3)
+                               mbits |= DML_CAR;
+                       if (msr & MSR_DSR3)
+                               mbits |= DML_DSR;
+               }
+       }
+       switch (how) {
+       case DMSET:
+               mbits = bits;
+               break;
+
+       case DMBIS:
+               mbits |= bits;
+               break;
+
+       case DMBIC:
+               mbits &= ~bits;
+               break;
+
+       case DMGET:
+               (void) splx(s);
+               return (mbits);
+       }
+       switch (unit & 03) {
+       case 2:
+               if (mbits & DML_DTR)
+                       dcaddr->dc_tcr |= TCR_DTR2;
+               else
+                       dcaddr->dc_tcr &= ~TCR_DTR2;
+               break;
+
+       case 3:
+               if (vax_boardtype != -1) {
+                       if (mbits & DML_DTR)
+                               dcaddr->dc_tcr |= TCR_DTR3;
+                       else
+                               dcaddr->dc_tcr &= ~TCR_DTR3;
+               }
+       }
+       if ((mbits & DML_DTR) && (dcsoftCAR[unit >> 2] & b))
+               dc_tty[unit]->t_state |= TS_CARR_ON;
+       (void) splx(s);
+       return (mbits);
+}
+
+/*
+ * This is called by timeout() periodically.
+ * Check to see if modem status bits have changed.
+ */
+void
+dcscan(arg)
+       void *arg;
+{
+       register dcregs *dcaddr;
+       register struct tty *tp;
+       register int i, bit, car;
+       int s;
+
+       s = spltty();
+       /* only channel 2 has modem control (what about line 3?) */
+       dcaddr = (dcregs *)dcpdma[i = 2].p_addr;
+       tp = dc_tty[i];
+       bit = TCR_DTR2;
+       if (dcsoftCAR[i >> 2] & bit)
+               car = 1;
+       else
+               car = dcaddr->dc_msr & MSR_DSR2;
+       if (car) {
+               /* 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)
+               dcaddr->dc_tcr &= ~bit;
+       splx(s);
+       timeout(dcscan, (void *)0, hz);
+}
+
+/*
+ * ----------------------------------------------------------------------------
+ *
+ * dcGetc --
+ *
+ *     Read a character from a serial line.
+ *
+ * Results:
+ *     A character read from the serial port.
+ *
+ * Side effects:
+ *     None.
+ *
+ * ----------------------------------------------------------------------------
+ */
+int
+dcGetc(dev)
+       dev_t dev;
+{
+       register dcregs *dcaddr;
+       register int c;
+       int s;
+
+       dcaddr = (dcregs *)dcpdma[minor(dev)].p_addr;
+       if (!dcaddr)
+               return (0);
+       s = spltty();
+       for (;;) {
+               if (!(dcaddr->dc_csr & CSR_RDONE))
+                       continue;
+               c = dcaddr->dc_rbuf;
+               DELAY(10);
+               if (((c >> 8) & 03) == (minor(dev) & 03))
+                       break;
+       }
+       splx(s);
+       return (c & 0xff);
+}
+
+/*
+ * Send a char on a port, non interrupt driven.
+ */
+void
+dcPutc(dev, c)
+       dev_t dev;
+       int c;
+{
+       register dcregs *dcaddr;
+       register u_short tcr;
+       register int timeout;
+       int s, line;
+
+       s = spltty();
+
+       dcaddr = (dcregs *)dcpdma[minor(dev)].p_addr;
+       tcr = dcaddr->dc_tcr;
+       dcaddr->dc_tcr = tcr | (1 << minor(dev));
+       MachEmptyWriteBuffer();
+       DELAY(10);
+       while (1) {
+               /*
+                * Wait for transmitter to be not busy.
+                */
+               timeout = 1000000;
+               while (!(dcaddr->dc_csr & CSR_TRDY) && timeout > 0)
+                       timeout--;
+               if (timeout == 0) {
+                       printf("dcPutc: timeout waiting for CSR_TRDY\n");
+                       break;
+               }
+               line = (dcaddr->dc_csr >> 8) & 3;
+               /*
+                * Check to be sure its the right port.
+                */
+               if (line != minor(dev)) {
+                       tcr |= 1 << line;
+                       dcaddr->dc_tcr &= ~(1 << line);
+                       MachEmptyWriteBuffer();
+                       DELAY(10);
+                       continue;
+               }
+               /*
+                * Start sending the character.
+                */
+               dcaddr->dc_tdr = dc_brk[0] | (c & 0xff);
+               MachEmptyWriteBuffer();
+               DELAY(10);
+               /*
+                * Wait for character to be sent.
+                */
+               while (1) {
+                       /*
+                        * cc -O bug: this code produces and infinite loop!
+                        * while (!(dcaddr->dc_csr & CSR_TRDY))
+                        *      ;
+                        */
+                       timeout = 1000000;
+                       while (!(dcaddr->dc_csr & CSR_TRDY) && timeout > 0)
+                               timeout--;
+                       line = (dcaddr->dc_csr >> 8) & 3;
+                       if (line != minor(dev)) {
+                               tcr |= 1 << line;
+                               dcaddr->dc_tcr &= ~(1 << line);
+                               MachEmptyWriteBuffer();
+                               DELAY(10);
+                               continue;
+                       }
+                       dcaddr->dc_tcr &= ~(1 << minor(dev));
+                       MachEmptyWriteBuffer();
+                       DELAY(10);
+                       break;
+               }
+               break;
+       }
+       /*
+        * Enable interrupts for other lines which became ready.
+        */
+       if (tcr & 0xF) {
+               dcaddr->dc_tcr = tcr;
+               MachEmptyWriteBuffer();
+               DELAY(10);
+       }
+
+       splx(s);
+}
+#endif /* NDC */
diff --git a/sys/arch/vax/vsa/dc7085cons.h b/sys/arch/vax/vsa/dc7085cons.h
new file mode 100644 (file)
index 0000000..1c5a55b
--- /dev/null
@@ -0,0 +1,170 @@
+/*     $NetBSD: dc7085cons.h,v 1.1 1996/07/20 18:55:10 ragge Exp $     */
+/*
+ * 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.
+ *
+ *     @(#)dc7085cons.h        8.1 (Berkeley) 6/10/93
+ *
+ * dc7085.h --
+ *
+ *     Definitions for the dc7085 chip.
+ *
+ *     Copyright (C) 1989 Digital Equipment Corporation.
+ *     Permission to use, copy, modify, and distribute this software and
+ *     its documentation for any purpose and without fee is hereby granted,
+ *     provided that the above copyright notice appears in all copies.
+ *     Digital Equipment Corporation makes no representations about the
+ *     suitability of this software for any purpose.  It is provided "as is"
+ *     without express or implied warranty.
+ *
+ * from: Header: /sprite/src/kernel/dev/ds3100.md/RCS/dc7085.h,
+ *     
+ *     v 1.4 89/08/15 19:52:46 rab Exp  SPRITE (DECWRL)
+ */
+
+#ifndef _DC7085
+#define _DC7085
+
+typedef volatile struct dc7085regs {
+       u_short dc_csr;         /* control and status (R/W) */
+       u_short pad0;
+       short   dc_rbuf_lpr;    /* receiver data (R), line params (W) */
+       u_short pad1;
+       u_short dc_tcr;         /* transmitter control (R/W) */
+       u_short pad2;
+       u_short dc_msr_tdr;     /* modem status (R), transmit data (W) */
+} dcregs;
+#define dc_rbuf dc_rbuf_lpr
+#define dc_lpr dc_rbuf_lpr
+#define dc_msr dc_msr_tdr
+#define dc_tdr dc_msr_tdr
+
+/*
+ * Control status register bits.
+ */
+#define CSR_TRDY       0x8000
+#define CSR_TIE                0x4000          /* not avail on VS2000 */
+#define CSR_TX_LINE_NUM 0x0300
+#define CSR_RDONE      0x0080
+#define CSR_RIE                0x0040          /* not avail on VS2000 */
+#define CSR_MSE                0x0020
+#define CSR_CLR                0x0010
+#define CSR_MAINT      0x0008
+
+/*
+ * Receiver buffer register bits.
+ */
+#define RBUF_DVAL              0x8000
+#define RBUF_OERR              0x4000
+#define RBUF_FERR              0x2000
+#define RBUF_PERR              0x1000
+#define RBUF_LINE_NUM          0x0300
+#define RBUF_LINE_NUM_SHIFT    8
+#define RBUF_CHAR              0x00FF
+
+/*
+ * Transmit control register values.
+ */
+#define TCR_DTR2               0x0400
+#define TCR_EN3                        0x0008
+#define TCR_EN2                        0x0004
+#define TCR_EN1                        0x0002
+#define TCR_EN0                        0x0001
+
+#define TCR_RTS2               0x0800          /* VS2000: LLBK_2 */
+#define TCR_RTS3               0x0200          /* VS2000: DSRS_2 */
+#define TCR_DTR3               0x0100          /* VS2000:  RTS_2 */
+
+/*
+ * Line parameter register bits.
+ */
+#define LPR_RXENAB     0x1000
+#define LPR_B50                0x0000
+#define LPR_B75                0x0100
+#define LPR_B110       0x0200
+#define LPR_B134       0x0300
+#define LPR_B150       0x0400
+#define LPR_B300       0x0500
+#define LPR_B600       0x0600
+#define LPR_B1200      0x0700
+#define LPR_B1800      0x0800
+#define LPR_B2000      0x0900
+#define LPR_B2400      0x0A00
+#define LPR_B3600      0x0B00
+#define LPR_B4800      0x0C00
+#define LPR_B7200      0x0D00
+#define LPR_B9600      0x0E00
+#define LPR_B19200     0x0F00
+#define LPR_B38400     0x0F00
+#define LPR_OPAR       0x0080
+#define LPR_PARENB     0x0040
+#define LPR_2_STOP     0x0020
+#define LPR_8_BIT_CHAR 0x0018
+#define LPR_7_BIT_CHAR 0x0010
+#define LPR_6_BIT_CHAR 0x0008
+#define LPR_5_BIT_CHAR 0x0000
+
+/*
+ * Modem status register bits.
+ */
+#define MSR_DSR2       0x0200
+
+#define MSR_RI2                0x0800          /* VS2000: 0x0004 */
+#define MSR_CD2                0x0400
+#define MSR_CTS2       0x0100
+#define MSR_RI3                0x0008          /* VS2000: not used/available */
+#define MSR_CD3                0x0004          /* VS2000: RI2 */
+#define MSR_DSR3       0x0002          /* VS2000: MBZ */
+#define MSR_CTS3       0x0001          /* VS2000: TMI_2 */
+
+/*
+ * The four serial ports.
+ */
+#define DCKBD_PORT     0
+#define DCMOUSE_PORT   1
+#define DCCOMM_PORT    2
+#define DCPRINTER_PORT 3
+
+/* bits in dm lsr, copied from dmreg.h */
+#define DML_DSR                0000400         /* data set ready, not a real DM bit */
+#define DML_RNG                0000200         /* ring */
+#define DML_CAR                0000100         /* carrier detect */
+#define DML_CTS                0000040         /* clear to send */
+#define DML_SR         0000020         /* secondary receive */
+#define DML_ST         0000010         /* secondary transmit */
+#define DML_RTS                0000004         /* request to send */
+#define DML_DTR                0000002         /* data terminal ready */
+#define DML_LE         0000001         /* line enable */
+
+#endif /* _DC7085 */
diff --git a/sys/arch/vax/vsa/hdc9224.c b/sys/arch/vax/vsa/hdc9224.c
new file mode 100644 (file)
index 0000000..bb9aaa4
--- /dev/null
@@ -0,0 +1,1144 @@
+/*     $NetBSD: hdc9224.c,v 1.4 1996/10/13 03:36:11 christos Exp $ */
+/*
+ * Copyright (c) 1996 Ludd, University of Lule}, Sweden.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Ludd by Bertram Barth.
+ *
+ * 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 at Ludd, University of 
+ *     Lule}, Sweden and its contributors.
+ * 4. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * with much help from (in alphabetical order):
+ *     Jeremy
+ *     Roger Ivie
+ *     Rick Macklem
+ *     Mike Young
+ */
+
+/* #define DEBUG       /* */
+/* #define TRACE       /* */
+static int haveLock = 0;
+static int keepLock = 0;
+
+#define F_READ 11
+#define F_WRITE 12
+
+#define trace(x)
+#define debug(x)
+
+#include "hdc.h"
+#if NHDC > 0
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/conf.h>
+#include <sys/file.h>
+#include <sys/stat.h> 
+#include <sys/ioctl.h>
+#include <sys/buf.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/disk.h>
+#include <sys/syslog.h>
+
+#include <machine/pte.h>
+#include <machine/sid.h>
+#include <machine/cpu.h>
+#include <machine/uvax.h>
+#include <machine/ka410.h>
+#include <machine/vsbus.h>
+
+#include <vax/vsa/hdc9224.h>
+
+
+/*
+ * some definitions 
+ */
+#define CTLRNAME  "hdc"
+#define UNITNAME  "rd"
+#define HDC_PRI          LOG_INFO
+
+/* Bits in minor device */ 
+#define HDCUNIT(dev)   DISKUNIT(dev)
+#define HDCPART(dev)   DISKPART(dev)
+#define HDCCTLR(dev)   0
+#define HDCLABELDEV(dev)       (MAKEDISKDEV(major(dev),HDCUNIT(dev),RAW_PART))
+
+#define MAX_WAIT       (1000*1000)     /* # of loop-instructions in seconds */
+
+
+/* 
+ * on-disk geometry block 
+ */
+#define _aP    __attribute__ ((packed))        /* force byte-alignment */
+struct rdgeom {
+  char mbz[10];                /* 10 bytes of zero */
+  long xbn_count _aP;  /* number of XBNs */
+  long dbn_count _aP;  /* number of DBNs */
+  long lbn_count _aP;  /* number of LBNs (Logical-Block-Numbers) */
+  long rbn_count _aP;  /* number of RBNs (Replacement-Block-Numbers) */
+  short nspt;          /* number of sectors per track */
+  short ntracks;       /* number of tracks */
+  short ncylinders;    /* number of cylinders */
+  short precomp;       /* first cylinder for write precompensation */
+  short reduced;       /* first cylinder for reduced write current */
+  short seek_rate;     /* seek rate or zero for buffered seeks */
+  short crc_eec;       /* 0 if CRC is being used or 1 if ECC is being used */
+  short rct;           /* "replacement control table" (RCT) */
+  short rct_ncopies;   /* number of copies of the RCT */
+  long media_id _aP;   /* media identifier */
+  short interleave;    /* sector-to-sector interleave */
+  short headskew;      /* head-to-head skew */
+  short cylskew;       /* cylinder-to-cylinder skew */
+  short gap0_size;     /* size of GAP 0 in the MFM format */
+  short gap1_size;     /* size of GAP 1 in the MFM format */
+  short gap2_size;     /* size of GAP 2 in the MFM format */
+  short gap3_size;     /* size of GAP 3 in the MFM format */
+  short sync_value;    /* sync value used to start a track when formatting */
+  char reserved[32];   /* reserved for use by the RQDX1/2/3 formatter */
+  short serial_number; /* serial number */
+#if 0  /* we don't need these 412 useless bytes ... */
+  char fill[412-2];    /* Filler bytes to the end of the block */
+  short checksum;      /* checksum over the XBN */
+#endif
+};
+
+/*
+ * Software status
+ */
+struct rdsoftc {
+       struct device   sc_dev;         /* must be here! (pseudo-OOP:) */
+       struct disk     sc_dk;          /* disklabel etc. */
+       struct rdgeom   sc_xbn;         /* on-disk geometry information */
+       struct rdparams {
+               u_short cylinders;      /* number of cylinders */
+               u_char  heads;          /* number of heads (tracks) */
+               u_char  sectors;        /* number of sectors/track */
+               u_long  diskblks;       /* number of sectors/disk */
+               u_long  disklbns;       /* number of available sectors */
+               u_long  blksize;        /* number of bytes/sector */
+               u_long  diskbytes;      /* number of bytes/disk */
+               char    diskname[8];
+       } sc_param;
+       int     sc_drive;               /* physical unit number */
+       int     sc_flags;
+       int     sc_state;
+       int     sc_mode;
+};
+
+struct hdcsoftc {
+       struct device sc_dev;           /* must be here (pseudo-OOP:) */
+       struct hdc9224_DKCreg *sc_dkc;  /* I/O address of the controller */
+       struct hdc9224_UDCreg sc_creg;  /* (command) registers to be written */
+       struct hdc9224_UDCreg sc_sreg;  /* (status) registers being read */
+       struct confargs *sc_cfargs;     /* remember args being probed with */
+       char    *sc_dmabase;            /* */
+       long    sc_dmasize;             /* */
+       long    sc_ioaddr;              /* unmapped I/O address */
+       long    sc_ivec;                /* interrupt vector address */
+       short   sc_ibit;                /* bit-value in interrupt register */
+       short   sc_status;              /* copy of status register */
+       short   sc_state;
+       short   sc_flags;
+       short   sc_errors;
+};
+
+/*
+ * Device definition for (new) autoconfiguration.
+ */
+int    hdcmatch  __P((struct device *parent, void *cfdata, void *aux));
+void   hdcattach __P((struct device *parent, struct device *self, void *aux));
+int    hdcprint  __P((void *aux, const char *name));
+
+struct cfdriver hdc_cd = {
+       NULL, "hdc", DV_DULL
+};
+struct cfattach hdc_ca = {
+       sizeof(struct hdcsoftc), hdcmatch, hdcattach
+};
+
+int    rdmatch __P((struct device *parent, void *cfdata, void *aux));
+void   rdattach __P((struct device *parent, struct device *self, void *aux));
+int    rdprint __P((void *aux, const char *name));
+void   rdstrategy __P((struct buf *bp));
+
+struct cfdriver rd_cd = {
+       NULL, "rd", DV_DISK
+};
+struct cfattach rd_ca = {
+       sizeof(struct rdsoftc), rdmatch, rdattach
+};
+
+struct dkdriver rddkdriver = { rdstrategy };
+
+/*
+ * prototypes for (almost) all the internal routines
+ */
+int hdc_reset  __P((struct hdcsoftc *sc));
+int hdc_select __P((struct hdcsoftc *sc, int drive));
+int hdc_command __P((struct hdcsoftc *sc, int cmd));
+
+int hdc_getdata         __P((struct hdcsoftc *hdc, struct rdsoftc *rd, int drive));
+int hdc_getlabel __P((struct hdcsoftc *hdc, struct rdsoftc *rd, int drive));
+
+void rdgetlabel __P((struct rdsoftc *sc));
+
+/*
+ * new-config's hdcmatch() is similiar to old-config's hdcprobe(), 
+ * thus we probe for the existence of the controller and reset it.
+ * NB: we can't initialize the controller yet, since space for hdcsoftc 
+ *     is not yet allocated. Thus we do this in hdcattach()...
+ */
+int
+hdcmatch(parent, match, aux)
+       struct device *parent;
+       void *match, *aux;
+{
+       struct cfdata *cf = match;
+       struct confargs *ca = aux;
+
+       trace(("hdcmatch(0x%x, %d, %s)\n", parent, cf->cf_unit, ca->ca_name));
+
+       if (strcmp(ca->ca_name, "hdc") &&
+           strcmp(ca->ca_name, "hdc9224") &&
+           strcmp(ca->ca_name, "HDC9224"))
+               return (0);
+
+       /*
+        * only(?) VS2000/KA410 has exactly one HDC9224 controller
+        */
+       if (vax_boardtype != VAX_BTYP_410) {
+               printf ("unexpected boardtype 0x%x in hdcmatch()\n", 
+                       vax_boardtype);
+               return (0);
+       }
+       if (cf->cf_unit != 0)
+               return (0);
+
+       return (1);
+}
+
+struct hdc_attach_args {
+       int ha_drive;
+};
+
+int
+rdprint(aux, name)
+       void *aux;
+       const char *name;
+{
+       struct hdc_attach_args *ha = aux;
+
+       trace(("rdprint(%d, %s)\n", ha->ha_drive, name));
+
+       if (!name)
+               printf (" drive %d", ha->ha_drive);
+       return (QUIET);
+}
+
+/*
+ * hdc_attach() probes for all possible devices
+ */
+void 
+hdcattach(parent, self, aux)
+       struct device *parent, *self;
+       void *aux;
+{
+       struct hdcsoftc *sc = (void*)self;
+       struct confargs *ca = aux;
+       struct hdc_attach_args ha;
+
+       trace(("hdcattach(0x%x, 0x%x, %s)\n", parent, self, ca->ca_name));
+
+       printf ("\n");
+       /*
+        * first reset/initialize the controller
+        */
+       sc->sc_cfargs = ca;
+
+       sc->sc_ioaddr = ca->ca_ioaddr;
+       sc->sc_dkc = (void*)uvax_phys2virt(sc->sc_ioaddr);
+       sc->sc_ibit = ca->ca_intbit;
+       sc->sc_ivec = ca->ca_intvec;
+       sc->sc_status = 0;
+       sc->sc_state = 0;
+       sc->sc_flags = 0;
+       sc->sc_errors = 0;
+
+       sc->sc_dkc     = (void*)uvax_phys2virt(KA410_DKC_BASE);
+       sc->sc_dmabase = (void*)uvax_phys2virt(KA410_DMA_BASE);
+       sc->sc_dmasize = KA410_DMA_SIZE;
+                                             
+       if (hdc_reset(sc) != 0) {
+               delay(500*1000);        /* wait .5 seconds */
+               if (hdc_reset(sc) != 0)
+                       printf ("problems with hdc_reset()...\n");
+       }
+
+       /*
+        * now probe for all possible disks
+        */
+       for (ha.ha_drive=0; ha.ha_drive<3; ha.ha_drive++)
+               (void)config_found(self, (void*)&ha, rdprint);
+
+#ifdef notyet
+       /*
+        * now that probing is done, we can register and enable interrupts
+        */
+       vsbus_intr_register(XXX);
+       vsbus_intr_enable(XXX);
+#endif
+}
+
+/*
+ * rdmatch() probes for the existence of a RD-type disk/floppy
+ */
+int
+rdmatch(parent, match, aux)
+       struct device *parent;
+       void *match, *aux;
+{
+       struct hdcsoftc *hdc = (void*)parent;
+       struct cfdata *cf = match;
+       struct hdc_attach_args *ha = aux;
+       int drive = ha->ha_drive;
+       int res;
+
+       trace(("rdmatch(%d, %d)\n", cf->cf_unit, drive));
+
+       if (cf->cf_unit != ha->ha_drive)
+               return (0);
+
+       switch (drive) {
+       case 0:
+       case 1:
+       case 2:
+               res = hdc_select(hdc, drive);
+               break;
+       default:
+               printf ("rdmatch: invalid unit-number %d\n", drive);
+               return (0);
+       }
+
+       debug (("cstat: %x dstat: %x\n", hdc->sc_sreg.udc_cstat,
+               hdc->sc_sreg.udc_dstat));
+       if (drive == 1) 
+         return (0);   /* XXX */
+
+       return (1);
+}
+
+void
+rdattach(parent, self, aux)
+       struct device *parent, *self;
+       void *aux;
+{
+       struct hdcsoftc *hdc = (void*)parent;
+       struct rdsoftc *rd = (void*)self;
+       struct hdc_attach_args *ha = aux;
+       struct rdparams *rp = &rd->sc_param;
+
+       trace(("rdattach(%d)\n", ha->ha_drive));
+
+       rd->sc_drive = ha->ha_drive;
+       /*
+        * Initialize and attach the disk structure.
+        */
+       rd->sc_dk.dk_driver = &rddkdriver;
+       rd->sc_dk.dk_name = rd->sc_dev.dv_xname;
+       disk_attach(&rd->sc_dk);
+       /*
+        * if it's not a floppy then evaluate the on-disk geometry.
+        * if neccessary correct the label...
+        */
+       printf("\n%s: ", rd->sc_dev.dv_xname);
+       if (rd->sc_drive == 2) {
+               printf("floppy (RX33)\n");
+       }
+       else {
+               hdc_getdata(hdc, rd, rd->sc_drive);
+               printf("%s, %d MB, %d LBN, %d cyl, %d head, %d sect/track\n",
+                      rp->diskname, rp->diskblks/2048, rp->disklbns, 
+                      rp->cylinders, rp->heads, rp->sectors);
+       }
+}
+
+/*
+ * Read/write routine for a buffer.  For now we poll the controller, 
+ * thus this routine waits for the transfer to complete.
+ */
+void
+rdstrategy(bp)
+       struct buf *bp;
+{
+       struct rdsoftc *rd = rd_cd.cd_devs[HDCUNIT(bp->b_dev)];
+       struct hdcsoftc *hdc = (void *)rd->sc_dev.dv_parent;
+       struct partition *p;
+       int blkno, i, s;
+
+       trace (("rdstrategy(#%d/%d)\n", bp->b_blkno, bp->b_bcount));
+
+       /* XXX          should make some checks... */
+
+       /*
+        * If it's a null transfer, return immediatly
+        */
+       if (bp->b_bcount == 0)
+               goto done;
+       
+       /*
+        * what follows now should not be here but in rdstart...
+        */
+       /*------------------------------*/
+       blkno = bp->b_blkno / (rd->sc_dk.dk_label->d_secsize / DEV_BSIZE);
+       if (HDCPART(bp->b_dev) != RAW_PART) {
+               p = &rd->sc_dk.dk_label->d_partitions[HDCPART(bp->b_dev)];
+               blkno += p->p_offset;
+       }
+       /* nblks = howmany(bp->b_bcount, sd->sc_dk.dk_label->d_secsize); */
+
+       if (hdc_strategy(hdc, rd, HDCUNIT(bp->b_dev), 
+                        ((bp->b_flags & B_READ) ? F_READ : F_WRITE),
+                        blkno, bp->b_bcount, bp->b_data) == 0)
+               goto done;
+       /*------------------------------*/
+bad:
+       bp->b_flags |= B_ERROR;
+done:
+       /*
+        * Correctly set the buf to indicate a completed xfer
+        */
+       bp->b_resid = 0;        /* ??? bertram */
+       biodone(bp);
+}
+
+int
+hdc_strategy(hdc, rd, unit, func, dblk, size, buf)
+       struct hdcsoftc *hdc;
+       struct rdsoftc *rd;
+       int unit;
+       int func;
+       int dblk;
+       int size;
+       char *buf;
+{
+       struct hdc9224_UDCreg *p = &hdc->sc_creg;
+       struct disklabel *lp = rd->sc_dk.dk_label;
+       int sect, head, cyl;
+       int scount;
+       int cmd, res = 0;
+
+       trace (("hdc_strategy(%d, %d, %d, %d, 0x%x)\n",
+               unit, func, dblk, size, buf));
+
+       hdc_select(hdc, unit);          /* select drive right now */
+
+       if (unit != 2 && dblk == -1) {  /* read the on-disk geometry */
+
+         p->udc_dma7  = 0;
+         p->udc_dma15 = 0;
+         p->udc_dma23 = 0;
+
+         p->udc_dsect = 0;
+         p->udc_dhead = 0;
+         p->udc_dcyl  = 0;
+
+         p->udc_scnt  = size/512; 
+         p->udc_rtcnt = 0xF0;
+         p->udc_mode  = 0xC0;
+         p->udc_term  = 0xB4;
+
+         vsbus_lockDMA(hdc->sc_cfargs);                /* bertram XXX */
+         haveLock = 1;
+         keepLock = 1;
+
+#ifdef PARANOID
+         bzero (hdc->sc_dmabase, size);        /* clear disk buffer */
+#endif
+         cmd = 0x5C | 0x03;                    /* bypass bad sectors */
+         cmd = 0x5C | 0x01;                    /* terminate if bad sector */
+
+         res = hdc_command (hdc, cmd);
+         /* hold the locking ! */
+         bcopy (hdc->sc_dmabase, buf, size);   /* copy to buf */
+         /* now release the locking */
+
+         vsbus_unlockDMA(hdc->sc_cfargs);
+         haveLock = 0;
+         keepLock = 0;
+
+         return (res);
+       }
+       
+       scount = size / 512;
+       while (scount) {
+         /*
+          * prepare drive/operation parameter
+          */
+         cyl  = dblk / lp->d_secpercyl;
+         sect = dblk % lp->d_secpercyl;
+         head = sect / lp->d_nsectors;
+         sect = sect % lp->d_nsectors;
+         if (unit == 2) 
+               sect++;
+         else
+               cyl++;          /* first cylinder is reserved */
+
+         size = 512 * min(scount, lp->d_nsectors - sect);
+
+         debug (("hdc_strategy: block #%d ==> s/t/c=%d/%d/%d (%d/%d)\n",
+                 dblk, sect, head, cyl, scount, size));
+
+         /*
+          * now initialize the register values ...
+          */
+         p->udc_dma7  = 0;
+         p->udc_dma15 = 0;
+         p->udc_dma23 = 0;
+
+         p->udc_dsect = sect;
+         head |= (cyl >> 4) & 0x70;
+         p->udc_dhead = head;
+         p->udc_dcyl  = cyl;
+
+         p->udc_scnt  = size/512; 
+
+         if (unit == 2) {      /* floppy */
+           p->udc_rtcnt = 0xF2;
+           p->udc_mode  = 0x81;        /* RX33 with RX50 media */
+           p->udc_mode  = 0x82;        /* RX33 with RX33 media */
+           p->udc_term  = 0xB4;        
+         } else {               /* disk */
+           p->udc_rtcnt = 0xF0;
+           p->udc_mode  = 0xC0;
+           p->udc_term  = 0xB4;
+         }
+         
+         vsbus_lockDMA(hdc->sc_cfargs);
+         haveLock = 1;
+         keepLock = 1;
+
+         if (func == F_WRITE) {
+           bcopy (buf, hdc->sc_dmabase, size); /* copy from buf */
+           cmd = 0xA0 | (unit==2 ? 1 : 0);
+           res = hdc_command (hdc, cmd);
+         }
+         else {
+#ifdef PARANOID
+           bzero (hdc->sc_dmabase, size);              /* clear disk buffer */
+#endif
+           cmd = 0x5C | 0x03;  /* bypass bad sectors */
+           cmd = 0x5C | 0x01;  /* terminate if bad sector */
+           res = hdc_command (hdc, cmd);
+           bcopy (hdc->sc_dmabase, buf, size); /* copy to buf */
+         }
+
+         vsbus_unlockDMA(hdc->sc_cfargs);
+         haveLock = 0;
+         keepLock = 0;
+
+         scount -= size/512;
+         dblk += size/512;
+         buf += size;
+       }
+
+       if (unit != 2)          /* deselect drive, if not floppy */
+         hdc_command (hdc, DKC_CMD_DRDESELECT);
+
+       return 0;
+}
+
+char hdc_iobuf[17*512];                /* we won't need more */
+
+#ifdef DEBUG
+/*
+ * display the contents of the on-disk geometry structure
+ */
+int
+hdc_printgeom(p)
+       struct rdgeom *p;
+{
+       char dname[8];
+       hdc_mid2str(p->media_id, dname);
+
+       printf ("**DiskData**    XBNs: %d, DBNs: %d, LBNs: %d, RBNs: %d\n",
+               p->xbn_count, p->dbn_count, p->lbn_count, p->rbn_count);
+       printf ("sec/track: %d, tracks: %d, cyl: %d, precomp/reduced: %d/%d\n",
+               p->nspt, p->ntracks, p->ncylinders, p->precomp, p->reduced);
+       printf ("seek-rate: %d, crc/eec: %s, RCT: %d, RCT-copies: %d\n",
+               p->seek_rate, p->crc_eec?"EEC":"CRC", p->rct, p->rct_ncopies);
+       printf ("media-ID: %s, interleave: %d, headskew: %d, cylskew: %d\n",
+               dname, p->interleave, p->headskew, p->cylskew);
+       printf ("gap0: %d, gap1: %d, gap2: %d, gap3: %d, sync-value: %d\n",
+               p->gap0_size, p->gap1_size, p->gap2_size, p->gap3_size, 
+               p->sync_value);
+}
+#endif
+
+/*
+ * Convert media_id to string/name (encoding is documented in mscp.h)
+ */
+int
+hdc_mid2str(media_id, name)
+       long media_id;
+       char *name;
+{
+       struct {                        /* For RD32 this struct holds: */
+               u_long mt:7;            /* number in name: 0x20 == 32 */
+               u_long a2:5;            /* ' ' encoded as 0x0 */
+               u_long a1:5;            /* 'D' encoded with base '@' */
+               u_long a0:5;            /* 'R' encoded with base '@' */
+               u_long d1:5;            /* 'U' encoded with base '@' */
+               u_long d0:5;            /* 'D' encoded with base '@' */
+       } *p = (void*)&media_id;
+
+#define MIDCHR(x)      (x ? x + '@' : ' ')
+
+       sprintf (name, "%c%c%d", MIDCHR(p->a0), MIDCHR(p->a1), p->mt);
+}
+
+int
+hdc_getdata(hdc, rd, unit)
+       struct hdcsoftc *hdc;
+       struct rdsoftc *rd;
+       int unit;
+{
+       struct disklabel *lp = rd->sc_dk.dk_label;
+       struct rdparams *rp = &rd->sc_param;
+       int res;
+
+       trace (("hdc_getdata(%d)\n", unit));
+
+       bzero(rd->sc_dk.dk_label, sizeof(struct disklabel));
+       bzero(rd->sc_dk.dk_cpulabel, sizeof(struct cpu_disklabel));
+
+       if (unit == 2) {
+               lp->d_secsize = DEV_BSIZE;
+               lp->d_ntracks = 2;
+               lp->d_nsectors = 15;
+               lp->d_ncylinders = 80;
+               lp->d_secpercyl = lp->d_ntracks * lp->d_nsectors;
+
+               return (0);
+       }
+
+       res = hdc_strategy(hdc, rd, unit, F_READ, -1, 4096, hdc_iobuf);
+       bcopy (hdc_iobuf, &rd->sc_xbn, sizeof(struct rdgeom));
+#ifdef DEBUG
+       hdc_printgeom(&rd->sc_xbn);
+#endif
+       lp->d_secsize = DEV_BSIZE;
+       lp->d_ntracks = rd->sc_xbn.ntracks;
+       lp->d_nsectors = rd->sc_xbn.nspt;
+       lp->d_ncylinders = rd->sc_xbn.ncylinders;
+       lp->d_secpercyl = lp->d_ntracks * lp->d_nsectors;
+
+       rp->cylinders = rd->sc_xbn.ncylinders;
+       rp->heads = rd->sc_xbn.ntracks;
+       rp->sectors = rd->sc_xbn.nspt;
+       rp->diskblks = rp->cylinders * rp->heads * rp->sectors;
+       rp->disklbns = rd->sc_xbn.lbn_count;
+       rp->blksize = DEV_BSIZE;
+       rp->diskbytes = rp->disklbns * rp->blksize;
+       hdc_mid2str(rd->sc_xbn.media_id, rp->diskname);
+
+       return (0);
+}
+
+int
+hdc_getlabel(hdc, rd, unit)
+       struct hdcsoftc *hdc;
+       struct rdsoftc *rd;
+       int unit;
+{
+       struct disklabel *lp = rd->sc_dk.dk_label;
+       struct disklabel *xp = (void*)(hdc_iobuf + 64);
+       int res;
+
+       trace (("hdc_getlabel(%d)\n", unit));
+
+#define LBL_CHECK(x)   if (xp->x != lp->x) {                   \
+                         printf ("%d-->%d\n", xp->x, lp->x);   \
+                         xp->x = lp->x;                        \
+                       }
+       res = hdc_strategy(hdc, rd, unit, F_READ, 0, DEV_BSIZE, hdc_iobuf);
+       LBL_CHECK(d_secsize);
+       LBL_CHECK(d_ntracks);
+       LBL_CHECK(d_nsectors);
+       LBL_CHECK(d_ncylinders);
+       LBL_CHECK(d_secpercyl);
+       bcopy(xp, lp, sizeof(struct disklabel));
+
+       return (0);
+}
+
+/*
+ * Return the size of a partition, if known, or -1 if not.
+ */
+hdcsize(dev)
+       dev_t dev;
+{
+       int unit = HDCUNIT(dev);
+       int part = HDCPART(dev);
+       struct rdsoftc *rd = rd_cd.cd_devs[unit];
+       int size;
+
+       trace (("hdcsize(%x == %d/%d)\n", dev, unit, part));
+
+       if (hdcopen(dev, 0, S_IFBLK) != 0)
+               return (-1);
+#if 0
+       if (rd->sc_dk.dk_label->d_partitions[part].p_fstype != FS_SWAP)
+               size = -1;
+       else
+#endif
+               size = rd->sc_dk.dk_label->d_partitions[part].p_size;
+       if (hdcclose(dev, 0, S_IFBLK) != 0)
+               return (-1);
+       debug (("hdcsize: size=%d\n", size));
+       return (size);
+}
+
+/*
+ *
+ */
+int
+hdcopen (dev, flag, fmt)
+       dev_t dev;
+       int flag;
+       int fmt;
+{
+       int unit = HDCUNIT(dev);
+       int part = HDCPART(dev);
+       struct hdcsoftc *hdc;
+       struct rdsoftc *rd;
+       int res, error;
+
+       trace (("hdcopen(0x%x = %d/%d)\n", dev, unit, part));
+
+       if (unit >= rd_cd.cd_ndevs) {
+               printf ("hdcopen: invalid unit %d\n", unit);
+               return ENXIO;
+       }
+       rd = rd_cd.cd_devs[unit];
+       if (!rd) {
+               printf("hdcopen: null-pointer in rdsoftc.\n");
+               return (ENXIO);
+       }
+       hdc = (void *)rd->sc_dev.dv_parent;
+       
+       /* XXX here's much more to do! XXX */
+
+       hdc_getdata (hdc, rd, unit);
+       hdc_getlabel (hdc, rd, unit);
+
+       return (0);
+}
+
+/*
+ *
+ */
+int
+hdcclose (dev, flag)
+       dev_t dev;
+       int flag;
+{
+       trace (("hdcclose()\n"));
+       return (0);
+}
+
+/*
+ *
+ */
+void
+hdcstrategy(bp)
+       register struct buf *bp;
+{
+       trace (("hdcstrategy()\n"));
+       rdstrategy(bp);
+       debug (("hdcstrategy done.\n"));
+}
+
+/*
+ *
+ */
+int
+hdcioctl(dev, cmd, data, flag, p)
+       dev_t dev;
+       int cmd;
+       caddr_t data;   /* aka: addr */
+       int flag;
+       struct proc *p;
+{
+       struct rdsoftc *rd = rd_cd.cd_devs[HDCUNIT(dev)];
+       struct hdcsoftc *hdc = (void *)rd->sc_dev.dv_parent;
+       int error;
+
+       trace (("hdcioctl(%x, %x)\n", dev, cmd));
+
+       /*
+        * If the device is not valid.. abandon ship
+        */
+       /* XXX */
+
+       switch (cmd) {
+       case DIOCGDINFO:
+               *(struct disklabel *)data = *(rd->sc_dk.dk_label);
+               return (0);
+
+       case DIOCGPART:
+               ((struct partinfo *)data)->disklab = rd->sc_dk.dk_label;
+               ((struct partinfo *)data)->part =
+                 &rd->sc_dk.dk_label->d_partitions[HDCPART(dev)];
+               return (0);
+
+       case DIOCWDINFO:
+       case DIOCSDINFO:
+/* XXX
+               if ((flag & FWRITE) == 0)
+                       return EBADF;
+
+               if ((error = sdlock(sd)) != 0)
+                       return error;
+               sd->flags |= SDF_LABELLING;
+*/
+               error = setdisklabel(rd->sc_dk.dk_label,
+                    (struct disklabel *)data, 0, rd->sc_dk.dk_cpulabel);
+               if (error == 0) {
+                       if (cmd == DIOCWDINFO)
+                               error = writedisklabel(HDCLABELDEV(dev),
+                                       rdstrategy, rd->sc_dk.dk_label,
+                                       rd->sc_dk.dk_cpulabel);
+               }
+/* XXX
+               sd->flags &= ~SDF_LABELLING;
+               sdunlock(sd);
+*/
+               return (error);
+
+       case DIOCWLABEL:
+               if ((flag & FWRITE) == 0)
+                       return (EBADF);
+/* XXX
+               if (*(int *)data)
+                       sd->flags |= SDF_WLABEL;
+               else
+                       sd->flags &= ~SDF_WLABEL;
+*/
+               return (0);
+             
+       default:
+               if (HDCPART(dev) != RAW_PART)
+                       return ENOTTY;
+               printf ("IOCTL %x not implemented.\n", cmd);
+               return (-1);
+       }
+}
+
+/*
+ *
+ */
+int 
+hdcintr() 
+{
+       trace (("hdcintr()\n"));
+}
+
+/*
+ * 
+ */
+int
+hdcread (dev, uio)
+       dev_t dev;
+       struct uio *uio;
+{
+       trace (("hdcread()\n"));
+       return (physio (hdcstrategy, NULL, dev, B_READ, minphys, uio));
+}
+
+/*
+ *
+ */
+int
+hdcwrite (dev, uio)
+       dev_t dev;
+       struct uio *uio;
+{
+       trace (("hdcwrite()\n"));
+       return (physio (hdcstrategy, NULL, dev, B_WRITE, minphys, uio));
+}
+
+/*
+ *
+ */
+int
+hdcdump(dev)
+       dev_t dev;
+{
+       trace (("hdcdump (%x)\n", dev));
+}
+
+/*
+ * we have to wait 0.7 usec between two accesses to any of the
+ * dkc-registers, on a VS2000 with 1 MIPS, this is roughly one
+ * instruction. Thus the loop-overhead will be enough...
+ */
+void
+hdc_readregs(sc)
+       struct hdcsoftc *sc;
+{
+       int i;
+       char *p;
+
+       trace(("hdc_readregs()\n"));
+
+       sc->sc_dkc->dkc_cmd = 0x40;     /* set internal counter to zero */
+       p = (void*)&sc->sc_sreg;        
+       for (i=0; i<10; i++)
+               *p++ = sc->sc_dkc->dkc_reg;     /* dkc_reg auto-increments */
+}
+
+void
+hdc_writeregs(sc)
+       struct hdcsoftc *sc;
+{
+       int i;
+       char *p;
+
+       trace(("hdc_writeregs()\n"));
+
+       sc->sc_dkc->dkc_cmd = 0x40;     /* set internal counter to zero */
+       p = (void*)&sc->sc_creg;        
+       for (i=0; i<10; i++)
+               sc->sc_dkc->dkc_reg = *p++;     /* dkc_reg auto-increments */
+}
+
+/*
+ * hdc_command() issues a command and polls the intreq-register
+ * to find when command has completed
+ */
+int
+hdc_command(sc, cmd)
+       struct hdcsoftc *sc;
+       int cmd;
+{
+       volatile u_char *intreq = (void*)uvax_phys2virt(KA410_INTREQ);
+       volatile u_char *intclr = (void*)uvax_phys2virt(KA410_INTCLR);
+       volatile u_char *intmsk = (void*)uvax_phys2virt(KA410_INTMSK);
+       int i, c;
+
+       trace (("hdc_command(%x)\n", cmd));
+       debug (("intr-state: %x %x %x\n", *intreq, *intclr, *intmsk));
+
+       if (!haveLock) {
+         vsbus_lockDMA(sc->sc_cfargs);
+         haveLock = 1;
+       }
+
+       hdc_writeregs(sc);              /* write the prepared registers */
+       *intclr = INTR_DC;              /* clear any old interrupt */
+       sc->sc_dkc->dkc_cmd = cmd;      /* issue the command */
+       for (i=0; i<MAX_WAIT; i++) {
+               if ((c = *intreq) & INTR_DC)
+                       break;
+       }
+       if ((c & INTR_DC) == 0) {
+               printf ("hdc_command: timeout in command 0x%x\n", cmd);
+       }
+       hdc_readregs(sc);               /* read the status registers */
+       sc->sc_status = sc->sc_dkc->dkc_stat;
+
+       if (!keepLock) {
+         vsbus_unlockDMA(sc->sc_cfargs);
+         haveLock = 0;
+       }
+
+       if (sc->sc_status != DKC_ST_DONE|DKC_TC_SUCCESS) {
+               printf ("command 0x%x completed with status 0x%x\n",
+                       cmd, sc->sc_status);
+               return (-1);
+       }
+       return (0);
+}
+
+/*
+ * writing zero into the command-register will reset the controller.
+ * This will not interrupt data-transfer commands!
+ * Also no interrupt is generated, thus we don't use hdc_command()
+ */
+int 
+hdc_reset(sc)
+       struct hdcsoftc *sc;
+{
+       trace (("hdc_reset()\n"));
+       
+       sc->sc_dkc->dkc_cmd = DKC_CMD_RESET;    /* issue RESET command */
+       hdc_readregs(sc);                       /* read the status registers */
+       sc->sc_status = sc->sc_dkc->dkc_stat;
+       if (sc->sc_status != DKC_ST_DONE|DKC_TC_SUCCESS) {
+               printf ("RESET command completed with status 0x%x\n",
+                       sc->sc_status);
+               return (-1);
+       }
+       return (0);
+}
+
+int
+hdc_rxselect(sc, unit)
+       struct hdcsoftc *sc;
+       int unit;
+{
+       register struct hdc9224_UDCreg *p = &sc->sc_creg;
+       register struct hdc9224_UDCreg *q = &sc->sc_sreg;
+       int error;
+
+       /*
+        * bring command-regs in some known-to-work state and
+        * select the drive with the DRIVE SELECT command.
+        */
+       p->udc_dma7  = 0;
+       p->udc_dma15 = 0;
+       p->udc_dma23 = 0;
+       p->udc_dsect = 1;       /* sectors are numbered 1..15 !!! */
+       p->udc_dhead = 0;
+       p->udc_dcyl  = 0;
+       p->udc_scnt  = 0;
+
+       p->udc_rtcnt = UDC_RC_RX33READ;
+       p->udc_mode  = UDC_MD_RX33;
+       p->udc_term  = UDC_TC_FDD;
+
+       /*
+        * this is ...
+        */
+       error = hdc_command (sc, DKC_CMD_DRSEL_RX33 | unit);
+
+       if ((error != 0) || (q->udc_dstat & UDC_DS_READY == 0)) {
+         printf("\nfloppy-drive not ready (new floppy inserted?)\n\n");
+         p->udc_rtcnt &= ~UDC_RC_INVRDY;       /* clear INVRDY-flag */
+         error = hdc_command(sc, DKC_CMD_DRSEL_RX33 | unit);
+         if ((error != 0) || (q->udc_dstat & UDC_DS_READY == 0)) {
+           printf("diskette not ready(1): %x/%x\n", error, q->udc_dstat);
+           printf("floppy-drive offline?\n");
+           return (-1);
+         }
+
+         if (q->udc_dstat & UDC_DS_TRK00)                  /* if track-0 */
+           error = hdc_command(sc, DKC_CMD_STEPIN_FDD);   /* step inwards */
+         else                                              /* else */
+           error = hdc_command(sc, DKC_CMD_STEPOUT_FDD);  /* step outwards */
+
+         if ((error != 0) || (q->udc_dstat & UDC_DS_READY == 1)) {
+           printf("diskette not ready(2): %x/%x\n", error, q->udc_dstat);
+           printf("No floppy inserted or drive offline\n");
+           /* return (-1); */
+         }
+
+         p->udc_rtcnt |= UDC_RC_INVRDY;
+         error = hdc_command(sc, DKC_CMD_DRSEL_RX33 | unit);
+         if ((error != 0) || (q->udc_dstat & UDC_DS_READY == 0)) {
+           printf("diskette not ready(3): %x/%x\n", error, q->udc_dstat);
+           printf("no floppy inserted or floppy-door open\n");
+           return(-1);
+         }
+         printf("floppy-drive reselected.\n");
+       }
+       if (error)
+               error = hdc_command (sc, DKC_CMD_DRSEL_RX33 | unit);
+
+       return (error);
+}
+
+int
+hdc_rdselect(sc, unit)
+       struct hdcsoftc *sc;
+       int unit;
+{
+       register struct hdc9224_UDCreg *p = &sc->sc_creg;
+       register struct hdc9224_UDCreg *q = &sc->sc_sreg;
+       int error;
+
+       /*
+        * bring "creg" in some known-to-work state and
+        * select the drive with the DRIVE SELECT command.
+        */
+       p->udc_dma7  = 0;
+       p->udc_dma15 = 0;
+       p->udc_dma23 = 0;
+       p->udc_dsect = 0;               /* sectors are numbered 0..16 */
+       p->udc_dhead = 0;
+       p->udc_dcyl  = 0;
+       p->udc_scnt  = 0;
+
+       p->udc_rtcnt = UDC_RC_HDD_READ;
+       p->udc_mode  = UDC_MD_HDD;
+       p->udc_term  = UDC_TC_HDD;
+
+       error = hdc_command (sc, DKC_CMD_DRSEL_HDD | unit);
+       if (error)
+               error = hdc_command (sc, DKC_CMD_DRSEL_HDD | unit);
+       
+       return (error);
+}
+
+/*
+ * bring command-regs into some known-to-work state and select
+ * the drive with the DRIVE SELECT command.
+ */
+int 
+hdc_select(sc, unit)
+       struct hdcsoftc *sc;
+       int unit;
+{
+       int error;
+
+       trace (("hdc_select(%x,%d)\n", sc, unit));
+
+       switch (unit) {
+       case 0:
+       case 1:
+               error = hdc_rdselect(sc, unit);
+               break;
+       case 2:
+               error = hdc_rxselect(sc, unit);
+               /* bertram: delay ??? XXX */
+               break;
+       default:
+               printf("invalid unit %d in hdc_select()\n", unit);
+               error = -1;
+       }
+
+       return (error);
+}
+
+#endif /* NHDC > 0 */
diff --git a/sys/arch/vax/vsa/hdc9224.h b/sys/arch/vax/vsa/hdc9224.h
new file mode 100644 (file)
index 0000000..43fe2cf
--- /dev/null
@@ -0,0 +1,196 @@
+/*     $NetBSD: hdc9224.h,v 1.1 1996/07/20 18:55:12 ragge Exp $ */
+/*
+ * Copyright (c) 1996 Ludd, University of Lule}, Sweden.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Ludd by Bertram Barth.
+ *
+ * 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 at Ludd, University of 
+ *     Lule}, Sweden and its contributors.
+ * 4. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+
+struct hdc9224_DKCreg {
+       unsigned char dkc_reg;  /* Disk Register Data Access Port (rw)*/
+       unsigned char fill[3];  /* bytes are longword aligned */
+       unsigned char dkc_cmd;  /* Disk Controller Command Port (wo) */
+#define dkc_stat dkc_cmd       /* Interrupt Status Port (ro) */
+};
+
+/*
+ * definition of some commands (constant bits only, incomplete!)
+ */
+#define DKC_CMD_RESET          0x00    /* terminate non-data-transfer cmds */
+#define DKC_CMD_DRDESELECT     0x01    /* done when no drive is in use */
+#define DKC_CMD_SETREGPTR      0x40    /* logically or-ed with reg-number */
+#define DKC_CMD_DRSELECT       0x20
+#define DKC_CMD_DRSEL_HDD      0x24    /* select HDD, or-ed with unit-numb. */
+#define DKC_CMD_DRSEL_RX33     0x28    /* or-ed with unit-number of RX33 */
+#define DKC_CMD_DRSEL_RX50     0x2C    /* or-ed with unit-number of RX50 */
+#define DKC_CMD_RESTORE                0x02
+#define DKC_CMD_STEP           0x04
+#define DKC_CMD_STEPIN_FDD     0x04    /* one step inward for floppy */
+#define DKC_CMD_STEPOUT_FDD    0x06    /* one step outward (toward cyl #0) */
+#define DKC_CMD_POLLDRIVE      0x10
+#define DKC_CMD_SEEKREADID     0x50
+#define DKC_CMD_FORMATTRACK    0x60
+#define DKC_CMD_READTRACK      0x5A
+#define DKC_CMD_READPHYSICAL   0x58
+#define DKC_CMD_READLOGICAL    0x5C
+#define DKC_CMD_READ_HDD       0x5D    /* read-logical, bypass=0, xfer=1 */
+#define DKC_CMD_READ_RX33      0x5D    /* ??? */
+#define DKC_CMD_WRITEPHYSICAL  0x80
+#define DKC_CMD_WRITELOGICAL   0xC0
+#define DKC_CMD_WRITE_HDD      0xA0    /* bypass=0, ddmark=0 */
+#define DKC_CMD_WRITE_RX33     0xA1    /* precompensation differs... */
+#define DKC_CMD_WRITE_RX50     0xA4
+
+/*
+ * Definition of bits in the DKC_STAT register
+ */
+#define DKC_ST_INTPEND (1<<7)          /* interrupt pending */
+#define DKC_ST_DMAREQ  (1<<6)          /* DMA request */
+#define DKC_ST_DONE    (1<<5)          /* command done */
+#define DKC_ST_TERMCOD (3<<3)          /* termination code (see below) */
+#define DKC_ST_RDYCHNG (1<<2)          /* ready change */
+#define DKC_ST_OVRUN   (1<<1)          /* overrun/underrun */
+#define DKC_ST_BADSECT (1<<0)          /* bad sector */
+
+/*
+ * Definition of the termination codes
+ */
+#define DKC_TC_SUCCESS (0<<3)          /* Successful completion */
+#define DKC_TC_RDIDERR (1<<3)          /* Error in READ-ID sequence */
+#define DKC_TC_VRFYERR (2<<3)          /* Error in VERIFY sequence */
+#define DKC_TC_DATAERR (3<<3)          /* Error in DATA-TRANSFER seq. */
+
+/*
+ * Definitions of delays neccessary for floppy-operation
+ */
+#define DKC_DELAY_MOTOR                500     /* allow 500 ms to reach speed */
+#define DKC_DELAY_SELECT        70     /* 70 ms for data-recovery-circuit */
+#define DKC_DELAY_POSITION      59     /* 59 ms for RX33, 100 ms for RX50 */
+#define DKC_DELAY_HEADSET       18     /* 18 ms when changing head-number */
+
+/*
+ * The HDC9224 has 11/15(?) internal registers which are accessible via
+ * the Disk-Register-Data-Access-Port DKC_REG
+ */
+struct hdc9224_UDCreg { /* internal disk controller registers */
+       u_char udc_dma7;        /*  0: DMA adress bits  0 -  7 */
+       u_char udc_dma15;       /*  1: DMA adress bits  8 - 15 */
+       u_char udc_dma23;       /*  2: DMA adress bits 16 - 23 */
+       u_char udc_dsect;       /*  3: desired/starting sector number */
+#define udc_csect udc_dsect    /*     current sector number */
+       u_char udc_dhead;       /*  4: cyl-bits 8-10, desired head number */
+#define udc_chead udc_dhead    /*     current head number */
+       u_char udc_dcyl;        /*  5: desired cylinder number */
+#define udc_ccyl udc_dcyl      /*     current cylinder number */
+       u_char udc_scnt;        /*  6: sector count register */
+       u_char udc_rtcnt;       /*  7: retry count register */
+       u_char udc_mode;        /*  8: operation mode/chip status */
+#define udc_cstat udc_mode     /*     chip status register */
+       u_char udc_term;        /*  9: termination conditions/drive status */
+#define udc_dstat udc_term     /*     drive status register */
+       u_char udc_data;        /* 10: data */
+};
+
+/*
+ * Definition of bits in the Current-Head register
+ */
+#define UDC_CH_BADSECT (1<<7)  /* indicates a bad sector (if bypass=0) */
+#define UDC_CH_CYLBITS (0x70)  /* bits 10-8 of current cylinder number */
+#define UDC_CH_HEADNO  (0x0F)  /* current head number */
+
+/*
+ * Definition of bits in the Retry-Count register
+ */
+#define UDC_RC_RTRYCNT (0xF0)  /* 1's compl. in read-log, 0 all others */
+#define UDC_RC_RXDISAB (1<<3)  /* must/should be 0 for normal operation */
+#define UDC_RC_INVRDY  (1<<2)  /* polarity of floppy-status, important! */
+#define UDC_RC_MOTOR   (1<<1)  /* turn on floppy-motor, no effect on HDD */
+#define UDC_RC_LOSPEED (1<<0)  /* floppy-speed select, RX33: 0, RX50: 1 */
+
+#define UDC_RC_HDD_READ         0xF2   /* 0x72 ??? */
+#define UDC_RC_HDD_WRT  0xF2   /* 0xF0 ??? */
+#define UDC_RC_RX33READ         0x76   /* enable retries when reading floppies */
+#define UDC_RC_RX33WRT  0xF6
+#define UDC_RC_RX50READ         0x77   /* enable retries when reading floppies */
+#define UDC_RC_RX50WRT  0xF7
+
+/*
+ * Definition of bits in the Operating-Mode register
+ */
+#define UDC_MD_HDMODE  (1<<7)  /* must be 1 for all FDD and HDD */
+#define UDC_MD_CHKCOD  (3<<5)  /* error-check: FDD/CRC: 0, HDD/ECC: 1 */
+#define UDC_MD_DENS    (1<<4)  /* density select, must be 0 */
+#define UDC_MD_UNUSED  (1<<3)  /* bit 3 is not used and must be 0 */
+#define UDC_MD_SRATE   (7<<0)  /* seek step rate */
+
+#define UDC_MD_HDD      0xC0
+#define UDC_MD_RX33     0x82
+#define UDC_MD_RX50     0x81
+
+/*
+ * Definition of bits in the Chip-Status register
+ */
+#define UDC_CS_RETREQ  (1<<7)  /* retry required */
+#define UDC_CS_ECCATT  (1<<6)  /* error correction attempted */
+#define UDC_CS_ECCERR  (1<<5)  /* ECC/CRC error */
+#define UDC_CS_DELDATA (1<<4)  /* deleted data mark */
+#define UDC_CS_SYNCERR (1<<3)  /* synchronization error */
+#define UDC_CS_COMPERR (1<<2)  /* compare error */
+#define UDC_CS_PRESDRV (0x3)   /* present drive selected */
+
+/*
+ * Definition of bits in the Termination-Conditions register
+ */
+#define UDC_TC_CRCPRE  (1<<7)  /* CRC register preset, must be 1 */
+#define UDC_TC_UNUSED  (1<<6)  /* bit 6 is not used and must be 0 */
+#define UDC_TC_INTDONE (1<<5)  /* interrupt on done */
+#define UDC_TC_TDELDAT (1<<4)  /* terminate on deleted data */
+#define UDC_TC_TDSTAT3 (1<<3)  /* terminate on drive status 3 change */
+#define UDC_TC_TWPROT  (1<<2)  /* terminate on write-protect (FDD only) */
+#define UDC_TC_INTRDCH (1<<1)  /* interrupt on ready change (FDD only) */
+#define UDC_TC_TWRFLT  (1<<0)  /* interrupt on write-fault (HDD only) */
+
+#define UDC_TC_HDD      0xA5   /* 0xB5 ??? */
+#define UDC_TC_FDD      0xA0   /* 0xAA ??? 0xB4 ??? */
+
+/*
+ * Definition of bits in the Disk-Status register
+ */
+#define UDC_DS_SELACK  (1<<7)  /* select acknowledge (harddisk only!) */
+#define UDC_DS_INDEX   (1<<6)  /* index point */
+#define UDC_DS_SKCOM   (1<<5)  /* seek complete */
+#define UDC_DS_TRK00   (1<<4)  /* track 0 */
+#define UDC_DS_DSTAT3  (1<<3)  /* drive status 3 (MBZ) */
+#define UDC_DS_WRPROT  (1<<2)  /* write protect (floppy only!) */
+#define UDC_DS_READY   (1<<1)  /* drive ready bit */
+#define UDC_DS_WRFAULT (1<<0)  /* write fault */
+
+
diff --git a/sys/arch/vax/vsa/lk201.c b/sys/arch/vax/vsa/lk201.c
new file mode 100644 (file)
index 0000000..52e6029
--- /dev/null
@@ -0,0 +1,394 @@
+/*
+ * The LK201 keycode mapping routine is here, along with initialization
+ * functions for the keyboard and mouse.
+ */
+
+
+#include <sys/param.h>
+#include <sys/syslog.h>
+#include <sys/select.h>
+#include <dev/cons.h>
+
+#include <pmax/include/pmioctl.h>
+
+#include <pmax/dev/lk201.h>
+
+
+/* Exported functions */
+extern int kbdMapChar __P((int keycode));
+
+extern void KBDReset __P(( dev_t dev, void (*putc) (dev_t, int) ));
+
+/*
+ * Keyboard to Ascii, unshifted.
+ */
+static unsigned char unshiftedAscii[] = {
+/*  0 */ KBD_NOKEY,    KBD_NOKEY,      KBD_NOKEY,      KBD_NOKEY,
+/*  4 */ KBD_NOKEY,    KBD_NOKEY,      KBD_NOKEY,      KBD_NOKEY,
+/*  8 */ KBD_NOKEY,    KBD_NOKEY,      KBD_NOKEY,      KBD_NOKEY,
+/*  c */ KBD_NOKEY,    KBD_NOKEY,      KBD_NOKEY,      KBD_NOKEY,
+/* 10 */ KBD_NOKEY,    KBD_NOKEY,      KBD_NOKEY,      KBD_NOKEY,
+/* 14 */ KBD_NOKEY,    KBD_NOKEY,      KBD_NOKEY,      KBD_NOKEY,
+/* 18 */ KBD_NOKEY,    KBD_NOKEY,      KBD_NOKEY,      KBD_NOKEY,
+/* 1c */ KBD_NOKEY,    KBD_NOKEY,      KBD_NOKEY,      KBD_NOKEY,
+/* 20 */ KBD_NOKEY,    KBD_NOKEY,      KBD_NOKEY,      KBD_NOKEY,
+/* 24 */ KBD_NOKEY,    KBD_NOKEY,      KBD_NOKEY,      KBD_NOKEY,
+/* 28 */ KBD_NOKEY,    KBD_NOKEY,      KBD_NOKEY,      KBD_NOKEY,
+/* 2c */ KBD_NOKEY,    KBD_NOKEY,      KBD_NOKEY,      KBD_NOKEY,
+/* 30 */ KBD_NOKEY,    KBD_NOKEY,      KBD_NOKEY,      KBD_NOKEY,
+/* 34 */ KBD_NOKEY,    KBD_NOKEY,      KBD_NOKEY,      KBD_NOKEY,
+/* 38 */ KBD_NOKEY,    KBD_NOKEY,      KBD_NOKEY,      KBD_NOKEY,
+/* 3c */ KBD_NOKEY,    KBD_NOKEY,      KBD_NOKEY,      KBD_NOKEY,
+/* 40 */ KBD_NOKEY,    KBD_NOKEY,      KBD_NOKEY,      KBD_NOKEY,
+/* 44 */ KBD_NOKEY,    KBD_NOKEY,      KBD_NOKEY,      KBD_NOKEY,
+/* 48 */ KBD_NOKEY,    KBD_NOKEY,      KBD_NOKEY,      KBD_NOKEY,
+/* 4c */ KBD_NOKEY,    KBD_NOKEY,      KBD_NOKEY,      KBD_NOKEY,
+/* 50 */ KBD_NOKEY,    KBD_NOKEY,      KBD_NOKEY,      KBD_NOKEY,
+/* 54 */ KBD_NOKEY,    KBD_NOKEY,      KBD_F1,         KBD_F2,
+/* 58 */ KBD_F3,       KBD_F4,         KBD_F5,         KBD_NOKEY,
+/* 5c */ KBD_NOKEY,    KBD_NOKEY,      KBD_NOKEY,      KBD_NOKEY,
+/* 60 */ KBD_NOKEY,    KBD_NOKEY,      KBD_NOKEY,      KBD_NOKEY,
+/* 64 */ KBD_F6,       KBD_F7,         KBD_F8,         KBD_F9,
+/* 68 */ KBD_F10,      KBD_NOKEY,      KBD_NOKEY,      KBD_NOKEY,
+/* 6c */ KBD_NOKEY,    KBD_NOKEY,      KBD_NOKEY,      KBD_NOKEY,
+/* 70 */ KBD_NOKEY,    '\033',         KBD_F12,        KBD_F13,
+/* 74 */ KBD_F14,      KBD_NOKEY,      KBD_NOKEY,      KBD_NOKEY,
+/* 78 */ KBD_NOKEY,    KBD_NOKEY,      KBD_NOKEY,      KBD_NOKEY,
+/* 7c */ KBD_HELP,     KBD_DO,         KBD_NOKEY,      KBD_NOKEY,
+/* 80 */ KBD_F17,      KBD_F18,        KBD_F19,        KBD_F20,
+/* 84 */ KBD_NOKEY,    KBD_NOKEY,      KBD_NOKEY,      KBD_NOKEY,
+/* 88 */ KBD_NOKEY,    KBD_NOKEY,      KBD_FIND,       KBD_INSERT,
+/* 8c */ KBD_REMOVE,   KBD_SELECT,     KBD_PREVIOUS,   KBD_NEXT,
+/* 90 */ KBD_NOKEY,    KBD_NOKEY,      '0',            KBD_NOKEY,
+/* 94 */ '.',          KBD_KP_ENTER,   '1',            '2',
+/* 98 */ '3',          '4',            '5',            '6',
+/* 9c */ ',',          '7',            '8',            '9',
+/* a0 */ '-',          KBD_KP_F1,      KBD_KP_F2,      KBD_KP_F3,
+/* a4 */ KBD_KP_F4,    KBD_NOKEY,      KBD_NOKEY,      KBD_LEFT,
+/* a8 */ KBD_RIGHT,    KBD_DOWN,       KBD_UP,         KBD_NOKEY,
+/* ac */ KBD_NOKEY,    KBD_NOKEY,      KBD_SHIFT,      KBD_CONTROL,
+/* b0 */ KBD_CAPSLOCK, KBD_ALTERNATE,  KBD_NOKEY,      KBD_NOKEY,
+/* b4 */ KBD_NOKEY,    KBD_NOKEY,      KBD_NOKEY,      KBD_NOKEY,
+/* b8 */ KBD_NOKEY,    KBD_NOKEY,      KBD_NOKEY,      KBD_NOKEY,
+/* bc */ KBD_DEL,      KBD_RET,        KBD_TAB,        '`',
+/* c0 */ '1',          'q',            'a',            'z',
+/* c4 */ KBD_NOKEY,    '2',            'w',            's',
+/* c8 */ 'x',          '<',            KBD_NOKEY,      '3',
+/* cc */ 'e',          'd',            'c',            KBD_NOKEY,
+/* d0 */ '4',          'r',            'f',            'v',
+/* d4 */ ' ',          KBD_NOKEY,      '5',            't',
+/* d8 */ 'g',          'b',            KBD_NOKEY,      '6',
+/* dc */ 'y',          'h',            'n',            KBD_NOKEY,
+/* e0 */ '7',          'u',            'j',            'm',
+/* e4 */ KBD_NOKEY,    '8',            'i',            'k',
+/* e8 */ ',',          KBD_NOKEY,      '9',            'o',
+/* ec */ 'l',          '.',            KBD_NOKEY,      '0',
+/* f0 */ 'p',          KBD_NOKEY,      ';',            '/',
+/* f4 */ KBD_NOKEY,    '=',            ']',            '\\',
+/* f8 */ KBD_NOKEY,    '-',            '[',            '\'',
+/* fc */ KBD_NOKEY,    KBD_NOKEY,      KBD_NOKEY,      KBD_NOKEY,
+};
+
+/*
+ * Keyboard to Ascii, shifted.
+ */
+static unsigned char shiftedAscii[] = {
+/*  0 */ KBD_NOKEY,    KBD_NOKEY,      KBD_NOKEY,      KBD_NOKEY,
+/*  4 */ KBD_NOKEY,    KBD_NOKEY,      KBD_NOKEY,      KBD_NOKEY,
+/*  8 */ KBD_NOKEY,    KBD_NOKEY,      KBD_NOKEY,      KBD_NOKEY,
+/*  c */ KBD_NOKEY,    KBD_NOKEY,      KBD_NOKEY,      KBD_NOKEY,
+/* 10 */ KBD_NOKEY,    KBD_NOKEY,      KBD_NOKEY,      KBD_NOKEY,
+/* 14 */ KBD_NOKEY,    KBD_NOKEY,      KBD_NOKEY,      KBD_NOKEY,
+/* 18 */ KBD_NOKEY,    KBD_NOKEY,      KBD_NOKEY,      KBD_NOKEY,
+/* 1c */ KBD_NOKEY,    KBD_NOKEY,      KBD_NOKEY,      KBD_NOKEY,
+/* 20 */ KBD_NOKEY,    KBD_NOKEY,      KBD_NOKEY,      KBD_NOKEY,
+/* 24 */ KBD_NOKEY,    KBD_NOKEY,      KBD_NOKEY,      KBD_NOKEY,
+/* 28 */ KBD_NOKEY,    KBD_NOKEY,      KBD_NOKEY,      KBD_NOKEY,
+/* 2c */ KBD_NOKEY,    KBD_NOKEY,      KBD_NOKEY,      KBD_NOKEY,
+/* 30 */ KBD_NOKEY,    KBD_NOKEY,      KBD_NOKEY,      KBD_NOKEY,
+/* 34 */ KBD_NOKEY,    KBD_NOKEY,      KBD_NOKEY,      KBD_NOKEY,
+/* 38 */ KBD_NOKEY,    KBD_NOKEY,      KBD_NOKEY,      KBD_NOKEY,
+/* 3c */ KBD_NOKEY,    KBD_NOKEY,      KBD_NOKEY,      KBD_NOKEY,
+/* 40 */ KBD_NOKEY,    KBD_NOKEY,      KBD_NOKEY,      KBD_NOKEY,
+/* 44 */ KBD_NOKEY,    KBD_NOKEY,      KBD_NOKEY,      KBD_NOKEY,
+/* 48 */ KBD_NOKEY,    KBD_NOKEY,      KBD_NOKEY,      KBD_NOKEY,
+/* 4c */ KBD_NOKEY,    KBD_NOKEY,      KBD_NOKEY,      KBD_NOKEY,
+/* 50 */ KBD_NOKEY,    KBD_NOKEY,      KBD_NOKEY,      KBD_NOKEY,
+/* 54 */ KBD_NOKEY,    KBD_NOKEY,      KBD_F1,         KBD_F2,
+/* 58 */ KBD_F3,       KBD_F4,         KBD_F5,         KBD_NOKEY,
+/* 5c */ KBD_NOKEY,    KBD_NOKEY,      KBD_NOKEY,      KBD_NOKEY,
+/* 60 */ KBD_NOKEY,    KBD_NOKEY,      KBD_NOKEY,      KBD_NOKEY,
+/* 64 */ KBD_F6,       KBD_F7,         KBD_F8,         KBD_F9,
+/* 68 */ KBD_F10,      KBD_NOKEY,      KBD_NOKEY,      KBD_NOKEY,
+/* 6c */ KBD_NOKEY,    KBD_NOKEY,      KBD_NOKEY,      KBD_NOKEY,
+/* 70 */ KBD_NOKEY,    KBD_F11,        KBD_F12,        KBD_F13,
+/* 74 */ KBD_F14,      KBD_NOKEY,      KBD_NOKEY,      KBD_NOKEY,
+/* 78 */ KBD_NOKEY,    KBD_NOKEY,      KBD_NOKEY,      KBD_NOKEY,
+/* 7c */ KBD_HELP,     KBD_DO,         KBD_NOKEY,      KBD_NOKEY,
+/* 80 */ KBD_F17,      KBD_F18,        KBD_F19,        KBD_F20,
+/* 84 */ KBD_NOKEY,    KBD_NOKEY,      KBD_NOKEY,      KBD_NOKEY,
+/* 88 */ KBD_NOKEY,    KBD_NOKEY,      KBD_FIND,       KBD_INSERT,
+/* 8c */ KBD_REMOVE,   KBD_SELECT,     KBD_PREVIOUS,   KBD_NEXT,
+/* 90 */ KBD_NOKEY,    KBD_NOKEY,      '0',            KBD_NOKEY,
+/* 94 */ '.',          KBD_KP_ENTER,   '1',            '2',
+/* 98 */ '3',          '4',            '5',            '6',
+/* 9c */ ',',          '7',            '8',            '9',
+/* a0 */ '-',          KBD_KP_F1,      KBD_KP_F2,      KBD_KP_F3,
+/* a4 */ KBD_KP_F4,    KBD_NOKEY,      KBD_NOKEY,      KBD_LEFT,
+/* a8 */ KBD_RIGHT,    KBD_DOWN,       KBD_UP,         KBD_NOKEY,
+/* ac */ KBD_NOKEY,    KBD_NOKEY,      KBD_SHIFT,      KBD_CONTROL,
+/* b0 */ KBD_CAPSLOCK, KBD_ALTERNATE,  KBD_NOKEY,      KBD_NOKEY,
+/* b4 */ KBD_NOKEY,    KBD_NOKEY,      KBD_NOKEY,      KBD_NOKEY,
+/* b8 */ KBD_NOKEY,    KBD_NOKEY,      KBD_NOKEY,      KBD_NOKEY,
+/* bc */ KBD_DEL,      KBD_RET,        KBD_TAB,        '~',
+/* c0 */ '!',          'q',            'a',            'z',
+/* c4 */ KBD_NOKEY,    '@',            'w',            's',
+/* c8 */ 'x',          '>',            KBD_NOKEY,      '#',
+/* cc */ 'e',          'd',            'c',            KBD_NOKEY,
+/* d0 */ '$',          'r',            'f',            'v',
+/* d4 */ ' ',          KBD_NOKEY,      '%',            't',
+/* d8 */ 'g',          'b',            KBD_NOKEY,      '^',
+/* dc */ 'y',          'h',            'n',            KBD_NOKEY,
+/* e0 */ '&',          'u',            'j',            'm',
+/* e4 */ KBD_NOKEY,    '*',            'i',            'k',
+/* e8 */ '<',          KBD_NOKEY,      '(',            'o',
+/* ec */ 'l',          '>',            KBD_NOKEY,      ')',
+/* f0 */ 'p',          KBD_NOKEY,      ':',            '?',
+/* f4 */ KBD_NOKEY,    '+',            '}',            '|',
+/* f8 */ KBD_NOKEY,    '_',            '{',            '"',
+/* fc */ KBD_NOKEY,    KBD_NOKEY,      KBD_NOKEY,      KBD_NOKEY,
+};
+
+/* 
+ * Keyboard initialization string.
+ */
+static u_char kbdInitString[] = {
+       LK_LED_ENABLE, LED_ALL,         /* show we are resetting keyboard */
+       LK_DEFAULTS,
+       LK_CMD_MODE(LK_AUTODOWN, 1), 
+       LK_CMD_MODE(LK_AUTODOWN, 2), 
+       LK_CMD_MODE(LK_AUTODOWN, 3), 
+       LK_CMD_MODE(LK_DOWN, 4),        /* could also be LK_AUTODOWN */
+       LK_CMD_MODE(LK_UPDOWN, 5),   
+       LK_CMD_MODE(LK_UPDOWN, 6),   
+       LK_CMD_MODE(LK_AUTODOWN, 7), 
+       LK_CMD_MODE(LK_AUTODOWN, 8), 
+       LK_CMD_MODE(LK_AUTODOWN, 9), 
+       LK_CMD_MODE(LK_AUTODOWN, 10), 
+       LK_CMD_MODE(LK_AUTODOWN, 11), 
+       LK_CMD_MODE(LK_AUTODOWN, 12), 
+       LK_CMD_MODE(LK_DOWN, 13), 
+       LK_CMD_MODE(LK_AUTODOWN, 14),
+       LK_AR_ENABLE,                   /* we want autorepeat by default */
+       LK_CL_ENABLE, 0x83,             /* keyclick, volume */
+       LK_KBD_ENABLE,                  /* the keyboard itself */
+       LK_BELL_ENABLE, 0x83,           /* keyboard bell, volume */
+       LK_LED_DISABLE, LED_ALL,        /* clear keyboard leds */
+};
+
+
+/*
+ * Initialize the Keyboard.
+ */
+void
+KBDReset(kbddev, putc)
+       dev_t kbddev;
+       void (*putc) __P((dev_t, int));
+{
+       register int i;
+       static int inKBDReset;
+
+       if (inKBDReset)
+               return;
+       inKBDReset = 1;
+       for (i = 0; i < sizeof(kbdInitString); i++)
+               (*putc)(kbddev, (int)kbdInitString[i]);
+       inKBDReset = 0;
+}
+
+/*
+ * ----------------------------------------------------------------------------
+ *
+ * kbdMapChar --
+ *
+ *     Map characters from the keyboard to ASCII. Return -1 if there is
+ *     no valid mapping.
+ *
+ * Results:
+ *     None.
+ *
+ * Side effects:
+ *     Remember state of shift and control keys.
+ *
+ * ----------------------------------------------------------------------------
+ */
+int
+kbdMapChar(cc)
+       int cc;
+{
+       static u_char shiftDown;
+       static u_char ctrlDown;
+       static u_char lastChar;
+
+       switch (cc) {
+       case KEY_REPEAT:
+               cc = lastChar;
+               goto done;
+
+       case KEY_UP:
+               shiftDown = 0;
+               ctrlDown = 0;
+               return (-1);
+
+       case KEY_SHIFT:
+       case KEY_R_SHIFT:
+               if (ctrlDown || shiftDown)
+                       shiftDown = 0;
+               else
+                       shiftDown = 1;
+               return (-1);
+
+       case KEY_CONTROL:
+               if (shiftDown || ctrlDown)
+                       ctrlDown = 0;
+               else
+                       ctrlDown = 1;
+               return (-1);
+
+       case LK_POWER_ERROR:
+       case LK_KDOWN_ERROR:
+       case LK_INPUT_ERROR:
+       case LK_OUTPUT_ERROR:
+               log(LOG_WARNING,
+                       "lk201: keyboard error, code=%x\n", cc);
+               return (-1);
+       }
+       if (shiftDown)
+               cc = shiftedAscii[cc];
+       else
+               cc = unshiftedAscii[cc];
+       if (cc >= KBD_NOKEY) {
+               /*
+                * A function key was typed - ignore it.
+                */
+               return (-1);
+       }
+       if (cc >= 'a' && cc <= 'z') {
+               if (ctrlDown)
+                       cc = cc - 'a' + '\1'; /* ^A */
+               else if (shiftDown)
+                       cc = cc - 'a' + 'A';
+       } else if (ctrlDown) {
+               if (cc >= '[' && cc <= '_')
+                       cc = cc - '@';
+               else if (cc == ' ' || cc == '@')
+                       cc = '\0';
+       }
+       lastChar = cc;
+done:
+       return (cc);
+}
+
+
+static int (*raw_kbd_getc) __P((dev_t dev)) = NULL;
+static dev_t lk_in_dev = NODEV;
+
+/*
+ * Divert input from a serial port to the lk-201 keyboard handler.
+ */
+void
+lk_divert(getfn, in_dev)
+       int (*getfn) __P ((dev_t dev)) ;
+       dev_t in_dev;
+{
+       raw_kbd_getc = getfn;
+       lk_in_dev = in_dev;
+}
+
+/*
+ * Get an ASCII character off of the keyboard.
+ * Simply pass the getc request onto the underlying
+ * serial driver, and map the resulting LK-201 keycode to ASCII.
+ * FIXME: this design can't handle cursor or keypad keys,
+ * and should be thrown away and replaced with a stackable
+ * "Bstreams"-style driver.
+ */
+int
+LKgetc(dev)
+       dev_t dev;      /* ignored */
+{
+       register int c;
+
+       extern  sccGetc();
+
+#if 0
+/*XXX*/ printf("LK-201 getc 0x%x( [%d %d]) in_dev [%d %d]\n",
+              raw_kbd_getc,
+              major(dev), minor(dev),
+              major(lk_in_dev), minor(lk_in_dev));
+#endif
+
+       if (raw_kbd_getc == NULL) {
+               panic("Reading from LK-201 before keyboard driver diverted\n");
+               return (-1);
+       }
+
+       for (;;) {
+               /* c = (*cn_tab.cn_kbdgetc)(cn_tab.cn_dev); */
+               c = (*raw_kbd_getc) (lk_in_dev);
+#if 0
+/*XXX*/ printf(" 0x%x [%c]", c, c);
+#endif
+               if (c == 0)
+                       return (-1);
+               if ((c = kbdMapChar(c & 0xff)) >= 0)
+                       break;
+       }
+       return (c);
+}
+
+
+/*
+ * Initialize the mouse.  (Doesn't really belong here.)
+ */
+void
+MouseInit(mdev, putc, getc)
+       dev_t mdev;
+       void (*putc) __P((dev_t, int));
+       int (*getc) __P((dev_t));
+{
+       int id_byte1, id_byte2, id_byte3, id_byte4;
+
+       /*
+        * Initialize the mouse.
+        */
+       (*putc)(mdev, MOUSE_SELF_TEST);
+       id_byte1 = (*getc)(mdev);
+       if (id_byte1 < 0) {
+               printf("MouseInit: Timeout on 1st byte of self-test report\n");
+               return;
+       }
+       id_byte2 = (*getc)(mdev);
+       if (id_byte2 < 0) {
+               printf("MouseInit: Timeout on 2nd byte of self-test report\n");
+               return;
+       }
+       id_byte3 = (*getc)(mdev);
+       if (id_byte3 < 0) {
+               printf("MouseInit: Timeout on 3rd byte of self-test report\n");
+               return;
+       }
+       id_byte4 = (*getc)(mdev);
+       if (id_byte4 < 0) {
+               printf("MouseInit: Timeout on 4th byte of self-test report\n");
+               return;
+       }
+       if ((id_byte2 & 0x0f) != 0x2)
+               printf("MouseInit: We don't have a mouse!!!\n");
+       /*
+        * For some reason, the mouse doesn't see this command if it comes
+        * too soon after a self test.
+        */
+       DELAY(100);
+       (*putc)(mdev, MOUSE_INCREMENTAL);
+}
diff --git a/sys/arch/vax/vsa/ncr.c b/sys/arch/vax/vsa/ncr.c
new file mode 100644 (file)
index 0000000..69e7411
--- /dev/null
@@ -0,0 +1,1283 @@
+/*     $NetBSD: ncr.c,v 1.5 1996/10/13 03:36:14 christos Exp $ */
+
+/* #define DEBUG       /* */
+/* #define TRACE       /* */
+/* #define POLL_MODE   /* */
+#define USE_VMAPBUF
+
+/*
+ * Copyright (c) 1995 David Jones, Gordon W. Ross
+ * Copyright (c) 1994 Adam Glass
+ * 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. The name of the authors may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ * 4. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by
+ *     Adam Glass, David Jones, and Gordon Ross
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``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 AUTHORS 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.
+ */
+
+/*
+ * This file contains only the machine-dependent parts of the
+ * Sun3 SCSI driver.  (Autoconfig stuff and DMA functions.)
+ * The machine-independent parts are in ncr5380sbc.c
+ *
+ * Supported hardware includes:
+ * Sun SCSI-3 on OBIO (Sun3/50,Sun3/60)
+ * Sun SCSI-3 on VME (Sun3/160,Sun3/260)
+ *
+ * Could be made to support the Sun3/E if someone wanted to.
+ *
+ * Note:  Both supported variants of the Sun SCSI-3 adapter have
+ * some really unusual "features" for this driver to deal with,
+ * generally related to the DMA engine.         The OBIO variant will
+ * ignore any attempt to write the FIFO count register while the
+ * SCSI bus is in DATA_IN or DATA_OUT phase.  This is dealt with
+ * by setting the FIFO count early in COMMAND or MSG_IN phase.
+ *
+ * The VME variant has a bit to enable or disable the DMA engine,
+ * but that bit also gates the interrupt line from the NCR5380!
+ * Therefore, in order to get any interrupt from the 5380, (i.e.
+ * for reselect) one must clear the DMA engine transfer count and
+ * then enable DMA.  This has the further complication that you
+ * CAN NOT touch the NCR5380 while the DMA enable bit is set, so
+ * we have to turn DMA back off before we even look at the 5380.
+ *
+ * What wonderfully whacky hardware this is!
+ *
+ * Credits, history:
+ *
+ * David Jones wrote the initial version of this module, which
+ * included support for the VME adapter only. (no reselection).
+ *
+ * Gordon Ross added support for the OBIO adapter, and re-worked
+ * both the VME and OBIO code to support disconnect/reselect.
+ * (Required figuring out the hardware "features" noted above.)
+ *
+ * The autoconfiguration boilerplate came from Adam Glass.
+ *
+ * VS2000:
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/conf.h>
+#include <sys/file.h>
+#include <sys/stat.h> 
+#include <sys/ioctl.h>
+#include <sys/buf.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/disk.h>
+#include <sys/syslog.h>
+
+/* #include <sys/errno.h> */
+
+#include <scsi/scsi_all.h>
+#include <scsi/scsi_debug.h>
+#include <scsi/scsiconf.h>
+
+#include <machine/uvax.h>
+#include <machine/ka410.h>
+#include <machine/ka43.h>
+#include <machine/vsbus.h>     /* struct confargs */
+
+#include <dev/ic/ncr5380reg.h>
+#include <dev/ic/ncr5380var.h>
+
+#define trace(x)
+#define debug(x)
+
+#ifndef NCR5380_CSRBITS
+#define NCR5380_CSRBITS \
+       "\020\010DEND\007DREQ\006PERR\005IREQ\004MTCH\003DCON\002ATN\001ACK"
+#endif
+
+#ifndef NCR5380_BUSCSRBITS
+#define NCR5380_BUSCSRBITS \
+       "\020\010RST\007BSY\006REQ\005MSG\004C/D\003I/O\002SEL\001DBP"
+#endif
+
+#include "ncr.h"
+
+#ifdef DDB
+#define integrate
+#else
+#define integrate static
+#endif
+
+/*
+ * Transfers smaller than this are done using PIO
+ * (on assumption they're not worth DMA overhead)
+ */
+#define MIN_DMA_LEN 128 
+
+/*
+ * Transfers lager than 65535 bytes need to be split-up.
+ * (Some of the FIFO logic has only 16 bits counters.)
+ * Make the size an integer multiple of the page size
+ * to avoid buf/cluster remap problems.         (paranoid?)
+ *
+ * bertram: VS2000 has an DMA-area which is 16KB, thus
+ * have a maximum DMA-size of 16KB...
+ */
+#ifdef DMA_SHARED
+#define MAX_DMA_LEN    0x2000          /* (8 * 1024) */
+#define DMA_ADDR_HBYTE 0x20
+#define DMA_ADDR_LBYTE 0x00
+#else
+#define MAX_DMA_LEN    0x4000          /* (16 * 1024) */
+#define DMA_ADDR_HBYTE 0x00
+#define DMA_ADDR_LBYTE 0x00
+#endif
+
+#ifdef DEBUG
+int si_debug = 3;
+static int si_link_flags = 0 /* | SDEV_DB2 */ ;
+#endif
+
+/*
+ * This structure is used to keep track of mappedpwd DMA requests.
+ * Note: combined the UDC command block with this structure, so
+ * the array of these has to be in DVMA space.
+ */
+struct si_dma_handle {
+       int             dh_flags;
+#define SIDH_BUSY      1               /* This DH is in use */
+#define SIDH_OUT       2               /* DMA does data out (write) */
+#define SIDH_PHYS      4
+#define SIDH_DONE      8
+       u_char *        dh_addr;        /* KVA of start of buffer */
+       int             dh_maplen;      /* Length of KVA mapping. */
+       u_char *        dh_dvma;        /* VA of buffer in DVMA space */
+       int             dh_xlen;
+};
+
+/*
+ * The first structure member has to be the ncr5380_softc
+ * so we can just cast to go back and fourth between them.
+ */
+struct si_softc {
+       struct ncr5380_softc    ncr_sc;
+       volatile struct si_regs *sc_regs;       /* do we really need this? */
+
+       struct si_dma_handle    *sc_dma;
+       struct confargs         *sc_cfargs;     
+
+       int     sc_xflags;      /* ka410/ka43: resid, sizeof(areg) */
+
+       char    *sc_dbase;
+       int     sc_dsize;
+       
+       volatile char   *sc_dareg;
+       volatile short  *sc_dcreg;
+       volatile char   *sc_ddreg;
+       volatile int    sc_dflags;
+       
+#define VSDMA_LOCKED   0x80    /* */
+#define VSDMA_WANTED   0x40    /* */
+#define VSDMA_IWANTED  0x20
+#define VSDMA_BLOCKED  0x10
+#define VSDMA_DMABUSY  0x08    /* DMA in progress */
+#define VSDMA_REGBUSY  0x04    /* accessing registers */
+#define VSDMA_WRBUF    0x02    /* writing to bounce-buffer */
+#define VSDMA_RDBUF    0x01    /* reading from bounce-buffer */
+
+#define VSDMA_STATUS   0xF0
+#define VSDMA_LCKTYPE  0x0F
+
+#ifdef POLL_MODE
+       volatile u_char *intreq;
+       volatile u_char *intclr;
+       volatile u_char *intmsk;
+       volatile int    intbit;
+#endif
+};
+
+extern int cold;       /* enable polling while cold-flag set */
+
+/* Options.  Interesting values are: 1,3,7 */
+int si_options = 3;    /* bertram: 3 or 7 ??? */
+#define SI_ENABLE_DMA  1       /* Use DMA (maybe polled) */
+#define SI_DMA_INTR    2       /* DMA completion interrupts */
+#define SI_DO_RESELECT 4       /* Allow disconnect/reselect */
+
+#define DMA_DIR_IN  1
+#define DMA_DIR_OUT 0
+
+/* How long to wait for DMA before declaring an error. */
+int si_dma_intr_timo = 500;    /* ticks (sec. X 100) */
+
+integrate char si_name[] = "ncr";
+integrate int  si_match();
+integrate void si_attach();
+integrate int  si_intr __P((void *));
+
+integrate void si_minphys __P((struct buf *bp));
+integrate void si_reset_adapter __P((struct ncr5380_softc *sc));
+
+void si_dma_alloc __P((struct ncr5380_softc *));
+void si_dma_free __P((struct ncr5380_softc *));
+void si_dma_poll __P((struct ncr5380_softc *));
+
+void si_intr_on __P((struct ncr5380_softc *));
+void si_intr_off __P((struct ncr5380_softc *));
+
+int si_dmaLockBus __P((struct ncr5380_softc *, int));
+int si_dmaToggleLock __P((struct ncr5380_softc *, int, int));
+int si_dmaReleaseBus __P((struct ncr5380_softc *, int));
+
+void si_dma_setup __P((struct ncr5380_softc *));
+void si_dma_start __P((struct ncr5380_softc *));
+void si_dma_eop __P((struct ncr5380_softc *));
+void si_dma_stop __P((struct ncr5380_softc *));
+
+static struct scsi_adapter     si_ops = {
+       ncr5380_scsi_cmd,               /* scsi_cmd()           */
+       si_minphys,                     /* scsi_minphys()       */
+       NULL,                           /* open_target_lu()     */
+       NULL,                           /* close_target_lu()    */
+};
+
+/* This is copied from julian's bt driver */
+/* "so we have a default dev struct for our link struct." */
+static struct scsi_device si_dev = {
+       NULL,           /* Use default error handler.       */
+       NULL,           /* Use default start handler.           */
+       NULL,           /* Use default async handler.       */
+       NULL,           /* Use default "done" routine.      */
+};
+
+
+struct cfdriver ncr_cd = {
+       NULL, si_name, DV_DULL
+};
+struct cfattach ncr_ca = {
+       sizeof(struct si_softc), si_match, si_attach,
+};
+
+void
+dk_establish(p,q)
+       struct disk *p;
+       struct device *q;
+{
+#if 0
+       printf ("faking dk_establish()...\n");
+#endif
+}
+
+
+integrate int
+si_match(parent, match, aux)
+       struct device   *parent;
+       void            *match, *aux;
+{
+       struct cfdata   *cf = match;
+       struct confargs *ca = aux;
+
+       trace(("ncr_match(0x%x, %d, %s)\n", parent, cf->cf_unit, ca->ca_name));
+
+       if (strcmp(ca->ca_name, "ncr") &&
+           strcmp(ca->ca_name, "ncr5380") &&
+           strcmp(ca->ca_name, "NCR5380"))
+               return (0);
+
+       /*
+        * we just define it being there ...
+        */
+       return (1);
+}
+
+integrate void
+si_set_portid(pid,port)
+       int pid;
+       int port;
+{
+       struct {
+         u_long    :2;
+         u_long id0:3;
+         u_long id1:3;
+         u_long    :26;
+       } *p;
+
+#ifdef DEBUG
+       int *ip;
+       ip = (void*)uvax_phys2virt(KA410_SCSIPORT);
+       p = (void*)uvax_phys2virt(KA410_SCSIPORT);
+       printf("scsi-id: (%x/%d) %d / %d\n", *ip, *ip, p->id0, p->id1);
+#endif
+
+       p = (void*)uvax_phys2virt(KA410_SCSIPORT);
+       switch (port) {
+       case 0:
+               p->id0 = pid;
+               printf(": scsi-id %d\n", p->id0);
+               break;
+       case 1:
+               p->id1 = pid;
+               printf(": scsi-id %d\n", p->id1);
+               break;
+       default:
+               printf("invalid port-number %d\n", port);
+       }
+}
+
+integrate void
+si_attach(parent, self, aux)
+       struct device   *parent, *self;
+       void            *aux;
+{
+       struct si_softc *sc = (struct si_softc *) self;
+       struct ncr5380_softc *ncr_sc = (struct ncr5380_softc *)sc;
+       volatile struct si_regs *regs;
+       struct confargs *ca = aux;
+       int i;
+       int *ip = aux;;
+
+       trace (("ncr_attach(0x%x, 0x%x, %s)\n", parent, self, ca->ca_name));
+
+       /*
+        *
+        */
+#ifdef POLL_MODE
+       sc->intreq = (void*)uvax_phys2virt(KA410_INTREQ);
+       sc->intmsk = (void*)uvax_phys2virt(KA410_INTMSK);
+       sc->intclr = (void*)uvax_phys2virt(KA410_INTCLR);
+       sc->intbit = ca->ca_intbit;
+#endif
+
+       sc->sc_cfargs = ca;     /* needed for interrupt-setup */
+
+       regs = (void*)uvax_phys2virt(ca->ca_ioaddr);
+
+       sc->sc_dareg = (void*)uvax_phys2virt(ca->ca_dareg);
+       sc->sc_dcreg = (void*)uvax_phys2virt(ca->ca_dcreg);
+       sc->sc_ddreg = (void*)uvax_phys2virt(ca->ca_ddreg);
+       sc->sc_dbase = (void*)uvax_phys2virt(ca->ca_dbase);
+       sc->sc_dsize = ca->ca_dsize;
+       sc->sc_dflags = 4;      /* XXX */
+       sc->sc_xflags = ca->ca_dflag;   /* should/will be renamed */
+       /*
+        * Fill in the prototype scsi_link.
+        */
+       ncr_sc->sc_link.channel = SCSI_CHANNEL_ONLY_ONE;
+       ncr_sc->sc_link.adapter_softc = sc;
+       ncr_sc->sc_link.adapter_target = ca->ca_idval;
+       ncr_sc->sc_link.adapter = &si_ops;
+       ncr_sc->sc_link.device = &si_dev;
+
+       si_set_portid(ca->ca_idval, ncr_sc->sc_dev.dv_unit);
+
+       /*
+        * Initialize fields used by the MI code
+        */
+       ncr_sc->sci_r0 = (void*)&regs->sci.sci_r0;
+       ncr_sc->sci_r1 = (void*)&regs->sci.sci_r1;
+       ncr_sc->sci_r2 = (void*)&regs->sci.sci_r2;
+       ncr_sc->sci_r3 = (void*)&regs->sci.sci_r3;
+       ncr_sc->sci_r4 = (void*)&regs->sci.sci_r4;
+       ncr_sc->sci_r5 = (void*)&regs->sci.sci_r5;
+       ncr_sc->sci_r6 = (void*)&regs->sci.sci_r6;
+       ncr_sc->sci_r7 = (void*)&regs->sci.sci_r7;
+
+       /*
+        * MD function pointers used by the MI code.
+        */
+       ncr_sc->sc_pio_out = ncr5380_pio_out;
+       ncr_sc->sc_pio_in =  ncr5380_pio_in;
+       ncr_sc->sc_dma_alloc = si_dma_alloc;
+       ncr_sc->sc_dma_free  = si_dma_free;
+       ncr_sc->sc_dma_poll  = si_dma_poll;     /* si_dma_poll not used! */
+       ncr_sc->sc_intr_on   = si_intr_on;      /* vsbus_unlockDMA; */
+       ncr_sc->sc_intr_off  = si_intr_off;     /* vsbus_lockDMA; */
+
+       ncr_sc->sc_dma_setup = NULL;            /* si_dma_setup not used! */
+       ncr_sc->sc_dma_start = si_dma_start;
+       ncr_sc->sc_dma_eop   = NULL;    
+       ncr_sc->sc_dma_stop  = si_dma_stop;
+
+       ncr_sc->sc_flags = 0;
+       if (si_options & SI_DO_RESELECT)
+               ncr_sc->sc_flags |= NCR5380_PERMIT_RESELECT;
+       if ((si_options & SI_DMA_INTR) == 0)
+               ncr_sc->sc_flags |= NCR5380_FORCE_POLLING;
+       ncr_sc->sc_min_dma_len = MIN_DMA_LEN;
+
+       /*
+        * Initialize fields used only here in the MD code.
+        */
+       i = SCI_OPENINGS * sizeof(struct si_dma_handle);
+       sc->sc_dma = (struct si_dma_handle *) malloc(i);
+       if (sc->sc_dma == NULL)
+               panic("si: dvma_malloc failed\n");
+       for (i = 0; i < SCI_OPENINGS; i++)
+               sc->sc_dma[i].dh_flags = 0;
+
+       sc->sc_regs = regs;
+       
+#ifdef DEBUG
+       if (si_debug)
+               printf("si: Set TheSoftC=%x TheRegs=%x\n", sc, regs);
+       ncr_sc->sc_link.flags |= si_link_flags;
+#endif
+
+       /*
+        *  Initialize si board itself.
+        */
+       si_reset_adapter(ncr_sc);
+       ncr5380_init(ncr_sc);
+       ncr5380_reset_scsibus(ncr_sc);
+       config_found(self, &(ncr_sc->sc_link), scsiprint);
+
+       /* 
+        * Now ready for interrupts. 
+        */
+       vsbus_intr_register(sc->sc_cfargs, si_intr, (void *)sc);
+       vsbus_intr_enable(sc->sc_cfargs);
+}
+
+integrate void
+si_minphys(struct buf *bp)
+{
+       debug(("minphys: blkno=%d, bcount=%d, data=0x%x, flags=%x\n",
+             bp->b_blkno, bp->b_bcount, bp->b_data, bp->b_flags));
+
+       if (bp->b_bcount > MAX_DMA_LEN) {
+#ifdef DEBUG
+               if (si_debug) {
+                       printf("si_minphys len = 0x%x.\n", bp->b_bcount);
+                       Debugger();
+               }
+#endif
+               bp->b_bcount = MAX_DMA_LEN;
+       }
+       return (minphys(bp));
+}
+
+
+#define CSR_WANT (SI_CSR_SBC_IP | SI_CSR_DMA_IP | \
+       SI_CSR_DMA_CONFLICT | SI_CSR_DMA_BUS_ERR )
+
+static int si_intrCount = 0;
+static int lastCSR = 0;
+
+integrate int
+si_intr(arg)
+       void *arg; 
+{
+       struct ncr5380_softc *ncr_sc = arg;
+       struct si_softc *sc = arg;
+       int count, claimed;
+
+       count = ++si_intrCount;
+       trace(("%s: si-intr(%d).....\n", ncr_sc->sc_dev.dv_xname, count));
+
+#ifdef DEBUG
+       /*
+        * Each DMA interrupt is followed by one spurious(?) interrupt.
+        * if (ncr_sc->sc_state & NCR_WORKING == 0) we know, that the
+        * interrupt was not claimed by the higher-level routine, so that
+        * it might be save to ignore these...
+        */
+       if ((ncr_sc->sc_state & NCR_DOINGDMA) == 0) {
+               printf("spurious(%d): %x, %d, status=%b\n", count,
+                      sc->sc_dflags, ncr_sc->sc_ncmds,
+                      *ncr_sc->sci_csr, NCR5380_CSRBITS);
+       }
+#endif
+       /*
+        * If there was a DMA operation in progress, now it's no longer
+        * active, since whatever caused the interrupt also interrupted
+        * the DMA operation. Thus accessing the registers now doesn't
+        * harm anything which is not yet broken...
+        */
+       debug(("si_intr(status: %x, dma-count: %d)\n", 
+              *ncr_sc->sci_csr, *sc->sc_dcreg));
+
+       /*
+        * First check for DMA errors / incomplete transfers
+        * If operation was read/data-in, the copy data from buffer
+        */
+       if (ncr_sc->sc_state & NCR_DOINGDMA) {
+               struct sci_req *sr = ncr_sc->sc_current;
+               struct si_dma_handle *dh = sr->sr_dma_hand;
+               int resid, ntrans;
+
+               resid = *sc->sc_dcreg;
+               if (resid == 1 && sc->sc_xflags) {
+                 debug(("correcting resid...\n"));
+                 resid = 0;
+               }
+               ntrans = dh->dh_xlen + resid;
+               if (resid == 0) {
+                       if ((dh->dh_flags & SIDH_OUT) == 0) {
+                               si_dmaToggleLock(ncr_sc,
+                                                VSDMA_DMABUSY, VSDMA_RDBUF);
+                               bcopy(sc->sc_dbase, dh->dh_dvma, ntrans);
+                               si_dmaToggleLock(ncr_sc,
+                                                VSDMA_RDBUF, VSDMA_DMABUSY);
+                               dh->dh_flags |= SIDH_DONE;
+                       }
+               }
+               else {
+#ifdef DEBUG
+                       int csr = *ncr_sc->sci_csr;
+                       printf("DMA incomplete (%d/%d) status = %b\n",
+                              ntrans, resid, csr, NCR5380_CSRBITS);
+                       if(csr != lastCSR) {
+                               int k = (csr & ~lastCSR) | (~csr & lastCSR);
+                               debug(("Changed status bits: %b\n",
+                                      k, NCR5380_CSRBITS));
+                               lastCSR = csr & 0xFF;
+                       }
+#endif
+                       printf("DMA incomplete: ntrans=%d/%d, lock=%x\n", 
+                              ntrans, dh->dh_xlen, sc->sc_dflags);
+                       ncr_sc->sc_state |= NCR_ABORTING;
+               }
+
+               if ((sc->sc_dflags & VSDMA_BLOCKED) == 0) {
+                       printf("not blocked during DMA.\n");
+               }
+               sc->sc_dflags &= ~VSDMA_BLOCKED;
+               si_dmaReleaseBus(ncr_sc, VSDMA_DMABUSY);
+       }
+       if ((sc->sc_dflags & VSDMA_BLOCKED) != 0) {
+               printf("blocked while not doing DMA.\n");
+               sc->sc_dflags &= ~VSDMA_BLOCKED;
+       }
+
+       /*
+        * Now, whatever it was, let the ncr5380sbc routine handle it...
+        */
+       claimed = ncr5380_intr(ncr_sc);
+#ifdef DEBUG
+       if (!claimed) {
+               printf("si_intr: spurious from SBC\n");
+               if (si_debug & 4) {
+                       Debugger();     /* XXX */
+               }
+       }
+#endif
+       trace(("%s: si-intr(%d) done, claimed=%d\n", 
+              ncr_sc->sc_dev.dv_xname, count, claimed));
+       return (claimed);
+}
+
+
+integrate void
+si_reset_adapter(struct ncr5380_softc *ncr_sc)
+{
+       struct si_softc *sc = (struct si_softc *)ncr_sc;
+       volatile struct si_regs *si = sc->sc_regs;
+
+#ifdef DEBUG
+       if (si_debug) {
+               printf("si_reset_adapter\n");
+       }
+#endif
+       SCI_CLR_INTR(ncr_sc);
+}
+
+
+/*****************************************************************
+ * Common functions for DMA
+ ****************************************************************/
+
+/*
+ * Allocate a DMA handle and put it in sc->sc_dma.  Prepare
+ * for DMA transfer.  On the Sun3, this means mapping the buffer
+ * into DVMA space.  dvma_mapin() flushes the cache for us.
+ */
+void
+si_dma_alloc(ncr_sc)
+       struct ncr5380_softc *ncr_sc;
+{
+       struct si_softc *sc = (struct si_softc *)ncr_sc;
+       struct sci_req *sr = ncr_sc->sc_current;
+       struct scsi_xfer *xs = sr->sr_xs;
+       struct buf *bp = sr->sr_xs->bp;
+       struct si_dma_handle *dh;
+       int i, xlen;
+       u_long addr;
+
+       trace (("si_dma_alloc()\n"));
+
+#ifdef DIAGNOSTIC
+       if (sr->sr_dma_hand != NULL)
+               panic("si_dma_alloc: already have DMA handle");
+#endif
+
+       addr = (u_long) ncr_sc->sc_dataptr;
+       debug(("addr=%x, dataptr=%x\n", addr, ncr_sc->sc_dataptr));
+       xlen = ncr_sc->sc_datalen;
+
+       /* Make sure our caller checked sc_min_dma_len. */
+       if (xlen < MIN_DMA_LEN)
+               panic("si_dma_alloc: xlen=0x%x\n", xlen);
+
+       /*
+        * Never attempt single transfers of more than 63k, because
+        * our count register may be only 16 bits (an OBIO adapter).
+        * This should never happen since already bounded by minphys().
+        * XXX - Should just segment these...
+        */
+       if (xlen > MAX_DMA_LEN) {
+               printf("si_dma_alloc: excessive xlen=0x%x\n", xlen);
+               Debugger();
+               ncr_sc->sc_datalen = xlen = MAX_DMA_LEN;
+       }
+
+       /* Find free DMA handle.  Guaranteed to find one since we have
+          as many DMA handles as the driver has processes. */
+       for (i = 0; i < SCI_OPENINGS; i++) {
+               if ((sc->sc_dma[i].dh_flags & SIDH_BUSY) == 0)
+                       goto found;
+       }
+       panic("si: no free DMA handles.");
+found:
+
+       dh = &sc->sc_dma[i];
+       dh->dh_flags = SIDH_BUSY;
+       dh->dh_addr = (u_char*) addr;
+       dh->dh_maplen  = xlen;
+       dh->dh_xlen  = xlen;
+       dh->dh_dvma = 0;
+
+       /* Copy the "write" flag for convenience. */
+       if (xs->flags & SCSI_DATA_OUT)
+               dh->dh_flags |= SIDH_OUT;
+
+#if 1
+       /*
+        * If the buffer has the flag B_PHYS, the the address specified
+        * in the buffer is a user-space address and we need to remap
+        * this address into kernel space so that using this buffer
+        * within the interrupt routine will work.
+        * If it's already a kernel space address, we need to make sure
+        * that all pages are in-core. the mapin() routine takes care
+        * of that.
+        */
+       if (bp && (bp->b_flags & B_PHYS))
+               dh->dh_flags |= SIDH_PHYS;
+#endif
+       
+       if (!bp) {
+               printf("ncr.c: struct buf *bp is null-pointer.\n");
+               dh->dh_flags = 0;
+               return;
+       }
+       if (bp->b_bcount < 0 || bp->b_bcount > MAX_DMA_LEN) {
+               printf("ncr.c: invalid bcount %d (0x%x)\n", 
+                      bp->b_bcount, bp->b_bcount);
+               dh->dh_flags = 0;
+               return;
+       }
+       dh->dh_dvma = bp->b_data;
+#if 0
+       /*
+        * mapping of user-space addresses is no longer neccessary, now
+        * that the vmapbuf/vunmapbuf routines exist. Now the higher-level
+        * driver already cares for the mapping!
+        */
+       if (bp->b_flags & B_PHYS) {
+               xdebug(("not mapping in... %x/%x %x\n", bp->b_saveaddr, 
+                       bp->b_data, bp->b_bcount));
+#ifdef USE_VMAPBUF
+               dh->dh_addr = bp->b_data;
+               dh->dh_maplen = bp->b_bcount;
+               vmapbuf(bp, bp->b_bcount);
+               dh->dh_dvma = bp->b_data;
+#else
+               dh->dh_dvma = (u_char*)vsdma_mapin(bp);
+#endif
+               xdebug(("addr %x, maplen %d, dvma %x, bcount %d, dir %s\n", 
+                      dh->dh_addr, dh->dh_maplen, dh->dh_dvma, bp->b_bcount,
+                      (dh->dh_flags & SIDH_OUT ? "OUT" : "IN")));
+       }
+#endif
+       /* success */
+       sr->sr_dma_hand = dh;
+
+       return;
+}
+
+
+void
+si_dma_free(ncr_sc)
+       struct ncr5380_softc *ncr_sc;
+{
+       struct si_softc *sc = (struct si_softc *)ncr_sc;
+       struct sci_req *sr = ncr_sc->sc_current;
+       struct scsi_xfer *xs = sr->sr_xs;
+       struct buf *bp = sr->sr_xs->bp;
+       struct si_dma_handle *dh = sr->sr_dma_hand;
+
+       trace (("si_dma_free()\n"));
+
+#ifdef DIAGNOSTIC
+       if (dh == NULL)
+               panic("si_dma_free: no DMA handle");
+#endif
+
+       if (ncr_sc->sc_state & NCR_DOINGDMA)
+               panic("si_dma_free: free while in progress");
+
+       if (dh->dh_flags & SIDH_BUSY) {
+#if 0
+               debug(("bp->b_flags=0x%x\n", bp->b_flags));
+               if (bp->b_flags & B_PHYS) {
+#ifdef USE_VMAPBUF
+                       printf("not unmapping(%x/%x %x/%x %d/%d)...\n", 
+                              dh->dh_addr, dh->dh_dvma,
+                              bp->b_saveaddr, bp->b_data,
+                              bp->b_bcount, dh->dh_maplen);
+                       /* vunmapbuf(bp, dh->dh_maplen); */
+                       printf("done.\n");
+#endif
+                       dh->dh_dvma = 0;
+               }
+#endif
+               dh->dh_flags = 0;
+       }
+       sr->sr_dma_hand = NULL;
+}
+
+
+/*
+ * REGBUSY and DMABUSY won't collide since the higher-level driver
+ * issues intr_on/intr_off before/after doing DMA. The only problem
+ * is to handle RDBUF/WRBUF wrt REGBUSY/DMABUSY
+ *
+ * There might be race-conditions, but for now we don't care for them...
+ */
+int 
+si_dmaLockBus(ncr_sc, lt)
+       struct ncr5380_softc *ncr_sc;
+       int lt;                 /* Lock-Type */
+{
+       struct si_softc *sc = (void*)ncr_sc;
+       int timeout = 200;      /* wait .2 seconds max. */
+
+       trace(("si_dmaLockBus(%x), cold: %d, current: %x\n", 
+              lt, cold, sc->sc_dflags));
+
+#ifdef POLL_MODE
+       if (cold)
+               return (0);
+#endif
+
+       if ((ncr_sc->sc_current != NULL) && (lt == VSDMA_REGBUSY)) {
+               printf("trying to use regs while sc_current is set.\n");
+               printf("lt=%x, fl=%x, cur=%x\n", 
+                      lt, sc->sc_dflags, ncr_sc->sc_current);
+       }
+       if ((ncr_sc->sc_current == NULL) && (lt != VSDMA_REGBUSY)) {
+               printf("trying to use/prepare DMA without current.\n");
+               printf("lt=%x, fl=%x, cur=%x\n", 
+                      lt, sc->sc_dflags, ncr_sc->sc_current);
+       }
+
+       if ((sc->sc_dflags & VSDMA_LOCKED) == 0) {
+               struct si_softc *sc = (struct si_softc *)ncr_sc;
+               sc->sc_dflags |= VSDMA_WANTED;
+               vsbus_lockDMA(sc->sc_cfargs);
+               sc->sc_dflags = VSDMA_LOCKED | lt;
+               return (0);
+       }
+
+#if 1
+       while ((sc->sc_dflags & VSDMA_LCKTYPE) != lt) {
+               debug(("busy wait(1)...\n"));
+               if (--timeout == 0) {
+                       printf("timeout in busy-wait(%x %x)\n",
+                              lt, sc->sc_dflags);
+                       sc->sc_dflags &= ~VSDMA_LCKTYPE;
+                       break;
+               }
+               delay(1000);
+       }
+       debug(("busy wait(1) done.\n"));
+       sc->sc_dflags |= lt;
+
+#else
+       if ((sc->sc_dflags & VSDMA_LCKTYPE) != lt) {
+               switch (lt) {
+
+               case VSDMA_RDBUF:
+                       /* sc->sc_dflags |= VSDMA_IWANTED; */
+                       debug(("busy wait(1)...\n"));
+                       while (sc->sc_dflags & 
+                              (VSDMA_WRBUF | VSDMA_DMABUSY)) {
+                               if (--timeout == 0) {
+                                       printf("timeout in busy-wait(1)\n");
+                                       sc->sc_dflags &= ~VSDMA_WRBUF;
+                                       sc->sc_dflags &= ~VSDMA_DMABUSY;
+                               }
+                               delay(1000);
+                       }
+                       /* sc->sc_dflags &= ~VSDMA_IWANTED; */
+                       debug(("busy wait(1) done.\n"));
+                       sc->sc_dflags |= lt;
+                       break;
+
+               case VSDMA_WRBUF:
+                       /* sc->sc_dflags |= VSDMA_IWANTED; */
+                       debug(("busy wait(2)...\n"));
+                       while (sc->sc_dflags & 
+                              (VSDMA_RDBUF | VSDMA_DMABUSY)) {
+                               if (--timeout == 0) {
+                                       printf("timeout in busy-wait(2)\n");
+                                       sc->sc_dflags &= ~VSDMA_RDBUF;
+                                       sc->sc_dflags &= ~VSDMA_DMABUSY;
+                               }
+                               delay(1000);
+                       }
+                       /* sc->sc_dflags &= ~VSDMA_IWANTED; */
+                       debug(("busy wait(2) done.\n"));
+                       sc->sc_dflags |= lt;
+                       break;
+
+               case VSDMA_DMABUSY:
+                       /* sc->sc_dflags |= VSDMA_IWANTED; */
+                       debug(("busy wait(3)...\n"));
+                       while (sc->sc_dflags & 
+                              (VSDMA_RDBUF | VSDMA_WRBUF)) {
+                               if (--timeout == 0) {
+                                       printf("timeout in busy-wait(3)\n");
+                                       sc->sc_dflags &= ~VSDMA_RDBUF;
+                                       sc->sc_dflags &= ~VSDMA_WRBUF;
+                               }
+                               delay(1000);
+                       }
+                       /* sc->sc_dflags &= ~VSDMA_IWANTED; */
+                       debug(("busy wait(3) done.\n"));
+                       sc->sc_dflags |= lt;
+                       break;
+
+               case VSDMA_REGBUSY:
+                       /* sc->sc_dflags |= VSDMA_IWANTED; */
+                       debug(("busy wait(4)...\n"));
+                       while (sc->sc_dflags & 
+                              (VSDMA_RDBUF | VSDMA_WRBUF | VSDMA_DMABUSY)) {
+                               if (--timeout == 0) {
+                                       printf("timeout in busy-wait(4)\n");
+                                       sc->sc_dflags &= ~VSDMA_RDBUF;
+                                       sc->sc_dflags &= ~VSDMA_WRBUF;
+                                       sc->sc_dflags &= ~VSDMA_DMABUSY;
+                               }
+                               delay(1000);
+                       }
+                       /* sc->sc_dflags &= ~VSDMA_IWANTED; */
+                       debug(("busy wait(4) done.\n"));
+                       sc->sc_dflags |= lt;
+                       break;
+
+               default:
+                       printf("illegal lockType %x in si_dmaLockBus()\n");
+               }
+       }
+       else
+               printf("already locked. (%x/%x)\n", lt, sc->sc_dflags);
+#endif
+       if (sc->sc_dflags & lt) /* successfully locked for this type */
+               return (0);
+
+       printf("spurious %x in si_dmaLockBus(%x)\n", lt, sc->sc_dflags);
+}
+
+/*
+ * the lock of this type is no longer needed. If all (internal) locks are
+ * released, release the DMA bus.
+ */
+int 
+si_dmaReleaseBus(ncr_sc, lt)
+       struct ncr5380_softc *ncr_sc;
+       int lt;                 /* Lock-Type */
+{
+       struct si_softc *sc = (void*)ncr_sc;
+
+       trace(("si_dmaReleaseBus(%x), cold: %d, current: %x\n", 
+              lt, cold, sc->sc_dflags));
+
+#ifdef POLL_MODE
+       if (cold)
+               return (0);
+#endif
+
+       if ((sc->sc_dflags & VSDMA_LCKTYPE) == lt) {
+               sc->sc_dflags &= ~lt;
+       }
+       else
+               printf("trying to release %x while flags = %x\n", lt,
+                      sc->sc_dflags);
+
+       if (sc->sc_dflags == VSDMA_LOCKED) {    /* no longer needed */
+               struct si_softc *sc = (struct si_softc *)ncr_sc;
+               vsbus_unlockDMA(sc->sc_cfargs);
+               sc->sc_dflags = 0;
+               return (0);
+       }
+}
+
+/*
+ * Just toggle the type of lock without releasing the lock...
+ * This is usually needed before/after bcopy() to/from DMA-buffer
+ */
+int 
+si_dmaToggleLock(ncr_sc, lt1, lt2)
+       struct ncr5380_softc *ncr_sc;
+       int lt1, lt2;           /* Lock-Type */
+{
+       struct si_softc *sc = (void*)ncr_sc;
+
+#ifdef POLL_MODE
+       if (cold)
+               return (0);
+#endif
+
+       if (((sc->sc_dflags & lt1) != 0) &&
+           ((sc->sc_dflags & lt2) == 0)) {
+               sc->sc_dflags |= lt2;
+               sc->sc_dflags &= ~lt1;
+               return (0);
+       }
+       printf("cannot toggle locking from %x to %x (current = %x)\n",
+              lt1, lt2, sc->sc_dflags);
+}
+
+/*
+ * This is called when the bus is going idle,
+ * so we want to enable the SBC interrupts.
+ * That is controlled by the DMA enable!
+ * Who would have guessed!
+ * What a NASTY trick!
+ */
+void
+si_intr_on(ncr_sc)
+       struct ncr5380_softc *ncr_sc;
+{
+       si_dmaReleaseBus(ncr_sc, VSDMA_REGBUSY);
+}
+
+/*
+ * This is called when the bus is idle and we are
+ * about to start playing with the SBC chip.
+ *
+ * VS2000 note: we have four kinds of access which are mutually exclusive: 
+ * - access to the NCR5380 registers
+ * - access to the HDC9224 registers
+ * - access to the DMA area 
+ * - doing DMA
+ */
+void
+si_intr_off(ncr_sc)
+       struct ncr5380_softc *ncr_sc;
+{
+       si_dmaLockBus(ncr_sc, VSDMA_REGBUSY);
+}
+
+/*****************************************************************
+ * VME functions for DMA
+ ****************************************************************/
+
+
+/*
+ * This function is called during the COMMAND or MSG_IN phase
+ * that preceeds a DATA_IN or DATA_OUT phase, in case we need
+ * to setup the DMA engine before the bus enters a DATA phase.
+ *
+ * XXX: The VME adapter appears to suppress SBC interrupts
+ * when the FIFO is not empty or the FIFO count is non-zero!
+ *
+ * On the VME version we just clear the DMA count and address
+ * here (to make sure it stays idle) and do the real setup
+ * later, in dma_start.
+ */
+void
+si_dma_setup(ncr_sc)
+       struct ncr5380_softc *ncr_sc;
+{
+       trace (("si_dma_setup(ncr_sc) !!!\n"));
+
+       /*
+        * VS2000: nothing to do ...
+        */
+}
+
+
+void
+si_dma_start(ncr_sc)
+       struct ncr5380_softc *ncr_sc;
+{
+       struct si_softc *sc = (struct si_softc *)ncr_sc;
+       struct sci_req *sr = ncr_sc->sc_current;
+       struct si_dma_handle *dh = sr->sr_dma_hand;
+       volatile struct si_regs *si = sc->sc_regs;
+       long data_pa;
+       int xlen;
+
+       trace(("si_dma_start(%x)\n", sr->sr_dma_hand));
+
+       /*
+        * we always transfer from/to base of DMA-area,
+        * thus the DMA-address is always the same, only size
+        * and direction matter/differ on VS2000
+        */
+
+       debug(("ncr_sc->sc_datalen = %d\n", ncr_sc->sc_datalen));
+       xlen = ncr_sc->sc_datalen;
+       dh->dh_xlen = xlen;
+
+       /*
+        * VS2000 has a fixed 16KB-area where DMA is restricted to. 
+        * All DMA-addresses are relative to this base: KA410_DMA_BASE
+        * Thus we need to copy the data into this area when writing,
+        * or copy from this area when reading. (kind of bounce-buffer)
+        */
+
+       /* Set direction (send/recv) */
+       if (dh->dh_flags & SIDH_OUT) {
+               /*
+                * We know that we are called while intr_off (regs locked)
+                * thus we toggle the lock from REGBUSY to WRBUF
+                * also we set the BLOCKIT flag, so that the locking of
+                * the DMA bus won't be released to the HDC9224...
+                */
+               debug(("preparing msg-out (bcopy)\n"));
+               si_dmaToggleLock(ncr_sc, VSDMA_REGBUSY, VSDMA_WRBUF);
+               bcopy(dh->dh_dvma, sc->sc_dbase, xlen);
+               si_dmaToggleLock(ncr_sc, VSDMA_WRBUF, VSDMA_REGBUSY);
+               *sc->sc_ddreg = DMA_DIR_OUT;
+       } 
+       else {
+               debug(("preparing data-in (bzero)\n"));
+               /* bzero(sc->sc_dbase, xlen); */
+               *sc->sc_ddreg = DMA_DIR_IN;
+       }
+       sc->sc_dflags |= VSDMA_BLOCKED;
+
+       *sc->sc_dareg = DMA_ADDR_HBYTE; /* high byte (6 bits) */
+       *sc->sc_dareg = DMA_ADDR_LBYTE; /* low byte */
+       *sc->sc_dcreg = 0 - xlen; /* bertram XXX */
+
+#ifdef DEBUG
+       if (si_debug & 2) {
+               printf("si_dma_start: dh=0x%x, pa=0x%x, xlen=%d, creg=0x%x\n",
+                          dh, data_pa, xlen, *sc->sc_dcreg);
+       }
+#endif
+
+#ifdef POLL_MODE
+       debug(("dma_start: cold=%d\n", cold));
+       if (cold) {
+               *sc->intmsk &= ~sc->intbit;
+               *sc->intclr = sc->intbit;
+       }
+       else
+               *sc->intmsk |= sc->intbit;
+#endif
+       /*
+        * Acknowledge the phase change.  (After DMA setup!)
+        * Put the SBIC into DMA mode, and start the transfer.
+        */
+       si_dmaToggleLock(ncr_sc, VSDMA_REGBUSY, VSDMA_DMABUSY);
+       if (dh->dh_flags & SIDH_OUT) {
+               *ncr_sc->sci_tcmd = PHASE_DATA_OUT;
+               SCI_CLR_INTR(ncr_sc);
+               *ncr_sc->sci_icmd = SCI_ICMD_DATA;
+               *ncr_sc->sci_mode |= (SCI_MODE_DMA | SCI_MODE_DMA_IE);
+               *ncr_sc->sci_dma_send = 0;      /* start it */
+       } else {
+               *ncr_sc->sci_tcmd = PHASE_DATA_IN;
+               SCI_CLR_INTR(ncr_sc);
+               *ncr_sc->sci_icmd = 0;
+               *ncr_sc->sci_mode |= (SCI_MODE_DMA | SCI_MODE_DMA_IE);
+               *ncr_sc->sci_irecv = 0; /* start it */
+       }
+       ncr_sc->sc_state |= NCR_DOINGDMA;
+       /*
+        * having a delay (eg. printf) here, seems to solve the problem.
+        * Isn't that strange ????
+        * Maybe the higher-level driver accesses one of the registers of
+        * the controller while DMA is in progress. Having a long enough
+        * delay here might prevent/delay this access until DMA bus is
+        * free again...
+        *
+        * The instruction ++++ printf("DMA started.\n"); ++++ 
+        * is long/slow enough, to make the SSCI driver work. Thus we
+        * try to find a delay() long/slow enough to do the same. The
+        * argument to this delay is relative to the transfer-count.
+        */
+       delay(3*xlen/4);                /* XXX solve this problem!!! XXX */
+
+#ifdef DEBUG
+       if (si_debug & 2) {
+               printf("si_dma_start: started, flags=0x%x\n",
+                          ncr_sc->sc_state);
+       }
+#endif
+}
+
+
+void
+si_vme_dma_eop(ncr_sc)
+       struct ncr5380_softc *ncr_sc;
+{
+       trace (("si_vme_dma_eop() !!!\n"));
+       /* Not needed - DMA was stopped prior to examining sci_csr */
+}
+
+/*
+ * si_dma_stop() has now become almost a nop-routine, since DMA-buffer
+ * has already been read within si_intr(), so there's nothing left to do.
+ */
+void
+si_dma_stop(ncr_sc)
+       struct ncr5380_softc *ncr_sc;
+{
+       struct si_softc *sc = (struct si_softc *)ncr_sc;
+       struct sci_req *sr = ncr_sc->sc_current;
+       struct si_dma_handle *dh = sr->sr_dma_hand;
+       volatile struct si_regs *si = sc->sc_regs;
+       int resid, ntrans;
+
+       if ((ncr_sc->sc_state & NCR_DOINGDMA) == 0) {
+#ifdef DEBUG
+               printf("si_dma_stop: dma not running\n");
+#endif
+               return;
+       }
+       ncr_sc->sc_state &= ~NCR_DOINGDMA;
+
+       /* Note that timeout may have set the error flag. */
+       if (ncr_sc->sc_state & NCR_ABORTING) {
+               printf("si_dma_stop: timeout?\n");
+               goto out;
+       }
+
+       /*
+        * Now try to figure out how much actually transferred
+        */
+       si_dmaLockBus(ncr_sc, VSDMA_DMABUSY);
+       si_dmaToggleLock(ncr_sc, VSDMA_DMABUSY, VSDMA_REGBUSY);
+       resid = *sc->sc_dcreg;
+       /* 
+        * XXX: don't correct at two places !!! 
+        */
+       if (resid == 1 && sc->sc_xflags) {      
+               resid = 0;
+       }
+       ntrans = dh->dh_xlen + resid;
+       if (resid != 0) 
+               printf("resid=%d, xlen=%d, ntrans=%d\n", 
+                      resid, dh->dh_xlen, ntrans);
+
+#ifdef DEBUG
+       if (si_debug & 2) {
+               printf("si_dma_stop: resid=0x%x ntrans=0x%x\n",
+                      resid, ntrans);
+       }
+#endif
+
+       if (ntrans < MIN_DMA_LEN) {
+               printf("si: fifo count: 0x%x\n", resid);
+               ncr_sc->sc_state |= NCR_ABORTING;
+               goto out;
+       }
+       if (ntrans > ncr_sc->sc_datalen)
+               panic("si_dma_stop: excess transfer");
+
+       /*
+        * On VS2000 in case of a READ-operation, we must now copy 
+        * the buffer-contents to the destination-address!
+        */
+       if ((dh->dh_flags & SIDH_OUT) == 0 &&
+           (dh->dh_flags & SIDH_DONE) == 0) {
+               printf("DMA buffer not yet copied.\n");
+               si_dmaToggleLock(ncr_sc, VSDMA_REGBUSY, VSDMA_RDBUF);
+               bcopy(sc->sc_dbase, dh->dh_dvma, ntrans);
+               si_dmaToggleLock(ncr_sc, VSDMA_RDBUF, VSDMA_REGBUSY);
+       }
+       si_dmaReleaseBus(ncr_sc, VSDMA_REGBUSY);
+
+       /* Adjust data pointer */
+       ncr_sc->sc_dataptr += ntrans;
+       ncr_sc->sc_datalen -= ntrans;
+
+out:
+       si_dmaLockBus(ncr_sc, VSDMA_DMABUSY);
+
+       /* Put SBIC back in PIO mode. */
+       *ncr_sc->sci_mode &= ~(SCI_MODE_DMA | SCI_MODE_DMA_IE);
+       *ncr_sc->sci_icmd = 0;
+
+       si_dmaReleaseBus(ncr_sc, VSDMA_DMABUSY);
+}
+
+/*
+ * Poll (spin-wait) for DMA completion.
+ * Called right after xx_dma_start(), and
+ * xx_dma_stop() will be called next.
+ */
+void
+si_dma_poll(ncr_sc)
+       struct ncr5380_softc *ncr_sc;
+{
+       struct si_softc *sc = (struct si_softc *)ncr_sc;
+       struct sci_req *sr = ncr_sc->sc_current;
+       struct si_dma_handle *dh = sr->sr_dma_hand;
+       int i, timeout;
+
+       if (! cold) 
+               printf("spurious call of DMA-poll ???");
+
+#ifdef POLL_MODE
+
+       delay(10000);
+       trace(("si_dma_poll(%x)\n", *sc->sc_dcreg));
+
+       /*
+        * interrupt-request has been cleared by dma_start, thus
+        * we do nothing else but wait for the intreq to reappear...
+        */
+
+       timeout = 5000;
+       for (i=0; i<timeout; i++) {
+               if (*sc->intreq & sc->intbit)
+                       break;
+               delay(100);
+       }
+       if ((*sc->intreq & sc->intbit) == 0) {
+               printf("si: DMA timeout (while polling)\n");
+               /* Indicate timeout as MI code would. */
+               sr->sr_flags |= SR_OVERDUE;
+       }
+#endif
+       return;
+}
diff --git a/sys/arch/vax/vsa/ncr.h b/sys/arch/vax/vsa/ncr.h
new file mode 100644 (file)
index 0000000..c30cf1e
--- /dev/null
@@ -0,0 +1,75 @@
+/*     $NetBSD: ncr.h,v 1.1 1996/07/20 18:55:15 ragge Exp $    */
+
+/*
+ * Register map for the Sun3 SCSI Interface (si)
+ * The first part of this register map is an NCR5380
+ * SCSI Bus Interface Controller (SBIC).  The rest is a
+ * DMA controller and custom logic in one of two flavors,
+ * one for the OBIO interface (3/50,3/60) and one for the
+ * VME interface (3/160,3/260,etc.), where some registers
+ * are implemented only on one or the other, some on both.
+ */
+
+/*
+ * Some of these registers apply to only one interface and some
+ * apply to both. The registers which apply to the Sun3/50 onboard 
+ * version only are udc_rdata and udc_raddr. The registers which
+ * apply to the Sun3 vme version only are dma_addr, dma_count, bpr,
+ * iv_am, and bcrh. Thus, the sbc registers, fifo_data, bcr, and csr 
+ * apply to both interfaces.
+ * One other feature of the vme interface: a write to the dma count 
+ * register also causes a write to the fifo byte count register and
+ * vis versa.
+ */
+
+/*
+ * NCR5380 Register map (byte-registers at longword addresses)
+ */
+struct ncr5380regs {
+       volatile u_long sci_r0;         /* 200C.0080: CUR_DATA/OUT_DATA (rw) */
+       volatile u_long sci_r1;         /* 200C.0084: INI_CMD           (rw) */
+       volatile u_long sci_r2;         /* 200C.0088: MODE              (rw) */
+       volatile u_long sci_r3;         /* 200C.008C: TAR_CMD           (rw) */
+       volatile u_long sci_r4;         /* 200C.0090: CUR_STAT/SEL_ENA  (rw) */
+       volatile u_long sci_r5;         /* 200C.0094: STATUS/DMA_SEND   (rw) */
+       volatile u_long sci_r6;         /* 200C.0098: IN_DATA/DMA_TRCV  (rw) */
+       volatile u_long sci_r7;         /* 200C.009C: RESET/DMA_IRCV    (rw) */
+};
+
+struct si_regs {
+       struct ncr5380regs sci;
+};
+
+/* possible values for the address modifier, sun3 vme version only */
+#define VME_SUPV_DATA_24       0x3d00
+
+/*
+ * Status Register.
+ * Note:
+ *     (r)     indicates bit is read only.
+ *     (rw)    indicates bit is read or write.
+ *     (v)     vme host adaptor interface only.
+ *     (o)     sun3/50 onboard host adaptor interface only.
+ *     (b)     both vme and sun3/50 host adaptor interfaces.
+ */
+#define SI_CSR_DMA_ACTIVE      0x8000  /* (r,o) dma transfer active */
+#define SI_CSR_DMA_CONFLICT    0x4000  /* (r,b) reg accessed while dmaing */
+#define SI_CSR_DMA_BUS_ERR     0x2000  /* (r,b) bus error during dma */
+#define SI_CSR_ID              0x1000  /* (r,b) 0 for 3/50, 1 for SCSI-3, */
+                                       /* 0 if SCSI-3 unmodified */
+#define SI_CSR_FIFO_FULL       0x0800  /* (r,b) fifo full */
+#define SI_CSR_FIFO_EMPTY      0x0400  /* (r,b) fifo empty */
+#define SI_CSR_SBC_IP          0x0200  /* (r,b) sbc interrupt pending */
+#define SI_CSR_DMA_IP          0x0100  /* (r,b) dma interrupt pending */
+#define SI_CSR_LOB             0x00c0  /* (r,v) number of leftover bytes */
+#define SI_CSR_LOB_THREE       0x00c0  /* (r,v) three leftover bytes */
+#define SI_CSR_LOB_TWO         0x0080  /* (r,v) two leftover bytes */
+#define SI_CSR_LOB_ONE         0x0040  /* (r,v) one leftover byte */
+#define SI_CSR_BPCON           0x0020  /* (rw,v) byte packing control */
+                                       /* dma is in 0=longwords, 1=words */
+#define SI_CSR_DMA_EN          0x0010  /* (rw,v) dma/interrupt enable */
+#define SI_CSR_SEND            0x0008  /* (rw,b) dma dir, 1=to device */
+#define SI_CSR_INTR_EN         0x0004  /* (rw,b) interrupts enable */
+#define SI_CSR_FIFO_RES                0x0002  /* (rw,b) inits fifo, 0=reset */
+#define SI_CSR_SCSI_RES                0x0001  /* (rw,b) reset sbc and udc, 0=reset */
+
diff --git a/sys/arch/vax/vsa/vsbus.c b/sys/arch/vax/vsa/vsbus.c
new file mode 100644 (file)
index 0000000..3973f56
--- /dev/null
@@ -0,0 +1,652 @@
+/*     $NetBSD: vsbus.c,v 1.4 1996/10/13 03:36:17 christos Exp $ */
+/*
+ * Copyright (c) 1996 Ludd, University of Lule}, Sweden.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Ludd by Bertram Barth.
+ *
+ * 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 at Ludd, University of 
+ *     Lule}, Sweden and its contributors.
+ * 4. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#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/scb.h>
+#include <machine/cpu.h>
+#include <machine/trap.h>
+#include <machine/nexus.h>
+
+#include <machine/uvax.h>
+#include <machine/ka410.h>
+#include <machine/ka43.h>
+
+#include <machine/vsbus.h>
+
+#define trace(x)
+#define debug(x)
+
+int    vsbus_match     __P((struct device *, void *, void *));
+void   vsbus_attach    __P((struct device *, struct device *, void *));
+int    vsbus_print     __P((void *, const char *));
+
+void   ka410_attach    __P((struct device *, struct device *, void *));
+void   ka43_attach     __P((struct device *, struct device *, void *));
+
+struct cfdriver vsbus_cd = { 
+       NULL, "vsbus", DV_DULL 
+};
+struct cfattach vsbus_ca = { 
+       sizeof(struct device), vsbus_match, vsbus_attach
+};
+
+/*
+void   vsbus_intr_register __P((struct confargs *ca, int (*)(void*), void*));
+void   vsbus_intr_unregister __P((struct confargs *));
+*/
+
+void   vsbus_intr_dispatch __P((int i));
+
+#define VSBUS_MAXDEVS  8
+#define VSBUS_MAXINTR  8
+
+struct confargs *vsbus_devs = NULL;
+
+#ifdef VAX410  /* also: KA420 */
+struct confargs ka410_devs[] = {
+       /* name         intslot intpri intvec   intbit  ioaddr  */
+       { "dc",         7,      7,      0x2C0,  (1<<7), KA410_SER_BASE, 
+                       6,      6,      0x2C4,  (1<<6), 0x01,           },
+       { "dc (xmit)",  6,      6,      0x2C4,  (1<<6), KA410_SER_BASE, },
+       { "le",         5,      5,      0x250,  (1<<5), KA410_LAN_BASE, 
+                       KA410_NWA_BASE, 0x00,                           },
+       { "ncr",        1,      1,      0x3F8,  (1<<1), KA410_SCS_BASE,
+                       KA410_SCS_DADR, KA410_SCS_DCNT, KA410_SCS_DDIR,
+                       KA410_DMA_BASE, KA410_DMA_SIZE, 0x00,   0x07,   },
+       { "hdc",        0,      0,      0x3FC,  (1<<0), KA410_DKC_BASE, 
+                       0, 0, 0, 
+                       KA410_DMA_BASE, KA410_DMA_SIZE, 0x00,           },
+#if 0
+       { "dc (recv)",  7,      7,      0x2C0,  (1<<7), KA410_SER_BASE, },
+       { "dc (xmit)",  6,      6,      0x2C4,  (1<<6), KA410_SER_BASE, },
+       { "hdc9224",    0,      0,      0x3FC,  (1<<0), KA410_DKC_BASE, },
+       { "ncr5380",    1,      1,      0x3F8,  (1<<1), KA410_SCS_BASE, },
+       { "am7990",     5,      5,      0x250,  (1<<5), KA410_LAN_BASE, },
+       { "NETOPT",     4,      4,      0x254,  (1<<4), KA410_LAN_BASE, },
+#endif
+       { "" },
+};
+#endif
+
+#ifdef VAX43
+struct confargs ka43_devs[] = {
+       /* name         intslot intpri intvec   intbit  ioaddr  */
+       { "dc",         7,      7,      0x2C0,  (1<<7), KA43_SER_BASE,  
+                       6,      6,      0x2C4,  (1<<6), 0x01,           },
+       { "dc (xmit)",  6,      6,      0x2C4,  (1<<6), KA43_SER_BASE,  },
+       { "le",         5,      5,      0x250,  (1<<5), KA43_LAN_BASE,  
+                       KA43_NWA_BASE,  0x00,                           },
+       { "ncr",        1,      1,      0x3F8,  (1<<1), KA43_SC1_BASE,
+                       KA43_SC1_DADR,  KA43_SC1_DCNT,  KA43_SC1_DDIR,  
+                       KA43_DMA_BASE,  KA43_DMA_SIZE,  0x01,   0x06,   },
+       { "ncr",        0,      0,      0x3FC,  (1<<0), KA43_SC2_BASE,
+                       KA43_SC2_DADR,  KA43_SC2_DCNT,  KA43_SC2_DDIR,
+                       KA43_DMA_BASE,  KA43_DMA_SIZE,  0x01,   0x06,   },
+#if 0
+       { "le (2nd)",   4,      4,      0x254,  (1<<4), 0x???,          },
+       { "NETOPT",     4,      4,      0x254,  (1<<4), 0x???,          },
+#endif
+       { "" },
+};
+#endif
+
+int
+vsbus_print(aux, name)
+       void *aux;
+       const char *name;
+{
+       struct confargs *ca = aux;
+
+       trace(("vsbus_print(%x, %s)\n", ca->ca_name, name));
+
+       if (name) {
+               printf ("device %s at %s", ca->ca_name, name);
+               return (UNSUPP);
+       }
+       return (UNCONF); 
+}
+
+int
+vsbus_match(parent, cf, aux)
+       struct  device  *parent;
+       void    *cf;
+       void    *aux;
+{
+       struct bp_conf *bp = aux;
+       
+       trace(("vsbus_match: bp->type = \"%s\"\n", bp->type));
+
+       if (strcmp(bp->type, "vsbus"))
+               return 0;
+       /*
+        * on machines which can have it, the vsbus is always there
+        */
+       if ((vax_bustype & VAX_VSBUS) == 0)
+               return (0);
+
+       return (1);
+}
+
+#if 1  /*------------------------------------------------------------*/
+#if 1
+#define REG(name)      short name; short X##name##X;
+#else
+#define REG(name)      int name;
+#endif
+static volatile struct {/* base address of DZ-controller: 0x200A0000 */
+  REG(csr);            /* 00 Csr: control/status register */
+  REG(rbuf);           /* 04 Rbuf/Lpr: receive buffer/line param reg. */
+  REG(tcr);            /* 08 Tcr: transmit console register */
+  REG(tdr);            /* 0C Msr/Tdr: modem status reg/transmit data reg */
+  REG(lpr0);           /* 10 Lpr0: */
+  REG(lpr1);           /* 14 Lpr0: */
+  REG(lpr2);           /* 18 Lpr0: */
+  REG(lpr3);           /* 1C Lpr0: */
+} *dz = (void*)0x200A0000; 
+extern int dzcnrint();
+extern int dzcntint();
+int hardclock_count = 0;
+int
+ka410_consintr_enable()
+{
+       vsbus_intr_enable(&ka410_devs[0]);
+       vsbus_intr_enable(&ka410_devs[1]);
+}
+
+int
+ka410_consRecv_intr(p)
+       void *p;
+{
+  /* printf("ka410_consRecv_intr: hc-count=%d\n", hardclock_count); */
+  dzcnrint();
+  /* printf("gencnrint() returned.\n"); */
+  return(0);
+}
+
+int
+ka410_consXmit_intr(p)
+       void *p;
+{
+  /* printf("ka410_consXmit_intr: hc-count=%d\n", hardclock_count); */
+  dzcntint();
+  /* printf("gencntint() returned.\n"); */
+  return(0);
+}
+#endif /*------------------------------------------------------------*/
+
+void
+vsbus_attach(parent, self, aux)
+       struct  device  *parent, *self;
+       void    *aux;
+{
+       struct confargs *ca;
+       int i;
+
+       printf("\n");
+       trace (("vsbus_attach()\n"));
+
+       printf("vsbus_attach: boardtype = %x\n", vax_boardtype);
+
+       switch (vax_boardtype) {
+       case VAX_BTYP_410:
+       case VAX_BTYP_420:
+               vsbus_devs = ka410_devs;
+               break;
+
+       case VAX_BTYP_43:
+       case VAX_BTYP_46:
+       case VAX_BTYP_49:
+               vsbus_devs = ka43_devs;
+               break;
+
+       default:
+               printf ("unsupported boardtype 0x%x in vsbus_attach()\n",
+                       vax_boardtype);
+               return;
+       }
+
+       /*
+        * first setup interrupt-table, so that devices can register
+        * their interrupt-routines...
+        */
+       vsbus_intr_setup();     
+
+       /*
+        * now check for all possible devices on this "bus"
+        */
+       for (i=0; i<VSBUS_MAXDEVS; i++) {
+               ca = &vsbus_devs[i];
+               if (*ca->ca_name == '\0')
+                       break;
+               config_found(self, (void*)ca, vsbus_print);
+       }
+
+       /*
+        * as long as there's no working DZ-driver, we use this dummy
+        */
+       vsbus_intr_register(&ka410_devs[0], ka410_consRecv_intr, NULL);
+       vsbus_intr_register(&ka410_devs[1], ka410_consXmit_intr, NULL);
+}
+
+#define VSBUS_MAX_INTR 8       /* 64? */
+/*
+ * interrupt service routines are given an int as argument, which is
+ * pushed onto stack as LITERAL. Thus the value is between 0-63.
+ * This array of 64 might be oversized for now, but it's all which 
+ * ever will be possible.
+ */
+struct vsbus_ivec {
+       struct ivec_dsp intr_vec;               /* this is referenced in SCB */
+       int             intr_count;             /* keep track of interrupts */
+       int             intr_flags;             /* valid, etc. */
+       void            (*enab)(int);           /* enable interrupt */
+       void            (*disab)(int);          /* disable interrupt */
+       void            (*prep)(int);           /* need pre-processing? */
+       int             (*handler)(void*);      /* isr-routine to call */
+       void            *hndlarg;               /* args to this routine */
+       void            (*postp)(int);          /* need post-processing? */
+} vsbus_ivtab[VSBUS_MAX_INTR];
+
+/*
+ * 
+ */
+int
+vsbus_intr_setup()
+{
+       int i;
+       struct vsbus_ivec *ip;
+       extern struct ivec_dsp idsptch;         /* subr.s */
+
+       for (i=0; i<VSBUS_MAX_INTR; i++) {
+               ip = &vsbus_ivtab[i];
+               bcopy(&idsptch, &ip->intr_vec, sizeof(struct ivec_dsp));
+               ip->intr_vec.pushlarg = i;
+               ip->intr_vec.hoppaddr = vsbus_intr_dispatch;
+               ip->intr_count = 0;
+               ip->intr_flags = 0;
+               ip->enab = NULL;
+               ip->disab = NULL;
+               ip->postp = NULL;
+       }
+       switch (vax_boardtype) {
+       case VAX_BTYP_410:
+       case VAX_BTYP_420:
+       case VAX_BTYP_43:
+       case VAX_BTYP_46:
+       case VAX_BTYP_49:
+               ka410_intr_setup();
+               return(0);
+       default:
+               printf("unsupported board-type 0x%x in vsbus_intr_setup()\n",
+                       vax_boardtype);
+               return(1);
+       }
+}
+
+int
+vsbus_intr_register(ca, handler, arg)
+       struct confargs *ca;
+       int (*handler)(void*);
+       void *arg;
+{
+       /* struct device *dev = arg; */
+       int i = ca->ca_intslot;
+       struct vsbus_ivec *ip = &vsbus_ivtab[i];
+
+       trace (("vsbus_intr_register(%s/%d)\n", ca->ca_name, ca->ca_intslot));
+
+       ip->handler = handler;
+       ip->hndlarg = arg;
+}
+
+int
+vsbus_intr_enable(ca)
+       struct confargs *ca;
+{
+       int i = ca->ca_intslot;
+       struct vsbus_ivec *ip = &vsbus_ivtab[i];
+
+       trace (("vsbus_intr_enable(%s/%d)\n", ca->ca_name, ca->ca_intslot));
+
+       /* XXX check for valid handler etc. !!! */
+       if (ip->handler == NULL) {
+               printf("interrupts for \"%s\"(%d) not enabled: null-handler\n",
+                     ca->ca_name, ca->ca_intslot);
+               return;
+       }
+
+       ip->enab(i);
+}
+
+int
+vsbus_intr_disable(ca)
+       struct confargs *ca;
+{
+       int i = ca->ca_intslot;
+       struct vsbus_ivec *ip = &vsbus_ivtab[i];
+
+       trace (("vsbus_intr_disable(%s/%d)\n", ca->ca_name, i));
+
+       ip->disab(i);
+}
+
+int 
+vsbus_intr_unregister(ca)
+       struct confargs *ca;
+{
+       int i = ca->ca_intslot;
+       struct vsbus_ivec *ip = &vsbus_ivtab[i];
+
+       trace (("vsbus_intr_unregister(%s/%d)\n", ca->ca_name, i));
+
+       ip->handler = NULL;
+       ip->hndlarg = NULL;
+}
+
+void
+vsbus_intr_dispatch(i)
+       register int i;
+{
+       register struct vsbus_ivec *ip = &vsbus_ivtab[i];
+
+       trace (("vsbus_intr_dispatch(%d)", i));
+       
+       if (i < VSBUS_MAX_INTR && ip->handler != NULL) {
+               ip->intr_count++;
+               debug (("intr-count[%d] = %d\n", i, ip->intr_count));
+               (ip->handler)(ip->hndlarg);
+               if (ip->postp)
+                       (ip->postp)(i);
+               return;
+       }
+
+       if (i < 0 || i >= VSBUS_MAX_INTR) {
+               printf ("stray interrupt %d on vsbus.\n", i);
+               return;
+       }
+
+       if (!ip->handler) {
+               printf ("unhandled interrupt %d on vsbus.\n", i);
+               return;
+       }
+}
+
+/*
+ * These addresses are invalid and will be updated/corrected by
+ * ka410_intr_setup(), but having them this way helps debugging
+ */
+static volatile u_char *ka410_intmsk = (void*)KA410_INTMSK;
+static volatile u_char *ka410_intreq = (void*)KA410_INTREQ;
+static volatile u_char *ka410_intclr = (void*)KA410_INTCLR;
+
+static void
+ka410_intr_enable(i)
+       int i;
+{
+       trace (("ka410_intr_enable(%d)\n", i));
+       *ka410_intmsk |= (1<<i);
+}
+
+static void
+ka410_intr_disable(i)
+       int i;
+{
+       trace (("ka410_intr_disable(%d)\n", i));
+       *ka410_intmsk &= ~(1<<i);
+}
+
+static void
+ka410_intr_clear(i)
+       int i;
+{
+       trace (("ka410_intr_clear(%d)\n", i));
+       *ka410_intclr = (1<<i);
+}
+
+ka410_intr_setup()
+{
+       int i;
+       struct vsbus_ivec *ip;
+       void **scbP = (void*)scb;
+
+       trace (("ka410_intr_setup()\n"));
+
+       ka410_intmsk = (void*)uvax_phys2virt(KA410_INTMSK);
+       ka410_intreq = (void*)uvax_phys2virt(KA410_INTREQ);
+       ka410_intclr = (void*)uvax_phys2virt(KA410_INTCLR);
+
+       *ka410_intmsk = 0;              /* disable all interrupts */
+       *ka410_intclr = 0xFF;           /* clear all old interrupts */
+
+       /*
+        * insert the VS2000-specific routines into ivec-table...
+        */
+       for (i=0; i<8; i++) {
+               ip = &vsbus_ivtab[i];
+               ip->enab  = ka410_intr_enable;
+               ip->disab = ka410_intr_disable;
+               /* ip->postp = ka410_intr_clear; bertram XXX */
+       }
+       /*
+        * ...and register the interrupt-vectors in SCB
+        */
+       scbP[IVEC_DC/4] = &vsbus_ivtab[0].intr_vec;
+       scbP[IVEC_SC/4] = &vsbus_ivtab[1].intr_vec;
+       scbP[IVEC_VS/4] = &vsbus_ivtab[2].intr_vec;
+       scbP[IVEC_VF/4] = &vsbus_ivtab[3].intr_vec;
+       scbP[IVEC_NS/4] = &vsbus_ivtab[4].intr_vec;
+       scbP[IVEC_NP/4] = &vsbus_ivtab[5].intr_vec;
+       scbP[IVEC_ST/4] = &vsbus_ivtab[6].intr_vec;
+       scbP[IVEC_SR/4] = &vsbus_ivtab[7].intr_vec;
+}
+
+/*
+ *
+ *
+ */
+
+static volatile struct dma_lock {
+       int     dl_locked;
+       int     dl_wanted;
+       void    *dl_owner;
+       int     dl_count;
+} dmalock = { 0, 0, NULL, 0 };
+
+int
+vsbus_lockDMA(ca)
+       struct confargs *ca;
+{
+       while (dmalock.dl_locked) {
+               dmalock.dl_wanted++;
+               sleep((caddr_t)&dmalock, PRIBIO);       /* PLOCK or PRIBIO ? */
+               dmalock.dl_wanted--;
+       }
+       dmalock.dl_locked++;
+       dmalock.dl_owner = ca;
+
+       /*
+        * no checks yet, no timeouts, nothing...
+        */
+
+#ifdef DEBUG
+       if ((++dmalock.dl_count % 1000) == 0)
+               printf("%d locks, owner: %s\n", dmalock.dl_count, ca->ca_name);
+#endif
+       return (0);
+}
+
+int 
+vsbus_unlockDMA(ca)
+       struct confargs *ca;
+{
+       if (dmalock.dl_locked != 1 || dmalock.dl_owner != ca) {
+               printf("locking-problem: %d, %s\n", dmalock.dl_locked,
+                      (dmalock.dl_owner ? dmalock.dl_owner : "null"));
+               dmalock.dl_locked = 0;
+               return (-1);
+       }
+       dmalock.dl_owner = NULL;
+       dmalock.dl_locked = 0;
+       if (dmalock.dl_wanted) {
+               wakeup((caddr_t)&dmalock);
+       }
+       return (0);
+}
+
+/*----------------------------------------------------------------------*/
+#if 0
+/*
+ * small set of routines needed for mapping when doing pseudo-DMA,
+ * quasi-DMA or virtual-DMA (choose whatever name you like).
+ *
+ * Once I know how VS3100 is doing real DMA (I hope it does), this
+ * should be rewritten to present a general interface...
+ *
+ */
+
+extern u_long uVAX_physmap;
+
+u_long
+vsdma_mapin(bp, len)
+       struct buf *bp;
+       int len;
+{
+       pt_entry_t *pte;        /* pointer to Page-Table-Entry */
+       struct pcb *pcb;        /* pointer to Process-Controll-Block */
+       pt_entry_t *xpte;
+       caddr_t addr;
+       int pgoff;              /* offset into 1st page */
+       int pgcnt;              /* number of pages needed */
+       int pfnum;
+       int i;
+
+       trace(("mapin(bp=%x, bp->data=%x)\n", bp, bp->b_data));
+
+       addr = bp->b_data;
+       pgoff = (int)bp->b_data & PGOFSET;      /* get starting offset */
+       pgcnt = btoc(bp->b_bcount + pgoff) + 1; /* one more than needed */
+       
+       /*
+        * Get a pointer to the pte pointing out the first virtual address.
+        * Use different ways in kernel and user space.
+        */
+       if ((bp->b_flags & B_PHYS) == 0) {
+               pte = kvtopte(addr);
+       } else {
+               pcb = bp->b_proc->p_vmspace->vm_pmap.pm_pcb;
+               pte = uvtopte(addr, pcb);
+       }
+
+       /*
+        * When we are doing DMA to user space, be sure that all pages
+        * we want to transfer to are mapped. WHY DO WE NEED THIS???
+        * SHOULDN'T THEY ALWAYS BE MAPPED WHEN DOING THIS???
+        */
+       for (i=0; i<(pgcnt-1); i++) {
+               if ((pte + i)->pg_pfn == 0) {
+                       int rv;
+                       rv = vm_fault(&bp->b_proc->p_vmspace->vm_map,
+                                     (unsigned)addr + i * NBPG,
+                                     VM_PROT_READ|VM_PROT_WRITE, FALSE);
+                       if (rv)
+                               panic("vs-DMA to nonexistent page, %d", rv);
+               }
+       }
+
+       /*
+        * now insert new mappings for this memory area into kernel's
+        * mapping-table
+        */
+       xpte = kvtopte(uVAX_physmap);
+       while (--pgcnt > 0) {
+               pfnum = pte->pg_pfn;
+               if (pfnum == 0)
+                       panic("vsbus: zero entry");
+               *(int *)xpte++ = *(int *)pte++;
+       }
+       *(int *)xpte = 0;       /* mark last mapped page as invalid! */
+
+       debug(("uVAX: 0x%x\n", uVAX_physmap + pgoff));
+
+       return (uVAX_physmap + pgoff);  /* ??? */
+}
+#endif
+/*----------------------------------------------------------------------*/
+/*
+ * Here follows some currently(?) unused stuff. Someday this should be removed
+ */
+
+#if 0
+/*
+ * Configure devices on VS2000/KA410 directly attached to vsbus
+ */
+void
+ka410_attach(parent, self, aux)
+       struct device *parent;
+       struct device *self;
+       void *aux;
+{
+       struct confargs *ca;
+       int i;
+
+       for (i=0; i<KA410_MAXDEVS; i++) {
+               ca = &ka410_devs[i];
+               if (*ca->ca_name == '\0')
+                       break;
+               config_found(self, (void*)ca, vsbus_print);
+       }
+       /*
+        * as long as there's no real DZ-driver, we used this dummy
+        */
+       vsbus_intr_register(&ka410_devs[0], ka410_consRecv_intr, NULL);
+       vsbus_intr_register(&ka410_devs[1], ka410_consXmit_intr, NULL);
+}
+
+#endif