--- /dev/null
+/* $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");
+}
--- /dev/null
+/* $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 */
--- /dev/null
+/* $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 */
+};
--- /dev/null
+/* $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);
+}
--- /dev/null
+/* $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 */
-# $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 $@
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
#
-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
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
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>
-/* $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.
#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};
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)
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:
uioaddr = uio630;
tmsaddr = qbdev(0774500);
break;
+
+ case VAX_8200:
+ nbi = 1;
+ biaddr = bi8200;
+ bioaddr = bio8200;
}
}
-/* $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.
#include "sys/reboot.h"
#include "lib/libsa/stand.h"
+#define V750UCODE(x) ((x>>8)&255)
+
#include <a.out.h>
/*
char line[100];
volatile u_int devtype, bootdev;
extern unsigned opendev;
+extern unsigned *bootregs;
-main()
+Xmain()
{
register howto asm("r11");
register bdev asm("r10");
hoppabort((x.a_entry&0x7fffffff),howto, devtype, esym);
return;
shread:
- printf("Short read\n");
+ printf("\nShort read\n\n");
return;
}
if (*cp == ')' || *cp == ':')
break;
if (*cp) {
- strncpy(pcs, line, 99);
+ bcopy(line, pcs, 99);
pcs[99] = 0;
i = cp - line + 1;
} else
-/* $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);
/*
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();
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);
}
}
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);
int i, major, adaptor, controller, unit, partition;
- switch (cpunumber) {
+ switch (vax_cputype) {
case VAX_78032:
case VAX_650:
adaptor = 0;
break;
+ case VAX_8200:
case VAX_750:
controller = 0; /* XXX Actually massbuss can be on 3 ctlr's */
unit = bootregs[3];
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;
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;
/*
* 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;
* 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;
}
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;
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;
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;
-/* $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.
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]));
-/* $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
+");
+
+
-/* $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.
#include "sys/reboot.h"
#include "lib/libsa/stand.h"
+#include "vaxstand.h"
+
#include <a.out.h>
char line[100];
int fill_buffer (void);
int write_disk (void);
-main()
+Xmain()
{
int adapt, ctlr, unit, part;
int res, i, loops;
-/* $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.
{
printf("\
Usage: device(adaptor, controller, drive, partition)file\n\
- <device><unit><partitonletter>:file\n\
+ <device><unit><partitonletter>:file\n\
");
}
{
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);
{
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))
*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;
/* 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 */
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;
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);
-/* $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.
#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;
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;
int bootdev;
void
-main()
+Xmain()
{
register bdev asm("r10");
+++ /dev/null
-/* $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;
-}
--- /dev/null
+/* $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) */
+
--- /dev/null
+/* $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);
+}
-/* $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.
/* 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"
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;
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);
}
{
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)
+ ;
}
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);
--- /dev/null
+/* $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;
+}
+
-/* $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)
*/
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
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
+
--- /dev/null
+/* $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;
--- /dev/null
+/* $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 */
+ }
+}
--- /dev/null
+/* $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
+}
--- /dev/null
+/* $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);
+}
--- /dev/null
+/* $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 */
-/* $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.
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
-/* $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.
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 ...
/*
--- /dev/null
+/* $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
-/* $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.
#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"
};
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;
* 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;
-/* $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) \
(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
+++ /dev/null
-# $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
-# $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
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.
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
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
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
-# $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"
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
# ${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 $@
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
cp $S/conf/param.c .
param.o: param.c Makefile
- ${NORMAL_C_C}
+ ${NORMAL_C}
ioconf.o: ioconf.c
${NORMAL_C}
[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'
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
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
-# $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
#
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
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
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 ;)
#
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
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
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
# 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
+++ /dev/null
-#!/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"
-
-}
-
+++ /dev/null
-# $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
-/* $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.
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;
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,
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;
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;
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++;
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 */
(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);
;
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);
}
--- /dev/null
+/* $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
-/* $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.
* 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);
/*
* 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;
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;
/*
* 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;
/*
* 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:
-/* $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.
#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>
*/
/*
- * 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;
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) {
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);
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);
-/* $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 */
};
/*
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
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,
-/* $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.
#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_ */
--- /dev/null
+/* $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_ */
-/* $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.
#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
.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
--- /dev/null
+/* $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));
-/* $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 {
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.
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));
-/* $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.
--- /dev/null
+/* $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));
--- /dev/null
+/* $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) */
+
--- /dev/null
+/* $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));
--- /dev/null
+/* $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
-/* $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.
/* 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));
--- /dev/null
+/* $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
-/* $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.
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;
: "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"
-/* $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
-/* $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
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;
-/* $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.
#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
-/* $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
/* 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) \
-/* $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;
-/* $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.
char pad; /* sizeof(struct ivec_dsp) == 16 */
};
+extern struct ivec_dsp idsptch;
+
#endif /* _LOCORE */
#endif _VAX_TRAP_H_
-/* $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.
typedef int32_t register_t;
+#define __BROKEN_INDIRECT_CONFIG
+
#endif /* _MACHTYPES_H_ */
--- /dev/null
+/* $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));
+++ /dev/null
-/* $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
-/* $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.
--- /dev/null
+/* $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 *));
+
-/* $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.
* 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;
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;
}
-/* $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.
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
};
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;
int
mbaprint(aux, mbaname)
- void *aux;
+ void *aux;
const char *mbaname;
{
struct mba_attach_args *ma = aux;
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;
-}
-
-
--- /dev/null
+# $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
+
--- /dev/null
+/* $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
+}
+
--- /dev/null
+/* $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 */
--- /dev/null
+/* $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;
+}
--- /dev/null
+/* $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
+}
--- /dev/null
+/* $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);
+}
--- /dev/null
+/* $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
+
--- /dev/null
+/* $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 *));
-# $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 $@
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
#
-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
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
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>
-/* $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.
#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};
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)
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:
uioaddr = uio630;
tmsaddr = qbdev(0774500);
break;
+
+ case VAX_8200:
+ nbi = 1;
+ biaddr = bi8200;
+ bioaddr = bio8200;
}
}
-/* $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.
#include "sys/reboot.h"
#include "lib/libsa/stand.h"
+#define V750UCODE(x) ((x>>8)&255)
+
#include <a.out.h>
/*
char line[100];
volatile u_int devtype, bootdev;
extern unsigned opendev;
+extern unsigned *bootregs;
-main()
+Xmain()
{
register howto asm("r11");
register bdev asm("r10");
hoppabort((x.a_entry&0x7fffffff),howto, devtype, esym);
return;
shread:
- printf("Short read\n");
+ printf("\nShort read\n\n");
return;
}
if (*cp == ')' || *cp == ':')
break;
if (*cp) {
- strncpy(pcs, line, 99);
+ bcopy(line, pcs, 99);
pcs[99] = 0;
i = cp - line + 1;
} else
-/* $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);
/*
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();
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);
}
}
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);
int i, major, adaptor, controller, unit, partition;
- switch (cpunumber) {
+ switch (vax_cputype) {
case VAX_78032:
case VAX_650:
adaptor = 0;
break;
+ case VAX_8200:
case VAX_750:
controller = 0; /* XXX Actually massbuss can be on 3 ctlr's */
unit = bootregs[3];
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;
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;
/*
* 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;
* 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;
}
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;
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;
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;
-/* $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.
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]));
-/* $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
+");
+
+
-/* $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.
#include "sys/reboot.h"
#include "lib/libsa/stand.h"
+#include "vaxstand.h"
+
#include <a.out.h>
char line[100];
int fill_buffer (void);
int write_disk (void);
-main()
+Xmain()
{
int adapt, ctlr, unit, part;
int res, i, loops;
-/* $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.
{
printf("\
Usage: device(adaptor, controller, drive, partition)file\n\
- <device><unit><partitonletter>:file\n\
+ <device><unit><partitonletter>:file\n\
");
}
{
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);
{
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))
*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;
/* 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 */
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;
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);
-/* $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.
#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;
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;
int bootdev;
void
-main()
+Xmain()
{
register bdev asm("r10");
+++ /dev/null
-/* $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;
-}
--- /dev/null
+/* $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) */
+
--- /dev/null
+/* $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);
+}
-/* $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.
/* 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"
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;
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);
}
{
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)
+ ;
}
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);
--- /dev/null
+/* $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;
+}
+
-/* $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)
*/
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
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
+
--- /dev/null
+/* $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;
--- /dev/null
+/* $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 */
+ }
+}
--- /dev/null
+/* $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
+}
--- /dev/null
+/* $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);
+}
--- /dev/null
+/* $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 */
-/* $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.
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
-/* $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.
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 ...
/*
--- /dev/null
+/* $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
-/* $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.
#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"
};
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;
* 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;
-/* $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) \
(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
-/* $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
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 = {
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;
}
/*ARGSUSED*/
-int
+void
dhustop(tp, flag)
register struct tty *tp;
{
tp->t_state |= TS_FLUSH;
}
(void) splx(s);
- return 0;
}
static void
-/* $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
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
}
/*ARGSUSED*/
-int
-dzstop (tp, flag)
+void
+dzstop(tp, flag)
register struct tty *tp;
{
register struct dz_softc *sc;
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
--- /dev/null
+/* $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 = ¤t_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
--- /dev/null
+/* $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
+++ /dev/null
-/* $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
+++ /dev/null
-/* $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
-/* $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.
* 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;
*/
-#include "ts.h"
-
-#if NTS > 0
-
-
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/mtio.h>
#include <sys/uio.h>
#include <sys/proc.h>
-#include <sys/tprintf.h>
#include <machine/pte.h>
#include <machine/sid.h>
#include <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];
* (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 *));
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 4 /* 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,
* 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));
}
/*
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;
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 */
* 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);
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. ???
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);
/*
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.
* 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 */
* 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
/* XXX */
}
- debug (("ubasetup done. [%x, %x, %d]\n", i, itmp, ioctl));
/*
* If it's an ioctl command, then assemble the command.
* 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;
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 */
/*
* 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));
}
/*
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;
/*
* 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 */
#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);
}
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);
}
* 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));
*/
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
*/
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 */
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
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
/*
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:
/*
* 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;
* 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;
}
* 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);
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
}
* (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
}
break;
- case TS_TC_FR:
+ case TS_TC_FR:
/*
* Function Reject -- The specified function was not
* initiated. Bits of interest include OFL, VCK, BOT,
}
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.
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:
}
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
}
break;
- case TS_TC_TPL:
+ case TS_TC_TPL:
/*
* Unrecoverable Error -- Tape position has been lost.
* No valid recovery procedures exist unless the tape
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
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);
}
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 */
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
* (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;
}
*/
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
*/
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;
}
*/
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;
}
*/
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)];
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;
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);
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;
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);
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 */
-
-/* $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
* 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.
*/
{
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;
#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.
* 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.
*
* 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);
}
/*
* 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)
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);
}
* 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;
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));
}
/*
* 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;
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;
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;
}
}
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.
*/
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.
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;
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
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
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;
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;
-/* $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
/*
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
/*
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
/*
* something like 0172520, by forcing it into the last 8K
* of UNIBUS memory space.
*/
-#define ubdevreg(addr) ((addr) & 017777)
+#define ubdevreg(addr) ((addr) & 017777)
-/* $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 */
};
/*
#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
-/* $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
* 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 {
* 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 */
}
}
* 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);
}
-/* $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.
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
*/
#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;
-};
-/* $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
* 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 */
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)
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
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
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;
}
#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;
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;
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;
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 = {
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
};
-/* $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 */
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;
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");
}
/*
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.
{
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 */
}
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
-/* $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);
#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);
#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? */
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 */
/* 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);
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);
#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);
#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);
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 */
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 */
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 */
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
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 */
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
-/* $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.
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
int flag;
struct proc *p;
{
- if (cpunumber != VAX_8600)
+ if (vax_cputype != VAX_8600)
return (ENXIO);
if (crltab.crl_state != CRL_IDLE)
return (EALREADY);
-/* $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.
-/* $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.
* 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
*/
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;
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;
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 */
break;
case 'a': /* absolute adressing mode */
- aa = 1; /* do not break here ! */
+ aa = 1; /* do not break here ! */
default:
switch (*(++ib->argp)) {
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 */
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) {
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);
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);
void
add_char(ib, c)
inst_buffer *ib;
- int c;
+ int c;
{
*ib->curp++ = 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
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);
}
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;
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;
-/* $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
-/* $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 *));
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:
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.
*/
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;
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;
+ }
+}
--- /dev/null
+/* $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++);
+}
-/* $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
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
return;
}
-int
+void
gencnstop(tp, flag)
struct tty *tp;
int flag;
{
- return 0;
+
}
void
-/* $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
-/* $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 ; \
popr $0x3f ; \
rei
-#define KSTACK 0
+#define KSTACK 0
#define ISTACK 1
#define INTVEC(label,stack) \
.long label+stack;
* 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
# _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.
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
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)
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
/*
* 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.
#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
--- /dev/null
+/* $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>
--- /dev/null
+/* $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>
--- /dev/null
+/* $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>
-/* $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.
* 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",
subtyp = *jon;
}
-int
-uvaxIII_clock()
-{
- mtpr(0x40, PR_ICCS); /* Start clock and enable interrupt */
- return 1;
-}
-
void
uvaxIII_memerr()
{
}
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();
}
/*
-/* $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.
* 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>
*/
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");
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 {
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;
};
#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)
ka750_steal_pages()
{
extern vm_offset_t avail_start, virtual_avail;
- extern struct nexus *nexus;
int junk;
/*
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);
+
+}
-/* $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));
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
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",
#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 */
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);
}
-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()
{
--- /dev/null
+/* $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);
+}
-/* $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.
* 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 */
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;
/*
}
}
-#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 {
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);
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);
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;
-}
-
-/* $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;
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);
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;
-/* $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.
* 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.
* 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;
/*
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
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;
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.
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,
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
*/
{
#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);
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.
void
cpu_initclocks()
{
- (cpu_calls[cpunumber].cpu_clock) ();
+ (cpu_calls[vax_cputype].cpu_clock) ();
}
int
size_t *d, f;
struct proc *g;
{
- printf("cpu_sysctl:\n");
return (EOPNOTSUPP);
}
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
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
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) {
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
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)
int
fuswintr(addr)
- caddr_t addr;
+ const void *addr;
{
panic("fuswintr: need to be implemented");
return 0;
int
suibyte(base, byte)
- int byte;
void *base;
+ short byte;
{
panic("suibyte: need to be implemented");
return 0;
int
suswintr(addr, cnt)
- caddr_t addr;
- u_int cnt;
+ void *addr;
+ short cnt;
{
panic("suswintr: need to be implemented");
return 0;
process_sstep(p, sstep)
struct proc *p;
{
- void *ptr;
+ void *ptr;
struct trapframe *tf;
if ((p->p_flag & P_INMEM) == 0)
void
cmrerr()
{
- (*cpu_calls[cpunumber].cpu_memerr) ();
+ (*cpu_calls[vax_cputype].cpu_memerr) ();
}
+++ /dev/null
-/* $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
-}
+++ /dev/null
-/* $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 */
+++ /dev/null
-/* $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 *));
-
-/* $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.
-/* $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.
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;
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().
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.
* 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;
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);
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);
}
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);
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;
{
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,
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;
boolean_t
pmap_is_referenced(pa)
- vm_offset_t pa;
+ vm_offset_t pa;
{
struct pv_entry *pv;
u_int *pte,spte=0;
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);
}
void
pmap_clear_reference(pa)
- vm_offset_t pa;
+ vm_offset_t pa;
{
struct pv_entry *pv;
int *pte;
void
pmap_clear_modify(pa)
- vm_offset_t pa;
+ vm_offset_t pa;
{
struct pv_entry *pv;
u_int *pte;
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
}
/*
- * 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;
}
/*
- * 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)
+/* $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 $ */
/*
-/* $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
{
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);
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;
*/
if (temp == dumpdev)
dumpdev = swdevt[0].sw_dev;
- panic("autoconf.c: argdev\n");
-/* if (temp == argdev)
- argdev = swdevt[0].sw_dev; */
#endif
}
-/* $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)
int
sbi_match(parent, cf, aux)
- struct device *parent;
- void *cf, *aux;
+ struct device *parent;
+ void *cf, *aux;
{
struct bp_conf *bp = 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
};
-/* $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.
* @(#)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 *));
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;
#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;
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;
}
- 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);
+++ /dev/null
-/* $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
-
-/* $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.
* 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();
--- /dev/null
+/* $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);
+}
-/* $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
--- /dev/null
+/* $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);
+}
-/* $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.
#include <machine/pcb.h>
#include <machine/frame.h>
#include <machine/cpu.h>
+#include <machine/sid.h>
#include <sys/syscallargs.h>
/* 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;
}
/* 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));
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;
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;
*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
--- /dev/null
+/* $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 */
--- /dev/null
+/* $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 */
--- /dev/null
+/* $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 */
--- /dev/null
+/* $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 */
+
+
--- /dev/null
+/*
+ * 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);
+}
--- /dev/null
+/* $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*)®s->sci.sci_r0;
+ ncr_sc->sci_r1 = (void*)®s->sci.sci_r1;
+ ncr_sc->sci_r2 = (void*)®s->sci.sci_r2;
+ ncr_sc->sci_r3 = (void*)®s->sci.sci_r3;
+ ncr_sc->sci_r4 = (void*)®s->sci.sci_r4;
+ ncr_sc->sci_r5 = (void*)®s->sci.sci_r5;
+ ncr_sc->sci_r6 = (void*)®s->sci.sci_r6;
+ ncr_sc->sci_r7 = (void*)®s->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;
+}
--- /dev/null
+/* $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 */
+
--- /dev/null
+/* $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