diff options
Diffstat (limited to 'sys/arch/vax')
155 files changed, 25555 insertions, 9802 deletions
diff --git a/sys/arch/vax/bi/bi.c b/sys/arch/vax/bi/bi.c new file mode 100644 index 00000000000..cfb0171ee76 --- /dev/null +++ b/sys/arch/vax/bi/bi.c @@ -0,0 +1,148 @@ +/* $NetBSD: bi.c,v 1.4 1996/10/13 03:34:44 christos Exp $ */ +/* + * Copyright (c) 1996 Ludd, University of Lule}, Sweden. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed at Ludd, University of + * Lule}, Sweden and its contributors. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + + +/* + * VAXBI specific routines. + */ +/* + * TODO + * handle BIbus errors more gracefully. + */ + +#include <sys/param.h> +#include <sys/device.h> + +#include <machine/mtpr.h> +#include <machine/nexus.h> +#include <machine/cpu.h> + +#include <arch/vax/bi/bireg.h> +#include <arch/vax/bi/bivar.h> + +static int bi_match __P((struct device *, void *, void *)); +static void bi_attach __P((struct device *, struct device *, void*)); +static int bi_print __P((void *, const char *)); + +struct cfdriver bi_cd = { + NULL, "bi", DV_DULL +}; + +struct cfattach bi_ca = { + sizeof(struct bi_softc), bi_match, bi_attach +}; + +struct bi_list bi_list[] = { + {BIDT_MS820, 1, "ms820"}, + {BIDT_DRB32, 0, "drb32"}, + {BIDT_DWBUA, 0, "dwbua"}, + {BIDT_KLESI, 0, "klesi"}, + {BIDT_KA820, 1, "ka820"}, + {BIDT_DB88, 0, "db88"}, + {BIDT_CIBCA, 0, "cibca"}, + {BIDT_DMB32, 0, "dmb32"}, + {BIDT_CIBCI, 0, "cibci"}, + {BIDT_KA800, 0, "ka800"}, + {BIDT_KDB50, 0, "kdb50"}, + {BIDT_DWMBA, 0, "dwmba"}, + {BIDT_KFBTA, 0, "kfbta"}, + {BIDT_DEBNK, 0, "debnk"}, + {BIDT_DEBNA, 0, "debna"}, + {0,0,0} +}; + +int +bi_print(aux, name) + void *aux; + const char *name; +{ + struct bi_attach_args *ba = aux; + struct bi_list *bl; + + if (name) { + for (bl = &bi_list[0]; bl->bl_nr; bl++) + if (bl->bl_nr == ba->ba_node->biic.bi_dtype) { + printf(bl->bl_name); + break; + } + if (bl->bl_nr == 0) + printf("unknown device 0x%x", + ba->ba_node->biic.bi_dtype); + printf(" at %s", name); + } + printf(" node %d", ba->ba_nodenr); + return bl->bl_havedriver ? UNCONF : UNSUPP; +} + +int +bi_match(parent, match, aux) + struct device *parent; + void *match, *aux; +{ + struct bp_conf *bp = aux; + + if (strcmp(bp->type, "bi")) + return 0; + return 1; +} + +void +bi_attach(parent, self, aux) + struct device *parent, *self; + void *aux; +{ + struct bp_conf *bp = aux; + struct bi_softc *bi = (void *)self; + struct bi_node *binode; + struct bi_attach_args ba; + int nodenr; + + printf("\n"); + binode = bi->bi_base = (struct bi_node *)bp->bp_addr; + + ba.ba_intcpu = 1 << mastercpu; + for (nodenr = 0; nodenr < NNODEBI; nodenr++) { + if (badaddr((caddr_t)&binode[nodenr], 4)) + continue; + + ba.ba_node = &binode[nodenr]; + ba.ba_nodenr = nodenr; + config_found(self, &ba, bi_print); + } +} + +void +bi_buserr() +{ + panic("bi_buserr"); +} diff --git a/sys/arch/vax/bi/bireg.h b/sys/arch/vax/bi/bireg.h new file mode 100644 index 00000000000..1663e168d95 --- /dev/null +++ b/sys/arch/vax/bi/bireg.h @@ -0,0 +1,245 @@ +/* $NetBSD: bireg.h,v 1.1 1996/07/19 14:26:53 ragge Exp $ */ +/* + * Copyright (c) 1988 Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Chris Torek. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)bireg.h 7.3 (Berkeley) 6/28/90 + */ + +/* + * VAXBI node definitions. + */ + +/* + * BI node addresses + */ +#define BI_BASE(bi) (0x20000000 + (bi) * 0x2000000) +#define MAXNBI 16 /* Spec says there can be 16 anyway */ +#define NNODEBI 16 /* 16 nodes per BI */ + +#define BI_PROBE 0x80000 /* CPU on 8200, NBIA on 8800 */ +/* + * BI nodes all start with BI interface registers (those on the BIIC chip). + * These are followed with interface-specific registers. + * + * NB: This structure does NOT include the four GPRs (not anymore!) + */ +struct biiregs { + u_short bi_dtype; /* device type */ + u_short bi_revs; /* revisions */ + u_long bi_csr; /* control and status register */ + u_long bi_ber; /* bus error register */ + u_long bi_eintrcsr; /* error interrupt control register */ + u_long bi_intrdes; /* interrupt destination register */ + /* the rest are not required for all nodes */ + u_long bi_ipintrmsk; /* IP interrupt mask register */ + u_long bi_fipsdes; /* Force-Bit IPINTR/STOP destination reg */ + u_long bi_ipintrsrc; /* IPINTR source register */ + u_long bi_sadr; /* starting address register */ + u_long bi_eadr; /* ending address register */ + u_long bi_bcicsr; /* BCI control and status register */ + u_long bi_wstat; /* write status register */ + u_long bi_fipscmd; /* Force-Bit IPINTR/STOP command reg */ + u_long bi_xxx1[3]; /* unused */ + u_long bi_uintrcsr; /* user interface interrupt control reg */ + u_long bi_xxx2[43]; /* unused */ +/* although these are on the BIIC, their interpretation varies */ +/* u_long bi_gpr[4]; */ /* general purpose registers */ +}; + +/* + * A generic BI node. + */ +struct bi_node { + struct biiregs biic; /* interface */ + u_long bi_xxx[1988]; /* pad to 8K */ +}; + +/* + * A cpu node. + */ +struct bi_cpu { + struct biiregs biic; /* interface chip */ + u_long bi_gpr[4]; /* gprs (unused) */ + u_long bi_sosr; /* slave only status register */ + u_long bi_xxx[63]; /* pad */ + u_long bi_rxcd; /* receive console data register */ +}; + +/* device types */ +#define BIDT_MS820 0x0001 /* MS820 memory board */ +#define BIDT_DRB32 0x0101 /* DRB32 Supercomputer gateway */ +#define BIDT_DWBUA 0x0102 /* DWBUA Unibus adapter */ +#define BIDT_KLESI 0x0103 /* KLESI-B adapter */ +#define BIDT_KA820 0x0105 /* KA820 cpu */ +#define BIDT_DB88 0x0106 /* DB88 adapter */ +#define BIDT_CIBCA 0x0108 /* Computer Interconnect adapter */ +#define BIDT_DMB32 0x0109 /* DMB32 adapter */ +#define BIDT_CIBCI 0x010b /* Computer Interconnect adapter (old) */ +#define BIDT_KA800 0x010c /* KA800 slave processor */ +#define BIDT_KDB50 0x010e /* KDB50 disk controller */ +#define BIDT_DWMBA 0x2107 /* XMI - BI adapter */ +#define BIDT_KFBTA 0x410d /* RD/RX disk controller */ +#define BIDT_DEBNK 0x410e /* BI Ethernet (Lance) + TK50 */ +#define BIDT_DEBNA 0x410f /* BI Ethernet (Lance) adapter */ + +/* bits in bi_csr */ +#define BICSR_IREV(x) ((u_char)((x) >> 24)) /* VAXBI interface rev */ +#define BICSR_TYPE(x) ((u_char)((x) >> 16)) /* BIIC type */ +#define BICSR_HES 0x8000 /* hard error summary */ +#define BICSR_SES 0x4000 /* soft error summary */ +#define BICSR_INIT 0x2000 /* initialise node */ +#define BICSR_BROKE 0x1000 /* broke */ +#define BICSR_STS 0x0800 /* self test status */ +#define BICSR_NRST 0x0400 /* node reset */ +#define BICSR_UWP 0x0100 /* unlock write pending */ +#define BICSR_HEIE 0x0080 /* hard error interrupt enable */ +#define BICSR_SEIE 0x0040 /* soft error interrupt enable */ +#define BICSR_ARB_MASK 0x0030 /* mask to get arbitration codes */ +#define BICSR_ARB_NONE 0x0030 /* no arbitration */ +#define BICSR_ARB_LOG 0x0020 /* low priority */ +#define BICSR_ARB_HIGH 0x0010 /* high priority */ +#define BICSR_ARB_RR 0x0000 /* round robin */ +#define BICSR_NODEMASK 0x000f /* node ID */ + +#define BICSR_BITS \ +"\20\20HES\17SES\16INIT\15BROKE\14STS\13NRST\11UWP\10HEIE\7SEIE" + +/* bits in bi_ber */ +#define BIBER_MBZ 0x8000fff0 +#define BIBER_NMR 0x40000000 /* no ack to multi-responder command */ +#define BIBER_MTCE 0x20000000 /* master transmit check error */ +#define BIBER_CTE 0x10000000 /* control transmit error */ +#define BIBER_MPE 0x08000000 /* master parity error */ +#define BIBER_ISE 0x04000000 /* interlock sequence error */ +#define BIBER_TDF 0x02000000 /* transmitter during fault */ +#define BIBER_IVE 0x01000000 /* ident vector error */ +#define BIBER_CPE 0x00800000 /* command parity error */ +#define BIBER_SPE 0x00400000 /* slave parity error */ +#define BIBER_RDS 0x00200000 /* read data substitute */ +#define BIBER_RTO 0x00100000 /* retry timeout */ +#define BIBER_STO 0x00080000 /* stall timeout */ +#define BIBER_BTO 0x00040000 /* bus timeout */ +#define BIBER_NEX 0x00020000 /* nonexistent address */ +#define BIBER_ICE 0x00010000 /* illegal confirmation error */ +#define BIBER_UPEN 0x00000008 /* user parity enable */ +#define BIBER_IPE 0x00000004 /* ID parity error */ +#define BIBER_CRD 0x00000002 /* corrected read data */ +#define BIBER_NPE 0x00000001 /* null bus parity error */ +#define BIBER_HARD 0x4fff0000 + +#define BIBER_BITS \ +"\20\37NMR\36MTCE\35CTE\34MPE\33ISE\32TDF\31IVE\30CPE\ +\27SPE\26RDS\25RTO\24STO\23BTO\22NEX\21ICE\4UPEN\3IPE\2CRD\1NPE" + +/* bits in bi_eintrcsr */ +#define BIEIC_INTRAB 0x01000000 /* interrupt abort */ +#define BIEIC_INTRC 0x00800000 /* interrupt complete */ +#define BIEIC_INTRSENT 0x00200000 /* interrupt command sent */ +#define BIEIC_INTRFORCE 0x00100000 /* interrupt force */ +#define BIEIC_LEVELMASK 0x000f0000 /* mask for interrupt levels */ +#define BIEIC_IPL17 0x00080000 /* ipl 0x17 */ +#define BIEIC_IPL16 0x00040000 /* ipl 0x16 */ +#define BIEIC_IPL15 0x00020000 /* ipl 0x15 */ +#define BIEIC_IPL14 0x00010000 /* ipl 0x14 */ +#define BIEIC_VECMASK 0x00003ffc /* vector mask for error intr */ + +/* bits in bi_intrdes */ +#define BIDEST_MASK 0x0000ffff /* one bit per node to be intr'ed */ + +/* bits in bi_ipintrmsk */ +#define BIIPINTR_MASK 0xffff0000 /* one per node to allow to ipintr */ + +/* bits in bi_fipsdes */ +#define BIFIPSD_MASK 0x0000ffff + +/* bits in bi_ipintrsrc */ +#define BIIPSRC_MASK 0xffff0000 + +/* sadr and eadr are simple addresses */ + +/* bits in bi_bcicsr */ +#define BCI_BURSTEN 0x00020000 /* burst mode enable */ +#define BCI_IPSTOP_FRC 0x00010000 /* ipintr/stop force */ +#define BCI_MCASTEN 0x00008000 /* multicast space enable */ +#define BCI_BCASTEN 0x00004000 /* broadcast enable */ +#define BCI_STOPEN 0x00002000 /* stop enable */ +#define BCI_RSRVDEN 0x00001000 /* reserved enable */ +#define BCI_IDENTEN 0x00000800 /* ident enable */ +#define BCI_INVALEN 0x00000400 /* inval enable */ +#define BCI_WINVEN 0x00000200 /* write invalidate enable */ +#define BCI_UINTEN 0x00000100 /* user interface csr space enable */ +#define BCI_BIICEN 0x00000080 /* BIIC csr space enable */ +#define BCI_INTEN 0x00000040 /* interrupt enable */ +#define BCI_IPINTEN 0x00000020 /* ipintr enable */ +#define BCI_PIPEEN 0x00000010 /* pipeline NXT enable */ +#define BCI_RTOEVEN 0x00000008 /* read timeout EV enable */ + +#define BCI_BITS \ +"\20\22BURSTEN\21IPSTOP_FRC\20MCASTEN\ +\17BCASTEN\16STOPEN\15RSRVDEN\14IDENTEN\13INVALEN\12WINVEN\11UINTEN\ +\10BIICEN\7INTEN\6IPINTEN\5PIPEEN\4RTOEVEN" + +/* bits in bi_wstat */ +#define BIW_GPR3 0x80000000 /* gpr 3 was written */ +#define BIW_GPR2 0x40000000 /* gpr 2 was written */ +#define BIW_GPR1 0x20000000 /* gpr 1 was written */ +#define BIW_GPR0 0x10000000 /* gpr 0 was written */ + +/* bits in force-bit ipintr/stop command register 8/ +#define BIFIPSC_CMDMASK 0x0000f000 /* command */ +#define BIFIPSC_MIDEN 0x00000800 /* master ID enable */ + +/* bits in bi_uintcsr */ +#define BIUI_INTAB 0xf0000000 /* interrupt abort level */ +#define BIUI_INTC 0x0f000000 /* interrupt complete bits */ +#define BIUI_SENT 0x00f00000 /* interrupt sent bits */ +#define BIUI_FORCE 0x000f0000 /* force interrupt level */ +#define BIUI_EVECEN 0x00008000 /* external vector enable */ +#define BIUI_VEC 0x00003ffc /* interrupt vector */ + +/* tell if a bi device is a slave (hence has SOSR) */ +#define BIDT_ISSLAVE(x) (((x) & 0x7f00) == 0) + +/* bits in bi_sosr */ +#define BISOSR_MEMSIZE 0x1ffc0000 /* memory size */ +#define BISOSR_BROKE 0x00001000 /* broke */ + +/* bits in bi_rxcd */ +#define BIRXCD_BUSY2 0x80000000 /* busy 2 */ +#define BIRXCD_NODE2 0x0f000000 /* node id 2 */ +#define BIRXCD_CHAR2 0x00ff0000 /* character 2 */ +#define BIRXCD_BUSY1 0x00008000 /* busy 1 */ +#define BIRXCD_NODE1 0x00000f00 /* node id 1 */ +#define BIRXCD_CHAR1 0x000000ff /* character 1 */ diff --git a/sys/arch/vax/bi/bivar.h b/sys/arch/vax/bi/bivar.h new file mode 100644 index 00000000000..bb6d3972cfb --- /dev/null +++ b/sys/arch/vax/bi/bivar.h @@ -0,0 +1,59 @@ +/* $NetBSD: bivar.h,v 1.1 1996/07/19 14:26:54 ragge Exp $ */ +/* + * Copyright (c) 1996 Ludd, University of Lule}, Sweden. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed at Ludd, University of + * Lule}, Sweden and its contributors. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + + +/* + * per-BI-adapter state. + */ +struct bi_softc { + struct device bi_dev; + struct bi_node *bi_base; +}; + +/* + * Struct used for autoconfiguration; attaching of BI nodes. + */ +struct bi_attach_args { + struct bi_node *ba_node; + int ba_nodenr; + int ba_intcpu; /* Mask of which cpus to interrupt */ +}; + +/* + * BI node list. + */ +struct bi_list { + u_short bl_nr; /* Unit ID# */ + u_short bl_havedriver; /* Have device driver */ + char *bl_name; /* DEC name */ +}; diff --git a/sys/arch/vax/bi/kdb.c b/sys/arch/vax/bi/kdb.c new file mode 100644 index 00000000000..13f8f4f8f74 --- /dev/null +++ b/sys/arch/vax/bi/kdb.c @@ -0,0 +1,313 @@ +/* $NetBSD: kdb.c,v 1.5 1997/01/11 11:34:39 ragge Exp $ */ +/* + * Copyright (c) 1996 Ludd, University of Lule}, Sweden. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed at Ludd, University of + * Lule}, Sweden and its contributors. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * KDB50 disk device driver + */ +/* + * TODO + * Implement node reset routine. + * Nices hardware error handling. + */ + +#include <sys/param.h> +#include <sys/kernel.h> +#include <sys/buf.h> +#include <sys/device.h> +#include <sys/proc.h> +#include <sys/malloc.h> + +#include <vm/vm.h> +#include <vm/vm_kern.h> + +#include <machine/sid.h> +#include <machine/pte.h> +#include <machine/pcb.h> +#include <machine/trap.h> +#include <machine/scb.h> + +#include <vax/bi/bireg.h> +#include <vax/bi/bivar.h> +#include <vax/bi/kdbreg.h> + +#include <vax/mscp/mscp.h> +#include <vax/mscp/mscpvar.h> +#include <vax/mscp/mscpreg.h> + +#define b_forw b_hash.le_next +/* + * Software status, per controller. + */ +struct kdb_softc { + struct device sc_dev; /* Autoconfig info */ + struct ivec_dsp sc_ivec; /* Interrupt vector handler */ + struct mscp_pack sc_kdb; /* Struct for kdb communication */ + struct mscp_softc *sc_softc; /* MSCP info (per mscpvar.h) */ + struct kdb_regs *sc_kr; /* KDB controller registers */ + struct mscp *sc_mscp; /* Keep pointer to active mscp */ +}; + +int kdbmatch __P((struct device *, void *, void *)); +void kdbattach __P((struct device *, struct device *, void *)); +void kdbreset __P((int)); +void kdbintr __P((int)); +void kdbctlrdone __P((struct device *, int)); +int kdbprint __P((void *, const char *)); +void kdbsaerror __P((struct device *, int)); +int kdbgo __P((struct device *, struct buf *)); + +struct cfdriver kdb_cd = { + NULL, "kdb", DV_DULL +}; + +struct cfattach kdb_ca = { + sizeof(struct kdb_softc), kdbmatch, kdbattach +}; + +/* + * More driver definitions, for generic MSCP code. + */ +struct mscp_ctlr kdb_mscp_ctlr = { + kdbctlrdone, + kdbgo, + kdbsaerror, +}; + +int +kdbprint(aux, name) + void *aux; + const char *name; +{ + if (name) + printf("%s: mscpbus", name); + return UNCONF; +} + +/* + * Poke at a supposed KDB to see if it is there. + */ +int +kdbmatch(parent, match, aux) + struct device *parent; + void *match, *aux; +{ + struct cfdata *cf = match; + struct bi_attach_args *ba = aux; + + if (ba->ba_node->biic.bi_dtype != BIDT_KDB50) + return 0; + + if (cf->cf_loc[0] != -1 && cf->cf_loc[0] != ba->ba_nodenr) + return 0; + + return 1; +} + +void +kdbattach(parent, self, aux) + struct device *parent, *self; + void *aux; +{ + struct kdb_softc *sc = (void *)self; + struct bi_attach_args *ba = aux; + struct mscp_attach_args ma; + extern struct ivec_dsp idsptch; + volatile int i = 10000; + + printf("\n"); + bcopy(&idsptch, &sc->sc_ivec, sizeof(struct ivec_dsp)); + scb->scb_nexvec[1][ba->ba_nodenr] = &sc->sc_ivec; + sc->sc_ivec.hoppaddr = kdbintr; + sc->sc_ivec.pushlarg = self->dv_unit; + sc->sc_kr = (void *)ba->ba_node; + + bzero(&sc->sc_kdb, sizeof (struct mscp_pack)); + + ma.ma_mc = &kdb_mscp_ctlr; + ma.ma_type = MSCPBUS_DISK|MSCPBUS_KDB; + ma.ma_uuda = (struct mscp_pack *)kvtophys(&sc->sc_kdb); + ma.ma_uda = &sc->sc_kdb; + ma.ma_ip = &sc->sc_kr->kdb_ip; + ma.ma_sa = &sc->sc_kr->kdb_sa; + ma.ma_sw = &sc->sc_kr->kdb_sw; + ma.ma_softc = &sc->sc_softc; + ma.ma_ivec = (int)&scb->scb_nexvec[1][ba->ba_nodenr] - (int)scb; + ma.ma_ctlrnr = ba->ba_nodenr; + sc->sc_kr->kdb_bi.bi_csr |= BICSR_NRST; + while (i--) /* Need delay??? */ + ; + sc->sc_kr->kdb_bi.bi_intrdes = ba->ba_intcpu; + sc->sc_kr->kdb_bi.bi_bcicsr |= BCI_STOPEN | BCI_IDENTEN | BCI_UINTEN | + BCI_INTEN; + sc->sc_kr->kdb_bi.bi_uintrcsr = ma.ma_ivec; + config_found(&sc->sc_dev, &ma, kdbprint); +} + +int +kdbgo(usc, bp) + struct device *usc; + struct buf *bp; +{ + struct kdb_softc *sc = (void *)usc; + struct mscp_softc *mi = sc->sc_softc; + struct mscp *mp = (void *)bp->b_actb; + struct pcb *pcb; + pt_entry_t *pte; + int pfnum, npf, o, i; + unsigned info = 0; + caddr_t addr; + + o = (int)bp->b_un.b_addr & PGOFSET; + npf = btoc(bp->b_bcount + o) + 1; + addr = bp->b_un.b_addr; + + /* + * Get a pointer to the pte pointing out the first virtual address. + * Use different ways in kernel and user space. + */ + if ((bp->b_flags & B_PHYS) == 0) { + pte = kvtopte(addr); + } else { + pcb = bp->b_proc->p_vmspace->vm_pmap.pm_pcb; + pte = uvtopte(addr, pcb); + } + + /* + * When we are doing DMA to user space, be sure that all pages + * we want to transfer to is mapped. WHY DO WE NEED THIS??? + * SHOULDN'T THEY ALWAYS BE MAPPED WHEN DOING THIS??? + */ + for (i = 0; i < (npf - 1); i++) { + if ((pte + i)->pg_pfn == 0) { + int rv; + rv = vm_fault(&bp->b_proc->p_vmspace->vm_map, + (unsigned)addr + i * NBPG, + VM_PROT_READ|VM_PROT_WRITE, FALSE); + if (rv) + panic("KDB DMA to nonexistent page, %d", rv); + } + } + /* + * pte's for userspace isn't necessary positioned + * in consecutive physical pages. We check if they + * are, otherwise we need to copy the pte's to a + * physically contigouos page area. + * XXX some copying here may be unneccessary. Subject to fix. + */ + if (bp->b_flags & B_PHYS) { + int i = kvtophys(pte); + unsigned k; + + if (trunc_page(i) != trunc_page(kvtophys(pte) + npf * 4)) { + info = (unsigned)malloc(2 * NBPG, M_DEVBUF, M_WAITOK); + k = (info + PGOFSET) & ~PGOFSET; + bcopy(pte, (void *)k, NBPG); + i = kvtophys(k); + } + mp->mscp_seq.seq_mapbase = i; + } else + mp->mscp_seq.seq_mapbase = (unsigned)pte; + mscp_dgo(mi, KDB_MAP | o, info, bp); + return 1; +} + +void +kdbsaerror(usc, doreset) + struct device *usc; + int doreset; +{ + struct kdb_softc *sc = (void *)usc; + register int code = sc->sc_kr->kdb_sa; + + if ((code & MP_ERR) == 0) + return; + printf("%s: controller error, sa=0x%x\n", sc->sc_dev.dv_xname, code); + /* What to do now??? */ +} + +/* + * Interrupt routine. Depending on the state of the controller, + * continue initialisation, or acknowledge command and response + * interrupts, and process responses. + */ +void +kdbintr(ctlr) + int ctlr; +{ + struct kdb_softc *sc = kdb_cd.cd_devs[ctlr]; + struct uba_softc *uh; + struct mscp_pack *ud; + + if (sc->sc_kr->kdb_sa & MP_ERR) { /* ctlr fatal error */ + kdbsaerror(&sc->sc_dev, 1); + return; + } + mscp_intr(sc->sc_softc); +} + +#ifdef notyet +/* + * The KDB50 has been reset. Reinitialise the controller + * and requeue outstanding I/O. + */ +void +kdbreset(ctlr) + int ctlr; +{ + register struct kdb_softc *sc; + + sc = kdb_cd.cd_devs[ctlr]; + printf(" kdb%d", ctlr); + + + /* reset queues and requeue pending transfers */ + mscp_requeue(sc->sc_softc); + + /* + * If it fails to initialise we will notice later and + * try again (and again...). Do not call kdbstart() + * here; it will be done after the controller finishes + * initialisation. + */ + if (kdbinit(sc)) + printf(" (hung)"); +} +#endif + +void +kdbctlrdone(usc, info) + struct device *usc; + int info; +{ + if (info) + free((void *)info, NBPG * 2); +} diff --git a/sys/arch/vax/bi/kdbreg.h b/sys/arch/vax/bi/kdbreg.h new file mode 100644 index 00000000000..95ed9548093 --- /dev/null +++ b/sys/arch/vax/bi/kdbreg.h @@ -0,0 +1,64 @@ +/* $NetBSD: kdbreg.h,v 1.1 1996/07/19 14:26:56 ragge Exp $ */ +/* + * Copyright (c) 1988 Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Chris Torek. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)kdbreg.h 7.3 (Berkeley) 6/28/90 + */ + +/* + * The KDB50 registers are embedded inside the bi interface + * general-purpose registers. + */ +struct kdb_regs { + struct biiregs kdb_bi; + short kdb_xxx; /* first half of GPR 0 unused */ + short kdb_ip; /* initialisation and polling */ + short kdb_sa; /* status & address (r/o half) */ + short kdb_sw; /* status & address (w/o half) */ +}; + +#define KDBSR_BITS \ +"\20\20ERR\17STEP4\16STEP3\15STEP2\14STEP1\13oldNV\12oldQB\11DI\10IE\1GO" + +/* + * Asserting KDB_MAP in values placed in mscp_seq.seq_buffer tells + * the KDB to use mscp_seq.seq_mapbase as a set of PTEs and seq_buffer + * as an offset value. Hence we need no mappings; the KDB50 reads + * the hardware page tables directly. (Without KDB_MAP, seq_bufer + * represents the physical memory address instead, and seq_mapbase is + * unused.) + */ +#define KDB_MAP 0x80000000 +#define KDB_PHYS 0 /* pseudo flag */ diff --git a/sys/arch/vax/boot/Makefile b/sys/arch/vax/boot/Makefile index f2ac372bc2d..b9a0cb46e9f 100644 --- a/sys/arch/vax/boot/Makefile +++ b/sys/arch/vax/boot/Makefile @@ -1,28 +1,29 @@ -# $OpenBSD: Makefile,v 1.6 1996/09/27 18:38:04 maja Exp $ -# $NetBSD: Makefile,v 1.9 1996/03/16 11:03:12 ragge Exp $ +# $OpenBSD: Makefile,v 1.7 1997/01/15 23:24:15 maja Exp $ +# $NetBSD: Makefile,v 1.11 1996/10/18 06:10:18 thorpej Exp $ # INCPATH=-I. -I../../.. -I../.. -I../../../lib/libsa -.PATH: ${.CURDIR}/../../../lib/libkern CC= cc AS= as S= ../../.. RELOC= 100000 -CFLAGS+=-O ${INCPATH} -DSTANDALONE -DRELOC=0x${RELOC} -D_VAX_INLINE_ +XXRPB= 0F4240 +CFLAGS+=-O ${INCPATH} -DSTANDALONE -DRELOC=0x${RELOC} \ + -D_VAX_INLINE_ -DXXRPB=0x$(XXRPB) -DEVS= autoconf.o hp.o ra.o tmscp.o ctu.o - -LIBKERN=libkern.a -KERNOBJ=__main.o strlen.o strcmp.o strncmp.o strncpy.o min.o strcpy.o +DEVS= autoconf.o hp.o ra.o tmscp.o ctu.o mfm.o rom.o romread.o \ + scsi_low.o scsi_hi.o sd.o .include "$S/lib/libsa/Makefile.inc" LIBSA= ${SALIB} -all: xxboot boot copy edlabel +SVAX= consio.o urem.o udiv.o str.o + +all: ${LIBSA} xxboot boot copy edlabel -libsvax.a: consio.o urem.o udiv.o +libsvax.a: ${SVAX} ar crv $@ $? ranlib $@ @@ -32,6 +33,9 @@ urem.o: ../vax/urem.s udiv.o: ../vax/udiv.s ${CC} -x assembler-with-cpp -E ../vax/udiv.s | as -o udiv.o +str.o: str.s + ${CC} -x assembler-with-cpp -E str.s | as -o str.o + # startups start.o: start.s @@ -42,29 +46,29 @@ srt0.o: srt0.s # -xxboot: start.o bootxx.o romread.o ${LIBSA} ${LIBKERN} libsvax.a +xxboot: start.o bootxx.o romread.o libsvax.a ld -N -Ttext ${RELOC} -o a.out start.o bootxx.o romread.o \ - ${LIBSA} ${LIBKERN} libsvax.a + ${LIBSA} libsvax.a @strip a.out @size a.out @dd if=a.out of=xxboot bs=32 skip=1 @rm -f a.out -boot: boot.o srt0.o devopen.o conf.o ${DEVS} ${LIBKERN} ${LIBSA} libsvax.a +boot: boot.o srt0.o devopen.o conf.o ${DEVS} libsvax.a ld -N -Ttext ${RELOC} -e nisse -o $@ srt0.o devopen.o boot.o \ - conf.o ${DEVS} ${LIBSA} ${LIBKERN} libsvax.a + conf.o ${DEVS} ${LIBSA} libsvax.a @strip boot @size boot -edlabel: edlabel.o srt0.o devopen.o conf.o ${DEVS} ${LIBKERN} ${LIBSA} libsvax.a +edlabel: edlabel.o srt0.o devopen.o conf.o ${DEVS} libsvax.a ld -N -Ttext ${RELOC} -e nisse -o $@ srt0.o devopen.o edlabel.o\ - conf.o ${DEVS} ${LIBSA} ${LIBKERN} libsvax.a + conf.o ${DEVS} ${LIBSA} libsvax.a @strip edlabel @size edlabel -copy: copy.o srt0.o devopen.o conf.o ${DEVS} ${LIBKERN} ${LIBSA} libsvax.a +copy: copy.o srt0.o devopen.o conf.o ${DEVS} libsvax.a ld -N -Ttext ${RELOC} -e nisse -o $@ srt0.o devopen.o copy.o \ - conf.o ${DEVS} ${LIBSA} ${LIBKERN} libsvax.a + conf.o ${DEVS} ${LIBSA} libsvax.a @strip copy @size copy @@ -98,14 +102,10 @@ bootxx.o: bootxx.c ${CC} -c ${CFLAGS} $*.c # -libkern.a: ${KERNOBJ} - @echo Creating standalone kern library - @ar rv libkern.a `lorder ${KERNOBJ} | tsort` - -# install: boot xxboot - install -c -o ${BINOWN} -g ${BINGRP} -m 444 boot ${DESTDIR}/ - install -c -o ${BINOWN} -g ${BINGRP} -m 444 xxboot ${DESTDIR}/usr/mdec + ${INSTALL} -c -o ${BINOWN} -g ${BINGRP} -m 444 boot ${DESTDIR}/ + ${INSTALL} -c -o ${BINOWN} -g ${BINGRP} -m 444 xxboot \ + ${DESTDIR}/usr/mdec rm -f ${DESTDIR}/usr/mdec/raboot ln ${DESTDIR}/usr/mdec/xxboot ${DESTDIR}/usr/mdec/raboot rm -f ${DESTDIR}/usr/mdec/hpboot @@ -115,7 +115,7 @@ clean:: rm -f start.o romread.o bootxx.o init.o xxboot boot racopy \ libsvax.a udiv.o urem.o consio.o ${DEVS} edlabel edlabel.o rm -f conf.o boot.o rom.o racopy.o srt0.o devopen.o rootcopy.o \ - copy copy.o + copy copy.o init.o .include <bsd.prog.mk> diff --git a/sys/arch/vax/boot/autoconf.c b/sys/arch/vax/boot/autoconf.c index ca08f01214a..d3b2d2b67fd 100644 --- a/sys/arch/vax/boot/autoconf.c +++ b/sys/arch/vax/boot/autoconf.c @@ -1,4 +1,4 @@ -/* $NetBSD: autoconf.c,v 1.5 1996/03/07 23:27:06 ragge Exp $ */ +/* $NetBSD: autoconf.c,v 1.6 1996/08/02 11:21:46 ragge Exp $ */ /* * Copyright (c) 1994 Ludd, University of Lule}, Sweden. * All rights reserved. @@ -39,8 +39,8 @@ #include "vaxstand.h" int nmba=0, nuba=0, nbi=0,nsbi=0,nuda=0; -int *mbaaddr, *ubaaddr; -int *udaaddr, *uioaddr, tmsaddr; +int *mbaaddr, *ubaaddr, *biaddr; +int *udaaddr, *uioaddr, tmsaddr, *bioaddr; static int mba750[]={0xf28000,0xf2a000,0xf2c000}; static int uba750[]={0xf30000,0xf32000}; @@ -55,6 +55,10 @@ static int uba780[]={0x20006000,0x20008000,0x2000a000,0x2000c000, static int uio780[]={0x20100000,0x20140000,0x20180000,0x201c0000, 0x22100000,0x22140000,0x22180000,0x221c0000}; +static int bi8200[]={0x20000000, 0x22000000, 0x24000000, 0x26000000, + 0x28000000, 0x2a000000}; +static int bio8200[]={0x20400000}; + static int uba630[]={0x20087800}; static int uio630[]={0x30000000}; #define qbdev(csr) (((csr) & 017777)-0x10000000) @@ -67,12 +71,11 @@ static int uda630[]={qbdev(0772150),qbdev(0760334)}; autoconf() { - int i = MACHID(mfpr(PR_SID)); - switch (i) { + switch (vax_cputype) { default: - printf("CPU type %d not supported by boot\n",i); + printf("CPU type %d not supported by boot\n",vax_cputype); asm("halt"); case VAX_8600: @@ -117,6 +120,11 @@ autoconf() uioaddr = uio630; tmsaddr = qbdev(0774500); break; + + case VAX_8200: + nbi = 1; + biaddr = bi8200; + bioaddr = bio8200; } } diff --git a/sys/arch/vax/boot/boot.c b/sys/arch/vax/boot/boot.c index 206db3dcf7a..7fd54220f49 100644 --- a/sys/arch/vax/boot/boot.c +++ b/sys/arch/vax/boot/boot.c @@ -1,4 +1,5 @@ -/* $NetBSD: boot.c,v 1.4 1995/09/16 15:54:20 ragge Exp $ */ +/* $OpenBSD: boot.c,v 1.3 1997/01/15 23:24:16 maja Exp $ */ +/* $NetBSD: boot.c,v 1.5 1996/08/02 11:21:49 ragge Exp $ */ /*- * Copyright (c) 1982, 1986 The Regents of the University of California. * All rights reserved. @@ -38,6 +39,8 @@ #include "sys/reboot.h" #include "lib/libsa/stand.h" +#define V750UCODE(x) ((x>>8)&255) + #include <a.out.h> /* @@ -49,8 +52,9 @@ char line[100]; volatile u_int devtype, bootdev; extern unsigned opendev; +extern unsigned *bootregs; -main() +Xmain() { register howto asm("r11"); register bdev asm("r10"); @@ -149,7 +153,7 @@ copyunix(howto, devtype, aio) hoppabort((x.a_entry&0x7fffffff),howto, devtype, esym); return; shread: - printf("Short read\n"); + printf("\nShort read\n\n"); return; } @@ -191,7 +195,7 @@ loadpcs() if (*cp == ')' || *cp == ':') break; if (*cp) { - strncpy(pcs, line, 99); + bcopy(line, pcs, 99); pcs[99] = 0; i = cp - line + 1; } else diff --git a/sys/arch/vax/boot/bootxx.c b/sys/arch/vax/boot/bootxx.c index 4a1b34f83d6..e7464b87273 100644 --- a/sys/arch/vax/boot/bootxx.c +++ b/sys/arch/vax/boot/bootxx.c @@ -1,4 +1,4 @@ -/* $NetBSD: bootxx.c,v 1.5 1996/02/17 18:23:21 ragge Exp $ */ +/* $NetBSD: bootxx.c,v 1.7 1996/08/02 11:21:53 ragge Exp $ */ /*- * Copyright (c) 1982, 1986 The Regents of the University of California. * All rights reserved. @@ -50,18 +50,21 @@ #include "../mba/mbareg.h" #include "../mba/hpreg.h" -#define NRSP 0 /* Kludge */ -#define NCMD 0 /* Kludge */ +#define NRSP 1 /* Kludge */ +#define NCMD 1 /* Kludge */ + #include "../uba/ubareg.h" #include "../uba/udareg.h" -#include "../vax/mscp.h" + +#include "../mscp/mscp.h" +#include "../mscp/mscpreg.h" #include "data.h" #include "vaxstand.h" #include <a.out.h> -int romstrategy(), romopen(); +int romstrategy(), romopen(); int command(int, int); /* @@ -71,39 +74,45 @@ int command(int, int); volatile u_int devtype, bootdev; unsigned opendev, boothowto, bootset; -int cpu_type, cpunumber; -unsigned *bootregs; -int is_750 = 0, is_mvax = 0, is_tmscp = 0; -struct rpb *rpb; -main() +extern unsigned *bootregs; +extern struct rpb *rpb; + +Xmain() { int io; + char *scbb; + char *new; char *hej = "/boot"; - cpu_type = mfpr(PR_SID); - cpunumber = (mfpr(PR_SID) >> 24) & 0xFF; - - switch (cpunumber) { + switch (vax_cputype) { case VAX_78032: case VAX_650: - { - int cpu_sie; /* sid-extension */ - - is_mvax = 1; - cpu_sie = *((int *) 0x20040004) >> 24; - cpu_type |= cpu_sie; - rpb = (struct rpb *)bootregs[11]; bootdev = rpb->devtyp; + /* + * now relocate rpb/bqo (which are used by ROM-routines) + */ + rpb = (void*)XXRPB; + bcopy ((void*)bootregs[11], rpb, 512); + rpb->rpb_base = rpb; + bqo = (void*)(512+(int)rpb); + bcopy ((void*)rpb->iovec, bqo, rpb->iovecsz); + rpb->iovec = (int)bqo; + bootregs[11] = (int)rpb; + break; - } + case VAX_8200: case VAX_750: - is_750 = 1; bootdev = bootregs[10]; break; + default: + printf("unknown cpu type %d\nRegister dump:\n", vax_cputype); + for (io = 0; io < 16; io++) + printf("r%d 0x%x\n", io, bootregs[io]); + asm("halt"); } bootset = getbootdev(); @@ -114,7 +123,7 @@ main() if (io >= 0 && io < SOPEN_MAX) { copyunix(io); } else { - printf("Boot failed. errno %d (%s)\n", errno, strerror(errno)); + printf("Boot failed, saerrno %d\n", errno); } } @@ -127,7 +136,7 @@ copyunix(aio) i = read(io, (char *) &x, sizeof(x)); if (i != sizeof(x) || N_BADMAG(x)) { - printf("Bad format: errno %s\n", strerror(errno)); + printf("Bad format\n"); return; } printf("%d", x.a_text); @@ -163,7 +172,7 @@ getbootdev() int i, major, adaptor, controller, unit, partition; - switch (cpunumber) { + switch (vax_cputype) { case VAX_78032: case VAX_650: adaptor = 0; @@ -172,6 +181,7 @@ getbootdev() break; + case VAX_8200: case VAX_750: controller = 0; /* XXX Actually massbuss can be on 3 ctlr's */ unit = bootregs[3]; @@ -181,23 +191,28 @@ getbootdev() partition = 0; switch (bootdev) { - case 0: /* massbuss boot */ + case BDEV_MBA: /* massbuss boot */ major = 0; /* hp / ... */ adaptor = (bootregs[1] & 0x6000) >> 17; break; - case 17: /* UDA50 boot */ + case BDEV_UDA: /* UDA50 boot */ major = 9; /* ra / mscp */ - if (is_750) + if (vax_cputype == VAX_750) adaptor = (bootregs[1] & 0x40000 ? 0 : 1); break; - case 18: /* TK50 boot */ + case BDEV_TK50: /* TK50 boot */ major = 15; /* tms / tmscp */ - is_tmscp = 1; /* use tape spec in mscp routines */ break; - case 64: + case 36: /* VS2000/KA410 ST506 disk */ + case 37: /* VS2000/KA410 SCSI tape */ + case 42: /* VS3100/76 SCSI-floppy(?) */ + major = 17; /* 17 is assigned to the ROM-drivers */ + break; + + case BDEV_CONSOLE: major = 8; break; @@ -224,7 +239,7 @@ struct disklabel lp; int part_off = 0; /* offset into partition holding /boot */ char io_buf[MAXBSIZE]; volatile struct uda { - struct uda1ca uda_ca; /* communications area */ + struct mscp_1ca uda_ca; /* communications area */ struct mscp uda_rsp; /* response packets */ struct mscp uda_cmd; /* command packets */ } uda; @@ -245,27 +260,27 @@ devopen(f, fname, file) /* * On uVAX we need to init [T]MSCP ctlr to be able to use it. */ - if (is_mvax) { + if (vax_cputype == VAX_78032 || vax_cputype == VAX_650) { switch (bootdev) { - case 17: /* MSCP */ - case 18: /* TMSCP */ + case BDEV_UDA: /* MSCP */ + case BDEV_TK50: /* TMSCP */ csr = (struct udadevice *)rpb->csrphy; csr->udaip = 0; /* Start init */ - while((csr->udasa & UDA_STEP1) == 0); + while((csr->udasa & MP_STEP1) == 0); csr->udasa = 0x8000; - while((csr->udasa & UDA_STEP2) == 0); + while((csr->udasa & MP_STEP2) == 0); csr->udasa = (short)(((u_int)&uda)&0xffff) + 8; - while((csr->udasa & UDA_STEP3) == 0); + while((csr->udasa & MP_STEP3) == 0); csr->udasa = 0x10; - while((csr->udasa & UDA_STEP4) == 0); + while((csr->udasa & MP_STEP4) == 0); csr->udasa = 0x0001; uda.uda_ca.ca_rspdsc = (int) &uda.uda_rsp.mscp_cmdref; uda.uda_ca.ca_cmddsc = (int) &uda.uda_cmd.mscp_cmdref; - if (is_tmscp) + if (bootdev == BDEV_TK50) uda.uda_cmd.mscp_vcid = 1; command(M_OP_SETCTLRC, 0); uda.uda_cmd.mscp_unit = rpb->unit; @@ -279,11 +294,10 @@ devopen(f, fname, file) * Actually disklabel is only needed when using hp disks, * but it doesn't hurt to always get it. */ - if (!is_tmscp) { + if ((bootdev != BDEV_TK50) && (bootdev != BDEV_CONSOLE)) { msg = getdisklabel((void *)LABELOFFSET + RELOC, &lp); - if (msg) { + if (msg) printf("getdisklabel: %s\n", msg); - } } return 0; } @@ -317,13 +331,13 @@ romstrategy(sc, func, dblk, size, buf, rsize) int block = dblk; int nsize = size; - switch (cpunumber) { + switch (vax_cputype) { case VAX_650: case VAX_78032: switch (bootdev) { - case 17: /* MSCP */ + case BDEV_UDA: /* MSCP */ uda.uda_cmd.mscp_seq.seq_lbn = dblk; uda.uda_cmd.mscp_seq.seq_bytecount = size; uda.uda_cmd.mscp_seq.seq_buffer = (int)buf; @@ -331,7 +345,7 @@ romstrategy(sc, func, dblk, size, buf, rsize) command(M_OP_READ, 0); break; - case 18: /* TMSCP */ + case BDEV_TK50: /* TMSCP */ if (dblk < curblock) { uda.uda_cmd.mscp_seq.seq_bytecount = curblock - dblk; @@ -351,16 +365,21 @@ romstrategy(sc, func, dblk, size, buf, rsize) command(M_OP_READ, 0); } break; + case 36: + case 37: + default: + romread_uvax(block, size, buf, bootregs); + break; } break; + case VAX_8200: case VAX_750: - if (bootdev) { + if (bootdev != BDEV_MBA) { while (size > 0) { - if ((read750(block, bootregs) & 0x01) == 0) - return 1; - + while ((read750(block, bootregs) & 0x01) == 0) + printf("Retrying read bn# %d\n", block); bcopy(0, buf, 512); size -= 512; buf += 512; diff --git a/sys/arch/vax/boot/conf.c b/sys/arch/vax/boot/conf.c index f516c4d2c3a..72b7f44faf0 100644 --- a/sys/arch/vax/boot/conf.c +++ b/sys/arch/vax/boot/conf.c @@ -1,4 +1,4 @@ -/* $NetBSD: conf.c,v 1.5 1996/02/17 18:23:18 ragge Exp $ */ +/* $NetBSD: conf.c,v 1.6 1996/08/02 11:21:56 ragge Exp $ */ /* * Copyright (c) 1994 Ludd, University of Lule}, Sweden. * All rights reserved. @@ -42,25 +42,33 @@ int raopen(), rastrategy(); int hpopen(), hpstrategy(); int ctuopen(), ctustrategy(); int tmscpopen(), tmscpstrategy(); +int romopen(), romstrategy(); +int mfmopen(), mfmstrategy(); +int sdopen(), sdstrategy(); + struct devsw devsw[]={ SADEV("hp",hpstrategy, hpopen, nullsys, noioctl), - SADEV("ht",nullsys, nodev, nullsys, noioctl), - SADEV("up",nullsys, nodev, nullsys, noioctl), - SADEV("hk",nullsys, nodev, nullsys, noioctl), + SADEV(0 ,nullsys, nodev, nullsys, noioctl), /* ht */ + SADEV(0 ,nullsys, nodev, nullsys, noioctl), /* up */ + SADEV(0 ,nullsys, nodev, nullsys, noioctl), /* hk */ SADEV( 0 ,nullsys, nodev, nullsys, noioctl), - SADEV("tm",nullsys, nodev, nullsys, noioctl), - SADEV("ts",nullsys, nodev, nullsys, noioctl), - SADEV("mt",nullsys, nodev, nullsys, noioctl), + SADEV(0 ,nullsys, nodev, nullsys, noioctl), /* tm */ + SADEV(0 ,nullsys, nodev, nullsys, noioctl), /* ts */ + SADEV(0 ,nullsys, nodev, nullsys, noioctl), /* mt */ SADEV("ctu",ctustrategy, ctuopen, nullsys, noioctl), SADEV("ra",rastrategy, raopen, nullsys, noioctl), - SADEV("ut",nullsys, nodev, nullsys, noioctl), - SADEV("id",nullsys, nodev, nullsys, noioctl), - SADEV("rx",nullsys, nodev, nullsys, noioctl), - SADEV("uu",nullsys, nodev, nullsys, noioctl), - SADEV("rl",nullsys, nodev, nullsys, noioctl), - SADEV("tms",tmscpstrategy, tmscpopen, nullsys, noioctl), - SADEV("kra",nullsys, nodev, nullsys, noioctl), + SADEV(0 ,nullsys, nodev, nullsys, noioctl), /* ut */ + SADEV(0 ,nullsys, nodev, nullsys, noioctl), /* id */ + SADEV(0 ,nullsys, nodev, nullsys, noioctl), /* rx */ + SADEV(0 ,nullsys, nodev, nullsys, noioctl), /* uu */ + SADEV(0 ,nullsys, nodev, nullsys, noioctl), /* rl */ + SADEV("mt",tmscpstrategy, tmscpopen, nullsys, noioctl), + SADEV(0 ,nullsys, nodev, nullsys, noioctl), /* crx */ + SADEV("rom",romstrategy, romopen, nullsys, noioctl), /* 17 */ + SADEV("mfm",mfmstrategy, mfmopen, nullsys, noioctl), /* 18 */ + SADEV("sd",sdstrategy, sdopen, nullsys, noioctl), /* 18 */ + SADEV("st",sdstrategy, sdopen, nullsys, noioctl), }; int ndevs = (sizeof(devsw)/sizeof(devsw[0])); diff --git a/sys/arch/vax/boot/consio.c b/sys/arch/vax/boot/consio.c index 39402cc1d44..94db46d0262 100644 --- a/sys/arch/vax/boot/consio.c +++ b/sys/arch/vax/boot/consio.c @@ -1,4 +1,4 @@ -/* $NetBSD: consio.c,v 1.3 1995/09/16 15:48:49 ragge Exp $ */ +/* $NetBSD: consio.c,v 1.4 1996/08/02 11:22:00 ragge Exp $ */ /* * Copyright (c) 1994 Ludd, University of Lule}, Sweden. * All rights reserved. @@ -38,24 +38,165 @@ #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 +"); + + diff --git a/sys/arch/vax/boot/copy.c b/sys/arch/vax/boot/copy.c index a67721d7458..c46ba5674e3 100644 --- a/sys/arch/vax/boot/copy.c +++ b/sys/arch/vax/boot/copy.c @@ -1,4 +1,4 @@ -/* $NetBSD: copy.c,v 1.2 1995/09/29 16:35:00 ragge Exp $ */ +/* $NetBSD: copy.c,v 1.3 1996/08/02 11:22:03 ragge Exp $ */ /*- * Copyright (c) 1982, 1986 The Regents of the University of California. * All rights reserved. @@ -38,6 +38,8 @@ #include "sys/reboot.h" #include "lib/libsa/stand.h" +#include "vaxstand.h" + #include <a.out.h> char line[100]; @@ -53,7 +55,7 @@ static int partlist[8]; int fill_buffer (void); int write_disk (void); -main() +Xmain() { int adapt, ctlr, unit, part; int res, i, loops; diff --git a/sys/arch/vax/boot/devopen.c b/sys/arch/vax/boot/devopen.c index d3468b427dd..8d58b778998 100644 --- a/sys/arch/vax/boot/devopen.c +++ b/sys/arch/vax/boot/devopen.c @@ -1,4 +1,4 @@ -/* $NetBSD: devopen.c,v 1.4 1996/03/16 11:02:28 ragge Exp $ */ +/* $NetBSD: devopen.c,v 1.6 1996/08/02 16:18:39 ragge Exp $ */ /*- * Copyright (c) 1993 John Brezak * All rights reserved. @@ -52,7 +52,7 @@ usage() { printf("\ Usage: device(adaptor, controller, drive, partition)file\n\ - <device><unit><partitonletter>:file\n\ + <device><unit><partitonletter>:file\n\ "); } @@ -62,15 +62,15 @@ devlookup(d,len) { struct devsw *dp = devsw; int i; - + for (i = 0; i < ndevs; i++, dp++) if (dp->dv_name && strncmp(dp->dv_name, d, len) == 0) - return(i); + return(i); printf("No such device - Configured devices are:\n"); for (dp = devsw, i = 0; i < ndevs; i++, dp++) if (dp->dv_name) - printf(" %s", dp->dv_name); + printf(" %s", dp->dv_name); printf("\n"); errno = ENODEV; return(-1); @@ -90,7 +90,7 @@ devparse(fname, dev, adapt, ctlr, unit, part, file) { int *argp, i; char *s, *args[4]; - + /* get device name and make lower case */ for(s = fname; *s && *s != '/' && *s != ':' && *s != '('; s++) if(isupper(*s)) @@ -117,19 +117,19 @@ devparse(fname, dev, adapt, ctlr, unit, part, file) *part = atoi(args[3]); break; case 3: - *ctlr = atoi(args[0]); - *unit = atoi(args[1]); - *part = atoi(args[2]); - break; + *ctlr = atoi(args[0]); + *unit = atoi(args[1]); + *part = atoi(args[2]); + break; case 2: - *unit = atoi(args[0]); - *part = atoi(args[1]); - break; + *unit = atoi(args[0]); + *part = atoi(args[1]); + break; case 1: - *part = atoi(args[0]); - break; + *part = atoi(args[0]); + break; case 0: - break; + break; } *file = ++s; @@ -142,25 +142,25 @@ devparse(fname, dev, adapt, ctlr, unit, part, file) /* lookup device and get index */ if ((*dev = devlookup(fname, s - fname)) < 0) - goto baddev; + goto baddev; /* isolate unit */ if ((*unit = atoi(s)) > sizeof(char)) - goto bad; + goto bad; for (; isdigit(*s); s++) ; /* translate partition */ if(!ispart(*s)) - goto bad; + goto bad; *part = *s++ - 'a'; if(*s != ':') - goto bad; + goto bad; *file = ++s; /* no device present */ - } else + } else *file = fname; /* return the remaining unparsed part as the file to boot */ @@ -176,8 +176,8 @@ bad: extern int bootdev; devopen(f, fname, file) - struct open_file *f; - const char *fname; + struct open_file *f; + const char *fname; char **file; { int n, error; @@ -190,12 +190,12 @@ devopen(f, fname, file) unit = B_UNIT(bootdev); part = B_PARTITION(bootdev); adapt = B_ADAPTOR(bootdev); - + if (error = devparse(fname, &dev, &adapt, &ctlr, &unit, &part, file)) return(error); - + dp = &devsw[dev]; - + if (!dp->dv_open) return(ENODEV); diff --git a/sys/arch/vax/boot/edlabel.c b/sys/arch/vax/boot/edlabel.c index 09844183bef..a5af6abe894 100644 --- a/sys/arch/vax/boot/edlabel.c +++ b/sys/arch/vax/boot/edlabel.c @@ -1,4 +1,4 @@ -/* $NetBSD: edlabel.c,v 1.1 1995/09/16 12:56:03 ragge Exp $ */ +/* $NetBSD: edlabel.c,v 1.2 1996/08/02 11:22:11 ragge Exp $ */ /* * Copyright (c) 1995 Ludd, University of Lule}, Sweden. * All rights reserved. @@ -88,7 +88,7 @@ setdefaultlabel() #define GETNUM2(out, num1, num) printf(out, num1, num);gets(store); \ if (*store) num = atoi(store); #define GETSTR(out, str) printf(out, str);gets(store); \ - if (*store) strcpy(str, store); + if (*store) bcopy(store, str, strlen(store)); #define FLAGS(out, flag) printf(out, lp->d_flags & flag?'y':'n');gets(store); \ if (*store == 'y' || *store == 'Y') lp->d_flags |= flag; \ else lp->d_flags &= ~flag; @@ -121,9 +121,11 @@ editlabel() GETNUM("drivedata 2? [%d] ", lp->d_drivedata[2]); GETNUM("drivedata 3? [%d] ", lp->d_drivedata[3]); GETNUM("drivedata 4? [%d] ", lp->d_drivedata[4]); + lp->d_secsize = 512; GETNUM("\nbytes/sector? [%d] ", lp->d_secsize); GETNUM("sectors/track? [%d] ", lp->d_nsectors); GETNUM("tracks/cylinder? [%d] ", lp->d_ntracks); + lp->d_secpercyl = lp->d_nsectors * lp->d_ntracks; GETNUM("sectors/cylinder? [%d] ", lp->d_secpercyl); GETNUM("cylinders? [%d] ", lp->d_ncylinders); lp->d_npartitions = MAXPARTITIONS; @@ -137,7 +139,7 @@ editlabel() int bootdev; void -main() +Xmain() { register bdev asm("r10"); diff --git a/sys/arch/vax/boot/init.c b/sys/arch/vax/boot/init.c deleted file mode 100644 index 94c7ad6276a..00000000000 --- a/sys/arch/vax/boot/init.c +++ /dev/null @@ -1,82 +0,0 @@ -/* $NetBSD: init.c,v 1.3 1995/09/16 13:34:21 ragge Exp $ */ -/* - * Copyright (c) 1995 Ludd, University of Lule}, Sweden. All rights reserved. - * - * This code is derived from software contributed to Ludd by Bertram Barth. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. 2. - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. 3. All advertising - * materials mentioning features or use of this software must display the - * following acknowledgement: This product includes software developed at - * Ludd, University of Lule}, Sweden and its contributors. 4. The name of the - * author may not be used to endorse or promote products derived from this - * software without specific prior written permission - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO - * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* All bugs are subject to removal without further notice */ - - - -#include "lib/libsa/stand.h" - -#include "../include/mtpr.h" /* mfpr(), mtpr() */ -#include "../include/sid.h" /* cpu_type, cpu_number */ - -#define NRSP 0 /* Kludge, must be done before udareg.h */ -#define NCMD 0 /* includes */ - -#include "../uba/udareg.h" /* struct udadevice */ - -#include "data.h" /* bootregs[], rpb, bqo */ - -struct rpb *rpb; -struct bqo *bqo; - -int is_750 = 0, is_mvax = 0; - -/* - * initdata() sets up data gotten from start routines, mostly for uVAX. - */ -int -initdata() -{ - int i, *tmp; - - cpu_type = mfpr(PR_SID); - cpunumber = (mfpr(PR_SID) >> 24) & 0xFF; - - switch (cpunumber) { - - case VAX_78032: - case VAX_650: - { - int cpu_sie; /* sid-extension */ - - is_mvax = 1; - cpu_sie = *((int *) 0x20040004) >> 24; - cpu_type |= cpu_sie; - - break; - } - case VAX_750: - is_750 = 1; - break; - } - return 0; -} diff --git a/sys/arch/vax/boot/ka410.h b/sys/arch/vax/boot/ka410.h new file mode 100644 index 00000000000..a022362c08f --- /dev/null +++ b/sys/arch/vax/boot/ka410.h @@ -0,0 +1,82 @@ +/* $NetBSD: ka410.h,v 1.1 1996/08/02 11:22:13 ragge Exp $ */ +/* + * Copyright (c) 1996 Ludd, University of Lule}, Sweden. + * All rights reserved. + * + * This code is derived from software contributed to Ludd by + * Bertram Barth. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed at Ludd, University of + * Lule}, Sweden and its contributors. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + + +/* + * interrupt request-, clear-, and mask register + */ +extern volatile unsigned char *ka410_intreq; +extern volatile unsigned char *ka410_intclr; +extern volatile unsigned char *ka410_intmsk; + +#define INTR_SR (1<<7) /* Serial line receiver or silo full */ +#define INTR_ST (1<<6) /* Serial line transmitter done */ +#define INTR_NP (1<<5) /* Network controller primary */ +#define INTR_NS (1<<4) /* Network controller secondary */ +#define INTR_VF (1<<3) /* Video end of frame */ +#define INTR_VS (1<<2) /* Video secondary */ +#define INTR_SC (1<<1) /* SCSI controller */ +#define INTR_DC (1<<0) /* Disk controller */ + +/* + * interrupt vector numbers + */ +#define IVEC_BASE 0x20040020 +#define IVEC_SR 0x000002C0 +#define IVEC_ST 0x000002C4 +#define IVEC_NP 0x00000250 +#define IVEC_NS 0x00000254 +#define IVEC_VF 0x00000244 +#define IVEC_VS 0x00000248 +#define IVEC_SC 0x000003F8 +#define IVEC_DC 0x000003FC + +/* + * Clock-Chip data in NVRAM + */ +#define KA410_CPMBX 0x200B0038 /* Console Mailbox (1 byte) */ +#define KA410_CPFLG 0x200B003C /* Console Program Flags (1 byte) */ +#define KA410_LK201_ID 0x200B0040 /* Keyboard Variation (1 byte) */ +#define KA410_CONS_ID 0x200B0044 /* Console Device Type (1 byte) */ +#define KA410_SCR 0x200B0048 /* Console Scratch RAM */ +#define KA410_TEMP 0x200B0058 /* Used by System Firmware */ +#define KA410_BAT_CHK 0x200B0088 /* Battery Check Data */ +#define KA410_BOOTDEV 0x200B0098 /* Default Boot Device (4 bytes) */ +#define KA410_BOOTFLG 0x200B00A8 /* Default Boot Flags (4 bytes) */ +#define KA410_SCRLEN 0x200B00B8 /* Number of pages of SCR (1 byte) */ +#define KA410_SCSIPORT 0x200B00BC /* Tape Controller Port Data */ +#define KA410_RESERVED 0x200B00C0 /* Reserved (16 bytes) */ + diff --git a/sys/arch/vax/boot/mfm.c b/sys/arch/vax/boot/mfm.c new file mode 100644 index 00000000000..bd271530ea4 --- /dev/null +++ b/sys/arch/vax/boot/mfm.c @@ -0,0 +1,640 @@ +/* $NetBSD: mfm.c,v 1.1 1996/08/02 11:22:16 ragge Exp $ */ +/* + * Copyright (c) 1996 Ludd, University of Lule}, Sweden. + * All rights reserved. + * + * This code is derived from software contributed to Ludd by + * Bertram Barth. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed at Ludd, University of + * Lule}, Sweden and its contributors. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * ToDo: + * + * - insert appropriate delays for diskette-drive where needed + * - allow more than one sector per diskette-read + * - check for and handle bad sectors + * - ??? + */ + +#include "sys/param.h" +#include "sys/reboot.h" +#include "sys/disklabel.h" + +#include "lib/libsa/stand.h" +#include "lib/libsa/ufs.h" + +#include "../include/pte.h" +#include "../include/sid.h" +#include "../include/mtpr.h" +#include "../include/reg.h" +#include "../include/rpb.h" + +#include "ka410.h" +#include "../vsa/hdc9224.h" + +#include "data.h" +#include "vaxstand.h" + +#define MAX_WAIT (1000*1000) /* # of loop-instructions in seconds */ + +struct mfm_softc { + int part; + int unit; +}; + +int mfmstrategy(), mfmopen(); +struct disklabel mfmlabel; +struct mfm_softc mfm_softc; +char io_buf[MAXBSIZE]; + +/* + * These should probably be somewhere else, but ka410 is the only + * one with mfm disks anyway... + */ +volatile unsigned char *ka410_intreq = (void*)0x2008000f; +volatile unsigned char *ka410_intclr = (void*)0x2008000f; +volatile unsigned char *ka410_intmsk = (void*)0x2008000c; + +static volatile struct hdc9224_DKCreg *dkc = (void *) 0x200c0000; +static volatile struct hdc9224_UDCreg sreg; /* input */ +static volatile struct hdc9224_UDCreg creg; /* output */ + +/* + * we have to wait 0.7 usec between two accesses to any of the + * dkc-registers, on a VS2000 with 1 MIPS, this is roughly one + * instruction. Thus the loop-overhead will be enough... + */ +static int +sreg_read() +{ + int i; + char *p; + + dkc->dkc_cmd = 0x40; /* set internal counter to zero */ + p = (void *) &sreg; + for (i = 0; i < 10; i++) + *p++ = dkc->dkc_reg; /* dkc_reg auto-increments */ +} + +static int +creg_write() +{ + int i; + char *p; + + dkc->dkc_cmd = 0x40; /* set internal counter to zero */ + p = (void *) &creg; + for (i = 0; i < 10; i++) + dkc->dkc_reg = *p++; /* dkc_reg auto-increments */ +} + +/* + * floppies are handled in a quite strange way by this controller... + * + * before reading/writing a sector from/to floppy, we use the SEEK/READ_ID + * command to place the head at the desired location. Then we wait some + * time before issueing the real command in order to let the drive become + * ready... + */ +int +mfm_rxprepare() +{ + int error; + + error = mfm_command(DKC_CMD_SEEKREADID | 0x04); /* step=1, verify=0 */ + if (error) { + printf("error while stepping to position %d/%d/%x. Retry...\n", + creg.udc_dsect, creg.udc_dhead, creg.udc_dcyl); + error = mfm_command(DKC_CMD_SEEKREADID | 0x04); + } + return error; +} + +int +mfm_rxselect(unit) + int unit; +{ + int error; + + /* + * bring "creg" in some known-to-work state and + * select the drive with the DRIVE SELECT command. + */ + creg.udc_dma7 = 0; + creg.udc_dma15 = 0; + creg.udc_dma23 = 0; + creg.udc_dsect = 1; /* sectors are numbered 1..15 !!! */ + creg.udc_dhead = 0; + creg.udc_dcyl = 0; + creg.udc_scnt = 0; + + creg.udc_rtcnt = UDC_RC_RX33READ; + creg.udc_mode = UDC_MD_RX33; + creg.udc_term = UDC_TC_FDD; + + /* + * this is ... + */ + error = mfm_command(DKC_CMD_DRSEL_RX33 | unit); + + if ((error != 0) || (sreg.udc_dstat & UDC_DS_READY == 0)) { + printf("\nfloppy-drive not ready (new floppy inserted?)\n\n"); + + creg.udc_rtcnt &= ~UDC_RC_INVRDY; /* clear INVRDY-flag */ + error = mfm_command(DKC_CMD_DRSEL_RX33 | unit); + if ((error != 0) || (sreg.udc_dstat & UDC_DS_READY == 0)) { + printf("diskette not ready(1): %x/%x\n", + error, sreg.udc_dstat); + printf("floppy-drive offline?\n"); + return (-1); + } + if (sreg.udc_dstat & UDC_DS_TRK00) + error = mfm_command(DKC_CMD_STEPIN_FDD); + else + error = mfm_command(DKC_CMD_STEPOUT_FDD); + + /* + * now ready should be 0, cause INVRDY is not set + * (retrying a command makes this fail...) + */ + if ((error != 0) || (sreg.udc_dstat & UDC_DS_READY == 1)) { + printf("diskette not ready(2): %x/%x\n", + error, sreg.udc_dstat); + } + creg.udc_rtcnt |= UDC_RC_INVRDY; + error = mfm_command(DKC_CMD_DRSEL_RX33 | unit); + + if ((error != 0) || (sreg.udc_dstat & UDC_DS_READY == 0)) { + printf("diskette not ready(3): %x/%x\n", + error, sreg.udc_dstat); + printf("no floppy inserted or floppy-door open\n"); + return (-1); + } + printf("floppy-drive reselected.\n"); + } + return (error); +} + +int +mfm_rdselect(unit) + int unit; +{ + int error; + + /* + * bring "creg" in some known-to-work state and + * select the drive with the DRIVE SELECT command. + */ + creg.udc_dma7 = 0; + creg.udc_dma15 = 0; + creg.udc_dma23 = 0; + creg.udc_dsect = 0; /* sectors are numbered 0..16 */ + creg.udc_dhead = 0; + creg.udc_dcyl = 0; + creg.udc_scnt = 0; + + creg.udc_rtcnt = UDC_RC_HDD_READ; + creg.udc_mode = UDC_MD_HDD; + creg.udc_term = UDC_TC_HDD; + + error = mfm_command(DKC_CMD_DRSEL_HDD | unit); + + return (error); +} + +static int mfm_retry = 0; + +int +mfm_command(cmd) + int cmd; +{ + int termcode, ready, i; + + creg_write(); /* write command-registers */ + *ka410_intclr = INTR_DC; + dkc->dkc_cmd = cmd; /* issue command */ + for (i = 0; i < MAX_WAIT; i++) { + if (*ka410_intreq & INTR_DC) /* wait for interrupt */ + break; + } + if ((*ka410_intreq & INTR_DC) == 0) + printf("timeout in mfm_command...\n"); + + sreg_read(); /* read status-registers */ + + if (dkc->dkc_stat == (DKC_ST_DONE | DKC_TC_SUCCESS)) + return (0); + + if (sreg.udc_cstat & UDC_CS_ECCERR) { + printf( +"\nspurious(?) ECC/CRC error at s%d/t%d/c%d [s%d/t%d/c%d(%d)]\n", + sreg.udc_csect, sreg.udc_chead, sreg.udc_ccyl, + creg.udc_dsect, creg.udc_dhead, creg.udc_dcyl,creg.udc_scnt); + if (sreg.udc_csect != creg.udc_dsect + creg.udc_scnt - 1) { + printf("DMA: %x %x %x [%x]\n", + sreg.udc_dma23, sreg.udc_dma15, + sreg.udc_dma7, 512 * (sreg.udc_csect - + creg.udc_dsect)); + creg.udc_scnt = creg.udc_scnt - + (sreg.udc_csect - creg.udc_dsect) - 1; + creg.udc_dsect = sreg.udc_csect + 1; + creg.udc_dma23 = sreg.udc_dma23; + creg.udc_dma15 = sreg.udc_dma15 + 2; + creg.udc_dma7 = 0; + printf("Retry starting from s%d/t%d/c%d (%d). ", + creg.udc_dsect, creg.udc_dhead, creg.udc_dcyl, + creg.udc_scnt); + } + goto retry; + } + termcode = (dkc->dkc_stat & DKC_ST_TERMCOD) >> 3; + ready = sreg.udc_dstat & UDC_DS_READY; + + printf("cmd:0x%x: termcode=0x%x, status=0x%x, cstat=0x%x, dstat=0x%x\n", + cmd, termcode, dkc->dkc_stat, sreg.udc_cstat, sreg.udc_dstat); + + if (dkc->dkc_stat & DKC_ST_BADSECT) + printf("bad sector found: s%d/t%d/c%d\n", creg.udc_dsect, + creg.udc_dhead, creg.udc_dcyl); +retry: + if ((mfm_retry == 0) && (sreg.udc_cstat & UDC_CS_RETREQ)) { + mfm_retry = 1; + printf("Retrying... "); + mfm_command(cmd); + printf("Retry done.\n"); + mfm_retry = 0; + } + return ((dkc->dkc_stat & DKC_ST_TERMCOD) >> 3); +} + +/* + * on-disk geometry block + */ +#define _aP __attribute__ ((packed)) /* force byte-alignment */ + +volatile struct mfm_xbn { + char mbz[10];/* 10 bytes of zero */ + long xbn_count _aP; /* number of XBNs */ + long dbn_count _aP; /* number of DBNs */ + long lbn_count _aP; /* number of LBNs (Logical-Block-Numbers) */ + long rbn_count _aP; /* number of RBNs (Replacement-Block-Numbers) */ + short nspt; /* number of sectors per track */ + short ntracks;/* number of tracks */ + short ncylinders; /* number of cylinders */ + short precomp;/* first cylinder for write precompensation */ + short reduced;/* first cylinder for reduced write current */ + short seek_rate; /* seek rate or zero for buffered + * seeks */ + short crc_eec;/* 0 if CRC is being used or 1 if ECC is + * being used */ + short rct; /* "replacement control table" (RCT) */ + short rct_ncopies; /* number of copies of the RCT */ + long media_id _aP; /* media identifier */ + short interleave; /* sector-to-sector interleave */ + short headskew; /* head-to-head skew */ + short cylskew;/* cylinder-to-cylinder skew */ + short gap0_size; /* size of GAP 0 in the MFM format */ + short gap1_size; /* size of GAP 1 in the MFM format */ + short gap2_size; /* size of GAP 2 in the MFM format */ + short gap3_size; /* size of GAP 3 in the MFM format */ + short sync_value; /* sync value used to start a track + * when formatting */ + char reserved[32]; /* reserved for use by the RQDX1/2/3 + * formatter */ + short serial_number; /* serial number */ + char fill[412]; /* Filler bytes to the end of the + * block */ + short checksum; /* checksum over the XBN */ +} mfm_xbn; + +display_xbn(p) + struct mfm_xbn *p; +{ + printf("**DiskData** XBNs: %d, DBNs: %d, LBNs: %d, RBNs: %d\n", + p->xbn_count, p->dbn_count, p->lbn_count, p->rbn_count); + printf("sect/track: %d, tracks: %d, cyl: %d, precomp/reduced: %d/%d\n", + p->nspt, p->ntracks, p->ncylinders, p->precomp, p->reduced); + printf("seek-rate: %d, crc/eec: %s, RCT: %d, RCT-copies: %d\n", + p->seek_rate, p->crc_eec ? "EEC" : "CRC", p->rct, p->rct_ncopies); + printf("media-ID: 0x%x, interleave: %d, headskew: %d, cylskew: %d\n", + &p->media_id, p->interleave, p->headskew, p->cylskew); + printf("gap0: %d, gap1: %d, gap2: %d, gap3: %d, sync-value: %d\n", + p->gap0_size, p->gap1_size, p->gap2_size, p->gap3_size, + p->sync_value); + printf("serial: %d, checksum: %d, size: %d, reserved: %32c\n", + p->serial_number, p->checksum, sizeof(*p), p->reserved); +} + +mfmopen(f, adapt, ctlr, unit, part) + struct open_file *f; + int ctlr, unit, part; +{ + char *msg; + struct disklabel *lp = &mfmlabel; + volatile struct mfm_softc *msc = &mfm_softc; + int i, err; + + bzero(lp, sizeof(struct disklabel)); + msc->unit = unit; + msc->part = part; + + err = mfmstrategy(msc, F_READ, LABELSECTOR, DEV_BSIZE, io_buf, &i); + if (err) { + printf("reading disklabel: %s\n", strerror(err)); + return 0; + } + msg = getdisklabel(io_buf + LABELOFFSET, lp); + if (msg) + printf("getdisklabel: %s\n", msg); + + f->f_devdata = (void *) msc; + + { + int k; + unsigned char *ucp; + struct mfm_xbn *xp; + + /* mfmstrategy(msc, F_READ, -16, 8192, io_buf, &i); */ + mfmstrategy(msc, F_READ, -16, 512, io_buf, &i); + printf("dumping raw disk-block #0:\n"); + ucp = io_buf; + for (k = 0; k < 128; k++) { + if (ucp[k] < 0x10) + printf("0"); + printf("%x ", ucp[k]); + if (k % 8 == 7) + printf(" "); + if (k % 16 == 15) + printf("\n"); + } + printf("\n"); + + xp = (void *) io_buf; + display_xbn(xp); + printf("\n"); + + } + + if (unit == 2) { /* floppy! */ + if (lp->d_ntracks != 2) { + printf("changing number of tracks from %d to %d.\n", + lp->d_ntracks, 2); + lp->d_ntracks = 2; + } + } else { /* hard-disk */ + unsigned short *usp = (void *) io_buf; + printf("label says: s/t/c = %d/%d/%d\n", + lp->d_nsectors, lp->d_ntracks, lp->d_ncylinders); + + if (lp->d_nsectors != usp[13]) { + printf("changing number of sectors from %d to %d.\n", + lp->d_nsectors, usp[13]); + lp->d_nsectors = usp[13]; + } + if (lp->d_ntracks != usp[14]) { + printf("changing number of heads/tracks from %d to %d.\n", + lp->d_ntracks, usp[14]); + lp->d_ntracks = usp[14]; + } + if (lp->d_ncylinders != usp[15]) { + printf("changing number of cylinders from %d to %d.\n", + lp->d_ncylinders, usp[15]); + lp->d_ncylinders = usp[15]; + } + lp->d_secpercyl = lp->d_nsectors * lp->d_ntracks; + } + + return (0); +} + +mfm_rxstrategy(msc, func, dblk, size, buf, rsize) + struct mfm_softc *msc; + int func; + daddr_t dblk; + char *buf; + int size, *rsize; +{ + struct disklabel *lp; + int block, sect, head, cyl, scount, i, cmd, res, sval; + + lp = &mfmlabel; + block = (dblk < 0 ? 0 : dblk + lp->d_partitions[msc->part].p_offset); + + mfm_rxselect(msc->unit); + + /* + * if label is empty, assume RX33 + */ + if (lp->d_nsectors == 0) + lp->d_nsectors = 15; + if (lp->d_ntracks == 0) + lp->d_ntracks = 2; + if (lp->d_secpercyl == 0) + lp->d_secpercyl = 30; + + bzero((void *) 0x200D0000, size); + scount = size / 512; + + while (scount) { + /* + * prepare drive/operation parameter + */ + cyl = block / lp->d_secpercyl; + sect = block % lp->d_secpercyl; + head = sect / lp->d_nsectors; + sect = sect % lp->d_nsectors; + + /* + * *rsize = 512; /* one sector after the other + * ... + */ + *rsize = 512 * min(scount, lp->d_nsectors - sect); + + /* + * now initialize the register values ... + */ + creg.udc_dma7 = 0; + creg.udc_dma15 = 0; + creg.udc_dma23 = 0; + + creg.udc_dsect = sect + 1; /* sectors are numbered 1..15 + * !!! */ + head |= (cyl >> 4) & 0x70; + creg.udc_dhead = head; + creg.udc_dcyl = cyl; + + creg.udc_scnt = *rsize / 512; + + if (func == F_WRITE) { + creg.udc_rtcnt = UDC_RC_RX33WRT; + creg.udc_mode = UDC_MD_RX33; + creg.udc_term = UDC_TC_FDD; + + mfm_rxprepare(); + /* copy from buf */ + bcopy(buf, (void *) 0x200D0000, *rsize); + res = mfm_command(DKC_CMD_WRITE_RX33); + } else { + creg.udc_rtcnt = UDC_RC_RX33READ; + creg.udc_mode = UDC_MD_RX33; + creg.udc_term = UDC_TC_FDD; + + mfm_rxprepare(); + /* clear disk buffer */ + bzero((void *) 0x200D0000, *rsize); + res = mfm_command(DKC_CMD_READ_RX33); + /* copy to buf */ + bcopy((void *) 0x200D0000, buf, *rsize); + } + + scount -= *rsize / 512; + block += *rsize / 512; + buf += *rsize; + } + + *rsize = size; + return 0; +} + +mfm_rdstrategy(msc, func, dblk, size, buf, rsize) + struct mfm_softc *msc; + int func; + daddr_t dblk; + char *buf; + int size, *rsize; +{ + struct disklabel *lp; + int block, sect, head, cyl, scount, i, cmd, res, sval; + + lp = &mfmlabel; + block = (dblk < 0 ? 0 : dblk + lp->d_partitions[msc->part].p_offset); + + /* + * if label is empty, assume RD32 (XXX this must go away!!!) + */ + if (lp->d_nsectors == 0) + lp->d_nsectors = 17; + if (lp->d_ntracks == 0) + lp->d_ntracks = 6; + if (lp->d_secpercyl == 0) + lp->d_secpercyl = 102; + + mfm_rdselect(msc->unit); + + bzero((void *) 0x200D0000, size); + scount = size / 512; + + while (scount) { + /* + * prepare drive/operation parameter + */ + cyl = block / lp->d_secpercyl; + sect = block % lp->d_secpercyl; + head = sect / lp->d_nsectors; + sect = sect % lp->d_nsectors; + + if (dblk < 0) { + printf("using raw diskblock-data!\n"); + printf("block %d, dblk %d ==> cyl %d, head %d, sect %d\n", + block, dblk, cyl, sect, head); + } else + cyl += 1; /* first cylinder is reserved for + * controller! */ + + *rsize = 512 * min(scount, lp->d_nsectors - sect); + /* + * now re-initialize the register values ... + */ + creg.udc_dma7 = 0; + creg.udc_dma15 = 0; + creg.udc_dma23 = 0; + + creg.udc_dsect = sect; + head |= (cyl >> 4) & 0x70; + creg.udc_dhead = head; + creg.udc_dcyl = cyl; + + creg.udc_scnt = *rsize / 512; + + if (func == F_WRITE) { + creg.udc_rtcnt = UDC_RC_HDD_WRT; + creg.udc_mode = UDC_MD_HDD; + creg.udc_term = UDC_TC_HDD; + cmd = DKC_CMD_WRITE_HDD; + + bcopy(buf, (void *) 0x200D0000, *rsize); + res = mfm_command(cmd); + } else { + creg.udc_rtcnt = UDC_RC_HDD_READ; + creg.udc_mode = UDC_MD_HDD; + creg.udc_term = UDC_TC_HDD; + cmd = DKC_CMD_READ_HDD; + + bzero((void *) 0x200D0000, *rsize); + res = mfm_command(cmd); + bcopy((void *) 0x200D0000, buf, *rsize); + } + + scount -= *rsize / 512; + block += *rsize / 512; + buf += *rsize; + } + + /* + * unselect the drive ... + */ + mfm_command(DKC_CMD_DRDESELECT); + + *rsize = size; + return 0; +} + +int +mfmstrategy(msc, func, dblk, size, buf, rsize) + struct mfm_softc *msc; + int func; + daddr_t dblk; + char *buf; + int size, *rsize; +{ + int res = -1; + + switch (msc->unit) { + case 0: + case 1: + res = mfm_rdstrategy(msc, func, dblk, size, buf, rsize); + break; + case 2: + res = mfm_rxstrategy(msc, func, dblk, size, buf, rsize); + break; + default: + printf("invalid unit %d in mfmstrategy()\n"); + } + return (res); +} diff --git a/sys/arch/vax/boot/ra.c b/sys/arch/vax/boot/ra.c index 43e368fe098..722b19d99cd 100644 --- a/sys/arch/vax/boot/ra.c +++ b/sys/arch/vax/boot/ra.c @@ -1,4 +1,4 @@ -/* $NetBSD: ra.c,v 1.4 1996/02/17 18:23:23 ragge Exp $ */ +/* $NetBSD: ra.c,v 1.5 1996/08/02 11:22:18 ragge Exp $ */ /* * Copyright (c) 1995 Ludd, University of Lule}, Sweden. * All rights reserved. @@ -31,8 +31,8 @@ /* All bugs are subject to removal without further notice */ -#define NRSP 0 /* Kludge */ -#define NCMD 0 /* Kludge */ +#define NRSP 1 /* Kludge */ +#define NCMD 1 /* Kludge */ #include "sys/param.h" #include "sys/disklabel.h" @@ -41,9 +41,16 @@ #include "../include/pte.h" #include "../include/macros.h" +#include "../include/sid.h" + #include "../uba/ubareg.h" #include "../uba/udareg.h" -#include "../vax/mscp.h" + +#include "../mscp/mscp.h" +#include "../mscp/mscpreg.h" + +#include "../bi/bireg.h" +#include "../bi/kdbreg.h" #include "vaxstand.h" @@ -62,10 +69,13 @@ struct ra_softc { int ubaddr; int part; int unit; + unsigned short *ra_ip; + unsigned short *ra_sa; + unsigned short *ra_sw; }; volatile struct uda { - struct uda1ca uda_ca; /* communications area */ + struct mscp_1ca uda_ca; /* communications area */ struct mscp uda_rsp; /* response packets */ struct mscp uda_cmd; /* command packets */ } uda; @@ -81,53 +91,84 @@ raopen(f, adapt, ctlr, unit, part) int ctlr, unit, part; { char *msg; - struct disklabel *lp=&ralabel; - volatile struct ra_softc *ra=&ra_softc; - volatile struct uba_regs *mr=(void *)ubaaddr[adapt]; + struct disklabel *lp = &ralabel; + volatile struct ra_softc *ra = &ra_softc; + volatile struct uba_regs *mr = (void *)ubaaddr[adapt]; volatile u_int *nisse; - unsigned short johan; + unsigned short johan, johan2; int i,err; - if(adapt>nuba) return(EADAPT); - if(ctlr>nuda) return(ECTLR); bzero(lp, sizeof(struct disklabel)); - ra->udaddr=uioaddr[adapt]+udaaddr[ctlr]; - ra->ubaddr=(int)mr; - ra->unit=unit; + ra->unit = unit; ra->part = part; - udacsr=(void*)ra->udaddr; - nisse=(u_int *)&mr->uba_map[0]; - nisse[494]=PG_V|(((u_int)&uda)>>9); - nisse[495]=nisse[494]+1; - ubauda=(void*)0x3dc00+(((u_int)(&uda))&0x1ff); + if (vax_cputype != VAX_8200) { + if (adapt > nuba) + return(EADAPT); + if (ctlr > nuda) + return(ECTLR); + nisse = (u_int *)&mr->uba_map[0]; + nisse[494] = PG_V | (((u_int)&uda) >> 9); + nisse[495] = nisse[494] + 1; + udacsr = (void*)uioaddr[adapt] + udaaddr[ctlr]; + ubauda = (void*)0x3dc00 + (((u_int)(&uda))&0x1ff); + johan = (((u_int)ubauda) & 0xffff) + 8; + johan2 = 3; + ra->ra_ip = (short *)&udacsr->udaip; + ra->ra_sa = ra->ra_sw = (short *)&udacsr->udasa; + ra->udaddr = uioaddr[adapt] + udaaddr[ctlr]; + ra->ubaddr = (int)mr; + *ra->ra_ip = 0; /* Start init */ + } else { + struct bi_node *bi = (void *)biaddr[adapt]; + struct kdb_regs *kb = (void *)&bi[ctlr]; + volatile int i = 10000; + + ra->ra_ip = &kb->kdb_ip; + ra->ra_sa = &kb->kdb_sa; + ra->ra_sw = &kb->kdb_sw; + johan = ((u_int)&uda.uda_ca.ca_rspdsc) & 0xffff; + johan2 = (((u_int)&uda.uda_ca.ca_rspdsc) & 0xffff0000) >> 16; + kb->kdb_bi.bi_csr |= BICSR_NRST; + while (i--) /* Need delay??? */ + ; + kb->kdb_bi.bi_ber = ~(BIBER_MBZ|BIBER_NMR|BIBER_UPEN);/* ??? */ + ubauda = &uda; + } + /* Init of this uda */ - udacsr->udaip=0; /* Start init */ - while((udacsr->udasa&UDA_STEP1) == 0); - udacsr->udasa=0x8000; - while((udacsr->udasa&UDA_STEP2) == 0); - johan=(((u_int)ubauda)&0xffff)+8; - udacsr->udasa=johan; - while((udacsr->udasa&UDA_STEP3) == 0); - udacsr->udasa=3; - while((udacsr->udasa&UDA_STEP4) == 0); - udacsr->udasa=0x0001; - uda.uda_ca.ca_rspdsc=(int)&ubauda->uda_rsp.mscp_cmdref; - uda.uda_ca.ca_cmddsc=(int)&ubauda->uda_cmd.mscp_cmdref; + while ((*ra->ra_sa & MP_STEP1) == 0) + ; + + *ra->ra_sw = 0x8000; + while ((*ra->ra_sa & MP_STEP2) == 0) + ; + + *ra->ra_sw = johan; + while ((*ra->ra_sa & MP_STEP3) == 0) + ; + + *ra->ra_sw = johan2; + while ((*ra->ra_sa & MP_STEP4) == 0) + ; + + *ra->ra_sw = 0x0001; + uda.uda_ca.ca_rspdsc = (int)&ubauda->uda_rsp.mscp_cmdref; + uda.uda_ca.ca_cmddsc = (int)&ubauda->uda_cmd.mscp_cmdref; + command(M_OP_SETCTLRC); - uda.uda_cmd.mscp_unit=ra->unit; + uda.uda_cmd.mscp_unit = ra->unit; command(M_OP_ONLINE); - err=rastrategy(ra,F_READ, LABELSECTOR, DEV_BSIZE, io_buf, &i); + err = rastrategy(ra,F_READ, LABELSECTOR, DEV_BSIZE, io_buf, &i); if(err){ printf("reading disklabel: %s\n",strerror(err)); return 0; } - msg=getdisklabel(io_buf+LABELOFFSET, lp); - if(msg) { - printf("getdisklabel: %s\n",msg); - } - f->f_devdata=(void *)ra; + msg = getdisklabel(io_buf+LABELOFFSET, lp); + if (msg) + printf("getdisklabel: %s\n", msg); + f->f_devdata = (void *)ra; return(0); } @@ -136,13 +177,14 @@ command(cmd) { volatile int hej; - uda.uda_cmd.mscp_opcode=cmd; - uda.uda_cmd.mscp_msglen=MSCP_MSGLEN; - uda.uda_rsp.mscp_msglen=MSCP_MSGLEN; + uda.uda_cmd.mscp_opcode = cmd; + uda.uda_cmd.mscp_msglen = MSCP_MSGLEN; + uda.uda_rsp.mscp_msglen = MSCP_MSGLEN; uda.uda_ca.ca_rspdsc |= MSCP_OWN|MSCP_INT; uda.uda_ca.ca_cmddsc |= MSCP_OWN|MSCP_INT; - hej=udacsr->udaip; - while(uda.uda_ca.ca_rspdsc<0); + hej = *ra_softc.ra_ip; + while(uda.uda_ca.ca_rspdsc<0) + ; } @@ -161,20 +203,23 @@ rastrategy(ra, func, dblk, size, buf, rsize) volatile int hej; - ur = (void *)ra->ubaddr; - udadev = (void*)ra->udaddr; - ptmapp = (u_int *)&ur->uba_map[0]; - lp = &ralabel; + if (vax_cputype != VAX_8200) { + ur = (void *)ra->ubaddr; + udadev = (void*)ra->udaddr; + ptmapp = (u_int *)&ur->uba_map[0]; - pfnum = (u_int)buf >> PGSHIFT; + pfnum = (u_int)buf >> PGSHIFT; - for(mapnr = 0, nsize = size; (nsize + NBPG) > 0; nsize -= NBPG) - ptmapp[mapnr++] = PG_V | pfnum++; + for(mapnr = 0, nsize = size; (nsize + NBPG) > 0; nsize -= NBPG) + ptmapp[mapnr++] = PG_V | pfnum++; + uda.uda_cmd.mscp_seq.seq_buffer = ((u_int)buf) & 0x1ff; + } else + uda.uda_cmd.mscp_seq.seq_buffer = ((u_int)buf); + lp = &ralabel; uda.uda_cmd.mscp_seq.seq_lbn = dblk + lp->d_partitions[ra->part].p_offset; uda.uda_cmd.mscp_seq.seq_bytecount = size; - uda.uda_cmd.mscp_seq.seq_buffer = ((u_int)buf) & 0x1ff; uda.uda_cmd.mscp_unit = ra->unit; if (func == F_WRITE) command(M_OP_WRITE); diff --git a/sys/arch/vax/boot/rom.c b/sys/arch/vax/boot/rom.c new file mode 100644 index 00000000000..f299f506350 --- /dev/null +++ b/sys/arch/vax/boot/rom.c @@ -0,0 +1,123 @@ +/* $NetBSD: rom.c,v 1.1 1996/08/02 11:22:21 ragge Exp $ */ +/* + * Copyright (c) 1996 Ludd, University of Lule}, Sweden. + * All rights reserved. + * + * This code is derived from software contributed to Ludd by + * Bertram Barth. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed at Ludd, University of + * Lule}, Sweden and its contributors. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "sys/param.h" +#include "sys/reboot.h" +#include "sys/disklabel.h" + +#include "lib/libsa/stand.h" +#include "lib/libsa/ufs.h" + +#include "../include/pte.h" +#include "../include/sid.h" +#include "../include/mtpr.h" +#include "../include/reg.h" +#include "../include/rpb.h" + +#include "data.h" +#include "vaxstand.h" + +extern unsigned *bootregs; +extern struct rpb *rpb; + +struct rom_softc { + int part; + int unit; +}; + +int romstrategy(), romopen(); +struct disklabel romlabel; +struct rom_softc rom_softc; +char io_buf[MAXBSIZE]; + +romopen(f, adapt, ctlr, unit, part) + struct open_file *f; + int ctlr, unit, part; +{ + char *msg; + struct disklabel *lp = &romlabel; + volatile struct rom_softc *rsc = &rom_softc; + int i,err; + + bootregs[11] = XXRPB; + rpb = (void*)XXRPB; + bqo = (void*)rpb->iovec; + + if (rpb->unit > 0 && (rpb->unit % 100) == 0) { + printf ("changing rpb->unit from %d ", rpb->unit); + rpb->unit /= 100; + printf ("to %d\n", rpb->unit); + } + + bzero(lp, sizeof(struct disklabel)); + rsc->unit = unit; + rsc->part = part; + + err = romstrategy(rsc, F_READ, LABELSECTOR, DEV_BSIZE, io_buf, &i); + if (err) { + printf("reading disklabel: %s\n",strerror(err)); + return 0; + } + msg = getdisklabel(io_buf+LABELOFFSET, lp); + if (msg) + printf("getdisklabel: %s\n",msg); + f->f_devdata = (void*)rsc; + return(0); +} + +romstrategy (rsc, func, dblk, size, buf, rsize) + struct rom_softc *rsc; + int func; + daddr_t dblk; + char *buf; + int size, *rsize; +{ + struct disklabel *lp; + int block; + + lp = &romlabel; + block = dblk + lp->d_partitions[rsc->part].p_offset; + if (rsc->unit >= 0 && rsc->unit < 10) + rpb->unit = rsc->unit; + + if (func == F_WRITE) + romwrite_uvax(block, size, buf, bootregs); + else + romread_uvax(block, size, buf, bootregs); + + *rsize = size; + return 0; +} + diff --git a/sys/arch/vax/boot/romread.s b/sys/arch/vax/boot/romread.s index 966280792fb..ff893c4b6d9 100644 --- a/sys/arch/vax/boot/romread.s +++ b/sys/arch/vax/boot/romread.s @@ -1,4 +1,4 @@ -/* $NetBSD: romread.s,v 1.3 1995/09/16 16:20:18 ragge Exp $ */ +/* $NetBSD: romread.s,v 1.4 1996/08/02 11:22:24 ragge Exp $ */ /* * Copyright (c) 1995 Ludd, University of Lule}, Sweden. * All rights reserved. @@ -40,20 +40,6 @@ #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) */ ENTRY(read750, 0xFFE) @@ -72,9 +58,9 @@ ENTRY(read750, 0xFFE) ret /* - * bulkread630 (int lbn, int size, void *buf, int *regs) + * romread_uvax (int lbn, int size, void *buf, int *regs) */ -ENTRY(bulkread630, 0xFFE) +ENTRY(romread_uvax, 0xFFE) movl 16(ap), r11 # array of bootregs movl 44(r11), r11 # restore boot-contents of r11 (rpb) movl 52(r11), r7 # load iovec/bqo into r7 @@ -87,3 +73,21 @@ ENTRY(bulkread630, 0xFFE) pushl 12(ap) # buffer-address calls $6, (r6) # call the qio-routine ret # r0 holds the result + +/* + * romwrite_uvax (int lbn, int size, void *buf, int *regs) + */ +ENTRY(romwrite_uvax, 0xFFE) + movl 16(ap), r11 # array of bootregs + movl 44(r11), r11 # restore boot-contents of r11 (rpb) + movl 52(r11), r7 # load iovec/bqo into r7 + addl3 (r7), r7, r6 # load qio into r6 + pushl r11 # base of rpb + pushl $0 # virtual-flag + pushl $32 # write-logical-block + pushl 4(ap) # lbn to start reading + pushl 8(ap) # number of bytes to read + pushl 12(ap) # buffer-address + calls $6, (r6) # call the qio-routine + ret # r0 holds the result + diff --git a/sys/arch/vax/boot/samachdep.h b/sys/arch/vax/boot/samachdep.h new file mode 100644 index 00000000000..829a17d2b49 --- /dev/null +++ b/sys/arch/vax/boot/samachdep.h @@ -0,0 +1,42 @@ +/* $NetBSD: samachdep.h,v 1.1 1996/08/02 11:22:28 ragge Exp $ */ + +/* + * Copyright (c) 1982, 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)samachdep.h 8.1 (Berkeley) 6/10/93 + */ + +#define NSCSI 1 +#define NSD 8 + +extern int howto; +extern unsigned int bootdev; diff --git a/sys/arch/vax/boot/scsi_hi.c b/sys/arch/vax/boot/scsi_hi.c new file mode 100644 index 00000000000..0102123cc32 --- /dev/null +++ b/sys/arch/vax/boot/scsi_hi.c @@ -0,0 +1,297 @@ +/* $NetBSD: scsi_hi.c,v 1.1 1996/08/02 11:22:31 ragge Exp $ */ + +/**************************************************************************** + * NS32K Monitor SCSI high-level driver + * Bruce Culbertson + * 8 March 1990 + * (This source is public domain source) + * + * There are three monitor SCSI commands. "Read" and "write" I think are + * fairly self explanatory once you read the help messages. They, in fact, + * execute the "extended read", "extended write", and "request sense" + * commands from the SCSI standard. + * + * "Raw" lets you execute any SCSI command but you need a SCSI reference to + * know what the commands are and what their formats are. The SCSI + * standard specifies that there are six buffers which, for example, hold a + * SCSI command or are the source or destination for data. You provide + * "raw" with an array of pointers to the six buffers. Using "edit", you + * can enter a SCSI command somewhere in memory and you can create the + * array of pointers. The array must actually be eight entries long; two + * entries are not used. By typing "raw <array address>", the SCSI command + * is executed. + * + * By the way, "read", "write", and "raw" talk only to the DP8490 SCSI + * controller. I have not had time to read the Adaptec data sheet and + * write a driver for it. + ****************************************************************************/ +#include "so.h" + +#define OK 0 +#define NOT_OK OK+1 +#define PRIVATE +#define PUBLIC +#define U8 unsigned char + +long scsiAdr = DEFAULT_SCSI_ADR, /* default SCSI address */ + scsiLun = DEFAULT_SCSI_LUN; + +struct cmd_desc { /* SCSI command description */ + const U8 *cmd; /* command string */ + const U8 *odata; /* data to output, if any */ + const struct cmd_desc *chain; /* next command */ +}; + +struct drive { /* SCSI drive description */ + U8 adr, lun; /* SCSI address and LUN */ + U8 flags; /* drive characteristics */ + U8 stat; /* drive state */ + const struct cmd_desc *init; /* list of initialize commands */ +}; +/* for drive.flags */ +#define EXTENDED_RDWR 1 /* device does extended read, write */ +#define EXTENDED_SENSE 2 /* device does extended sense */ +/* for drive.stat */ +#define INITIALIZED 1 /* device is initialized */ + +PRIVATE struct drive drive_tbl[] = { +#if 1 + {0, 0, 0, 1, 0}, + {1, 0, 0, 1, 0}, + {2, 0, 0, 1, 0}, + {3, 0, 0, 1, 0}, + {4, 0, 0, 1, 0}, + {5, 0, 0, 1, 0}, + {6, 0, 0, 1, 0}, + {7, 0, 0, 1, 0}, +#else + {0, 0, EXTENDED_RDWR | EXTENDED_SENSE, 1, 0}, + {1, 0, EXTENDED_RDWR | EXTENDED_SENSE, 1, 0}, + {2, 0, EXTENDED_RDWR | EXTENDED_SENSE, 1, 0}, + {3, 0, EXTENDED_RDWR | EXTENDED_SENSE, 1, 0}, + {4, 0, EXTENDED_RDWR | EXTENDED_SENSE, 1, 0}, + {5, 0, EXTENDED_RDWR | EXTENDED_SENSE, 1, 0}, + {6, 0, EXTENDED_RDWR | EXTENDED_SENSE, 1, 0}, + {7, 0, EXTENDED_RDWR | EXTENDED_SENSE, 1, 0}, +#endif +}; +#define DRV_TBL_SZ (sizeof (drive_tbl) / sizeof (struct drive)) + +/* Round up to multiple of four since SCSI transfers are always multiples + * of four bytes. + */ +#define CMD_LEN 12 /* longest SCSI command */ +#define SENSE_LEN 24 /* extended sense length */ +#define MSG_LEN 4 +#define STAT_LEN 4 + +#define MAX_SCSI_RETRIES 6 +#define CMD_IX 2 +#define CMD_SENSE 0x03 +#define CMD_READ 0x08 +#define CMD_WRITE 0x0a +#define CMD_XREAD 0x28 +#define CMD_XWRITE 0x2a +PRIVATE U8 cmd_buf[CMD_LEN]; + +#define SENSE_KEY 2 +#define NO_SENSE 0 +#define RECOVERY_ERR 1 +#define UNIT_ATTN 6 +#define ADD_SENSE_CODE 12 +#define SENSE_RST 0x29 +PRIVATE U8 sense_buf[SENSE_LEN]; + +#define CHECK_CONDITION 2 +#define STAT_IX 3 +#define STAT_MASK 0x1f +PRIVATE U8 stat_buf[STAT_LEN]; +#define IMSG_IX 7 +PRIVATE U8 msg_buf[MSG_LEN]; + +#define ODATA_IX 0 +#define IDATA_IX 1 +PRIVATE struct scsi_args scsi_args; + +/*===========================================================================* + * sc_rdwt * + *===========================================================================*/ +/* Carry out a read or write request for the SCSI disk. */ +PRIVATE int +sc_rdwt(op, block, ram_adr, len, sc_adr, lun) +long block, ram_adr, len, sc_adr, lun; +{ + int retries, ret; + U8 *p; + struct drive *dp; + + printf ("sc_rdwt: op %x, block %d, ram %x, len %d, sc_adr %d, lun %d\n", + op, block, ram_adr, len, sc_adr, lun); + + /* get drive characteristics */ + for (dp = drive_tbl; dp < drive_tbl + DRV_TBL_SZ - 1; ++dp) + if (dp->adr == sc_adr && dp->lun == lun) break; + if (dp == drive_tbl + DRV_TBL_SZ - 1) { + dp->adr = sc_adr; /* have default, set adr, lun */ + dp->lun = lun; + } + for (retries = 0; retries < MAX_SCSI_RETRIES; ++retries) { + if (dp->init && !(dp->stat & INITIALIZED)) + if (OK != sc_initialize (dp)) { + printf("SCSI cannot initialize device\n"); + return NOT_OK; + } + p = cmd_buf; /* build SCSI command */ + if (dp->flags & EXTENDED_RDWR) { /* use extended commands */ + *p++ = (op == DISK_READ)? CMD_XREAD: CMD_XWRITE; + *p++ = lun << 5; + *p++ = (block >> 24) & 0xff; + *p++ = (block >> 16) & 0xff; + *p++ = (block >> 8) & 0xff; + *p++ = (block >> 0) & 0xff; + *p++ = 0; + *p++ = (len >> 8) & 0xff; + *p++ = (len >> 0) & 0xff; + *p = 0; + } else { /* use short (SASI) commands */ + *p++ = (op == DISK_READ)? CMD_READ: CMD_WRITE; + *p++ = (lun << 5) | ((block >> 16) & 0x1f); + *p++ = (block >> 8) & 0xff; + *p++ = (block >> 0) & 0xff; + *p++ = len; + *p = 0; + } + if (op == DISK_READ) + ret = exec_scsi_hi (cmd_buf, (U8 *)ram_adr, (U8 *)0, dp); + else + ret = exec_scsi_hi (cmd_buf, (U8 *)0, (U8 *)ram_adr, dp); + if (OK == ret) return OK; + dp->stat &= ~INITIALIZED; + } + printf("SCSI %s, block %d failed even after retries\n", + op == DISK_READ? "READ": "WRITE", block); + return NOT_OK; +} + +/*===========================================================================* + * sc_initialize * + *===========================================================================*/ +/* Execute the list of initialization commands for the given drive. + */ +int +sc_initialize (dp) +struct drive *dp; +{ + const struct cmd_desc *cp; + + for (cp = dp->init; cp != 0; cp = cp->chain) + if (OK != exec_scsi_hi (cp->cmd, 0, cp->odata, dp)) { + dp->stat &= ~INITIALIZED; + return NOT_OK; + } + dp->stat |= INITIALIZED; + return OK; +} + +/*===========================================================================* + * exec_scsi_hi * + *===========================================================================*/ +/* Execute a "high-level" SCSI command. This means execute a low level + * command and, if it fails, execute a request sense to find out why. + */ +PRIVATE int +exec_scsi_hi(cmd, data_in, data_out, dp) +U8 *cmd, *data_out, *data_in; +struct drive *dp; +{ + scsi_args.ptr[CMD_IX] = (long)cmd; + scsi_args.ptr[STAT_IX] = (long)stat_buf; + scsi_args.ptr[IMSG_IX] = (long)msg_buf; + scsi_args.ptr[IDATA_IX] = (long)data_in; + scsi_args.ptr[ODATA_IX] = (long)data_out; + if (OK != exec_scsi_low (&scsi_args, dp->adr)) + return NOT_OK; + *stat_buf &= STAT_MASK; /* strip off lun */ + if (*stat_buf == 0) + /* Success -- this should be the usual case */ + return OK; + if (*stat_buf != CHECK_CONDITION) { + /* do not know how to handle this so return error */ + printf("SCSI device returned unknown status: %d\n", *stat_buf); + return NOT_OK; + } + /* Something funny happened, need to execute request-sense command + * to learn more. + */ + if (OK == get_sense(dp)) + /* Something funny happened, but the device recovered from it and + * the command succeeded. + */ + return OK; + return NOT_OK; +} + +/*===========================================================================* + * get_sense * + *===========================================================================*/ +/* Execute a "request sense" SCSI command and check results. When a SCSI + * command returns CHECK_CONDITION, a request-sense command must be executed. + * A request-sense command provides information about the original command. + * The original command might have succeeded, in which case it does not + * need to be retried and OK is returned. Examples: read error corrected + * with error correction code, or error corrected by retries performed by + * the SCSI device. The original command also could have failed, in + * which case NOT_OK is returned. + */ +#define XLOGICAL_ADR \ + (sense_buf[3]<<24 | sense_buf[4]<<16 | sense_buf[5]<<8 | sense_buf[6]) +#define LOGICAL_ADR \ + (sense_buf[1]<<16 | sense_buf[2]<<8 | sense_buf[3]) + +PRIVATE int +get_sense (dp) +struct drive *dp; +{ + U8 *p; + + p = cmd_buf; /* build SCSI command */ + *p++ = CMD_SENSE; + *p++ = dp->lun << 5; + *p++ = 0; + *p++ = 0; + *p++ = (dp->flags & EXTENDED_SENSE)? SENSE_LEN: 0; + *p = 0; + scsi_args.ptr[IDATA_IX] = (long)sense_buf; + scsi_args.ptr[ODATA_IX] = 0; + scsi_args.ptr[CMD_IX] = (long)cmd_buf; + scsi_args.ptr[STAT_IX] = (long)stat_buf; + scsi_args.ptr[IMSG_IX] = (long)msg_buf; + if (OK != exec_scsi_low (&scsi_args, dp->adr)) { + printf("SCSI SENSE command failed\n"); + return NOT_OK; + } + if ((*stat_buf & STAT_MASK) != 0) { + printf("SCSI SENSE returned wrong status %d\n", *stat_buf); + return NOT_OK; + } + if (0 == (dp->flags & EXTENDED_SENSE)) { + printf("SCSI request sense, code 0x%x, log_adr 0x%x\n", + sense_buf[0], LOGICAL_ADR); + return NOT_OK; + } + switch (sense_buf[SENSE_KEY] & 0xf) { + case NO_SENSE: + case UNIT_ATTN: /* reset */ + return NOT_OK; /* must retry command */ + case RECOVERY_ERR: + /* eventually, we probably do not want to hear about these. */ + printf("SCSI ok with recovery, code 0x%x, logical address 0x%x\n", + sense_buf[ADD_SENSE_CODE], XLOGICAL_ADR); + return OK; /* orig command was ok with recovery */ + default: + printf("SCSI failure: key 0x%x code 0x%x log adr 0x%x sense buf 0x%x\n", + sense_buf[SENSE_KEY], sense_buf[ADD_SENSE_CODE], + XLOGICAL_ADR, sense_buf); + return NOT_OK; /* orig command failed */ + } +} diff --git a/sys/arch/vax/boot/scsi_low.c b/sys/arch/vax/boot/scsi_low.c new file mode 100644 index 00000000000..a86a82de7c9 --- /dev/null +++ b/sys/arch/vax/boot/scsi_low.c @@ -0,0 +1,479 @@ +/* $NetBSD: scsi_low.c,v 1.1 1996/08/02 11:22:34 ragge Exp $ */ + +/**************************************************************************** + * NS32K Monitor SCSI low-level driver + * Bruce Culbertson + * 8 March 1990 + * (This source is public domain source.) + * + * Originally written by Bruce Culbertson for a ns32016 port of Minix. + * Adapted from that for the pc532 (ns32632) monitor. + * Adapted from that for NetBSD/pc532 by Philip L. Bunde. + * + * Do not use DMA -- makes 32016 and pc532 versions compatible. + * Do not use interrupts -- makes it harder for the user code to bomb + * this code. + ****************************************************************************/ + +#include "so.h" +#include "ka410.h" + +#define BB_DEBUG(x) printf x +#define CLEAR_INTR() *ka410_intclr=INTR_SC +#define CHECK_INTR() *ka410_intreq&INTR_SC + +#define OK 0 +#define NOT_OK OK+1 +#define PRIVATE +#define PUBLIC +#define WR_ADR(adr,val) (*((volatile unsigned char *)(adr))=(val)) +#define RD_ADR(adr) (*((volatile unsigned char *)(adr))) +/* #define AIC6250 0 */ +/* #define DP8490 1 */ +#define MAX_CACHE 0x4000 + +/* SCSI bus phases + */ +#define PH_ODATA 0 +#define PH_IDATA 1 +#define PH_CMD 2 +#define PH_STAT 3 +#define PH_IMSG 7 +#define PH_NONE 8 +#define PH_IN(phase) ((phase) & 1) + +/* NCR5380 SCSI controller registers + */ +#define SC_CTL 0x200C0080 /* base for control registers */ +#define SC_DMA 0x200D0000 /* base for data registers (8/16K) */ +#define SC_CURDATA SC_CTL+(4*0) +#define SC_OUTDATA SC_CTL+(4*0) +#define SC_ICMD SC_CTL+(4*1) +#define SC_MODE SC_CTL+(4*2) +#define SC_TCMD SC_CTL+(4*3) +#define SC_STAT1 SC_CTL+(4*4) +#define SC_STAT2 SC_CTL+(4*5) +#define SC_START_SEND SC_CTL+(4*5) +#define SC_INDATA SC_CTL+(4*6) +#define SC_RESETIP SC_CTL+(4*7) +#define SC_START_RCV SC_CTL+(4*7) + +/* Bits in NCR5380 registers + */ +#define SC_A_RST 0x80 +#define SC_A_SEL 0x04 +#define SC_S_SEL 0x02 +#define SC_S_REQ 0x20 +#define SC_S_BSY 0x40 +#define SC_S_BSYERR 0x04 +#define SC_S_PHASE 0x08 +#define SC_S_IRQ 0x10 +#define SC_S_DRQ 0x40 +#define SC_M_DMA 0x02 +#define SC_M_BSY 0x04 +#define SC_ENABLE_DB 0x01 + +/* Status of interrupt routine, returned in m1_i1 field of message. + */ +#define ISR_NOTDONE 0 +#define ISR_OK 1 +#define ISR_BSYERR 2 +#define ISR_RSTERR 3 +#define ISR_BADPHASE 4 +#define ISR_TIMEOUT 5 + +#define ICU_ADR 0xfffffe00 +#define ICU_IO (ICU_ADR+20) +#define ICU_DIR (ICU_ADR+21) +#define ICU_DATA (ICU_ADR+19) +#define ICU_SCSI_BIT 0x80 + +/* Miscellaneous + */ +#define MAX_WAIT (1000*1000) +#define SC_LOG_LEN 32 + +PRIVATE struct scsi_args *sc_ptrs; +PRIVATE char sc_cur_phase, + sc_reset_done = 1, + sc_have_msg, + sc_accept_int, + sc_dma_dir; + +long sc_dma_port = SC_DMA, + sc_dma_adr; + +#ifdef DEBUG +struct sc_log { + unsigned char stat1, stat2; +} sc_log [SC_LOG_LEN], + *sc_log_head = sc_log; +int sc_spurious_int; +#endif +unsigned char + sc_watchdog_error; /* watch dog error */ + +/* error messages */ +char *scsi_errors[] = { + 0, /* ISR_NOTDONE */ + 0, /* ISR_OK */ + "busy error", /* ISR_BSYERR */ + "reset error", /* ISR_RSTERR */ + "NULL pointer for current phase", /* ISR_BADPHASE */ + "timeout", /* ISR_TIMEOUT */ +}; + +/*===========================================================================* + * exec_scsi_low * + *===========================================================================*/ +/* Execute a generic SCSI command. Passed pointers to eight buffers: + * data-out, data-in, command, status, dummy, dummy, message-out, message-in. + */ +PUBLIC +int +exec_scsi_low (args, scsi_adr) +struct scsi_args *args; +long scsi_adr; +{ + int ret; + + BB_DEBUG (("exec_scsi_low(0x%x, %d)\n", args, scsi_adr)); + + sc_ptrs = args; /* make pointers globally accessible */ + /* bertram ??? scCtlrSelect (DP8490); */ + if (!sc_reset_done) sc_reset(); + /* TCMD has some undocumented behavior in initiator mode. I think the + * data bus cannot be enabled if i/o is asserted. + */ + WR_ADR (SC_TCMD, 0); + if (OK != sc_wait_bus_free ()) { /* bus-free phase */ + printf("SCSI: bus not free\n"); + return NOT_OK; + } + sc_cur_phase = PH_NONE; + sc_have_msg = 0; + if (OK != sc_select (scsi_adr)) /* select phase */ + return NOT_OK; + sc_watchdog_error = 0; + ret = sc_receive (); /* isr does the rest */ + if (ret == ISR_OK) return OK; + else { + sc_reset(); + printf("SCSI: %s\n", scsi_errors[ret]); + return NOT_OK; + } +} + +/*===========================================================================* + * sc_reset * + *===========================================================================*/ +/* + * Reset SCSI bus. + */ +PRIVATE +sc_reset() +{ + volatile int i; + + BB_DEBUG (("sc_reset()\n")); + + WR_ADR (SC_MODE, 0); /* get into harmless state */ + WR_ADR (SC_OUTDATA, 0); + WR_ADR (SC_ICMD, SC_A_RST); /* assert RST on SCSI bus */ + i = 200; /* wait 25 usec */ + while (i--); + WR_ADR (SC_ICMD, 0); /* deassert RST, get off bus */ + sc_reset_done = 1; +} + +/*===========================================================================* + * sc_wait_bus_free * + *===========================================================================*/ +PRIVATE int +sc_wait_bus_free() +{ + int i = MAX_WAIT; + volatile int j; + + BB_DEBUG (("sc_wait_bus_free()\n")); + + while (i--) { + /* Must be clear for 2 usec, so read twice */ + if (RD_ADR (SC_STAT1) & (SC_S_BSY | SC_S_SEL)) continue; + for (j = 0; j < 25; ++j); + if (RD_ADR (SC_STAT1) & (SC_S_BSY | SC_S_SEL)) continue; + return OK; + } + sc_reset_done = 0; + return NOT_OK; +} + +/*===========================================================================* + * sc_select * + *===========================================================================*/ +/* This duplicates much of the work that the interrupt routine would do on a + * phase mismatch and, in fact, the original plan was to just do the select, + * let a phase mismatch occur, and let the interrupt routine do the rest. + * That didn't work because the 5380 did not reliably generate the phase + * mismatch interrupt after selection. + */ +PRIVATE int +sc_select(adr) +long adr; +{ + int i, stat1; + long new_ptr; + + BB_DEBUG (("sc_select(%d)\n", adr)); + + CLEAR_INTR(); + WR_ADR (SC_OUTDATA, adr); /* SCSI bus address */ + WR_ADR (SC_ICMD, SC_A_SEL | SC_ENABLE_DB); + for (i = 0;; ++i) { /* wait for target to assert SEL */ + if (CHECK_INTR() == 0) + continue; + stat1 = RD_ADR (SC_STAT1); + if (stat1 & SC_S_BSY) break; /* select successful */ + if (i > MAX_WAIT) { /* timeout */ + printf("SCSI: SELECT timeout\n"); + sc_reset(); + return NOT_OK; + } + } + CLEAR_INTR(); + WR_ADR (SC_ICMD, 0); /* clear SEL, disable data out */ + WR_ADR (SC_OUTDATA, 0); + for (i = 0;; ++i) { /* wait for target to assert REQ */ + if (CHECK_INTR() == 0) + continue; + if (stat1 & SC_S_REQ) break; /* target requesting transfer */ + if (i > MAX_WAIT) { /* timeout */ + printf("SCSI: REQ timeout\n"); + sc_reset(); + return NOT_OK; + } + stat1 = RD_ADR (SC_STAT1); + } + sc_cur_phase = (stat1 >> 2) & 7; /* get new phase from controller */ + if (sc_cur_phase != PH_CMD) { + printf("SCSI: bad phase = %d\n", sc_cur_phase); + sc_reset(); + return NOT_OK; + } + new_ptr = sc_ptrs->ptr[PH_CMD]; + if (new_ptr == 0) { + printf("SCSI: NULL command pointer\n"); + sc_reset(); + return NOT_OK; + } + sc_accept_int = 1; + sc_dma_setup (DISK_WRITE, new_ptr); + CLEAR_INTR(); + WR_ADR (SC_TCMD, PH_CMD); + WR_ADR (SC_ICMD, SC_ENABLE_DB); + WR_ADR (SC_MODE, SC_M_BSY | SC_M_DMA); + WR_ADR (SC_START_SEND, 0); + return OK; +} + +/*===========================================================================* + * scsi_interrupt * + *===========================================================================*/ +/* SCSI interrupt handler. + */ +PUBLIC +int +scsi_interrupt() +{ + unsigned char stat2, dummy; + long new_ptr; + int ret = ISR_NOTDONE; + + BB_DEBUG (("scsi_interrupt()\n")); + + stat2 = RD_ADR (SC_STAT2); /* get status before clearing request */ + +# ifdef DEBUG /* debugging log of interrupts */ + sc_log_head->stat1 = RD_ADR (SC_STAT1); + sc_log_head->stat2 = stat2; + if (++sc_log_head >= sc_log + SC_LOG_LEN) sc_log_head = sc_log; + sc_log_head->stat1 = sc_log_head->stat2 = 0xff; +# endif + + for (;;) { + dummy = RD_ADR (SC_RESETIP); /* clear interrupt request */ + if (!sc_accept_int || /* return if spurious interrupt */ + (!sc_watchdog_error && + (stat2 & SC_S_BSYERR) == 0 && (stat2 & SC_S_PHASE) != 0)) + { +# ifdef DEBUG + ++sc_spurious_int; +# endif + printf ("sc_spurious_int\n"); + return ret; + } + RD_ADR (SC_MODE) &= ~SC_M_DMA; /* clear DMA mode */ + WR_ADR (SC_ICMD, 0); /* disable data bus */ + if (sc_cur_phase != PH_NONE) { /* if did DMA, save the new pointer */ + new_ptr = sc_dma_adr; /* fetch new pointer from DMA cntlr */ + if (sc_cur_phase == PH_IMSG && /* have message? */ + new_ptr != sc_ptrs->ptr[PH_IMSG]) sc_have_msg = 1; + sc_ptrs->ptr[sc_cur_phase] = /* save pointer */ + new_ptr; + } + if (sc_watchdog_error) ret = ISR_TIMEOUT; + else if (stat2 & SC_S_BSYERR) { /* target deasserted BSY? */ + printf ("target deasserted BSY?\n"); + if (sc_have_msg) ret = ISR_OK; + else ret = ISR_BSYERR; + } else if (!(stat2 & SC_S_PHASE)) {/* if phase mismatch, setup new phase */ + printf ("phase mismatch\n"); + sc_cur_phase = /* get new phase from controller */ + (RD_ADR (SC_STAT1) >> 2) & 7; + new_ptr = sc_ptrs->ptr[sc_cur_phase]; + if (new_ptr == 0) ret = ISR_BADPHASE; + else { + WR_ADR (SC_TCMD, sc_cur_phase); /* write new phase into TCMD */ + if (PH_IN (sc_cur_phase)) { /* set DMA controller */ + sc_dma_setup (DISK_READ, new_ptr); + RD_ADR (SC_MODE) |= SC_M_DMA; + CLEAR_INTR(); + WR_ADR (SC_START_RCV, 0); /* tell SCSI to start DMA */ + } else { + sc_dma_setup (DISK_WRITE, new_ptr); + RD_ADR (SC_MODE) |= SC_M_DMA; + WR_ADR (SC_ICMD, SC_ENABLE_DB); + CLEAR_INTR(); + WR_ADR (SC_START_SEND, 0); + } + } + } else ret = ISR_RSTERR; + if (ret != ISR_NOTDONE) { /* if done, send message to task */ + sc_watchdog_error = 0; + sc_accept_int = 0; + WR_ADR (SC_MODE, 0); /* clear monbsy, dma */ + break; /* reti re-enables ints */ + } + if (0 == ((stat2 = /* check for another interrupt */ + RD_ADR (SC_STAT2)) & SC_S_IRQ)) + { + break; + } + } + return ret; +} + +/*===========================================================================* + * sc_dma_setup * + *===========================================================================*/ +/* Fake DMA setup. Just store pointers and direction in global variables. + * + * The pseudo-DMA is subtler than it looks because of the cache. + * + * 1) When accessing I/O devices through a cache, some mechanism is + * necessary to ensure you access the device rather than the cache. + * On the 32532, the IODEC signal is supposed to be asserted for I/O + * addresses to accomplish this. However, a bug makes this much + * slower than necessary and severely hurts pseudo-DMA performance. + * Hence, IODEC is not asserted for the SCSI DMA port. + * + * 2) Because of (1), we must devise our own method of forcing the + * SCSI DMA port to be read. 0x8000000 addresses have been decoded + * to all access this port. By always using new addresses to access + * the DMA port (wrapping only after reading MAX_CACHE bytes), we + * force cache misses and, hence, device reads. Since the cache + * is write-through, we do not need to worry about writes. + * + * 3) It is possible to miss the last few bytes of a transfer if + * bus transfer size is not considered. The loop in sc_receive() + * transfers data until the interrupt signal is asserted. If + * bytes are transferred, the attempt to move the first byte of a + * double word causes the whole word to be read into the cache. + * Then the byte is transferred. If reading the double word + * completed the SCSI transfer, then the loop exits since + * interrupt is asserted. However, the last few bytes have only + * been moved into the cache -- they have not been moved to the + * DMA destination. + * + * 4) It is also possible to miss the first few bytes of a transfer. + * If the address used to access pseudo-dma port is not double word + * aligned, the whole double word is read into the cache, and then + * data is moved from the middle of the word (i.e. something other + * than the first bytes read from the SCSI controller) by the + * pseudo-dma loop in sc_receive(). + */ +sc_dma_setup (dir, adr) +int dir; +long adr; +{ + BB_DEBUG (("sc_dma_setup(%d, %d)\n", dir, adr)); + + CLEAR_INTR(); + /* if (sc_dma_port > SC_DMA + MAX_CACHE) */ + sc_dma_port = SC_DMA; + sc_dma_dir = dir; + sc_dma_adr = adr; +} + +/*===========================================================================* + * sc_receive * + *===========================================================================*/ +/* Replacement for Minix receive(), which waits for a message. This code + * spins, waiting for data to transfer or interrupt requests to handle. + * See sc_dma_setup for details. + */ +int +sc_receive() +{ + int stat2, isr_ret; + int i, c; + + BB_DEBUG (("sc_receive()\n")); + + /* + * check the interrupt-flag and wait if it reappears... + */ + c = *ka410_intreq; + printf ("begin: %x/%x ", c, *ka410_intreq); + for (i=0; i<100; i++) { + if ((c = *ka410_intreq) & INTR_SC) + break; + printf (" %x ", c); + } + if (i==100) + printf ("timeout in sc_receive.\n"); + +#if 1 + for (;;) { + stat2 = RD_ADR (SC_STAT2); + if (stat2 & SC_S_IRQ) { + if (ISR_NOTDONE != (isr_ret = scsi_interrupt())) break; + } else if (stat2 & SC_S_DRQ) { /* test really not necessary on pc532 */ + if (sc_dma_dir == DISK_READ) + *((long *)sc_dma_adr)++ = *((volatile long *)sc_dma_port)++; + else *((volatile long *)sc_dma_port)++ = *((long *)sc_dma_adr)++; + } + } +#endif + printf ("isr_ret: %d (ISR_NOTDONE: %d)\n", isr_ret, ISR_NOTDONE); + return isr_ret; +} + +/*===========================================================================* + * scCtlrSelect + *===========================================================================*/ +/* Select a SCSI device. + */ +scCtlrSelect (ctlr) +int ctlr; +{ + BB_DEBUG (("scCtlrSelect()\n")); +#if 0 + RD_ADR (ICU_IO) &= ~ICU_SCSI_BIT; /* i/o, not port */ + RD_ADR (ICU_DIR) &= ~ICU_SCSI_BIT; /* output */ + if (ctlr == DP8490) + RD_ADR (ICU_DATA) &= ~ICU_SCSI_BIT; /* select = 0 for 8490 */ + else + RD_ADR (ICU_DATA) |= ICU_SCSI_BIT; /* select = 1 for AIC6250 */ +#endif +} diff --git a/sys/arch/vax/boot/sd.c b/sys/arch/vax/boot/sd.c new file mode 100644 index 00000000000..30b08c3ff57 --- /dev/null +++ b/sys/arch/vax/boot/sd.c @@ -0,0 +1,247 @@ +/* $NetBSD: sd.c,v 1.1 1996/08/02 11:22:36 ragge Exp $ */ + +/* + * Copyright (c) 1988 University of Utah. + * Copyright (c) 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Van Jacobson of Lawrence Berkeley Laboratory and the Systems + * Programming Group of the University of Utah Computer Science Department. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * from: Utah $Hdr: sd.c 1.9 92/12/21$ + * + * @(#)sd.c 8.1 (Berkeley) 6/10/93 + */ + +/* + * SCSI CCS disk driver + */ + +#include <sys/param.h> +#include <sys/disklabel.h> +#include "stand.h" +#include "samachdep.h" + +#define SC_DEBUG 1 /* bertram */ +#define SD_DEBUG 1 /* bertram */ + +/*----------------------------------------------------------------------*/ +int +scsialive(int ctlr) +{ + return 1; /* controller always alive! */ +} + +/* call functions in scsi_hi.c */ +#include "so.h" + +int +scsi_tt_read(ctlr, slave, buf, len, blk, nblk) + int ctlr, slave; + u_char *buf; + u_int len; + daddr_t blk; + u_int nblk; +{ +#ifdef SC_DEBUG +printf("scsi_tt_read: ctlr %d, slave %d, len %d, blk %d, nblk %d\n", + ctlr, slave, len, blk, nblk ); +#endif + if (sc_rdwt(DISK_READ, blk, buf, nblk, 1<<slave, 0) == 0) + return 0; + return -2; +} + +int +scsi_tt_write(ctlr, slave, buf, len, blk, nblk) + int ctlr, slave; + u_char *buf; + u_int len; + daddr_t blk; + u_int nblk; +{ +#ifdef SC_DEBUG +printf("scsi_tt_write: ctlr %d, slave %d, len %d, blk %d, nblk %d\n", + ctlr, slave, len, blk, nblk ); +#endif +#if 0 + if (sc_rdwt(DISK_WRITE, blk, buf, nblk, 1<<slave, 0) == 0) + return 0; +#endif + return -2; +} + +/*----------------------------------------------------------------------*/ + +struct sd_softc { + int sc_ctlr; + int sc_unit; + int sc_part; + char sc_retry; + char sc_alive; + struct disklabel sc_label; +} sd_softc[NSCSI][NSD]; + +#ifdef SD_DEBUG +int debug = SD_DEBUG; +#endif + +#define SDRETRY 2 + +sdinit(ctlr, unit) + int ctlr, unit; +{ + register struct sd_softc *ss = &sd_softc[ctlr][unit]; + + /* HP version does test_unit_ready + * followed by read_capacity to get blocksize + */ + ss->sc_alive = 1; + return (1); +} + +sdreset(ctlr, unit) + int ctlr, unit; +{ +} + +char io_buf[MAXBSIZE]; + +sdgetinfo(ss) + register struct sd_softc *ss; +{ + register struct disklabel *lp; + char *msg, *getdisklabel(); + int sdstrategy(), i, err; + + lp = &sd_softc[ss->sc_ctlr][ss->sc_unit].sc_label; + bzero((caddr_t)lp, sizeof *lp); + lp->d_secsize = DEV_BSIZE; + lp->d_secpercyl = 1; + lp->d_npartitions = MAXPARTITIONS; + lp->d_partitions[ss->sc_part].p_offset = 0; + lp->d_partitions[ss->sc_part].p_size = 0x7fffffff; + + if (err = sdstrategy(ss, F_READ, + LABELSECTOR, DEV_BSIZE, io_buf, &i) < 0) { + printf("sdgetinfo: sdstrategy error %d\n", err); + return 0; + } + + msg = getdisklabel(io_buf, lp); + if (msg) { + printf("sd(%d,%d,%d): %s\n", + ss->sc_ctlr, ss->sc_unit, ss->sc_part, msg); + return 0; + } + return(1); +} + +sdopen(f, ctlr, unit, part) + struct open_file *f; + int ctlr, unit, part; +{ + register struct sd_softc *ss; + register struct disklabel *lp; + +#ifdef SD_DEBUG + if (debug) + printf("sdopen: ctlr=%d unit=%d part=%d\n", + ctlr, unit, part); +#endif + + if (ctlr >= NSCSI || !scsialive(ctlr)) + return (EADAPT); + if (unit >= NSD) + return (ECTLR); + ss = &sd_softc[ctlr][unit]; /* XXX alloc()? keep pointers? */ + ss->sc_part = part; + ss->sc_unit = unit; + ss->sc_ctlr = ctlr; + if (!ss->sc_alive) { + if (!sdinit(ctlr, unit)) + return (ENXIO); + if (!sdgetinfo(ss)) + return (ERDLAB); + } + lp = &sd_softc[ctlr][unit].sc_label; + if (part >= lp->d_npartitions || lp->d_partitions[part].p_size == 0) + return (EPART); + + f->f_devdata = (void *)ss; + return (0); +} + +int +sdstrategy(ss, func, dblk, size, buf, rsize) + register struct sd_softc *ss; + int func; + daddr_t dblk; /* block number */ + u_int size; /* request size in bytes */ + char *buf; + u_int *rsize; /* out: bytes transferred */ +{ + register int ctlr = ss->sc_ctlr; + register int unit = ss->sc_unit; + register int part = ss->sc_part; + register struct partition *pp = &ss->sc_label.d_partitions[part]; + u_int nblk = size >> DEV_BSHIFT; + u_int blk = dblk + pp->p_offset; + char stat; + + if (size == 0) + return(0); + + ss->sc_retry = 0; + +#ifdef SD_DEBUG + if (debug) + printf("sdstrategy(%d,%d): size=%d blk=%d nblk=%d\n", + ctlr, unit, size, blk, nblk); +#endif + +retry: + if (func == F_READ) + stat = scsi_tt_read(ctlr, unit, buf, size, blk, nblk); + else + stat = scsi_tt_write(ctlr, unit, buf, size, blk, nblk); + if (stat) { + printf("sd(%d,%d,%d): block=%x, error=0x%x\n", + ctlr, unit, ss->sc_part, blk, stat); + if (++ss->sc_retry > SDRETRY) + return(EIO); + goto retry; + } + *rsize = size; + + return(0); +} diff --git a/sys/arch/vax/boot/so.h b/sys/arch/vax/boot/so.h new file mode 100644 index 00000000000..3ead2c8e14b --- /dev/null +++ b/sys/arch/vax/boot/so.h @@ -0,0 +1,57 @@ +/* $NetBSD: so.h,v 1.1 1996/08/02 11:22:41 ragge Exp $ */ + +#ifndef _SO_H_INCLUDE +#define _SO_H_INCLUDE + +/* Definitions for standalone I/O lib */ + +/* #define SCSI_POLLED 0x200C0080 */ +#define SCSI_DMA 0x200D0000 + +/* Which SCSI device to use by default */ +#define DEFAULT_SCSI_ADR 1 +#define DEFAULT_SCSI_LUN 0 + +/* Low level scsi operation codes */ +#define DISK_READ 3 +#define DISK_WRITE 4 + +/* The size of a disk block */ +#define DBLKSIZE 512 + +/* Some disk address that will never be used */ +#define INSANE_BADDR 0x800000 + +struct scsi_args { + long ptr [8]; +}; + +#ifndef NULL +#define NULL 0L +#endif + +/* + * The next macro defines where the "break" area in memory ends for + * malloc() and friends. The area between edata and this address will + * then be reserved and should not be used for anything else (or you will + * no doubt have big problems). Depending on where your program's end-of-data + * is, you may wish to locate this in such a way as to usurp a minimum + * amount of memory. + */ +#define BREAK_END_ADDR ((char *)0x400000) /* to 4MB */ + +/* Selectivly enable inline functions */ +#ifndef NO_INLINE +#define Inline inline +#else +#define Inline +#endif + +extern void fatal(), warn(); +extern long ulimit(int, long); +extern int brk(char *); +extern char *sbrk(int); + +extern int sc_rdwt(); + +#endif /* _SO_H_INCLUDE */ diff --git a/sys/arch/vax/boot/srt0.s b/sys/arch/vax/boot/srt0.s index 1fc8dfca8e3..bfe5acafe34 100644 --- a/sys/arch/vax/boot/srt0.s +++ b/sys/arch/vax/boot/srt0.s @@ -1,4 +1,4 @@ -/* $NetBSD: srt0.s,v 1.5 1996/03/07 23:27:10 ragge Exp $ */ +/* $NetBSD: srt0.s,v 1.6 1996/08/02 11:22:44 ragge Exp $ */ /* * Copyright (c) 1994 Ludd, University of Lule}, Sweden. * All rights reserved. @@ -58,7 +58,9 @@ _start: .globl _start 1: movl $relocated, (sp) # return-address on top of stack rsb # can be replaced with new address relocated: # now relocation is done !!! - calls $0,_main # Were here! + movl sp, _bootregs + calls $0, _setup + calls $0, _Xmain # Were here! halt # no return diff --git a/sys/arch/vax/boot/start.s b/sys/arch/vax/boot/start.s index 55b2fc0438a..51edf004a88 100644 --- a/sys/arch/vax/boot/start.s +++ b/sys/arch/vax/boot/start.s @@ -1,4 +1,4 @@ -/* $NetBSD: start.s,v 1.7 1996/02/02 19:08:33 mycroft Exp $ */ +/* $NetBSD: start.s,v 1.8 1996/08/02 11:22:47 ragge Exp $ */ /* * Copyright (c) 1995 Ludd, University of Lule}, Sweden. * All rights reserved. @@ -172,7 +172,8 @@ start_all: relocated: # now relocation is done !!! movl sp, _bootregs movl ap, _boothowto - calls $0, _main # call main() which is + calls $0, _setup + calls $0, _Xmain # call Xmain (gcc workaround)which is halt # not intended to return ... /* diff --git a/sys/arch/vax/boot/str.s b/sys/arch/vax/boot/str.s new file mode 100644 index 00000000000..685574e0371 --- /dev/null +++ b/sys/arch/vax/boot/str.s @@ -0,0 +1,70 @@ +/* $NetBSD: str.s,v 1.2 1996/08/02 16:18:40 ragge Exp $ */ +/* + * Copyright (c) 1996 Ludd, University of Lule}, Sweden. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed at Ludd, University of + * Lule}, Sweden and its contributors. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Small versions of the most common string functions not using any + * emulated instructions. + */ + +#include "../include/asm.h" + +ENTRY(strlen, 0); + movl 4(ap), r0 +1: tstb (r0)+ + bneq 1b + decl r0 + subl2 4(ap), r0 + ret + +ENTRY(strncmp, 0) + movl 12(ap), r3 + brb 5f + +ENTRY(strcmp, 0) + movl $250, r3 # max string len to compare +5: movl 4(ap), r2 + movl 8(ap), r1 + movl $1, r0 + +2: cmpb (r2),(r1)+ + bneq 1f # something differ + tstb (r2)+ + beql 4f # continue, strings unequal + decl r3 # max string len encountered? + bneq 2b + +4: clrl r0 # We are done, strings equal. + ret + +1: bgtr 3f + mnegl r0, r0 +3: ret diff --git a/sys/arch/vax/boot/tmscp.c b/sys/arch/vax/boot/tmscp.c index f5d0fe11879..b63022212f7 100644 --- a/sys/arch/vax/boot/tmscp.c +++ b/sys/arch/vax/boot/tmscp.c @@ -1,4 +1,4 @@ -/* $NetBSD: tmscp.c,v 1.2 1996/02/17 18:23:24 ragge Exp $ */ +/* $NetBSD: tmscp.c,v 1.3 1996/08/02 11:22:53 ragge Exp $ */ /* * Copyright (c) 1995 Ludd, University of Lule}, Sweden. * All rights reserved. @@ -43,7 +43,8 @@ #include "../include/macros.h" #include "../uba/ubareg.h" #include "../uba/udareg.h" -#include "../vax/mscp.h" +#include "../mscp/mscp.h" +#include "../mscp/mscpreg.h" #include "vaxstand.h" @@ -63,7 +64,7 @@ struct ra_softc { }; static volatile struct uda { - struct uda1ca uda_ca; /* communications area */ + struct mscp_1ca uda_ca; /* communications area */ struct mscp uda_rsp; /* response packets */ struct mscp uda_cmd; /* command packets */ } uda; @@ -100,14 +101,14 @@ tmscpopen(f, adapt, ctlr, unit, part) * Init of this tmscp ctlr. */ udacsr->udaip=0; /* Start init */ - while((udacsr->udasa&UDA_STEP1) == 0); + while((udacsr->udasa&MP_STEP1) == 0); udacsr->udasa=0x8000; - while((udacsr->udasa&UDA_STEP2) == 0); + while((udacsr->udasa&MP_STEP2) == 0); johan=(((u_int)ubauda)&0xffff)+8; udacsr->udasa=johan; - while((udacsr->udasa&UDA_STEP3) == 0); + while((udacsr->udasa&MP_STEP3) == 0); udacsr->udasa=3; - while((udacsr->udasa&UDA_STEP4) == 0); + while((udacsr->udasa&MP_STEP4) == 0); udacsr->udasa=0x0001; uda.uda_ca.ca_rspdsc=(int)&ubauda->uda_rsp.mscp_cmdref; diff --git a/sys/arch/vax/boot/vaxstand.h b/sys/arch/vax/boot/vaxstand.h index f3217fdb235..2d068b9d6d9 100644 --- a/sys/arch/vax/boot/vaxstand.h +++ b/sys/arch/vax/boot/vaxstand.h @@ -1,4 +1,4 @@ -/* $NetBSD: vaxstand.h,v 1.4 1996/02/17 18:23:25 ragge Exp $ */ +/* $NetBSD: vaxstand.h,v 1.5 1996/08/02 11:22:56 ragge Exp $ */ /* * Copyright (c) 1994 Ludd, University of Lule}, Sweden. * All rights reserved. @@ -34,13 +34,12 @@ #define MAXNMBA 8 /* Massbussadapters */ #define MAXNUBA 8 /* Unibusadapters */ -#define MAXNBI 4 /* Bi-bussadapters */ #define MAXMBAU 8 /* Units on an mba */ -#define MAXBIN 16 /* Bi-nodes */ /* Variables used in autoconf */ extern int nmba, nuba, nbi, nsbi, nuda; -extern int *ubaaddr, *mbaaddr, *udaaddr, *uioaddr; +extern int *ubaaddr, *mbaaddr, *udaaddr, *uioaddr, *biaddr; +extern int cpunumber; /* devsw type definitions, used in bootxx and conf */ #define SADEV(name,strategy,open,close,ioctl) \ @@ -50,3 +49,17 @@ extern int *ubaaddr, *mbaaddr, *udaaddr, *uioaddr; (int(*)(struct open_file *))close, \ (int(*)(struct open_file *,u_long, void *))ioctl} +/* + * Easy-to-use definitions + */ +#define min(x,y) (x < y ? x : y) + +/* + * Device numbers gotten from boot prom. + */ +#define BDEV_MBA 0 +#define BDEV_RK06 1 +#define BDEV_RL02 2 +#define BDEV_UDA 17 +#define BDEV_TK50 18 +#define BDEV_CONSOLE 64 diff --git a/sys/arch/vax/conf/EVERYTHING b/sys/arch/vax/conf/EVERYTHING deleted file mode 100644 index 101d475b0c9..00000000000 --- a/sys/arch/vax/conf/EVERYTHING +++ /dev/null @@ -1,93 +0,0 @@ -# $OpenBSD: EVERYTHING,v 1.4 1996/09/20 06:45:26 deraadt Exp $ -# $NetBSD: EVERYTHING,v 1.1 1995/03/29 22:54:02 ragge Exp $ -# -# This file contains everything that is known to be compiled -# without errors. Some things may not be tested, like NETISO. -# - -include "std.vax" - -# Here are all different supported CPU types listed. -options "VAX750" -options "VAX630" - -# Kernel identification -options EVERYTHING - -# Max users on system; this is just a hint -maxusers 16 - -# Paging system, we always have them all. -options SWAPPAGER, DEVPAGER - -# Kernel compiled-in symbolic debugger -#options DDB - -# System V shared memory -options SYSVMSG # Message passing -options SYSVSEM # Semaphores -options SYSVSHM # Shared memory -options SHMMAXPGS=1024 - -# Network support -options INET # Internet protocol, (almost) mandatory -options ETHER # Ethernet, probably needed -options NS # Xerox Network system, untested -options ISO,TPIP # ISO network, untested -options EON -options CCITT,LLC,HDLC - -# All supported filesystem types -options FFS,QUOTA # Normal fast filesystem, mandatory -options LFS # Log-structured file system -options MFS # Memory filesystem -options NFSCLIENT # Network filesystem client -options NFSSERVER # Network filesystem server -options CD9660 # CDRom filesystem -options FDESC # Filedescriptors, /dev/fd -options FIFO -options KERNFS # Kernel info filesystems -options NULLFS -options PORTAL -options PROCFS # Process filesystem -options UMAPFS -options UNION - -# Old compat stuff; needed to run 4.3BSD Reno programs -options COMPAT_43 -options COMPAT_09 -options COMPAT_10 -options COMPAT_RENO -#options TCP_COMPAT_42 # Bug compat with 4.2BSD systems (like NDIX) - -# loadable kernel modules. -options LKM - - -# Kernel(s) to compile -config bsd root on hp0 swap on hp0 - -# All supported CPU:s -cpu0 at backplane0 - -# Main buses at backplane -sbi* at backplane0 - -# Devices connected at sbi -mem* at sbi? tr? # Memory subsystems -uba0 at sbi? tr? # Unibus adapters - -# Disk controllers at Unibus -uda0 at uba? csr 0172150 # UDA50/KDA50/RQDX3 -ra0 at uda0 drive 0 # RA??/RD?? - -# Ethernet cards -de0 at uba? csr 0174510 # DEUNA/DELUA -qe0 at uba? csr 0174440 # DEQNA/DELQA - -# Tape drivers -tmscp0 at uba? csr 0174500 -tms0 at tmscp0 drive ? # TK50/TU81 - -pseudo-device loop -pseudo-device pty 48 diff --git a/sys/arch/vax/conf/GENERIC b/sys/arch/vax/conf/GENERIC index 6a181c456bc..400d4a88659 100644 --- a/sys/arch/vax/conf/GENERIC +++ b/sys/arch/vax/conf/GENERIC @@ -1,16 +1,20 @@ -# $NetBSD: GENERIC,v 1.13 1996/05/19 16:25:23 ragge Exp $ +# $OpenBSD: GENERIC,v 1.7 1997/01/15 23:24:29 maja Exp $ +# $NetBSD: GENERIC,v 1.19 1997/01/11 11:15:38 ragge Exp $ # # GENERIC VAX configuration file; all supported devices. # -include "std.vax" +machine vax # Here are all different supported CPU types listed. options "VAX8600" +options "VAX8200" options "VAX780" options "VAX750" -options "VAX630" -options "VAX650" +options "VAX630" # MV II +options "VAX650" # MV III, 3600, 3800, 3900 +options "VAX410" # VS 2000 +options "VAX43" # VS 3100/76 # Kernel identification options GENERIC @@ -49,6 +53,10 @@ options SYSVMSG options SYSVSEM options SYSVSHM +# What executables to look for. +options EXEC_AOUT +options EXEC_SCRIPT + # Old compat stuff; needed to run 4.3BSD Reno programs. # Note that if COMPAT_ULTRIX is set, you lose compatibility with # 4.3BSD Reno programs and get Ultrix compatibility instead. @@ -56,19 +64,38 @@ options SYSVSHM options COMPAT_43 options COMPAT_09 options COMPAT_10 +options COMPAT_11 +options COMPAT_12 #options COMPAT_ULTRIX #options TCP_COMPAT_42 options LKM - # Kernel(s) to compile config bsd swap generic +backplane0 at root + # Devices directly attached to backplane. cpu0 at backplane0 # Only one CPU so far. sbi* at backplane0 # SBI's are always at backplane (Abus). mem* at backplane0 # Some machines have memory at backplane. +bi* at backplane0 # VAXBI bus +cmi0 at backplane0 # 11/750 internal bus. +uba0 at backplane0 # MicroVAXen only have QBUS. +vsbus0 at backplane0 # Internal "virtual" VAXstation bus + +# Devices connected at VAXBI +cpu0 at bi? node? # KA820/KA825 cpu +mem* at bi? node? # Memory subsystems +#ni* at bi? node? # DEBNA/DEBNT ethernet adapter +kdb* at bi? node? # KDB50 MSCP disk ctlr +mscpbus* at kdb? + +# Devices connected at cmi +mem* at cmi? tr? # Memory subsystems +uba* at cmi? tr? # Unibus adapters +mba* at cmi? tr? # Massbus adapters # Devices connected at sbi mem* at sbi? tr? # Memory subsystems @@ -79,26 +106,38 @@ mba* at sbi? tr? # Massbus adapters hp* at mba? drive? # RM/RP disk drives # Disk controllers at Unibus -uda0 at uba? csr 0172150 -ra0 at uda0 drive 0 -ra1 at uda0 drive 1 -ra2 at uda0 drive 2 -ra3 at uda0 drive 3 - +uda0 at uba? csr 0172150 # UDA50/RQDX? uda1 at uba? csr 0160334 -ra4 at uda1 drive 0 -ra5 at uda1 drive 1 -ra6 at uda1 drive 2 -ra7 at uda1 drive 3 +mscpbus* at uda? + +# Tape drivers +mtc0 at uba? csr 0174500 # Tape MSCP ctlr +mscpbus* at mtc? + +# MSCP devices +ra* at mscpbus? drive? # MSCP disk +mt* at mscpbus? drive? # MSCP tape + +# Unibus tapes +#ts0 at uba? csr 0172520 # TS11/TSV05 tape. + +# VS2000 builtin MFM controller (HDC9224) +hdc0 at vsbus0 # The strange builtin MFM controller +rd* at hdc0 drive? # The RD disk subsystem on VS2000 + +# VAXstation builtin SCSI-controller (NCR5380) +ncr0 at vsbus0 # 1st built-in SCSI interface +ncr1 at vsbus0 # 2nd built-in SCSI interface +scsibus* at ncr? + +sd* at scsibus? target? lun? +st* at scsibus? target? lun? + # Ethernet cards de0 at uba? csr 0174510 # DELUA/DEUNA qe0 at uba? csr 0174440 # DEQNA/DELQA - -# Tape drivers -tmscp0 at uba? csr 0174500 # TMSCP ctlr -tms0 at tmscp0 drive ? # TMSCP tape -ts0 at uba? csr 0172520 # TS11/TSV05 tape. +le0 at vsbus0 # LANCE # Terminal lines dhu0 at uba? csr 0160440 # DHU-11 @@ -106,9 +145,10 @@ dz0 at uba? csr 0160100 # DZ-11 pseudo-device loop 1 pseudo-device pty 48 -pseudo-device bpfilter 8 +pseudo-device bpfilter 8 # Not supported by de or qe yet. pseudo-device sl 2 pseudo-device ppp 2 pseudo-device tun 2 pseudo-device tb 1 pseudo-device vnd 4 +pseudo-device ccd 4 diff --git a/sys/arch/vax/conf/Makefile.vax b/sys/arch/vax/conf/Makefile.vax index 4d8b0eff776..4167eab268e 100644 --- a/sys/arch/vax/conf/Makefile.vax +++ b/sys/arch/vax/conf/Makefile.vax @@ -1,6 +1,7 @@ -# $Bsd: Makefile.vax,v 1.21 1996/05/11 16:13:17 mycroft Exp $ +# $OpenBSD: Makefile.vax,v 1.5 1997/01/15 23:24:30 maja Exp $ +# $NetBSD: Makefile.vax,v 1.28 1996/12/01 06:12:39 jonathan Exp $ -# Makefile for Bsd +# Makefile for NetBSD # # This makefile is constructed from a machine description: # config machineid @@ -17,27 +18,34 @@ # # -DTRACE compile in kernel tracing hooks # -DQUOTA compile in file system quotas -# -DUUDMA compile in unibus tu58 pseudo-dma code # DEBUG is set to -g if debugging. # PROF is set to -pg if profiling. -AS?= as CC?= cc -CPP?= cpp LD?= ld -STRIP?= strip -d -TOUCH?= touch -f -c +MKDEP?= mkdep +STRIP?= strip +COPTS?= -O2 # source tree is located via $S relative to the compilation directory -S= ../../../.. -VAX= ../.. +.ifndef S +S!= cd ../../../..; pwd +.endif +VAX= $S/arch/vax -INCLUDES= -I. -I$S/arch -I$S -CPPFLAGS= ${INCLUDES} ${IDENT} -D_KERNEL -D_VAX_INLINE_ -CFLAGS= ${DEBUG} -O2 -Werror +INCLUDES= -I. -I$S/arch -I$S -nostdinc +CPPFLAGS= ${INCLUDES} ${IDENT} ${PARAM} -D_KERNEL \ + -D_VAX_INLINE_ +CWARNFLAGS= -Werror +CFLAGS= ${DEBUG} ${COPTS} ${CWARNFLAGS} AFLAGS= -x assembler-with-cpp -traditional-cpp -D_LOCORE LINKFLAGS= -Z -Ttext 80000000 -e _start +STRIPFLAGS= -d + +HOSTED_CC= ${CC} +HOSTED_CPPFLAGS=${CPPFLAGS:S/^-nostdinc$//} +HOSTED_CFLAGS= ${CFLAGS} ### find out what to use for libkern .include "$S/lib/libkern/Makefile.inc" @@ -55,19 +63,13 @@ LIBCOMPAT= ${COMPATLIB} LIBCOMPAT= ${COMPATLIB_PROF} .endif -# compile rules: rules are named ${TYPE}_${SUFFIX}${CONFIG_DEP} -# where TYPE is NORMAL, DRIVER, or PROFILE}; SUFFIX is the file suffix, -# capitalized (e.g. C for a .c file), and CONFIG_DEP is _C if the file -# is marked as config-dependent. +# compile rules: rules are named ${TYPE}_${SUFFIX} where TYPE is NORMAL or +# HOSTED}, and SUFFIX is the file suffix, capitalized (e.g. C for a .c file). NORMAL_C= ${CC} ${CFLAGS} ${CPPFLAGS} ${PROF} -c $< -NORMAL_C_C= ${CC} ${CFLAGS} ${CPPFLAGS} ${PROF} ${PARAM} -c $< - -DRIVER_C= ${CC} ${CFLAGS} ${CPPFLAGS} ${PROF} -c $< -DRIVER_C_C= ${CC} ${CFLAGS} ${CPPFLAGS} ${PROF} ${PARAM} -c $< - NORMAL_S= ${CC} ${AFLAGS} ${CPPFLAGS} -c $< -NORMAL_S_C= ${CC} ${AFLAGS} ${CPPFLAGS} ${PARAM} -c $< + +HOSTED_C= ${HOSTED_CC} ${HOSTED_CFLAGS} ${HOSTED_CPPFLAGS} -c $< %OBJS @@ -80,7 +82,7 @@ NORMAL_S_C= ${CC} ${AFLAGS} ${CPPFLAGS} ${PARAM} -c $< # ${SYSTEM_LD_HEAD} # ${SYSTEM_LD} swapxxx.o # ${SYSTEM_LD_TAIL} -SYSTEM_OBJ= intvec.o subr.o lim.o \ +SYSTEM_OBJ= intvec.o subr.o \ param.o ioconf.o ${OBJS} ${LIBKERN} ${LIBCOMPAT} SYSTEM_DEP= Makefile ${SYSTEM_OBJ} SYSTEM_LD_HEAD= @rm -f $@ @@ -93,9 +95,9 @@ DEBUG?= LINKFLAGS+= -X SYSTEM_LD_TAIL+=; \ echo cp $@ $@.gdb; rm -f $@.gdb; cp $@ $@.gdb; \ - echo ${STRIP} $@; ${STRIP} $@ + echo ${STRIP} ${STRIPFLAGS} $@; ${STRIP} ${STRIPFLAGS} $@ .else -LINKFLAGS+= -x +LINKFLAGS+= -S .endif %LOAD @@ -105,7 +107,7 @@ param.c: $S/conf/param.c cp $S/conf/param.c . param.o: param.c Makefile - ${NORMAL_C_C} + ${NORMAL_C} ioconf.o: ioconf.c ${NORMAL_C} @@ -120,7 +122,7 @@ clean:: [Ee]rrs linterrs makelinks lint: - @lint -hbxncez -DGENERIC -Dvolatile= ${CPPFLAGS} ${PARAM} -UKGDB \ + @lint -hbxncez -DGENERIC -Dvolatile= ${CPPFLAGS} -UKGDB \ ${VAX}/vax/Locore.c ${CFILES} ${VAX}/vax/swapgeneric.c \ ioconf.c param.c | \ grep -v 'static function .* unused' @@ -136,14 +138,13 @@ links: sed 's,../.*/\(.*.o\),rm -f \1; ln -s ../GENERIC/\1 \1,' > makelinks sh makelinks && rm -f dontlink -SRCS= ${VAX}/vax/intvec.s ${VAX}/vax/subr.s lim.c \ +SRCS= ${VAX}/vax/intvec.s ${VAX}/vax/subr.s \ param.c ioconf.c ${CFILES} ${SFILES} depend:: .depend .depend: ${SRCS} param.c - mkdep ${AFLAGS} ${CPPFLAGS} ${VAX}/vax/intvec.s ${VAX}/vax/subr.s - mkdep -a ${CFLAGS} ${CPPFLAGS} lim.c - mkdep -a ${CFLAGS} ${CPPFLAGS} param.c ioconf.c ${CFILES} - mkdep -a ${AFLAGS} ${CPPFLAGS} ${SFILES} + ${MKDEP} ${AFLAGS} ${CPPFLAGS} ${VAX}/vax/intvec.s ${VAX}/vax/subr.s + ${MKDEP} -a ${CFLAGS} ${CPPFLAGS} param.c ioconf.c ${CFILES} + ${MKDEP} -a ${AFLAGS} ${CPPFLAGS} ${SFILES} # depend on root or device configuration @@ -166,10 +167,4 @@ intvec.o: ${VAX}/vax/intvec.s subr.o: ${VAX}/vax/subr.s ${NORMAL_S} -lim.c: ioconf.c - ../../conf/mkoldconf.awk < ioconf.c > lim.c - -lim.o: lim.c - ${NORMAL_C_C} - %RULES diff --git a/sys/arch/vax/conf/files.vax b/sys/arch/vax/conf/files.vax index b9176eabbd5..61bd0f44a7a 100644 --- a/sys/arch/vax/conf/files.vax +++ b/sys/arch/vax/conf/files.vax @@ -1,4 +1,4 @@ -# $NetBSD: files.vax,v 1.19 1996/05/19 16:25:29 ragge Exp $ +# $NetBSD: files.vax,v 1.23 1997/01/05 18:50:27 ragge Exp $ # # new style config file for vax architecture # @@ -13,22 +13,32 @@ attach backplane at root device sbi { tr=-1 } attach sbi at backplane +file arch/vax/vax/sbi.c sbi needs-flag + +device cmi { tr=-1 } +attach cmi at backplane + device bi { node=-1 } attach bi at backplane +file arch/vax/bi/bi.c bi needs-flag + +device vsbus { } +attach vsbus at backplane +file arch/vax/vsa/vsbus.c vsbus device cpu attach cpu at backplane with cpu_backplane attach cpu at bi with cpu_bi + device mem attach mem at backplane with mem_backplane attach mem at bi with mem_bi attach mem at sbi with mem_sbi - -file arch/vax/vax/sbi.c sbi needs-flag -file arch/vax/vax/bi.c bi needs-flag +attach mem at cmi with mem_cmi device mba { drive = -1 } -attach mba at sbi +attach mba at sbi with mba_sbi +attach mba at cmi with mba_cmi file arch/vax/mba/mba.c mba needs-flag device hp: disk @@ -40,35 +50,43 @@ device ht attach ht at mba file arch/vax/mba/ht.c ht needs-flag +# MSCP device drivers +include "arch/vax/mscp/files.mscp" +major {ra = 9} +major {mt = 16} + +# KDB50 on BI +device kdb: mscp +attach kdb at bi +file arch/vax/bi/kdb.c kdb + device uba { csr } -attach uba at sbi, bi +attach uba at backplane with uba_backplane +attach uba at sbi with uba_sbi +attach uba at cmi with uba_cmi +attach uba at bi with uba_bi file arch/vax/uba/uba.c uba -device uda { drive=-1 } +device mtc: mscp +attach mtc at uba +device uda: mscp attach uda at uba -file arch/vax/uba/uda.c uda needs-count +file arch/vax/uba/uda.c uda | mtc device de:ifnet, ether attach de at uba file arch/vax/if/if_de.c de -device ra: disk -attach ra at uda -file arch/vax/vax/mscp.c ra needs-count -major {ra = 9} - -# TK50/TU81 at UBA -device tmscp {drive = -1} -attach tmscp at uba -device tms -attach tms at tmscp -file arch/vax/uba/tmscp.c tmscp needs-count - # DEQNA/DELQA used on Qbus device qe:ifnet, ether attach qe at uba file arch/vax/if/if_qe.c qe +# DEBNA/DEBNT Ethernet Adapter +device ni:ifnet, ether +attach ni at bi +file arch/vax/bi/ni.c ni + # TS11 at UBA device ts attach ts at uba @@ -84,6 +102,50 @@ device dz attach dz at uba file arch/vax/uba/dz.c dz needs-count +# RD-type disks at VS2000's onboard MFM-controller +device hdc { drive = -1 } +attach hdc at vsbus +file arch/vax/vsa/hdc9224.c hdc needs-flag + +device rd: disk +attach rd at hdc +major {rd = 19} + +# +# Machine-independent SCSI driver. +# +include "../../../scsi/files.scsi" +major { sd = 20 } +major { st = 21 } +major { cd = 22 } + +# Memory Disk for install floppy +pseudo-device md +file dev/md.c md needs-flag +major { md = 23 } + +# builtin NCR5380 SCSI-controller on VAXstation +device ncr: scsi, ncr5380sbc +attach ncr at vsbus +file arch/vax/vsa/ncr.c ncr needs-flag + +# LANCE ethernet controller on VAXstation +attach le at vsbus +file arch/vax/if/if_le.c le + +# DC367-B in VAXstation 2000/3100 (DZ-like 4-port serial line controller, +# controls keyboard, mouse, modem, and printer/console) +device dc +attach dc at vsbus +file arch/vax/vsa/dc.c dc needs-flag +file arch/vax/vsa/lk201.c dc + +# PM Framebuffer in VAXstation 2000/3100 +device pm +attach pm at vsbus +file arch/vax/vsa/pm.c pm needs-flag + + # These devices aren't tested (or even compiled!) # They are just included here to make some files happy ;) # @@ -112,12 +174,6 @@ device mu attach mu at mba file arch/vax/mba/mt.c mu needs-count -# KDB50 on BI -device kdb { drive=-1 } -attach kdb at bi -file arch/vax/bi/kdb.c kdb needs-count - - # DMF32 on UBA device dmf attach dmf at uba @@ -244,17 +300,23 @@ file dev/cninit.c file arch/vax/vax/locore.c file arch/vax/vax/mem.c file arch/vax/vax/clock.c -file arch/vax/vax/gencons.c +file arch/vax/vax/gencons.c vax8600|vax8200|vax780|vax750|vax630|ka650 +file arch/vax/vax/dzcons.c vax410 | vax43 file arch/vax/vax/pmap.c file arch/vax/vax/machdep.c file arch/vax/vax/ka750.c vax750 -file arch/vax/vax/ka780.c vax780 file arch/vax/vax/ctu.c vax750 -file arch/vax/vax/uvaxII.c vax630 -file arch/vax/vax/emulate.s vax630 | ka650 -file arch/vax/vax/ka650.c vax650 +file arch/vax/vax/ka780.c vax780 +file arch/vax/vax/cfl.c vax780 +file arch/vax/vax/ka820.c vax8200 file arch/vax/vax/ka860.c vax8600 file arch/vax/vax/crl.c vax8600 +file arch/vax/vax/uvax.c vax630 | vax410 | vax43 +file arch/vax/vax/ka630.c vax630 +file arch/vax/vax/ka410.c vax410 +file arch/vax/vax/ka43.c vax43 +file arch/vax/vax/emulate.s vax630 | ka650 +file arch/vax/vax/ka650.c vax650 file arch/vax/vax/conf.c file arch/vax/vax/urem.s file arch/vax/vax/udiv.s @@ -266,7 +328,7 @@ file arch/vax/vax/autoconf.c file arch/vax/vax/random.s inet file arch/vax/vax/in_cksum.c inet file arch/vax/vax/ns_cksum.c ns -file arch/vax/vax/disksubr.c ffs +file arch/vax/vax/disksubr.c disk | tape file arch/vax/if/if_uba.c de | qe file arch/vax/vax/db_machdep.c ddb file arch/vax/vax/db_disasm.c ddb @@ -275,9 +337,7 @@ include "../../../compat/ultrix/files.ultrix" # Dom h{ra f}r vara kvar s} l{nge f}r vi se vilka vi beh|ver... #arch/vax/vax/dkbad.c standard -#arch/vax/vax/flp.c standard #arch/vax/vax/ka730.c standard -#arch/vax/vax/ka820.c standard #arch/vax/vax/rx50.c standard #arch/vax/vax/iidr.o optional ii #arch/vax/vax/iidrsys.o optional ii diff --git a/sys/arch/vax/conf/mkoldconf.awk b/sys/arch/vax/conf/mkoldconf.awk deleted file mode 100644 index 81b2cb1e0d7..00000000000 --- a/sys/arch/vax/conf/mkoldconf.awk +++ /dev/null @@ -1,151 +0,0 @@ -#!/usr/bin/awk -f -# -# $NetBSD: mkoldconf.awk,v 1.7 1996/03/17 22:56:31 ragge Exp $ -# - -/tms_cd/{ - tmsplats[ntms]=$3; - tmsaddr[ntms]=$6; - ntms++; -} - -/ts_cd/{ - tsplats[nts]=$3; - tsaddr[nts]=$6; - nts++; -} - -/ra_cd/{ - raplats[nra]=$3; - raaddr[nra]=$6; - nra++; -} - -{ - if(savenext==1){ - l=sprintf("%d",$3) - udanummer[l-1]=nuda-1 - savenext=0; - } -} - - -{ - if(tmssavenext==1){ - l=sprintf("%d",$3) - tmsnummer[l-1]=ntmscp-1 - tmssavenext=0; - } - if(tssavenext==1){ - l=sprintf("%d",$3) - tsnummer[l-1]=nts-1 - tssavenext=0; - } -} - -/tmscp_cd/{ - tmscpplats[ntmscp]=$3; - tmscpaddr[ntmscp]=$6; - ntmscp++; - tmssavenext=1; -} - -/uda_cd/{ - udaplats[nuda]=$3; - udaddr[nuda]=$6; - nuda++; - savenext=1; -} - - -/};/{ - k=0; - m=0; -} - -{ - if (k==1){ - for(i=1;i<NF+1;i++){ - loc[loccnt+i]=$i; - } - loccnt+=NF; - } -} - -/static int loc/{ - k=1; - loccnt=0; -} - -{ - if(m==1){ - for(i=1;i<NF+1;i++){ - pv[i]=$i; - } - } -} - -/static short pv/{ - m=1; -} - -END{ - -printf "#include <sys/param.h>\n" -printf "#include <machine/pte.h>\n" -printf "#include <sys/buf.h>\n" -printf "#include <sys/map.h>\n" - -printf "#include <vax/uba/ubavar.h>\n" - -printf "int antal_ra=%d;\n",nra-1 -printf "int antal_uda=%d;\n",nuda-1 -printf "int antal_ts=%d;\n",nts-1 -printf "int antal_tms=%d;\n",ntms-1 -printf "int antal_tmscp=%d;\n",ntmscp-1 - -printf "extern struct uba_driver udadriver;\n" -if(nts) printf "extern struct uba_driver tsdriver;\n" -if(nts) printf "void tsintr();\n" -if(ntms) printf "extern struct uba_driver tmscpdriver;\n" -if(ntms) printf "void tmscpintr();\n" -printf "void udaintr();\n" -printf "int ra_cd=0, ra_ca=0, tms_cd=0, tms_ca=0;\n" -printf "#define C (caddr_t)\n" - -printf "struct uba_ctlr ubminit[]={\n" -for(i=1;i<nuda;i++){ - k=sprintf("%d",udaddr[i]) - printf " { &udadriver, %d,'?',0,udaintr,C %s},\n", - udaplats[i],loc[k+1] -} -for(i=1;i<nts;i++){ - k=sprintf("%d",tsaddr[i]) -if(nts)printf " { &tsdriver, %d,'?',0,tsintr,C %s},\n", - tsplats[i],loc[k+1] -} -for(i=1;i<ntmscp;i++){ - k=sprintf("%d",tmscpaddr[i]) -if(ntms)printf " { &tmscpdriver, %d,'?',0,tmscpintr,C %s},\n", - tmscpplats[i],loc[k+1] -} -printf "0};\n" - -printf "struct uba_device ubdinit[]={\n" -for(i=1;i<nra;i++){ - k=sprintf("%d",raaddr[i]) - printf " { &udadriver,%d,%d,'?',%d,0,0,1,0},\n",raplats[i], - rr++/4,loc[k+1] -} -for(i=1;i<nts;i++){ - k=sprintf("%d",tsaddr[i]) - printf " {&tsdriver,%d,0,'?',0,0,C 0,1,0},\n",tsplats[i] -} -for(i=1;i<ntms;i++){ - k=sprintf("%d",tmsaddr[i]) - printf " {&tmscpdriver,%d,0,'?',0,0,C 0,1,0},\n",tmsplats[i] -} -printf "0};\n" - -} - diff --git a/sys/arch/vax/conf/std.vax b/sys/arch/vax/conf/std.vax deleted file mode 100644 index ba605d9b4c6..00000000000 --- a/sys/arch/vax/conf/std.vax +++ /dev/null @@ -1,10 +0,0 @@ -# $NetBSD: std.vax,v 1.3 1995/02/13 00:41:59 ragge Exp $ -# -# Std vaxfiles -# -machine vax - -backplane0 at root - -options MAXFDESCS=2048 -options TIMEZONE=-60, DST=1 diff --git a/sys/arch/vax/if/if_de.c b/sys/arch/vax/if/if_de.c index 32098cb08b0..c6ffce37a89 100644 --- a/sys/arch/vax/if/if_de.c +++ b/sys/arch/vax/if/if_de.c @@ -1,4 +1,4 @@ -/* $NetBSD: if_de.c,v 1.21 1996/05/19 16:43:02 ragge Exp $ */ +/* $NetBSD: if_de.c,v 1.25 1996/11/15 03:11:19 thorpej Exp $ */ /* * Copyright (c) 1982, 1986, 1989 Regents of the University of California. @@ -206,7 +206,7 @@ deattach(parent, self, aux) addr->pcsr0 = PCSR0_RSET; (void)dewait(ds, "reset"); - ds->ds_ubaddr = uballoc(ds->ds_dev.dv_parent->dv_unit, + ds->ds_ubaddr = uballoc((void *)ds->ds_dev.dv_parent, (char *)&ds->ds_pcbb, sizeof (struct de_pcbb), 0); addr->pcsr2 = ds->ds_ubaddr & 0xffff; addr->pcsr3 = (ds->ds_ubaddr >> 16) & 0x3; @@ -217,7 +217,7 @@ deattach(parent, self, aux) addr->pclow = CMD_GETCMD; (void)dewait(ds, "read addr "); - ubarelse(ds->ds_dev.dv_parent->dv_unit, &ds->ds_ubaddr); + ubarelse((void *)ds->ds_dev.dv_parent, &ds->ds_ubaddr); bcopy((caddr_t)&ds->ds_pcbb.pcbb2, (caddr_t)ds->ds_addr, sizeof (ds->ds_addr)); printf("%s: hardware address %s\n", ds->ds_dev.dv_xname, @@ -273,14 +273,14 @@ deinit(ds) if (ds->ds_flags & DSF_RUNNING) return; if ((ifp->if_flags & IFF_RUNNING) == 0) { - if (if_ubaminit(&ds->ds_deuba, ds->ds_dev.dv_parent->dv_unit, + if (if_ubaminit(&ds->ds_deuba, (void *)ds->ds_dev.dv_parent, sizeof (struct ether_header), (int)btoc(ETHERMTU), ds->ds_ifr, NRCV, ds->ds_ifw, NXMT) == 0) { printf("%s: can't initialize\n", ds->ds_dev.dv_xname); ds->ds_if.if_flags &= ~IFF_UP; return; } - ds->ds_ubaddr = uballoc(ds->ds_dev.dv_parent->dv_unit, + ds->ds_ubaddr = uballoc((void *)ds->ds_dev.dv_parent, INCORE_BASE(ds), INCORE_SIZE(ds), 0); } addr = ds->ds_vaddr; @@ -383,9 +383,13 @@ destart(ifp) if (rp->r_flags & XFLG_OWN) panic("deuna xmit in progress"); len = if_ubaput(&ds->ds_deuba, &ds->ds_ifw[ds->ds_xfree], m); - if (ds->ds_deuba.iff_flags & UBA_NEEDBDP) - UBAPURGE(ds->ds_deuba.iff_uba, - ds->ds_ifw[ds->ds_xfree].ifw_bdp); + if (ds->ds_deuba.iff_flags & UBA_NEEDBDP) { + struct uba_softc *uh = (void *)ds->ds_dev.dv_parent; + + if (uh->uh_ubapurge) + (*uh->uh_ubapurge) + (uh, ds->ds_ifw[ds->ds_xfree].ifw_bdp); + } rp->r_slen = len; rp->r_tdrerr = 0; rp->r_flags = XFLG_STP|XFLG_ENP|XFLG_OWN; @@ -447,10 +451,15 @@ deintr(unit) if (rp->r_flags & XFLG_ERRS) { /* output error */ ds->ds_if.if_oerrors++; - if (dedebug) - printf("de%d: oerror, flags=%b tdrerr=%b (len=%d)\n", - unit, rp->r_flags, XFLG_BITS, - rp->r_tdrerr, XERR_BITS, rp->r_slen); + if (dedebug) { + char bits[64]; + printf("de%d: oerror, flags=%s ", + unit, bitmask_snprintf(rp->r_flags, + XFLG_BITS, bits, sizeof(bits))); + printf("tdrerr%s (len=%d)\n", + rp->r_tdrerr, XERR_BITS, + bits, sizeof(bits)); + } } else if (rp->r_flags & XFLG_ONE) { /* one collision */ ds->ds_if.if_collisions++; @@ -503,9 +512,13 @@ derecv(unit) rp = &ds->ds_rrent[ds->ds_rindex]; while ((rp->r_flags & RFLG_OWN) == 0) { ds->ds_if.if_ipackets++; - if (ds->ds_deuba.iff_flags & UBA_NEEDBDP) - UBAPURGE(ds->ds_deuba.iff_uba, - ds->ds_ifr[ds->ds_rindex].ifrw_bdp); + if (ds->ds_deuba.iff_flags & UBA_NEEDBDP) { + struct uba_softc *uh = (void *)ds->ds_dev.dv_parent; + + if (uh->uh_ubapurge) + (*uh->uh_ubapurge) + (uh,ds->ds_ifr[ds->ds_rindex].ifrw_bdp); + } len = (rp->r_lenerr&RERR_MLEN) - sizeof (struct ether_header) - 4; /* don't forget checksum! */ /* check for errors */ @@ -514,10 +527,16 @@ derecv(unit) (rp->r_lenerr & (RERR_BUFL|RERR_UBTO|RERR_NCHN)) || len < ETHERMIN || len > ETHERMTU) { ds->ds_if.if_ierrors++; - if (dedebug) - printf("de%d: ierror, flags=%b lenerr=%b (len=%d)\n", - unit, rp->r_flags, RFLG_BITS, rp->r_lenerr, - RERR_BITS, len); + if (dedebug) { + char bits[64]; + printf("de%d: ierror, flags=%s ", + unit, bitmask_snprintf(rp->r_flags, + RFLG_BITS, bits, sizeof(bits))); + printf("lenerr=%s (len=%d)\n", + bitmask_snprintf(rp->r_lenerr, + RERR_BITS, bits, sizeof(bits)), + len); + } } else deread(ds, &ds->ds_ifr[ds->ds_rindex], len); @@ -662,10 +681,13 @@ dewait(ds, fn) ; csr0 = addr->pcsr0; addr->pchigh = csr0 >> 8; - if (csr0 & PCSR0_PCEI) - printf("de%d: %s failed, csr0=%b csr1=%b\n", - ds->ds_dev.dv_unit, fn, csr0, PCSR0_BITS, - addr->pcsr1, PCSR1_BITS); + if (csr0 & PCSR0_PCEI) { + char bits[64]; + printf("de%d: %s failed, csr0=%s ", ds->ds_dev.dv_unit, fn, + bitmask_snprintf(csr0, PCSR0_BITS, bits, sizeof(bits))); + printf("csr1=%s\n", bitmask_snprintf(addr->pcsr1, PCSR1_BITS, + bits, sizeof(bits))); + } return (csr0 & PCSR0_PCEI); } diff --git a/sys/arch/vax/if/if_le.c b/sys/arch/vax/if/if_le.c new file mode 100644 index 00000000000..a41d5db2edf --- /dev/null +++ b/sys/arch/vax/if/if_le.c @@ -0,0 +1,238 @@ +/* $NetBSD: if_le.c,v 1.3 1996/10/13 03:34:53 christos Exp $ */ + +#define LEDEBUG 1 /* debug-level: 0 or 1 */ +/* #define LE_CHIP_IS_POKEY /* does VS2000 need this ??? */ + +/*- + * Copyright (c) 1995 Charles M. Hannum. All rights reserved. + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Ralph Campbell and Rick Macklem. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)if_le.c 8.2 (Berkeley) 11/16/93 + */ + +#include "bpfilter.h" + +#include <sys/param.h> +#include <sys/syslog.h> +#include <sys/socket.h> +#include <sys/device.h> + +#include <net/if.h> + +#if INET +#include <netinet/in.h> +#include <netinet/if_ether.h> +#endif + +/* + * This would be nice, but it's not yet there... + * + * #include <machine/autoconf.h> + */ + +#include <machine/pte.h> +#include <machine/cpu.h> +#include <machine/mtpr.h> +#include <machine/uvax.h> +#include <machine/ka410.h> +#include <machine/vsbus.h> + +#include <dev/ic/am7990reg.h> +#define LE_NEED_BUF_CONTIG +#include <dev/ic/am7990var.h> + +#include <dev/tc/if_levar.h> + +#define xdebug(x) + +#ifdef LE_CHIP_IS_POKEY +/* + * access LANCE registers and double-check their contents + */ +#define wbflush() /* do nothing */ +void lewritereg(); +#define LERDWR(cntl, src, dst) { (dst) = (src); wbflush(); } +#define LEWREG(src, dst) lewritereg(&(dst), (src)) +#endif + +#define LE_IOSIZE 64*1024 /* 64K of real-mem are reserved and already */ +extern void *le_iomem; /* mapped into virt-mem by cpu_steal_pages */ +extern u_long le_ioaddr; /* le_iomem is virt, le_ioaddr is phys */ + +#define LE_SOFTC(unit) le_cd.cd_devs[unit] +#define LE_DELAY(x) DELAY(x) + +int lematch __P((struct device *, void *, void *)); +void leattach __P((struct device *, struct device *, void *)); + +int leintr __P((void *sc)); + +struct cfattach le_ca = { + sizeof(struct le_softc), lematch, leattach +}; + +integrate void +lewrcsr(sc, port, val) + struct le_softc *sc; + u_int16_t port, val; +{ + struct lereg1 *ler1 = sc->sc_r1; + +#ifdef LE_CHIP_IS_POKEY + LEWREG(port, ler1->ler1_rap); + LERDWR(port, val, ler1->ler1_rdp); +#else + ler1->ler1_rap = port; + ler1->ler1_rdp = val; +#endif +} + +integrate u_int16_t +lerdcsr(sc, port) + struct le_softc *sc; + u_int16_t port; +{ + struct lereg1 *ler1 = sc->sc_r1; + u_int16_t val; + +#ifdef LE_CHIP_IS_POKEY + LEWREG(port, ler1->ler1_rap); + LERDWR(0, ler1->ler1_rdp, val); +#else + ler1->ler1_rap = port; + val = ler1->ler1_rdp; +#endif + return (val); +} + +int +lematch(parent, match, aux) + struct device *parent; + void *match, *aux; +{ + struct cfdata *cf = match; + struct confargs *ca = aux; + + /* + * There could/should be more checks, but for now... + */ + if (strcmp(ca->ca_name, "le") && + strcmp(ca->ca_name, "am7990") && + strcmp(ca->ca_name, "AM7990")) + return (0); + + return (1); +} + +/* + * + */ +void +leattach(parent, self, aux) + struct device *parent, *self; + void *aux; +{ + register struct le_softc *sc = (void *)self; + struct confargs *ca = aux; + u_char *cp; /* pointer to MAC address */ + int i; + + sc->sc_r1 = (void*)uvax_phys2virt(ca->ca_ioaddr); + + sc->sc_am7990.sc_conf3 = 0; + sc->sc_am7990.sc_mem = le_iomem; + sc->sc_am7990.sc_addr = le_ioaddr; + sc->sc_am7990.sc_memsize = LE_IOSIZE; + + xdebug(("leattach: mem=%x, addr=%x, size=%x (%d)\n", + sc->sc_am7990.sc_mem, sc->sc_am7990.sc_addr, + sc->sc_am7990.sc_memsize, sc->sc_am7990.sc_memsize)); + + sc->sc_am7990.sc_copytodesc = am7990_copytobuf_contig; + sc->sc_am7990.sc_copyfromdesc = am7990_copyfrombuf_contig; + sc->sc_am7990.sc_copytobuf = am7990_copytobuf_contig; + sc->sc_am7990.sc_copyfrombuf = am7990_copyfrombuf_contig; + sc->sc_am7990.sc_zerobuf = am7990_zerobuf_contig; + + /* + * Get the ethernet address out of rom + */ + for (i = 0; i < sizeof(sc->sc_am7990.sc_arpcom.ac_enaddr); i++) { + int *eaddr = (void*)uvax_phys2virt(ca->ca_enaddr); + sc->sc_am7990.sc_arpcom.ac_enaddr[i] = (u_char)eaddr[i]; + } + + bcopy(self->dv_xname, sc->sc_am7990.sc_arpcom.ac_if.if_xname, IFNAMSIZ); + am7990_config(&sc->sc_am7990); + +#ifdef LEDEBUG + sc->sc_am7990.sc_debug = LEDEBUG; +#endif + + vsbus_intr_register(ca, am7990_intr, &sc->sc_am7990); + vsbus_intr_enable(ca); +} + +integrate void +lehwinit(sc) + struct le_softc *sc; +{ +} + +#ifdef LE_CHIP_IS_POKEY +/* + * Write a lance register port, reading it back to ensure success. This seems + * to be necessary during initialization, since the chip appears to be a bit + * pokey sometimes. + */ +void +lewritereg(regptr, val) + register volatile u_short *regptr; + register u_short val; +{ + register int i = 0; + + while (*regptr != val) { + *regptr = val; + wbflush(); + if (++i > 10000) { + printf("le: Reg did not settle (to x%x): x%x\n", val, + *regptr); + return; + } + DELAY(100); + } +} +#endif diff --git a/sys/arch/vax/if/if_qe.c b/sys/arch/vax/if/if_qe.c index cb5fedd8029..8c150fb3d44 100644 --- a/sys/arch/vax/if/if_qe.c +++ b/sys/arch/vax/if/if_qe.c @@ -1,4 +1,4 @@ -/* $NetBSD: if_qe.c,v 1.15 1996/05/19 16:43:07 ragge Exp $ */ +/* $NetBSD: if_qe.c,v 1.18 1996/10/13 03:34:55 christos Exp $ */ /* * Copyright (c) 1988 Regents of the University of California. @@ -290,8 +290,8 @@ qematch(parent, match, aux) * Map the communications area and the setup packet. */ sc->setupaddr = - uballoc(0, (caddr_t)sc->setup_pkt, sizeof(sc->setup_pkt), 0); - sc->rringaddr = (struct qe_ring *) uballoc(0, (caddr_t)sc->rring, + uballoc(ubasc, (caddr_t)sc->setup_pkt, sizeof(sc->setup_pkt), 0); + sc->rringaddr = (struct qe_ring *) uballoc(ubasc, (caddr_t)sc->rring, sizeof(struct qe_ring) * (NTOT+2), 0); prp = (struct qe_ring *)UBAI_ADDR((int)sc->rringaddr); @@ -338,8 +338,8 @@ qematch(parent, match, aux) /* * All done with the bus resources. */ - ubarelse(0, &sc->setupaddr); - ubarelse(0, (int *)&sc->rringaddr); + ubarelse(ubasc, &sc->setupaddr); + ubarelse(ubasc, (int *)&sc->rringaddr); sc->ipl = 0x15; ua->ua_ivec = qeintr; return 1; @@ -418,6 +418,7 @@ qeinit(sc) struct qe_softc *sc; { struct qedevice *addr = sc->qe_vaddr; + struct uba_softc *ubasc = (void *)sc->qe_dev.dv_parent; struct ifnet *ifp = (struct ifnet *)&sc->qe_if; int i; int s; @@ -432,13 +433,13 @@ qeinit(sc) /* * map the communications area onto the device */ - i = uballoc(0, (caddr_t)sc->rring, + i = uballoc(ubasc, (caddr_t)sc->rring, sizeof(struct qe_ring) * (NTOT+2), 0); if (i == 0) goto fail; sc->rringaddr = (struct qe_ring *)UBAI_ADDR(i); sc->tringaddr = sc->rringaddr + NRCV + 1; - i = uballoc(0, (caddr_t)sc->setup_pkt, + i = uballoc(ubasc, (caddr_t)sc->setup_pkt, sizeof(sc->setup_pkt), 0); if (i == 0) goto fail; @@ -446,7 +447,7 @@ qeinit(sc) /* * init buffers and maps */ - if (if_ubaminit(&sc->qe_uba, sc->qe_dev.dv_parent->dv_unit, + if (if_ubaminit(&sc->qe_uba, (void *)sc->qe_dev.dv_parent, sizeof (struct ether_header), (int)btoc(MAXPACKETSIZE), sc->qe_ifr, NRCV, sc->qe_ifw, NXMT) == 0) { fail: diff --git a/sys/arch/vax/if/if_uba.c b/sys/arch/vax/if/if_uba.c index 5c793de044c..4b023563c78 100644 --- a/sys/arch/vax/if/if_uba.c +++ b/sys/arch/vax/if/if_uba.c @@ -1,4 +1,4 @@ -/* $NetBSD: if_uba.c,v 1.11 1996/03/17 22:56:36 ragge Exp $ */ +/* $NetBSD: if_uba.c,v 1.12 1996/08/20 14:07:46 ragge Exp $ */ /* * Copyright (c) 1982, 1986, 1988 Regents of the University of California. @@ -50,7 +50,7 @@ #include <machine/pte.h> #include <machine/mtpr.h> #include <machine/vmparam.h> -#include <machine/macros.h> +#include <machine/cpu.h> #include <vax/if/if_uba.h> #include <vax/uba/ubareg.h> @@ -68,20 +68,20 @@ static void restor_xmtbuf __P((struct ifxmt *)); */ /* - * Init UNIBUS for interface on uban whose headers of size hlen are to + * Init UNIBUS for interface whose headers of size hlen are to * end on a page boundary. We allocate a UNIBUS map register for the page * with the header, and nmr more UNIBUS map registers for i/o on the adapter, * doing this once for each read and once for each write buffer. We also * allocate page frames in the mbuffer pool for these pages. */ int -if_ubaminit(ifu, uban, hlen, nmr, ifr, nr, ifw, nw) +if_ubaminit(ifu, uh, hlen, nmr, ifr, nr, ifw, nw) register struct ifubinfo *ifu; - int uban, hlen, nmr, nr, nw; + struct uba_softc *uh; + int hlen, nmr, nr, nw; register struct ifrw *ifr; register struct ifxmt *ifw; { - struct uba_softc *ubasc; register caddr_t p; caddr_t cp; int i, nclbytes, off; @@ -111,10 +111,9 @@ if_ubaminit(ifu, uban, hlen, nmr, ifr, nr, ifw, nw) p += nclbytes; } ifu->iff_hlen = hlen; - ifu->iff_uban = uban; - ubasc = uba_cd.cd_devs[uban]; - ifu->iff_uba = ubasc->uh_uba; - ifu->iff_ubamr = ubasc->uh_mr; + ifu->iff_softc = uh; + ifu->iff_uba = uh->uh_uba; + ifu->iff_ubamr = uh->uh_mr; } for (i = 0; i < nr; i++) if (if_ubaalloc(ifu, &ifr[i], nmr) == 0) { @@ -137,9 +136,9 @@ if_ubaminit(ifu, uban, hlen, nmr, ifr, nr, ifw, nw) return (1); bad: while (--nw >= 0) - ubarelse(ifu->iff_uban, &ifw[nw].ifw_info); + ubarelse(ifu->iff_softc, &ifw[nw].ifw_info); while (--nr >= 0) - ubarelse(ifu->iff_uban, &ifr[nr].ifrw_info); + ubarelse(ifu->iff_softc, &ifr[nr].ifrw_info); free(cp, M_DEVBUF); ifr[0].ifrw_addr = 0; return (0); @@ -159,7 +158,7 @@ if_ubaalloc(ifu, ifrw, nmr) register int info; info = - uballoc(ifu->iff_uban, ifrw->ifrw_addr, nmr*NBPG + ifu->iff_hlen, + uballoc(ifu->iff_softc, ifrw->ifrw_addr, nmr*NBPG + ifu->iff_hlen, ifu->iff_flags); if (info == 0) return (0); diff --git a/sys/arch/vax/if/if_uba.h b/sys/arch/vax/if/if_uba.h index 8b425fd98f0..5ae8c5170ab 100644 --- a/sys/arch/vax/if/if_uba.h +++ b/sys/arch/vax/if/if_uba.h @@ -1,4 +1,4 @@ -/* $NetBSD: if_uba.h,v 1.5 1996/04/08 18:34:57 ragge Exp $ */ +/* $NetBSD: if_uba.h,v 1.6 1996/08/20 14:07:50 ragge Exp $ */ /* * Copyright (c) 1982, 1986 Regents of the University of California. @@ -68,11 +68,11 @@ * Information per interface. */ struct ifubinfo { - short iff_uban; /* uba number */ + short iff_flags; /* used during uballoc's */ short iff_hlen; /* local net header length */ struct uba_regs *iff_uba; /* uba adaptor regs, in vm */ struct pte *iff_ubamr; /* uba map regs, in vm */ - short iff_flags; /* used during uballoc's */ + struct uba_softc *iff_softc; /* uba */ }; /* @@ -116,7 +116,7 @@ struct ifuba { struct ifxmt ifu_xmt; }; -#define ifu_uban ifu_info.iff_uban +#define ifu_softc ifu_info.iff_softc #define ifu_hlen ifu_info.iff_hlen #define ifu_uba ifu_info.iff_uba #define ifu_ubamr ifu_info.iff_ubamr @@ -134,7 +134,7 @@ struct ifuba { if_ubaput(&(ifu)->ifu_info, &(ifu)->ifu_xmt, m) /* Prototypes */ -int if_ubaminit __P((struct ifubinfo *, int, int, int, +int if_ubaminit __P((struct ifubinfo *, struct uba_softc *, int, int, struct ifrw *, int, struct ifxmt *, int)); int if_ubaput __P((struct ifubinfo *, struct ifxmt *, struct mbuf *)); struct mbuf *if_ubaget __P((struct ifubinfo *, struct ifrw *, int, diff --git a/sys/arch/vax/include/ansi.h b/sys/arch/vax/include/ansi.h index 088f4a3dbec..a9ded0b66e0 100644 --- a/sys/arch/vax/include/ansi.h +++ b/sys/arch/vax/include/ansi.h @@ -1,4 +1,4 @@ -/* $NetBSD: ansi.h,v 1.4 1996/03/16 01:32:03 jtc Exp $ */ +/* $NetBSD: ansi.h,v 1.5 1996/11/15 22:39:01 jtc Exp $ */ /*- * Copyright (c) 1990 The Regents of the University of California. @@ -57,5 +57,8 @@ #define _BSD_VA_LIST_ char * /* va_list */ #define _BSD_WCHAR_T_ int /* wchar_t */ #define _BSD_WINT_T_ int /* wint_t */ +#define _BSD_CLOCKID_T_ int +#define _BSD_TIMER_T_ int + #endif /* _ANSI_H_ */ diff --git a/sys/arch/vax/include/aout_machdep.h b/sys/arch/vax/include/aout_machdep.h new file mode 100644 index 00000000000..3d34ccc79e5 --- /dev/null +++ b/sys/arch/vax/include/aout_machdep.h @@ -0,0 +1,49 @@ +/* $NetBSD: aout_machdep.h,v 1.4 1995/09/23 14:57:40 ragge Exp $ */ + +/* + * Copyright (c) 1993 Christopher G. Demetriou + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _VAX_EXEC_H_ +#define _VAX_EXEC_H_ + +#define __LDPGSZ 1024 + +/* Relocation format. */ +struct relocation_info_vax { + int r_address; /* offset in text or data segment */ + unsigned int r_symbolnum : 24, /* ordinal number of add symbol */ + r_pcrel : 1, /* 1 if value should be pc-relative */ + r_length : 2, /* log base 2 of value's width */ + r_extern : 1, /* 1 if need to add symbol to value */ + r_baserel : 1, /* linkage table relative */ + r_jmptable : 1, /* relocate to jump table */ + r_relative : 1, /* load address relative */ + r_copy : 1; /* run time copy */ +}; +#define relocation_info relocation_info_vax + +#endif /* _VAX_EXEC_H_ */ diff --git a/sys/arch/vax/include/asm.h b/sys/arch/vax/include/asm.h index b77cf3d421a..b97107d906e 100644 --- a/sys/arch/vax/include/asm.h +++ b/sys/arch/vax/include/asm.h @@ -1,4 +1,4 @@ -/* $NetBSD: asm.h,v 1.4 1996/01/06 18:37:35 ragge Exp $ */ +/* $NetBSD: asm.h,v 1.5 1996/11/30 02:49:06 jtc Exp $ */ /* * Copyright (c) 1982, 1993 * The Regents of the University of California. All rights reserved. @@ -51,7 +51,7 @@ #define R11 0x800 #ifdef __STDC__ -#ifdef PROF +#ifdef GPROF #define ENTRY(x, regs) \ .globl _ ## x ## ; .align 2; _ ## x ## : .word regs; \ .data; 1:; .long 0; .text; moval 1b,r0; jsb mcount @@ -65,7 +65,7 @@ .globl x; .align 2; x ## : .word regs #endif # else -#ifdef PROF +#ifdef GPROF #define ENTRY(x, regs) \ .globl _/**/x; .align 2; _/**/x: .word regs; \ .data; 1:; .long 0; .text; moval 1b,r0; jsb mcount diff --git a/sys/arch/vax/include/clock.h b/sys/arch/vax/include/clock.h new file mode 100644 index 00000000000..28bffbe9a13 --- /dev/null +++ b/sys/arch/vax/include/clock.h @@ -0,0 +1,69 @@ +/* $NetBSD: clock.h,v 1.1 1996/07/20 17:35:42 ragge Exp $ */ +/* + * Copyright (c) 1996 Ludd, University of Lule}, Sweden. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed at Ludd, University of + * Lule}, Sweden and its contributors. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +/* + * Conversion structure. + */ +struct chiptime { + long sec; + long min; + long hour; + long day; + long mon; + long year; +}; + +/* + * Time constants. These are unlikely to change. + */ +#define IS_LEAPYEAR(y) (((y % 4) == 0) && (y % 100)) + +#define SEC_PER_MIN (60) +#define SEC_PER_HOUR (SEC_PER_MIN * 60) +#define SEC_PER_DAY (SEC_PER_HOUR * 24) +#define DAYSPERYEAR(y) (IS_LEAPYEAR(y) ? 366 : 365) +#define SECPERYEAR(y) (DAYSPERYEAR(y) * SEC_PER_DAY) + +#define CLKREAD_OK 0 +#define CLKREAD_BAD -1 +#define CLKREAD_WARN -2 + +#define TODRBASE (1 << 28) /* Rumours says it comes from VMS */ + +/* Prototypes */ +long chiptotime __P((struct chiptime *)); +void timetochip __P((struct chiptime *)); +void generic_clock __P((void)); +void no_nicr_clock __P((void)); +int generic_clkread __P((time_t)); +void generic_clkwrite __P((void)); diff --git a/sys/arch/vax/include/cpu.h b/sys/arch/vax/include/cpu.h index a99710bd042..b928a64d131 100644 --- a/sys/arch/vax/include/cpu.h +++ b/sys/arch/vax/include/cpu.h @@ -1,4 +1,4 @@ -/* $NetBSD: cpu.h,v 1.17 1996/05/19 16:43:16 ragge Exp $ */ +/* $NetBSD: cpu.h,v 1.19 1996/07/20 17:58:12 ragge Exp $ */ /* * Copyright (c) 1994 Ludd, University of Lule}, Sweden @@ -42,17 +42,17 @@ #define cpu_wait(p) #define cpu_swapout(p) - -extern int cpunumber, cpu_type; extern struct cpu_dep cpu_calls[]; struct cpu_dep { void (*cpu_steal_pages) __P((void)); /* pmap init before mm is on */ - int (*cpu_clock) __P((void)); /* CPU dependent clock handling */ + void (*cpu_clock) __P((void)); /* CPU dep RT clock start */ int (*cpu_mchk) __P((caddr_t)); /* Machine check handling */ void (*cpu_memerr) __P((void)); /* Memory subsystem errors */ /* Autoconfiguration */ void (*cpu_conf) __P((struct device *, struct device *, void *)); + int (*cpu_clkread) __P((time_t)); /* Read cpu clock time */ + void (*cpu_clkwrite) __P((void)); /* Write system time to cpu */ }; struct clockframe { @@ -60,9 +60,12 @@ struct clockframe { int ps; }; +extern int cold; +extern int mastercpu; + #define setsoftnet() mtpr(12,PR_SIRR) #define setsoftclock() mtpr(8,PR_SIRR) - +#define todr() mfpr(PR_TODR) /* * Preempt the current process if in interrupt from user mode, * or after the current trap/syscall if in system mode. @@ -93,7 +96,8 @@ extern int want_resched; /* resched() was called */ int badaddr __P((caddr_t, int)); void cpu_set_kpc __P((struct proc *, void (*)(struct proc *))); void cpu_swapin __P((struct proc *)); -int hp_getdev __P((int, int)); +int hp_getdev __P((int, int, char **)); +int ra_getdev __P((int, int, int, char **)); void configure __P((void)); void dumpconf __P((void)); void dumpsys __P((void)); diff --git a/sys/arch/vax/include/endian.h b/sys/arch/vax/include/endian.h index ac0699c9329..02e1fee60a0 100644 --- a/sys/arch/vax/include/endian.h +++ b/sys/arch/vax/include/endian.h @@ -1,5 +1,5 @@ -/* $OpenBSD: endian.h,v 1.3 1996/11/25 13:11:40 niklas Exp $ */ -/* $NetBSD: endian.h,v 1.7 1996/04/08 18:35:48 ragge Exp $ */ +/* $OpenBSD: endian.h,v 1.4 1997/01/15 23:24:37 maja Exp $ */ +/* $NetBSD: endian.h,v 1.8 1996/10/13 03:28:00 christos Exp $ */ /* * Copyright (c) 1987, 1991 Regents of the University of California. diff --git a/sys/arch/vax/include/ka410.h b/sys/arch/vax/include/ka410.h new file mode 100644 index 00000000000..379cf984057 --- /dev/null +++ b/sys/arch/vax/include/ka410.h @@ -0,0 +1,212 @@ +/* $NetBSD: ka410.h,v 1.1 1996/07/20 17:58:14 ragge Exp $ */ +/* + * Copyright (c) 1996 Ludd, University of Lule}, Sweden. + * All rights reserved. + * + * This code is derived from software contributed to Ludd by Bertram Barth. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed at Ludd, University of + * Lule}, Sweden and its contributors. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Definition for I/O addresses of + * + * MicroVAX 2000 (TeamMate) + * VAXstation 2000 (VAXstar) + */ + +#define KA410_SIDEX 0x20040004 /* SID extension register */ + +#define KA410_CFGTST 0x20020000 /* Configuration and Test register */ +#define KA410_IORESET 0x20020000 /* I/O Reset register */ + +#define KA410_ROM_BASE 0x20040000 /* System module ROM */ +#define KA410_ROM_END 0x2007FFFF +#define KA410_ROM_SIZE 0x40000 + +#define KA410_IVN_BASE 0x20040020 /* Interrupt Vector Numbers */ +#define KA410_IVN_END 0x2004003F +#define KA410_IVN_SIZE 0x20 + +#define KA410_HLTCOD 0x20080000 /* Halt Code Register */ +#define KA410_MSER 0x20080004 /* Memory System Error register */ +#define KA410_MEAR 0x20080008 /* Memory Error Address register */ +#define KA410_INTMSK 0x2008000C /* Interrupt Mask register */ +#define KA410_VDCORG 0x2008000D /* Video Controller Origin Register */ +#define KA410_VDCSEL 0x2008000E /* Video Controller Select Register */ +#define KA410_INTREQ 0x2008000F /* Interrupt Request register */ +#define KA410_INTCLR 0x2008000F /* Interrupt Request clear register */ + +/* + * Other fixed addresses which should be mapped + */ +#define KA410_CPU_BASE 0x20080000 +#define KA410_CPU_END 0x200800FF +#define KA410_CPU_SIZE 0x100 +#define KA410_NWA_BASE 0x20090000 /* Network Address ROM */ +#define KA410_NWA_END 0x2009007F +#define KA410_NWA_SIZE 0x80 +#define KA410_SER_BASE 0x200A0000 /* Serial line controller */ +#define KA410_SER_END 0x200A000F +#define KA410_SER_SIZE 0x10 +#define KA410_WAT_BASE 0x200B0000 /* TOY clock and NV-RAM */ +#define KA410_WAT_END 0x200B00FF +#define KA410_WAT_SIZE 0x100 +#define KA410_DKC_BASE 0x200C0000 /* Disk Controller Ports */ +#define KA410_DKC_END 0x200C0007 +#define KA410_DKC_SIZE 0x08 +#define KA410_SCS_BASE 0x200C0080 /* Tape (SCSI) Controller Chip */ +#define KA410_SCS_END 0x200C009F +#define KA410_SCS_SIZE 0x20 +#define KA410_DMA_BASE 0x200D0000 /* Disk Data buffer RAM */ +#define KA410_DMA_END 0x200D3FFF +#define KA410_DMA_SIZE 0x4000 +#define KA410_LAN_BASE 0x200E0000 /* LANCE chip registers */ +#define KA410_LAN_END 0x200E0007 +#define KA410_LAN_SIZE 0x08 +#define KA410_CUR_BASE 0x200F0000 /* Monochrome video cursor chip */ +#define KA410_CUR_END 0x200F0007 +#define KA410_CUR_SIZE 0x08 + +#define KA410_SCS_DADR 0x200C00A0 /* Tape(SCSI) DMA address register */ +#define KA410_SCS_DCNT 0x200C00C0 /* Tape(SCSI) DMA byte count reg. */ +#define KA410_SCS_DDIR 0x200C00C4 /* Tape(SCSI) DMA transfer direction */ + +#define KA410_CUR_CMD 0x200F0000 /* Cursor Command Register */ +#define KA410_CUR_XPOS 0x200F0004 /* Cursor X position */ +#define KA410_CUR_YPOS 0x200F0008 /* Cursor Y position */ + +#define KA410_CUR_XMIN1 0x200F000C /* Region 1 left edge */ +#define KA410_CUR_XMAX1 0x200F0010 /* Region 1 right edge */ +#define KA410_CUR_YMIN1 0x200F0014 /* Region 1 top edge */ +#define KA410_CUR_YMAX1 0x200F0018 /* Region 1 bottom edge */ + +#define KA410_CUR_XMIN2 0x200F002C /* Region 2 left edge */ +#define KA410_CUR_XMAX2 0x200F0030 /* Region 2 right edge */ +#define KA410_CUR_YMIN2 0x200F0034 /* Region 2 top edge */ +#define KA410_CUR_YMAX2 0x200F0038 /* Region 2 bottom edge */ + +/* + * Definitions for the Configuration and Test Register + */ +#define KA410_CFG_MULTU 0x80 /* MicroVAX or VAXstation */ +#define KA410_CFG_NETOPT 0x40 /* Network option present */ +#define KA410_CFG_L3CON 0x20 /* Console on line #3 of dc */ +#define KA410_CFG_CURTEST 0x10 /* Cursor Test (monochrom) */ +#define KA410_CFG_VIDOPT 0x08 /* Video option present */ +#define KA410_CFG_MEMSZ 0x07 /* Memory option type/size */ + +#define KA410_CFG_0MB 0x00 /* No additional Memory board */ +#define KA410_CFG_1MB 0x01 +#define KA410_CFG_2MB 0x02 +#define KA410_CFG_4MB 0x03 +#define KA410_CFG_6MB 0x04 +#define KA410_CFG_8MB 0x05 +#define KA410_CFG_12MB 0x06 +#define KA410_CFG_14MB 0x07 + + +/* + * interrupt request-, clear-, and mask register + */ +extern volatile unsigned char *ka410_intreq; +extern volatile unsigned char *ka410_intclr; +extern volatile unsigned char *ka410_intmsk; + +#define INTR_SR (1<<7) /* Serial line receiver or silo full */ +#define INTR_ST (1<<6) /* Serial line transmitter done */ +#define INTR_NP (1<<5) /* Network controller primary */ +#define INTR_NS (1<<4) /* Network controller secondary */ +#define INTR_VF (1<<3) /* Video end of frame */ +#define INTR_VS (1<<2) /* Video secondary */ +#define INTR_SC (1<<1) /* SCSI controller */ +#define INTR_DC (1<<0) /* Disk controller */ + +/* + * interrupt vector numbers + */ +#define IVEC_BASE 0x20040020 +#define IVEC_SR 0x000002C0 +#define IVEC_ST 0x000002C4 +#define IVEC_NP 0x00000250 +#define IVEC_NS 0x00000254 +#define IVEC_VF 0x00000244 +#define IVEC_VS 0x00000248 +#define IVEC_SC 0x000003F8 +#define IVEC_DC 0x000003FC + +/* + * Clock-Chip data in NVRAM + */ +#define KA410_CPMBX 0x200B0038 /* Console Mailbox (1 byte) */ +#define KA410_CPFLG 0x200B003C /* Console Program Flags (1 byte) */ +#define KA410_LK201_ID 0x200B0040 /* Keyboard Variation (1 byte) */ +#define KA410_CONS_ID 0x200B0044 /* Console Device Type (1 byte) */ +#define KA410_SCR 0x200B0048 /* Console Scratch RAM */ +#define KA410_TEMP 0x200B0058 /* Used by System Firmware */ +#define KA410_BAT_CHK 0x200B0088 /* Battery Check Data */ +#define KA410_BOOTDEV 0x200B0098 /* Default Boot Device (4 bytes) */ +#define KA410_BOOTFLG 0x200B00A8 /* Default Boot Flags (4 bytes) */ +#define KA410_SCRLEN 0x200B00B8 /* Number of pages of SCR (1 byte) */ +#define KA410_SCSIPORT 0x200B00BC /* Tape Controller Port Data */ +#define KA410_RESERVED 0x200B00C0 /* Reserved (16 bytes) */ + + +struct ka410_cpu { + u_long ka410_hltcod; + u_long ka410_mser; + u_long ka410_cear; + u_long ka410_intmsk; +}; + +/* + * KA410 uses bits 2-9 of longwords to store single bytes in NVRAM, + * thus we declare the clock as an struct of bit-fields, so that the + * generic clock-routines work for KA410... + */ +struct ka410_clock { + u_long :2; u_long sec :8; u_long :22; + u_long :2; u_long secalrm :8; u_long :22; + u_long :2; u_long min :8; u_long :22; + u_long :2; u_long minalrm :8; u_long :22; + u_long :2; u_long hr :8; u_long :22; + u_long :2; u_long hralrm :8; u_long :22; + u_long :2; u_long dayofwk :8; u_long :22; + u_long :2; u_long day :8; u_long :22; + u_long :2; u_long mon :8; u_long :22; + u_long :2; u_long yr :8; u_long :22; + u_long :2; u_long csr0 :8; u_long :22; + u_long :2; u_long csr1 :8; u_long :22; + u_long :2; u_long csr2 :8; u_long :22; + u_long :2; u_long csr3 :8; u_long :22; + u_long :2; u_long cpmbx :8; u_long :22; +}; + +/* Prototypes */ +int ka410_setup __P((struct uvax_calls *p, int flags)); +static int ka410_clkread __P((time_t)); +static void ka410_clkwrite __P((void)); diff --git a/sys/arch/vax/include/ka420.h b/sys/arch/vax/include/ka420.h new file mode 100644 index 00000000000..ed1fa240782 --- /dev/null +++ b/sys/arch/vax/include/ka420.h @@ -0,0 +1,140 @@ +/* $NetBSD: ka420.h,v 1.1 1996/07/20 17:58:15 ragge Exp $ */ +/* + * Copyright (c) 1996 Ludd, University of Lule}, Sweden. + * All rights reserved. + * + * This code is derived from software contributed to Ludd by Bertram Barth. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed at Ludd, University of + * Lule}, Sweden and its contributors. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Definitions for I/O addresses of + * + * VAXstation 3100 models 30, 40 (PVAX) + * MicroVAX 3100 models 10, 20 (Teammate II) + * MicroVAX 3100 models 10e, 20e (Teammate II) + * VAXstation 3100 models 38, 48 (PVAX rev#7) + */ + +#define KA420_SIDEX 0x20040004 /* SID extension register */ + +#define KA420_CH2_BASE 0x10000000 /* 2nd level cache data area */ +#define KA420_CH2_END 0x10007FFF +#define KA420_CH2_SIZE 0x8000 +#define KA420_CT2_BASE 0x10010000 /* 2nd level cache tag area */ +#define KA420_CT2_END 0x10017FFF +#define KA420_CT2_SIZE 0x8000 +#define KA420_CH2_CREG 0x20084000 /* 2nd level cache control register */ + +#define KA420_CFGTST 0x20020000 /* Configuration and Test register */ +#define KA420_IORESET 0x20020000 /* I/O Reset register */ + +#define KA420_ROM_BASE 0x20040000 /* System module ROM */ +#define KA420_ROM_END 0x2007FFFF +#define KA420_ROM_SIZE 0x40000 /* ??? */ + +#define KA420_IVN_BASE 0x20040020 /* Interrupt Vector Numbers */ +#define KA420_IVN_END 0x2004003F +#define KA420_IVN_SIZE 0x20 + +#define KA420_HLTCOD 0x20080000 /* Halt Code Register */ +#define KA420_MSER 0x20080004 /* Memory System Error register */ +#define KA420_MEAR 0x20080008 /* Memory Error Address register */ +#define KA420_INTMSK 0x2008000C /* Interrupt Mask register */ +#define KA420_VDCORG 0x2008000D /* Video Controller Origin Register */ +#define KA420_VDCSEL 0x2008000E /* Video Controller Select Register */ +#define KA420_INTREQ 0x2008000F /* Interrupt Request register */ +#define KA420_INTCLR 0x2008000F /* Interrupt Request clear register */ + +/* + * Other fixed addresses which should be mapped + */ +#define KA420_NWA_BASE 0x20090000 /* Network Address ROM */ +#define KA420_NWA_END 0x2009007F +#define KA420_NWA_SIZE 0x80 +#define KA420_SER_BASE 0x200A0000 /* Serial line controller */ +#define KA420_SER_END 0x200A000F +#define KA420_SER_SIZE 0x10 +#define KA420_WAT_BASE 0x200B0000 /* TOY clock and NV-RAM */ +#define KA420_WAT_END 0x200B00FF +#define KA420_WAT_SIZE 0x100 +#define KA420_DKC_BASE 0x200C0000 /* Disk Controller Ports */ +#define KA420_DKC_END 0x200C0007 +#define KA420_DKC_SIZE 0x08 +#define KA420_SCS_BASE 0x200C0080 /* Tape (SCSI) Controller Chip */ +#define KA420_SCS_END 0x200C009F +#define KA420_SCS_SIZE 0x20 +#define KA420_D16_BASE 0x200D0000 /* 16KB (compatibility) Data Buffer */ +#define KA420_D16_END 0x200D3FFF +#define KA420_D16_SIZE 0x4000 +#define KA420_LAN_BASE 0x200E0000 /* LANCE chip registers */ +#define KA420_LAN_END 0x200E0007 +#define KA420_LAN_SIZE 0x08 +#define KA420_CUR_BASE 0x200F0000 /* Monochrome video cursor chip */ +#define KA420_CUR_END 0x200F0007 +#define KA420_CUR_SIZE 0x08 +#define KA420_DMA_BASE 0x202D0000 /* 128KB Data Buffer */ +#define KA420_DMA_END 0x202EFFFF +#define KA420_DMA_SIZE 0x20000 + +#define KA420_SCD_DADR 0x200C00A0 /* Tape(SCSI) DMA address register */ +#define KA420_SCD_DCNT 0x200C00C0 /* Tape(SCSI) DMA byte count reg. */ +#define KA420_SCD_DDIR 0x200C00C4 /* Tape(SCSI) DMA transfer direction */ + +#define KA420_STC_MODE 0x200C00E0 /* Storage Controller Mode register */ + +#define KA420_CUR_CMD 0x200F0000 /* Cursor Command Register */ +#define KA420_CUR_XPOS 0x200F0004 /* Cursor X position */ +#define KA420_CUR_YPOS 0x200F0008 /* Cursor Y position */ + +#define KA420_CUR_XMIN1 0x200F000C /* Region 1 left edge */ +#define KA420_CUR_XMAX1 0x200F0010 /* Region 1 right edge */ +#define KA420_CUR_YMIN1 0x200F0014 /* Region 1 top edge */ +#define KA420_CUR_YMAX1 0x200F0018 /* Region 1 bottom edge */ + +#define KA420_CUR_XMIN2 0x200F002C /* Region 2 left edge */ +#define KA420_CUR_XMAX2 0x200F0030 /* Region 2 right edge */ +#define KA420_CUR_YMIN2 0x200F0034 /* Region 2 top edge */ +#define KA420_CUR_YMAX2 0x200F0038 /* Region 2 bottom edge */ + +/* + * Clock-Chip data in NVRAM + */ +#define KA420_CPMBX 0x200B0038 /* Console Mailbox (1 byte) */ +#define KA420_CPFLG 0x200B003C /* Console Program Flags (1 byte) */ +#define KA420_LK201_ID 0x200B0040 /* Keyboard Variation (1 byte) */ +#define KA420_CONS_ID 0x200B0044 /* Console Device Type (1 byte) */ +#define KA420_SCR 0x200B0048 /* Console Scratch RAM */ +#define KA420_TEMP 0x200B0058 /* Used by System Firmware */ +#define KA420_BAT_CHK 0x200B0088 /* Battery Check Data */ +#define KA420_BOOTDEV 0x200B0098 /* Default Boot Device (4 bytes) */ +#define KA420_BOOTFLG 0x200B00A8 /* Default Boot Flags (4 bytes) */ +#define KA420_SCRLEN 0x200B00B8 /* Number of pages of SCR (1 byte) */ +#define KA420_SCSIPORT 0x200B00BC /* Tape Controller Port Data */ +#define KA420_RESERVED 0x200B00C0 /* Reserved (16 bytes) */ + diff --git a/sys/arch/vax/include/ka43.h b/sys/arch/vax/include/ka43.h new file mode 100644 index 00000000000..41981ebde78 --- /dev/null +++ b/sys/arch/vax/include/ka43.h @@ -0,0 +1,209 @@ +/* $NetBSD: ka43.h,v 1.1 1996/07/20 17:58:16 ragge Exp $ */ +/* + * Copyright (c) 1996 Ludd, University of Lule}, Sweden. + * All rights reserved. + * + * This code is derived from software contributed to Ludd by Bertram Barth. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed at Ludd, University of + * Lule}, Sweden and its contributors. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Definitions for I/O addresses of + * + * VAXstation 3100 model 76 (RigelMAX) + */ + +#define KA43_SIDEX 0x20040004 /* SID extension register */ + +#define KA43_CFGTST 0x20020000 /* Configuration and Test register */ +#define KA43_IORESET 0x20020000 /* I/O Reset register */ + +#define KA43_ROMGETC 0x20040044 +#define KA43_ROMPUTC 0x20040058 +#define KA43_ROMPUTS 0x2004004C + +#define KA43_CH2_BASE 0x10000000 /* 2nd level cache data area */ +#define KA43_CH2_END 0x1FFFFFFF +#define KA43_CH2_SIZE 0x10000000 +#define KA43_CT2_BASE 0x21000000 /* 2nd level cache tag area */ +#define KA43_CT2_END 0x2101FFFF +#define KA43_CT2_SIZE 0x20000 +#define KA43_CH2_CREG 0x21100000 /* 2nd level cache control register */ +#define KA43_SESR 0x21100000 /* ??? */ + +#define KA43_ROM_BASE 0x20040000 /* System module ROM */ +#define KA43_ROM_END 0x2007FFFF +#define KA43_ROM_SIZE 0x40000 /* ??? */ + +#define KA43_IVN_BASE 0x20040020 /* Interrupt Vector Numbers */ +#define KA43_IVN_END 0x2004003F +#define KA43_IVN_SIZE 0x20 + +#define KA43_HLTCOD 0x20080000 /* Halt Code Register */ +#define KA43_MSER 0x20080004 /* Memory System Error register */ +#define KA43_MEAR 0x20080008 /* Memory Error Address register */ +#define KA43_INTMSK 0x2008000C /* Interrupt Mask register */ +#define KA43_VDCORG 0x2008000D /* Video Controller Origin Register */ +#define KA43_VDCSEL 0x2008000E /* Video Controller Select Register */ +#define KA43_INTREQ 0x2008000F /* Interrupt Request register */ +#define KA43_INTCLR 0x2008000F /* Interrupt Request clear register */ +#define KA43_DIAGDSP 0x20080010 +#define KA43_PARCTL 0x20080014 /* Parity Control Register */ +#define KA43_DIAGTME 0x2008001E + +#define KA43_PCTL_DPEN 0x00000001 /* DMA parity enable (bit 0) */ +#define KA43_PCTL_CPEN 0x00000002 /* CPU Parity enable (bit 1) */ +#define KA43_PCTL_DMA 0x01000000 /* LANCE DMA control (bit 24) */ + +#define KA43_SESR_CENB 0x00000001 +#define KA43_SESR_SERR 0x00000002 +#define KA43_SESR_LERR 0x00000004 +#define KA43_SESR_CERR 0x00000008 +#define KA43_SESR_DIRTY 0x00000010 +#define KA43_SESR_MISS 0x00000020 +#define KA43_SESR_DPE 0x00000040 +#define KA43_SESR_TPE 0x00000080 +#define KA43_SESR_WSB 0x00010000 +#define KA43_SESR_CIEA 0x7FFC0000 + +#define KA43_PCS_FORCEHIT (1<<0) /* Force hit */ +#define KA43_PCS_ENABLE (1<<1) /* Enable primary cache */ +#define KA43_PCS_FLUSH (1<<2) /* Flush cache */ +#define KA43_PCS_REFRESH (1<<3) /* Enable refresh */ +#define KA43_PCS_HIT (1<<4) /* Cache hit */ +#define KA43_PCS_INTERRUPT (1<<5) /* Interrupt pending */ +#define KA43_PCS_TRAP2 (1<<6) /* Trap while trap */ +#define KA43_PCS_TRAP1 (1<<7) /* Micro trap / machine check */ +#define KA43_PCS_TPERR (1<<8) /* Tag parity error */ +#define KA43_PCS_DPERR (1<<9) /* Dal data parity error */ +#define KA43_PCS_PPERR (1<<10) /* P data parity error */ +#define KA43_PCS_BUSERR (1<<11) /* Bus error */ +#define KA43_PCS_BCHIT (1<<12) /* B cache hit */ + +/* + * Other fixed addresses which should be mapped + */ +#define KA43_CPU_BASE 0x20080000 /* so called "CPU registers" */ +#define KA43_CPU_END 0x200800FF +#define KA43_CPU_SIZE 0x100 +#define KA43_NWA_BASE 0x20090000 /* Network Address ROM */ +#define KA43_NWA_END 0x2009007F +#define KA43_NWA_SIZE 0x80 +#define KA43_SER_BASE 0x200A0000 /* Serial line controller */ +#define KA43_SER_END 0x200A000F +#define KA43_SER_SIZE 0x10 +#define KA43_WAT_BASE 0x200B0000 /* TOY clock and NV-RAM */ +#define KA43_WAT_END 0x200B00FF +#define KA43_WAT_SIZE 0x100 +#define KA43_SC1_BASE 0x200C0080 /* 1st SCSI Controller Chip */ +#define KA43_SC1_END 0x200C009F +#define KA43_SC1_SIZE 0x20 +#define KA43_SC2_BASE 0x200C0180 /* 2nd SCSI Controller Chip */ +#define KA43_SC2_END 0x200C019F +#define KA43_SC2_SIZE 0x20 +#define KA43_SCS_BASE 0x200C0000 /* area occupied by SCSI 1+2 */ +#define KA43_SCS_END 0x200C01FF +#define KA43_SCS_SIZE 0x200 +#define KA43_LAN_BASE 0x200E0000 /* LANCE chip registers */ +#define KA43_LAN_END 0x200E0007 +#define KA43_LAN_SIZE 0x08 +#define KA43_CUR_BASE 0x200F0000 /* Monochrome video cursor chip */ +#define KA43_CUR_END 0x200F003C +#define KA43_CUR_SIZE 0x40 +#define KA43_DMA_BASE 0x202D0000 /* 128KB Data Buffer */ +#define KA43_DMA_END 0x202EFFFF +#define KA43_DMA_SIZE 0x20000 +#define KA43_VME_BASE 0x30000000 +#define KA43_VME_END 0x3003FFFF +#define KA43_VME_SIZE 0x40000 + +#define KA43_SC1_DADR 0x200C00A0 /* (1st SCSI) DMA address register */ +#define KA43_SC1_DCNT 0x200C00C0 /* (1st SCSI) DMA byte count reg. */ +#define KA43_SC1_DDIR 0x200C00C4 /* (1st SCSI) DMA transfer direction */ +#define KA43_SC2_DADR 0x200C01A0 +#define KA43_SC2_DCNT 0x200C01C0 +#define KA43_SC2_DDIR 0x200C01C4 + +#define KA43_CUR_CMD 0x200F0000 /* Cursor Command Register */ +#define KA43_CUR_XPOS 0x200F0004 /* Cursor X position */ +#define KA43_CUR_YPOS 0x200F0008 /* Cursor Y position */ + +#define KA43_CUR_XMIN1 0x200F000C /* Region 1 left edge */ +#define KA43_CUR_XMAX1 0x200F0010 /* Region 1 right edge */ +#define KA43_CUR_YMIN1 0x200F0014 /* Region 1 top edge */ +#define KA43_CUR_YMAX1 0x200F0018 /* Region 1 bottom edge */ + +#define KA43_CUR_XMIN2 0x200F002C /* Region 2 left edge */ +#define KA43_CUR_XMAX2 0x200F0030 /* Region 2 right edge */ +#define KA43_CUR_YMIN2 0x200F0034 /* Region 2 top edge */ +#define KA43_CUR_YMAX2 0x200F0038 /* Region 2 bottom edge */ + +/* + * Clock-Chip data in NVRAM + */ +#define KA43_CPMBX 0x200B0038 /* Console Mailbox (1 byte) */ +#define KA43_CPFLG 0x200B003C /* Console Program Flags (1 byte) */ +#define KA43_LK201_ID 0x200B0040 /* Keyboard Variation (1 byte) */ +#define KA43_CONS_ID 0x200B0044 /* Console Device Type (1 byte) */ +#define KA43_SCR 0x200B0048 /* Console Scratch RAM */ +#define KA43_TEMP 0x200B0058 /* Used by System Firmware */ +#define KA43_BAT_CHK 0x200B0088 /* Battery Check Data */ +#define KA43_PASSWD 0x200B0098 /* ??? */ +#define KA43_BOOTFLG 0x200B00A8 /* Default Boot Flags (4 bytes) */ +#define KA43_SCRLEN 0x200B00B8 /* Number of pages of SCR (1 byte) */ +#define KA43_SCSIPORT 0x200B00BC /* Tape Controller Port Data */ +#define KA43_RESERVED 0x200B00C0 /* Reserved (16 bytes) */ + +struct ka43_cpu { + u_long ka43_hltcod; + u_long ka43_mser; + u_long ka43_cear; + u_long ka43_intmsk; +}; + +struct ka43_clock { + u_long :2; u_long sec :8; u_long :22; + u_long :2; u_long secalrm :8; u_long :22; + u_long :2; u_long min :8; u_long :22; + u_long :2; u_long minalrm :8; u_long :22; + u_long :2; u_long hr :8; u_long :22; + u_long :2; u_long hralrm :8; u_long :22; + u_long :2; u_long dayofwk :8; u_long :22; + u_long :2; u_long day :8; u_long :22; + u_long :2; u_long mon :8; u_long :22; + u_long :2; u_long yr :8; u_long :22; + u_long :2; u_long csr0 :8; u_long :22; + u_long :2; u_long csr1 :8; u_long :22; + u_long :2; u_long csr2 :8; u_long :22; + u_long :2; u_long csr3 :8; u_long :22; + u_long :2; u_long cpmbx :8; u_long :22; +}; + +int ka43_setup __P((struct uvax_calls *p, int flags)); +static int ka43_clkread __P((time_t)); +static void ka43_clkwrite __P((void)); diff --git a/sys/arch/vax/include/uvaxII.h b/sys/arch/vax/include/ka630.h index db6227ca193..09875115955 100644 --- a/sys/arch/vax/include/uvaxII.h +++ b/sys/arch/vax/include/ka630.h @@ -1,4 +1,4 @@ -/* $NetBSD: uvaxII.h,v 1.4 1996/05/19 16:43:28 ragge Exp $ */ +/* $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. @@ -61,9 +61,6 @@ struct uvaxIIcpu { /* 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 /* @@ -122,13 +119,7 @@ struct ka630clock { }; #endif -struct sbi_attach_args; +static int ka630_clkread __P((time_t)); +static void ka630_clkwrite __P((void)); -/* 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 diff --git a/sys/arch/vax/include/ka750.h b/sys/arch/vax/include/ka750.h index 9c6e108879b..c8cce51eb25 100644 --- a/sys/arch/vax/include/ka750.h +++ b/sys/arch/vax/include/ka750.h @@ -1,4 +1,4 @@ -/* $NetBSD: ka750.h,v 1.6 1996/05/19 16:43:23 ragge Exp $ */ +/* $NetBSD: ka750.h,v 1.7 1996/07/20 17:58:17 ragge Exp $ */ /* * Copyright (c) 1994 Ludd, University of Lule}, Sweden. @@ -44,7 +44,6 @@ /* 11/750 specific prototypes */ void ka750_conf __P((struct device *, struct device *, void *)); -int ka750_clock __P((void)); void ka750_memenable __P((struct sbi_attach_args *, struct device *)); void ka750_memerr __P((void)); int ka750_mchk __P((caddr_t)); diff --git a/sys/arch/vax/include/ka820.h b/sys/arch/vax/include/ka820.h new file mode 100644 index 00000000000..10d285cd381 --- /dev/null +++ b/sys/arch/vax/include/ka820.h @@ -0,0 +1,148 @@ +/* $NetBSD: ka820.h,v 1.1 1996/07/20 17:33:09 ragge Exp $ */ +/* + * Copyright (c) 1988 Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Chris Torek. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)ka820.h 7.3 (Berkeley) 6/28/90 + */ + +/* + * Definitions specific to the ka820 cpu. + */ + +/* + * Device addresses. + */ +#define KA820_PORTADDR 0x20088000 /* port controller */ +#define KA820_BRAMADDR 0x20090000 /* boot ram */ +#define KA820_EEPROMADDR 0x20098000 /* eeprom */ +#define KA820_RX50ADDR 0x200b0000 /* rcx50 */ +#define KA820_CLOCKADDR 0x200b8000 /* watch chip */ + +/* + * Sizes. The port controller, RCX50, and watch chip are all one page. + */ +#define KA820_BRPAGES 16 /* 8K */ +#define KA820_EEPAGES 64 /* 32K */ + +/* port controller CSR bit values */ +#define KA820PORT_RSTHALT 0x80000000 /* restart halt */ +#define KA820PORT_LCONS 0x40000000 /* logical console */ +#define KA820PORT_LCONSEN 0x20000000 /* logical console enable */ +#define KA820PORT_BIRESET 0x10000000 /* BI reset */ +#define KA820PORT_BISTF 0x08000000 /* ??? */ +#define KA820PORT_ENBAPT 0x04000000 /* ??? */ +#define KA820PORT_STPASS 0x02000000 /* self test pass */ +#define KA820PORT_RUN 0x01000000 /* run */ +#define KA820PORT_WWPE 0x00800000 /* ??? parity even? */ +#define KA820PORT_EVLCK 0x00400000 /* event lock */ +#define KA820PORT_WMEM 0x00200000 /* write mem */ +#define KA820PORT_EV4 0x00100000 /* event 4 */ +#define KA820PORT_EV3 0x00080000 /* event 3 */ +#define KA820PORT_EV2 0x00040000 /* event 2 */ +#define KA820PORT_EV1 0x00020000 /* event 1 */ +#define KA820PORT_EV0 0x00010000 /* event 0 */ +#define KA820PORT_WWPO 0x00008000 /* ??? parity odd? */ +#define KA820PORT_PERH 0x00004000 /* parity error H */ +#define KA820PORT_ENBPIPE 0x00002000 /* enable? pipe */ +#define KA820PORT_TIMEOUT 0x00001000 /* timeout */ +#define KA820PORT_RSVD 0x00000800 /* reserved */ +#define KA820PORT_CONSEN 0x00000400 /* console interrupt enable */ +#define KA820PORT_CONSCLR 0x00000200 /* clear console interrupt */ +#define KA820PORT_CONSINTR 0x00000100 /* console interrupt req */ +#define KA820PORT_RXIE 0x00000080 /* RX50 interrupt enable */ +#define KA820PORT_RXCLR 0x00000040 /* clear RX50 interrupt */ +#define KA820PORT_RXIRQ 0x00000020 /* RX50 interrupt request */ +#define KA820PORT_IPCLR 0x00000010 /* clear IP interrupt */ +#define KA820PORT_IPINTR 0x00000008 /* IP interrupt request */ +#define KA820PORT_CRDEN 0x00000004 /* enable CRD interrupts */ +#define KA820PORT_CRDCLR 0x00000002 /* clear CRD interrupt */ +#define KA820PORT_CRDINTR 0x00000001 /* CRD interrupt request */ + +/* what the heck */ +#define KA820PORT_BITS \ +"\20\40RSTHALT\37LCONS\36LCONSEN\35BIRESET\34BISTF\33ENBAPT\32STPASS\31RUN\ +\30WWPE\27EVLCK\26WMEM\25EV4\24EV3\23EV2\22EV1\21EV\20WWPO\17PERH\16ENBPIPE\ +\15TIMEOUT\13CONSEN\12CONSCLR\11CONSINTR\10RXIE\7RXCLR\6RXIRQ\5IPCLR\4IPINTR\ +\3CRDEN\2CLRCLR\1CRDINTR" + +/* clock CSR bit values, per csr */ +#define KA820CLK_0_BUSY 0x01 /* busy (time changing) */ +#define KA820CLK_1_GO 0x0c /* run */ +#define KA820CLK_1_SET 0x0d /* set the time */ +#define KA820CLK_3_VALID 0x01 /* clock is valid */ + +#ifndef LOCORE +struct ka820port { + u_long csr; + /* that seems to be all.... */ +}; + +struct ka820clock { + u_char sec; + u_char pad0; + u_char secalrm; + u_char pad1; + u_char min; + u_char pad2; + u_char minalrm; + u_char pad3; + u_char hr; + u_char pad4; + u_char hralrm; + u_char pad5; + u_char dayofwk; + u_char pad6; + u_char day; + u_char pad7; + u_char mon; + u_char pad8; + u_char yr; + u_char pad9; + u_short csr0; + u_short csr1; + u_short csr2; + u_short csr3; +}; + +/* + * Prototypes. + */ +void ka820_conf __P((struct device *, struct device *, void *)); +void ka820_memerr __P((void)); +int ka820_mchk __P((caddr_t)); +void ka820_steal_pages __P((void)); +int ka820_clkread __P((time_t)); +void ka820_clkwrite __P((void)); +#endif diff --git a/sys/arch/vax/include/macros.h b/sys/arch/vax/include/macros.h index b08881f0791..1d863e915a4 100644 --- a/sys/arch/vax/include/macros.h +++ b/sys/arch/vax/include/macros.h @@ -1,4 +1,4 @@ -/* $NetBSD: macros.h,v 1.8 1996/03/17 22:44:50 ragge Exp $ */ +/* $NetBSD: macros.h,v 1.10 1997/01/11 11:07:52 ragge Exp $ */ /* * Copyright (c) 1994 Ludd, University of Lule}, Sweden. @@ -117,6 +117,7 @@ static __inline__ int bcmp(const void *b1, const void *b2, size_t len){ return ret; } +#if 0 /* unused, but no point in deleting it since it _is_ an instruction */ static __inline__ int locc(int mask, char *cp,u_int size){ register ret; @@ -126,8 +127,10 @@ static __inline__ int locc(int mask, char *cp,u_int size){ : "r0","r1" ); return ret; } +#endif -static __inline__ int scanc(u_int size, u_char *cp,u_char *table, int mask){ +static __inline__ int +scanc(u_int size, const u_char *cp, const u_char *table, int mask){ register ret; asm __volatile("scanc %1,(%2),(%3),%4;movl r0,%0" diff --git a/sys/arch/vax/include/mtpr.h b/sys/arch/vax/include/mtpr.h index 0ee73aa8575..f106ab687f9 100644 --- a/sys/arch/vax/include/mtpr.h +++ b/sys/arch/vax/include/mtpr.h @@ -1,4 +1,4 @@ -/* $NetBSD: mtpr.h,v 1.8 1996/03/07 23:23:59 ragge Exp $ */ +/* $NetBSD: mtpr.h,v 1.9 1996/07/20 17:58:18 ragge Exp $ */ /* * Copyright (c) 1994 Ludd, University of Lule}, Sweden. @@ -119,6 +119,29 @@ #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 diff --git a/sys/arch/vax/include/nexus.h b/sys/arch/vax/include/nexus.h index fe9a2fb0288..6f15874f874 100644 --- a/sys/arch/vax/include/nexus.h +++ b/sys/arch/vax/include/nexus.h @@ -1,4 +1,4 @@ -/* $NetBSD: nexus.h,v 1.10 1996/03/02 14:27:53 ragge Exp $ */ +/* $NetBSD: nexus.h,v 1.12 1996/08/20 14:19:43 ragge Exp $ */ /*- * Copyright (c) 1982, 1986 The Regents of the University of California. @@ -38,6 +38,17 @@ #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. * * Each machine has an address of backplane slots (nexi). @@ -63,10 +74,6 @@ #define NNEX730 NNEXSBI #define NEX730 ((struct nexus *)0xf20000) #endif -#if VAX630 -#define NNEX630 1 -#define NEX630 ((struct nexus *)0x20088000) -#endif #define NEXSIZE 0x2000 #if VAX8600 @@ -102,20 +109,11 @@ struct mem_softc { int sc_memnr; }; -struct iobus { - int io_type; - int io_addr; - int io_size; - int io_details; -}; - -struct nexusconnect { - int psb_nnexus; - struct nexus *psb_nexbase; - int psb_ubatype; - int psb_nubabdp; - caddr_t *psb_umaddr; - int *psb_nextype; +struct bp_conf { + char *type; + int num; + int partyp; + int bp_addr; }; extern caddr_t *nex_vec; diff --git a/sys/arch/vax/include/param.h b/sys/arch/vax/include/param.h index ec5d9c6b95b..a50abd5fe93 100644 --- a/sys/arch/vax/include/param.h +++ b/sys/arch/vax/include/param.h @@ -1,4 +1,5 @@ -/* $NetBSD: param.h,v 1.19 1996/03/04 05:04:43 cgd Exp $ */ +/* $OpenBSD: param.h,v 1.6 1997/01/15 23:24:42 maja Exp $ */ +/* $NetBSD: param.h,v 1.22 1997/01/11 11:06:17 ragge Exp $ */ /*- * Copyright (c) 1990 The Regents of the University of California. * All rights reserved. @@ -74,7 +75,8 @@ #define DEV_BSIZE (1 << DEV_BSHIFT) #define BLKDEV_IOSIZE 2048 -#define MAXPHYS (63 * 1024) /* max raw I/O transfer size */ +#define MAXPHYS (63 * 1024) /* max raw I/O transfer size */ +#define MAXBSIZE 0x4000 /* max FS block size - XXX */ #define CLSIZELOG2 1 #define CLSIZE 2 @@ -160,7 +162,6 @@ #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 */ @@ -169,10 +170,18 @@ #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 diff --git a/sys/arch/vax/include/pmap.h b/sys/arch/vax/include/pmap.h index 870776d4a5e..a4f22ce6e01 100644 --- a/sys/arch/vax/include/pmap.h +++ b/sys/arch/vax/include/pmap.h @@ -1,4 +1,4 @@ -/* $NetBSD: pmap.h,v 1.16 1996/04/08 18:35:51 ragge Exp $ */ +/* $NetBSD: pmap.h,v 1.17 1996/07/20 17:58:22 ragge Exp $ */ /* * Copyright (c) 1987 Carnegie-Mellon University @@ -85,6 +85,7 @@ typedef struct pv_entry { /* ROUND_PAGE used before vm system is initialized */ #define ROUND_PAGE(x) (((uint)(x) + PAGE_SIZE-1)& ~(PAGE_SIZE - 1)) +#define TRUNC_PAGE(x) ((uint)(x) & ~(PAGE_SIZE - 1)) /* Mapping macros used when allocating SPT */ #define MAPVIRT(ptr, count) \ diff --git a/sys/arch/vax/include/sid.h b/sys/arch/vax/include/sid.h index 2888b904525..4270623b85e 100644 --- a/sys/arch/vax/include/sid.h +++ b/sys/arch/vax/include/sid.h @@ -1,4 +1,4 @@ -/* $NetBSD: sid.h,v 1.6 1995/11/12 14:37:18 ragge Exp $ */ +/* $NetBSD: sid.h,v 1.8 1996/08/20 14:19:41 ragge Exp $ */ /* * Copyright (c) 1994 Ludd, University of Lule}, Sweden. @@ -30,33 +30,173 @@ * 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; diff --git a/sys/arch/vax/include/trap.h b/sys/arch/vax/include/trap.h index ff7f89cf3b1..619b2d9ac07 100644 --- a/sys/arch/vax/include/trap.h +++ b/sys/arch/vax/include/trap.h @@ -1,4 +1,4 @@ -/* $NetBSD: trap.h,v 1.13 1996/04/08 18:35:52 ragge Exp $ */ +/* $NetBSD: trap.h,v 1.14 1997/01/11 11:46:43 ragge Exp $ */ /*- * Copyright (c) 1990 The Regents of the University of California. @@ -110,6 +110,8 @@ struct ivec_dsp { char pad; /* sizeof(struct ivec_dsp) == 16 */ }; +extern struct ivec_dsp idsptch; + #endif /* _LOCORE */ #endif _VAX_TRAP_H_ diff --git a/sys/arch/vax/include/types.h b/sys/arch/vax/include/types.h index 09118fd8a40..e44feb1b395 100644 --- a/sys/arch/vax/include/types.h +++ b/sys/arch/vax/include/types.h @@ -1,4 +1,4 @@ -/* $NetBSD: types.h,v 1.9 1996/04/08 18:35:53 ragge Exp $ */ +/* $NetBSD: types.h,v 1.10 1996/12/05 00:14:00 cgd Exp $ */ /*- * Copyright (c) 1990 The Regents of the University of California. @@ -70,4 +70,6 @@ typedef unsigned long long u_int64_t; typedef int32_t register_t; +#define __BROKEN_INDIRECT_CONFIG + #endif /* _MACHTYPES_H_ */ diff --git a/sys/arch/vax/include/uvax.h b/sys/arch/vax/include/uvax.h new file mode 100644 index 00000000000..df7bc81f6a6 --- /dev/null +++ b/sys/arch/vax/include/uvax.h @@ -0,0 +1,115 @@ +/* $NetBSD: uvax.h,v 1.1 1996/07/20 17:58:24 ragge Exp $ */ +/* + * Copyright (c) 1996 Ludd, University of Lule}, Sweden. + * All rights reserved. + * + * This code is derived from software contributed to Ludd by Bertram Barth. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed at Ludd, University of + * Lule}, Sweden and its contributors. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * generic(?) MicroVAX and VAXstation support + * + * There are similarities to struct cpu_calls[] in autoconf.c + */ + +/* + * Prototypes for autoconf.c + */ +struct device; +void uvax_conf __P((struct device*, struct device*, void*)); +int uvax_clock __P((void)); +void uvax_memerr __P((void)); +int uvax_mchk __P((caddr_t)); +void uvax_steal_pages __P((void)); + +int uvax_setup __P((int mapen)); + +struct uvax_calls { + u_long (*uc_phys2virt) __P((u_long)); /* most often used! */ + u_long (*uc_memsize) __P((void)); + void (*uc_steal_pages) __P((void)); + void (*uc_conf) __P((struct device*, struct device*, void*)); + void (*uc_memerr) __P((void)); + int (*uc_mchk) __P((caddr_t)); + int (*uc_clkread) __P((time_t)); + void (*uc_clkwrite) __P((void)); + + char *uc_name; + u_char *uc_intreq; + u_char *uc_intclr; + u_char *uc_intmsk; + + void *le_iomem; /* base addr of RAM -- CPU's view */ + u_long *le_ioaddr; /* base addr of RAM -- LANCE's view */ + int *le_memsize; /* size of RAM reserved for LANCE */ + + void *uc_physmap; + int uc_busTypes; + int uc_vups; /* used by delay() */ + + int uv_flags; + int vs_flags; +}; + +extern struct uvax_calls guc; /* Generic uVAX Calls */ +extern struct uvax_calls *ucp; + +struct uc_map { + u_long um_base; + u_long um_end; + u_long um_size; + u_long um_virt; +}; +extern struct uc_map *uc_physmap; + +/* + * Generic definitions common on all MicroVAXen clock chip. + */ +#define uVAX_CLKVRT 0200 +#define uVAX_CLKUIP 0200 +#define uVAX_CLKRATE 040 +#define uVAX_CLKENABLE 06 +#define uVAX_CLKSET 0206 + +/* cpmbx bits */ +#define uVAX_CLKHLTACT 03 + +/* halt action values */ +#define uVAX_CLKRESTRT 01 +#define uVAX_CLKREBOOT 02 +#define uVAX_CLKHALT 03 + +/* in progress flags */ +#define uVAX_CLKBOOT 04 +#define uVAX_CLKRSTRT 010 +#define uVAX_CLKLANG 0360 + +/* Prototypes */ +int uvax_clkread __P((time_t)); +void uvax_clkwrite __P((void)); diff --git a/sys/arch/vax/include/vmparam.h b/sys/arch/vax/include/vmparam.h index 36d52b2b10a..459c120e218 100644 --- a/sys/arch/vax/include/vmparam.h +++ b/sys/arch/vax/include/vmparam.h @@ -1,4 +1,4 @@ -/* $NetBSD: vmparam.h,v 1.11 1996/02/02 19:08:43 mycroft Exp $ */ +/* $NetBSD: vmparam.h,v 1.12 1996/07/20 17:58:26 ragge Exp $ */ /*- * Copyright (c) 1990 The Regents of the University of California. @@ -99,6 +99,11 @@ #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. * KALLOCMEM is kernel malloc area size. How much needed for each process? diff --git a/sys/arch/vax/include/vsbus.h b/sys/arch/vax/include/vsbus.h new file mode 100644 index 00000000000..81257f57d11 --- /dev/null +++ b/sys/arch/vax/include/vsbus.h @@ -0,0 +1,86 @@ +/* $NetBSD: vsbus.h,v 1.1 1996/07/20 17:58:28 ragge Exp $ */ +/* + * Copyright (c) 1996 Ludd, University of Lule}, Sweden. + * All rights reserved. + * + * This code is derived from software contributed to Ludd by Bertram Barth. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed at Ludd, University of + * Lule}, Sweden and its contributors. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Generic definitions for the (virtual) vsbus. contains common info + * used by all VAXstations. + */ +struct confargs { + char ca_name[16]; /* device name */ + int ca_intslot; /* device interrupt-slot */ + int ca_intpri; /* device interrupt "priority" */ + int ca_intvec; /* interrup-vector offset */ + int ca_intbit; /* bit in interrupt-register */ + int ca_ioaddr; /* device hardware I/O address */ + + int ca_aux1; /* additional info (DMA, etc.) */ + int ca_aux2; + int ca_aux3; + int ca_aux4; + int ca_aux5; + int ca_aux6; + int ca_aux7; + int ca_aux8; + +#define ca_recvslot ca_intslot /* DC/DZ: Receiver configuration */ +#define ca_recvpri ca_intpri +#define ca_recvvec ca_intvec +#define ca_recvbit ca_intbit +#define ca_xmitslot ca_aux1 /* DC/DZ: transmitter configuration */ +#define ca_xmitpri ca_aux2 /* DC/DZ: */ +#define ca_xmitvec ca_aux3 +#define ca_xmitbit ca_aux4 +#define ca_dcflags ca_aux5 + +#define ca_dareg ca_aux1 /* SCSI: DMA address register */ +#define ca_dcreg ca_aux2 /* SCSI: DMA byte count register */ +#define ca_ddreg ca_aux3 /* SCSI: DMA transfer direction */ +#define ca_dbase ca_aux4 /* SCSI: DMA buffer address */ +#define ca_dsize ca_aux5 /* SCSI: DMA buffer size */ +#define ca_dflag ca_aux6 /* SCSI: DMA flags (eg. shared) */ +#define ca_idval ca_aux7 /* SCSI: host-ID to use/set */ +#define ca_idreg ca_aux8 /* SCSI: host-ID port register */ + +#define ca_enaddr ca_aux1 /* LANCE: Ethernet address in ROM */ +#define ca_leflags ca_aux2 +}; + +int vsbus_intr_register __P((struct confargs *, int(*)(void*), void*)); +int vsbus_intr_enable __P((struct confargs *)); +int vsbus_intr_disable __P((struct confargs *)); +int vsbus_intr_unregister __P((struct confargs *)); + +int vsbus_lockDMA __P((struct confargs *)); +int vsbus_unlockDMA __P((struct confargs *)); + diff --git a/sys/arch/vax/mba/hp.c b/sys/arch/vax/mba/hp.c index 65c33749d88..6bc9955e012 100644 --- a/sys/arch/vax/mba/hp.c +++ b/sys/arch/vax/mba/hp.c @@ -1,4 +1,4 @@ -/* $NetBSD: hp.c,v 1.9 1996/05/19 16:43:34 ragge Exp $ */ +/* $NetBSD: hp.c,v 1.12 1996/10/13 03:34:58 christos Exp $ */ /* * Copyright (c) 1996 Ludd, University of Lule}, Sweden. * All rights reserved. @@ -471,8 +471,9 @@ hpwrite(dev, uio) * Convert physical adapternr and unit to the unit number used by kernel. */ int -hp_getdev(mbanr, unit) +hp_getdev(mbanr, unit, uname) int mbanr, unit; + char **uname; { struct mba_softc *ms; struct hp_softc *sc; @@ -484,8 +485,10 @@ hp_getdev(mbanr, unit) sc = hp_cd.cd_devs[i]; ms = (void *)sc->sc_dev.dv_parent; - if (ms->sc_physnr == mbanr && sc->sc_physnr == unit) + if (ms->sc_physnr == mbanr && sc->sc_physnr == unit) { + *uname = sc->sc_dev.dv_xname; return i; + } } return -1; } diff --git a/sys/arch/vax/mba/mba.c b/sys/arch/vax/mba/mba.c index 17ea88af639..40cce611747 100644 --- a/sys/arch/vax/mba/mba.c +++ b/sys/arch/vax/mba/mba.c @@ -1,4 +1,4 @@ -/* $NetBSD: mba.c,v 1.6 1996/04/08 18:38:59 ragge Exp $ */ +/* $NetBSD: mba.c,v 1.10 1996/10/13 03:35:00 christos Exp $ */ /* * Copyright (c) 1994, 1996 Ludd, University of Lule}, Sweden. * All rights reserved. @@ -81,7 +81,11 @@ struct cfdriver mba_cd = { NULL, "mba", DV_DULL }; -struct cfattach mba_ca = { +struct cfattach mba_cmi_ca = { + sizeof(struct mba_softc), mbamatch, mbaattach +}; + +struct cfattach mba_sbi_ca = { sizeof(struct mba_softc), mbamatch, mbaattach }; @@ -134,7 +138,7 @@ mbaattach(parent, self, aux) sc->sc_physnr = sa->nexnum - 8; /* MBA's have TR between 8 - 11... */ #ifdef VAX750 - if (cpunumber == VAX_750) + if (vax_cputype == VAX_750) sc->sc_physnr += 4; /* ...but not on 11/750 */ #endif sc->sc_first = 0; @@ -238,7 +242,7 @@ mbaintr(mba) int mbaprint(aux, mbaname) - void *aux; + void *aux; const char *mbaname; { struct mba_attach_args *ma = aux; @@ -284,71 +288,10 @@ mbastart(sc) volatile struct mba_regs *mr = sc->sc_mbareg; struct buf *bp = md->md_q.b_actf; - mbamapregs(sc); + disk_reallymapin(md->md_q.b_actf, sc->sc_mbareg->mba_map, 0, PG_V); sc->sc_state = SC_ACTIVE; mr->mba_var = ((u_int)bp->b_un.b_addr & PGOFSET); mr->mba_bc = (~bp->b_bcount) + 1; (*md->md_start)(md); /* machine-dependent start */ } - -/* - * Setup map registers for a dma transfer. - * This routine could be synced with the other adapter map routines! - */ -void -mbamapregs(sc) - struct mba_softc *sc; -{ - struct mba_device *md = sc->sc_first; - volatile struct mba_regs *mr = sc->sc_mbareg; - struct buf *bp = md->md_q.b_actf; - struct pcb *pcb; - pt_entry_t *pte; - volatile pt_entry_t *io; - int pfnum, npf, o, i; - caddr_t addr; - - o = (int)bp->b_un.b_addr & PGOFSET; - npf = btoc(bp->b_bcount + o) + 1; - addr = bp->b_un.b_addr; - - /* - * Get a pointer to the pte pointing out the first virtual address. - * Use different ways in kernel and user space. - */ - if ((bp->b_flags & B_PHYS) == 0) { - pte = kvtopte(addr); - } else { - pcb = bp->b_proc->p_vmspace->vm_pmap.pm_pcb; - pte = uvtopte(addr, pcb); - } - - /* - * When we are doing DMA to user space, be sure that all pages - * we want to transfer to is mapped. WHY DO WE NEED THIS??? - * SHOULDN'T THEY ALWAYS BE MAPPED WHEN DOING THIS??? - */ - for (i = 0; i < (npf - 1); i++) { - if ((pte + i)->pg_pfn == 0) { - int rv; - rv = vm_fault(&bp->b_proc->p_vmspace->vm_map, - (unsigned)addr + i * NBPG, - VM_PROT_READ|VM_PROT_WRITE, FALSE); - if (rv) - panic("MBA DMA to nonexistent page, %d", rv); - } - } - - io = &mr->mba_map[0]; - while (--npf > 0) { - pfnum = pte->pg_pfn; - if (pfnum == 0) - panic("mba zero entry"); - pte++; - *(int *)io++ = pfnum | PG_V; - } - *(int *)io = 0; -} - - diff --git a/sys/arch/vax/mscp/files.mscp b/sys/arch/vax/mscp/files.mscp new file mode 100644 index 00000000000..ad85bcbebbc --- /dev/null +++ b/sys/arch/vax/mscp/files.mscp @@ -0,0 +1,20 @@ +# $NetBSD: files.mscp,v 1.1 1996/07/01 20:41:30 ragge Exp $ +# +# File and device description for MSCP devices. +# + +define mscp {} +file arch/vax/mscp/mscp.c +file arch/vax/mscp/mscp_subr.c + +device mscpbus {drive = -1} +attach mscpbus at mscp + +device ra: disk +attach ra at mscpbus +file arch/vax/mscp/mscp_disk.c ra needs-flag + +device mt: tape +attach mt at mscpbus +file arch/vax/mscp/mscp_tape.c mt needs-flag + diff --git a/sys/arch/vax/mscp/mscp.c b/sys/arch/vax/mscp/mscp.c new file mode 100644 index 00000000000..e8cb619ecb8 --- /dev/null +++ b/sys/arch/vax/mscp/mscp.c @@ -0,0 +1,508 @@ +/* $NetBSD: mscp.c,v 1.5 1997/01/11 11:20:31 ragge Exp $ */ + +/* + * Copyright (c) 1996 Ludd, University of Lule}, Sweden. + * Copyright (c) 1988 Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Chris Torek. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)mscp.c 7.5 (Berkeley) 12/16/90 + */ + +/* + * MSCP generic driver routines + */ + +#include <sys/param.h> +#include <sys/buf.h> +#include <sys/malloc.h> +#include <sys/device.h> + +#include <vax/mscp/mscp.h> +#include <vax/mscp/mscpvar.h> + +#define PCMD PSWP /* priority for command packet waits */ + +/* + * During transfers, mapping info is saved in the buffer's b_resid. + */ +#define b_info b_resid + +/* + * Get a command packet. Second argument is true iff we are + * to wait if necessary. Return NULL if none are available and + * we cannot wait. + */ +struct mscp * +mscp_getcp(mi, canwait) + register struct mscp_softc *mi; + int canwait; +{ +#define mri (&mi->mi_cmd) + register struct mscp *mp; + register int i; + int s = splbio(); + +again: + /* + * Ensure that we have some command credits, and + * that the next command packet is free. + */ + if (mi->mi_credits <= MSCP_MINCREDITS) { + if (!canwait) { + splx(s); + return (NULL); + } + mi->mi_wantcredits = 1; + sleep((caddr_t) &mi->mi_wantcredits, PCMD); + goto again; + } + i = mri->mri_next; + if (mri->mri_desc[i] & MSCP_OWN) { + if (!canwait) { + splx(s); + return (NULL); + } + mi->mi_wantcmd = 1; + sleep((caddr_t) &mi->mi_wantcmd, PCMD); + goto again; + } + mi->mi_credits--; + mri->mri_desc[i] &= ~MSCP_INT; + mri->mri_next = (mri->mri_next + 1) % mri->mri_size; + splx(s); + mp = &mri->mri_ring[i]; + + /* + * Initialise some often-zero fields. + * ARE THE LAST TWO NECESSARY IN GENERAL? IT SURE WOULD BE + * NICE IF DEC SOLD DOCUMENTATION FOR THEIR OWN CONTROLLERS. + */ + mp->mscp_msglen = MSCP_MSGLEN; + mp->mscp_flags = 0; + mp->mscp_modifier = 0; + mp->mscp_seq.seq_bytecount = 0; + mp->mscp_seq.seq_buffer = 0; + mp->mscp_seq.seq_mapbase = 0; +/*???*/ mp->mscp_sccc.sccc_errlgfl = 0; +/*???*/ mp->mscp_sccc.sccc_copyspd = 0; + return (mp); +#undef mri +} + +#ifdef AVOID_EMULEX_BUG +int mscp_aeb_xor = 0x8000bb80; +#endif + +/* + * Handle a response ring transition. + */ +void +mscp_dorsp(mi) + register struct mscp_softc *mi; +{ + struct device *drive; + struct mscp_device *me = mi->mi_me; + struct mscp_ctlr *mc = mi->mi_mc; + register struct buf *bp; + register struct mscp *mp; + register int nextrsp; + int st, error, info; + extern int cold; + extern struct mscp slavereply; + + nextrsp = mi->mi_rsp.mri_next; +loop: + if (mi->mi_rsp.mri_desc[nextrsp] & MSCP_OWN) { + /* + * No more responses. Remember the next expected + * response index. Check to see if we have some + * credits back, and wake up sleepers if so. + */ + mi->mi_rsp.mri_next = nextrsp; + if (mi->mi_wantcredits && mi->mi_credits > MSCP_MINCREDITS) { + mi->mi_wantcredits = 0; + wakeup((caddr_t) &mi->mi_wantcredits); + } + return; + } + + mp = &mi->mi_rsp.mri_ring[nextrsp]; + mi->mi_credits += MSCP_CREDITS(mp->mscp_msgtc); + /* + * Controllers are allowed to interrupt as any drive, so we + * must check the command before checking for a drive. + */ + if (mp->mscp_opcode == (M_OP_SETCTLRC | M_OP_END)) { + if ((mp->mscp_status & M_ST_MASK) == M_ST_SUCCESS) { + mi->mi_flags |= MSC_READY; + } else { + printf("%s: SETCTLRC failed: %d ", + mi->mi_dev.dv_xname, mp->mscp_status); + mscp_printevent(mp); + } + goto done; + } + + /* + * Found a response. Update credit information. If there is + * nothing else to do, jump to `done' to get the next response. + */ + if (mp->mscp_unit >= mi->mi_driveno) { /* Must expand drive table */ + int tmpno = ((mp->mscp_unit + 32) & 0xffe0) * sizeof(void *); + struct device **tmp = (struct device **) + malloc(tmpno, M_DEVBUF, M_NOWAIT); + bzero(tmp, tmpno); + if (mi->mi_driveno) { + bcopy(mi->mi_dp, tmp, mi->mi_driveno); + free(mi->mi_dp, mi->mi_driveno); + } + mi->mi_driveno = tmpno; + mi->mi_dp = tmp; + } + + drive = mi->mi_dp[mp->mscp_unit]; + + switch (MSCP_MSGTYPE(mp->mscp_msgtc)) { + + case MSCPT_SEQ: + break; + + case MSCPT_DATAGRAM: + (*me->me_dgram)(drive, mp, mi); + goto done; + + case MSCPT_CREDITS: + goto done; + + case MSCPT_MAINTENANCE: + default: + printf("%s: unit %d: unknown message type 0x%x ignored\n", + mi->mi_dev.dv_xname, mp->mscp_unit, + MSCP_MSGTYPE(mp->mscp_msgtc)); + goto done; + } + + /* + * Handle individual responses. + */ + st = mp->mscp_status & M_ST_MASK; + error = 0; + switch (mp->mscp_opcode) { + + case M_OP_END: + /* + * The controller presents a bogus END packet when + * a read/write command is given with an illegal + * block number. This is contrary to the MSCP + * specification (ENDs are to be given only for + * invalid commands), but that is the way of it. + */ + if (st == M_ST_INVALCMD && mp->mscp_cmdref != 0) { + printf("%s: bad lbn (%d)?\n", drive->dv_xname, + (int)mp->mscp_seq.seq_lbn); + error = EIO; + goto rwend; + } + goto unknown; + + case M_OP_ONLINE | M_OP_END: + /* + * Finished an ON LINE request. Call the driver to + * find out whether it succeeded. If so, mark it on + * line. + */ + (*me->me_online)(drive, mp); + break; + + case M_OP_GETUNITST | M_OP_END: + /* + * Got unit status. If we are autoconfiguring, save + * the mscp struct so that mscp_attach know what to do. + * If the drive isn't configured, call config_found() + * to set it up, otherwise it's just a "normal" unit + * status. + */ + if (cold) + bcopy(mp, &slavereply, sizeof(struct mscp)); + + if (mp->mscp_status == (M_ST_OFFLINE|M_OFFLINE_UNKNOWN)) + break; + + if (drive == 0) { + struct drive_attach_args da; + + da.da_mp = (struct mscp *)mp; + da.da_typ = mi->mi_type; + config_found(&mi->mi_dev, (void *)&da, mscp_print); + } else + /* Hack to avoid complaints */ + if (!(((mp->mscp_event & M_ST_MASK) == M_ST_AVAILABLE) + && cold)) + (*me->me_gotstatus)(drive, mp); + break; + + case M_OP_AVAILATTN: + /* + * The drive went offline and we did not notice. + * Mark it off line now, to force an on line request + * next, so we can make sure it is still the same + * drive. + * + * IF THE UDA DRIVER HAS A COMMAND AWAITING UNIBUS + * RESOURCES, THAT COMMAND MAY GO OUT BEFORE THE ON + * LINE. IS IT WORTH FIXING?? + */ +#ifdef notyet + (*md->md_offline)(ui, mp); +#endif + break; + + case M_OP_POS | M_OP_END: + case M_OP_WRITM | M_OP_END: + /* + * A non-data transfer operation completed. + */ + (*me->me_cmddone)(drive, mp); + break; + + case M_OP_READ | M_OP_END: + case M_OP_WRITE | M_OP_END: + /* + * A transfer finished. Get the buffer, and release its + * map registers via ubadone(). If the command finished + * with an off line or available status, the drive went + * off line (the idiot controller does not tell us until + * it comes back *on* line, or until we try to use it). + */ +#ifdef DIAGNOSTIC + if (mp->mscp_cmdref == 0) { + /* + * No buffer means there is a bug somewhere! + */ + printf("%s: io done, but no buffer?\n", + drive->dv_xname); + mscp_hexdump(mp); + break; + } +#endif +rwend: + bp = (struct buf *) mp->mscp_cmdref; + + /* + * Mark any error-due-to-bad-LBN (via `goto rwend'). + * WHAT STATUS WILL THESE HAVE? IT SURE WOULD BE NICE + * IF DEC SOLD DOCUMENTATION FOR THEIR OWN CONTROLLERS. + */ + if (error) { + bp->b_flags |= B_ERROR; + bp->b_error = error; + } + if (st == M_ST_OFFLINE || st == M_ST_AVAILABLE) { +#ifdef notyet + (*md->md_offline)(ui, mp); +#endif + } + + /* + * Unlink the transfer from the wait queue. + */ + _remque(&bp->b_actf); + + /* + * If the transfer has something to do with bad + * block forwarding, let the driver handle the + * rest. + */ + if ((bp->b_flags & B_BAD) != 0 && me->me_bb != NULL) { + (*me->me_bb)(drive, mp, bp); + goto out; + } + + /* + * If the transfer failed, give the driver a crack + * at fixing things up. + */ + if (st != M_ST_SUCCESS) { + switch ((*me->me_ioerr)(drive, mp, bp)) { + + case MSCP_DONE: /* fixed */ + break; + + case MSCP_RESTARTED: /* still working on it */ + goto out; + + case MSCP_FAILED: /* no luck */ + /* XXX must move to ra.c */ + mscp_printevent(mp); + break; + } + } + + /* + * Set the residual count and mark the transfer as + * done. If the I/O wait queue is now empty, release + * the shared BDP, if any. + */ + info = bp->b_info; /* we are about to clobber it */ + bp->b_resid = bp->b_bcount - mp->mscp_seq.seq_bytecount; + + (*mc->mc_ctlrdone)(mi->mi_dev.dv_parent, info); + (*me->me_iodone)(drive, bp); +out: + break; + + case M_OP_REPLACE | M_OP_END: + /* + * A replace operation finished. Just let the driver + * handle it (if it does replaces). + */ + if (me->me_replace == NULL) + printf("%s: bogus REPLACE end\n", drive->dv_xname); + else + (*me->me_replace)(drive, mp); + break; + + default: + /* + * If it is not one of the above, we cannot handle it. + * (And we should not have received it, for that matter.) + */ +unknown: + printf("%s: unknown opcode 0x%x status 0x%x ignored\n", + drive->dv_xname, mp->mscp_opcode, mp->mscp_status); +#ifdef DIAGNOSTIC + mscp_hexdump(mp); +#endif + break; + } + + /* + * If the drive needs to be put back in the controller queue, + * do that now. (`bp' below ought to be `dp', but they are all + * struct buf *.) Note that b_active was cleared in the driver; + * we presume that there is something to be done, hence reassert it. + */ +#ifdef notyet /* XXX */ + if (ui->ui_flags & UNIT_REQUEUE) { + bp = &md->md_utab[ui->ui_unit]; + if (bp->b_active) panic("mscp_dorsp requeue"); + MSCP_APPEND(bp, mi->mi_XXXtab, b_hash.le_next); +/* Was: MSCP_APPEND(bp, mi->mi_XXXtab, b_forw); */ + bp->b_active = 1; + ui->ui_flags &= ~UNIT_REQUEUE; + } +#endif +done: + /* + * Give back the response packet, and take a look at the next. + */ + mp->mscp_msglen = MSCP_MSGLEN; + mi->mi_rsp.mri_desc[nextrsp] |= MSCP_OWN; + nextrsp = (nextrsp + 1) % mi->mi_rsp.mri_size; + goto loop; +} + +/* + * Requeue outstanding transfers, e.g., after bus reset. + * Also requeue any drives that have on line or unit status + * info pending. + */ +void +mscp_requeue(mi) + struct mscp_softc *mi; +{ + register struct mscp_device *me = mi->mi_me; + register struct buf *bp, *dp; + register int unit; + struct buf *nextbp; + +panic("mscp_requeue"); + /* + * Clear the controller chain. Mark everything un-busy; we + * will soon fix any that are in fact busy. + */ +#ifdef notyet /* XXX */ + mi->mi_XXXtab->b_actf = NULL; + mi->mi_XXXtab->b_active = 0; + for (unit = 0, dp = md->md_utab; unit < md->md_nunits; unit++, dp++) { + ui = md->md_dinfo[unit]; + if (ui == NULL || !ui->ui_alive || ui->ui_ctlr != mi->mi_ctlr) + continue; /* not ours */ + dp->b_hash.le_next = NULL; + dp->b_active = 0; + } + /* + * Scan the wait queue, linking buffers onto drive queues. + * Note that these must be put at the front of the drive queue, + * lest we reorder I/O operations. + */ + for (bp = *mi->mi_XXXwtab.b_actb; bp != &mi->mi_XXXwtab; bp = nextbp) { + nextbp = *bp->b_actb; + dp = &md->md_utab[minor(bp->b_dev) >> md->md_unitshift]; + bp->b_actf = dp->b_actf; + if (dp->b_actf == NULL) + dp->b_actb = (void *)bp; + dp->b_actf = bp; + } + mi->mi_XXXwtab.b_actf = *mi->mi_XXXwtab.b_actb = &mi->mi_XXXwtab; + + /* + * Scan for drives waiting for on line or status responses, + * and for drives with pending transfers. Put these on the + * controller queue, and mark the controller busy. + */ + for (unit = 0, dp = md->md_utab; unit < md->md_nunits; unit++, dp++) { + ui = md->md_dinfo[unit]; + if (ui == NULL || !ui->ui_alive || ui->ui_ctlr != mi->mi_ctlr) + continue; + ui->ui_flags &= ~(UNIT_HAVESTATUS | UNIT_ONLINE); + if ((ui->ui_flags & UNIT_REQUEUE) == 0 && dp->b_actf == NULL) + continue; + ui->ui_flags &= ~UNIT_REQUEUE; + MSCP_APPEND(dp, mi->mi_XXXtab, b_hash.le_next); + + dp->b_active = 1; + mi->mi_XXXtab->b_active = 1; + } + +#endif +#ifdef AVOID_EMULEX_BUG + /* + * ... and clear the index-to-buffer table. + */ + for (unit = 0; unit < AEB_MAX_BP; unit++) + mi->mi_bp[unit] = 0; +#endif +} + diff --git a/sys/arch/vax/vax/mscp.h b/sys/arch/vax/mscp/mscp.h index 1f538382277..64d5031d5ff 100644 --- a/sys/arch/vax/vax/mscp.h +++ b/sys/arch/vax/mscp/mscp.h @@ -1,4 +1,4 @@ -/* $NetBSD: mscp.h,v 1.3 1995/10/20 13:51:56 ragge Exp $ */ +/* $NetBSD: mscp.h,v 1.2 1996/07/10 23:35:59 ragge Exp $ */ /* * Copyright (c) 1988 Regents of the University of California. @@ -64,6 +64,7 @@ #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 */ @@ -88,6 +89,15 @@ #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 */ @@ -130,6 +140,8 @@ #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 @@ -165,6 +177,10 @@ #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 @@ -189,6 +205,10 @@ #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 */ /* @@ -236,7 +256,7 @@ struct mscpv_sccc { u_short sccc_hosttimo; /* host timeout */ u_short sccc_usefrac; /* use fraction */ long sccc_time; /* time and date */ - long sccc_xxx1; /* ? */ + long sccc_time1; /* it's a quad field */ long sccc_errlgfl; /* ? */ short sccc_xxx2; /* ? */ short sccc_copyspd; /* ? */ diff --git a/sys/arch/vax/mscp/mscp_disk.c b/sys/arch/vax/mscp/mscp_disk.c new file mode 100644 index 00000000000..394e1edf302 --- /dev/null +++ b/sys/arch/vax/mscp/mscp_disk.c @@ -0,0 +1,966 @@ +/* $NetBSD: mscp_disk.c,v 1.7 1997/01/11 11:20:32 ragge Exp $ */ +/* + * Copyright (c) 1996 Ludd, University of Lule}, Sweden. + * Copyright (c) 1988 Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Chris Torek. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)uda.c 7.32 (Berkeley) 2/13/91 + */ + +/* + * RA disk device driver + */ + +/* + * TODO + * write bad block forwarding code + */ + +#include <sys/param.h> +#include <sys/buf.h> +#include <sys/device.h> +#include <sys/disk.h> +#include <sys/disklabel.h> +#include <sys/ioctl.h> +#include <sys/stat.h> +#include <sys/fcntl.h> +#include <sys/proc.h> +#include <sys/systm.h> + +#include <ufs/ffs/fs.h> /* For some disklabel stuff */ + +#include <vax/mscp/mscp.h> +#include <vax/mscp/mscpvar.h> + +/* + * Drive status, per drive + */ +struct ra_softc { + struct device ra_dev; /* Autoconf struct */ + struct disk ra_disk; + int ra_state; /* open/closed state */ + u_long ra_mediaid; /* media id */ + int ra_hwunit; /* Hardware unit number */ + int ra_havelabel; /* true if we have a label */ + int ra_wlabel; /* label sector is currently writable */ + int ra_isafloppy; /* unit is a floppy disk */ +}; + +int ramatch __P((struct device *, void *, void *)); +void raattach __P((struct device *, struct device *, void *)); +void radgram __P((struct device *, struct mscp *, struct mscp_softc *)); +void raiodone __P((struct device *, struct buf *)); +int raonline __P((struct device *, struct mscp *)); +int ragotstatus __P((struct device *, struct mscp *)); +void rareplace __P((struct device *, struct mscp *)); +int raioerror __P((struct device *, struct mscp *, struct buf *)); +void rafillin __P((struct buf *, struct mscp *)); +void rabb __P((struct device *, struct mscp *, struct buf *)); +int raopen __P((dev_t, int, int, struct proc *)); +int raclose __P((dev_t, int, int, struct proc *)); +void rastrategy __P((struct buf *)); +void rastrat1 __P((struct buf *)); +int raread __P((dev_t, struct uio *)); +int rawrite __P((dev_t, struct uio *)); +int raioctl __P((dev_t, int, caddr_t, int, struct proc *)); +int radump __P((dev_t, daddr_t, caddr_t, size_t)); +int rasize __P((dev_t)); +int ra_putonline __P((struct ra_softc *)); + + +struct mscp_device ra_device = { + radgram, + raiodone, + raonline, + ragotstatus, + rareplace, + raioerror, + rabb, + rafillin, +}; + +/* + * Device to unit number and partition and back + */ +#define UNITSHIFT 3 +#define UNITMASK 7 +#define raunit(dev) (minor(dev) >> UNITSHIFT) +#define rapart(dev) (minor(dev) & UNITMASK) +#define raminor(u, p) (((u) << UNITSHIFT) | (p)) + +struct cfdriver ra_cd = { + NULL, "ra", DV_DULL +}; + +struct cfattach ra_ca = { + sizeof(struct ra_softc), ramatch, raattach +}; + +/* + * Software state, per drive + */ +#define RA_OFFLINE 0 +#define RA_WANTOPEN 1 +#define RA_ONLINE 3 + +/* + * More driver definitions, for generic MSCP code. + */ +extern int cold; + +int +ramatch(parent, match, aux) + struct device *parent; + void *match, *aux; +{ + struct cfdata *cf = match; + struct drive_attach_args *da = aux; + struct mscp *mp = da->da_mp; + + if ((da->da_typ & MSCPBUS_DISK) == 0) + return 0; + if (cf->cf_loc[0] != -1 && cf->cf_loc[0] != mp->mscp_unit) + return 0; + return 1; +} + +/* + * The attach routine only checks and prints drive type. + * Bringing the disk online is done when the disk is accessed + * the first time. + */ +void +raattach(parent, self, aux) + struct device *parent, *self; + void *aux; +{ + struct ra_softc *ra = (void *)self; + struct drive_attach_args *da = aux; + struct mscp *mp = da->da_mp; + struct mscp_softc *mi = (void *)parent; + struct disklabel *dl; + + ra->ra_mediaid = mp->mscp_guse.guse_mediaid; + ra->ra_state = RA_OFFLINE; + ra->ra_havelabel = 0; + ra->ra_hwunit = mp->mscp_unit; + mi->mi_dp[mp->mscp_unit] = self; + disk_attach((struct disk *)&ra->ra_disk); + + /* Fill in what we know. The actual size is gotten later */ + dl = ra->ra_disk.dk_label; + + dl->d_secsize = DEV_BSIZE; + dl->d_nsectors = mp->mscp_guse.guse_nspt; + dl->d_ntracks = mp->mscp_guse.guse_ngpc; + dl->d_secpercyl = dl->d_nsectors * dl->d_ntracks; + disk_printtype(mp->mscp_unit, mp->mscp_guse.guse_mediaid); +} + +/* + * (Try to) put the drive online. This is done the first time the + * drive is opened, or if it har fallen offline. + */ +int +ra_putonline(ra) + struct ra_softc *ra; +{ + struct mscp *mp; + struct mscp_softc *mi = (struct mscp_softc *)ra->ra_dev.dv_parent; + struct disklabel *dl; + volatile int i; + char *msg; + + dl = ra->ra_disk.dk_label; + + ra->ra_state = RA_WANTOPEN; + mp = mscp_getcp(mi, MSCP_WAIT); + mp->mscp_opcode = M_OP_ONLINE; + mp->mscp_unit = ra->ra_hwunit; + mp->mscp_cmdref = (long)&ra->ra_state; + *mp->mscp_addr |= MSCP_OWN | MSCP_INT; + + /* Poll away */ + i = *mi->mi_ip; + if (tsleep(&ra->ra_state, PRIBIO, "raonline", 100*100)) { + ra->ra_state = RA_OFFLINE; + return MSCP_FAILED; + } + + if (ra->ra_state == RA_OFFLINE) + return MSCP_FAILED; + if (ra->ra_isafloppy) + return MSCP_DONE; + dl->d_partitions[0].p_size = dl->d_partitions[2].p_size = + dl->d_secperunit; + dl->d_partitions[0].p_offset = dl->d_partitions[2].p_offset = 0; + + printf("%s", ra->ra_dev.dv_xname); + if ((msg = readdisklabel(raminor(ra->ra_dev.dv_unit, 0), + rastrategy, dl, NULL)) != NULL) + printf(": %s", msg); + else + ra->ra_havelabel = 1; + ra->ra_state = RA_ONLINE; + + printf(": size %d sectors\n", dl->d_secperunit); + + return MSCP_DONE; +} +/* + * Open a drive. + */ +/*ARGSUSED*/ +int +raopen(dev, flag, fmt, p) + dev_t dev; + int flag, fmt; + struct proc *p; +{ + register struct ra_softc *ra; + int part, unit, mask; + + /* + * Make sure this is a reasonable open request. + */ + unit = raunit(dev); + if (unit >= ra_cd.cd_ndevs) + return ENXIO; + ra = ra_cd.cd_devs[unit]; + if (ra == 0) + return ENXIO; + + /* + * If this is the first open; we must first try to put + * the disk online (and read the label). + */ + if (ra->ra_state == RA_OFFLINE) + if (ra_putonline(ra) == MSCP_FAILED) + return EIO; + + part = raunit(dev); + if (ra->ra_isafloppy == 0) + if (part >= ra->ra_disk.dk_label->d_npartitions) + return ENXIO; + + /* + * Wait for the state to settle + */ +#if notyet + while (ra->ra_state != RA_ONLINE) + if ((error = tsleep((caddr_t)ra, (PZERO + 1) | PCATCH, + devopn, 0))) { + splx(s); + return (error); + } +#endif + + mask = 1 << part; + + switch (fmt) { + case S_IFCHR: + ra->ra_disk.dk_copenmask |= mask; + break; + case S_IFBLK: + ra->ra_disk.dk_bopenmask |= mask; + break; + } + ra->ra_disk.dk_openmask |= mask; + return 0; +} + +/* ARGSUSED */ +int +raclose(dev, flags, fmt, p) + dev_t dev; + int flags, fmt; + struct proc *p; +{ + register int unit = raunit(dev); + register struct ra_softc *ra = ra_cd.cd_devs[unit]; + int mask = (1 << rapart(dev)); + + switch (fmt) { + case S_IFCHR: + ra->ra_disk.dk_copenmask &= ~mask; + break; + case S_IFBLK: + ra->ra_disk.dk_bopenmask &= ~mask; + break; + } + ra->ra_disk.dk_openmask = + ra->ra_disk.dk_copenmask | ra->ra_disk.dk_bopenmask; + + /* + * Should wait for I/O to complete on this partition even if + * others are open, but wait for work on blkflush(). + */ +#if 0 + if (ra->ra_openpart == 0) { + s = splbio(); + while (udautab[unit].b_actf) + sleep((caddr_t)&udautab[unit], PZERO - 1); + splx(s); + ra->ra_state = CLOSED; + ra->ra_wlabel = 0; + } +#endif + return (0); +} + +/* + * Queue a transfer request, and if possible, hand it to the controller. + * + * This routine is broken into two so that the internal version + * udastrat1() can be called by the (nonexistent, as yet) bad block + * revectoring routine. + */ +void +rastrategy(bp) + register struct buf *bp; +{ + register int unit; + register struct ra_softc *ra; + int p; + /* + * Make sure this is a reasonable drive to use. + */ + unit = raunit(bp->b_dev); + if (unit > ra_cd.cd_ndevs || (ra = ra_cd.cd_devs[unit]) == NULL) { + bp->b_error = ENXIO; + goto bad; + } + /* + * If drive is open `raw' or reading label, let it at it. + */ + if (ra->ra_state < RA_ONLINE) { + mscp_strategy(bp, ra->ra_dev.dv_parent); + return; + } + p = rapart(bp->b_dev); + + /* + * Determine the size of the transfer, and make sure it is + * within the boundaries of the partition. + */ + if (ra->ra_isafloppy) { + if (bp->b_blkno >= ra->ra_disk.dk_label->d_secperunit) { + bp->b_resid = bp->b_bcount; + goto done; + } + } else + if (bounds_check_with_label(bp, ra->ra_disk.dk_label, + ra->ra_wlabel) <= 0) { + bp->b_error = ENXIO; + goto bad; + } + + mscp_strategy(bp, ra->ra_dev.dv_parent); + return; + +bad: + bp->b_flags |= B_ERROR; +done: + biodone(bp); +} + +int +raread(dev, uio) + dev_t dev; + struct uio *uio; +{ + + return (physio(rastrategy, NULL, dev, B_READ, minphys, uio)); +} + +int +rawrite(dev, uio) + dev_t dev; + struct uio *uio; +{ + + return (physio(rastrategy, NULL, dev, B_WRITE, minphys, uio)); +} + +void +raiodone(usc, bp) + struct device *usc; + struct buf *bp; +{ + + biodone(bp); +} + +/* + * Fill in disk addresses in a mscp packet waiting for transfer. + */ +void +rafillin(bp, mp) + struct buf *bp; + struct mscp *mp; +{ + int unit = raunit(bp->b_dev); + int part = rapart(bp->b_dev); + struct ra_softc *ra = ra_cd.cd_devs[unit]; + struct disklabel *lp = ra->ra_disk.dk_label; + + + /* XXX more checks needed */ + mp->mscp_unit = ra->ra_hwunit; + mp->mscp_seq.seq_lbn = bp->b_blkno + lp->d_partitions[part].p_offset; + mp->mscp_seq.seq_bytecount = bp->b_bcount; +} + +/* + * Handle an error datagram. + * This can come from an unconfigured drive as well. + */ +void +radgram(usc, mp, mi) + struct device *usc; + struct mscp *mp; + struct mscp_softc *mi; +{ + if (mscp_decodeerror(usc == NULL?"unconf ra" : usc->dv_xname, mp, mi)) + return; + /* + * SDI status information bytes 10 and 11 are the microprocessor + * error code and front panel code respectively. These vary per + * drive type and are printed purely for field service information. + */ + if (mp->mscp_format == M_FM_SDI) + printf("\tsdi uproc error code 0x%x, front panel code 0x%x\n", + mp->mscp_erd.erd_sdistat[10], + mp->mscp_erd.erd_sdistat[11]); +} + +/* + * A drive came on line. Check its type and size. Return DONE if + * we think the drive is truly on line. In any case, awaken anyone + * sleeping on the drive on-line-ness. + */ +int +raonline(usc, mp) + struct device *usc; + struct mscp *mp; +{ + register struct ra_softc *ra = (void *)usc; + struct disklabel *dl; + int p = 0, d, n; + + wakeup((caddr_t)&ra->ra_state); + if ((mp->mscp_status & M_ST_MASK) != M_ST_SUCCESS) { + printf("%s: attempt to bring on line failed: ", + ra->ra_dev.dv_xname); + mscp_printevent(mp); + ra->ra_state = RA_OFFLINE; + return (MSCP_FAILED); + } + + /* + * Fill in the rest of disk size. + */ + ra->ra_state = RA_WANTOPEN; + dl = ra->ra_disk.dk_label; + dl->d_secperunit = (daddr_t)mp->mscp_onle.onle_unitsize; + + if (dl->d_secpercyl != 0) + dl->d_ncylinders = dl->d_secperunit/dl->d_secpercyl; + else + ra->ra_isafloppy = 1; + dl->d_type = DTYPE_MSCP; + dl->d_rpm = 3600; + dl->d_bbsize = BBSIZE; + dl->d_sbsize = SBSIZE; + + /* Create the disk name for disklabel. Phew... */ + d = ra->ra_mediaid; + dl->d_typename[p++] = MSCP_MID_CHAR(2, d); + dl->d_typename[p++] = MSCP_MID_CHAR(1, d); + if (MSCP_MID_ECH(0, d)) + dl->d_typename[p++] = MSCP_MID_CHAR(0, d); + n = MSCP_MID_NUM(d); + if (n > 99) { + dl->d_typename[p++] = '1'; + n -= 100; + } + if (n > 9) { + dl->d_typename[p++] = (n / 10) + '0'; + n %= 10; + } + dl->d_typename[p++] = n + '0'; + dl->d_typename[p] = 0; + dl->d_npartitions = MAXPARTITIONS; + + return (MSCP_DONE); +} + +/* + * We got some (configured) unit's status. Return DONE if it succeeded. + */ +int +ragotstatus(usc, mp) + register struct device *usc; + register struct mscp *mp; +{ + if ((mp->mscp_status & M_ST_MASK) != M_ST_SUCCESS) { + printf("%s: attempt to get status failed: ", usc->dv_xname); + mscp_printevent(mp); + return (MSCP_FAILED); + } + /* record for (future) bad block forwarding and whatever else */ +#ifdef notyet + uda_rasave(ui->ui_unit, mp, 1); +#endif + return (MSCP_DONE); +} + +/* + * A transfer failed. We get a chance to fix or restart it. + * Need to write the bad block forwaring code first.... + */ +/*ARGSUSED*/ +int +raioerror(usc, mp, bp) + register struct device *usc; + register struct mscp *mp; + struct buf *bp; +{ +printf("raioerror\n"); +#if 0 + if (mp->mscp_flags & M_EF_BBLKR) { + /* + * A bad block report. Eventually we will + * restart this transfer, but for now, just + * log it and give up. + */ + log(LOG_ERR, "ra%d: bad block report: %d%s\n", + ui->ui_unit, (int)mp->mscp_seq.seq_lbn, + mp->mscp_flags & M_EF_BBLKU ? " + others" : ""); + } else { + /* + * What the heck IS a `serious exception' anyway? + * IT SURE WOULD BE NICE IF DEC SOLD DOCUMENTATION + * FOR THEIR OWN CONTROLLERS. + */ + if (mp->mscp_flags & M_EF_SEREX) + log(LOG_ERR, "ra%d: serious exception reported\n", + ui->ui_unit); + } +#endif + return (MSCP_FAILED); +} + +/* + * A replace operation finished. + */ +/*ARGSUSED*/ +void +rareplace(usc, mp) + struct device *usc; + struct mscp *mp; +{ + + panic("udareplace"); +} + +/* + * A bad block related operation finished. + */ +/*ARGSUSED*/ +void +rabb(usc, mp, bp) + struct device *usc; + struct mscp *mp; + struct buf *bp; +{ + + panic("udabb"); +} + + +/* + * I/O controls. + */ +int +raioctl(dev, cmd, data, flag, p) + dev_t dev; + int cmd; + caddr_t data; + int flag; + struct proc *p; +{ + register int unit = raunit(dev); + register struct disklabel *lp; + register struct ra_softc *ra = ra_cd.cd_devs[unit]; + int error = 0; + + lp = ra->ra_disk.dk_label; + + switch (cmd) { + + case DIOCGDINFO: + bcopy(lp, data, sizeof (struct disklabel)); + break; + + case DIOCGPART: + ((struct partinfo *)data)->disklab = lp; + ((struct partinfo *)data)->part = + &lp->d_partitions[rapart(dev)]; + break; + + case DIOCSDINFO: + if ((flag & FWRITE) == 0) + error = EBADF; + else + error = setdisklabel(lp, (struct disklabel *)data,0,0); + break; + + case DIOCWLABEL: + if ((flag & FWRITE) == 0) + error = EBADF; + else + ra->ra_wlabel = 1; + break; + + case DIOCWDINFO: + if ((flag & FWRITE) == 0) + error = EBADF; + else { + ra->ra_wlabel = 1; + error = writedisklabel(dev, rastrategy, lp,0); + ra->ra_wlabel = 0; + } + break; + + default: + error = ENOTTY; + break; + } + return (error); +} + +#if 0 +/* + * Do a panic dump. We set up the controller for one command packet + * and one response packet, for which we use `struct uda1'. + */ +struct uda1 { + struct uda1ca uda1_ca; /* communications area */ + struct mscp uda1_rsp; /* response packet */ + struct mscp uda1_cmd; /* command packet */ +} uda1; +#endif + +#define DBSIZE 32 /* dump 16K at a time */ + +int +radump(dev, blkno, va, size) + dev_t dev; + daddr_t blkno; + caddr_t va; + size_t size; +{ +#if 0 + struct udadevice *udaddr; + struct uda1 *ud_ubaddr; + char *start; + int num, blk, unit, maxsz, blkoff, reg; + struct partition *pp; + struct uba_regs *uba; + struct uba_device *ui; + struct uda1 *ud; + struct pte *io; + int i; + + /* + * Make sure the device is a reasonable place on which to dump. + */ + unit = udaunit(dev); + if (unit >= NRA) + return (ENXIO); +#define phys(cast, addr) ((cast) ((int)addr & 0x7fffffff)) + ui = phys(struct uba_device *, udadinfo[unit]); + if (ui == NULL || ui->ui_alive == 0) + return (ENXIO); + + /* + * Find and initialise the UBA; get the physical address of the + * device registers, and of communications area and command and + * response packet. + */ + uba = phys(struct uba_softc *, ui->ui_hd)->uh_physuba; + ubainit(ui->ui_hd); + udaddr = (struct udadevice *)ui->ui_physaddr; + ud = phys(struct uda1 *, &uda1); + /* + * Map the ca+packets into Unibus I/O space so the UDA50 can get + * at them. Use the registers at the end of the Unibus map (since + * we will use the registers at the beginning to map the memory + * we are dumping). + */ + num = btoc(sizeof(struct uda1)) + 1; + reg = NUBMREG - num; + io = (void *)&uba->uba_map[reg]; + for (i = 0; i < num; i++) + *(int *)io++ = UBAMR_MRV | (btop(ud) + i); + ud_ubaddr = (struct uda1 *)(((int)ud & PGOFSET) | (reg << 9)); + + /* + * Initialise the controller, with one command and one response + * packet. + */ + udaddr->udaip = 0; + if (udadumpwait(udaddr, UDA_STEP1)) + return (EFAULT); + udaddr->udasa = UDA_ERR; + if (udadumpwait(udaddr, UDA_STEP2)) + return (EFAULT); + udaddr->udasa = (int)&ud_ubaddr->uda1_ca.ca_rspdsc; + if (udadumpwait(udaddr, UDA_STEP3)) + return (EFAULT); + udaddr->udasa = ((int)&ud_ubaddr->uda1_ca.ca_rspdsc) >> 16; + if (udadumpwait(udaddr, UDA_STEP4)) + return (EFAULT); + ((struct uda_softc *)uda_cd.cd_devs[ui->ui_ctlr])->sc_micro = udaddr->udasa & 0xff; + udaddr->udasa = UDA_GO; + + /* + * Set up the command and response descriptor, then set the + * controller characteristics and bring the drive on line. + * Note that all uninitialised locations in uda1_cmd are zero. + */ + ud->uda1_ca.ca_rspdsc = (long)&ud_ubaddr->uda1_rsp.mscp_cmdref; + ud->uda1_ca.ca_cmddsc = (long)&ud_ubaddr->uda1_cmd.mscp_cmdref; + /* ud->uda1_cmd.mscp_sccc.sccc_ctlrflags = 0; */ + /* ud->uda1_cmd.mscp_sccc.sccc_version = 0; */ + if (udadumpcmd(M_OP_SETCTLRC, ud, ui)) + return (EFAULT); + ud->uda1_cmd.mscp_unit = ui->ui_slave; + if (udadumpcmd(M_OP_ONLINE, ud, ui)) + return (EFAULT); + + pp = phys(struct partition *, + &udalabel[unit].d_partitions[udapart(dev)]); + maxsz = pp->p_size; + blkoff = pp->p_offset; + + /* + * Dump all of physical memory, or as much as will fit in the + * space provided. + */ + start = 0; + printf("Dumpar {r inte implementerade {n :) \n"); + asm("halt"); +/* num = maxfree; */ + if (dumplo + num >= maxsz) + num = maxsz - dumplo; + blkoff += dumplo; + + /* + * Write out memory, DBSIZE pages at a time. + * N.B.: this code depends on the fact that the sector + * size == the page size. + */ + while (num > 0) { + blk = num > DBSIZE ? DBSIZE : num; + io = (void *)uba->uba_map; + /* + * Map in the pages to write, leaving an invalid entry + * at the end to guard against wild Unibus transfers. + * Then do the write. + */ + for (i = 0; i < blk; i++) + *(int *)io++ = UBAMR_MRV | (btop(start) + i); + *(int *)io = 0; + ud->uda1_cmd.mscp_unit = ui->ui_slave; + ud->uda1_cmd.mscp_seq.seq_lbn = btop(start) + blkoff; + ud->uda1_cmd.mscp_seq.seq_bytecount = blk << PGSHIFT; + if (udadumpcmd(M_OP_WRITE, ud, ui)) + return (EIO); + start += blk << PGSHIFT; + num -= blk; + } + return (0); /* made it! */ +} + +/* + * Wait for some of the bits in `bits' to come on. If the error bit + * comes on, or ten seconds pass without response, return true (error). + */ +int +udadumpwait(udaddr, bits) + struct udadevice *udaddr; + register int bits; +{ + register int timo = todr() + 1000; + + while ((udaddr->udasa & bits) == 0) { + if (udaddr->udasa & UDA_ERR) { + char bits[64]; + printf("udasa=%s\ndump ", + bitmask_snprintf(udaddr->udasa, udasr_bits, + bits, sizeof(bits))); + return (1); + } + if (todr() >= timo) { + printf("timeout\ndump "); + return (1); + } + } + return (0); +} + +/* + * Feed a command to the UDA50, wait for its response, and return + * true iff something went wrong. + */ +int +udadumpcmd(op, ud, ui) + int op; + struct uda1 *ud; + struct uba_device *ui; +{ + volatile struct udadevice *udaddr; + volatile int n; +#define mp (&ud->uda1_rsp) + + udaddr = (struct udadevice *)ui->ui_physaddr; + ud->uda1_cmd.mscp_opcode = op; + ud->uda1_cmd.mscp_msglen = MSCP_MSGLEN; + ud->uda1_rsp.mscp_msglen = MSCP_MSGLEN; + ud->uda1_ca.ca_rspdsc |= MSCP_OWN | MSCP_INT; + ud->uda1_ca.ca_cmddsc |= MSCP_OWN | MSCP_INT; + if (udaddr->udasa & UDA_ERR) { + char bits[64]; + printf("udasa=%s\ndump ", bitmask_snprintf(udaddr->udasa, + udasr_bits, bits, sizeof(bits))); + return (1); + } + n = udaddr->udaip; + n = todr() + 1000; + for (;;) { + if (todr() > n) { + printf("timeout\ndump "); + return (1); + } + if (ud->uda1_ca.ca_cmdint) + ud->uda1_ca.ca_cmdint = 0; + if (ud->uda1_ca.ca_rspint == 0) + continue; + ud->uda1_ca.ca_rspint = 0; + if (mp->mscp_opcode == (op | M_OP_END)) + break; + printf("\n"); + switch (MSCP_MSGTYPE(mp->mscp_msgtc)) { + + case MSCPT_SEQ: + printf("sequential"); + break; + + case MSCPT_DATAGRAM: + mscp_decodeerror("uda", ui->ui_ctlr, mp); + printf("datagram"); + break; + + case MSCPT_CREDITS: + printf("credits"); + break; + + case MSCPT_MAINTENANCE: + printf("maintenance"); + break; + + default: + printf("unknown (type 0x%x)", + MSCP_MSGTYPE(mp->mscp_msgtc)); + break; + } + printf(" ignored\ndump "); + ud->uda1_ca.ca_rspdsc |= MSCP_OWN | MSCP_INT; + } + if ((mp->mscp_status & M_ST_MASK) != M_ST_SUCCESS) { + printf("error: op 0x%x => 0x%x status 0x%x\ndump ", op, + mp->mscp_opcode, mp->mscp_status); + return (1); + } +#endif + return (0); +#undef mp +} + +/* + * Return the size of a partition, if known, or -1 if not. + */ +int +rasize(dev) + dev_t dev; +{ + register int unit = raunit(dev); + struct ra_softc *ra; + + if (unit >= ra_cd.cd_ndevs || ra_cd.cd_devs[unit] == 0) + return -1; + + ra = ra_cd.cd_devs[unit]; + + if (ra->ra_state == RA_OFFLINE) + if (ra_putonline(ra) == MSCP_FAILED) + return -1; + + return ra->ra_disk.dk_label->d_partitions[rapart(dev)].p_size; +} + +int +ra_getdev(adaptor, controller, unit, uname) + int adaptor, controller, unit; + char **uname; +{ + struct mscp_softc *mi; + struct ra_softc *ra; + int i; + + for (i = 0; i < ra_cd.cd_ndevs; i++) { + if ((ra = ra_cd.cd_devs[i]) == 0) + continue; + + mi = (void *)ra->ra_dev.dv_parent; + if (mi->mi_ctlrnr == controller && mi->mi_adapnr == adaptor && + ra->ra_hwunit == unit) { + *uname = ra->ra_dev.dv_xname; + return i; + } + } + return -1; +} diff --git a/sys/arch/vax/mscp/mscp_subr.c b/sys/arch/vax/mscp/mscp_subr.c new file mode 100644 index 00000000000..8634a33ecc3 --- /dev/null +++ b/sys/arch/vax/mscp/mscp_subr.c @@ -0,0 +1,836 @@ +/* $NetBSD: mscp_subr.c,v 1.6 1997/01/11 11:20:34 ragge Exp $ */ +/* + * Copyright (c) 1996 Ludd, University of Lule}, Sweden. + * Copyright (c) 1988 Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Chris Torek. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)mscp.c 7.5 (Berkeley) 12/16/90 + */ + +/* + * MSCP generic driver routines + */ + +#include <sys/param.h> +#include <sys/device.h> +#include <sys/buf.h> +#include <sys/systm.h> +#include <sys/proc.h> + +#include <machine/sid.h> + +#include <vax/mscp/mscp.h> +#include <vax/mscp/mscpreg.h> +#include <vax/mscp/mscpvar.h> + +#include "ra.h" +#include "mt.h" + +#define b_forw b_hash.le_next + +int mscp_match __P((struct device *, void *, void *)); +void mscp_attach __P((struct device *, struct device *, void *)); +void mscp_start __P((struct mscp_softc *)); +int mscp_init __P((struct mscp_softc *)); +void mscp_initds __P((struct mscp_softc *)); +int mscp_waitstep __P((struct mscp_softc *, int, int)); + +struct cfattach mscpbus_ca = { + sizeof(struct mscp_softc), mscp_match, mscp_attach +}; + +struct cfdriver mscpbus_cd = { + NULL, "mscpbus", DV_DULL +}; + +struct mscp slavereply; + +/* + * This function is for delay during init. Some MSCP clone card (Dilog) + * can't handle fast read from its registers, and therefore need + * a delay between them. + */ + +#define DELAYTEN 1000 +int +mscp_waitstep(mi, mask, result) + struct mscp_softc *mi; + int mask, result; +{ + int status = 1; + + if ((*mi->mi_sa & mask) != result) { + volatile int count = 0; + while ((*mi->mi_sa & mask) != result) { + DELAY(10000); + count += 1; + if (count > DELAYTEN) + break; + } + if (count > DELAYTEN) + status = 0; + } + return status; +} + +int +mscp_match(parent, match, aux) + struct device *parent; + void *match, *aux; +{ + struct mscp_attach_args *ma = aux; + +#if NRA + if (ma->ma_type & MSCPBUS_DISK) + return 1; +#endif +#if NMT + if (ma->ma_type & MSCPBUS_TAPE) + return 1; +#endif + return 0; +}; + +void +mscp_attach(parent, self, aux) + struct device *parent, *self; + void *aux; +{ + struct mscp_attach_args *ma = aux; + struct mscp_softc *mi = (void *)self; + volatile struct mscp *mp; + volatile int i; + int timeout, next = 0; + + mi->mi_mc = ma->ma_mc; + mi->mi_me = NULL; + mi->mi_type = ma->ma_type; + mi->mi_uuda = ma->ma_uuda; + mi->mi_uda = ma->ma_uda; + mi->mi_ip = ma->ma_ip; + mi->mi_sa = ma->ma_sa; + mi->mi_sw = ma->ma_sw; + mi->mi_ivec = ma->ma_ivec; + mi->mi_adapnr = ma->ma_adapnr; + mi->mi_ctlrnr = ma->ma_ctlrnr; + *ma->ma_softc = mi; + /* + * Go out to init the bus, so that we can give commands + * to its devices. + */ + mi->mi_cmd.mri_size = NCMD; + mi->mi_cmd.mri_desc = mi->mi_uda->mp_ca.ca_cmddsc; + mi->mi_cmd.mri_ring = mi->mi_uda->mp_cmd; + mi->mi_rsp.mri_size = NRSP; + mi->mi_rsp.mri_desc = mi->mi_uda->mp_ca.ca_rspdsc; + mi->mi_rsp.mri_ring = mi->mi_uda->mp_rsp; + mi->mi_actf = (void *)&mi->mi_actf; /* Circular wait queue */ + mi->mi_actb = (void *)&mi->mi_actf; + + if (mscp_init(mi)) { + printf("%s: can't init, controller hung\n", + mi->mi_dev.dv_xname); + return; + } + +#if NRA + if (ma->ma_type & MSCPBUS_DISK) { + extern struct mscp_device ra_device; + + mi->mi_me = &ra_device; + } +#endif +#if NMT + if (ma->ma_type & MSCPBUS_TAPE) { + extern struct mscp_device mt_device; + + mi->mi_me = &mt_device; + } +#endif + /* + * Go out and search for sub-units on this MSCP bus, + * and call config_found for each found. + */ +findunit: + mp = mscp_getcp(mi, MSCP_DONTWAIT); + if (mp == NULL) + panic("mscpattach: no packets"); + mp->mscp_opcode = M_OP_GETUNITST; + mp->mscp_unit = next; + mp->mscp_modifier = M_GUM_NEXTUNIT; + *mp->mscp_addr |= MSCP_OWN | MSCP_INT; + slavereply.mscp_opcode = 0; + + i = *mi->mi_ip; /* Kick off polling */ + mp = &slavereply; + timeout = 1000; + while (timeout-- > 0) { + DELAY(10000); + if (mp->mscp_opcode) + goto gotit; + } + printf("%s: no response to Get Unit Status request\n", + mi->mi_dev.dv_xname); + return; + +gotit: /* + * Got a slave response. If the unit is there, use it. + */ + switch (mp->mscp_status & M_ST_MASK) { + + case M_ST_SUCCESS: /* worked */ + case M_ST_AVAILABLE: /* found another drive */ + break; /* use it */ + + case M_ST_OFFLINE: + /* + * Figure out why it is off line. It may be because + * it is nonexistent, or because it is spun down, or + * for some other reason. + */ + switch (mp->mscp_status & ~M_ST_MASK) { + + case M_OFFLINE_UNKNOWN: + /* + * No such drive, and there are none with + * higher unit numbers either, if we are + * using M_GUM_NEXTUNIT. + */ + mi->mi_ierr = 3; + return; + + case M_OFFLINE_UNMOUNTED: + /* + * The drive is not spun up. Use it anyway. + * + * N.B.: this seems to be a common occurrance + * after a power failure. The first attempt + * to bring it on line seems to spin it up + * (and thus takes several minutes). Perhaps + * we should note here that the on-line may + * take longer than usual. + */ + break; + + default: + /* + * In service, or something else equally unusable. + */ + printf("%s: unit %d off line: ", mi->mi_dev.dv_xname, + mp->mscp_unit); + mscp_printevent((struct mscp *)mp); + next++; + goto findunit; + } + break; + + default: + printf("%s: unable to get unit status: ", mi->mi_dev.dv_xname); + mscp_printevent((struct mscp *)mp); + return; + } + + /* + * If we get a lower number, we have circulated around all + * devices and are finished, otherwise try to find next unit. + * We shouldn't ever get this, it's a workaround. + */ + if (mp->mscp_unit < next) + return; + + next = mp->mscp_unit + 1; + goto findunit; +} + + +/* + * The ctlr gets initialised, normally after boot but may also be + * done if the ctlr gets in an unknown state. Returns 1 if init + * fails, 0 otherwise. + */ +int +mscp_init(mi) + struct mscp_softc *mi; +{ + struct mscp *mp; + volatile int i; + int status, count; + unsigned int j = 0; + + /* + * While we are thinking about it, reset the next command + * and response indicies. + */ + mi->mi_cmd.mri_next = 0; + mi->mi_rsp.mri_next = 0; + + mi->mi_flags |= MSC_IGNOREINTR; + + if ((mi->mi_type & MSCPBUS_KDB) == 0) + *mi->mi_ip = 0; /* Kick off */ + + status = mscp_waitstep(mi, MP_STEP1, MP_STEP1);/* Wait to it wakes up */ + if (status == 0) + return 1; /* Init failed */ + if (*mi->mi_sa & MP_ERR) { + (*mi->mi_mc->mc_saerror)(mi->mi_dev.dv_parent, 0); + return 1; + } + + /* step1 */ + *mi->mi_sw = MP_ERR | (NCMDL2 << 11) | (NRSPL2 << 8) | + MP_IE | (mi->mi_ivec >> 2); + status = mscp_waitstep(mi, STEP1MASK, STEP1GOOD); + if (status == 0) { + (*mi->mi_mc->mc_saerror)(mi->mi_dev.dv_parent, 0); + return 1; + } + + /* step2 */ + *mi->mi_sw = (int)&mi->mi_uuda->mp_ca.ca_rspdsc[0] | + (vax_cputype == VAX_780 || vax_cputype == VAX_8600 ? MP_PI : 0); + status = mscp_waitstep(mi, STEP2MASK, STEP2GOOD(mi->mi_ivec >> 2)); + if (status == 0) { + (*mi->mi_mc->mc_saerror)(mi->mi_dev.dv_parent, 0); + return 1; + } + + /* step3 */ + *mi->mi_sw = ((int)&mi->mi_uuda->mp_ca.ca_rspdsc[0]) >> 16; + status = mscp_waitstep(mi, STEP3MASK, STEP3GOOD); + if (status == 0) { + (*mi->mi_mc->mc_saerror)(mi->mi_dev.dv_parent, 0); + return 1; + } + i = *mi->mi_sa & 0377; + printf(": version %d model %d\n", i & 15, i >> 4); + +#define BURST 4 /* XXX */ + if (mi->mi_type & MSCPBUS_UDA) { + *mi->mi_sw = MP_GO | (BURST - 1) << 2; + printf("%s: DMA burst size set to %d\n", + mi->mi_dev.dv_xname, BURST); + } + *mi->mi_sw = MP_GO; + + mscp_initds(mi); + mi->mi_flags &= ~MSC_IGNOREINTR; + + /* + * Set up all necessary info in the bus softc struct, get a + * mscp packet and set characteristics for this controller. + */ + mi->mi_credits = MSCP_MINCREDITS + 1; + mp = mscp_getcp(mi, MSCP_DONTWAIT); + + mi->mi_credits = 0; + mp->mscp_opcode = M_OP_SETCTLRC; + mp->mscp_unit = mp->mscp_modifier = mp->mscp_flags = + mp->mscp_sccc.sccc_version = mp->mscp_sccc.sccc_hosttimo = + mp->mscp_sccc.sccc_time = mp->mscp_sccc.sccc_time1 = + mp->mscp_sccc.sccc_errlgfl = 0; + mp->mscp_sccc.sccc_ctlrflags = M_CF_ATTN | M_CF_MISC | M_CF_THIS; + *mp->mscp_addr |= MSCP_OWN | MSCP_INT; + i = *mi->mi_ip; + + count = 0; + while (count < DELAYTEN) { + if (((volatile)mi->mi_flags & MSC_READY) != 0) + break; + if ((j = *mi->mi_sa) & MP_ERR) + goto out; + DELAY(10000); + count += 1; + } + if (count == DELAYTEN) { +out: + printf("%s: couldn't set ctlr characteristics, sa=%x\n", + mi->mi_dev.dv_xname, j); + return 1; + } + return 0; +} + +/* + * Initialise the various data structures that control the mscp protocol. + */ +void +mscp_initds(mi) + struct mscp_softc *mi; +{ + struct mscp_pack *uud = mi->mi_uuda; + struct mscp_pack *ud = mi->mi_uda; + struct mscp *mp; + int i; + + for (i = 0, mp = ud->mp_rsp; i < NRSP; i++, mp++) { + ud->mp_ca.ca_rspdsc[i] = MSCP_OWN | MSCP_INT | + (long)&uud->mp_rsp[i].mscp_cmdref; + mp->mscp_addr = &ud->mp_ca.ca_rspdsc[i]; + mp->mscp_msglen = MSCP_MSGLEN; + } + for (i = 0, mp = ud->mp_cmd; i < NCMD; i++, mp++) { + ud->mp_ca.ca_cmddsc[i] = MSCP_INT | + (long)&uud->mp_cmd[i].mscp_cmdref; + mp->mscp_addr = &ud->mp_ca.ca_cmddsc[i]; + mp->mscp_msglen = MSCP_MSGLEN; + if (mi->mi_type & MSCPBUS_TAPE) + mp->mscp_vcid = 1; + } +} + +void +mscp_intr(mi) + struct mscp_softc *mi; +{ + struct mscp_pack *ud = mi->mi_uda; + + if (mi->mi_flags & MSC_IGNOREINTR) + return; + /* + * Check for response and command ring transitions. + */ + if (ud->mp_ca.ca_rspint) { + ud->mp_ca.ca_rspint = 0; + mscp_dorsp(mi); + } + if (ud->mp_ca.ca_cmdint) { + ud->mp_ca.ca_cmdint = 0; + MSCP_DOCMD(mi); + } + + /* + * If there are any not-yet-handled requeset, try them now. + * XXX - We handles them (erroneous) in last-in first-handled order. + * Must we fix this??? + */ + while (mi->mi_w) { + struct buf *bp = mi->mi_w; + + mi->mi_w = (void *)bp->b_actb; + mscp_strategy(bp, (struct device *)mi); + if (mi->mi_w == bp) + break; + } +} + +int +mscp_print(aux, name) + void *aux; + const char *name; +{ + return UNCONF; +} + +/* + * common strategy routine for all types of MSCP devices. + * bp is the current buf, dp is the drive queue. + */ +void +mscp_strategy(bp, usc) + struct buf *bp; + struct device *usc; +{ + struct mscp_softc *mi = (void *)usc; + struct mscp *mp; + int s = spl6(); + + /* + * Ok; we are ready to try to start a xfer. Get a MSCP packet + * and try to start... + */ + if ((mp = mscp_getcp(mi, MSCP_DONTWAIT)) == NULL) { + if (mi->mi_credits > MSCP_MINCREDITS) + printf("%s: command ring too small\n", + mi->mi_dev.dv_parent->dv_xname); + /* + * By some (strange) reason we didn't get a MSCP packet. + * Put it on queue and wait for free packets. + */ + (void *)bp->b_actb = mi->mi_w; + mi->mi_w = bp; + splx(s); + return; + } + + /* + * Set up the MSCP packet and ask the ctlr to start. + */ + mp->mscp_opcode = (bp->b_flags & B_READ) ? M_OP_READ : M_OP_WRITE; + (*mi->mi_me->me_fillin)(bp, mp); + (void *)bp->b_actb = mp; /* b_actb is unused, save mscp packet here */ + (*mi->mi_mc->mc_go)(mi->mi_dev.dv_parent, bp); + splx(s); +} + +void +mscp_dgo(mi, buffer, info, bp) + struct mscp_softc *mi; + long buffer, info; + struct buf *bp; +{ + volatile int i; + struct mscp *mp; + + /* + * Fill in the MSCP packet and move the buffer to the I/O wait queue. + */ + mp = (void *)bp->b_actb; + + mp->mscp_seq.seq_buffer = buffer; + + _insque(&bp->b_actf, &mi->mi_actf); + + bp->b_resid = info; + mp->mscp_cmdref = (long) bp; + *mp->mscp_addr |= MSCP_OWN | MSCP_INT; + + i = *mi->mi_ip; +} + +#ifdef DIAGNOSTIC +/* + * Dump the entire contents of an MSCP packet in hex. Mainly useful + * for debugging.... + */ +void +mscp_hexdump(mp) + register struct mscp *mp; +{ + register long *p = (long *) mp; + register int i = mp->mscp_msglen; + + if (i > 256) /* sanity */ + i = 256; + i /= sizeof (*p); /* ASSUMES MULTIPLE OF sizeof(long) */ + while (--i >= 0) + printf("0x%x ", (int)*p++); + printf("\n"); +} +#endif + +/* + * MSCP error reporting + */ + +/* + * Messages for the various subcodes. + */ +static char unknown_msg[] = "unknown subcode"; + +/* + * Subcodes for Success (0) + */ +static char *succ_msgs[] = { + "normal", /* 0 */ + "spin down ignored", /* 1 = Spin-Down Ignored */ + "still connected", /* 2 = Still Connected */ + unknown_msg, + "dup. unit #", /* 4 = Duplicate Unit Number */ + unknown_msg, + unknown_msg, + unknown_msg, + "already online", /* 8 = Already Online */ + unknown_msg, + unknown_msg, + unknown_msg, + unknown_msg, + unknown_msg, + unknown_msg, + unknown_msg, + "still online", /* 16 = Still Online */ +}; + +/* + * Subcodes for Invalid Command (1) + */ +static char *icmd_msgs[] = { + "invalid msg length", /* 0 = Invalid Message Length */ +}; + +/* + * Subcodes for Command Aborted (2) + */ +/* none known */ + +/* + * Subcodes for Unit Offline (3) + */ +static char *offl_msgs[] = { + "unknown drive", /* 0 = Unknown, or online to other ctlr */ + "not mounted", /* 1 = Unmounted, or RUN/STOP at STOP */ + "inoperative", /* 2 = Unit Inoperative */ + unknown_msg, + "duplicate", /* 4 = Duplicate Unit Number */ + unknown_msg, + unknown_msg, + unknown_msg, + "in diagnosis", /* 8 = Disabled by FS or diagnostic */ +}; + +/* + * Subcodes for Unit Available (4) + */ +/* none known */ + +/* + * Subcodes for Media Format Error (5) + */ +static char *media_fmt_msgs[] = { + "fct unread - edc", /* 0 = FCT unreadable */ + "invalid sector header",/* 1 = Invalid Sector Header */ + "not 512 sectors", /* 2 = Not 512 Byte Sectors */ + "not formatted", /* 3 = Not Formatted */ + "fct ecc", /* 4 = FCT ECC */ +}; + +/* + * Subcodes for Write Protected (6) + * N.B.: Code 6 subcodes are 7 bits higher than other subcodes + * (i.e., bits 12-15). + */ +static char *wrprot_msgs[] = { + unknown_msg, + "software", /* 1 = Software Write Protect */ + "hardware", /* 2 = Hardware Write Protect */ +}; + +/* + * Subcodes for Compare Error (7) + */ +/* none known */ + +/* + * Subcodes for Data Error (8) + */ +static char *data_msgs[] = { + "forced error", /* 0 = Forced Error (software) */ + unknown_msg, + "header compare", /* 2 = Header Compare Error */ + "sync timeout", /* 3 = Sync Timeout Error */ + unknown_msg, + unknown_msg, + unknown_msg, + "uncorrectable ecc", /* 7 = Uncorrectable ECC */ + "1 symbol ecc", /* 8 = 1 bit ECC */ + "2 symbol ecc", /* 9 = 2 bit ECC */ + "3 symbol ecc", /* 10 = 3 bit ECC */ + "4 symbol ecc", /* 11 = 4 bit ECC */ + "5 symbol ecc", /* 12 = 5 bit ECC */ + "6 symbol ecc", /* 13 = 6 bit ECC */ + "7 symbol ecc", /* 14 = 7 bit ECC */ + "8 symbol ecc", /* 15 = 8 bit ECC */ +}; + +/* + * Subcodes for Host Buffer Access Error (9) + */ +static char *host_buffer_msgs[] = { + unknown_msg, + "odd xfer addr", /* 1 = Odd Transfer Address */ + "odd xfer count", /* 2 = Odd Transfer Count */ + "non-exist. memory", /* 3 = Non-Existent Memory */ + "memory parity", /* 4 = Memory Parity Error */ +}; + +/* + * Subcodes for Controller Error (10) + */ +static char *cntlr_msgs[] = { + unknown_msg, + "serdes overrun", /* 1 = Serialiser/Deserialiser Overrun */ + "edc", /* 2 = Error Detection Code? */ + "inconsistant internal data struct",/* 3 = Internal Error */ +}; + +/* + * Subcodes for Drive Error (11) + */ +static char *drive_msgs[] = { + unknown_msg, + "sdi command timeout", /* 1 = SDI Command Timeout */ + "ctlr detected protocol",/* 2 = Controller Detected Protocol Error */ + "positioner", /* 3 = Positioner Error */ + "lost rd/wr ready", /* 4 = Lost R/W Ready Error */ + "drive clock dropout", /* 5 = Lost Drive Clock */ + "lost recvr ready", /* 6 = Lost Receiver Ready */ + "drive detected error", /* 7 = Drive Error */ + "ctlr detected pulse or parity",/* 8 = Pulse or Parity Error */ +}; + +/* + * The following table correlates message codes with the + * decoding strings. + */ +struct code_decode { + char *cdc_msg; + int cdc_nsubcodes; + char **cdc_submsgs; +} code_decode[] = { +#define SC(m) sizeof (m) / sizeof (m[0]), m + {"success", SC(succ_msgs)}, + {"invalid command", SC(icmd_msgs)}, + {"command aborted", 0, 0}, + {"unit offline", SC(offl_msgs)}, + {"unit available", 0, 0}, + {"media format error", SC(media_fmt_msgs)}, + {"write protected", SC(wrprot_msgs)}, + {"compare error", 0, 0}, + {"data error", SC(data_msgs)}, + {"host buffer access error", SC(host_buffer_msgs)}, + {"controller error", SC(cntlr_msgs)}, + {"drive error", SC(drive_msgs)}, +#undef SC +}; + +/* + * Print the decoded error event from an MSCP error datagram. + */ +void +mscp_printevent(mp) + struct mscp *mp; +{ + register int event = mp->mscp_event; + register struct code_decode *cdc; + int c, sc; + char *cm, *scm; + + /* + * The code is the lower six bits of the event number (aka + * status). If that is 6 (write protect), the subcode is in + * bits 12-15; otherwise, it is in bits 5-11. + * I WONDER WHAT THE OTHER BITS ARE FOR. IT SURE WOULD BE + * NICE IF DEC SOLD DOCUMENTATION FOR THEIR OWN CONTROLLERS. + */ + c = event & M_ST_MASK; + sc = (c != 6 ? event >> 5 : event >> 12) & 0x7ff; + if (c >= sizeof code_decode / sizeof code_decode[0]) + cm = "- unknown code", scm = "??"; + else { + cdc = &code_decode[c]; + cm = cdc->cdc_msg; + if (sc >= cdc->cdc_nsubcodes) + scm = unknown_msg; + else + scm = cdc->cdc_submsgs[sc]; + } + printf(" %s (%s) (code %d, subcode %d)\n", cm, scm, c, sc); +} + +static char *codemsg[16] = { + "lbn", "code 1", "code 2", "code 3", + "code 4", "code 5", "rbn", "code 7", + "code 8", "code 9", "code 10", "code 11", + "code 12", "code 13", "code 14", "code 15" +}; +/* + * Print the code and logical block number for an error packet. + * THIS IS PROBABLY PECULIAR TO DISK DRIVES. IT SURE WOULD BE + * NICE IF DEC SOLD DOCUMENTATION FOR THEIR OWN CONTROLLERS. + */ +int +mscp_decodeerror(name, mp, mi) + char *name; + register struct mscp *mp; + struct mscp_softc *mi; +{ + int issoft; + /* + * We will get three sdi errors of type 11 after autoconfig + * is finished; depending of searching for non-existing units. + * How can we avoid this??? + */ + if (((mp->mscp_event & M_ST_MASK) == 11) && (mi->mi_ierr++ < 3)) + return 1; + /* + * For bad blocks, mp->mscp_erd.erd_hdr identifies a code and + * the logical block number. Code 0 is a regular block; code 6 + * is a replacement block. The remaining codes are currently + * undefined. The code is in the upper four bits of the header + * (bits 0-27 are the lbn). + */ + issoft = mp->mscp_flags & (M_LF_SUCC | M_LF_CONT); +#define BADCODE(h) (codemsg[(unsigned)(h) >> 28]) +#define BADLBN(h) ((h) & 0xfffffff) + + printf("%s: drive %d %s error datagram%s:", name, mp->mscp_unit, + issoft ? "soft" : "hard", + mp->mscp_flags & M_LF_CONT ? " (continuing)" : ""); + switch (mp->mscp_format & 0377) { + + case M_FM_CTLRERR: /* controller error */ + break; + + case M_FM_BUSADDR: /* host memory access error */ + printf(" memory addr 0x%x:", (int)mp->mscp_erd.erd_busaddr); + break; + + case M_FM_DISKTRN: + printf(" unit %d: level %d retry %d, %s %d:", + mp->mscp_unit, + mp->mscp_erd.erd_level, mp->mscp_erd.erd_retry, + BADCODE(mp->mscp_erd.erd_hdr), + (int)BADLBN(mp->mscp_erd.erd_hdr)); + break; + + case M_FM_SDI: + printf(" unit %d: %s %d:", mp->mscp_unit, + BADCODE(mp->mscp_erd.erd_hdr), + (int)BADLBN(mp->mscp_erd.erd_hdr)); + break; + + case M_FM_SMLDSK: + printf(" unit %d: small disk error, cyl %d:", + mp->mscp_unit, mp->mscp_erd.erd_sdecyl); + break; + + case M_FM_TAPETRN: + printf(" unit %d: tape transfer error, grp 0x%x event 0%o:", + mp->mscp_unit, mp->mscp_erd.erd_sdecyl, mp->mscp_event); + break; + + case M_FM_STIERR: + printf(" unit %d: STI error, event 0%o:", mp->mscp_unit, + mp->mscp_event); + break; + + default: + printf(" unit %d: unknown error, format 0x%x:", + mp->mscp_unit, mp->mscp_format); + } + mscp_printevent(mp); + return 0; +#undef BADCODE +#undef BADLBN +} diff --git a/sys/arch/vax/mscp/mscp_tape.c b/sys/arch/vax/mscp/mscp_tape.c new file mode 100644 index 00000000000..85470b55ed7 --- /dev/null +++ b/sys/arch/vax/mscp/mscp_tape.c @@ -0,0 +1,535 @@ +/* $NetBSD: mscp_tape.c,v 1.4 1997/01/11 11:20:35 ragge Exp $ */ +/* + * Copyright (c) 1996 Ludd, University of Lule}, Sweden. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed at Ludd, University of + * Lule}, Sweden and its contributors. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +/* + * MSCP tape device driver + */ + +/* + * TODO + * Write status handling code. + */ + +#include <sys/param.h> +#include <sys/device.h> +#include <sys/kernel.h> +#include <sys/buf.h> +#include <sys/ioccom.h> +#include <sys/mtio.h> +#include <sys/fcntl.h> +#include <sys/malloc.h> +#include <sys/systm.h> +#include <sys/proc.h> + +#include <vax/mscp/mscp.h> +#include <vax/mscp/mscpvar.h> + +/* + * Drive status, per drive + */ +struct mt_softc { + struct device mt_dev; /* Autoconf struct */ + int mt_state; /* open/closed state */ + int mt_hwunit; /* Hardware unit number */ + int mt_inuse; /* Locks the tape drive for others */ + int mt_waswrite; /* Last operation was a write op */ + int mt_serex; /* Got serious exception */ +}; + +#define MT_OFFLINE 0 +#define MT_ONLINE 1 + +int mtmatch __P((struct device *, void *, void *)); +void mtattach __P((struct device *, struct device *, void *)); +void mtdgram __P((struct device *, struct mscp *, struct mscp_softc *)); +void mtiodone __P((struct device *, struct buf *)); +int mtonline __P((struct device *, struct mscp *)); +int mtgotstatus __P((struct device *, struct mscp *)); +int mtioerror __P((struct device *, struct mscp *, struct buf *)); +void mtfillin __P((struct buf *, struct mscp *)); +int mtopen __P((dev_t, int, int, struct proc *)); +int mtclose __P((dev_t, int, int, struct proc *)); +void mtstrategy __P((struct buf *)); +int mtread __P((dev_t, struct uio *)); +int mtwrite __P((dev_t, struct uio *)); +int mtioctl __P((dev_t, int, caddr_t, int, struct proc *)); +int mtdump __P((dev_t, daddr_t, caddr_t, size_t)); +void mtcmd __P((struct mt_softc *, int)); +void mtcmddone __P((struct device *, struct mscp *)); + +struct mscp_device mt_device = { + mtdgram, + mtiodone, + mtonline, + mtgotstatus, + 0, + mtioerror, + 0, + mtfillin, + mtcmddone, +}; + +/* This is not good, should allow more than 4 tapes/device type */ +#define mtunit(dev) (minor(dev) & T_UNIT) +#define mtnorewind(dev) (dev & T_NOREWIND) +#define mthdensity(dev) (dev & T_1600BPI) + +struct cfdriver mt_cd = { + NULL, "mt", DV_DULL +}; + +struct cfattach mt_ca = { + sizeof(struct mt_softc), mtmatch, mtattach +}; + +/* + * More driver definitions, for generic MSCP code. + */ + +int +mtmatch(parent, match, aux) + struct device *parent; + void *match, *aux; +{ + struct cfdata *cf = match; + struct drive_attach_args *da = aux; + struct mscp *mp = da->da_mp; + + if ((da->da_typ & MSCPBUS_TAPE) == 0) + return 0; + if (cf->cf_loc[0] != -1 && cf->cf_loc[0] != mp->mscp_unit) + return 0; + return 1; +} + +/* + * The attach routine only checks and prints drive type. + */ +void +mtattach(parent, self, aux) + struct device *parent, *self; + void *aux; +{ + struct mt_softc *mt = (void *)self; + struct drive_attach_args *da = aux; + struct mscp *mp = da->da_mp; + struct mscp_softc *mi = (void *)parent; + + mt->mt_hwunit = mp->mscp_unit; + mi->mi_dp[mp->mscp_unit] = self; + + disk_printtype(mp->mscp_unit, mp->mscp_guse.guse_mediaid); +} + +/* + * (Try to) put the drive online. This is done the first time the + * drive is opened, or if it has fallen offline. + */ +int +mt_putonline(mt) + struct mt_softc *mt; +{ + struct mscp *mp; + struct mscp_softc *mi = (struct mscp_softc *)mt->mt_dev.dv_parent; + volatile int i; + + (volatile)mt->mt_state = MT_OFFLINE; + mp = mscp_getcp(mi, MSCP_WAIT); + mp->mscp_opcode = M_OP_ONLINE; + mp->mscp_unit = mt->mt_hwunit; + mp->mscp_cmdref = (long)&mt->mt_state; + *mp->mscp_addr |= MSCP_OWN | MSCP_INT; + + /* Poll away */ + i = *mi->mi_ip; + if (tsleep(&mt->mt_state, PRIBIO, "mtonline", 240 * hz)) + return MSCP_FAILED; + + if ((volatile)mt->mt_state != MT_ONLINE) + return MSCP_FAILED; + + return MSCP_DONE; +} +/* + * Open a drive. + */ +/*ARGSUSED*/ +int +mtopen(dev, flag, fmt, p) + dev_t dev; + int flag, fmt; + struct proc *p; +{ + register struct mt_softc *mt; + int unit; + + /* + * Make sure this is a reasonable open request. + */ + unit = mtunit(dev); + if (unit >= mt_cd.cd_ndevs) + return ENXIO; + mt = mt_cd.cd_devs[unit]; + if (mt == 0) + return ENXIO; + + if (mt->mt_inuse) + return EBUSY; + mt->mt_inuse = 1; + + if (mt_putonline(mt) == MSCP_FAILED) + return EIO; + + return 0; +} + +/* ARGSUSED */ +int +mtclose(dev, flags, fmt, p) + dev_t dev; + int flags, fmt; + struct proc *p; +{ + int unit = mtunit(dev); + struct mt_softc *mt = mt_cd.cd_devs[unit]; + + /* + * If we just have finished a writing, write EOT marks. + */ + if ((flags & FWRITE) && mt->mt_waswrite) { + mtcmd(mt, MTWEOF); + mtcmd(mt, MTWEOF); + mtcmd(mt, MTBSR); + } + if (mtnorewind(dev) == 0) + mtcmd(mt, MTREW); + if (mt->mt_serex) + mtcmd(mt, -1); + + mt->mt_inuse = 0; /* Release the tape */ + return 0; +} + +void +mtstrategy(bp) + register struct buf *bp; +{ + register int unit; + register struct mt_softc *mt; + + /* + * Make sure this is a reasonable drive to use. + */ + unit = mtunit(bp->b_dev); + if (unit > mt_cd.cd_ndevs || (mt = mt_cd.cd_devs[unit]) == NULL) { + bp->b_error = ENXIO; + goto bad; + } + + mscp_strategy(bp, mt->mt_dev.dv_parent); + return; + +bad: + bp->b_flags |= B_ERROR; + biodone(bp); +} + +int +mtread(dev, uio) + dev_t dev; + struct uio *uio; +{ + + return (physio(mtstrategy, NULL, dev, B_READ, minphys, uio)); +} + +int +mtwrite(dev, uio) + dev_t dev; + struct uio *uio; +{ + + return (physio(mtstrategy, NULL, dev, B_WRITE, minphys, uio)); +} + +void +mtiodone(usc, bp) + struct device *usc; + struct buf *bp; +{ + + biodone(bp); +} + +/* + * Fill in drive addresses in a mscp packet waiting for transfer. + */ +void +mtfillin(bp, mp) + struct buf *bp; + struct mscp *mp; +{ + int unit = mtunit(bp->b_dev); + struct mt_softc *mt = mt_cd.cd_devs[unit]; + + mp->mscp_unit = mt->mt_hwunit; + if (mt->mt_serex == 2) { + mp->mscp_modifier = M_MD_CLSEX; + mt->mt_serex = 0; + } else + mp->mscp_modifier = 0; + + mp->mscp_seq.seq_bytecount = bp->b_bcount; +} + +/* + * Handle an error datagram. + */ +void +mtdgram(usc, mp, mi) + struct device *usc; + struct mscp *mp; + struct mscp_softc *mi; +{ + if (mscp_decodeerror(usc == NULL?"unconf mt" : usc->dv_xname, mp, mi)) + return; +} + +/* + * A drive came on line, make sure it really _is_ on line before + * trying to use it. + */ +int +mtonline(usc, mp) + struct device *usc; + struct mscp *mp; +{ + register struct mt_softc *mt = (void *)usc; + + wakeup((caddr_t)&mt->mt_state); + if ((mp->mscp_status & M_ST_MASK) == M_ST_SUCCESS) + mt->mt_state = MT_ONLINE; + + return (MSCP_DONE); +} + +/* + * We got some (configured) unit's status. Return DONE. + */ +int +mtgotstatus(usc, mp) + register struct device *usc; + register struct mscp *mp; +{ + return (MSCP_DONE); +} + +static char *mt_ioerrs[] = { + "invalid command", /* 1 M_ST_INVALCMD */ + "command aborted", /* 2 M_ST_ABORTED */ + "unit offline", /* 3 M_ST_OFFLINE */ + "unknown", /* 4 M_ST_AVAILABLE */ + "unknown", /* 5 M_ST_MFMTERR */ + "unit write protected", /* 6 M_ST_WRPROT */ + "compare error", /* 7 M_ST_COMPERR */ + "data error", /* 8 M_ST_DATAERR */ + "host buffer access error", /* 9 M_ST_HOSTBUFERR */ + "controller error", /* 10 M_ST_CTLRERR */ + "drive error", /* 11 M_ST_DRIVEERR */ + "formatter error", /* 12 M_ST_FORMATTERR */ + "BOT encountered", /* 13 M_ST_BOT */ + "tape mark encountered",/* 14 M_ST_TAPEMARK */ + "unknown", /* 15 */ + "record data truncated",/* 16 M_ST_RDTRUNC */ +}; + +/* + * An I/O error, may be because of a tapemark encountered. + * Check that before failing. + */ +/*ARGSUSED*/ +int +mtioerror(usc, mp, bp) + register struct device *usc; + register struct mscp *mp; + struct buf *bp; +{ + struct mt_softc *mt = (void *)usc; + int st = mp->mscp_status & M_ST_MASK; + + if (mp->mscp_flags & M_EF_SEREX) + mt->mt_serex = 1; + if (st == M_ST_TAPEMARK) + mt->mt_serex = 2; + else { + if (st && st < 17) + printf("%s: error %d (%s)\n", mt->mt_dev.dv_xname, st, + mt_ioerrs[st-1]); + else + printf("%s: error %d\n", mt->mt_dev.dv_xname, st); + bp->b_flags |= B_ERROR; + } + + return (MSCP_DONE); +} + +/* + * I/O controls. + */ +int +mtioctl(dev, cmd, data, flag, p) + dev_t dev; + int cmd; + caddr_t data; + int flag; + struct proc *p; +{ + register int unit = mtunit(dev); + register struct mt_softc *mt = mt_cd.cd_devs[unit]; + struct mtop *mtop; + struct mtget *mtget; + int error = 0, i; + + + switch (cmd) { + + case MTIOCTOP: + mtop = (void *)data; + i = mtop->mt_count; + while (i-- > 0) + mtcmd(mt, mtop->mt_op); + break; + + case MTIOCGET: + mtget = (void *)data; + mtget->mt_type = MT_ISTMSCP; + /* XXX we need to fill in more fields here */ + break; + + default: + error = ENXIO; + break; + } + return (error); +} + +/* + * No crash dump support... + */ +int +mtdump(dev, blkno, va, size) + dev_t dev; + daddr_t blkno; + caddr_t va; + size_t size; +{ + return -1; +} + +/* + * Send a command to the tape drive. Wait until the command is + * finished before returning. + */ +void +mtcmd(mt, cmd) + struct mt_softc *mt; + int cmd; +{ + struct mscp *mp; + struct mscp_softc *mi = (void *)mt->mt_dev.dv_parent; + volatile int i; + + mp = mscp_getcp(mi, MSCP_WAIT); + + mp->mscp_unit = mt->mt_hwunit; + mp->mscp_cmdref = -1; + *mp->mscp_addr |= MSCP_OWN | MSCP_INT; + + switch (cmd) { + case MTWEOF: + mp->mscp_opcode = M_OP_WRITM; + break; + + case MTBSF: + mp->mscp_modifier = M_MD_REVERSE; + case MTFSF: + mp->mscp_opcode = M_OP_POS; + mp->mscp_modifier |= M_MD_OBJCOUNT; + mp->mscp_seq.seq_buffer = 1; + break; + + case MTBSR: + mp->mscp_modifier = M_MD_REVERSE; + case MTFSR: + mp->mscp_opcode = M_OP_POS; + mp->mscp_modifier |= M_MD_OBJCOUNT; + mp->mscp_seq.seq_bytecount = 1; + break; + + case MTREW: + mp->mscp_opcode = M_OP_POS; + mp->mscp_modifier = M_MD_REWIND | M_MD_CLSEX; + mt->mt_serex = 0; + break; + + case -1: /* Clear serious exception only */ + mp->mscp_opcode = M_OP_POS; + mp->mscp_modifier = M_MD_CLSEX; + mt->mt_serex = 0; + break; + + default: + printf("Bad ioctl %x\n", cmd); + mp->mscp_opcode = M_OP_POS; + break; + } + + i = *mi->mi_ip; + tsleep(&mt->mt_inuse, PRIBIO, "mtioctl", 0); +} + +/* + * Called from bus routines whenever a non-data transfer is finished. + */ +void +mtcmddone(usc, mp) + struct device *usc; + struct mscp *mp; +{ + struct mt_softc *mt = (void *)usc; + + if (mp->mscp_status) + printf("%s: bad status %x\n", mt->mt_dev.dv_xname, + mp->mscp_status); + wakeup(&mt->mt_inuse); +} diff --git a/sys/arch/vax/mscp/mscpreg.h b/sys/arch/vax/mscp/mscpreg.h new file mode 100644 index 00000000000..a5c6993a883 --- /dev/null +++ b/sys/arch/vax/mscp/mscpreg.h @@ -0,0 +1,123 @@ +/* $NetBSD: mscpreg.h,v 1.1 1996/07/01 20:41:37 ragge Exp $ */ +/* + * Copyright (c) 1996 Ludd, University of Lule}, Sweden. + * Copyright (c) 1988 Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Chris Torek. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)udareg.h 7.3 (Berkeley) 5/8/91 + */ + +/* + * NRSPL2 and NCMDL2 control the number of response and command + * packets respectively. They may be any value from 0 to 7, though + * setting them higher than 5 is unlikely to be of any value. + * If you get warnings about your command ring being too small, + * try increasing the values by one. + */ +#define NRSPL2 5 +#define NCMDL2 5 +#define NRSP (1 << NRSPL2) +#define NCMD (1 << NCMDL2) + +/* + * Communication area definition. This seems to be the same for + * all types of MSCP controllers. + */ + +struct mscp_ca { + short ca_xxx1; /* unused */ + char ca_xxx2; /* unused */ + char ca_bdp; /* BDP to purge */ + short ca_cmdint; /* command ring transition flag */ + short ca_rspint; /* response ring transition flag */ + long ca_rspdsc[NRSP];/* response descriptors */ + long ca_cmddsc[NCMD];/* command descriptors */ +}; + +/* + * Simplified routines (e.g., uddump) reprogram the UDA50 for one command + * and one response at a time; uda1ca is like udaca except that it provides + * exactly one command and response descriptor. + */ +struct mscp_1ca { + short ca_xxx1; + char ca_xxx2; + char ca_bdp; + short ca_cmdint; + short ca_rspint; + long ca_rspdsc; + long ca_cmddsc; +}; + +/* + * Combined communications area and MSCP packet pools, per controller. + * NRSP and NCMD must be defined before this struct is used. + */ + +struct mscp_pack { + struct mscp_ca mp_ca; /* communications area */ + struct mscp mp_rsp[NRSP]; /* response packets */ + struct mscp mp_cmd[NCMD]; /* command packets */ +}; + +/* + * Bits in UDA status register during initialisation + */ +#define MP_ERR 0x8000 /* error */ +#define MP_STEP4 0x4000 /* step 4 has started */ +#define MP_STEP3 0x2000 /* step 3 has started */ +#define MP_STEP2 0x1000 /* step 2 has started */ +#define MP_STEP1 0x0800 /* step 1 has started */ +#define MP_NV 0x0400 /* no host settable interrupt vector */ +#define MP_QB 0x0200 /* controller supports Q22 bus */ +#define MP_DI 0x0100 /* controller implements diagnostics */ +#define MP_IE 0x0080 /* interrupt enable */ +#define MP_NCNRMASK 0x003f /* in STEP1, bits 0-2=NCMDL2, 3-5=NRSPL2 */ +#define MP_IVECMASK 0x007f /* in STEP2, bits 0-6 are interruptvec / 4 */ +#define MP_PI 0x0001 /* host requests adapter purge interrupts */ +#define MP_GO 0x0001 /* Go command to ctlr */ + +#define ALLSTEPS (MP_ERR | MP_STEP4 | MP_STEP3 | MP_STEP2 | MP_STEP1) + +#define STEP0MASK (ALLSTEPS | MP_NV) + +#define STEP1MASK (ALLSTEPS | MP_IE | MP_NCNRMASK) +#define STEP1GOOD (MP_STEP2 | MP_IE | (NCMDL2 << 3) | NRSPL2) + +#define STEP2MASK (ALLSTEPS | MP_IE | MP_IVECMASK) +#define STEP2GOOD(iv) (MP_STEP3 | MP_IE | (iv)) + +#define STEP3MASK ALLSTEPS +#define STEP3GOOD MP_STEP4 + diff --git a/sys/arch/vax/mscp/mscpvar.h b/sys/arch/vax/mscp/mscpvar.h new file mode 100644 index 00000000000..8871f96f2ba --- /dev/null +++ b/sys/arch/vax/mscp/mscpvar.h @@ -0,0 +1,254 @@ +/* $NetBSD: mscpvar.h,v 1.4 1997/01/11 11:20:36 ragge Exp $ */ +/* + * Copyright (c) 1996 Ludd, University of Lule}, Sweden. + * Copyright (c) 1988 Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Chris Torek. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)mscpvar.h 7.3 (Berkeley) 6/28/90 + */ + +/* + * MSCP generic driver configuration + */ + +/* + * Enabling MSCP_PARANOIA makes the response code perform various checks + * on the hardware. (Right now it verifies only the buffer pointer in + * mscp_cmdref.) + * + * Enabling AVOID_EMULEX_BUG selects an alternative method of identifying + * transfers in progress, which gets around a rather peculiar bug in the + * SC41/MS. Enabling MSCP_PARANOIA instead should work, but will cause + * `extra' Unibus resets. + * + * Either of these flags can simply be included as an `options' line in + * your configuration file. + */ + +/* #define MSCP_PARANOIA */ +/* #define AVOID_EMULEX_BUG */ + +/* + * Ring information, per ring (one each for commands and responses). + */ +struct mscp_ri { + int mri_size; /* ring size */ + int mri_next; /* next (expected|free) */ + long *mri_desc; /* base address of descriptors */ + struct mscp *mri_ring; /* base address of packets */ +}; + +struct mscp_ctlr { + void (*mc_ctlrdone) /* controller operation complete */ + __P((struct device *, int)); + int (*mc_go) /* device-specific start routine */ + __P((struct device *, struct buf *)); + void (*mc_saerror) /* ctlr error handling */ + __P((struct device *, int)); +}; + +struct mscp_softc; + +struct mscp_device { + void (*me_dgram) /* error datagram */ + __P((struct device *, struct mscp *, struct mscp_softc *)); + void (*me_iodone) /* normal I/O is done */ + __P((struct device *, struct buf *)); + int (*me_online) /* drive on line */ + __P((struct device *, struct mscp *)); + int (*me_gotstatus) /* got unit status */ + __P((struct device *, struct mscp *)); + void (*me_replace) /* replace done */ + __P((struct device *, struct mscp *)); + int (*me_ioerr) /* read or write failed */ + __P((struct device *, struct mscp *, struct buf *)); + void (*me_bb) /* B_BAD io done */ + __P((struct device *, struct mscp *, struct buf *)); + void (*me_fillin) /* Fill in mscp info for this drive */ + __P((struct buf *,struct mscp *)); + void (*me_cmddone) /* Non-data transfer operation is done */ + __P((struct device *, struct mscp *)); +}; + +/* + * This struct is used when attaching a mscpbus. + */ +struct mscp_attach_args { + struct mscp_ctlr *ma_mc; /* Pointer to ctlr's mscp_ctlr */ + int ma_type; /* disk/tape bus type */ + struct mscp_pack *ma_uda; /* comm area virtual */ + struct mscp_pack *ma_uuda; /* comm area on bus */ + struct mscp_softc **ma_softc; /* backpointer to bus softc */ + short *ma_ip; /* initialisation and polling */ + short *ma_sa; /* status & address (read part) */ + short *ma_sw; /* status & address (write part) */ + short ma_ivec; /* Interrupt vector to use */ + char ma_ctlrnr; /* Phys ctlr nr */ + char ma_adapnr; /* Phys adapter nr */ +}; +#define MSCPBUS_DISK 001 /* Bus is used for disk mounts */ +#define MSCPBUS_TAPE 002 /* Bus is used for tape mounts */ +#define MSCPBUS_UDA 004 /* ctlr is disk on unibus/qbus */ +#define MSCPBUS_KDB 010 /* ctlr is disk on BI */ +#define MSCPBUS_KLE 020 /* ctlr is tape on unibus/qbus */ + +/* + * Used when going for child devices. + */ +struct drive_attach_args { + struct mscp *da_mp; /* this devices response struct */ + int da_typ; /* Parent of type */ +}; + +/* + * Return values from functions. + * MSCP_RESTARTED is peculiar to I/O errors. + */ +#define MSCP_DONE 0 /* all ok */ +#define MSCP_FAILED 1 /* no go */ +#define MSCP_RESTARTED 2 /* transfer restarted */ + +/* + * Per device information. + * + * mi_ip is a pointer to the inverting pointers (things that get `ui's + * given unit numbers) FOR THIS CONTROLLER (NOT the whole set!). + * + * b_actf holds a queue of those transfers that were started but have + * not yet finished. Other Unibus drivers do not need this as they hand + * out requests one at a time. MSCP devices, however, take a slew of + * requests and pick their own order to execute them. This means that + * we have to have a place to move transfers that were given to the + * controller, so we can tell those apart from those that have not yet + * been handed out; b_actf is that place. + */ +struct mscp_softc { + struct device mi_dev; /* Autoconf stuff */ + struct mscp_ri mi_cmd; /* MSCP command ring info */ + struct mscp_ri mi_rsp; /* MSCP response ring info */ + short mi_credits; /* transfer credits */ + char mi_wantcmd; /* waiting for command packet */ + char mi_wantcredits; /* waiting for transfer credits */ + struct buf *mi_actf; /* Pointer to buffers in */ + struct buf *mi_actb; /* circular wait queue */ + struct mscp_ctlr *mi_mc; /* Pointer to parent's mscp_ctlr */ + struct mscp_device *mi_me; /* Pointer to child's mscp_device */ + struct device **mi_dp; /* array of backpointers */ + int mi_driveno; /* Max physical drive number found */ + char mi_ctlrnr; /* Phys ctlr nr */ + char mi_adapnr; /* Phys adapter nr */ + int mi_flags; + struct mscp_pack *mi_uda; /* virtual address */ + struct mscp_pack *mi_uuda; /* (device-specific) address */ + int mi_type; + short mi_ivec; /* Interrupt vector to use */ + short mi_ierr; /* Init err counter */ + volatile short *mi_ip; /* initialisation and polling */ + volatile short *mi_sa; /* status & address (read part) */ + volatile short *mi_sw; /* status & address (write part) */ + struct buf *mi_w; /* While waiting for packets */ +}; + +/* mi_flags */ +#define MSC_STARTPOLL 1 +#define MSC_INSTART 2 +#define MSC_IGNOREINTR 4 +#define MSC_READY 8 + +/* + * We have run out of credits when mi_credits is <= MSCP_MINCREDITS. + * It is still possible to issue one command in this case, but it must + * not be a data transfer. E.g., `get command status' or `abort command' + * is legal, while `read' is not. + */ +#define MSCP_MINCREDITS 1 + +/* + * Flags for mscp_getcp(). + */ +#define MSCP_WAIT 1 +#define MSCP_DONTWAIT 0 + + /* get a command packet */ + +/* + * Unit flags + */ +#define UNIT_ONLINE 0x01 /* drive is on line */ +#define UNIT_HAVESTATUS 0x02 /* got unit status */ +#define UNIT_REQUEUE 0x04 /* requeue after response */ + +/* + * Handle a command ring transition: wake up sleepers for command packets. + * This is too simple to bother with a function call. + */ +#define MSCP_DOCMD(mi) { \ + if ((mi)->mi_wantcmd) { \ + (mi)->mi_wantcmd = 0; \ + wakeup((caddr_t) &(mi)->mi_wantcmd); \ + } \ +} + +/* + * The following macro appends a buffer to a drive queue or a drive to + * a controller queue, given the name of the forward link. Use as + * `APPEND(dp, &um->um_tab, b_forw)' or `APPEND(bp, dp, av_forw)', + * where `bp' is a transfer request, `dp' is a drive queue, and `um_tab' + * is a controller queue. (That is, the forward link for controller + * queues is `b_forw'; for drive queues, it is `av_forw'.) + */ + +#define MSCP_APPEND(bp, queue, link) { \ + (bp)->link = NULL; \ + if ((queue)->link == NULL) \ + (queue)->link = (bp); \ + else \ + *(queue)->b_actb = (bp); \ + (queue)->b_actb = &(bp)->link; \ +} + +/* Prototypes */ +struct mscp *mscp_getcp __P((struct mscp_softc *, int)); +void mscp_printevent __P((struct mscp *)); +void mscp_go __P((struct mscp_softc *, struct mscp *, int)); +void mscp_requeue __P((struct mscp_softc *)); +void mscp_dorsp __P((struct mscp_softc *)); +int mscp_decodeerror __P((char *, struct mscp *, struct mscp_softc *)); +int mscp_print __P((void *, const char *)); +void mscp_hexdump __P((struct mscp *)); +void mscp_strategy __P((struct buf *, struct device *)); +void mscp_printtype __P((int, int)); +int mscp_waitstep __P((struct mscp_softc *, int, int)); +void mscp_dgo __P((struct mscp_softc *, long, long, struct buf *)); +void mscp_intr __P((struct mscp_softc *)); diff --git a/sys/arch/vax/stand/Makefile b/sys/arch/vax/stand/Makefile index f2ac372bc2d..b9a0cb46e9f 100644 --- a/sys/arch/vax/stand/Makefile +++ b/sys/arch/vax/stand/Makefile @@ -1,28 +1,29 @@ -# $OpenBSD: Makefile,v 1.6 1996/09/27 18:38:04 maja Exp $ -# $NetBSD: Makefile,v 1.9 1996/03/16 11:03:12 ragge Exp $ +# $OpenBSD: Makefile,v 1.7 1997/01/15 23:24:15 maja Exp $ +# $NetBSD: Makefile,v 1.11 1996/10/18 06:10:18 thorpej Exp $ # INCPATH=-I. -I../../.. -I../.. -I../../../lib/libsa -.PATH: ${.CURDIR}/../../../lib/libkern CC= cc AS= as S= ../../.. RELOC= 100000 -CFLAGS+=-O ${INCPATH} -DSTANDALONE -DRELOC=0x${RELOC} -D_VAX_INLINE_ +XXRPB= 0F4240 +CFLAGS+=-O ${INCPATH} -DSTANDALONE -DRELOC=0x${RELOC} \ + -D_VAX_INLINE_ -DXXRPB=0x$(XXRPB) -DEVS= autoconf.o hp.o ra.o tmscp.o ctu.o - -LIBKERN=libkern.a -KERNOBJ=__main.o strlen.o strcmp.o strncmp.o strncpy.o min.o strcpy.o +DEVS= autoconf.o hp.o ra.o tmscp.o ctu.o mfm.o rom.o romread.o \ + scsi_low.o scsi_hi.o sd.o .include "$S/lib/libsa/Makefile.inc" LIBSA= ${SALIB} -all: xxboot boot copy edlabel +SVAX= consio.o urem.o udiv.o str.o + +all: ${LIBSA} xxboot boot copy edlabel -libsvax.a: consio.o urem.o udiv.o +libsvax.a: ${SVAX} ar crv $@ $? ranlib $@ @@ -32,6 +33,9 @@ urem.o: ../vax/urem.s udiv.o: ../vax/udiv.s ${CC} -x assembler-with-cpp -E ../vax/udiv.s | as -o udiv.o +str.o: str.s + ${CC} -x assembler-with-cpp -E str.s | as -o str.o + # startups start.o: start.s @@ -42,29 +46,29 @@ srt0.o: srt0.s # -xxboot: start.o bootxx.o romread.o ${LIBSA} ${LIBKERN} libsvax.a +xxboot: start.o bootxx.o romread.o libsvax.a ld -N -Ttext ${RELOC} -o a.out start.o bootxx.o romread.o \ - ${LIBSA} ${LIBKERN} libsvax.a + ${LIBSA} libsvax.a @strip a.out @size a.out @dd if=a.out of=xxboot bs=32 skip=1 @rm -f a.out -boot: boot.o srt0.o devopen.o conf.o ${DEVS} ${LIBKERN} ${LIBSA} libsvax.a +boot: boot.o srt0.o devopen.o conf.o ${DEVS} libsvax.a ld -N -Ttext ${RELOC} -e nisse -o $@ srt0.o devopen.o boot.o \ - conf.o ${DEVS} ${LIBSA} ${LIBKERN} libsvax.a + conf.o ${DEVS} ${LIBSA} libsvax.a @strip boot @size boot -edlabel: edlabel.o srt0.o devopen.o conf.o ${DEVS} ${LIBKERN} ${LIBSA} libsvax.a +edlabel: edlabel.o srt0.o devopen.o conf.o ${DEVS} libsvax.a ld -N -Ttext ${RELOC} -e nisse -o $@ srt0.o devopen.o edlabel.o\ - conf.o ${DEVS} ${LIBSA} ${LIBKERN} libsvax.a + conf.o ${DEVS} ${LIBSA} libsvax.a @strip edlabel @size edlabel -copy: copy.o srt0.o devopen.o conf.o ${DEVS} ${LIBKERN} ${LIBSA} libsvax.a +copy: copy.o srt0.o devopen.o conf.o ${DEVS} libsvax.a ld -N -Ttext ${RELOC} -e nisse -o $@ srt0.o devopen.o copy.o \ - conf.o ${DEVS} ${LIBSA} ${LIBKERN} libsvax.a + conf.o ${DEVS} ${LIBSA} libsvax.a @strip copy @size copy @@ -98,14 +102,10 @@ bootxx.o: bootxx.c ${CC} -c ${CFLAGS} $*.c # -libkern.a: ${KERNOBJ} - @echo Creating standalone kern library - @ar rv libkern.a `lorder ${KERNOBJ} | tsort` - -# install: boot xxboot - install -c -o ${BINOWN} -g ${BINGRP} -m 444 boot ${DESTDIR}/ - install -c -o ${BINOWN} -g ${BINGRP} -m 444 xxboot ${DESTDIR}/usr/mdec + ${INSTALL} -c -o ${BINOWN} -g ${BINGRP} -m 444 boot ${DESTDIR}/ + ${INSTALL} -c -o ${BINOWN} -g ${BINGRP} -m 444 xxboot \ + ${DESTDIR}/usr/mdec rm -f ${DESTDIR}/usr/mdec/raboot ln ${DESTDIR}/usr/mdec/xxboot ${DESTDIR}/usr/mdec/raboot rm -f ${DESTDIR}/usr/mdec/hpboot @@ -115,7 +115,7 @@ clean:: rm -f start.o romread.o bootxx.o init.o xxboot boot racopy \ libsvax.a udiv.o urem.o consio.o ${DEVS} edlabel edlabel.o rm -f conf.o boot.o rom.o racopy.o srt0.o devopen.o rootcopy.o \ - copy copy.o + copy copy.o init.o .include <bsd.prog.mk> diff --git a/sys/arch/vax/stand/autoconf.c b/sys/arch/vax/stand/autoconf.c index ca08f01214a..d3b2d2b67fd 100644 --- a/sys/arch/vax/stand/autoconf.c +++ b/sys/arch/vax/stand/autoconf.c @@ -1,4 +1,4 @@ -/* $NetBSD: autoconf.c,v 1.5 1996/03/07 23:27:06 ragge Exp $ */ +/* $NetBSD: autoconf.c,v 1.6 1996/08/02 11:21:46 ragge Exp $ */ /* * Copyright (c) 1994 Ludd, University of Lule}, Sweden. * All rights reserved. @@ -39,8 +39,8 @@ #include "vaxstand.h" int nmba=0, nuba=0, nbi=0,nsbi=0,nuda=0; -int *mbaaddr, *ubaaddr; -int *udaaddr, *uioaddr, tmsaddr; +int *mbaaddr, *ubaaddr, *biaddr; +int *udaaddr, *uioaddr, tmsaddr, *bioaddr; static int mba750[]={0xf28000,0xf2a000,0xf2c000}; static int uba750[]={0xf30000,0xf32000}; @@ -55,6 +55,10 @@ static int uba780[]={0x20006000,0x20008000,0x2000a000,0x2000c000, static int uio780[]={0x20100000,0x20140000,0x20180000,0x201c0000, 0x22100000,0x22140000,0x22180000,0x221c0000}; +static int bi8200[]={0x20000000, 0x22000000, 0x24000000, 0x26000000, + 0x28000000, 0x2a000000}; +static int bio8200[]={0x20400000}; + static int uba630[]={0x20087800}; static int uio630[]={0x30000000}; #define qbdev(csr) (((csr) & 017777)-0x10000000) @@ -67,12 +71,11 @@ static int uda630[]={qbdev(0772150),qbdev(0760334)}; autoconf() { - int i = MACHID(mfpr(PR_SID)); - switch (i) { + switch (vax_cputype) { default: - printf("CPU type %d not supported by boot\n",i); + printf("CPU type %d not supported by boot\n",vax_cputype); asm("halt"); case VAX_8600: @@ -117,6 +120,11 @@ autoconf() uioaddr = uio630; tmsaddr = qbdev(0774500); break; + + case VAX_8200: + nbi = 1; + biaddr = bi8200; + bioaddr = bio8200; } } diff --git a/sys/arch/vax/stand/boot.c b/sys/arch/vax/stand/boot.c index 206db3dcf7a..7fd54220f49 100644 --- a/sys/arch/vax/stand/boot.c +++ b/sys/arch/vax/stand/boot.c @@ -1,4 +1,5 @@ -/* $NetBSD: boot.c,v 1.4 1995/09/16 15:54:20 ragge Exp $ */ +/* $OpenBSD: boot.c,v 1.3 1997/01/15 23:24:16 maja Exp $ */ +/* $NetBSD: boot.c,v 1.5 1996/08/02 11:21:49 ragge Exp $ */ /*- * Copyright (c) 1982, 1986 The Regents of the University of California. * All rights reserved. @@ -38,6 +39,8 @@ #include "sys/reboot.h" #include "lib/libsa/stand.h" +#define V750UCODE(x) ((x>>8)&255) + #include <a.out.h> /* @@ -49,8 +52,9 @@ char line[100]; volatile u_int devtype, bootdev; extern unsigned opendev; +extern unsigned *bootregs; -main() +Xmain() { register howto asm("r11"); register bdev asm("r10"); @@ -149,7 +153,7 @@ copyunix(howto, devtype, aio) hoppabort((x.a_entry&0x7fffffff),howto, devtype, esym); return; shread: - printf("Short read\n"); + printf("\nShort read\n\n"); return; } @@ -191,7 +195,7 @@ loadpcs() if (*cp == ')' || *cp == ':') break; if (*cp) { - strncpy(pcs, line, 99); + bcopy(line, pcs, 99); pcs[99] = 0; i = cp - line + 1; } else diff --git a/sys/arch/vax/stand/bootxx.c b/sys/arch/vax/stand/bootxx.c index 4a1b34f83d6..e7464b87273 100644 --- a/sys/arch/vax/stand/bootxx.c +++ b/sys/arch/vax/stand/bootxx.c @@ -1,4 +1,4 @@ -/* $NetBSD: bootxx.c,v 1.5 1996/02/17 18:23:21 ragge Exp $ */ +/* $NetBSD: bootxx.c,v 1.7 1996/08/02 11:21:53 ragge Exp $ */ /*- * Copyright (c) 1982, 1986 The Regents of the University of California. * All rights reserved. @@ -50,18 +50,21 @@ #include "../mba/mbareg.h" #include "../mba/hpreg.h" -#define NRSP 0 /* Kludge */ -#define NCMD 0 /* Kludge */ +#define NRSP 1 /* Kludge */ +#define NCMD 1 /* Kludge */ + #include "../uba/ubareg.h" #include "../uba/udareg.h" -#include "../vax/mscp.h" + +#include "../mscp/mscp.h" +#include "../mscp/mscpreg.h" #include "data.h" #include "vaxstand.h" #include <a.out.h> -int romstrategy(), romopen(); +int romstrategy(), romopen(); int command(int, int); /* @@ -71,39 +74,45 @@ int command(int, int); volatile u_int devtype, bootdev; unsigned opendev, boothowto, bootset; -int cpu_type, cpunumber; -unsigned *bootregs; -int is_750 = 0, is_mvax = 0, is_tmscp = 0; -struct rpb *rpb; -main() +extern unsigned *bootregs; +extern struct rpb *rpb; + +Xmain() { int io; + char *scbb; + char *new; char *hej = "/boot"; - cpu_type = mfpr(PR_SID); - cpunumber = (mfpr(PR_SID) >> 24) & 0xFF; - - switch (cpunumber) { + switch (vax_cputype) { case VAX_78032: case VAX_650: - { - int cpu_sie; /* sid-extension */ - - is_mvax = 1; - cpu_sie = *((int *) 0x20040004) >> 24; - cpu_type |= cpu_sie; - rpb = (struct rpb *)bootregs[11]; bootdev = rpb->devtyp; + /* + * now relocate rpb/bqo (which are used by ROM-routines) + */ + rpb = (void*)XXRPB; + bcopy ((void*)bootregs[11], rpb, 512); + rpb->rpb_base = rpb; + bqo = (void*)(512+(int)rpb); + bcopy ((void*)rpb->iovec, bqo, rpb->iovecsz); + rpb->iovec = (int)bqo; + bootregs[11] = (int)rpb; + break; - } + case VAX_8200: case VAX_750: - is_750 = 1; bootdev = bootregs[10]; break; + default: + printf("unknown cpu type %d\nRegister dump:\n", vax_cputype); + for (io = 0; io < 16; io++) + printf("r%d 0x%x\n", io, bootregs[io]); + asm("halt"); } bootset = getbootdev(); @@ -114,7 +123,7 @@ main() if (io >= 0 && io < SOPEN_MAX) { copyunix(io); } else { - printf("Boot failed. errno %d (%s)\n", errno, strerror(errno)); + printf("Boot failed, saerrno %d\n", errno); } } @@ -127,7 +136,7 @@ copyunix(aio) i = read(io, (char *) &x, sizeof(x)); if (i != sizeof(x) || N_BADMAG(x)) { - printf("Bad format: errno %s\n", strerror(errno)); + printf("Bad format\n"); return; } printf("%d", x.a_text); @@ -163,7 +172,7 @@ getbootdev() int i, major, adaptor, controller, unit, partition; - switch (cpunumber) { + switch (vax_cputype) { case VAX_78032: case VAX_650: adaptor = 0; @@ -172,6 +181,7 @@ getbootdev() break; + case VAX_8200: case VAX_750: controller = 0; /* XXX Actually massbuss can be on 3 ctlr's */ unit = bootregs[3]; @@ -181,23 +191,28 @@ getbootdev() partition = 0; switch (bootdev) { - case 0: /* massbuss boot */ + case BDEV_MBA: /* massbuss boot */ major = 0; /* hp / ... */ adaptor = (bootregs[1] & 0x6000) >> 17; break; - case 17: /* UDA50 boot */ + case BDEV_UDA: /* UDA50 boot */ major = 9; /* ra / mscp */ - if (is_750) + if (vax_cputype == VAX_750) adaptor = (bootregs[1] & 0x40000 ? 0 : 1); break; - case 18: /* TK50 boot */ + case BDEV_TK50: /* TK50 boot */ major = 15; /* tms / tmscp */ - is_tmscp = 1; /* use tape spec in mscp routines */ break; - case 64: + case 36: /* VS2000/KA410 ST506 disk */ + case 37: /* VS2000/KA410 SCSI tape */ + case 42: /* VS3100/76 SCSI-floppy(?) */ + major = 17; /* 17 is assigned to the ROM-drivers */ + break; + + case BDEV_CONSOLE: major = 8; break; @@ -224,7 +239,7 @@ struct disklabel lp; int part_off = 0; /* offset into partition holding /boot */ char io_buf[MAXBSIZE]; volatile struct uda { - struct uda1ca uda_ca; /* communications area */ + struct mscp_1ca uda_ca; /* communications area */ struct mscp uda_rsp; /* response packets */ struct mscp uda_cmd; /* command packets */ } uda; @@ -245,27 +260,27 @@ devopen(f, fname, file) /* * On uVAX we need to init [T]MSCP ctlr to be able to use it. */ - if (is_mvax) { + if (vax_cputype == VAX_78032 || vax_cputype == VAX_650) { switch (bootdev) { - case 17: /* MSCP */ - case 18: /* TMSCP */ + case BDEV_UDA: /* MSCP */ + case BDEV_TK50: /* TMSCP */ csr = (struct udadevice *)rpb->csrphy; csr->udaip = 0; /* Start init */ - while((csr->udasa & UDA_STEP1) == 0); + while((csr->udasa & MP_STEP1) == 0); csr->udasa = 0x8000; - while((csr->udasa & UDA_STEP2) == 0); + while((csr->udasa & MP_STEP2) == 0); csr->udasa = (short)(((u_int)&uda)&0xffff) + 8; - while((csr->udasa & UDA_STEP3) == 0); + while((csr->udasa & MP_STEP3) == 0); csr->udasa = 0x10; - while((csr->udasa & UDA_STEP4) == 0); + while((csr->udasa & MP_STEP4) == 0); csr->udasa = 0x0001; uda.uda_ca.ca_rspdsc = (int) &uda.uda_rsp.mscp_cmdref; uda.uda_ca.ca_cmddsc = (int) &uda.uda_cmd.mscp_cmdref; - if (is_tmscp) + if (bootdev == BDEV_TK50) uda.uda_cmd.mscp_vcid = 1; command(M_OP_SETCTLRC, 0); uda.uda_cmd.mscp_unit = rpb->unit; @@ -279,11 +294,10 @@ devopen(f, fname, file) * Actually disklabel is only needed when using hp disks, * but it doesn't hurt to always get it. */ - if (!is_tmscp) { + if ((bootdev != BDEV_TK50) && (bootdev != BDEV_CONSOLE)) { msg = getdisklabel((void *)LABELOFFSET + RELOC, &lp); - if (msg) { + if (msg) printf("getdisklabel: %s\n", msg); - } } return 0; } @@ -317,13 +331,13 @@ romstrategy(sc, func, dblk, size, buf, rsize) int block = dblk; int nsize = size; - switch (cpunumber) { + switch (vax_cputype) { case VAX_650: case VAX_78032: switch (bootdev) { - case 17: /* MSCP */ + case BDEV_UDA: /* MSCP */ uda.uda_cmd.mscp_seq.seq_lbn = dblk; uda.uda_cmd.mscp_seq.seq_bytecount = size; uda.uda_cmd.mscp_seq.seq_buffer = (int)buf; @@ -331,7 +345,7 @@ romstrategy(sc, func, dblk, size, buf, rsize) command(M_OP_READ, 0); break; - case 18: /* TMSCP */ + case BDEV_TK50: /* TMSCP */ if (dblk < curblock) { uda.uda_cmd.mscp_seq.seq_bytecount = curblock - dblk; @@ -351,16 +365,21 @@ romstrategy(sc, func, dblk, size, buf, rsize) command(M_OP_READ, 0); } break; + case 36: + case 37: + default: + romread_uvax(block, size, buf, bootregs); + break; } break; + case VAX_8200: case VAX_750: - if (bootdev) { + if (bootdev != BDEV_MBA) { while (size > 0) { - if ((read750(block, bootregs) & 0x01) == 0) - return 1; - + while ((read750(block, bootregs) & 0x01) == 0) + printf("Retrying read bn# %d\n", block); bcopy(0, buf, 512); size -= 512; buf += 512; diff --git a/sys/arch/vax/stand/conf.c b/sys/arch/vax/stand/conf.c index f516c4d2c3a..72b7f44faf0 100644 --- a/sys/arch/vax/stand/conf.c +++ b/sys/arch/vax/stand/conf.c @@ -1,4 +1,4 @@ -/* $NetBSD: conf.c,v 1.5 1996/02/17 18:23:18 ragge Exp $ */ +/* $NetBSD: conf.c,v 1.6 1996/08/02 11:21:56 ragge Exp $ */ /* * Copyright (c) 1994 Ludd, University of Lule}, Sweden. * All rights reserved. @@ -42,25 +42,33 @@ int raopen(), rastrategy(); int hpopen(), hpstrategy(); int ctuopen(), ctustrategy(); int tmscpopen(), tmscpstrategy(); +int romopen(), romstrategy(); +int mfmopen(), mfmstrategy(); +int sdopen(), sdstrategy(); + struct devsw devsw[]={ SADEV("hp",hpstrategy, hpopen, nullsys, noioctl), - SADEV("ht",nullsys, nodev, nullsys, noioctl), - SADEV("up",nullsys, nodev, nullsys, noioctl), - SADEV("hk",nullsys, nodev, nullsys, noioctl), + SADEV(0 ,nullsys, nodev, nullsys, noioctl), /* ht */ + SADEV(0 ,nullsys, nodev, nullsys, noioctl), /* up */ + SADEV(0 ,nullsys, nodev, nullsys, noioctl), /* hk */ SADEV( 0 ,nullsys, nodev, nullsys, noioctl), - SADEV("tm",nullsys, nodev, nullsys, noioctl), - SADEV("ts",nullsys, nodev, nullsys, noioctl), - SADEV("mt",nullsys, nodev, nullsys, noioctl), + SADEV(0 ,nullsys, nodev, nullsys, noioctl), /* tm */ + SADEV(0 ,nullsys, nodev, nullsys, noioctl), /* ts */ + SADEV(0 ,nullsys, nodev, nullsys, noioctl), /* mt */ SADEV("ctu",ctustrategy, ctuopen, nullsys, noioctl), SADEV("ra",rastrategy, raopen, nullsys, noioctl), - SADEV("ut",nullsys, nodev, nullsys, noioctl), - SADEV("id",nullsys, nodev, nullsys, noioctl), - SADEV("rx",nullsys, nodev, nullsys, noioctl), - SADEV("uu",nullsys, nodev, nullsys, noioctl), - SADEV("rl",nullsys, nodev, nullsys, noioctl), - SADEV("tms",tmscpstrategy, tmscpopen, nullsys, noioctl), - SADEV("kra",nullsys, nodev, nullsys, noioctl), + SADEV(0 ,nullsys, nodev, nullsys, noioctl), /* ut */ + SADEV(0 ,nullsys, nodev, nullsys, noioctl), /* id */ + SADEV(0 ,nullsys, nodev, nullsys, noioctl), /* rx */ + SADEV(0 ,nullsys, nodev, nullsys, noioctl), /* uu */ + SADEV(0 ,nullsys, nodev, nullsys, noioctl), /* rl */ + SADEV("mt",tmscpstrategy, tmscpopen, nullsys, noioctl), + SADEV(0 ,nullsys, nodev, nullsys, noioctl), /* crx */ + SADEV("rom",romstrategy, romopen, nullsys, noioctl), /* 17 */ + SADEV("mfm",mfmstrategy, mfmopen, nullsys, noioctl), /* 18 */ + SADEV("sd",sdstrategy, sdopen, nullsys, noioctl), /* 18 */ + SADEV("st",sdstrategy, sdopen, nullsys, noioctl), }; int ndevs = (sizeof(devsw)/sizeof(devsw[0])); diff --git a/sys/arch/vax/stand/consio.c b/sys/arch/vax/stand/consio.c index 39402cc1d44..94db46d0262 100644 --- a/sys/arch/vax/stand/consio.c +++ b/sys/arch/vax/stand/consio.c @@ -1,4 +1,4 @@ -/* $NetBSD: consio.c,v 1.3 1995/09/16 15:48:49 ragge Exp $ */ +/* $NetBSD: consio.c,v 1.4 1996/08/02 11:22:00 ragge Exp $ */ /* * Copyright (c) 1994 Ludd, University of Lule}, Sweden. * All rights reserved. @@ -38,24 +38,165 @@ #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 +"); + + diff --git a/sys/arch/vax/stand/copy.c b/sys/arch/vax/stand/copy.c index a67721d7458..c46ba5674e3 100644 --- a/sys/arch/vax/stand/copy.c +++ b/sys/arch/vax/stand/copy.c @@ -1,4 +1,4 @@ -/* $NetBSD: copy.c,v 1.2 1995/09/29 16:35:00 ragge Exp $ */ +/* $NetBSD: copy.c,v 1.3 1996/08/02 11:22:03 ragge Exp $ */ /*- * Copyright (c) 1982, 1986 The Regents of the University of California. * All rights reserved. @@ -38,6 +38,8 @@ #include "sys/reboot.h" #include "lib/libsa/stand.h" +#include "vaxstand.h" + #include <a.out.h> char line[100]; @@ -53,7 +55,7 @@ static int partlist[8]; int fill_buffer (void); int write_disk (void); -main() +Xmain() { int adapt, ctlr, unit, part; int res, i, loops; diff --git a/sys/arch/vax/stand/devopen.c b/sys/arch/vax/stand/devopen.c index d3468b427dd..8d58b778998 100644 --- a/sys/arch/vax/stand/devopen.c +++ b/sys/arch/vax/stand/devopen.c @@ -1,4 +1,4 @@ -/* $NetBSD: devopen.c,v 1.4 1996/03/16 11:02:28 ragge Exp $ */ +/* $NetBSD: devopen.c,v 1.6 1996/08/02 16:18:39 ragge Exp $ */ /*- * Copyright (c) 1993 John Brezak * All rights reserved. @@ -52,7 +52,7 @@ usage() { printf("\ Usage: device(adaptor, controller, drive, partition)file\n\ - <device><unit><partitonletter>:file\n\ + <device><unit><partitonletter>:file\n\ "); } @@ -62,15 +62,15 @@ devlookup(d,len) { struct devsw *dp = devsw; int i; - + for (i = 0; i < ndevs; i++, dp++) if (dp->dv_name && strncmp(dp->dv_name, d, len) == 0) - return(i); + return(i); printf("No such device - Configured devices are:\n"); for (dp = devsw, i = 0; i < ndevs; i++, dp++) if (dp->dv_name) - printf(" %s", dp->dv_name); + printf(" %s", dp->dv_name); printf("\n"); errno = ENODEV; return(-1); @@ -90,7 +90,7 @@ devparse(fname, dev, adapt, ctlr, unit, part, file) { int *argp, i; char *s, *args[4]; - + /* get device name and make lower case */ for(s = fname; *s && *s != '/' && *s != ':' && *s != '('; s++) if(isupper(*s)) @@ -117,19 +117,19 @@ devparse(fname, dev, adapt, ctlr, unit, part, file) *part = atoi(args[3]); break; case 3: - *ctlr = atoi(args[0]); - *unit = atoi(args[1]); - *part = atoi(args[2]); - break; + *ctlr = atoi(args[0]); + *unit = atoi(args[1]); + *part = atoi(args[2]); + break; case 2: - *unit = atoi(args[0]); - *part = atoi(args[1]); - break; + *unit = atoi(args[0]); + *part = atoi(args[1]); + break; case 1: - *part = atoi(args[0]); - break; + *part = atoi(args[0]); + break; case 0: - break; + break; } *file = ++s; @@ -142,25 +142,25 @@ devparse(fname, dev, adapt, ctlr, unit, part, file) /* lookup device and get index */ if ((*dev = devlookup(fname, s - fname)) < 0) - goto baddev; + goto baddev; /* isolate unit */ if ((*unit = atoi(s)) > sizeof(char)) - goto bad; + goto bad; for (; isdigit(*s); s++) ; /* translate partition */ if(!ispart(*s)) - goto bad; + goto bad; *part = *s++ - 'a'; if(*s != ':') - goto bad; + goto bad; *file = ++s; /* no device present */ - } else + } else *file = fname; /* return the remaining unparsed part as the file to boot */ @@ -176,8 +176,8 @@ bad: extern int bootdev; devopen(f, fname, file) - struct open_file *f; - const char *fname; + struct open_file *f; + const char *fname; char **file; { int n, error; @@ -190,12 +190,12 @@ devopen(f, fname, file) unit = B_UNIT(bootdev); part = B_PARTITION(bootdev); adapt = B_ADAPTOR(bootdev); - + if (error = devparse(fname, &dev, &adapt, &ctlr, &unit, &part, file)) return(error); - + dp = &devsw[dev]; - + if (!dp->dv_open) return(ENODEV); diff --git a/sys/arch/vax/stand/edlabel.c b/sys/arch/vax/stand/edlabel.c index 09844183bef..a5af6abe894 100644 --- a/sys/arch/vax/stand/edlabel.c +++ b/sys/arch/vax/stand/edlabel.c @@ -1,4 +1,4 @@ -/* $NetBSD: edlabel.c,v 1.1 1995/09/16 12:56:03 ragge Exp $ */ +/* $NetBSD: edlabel.c,v 1.2 1996/08/02 11:22:11 ragge Exp $ */ /* * Copyright (c) 1995 Ludd, University of Lule}, Sweden. * All rights reserved. @@ -88,7 +88,7 @@ setdefaultlabel() #define GETNUM2(out, num1, num) printf(out, num1, num);gets(store); \ if (*store) num = atoi(store); #define GETSTR(out, str) printf(out, str);gets(store); \ - if (*store) strcpy(str, store); + if (*store) bcopy(store, str, strlen(store)); #define FLAGS(out, flag) printf(out, lp->d_flags & flag?'y':'n');gets(store); \ if (*store == 'y' || *store == 'Y') lp->d_flags |= flag; \ else lp->d_flags &= ~flag; @@ -121,9 +121,11 @@ editlabel() GETNUM("drivedata 2? [%d] ", lp->d_drivedata[2]); GETNUM("drivedata 3? [%d] ", lp->d_drivedata[3]); GETNUM("drivedata 4? [%d] ", lp->d_drivedata[4]); + lp->d_secsize = 512; GETNUM("\nbytes/sector? [%d] ", lp->d_secsize); GETNUM("sectors/track? [%d] ", lp->d_nsectors); GETNUM("tracks/cylinder? [%d] ", lp->d_ntracks); + lp->d_secpercyl = lp->d_nsectors * lp->d_ntracks; GETNUM("sectors/cylinder? [%d] ", lp->d_secpercyl); GETNUM("cylinders? [%d] ", lp->d_ncylinders); lp->d_npartitions = MAXPARTITIONS; @@ -137,7 +139,7 @@ editlabel() int bootdev; void -main() +Xmain() { register bdev asm("r10"); diff --git a/sys/arch/vax/stand/init.c b/sys/arch/vax/stand/init.c deleted file mode 100644 index 94c7ad6276a..00000000000 --- a/sys/arch/vax/stand/init.c +++ /dev/null @@ -1,82 +0,0 @@ -/* $NetBSD: init.c,v 1.3 1995/09/16 13:34:21 ragge Exp $ */ -/* - * Copyright (c) 1995 Ludd, University of Lule}, Sweden. All rights reserved. - * - * This code is derived from software contributed to Ludd by Bertram Barth. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. 2. - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. 3. All advertising - * materials mentioning features or use of this software must display the - * following acknowledgement: This product includes software developed at - * Ludd, University of Lule}, Sweden and its contributors. 4. The name of the - * author may not be used to endorse or promote products derived from this - * software without specific prior written permission - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO - * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* All bugs are subject to removal without further notice */ - - - -#include "lib/libsa/stand.h" - -#include "../include/mtpr.h" /* mfpr(), mtpr() */ -#include "../include/sid.h" /* cpu_type, cpu_number */ - -#define NRSP 0 /* Kludge, must be done before udareg.h */ -#define NCMD 0 /* includes */ - -#include "../uba/udareg.h" /* struct udadevice */ - -#include "data.h" /* bootregs[], rpb, bqo */ - -struct rpb *rpb; -struct bqo *bqo; - -int is_750 = 0, is_mvax = 0; - -/* - * initdata() sets up data gotten from start routines, mostly for uVAX. - */ -int -initdata() -{ - int i, *tmp; - - cpu_type = mfpr(PR_SID); - cpunumber = (mfpr(PR_SID) >> 24) & 0xFF; - - switch (cpunumber) { - - case VAX_78032: - case VAX_650: - { - int cpu_sie; /* sid-extension */ - - is_mvax = 1; - cpu_sie = *((int *) 0x20040004) >> 24; - cpu_type |= cpu_sie; - - break; - } - case VAX_750: - is_750 = 1; - break; - } - return 0; -} diff --git a/sys/arch/vax/stand/ka410.h b/sys/arch/vax/stand/ka410.h new file mode 100644 index 00000000000..a022362c08f --- /dev/null +++ b/sys/arch/vax/stand/ka410.h @@ -0,0 +1,82 @@ +/* $NetBSD: ka410.h,v 1.1 1996/08/02 11:22:13 ragge Exp $ */ +/* + * Copyright (c) 1996 Ludd, University of Lule}, Sweden. + * All rights reserved. + * + * This code is derived from software contributed to Ludd by + * Bertram Barth. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed at Ludd, University of + * Lule}, Sweden and its contributors. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + + +/* + * interrupt request-, clear-, and mask register + */ +extern volatile unsigned char *ka410_intreq; +extern volatile unsigned char *ka410_intclr; +extern volatile unsigned char *ka410_intmsk; + +#define INTR_SR (1<<7) /* Serial line receiver or silo full */ +#define INTR_ST (1<<6) /* Serial line transmitter done */ +#define INTR_NP (1<<5) /* Network controller primary */ +#define INTR_NS (1<<4) /* Network controller secondary */ +#define INTR_VF (1<<3) /* Video end of frame */ +#define INTR_VS (1<<2) /* Video secondary */ +#define INTR_SC (1<<1) /* SCSI controller */ +#define INTR_DC (1<<0) /* Disk controller */ + +/* + * interrupt vector numbers + */ +#define IVEC_BASE 0x20040020 +#define IVEC_SR 0x000002C0 +#define IVEC_ST 0x000002C4 +#define IVEC_NP 0x00000250 +#define IVEC_NS 0x00000254 +#define IVEC_VF 0x00000244 +#define IVEC_VS 0x00000248 +#define IVEC_SC 0x000003F8 +#define IVEC_DC 0x000003FC + +/* + * Clock-Chip data in NVRAM + */ +#define KA410_CPMBX 0x200B0038 /* Console Mailbox (1 byte) */ +#define KA410_CPFLG 0x200B003C /* Console Program Flags (1 byte) */ +#define KA410_LK201_ID 0x200B0040 /* Keyboard Variation (1 byte) */ +#define KA410_CONS_ID 0x200B0044 /* Console Device Type (1 byte) */ +#define KA410_SCR 0x200B0048 /* Console Scratch RAM */ +#define KA410_TEMP 0x200B0058 /* Used by System Firmware */ +#define KA410_BAT_CHK 0x200B0088 /* Battery Check Data */ +#define KA410_BOOTDEV 0x200B0098 /* Default Boot Device (4 bytes) */ +#define KA410_BOOTFLG 0x200B00A8 /* Default Boot Flags (4 bytes) */ +#define KA410_SCRLEN 0x200B00B8 /* Number of pages of SCR (1 byte) */ +#define KA410_SCSIPORT 0x200B00BC /* Tape Controller Port Data */ +#define KA410_RESERVED 0x200B00C0 /* Reserved (16 bytes) */ + diff --git a/sys/arch/vax/stand/mfm.c b/sys/arch/vax/stand/mfm.c new file mode 100644 index 00000000000..bd271530ea4 --- /dev/null +++ b/sys/arch/vax/stand/mfm.c @@ -0,0 +1,640 @@ +/* $NetBSD: mfm.c,v 1.1 1996/08/02 11:22:16 ragge Exp $ */ +/* + * Copyright (c) 1996 Ludd, University of Lule}, Sweden. + * All rights reserved. + * + * This code is derived from software contributed to Ludd by + * Bertram Barth. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed at Ludd, University of + * Lule}, Sweden and its contributors. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * ToDo: + * + * - insert appropriate delays for diskette-drive where needed + * - allow more than one sector per diskette-read + * - check for and handle bad sectors + * - ??? + */ + +#include "sys/param.h" +#include "sys/reboot.h" +#include "sys/disklabel.h" + +#include "lib/libsa/stand.h" +#include "lib/libsa/ufs.h" + +#include "../include/pte.h" +#include "../include/sid.h" +#include "../include/mtpr.h" +#include "../include/reg.h" +#include "../include/rpb.h" + +#include "ka410.h" +#include "../vsa/hdc9224.h" + +#include "data.h" +#include "vaxstand.h" + +#define MAX_WAIT (1000*1000) /* # of loop-instructions in seconds */ + +struct mfm_softc { + int part; + int unit; +}; + +int mfmstrategy(), mfmopen(); +struct disklabel mfmlabel; +struct mfm_softc mfm_softc; +char io_buf[MAXBSIZE]; + +/* + * These should probably be somewhere else, but ka410 is the only + * one with mfm disks anyway... + */ +volatile unsigned char *ka410_intreq = (void*)0x2008000f; +volatile unsigned char *ka410_intclr = (void*)0x2008000f; +volatile unsigned char *ka410_intmsk = (void*)0x2008000c; + +static volatile struct hdc9224_DKCreg *dkc = (void *) 0x200c0000; +static volatile struct hdc9224_UDCreg sreg; /* input */ +static volatile struct hdc9224_UDCreg creg; /* output */ + +/* + * we have to wait 0.7 usec between two accesses to any of the + * dkc-registers, on a VS2000 with 1 MIPS, this is roughly one + * instruction. Thus the loop-overhead will be enough... + */ +static int +sreg_read() +{ + int i; + char *p; + + dkc->dkc_cmd = 0x40; /* set internal counter to zero */ + p = (void *) &sreg; + for (i = 0; i < 10; i++) + *p++ = dkc->dkc_reg; /* dkc_reg auto-increments */ +} + +static int +creg_write() +{ + int i; + char *p; + + dkc->dkc_cmd = 0x40; /* set internal counter to zero */ + p = (void *) &creg; + for (i = 0; i < 10; i++) + dkc->dkc_reg = *p++; /* dkc_reg auto-increments */ +} + +/* + * floppies are handled in a quite strange way by this controller... + * + * before reading/writing a sector from/to floppy, we use the SEEK/READ_ID + * command to place the head at the desired location. Then we wait some + * time before issueing the real command in order to let the drive become + * ready... + */ +int +mfm_rxprepare() +{ + int error; + + error = mfm_command(DKC_CMD_SEEKREADID | 0x04); /* step=1, verify=0 */ + if (error) { + printf("error while stepping to position %d/%d/%x. Retry...\n", + creg.udc_dsect, creg.udc_dhead, creg.udc_dcyl); + error = mfm_command(DKC_CMD_SEEKREADID | 0x04); + } + return error; +} + +int +mfm_rxselect(unit) + int unit; +{ + int error; + + /* + * bring "creg" in some known-to-work state and + * select the drive with the DRIVE SELECT command. + */ + creg.udc_dma7 = 0; + creg.udc_dma15 = 0; + creg.udc_dma23 = 0; + creg.udc_dsect = 1; /* sectors are numbered 1..15 !!! */ + creg.udc_dhead = 0; + creg.udc_dcyl = 0; + creg.udc_scnt = 0; + + creg.udc_rtcnt = UDC_RC_RX33READ; + creg.udc_mode = UDC_MD_RX33; + creg.udc_term = UDC_TC_FDD; + + /* + * this is ... + */ + error = mfm_command(DKC_CMD_DRSEL_RX33 | unit); + + if ((error != 0) || (sreg.udc_dstat & UDC_DS_READY == 0)) { + printf("\nfloppy-drive not ready (new floppy inserted?)\n\n"); + + creg.udc_rtcnt &= ~UDC_RC_INVRDY; /* clear INVRDY-flag */ + error = mfm_command(DKC_CMD_DRSEL_RX33 | unit); + if ((error != 0) || (sreg.udc_dstat & UDC_DS_READY == 0)) { + printf("diskette not ready(1): %x/%x\n", + error, sreg.udc_dstat); + printf("floppy-drive offline?\n"); + return (-1); + } + if (sreg.udc_dstat & UDC_DS_TRK00) + error = mfm_command(DKC_CMD_STEPIN_FDD); + else + error = mfm_command(DKC_CMD_STEPOUT_FDD); + + /* + * now ready should be 0, cause INVRDY is not set + * (retrying a command makes this fail...) + */ + if ((error != 0) || (sreg.udc_dstat & UDC_DS_READY == 1)) { + printf("diskette not ready(2): %x/%x\n", + error, sreg.udc_dstat); + } + creg.udc_rtcnt |= UDC_RC_INVRDY; + error = mfm_command(DKC_CMD_DRSEL_RX33 | unit); + + if ((error != 0) || (sreg.udc_dstat & UDC_DS_READY == 0)) { + printf("diskette not ready(3): %x/%x\n", + error, sreg.udc_dstat); + printf("no floppy inserted or floppy-door open\n"); + return (-1); + } + printf("floppy-drive reselected.\n"); + } + return (error); +} + +int +mfm_rdselect(unit) + int unit; +{ + int error; + + /* + * bring "creg" in some known-to-work state and + * select the drive with the DRIVE SELECT command. + */ + creg.udc_dma7 = 0; + creg.udc_dma15 = 0; + creg.udc_dma23 = 0; + creg.udc_dsect = 0; /* sectors are numbered 0..16 */ + creg.udc_dhead = 0; + creg.udc_dcyl = 0; + creg.udc_scnt = 0; + + creg.udc_rtcnt = UDC_RC_HDD_READ; + creg.udc_mode = UDC_MD_HDD; + creg.udc_term = UDC_TC_HDD; + + error = mfm_command(DKC_CMD_DRSEL_HDD | unit); + + return (error); +} + +static int mfm_retry = 0; + +int +mfm_command(cmd) + int cmd; +{ + int termcode, ready, i; + + creg_write(); /* write command-registers */ + *ka410_intclr = INTR_DC; + dkc->dkc_cmd = cmd; /* issue command */ + for (i = 0; i < MAX_WAIT; i++) { + if (*ka410_intreq & INTR_DC) /* wait for interrupt */ + break; + } + if ((*ka410_intreq & INTR_DC) == 0) + printf("timeout in mfm_command...\n"); + + sreg_read(); /* read status-registers */ + + if (dkc->dkc_stat == (DKC_ST_DONE | DKC_TC_SUCCESS)) + return (0); + + if (sreg.udc_cstat & UDC_CS_ECCERR) { + printf( +"\nspurious(?) ECC/CRC error at s%d/t%d/c%d [s%d/t%d/c%d(%d)]\n", + sreg.udc_csect, sreg.udc_chead, sreg.udc_ccyl, + creg.udc_dsect, creg.udc_dhead, creg.udc_dcyl,creg.udc_scnt); + if (sreg.udc_csect != creg.udc_dsect + creg.udc_scnt - 1) { + printf("DMA: %x %x %x [%x]\n", + sreg.udc_dma23, sreg.udc_dma15, + sreg.udc_dma7, 512 * (sreg.udc_csect - + creg.udc_dsect)); + creg.udc_scnt = creg.udc_scnt - + (sreg.udc_csect - creg.udc_dsect) - 1; + creg.udc_dsect = sreg.udc_csect + 1; + creg.udc_dma23 = sreg.udc_dma23; + creg.udc_dma15 = sreg.udc_dma15 + 2; + creg.udc_dma7 = 0; + printf("Retry starting from s%d/t%d/c%d (%d). ", + creg.udc_dsect, creg.udc_dhead, creg.udc_dcyl, + creg.udc_scnt); + } + goto retry; + } + termcode = (dkc->dkc_stat & DKC_ST_TERMCOD) >> 3; + ready = sreg.udc_dstat & UDC_DS_READY; + + printf("cmd:0x%x: termcode=0x%x, status=0x%x, cstat=0x%x, dstat=0x%x\n", + cmd, termcode, dkc->dkc_stat, sreg.udc_cstat, sreg.udc_dstat); + + if (dkc->dkc_stat & DKC_ST_BADSECT) + printf("bad sector found: s%d/t%d/c%d\n", creg.udc_dsect, + creg.udc_dhead, creg.udc_dcyl); +retry: + if ((mfm_retry == 0) && (sreg.udc_cstat & UDC_CS_RETREQ)) { + mfm_retry = 1; + printf("Retrying... "); + mfm_command(cmd); + printf("Retry done.\n"); + mfm_retry = 0; + } + return ((dkc->dkc_stat & DKC_ST_TERMCOD) >> 3); +} + +/* + * on-disk geometry block + */ +#define _aP __attribute__ ((packed)) /* force byte-alignment */ + +volatile struct mfm_xbn { + char mbz[10];/* 10 bytes of zero */ + long xbn_count _aP; /* number of XBNs */ + long dbn_count _aP; /* number of DBNs */ + long lbn_count _aP; /* number of LBNs (Logical-Block-Numbers) */ + long rbn_count _aP; /* number of RBNs (Replacement-Block-Numbers) */ + short nspt; /* number of sectors per track */ + short ntracks;/* number of tracks */ + short ncylinders; /* number of cylinders */ + short precomp;/* first cylinder for write precompensation */ + short reduced;/* first cylinder for reduced write current */ + short seek_rate; /* seek rate or zero for buffered + * seeks */ + short crc_eec;/* 0 if CRC is being used or 1 if ECC is + * being used */ + short rct; /* "replacement control table" (RCT) */ + short rct_ncopies; /* number of copies of the RCT */ + long media_id _aP; /* media identifier */ + short interleave; /* sector-to-sector interleave */ + short headskew; /* head-to-head skew */ + short cylskew;/* cylinder-to-cylinder skew */ + short gap0_size; /* size of GAP 0 in the MFM format */ + short gap1_size; /* size of GAP 1 in the MFM format */ + short gap2_size; /* size of GAP 2 in the MFM format */ + short gap3_size; /* size of GAP 3 in the MFM format */ + short sync_value; /* sync value used to start a track + * when formatting */ + char reserved[32]; /* reserved for use by the RQDX1/2/3 + * formatter */ + short serial_number; /* serial number */ + char fill[412]; /* Filler bytes to the end of the + * block */ + short checksum; /* checksum over the XBN */ +} mfm_xbn; + +display_xbn(p) + struct mfm_xbn *p; +{ + printf("**DiskData** XBNs: %d, DBNs: %d, LBNs: %d, RBNs: %d\n", + p->xbn_count, p->dbn_count, p->lbn_count, p->rbn_count); + printf("sect/track: %d, tracks: %d, cyl: %d, precomp/reduced: %d/%d\n", + p->nspt, p->ntracks, p->ncylinders, p->precomp, p->reduced); + printf("seek-rate: %d, crc/eec: %s, RCT: %d, RCT-copies: %d\n", + p->seek_rate, p->crc_eec ? "EEC" : "CRC", p->rct, p->rct_ncopies); + printf("media-ID: 0x%x, interleave: %d, headskew: %d, cylskew: %d\n", + &p->media_id, p->interleave, p->headskew, p->cylskew); + printf("gap0: %d, gap1: %d, gap2: %d, gap3: %d, sync-value: %d\n", + p->gap0_size, p->gap1_size, p->gap2_size, p->gap3_size, + p->sync_value); + printf("serial: %d, checksum: %d, size: %d, reserved: %32c\n", + p->serial_number, p->checksum, sizeof(*p), p->reserved); +} + +mfmopen(f, adapt, ctlr, unit, part) + struct open_file *f; + int ctlr, unit, part; +{ + char *msg; + struct disklabel *lp = &mfmlabel; + volatile struct mfm_softc *msc = &mfm_softc; + int i, err; + + bzero(lp, sizeof(struct disklabel)); + msc->unit = unit; + msc->part = part; + + err = mfmstrategy(msc, F_READ, LABELSECTOR, DEV_BSIZE, io_buf, &i); + if (err) { + printf("reading disklabel: %s\n", strerror(err)); + return 0; + } + msg = getdisklabel(io_buf + LABELOFFSET, lp); + if (msg) + printf("getdisklabel: %s\n", msg); + + f->f_devdata = (void *) msc; + + { + int k; + unsigned char *ucp; + struct mfm_xbn *xp; + + /* mfmstrategy(msc, F_READ, -16, 8192, io_buf, &i); */ + mfmstrategy(msc, F_READ, -16, 512, io_buf, &i); + printf("dumping raw disk-block #0:\n"); + ucp = io_buf; + for (k = 0; k < 128; k++) { + if (ucp[k] < 0x10) + printf("0"); + printf("%x ", ucp[k]); + if (k % 8 == 7) + printf(" "); + if (k % 16 == 15) + printf("\n"); + } + printf("\n"); + + xp = (void *) io_buf; + display_xbn(xp); + printf("\n"); + + } + + if (unit == 2) { /* floppy! */ + if (lp->d_ntracks != 2) { + printf("changing number of tracks from %d to %d.\n", + lp->d_ntracks, 2); + lp->d_ntracks = 2; + } + } else { /* hard-disk */ + unsigned short *usp = (void *) io_buf; + printf("label says: s/t/c = %d/%d/%d\n", + lp->d_nsectors, lp->d_ntracks, lp->d_ncylinders); + + if (lp->d_nsectors != usp[13]) { + printf("changing number of sectors from %d to %d.\n", + lp->d_nsectors, usp[13]); + lp->d_nsectors = usp[13]; + } + if (lp->d_ntracks != usp[14]) { + printf("changing number of heads/tracks from %d to %d.\n", + lp->d_ntracks, usp[14]); + lp->d_ntracks = usp[14]; + } + if (lp->d_ncylinders != usp[15]) { + printf("changing number of cylinders from %d to %d.\n", + lp->d_ncylinders, usp[15]); + lp->d_ncylinders = usp[15]; + } + lp->d_secpercyl = lp->d_nsectors * lp->d_ntracks; + } + + return (0); +} + +mfm_rxstrategy(msc, func, dblk, size, buf, rsize) + struct mfm_softc *msc; + int func; + daddr_t dblk; + char *buf; + int size, *rsize; +{ + struct disklabel *lp; + int block, sect, head, cyl, scount, i, cmd, res, sval; + + lp = &mfmlabel; + block = (dblk < 0 ? 0 : dblk + lp->d_partitions[msc->part].p_offset); + + mfm_rxselect(msc->unit); + + /* + * if label is empty, assume RX33 + */ + if (lp->d_nsectors == 0) + lp->d_nsectors = 15; + if (lp->d_ntracks == 0) + lp->d_ntracks = 2; + if (lp->d_secpercyl == 0) + lp->d_secpercyl = 30; + + bzero((void *) 0x200D0000, size); + scount = size / 512; + + while (scount) { + /* + * prepare drive/operation parameter + */ + cyl = block / lp->d_secpercyl; + sect = block % lp->d_secpercyl; + head = sect / lp->d_nsectors; + sect = sect % lp->d_nsectors; + + /* + * *rsize = 512; /* one sector after the other + * ... + */ + *rsize = 512 * min(scount, lp->d_nsectors - sect); + + /* + * now initialize the register values ... + */ + creg.udc_dma7 = 0; + creg.udc_dma15 = 0; + creg.udc_dma23 = 0; + + creg.udc_dsect = sect + 1; /* sectors are numbered 1..15 + * !!! */ + head |= (cyl >> 4) & 0x70; + creg.udc_dhead = head; + creg.udc_dcyl = cyl; + + creg.udc_scnt = *rsize / 512; + + if (func == F_WRITE) { + creg.udc_rtcnt = UDC_RC_RX33WRT; + creg.udc_mode = UDC_MD_RX33; + creg.udc_term = UDC_TC_FDD; + + mfm_rxprepare(); + /* copy from buf */ + bcopy(buf, (void *) 0x200D0000, *rsize); + res = mfm_command(DKC_CMD_WRITE_RX33); + } else { + creg.udc_rtcnt = UDC_RC_RX33READ; + creg.udc_mode = UDC_MD_RX33; + creg.udc_term = UDC_TC_FDD; + + mfm_rxprepare(); + /* clear disk buffer */ + bzero((void *) 0x200D0000, *rsize); + res = mfm_command(DKC_CMD_READ_RX33); + /* copy to buf */ + bcopy((void *) 0x200D0000, buf, *rsize); + } + + scount -= *rsize / 512; + block += *rsize / 512; + buf += *rsize; + } + + *rsize = size; + return 0; +} + +mfm_rdstrategy(msc, func, dblk, size, buf, rsize) + struct mfm_softc *msc; + int func; + daddr_t dblk; + char *buf; + int size, *rsize; +{ + struct disklabel *lp; + int block, sect, head, cyl, scount, i, cmd, res, sval; + + lp = &mfmlabel; + block = (dblk < 0 ? 0 : dblk + lp->d_partitions[msc->part].p_offset); + + /* + * if label is empty, assume RD32 (XXX this must go away!!!) + */ + if (lp->d_nsectors == 0) + lp->d_nsectors = 17; + if (lp->d_ntracks == 0) + lp->d_ntracks = 6; + if (lp->d_secpercyl == 0) + lp->d_secpercyl = 102; + + mfm_rdselect(msc->unit); + + bzero((void *) 0x200D0000, size); + scount = size / 512; + + while (scount) { + /* + * prepare drive/operation parameter + */ + cyl = block / lp->d_secpercyl; + sect = block % lp->d_secpercyl; + head = sect / lp->d_nsectors; + sect = sect % lp->d_nsectors; + + if (dblk < 0) { + printf("using raw diskblock-data!\n"); + printf("block %d, dblk %d ==> cyl %d, head %d, sect %d\n", + block, dblk, cyl, sect, head); + } else + cyl += 1; /* first cylinder is reserved for + * controller! */ + + *rsize = 512 * min(scount, lp->d_nsectors - sect); + /* + * now re-initialize the register values ... + */ + creg.udc_dma7 = 0; + creg.udc_dma15 = 0; + creg.udc_dma23 = 0; + + creg.udc_dsect = sect; + head |= (cyl >> 4) & 0x70; + creg.udc_dhead = head; + creg.udc_dcyl = cyl; + + creg.udc_scnt = *rsize / 512; + + if (func == F_WRITE) { + creg.udc_rtcnt = UDC_RC_HDD_WRT; + creg.udc_mode = UDC_MD_HDD; + creg.udc_term = UDC_TC_HDD; + cmd = DKC_CMD_WRITE_HDD; + + bcopy(buf, (void *) 0x200D0000, *rsize); + res = mfm_command(cmd); + } else { + creg.udc_rtcnt = UDC_RC_HDD_READ; + creg.udc_mode = UDC_MD_HDD; + creg.udc_term = UDC_TC_HDD; + cmd = DKC_CMD_READ_HDD; + + bzero((void *) 0x200D0000, *rsize); + res = mfm_command(cmd); + bcopy((void *) 0x200D0000, buf, *rsize); + } + + scount -= *rsize / 512; + block += *rsize / 512; + buf += *rsize; + } + + /* + * unselect the drive ... + */ + mfm_command(DKC_CMD_DRDESELECT); + + *rsize = size; + return 0; +} + +int +mfmstrategy(msc, func, dblk, size, buf, rsize) + struct mfm_softc *msc; + int func; + daddr_t dblk; + char *buf; + int size, *rsize; +{ + int res = -1; + + switch (msc->unit) { + case 0: + case 1: + res = mfm_rdstrategy(msc, func, dblk, size, buf, rsize); + break; + case 2: + res = mfm_rxstrategy(msc, func, dblk, size, buf, rsize); + break; + default: + printf("invalid unit %d in mfmstrategy()\n"); + } + return (res); +} diff --git a/sys/arch/vax/stand/ra.c b/sys/arch/vax/stand/ra.c index 43e368fe098..722b19d99cd 100644 --- a/sys/arch/vax/stand/ra.c +++ b/sys/arch/vax/stand/ra.c @@ -1,4 +1,4 @@ -/* $NetBSD: ra.c,v 1.4 1996/02/17 18:23:23 ragge Exp $ */ +/* $NetBSD: ra.c,v 1.5 1996/08/02 11:22:18 ragge Exp $ */ /* * Copyright (c) 1995 Ludd, University of Lule}, Sweden. * All rights reserved. @@ -31,8 +31,8 @@ /* All bugs are subject to removal without further notice */ -#define NRSP 0 /* Kludge */ -#define NCMD 0 /* Kludge */ +#define NRSP 1 /* Kludge */ +#define NCMD 1 /* Kludge */ #include "sys/param.h" #include "sys/disklabel.h" @@ -41,9 +41,16 @@ #include "../include/pte.h" #include "../include/macros.h" +#include "../include/sid.h" + #include "../uba/ubareg.h" #include "../uba/udareg.h" -#include "../vax/mscp.h" + +#include "../mscp/mscp.h" +#include "../mscp/mscpreg.h" + +#include "../bi/bireg.h" +#include "../bi/kdbreg.h" #include "vaxstand.h" @@ -62,10 +69,13 @@ struct ra_softc { int ubaddr; int part; int unit; + unsigned short *ra_ip; + unsigned short *ra_sa; + unsigned short *ra_sw; }; volatile struct uda { - struct uda1ca uda_ca; /* communications area */ + struct mscp_1ca uda_ca; /* communications area */ struct mscp uda_rsp; /* response packets */ struct mscp uda_cmd; /* command packets */ } uda; @@ -81,53 +91,84 @@ raopen(f, adapt, ctlr, unit, part) int ctlr, unit, part; { char *msg; - struct disklabel *lp=&ralabel; - volatile struct ra_softc *ra=&ra_softc; - volatile struct uba_regs *mr=(void *)ubaaddr[adapt]; + struct disklabel *lp = &ralabel; + volatile struct ra_softc *ra = &ra_softc; + volatile struct uba_regs *mr = (void *)ubaaddr[adapt]; volatile u_int *nisse; - unsigned short johan; + unsigned short johan, johan2; int i,err; - if(adapt>nuba) return(EADAPT); - if(ctlr>nuda) return(ECTLR); bzero(lp, sizeof(struct disklabel)); - ra->udaddr=uioaddr[adapt]+udaaddr[ctlr]; - ra->ubaddr=(int)mr; - ra->unit=unit; + ra->unit = unit; ra->part = part; - udacsr=(void*)ra->udaddr; - nisse=(u_int *)&mr->uba_map[0]; - nisse[494]=PG_V|(((u_int)&uda)>>9); - nisse[495]=nisse[494]+1; - ubauda=(void*)0x3dc00+(((u_int)(&uda))&0x1ff); + if (vax_cputype != VAX_8200) { + if (adapt > nuba) + return(EADAPT); + if (ctlr > nuda) + return(ECTLR); + nisse = (u_int *)&mr->uba_map[0]; + nisse[494] = PG_V | (((u_int)&uda) >> 9); + nisse[495] = nisse[494] + 1; + udacsr = (void*)uioaddr[adapt] + udaaddr[ctlr]; + ubauda = (void*)0x3dc00 + (((u_int)(&uda))&0x1ff); + johan = (((u_int)ubauda) & 0xffff) + 8; + johan2 = 3; + ra->ra_ip = (short *)&udacsr->udaip; + ra->ra_sa = ra->ra_sw = (short *)&udacsr->udasa; + ra->udaddr = uioaddr[adapt] + udaaddr[ctlr]; + ra->ubaddr = (int)mr; + *ra->ra_ip = 0; /* Start init */ + } else { + struct bi_node *bi = (void *)biaddr[adapt]; + struct kdb_regs *kb = (void *)&bi[ctlr]; + volatile int i = 10000; + + ra->ra_ip = &kb->kdb_ip; + ra->ra_sa = &kb->kdb_sa; + ra->ra_sw = &kb->kdb_sw; + johan = ((u_int)&uda.uda_ca.ca_rspdsc) & 0xffff; + johan2 = (((u_int)&uda.uda_ca.ca_rspdsc) & 0xffff0000) >> 16; + kb->kdb_bi.bi_csr |= BICSR_NRST; + while (i--) /* Need delay??? */ + ; + kb->kdb_bi.bi_ber = ~(BIBER_MBZ|BIBER_NMR|BIBER_UPEN);/* ??? */ + ubauda = &uda; + } + /* Init of this uda */ - udacsr->udaip=0; /* Start init */ - while((udacsr->udasa&UDA_STEP1) == 0); - udacsr->udasa=0x8000; - while((udacsr->udasa&UDA_STEP2) == 0); - johan=(((u_int)ubauda)&0xffff)+8; - udacsr->udasa=johan; - while((udacsr->udasa&UDA_STEP3) == 0); - udacsr->udasa=3; - while((udacsr->udasa&UDA_STEP4) == 0); - udacsr->udasa=0x0001; - uda.uda_ca.ca_rspdsc=(int)&ubauda->uda_rsp.mscp_cmdref; - uda.uda_ca.ca_cmddsc=(int)&ubauda->uda_cmd.mscp_cmdref; + while ((*ra->ra_sa & MP_STEP1) == 0) + ; + + *ra->ra_sw = 0x8000; + while ((*ra->ra_sa & MP_STEP2) == 0) + ; + + *ra->ra_sw = johan; + while ((*ra->ra_sa & MP_STEP3) == 0) + ; + + *ra->ra_sw = johan2; + while ((*ra->ra_sa & MP_STEP4) == 0) + ; + + *ra->ra_sw = 0x0001; + uda.uda_ca.ca_rspdsc = (int)&ubauda->uda_rsp.mscp_cmdref; + uda.uda_ca.ca_cmddsc = (int)&ubauda->uda_cmd.mscp_cmdref; + command(M_OP_SETCTLRC); - uda.uda_cmd.mscp_unit=ra->unit; + uda.uda_cmd.mscp_unit = ra->unit; command(M_OP_ONLINE); - err=rastrategy(ra,F_READ, LABELSECTOR, DEV_BSIZE, io_buf, &i); + err = rastrategy(ra,F_READ, LABELSECTOR, DEV_BSIZE, io_buf, &i); if(err){ printf("reading disklabel: %s\n",strerror(err)); return 0; } - msg=getdisklabel(io_buf+LABELOFFSET, lp); - if(msg) { - printf("getdisklabel: %s\n",msg); - } - f->f_devdata=(void *)ra; + msg = getdisklabel(io_buf+LABELOFFSET, lp); + if (msg) + printf("getdisklabel: %s\n", msg); + f->f_devdata = (void *)ra; return(0); } @@ -136,13 +177,14 @@ command(cmd) { volatile int hej; - uda.uda_cmd.mscp_opcode=cmd; - uda.uda_cmd.mscp_msglen=MSCP_MSGLEN; - uda.uda_rsp.mscp_msglen=MSCP_MSGLEN; + uda.uda_cmd.mscp_opcode = cmd; + uda.uda_cmd.mscp_msglen = MSCP_MSGLEN; + uda.uda_rsp.mscp_msglen = MSCP_MSGLEN; uda.uda_ca.ca_rspdsc |= MSCP_OWN|MSCP_INT; uda.uda_ca.ca_cmddsc |= MSCP_OWN|MSCP_INT; - hej=udacsr->udaip; - while(uda.uda_ca.ca_rspdsc<0); + hej = *ra_softc.ra_ip; + while(uda.uda_ca.ca_rspdsc<0) + ; } @@ -161,20 +203,23 @@ rastrategy(ra, func, dblk, size, buf, rsize) volatile int hej; - ur = (void *)ra->ubaddr; - udadev = (void*)ra->udaddr; - ptmapp = (u_int *)&ur->uba_map[0]; - lp = &ralabel; + if (vax_cputype != VAX_8200) { + ur = (void *)ra->ubaddr; + udadev = (void*)ra->udaddr; + ptmapp = (u_int *)&ur->uba_map[0]; - pfnum = (u_int)buf >> PGSHIFT; + pfnum = (u_int)buf >> PGSHIFT; - for(mapnr = 0, nsize = size; (nsize + NBPG) > 0; nsize -= NBPG) - ptmapp[mapnr++] = PG_V | pfnum++; + for(mapnr = 0, nsize = size; (nsize + NBPG) > 0; nsize -= NBPG) + ptmapp[mapnr++] = PG_V | pfnum++; + uda.uda_cmd.mscp_seq.seq_buffer = ((u_int)buf) & 0x1ff; + } else + uda.uda_cmd.mscp_seq.seq_buffer = ((u_int)buf); + lp = &ralabel; uda.uda_cmd.mscp_seq.seq_lbn = dblk + lp->d_partitions[ra->part].p_offset; uda.uda_cmd.mscp_seq.seq_bytecount = size; - uda.uda_cmd.mscp_seq.seq_buffer = ((u_int)buf) & 0x1ff; uda.uda_cmd.mscp_unit = ra->unit; if (func == F_WRITE) command(M_OP_WRITE); diff --git a/sys/arch/vax/stand/rom.c b/sys/arch/vax/stand/rom.c new file mode 100644 index 00000000000..f299f506350 --- /dev/null +++ b/sys/arch/vax/stand/rom.c @@ -0,0 +1,123 @@ +/* $NetBSD: rom.c,v 1.1 1996/08/02 11:22:21 ragge Exp $ */ +/* + * Copyright (c) 1996 Ludd, University of Lule}, Sweden. + * All rights reserved. + * + * This code is derived from software contributed to Ludd by + * Bertram Barth. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed at Ludd, University of + * Lule}, Sweden and its contributors. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "sys/param.h" +#include "sys/reboot.h" +#include "sys/disklabel.h" + +#include "lib/libsa/stand.h" +#include "lib/libsa/ufs.h" + +#include "../include/pte.h" +#include "../include/sid.h" +#include "../include/mtpr.h" +#include "../include/reg.h" +#include "../include/rpb.h" + +#include "data.h" +#include "vaxstand.h" + +extern unsigned *bootregs; +extern struct rpb *rpb; + +struct rom_softc { + int part; + int unit; +}; + +int romstrategy(), romopen(); +struct disklabel romlabel; +struct rom_softc rom_softc; +char io_buf[MAXBSIZE]; + +romopen(f, adapt, ctlr, unit, part) + struct open_file *f; + int ctlr, unit, part; +{ + char *msg; + struct disklabel *lp = &romlabel; + volatile struct rom_softc *rsc = &rom_softc; + int i,err; + + bootregs[11] = XXRPB; + rpb = (void*)XXRPB; + bqo = (void*)rpb->iovec; + + if (rpb->unit > 0 && (rpb->unit % 100) == 0) { + printf ("changing rpb->unit from %d ", rpb->unit); + rpb->unit /= 100; + printf ("to %d\n", rpb->unit); + } + + bzero(lp, sizeof(struct disklabel)); + rsc->unit = unit; + rsc->part = part; + + err = romstrategy(rsc, F_READ, LABELSECTOR, DEV_BSIZE, io_buf, &i); + if (err) { + printf("reading disklabel: %s\n",strerror(err)); + return 0; + } + msg = getdisklabel(io_buf+LABELOFFSET, lp); + if (msg) + printf("getdisklabel: %s\n",msg); + f->f_devdata = (void*)rsc; + return(0); +} + +romstrategy (rsc, func, dblk, size, buf, rsize) + struct rom_softc *rsc; + int func; + daddr_t dblk; + char *buf; + int size, *rsize; +{ + struct disklabel *lp; + int block; + + lp = &romlabel; + block = dblk + lp->d_partitions[rsc->part].p_offset; + if (rsc->unit >= 0 && rsc->unit < 10) + rpb->unit = rsc->unit; + + if (func == F_WRITE) + romwrite_uvax(block, size, buf, bootregs); + else + romread_uvax(block, size, buf, bootregs); + + *rsize = size; + return 0; +} + diff --git a/sys/arch/vax/stand/romread.s b/sys/arch/vax/stand/romread.s index 966280792fb..ff893c4b6d9 100644 --- a/sys/arch/vax/stand/romread.s +++ b/sys/arch/vax/stand/romread.s @@ -1,4 +1,4 @@ -/* $NetBSD: romread.s,v 1.3 1995/09/16 16:20:18 ragge Exp $ */ +/* $NetBSD: romread.s,v 1.4 1996/08/02 11:22:24 ragge Exp $ */ /* * Copyright (c) 1995 Ludd, University of Lule}, Sweden. * All rights reserved. @@ -40,20 +40,6 @@ #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) */ ENTRY(read750, 0xFFE) @@ -72,9 +58,9 @@ ENTRY(read750, 0xFFE) ret /* - * bulkread630 (int lbn, int size, void *buf, int *regs) + * romread_uvax (int lbn, int size, void *buf, int *regs) */ -ENTRY(bulkread630, 0xFFE) +ENTRY(romread_uvax, 0xFFE) movl 16(ap), r11 # array of bootregs movl 44(r11), r11 # restore boot-contents of r11 (rpb) movl 52(r11), r7 # load iovec/bqo into r7 @@ -87,3 +73,21 @@ ENTRY(bulkread630, 0xFFE) pushl 12(ap) # buffer-address calls $6, (r6) # call the qio-routine ret # r0 holds the result + +/* + * romwrite_uvax (int lbn, int size, void *buf, int *regs) + */ +ENTRY(romwrite_uvax, 0xFFE) + movl 16(ap), r11 # array of bootregs + movl 44(r11), r11 # restore boot-contents of r11 (rpb) + movl 52(r11), r7 # load iovec/bqo into r7 + addl3 (r7), r7, r6 # load qio into r6 + pushl r11 # base of rpb + pushl $0 # virtual-flag + pushl $32 # write-logical-block + pushl 4(ap) # lbn to start reading + pushl 8(ap) # number of bytes to read + pushl 12(ap) # buffer-address + calls $6, (r6) # call the qio-routine + ret # r0 holds the result + diff --git a/sys/arch/vax/stand/samachdep.h b/sys/arch/vax/stand/samachdep.h new file mode 100644 index 00000000000..829a17d2b49 --- /dev/null +++ b/sys/arch/vax/stand/samachdep.h @@ -0,0 +1,42 @@ +/* $NetBSD: samachdep.h,v 1.1 1996/08/02 11:22:28 ragge Exp $ */ + +/* + * Copyright (c) 1982, 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)samachdep.h 8.1 (Berkeley) 6/10/93 + */ + +#define NSCSI 1 +#define NSD 8 + +extern int howto; +extern unsigned int bootdev; diff --git a/sys/arch/vax/stand/scsi_hi.c b/sys/arch/vax/stand/scsi_hi.c new file mode 100644 index 00000000000..0102123cc32 --- /dev/null +++ b/sys/arch/vax/stand/scsi_hi.c @@ -0,0 +1,297 @@ +/* $NetBSD: scsi_hi.c,v 1.1 1996/08/02 11:22:31 ragge Exp $ */ + +/**************************************************************************** + * NS32K Monitor SCSI high-level driver + * Bruce Culbertson + * 8 March 1990 + * (This source is public domain source) + * + * There are three monitor SCSI commands. "Read" and "write" I think are + * fairly self explanatory once you read the help messages. They, in fact, + * execute the "extended read", "extended write", and "request sense" + * commands from the SCSI standard. + * + * "Raw" lets you execute any SCSI command but you need a SCSI reference to + * know what the commands are and what their formats are. The SCSI + * standard specifies that there are six buffers which, for example, hold a + * SCSI command or are the source or destination for data. You provide + * "raw" with an array of pointers to the six buffers. Using "edit", you + * can enter a SCSI command somewhere in memory and you can create the + * array of pointers. The array must actually be eight entries long; two + * entries are not used. By typing "raw <array address>", the SCSI command + * is executed. + * + * By the way, "read", "write", and "raw" talk only to the DP8490 SCSI + * controller. I have not had time to read the Adaptec data sheet and + * write a driver for it. + ****************************************************************************/ +#include "so.h" + +#define OK 0 +#define NOT_OK OK+1 +#define PRIVATE +#define PUBLIC +#define U8 unsigned char + +long scsiAdr = DEFAULT_SCSI_ADR, /* default SCSI address */ + scsiLun = DEFAULT_SCSI_LUN; + +struct cmd_desc { /* SCSI command description */ + const U8 *cmd; /* command string */ + const U8 *odata; /* data to output, if any */ + const struct cmd_desc *chain; /* next command */ +}; + +struct drive { /* SCSI drive description */ + U8 adr, lun; /* SCSI address and LUN */ + U8 flags; /* drive characteristics */ + U8 stat; /* drive state */ + const struct cmd_desc *init; /* list of initialize commands */ +}; +/* for drive.flags */ +#define EXTENDED_RDWR 1 /* device does extended read, write */ +#define EXTENDED_SENSE 2 /* device does extended sense */ +/* for drive.stat */ +#define INITIALIZED 1 /* device is initialized */ + +PRIVATE struct drive drive_tbl[] = { +#if 1 + {0, 0, 0, 1, 0}, + {1, 0, 0, 1, 0}, + {2, 0, 0, 1, 0}, + {3, 0, 0, 1, 0}, + {4, 0, 0, 1, 0}, + {5, 0, 0, 1, 0}, + {6, 0, 0, 1, 0}, + {7, 0, 0, 1, 0}, +#else + {0, 0, EXTENDED_RDWR | EXTENDED_SENSE, 1, 0}, + {1, 0, EXTENDED_RDWR | EXTENDED_SENSE, 1, 0}, + {2, 0, EXTENDED_RDWR | EXTENDED_SENSE, 1, 0}, + {3, 0, EXTENDED_RDWR | EXTENDED_SENSE, 1, 0}, + {4, 0, EXTENDED_RDWR | EXTENDED_SENSE, 1, 0}, + {5, 0, EXTENDED_RDWR | EXTENDED_SENSE, 1, 0}, + {6, 0, EXTENDED_RDWR | EXTENDED_SENSE, 1, 0}, + {7, 0, EXTENDED_RDWR | EXTENDED_SENSE, 1, 0}, +#endif +}; +#define DRV_TBL_SZ (sizeof (drive_tbl) / sizeof (struct drive)) + +/* Round up to multiple of four since SCSI transfers are always multiples + * of four bytes. + */ +#define CMD_LEN 12 /* longest SCSI command */ +#define SENSE_LEN 24 /* extended sense length */ +#define MSG_LEN 4 +#define STAT_LEN 4 + +#define MAX_SCSI_RETRIES 6 +#define CMD_IX 2 +#define CMD_SENSE 0x03 +#define CMD_READ 0x08 +#define CMD_WRITE 0x0a +#define CMD_XREAD 0x28 +#define CMD_XWRITE 0x2a +PRIVATE U8 cmd_buf[CMD_LEN]; + +#define SENSE_KEY 2 +#define NO_SENSE 0 +#define RECOVERY_ERR 1 +#define UNIT_ATTN 6 +#define ADD_SENSE_CODE 12 +#define SENSE_RST 0x29 +PRIVATE U8 sense_buf[SENSE_LEN]; + +#define CHECK_CONDITION 2 +#define STAT_IX 3 +#define STAT_MASK 0x1f +PRIVATE U8 stat_buf[STAT_LEN]; +#define IMSG_IX 7 +PRIVATE U8 msg_buf[MSG_LEN]; + +#define ODATA_IX 0 +#define IDATA_IX 1 +PRIVATE struct scsi_args scsi_args; + +/*===========================================================================* + * sc_rdwt * + *===========================================================================*/ +/* Carry out a read or write request for the SCSI disk. */ +PRIVATE int +sc_rdwt(op, block, ram_adr, len, sc_adr, lun) +long block, ram_adr, len, sc_adr, lun; +{ + int retries, ret; + U8 *p; + struct drive *dp; + + printf ("sc_rdwt: op %x, block %d, ram %x, len %d, sc_adr %d, lun %d\n", + op, block, ram_adr, len, sc_adr, lun); + + /* get drive characteristics */ + for (dp = drive_tbl; dp < drive_tbl + DRV_TBL_SZ - 1; ++dp) + if (dp->adr == sc_adr && dp->lun == lun) break; + if (dp == drive_tbl + DRV_TBL_SZ - 1) { + dp->adr = sc_adr; /* have default, set adr, lun */ + dp->lun = lun; + } + for (retries = 0; retries < MAX_SCSI_RETRIES; ++retries) { + if (dp->init && !(dp->stat & INITIALIZED)) + if (OK != sc_initialize (dp)) { + printf("SCSI cannot initialize device\n"); + return NOT_OK; + } + p = cmd_buf; /* build SCSI command */ + if (dp->flags & EXTENDED_RDWR) { /* use extended commands */ + *p++ = (op == DISK_READ)? CMD_XREAD: CMD_XWRITE; + *p++ = lun << 5; + *p++ = (block >> 24) & 0xff; + *p++ = (block >> 16) & 0xff; + *p++ = (block >> 8) & 0xff; + *p++ = (block >> 0) & 0xff; + *p++ = 0; + *p++ = (len >> 8) & 0xff; + *p++ = (len >> 0) & 0xff; + *p = 0; + } else { /* use short (SASI) commands */ + *p++ = (op == DISK_READ)? CMD_READ: CMD_WRITE; + *p++ = (lun << 5) | ((block >> 16) & 0x1f); + *p++ = (block >> 8) & 0xff; + *p++ = (block >> 0) & 0xff; + *p++ = len; + *p = 0; + } + if (op == DISK_READ) + ret = exec_scsi_hi (cmd_buf, (U8 *)ram_adr, (U8 *)0, dp); + else + ret = exec_scsi_hi (cmd_buf, (U8 *)0, (U8 *)ram_adr, dp); + if (OK == ret) return OK; + dp->stat &= ~INITIALIZED; + } + printf("SCSI %s, block %d failed even after retries\n", + op == DISK_READ? "READ": "WRITE", block); + return NOT_OK; +} + +/*===========================================================================* + * sc_initialize * + *===========================================================================*/ +/* Execute the list of initialization commands for the given drive. + */ +int +sc_initialize (dp) +struct drive *dp; +{ + const struct cmd_desc *cp; + + for (cp = dp->init; cp != 0; cp = cp->chain) + if (OK != exec_scsi_hi (cp->cmd, 0, cp->odata, dp)) { + dp->stat &= ~INITIALIZED; + return NOT_OK; + } + dp->stat |= INITIALIZED; + return OK; +} + +/*===========================================================================* + * exec_scsi_hi * + *===========================================================================*/ +/* Execute a "high-level" SCSI command. This means execute a low level + * command and, if it fails, execute a request sense to find out why. + */ +PRIVATE int +exec_scsi_hi(cmd, data_in, data_out, dp) +U8 *cmd, *data_out, *data_in; +struct drive *dp; +{ + scsi_args.ptr[CMD_IX] = (long)cmd; + scsi_args.ptr[STAT_IX] = (long)stat_buf; + scsi_args.ptr[IMSG_IX] = (long)msg_buf; + scsi_args.ptr[IDATA_IX] = (long)data_in; + scsi_args.ptr[ODATA_IX] = (long)data_out; + if (OK != exec_scsi_low (&scsi_args, dp->adr)) + return NOT_OK; + *stat_buf &= STAT_MASK; /* strip off lun */ + if (*stat_buf == 0) + /* Success -- this should be the usual case */ + return OK; + if (*stat_buf != CHECK_CONDITION) { + /* do not know how to handle this so return error */ + printf("SCSI device returned unknown status: %d\n", *stat_buf); + return NOT_OK; + } + /* Something funny happened, need to execute request-sense command + * to learn more. + */ + if (OK == get_sense(dp)) + /* Something funny happened, but the device recovered from it and + * the command succeeded. + */ + return OK; + return NOT_OK; +} + +/*===========================================================================* + * get_sense * + *===========================================================================*/ +/* Execute a "request sense" SCSI command and check results. When a SCSI + * command returns CHECK_CONDITION, a request-sense command must be executed. + * A request-sense command provides information about the original command. + * The original command might have succeeded, in which case it does not + * need to be retried and OK is returned. Examples: read error corrected + * with error correction code, or error corrected by retries performed by + * the SCSI device. The original command also could have failed, in + * which case NOT_OK is returned. + */ +#define XLOGICAL_ADR \ + (sense_buf[3]<<24 | sense_buf[4]<<16 | sense_buf[5]<<8 | sense_buf[6]) +#define LOGICAL_ADR \ + (sense_buf[1]<<16 | sense_buf[2]<<8 | sense_buf[3]) + +PRIVATE int +get_sense (dp) +struct drive *dp; +{ + U8 *p; + + p = cmd_buf; /* build SCSI command */ + *p++ = CMD_SENSE; + *p++ = dp->lun << 5; + *p++ = 0; + *p++ = 0; + *p++ = (dp->flags & EXTENDED_SENSE)? SENSE_LEN: 0; + *p = 0; + scsi_args.ptr[IDATA_IX] = (long)sense_buf; + scsi_args.ptr[ODATA_IX] = 0; + scsi_args.ptr[CMD_IX] = (long)cmd_buf; + scsi_args.ptr[STAT_IX] = (long)stat_buf; + scsi_args.ptr[IMSG_IX] = (long)msg_buf; + if (OK != exec_scsi_low (&scsi_args, dp->adr)) { + printf("SCSI SENSE command failed\n"); + return NOT_OK; + } + if ((*stat_buf & STAT_MASK) != 0) { + printf("SCSI SENSE returned wrong status %d\n", *stat_buf); + return NOT_OK; + } + if (0 == (dp->flags & EXTENDED_SENSE)) { + printf("SCSI request sense, code 0x%x, log_adr 0x%x\n", + sense_buf[0], LOGICAL_ADR); + return NOT_OK; + } + switch (sense_buf[SENSE_KEY] & 0xf) { + case NO_SENSE: + case UNIT_ATTN: /* reset */ + return NOT_OK; /* must retry command */ + case RECOVERY_ERR: + /* eventually, we probably do not want to hear about these. */ + printf("SCSI ok with recovery, code 0x%x, logical address 0x%x\n", + sense_buf[ADD_SENSE_CODE], XLOGICAL_ADR); + return OK; /* orig command was ok with recovery */ + default: + printf("SCSI failure: key 0x%x code 0x%x log adr 0x%x sense buf 0x%x\n", + sense_buf[SENSE_KEY], sense_buf[ADD_SENSE_CODE], + XLOGICAL_ADR, sense_buf); + return NOT_OK; /* orig command failed */ + } +} diff --git a/sys/arch/vax/stand/scsi_low.c b/sys/arch/vax/stand/scsi_low.c new file mode 100644 index 00000000000..a86a82de7c9 --- /dev/null +++ b/sys/arch/vax/stand/scsi_low.c @@ -0,0 +1,479 @@ +/* $NetBSD: scsi_low.c,v 1.1 1996/08/02 11:22:34 ragge Exp $ */ + +/**************************************************************************** + * NS32K Monitor SCSI low-level driver + * Bruce Culbertson + * 8 March 1990 + * (This source is public domain source.) + * + * Originally written by Bruce Culbertson for a ns32016 port of Minix. + * Adapted from that for the pc532 (ns32632) monitor. + * Adapted from that for NetBSD/pc532 by Philip L. Bunde. + * + * Do not use DMA -- makes 32016 and pc532 versions compatible. + * Do not use interrupts -- makes it harder for the user code to bomb + * this code. + ****************************************************************************/ + +#include "so.h" +#include "ka410.h" + +#define BB_DEBUG(x) printf x +#define CLEAR_INTR() *ka410_intclr=INTR_SC +#define CHECK_INTR() *ka410_intreq&INTR_SC + +#define OK 0 +#define NOT_OK OK+1 +#define PRIVATE +#define PUBLIC +#define WR_ADR(adr,val) (*((volatile unsigned char *)(adr))=(val)) +#define RD_ADR(adr) (*((volatile unsigned char *)(adr))) +/* #define AIC6250 0 */ +/* #define DP8490 1 */ +#define MAX_CACHE 0x4000 + +/* SCSI bus phases + */ +#define PH_ODATA 0 +#define PH_IDATA 1 +#define PH_CMD 2 +#define PH_STAT 3 +#define PH_IMSG 7 +#define PH_NONE 8 +#define PH_IN(phase) ((phase) & 1) + +/* NCR5380 SCSI controller registers + */ +#define SC_CTL 0x200C0080 /* base for control registers */ +#define SC_DMA 0x200D0000 /* base for data registers (8/16K) */ +#define SC_CURDATA SC_CTL+(4*0) +#define SC_OUTDATA SC_CTL+(4*0) +#define SC_ICMD SC_CTL+(4*1) +#define SC_MODE SC_CTL+(4*2) +#define SC_TCMD SC_CTL+(4*3) +#define SC_STAT1 SC_CTL+(4*4) +#define SC_STAT2 SC_CTL+(4*5) +#define SC_START_SEND SC_CTL+(4*5) +#define SC_INDATA SC_CTL+(4*6) +#define SC_RESETIP SC_CTL+(4*7) +#define SC_START_RCV SC_CTL+(4*7) + +/* Bits in NCR5380 registers + */ +#define SC_A_RST 0x80 +#define SC_A_SEL 0x04 +#define SC_S_SEL 0x02 +#define SC_S_REQ 0x20 +#define SC_S_BSY 0x40 +#define SC_S_BSYERR 0x04 +#define SC_S_PHASE 0x08 +#define SC_S_IRQ 0x10 +#define SC_S_DRQ 0x40 +#define SC_M_DMA 0x02 +#define SC_M_BSY 0x04 +#define SC_ENABLE_DB 0x01 + +/* Status of interrupt routine, returned in m1_i1 field of message. + */ +#define ISR_NOTDONE 0 +#define ISR_OK 1 +#define ISR_BSYERR 2 +#define ISR_RSTERR 3 +#define ISR_BADPHASE 4 +#define ISR_TIMEOUT 5 + +#define ICU_ADR 0xfffffe00 +#define ICU_IO (ICU_ADR+20) +#define ICU_DIR (ICU_ADR+21) +#define ICU_DATA (ICU_ADR+19) +#define ICU_SCSI_BIT 0x80 + +/* Miscellaneous + */ +#define MAX_WAIT (1000*1000) +#define SC_LOG_LEN 32 + +PRIVATE struct scsi_args *sc_ptrs; +PRIVATE char sc_cur_phase, + sc_reset_done = 1, + sc_have_msg, + sc_accept_int, + sc_dma_dir; + +long sc_dma_port = SC_DMA, + sc_dma_adr; + +#ifdef DEBUG +struct sc_log { + unsigned char stat1, stat2; +} sc_log [SC_LOG_LEN], + *sc_log_head = sc_log; +int sc_spurious_int; +#endif +unsigned char + sc_watchdog_error; /* watch dog error */ + +/* error messages */ +char *scsi_errors[] = { + 0, /* ISR_NOTDONE */ + 0, /* ISR_OK */ + "busy error", /* ISR_BSYERR */ + "reset error", /* ISR_RSTERR */ + "NULL pointer for current phase", /* ISR_BADPHASE */ + "timeout", /* ISR_TIMEOUT */ +}; + +/*===========================================================================* + * exec_scsi_low * + *===========================================================================*/ +/* Execute a generic SCSI command. Passed pointers to eight buffers: + * data-out, data-in, command, status, dummy, dummy, message-out, message-in. + */ +PUBLIC +int +exec_scsi_low (args, scsi_adr) +struct scsi_args *args; +long scsi_adr; +{ + int ret; + + BB_DEBUG (("exec_scsi_low(0x%x, %d)\n", args, scsi_adr)); + + sc_ptrs = args; /* make pointers globally accessible */ + /* bertram ??? scCtlrSelect (DP8490); */ + if (!sc_reset_done) sc_reset(); + /* TCMD has some undocumented behavior in initiator mode. I think the + * data bus cannot be enabled if i/o is asserted. + */ + WR_ADR (SC_TCMD, 0); + if (OK != sc_wait_bus_free ()) { /* bus-free phase */ + printf("SCSI: bus not free\n"); + return NOT_OK; + } + sc_cur_phase = PH_NONE; + sc_have_msg = 0; + if (OK != sc_select (scsi_adr)) /* select phase */ + return NOT_OK; + sc_watchdog_error = 0; + ret = sc_receive (); /* isr does the rest */ + if (ret == ISR_OK) return OK; + else { + sc_reset(); + printf("SCSI: %s\n", scsi_errors[ret]); + return NOT_OK; + } +} + +/*===========================================================================* + * sc_reset * + *===========================================================================*/ +/* + * Reset SCSI bus. + */ +PRIVATE +sc_reset() +{ + volatile int i; + + BB_DEBUG (("sc_reset()\n")); + + WR_ADR (SC_MODE, 0); /* get into harmless state */ + WR_ADR (SC_OUTDATA, 0); + WR_ADR (SC_ICMD, SC_A_RST); /* assert RST on SCSI bus */ + i = 200; /* wait 25 usec */ + while (i--); + WR_ADR (SC_ICMD, 0); /* deassert RST, get off bus */ + sc_reset_done = 1; +} + +/*===========================================================================* + * sc_wait_bus_free * + *===========================================================================*/ +PRIVATE int +sc_wait_bus_free() +{ + int i = MAX_WAIT; + volatile int j; + + BB_DEBUG (("sc_wait_bus_free()\n")); + + while (i--) { + /* Must be clear for 2 usec, so read twice */ + if (RD_ADR (SC_STAT1) & (SC_S_BSY | SC_S_SEL)) continue; + for (j = 0; j < 25; ++j); + if (RD_ADR (SC_STAT1) & (SC_S_BSY | SC_S_SEL)) continue; + return OK; + } + sc_reset_done = 0; + return NOT_OK; +} + +/*===========================================================================* + * sc_select * + *===========================================================================*/ +/* This duplicates much of the work that the interrupt routine would do on a + * phase mismatch and, in fact, the original plan was to just do the select, + * let a phase mismatch occur, and let the interrupt routine do the rest. + * That didn't work because the 5380 did not reliably generate the phase + * mismatch interrupt after selection. + */ +PRIVATE int +sc_select(adr) +long adr; +{ + int i, stat1; + long new_ptr; + + BB_DEBUG (("sc_select(%d)\n", adr)); + + CLEAR_INTR(); + WR_ADR (SC_OUTDATA, adr); /* SCSI bus address */ + WR_ADR (SC_ICMD, SC_A_SEL | SC_ENABLE_DB); + for (i = 0;; ++i) { /* wait for target to assert SEL */ + if (CHECK_INTR() == 0) + continue; + stat1 = RD_ADR (SC_STAT1); + if (stat1 & SC_S_BSY) break; /* select successful */ + if (i > MAX_WAIT) { /* timeout */ + printf("SCSI: SELECT timeout\n"); + sc_reset(); + return NOT_OK; + } + } + CLEAR_INTR(); + WR_ADR (SC_ICMD, 0); /* clear SEL, disable data out */ + WR_ADR (SC_OUTDATA, 0); + for (i = 0;; ++i) { /* wait for target to assert REQ */ + if (CHECK_INTR() == 0) + continue; + if (stat1 & SC_S_REQ) break; /* target requesting transfer */ + if (i > MAX_WAIT) { /* timeout */ + printf("SCSI: REQ timeout\n"); + sc_reset(); + return NOT_OK; + } + stat1 = RD_ADR (SC_STAT1); + } + sc_cur_phase = (stat1 >> 2) & 7; /* get new phase from controller */ + if (sc_cur_phase != PH_CMD) { + printf("SCSI: bad phase = %d\n", sc_cur_phase); + sc_reset(); + return NOT_OK; + } + new_ptr = sc_ptrs->ptr[PH_CMD]; + if (new_ptr == 0) { + printf("SCSI: NULL command pointer\n"); + sc_reset(); + return NOT_OK; + } + sc_accept_int = 1; + sc_dma_setup (DISK_WRITE, new_ptr); + CLEAR_INTR(); + WR_ADR (SC_TCMD, PH_CMD); + WR_ADR (SC_ICMD, SC_ENABLE_DB); + WR_ADR (SC_MODE, SC_M_BSY | SC_M_DMA); + WR_ADR (SC_START_SEND, 0); + return OK; +} + +/*===========================================================================* + * scsi_interrupt * + *===========================================================================*/ +/* SCSI interrupt handler. + */ +PUBLIC +int +scsi_interrupt() +{ + unsigned char stat2, dummy; + long new_ptr; + int ret = ISR_NOTDONE; + + BB_DEBUG (("scsi_interrupt()\n")); + + stat2 = RD_ADR (SC_STAT2); /* get status before clearing request */ + +# ifdef DEBUG /* debugging log of interrupts */ + sc_log_head->stat1 = RD_ADR (SC_STAT1); + sc_log_head->stat2 = stat2; + if (++sc_log_head >= sc_log + SC_LOG_LEN) sc_log_head = sc_log; + sc_log_head->stat1 = sc_log_head->stat2 = 0xff; +# endif + + for (;;) { + dummy = RD_ADR (SC_RESETIP); /* clear interrupt request */ + if (!sc_accept_int || /* return if spurious interrupt */ + (!sc_watchdog_error && + (stat2 & SC_S_BSYERR) == 0 && (stat2 & SC_S_PHASE) != 0)) + { +# ifdef DEBUG + ++sc_spurious_int; +# endif + printf ("sc_spurious_int\n"); + return ret; + } + RD_ADR (SC_MODE) &= ~SC_M_DMA; /* clear DMA mode */ + WR_ADR (SC_ICMD, 0); /* disable data bus */ + if (sc_cur_phase != PH_NONE) { /* if did DMA, save the new pointer */ + new_ptr = sc_dma_adr; /* fetch new pointer from DMA cntlr */ + if (sc_cur_phase == PH_IMSG && /* have message? */ + new_ptr != sc_ptrs->ptr[PH_IMSG]) sc_have_msg = 1; + sc_ptrs->ptr[sc_cur_phase] = /* save pointer */ + new_ptr; + } + if (sc_watchdog_error) ret = ISR_TIMEOUT; + else if (stat2 & SC_S_BSYERR) { /* target deasserted BSY? */ + printf ("target deasserted BSY?\n"); + if (sc_have_msg) ret = ISR_OK; + else ret = ISR_BSYERR; + } else if (!(stat2 & SC_S_PHASE)) {/* if phase mismatch, setup new phase */ + printf ("phase mismatch\n"); + sc_cur_phase = /* get new phase from controller */ + (RD_ADR (SC_STAT1) >> 2) & 7; + new_ptr = sc_ptrs->ptr[sc_cur_phase]; + if (new_ptr == 0) ret = ISR_BADPHASE; + else { + WR_ADR (SC_TCMD, sc_cur_phase); /* write new phase into TCMD */ + if (PH_IN (sc_cur_phase)) { /* set DMA controller */ + sc_dma_setup (DISK_READ, new_ptr); + RD_ADR (SC_MODE) |= SC_M_DMA; + CLEAR_INTR(); + WR_ADR (SC_START_RCV, 0); /* tell SCSI to start DMA */ + } else { + sc_dma_setup (DISK_WRITE, new_ptr); + RD_ADR (SC_MODE) |= SC_M_DMA; + WR_ADR (SC_ICMD, SC_ENABLE_DB); + CLEAR_INTR(); + WR_ADR (SC_START_SEND, 0); + } + } + } else ret = ISR_RSTERR; + if (ret != ISR_NOTDONE) { /* if done, send message to task */ + sc_watchdog_error = 0; + sc_accept_int = 0; + WR_ADR (SC_MODE, 0); /* clear monbsy, dma */ + break; /* reti re-enables ints */ + } + if (0 == ((stat2 = /* check for another interrupt */ + RD_ADR (SC_STAT2)) & SC_S_IRQ)) + { + break; + } + } + return ret; +} + +/*===========================================================================* + * sc_dma_setup * + *===========================================================================*/ +/* Fake DMA setup. Just store pointers and direction in global variables. + * + * The pseudo-DMA is subtler than it looks because of the cache. + * + * 1) When accessing I/O devices through a cache, some mechanism is + * necessary to ensure you access the device rather than the cache. + * On the 32532, the IODEC signal is supposed to be asserted for I/O + * addresses to accomplish this. However, a bug makes this much + * slower than necessary and severely hurts pseudo-DMA performance. + * Hence, IODEC is not asserted for the SCSI DMA port. + * + * 2) Because of (1), we must devise our own method of forcing the + * SCSI DMA port to be read. 0x8000000 addresses have been decoded + * to all access this port. By always using new addresses to access + * the DMA port (wrapping only after reading MAX_CACHE bytes), we + * force cache misses and, hence, device reads. Since the cache + * is write-through, we do not need to worry about writes. + * + * 3) It is possible to miss the last few bytes of a transfer if + * bus transfer size is not considered. The loop in sc_receive() + * transfers data until the interrupt signal is asserted. If + * bytes are transferred, the attempt to move the first byte of a + * double word causes the whole word to be read into the cache. + * Then the byte is transferred. If reading the double word + * completed the SCSI transfer, then the loop exits since + * interrupt is asserted. However, the last few bytes have only + * been moved into the cache -- they have not been moved to the + * DMA destination. + * + * 4) It is also possible to miss the first few bytes of a transfer. + * If the address used to access pseudo-dma port is not double word + * aligned, the whole double word is read into the cache, and then + * data is moved from the middle of the word (i.e. something other + * than the first bytes read from the SCSI controller) by the + * pseudo-dma loop in sc_receive(). + */ +sc_dma_setup (dir, adr) +int dir; +long adr; +{ + BB_DEBUG (("sc_dma_setup(%d, %d)\n", dir, adr)); + + CLEAR_INTR(); + /* if (sc_dma_port > SC_DMA + MAX_CACHE) */ + sc_dma_port = SC_DMA; + sc_dma_dir = dir; + sc_dma_adr = adr; +} + +/*===========================================================================* + * sc_receive * + *===========================================================================*/ +/* Replacement for Minix receive(), which waits for a message. This code + * spins, waiting for data to transfer or interrupt requests to handle. + * See sc_dma_setup for details. + */ +int +sc_receive() +{ + int stat2, isr_ret; + int i, c; + + BB_DEBUG (("sc_receive()\n")); + + /* + * check the interrupt-flag and wait if it reappears... + */ + c = *ka410_intreq; + printf ("begin: %x/%x ", c, *ka410_intreq); + for (i=0; i<100; i++) { + if ((c = *ka410_intreq) & INTR_SC) + break; + printf (" %x ", c); + } + if (i==100) + printf ("timeout in sc_receive.\n"); + +#if 1 + for (;;) { + stat2 = RD_ADR (SC_STAT2); + if (stat2 & SC_S_IRQ) { + if (ISR_NOTDONE != (isr_ret = scsi_interrupt())) break; + } else if (stat2 & SC_S_DRQ) { /* test really not necessary on pc532 */ + if (sc_dma_dir == DISK_READ) + *((long *)sc_dma_adr)++ = *((volatile long *)sc_dma_port)++; + else *((volatile long *)sc_dma_port)++ = *((long *)sc_dma_adr)++; + } + } +#endif + printf ("isr_ret: %d (ISR_NOTDONE: %d)\n", isr_ret, ISR_NOTDONE); + return isr_ret; +} + +/*===========================================================================* + * scCtlrSelect + *===========================================================================*/ +/* Select a SCSI device. + */ +scCtlrSelect (ctlr) +int ctlr; +{ + BB_DEBUG (("scCtlrSelect()\n")); +#if 0 + RD_ADR (ICU_IO) &= ~ICU_SCSI_BIT; /* i/o, not port */ + RD_ADR (ICU_DIR) &= ~ICU_SCSI_BIT; /* output */ + if (ctlr == DP8490) + RD_ADR (ICU_DATA) &= ~ICU_SCSI_BIT; /* select = 0 for 8490 */ + else + RD_ADR (ICU_DATA) |= ICU_SCSI_BIT; /* select = 1 for AIC6250 */ +#endif +} diff --git a/sys/arch/vax/stand/sd.c b/sys/arch/vax/stand/sd.c new file mode 100644 index 00000000000..30b08c3ff57 --- /dev/null +++ b/sys/arch/vax/stand/sd.c @@ -0,0 +1,247 @@ +/* $NetBSD: sd.c,v 1.1 1996/08/02 11:22:36 ragge Exp $ */ + +/* + * Copyright (c) 1988 University of Utah. + * Copyright (c) 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Van Jacobson of Lawrence Berkeley Laboratory and the Systems + * Programming Group of the University of Utah Computer Science Department. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * from: Utah $Hdr: sd.c 1.9 92/12/21$ + * + * @(#)sd.c 8.1 (Berkeley) 6/10/93 + */ + +/* + * SCSI CCS disk driver + */ + +#include <sys/param.h> +#include <sys/disklabel.h> +#include "stand.h" +#include "samachdep.h" + +#define SC_DEBUG 1 /* bertram */ +#define SD_DEBUG 1 /* bertram */ + +/*----------------------------------------------------------------------*/ +int +scsialive(int ctlr) +{ + return 1; /* controller always alive! */ +} + +/* call functions in scsi_hi.c */ +#include "so.h" + +int +scsi_tt_read(ctlr, slave, buf, len, blk, nblk) + int ctlr, slave; + u_char *buf; + u_int len; + daddr_t blk; + u_int nblk; +{ +#ifdef SC_DEBUG +printf("scsi_tt_read: ctlr %d, slave %d, len %d, blk %d, nblk %d\n", + ctlr, slave, len, blk, nblk ); +#endif + if (sc_rdwt(DISK_READ, blk, buf, nblk, 1<<slave, 0) == 0) + return 0; + return -2; +} + +int +scsi_tt_write(ctlr, slave, buf, len, blk, nblk) + int ctlr, slave; + u_char *buf; + u_int len; + daddr_t blk; + u_int nblk; +{ +#ifdef SC_DEBUG +printf("scsi_tt_write: ctlr %d, slave %d, len %d, blk %d, nblk %d\n", + ctlr, slave, len, blk, nblk ); +#endif +#if 0 + if (sc_rdwt(DISK_WRITE, blk, buf, nblk, 1<<slave, 0) == 0) + return 0; +#endif + return -2; +} + +/*----------------------------------------------------------------------*/ + +struct sd_softc { + int sc_ctlr; + int sc_unit; + int sc_part; + char sc_retry; + char sc_alive; + struct disklabel sc_label; +} sd_softc[NSCSI][NSD]; + +#ifdef SD_DEBUG +int debug = SD_DEBUG; +#endif + +#define SDRETRY 2 + +sdinit(ctlr, unit) + int ctlr, unit; +{ + register struct sd_softc *ss = &sd_softc[ctlr][unit]; + + /* HP version does test_unit_ready + * followed by read_capacity to get blocksize + */ + ss->sc_alive = 1; + return (1); +} + +sdreset(ctlr, unit) + int ctlr, unit; +{ +} + +char io_buf[MAXBSIZE]; + +sdgetinfo(ss) + register struct sd_softc *ss; +{ + register struct disklabel *lp; + char *msg, *getdisklabel(); + int sdstrategy(), i, err; + + lp = &sd_softc[ss->sc_ctlr][ss->sc_unit].sc_label; + bzero((caddr_t)lp, sizeof *lp); + lp->d_secsize = DEV_BSIZE; + lp->d_secpercyl = 1; + lp->d_npartitions = MAXPARTITIONS; + lp->d_partitions[ss->sc_part].p_offset = 0; + lp->d_partitions[ss->sc_part].p_size = 0x7fffffff; + + if (err = sdstrategy(ss, F_READ, + LABELSECTOR, DEV_BSIZE, io_buf, &i) < 0) { + printf("sdgetinfo: sdstrategy error %d\n", err); + return 0; + } + + msg = getdisklabel(io_buf, lp); + if (msg) { + printf("sd(%d,%d,%d): %s\n", + ss->sc_ctlr, ss->sc_unit, ss->sc_part, msg); + return 0; + } + return(1); +} + +sdopen(f, ctlr, unit, part) + struct open_file *f; + int ctlr, unit, part; +{ + register struct sd_softc *ss; + register struct disklabel *lp; + +#ifdef SD_DEBUG + if (debug) + printf("sdopen: ctlr=%d unit=%d part=%d\n", + ctlr, unit, part); +#endif + + if (ctlr >= NSCSI || !scsialive(ctlr)) + return (EADAPT); + if (unit >= NSD) + return (ECTLR); + ss = &sd_softc[ctlr][unit]; /* XXX alloc()? keep pointers? */ + ss->sc_part = part; + ss->sc_unit = unit; + ss->sc_ctlr = ctlr; + if (!ss->sc_alive) { + if (!sdinit(ctlr, unit)) + return (ENXIO); + if (!sdgetinfo(ss)) + return (ERDLAB); + } + lp = &sd_softc[ctlr][unit].sc_label; + if (part >= lp->d_npartitions || lp->d_partitions[part].p_size == 0) + return (EPART); + + f->f_devdata = (void *)ss; + return (0); +} + +int +sdstrategy(ss, func, dblk, size, buf, rsize) + register struct sd_softc *ss; + int func; + daddr_t dblk; /* block number */ + u_int size; /* request size in bytes */ + char *buf; + u_int *rsize; /* out: bytes transferred */ +{ + register int ctlr = ss->sc_ctlr; + register int unit = ss->sc_unit; + register int part = ss->sc_part; + register struct partition *pp = &ss->sc_label.d_partitions[part]; + u_int nblk = size >> DEV_BSHIFT; + u_int blk = dblk + pp->p_offset; + char stat; + + if (size == 0) + return(0); + + ss->sc_retry = 0; + +#ifdef SD_DEBUG + if (debug) + printf("sdstrategy(%d,%d): size=%d blk=%d nblk=%d\n", + ctlr, unit, size, blk, nblk); +#endif + +retry: + if (func == F_READ) + stat = scsi_tt_read(ctlr, unit, buf, size, blk, nblk); + else + stat = scsi_tt_write(ctlr, unit, buf, size, blk, nblk); + if (stat) { + printf("sd(%d,%d,%d): block=%x, error=0x%x\n", + ctlr, unit, ss->sc_part, blk, stat); + if (++ss->sc_retry > SDRETRY) + return(EIO); + goto retry; + } + *rsize = size; + + return(0); +} diff --git a/sys/arch/vax/stand/so.h b/sys/arch/vax/stand/so.h new file mode 100644 index 00000000000..3ead2c8e14b --- /dev/null +++ b/sys/arch/vax/stand/so.h @@ -0,0 +1,57 @@ +/* $NetBSD: so.h,v 1.1 1996/08/02 11:22:41 ragge Exp $ */ + +#ifndef _SO_H_INCLUDE +#define _SO_H_INCLUDE + +/* Definitions for standalone I/O lib */ + +/* #define SCSI_POLLED 0x200C0080 */ +#define SCSI_DMA 0x200D0000 + +/* Which SCSI device to use by default */ +#define DEFAULT_SCSI_ADR 1 +#define DEFAULT_SCSI_LUN 0 + +/* Low level scsi operation codes */ +#define DISK_READ 3 +#define DISK_WRITE 4 + +/* The size of a disk block */ +#define DBLKSIZE 512 + +/* Some disk address that will never be used */ +#define INSANE_BADDR 0x800000 + +struct scsi_args { + long ptr [8]; +}; + +#ifndef NULL +#define NULL 0L +#endif + +/* + * The next macro defines where the "break" area in memory ends for + * malloc() and friends. The area between edata and this address will + * then be reserved and should not be used for anything else (or you will + * no doubt have big problems). Depending on where your program's end-of-data + * is, you may wish to locate this in such a way as to usurp a minimum + * amount of memory. + */ +#define BREAK_END_ADDR ((char *)0x400000) /* to 4MB */ + +/* Selectivly enable inline functions */ +#ifndef NO_INLINE +#define Inline inline +#else +#define Inline +#endif + +extern void fatal(), warn(); +extern long ulimit(int, long); +extern int brk(char *); +extern char *sbrk(int); + +extern int sc_rdwt(); + +#endif /* _SO_H_INCLUDE */ diff --git a/sys/arch/vax/stand/srt0.s b/sys/arch/vax/stand/srt0.s index 1fc8dfca8e3..bfe5acafe34 100644 --- a/sys/arch/vax/stand/srt0.s +++ b/sys/arch/vax/stand/srt0.s @@ -1,4 +1,4 @@ -/* $NetBSD: srt0.s,v 1.5 1996/03/07 23:27:10 ragge Exp $ */ +/* $NetBSD: srt0.s,v 1.6 1996/08/02 11:22:44 ragge Exp $ */ /* * Copyright (c) 1994 Ludd, University of Lule}, Sweden. * All rights reserved. @@ -58,7 +58,9 @@ _start: .globl _start 1: movl $relocated, (sp) # return-address on top of stack rsb # can be replaced with new address relocated: # now relocation is done !!! - calls $0,_main # Were here! + movl sp, _bootregs + calls $0, _setup + calls $0, _Xmain # Were here! halt # no return diff --git a/sys/arch/vax/stand/start.s b/sys/arch/vax/stand/start.s index 55b2fc0438a..51edf004a88 100644 --- a/sys/arch/vax/stand/start.s +++ b/sys/arch/vax/stand/start.s @@ -1,4 +1,4 @@ -/* $NetBSD: start.s,v 1.7 1996/02/02 19:08:33 mycroft Exp $ */ +/* $NetBSD: start.s,v 1.8 1996/08/02 11:22:47 ragge Exp $ */ /* * Copyright (c) 1995 Ludd, University of Lule}, Sweden. * All rights reserved. @@ -172,7 +172,8 @@ start_all: relocated: # now relocation is done !!! movl sp, _bootregs movl ap, _boothowto - calls $0, _main # call main() which is + calls $0, _setup + calls $0, _Xmain # call Xmain (gcc workaround)which is halt # not intended to return ... /* diff --git a/sys/arch/vax/stand/str.s b/sys/arch/vax/stand/str.s new file mode 100644 index 00000000000..685574e0371 --- /dev/null +++ b/sys/arch/vax/stand/str.s @@ -0,0 +1,70 @@ +/* $NetBSD: str.s,v 1.2 1996/08/02 16:18:40 ragge Exp $ */ +/* + * Copyright (c) 1996 Ludd, University of Lule}, Sweden. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed at Ludd, University of + * Lule}, Sweden and its contributors. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Small versions of the most common string functions not using any + * emulated instructions. + */ + +#include "../include/asm.h" + +ENTRY(strlen, 0); + movl 4(ap), r0 +1: tstb (r0)+ + bneq 1b + decl r0 + subl2 4(ap), r0 + ret + +ENTRY(strncmp, 0) + movl 12(ap), r3 + brb 5f + +ENTRY(strcmp, 0) + movl $250, r3 # max string len to compare +5: movl 4(ap), r2 + movl 8(ap), r1 + movl $1, r0 + +2: cmpb (r2),(r1)+ + bneq 1f # something differ + tstb (r2)+ + beql 4f # continue, strings unequal + decl r3 # max string len encountered? + bneq 2b + +4: clrl r0 # We are done, strings equal. + ret + +1: bgtr 3f + mnegl r0, r0 +3: ret diff --git a/sys/arch/vax/stand/tmscp.c b/sys/arch/vax/stand/tmscp.c index f5d0fe11879..b63022212f7 100644 --- a/sys/arch/vax/stand/tmscp.c +++ b/sys/arch/vax/stand/tmscp.c @@ -1,4 +1,4 @@ -/* $NetBSD: tmscp.c,v 1.2 1996/02/17 18:23:24 ragge Exp $ */ +/* $NetBSD: tmscp.c,v 1.3 1996/08/02 11:22:53 ragge Exp $ */ /* * Copyright (c) 1995 Ludd, University of Lule}, Sweden. * All rights reserved. @@ -43,7 +43,8 @@ #include "../include/macros.h" #include "../uba/ubareg.h" #include "../uba/udareg.h" -#include "../vax/mscp.h" +#include "../mscp/mscp.h" +#include "../mscp/mscpreg.h" #include "vaxstand.h" @@ -63,7 +64,7 @@ struct ra_softc { }; static volatile struct uda { - struct uda1ca uda_ca; /* communications area */ + struct mscp_1ca uda_ca; /* communications area */ struct mscp uda_rsp; /* response packets */ struct mscp uda_cmd; /* command packets */ } uda; @@ -100,14 +101,14 @@ tmscpopen(f, adapt, ctlr, unit, part) * Init of this tmscp ctlr. */ udacsr->udaip=0; /* Start init */ - while((udacsr->udasa&UDA_STEP1) == 0); + while((udacsr->udasa&MP_STEP1) == 0); udacsr->udasa=0x8000; - while((udacsr->udasa&UDA_STEP2) == 0); + while((udacsr->udasa&MP_STEP2) == 0); johan=(((u_int)ubauda)&0xffff)+8; udacsr->udasa=johan; - while((udacsr->udasa&UDA_STEP3) == 0); + while((udacsr->udasa&MP_STEP3) == 0); udacsr->udasa=3; - while((udacsr->udasa&UDA_STEP4) == 0); + while((udacsr->udasa&MP_STEP4) == 0); udacsr->udasa=0x0001; uda.uda_ca.ca_rspdsc=(int)&ubauda->uda_rsp.mscp_cmdref; diff --git a/sys/arch/vax/stand/vaxstand.h b/sys/arch/vax/stand/vaxstand.h index f3217fdb235..2d068b9d6d9 100644 --- a/sys/arch/vax/stand/vaxstand.h +++ b/sys/arch/vax/stand/vaxstand.h @@ -1,4 +1,4 @@ -/* $NetBSD: vaxstand.h,v 1.4 1996/02/17 18:23:25 ragge Exp $ */ +/* $NetBSD: vaxstand.h,v 1.5 1996/08/02 11:22:56 ragge Exp $ */ /* * Copyright (c) 1994 Ludd, University of Lule}, Sweden. * All rights reserved. @@ -34,13 +34,12 @@ #define MAXNMBA 8 /* Massbussadapters */ #define MAXNUBA 8 /* Unibusadapters */ -#define MAXNBI 4 /* Bi-bussadapters */ #define MAXMBAU 8 /* Units on an mba */ -#define MAXBIN 16 /* Bi-nodes */ /* Variables used in autoconf */ extern int nmba, nuba, nbi, nsbi, nuda; -extern int *ubaaddr, *mbaaddr, *udaaddr, *uioaddr; +extern int *ubaaddr, *mbaaddr, *udaaddr, *uioaddr, *biaddr; +extern int cpunumber; /* devsw type definitions, used in bootxx and conf */ #define SADEV(name,strategy,open,close,ioctl) \ @@ -50,3 +49,17 @@ extern int *ubaaddr, *mbaaddr, *udaaddr, *uioaddr; (int(*)(struct open_file *))close, \ (int(*)(struct open_file *,u_long, void *))ioctl} +/* + * Easy-to-use definitions + */ +#define min(x,y) (x < y ? x : y) + +/* + * Device numbers gotten from boot prom. + */ +#define BDEV_MBA 0 +#define BDEV_RK06 1 +#define BDEV_RL02 2 +#define BDEV_UDA 17 +#define BDEV_TK50 18 +#define BDEV_CONSOLE 64 diff --git a/sys/arch/vax/uba/dhu.c b/sys/arch/vax/uba/dhu.c index 8dcf6236d7f..10ade80d77d 100644 --- a/sys/arch/vax/uba/dhu.c +++ b/sys/arch/vax/uba/dhu.c @@ -1,4 +1,4 @@ -/* $NetBSD: dhu.c,v 1.5 1996/05/19 16:27:02 ragge Exp $ */ +/* $NetBSD: dhu.c,v 1.9 1997/01/11 11:34:41 ragge Exp $ */ /* * Copyright (c) 1996 Ken C. Wellsch. All rights reserved. * Copyright (c) 1992, 1993 @@ -132,7 +132,7 @@ static unsigned dhumctl __P((struct dhu_softc *,int, int, int)); int dhuread __P((dev_t, struct uio *, int)); int dhuwrite __P((dev_t, struct uio *, int)); int dhuioctl __P((dev_t, u_long, caddr_t, int, struct proc *)); - int dhustop __P((struct tty *, int)); + void dhustop __P((struct tty *, int)); struct tty * dhutty __P((dev_t)); struct cfdriver dhu_cd = { @@ -376,9 +376,9 @@ dhuopen(dev, flag, mode, p) sc->sc_dhu[line].dhu_state = STATE_IDLE; - sc->sc_dhu[line].dhu_txaddr = uballoc( - sc->sc_dev.dv_parent->dv_unit, - tp->t_outq.c_cs, tp->t_outq.c_cn, 0); + sc->sc_dhu[line].dhu_txaddr = + uballoc((struct uba_softc *)sc->sc_dev.dv_parent, + tp->t_outq.c_cs, tp->t_outq.c_cn, 0); dhuaddr = sc->sc_addr; @@ -561,7 +561,7 @@ dhutty(dev) } /*ARGSUSED*/ -int +void dhustop(tp, flag) register struct tty *tp; { @@ -590,7 +590,6 @@ dhustop(tp, flag) tp->t_state |= TS_FLUSH; } (void) splx(s); - return 0; } static void diff --git a/sys/arch/vax/uba/dz.c b/sys/arch/vax/uba/dz.c index f1636b7f3ef..bc583be03c1 100644 --- a/sys/arch/vax/uba/dz.c +++ b/sys/arch/vax/uba/dz.c @@ -1,4 +1,4 @@ -/* $NetBSD: dz.c,v 1.1 1996/04/08 17:22:20 ragge Exp $ */ +/* $NetBSD: dz.c,v 1.4 1996/10/13 03:35:15 christos Exp $ */ /* * Copyright (c) 1996 Ken C. Wellsch. All rights reserved. * Copyright (c) 1992, 1993 @@ -121,7 +121,7 @@ struct tty * dztty __P((dev_t)); int dzread __P((dev_t, struct uio *, int)); int dzwrite __P((dev_t, struct uio *, int)); int dzioctl __P((dev_t, int, caddr_t, int, struct proc *)); - int dzstop __P((struct tty *, int)); + void dzstop __P((struct tty *, int)); struct cfdriver dz_cd = { NULL, "dz", DV_TTY @@ -547,8 +547,8 @@ dztty (dev) } /*ARGSUSED*/ -int -dzstop (tp, flag) +void +dzstop(tp, flag) register struct tty *tp; { register struct dz_softc *sc; @@ -560,14 +560,12 @@ dzstop (tp, flag) s = spltty(); - if (tp->t_state & TS_BUSY) - { + if (tp->t_state & TS_BUSY) { sc->sc_dz[line].dz_end = sc->sc_dz[line].dz_mem; if (!(tp->t_state & TS_TTSTOP)) tp->t_state |= TS_FLUSH; } (void) splx(s); - return 0; } static void diff --git a/sys/arch/vax/uba/qd.c b/sys/arch/vax/uba/qd.c new file mode 100644 index 00000000000..71acc0792cc --- /dev/null +++ b/sys/arch/vax/uba/qd.c @@ -0,0 +1,3611 @@ +/* $NetBSD: qd.c,v 1.4 1996/10/13 03:35:17 christos Exp $ */ + +/*- + * Copyright (c) 1988 Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)qd.c 7.1 (Berkeley) 6/28/91 + */ + +/************************************************************************ +* * +* Copyright (c) 1985-1988 by * +* Digital Equipment Corporation, Maynard, MA * +* All rights reserved. * +* * +* This software is furnished under a license and may be used and * +* copied only in accordance with the terms of such license and * +* with the inclusion of the above copyright notice. This * +* software or any other copies thereof may not be provided or * +* otherwise made available to any other person. No title to and * +* ownership of the software is hereby transferred. * +* * +* The information in this software is subject to change without * +* notice and should not be construed as a commitment by Digital * +* Equipment Corporation. * +* * +* Digital assumes no responsibility for the use or reliability * +* of its software on equipment which is not supplied by Digital. * +* * +*************************************************************************/ + +/* + * qd.c - QDSS display driver for VAXSTATION-II GPX workstation + */ + +#include "qd.h" + +#if NQD > 0 +#include "../include/pte.h" +#include "../include/mtpr.h" +#include "sys/param.h" +#include "../include/cpu.h" +#include "sys/conf.h" +#include "sys/user.h" +#include "qdioctl.h" +#include "sys/tty.h" +#include "sys/map.h" +#include "sys/buf.h" +#include "sys/vm.h" +#include "sys/clist.h" +#include "sys/file.h" +#include "sys/uio.h" +#include "sys/kernel.h" +#include "sys/exec.h" +#include "sys/proc.h" +#include "ubareg.h" +#include "ubavar.h" +#include "sys/syslog.h" +#include "qduser.h" /* definitions shared with user level client */ +#include "qdreg.h" /* QDSS device register structures */ + +/* + * QDSS driver status flags for tracking operational state + */ +struct qdflags { + u_int inuse; /* which minor dev's are in use now */ + u_int config; /* I/O page register content */ + u_int mapped; /* user mapping status word */ + u_int kernel_loop; /* if kernel console is redirected */ + u_int user_dma; /* DMA from user space in progress */ + u_short pntr_id; /* type code of pointing device */ + u_short duart_imask; /* shadowing for duart intrpt mask reg */ + u_short adder_ie; /* shadowing for adder intrpt enbl reg */ + u_short curs_acc; /* cursor acceleration factor */ + u_short curs_thr; /* cursor acceleration threshold level */ + u_short tab_res; /* tablet resolution factor */ + u_short selmask; /* mask for active qd select entries */ +}; + +/* + * bit definitions for 'inuse' entry + */ +#define CONS_DEV 0x01 +#define GRAPHIC_DEV 0x04 + +/* + * bit definitions for 'mapped' member of flag structure + */ +#define MAPDEV 0x01 /* hardware is mapped */ +#define MAPDMA 0x02 /* DMA buffer mapped */ +#define MAPEQ 0x04 /* event queue buffer mapped */ +#define MAPSCR 0x08 /* scroll param area mapped */ +#define MAPCOLOR 0x10 /* color map writing buffer mapped */ + +/* + * bit definitions for 'selmask' member of qdflag structure + */ +#define SEL_READ 0x01 /* read select is active */ +#define SEL_WRITE 0x02 /* write select is active */ + +/* + * constants used in shared memory operations + */ +#define EVENT_BUFSIZE 1024 /* # of bytes per device's event buffer */ +#define MAXEVENTS ( (EVENT_BUFSIZE - sizeof(struct qdinput)) \ + / sizeof(struct _vs_event) ) +#define DMA_BUFSIZ (1024 * 10) +#define COLOR_BUFSIZ ((sizeof(struct color_buf) + 512) & ~0x01FF) + +/* + * reference to an array of "uba_device" structures built by the auto + * configuration program. The uba_device structure decribes the device + * sufficiently for the driver to talk to it. The auto configuration code + * fills in the uba_device structures (located in ioconf.c) from user + * maintained info. + */ +struct uba_device *qdinfo[NQD]; /* array of pntrs to each QDSS's */ +struct tty qd_tty[NQD*4]; /* teletype structures for each.. */ +extern char qvmem[][128*NBPG]; +extern struct pte QVmap[][128]; +#define CHUNK (64 * 1024) +#define QMEMSIZE (1024 * 1024 * 4) /* 4 meg */ + +/* + * static storage used by multiple functions in this code + */ +int Qbus_unmap[NQD]; /* Qbus mapper release code */ +struct qdflags qdflags[NQD]; /* QDSS device status flags */ +struct qdmap qdmap[NQD]; /* QDSS register map structure */ +caddr_t qdbase[NQD]; /* base address of each QDSS unit */ +struct buf qdbuf[NQD]; /* buf structs used by strategy */ +short qdopened[NQD]; /* graphics device is open exclusive use */ + +/* + * the array "event_shared[]" is made up of a number of event queue buffers + * equal to the number of QDSS's configured into the running kernel (NQD). + * Each event queue buffer begins with an event queue header (struct qdinput) + * followed by a group of event queue entries (struct _vs_event). The array + * "*eq_header[]" is an array of pointers to the start of each event queue + * buffer in "event_shared[]". + */ +#define EQSIZE ((EVENT_BUFSIZE * NQD) + 512) + +char event_shared[EQSIZE]; /* reserve space for event bufs */ +struct qdinput *eq_header[NQD]; /* event queue header pntrs */ + +/* + * This allocation method reserves enough memory pages for NQD shared DMA I/O + * buffers. Each buffer must consume an integral number of memory pages to + * guarantee that a following buffer will begin on a page boundary. Also, + * enough space is allocated so that the FIRST I/O buffer can start at the + * 1st page boundary after "&DMA_shared". Page boundaries are used so that + * memory protections can be turned on/off for individual buffers. + */ +#define IOBUFSIZE ((DMA_BUFSIZ * NQD) + 512) + +char DMA_shared[IOBUFSIZE]; /* reserve I/O buffer space */ +struct DMAreq_header *DMAheader[NQD]; /* DMA buffer header pntrs */ + +/* + * The driver assists a client in scroll operations by loading dragon + * registers from an interrupt service routine. The loading is done using + * parameters found in memory shrade between the driver and it's client. + * The scroll parameter structures are ALL loacted in the same memory page + * for reasons of memory economy. + */ +char scroll_shared[2 * 512]; /* reserve space for scroll structs */ +struct scroll *scroll[NQD]; /* pointers to scroll structures */ + +/* + * the driver is programmable to provide the user with color map write + * services at VSYNC interrupt time. At interrupt time the driver loads + * the color map with any user-requested load data found in shared memory + */ +#define COLOR_SHARED ((COLOR_BUFSIZ * NQD) + 512) + +char color_shared[COLOR_SHARED]; /* reserve space: color bufs */ +struct color_buf *color_buf[NQD]; /* pointers to color bufs */ + +/* + * mouse input event structures + */ +struct mouse_report last_rep[NQD]; +struct mouse_report current_rep[NQD]; + +struct proc *qdrsel[NQD]; /* process waiting for select */ +struct _vs_cursor cursor[NQD]; /* console cursor */ +int qdcount = 0; /* count of successfully probed qd's */ +int nNQD = NQD; +int DMAbuf_size = DMA_BUFSIZ; +int QDlast_DMAtype; /* type of the last DMA operation */ + +#define QDSSMAJOR 41 /* QDSS major device number */ +/* + * macro to get system time. Used to time stamp event queue entries + */ +#define TOY ((time.tv_sec * 100) + (time.tv_usec / 10000)) + +int qdprobe(); +int qdattach(); +int qddint(); /* DMA gate array intrpt service */ +int qdaint(); /* Dragon ADDER intrpt service */ +int qdiint(); + +u_short qdstd[] = { 0 }; + +struct uba_driver qddriver = { + qdprobe, /* device probe entry */ + 0, /* no slave device */ + qdattach, /* device attach entry */ + 0, /* no "fill csr/ba to start" */ + qdstd, /* device addresses */ + "qd", /* device name string */ + qdinfo /* ptr to QDSS's uba_device struct */ +}; + +#define QDPRIOR (PZERO-1) /* must be negative */ +#define FALSE 0 +#define TRUE ~FALSE +#define BAD -1 +#define GOOD 0 + +/* + * macro to create a system virtual page number from system virtual adrs + */ +#define VTOP(x) (((int)x & ~0xC0000000) >> PGSHIFT) + +/* + * QDSS register address offsets from start of QDSS address space + */ +#define QDSIZE (52 * 1024) /* size of entire QDSS foot print */ +#define TMPSIZE (16 * 1024) /* template RAM is 8k SHORT WORDS */ +#define TMPSTART 0x8000 /* offset of template RAM from base adrs */ +#define REGSIZE (5 * 512) /* regs touch 2.5k (5 pages) of addr space */ +#define REGSTART 0xC000 /* offset of reg pages from base adrs */ +#define ADDER (REGSTART+0x000) +#define DGA (REGSTART+0x200) +#define DUART (REGSTART+0x400) +#define MEMCSR (REGSTART+0x800) +#define CLRSIZE (3 * 512) /* color map size */ +#define CLRSTART (REGSTART+0xA00) /* color map start offset from base */ +/* 0x0C00 really */ +#define RED (CLRSTART+0x000) +#define BLUE (CLRSTART+0x200) +#define GREEN (CLRSTART+0x400) + + +/* + * QDSS minor device numbers. The *real* minor device numbers are in + * the bottom two bits of the major/minor device spec. Bits 2 and up are + * used to specify the QDSS device number (ie: which one?) + */ + +#define CONS 0 +#define GRAPHIC 2 + +/* + * console cursor bitmap (white block cursor) + */ +short cons_cursor[32] = { + /* A */ 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, + 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, + /* B */ 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, + 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF +}; + +/* + * constants used in font operations + */ +#define CHARS 190 /* # of chars in the font */ +#define CHAR_HEIGHT 15 /* char height in pixels */ +#define CHAR_WIDTH 8 /* char width in pixels*/ +#define FONT_WIDTH (CHAR_WIDTH * CHARS) /* font width in pixels */ +#define ROWS CHAR_HEIGHT +#define FONT_X 0 /* font's off screen adrs */ +#define FONT_Y (2048 - CHAR_HEIGHT) + +/* Offset to second row characters (XXX - should remove) */ +#define FONT_OFFSET ((MAX_SCREEN_X/CHAR_WIDTH)*CHAR_HEIGHT) + +extern char q_font[]; /* reference font object code */ +extern u_short q_key[]; /* reference key xlation tables */ +extern u_short q_shift_key[]; +extern char *q_special[]; + +/* + * definitions for cursor acceleration reporting + */ +#define ACC_OFF 0x01 /* acceleration is inactive */ + +/* + * virtual console support. + */ +extern (*v_putc)(); +#ifdef KADB +extern (*v_getc)(); +extern (*v_poll)(); +#endif +extern struct cdevsw *consops; +int qdputc(); +int qdgetc(); +int qdpoll(); +int qdstart(); +int qdpolling = 0; + +/* + * LK-201 state storage for input console keyboard conversion to ASCII + */ +struct q_keyboard { + int shift; /* state variables */ + int cntrl; + int lock; + int lastcode; /* last keycode typed */ + unsigned kup[8]; /* bits for each keycode*/ + unsigned dkeys[8]; /* down/up mode keys */ + char last; /* last character */ +} q_keyboard; + +/* + * tty settings on first open + */ +#define IFLAG (BRKINT|ISTRIP|IXON|IXANY|ICRNL|IMAXBEL) +#define OFLAG (OPOST|OXTABS|ONLCR) +#define LFLAG (ISIG|ICANON|ECHO|IEXTEN) +#define CFLAG (PARENB|CREAD|CS7|CLOCAL) + +/* + * Init QDSS as console (before probe routine) + */ + +qdcons_init() +{ + register unit; + caddr_t phys_adr; /* physical QDSS base adrs */ + u_int mapix; /* index into QVmap[] array */ + struct percpu *pcpu; /* pointer to cpusw structure */ + register struct qbus *qb; + u_short *qdaddr; /* address of QDSS IO page CSR */ + u_short *devptr; /* vitual device space */ + extern cnputc(); + +#define QDSSCSR 0x1F00 + + if (v_putc != cnputc) + return 0; + + unit = 0; + + /* + * find the cpusw entry that matches this machine. + */ + for (pcpu = percpu; pcpu && pcpu->pc_cputype != cpu; pcpu++) + ; + if (pcpu == NULL) + return 0; + if (pcpu->pc_io->io_type != IO_QBUS) + return 0; + + /* + * Map device registers - the last 8K of qvmem. + */ + qb = (struct qbus *)pcpu->pc_io->io_details; + ioaccess(qb->qb_iopage, UMEMmap[0] + qb->qb_memsize, + UBAIOPAGES * NBPG); + devptr = (u_short *)((char *)umem[0]+(qb->qb_memsize * NBPG)); + qdaddr = (u_short *)((u_int)devptr + ubdevreg(QDSSCSR)); + if (badaddr((caddr_t)qdaddr, sizeof(short))) + return 0; + + /* + * Map q-bus memory used by qdss. (separate map) + */ + mapix = QMEMSIZE - (CHUNK * (unit + 1)); + phys_adr = qb->qb_maddr + mapix; + ioaccess(phys_adr, QVmap[0], (CHUNK*NQD)); + + /* + * tell QDSS which Q memory address base to decode + * (shifted right 16 bits - its in 64K units) + */ + *qdaddr = (u_short)((int)mapix >> 16); + qdflags[unit].config = *(u_short *)qdaddr; + + /* + * load qdmap struct with the virtual addresses of the QDSS elements + */ + qdbase[unit] = (caddr_t) (qvmem[0]); + qdmap[unit].template = qdbase[unit] + TMPSTART; + qdmap[unit].adder = qdbase[unit] + ADDER; + qdmap[unit].dga = qdbase[unit] + DGA; + qdmap[unit].duart = qdbase[unit] + DUART; + qdmap[unit].memcsr = qdbase[unit] + MEMCSR; + qdmap[unit].red = qdbase[unit] + RED; + qdmap[unit].blue = qdbase[unit] + BLUE; + qdmap[unit].green = qdbase[unit] + GREEN; + + qdflags[unit].duart_imask = 0; /* init shadow variables */ + + /* + * init the QDSS + */ + /* + printf("qdbase[0] = %x, qdmap[0].memcsr = %x\n", + (char *)qdbase[0], qdmap[0].memcsr); + */ + + *(short *)qdmap[unit].memcsr |= SYNC_ON; /* once only: turn on sync */ + + cursor[unit].x = 0; + cursor[unit].y = 0; + init_shared(unit); /* init shared memory */ + setup_dragon(unit); /* init the ADDER/VIPER stuff */ + clear_qd_screen(unit); /* clear the screen */ + ldfont(unit); /* load the console font */ + ldcursor(unit, cons_cursor); /* load default cursor map */ + setup_input(unit); /* init the DUART */ + v_putc = qdputc; /* kernel console output to qdss */ +#ifdef KADB + v_getc = qdgetc; /* kernel console input from qdss */ + v_poll = qdpoll; /* kdb hook to disable char intr */ +#endif + consops = &cdevsw[QDSSMAJOR]; /* virtual console is qdss */ + return 1; + +} /* qdcons_init */ + +/* + * Configure QDSS into Q memory and make it intrpt. + * + * side effects: QDSS gets mapped into Qbus memory space at the first + * vacant 64kb boundary counting back from the top of + * Qbus memory space (qvmem+4mb) + * + * return: QDSS bus request level and vector address returned in + * registers by UNIX convention. + * + */ +qdprobe(reg) + caddr_t reg; /* character pointer to the QDSS I/O page register */ +{ + register int br, cvec; + register int unit; + struct dga *dga; /* pointer to gate array structure */ + int vector; +#ifdef notdef + int *ptep; /* page table entry pointer */ + caddr_t phys_adr; /* physical QDSS base adrs */ + u_int mapix; +#endif + +#ifdef lint + br = 0; cvec = br; br = cvec; nNQD = br; br = nNQD; + qddint(0); qdaint(0); qdiint(0); (void)qdgetc(); +#endif + + /* + * calculate board unit number from I/O page register address + */ + unit = (int) (((int)reg >> 1) & 0x0007); + + /* + * QDSS regs must be mapped to Qbus memory space at a 64kb + * physical boundary. The Qbus memory space is mapped into + * the system memory space at config time. After config + * runs, "qvmem[0]" (ubavar.h) holds the system virtual adrs + * of the start of Qbus memory. The Qbus memory page table + * is found via an array of pte ptrs called "QVmap[]" (ubavar.h) + * which is also loaded at config time. These are the + * variables used below to find a vacant 64kb boundary in + * Qbus memory, and load it's corresponding physical adrs + * into the QDSS's I/O page CSR. + */ + + /* + * Only if QD is the graphics device. + */ + + /* if this QDSS is NOT the console, then do init here.. */ + + if (unit != 0) { + printf("qd: can't support two qdss's (yet)\n"); +#ifdef notdef /* can't test */ + if (v_consputc != qdputc || unit != 0) { + + /* + * read QDSS config info + */ + qdflags[unit].config = *(u_short *)reg; + + /* + * find an empty 64kb adrs boundary + */ + + qdbase[unit] = (caddr_t) (qvmem[0] + QMEMSIZE - CHUNK); + + /* + * find the cpusw entry that matches this machine. + */ + cpup = &cpusw[cpu]; + while (!(BADADDR(qdbase[unit], sizeof(short)))) + qdbase[unit] -= CHUNK; + + /* + * tell QDSS which Q memory address base to decode + */ + mapix = (int) (VTOP(qdbase[unit]) - VTOP(qvmem[0])); + ptep = (int *) QVmap[0] + mapix; + phys_adr = (caddr_t)(((int)*ptep&0x001FFFFF)<<PGSHIFT); + *(u_short *)reg = (u_short) ((int)phys_adr >> 16); + + /* + * load QDSS adrs map with system addresses + * of device regs + */ + qdmap[unit].template = qdbase[unit] + TMPSTART; + qdmap[unit].adder = qdbase[unit] + ADDER; + qdmap[unit].dga = qdbase[unit] + DGA; + qdmap[unit].duart = qdbase[unit] + DUART; + qdmap[unit].memcsr = qdbase[unit] + MEMCSR; + qdmap[unit].red = qdbase[unit] + RED; + qdmap[unit].blue = qdbase[unit] + BLUE; + qdmap[unit].green = qdbase[unit] + GREEN; + + /* device init */ + + cursor[unit].x = 0; + cursor[unit].y = 0; + init_shared(unit); /* init shared memory */ + setup_dragon(unit); /* init the ADDER/VIPER stuff */ + ldcursor(unit, cons_cursor); /* load default cursor map */ + setup_input(unit); /* init the DUART */ + clear_qd_screen(unit); + ldfont(unit); /* load the console font */ + + /* once only: turn on sync */ + + *(short *)qdmap[unit].memcsr |= SYNC_ON; + } +#endif /*notdef*/ + } + + /* + * The QDSS interrupts at HEX vectors xx0 (DMA) xx4 + * (ADDER) and xx8 (DUART). Therefore, we take three + * vectors from the vector pool, and then continue + * to take them until we get a xx0 HEX vector. The + * pool provides vectors in contiguous decending + * order. + */ + + vector = (uba_hd[0].uh_lastiv -= 4*3); /* take three vectors */ + + while (vector & 0x0F) { /* if lo nibble != 0.. */ + /* ..take another vector */ + vector = (uba_hd[0].uh_lastiv -= 4); + } + + /* + * setup DGA to do a DMA interrupt (transfer count = 0) + */ + dga = (struct dga *) qdmap[unit].dga; + dga->csr = (short) HALT; /* disable everything */ + dga->ivr = (short) vector; /* load intrpt base vector */ + dga->bytcnt_lo = (short) 0; /* DMA xfer count = 0 */ + dga->bytcnt_hi = (short) 0; + + /* + * turn on DMA interrupts + */ + dga->csr &= ~SET_DONE_FIFO; + dga->csr |= DMA_IE | DL_ENB; + + DELAY(20000); /* wait for the intrpt */ + dga->csr = HALT; /* stop the wheels */ + + if (cvec != vector) /* if vector != base vector.. */ + return(0); /* ..return = 'no device' */ + + /* + * score this as an existing qdss + */ + qdcount++; + + return(sizeof(short)); /* return size of QDSS I/O page reg */ + +} /* qdprobe */ + +qdattach(ui) + struct uba_device *ui; +{ + register unit; /* QDSS module # for this call */ + + unit = ui->ui_unit; /* get QDSS number */ + + /* + * init "qdflags[]" for this QDSS + */ + qdflags[unit].inuse = 0; /* init inuse variable EARLY! */ + qdflags[unit].mapped = 0; + qdflags[unit].kernel_loop = -1; + qdflags[unit].user_dma = 0; + qdflags[unit].curs_acc = ACC_OFF; + qdflags[unit].curs_thr = 128; + qdflags[unit].tab_res = 2; /* default tablet resolution factor */ + qdflags[unit].duart_imask = 0; /* init shadow variables */ + qdflags[unit].adder_ie = 0; + + /* + * init structures used in kbd/mouse interrupt service. This code must + * come after the "init_shared()" routine has run since that routine + * inits the eq_header[unit] structure used here. + */ + + /* + * init the "latest mouse report" structure + */ + last_rep[unit].state = 0; + last_rep[unit].dx = 0; + last_rep[unit].dy = 0; + last_rep[unit].bytcnt = 0; + + /* + * init the event queue (except mouse position) + */ + eq_header[unit]->header.events = + (struct _vs_event *)((int)eq_header[unit] + sizeof(struct qdinput)); + + eq_header[unit]->header.size = MAXEVENTS; + eq_header[unit]->header.head = 0; + eq_header[unit]->header.tail = 0; + + /* + * open exclusive for graphics device. + */ + qdopened[unit] = 0; + +} /* qdattach */ + +/*ARGSUSED*/ +qdopen(dev, flag) + dev_t dev; + int flag; +{ + register struct uba_device *ui; /* ptr to uba structures */ + register struct dga *dga; /* ptr to gate array struct */ + register struct tty *tp; + struct duart *duart; + int unit; + int minor_dev; + + minor_dev = minor(dev); /* get QDSS minor device number */ + unit = minor_dev >> 2; + + /* + * check for illegal conditions + */ + ui = qdinfo[unit]; /* get ptr to QDSS device struct */ + if (ui == 0 || ui->ui_alive == 0) + return(ENXIO); /* no such device or address */ + + duart = (struct duart *) qdmap[unit].duart; + dga = (struct dga *) qdmap[unit].dga; + + if ((minor_dev & 0x03) == 2) { + /* + * this is the graphic device... + */ + if (qdopened[unit] != 0) + return(EBUSY); + else + qdopened[unit] = 1; + qdflags[unit].inuse |= GRAPHIC_DEV; /* graphics dev is open */ + /* + * enble kbd & mouse intrpts in DUART mask reg + */ + qdflags[unit].duart_imask |= 0x22; + duart->imask = qdflags[unit].duart_imask; + } else { + /* + * this is the console + */ + qdflags[unit].inuse |= CONS_DEV; /* mark console as open */ + dga->csr |= CURS_ENB; + qdflags[unit].duart_imask |= 0x02; + duart->imask = qdflags[unit].duart_imask; + /* + * some setup for tty handling + */ + tp = &qd_tty[minor_dev]; + tp->t_addr = ui->ui_addr; + tp->t_oproc = qdstart; + if ((tp->t_state & TS_ISOPEN) == 0) { + ttychars(tp); + tp->t_ispeed = B9600; + tp->t_ospeed = B9600; + tp->t_state = TS_ISOPEN | TS_CARR_ON; + tp->t_iflag = TTYDEF_IFLAG; + tp->t_oflag = TTYDEF_OFLAG; + tp->t_lflag = TTYDEF_LFLAG; + tp->t_cflag = TTYDEF_CFLAG; + } + /* + * enable intrpts, open line discipline + */ + dga->csr |= GLOBAL_IE; /* turn on the interrupts */ + return ((*linesw[tp->t_line].l_open)(dev, tp)); + } + dga->csr |= GLOBAL_IE; /* turn on the interrupts */ + return(0); + +} /* qdopen */ + +/*ARGSUSED*/ +qdclose(dev, flag, mode, p) + dev_t dev; + int flag, mode; + struct proc *p; +{ + register struct tty *tp; + register struct qdmap *qd; + register int *ptep; + struct dga *dga; /* gate array register map pointer */ + struct duart *duart; + struct adder *adder; + int unit; + int minor_dev; + u_int mapix; + int i; /* SIGNED index */ + + minor_dev = minor(dev); /* get minor device number */ + unit = minor_dev >> 2; /* get QDSS number */ + qd = &qdmap[unit]; + + if ((minor_dev & 0x03) == 2) { + /* + * this is the graphic device... + */ + if (qdopened[unit] != 1) + return(EBUSY); + else + qdopened[unit] = 0; /* allow it to be re-opened */ + /* + * re-protect device memory + */ + if (qdflags[unit].mapped & MAPDEV) { + /* + * TEMPLATE RAM + */ + mapix = VTOP((int)qd->template) - VTOP(qvmem[0]); + ptep = (int *)(QVmap[0] + mapix); + for (i = 0; i < btop(TMPSIZE); i++, ptep++) + *ptep = (*ptep & ~PG_PROT) | PG_V | PG_KW; + /* + * ADDER + */ + mapix = VTOP((int)qd->adder) - VTOP(qvmem[0]); + ptep = (int *)(QVmap[0] + mapix); + for (i = 0; i < btop(REGSIZE); i++, ptep++) + *ptep = (*ptep & ~PG_PROT) | PG_V | PG_KW; + /* + * COLOR MAPS + */ + mapix = VTOP((int)qd->red) - VTOP(qvmem[0]); + ptep = (int *)(QVmap[0] + mapix); + for (i = 0; i < btop(CLRSIZE); i++, ptep++) + *ptep = (*ptep & ~PG_PROT) | PG_V | PG_KW; + } + + /* + * re-protect DMA buffer and free the map registers + */ + if (qdflags[unit].mapped & MAPDMA) { + dga = (struct dga *) qdmap[unit].dga; + adder = (struct adder *) qdmap[unit].adder; + dga->csr &= ~DMA_IE; + dga->csr &= ~0x0600; /* kill DMA */ + adder->command = CANCEL; + /* + * if DMA was running, flush spurious intrpt + */ + if (dga->bytcnt_lo != 0) { + dga->bytcnt_lo = 0; + dga->bytcnt_hi = 0; + DMA_SETIGNORE(DMAheader[unit]); + dga->csr |= DMA_IE; + dga->csr &= ~DMA_IE; + } + ptep = (int *) + ((VTOP(DMAheader[unit]*4)) + (mfpr(SBR)|0x80000000)); + for (i = 0; i < btop(DMAbuf_size); i++, ptep++) + *ptep = (*ptep & ~PG_PROT) | PG_V | PG_KW; + ubarelse(0, &Qbus_unmap[unit]); + } + + /* + * re-protect 1K (2 pages) event queue + */ + if (qdflags[unit].mapped & MAPEQ) { + ptep = (int *) + ((VTOP(eq_header[unit])*4) + (mfpr(SBR)|0x80000000)); + *ptep = (*ptep & ~PG_PROT) | PG_KW | PG_V; ptep++; + *ptep = (*ptep & ~PG_PROT) | PG_KW | PG_V; + } + /* + * re-protect scroll param area and disable scroll intrpts + */ + if (qdflags[unit].mapped & MAPSCR) { + ptep = (int *) ((VTOP(scroll[unit]) * 4) + + (mfpr(SBR) | 0x80000000)); + /* + * re-protect 512 scroll param area + */ + *ptep = (*ptep & ~PG_PROT) | PG_KW | PG_V; + adder = (struct adder *) qdmap[unit].adder; + qdflags[unit].adder_ie &= ~FRAME_SYNC; + adder->interrupt_enable = qdflags[unit].adder_ie; + } + /* + * re-protect color map write buffer area and kill intrpts + */ + if (qdflags[unit].mapped & MAPCOLOR) { + ptep = (int *) ((VTOP(color_buf[unit]) * 4) + + (mfpr(SBR) | 0x80000000)); + *ptep = (*ptep & ~PG_PROT) | PG_KW | PG_V; ptep++; + *ptep = (*ptep & ~PG_PROT) | PG_KW | PG_V; + color_buf[unit]->status = 0; + adder = (struct adder *) qdmap[unit].adder; + qdflags[unit].adder_ie &= ~VSYNC; + adder->interrupt_enable = qdflags[unit].adder_ie; + } + mtpr(TBIA, 0); + /* flag everything now unmapped */ + qdflags[unit].mapped = 0; + qdflags[unit].inuse &= ~GRAPHIC_DEV; + qdflags[unit].curs_acc = ACC_OFF; + qdflags[unit].curs_thr = 128; + /* + * restore the console + */ + dga = (struct dga *) qdmap[unit].dga; + adder = (struct adder *) qdmap[unit].adder; + dga->csr &= ~DMA_IE; + dga->csr &= ~0x0600; /* halt the DMA! (just in case...) */ + dga->csr |= DMA_ERR; /* clear error condition */ + adder->command = CANCEL; + /* + * if DMA was running, flush spurious intrpt + */ + if (dga->bytcnt_lo != 0) { + dga->bytcnt_lo = 0; + dga->bytcnt_hi = 0; + DMA_SETIGNORE(DMAheader[unit]); + dga->csr |= DMA_IE; + dga->csr &= ~DMA_IE; + } + init_shared(unit); /* init shared memory */ + setup_dragon(unit); /* init ADDER/VIPER */ + ldcursor(unit, cons_cursor); /* load default cursor map */ + setup_input(unit); /* init the DUART */ + ldfont(unit); + cursor[unit].x = 0; + cursor[unit].y = 0; + /* + * shut off the mouse rcv intrpt and turn on kbd intrpts + */ + duart = (struct duart *) qdmap[unit].duart; + qdflags[unit].duart_imask &= ~(0x20); + qdflags[unit].duart_imask |= 0x02; + duart->imask = qdflags[unit].duart_imask; + /* + * shut off interrupts if all is closed + */ + if (!(qdflags[unit].inuse & CONS_DEV)) { + dga = (struct dga *) qdmap[unit].dga; + dga->csr &= ~(GLOBAL_IE | DMA_IE); + } + } else { + /* + * this is the console + */ + tp = &qd_tty[minor_dev]; + (*linesw[tp->t_line].l_close)(tp, flag); + ttyclose(tp); + tp->t_state = 0; + qdflags[unit].inuse &= ~CONS_DEV; + /* + * if graphics device is closed, kill interrupts + */ + if (!(qdflags[unit].inuse & GRAPHIC_DEV)) { + dga = (struct dga *) qdmap[unit].dga; + dga->csr &= ~(GLOBAL_IE | DMA_IE); + } + } + + return(0); + +} /* qdclose */ + +qdioctl(dev, cmd, datap, flags) + dev_t dev; + int cmd; + register caddr_t datap; + int flags; +{ + register int *ptep; /* page table entry pointer */ + register int mapix; /* QVmap[] page table index */ + register struct _vs_event *event; + register struct tty *tp; + register i; + struct qdmap *qd; /* pointer to device map struct */ + struct dga *dga; /* Gate Array reg structure pntr */ + struct duart *duart; /* DUART reg structure pointer */ + struct adder *adder; /* ADDER reg structure pointer */ + struct prgkbd *cmdbuf; + struct prg_cursor *curs; + struct _vs_cursor *pos; + int unit = minor(dev) >> 2; /* number of caller's QDSS */ + u_int minor_dev = minor(dev); + int error; + int s; + short *temp; /* a pointer to template RAM */ + + /* + * service graphic device ioctl commands + */ + switch (cmd) { + + case QD_GETEVENT: + /* + * extract the oldest event from the event queue + */ + if (ISEMPTY(eq_header[unit])) { + event = (struct _vs_event *) datap; + event->vse_device = VSE_NULL; + break; + } + event = (struct _vs_event *) GETBEGIN(eq_header[unit]); + s = spl5(); + GETEND(eq_header[unit]); + splx(s); + bcopy((caddr_t)event, datap, sizeof(struct _vs_event)); + break; + + case QD_RESET: + /* + * init the dragon stuff, DUART, and driver variables + */ + init_shared(unit); /* init shared memory */ + setup_dragon(unit); /* init the ADDER/VIPER stuff */ + clear_qd_screen(unit); + ldcursor(unit, cons_cursor); /* load default cursor map */ + ldfont(unit); /* load the console font */ + setup_input(unit); /* init the DUART */ + break; + + case QD_SET: + /* + * init the DUART and driver variables + */ + init_shared(unit); + setup_input(unit); + break; + + case QD_CLRSCRN: + /* + * clear the QDSS screen. (NOTE that this reinits the dragon) + */ +#ifdef notdef /* has caused problems and isn't necessary */ + setup_dragon(unit); + clear_qd_screen(unit); +#endif + break; + + case QD_WTCURSOR: + /* + * load a cursor into template RAM + */ + ldcursor(unit, (short *)datap); + break; + + case QD_RDCURSOR: + + temp = (short *) qdmap[unit].template; + /* + * cursor is 32 WORDS from the end of the 8k WORD... + * ...template space + */ + temp += (8 * 1024) - 32; + for (i = 0; i < 32; ++i, datap += sizeof(short)) + *(short *)datap = *temp++; + break; + + case QD_POSCURSOR: + /* + * position the mouse cursor + */ + dga = (struct dga *) qdmap[unit].dga; + pos = (struct _vs_cursor *) datap; + s = spl5(); + dga->x_cursor = TRANX(pos->x); + dga->y_cursor = TRANY(pos->y); + eq_header[unit]->curs_pos.x = pos->x; + eq_header[unit]->curs_pos.y = pos->y; + splx(s); + break; + + case QD_PRGCURSOR: + /* + * set the cursor acceleration factor + */ + curs = (struct prg_cursor *) datap; + s = spl5(); + qdflags[unit].curs_acc = curs->acc_factor; + qdflags[unit].curs_thr = curs->threshold; + splx(s); + break; + + case QD_MAPDEVICE: + /* + * enable 'user write' to device pages + */ + qdflags[unit].mapped |= MAPDEV; + qd = (struct qdmap *) &qdmap[unit]; + /* + * enable user write to template RAM + */ + mapix = VTOP((int)qd->template) - VTOP(qvmem[0]); + ptep = (int *)(QVmap[0] + mapix); + for (i = 0; i < btop(TMPSIZE); i++, ptep++) + *ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V; + /* + * enable user write to registers + */ + mapix = VTOP((int)qd->adder) - VTOP(qvmem[0]); + ptep = (int *)(QVmap[0] + mapix); + for (i = 0; i < btop(REGSIZE); i++, ptep++) + *ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V; + /* + * enable user write to color maps + */ + mapix = VTOP((int)qd->red) - VTOP(qvmem[0]); + ptep = (int *)(QVmap[0] + mapix); + for (i = 0; i < btop(CLRSIZE); i++, ptep++) + *ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V; + /* + * enable user write to DUART + */ + mapix = VTOP((int)qd->duart) - VTOP(qvmem[0]); + ptep = (int *)(QVmap[0] + mapix); + *ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V; /* duart page */ + + mtpr(TBIA, 0); /* invalidate translation buffer */ + + /* + * stuff qdmap structure in return buffer + */ + bcopy((caddr_t)qd, datap, sizeof(struct qdmap)); + break; + + case QD_MAPIOBUF: + /* + * do setup for DMA by user process + * + * set 'user write enable' bits for DMA buffer + */ + qdflags[unit].mapped |= MAPDMA; + ptep = (int *) ((VTOP(DMAheader[unit]) * 4) + + (mfpr(SBR) | 0x80000000)); + for (i = 0; i < btop(DMAbuf_size); i++, ptep++) + *ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V; + mtpr(TBIA, 0); /* invalidate translation buffer */ + /* + * set up QBUS map registers for DMA + */ + DMAheader[unit]->QBAreg = + uballoc(0, (caddr_t)DMAheader[unit], DMAbuf_size, 0); + if (DMAheader[unit]->QBAreg == 0) + printf("qd%d: qdioctl: QBA setup error\n", unit); + Qbus_unmap[unit] = DMAheader[unit]->QBAreg; + DMAheader[unit]->QBAreg &= 0x3FFFF; + /* + * return I/O buf adr + */ + *(int *)datap = (int) DMAheader[unit]; + break; + + case QD_MAPSCROLL: + /* + * map the shared scroll param area and enable scroll interpts + */ + qdflags[unit].mapped |= MAPSCR; + ptep = (int *) ((VTOP(scroll[unit]) * 4) + + (mfpr(SBR) | 0x80000000)); + /* + * allow user write to scroll area + */ + *ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V; + mtpr(TBIA, 0); /* invalidate translation buf */ + scroll[unit]->status = 0; + adder = (struct adder *) qdmap[unit].adder; + qdflags[unit].adder_ie |= FRAME_SYNC; + adder->interrupt_enable = qdflags[unit].adder_ie; + *(int *)datap = (int) scroll[unit]; /* return scroll area */ + break; + + case QD_UNMAPSCROLL: + /* + * unmap shared scroll param area and disable scroll intrpts + */ + if (qdflags[unit].mapped & MAPSCR) { + qdflags[unit].mapped &= ~MAPSCR; + ptep = (int *) ((VTOP(scroll[unit]) * 4) + + (mfpr(SBR) | 0x80000000)); + /* + * re-protect 512 scroll param area + */ + *ptep = (*ptep & ~PG_PROT) | PG_KW | PG_V; + mtpr(TBIA, 0); /* smash CPU's translation buf */ + adder = (struct adder *) qdmap[unit].adder; + qdflags[unit].adder_ie &= ~FRAME_SYNC; + adder->interrupt_enable = qdflags[unit].adder_ie; + } + break; + + case QD_MAPCOLOR: + /* + * map shared color map write buf and turn on vsync intrpt + */ + qdflags[unit].mapped |= MAPCOLOR; + ptep = (int *) ((VTOP(color_buf[unit]) * 4) + + (mfpr(SBR) | 0x80000000)); + /* + * allow user write to color map write buffer + */ + *ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V; ptep++; + *ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V; + mtpr(TBIA, 0); /* clr CPU translation buf */ + adder = (struct adder *) qdmap[unit].adder; + qdflags[unit].adder_ie |= VSYNC; + adder->interrupt_enable = qdflags[unit].adder_ie; + /* + * return color area address + */ + *(int *)datap = (int) color_buf[unit]; + break; + + case QD_UNMAPCOLOR: + /* + * unmap shared color map write buffer and kill VSYNC intrpts + */ + if (qdflags[unit].mapped & MAPCOLOR) { + qdflags[unit].mapped &= ~MAPCOLOR; + ptep = (int *) ((VTOP(color_buf[unit]) * 4) + + (mfpr(SBR) | 0x80000000)); + /* + * re-protect color map write buffer + */ + *ptep = (*ptep & ~PG_PROT) | PG_KW | PG_V; ptep++; + *ptep = (*ptep & ~PG_PROT) | PG_KW | PG_V; + mtpr(TBIA, 0); + adder = (struct adder *) qdmap[unit].adder; + qdflags[unit].adder_ie &= ~VSYNC; + adder->interrupt_enable = qdflags[unit].adder_ie; + } + break; + + case QD_MAPEVENT: + /* + * give user write access to the event queue + */ + qdflags[unit].mapped |= MAPEQ; + ptep = (int *) ((VTOP(eq_header[unit]) * 4) + + (mfpr(SBR) | 0x80000000)); + /* + * allow user write to 1K event queue + */ + *ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V; ptep++; + *ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V; + mtpr(TBIA, 0); /* clr CPU translation buf */ + /* + * return event queue address + */ + *(int *)datap = (int)eq_header[unit]; + break; + + case QD_PRGKBD: + /* + * pass caller's programming commands to LK201 + */ + duart = (struct duart *)qdmap[unit].duart; + cmdbuf = (struct prgkbd *)datap; /* pnt to kbd cmd buf */ + /* + * send command + */ + for (i = 1000; i > 0; --i) { + if (duart->statusA&XMT_RDY) { + duart->dataA = cmdbuf->cmd; + break; + } + } + if (i == 0) { + printf("qd%d: qdioctl: timeout on XMT_RDY [1]\n", unit); + break; + } + /* + * send param1? + */ + if (cmdbuf->cmd & LAST_PARAM) + break; + for (i = 1000; i > 0; --i) { + if (duart->statusA&XMT_RDY) { + duart->dataA = cmdbuf->param1; + break; + } + } + if (i == 0) { + printf("qd%d: qdioctl: timeout on XMT_RDY [2]\n", unit); + break; + } + /* + * send param2? + */ + if (cmdbuf->param1 & LAST_PARAM) + break; + for (i = 1000; i > 0; --i) { + if (duart->statusA&XMT_RDY) { + duart->dataA = cmdbuf->param2; + break; + } + } + if (i == 0) { + printf("qd%d: qdioctl: timeout on XMT_RDY [3]\n", unit); + break; + } + break; + + case QD_PRGMOUSE: + /* + * pass caller's programming commands to the mouse + */ + duart = (struct duart *) qdmap[unit].duart; + for (i = 1000; i > 0; --i) { + if (duart->statusB&XMT_RDY) { + duart->dataB = *datap; + break; + } + } + if (i == 0) { + printf("qd%d: qdioctl: timeout on XMT_RDY [4]\n", unit); + } + break; + + case QD_RDCONFIG: + /* + * get QDSS configuration word and return it + */ + *(short *)datap = qdflags[unit].config; + break; + + case QD_KERN_LOOP: + case QD_KERN_UNLOOP: + /* + * vestige from ultrix. BSD uses TIOCCONS to redirect + * kernel console output. + */ + break; + + case QD_PRGTABLET: + /* + * program the tablet + */ + duart = (struct duart *) qdmap[unit].duart; + for (i = 1000; i > 0; --i) { + if (duart->statusB&XMT_RDY) { + duart->dataB = *datap; + break; + } + } + if (i == 0) { + printf("qd%d: qdioctl: timeout on XMT_RDY [5]\n", unit); + } + break; + + case QD_PRGTABRES: + /* + * program the tablet report resolution factor + */ + qdflags[unit].tab_res = *(short *)datap; + break; + + default: + /* + * service tty ioctl's + */ + if (!(minor_dev & 0x02)) { + tp = &qd_tty[minor_dev]; + error = + (*linesw[tp->t_line].l_ioctl)(tp, cmd, datap, flags); + if (error >= 0) { + return(error); + } + error = ttioctl(tp, cmd, datap, flags); + if (error >= 0) { + return(error); + } + } + break; + } + + return(0); + +} /* qdioctl */ + +qdselect(dev, rw) + dev_t dev; + int rw; +{ + register s; + register unit; + register struct tty *tp; + u_int minor_dev = minor(dev); + + s = spl5(); + unit = minor_dev >> 2; + + switch (rw) { + case FREAD: + if ((minor_dev & 0x03) == 2) { + /* + * this is a graphics device, so check for events + */ + if(!(ISEMPTY(eq_header[unit]))) { + splx(s); + return(1); + } + qdrsel[unit] = u.u_procp; + qdflags[unit].selmask |= SEL_READ; + splx(s); + return(0); + } else { + /* + * this is a tty device + */ + tp = &qd_tty[minor_dev]; + if (ttnread(tp)) + return(1); + tp->t_rsel = u.u_procp; + splx(s); + return(0); + } + + case FWRITE: + if ((minor(dev) & 0x03) == 2) { + /* + * this is a graphics device, so check for dma buffers + */ + if (DMA_ISEMPTY(DMAheader[unit])) + { + splx(s); + return(1); + } + qdrsel[unit] = u.u_procp; + qdflags[unit].selmask |= SEL_WRITE; + splx(s); + return(0); + } else { + /* + * this is a tty device + */ + tp = &qd_tty[minor_dev]; + if (tp->t_outq.c_cc <= tp->t_lowat) + return(1); + tp->t_wsel = u.u_procp; + splx(s); + return(0); + } + } + splx(s); + return(0); + +} /* qdselect() */ + +extern qd_strategy(); + +qdwrite(dev, uio) + dev_t dev; + struct uio *uio; +{ + register struct tty *tp; + register minor_dev; + register unit; + + minor_dev = minor(dev); + unit = (minor_dev >> 2) & 0x07; + + if (((minor_dev&0x03) != 0x02) && (qdflags[unit].inuse&CONS_DEV)) { + /* + * this is the console... + */ + tp = &qd_tty[minor_dev]; + return ((*linesw[tp->t_line].l_write)(tp, uio)); + } else if (qdflags[unit].inuse & GRAPHIC_DEV) { + /* + * this is a DMA xfer from user space + */ + return (physio(qd_strategy, &qdbuf[unit], + dev, B_WRITE, minphys, uio)); + } + return (ENXIO); +} + +qdread(dev, uio) + dev_t dev; + struct uio *uio; +{ + register struct tty *tp; + register minor_dev; + register unit; + + minor_dev = minor(dev); + unit = (minor_dev >> 2) & 0x07; + + if ((minor_dev & 0x03) != 0x02 && qdflags[unit].inuse & CONS_DEV) { + /* + * this is the console + */ + tp = &qd_tty[minor_dev]; + return ((*linesw[tp->t_line].l_read)(tp, uio)); + } else if (qdflags[unit].inuse & GRAPHIC_DEV) { + /* + * this is a bitmap-to-processor xfer + */ + return (physio(qd_strategy, &qdbuf[unit], + dev, B_READ, minphys, uio)); + } + return (ENXIO); +} + +/*************************************************************** +* +* qd_strategy()... strategy routine to do DMA +* +***************************************************************/ + +qd_strategy(bp) + register struct buf *bp; +{ + register struct dga *dga; + register struct adder *adder; + register unit; + int QBAreg; + int s; + int cookie; + + unit = (minor(bp->b_dev) >> 2) & 0x07; + + /* + * init pointers + */ + if ((QBAreg = ubasetup(0, bp, 0)) == 0) { + printf("qd%d: qd_strategy: QBA setup error\n", unit); + goto STRAT_ERR; + } + dga = (struct dga *) qdmap[unit].dga; + s = spl5(); + qdflags[unit].user_dma = -1; + dga->csr |= DMA_IE; + cookie = QBAreg & 0x3FFFF; + dga->adrs_lo = (short) cookie; + dga->adrs_hi = (short) (cookie >> 16); + dga->bytcnt_lo = (short) bp->b_bcount; + dga->bytcnt_hi = (short) (bp->b_bcount >> 16); + + while (qdflags[unit].user_dma) { + sleep((caddr_t)&qdflags[unit].user_dma, QDPRIOR); + } + splx(s); + ubarelse(0, &QBAreg); + if (!(dga->csr & DMA_ERR)) { + iodone(bp); + return; + } + +STRAT_ERR: + adder = (struct adder *) qdmap[unit].adder; + adder->command = CANCEL; /* cancel adder activity */ + dga->csr &= ~DMA_IE; + dga->csr &= ~0x0600; /* halt DMA (reset fifo) */ + dga->csr |= DMA_ERR; /* clear error condition */ + bp->b_flags |= B_ERROR; /* flag an error to physio() */ + + /* + * if DMA was running, flush spurious intrpt + */ + if (dga->bytcnt_lo != 0) { + dga->bytcnt_lo = 0; + dga->bytcnt_hi = 0; + DMA_SETIGNORE(DMAheader[unit]); + dga->csr |= DMA_IE; + } + iodone(bp); + +} /* qd_strategy */ + +/* + * Start output to the console screen + */ +qdstart(tp) + register struct tty *tp; +{ + register which_unit, unit, c; + int s; + + unit = minor(tp->t_dev); + which_unit = (unit >> 2) & 0x3; + unit &= 0x03; + + s = spl5(); + + /* + * If it's currently active, or delaying, no need to do anything. + */ + if (tp->t_state & (TS_TIMEOUT|TS_BUSY|TS_TTSTOP)) + goto out; + + /* + * Display chars until the queue is empty. + * Drop input from anything but the console + * device on the floor. + * + * XXX - this loop is done at spltty. + * + */ + while (tp->t_outq.c_cc) { + c = getc(&tp->t_outq); + if (unit == 0) + blitc(which_unit, (u_char)c); + } + /* + * If there are sleepers, and output has drained below low + * water mark, wake up the sleepers. + */ + if (tp->t_outq.c_cc <= tp->t_lowat) { + if (tp->t_state & TS_ASLEEP){ + tp->t_state &= ~TS_ASLEEP; + wakeup((caddr_t) &tp->t_outq); + } + } + + tp->t_state &= ~TS_BUSY; + +out: + splx(s); + +} /* qdstart */ + +/*ARGSUSED*/ +void +qdstop(tp, flag) + register struct tty *tp; + int flag; +{ + register int s; + + s = spl5(); /* block intrpts during state modification */ + if (tp->t_state & TS_BUSY) + if ((tp->t_state & TS_TTSTOP) == 0) + tp->t_state |= TS_FLUSH; + else + tp->t_state &= ~TS_BUSY; + splx(s); +} + +/* + * Output a character to the QDSS screen + */ + +blitc(unit, chr) + register unit; + register u_char chr; +{ + register struct adder *adder; + register struct dga *dga; + register int i; + int nograph = !(qdflags[unit].inuse&GRAPHIC_DEV); + static short inescape[NQD]; + + adder = (struct adder *)qdmap[unit].adder; + dga = (struct dga *) qdmap[unit].dga; + /* + * BSD comment: this (&=0177) defeats the extended character + * set code for the glass tty, but if i had the time i would + * spend it ripping out the code completely. This driver + * is too big for its own good. + */ + chr &= 0177; + /* + * Cursor addressing (so vi will work). + * Decode for "\E=%.%." cursor motion description. + * Corresponds to type "qdcons" in /etc/termcap: + * + * qd|qdss|qdcons|qdss glass tty (4.4 BSD):\ + * :am:do=^J:le=^H:bs:cm=\E=%.%.:cl=1^Z:co#128:li#57::nd=^L:up=^K: + * + */ + if (inescape[unit] && nograph) { + switch (inescape[unit]++) { + case 1: + if (chr != '=') { + /* abort escape sequence */ + inescape[unit] = 0; + blitc(unit, chr); + } + return; + case 2: + /* position row */ + cursor[unit].y = CHAR_HEIGHT * chr; + if (cursor[unit].y > 863 - CHAR_HEIGHT) + cursor[unit].y = 863 - CHAR_HEIGHT; + dga->y_cursor = TRANY(cursor[unit].y); + return; + case 3: + /* position column */ + cursor[unit].x = CHAR_WIDTH * chr; + if (cursor[unit].x > 1024 - CHAR_WIDTH) + cursor[unit].x = 1023 - CHAR_WIDTH; + dga->x_cursor = TRANX(cursor[unit].x); + inescape[unit] = 0; + return; + default: + inescape[unit] = 0; + blitc(unit, chr); + } + } + + switch (chr) { + case '\r': /* return char */ + cursor[unit].x = 0; + if (nograph) + dga->x_cursor = TRANX(cursor[unit].x); + return; + + case '\t': /* tab char */ + for (i = 8 - ((cursor[unit].x >> 3) & 0x07); i > 0; --i) { + blitc(unit, ' '); + } + return; + + case '\n': /* line feed char */ + if ((cursor[unit].y += CHAR_HEIGHT) > (863 - CHAR_HEIGHT)) { + if (nograph) { + cursor[unit].y -= CHAR_HEIGHT; + scroll_up(adder); + } else + cursor[unit].y = 0; + } + if (nograph) + dga->y_cursor = TRANY(cursor[unit].y); + return; + + case '\b': /* backspace char */ + if (cursor[unit].x > 0) { + cursor[unit].x -= CHAR_WIDTH; + if (nograph) + dga->x_cursor = TRANX(cursor[unit].x); + } + return; + case CTRL('k'): /* cursor up */ + if (nograph && cursor[unit].y > 0) { + cursor[unit].y -= CHAR_HEIGHT; + dga->y_cursor = TRANY(cursor[unit].y); + } + return; + + case CTRL('^'): /* home cursor */ + if (nograph) { + cursor[unit].x = 0; + dga->x_cursor = TRANX(cursor[unit].x); + cursor[unit].y = 0; + dga->y_cursor = TRANY(cursor[unit].y); + } + return; + + case CTRL('l'): /* cursor right */ + if (nograph && cursor[unit].x < 1023 - CHAR_WIDTH) { + cursor[unit].x += CHAR_WIDTH; + dga->x_cursor = TRANX(cursor[unit].x); + } + return; + + case CTRL('z'): /* clear screen */ + if (nograph) { + setup_dragon(unit); + clear_qd_screen(unit); + /* home cursor - termcap seems to assume this */ + cursor[unit].x = 0; + dga->x_cursor = TRANX(cursor[unit].x); + cursor[unit].y = 0; + dga->y_cursor = TRANY(cursor[unit].y); + } + return; + + case '\033': /* start escape sequence */ + if (nograph) + inescape[unit] = 1; + return; + + default: + if ((chr < ' ') || (chr > '~')) + return; + } + /* + * setup VIPER operand control registers + */ + write_ID(adder, CS_UPDATE_MASK, 0x0001); /* select plane #0 */ + write_ID(adder, SRC1_OCR_B, + EXT_NONE | INT_SOURCE | ID | BAR_SHIFT_DELAY); + write_ID(adder, CS_UPDATE_MASK, 0x00FE); /* select other planes */ + write_ID(adder, SRC1_OCR_B, + EXT_SOURCE | INT_NONE | NO_ID | BAR_SHIFT_DELAY); + write_ID(adder, CS_UPDATE_MASK, 0x00FF); /* select all planes */ + write_ID(adder, DST_OCR_B, + EXT_NONE | INT_NONE | NO_ID | NO_BAR_SHIFT_DELAY); + write_ID(adder, MASK_1, 0xFFFF); + write_ID(adder, VIPER_Z_LOAD | FOREGROUND_COLOR_Z, 1); + write_ID(adder, VIPER_Z_LOAD | BACKGROUND_COLOR_Z, 0); + adder->x_clip_min = 0; + adder->x_clip_max = 1024; + adder->y_clip_min = 0; + adder->y_clip_max = 864; + /* + * load DESTINATION origin and vectors + */ + adder->fast_dest_dy = 0; + adder->slow_dest_dx = 0; + adder->error_1 = 0; + adder->error_2 = 0; + adder->rasterop_mode = DST_WRITE_ENABLE | NORMAL; + (void)wait_status(adder, RASTEROP_COMPLETE); + adder->destination_x = cursor[unit].x; + adder->fast_dest_dx = CHAR_WIDTH; + adder->destination_y = cursor[unit].y; + adder->slow_dest_dy = CHAR_HEIGHT; + /* + * load SOURCE origin and vectors + */ + if ((chr - ' ') > (CHARS - 1)) { + printf("Invalid character (x)%x in blitc\n",chr); + chr = ' '; + } + /* + * X position is modulo the number of characters per line + */ + adder->source_1_x = FONT_X + + (((chr - ' ') % (MAX_SCREEN_X/CHAR_WIDTH)) * CHAR_WIDTH); + /* + * Point to either first or second row + */ + adder->source_1_y = 2048 - 15 * + (((chr - ' ')/(MAX_SCREEN_X/CHAR_WIDTH)) + 1); + adder->source_1_dx = CHAR_WIDTH; + adder->source_1_dy = CHAR_HEIGHT; + write_ID(adder, LU_FUNCTION_R1, FULL_SRC_RESOLUTION | LF_SOURCE); + adder->cmd = RASTEROP | OCRB | 0 | S1E | DTE; + /* + * update console cursor coordinates + */ + cursor[unit].x += CHAR_WIDTH; + if (nograph) + dga->x_cursor = TRANX(cursor[unit].x); + if (cursor[unit].x > (1024 - CHAR_WIDTH)) { + blitc(unit, '\r'); + blitc(unit, '\n'); + } + +} /* blitc */ + +qdreset() { } + +/* + * INTERRUPT SERVICE ROUTINES + */ + +/* + * Service "DMA DONE" interrupt condition + */ +qddint(qd) + register qd; +{ + register struct DMAreq_header *header; + register struct DMAreq *request; + register struct dga *dga; + struct adder *adder; + int cookie; /* DMA adrs for QDSS */ + + (void)spl4(); /* allow interval timer in */ + + /* + * init pointers + */ + header = DMAheader[qd]; /* register for optimization */ + dga = (struct dga *) qdmap[qd].dga; + adder = (struct adder *) qdmap[qd].adder; + + /* + * if this interrupt flagged as bogus for interrupt flushing purposes.. + */ + if (DMA_ISIGNORE(header)) { + DMA_CLRIGNORE(header); + return; + } + + /* + * dump a DMA hardware error message if appropriate + */ + if (dga->csr & DMA_ERR) { + + if (dga->csr & PARITY_ERR) + printf("qd%d: qddint: DMA hardware parity fault.\n", qd); + + if (dga->csr & BUS_ERR) + printf("qd%d: qddint: DMA hardware bus error.\n", qd); + } + + /* + * if this was a DMA from user space... + */ + if (qdflags[qd].user_dma) { + qdflags[qd].user_dma = 0; + wakeup((caddr_t)&qdflags[qd].user_dma); + return; + } + + /* + * if we're doing DMA request queue services, field the error condition + */ + if (dga->csr & DMA_ERR) { + + dga->csr &= ~0x0600; /* halt DMA (reset fifo) */ + dga->csr |= DMA_ERR; /* clear error condition */ + adder->command = CANCEL; /* cancel adder activity */ + + DMA_SETERROR(header); /* flag error in header status word */ + DMA_CLRACTIVE(header); + header->DMAreq[header->oldest].DMAdone |= HARD_ERROR; + header->newest = header->oldest; + header->used = 0; + + if (qdrsel[qd] && qdflags[qd].selmask & SEL_WRITE) { + selwakeup(qdrsel[qd], 0); + qdrsel[qd] = 0; + qdflags[qd].selmask &= ~SEL_WRITE; + } + + if (dga->bytcnt_lo != 0) { + dga->bytcnt_lo = 0; + dga->bytcnt_hi = 0; + DMA_SETIGNORE(header); + } + return; + } + + /* + * if the DMA request queue is now becoming non-full, + * wakeup "select" client. + */ + if (DMA_ISFULL(header)) { + if (qdrsel[qd] && qdflags[qd].selmask & SEL_WRITE) { + selwakeup(qdrsel[qd], 0); + qdrsel[qd] = 0; + qdflags[qd].selmask &= ~SEL_WRITE; + } + } + + header->DMAreq[header->oldest].DMAdone |= REQUEST_DONE; + QDlast_DMAtype = header->DMAreq[header->oldest].DMAtype; + + /* check for unexpected interrupt */ + if (DMA_ISEMPTY(header)) + return; + + DMA_GETEND(header); /* update request queue indices */ + + /* + * if no more DMA pending, wake up "select" client and exit + */ + if (DMA_ISEMPTY(header)) { + + if (qdrsel[qd] && qdflags[qd].selmask & SEL_WRITE) { + selwakeup(qdrsel[qd], 0); + qdrsel[qd] = 0; + qdflags[qd].selmask &= ~SEL_WRITE; + } + + DMA_CLRACTIVE(header); /* flag DMA done */ + return; + } + + /* + * initiate next DMA xfer + */ + request = DMA_GETBEGIN(header); + if (request->DMAtype != QDlast_DMAtype) { + dga->csr &= ~0x0600; /* halt DMA (reset fifo) */ + adder->command = CANCEL; /* cancel adder activity */ + } + + + switch (request->DMAtype) { + + case DISPLIST: + if (request->DMAtype != QDlast_DMAtype) { + dga->csr |= DL_ENB; + dga->csr &= ~(BTOP_ENB | BYTE_DMA); + } + break; + + case PTOB: + if (request->DMAtype != QDlast_DMAtype) { + if (request->DMAdone & BYTE_PACK) + dga->csr |= (PTOB_ENB | BYTE_DMA); + else { + dga->csr |= PTOB_ENB; + dga->csr &= ~BYTE_DMA; + } + } + break; + + case BTOP: + if (request->DMAtype != QDlast_DMAtype) { + if (request->DMAdone & BYTE_PACK) { + dga->csr &= ~DL_ENB; + dga->csr |= (BTOP_ENB | BYTE_DMA); + } + else { + dga->csr |= BTOP_ENB; + dga->csr &= ~(BYTE_DMA | DL_ENB); + } + } + break; + default: + printf("qd%d: qddint: illegal DMAtype parameter.\n", qd); + DMA_CLRACTIVE(header); /* flag DMA done */ + return; + } + + if (request->DMAdone & COUNT_ZERO) { + dga->csr &= ~SET_DONE_FIFO; + } + else if (request->DMAdone & FIFO_EMPTY) { + dga->csr |= SET_DONE_FIFO; + } + + if (request->DMAdone & WORD_PACK) + dga->csr &= ~BYTE_DMA; + else if (request->DMAdone & BYTE_PACK) + dga->csr |= BYTE_DMA; + + dga->csr |= DMA_IE; + QDlast_DMAtype = request->DMAtype; + + cookie = ((int)request->bufp - (int)header) + (int)header->QBAreg; + + dga->adrs_lo = (short) cookie; + dga->adrs_hi = (short) (cookie >> 16); + + dga->bytcnt_lo = (short) request->length; + dga->bytcnt_hi = (short) (request->length >> 16); + + return; +} + +/* + * ADDER interrupt service routine + */ +qdaint(qd) + register qd; +{ + register struct adder *adder; + struct color_buf *cbuf; + int i; + register struct rgb *rgbp; + register short *red; + register short *green; + register short *blue; + + (void)spl4(); /* allow interval timer in */ + + adder = (struct adder *) qdmap[qd].adder; + + /* + * service the vertical blank interrupt (VSYNC bit) by loading + * any pending color map load request + */ + if (adder->status & VSYNC) { + adder->status &= ~VSYNC; /* clear the interrupt */ + cbuf = color_buf[qd]; + if (cbuf->status & LOAD_COLOR_MAP) { + + red = (short *) qdmap[qd].red; + green = (short *) qdmap[qd].green; + blue = (short *) qdmap[qd].blue; + + for (i = cbuf->count, rgbp = cbuf->rgb; + --i >= 0; rgbp++) { + red[rgbp->offset] = (short) rgbp->red; + green[rgbp->offset] = (short) rgbp->green; + blue[rgbp->offset] = (short) rgbp->blue; + } + + cbuf->status &= ~LOAD_COLOR_MAP; + } + } + + /* + * service the scroll interrupt (FRAME_SYNC bit) + */ + if (adder->status & FRAME_SYNC) { + adder->status &= ~FRAME_SYNC; /* clear the interrupt */ + + if (scroll[qd]->status & LOAD_REGS) { + + for (i = 1000, adder->status = 0; i > 0 && + !(adder->status&ID_SCROLL_READY); --i) + ; + + if (i == 0) { + printf("qd%d: qdaint: timeout on ID_SCROLL_READY\n", + qd); + return; + } + + adder->ID_scroll_data = scroll[qd]->viper_constant; + adder->ID_scroll_command = ID_LOAD | SCROLL_CONSTANT; + + adder->y_scroll_constant = + scroll[qd]->y_scroll_constant; + adder->y_offset_pending = scroll[qd]->y_offset; + + if (scroll[qd]->status & LOAD_INDEX) { + + adder->x_index_pending = + scroll[qd]->x_index_pending; + adder->y_index_pending = + scroll[qd]->y_index_pending; + } + + scroll[qd]->status = 0x00; + } + } +} + +/* + * DUART input interrupt service routine + * + * XXX - this routine should be broken out - it is essentially + * straight line code. + */ + +qdiint(qd) + register qd; +{ + register struct _vs_event *event; + register struct qdinput *eqh; + struct dga *dga; + struct duart *duart; + struct mouse_report *new_rep; + struct uba_device *ui; + struct tty *tp; + u_short chr; + u_short status; + u_short data; + u_short key; + char do_wakeup = 0; /* flag to do a select wakeup call */ + char a, b, c; /* mouse button test variables */ + + (void)spl4(); /* allow interval timer in */ + + eqh = eq_header[qd]; /* optimized as a register */ + new_rep = ¤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 diff --git a/sys/arch/vax/uba/qv.c b/sys/arch/vax/uba/qv.c new file mode 100644 index 00000000000..650487dad4b --- /dev/null +++ b/sys/arch/vax/uba/qv.c @@ -0,0 +1,1323 @@ +/* $NetBSD: qv.c,v 1.2 1996/09/02 06:44:28 mycroft Exp $ */ + +/*- + * Copyright (c) 1988 + * The Regents of the University of California. All rights reserved. + * (c) UNIX System Laboratories, Inc. + * All or some portions of this file are derived from material licensed + * to the University of California by American Telephone and Telegraph + * Co. or Unix System Laboratories, Inc. and are reproduced herein with + * the permission of UNIX System Laboratories, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)qv.c 7.2 (Berkeley) 1/21/94 + */ + +/* + * derived from: @(#)qv.c 1.8 (ULTRIX) 8/21/85 + */ + +/************************************************************************ + * * + * Copyright (c) 1985 by * + * Digital Equipment Corporation, Maynard, MA * + * All rights reserved. * + * * + * This software is furnished under a license and may be used and * + * copied only in accordance with the terms of such license and * + * with the inclusion of the above copyright notice. This * + * software or any other copies thereof may not be provided or * + * otherwise made available to any other person. No title to and * + * ownership of the software is hereby transferred. * + * * + * This software is derived from software received from the * + * University of California, Berkeley, and from Bell * + * Laboratories. Use, duplication, or disclosure is subject to * + * restrictions under license agreements with University of * + * California and with AT&T. * + * * + * The information in this software is subject to change without * + * notice and should not be construed as a commitment by Digital * + * Equipment Corporation. * + * * + * Digital assumes no responsibility for the use or reliability * + * of its software on equipment which is not supplied by Digital. * + * * + ************************************************************************ + * + * This driver provides glass tty functionality to the qvss. It is a strange + * device in that it supports three subchannels. The first being the asr, + * the second being a channel that intercepts the chars headed for the screen + * ( like a pseudo tty ) and the third being a source of mouse state changes. + * NOTE: the second is conditional on #ifdef CONS_HACK in this version + * of the driver, as it's a total crock. + * + * There may be one and only one qvss in the system. This restriction is based + * on the inability to map more than one at a time. This restriction will + * exist until the kernel has shared memory services. This driver therefore + * support a single unit. No attempt was made to have it service more. + * + * (this belongs in sccs - not here) + * + * 02 Aug 85 -- rjl + * Changed the names of the special setup routines so that the system + * can have a qvss or a qdss system console. + * + * 03 Jul 85 -- rjl + * Added a check for virtual mode in qvputc so that the driver + * doesn't crash while in a dump which is done in physical mode. + * + * 10 Apr 85 -- jg + * Well, our theory about keyboard handling was wrong; most of the + * keyboard is in autorepeat, down mode. These changes are to make + * the qvss work the same as the Vs100, which is not necessarily + * completely correct, as some chord usage may fail. But since we + * can't easily change the Vs100, we might as well propagate the + * problem to another device. There are also changes for screen and + * mouse accellaration. + * + * 27 Mar 85 -- rjl + * MicroVAX-II systems have interval timers that interrupt at ipl4. + * Everything else is higher and thus causes us to miss clock ticks. The + * problem isn't severe except in the case of a device like this one that + * generates lots of interrupts. We aren't willing to make this change to + * all device drivers but it seems acceptable in this case. + * + * 3 Dec 84 -- jg + * To continue the tradition of building a better mouse trap, this + * driver has been extended to form Vs100 style event queues. If the + * mouse device is open, the keyboard events are intercepted and put + * into the shared memory queue. Unfortunately, we are ending up with + * one of the longest Unix device drivers. Sigh.... + * + * 20 Nov 84 -- rjl + * As a further complication this driver is required to function as the + * virtual system console. This code runs before and during auto- + * configuration and therefore is require to have a second path for setup. + * It is futher constrained to have a character output routine that + * is not dependant on the interrupt system. + * + */ + + +#include "qv.h" +#if NQV > 0 + +#include "../include/pte.h" + +#include "sys/param.h" +#include "sys/conf.h" +#include "sys/user.h" +#include "qvioctl.h" +#include "sys/tty.h" +#include "sys/map.h" +#include "sys/buf.h" +#include "sys/vm.h" +#include "sys/clist.h" +#include "sys/file.h" +#include "sys/uio.h" +#include "sys/kernel.h" +#include "sys/syslog.h" +#include "../include/cpu.h" +#include "../include/mtpr.h" +#include "ubareg.h" +#include "ubavar.h" + +#define CONS_HACK + +struct uba_device *qvinfo[NQV]; + +struct tty qv_tty[NQV*4]; + +#define nNQV NQV +int nqv = NQV*4; + +/* + * Definition of the driver for the auto-configuration program. + */ +int qvprobe(), qvattach(), qvkint(), qvvint(); +u_short qvstd[] = { 0 }; +struct uba_driver qvdriver = + { qvprobe, 0, qvattach, 0, qvstd, "qv", qvinfo }; + +extern char qvmem[][512*NBPG]; +extern struct pte QVmap[][512]; + +/* + * Local variables for the driver. Initialized for 15' screen + * so that it can be used during the boot process. + */ + +#define QVWAITPRI (PZERO+1) +#define QVSSMAJOR 40 + +#define QVKEYBOARD 0 /* minor 0, keyboard/glass tty */ +#define QVPCONS 1 /* minor 1, console interceptor XXX */ +#define QVMOUSECHAN 2 /* minor 2, mouse */ +#define QVSPARE 3 /* unused */ +#define QVCHAN(unit) ((unit) & 03) +/* + * v_putc is the switch that is used to redirect the console cnputc to the + * virtual console vputc. consops is used to redirect the console + * device to the qvss console. + */ +extern (*v_putc)(); +extern struct cdevsw *consops; +/* + * qv_def_scrn is used to select the appropriate tables. 0=15 inch 1=19 inch, + * 2 = uVAXII. + */ +int qv_def_scrn = 2; + +#define QVMAXEVQ 64 /* must be power of 2 */ +#define EVROUND(x) ((x) & (QVMAXEVQ - 1)) + +/* + * Screen parameters 15 & 19 inch monitors. These determine the max size in + * pixel and character units for the display and cursor positions. + * Notice that the mouse defaults to original square algorithm, but X + * will change to its defaults once implemented. + */ +struct qv_info *qv_scn; +struct qv_info qv_scn_defaults[] = { + {0, {0, 0}, 0, {0, 0}, 0, 0, 30, 80, 768, 480, 768-16, 480-16, + 0, 0, 0, 0, 0, QVMAXEVQ, 0, 0, {0, 0}, {0, 0, 0, 0}, 2, 4}, + {0, {0, 0}, 0, {0, 0}, 0, 0, 55, 120, 960, 864, 960-16, 864-16, + 0, 0, 0, 0, 0, QVMAXEVQ, 0, 0, {0, 0}, {0, 0, 0, 0}, 2, 4}, + {0, {0, 0}, 0, {0, 0}, 0, 0, 56, 120,1024, 864,1024-16, 864-16, + 0, 0, 0, 0, 0, QVMAXEVQ, 0, 0, {0, 0}, {0, 0, 0, 0}, 2, 4} +}; + +/* + * Screen controller initialization parameters. The definations and use + * of these parameters can be found in the Motorola 68045 crtc specs. In + * essence they set the display parameters for the chip. The first set is + * for the 15" screen and the second is for the 19" seperate sync. There + * is also a third set for a 19" composite sync monitor which we have not + * tested and which is not supported. + */ +static short qv_crt_parms[][16] = { + { 31, 25, 27, 0142, 31, 13, 30, 31, 4, 15, 040, 0, 0, 0, 0, 0 }, +/* VR100*/ { 39, 30, 32, 0262, 55, 5, 54, 54, 4, 15, 040, 0, 0, 0, 0, 0 }, +/* VR260*/ { 39, 32, 33, 0264, 56, 5, 54, 54, 4, 15, 040, 0, 0, 0, 0, 0}, +}; + +/* + * Screen parameters + */ +struct qv_info *qv_scn; +int maxqvmem = 254*1024 - sizeof(struct qv_info) - QVMAXEVQ*sizeof(vsEvent); + +/* + * Keyboard state + */ +struct qv_keyboard { + int shift; /* state variables */ + int cntrl; + int lock; + char last; /* last character */ +} qv_keyboard; + +short divdefaults[15] = { LK_DOWN, /* 0 doesn't exist */ + LK_AUTODOWN, LK_AUTODOWN, LK_AUTODOWN, LK_DOWN, + LK_UPDOWN, LK_UPDOWN, LK_AUTODOWN, LK_AUTODOWN, + LK_AUTODOWN, LK_AUTODOWN, LK_AUTODOWN, LK_AUTODOWN, + LK_DOWN, LK_AUTODOWN }; + +short kbdinitstring[] = { /* reset any random keyboard stuff */ + LK_AR_ENABLE, /* we want autorepeat by default */ + LK_CL_ENABLE, /* keyclick */ + 0x84, /* keyclick volume */ + LK_KBD_ENABLE, /* the keyboard itself */ + LK_BELL_ENABLE, /* keyboard bell */ + 0x84, /* bell volume */ + LK_LED_DISABLE, /* keyboard leds */ + LED_ALL }; +#define KBD_INIT_LENGTH sizeof(kbdinitstring)/sizeof(short) + +#define TOY ((time.tv_sec * 100) + (time.tv_usec / 10000)) + +int qv_ipl_lo = 1; /* IPL low flag */ +int mouseon = 0; /* mouse channel is enabled when 1*/ +struct proc *qvrsel; /* process waiting for select */ + +int qvstart(), qvputc(), ttrstrt(); + +/* + * Keyboard translation and font tables + */ +extern u_short q_key[], q_shift_key[], q_cursor[]; +extern char *q_special[], q_font[]; + +/* + * See if the qvss will interrupt. + */ + +/*ARGSUSED*/ +qvprobe(reg, ctlr) + caddr_t reg; + int ctlr; +{ + register int br, cvec; /* these are ``value-result'' */ + register struct qvdevice *qvaddr = (struct qvdevice *)reg; + static int tvec, ovec; + +#ifdef lint + br = 0; cvec = br; br = cvec; + qvkint(0); qvvint(0); +#endif + /* + * Allocate the next two vectors + */ + tvec = 0360; + ovec = cvec; + /* + * Turn on the keyboard and vertical interrupt vectors. + */ + qvaddr->qv_intcsr = 0; /* init the interrupt controler */ + qvaddr->qv_intcsr = 0x40; /* reset irr */ + qvaddr->qv_intcsr = 0x80; /* specify individual vectors */ + qvaddr->qv_intcsr = 0xc0; /* preset autoclear data */ + qvaddr->qv_intdata = 0xff; /* all setup as autoclear */ + + qvaddr->qv_intcsr = 0xe0; /* preset vector address 1 */ + qvaddr->qv_intdata = tvec; /* give it the keyboard vector */ + qvaddr->qv_intcsr = 0x28; /* enable tx/rx interrupt */ + + qvaddr->qv_intcsr = 0xe1; /* preset vector address 2 */ + qvaddr->qv_intdata = tvec+4; /* give it the vertical sysnc */ + qvaddr->qv_intcsr = 0x29; /* enable */ + + qvaddr->qv_intcsr = 0xa1; /* arm the interrupt ctrl */ + + qvaddr->qv_uartcmd = 0x15; /* set mode pntr/enable rx/tx */ + qvaddr->qv_uartmode = 0x17; /* noparity, 8-bit */ + qvaddr->qv_uartmode = 0x07; /* 1 stop bit */ + qvaddr->qv_uartstatus = 0x99; /* 4800 baud xmit/recv */ + qvaddr->qv_uartintstatus = 2; /* enable recv interrupts */ + + qvaddr->qv_csr |= QV_INT_ENABLE | QV_CUR_MODE; + + DELAY(10000); + + qvaddr->qv_csr &= ~QV_INT_ENABLE; + + /* + * If the qvss did interrupt it was the second vector not + * the first so we have to return the first so that they + * will be setup properly + */ + if( ovec == cvec ) { + return 0; + } else + cvec -= 4; + return (sizeof (struct qvdevice)); +} + +/* + * Routine called to attach a qv. + */ +qvattach(ui) + struct uba_device *ui; +{ + + /* + * If not the console then we have to setup the screen + */ + if (v_putc != qvputc || ui->ui_unit != 0) + (void)qv_setup((struct qvdevice *)ui->ui_addr, ui->ui_unit, 1); + else + qv_scn->qvaddr = (struct qvdevice *)ui->ui_addr; +} + + +/*ARGSUSED*/ +qvopen(dev, flag) + dev_t dev; +{ + register struct tty *tp; + register int unit, qv; + register struct qvdevice *qvaddr; + register struct uba_device *ui; + register struct qv_info *qp = qv_scn; + + unit = minor(dev); + qv = unit >> 2; + if (unit >= nqv || (ui = qvinfo[qv])== 0 || ui->ui_alive == 0) + return (ENXIO); + if (QVCHAN(unit) == QVSPARE +#ifndef CONS_HACK + || QVCHAN(unit) == QVPCONS +#endif + ) + return (ENODEV); + tp = &qv_tty[unit]; + if (tp->t_state&TS_XCLUDE && u.u_uid!=0) + return (EBUSY); + qvaddr = (struct qvdevice *)ui->ui_addr; + qv_scn->qvaddr = qvaddr; + tp->t_addr = (caddr_t)qvaddr; + tp->t_oproc = qvstart; + + if ((tp->t_state&TS_ISOPEN) == 0) { + ttychars(tp); + tp->t_state = TS_ISOPEN|TS_CARR_ON; + tp->t_ispeed = B9600; + tp->t_ospeed = B9600; + if( QVCHAN(unit) == QVKEYBOARD ) { + /* make sure keyboard is always back to default */ + qvkbdreset(); + qvaddr->qv_csr |= QV_INT_ENABLE; + tp->t_iflag = TTYDEF_IFLAG; + tp->t_oflag = TTYDEF_OFLAG; + tp->t_lflag = TTYDEF_LFLAG; + tp->t_cflag = TTYDEF_CFLAG; + } + /* XXX ?why? else + tp->t_flags = RAW; + */ + } + /* + * Process line discipline specific open if its not the + * mouse channel. For the mouse we init the ring ptr's. + */ + if( QVCHAN(unit) != QVMOUSECHAN ) + return ((*linesw[tp->t_line].l_open)(dev, tp)); + else { + mouseon = 1; + /* set up event queue for later */ + qp->ibuff = (vsEvent *)qp - QVMAXEVQ; + qp->iqsize = QVMAXEVQ; + qp->ihead = qp->itail = 0; + return 0; + } +} + +/* + * Close a QVSS line. + */ +/*ARGSUSED*/ +qvclose(dev, flag, mode, p) + dev_t dev; + int flag, mode; + struct proc *p; +{ + register struct tty *tp; + register unit; + register struct qvdevice *qvaddr; + int error; + + unit = minor(dev); + tp = &qv_tty[unit]; + + /* + * If this is the keyboard unit (0) shutdown the + * interface. + */ + qvaddr = (struct qvdevice *)tp->t_addr; + if (QVCHAN(unit) == QVKEYBOARD ) + qvaddr->qv_csr &= ~QV_INT_ENABLE; + + /* + * If unit is not the mouse channel call the line disc. + * otherwise clear the state flag, and put the keyboard into down/up. + */ + if (QVCHAN(unit) != QVMOUSECHAN) { + (*linesw[tp->t_line].l_close)(tp, flag); + error = ttyclose(tp); + } else { + mouseon = 0; + qv_init( qvaddr ); + error = 0; + } + tp->t_state = 0; + return (error); +} + +qvread(dev, uio) + dev_t dev; + struct uio *uio; +{ + register struct tty *tp; + int unit = minor( dev ); + + if (QVCHAN(unit) != QVMOUSECHAN) { + tp = &qv_tty[unit]; + return ((*linesw[tp->t_line].l_read)(tp, uio)); + } + return (ENXIO); +} + +qvwrite(dev, uio) + dev_t dev; + struct uio *uio; +{ + register struct tty *tp; + int unit = minor( dev ); + + /* + * If this is the mouse we simply fake the i/o, otherwise + * we let the line disp. handle it. + */ + if (QVCHAN(unit) == QVMOUSECHAN) { + uio->uio_offset = uio->uio_resid; + uio->uio_resid = 0; + return 0; + } + tp = &qv_tty[unit]; + return ((*linesw[tp->t_line].l_write)(tp, uio)); +} + + +/* + * Mouse activity select routine + */ +qvselect(dev, rw) +dev_t dev; +{ + register int s = spl5(); + register struct qv_info *qp = qv_scn; + + if( QVCHAN(minor(dev)) == QVMOUSECHAN ) + switch(rw) { + case FREAD: /* if events okay */ + if(qp->ihead != qp->itail) { + splx(s); + return(1); + } + qvrsel = u.u_procp; + splx(s); + return(0); + default: /* can never write */ + splx(s); + return(0); + } + else { + splx(s); + return( ttselect(dev, rw) ); + } + /*NOTREACHED*/ +} + +/* + * QVSS keyboard interrupt. + */ +qvkint(qv) + int qv; +{ + struct tty *tp; + register c; + struct uba_device *ui; + register int key; + register int i; + + ui = qvinfo[qv]; + if (ui == 0 || ui->ui_alive == 0) + return; + tp = &qv_tty[qv<<2]; + /* + * Get a character from the keyboard. + */ + key = ((struct qvdevice *)ui->ui_addr)->qv_uartdata & 0xff; + if( mouseon == 0) { + /* + * Check for various keyboard errors + */ + if( key == LK_POWER_ERROR || key == LK_KDOWN_ERROR || + key == LK_INPUT_ERROR || key == LK_OUTPUT_ERROR) { + log(LOG_ERR, + "qv%d: Keyboard error, code = %x\n",qv,key); + return; + } + if( key < LK_LOWEST ) return; + /* + * See if its a state change key + */ + switch ( key ) { + case LOCK: + qv_keyboard.lock ^= 0xffff; /* toggle */ + if( qv_keyboard.lock ) + qv_key_out( LK_LED_ENABLE ); + else + qv_key_out( LK_LED_DISABLE ); + qv_key_out( LED_3 ); + return; + case SHIFT: + qv_keyboard.shift ^= 0xffff; + return; + case CNTRL: + qv_keyboard.cntrl ^= 0xffff; + return; + case ALLUP: + qv_keyboard.cntrl = qv_keyboard.shift = 0; + return; + case REPEAT: + c = qv_keyboard.last; + break; + default: + /* + * Test for control characters. If set, see if the character + * is elligible to become a control character. + */ + if( qv_keyboard.cntrl ) { + c = q_key[ key ]; + if( c >= ' ' && c <= '~' ) + c &= 0x1f; + } else if( qv_keyboard.lock || qv_keyboard.shift ) + c = q_shift_key[ key ]; + else + c = q_key[ key ]; + break; + } + + qv_keyboard.last = c; + + /* + * Check for special function keys + */ + if( c & 0x80 ) { + register char *string; + string = q_special[ c & 0x7f ]; + while( *string ) + (*linesw[tp->t_line].l_rint)(*string++, tp); + } else + (*linesw[tp->t_line].l_rint)(c, tp); + } else { + /* + * Mouse channel is open put it into the event queue + * instead. + */ + register struct qv_info *qp = qv_scn; + register vsEvent *vep; + + if ((i = EVROUND(qp->itail+1)) == qp->ihead) + return; + vep = &qp->ibuff[qp->itail]; + vep->vse_direction = VSE_KBTRAW; + vep->vse_type = VSE_BUTTON; + vep->vse_device = VSE_DKB; + vep->vse_x = qp->mouse.x; + vep->vse_y = qp->mouse.y; + vep->vse_time = TOY; + vep->vse_key = key; + qp->itail = i; + if(qvrsel) { + selwakeup(qvrsel,0); + qvrsel = 0; + } + } +} + +/* + * Ioctl for QVSS. + */ +/*ARGSUSED*/ +qvioctl(dev, cmd, data, flag) + dev_t dev; + register caddr_t data; +{ + register struct tty *tp; + register int unit = minor(dev); + register struct qv_info *qp = qv_scn; + register struct qv_kpcmd *qk; + register unsigned char *cp; + int error; + + /* + * Check for and process qvss specific ioctl's + */ + switch( cmd ) { + case QIOCGINFO: /* return screen info */ + bcopy((caddr_t)qp, data, sizeof (struct qv_info)); + break; + + case QIOCSMSTATE: /* set mouse state */ + qp->mouse = *((vsCursor *)data); + qv_pos_cur( qp->mouse.x, qp->mouse.y ); + break; + + case QIOCINIT: /* init screen */ + qv_init( qp->qvaddr ); + break; + + case QIOCKPCMD: + qk = (struct qv_kpcmd *)data; + if(qk->nbytes == 0) qk->cmd |= 0200; + if(mouseon == 0) qk->cmd |= 1; /* no mode changes */ + qv_key_out(qk->cmd); + cp = &qk->par[0]; + while(qk->nbytes-- > 0) { /* terminate parameters */ + if(qk->nbytes <= 0) *cp |= 0200; + qv_key_out(*cp++); + } + break; + case QIOCADDR: /* get struct addr */ + *(struct qv_info **) data = qp; + break; + default: /* not ours ?? */ + tp = &qv_tty[unit]; + error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag); + if (error >= 0) + return (error); + error = ttioctl(tp, cmd, data, flag); + if (error >= 0) { + return (error); + } + break; + } + return (0); +} +/* + * Initialize the screen and the scanmap + */ +qv_init(qvaddr) +struct qvdevice *qvaddr; +{ + register short *scanline; + register int i; + register short scan; + register char *ptr; + register struct qv_info *qp = qv_scn; + + /* + * Clear the bit map + */ + for( i=0 , ptr = qp->bitmap ; i<240 ; i += 2 , ptr += 2048) + bzero( ptr, 2048 ); + /* + * Reinitialize the scanmap + */ + scan = qvaddr->qv_csr & QV_MEM_BANK; + scanline = qp->scanmap; + for(i = 0 ; i < qp->max_y ; i++ ) + *scanline++ = scan++; + + /* + * Home the cursor + */ + qp->row = qp->col = 0; + + /* + * Reset the cursor to the default type. + */ + for( i=0 ; i<16 ; i++ ) + qp->cursorbits[i] = q_cursor[i]; + qvaddr->qv_csr |= QV_CUR_MODE; + /* + * Reset keyboard to default state. + */ + qvkbdreset(); +} + +qvreset() +{ +} +qvkbdreset() +{ + register int i; + qv_key_out(LK_DEFAULTS); + for( i=1 ; i < 15 ; i++ ) + qv_key_out( divdefaults[i] | (i<<3)); + for (i = 0; i < KBD_INIT_LENGTH; i++) + qv_key_out(kbdinitstring[i]); +} + +#define abs(x) (((x) > 0) ? (x) : (-(x))) +/* + * QVSS vertical sync interrupt + */ +qvvint(qv) + int qv; +{ + extern int selwait; + register struct qvdevice *qvaddr; + struct uba_device *ui; + register struct qv_info *qp = qv_scn; + int unit; + struct tty *tp0; + int i; + register int j; + /* + * Mouse state info + */ + static ushort omouse = 0, nmouse = 0; + static char omx=0, omy=0, mx=0, my=0, om_switch=0, m_switch=0; + register int dx, dy; + + /* + * Test and set the qv_ipl_lo flag. If the result is not zero then + * someone else must have already gotten here. + */ + if( --qv_ipl_lo ) + return; + (void)spl4(); + ui = qvinfo[qv]; + unit = qv<<2; + qvaddr = (struct qvdevice *)ui->ui_addr; + tp0 = &qv_tty[QVCHAN(unit) + QVMOUSECHAN]; + /* + * See if the mouse has moved. + */ + if( omouse != (nmouse = qvaddr->qv_mouse) ) { + omouse = nmouse; + mx = nmouse & 0xff; + my = nmouse >> 8; + dy = my - omy; omy = my; + dx = mx - omx; omx = mx; + if( dy < 50 && dy > -50 && dx < 50 && dx > -50 ) { + register vsEvent *vep; + if( qp->mscale < 0 ) { /* Ray Lanza's original */ + if( dy < 0 ) + dy = -( dy * dy ); + else + dy *= dy; + if( dx < 0 ) + dx = -( dx * dx ); + else + dx *= dx; + } + else { /* Vs100 style, see WGA spec */ + int thresh = qp->mthreshold; + int scale = qp->mscale; + if( abs(dx) > thresh ) { + if ( dx < 0 ) + dx = (dx + thresh)*scale - thresh; + else + dx = (dx - thresh)*scale + thresh; + } + if( abs(dy) > thresh ) { + if ( dy < 0 ) + dy = (dy + thresh)*scale - thresh; + else + dy = (dy - thresh)*scale + thresh; + } + } + qp->mouse.x += dx; + qp->mouse.y -= dy; + if( qp->mouse.x < 0 ) + qp->mouse.x = 0; + if( qp->mouse.y < 0 ) + qp->mouse.y = 0; + if( qp->mouse.x > qp->max_cur_x ) + qp->mouse.x = qp->max_cur_x; + if( qp->mouse.y > qp->max_cur_y ) + qp->mouse.y = qp->max_cur_y; + if( tp0->t_state & TS_ISOPEN ) + qv_pos_cur( qp->mouse.x, qp->mouse.y ); + if (qp->mouse.y < qp->mbox.bottom && + qp->mouse.y >= qp->mbox.top && + qp->mouse.x < qp->mbox.right && + qp->mouse.x >= qp->mbox.left) goto switches; + qp->mbox.bottom = 0; /* trash box */ + if (EVROUND(qp->itail+1) == qp->ihead) + goto switches; + i = EVROUND(qp->itail - 1); + if ((qp->itail != qp->ihead) && (i != qp->ihead)) { + vep = & qp->ibuff[i]; + if(vep->vse_type == VSE_MMOTION) { + vep->vse_x = qp->mouse.x; + vep->vse_y = qp->mouse.y; + goto switches; + } + } + /* put event into queue and do select */ + vep = & qp->ibuff[qp->itail]; + vep->vse_type = VSE_MMOTION; + vep->vse_time = TOY; + vep->vse_x = qp->mouse.x; + vep->vse_y = qp->mouse.y; + qp->itail = EVROUND(qp->itail+1); + } + } + /* + * See if mouse switches have changed. + */ +switches:if( om_switch != ( m_switch = (qvaddr->qv_csr & QV_MOUSE_ANY) >> 8 ) ) { + qp->mswitches = ~m_switch & 0x7; + for (j = 0; j < 3; j++) { /* check each switch */ + register vsEvent *vep; + if ( ((om_switch>>j) & 1) == ((m_switch>>j) & 1) ) + continue; + /* check for room in the queue */ + if ((i = EVROUND(qp->itail+1)) == qp->ihead) return; + /* put event into queue and do select */ + vep = &qp->ibuff[qp->itail]; + vep->vse_type = VSE_BUTTON; + vep->vse_key = 2 - j; + vep->vse_direction = VSE_KBTDOWN; + if ( (m_switch >> j) & 1) + vep->vse_direction = VSE_KBTUP; + vep->vse_device = VSE_MOUSE; + vep->vse_time = TOY; + vep->vse_x = qp->mouse.x; + vep->vse_y = qp->mouse.y; + } + qp->itail = i; + om_switch = m_switch; + qp->mswitches = m_switch; + } + /* if we have proc waiting, and event has happened, wake him up */ + if(qvrsel && (qp->ihead != qp->itail)) { + selwakeup(qvrsel,0); + qvrsel = 0; + } + /* + * Okay we can take another hit now + */ + qv_ipl_lo = 1; +} + +/* + * Start transmission + */ +qvstart(tp) + register struct tty *tp; +{ + register int unit, c; + register struct tty *tp0; + int s; + + unit = minor(tp->t_dev); +#ifdef CONS_HACK + tp0 = &qv_tty[(unit&0xfc)+QVPCONS]; +#endif + unit = QVCHAN(unit); + + s = spl5(); + /* + * If it's currently active, or delaying, no need to do anything. + */ + if (tp->t_state&(TS_TIMEOUT|TS_BUSY|TS_TTSTOP)) + goto out; + /* + * Display chars until the queue is empty, if the second subchannel + * is open direct them there. Drop characters from subchannels other + * than 0 on the floor. + */ + + while( tp->t_outq.c_cc ) { + c = getc(&tp->t_outq); + if (unit == QVKEYBOARD) +#ifdef CONS_HACK + if( tp0->t_state & TS_ISOPEN ){ + (*linesw[tp0->t_line].l_rint)(c, tp0); + } else +#endif + qvputchar( c & 0xff ); + } + /* + * Position the cursor to the next character location. + */ + qv_pos_cur( qv_scn->col*8, qv_scn->row*15 ); + + /* + * If there are sleepers, and output has drained below low + * water mark, wake up the sleepers. + */ + if ( tp->t_outq.c_cc<= tp->t_lowat ) { + if (tp->t_state&TS_ASLEEP){ + tp->t_state &= ~TS_ASLEEP; + wakeup((caddr_t)&tp->t_outq); + } + } + tp->t_state &= ~TS_BUSY; +out: + splx(s); +} + +/* + * Stop output on a line, e.g. for ^S/^Q or output flush. + */ +/*ARGSUSED*/ +void +qvstop(tp, flag) + register struct tty *tp; + int flag; +{ + register int s; + + /* + * Block input/output interrupts while messing with state. + */ + s = spl5(); + if (tp->t_state & TS_BUSY) { + if ((tp->t_state&TS_TTSTOP)==0) { + tp->t_state |= TS_FLUSH; + } else + tp->t_state &= ~TS_BUSY; + } + splx(s); +} + +qvputc(c) +char c; +{ + qvputchar(c); + if (c == '\n') + qvputchar('\r'); +} + +/* + * Routine to display a character on the screen. The model used is a + * glass tty. It is assummed that the user will only use this emulation + * during system boot and that the screen will be eventually controlled + * by a window manager. + * + */ +qvputchar( c ) +register char c; +{ + + register char *b_row, *f_row; + register int i; + register short *scanline; + register int ote = 128; + register struct qv_info *qp = qv_scn; + + /* + * This routine may be called in physical mode by the dump code + * so we check and punt if that's the case. + */ + if( (mfpr(MAPEN) & 1) == 0 ) + return; + + c &= 0x7f; + + switch ( c ) { + case '\t': /* tab */ + for( i = 8 - (qp->col & 0x7) ; i > 0 ; i-- ) + qvputchar( ' ' ); + break; + + case '\r': /* return */ + qp->col = 0; + break; + + case '\010': /* backspace */ + if( --qp->col < 0 ) + qp->col = 0; + break; + + case '\n': /* linefeed */ + if( qp->row+1 >= qp->max_row ) + qvscroll(); + else + qp->row++; + /* + * Position the cursor to the next character location. + */ + qv_pos_cur( qp->col*8, qp->row*15 ); + break; + + case '\007': /* bell */ + /* + * We don't do anything to the keyboard until after + * autoconfigure. + */ + if( qp->qvaddr ) + qv_key_out( LK_RING_BELL ); + return; + + default: + if( c >= ' ' && c <= '~' ) { + scanline = qp->scanmap; + b_row = qp->bitmap+(scanline[qp->row*15]&0x3ff)*128+qp->col; + i = c - ' '; + if( i < 0 || i > 95 ) + i = 0; + else + i *= 15; + f_row = (char *)((int)q_font + i); + +/* for( i=0 ; i<15 ; i++ , b_row += 128, f_row++ ) + *b_row = *f_row;*/ + /* inline expansion for speed */ + *b_row = *f_row++; b_row += ote; + *b_row = *f_row++; b_row += ote; + *b_row = *f_row++; b_row += ote; + *b_row = *f_row++; b_row += ote; + *b_row = *f_row++; b_row += ote; + *b_row = *f_row++; b_row += ote; + *b_row = *f_row++; b_row += ote; + *b_row = *f_row++; b_row += ote; + *b_row = *f_row++; b_row += ote; + *b_row = *f_row++; b_row += ote; + *b_row = *f_row++; b_row += ote; + *b_row = *f_row++; b_row += ote; + *b_row = *f_row++; b_row += ote; + *b_row = *f_row++; b_row += ote; + *b_row = *f_row++; b_row += ote; + + if( ++qp->col >= qp->max_col ) { + qp->col = 0 ; + if( qp->row+1 >= qp->max_row ) + qvscroll(); + else + qp->row++; + } + } + break; + } +} + +/* + * Position the cursor to a particular spot. + */ +qv_pos_cur( x, y) +register int x,y; +{ + register struct qvdevice *qvaddr; + register struct qv_info *qp = qv_scn; + register index; + + if( qvaddr = qp->qvaddr ) { + if( y < 0 || y > qp->max_cur_y ) + y = qp->max_cur_y; + if( x < 0 || x > qp->max_cur_x ) + x = qp->max_cur_x; + qp->cursor.x = x; /* keep track of real cursor*/ + qp->cursor.y = y; /* position, indep. of mouse*/ + + qvaddr->qv_crtaddr = 10; /* select cursor start reg */ + qvaddr->qv_crtdata = y & 0xf; + qvaddr->qv_crtaddr = 11; /* select cursor end reg */ + qvaddr->qv_crtdata = y & 0xf; + qvaddr->qv_crtaddr = 14; /* select cursor y pos. */ + qvaddr->qv_crtdata = y >> 4; + qvaddr->qv_xcur = x; /* pos x axis */ + /* + * If the mouse is being used then we change the mode of + * cursor display based on the pixels under the cursor + */ + if( mouseon ) { + index = y*128 + x/8; + if( qp->bitmap[ index ] && qp->bitmap[ index+128 ] ) + qvaddr->qv_csr &= ~QV_CUR_MODE; + else + qvaddr->qv_csr |= QV_CUR_MODE; + } + } +} +/* + * Scroll the bitmap by moving the scanline map words. This could + * be done by moving the bitmap but it's much too slow for a full screen. + * The only drawback is that the scanline map must be reset when the user + * wants to do graphics. + */ +qvscroll() +{ + short tmpscanlines[15]; + register char *b_row; + register short *scanline; + register struct qv_info *qp = qv_scn; + + /* + * If the mouse is on we don't scroll so that the bit map + * remains sane. + */ + if( mouseon ) { + qp->row = 0; + return; + } + /* + * Save the first 15 scanlines so that we can put them at + * the bottom when done. + */ + bcopy((caddr_t)qp->scanmap, (caddr_t)tmpscanlines, sizeof tmpscanlines); + + /* + * Clear the wrapping line so that it won't flash on the bottom + * of the screen. + */ + scanline = qp->scanmap; + b_row = qp->bitmap+(*scanline&0x3ff)*128; + bzero( b_row, 1920 ); + + /* + * Now move the scanlines down + */ + bcopy((caddr_t)(qp->scanmap+15), (caddr_t)qp->scanmap, + (qp->row * 15) * sizeof (short) ); + + /* + * Now put the other lines back + */ + bcopy((caddr_t)tmpscanlines, (caddr_t)(qp->scanmap+(qp->row * 15)), + sizeof (tmpscanlines) ); + +} + +/* + * Output to the keyboard. This routine status polls the transmitter on the + * keyboard to output a code. The timer is to avoid hanging on a bad device. + */ +qv_key_out(c) + u_short c; +{ + int timer = 30000; + register struct qv_info *qp = qv_scn; + + if (qp->qvaddr) { + while ((qp->qvaddr->qv_uartstatus & 0x4) == 0 && timer--) + ; + qp->qvaddr->qv_uartdata = c; + } +} +/* + * Virtual console initialization. This routine sets up the qvss so that it can + * be used as the system console. It is invoked before autoconfig and has to do + * everything necessary to allow the device to serve as the system console. + * In this case it must map the q-bus and device areas and initialize the qvss + * screen. + */ +qvcons_init() +{ + struct percpu *pcpu; /* pointer to percpu structure */ + register struct qbus *qb; + struct qvdevice *qvaddr; /* device pointer */ + short *devptr; /* virtual device space */ + extern cnputc(); /* standard serial console putc */ +#define QVSSCSR 017200 + + /* + * If secondary console already configured, + * don't override the previous one. + */ + if (v_putc != cnputc) + return 0; + /* + * find the percpu entry that matches this machine. + */ + for( pcpu = percpu ; pcpu && pcpu->pc_cputype != cpu ; pcpu++ ) + ; + if( pcpu == NULL ) + return 0; + if (pcpu->pc_io->io_type != IO_QBUS) + return 0; + + /* + * Found an entry for this cpu. Because this device is Microvax specific + * we assume that there is a single q-bus and don't have to worry about + * multiple adapters. + * + * Map the device registers. + */ + qb = (struct qbus *)pcpu->pc_io->io_details; + ioaccess(qb->qb_iopage, UMEMmap[0] + qb->qb_memsize, UBAIOPAGES * NBPG); + + /* + * See if the qvss is there. + */ + devptr = (short *)((char *)umem[0] + (qb->qb_memsize * NBPG)); + qvaddr = (struct qvdevice *)((u_int)devptr + ubdevreg(QVSSCSR)); + if (badaddr((caddr_t)qvaddr, sizeof(short))) + return 0; + /* + * Okay the device is there lets set it up + */ + if (!qv_setup(qvaddr, 0, 0)) + return 0; + v_putc = qvputc; + consops = &cdevsw[QVSSMAJOR]; + return 1; +} +/* + * Do the board specific setup + */ +qv_setup(qvaddr, unit, probed) +struct qvdevice *qvaddr; +int unit; +int probed; +{ + caddr_t qvssmem; /* pointer to the display mem */ + register i; /* simple index */ + register struct qv_info *qp; + register int *pte; + struct percpu *pcpu; /* pointer to percpu structure */ + register struct qbus *qb; + + /* + * find the percpu entry that matches this machine. + */ + for( pcpu = percpu ; pcpu && pcpu->pc_cputype != cpu ; pcpu++ ) + ; + if( pcpu == NULL ) + return(0); + + /* + * Found an entry for this cpu. Because this device is Microvax specific + * we assume that there is a single q-bus and don't have to worry about + * multiple adapters. + * + * Map the device memory. + */ + qb = (struct qbus *)pcpu->pc_io->io_details; + + i = (u_int)(qvaddr->qv_csr & QV_MEM_BANK) << 7; + ioaccess(qb->qb_maddr + i, QVmap[unit], 512 * NBPG); + qvssmem = qvmem[unit]; + pte = (int *)(QVmap[unit]); + for (i=0; i < 512; i++, pte++) + *pte = (*pte & ~PG_PROT) | PG_UW | PG_V; + + qv_scn = (struct qv_info *)((u_int)qvssmem + 251*1024); + qp = qv_scn; + if( (qvaddr->qv_csr & QV_19INCH) && qv_def_scrn == 0) + qv_def_scrn = 1; + *qv_scn = qv_scn_defaults[ qv_def_scrn ]; + if (probed) + qp->qvaddr = qvaddr; + qp->bitmap = qvssmem; + qp->scanmap = (short *)((u_int)qvssmem + 254*1024); + qp->cursorbits = (short *)((u_int)qvssmem + 256*1024-32); + /* set up event queue for later */ + qp->ibuff = (vsEvent *)qp - QVMAXEVQ; + qp->iqsize = QVMAXEVQ; + qp->ihead = qp->itail = 0; + + /* + * Setup the crt controller chip. + */ + for( i=0 ; i<16 ; i++ ) { + qvaddr->qv_crtaddr = i; + qvaddr->qv_crtdata = qv_crt_parms[ qv_def_scrn ][ i ]; + } + /* + * Setup the display. + */ + qv_init( qvaddr ); + + /* + * Turn on the video + */ + qvaddr->qv_csr |= QV_VIDEO_ENA ; + return 1; +} +#endif diff --git a/sys/arch/vax/uba/tmscp.c b/sys/arch/vax/uba/tmscp.c deleted file mode 100644 index ef490d93e3d..00000000000 --- a/sys/arch/vax/uba/tmscp.c +++ /dev/null @@ -1,2211 +0,0 @@ -/* $NetBSD: tmscp.c,v 1.12 1996/04/08 18:37:30 ragge Exp $ */ - -/*- - * Copyright (c) 1991 The Regents of the University of California. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)tmscp.c 7.16 (Berkeley) 5/9/91 - */ - -/* - * sccsid = "@(#)tmscp.c 1.24 (ULTRIX) 1/21/86"; - */ - -/************************************************************************ - * * - * Licensed from Digital Equipment Corporation * - * Copyright (c) * - * Digital Equipment Corporation * - * Maynard, Massachusetts * - * 1985, 1986 * - * All rights reserved. * - * * - * The Information in this software is subject to change * - * without notice and should not be construed as a commitment * - * by Digital Equipment Corporation. Digital makes no * - * representations about the suitability of this software for * - * any purpose. It is supplied "As Is" without expressed or * - * implied warranty. * - * * - * If the Regents of the University of California or its * - * licensees modify the software in a manner creating * - * diriviative copyright rights, appropriate copyright * - * legends may be placed on the drivative work in addition * - * to that set forth above. * - * * - ************************************************************************ - * - * tmscp.c - TMSCP (TK50/TU81) tape device driver - * - * Modification History: - * - * 06-Jan-86 - afd - * Changed the probe routine to use DELAY (not TODR). This now - * works for MicroVAXen as well. This eliminates the busy-wait - * for MicroVAXen so a dead TK50 controller will not hang autoconf. - * - * 06-Dec-85 - afd - * Fixed a bug in density selection. The "set unit characteristics" - * command to select density, was clearing the "unit flags" field - * where the CACHE bit was for TU81-E. Now the unit's "format" and - * "unitflgs" are saved in tms_info struct. And are used on STUNT - * commands. - * - * 19-Oct-85 - afd - * Added support to the open routine to allow drives to be opened - * for low density (800 or 1600 bpi) use. When the slave routine - * initiates a "get-unit-char" cmd, the format menu for the unit - * is saved in the tms_info structure. The format menu is used in the - * start routine to select the proper low density. - * - * 02-Oct-85 - afd - * When a tmscp-type controller is initializing, it is possible for - * the sa reg to become 0 between states. Thus the init code in - * the interrupt routine had to be modified to reflect this. - * - * 21-Sep-85 - afd - * The TK50 declares a serious exception when a tape mark is encountered. - * This causes problems to dd (& other UN*X utilities). So a flag - * is set in the rsp() routine when a tape mark is encountered. If - * this flag is set, the start() routine appends the Clear Serious - * Exception modifier to the next command. - * - * 03-Sep-85 -- jaw - * messed up previous edit.. - * - * 29-Aug-85 - jaw - * fixed bugs in 8200 and 750 buffered datapath handling. - * - * 06-Aug-85 - afd - * 1. When repositioning records or files, the count of items skipped - * does NOT HAVE to be returned by controllers (& the TU81 doesn't). - * So tmscprsp() had to be modified to stop reporting - * residual count errors on reposition commands. - * - * 2. Fixed bug in the open routine which allowed multiple opens. - * - * 18-Jul-85 - afd - * 1. Need to return status when mt status (or corresponding ioctl) is done. - * Save resid, flags, endcode & status in tmscprsp() routine (except on - * clear serious exception no-op). Return these fields when status - * ioctl is done (in tmscpcommand()). How they are returned: - * mt_resid = resid - * mt_dsreg = flags|endcode - * mt_erreg = status - * - * 2. Added latent support for enabling/disabling caching. This is - * handled along with all other ioctl commands. - * - * 3. Need to issue a no-op on unrecognized ioctl in tmscpstart(), since - * we have already commited to issuing a command at that point. - * - * 4. In tmscprsp() routine if encode is 0200 (invalid command issued); - * We need to: Unlink the buffer from the I/O wait queue, - * and signal iodone, so the higher level command can exit! - * Just as if it were a valid command. - * - * 11-jul-85 -- jaw - * fix bua/bda map registers. - * - * 19-Jun-85 -- jaw - * VAX8200 name change. - * - * 06-Jun-85 - jaw - * fixes for 8200. - * - * 9-Apr-85 - afd - * Added timeout code to the probe routine, so if the controller - * fails to init in 10 seconds we return failed status. - * - * 13-Mar-85 -jaw - * Changes for support of the VAX8200 were merged in. - * - * 27-Feb-85 -tresvik - * Changes for support of the VAX8600 were merged in. - * - */ - -#define NTMS 2 /* XXX - This is _wery_ kludgy! /ragge */ - -#include "tmscp.h" -#if NTMSCP > 0 - -#include <sys/param.h> -#include <sys/systm.h> -#include <sys/buf.h> -#include <sys/conf.h> -#include <sys/errno.h> -#include <sys/file.h> -#include <sys/map.h> -#include <sys/ioctl.h> -#include <sys/syslog.h> -#include <sys/mtio.h> -/* #include <sys/cmap.h> */ -#include <sys/uio.h> -#include <sys/proc.h> -#include <sys/tprintf.h> -#include <sys/proc.h> - -#include <machine/pte.h> -#include <machine/cpu.h> -#include <machine/mtpr.h> -#include <machine/sid.h> - -#include <vax/uba/ubareg.h> -#include <vax/uba/ubavar.h> - -#define TENSEC (1000) -#define TMS_PRI LOG_INFO - -#define NRSPL2 3 /* log2 number of response packets */ -#define NCMDL2 3 /* log2 number of command packets */ -#define NRSP (1<<NRSPL2) -#define NCMD (1<<NCMDL2) - -#include <vax/uba/tmscpreg.h> -#include <vax/vax/tmscpinf.h> -#include <vax/vax/mscpvar.h> - -int tmscp_match __P((struct device *, void *, void *)); -void tmscp_attach __P((struct device *, struct device *, void *)); -void tmscpstrategy __P((struct buf *)); - -struct cfdriver tmscp_cd = { - NULL, "tmscp", DV_DULL -}; - -struct cfattach tmscp_ca = { - sizeof(struct device), tmscp_match, tmscp_attach -}; - -/* Software state per controller */ - -struct tmscp_softc { - short sc_state; /* state of controller */ - short sc_mapped; /* Unibus map allocated for tmscp struct? */ - int sc_ubainfo; /* Unibus mapping info */ - struct tmscp *sc_tmscp; /* Unibus address of tmscp struct */ - int sc_ivec; /* interrupt vector address */ - short sc_credits; /* transfer credits */ - short sc_lastcmd; /* pointer into command ring */ - short sc_lastrsp; /* pointer into response ring */ - short sc_ipl; /* interrupt priority (Q-bus) */ -} tmscp_softc[NTMSCP]; - -struct tmscp { - struct tmscpca tmscp_ca; /* communications area */ - struct mscp tmscp_rsp[NRSP]; /* response packets */ - struct mscp tmscp_cmd[NCMD]; /* command packets */ -} tmscp[NTMSCP]; - -int tmscpprobe __P((caddr_t, int, struct uba_ctlr *, struct uba_softc *)); -int tmscpslave __P((struct uba_device *, caddr_t)); -int tmscpinit __P((int)); -void tmscpattach __P((struct uba_device *)); -void tmscpintr __P((int)); -void tmscprsp __P((struct uba_ctlr *, struct tmscp *, - struct tmscp_softc *, int)); -void tmscpstart __P((struct uba_ctlr *)); -void tmscpcommand __P((dev_t, int, int)); -struct mscp *tmscpgetcp __P((struct uba_ctlr *)); -void errinfo __P((int)); -int tmscpcmd __P((int, struct tmscp *, struct tmscpdevice *)); - -int tmscpopen __P((dev_t, int, int, struct proc *p)); -int tmscpclose __P((dev_t, int, int, struct proc *p)); -void tmscpstrategy __P((struct buf *)); -int tmscpread __P((dev_t, struct uio *)); -int tmscpwrite __P((dev_t, struct uio *)); -int tmscpdump __P((dev_t, daddr_t, caddr_t, size_t)); -int tmscpioctl __P((dev_t, u_long, caddr_t, int, struct proc *)); -void tmscpreset __P((int)); - -/* - * Per drive-unit info - */ -struct tms_info { - daddr_t tms_dsize; /* Max user size from online pkt */ - unsigned tms_type; /* Drive type int field */ - int tms_resid; /* residual from last xfer */ - u_char tms_endcode; /* last command endcode */ - u_char tms_flags; /* last command end flags */ - unsigned tms_status; /* Command status from last command */ - char tms_openf; /* lock against multiple opens */ - char tms_lastiow; /* last op was a write */ - char tms_serex; /* set when serious exception occurs */ - char tms_clserex; /* set when serex being cleared by no-op */ - short tms_fmtmenu; /* the unit's format (density) menu */ - short tms_unitflgs; /* unit flag parameters */ - short tms_format; /* the unit's current format (density) */ - tpr_t tms_tpr; /* tprintf handle */ -} tms_info[NTMS]; - -void tmserror __P((struct uba_ctlr *, struct mslg *)); - - -struct uba_ctlr *tmscpminfo[NTMSCP]; -struct uba_device *tmsdinfo[NTMS]; -/* - * ifdef other tmscp devices here if they allow more than 1 unit/controller - */ -struct uba_device *tmscpip[NTMSCP][1]; -struct buf ctmscpbuf[NTMSCP]; /* internal cmd buffer (for ioctls) */ -struct buf tmsutab[NTMS]; /* Drive queue */ -struct buf tmscpwtab[NTMSCP]; /* I/O wait queue, per controller */ -int tmscpmicro[NTMSCP]; /* to store microcode level */ -short utoctlr[NTMS]; /* Slave unit to controller mapping */ - /* filled in by the slave routine */ - -/* Bits in minor device */ -#define TMSUNIT(dev) (minor(dev)&03) -#define T_HIDENSITY 010 - -/* Slave unit to controller mapping */ -#define TMSCPCTLR(dev) (utoctlr[TMSUNIT(dev)]) - -/* - * Internal (ioctl) command codes (these must also be declared in the - * tmscpioctl routine). These correspond to ioctls in mtio.h - */ -#define TMS_WRITM 0 /* write tape mark */ -#define TMS_FSF 1 /* forward space file */ -#define TMS_BSF 2 /* backward space file */ -#define TMS_FSR 3 /* forward space record */ -#define TMS_BSR 4 /* backward space record */ -#define TMS_REW 5 /* rewind tape */ -#define TMS_OFFL 6 /* rewind tape & mark unit offline */ -#define TMS_SENSE 7 /* noop - do a get unit status */ -#define TMS_CACHE 8 /* enable cache */ -#define TMS_NOCACHE 9 /* disable cache */ -/* These go last: after all real mt cmds, just bump the numbers up */ -#define TMS_CSE 10 /* clear serious exception */ -#define TMS_LOWDENSITY 11 /* set unit to low density */ -#define TMS_HIDENSITY 12 /* set unit to high density */ - -/* - * Controller states - */ -#define S_IDLE 0 /* hasn't been initialized */ -#define S_STEP1 1 /* doing step 1 init */ -#define S_STEP2 2 /* doing step 2 init */ -#define S_STEP3 3 /* doing step 3 init */ -#define S_SCHAR 4 /* doing "set controller characteristics" */ -#define S_RUN 5 /* running */ - -int tmscperror = 0; /* causes hex dump of packets */ -int tmscp_cp_wait = 0; /* Something to wait on for command */ - /* packets and or credits. */ -extern int hz; /* Should find the right include */ - -#ifdef DEBUG -#define printd if (tmscpdebug) printf -int tmscpdebug = 1; -#define printd10 if(tmscpdebug >= 10) printf -#endif - -#define DRVNAME "tms" -#define CTRLNAME "tmscp" - -u_short tmscpstd[] = { 0174504, 0 }; -struct uba_driver tmscpdriver = -{ tmscpprobe, tmscpslave, tmscpattach, 0, tmscpstd, DRVNAME, tmsdinfo, CTRLNAME -, tmscpminfo, 0}; - -#define b_qsize b_resid /* queue size per drive, in tmsutab */ -#define b_ubinfo b_resid /* Unibus mapping info, per buffer */ - - -/*************************************************************************/ - -#define DELAYTEN 1000 -extern struct cfdriver uba_cd; - -/* - * Unfortunately qbgetpri can't be used because the TK50 doesn't flip the - * TMSCP_STEP2 flag in the tmscpsa register until after the pending interrupt - * has been acknowledged by the cpu. If you are at spl6(), the TMSCP_STEP2 - * flag never gets set and you return (0). - */ -int -tmscpprobe(reg, ctlr, um, uh) - caddr_t reg; /* address of the IP register */ - int ctlr; /* index of controller in the tmscp_softc array */ - struct uba_ctlr *um; - struct uba_softc *uh; -{ - /* register int br, cvec; MUST be 1st (r11 & r10): IPL and intr vec */ - register struct tmscp_softc *sc = &tmscp_softc[ctlr]; - /* ptr to software controller structure */ - volatile struct tmscpdevice *tmscpaddr; - int count; /* for probe delay time out */ - struct uba_softc *ubasc; - -# ifdef lint - br = 0; cvec = br; br = cvec; reg = reg; - tmscpreset(0); tmscpintr(0); -# endif - - tmscpminfo[ctlr] = um; - tmscpaddr = (struct tmscpdevice *) reg; - /* - * Set host-settable interrupt vector. - * Assign 0 to the ip register to start the tmscp-device initialization. - * The device is not really initialized at this point, this is just to - * find out if the device exists. - */ - ubasc = uba_cd.cd_devs[0]; /* XXX */ - sc->sc_ivec = (ubasc->uh_lastiv -= 4); - tmscpaddr->tmscpip = 0; - - count=0; - while(count < DELAYTEN) - { /* wait for at most 10 secs */ - if((tmscpaddr->tmscpsa & TMSCP_STEP1) != 0) - break; - DELAY(10000); - count=count+1; - } - if (count == DELAYTEN) - return(0); - - tmscpaddr->tmscpsa = TMSCP_ERR|(NCMDL2<<11)|(NRSPL2<<8)|TMSCP_IE|(sc->sc_ivec/4); - - count=0; - while(count < DELAYTEN) - { - if((tmscpaddr->tmscpsa & TMSCP_STEP2) != 0) - break; - DELAY(10000); - count = count+1; - } - if (count == DELAYTEN) - return(0); - -#ifdef QBA - sc->sc_ipl = 0x15; -#endif - return(sizeof (struct tmscpdevice)); -} - -/* - * Try to find a slave (a drive) on the controller. - * If the controller is not in the run state, call init to initialize it. - */ -int -tmscpslave (ui, reg) - struct uba_device *ui; /* ptr to the uba device structure */ - caddr_t reg; /* addr of the device controller */ -{ - register struct uba_ctlr *um = tmscpminfo[ui->ui_ctlr]; - volatile struct tmscp_softc *sc = &tmscp_softc[ui->ui_ctlr]; - volatile struct tms_info *tms = &tms_info[ui->ui_unit]; - volatile struct tmscpdevice *tmscpaddr; /* ptr to IP & SA */ - volatile struct mscp *mp; - volatile int i; /* Something to write into to start */ - /* the tmscp polling */ - -# ifdef lint - reg = reg; -# endif - tmscpaddr = (struct tmscpdevice *)um->um_addr; - /* - * If its not in the run state, start the initialization process - * (tmscpintr will complete it); if the initialization doesn't start; - * then return. - */ - if(sc->sc_state != S_RUN) - { -# ifdef DEBUG - printd("tmscpslave: ctlr not running: calling init \n"); -# endif - if(!tmscpinit(ui->ui_ctlr)) - return(0); - } - /* - * Wait for the controller to come into the run state or go idle. - * If it goes idle return. - */ -# ifdef DEBUG - i=1; -# endif - while(sc->sc_state != S_RUN && sc->sc_state != S_IDLE) -# ifdef DEBUG - if (tmscpaddr->tmscpsa & TMSCP_ERR && i) - { - printd("tmscp-device: fatal error (%o)\n", tmscpaddr->tmscpsa&0xffff); - i=0; - } -# endif - ; /* wait */ - if(sc->sc_state == S_IDLE) - { /* The tmscp device failed to initialize */ - printf("tmscp controller failed to init\n"); - return(0); - } - /* The controller is up so see if the drive is there */ - if(0 == (mp = tmscpgetcp(um))) - { - printf("tmscp can't get command packet\n"); - return(0); - } - /* Need to determine the drive type for generic driver */ - mp->mscp_opcode = M_OP_GTUNT; /* This should give us the device type */ - mp->mscp_unit = ui->ui_slave; - mp->mscp_cmdref = (long) ui->ui_slave; - tms->tms_status = 0; /* set to zero */ - tmscpip[ui->ui_ctlr][ui->ui_slave] = ui; - *((long *) mp->mscp_dscptr ) |= TMSCP_OWN | TMSCP_INT;/* maybe we should poll*/ - i = tmscpaddr->tmscpip; -#ifdef lint - i = i; -#endif - while(!tms->tms_status) - ; /* Wait for some status */ -# ifdef DEBUG - printd("tmscpslave: status = %o\n",tms->tms_status & M_ST_MASK); -# endif - tmscpip[ui->ui_ctlr][ui->ui_slave] = 0; - if(!tms->tms_type) /* packet from a GTUNT */ - return(0); /* Failed No such drive */ - else - return(1); /* Got it and it is there */ -} - - -/* - * Set ui flags to zero to show device is not online & set tmscpip. - * Unit to Controller mapping is set up here. - * Open routine will issue the online command, later. - */ -void -tmscpattach (ui) - register struct uba_device *ui; /* ptr to unibus dev struct */ -{ - - ui->ui_flags = 0; - tmscpip[ui->ui_ctlr][ui->ui_slave] = ui; -# ifdef DEBUG - /* - * Check to see if the drive is available. - * If not then just print debug. - */ - if(tms_info[ui->ui_unit].tms_status != M_ST_AVLBL) - printd("tmscpattach: unavailable \n"); -# endif - utoctlr[ui->ui_unit] = ui->ui_ctlr; -} - - -/* - * TMSCP interrupt routine. - */ -void -tmscpintr(d) - int d; -{ - volatile struct uba_ctlr *um = tmscpminfo[d]; - volatile struct tmscpdevice *tmscpaddr = - (struct tmscpdevice *)um->um_addr; - struct buf *bp; - volatile int i; - volatile struct tmscp_softc *sc = &tmscp_softc[d]; - struct tmscp *tm = &tmscp[d]; - struct tmscp *ttm; - volatile struct mscp *mp; - -# ifdef DEBUG - printd10("tmscpintr: state %d, tmscpsa %o\n", sc->sc_state, tmscpaddr->tmscpsa); -# endif - -#ifdef QBA - if (cpunumber == VAX_78032) - splx(sc->sc_ipl); -#endif - /* - * How the interrupt is handled depends on the state of the controller. - */ - switch (sc->sc_state) { - - case S_IDLE: - printf("tmscp%d: random interrupt ignored\n", d); - return; - - /* Controller was in step 1 last, see if its gone to step 2 */ - case S_STEP1: -# define STEP1MASK 0174377 -# define STEP1GOOD (TMSCP_STEP2|TMSCP_IE|(NCMDL2<<3)|NRSPL2) - for (i = 0; i < 150; i++) - { - if ((tmscpaddr->tmscpsa&STEP1MASK) != STEP1GOOD) - { /* still in step 1 (wait 1/100 sec) */ - DELAY(10000); -# ifdef DEBUG - printd("still in step 1, delaying\n"); -# endif DEBUG - } - else - break; - } - if (i > 149) - { - sc->sc_state = S_IDLE; - printf("failed to initialize, in step1: sa 0x%x", tmscpaddr->tmscpsa); - wakeup((caddr_t)um); - return; - } - tmscpaddr->tmscpsa = ((int)&sc->sc_tmscp->tmscp_ca.ca_ringbase) - | ((cpunumber == VAX_780 || cpunumber == VAX_8600) ? - TMSCP_PI : 0); - sc->sc_state = S_STEP2; - return; - - /* Controller was in step 2 last, see if its gone to step 3 */ - case S_STEP2: -# define STEP2MASK 0174377 -# define STEP2GOOD (TMSCP_STEP3|TMSCP_IE|(sc->sc_ivec/4)) - for (i = 0; i < 150; i++) - { - if ((tmscpaddr->tmscpsa&STEP2MASK) != STEP2GOOD) - { /* still in step 2 (wait 1/100 sec) */ - DELAY(10000); -# ifdef DEBUG - printd("still in step 2, delaying\n"); -# endif DEBUG - } - else - break; - } - if (i > 149) - { - sc->sc_state = S_IDLE; - printf("failed to initialize, in step2: sa 0x%x", tmscpaddr->tmscpsa); - wakeup((caddr_t)um); - return; - } - tmscpaddr->tmscpsa = ((int)&sc->sc_tmscp->tmscp_ca.ca_ringbase)>>16; - sc->sc_state = S_STEP3; - return; - - /* Controller was in step 3 last, see if its gone to step 4 */ - case S_STEP3: -# define STEP3MASK 0174000 -# define STEP3GOOD TMSCP_STEP4 - for (i = 0; i < 150; i++) - { - if ((tmscpaddr->tmscpsa&STEP3MASK) != STEP3GOOD) - { /* still in step 3 (wait 1/100 sec) */ - DELAY(10000); -# ifdef DEBUG - printd("still in step 3, delaying\n"); -# endif DEBUG - } - else - break; - } - if (i > 149) - { - sc->sc_state = S_IDLE; - printf("failed to initialize, in step3: sa 0x%x", tmscpaddr->tmscpsa); - wakeup((caddr_t)um); - return; - } - /* - * Get microcode version and model number of controller; - * Signal initialization complete (_GO) (to the controller); - * ask for Last Fail response if tmscperror is set; - * Set state to "set controller characteristics". - */ - tmscpmicro[d] = tmscpaddr->tmscpsa; - tmscpaddr->tmscpsa = TMSCP_GO | (tmscperror? TMSCP_LF : 0); - sc->sc_state = S_SCHAR; -# ifdef DEBUG - printd("tmscpintr: completed state %d \n", sc->sc_state); - printd("tmscp%d Version %d model %d\n",d,tmscpmicro[d]&0xF, - (tmscpmicro[d]>>4) & 0xF); -# endif - - /* - * Initialize the data structures (response and command queues). - */ - ttm = sc->sc_tmscp; - for (i = 0; i < NRSP; i++) - { - tm->tmscp_ca.ca_rspdsc[i] = TMSCP_OWN | TMSCP_INT | - (long)&ttm->tmscp_rsp[i].mscp_cmdref; - tm->tmscp_rsp[i].mscp_dscptr = &tm->tmscp_ca.ca_rspdsc[i]; - tm->tmscp_rsp[i].mscp_header.tmscp_msglen = mscp_msglen; - } - for (i = 0; i < NCMD; i++) - { - tm->tmscp_ca.ca_cmddsc[i] = TMSCP_INT | - (long)&ttm->tmscp_cmd[i].mscp_cmdref; - tm->tmscp_cmd[i].mscp_dscptr = &tm->tmscp_ca.ca_cmddsc[i]; - tm->tmscp_cmd[i].mscp_header.tmscp_msglen = mscp_msglen; - tm->tmscp_cmd[i].mscp_header.tmscp_vcid = 1; - } - bp = &tmscpwtab[d]; - bp->b_actf = NULL; - sc->sc_lastcmd = 1; - sc->sc_lastrsp = 0; - mp = &tmscp[d].tmscp_cmd[0]; - mp->mscp_unit = mp->mscp_modifier = 0; - mp->mscp_flags = 0; - mp->mscp_version = 0; - mp->mscp_cntflgs = M_CF_ATTN|M_CF_MISC|M_CF_THIS; - /* - * A host time out value of 0 means that the controller will not - * time out. This is ok for the TK50. - */ - mp->mscp_hsttmo = 0; - mp->mscp_time = 0; - mp->mscp_cntdep = 0; - mp->mscp_opcode = M_OP_STCON; - *((long *)mp->mscp_dscptr) |= TMSCP_OWN|TMSCP_INT; - i = tmscpaddr->tmscpip; /* initiate polling */ - return; - - case S_SCHAR: - case S_RUN: - break; - - default: - printf("tmscp%d: interrupt in unknown state %d ignored\n",d,sc->sc_state); - return; - } /* end switch */ - - /* - * The controller state is S_SCHAR or S_RUN - */ - - /* - * If the error bit is set in the SA register then print an error - * message and reinitialize the controller. - */ - if (tmscpaddr->tmscpsa&TMSCP_ERR) - { - printf("tmscp%d: fatal error (%o)\n", d, tmscpaddr->tmscpsa&0xffff); - tmscpaddr->tmscpip = 0; - wakeup((caddr_t)um); - } - /* - * Check for a buffer purge request. (Won't happen w/ TK50 on Q22 bus) - */ - if (tm->tmscp_ca.ca_bdp) - { - UBAPURGE(um->um_hd->uh_uba, tm->tmscp_ca.ca_bdp); - tm->tmscp_ca.ca_bdp = 0; - tmscpaddr->tmscpsa = 0; /* signal purge complete */ - } - - /* - * Check for response ring transition. - */ - if (tm->tmscp_ca.ca_rspint) - { - tm->tmscp_ca.ca_rspint = 0; - for (i = sc->sc_lastrsp;; i++) - { - i %= NRSP; - if (tm->tmscp_ca.ca_rspdsc[i]&TMSCP_OWN) - break; - tmscprsp((struct uba_ctlr *)um, tm, - (struct tmscp_softc *)sc, i); - tm->tmscp_ca.ca_rspdsc[i] |= TMSCP_OWN; - } - sc->sc_lastrsp = i; - } - - /* - * Check for command ring transition. - */ - if (tm->tmscp_ca.ca_cmdint) - { -# ifdef DEBUG - printd("tmscpintr: command ring transition\n"); -# endif - tm->tmscp_ca.ca_cmdint = 0; - } - if(tmscp_cp_wait) - wakeup((caddr_t)&tmscp_cp_wait); - (void) tmscpstart((struct uba_ctlr *)um); -} - - -/* - * Open a tmscp device and set the unit online. If the controller is not - * in the run state, call init to initialize the tmscp controller first. - */ - -/* ARGSUSED */ -int -tmscpopen(dev, flag, type, p) - dev_t dev; - int flag, type; - struct proc *p; -{ - register int unit; - register struct uba_device *ui; - register struct tmscp_softc *sc; - register struct tms_info *tms; - register volatile struct mscp *mp; - register struct uba_ctlr *um; - volatile struct tmscpdevice *tmscpaddr; - volatile int i; - int s; - - unit = TMSUNIT(dev); -# ifdef DEBUG - printd("tmscpopen unit %d\n",unit); - if(tmscpdebug)DELAY(10000); -# endif - if (unit >= NTMS || (ui = tmsdinfo[unit]) == 0 || ui->ui_alive == 0) - return (ENXIO); - tms = &tms_info[ui->ui_unit]; - if (tms->tms_openf) - return (EBUSY); - sc = &tmscp_softc[ui->ui_ctlr]; - tms->tms_openf = 1; - tms->tms_tpr = tprintf_open(curproc); - s = splbio(); - if (sc->sc_state != S_RUN) - { - if (sc->sc_state == S_IDLE) - if(!tmscpinit(ui->ui_ctlr)) - { - printf("tmscp controller failed to init\n"); - (void) splx(s); - tms->tms_openf = 0; - return(ENXIO); - } - /* - * Wait for initialization to complete - */ - timeout(wakeup,(caddr_t)ui->ui_mi,11*hz); /* to be sure*/ - sleep((caddr_t)ui->ui_mi, 0); - if (sc->sc_state != S_RUN) - { - (void) splx(s); - tms->tms_openf = 0; - return (EIO); - } - } - /* - * Check to see if the device is really there. - * this code was taken from Fred Canters 11 driver - */ - um = ui->ui_mi; - tmscpaddr = (struct tmscpdevice *) um->um_addr; - (void) splx(s); - if(ui->ui_flags == 0) - { - s = splbio(); - while(0 ==(mp = tmscpgetcp(um))) - { - tmscp_cp_wait++; - sleep((caddr_t)&tmscp_cp_wait,PSWP+1); - tmscp_cp_wait--; - } - (void) splx(s); - mp->mscp_opcode = M_OP_ONLIN; - mp->mscp_unit = ui->ui_slave; - mp->mscp_cmdref = (long) & tms->tms_type; - /* need to sleep on something */ -# ifdef DEBUG - printd("tmscpopen: bring unit %d online\n",ui->ui_unit); -# endif - *((long *) mp->mscp_dscptr ) |= TMSCP_OWN | TMSCP_INT; - i = tmscpaddr->tmscpip; -#ifdef lint - i = i; -#endif - /* - * To make sure we wake up, timeout in 240 seconds. - * Wakeup in tmscprsp routine. - * 240 seconds (4 minutes) is necessary since a rewind - * can take a few minutes. - */ - timeout(wakeup,(caddr_t) mp->mscp_cmdref,240 * hz); - sleep((caddr_t) mp->mscp_cmdref,PSWP+1); - } - if(ui->ui_flags == 0) { - tms->tms_openf = 0; - return(ENXIO); /* Didn't go online */ - } - tms->tms_lastiow = 0; - /* - * If the high density device is not specified, set unit to low - * density. This is done as an "internal" ioctl command so - * that the command setup and response handling - * is done thru "regular" command routines. - */ - if ((minor(dev) & T_HIDENSITY) == 0) - tmscpcommand(dev, TMS_LOWDENSITY, 1); - else - tmscpcommand(dev, TMS_HIDENSITY, 1); - return (0); -} - - -/* - * Close tape device. - * - * If tape was open for writing or last operation was - * a write, then write two EOF's and backspace over the last one. - * Unless this is a non-rewinding special file, rewind the tape. - * - * NOTE: - * We want to be sure that any serious exception is cleared on the - * close. A Clear Serious Exception (CSE) modifier is always done on - * the rewind command. For the non-rewind case we check to see if the - * "serex" field is set in the softc struct; if it is then issue a noop - * command with the CSE modifier. - * Make the tape available to others, by clearing openf flag. - */ -int -tmscpclose(dev, flag, type, p) - register dev_t dev; - register flag, type; - struct proc *p; -{ - register struct tms_info *tms; - register struct uba_device *ui; - - ui = tmsdinfo[TMSUNIT(dev)]; -# ifdef DEBUG - printd("tmscpclose: ctlr = %d\n",TMSCPCTLR(dev)); - printd("tmscpclose: unit = %d\n",TMSUNIT(dev)); - if(tmscpdebug)DELAY(10000); -# endif - tms = &tms_info[ui->ui_unit]; - if (flag == FWRITE || ((flag&FWRITE) && tms->tms_lastiow)) - { - /* device, command, count */ - tmscpcommand (dev, TMS_WRITM, 1); - tmscpcommand (dev, TMS_WRITM, 1); - tmscpcommand (dev, TMS_BSR, 1); - } - if ((minor(dev)&T_NOREWIND) == 0) - /* - * Don't hang waiting for rewind complete. - */ - tmscpcommand(dev, TMS_REW, 0); - else - if (tms->tms_serex) - { -# ifdef DEBUG - printd("tmscpclose: clearing serex\n"); - if(tmscpdebug)DELAY(10000); -# endif - tmscpcommand(dev, TMS_CSE, 1); - } - tprintf_close(tms->tms_tpr); - tms->tms_openf = 0; - return (0); -} - - -/* - * Execute a command on the tape drive a specified number of times. - * This routine sets up a buffer and calls the strategy routine which - * links the buffer onto the drive's buffer queue. - * The start routine will take care of creating a tmscp command packet - * with the command. The start routine is called by the strategy or the - * interrupt routine. - */ -void -tmscpcommand (dev, com, count) - register dev_t dev; - int com, count; -{ - register struct uba_device *ui; - register struct buf *bp; - register int s; - int unit = TMSUNIT(dev); - - ui = tmsdinfo[unit]; - bp = &ctmscpbuf[ui->ui_ctlr]; - - s = splbio(); - while (bp->b_flags&B_BUSY) - { - /* - * This special check is because B_BUSY never - * gets cleared in the non-waiting rewind case. - */ - if (bp->b_bcount == 0 && (bp->b_flags&B_DONE)) - break; - bp->b_flags |= B_WANTED; - sleep((caddr_t)bp, PRIBIO); - } - bp->b_flags = B_BUSY|B_READ; - splx(s); - /* - * Load the buffer. The b_count field gets used to hold the command - * count. the b_resid field gets used to hold the command mneumonic. - * These 2 fields are "known" to be "safe" to use for this purpose. - * (Most other drivers also use these fields in this way.) - */ - bp->b_dev = dev; - bp->b_bcount = count; - bp->b_resid = com; - bp->b_blkno = 0; - tmscpstrategy(bp); - /* - * In case of rewind from close, don't wait. - * This is the only case where count can be 0. - */ - if (count == 0) - return; - iowait(bp); - if (bp->b_flags&B_WANTED) - wakeup((caddr_t)bp); - bp->b_flags &= B_ERROR; -} - -/* - * Find an unused command packet - */ -struct mscp * -tmscpgetcp(um) - struct uba_ctlr *um; -{ - register volatile struct mscp *mp; - register volatile struct tmscpca *cp; - register struct tmscp_softc *sc; - register int i; - int s; - - s = splbio(); - cp = &tmscp[um->um_ctlr].tmscp_ca; - sc = &tmscp_softc[um->um_ctlr]; - /* - * If no credits, can't issue any commands - * until some outstanding commands complete. - */ - i = sc->sc_lastcmd; -# ifdef DEBUG - printd10("tmscpgetcp: %d credits remain\n", sc->sc_credits); -# endif - if(((cp->ca_cmddsc[i]&(TMSCP_OWN|TMSCP_INT))==TMSCP_INT) && - (sc->sc_credits >= 2)) - { - sc->sc_credits--; /* This commits to issuing a command */ - cp->ca_cmddsc[i] &= ~TMSCP_INT; - mp = &tmscp[um->um_ctlr].tmscp_cmd[i]; - mp->mscp_unit = mp->mscp_modifier = 0; - mp->mscp_opcode = mp->mscp_flags = 0; - mp->mscp_bytecnt = mp->mscp_buffer = 0; - sc->sc_lastcmd = (i + 1) % NCMD; - (void) splx(s); - return((struct mscp *)mp); - } - (void) splx(s); - return(NULL); -} - - -/* - * Initialize a TMSCP device. Set up UBA mapping registers, - * initialize data structures, and start hardware - * initialization sequence. - */ -int -tmscpinit (d) - int d; /* index to the controller */ -{ - register struct tmscp_softc *sc; - register struct tmscp *t; - volatile struct tmscpdevice *tmscpaddr; - struct uba_ctlr *um; - - sc = &tmscp_softc[d]; - um = tmscpminfo[d]; - um->um_tab.b_active++; - t = &tmscp[d]; - tmscpaddr = (struct tmscpdevice *)um->um_addr; - if (sc->sc_mapped == 0) - { - /* - * Map the communications area and command - * and response packets into Unibus address - * space. - */ - sc->sc_ubainfo = uballoc(um->um_ubanum, (caddr_t)t, sizeof (struct tmscp), 0); - sc->sc_tmscp = (struct tmscp *)(UBAI_ADDR(sc->sc_ubainfo)); - sc->sc_mapped = 1; - } - - /* - * Start the hardware initialization sequence. - */ - tmscpaddr->tmscpip = 0; /* start initialization */ - - while((tmscpaddr->tmscpsa & TMSCP_STEP1) == 0) - { -# ifdef DEBUG - printd("tmscpinit: tmscpsa = 0%o\n",tmscpaddr->tmscpsa); - DELAY(100000); -# endif - if(tmscpaddr->tmscpsa & TMSCP_ERR) - return(0); /* CHECK */ - } - tmscpaddr->tmscpsa=TMSCP_ERR|(NCMDL2<<11)|(NRSPL2<<8)|TMSCP_IE|(sc->sc_ivec/4); - /* - * Initialization continues in the interrupt routine. - */ - sc->sc_state = S_STEP1; - sc->sc_credits = 0; - return(1); -} - - -/* - * Start I/O operation - * This code is convoluted. The majority of it was copied from the uda driver. - */ -void -tmscpstart(um) - register struct uba_ctlr *um; -{ - register struct buf *bp, *dp; - register volatile struct mscp *mp; - register struct tmscp_softc *sc; - register struct tms_info *tms; - register struct uba_device *ui; - volatile struct tmscpdevice *tmscpaddr; - volatile struct tmscp *tm = &tmscp[um->um_ctlr]; - volatile int i; - int tempi; - char ioctl; /* flag: set true if its an IOCTL command */ - - sc = &tmscp_softc[um->um_ctlr]; - - for(;;) - { - if ((dp = um->um_tab.b_actf) == NULL) - { - /* - * Release unneeded UBA resources and return - * (drive was inactive) - */ - um->um_tab.b_active = 0; - break; - } - if ((bp = dp->b_actf) == NULL) - { - /* - * No more requests for this drive, remove - * from controller queue and look at next drive. - * We know we're at the head of the controller queue. - */ - dp->b_active = 0; - um->um_tab.b_actf = dp->b_hash.le_next; - continue; /* Need to check for loop */ - } - um->um_tab.b_active++; - tmscpaddr = (struct tmscpdevice *)um->um_addr; - ui = tmsdinfo[(TMSUNIT(bp->b_dev))]; - tms = &tms_info[ui->ui_unit]; - if ((tmscpaddr->tmscpsa&TMSCP_ERR) || sc->sc_state != S_RUN) - { - tprintf(tms->tms_tpr, - "tms%d: hard error bn%d\n", - minor(bp->b_dev)&03, bp->b_blkno); - log(TMS_PRI, "tmscp%d: sa 0%o, state %d\n",um->um_ctlr, - tmscpaddr->tmscpsa&0xffff, sc->sc_state); - (void)tmscpinit(um->um_ctlr); - /* SHOULD REQUEUE OUTSTANDING REQUESTS, LIKE TMSCPRESET */ - break; - } - /* - * Default is that last command was NOT a write command; - * if a write command is done it will be detected in tmscprsp. - */ - tms->tms_lastiow = 0; - if (ui->ui_flags == 0) - { /* not online */ - if ((mp = tmscpgetcp(um)) == NULL) - break; - mp->mscp_opcode = M_OP_ONLIN; - mp->mscp_unit = ui->ui_slave; - dp->b_active = 2; - um->um_tab.b_actf = dp->b_hash.le_next; /* remove from controller q */ - *((long *)mp->mscp_dscptr) |= TMSCP_OWN|TMSCP_INT; - if (tmscpaddr->tmscpsa&TMSCP_ERR) - printf("tmscp%d fatal error (0%o)\n",um->um_ctlr, - tmscpaddr->tmscpsa&0xffff); - i = tmscpaddr->tmscpip; - continue; - } - switch (cpunumber) { - - case VAX_8600: - case VAX_780: - i = UBA_NEEDBDP|UBA_CANTWAIT; - break; - case VAX_750: - i = um->um_ubinfo|UBA_HAVEBDP|UBA_CANTWAIT; - break; - case VAX_730: - case VAX_78032: - i = UBA_CANTWAIT; - break; - } /* end switch (cpunumber) */ - /* - * If command is an ioctl command then set the ioctl flag for later use. - * If not (i.e. it is a read or write) then attempt - * to set up a buffer pointer. - */ - ioctl = 0; - if (bp == &ctmscpbuf[um->um_ctlr]) - ioctl = 1; - else - if ((i = ubasetup(um->um_ubanum, bp, i)) == 0) - { - if(dp->b_qsize != 0) - break; /* When a command completes and */ - /* frees a bdp tmscpstart will be called */ - if ((mp = tmscpgetcp(um)) == NULL) - break; -# ifdef DEBUG - printd("tmscpstart: GTUNT %d ubasetup = %d\n",ui->ui_unit, i); - if(tmscpdebug)DELAY(10000); -# endif - mp->mscp_opcode = M_OP_GTUNT; - mp->mscp_unit = ui->ui_slave; - *((long *)mp->mscp_dscptr) |= TMSCP_OWN|TMSCP_INT; - if (tmscpaddr->tmscpsa&TMSCP_ERR) - printf("tmscp%d: fatal error (0%o)\n",um->um_ctlr, - tmscpaddr->tmscpsa&0xffff); - i = tmscpaddr->tmscpip; /* initiate polling */ - break; - } -# if defined(VAX750) - if (cpunumber == VAX_750) - tempi = i & 0xfffffff; /* mask off bdp */ - else -# endif - tempi = i; - if ((mp = tmscpgetcp(um)) == NULL) - { - if (!ioctl) /* only need to release if NOT ioctl */ - ubarelse(um->um_ubanum,&tempi); - break; - } - mp->mscp_cmdref = (long)bp; /* pointer to get back */ - mp->mscp_unit = ui->ui_slave; - /* - * If its an ioctl-type command then set up the appropriate - * tmscp command; by doing a switch on the "b_resid" field where - * the command mneumonic is stored. - */ - if (ioctl) - { -# ifdef DEBUG - printd("tmscpstart: doing ioctl cmd %d\n", bp->b_resid); -# endif - /* - * The reccnt and tmkcnt fields are set to zero by the getcp - * routine (as bytecnt and buffer fields). Thus reccnt and - * tmkcnt are only modified here if they need to be set to - * a non-zero value. - */ - switch ((int)bp->b_resid) { - - case TMS_WRITM: - mp->mscp_opcode = M_OP_WRITM; - break; - case TMS_FSF: - mp->mscp_opcode = M_OP_REPOS; - mp->mscp_tmkcnt = bp->b_bcount; - break; - case TMS_BSF: - mp->mscp_opcode = M_OP_REPOS; - mp->mscp_modifier = M_MD_REVRS; - mp->mscp_tmkcnt = bp->b_bcount; - break; - case TMS_FSR: - mp->mscp_opcode = M_OP_REPOS; - mp->mscp_modifier = M_MD_OBJCT; - mp->mscp_reccnt = bp->b_bcount; - break; - case TMS_BSR: - mp->mscp_opcode = M_OP_REPOS; - mp->mscp_modifier = M_MD_REVRS | M_MD_OBJCT; - mp->mscp_reccnt = bp->b_bcount; - break; - /* - * Clear serious exception is done for Rewind & Available cmds - */ - case TMS_REW: - mp->mscp_opcode = M_OP_REPOS; - mp->mscp_modifier = M_MD_REWND | M_MD_CLSEX; - if (bp->b_bcount == 0) - mp->mscp_modifier |= M_MD_IMMED; - tms->tms_serex = 0; - break; - case TMS_OFFL: - mp->mscp_opcode = M_OP_AVAIL; - mp->mscp_modifier = M_MD_UNLOD | M_MD_CLSEX; - tms->tms_serex = 0; - break; - case TMS_SENSE: - mp->mscp_opcode = M_OP_GTUNT; - break; - case TMS_CACHE: - mp->mscp_opcode = M_OP_STUNT; - tms->tms_unitflgs |= M_UF_WBKNV; - mp->mscp_unitflgs = tms->tms_unitflgs; - mp->mscp_format = tms->tms_format; - /* default device dependant parameters */ - mp->mscp_mediaid = 0; - break; - case TMS_NOCACHE: - mp->mscp_opcode = M_OP_STUNT; - tms->tms_unitflgs &= ~(M_UF_WBKNV); - mp->mscp_unitflgs = tms->tms_unitflgs; - mp->mscp_format = tms->tms_format; - /* default device dependant parameters */ - mp->mscp_mediaid = 0; - break; - case TMS_CSE: - /* - * This is a no-op command. It performs a - * clear serious exception only. (Done on a - * non-rewinding close after a serious exception.) - */ - mp->mscp_opcode = M_OP_REPOS; - mp->mscp_modifier = M_MD_CLSEX; - tms->tms_serex = 0; - tms->tms_clserex = 1; - break; - case TMS_LOWDENSITY: - /* - * Set the unit to low density - */ - mp->mscp_opcode = M_OP_STUNT; - mp->mscp_unitflgs = tms->tms_unitflgs; - mp->mscp_mediaid = 0; /* default device dependant parameters */ - if ((tms->tms_fmtmenu & M_TF_800) != 0) - mp->mscp_format = M_TF_800; - else - mp->mscp_format = M_TF_PE & tms->tms_fmtmenu; - tms->tms_format = mp->mscp_format; - break; - case TMS_HIDENSITY: - /* - * Set the unit to high density (format == 0) - */ - mp->mscp_opcode = M_OP_STUNT; - mp->mscp_unitflgs = tms->tms_unitflgs; - mp->mscp_mediaid = 0; /* default device dependant parameters */ - mp->mscp_format = 0; - tms->tms_format = 0; - break; - default: - printf("Bad ioctl on tms unit %d\n", ui->ui_unit); - /* Need a no-op. Reposition no amount */ - mp->mscp_opcode = M_OP_REPOS; - break; - } /* end switch (bp->b_resid) */ - } - else /* Its a read/write command (not an ioctl) */ - { - mp->mscp_opcode = bp->b_flags&B_READ ? M_OP_READ : M_OP_WRITE; - mp->mscp_bytecnt = bp->b_bcount; - mp->mscp_buffer = UBAI_ADDR(i) | (UBAI_BDP(i) << 24); - - bp->b_ubinfo = tempi; /* save mapping info */ - } - if (tms->tms_serex == 2) /* if tape mark read */ - { - mp->mscp_modifier |= M_MD_CLSEX; /* clear serious exc */ - tms->tms_serex = 0; - } - *((long *)mp->mscp_dscptr) |= TMSCP_OWN|TMSCP_INT; -# ifdef DEBUG - printd("tmscpstart: opcode 0%o mod %o unit %d cnt %d\n",mp->mscp_opcode,mp->mscp_modifier,mp->mscp_unit,mp->mscp_bytecnt); - if(tmscpdebug)DELAY(100000); -# endif - i = tmscpaddr->tmscpip; /* initiate polling */ - dp->b_qsize++; - /* - * Move drive to the end of the controller queue - */ - if (dp->b_hash.le_next != NULL) - { - um->um_tab.b_actf = dp->b_hash.le_next; - MSCP_APPEND(dp, &um->um_tab, b_hash.le_next); - } - /* - * Move buffer to I/O wait queue - */ - dp->b_actf = bp->b_actf; - dp = &tmscpwtab[um->um_ctlr]; - MSCP_APPEND(bp, dp, b_actf); - if (tmscpaddr->tmscpsa&TMSCP_ERR) - { - printf("tmscp%d: fatal error (0%o)\n", um->um_ctlr, tmscpaddr->tmscpsa&0xffff); - (void)tmscpinit(um->um_ctlr); - break; - } - } /* end for */ - /* - * Check for response ring transitions lost in the - * Race condition - */ - for (i = sc->sc_lastrsp;; i++) - { - i %= NRSP; - if (tm->tmscp_ca.ca_rspdsc[i]&TMSCP_OWN) - break; - tmscprsp(um, (struct tmscp *)tm, sc, i); - tm->tmscp_ca.ca_rspdsc[i] |= TMSCP_OWN; - } - sc->sc_lastrsp = i; -} - - -/* - * Process a response packet - */ -void -tmscprsp(um, tm, sc, i) - register struct uba_ctlr *um; - struct tmscp *tm; - register struct tmscp_softc *sc; - int i; -{ - register volatile struct mscp *mp; - register struct tms_info *tms; - struct uba_device *ui; - struct buf *dp, *bp; - int st; - struct uba_softc *ubasc; - - mp = &tm->tmscp_rsp[i]; - mp->mscp_header.tmscp_msglen = mscp_msglen; - sc->sc_credits += mp->mscp_header.tmscp_credits & 0xf; /* low 4 bits */ - if ((mp->mscp_header.tmscp_credits & 0xf0) > 0x10) /* Check */ - return; -# ifdef DEBUG - printd("tmscprsp, opcode 0%o status 0%o\n",mp->mscp_opcode,mp->mscp_status&M_ST_MASK); -# endif - /* - * If it's an error log message (datagram), - * pass it on for more extensive processing. - */ - if ((mp->mscp_header.tmscp_credits & 0xf0) == 0x10) - { /* check */ - tmserror(um, (struct mslg *)mp); - return; - } - st = mp->mscp_status&M_ST_MASK; - /* - * The controller interrupts as drive 0. - * This means that you must check for controller interrupts - * before you check to see if there is a drive 0. - */ - if((M_OP_STCON|M_OP_END) == mp->mscp_opcode) - { - if (st == M_ST_SUCC) - { -# ifdef DEBUG - printd("ctlr has %d credits\n", mp->mscp_header.tmscp_credits & 0xf); - printd("ctlr timeout = %d\n", mp->mscp_cnttmo); -# endif - sc->sc_state = S_RUN; - } - else - sc->sc_state = S_IDLE; - um->um_tab.b_active = 0; - wakeup((caddr_t)um); - return; - } - if (mp->mscp_unit >= NTMS) - return; - if ((ui = tmscpip[um->um_ctlr][mp->mscp_unit]) == 0) - return; - tms = &tms_info[ui->ui_unit]; - /* - * Save endcode, endflags, and status for mtioctl get unit status. - * NOTE: Don't do this on Clear serious exception (reposition no-op); - * which is done on close since this would - * overwrite the real status we want. - */ - if (tms->tms_clserex != 1) - { - tms->tms_endcode = mp->mscp_opcode; - tms->tms_flags = mp->mscp_flags; - tms->tms_status = st; - } - else tms->tms_clserex = 0; - - switch (mp->mscp_opcode) { - case M_OP_ONLIN|M_OP_END: - tms->tms_type = mp->mscp_mediaid; - dp = &tmsutab[ui->ui_unit]; - if (st == M_ST_SUCC) - { - /* - * Link the drive onto the controller queue - */ - MSCP_APPEND(dp, &um->um_tab, b_hash.le_next); - ui->ui_flags = 1; /* mark it online */ - tms->tms_dsize=(daddr_t)mp->mscp_maxwrt; -# ifdef DEBUG - printd("tmscprsp: unit %d online\n", mp->mscp_unit); -# endif - /* - * This define decodes the Media type identifier - */ -# define F_to_C(x,i) ( ((x)->mscp_mediaid) >> (i*5+7) & 0x1f ? ( ( (((x)->mscp_mediaid) >>( i*5 + 7)) & 0x1f) + 'A' - 1): ' ') -# ifdef DEBUG - printd("tmscprsp: unit %d online %x %c%c %c%c%c%d\n" - ,mp->mscp_unit, mp->mscp_mediaid ,F_to_C(mp,4) - ,F_to_C(mp,3), F_to_C(mp,2) - ,F_to_C(mp,1), F_to_C(mp,0), mp->mscp_mediaid & 0x7f); -# endif - dp->b_active = 1; - } /* end if st == M_ST_SUCC */ - else - { - if ((bp = dp->b_actf)) - tprintf(tms->tms_tpr, - "tms%d: hard error bn%d: OFFLINE\n", - minor(bp->b_dev)&03, bp->b_blkno); - else - tprintf(tms->tms_tpr, - "tms%d: hard error: OFFLINE\n", - ui->ui_unit); - while ((bp = dp->b_actf)) - { - dp->b_actf = bp->b_actf; - bp->b_flags |= B_ERROR; - iodone(bp); - } - } - if(mp->mscp_cmdref!=NULL) - /* Seems to get lost sometimes in uda */ - wakeup((caddr_t)mp->mscp_cmdref); - break; - /* - * The AVAILABLE ATTENTION message occurs when the - * unit becomes available after loading, - * marking the unit offline (ui_flags = 0) will force an - * online command prior to using the unit. - */ - case M_OP_AVATN: - ui->ui_flags = 0; - tms->tms_type = mp->mscp_mediaid; - break; - case M_OP_END: - /* - * An endcode without an opcode (0200) is an invalid command. - * The mscp specification states that this would be a protocol - * type error, such as illegal opcodes. The mscp spec. also - * states that parameter error type of invalid commands should - * return the normal end message for the command. This does not appear - * to be the case. An invalid logical block number returned an endcode - * of 0200 instead of the 0241 (read) that was expected. - */ - - printf("tmscp%d: invalid cmd, endcode = %o, status=%o\n", - um->um_ctlr, mp->mscp_opcode, st); - bp = (struct buf *)mp->mscp_cmdref; - /* - * Unlink buffer from I/O wait queue. - * And signal iodone, so the higher level command can exit! - * - */ - dp = &tmscpwtab[um->um_ctlr]; - while (dp && dp->b_actf != bp) - dp = dp->b_actf; - if (dp == NULL) - panic("tmscp: don't work1!"); - dp->b_actf = bp->b_actf; - dp = &tmsutab[ui->ui_unit]; - dp->b_qsize--; - iodone(bp); - break; - case M_OP_WRITE|M_OP_END: - /* mark the last io op as a write */ - tms->tms_lastiow = 1; - case M_OP_READ|M_OP_END: - case M_OP_WRITM|M_OP_END: - case M_OP_REPOS|M_OP_END: - case M_OP_STUNT|M_OP_END: - /* - * The AVAILABLE message occurs when the mt ioctl "rewoffl" is - * issued. For the ioctl, "rewoffl", a tmscp AVAILABLE command is - * done with the UNLOAD modifier. This performs a rewind, followed - * by marking the unit offline. So mark the unit offline - * software wise as well (ui_flags = 0 and - * tms->tms_openf = 0). - */ - case M_OP_AVAIL|M_OP_END: -# ifdef DEBUG - printd("tmscprsp: position = %d\n", mp->mscp_lbn); -# endif - bp = (struct buf *)mp->mscp_cmdref; - /* - * Only need to release buffer if the command was read or write. - * No ubasetup was done in "tmscpstart" if it was an ioctl cmd. - */ - if (mp->mscp_opcode == (M_OP_READ|M_OP_END) || - mp->mscp_opcode == (M_OP_WRITE|M_OP_END)) - ubarelse(um->um_ubanum, (int *)&bp->b_ubinfo); - /* - * Unlink buffer from I/O wait queue. - */ - dp = &tmscpwtab[um->um_ctlr]; - while (dp && dp->b_actf != bp) - dp = dp->b_actf; - if (dp == NULL) - panic("tmscp: don't work2!"); - dp->b_actf = bp->b_actf; -# if defined(VAX750) - ubasc = uba_cd.cd_devs[um->um_ubanum]; - if (cpunumber == VAX_750) { - if ((tmscpwtab[um->um_ctlr].b_actf == NULL) && - (um->um_ubinfo != 0)) { - ubarelse(um->um_ubanum, &um->um_ubinfo); - } - else { - if (mp->mscp_opcode == (M_OP_READ|M_OP_END) || - mp->mscp_opcode == (M_OP_WRITE|M_OP_END)) - UBAPURGE(ubasc->uh_uba,(um->um_ubinfo >>28) & 0x0f); - } - } -# endif - dp = &tmsutab[ui->ui_unit]; - dp->b_qsize--; - if (st == M_ST_OFFLN || st == M_ST_AVLBL) - { - ui->ui_flags = 0; /* mark unit offline */ - tms->tms_openf = 0; - tms->tms_type = mp->mscp_mediaid; - /* - * Link the buffer onto the front of the drive queue - */ - bp->b_actf = dp->b_actf; - dp->b_actf = bp; - /* - * Link the drive onto the controller queue - */ - if (dp->b_active == 0) - { - MSCP_APPEND(dp, &um->um_tab, b_hash.le_next); - dp->b_active = 1; - } -# if defined(VAX750) - if (cpunumber == VAX_750 && um->um_ubinfo == 0) - um->um_ubinfo = uballoc(um->um_ubanum, (caddr_t)0, 0, UBA_NEEDBDP); -# endif - return; - } - if (st != M_ST_SUCC) - { - if (mp->mscp_flags & M_EF_SEREX) - tms->tms_serex = 1; - if (st != M_ST_TAPEM) - { - tprintf(tms->tms_tpr, - "tms%d: hard error bn%d\n", - minor(bp->b_dev)&03, bp->b_blkno); - errinfo(st); /* produces more info */ -# ifdef DEBUG - printd("tmscprsp: error; status sub-code = 0%o, flags = 0%o\n", - (mp->mscp_status & 177740)>>5, mp->mscp_flags); -# endif - bp->b_flags |= B_ERROR; - } - else - /* Hit a tape mark - Set serex flag to - * a special value so we can clear the - * serious exception on the next command. - */ - tms->tms_serex = 2; - } - /* - * The tmscp spec states that controllers do not have to - * report the number of records or files skipped. So on - * reposition commands we go strictly by cmd status. - */ - if (mp->mscp_opcode != (M_OP_REPOS|M_OP_END)) - bp->b_resid = bp->b_bcount - mp->mscp_bytecnt; - else - bp->b_resid = 0; - tms->tms_resid = bp->b_resid; - iodone(bp); - break; - - case M_OP_GTUNT|M_OP_END: -# ifdef DEBUG - printd("tmscprsp: GTUNT end packet status = 0%o\n",st); - printd("tmscprsp: unit %d mediaid %x %c%c %c%c%c%d %x %x t=%d\n" - ,mp->mscp_unit, mp->mscp_mediaid - ,F_to_C(mp,4),F_to_C(mp,3),F_to_C(mp,2) - ,F_to_C(mp,1),F_to_C(mp,0) - ,mp->mscp_mediaid & 0x7f - ,mp->mscp_unitid.val[0] - ,mp->mscp_unitid.val[1] - ,mp->mscp_format); -# endif - tms->tms_type = mp->mscp_mediaid; - tms->tms_fmtmenu = mp->mscp_fmtmenu; - tms->tms_unitflgs = mp->mscp_unitflgs; - break; - - default: - printf("tmscp unknown packet\n"); - tmserror(um, (struct mslg *)mp); - } /* end switch mp->mscp_opcode */ -} - - -/* - * Give a meaningful error when the mscp_status field returns an error code. - */ - -void -errinfo(st) - int st; /* the status code */ -{ - switch(st) { - case M_ST_ICMD: - printf("invalid command\n"); - break; - case M_ST_ABRTD: - printf("command aborted\n"); - break; - case M_ST_OFFLN: - printf("unit offline\n"); - break; - case M_ST_WRTPR: - printf("unit write protected\n"); - break; - case M_ST_COMP: - printf("compare error\n"); - break; - case M_ST_DATA: - printf("data error\n"); - break; - case M_ST_HSTBF: - printf("host buffer access error\n"); - break; - case M_ST_CNTLR: - printf("controller error\n"); - break; - case M_ST_DRIVE: - printf("drive error\n"); - break; - case M_ST_FMTER: - printf("formatter error\n"); - break; - case M_ST_BOT: - printf("BOT encountered\n"); - break; - case M_ST_TAPEM: - printf("tape mark encountered\n"); - break; - case M_ST_RDTRN: - printf("record data truncated\n"); - break; - case M_ST_PLOST: - printf("position lost\n"); - break; - case M_ST_SEX: - printf("serious exception\n"); - break; - case M_ST_LED: - printf("LEOT detected\n"); - break; - } -} - - -/* - * Manage buffers and perform block mode read and write operations. - */ -void -tmscpstrategy (bp) - register struct buf *bp; -{ - register struct uba_device *ui; - register struct uba_ctlr *um; - register struct buf *dp; - register int unit = TMSUNIT(bp->b_dev); - int s; - - if (unit >= NTMS) - { -# ifdef DEBUG - printd ("tmscpstrategy: bad unit # %d\n",unit); -# endif - bp->b_flags |= B_ERROR; - iodone(bp); - return; - } - ui = tmsdinfo[unit]; - um = ui->ui_mi; - if (ui == 0 || ui->ui_alive == 0) - { - bp->b_flags |= B_ERROR; - iodone(bp); - return; - } - s = splbio(); - /* - * Link the buffer onto the drive queue - */ - dp = &tmsutab[ui->ui_unit]; - MSCP_APPEND(bp, dp, b_actf); - /* - * Link the drive onto the controller queue - */ - if (dp->b_active == 0) - { - MSCP_APPEND(dp, &um->um_tab, b_hash.le_next); - dp->b_active = 1; - } - /* - * If the controller is not active, start it. - */ - if (um->um_tab.b_active == 0) - { -# if defined(VAX750) - if (cpunumber == VAX_750 - && tmscpwtab[um->um_ctlr].b_actf == NULL) - { - if (um->um_ubinfo != 0) - log(TMS_PRI, "tmscpstrategy: ubinfo 0x%x\n", - um->um_ubinfo); - else - um->um_ubinfo = uballoc(um->um_ubanum, (caddr_t)0, 0, UBA_NEEDBDP); - } -# endif -# ifdef DEBUG - printd10("tmscpstrategy: Controller not active, starting it\n"); -# endif - (void) tmscpstart(um); - } - splx(s); - return; -} - -int -tmscpread(dev, uio) - dev_t dev; - struct uio *uio; -{ - - return (physio(tmscpstrategy, NULL, dev, B_READ, minphys, uio)); -} - -int -tmscpwrite(dev, uio) - dev_t dev; - struct uio *uio; -{ - - return (physio(tmscpstrategy, NULL, dev, B_WRITE, minphys, uio)); -} - -#define DBSIZE 32 - -#define ca_Rspdsc ca_rspdsc[0] -#define ca_Cmddsc ca_rspdsc[1] -#define tmscp_Rsp tmscp_rsp[0] -#define tmscp_Cmd tmscp_cmd[0] - -struct tmscp tmscpd[NTMSCP]; - -int -tmscpdump(dev, blkno, va, size) - dev_t dev; - daddr_t blkno; - caddr_t va; - size_t size; -{ -#ifdef notyet - volatile struct tmscpdevice *tmscpaddr; - volatile struct tmscp *tmscp_ubaddr; - char *start; - int num, blk, unit; - register struct uba_regs *uba; - register struct uba_device *ui; - register volatile struct tmscp *tmscpp; - register struct pte *io; - register int i; - - unit = minor(dev) & 03; - if (unit >= NTMS) - return (ENXIO); -# define phys(cast, addr) ((cast)((int)addr & 0x7fffffff)) - ui = phys(struct uba_device *, tmsdinfo[unit]); - if (ui->ui_alive == 0) - return (ENXIO); - uba = phys(struct uba_softc *, ui->ui_hd)->uh_physuba; - ubainit(uba); - tmscpaddr = (struct tmscpdevice *)ui->ui_physaddr; - DELAY(2000000); - tmscpp = phys(struct tmscp *, &tmscpd[ui->ui_ctlr]); - - num = btoc(sizeof(struct tmscp)) + 1; - io = (struct pte *)&uba->uba_map[NUBMREG-num]; - for(i = 0; i<num; i++) - *(int *)io++ = UBAMR_MRV|(btop(tmscpp)+i); - tmscp_ubaddr = (struct tmscp *)(((int)tmscpp & PGOFSET)|((NUBMREG-num)<<9)); - - tmscpaddr->tmscpip = 0; - while ((tmscpaddr->tmscpsa & TMSCP_STEP1) == 0) - if(tmscpaddr->tmscpsa & TMSCP_ERR) return(EFAULT); - tmscpaddr->tmscpsa = TMSCP_ERR; - while ((tmscpaddr->tmscpsa & TMSCP_STEP2) == 0) - if(tmscpaddr->tmscpsa & TMSCP_ERR) return(EFAULT); - tmscpaddr->tmscpsa = (short)((int)&tmscp_ubaddr->tmscp_ca.ca_ringbase); - while ((tmscpaddr->tmscpsa & TMSCP_STEP3) == 0) - if(tmscpaddr->tmscpsa & TMSCP_ERR) return(EFAULT); - tmscpaddr->tmscpsa = (short)(((int)&tmscp_ubaddr->tmscp_ca.ca_ringbase) >> 16); - while ((tmscpaddr->tmscpsa & TMSCP_STEP4) == 0) - if(tmscpaddr->tmscpsa & TMSCP_ERR) return(EFAULT); - tmscpaddr->tmscpsa = TMSCP_GO; - tmscpp->tmscp_ca.ca_Rspdsc = (long)&tmscp_ubaddr->tmscp_Rsp.mscp_cmdref; - tmscpp->tmscp_ca.ca_Cmddsc = (long)&tmscp_ubaddr->tmscp_Cmd.mscp_cmdref; - tmscpp->tmscp_Cmd.mscp_header.tmscp_vcid = 1; /* for tape */ - tmscpp->tmscp_Cmd.mscp_cntflgs = 0; - tmscpp->tmscp_Cmd.mscp_version = 0; - if (tmscpcmd(M_OP_STCON, tmscpp, tmscpaddr) == 0) { - return(EFAULT); - } - tmscpp->tmscp_Cmd.mscp_unit = ui->ui_slave; - if (tmscpcmd(M_OP_ONLIN, tmscpp, tmscpaddr) == 0) { - return(EFAULT); - } - - num = maxfree; - start = 0; - while (num > 0) - { - blk = num > DBSIZE ? DBSIZE : num; - io = (struct pte *)uba->uba_map; - for (i = 0; i < blk; i++) - *(int *)io++ = (btop(start)+i) | UBAMR_MRV; - *(int *)io = 0; - tmscpp->tmscp_Cmd.mscp_lbn = btop(start); - tmscpp->tmscp_Cmd.mscp_unit = ui->ui_slave; - tmscpp->tmscp_Cmd.mscp_bytecnt = blk*NBPG; -# ifdef MVAX - if( cpu == MVAX_I ) - tmscpp->tmscp_Cmd.mscp_buffer = (long) start; - else -# endif MVAX - tmscpp->tmscp_Cmd.mscp_buffer = 0; - if (tmscpcmd(M_OP_WRITE, tmscpp, tmscpaddr) == 0) - return(EIO); - start += blk*NBPG; - num -= blk; - } -#endif - return (0); -} - - -/* - * Perform a standalone tmscp command. This routine is only used by tmscpdump. - */ - -int -tmscpcmd(op, tmscpp, tmscpaddr) - int op; - struct tmscp *tmscpp; - struct tmscpdevice *tmscpaddr; -{ - volatile int i; - - - tmscpp->tmscp_Cmd.mscp_opcode = op; - tmscpp->tmscp_Rsp.mscp_header.tmscp_msglen = mscp_msglen; - tmscpp->tmscp_Cmd.mscp_header.tmscp_msglen = mscp_msglen; - tmscpp->tmscp_ca.ca_Rspdsc |= TMSCP_OWN|TMSCP_INT; - tmscpp->tmscp_ca.ca_Cmddsc |= TMSCP_OWN|TMSCP_INT; - if (tmscpaddr->tmscpsa&TMSCP_ERR) - printf("tmscp fatal error (0%o)\n", tmscpaddr->tmscpsa&0xffff); - i = tmscpaddr->tmscpip; -#ifdef lint - i = i; -#endif - for (;;) - { - if (tmscpp->tmscp_ca.ca_cmdint) - tmscpp->tmscp_ca.ca_cmdint = 0; - if (tmscpp->tmscp_ca.ca_rspint) - break; - } - tmscpp->tmscp_ca.ca_rspint = 0; - if (tmscpp->tmscp_Rsp.mscp_opcode != (op|M_OP_END) || - (tmscpp->tmscp_Rsp.mscp_status&M_ST_MASK) != M_ST_SUCC) - { - printf("error: com %d opc 0x%x stat 0x%x\ndump ", op, - tmscpp->tmscp_Rsp.mscp_opcode, tmscpp->tmscp_Rsp.mscp_status); - return(0); - } - return(1); -} - -/* - * Catch ioctl commands, and call the "command" routine to do them. - */ - -/* ARGSUSED */ -int -tmscpioctl(dev, cmd, data, flag, p) - dev_t dev; - u_long cmd; - caddr_t data; - int flag; - struct proc *p; -{ - register struct buf *bp = &ctmscpbuf[TMSCPCTLR(dev)]; - register callcount; /* number of times to call cmd routine */ - register struct uba_device *ui; - register struct tms_info *tms; - int fcount; /* number of files (or records) to space */ - int error = 0; - register struct mtop *mtop; /* mag tape cmd op to perform */ - register struct mtget *mtget; /* mag tape struct to get info in */ - - /* we depend of the values and order of the TMS ioctl codes here */ - static tmsops[] = - {TMS_WRITM,TMS_FSF,TMS_BSF,TMS_FSR,TMS_BSR,TMS_REW,TMS_OFFL,TMS_SENSE, - TMS_CACHE,TMS_NOCACHE}; - - switch (cmd) { - case MTIOCTOP: /* tape operation */ - mtop = (struct mtop *)data; - switch (mtop->mt_op) { - - case MTWEOF: - callcount = mtop->mt_count; - fcount = 1; - break; - case MTFSF: case MTBSF: - case MTFSR: case MTBSR: - callcount = 1; - fcount = mtop->mt_count; - break; - case MTREW: case MTOFFL: case MTNOP: - case MTCACHE: case MTNOCACHE: - callcount = 1; - fcount = 1; /* wait for this rewind */ - break; - default: - return (ENXIO); - } /* end switch mtop->mt_op */ - - if (callcount <= 0 || fcount <= 0) - return (EINVAL); - while (--callcount >= 0) - { - tmscpcommand(dev, tmsops[mtop->mt_op], fcount); - if ((mtop->mt_op == MTFSR || mtop->mt_op == MTBSR) && - bp->b_resid) - return (EIO); - if (bp->b_flags & B_ERROR) /* like hitting BOT */ - break; - } - if (bp->b_flags&B_ERROR) - if ((error = bp->b_error)==0) - return (EIO); - return (error); - - case MTIOCGET: - /* - * Return status info associated with the particular UNIT. - */ - ui = tmsdinfo[TMSUNIT(dev)]; - tms = &tms_info[ui->ui_unit]; - mtget = (struct mtget *)data; - mtget->mt_type = MT_ISTMSCP; - mtget->mt_dsreg = tms->tms_flags << 8; - mtget->mt_dsreg |= tms->tms_endcode; - mtget->mt_erreg = tms->tms_status; - mtget->mt_resid = tms->tms_resid; - break; - - default: - return (ENXIO); - } - return (0); -} - - -/* - * Reset (for raw mode use only). - */ -void -tmscpreset (uban) - int uban; -{ - register struct uba_ctlr *um; - register struct uba_device *ui; - register struct buf *bp, *dp; - register int unit; - struct buf *nbp; - int d; - - for (d = 0; d < NTMSCP; d++) - { - if ((um = tmscpminfo[d]) == 0 || um->um_ubanum != uban || - um->um_alive == 0) - continue; - printf(" tmscp%d", d); - um->um_tab.b_active = 0; - um->um_tab.b_actf = 0; - tmscp_softc[d].sc_state = S_IDLE; - tmscp_softc[d].sc_mapped = 0; - for (unit = 0; unit < NTMS; unit++) - { - if ((ui = tmsdinfo[unit]) == 0) - continue; - if (ui->ui_alive == 0 || ui->ui_mi != um) - continue; - tmsutab[unit].b_active = 0; - tmsutab[unit].b_qsize = 0; - } - for (bp = tmscpwtab[d].b_actf; bp; bp = nbp) - { - nbp = bp->b_actf; - bp->b_ubinfo = 0; - /* - * Link the buffer onto the drive queue - */ - dp = &tmsutab[TMSUNIT(bp->b_dev)]; - MSCP_APPEND(bp, dp, b_actf); - /* - * Link the drive onto the controller queue - */ - if (dp->b_active == 0) - { - MSCP_APPEND(dp, &um->um_tab, b_hash.le_next); - dp->b_active = 1; - } - } - (void)tmscpinit(d); - } -} - - -/* - * Process an error log message - * - * Only minimal decoding is done, only "useful" - * information is printed. Eventually should - * send message to an error logger. - */ -void -tmserror(um, mp) - register struct uba_ctlr *um; - register struct mslg *mp; -{ - register i; - -# ifdef DEBUG - printd("tmserror:\n"); -# endif - if(!(mp->mslg_flags & (M_LF_SUCC | M_LF_CONT))) - log(TMS_PRI, "tmscp%d: %s error, ", um->um_ctlr, - mp->mslg_flags & ( M_LF_SUCC | M_LF_CONT ) ? "soft" : "hard"); - - switch (mp->mslg_format) { - - case M_FM_CNTERR: - log(TMS_PRI, "controller error, event 0%o\n", mp->mslg_event); - break; - case M_FM_BUSADDR: - log(TMS_PRI, "host memory access error, event 0%o, addr 0%o\n", - mp->mslg_event, - (unsigned int)(mp->mslg_unitid & 0xffffffff)); - break; - case M_FM_TAPETRN: - log(TMS_PRI, "tape transfer error, unit %d, grp 0x%x, event 0%o\n", - mp->mslg_unit, mp->mslg_group, mp->mslg_event); - break; - case M_FM_STIERR: - log(TMS_PRI, "STI error, unit %d, event 0%o\n", - mp->mslg_unit, mp->mslg_event); -#ifdef notdef - /* too painful to do with log() */ - for(i = 0; i < 62;i++) - mprintf("\t0x%x",mp->mslg_stiunsucc[i] & 0xff); - mprintf("\n"); -#endif - break; - case M_FM_STIDEL: - log(TMS_PRI, "STI Drive Error Log, unit %d, event 0%o\n", - mp->mslg_unit, mp->mslg_event); - break; - case M_FM_STIFEL: - log(TMS_PRI, "STI Formatter Error Log, unit %d, event 0%o\n", - mp->mslg_unit, mp->mslg_event); - break; - default: - log(TMS_PRI, "unknown error, unit %d, format 0%o, event 0%o\n", - mp->mslg_unit, mp->mslg_format, mp->mslg_event); - } - - if (tmscperror) - { - register long *p = (long *)mp; - - for (i = 0; i < mp->mslg_header.tmscp_msglen; i += sizeof(*p)) - printf("%x ", (unsigned int)*p++); - printf("\n"); - } -} - -int -tmscp_match(parent, match, aux) - struct device *parent; - void *match, *aux; -{ - return 0; -} - -void -tmscp_attach(parent, self, aux) - struct device *parent, *self; - void *aux; -{ -} - -#endif diff --git a/sys/arch/vax/uba/tmscpreg.h b/sys/arch/vax/uba/tmscpreg.h deleted file mode 100644 index de806fcdb53..00000000000 --- a/sys/arch/vax/uba/tmscpreg.h +++ /dev/null @@ -1,120 +0,0 @@ -/* $NetBSD: tmscpreg.h,v 1.1 1995/02/23 17:53:19 ragge Exp $ */ - -/*- - * Copyright (c) 1991 The Regents of the University of California. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)tmscpreg.h 7.2 (Berkeley) 5/9/91 - */ - -/* @(#)tmscpreg.h 1.1 11/2/84 84/09/25 */ - -/**************************************************************** - * * - * Licensed from Digital Equipment Corporation * - * Copyright (c) * - * Digital Equipment Corporation * - * Maynard, Massachusetts * - * 1985, 1986 * - * All rights reserved. * - * * - * The Information in this software is subject to change * - * without notice and should not be construed as a commitment * - * by Digital Equipment Corporation. Digital makes no * - * representations about the suitability of this software for * - * any purpose. It is supplied "As Is" without expressed or * - * implied warranty. * - * * - * If the Regents of the University of California or its * - * licensees modify the software in a manner creating * - * diriviative copyright rights, appropriate copyright * - * legends may be placed on the drivative work in addition * - * to that set forth above. * - * * - ****************************************************************/ -/* - * TMSCP registers and structures - */ - -#ifndef _UBA_TMSCPREG_ -#define _UBA_TMSCPREG_ -struct tmscpdevice { - short tmscpip; /* initialization and polling */ - short tmscpsa; /* status and address */ -}; - -#define TMSCP_ERR 0100000 /* error bit */ -#define TMSCP_STEP4 0040000 /* step 4 has started */ -#define TMSCP_STEP3 0020000 /* step 3 has started */ -#define TMSCP_STEP2 0010000 /* step 2 has started */ -#define TMSCP_STEP1 0004000 /* step 1 has started */ -#define TMSCP_NV 0002000 /* no host settable interrupt vector */ -#define TMSCP_QB 0001000 /* controller supports Q22 bus */ -#define TMSCP_DI 0000400 /* controller implements diagnostics */ -#define TMSCP_OD 0000200 /* port allows odd host addr's in the buffer descriptor */ -#define TMSCP_IE 0000200 /* interrupt enable */ -#define TMSCP_MP 0000100 /* port supports address mapping */ -#define TMSCP_LF 0000002 /* host requests last fail response packet */ -#define TMSCP_PI 0000001 /* host requests adapter purge interrupts */ -#define TMSCP_GO 0000001 /* start operation, after init */ - - -/* - * TMSCP Communications Area - */ - -struct tmscpca { - short ca_xxx1; /* unused */ - char ca_xxx2; /* unused */ - char ca_bdp; /* BDP to purge */ - short ca_cmdint; /* command queue transition interrupt flag */ - short ca_rspint; /* response queue transition interrupt flag */ - long ca_rspdsc[NRSP];/* response descriptors */ - long ca_cmddsc[NCMD];/* command descriptors */ -}; - -#define ca_ringbase ca_rspdsc[0] - -#define TMSCP_OWN 0x80000000 /* port owns this descriptor (else host - owns it) */ -#define TMSCP_INT 0x40000000 /* allow interrupt on ring transition */ - -#define TMSCP_MAP 0x80000000 /* modifier for mapped buffer descriptors */ - -/* - * TMSCP packet info (same as MSCP) - */ -struct mscp_header { - short tmscp_msglen; /* length of MSCP packet */ - char tmscp_credits; /* low 4 bits: credits, high 4 bits: msgtype */ - char tmscp_vcid; /* virtual circuit id (connection id) */ -}; -#endif diff --git a/sys/arch/vax/uba/ts.c b/sys/arch/vax/uba/ts.c index c2bb299e6a2..cdb14f69d4a 100644 --- a/sys/arch/vax/uba/ts.c +++ b/sys/arch/vax/uba/ts.c @@ -1,4 +1,4 @@ -/* $NetBSD: ts.c,v 1.6 1996/04/08 18:37:32 ragge Exp $ */ +/* $NetBSD: ts.c,v 1.11 1997/01/11 11:34:43 ragge Exp $ */ /*- * Copyright (c) 1991 The Regents of the University of California. @@ -14,8 +14,8 @@ * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. + * This product includes software developed by the University of + * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. @@ -32,35 +32,35 @@ * 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. * + * * ************************************************************************/ /* @@ -69,20 +69,9 @@ * 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 @@ -92,10 +81,10 @@ #define ENABLE_END #define ENABLE_EAI /* enable Attention-Interrupts */ -#undef ENABLE_EAI +#undef ENABLE_EAI #define ENABLE_ERI /* Enable Release Buffer Interrupts */ -#undef ENABLE_ERI +#undef ENABLE_ERI #ifdef DEBUG int tsdebug = 1; @@ -129,11 +118,6 @@ int tstrace = 1; */ -#include "ts.h" - -#if NTS > 0 - - #include <sys/param.h> #include <sys/systm.h> #include <sys/kernel.h> @@ -147,7 +131,6 @@ int tstrace = 1; #include <sys/mtio.h> #include <sys/uio.h> #include <sys/proc.h> -#include <sys/tprintf.h> #include <machine/pte.h> #include <machine/sid.h> @@ -159,24 +142,14 @@ int tstrace = 1; #include <vax/uba/tsreg.h> -int ts_match __P((struct device *, void *, void *)); -void ts_attach __P((struct device *, struct device *, void *)); -void tsstrategy __P((struct buf *)); - -struct cfdriver ts_cd = { - NULL, "ts", DV_DULL -}; - -struct cfattach ts_ca = { - sizeof(struct device), ts_match, ts_attach -}; +#include "ts.h" /* * ts command packets and communication area (per controller) */ -struct ts { +struct ts { struct tsdevice *reg; /* address of i/o-registers */ - struct tscmd cmd; /* command packet(s) */ + struct tscmd cmd; /* command packet(s) */ struct tsmsg msg; /* message packet(s) */ } ts[NTS]; @@ -186,37 +159,38 @@ struct ts { * (thus we have no struct ts_info) */ struct ts_softc { - struct ts *sc_ts; /* Unibus address of uda struct */ - short sc_mapped; /* Unibus map allocated ? */ - int sc_ubainfo; /* Unibus mapping info */ - short sc_state; /* see below: ST_xxx */ - short sc_flags; /* see below: FL_xxx */ + struct device sc_dev; /* Autoconf ... */ + struct uba_unit sc_unit; /* Struct common for UBA to talk */ + struct ts *sc_ts; /* Unibus address of uda struct */ + short sc_mapped; /* Unibus map allocated ? */ + int sc_ubainfo; /* Unibus mapping info */ + short sc_state; /* see below: ST_xxx */ + short sc_flags; /* see below: FL_xxx */ short sc_lcmd; /* last command word */ short sc_rtc; /* retry count for lcmd */ short sc_lssr; /* last status register */ short sc_lmsgh; /* last message header */ short sc_lxst0; /* last status word */ short sc_cmdf; /* command flags (ack,cvc,ie) */ - short sc_openf; /* lock against multiple opens */ + short sc_openf; /* lock against multiple opens */ short sc_liowf; /* last operation was write */ - int sc_micro; /* microcode revision */ - int sc_ivec; /* interrupt vector address */ - short sc_ipl; /* interrupt priority, Q-bus */ - tpr_t sc_tpr; /* tprintf handle */ -} ts_softc[NTS]; - -int tsprobe __P((caddr_t, int, struct uba_ctlr *, struct uba_softc *)); -int tsslave __P((struct uba_device *, caddr_t)); -void tsattach __P((struct uba_device *)); + int sc_micro; /* microcode revision */ + int sc_ivec; /* interrupt vector address */ + short sc_ipl; /* interrupt priority, Q-bus */ +}; + void tsintr __P((int)); -int tsinit __P((int)); +int tsinit __P((struct ts_softc *)); void tscommand __P((dev_t, int, int)); int tsstatus __P((int)); int tsexec __P((int, int)); -int tsstart __P((struct uba_ctlr *, struct buf *)); +int tsstart __P((struct ts_softc *, struct buf *)); int tswchar __P((int)); void tsreset __P((int)); void tsxstatus __P((struct tsmsg *)); +int tsmatch __P((struct device *, void *, void *)); +void tsattach __P((struct device *, struct device *, void *)); +void tsstrategy __P((struct buf *)); int tsopen __P((dev_t, int, int, struct proc *)); int tsclose __P((dev_t, int, int, struct proc *)); @@ -225,37 +199,30 @@ int tsread __P((dev_t, struct uio *)); int tswrite __P((dev_t, struct uio *)); int tsdump __P((dev_t, daddr_t, caddr_t, size_t)); +struct cfdriver ts_cd = { + NULL, "ts", DV_DULL +}; + +struct cfattach ts_ca = { + sizeof(struct ts_softc), tsmatch, tsattach +}; + #define ST_INVALID 0 /* uninitialized, before probe */ #define ST_PROBE 1 /* during tsprobe(), not used */ #define ST_SLAVE 2 /* in tsslave(), init almost complete */ #define ST_ATTACH 3 /* during tsattach(), not used */ -#define ST_INITIALIZED 4 /* init completed, set by tsintr() */ +#define ST_INITIALIZED 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, @@ -274,30 +241,25 @@ struct buf *ts_wtab[NTS]; /* dummy I/O wait queue */ * initialize data structures, what else ??? */ int -tsinit (unit) - int unit; +tsinit (sc) + struct ts_softc *sc; { - register struct ts_softc *sc; volatile struct tsdevice *tsregs; - struct uba_ctlr *um; + int unit = sc->sc_dev.dv_unit; + struct uba_unit *uu; - trace (("tsinit: unit = %d\n", unit)); - - sc = &ts_softc[unit]; - um = zsinfo[unit]; - um->um_tab.b_active++; /* ??? */ - tsregs = (struct tsdevice *)um->um_addr; + uu = &sc->sc_unit; + tsregs = (struct tsdevice *)ts[unit].reg; if (sc->sc_mapped == 0) { /* * Map the communications area and command and message * buffer into Unibus address space. */ - sc->sc_ubainfo = uballoc (um->um_ubanum, (caddr_t)&ts[unit], - sizeof (struct ts), TS_UBAFLAGS); + sc->sc_ubainfo = uballoc((struct uba_softc *) + sc->sc_dev.dv_parent, + (caddr_t)&ts[unit], sizeof (struct ts), TS_UBAFLAGS); sc->sc_ts = (struct ts *)(UBAI_ADDR(sc->sc_ubainfo)); sc->sc_mapped = 1; - debug (("sc_mapped: %d [%x, %x]\n", sc->sc_mapped, - sc->sc_ubainfo, sc->sc_ts)); } /* @@ -320,7 +282,7 @@ tsexec (ctlr, cmd) int ctlr; int cmd; { - register struct ts_softc *sc = &ts_softc[ctlr]; + register struct ts_softc *sc = ts_cd.cd_devs[ctlr]; register struct tscmd *tscmdp = &ts[ctlr].cmd; register long tscmdma = (long)&sc->sc_ts->cmd; /* mapped address */ volatile struct tsdevice *tsreg = ts[ctlr].reg; @@ -349,13 +311,12 @@ tsexec (ctlr, cmd) case TS_CMD_STAT: cmdName = "Get Status (END)"; break; default: cmdName = "unexptected Command"; break; } - debug (("tsexec: cmd = 0x%x (%s)\n", tscmdp->cmdr, cmdName)); #endif sr = tsreg->tssr; if ((sr & TS_SSR) == 0) { /* subsystem NOT ready */ printf ("%s%d: subsystem not ready [%x]\n", - CTLRNAME, ctlr, sr); + sc->sc_dev.dv_xname, sr); return (-1); } dbx = ((char*)tsreg) + 3; /* dbx is located at the fourth byte */ @@ -375,7 +336,7 @@ tsexec (ctlr, cmd) * wait for SSR or RMR to show up */ sr = tsreg->tssr; - if ((sr & TS_SSR) != 0) { /* something went wrong .. */ + if ((sr & TS_SSR) != 0) { /* something went wrong .. */ if (sr & TS_RMR) { printf ("ts: error writing TSDB (RMR)\n"); return (-1); @@ -404,15 +365,14 @@ tscommand (dev, cmd, count) int count; { register struct buf *bp; - register int s; + register int s; trace (("tscommand (%d, %x, %d)\n", TS_UNIT(dev), cmd, count)); s = splbio(); bp = &ts_cbuf[TS_UNIT(dev)]; -#if 1 + while (bp->b_flags & B_BUSY) { - debug (("looping 'cause B_BUSY\n")); /* * This special check is because B_BUSY never * gets cleared in the non-waiting rewind case. ??? @@ -420,12 +380,11 @@ tscommand (dev, cmd, count) if (bp->b_bcount == 0 && (bp->b_flags & B_DONE)) break; bp->b_flags |= B_WANTED; - debug (("sleeping ...\n"));; sleep ((caddr_t)bp, PRIBIO); /* check MOT-flag !!! */ } bp->b_flags = B_BUSY | B_READ; -#endif + splx(s); /* @@ -438,7 +397,6 @@ tscommand (dev, cmd, count) bp->b_bcount = count; bp->b_resid = cmd; bp->b_blkno = 0; - debug (("tscommand: calling tsstrategy ...\n")); tsstrategy (bp); /* * In case of rewind from close, don't wait. @@ -459,42 +417,34 @@ tscommand (dev, cmd, count) * Start an I/O operation on TS05 controller */ int -tsstart (um, bp) - register struct uba_ctlr *um; +tsstart (sc, bp) + register struct ts_softc *sc; register struct buf *bp; { - register struct ts_softc *sc = &ts_softc[um->um_ctlr]; - volatile struct tsdevice *tsreg = ts[um->um_ctlr].reg; - register struct tscmd *tscmdp = &ts[um->um_ctlr].cmd; + int ctlr = sc->sc_dev.dv_unit; + volatile struct tsdevice *tsreg = ts[ctlr].reg; + register struct tscmd *tscmdp = &ts[ctlr].cmd; register struct buf *dp; volatile int i, itmp; - int unit; int ioctl; int cmd; - unit = um->um_ctlr; - trace (("tsstart (unit = %d)\n", unit)); - sc = &ts_softc[unit]; - - if ((dp = ts_wtab[unit]) != NULL) { + if ((dp = ts_wtab[ctlr]) != NULL) { /* * There's already a command pending ... * Either we are called by tsintr or we have missed * something important (race condition). */ - debug (("tsstart: I/O queue not empty.\n")); /* bertram: ubarelse ??? */ - ts_wtab[um->um_ctlr] = NULL; + ts_wtab[ctlr] = NULL; dp->b_flags |= B_ERROR; iodone (dp); if (tsreg->tssr & TS_SC) { /* Special Condition; Error */ - tprintf (sc->sc_tpr, "%s%d: error at bn%d\n", - UNITNAME, unit, dp->b_blkno); - log (TS_PRI, "%s%d: tssr 0x%x, state %d\n", - CTLRNAME, unit, tsreg->tssr, sc->sc_state); - tsinit (unit); + log (TS_PRI, "%s: tssr 0x%x, state %d\n", + sc->sc_dev.dv_xname, tsreg->tssr, sc->sc_state); + tsinit (sc); return (-1); } /* XXX */ @@ -505,47 +455,43 @@ tsstart (um, bp) * If it's an ioctl then just set the flags for later use; * For other commands attempt to setup a buffer pointer. */ - if (bp == &ts_cbuf[um->um_ctlr]) { + if (bp == &ts_cbuf[ctlr]) { ioctl = 1; - debug (("tsstart(ioctl): unit %d\n", um->um_ctlr)); } else { ioctl = 0; - debug (("tsstart(rw): unit %d\n", um->um_ctlr)); /* * now we try to map the buffer into uba map space (???) */ i = TS_UBAFLAGS; - switch (cpunumber) { + switch (vax_cputype) { case VAX_8600: case VAX_780: i |= UBA_CANTWAIT; break; case VAX_750: - i |= um->um_ubinfo | UBA_CANTWAIT; + i |= sc->sc_unit.uu_ubinfo | UBA_CANTWAIT; break; case VAX_730: case VAX_78032: i |= UBA_CANTWAIT; break; default: - printf ("unsupported cpu %d in tsstart.\n", cpunumber); - } /* end switch (cpunumber) */ + printf ("unsupported cpu %d in tsstart.\n", vax_cputype); + } /* end switch (vax_cputype) */ - debug (("ubasetup (%x, %x, %x)\n", um->um_ubanum, bp, i)); - if ((i = ubasetup (um->um_ubanum, bp, i)) == 0) { + if ((i = ubasetup(sc->sc_dev.dv_parent->dv_unit, bp, i)) == 0) { /* * For some reasons which I don't (yet? :) understand, * tmscp.c initiates in this situation a GET-UNIT * command. (Because no data-buffers are neccess. ??) */ - debug (("tsstart: %d, ubasetup = 0\n", um->um_ctlr)); cmd = TS_CMD_STAT; goto do_cmd; return (-1); /* ??? */ } #if defined(VAX750) - if (cpunumber == VAX_750) + if (vax_cputype == VAX_750) itmp = i & 0xfffffff; /* mask off bdp */ else #endif @@ -553,7 +499,6 @@ tsstart (um, bp) /* XXX */ } - debug (("ubasetup done. [%x, %x, %d]\n", i, itmp, ioctl)); /* * If it's an ioctl command, then assemble the command. @@ -561,7 +506,6 @@ tsstart (um, bp) * in <sys/mtio.h> */ if (ioctl) { - debug (("tsstart: doing ioctl %d\n", bp->b_resid)); switch ((int)bp->b_resid) { case MTWEOF: cmd = TS_CMD_WTM; @@ -597,24 +541,20 @@ tsstart (um, bp) cmd = TS_CMD_STAT; break; default: - printf ("%s%d: bad ioctl %d\n", - CTLRNAME, unit, (int)bp->b_resid); + printf ("%s: bad ioctl %d\n", sc->sc_dev.dv_xname, + (int)bp->b_resid); /* Need a no-op. get status */ cmd = TS_CMD_STAT; } /* end switch (bp->b_resid) */ } else { /* Its a read/write command (not an ioctl) */ - debug (("tsstart: non-ioctl [%x, %xi, %x]\n", - tscmdp, UBAI_ADDR(i), bp)); tscmdp->cw1 = UBAI_ADDR(i) & 0xffff; tscmdp->cw2 = (UBAI_ADDR(i) >> 16) & 0x3f; tscmdp->cw3 = bp->b_bcount; if (bp->b_flags & B_READ) { - debug (("read-command(%d)\n", tscmdp->cw3)); cmd = TS_CMD_RNF; } else { - debug (("write-command(%d)\n", tscmdp->cw3)); cmd = TS_CMD_WD; } bp->b_ubinfo = itmp; /* save mapping info */ @@ -623,22 +563,20 @@ tsstart (um, bp) /* * Move buffer to I/O wait pseudo-queue */ - if (ts_wtab[um->um_ctlr]) { + if (ts_wtab[ctlr]) { /* * we are already waiting for something ... * this should not happen, so we have a problem now. * bertram: set error-flag and call iodone() ??? */ - debug (("tsstart: already waiting for something ...\n")); } - ts_wtab[um->um_ctlr] = bp; + ts_wtab[ctlr] = bp; /* * Now that the command-buffer is setup, give it to the controller */ do_cmd: - debug (("tsstart: calling tsexec(%d, %d)\n", unit, cmd)); - return (tsexec (unit, cmd)); + return (tsexec(ctlr, cmd)); } /* @@ -650,6 +588,7 @@ int tswchar (ctlr) int ctlr; { + struct ts_softc *sc = ts_cd.cd_devs[ctlr]; volatile struct tsdevice *tsregs = ts[ctlr].reg; volatile struct tscmd *tscmdp = &ts[ctlr].cmd; volatile struct tsmsg *tsmsgp = &ts[ctlr].msg; @@ -658,17 +597,17 @@ tswchar (ctlr) /* * assemble and send "WRITE CHARACTERISTICS" command */ - ma = (long)tsmsgp; - if (ma & 0x7FC00001) { /* address must be even and 22-bit */ - printf ("invalid address 0x%0x for msg-buffer.\n", ma); - return (-1); - } - - tsmsgp->hdr = ma & 0xFFFF; /* low order addr. bits */ - tsmsgp->dfl = (ma >> 16) & 0x003F; /* high order addr. bits */ - tsmsgp->rbpcr = 16; /* size of message-buffer */ - tsmsgp->xst0 = 0; /* chacacteristics mode word */ - tsmsgp->xst1 = 0; /* control word (ext.feat.) */ + ma = (long)tsmsgp; + if (ma & 0x7FC00001) { /* address must be even and 22-bit */ + printf ("invalid address 0x%0x for msg-buffer.\n", ma); + return (-1); + } + + tsmsgp->hdr = ma & 0xFFFF; /* low order addr. bits */ + tsmsgp->dfl = (ma >> 16) & 0x003F; /* high order addr. bits */ + tsmsgp->rbpcr = 16; /* size of message-buffer */ + tsmsgp->xst0 = 0; /* chacacteristics mode word */ + tsmsgp->xst1 = 0; /* control word (ext.feat.) */ #ifdef TS11_COMPAT tsmsgp->rbpcr = 14; /* size of message-buffer */ @@ -695,29 +634,29 @@ tswchar (ctlr) #endif #endif - tscmdp->cmdr = TS_CF_ACK | TS_CF_IE | TS_CMD_WCHAR; /* obsolete */ - tscmdp->cw1 = ma & 0xFFFF; - tscmdp->cw2 = (ma >> 16) & 0x003F; - tscmdp->cw3 = 10; /* size of charact.-data */ + tscmdp->cmdr = TS_CF_ACK | TS_CF_IE | TS_CMD_WCHAR; /* obsolete */ + tscmdp->cw1 = ma & 0xFFFF; + tscmdp->cw2 = (ma >> 16) & 0x003F; + tscmdp->cw3 = 10; /* size of charact.-data */ - if (tsexec (ctlr, TS_CMD_WCHAR) < 0) { - printf ("%s%d: write characteristics command failed [%x]\n", - CTLRNAME, ctlr, tsregs->tssr); - return (-1); + if (tsexec (ctlr, TS_CMD_WCHAR) < 0) { + printf ("%s: write characteristics command failed [%x]\n", + sc->sc_dev.dv_xname, tsregs->tssr); + return (-1); } - timeout = 1000; /* timeout in 10 seconds */ - do { + timeout = 1000; /* timeout in 10 seconds */ + do { DELAY(10000); - sr = tsregs->tssr; - debug10 (("\ttssr: 0x%x\n", sr)); - if (timeout-- > 0) { - printf ("timeout during initialize."); - tsstatus (sr); - return (-1); - } - } while ((sr & TS_SSR) == 0); - tsstatus (sr); + sr = tsregs->tssr; + debug10 (("\ttssr: 0x%x\n", sr)); + if (timeout-- > 0) { + printf ("timeout during initialize."); + tsstatus (sr); + return (-1); + } + } while ((sr & TS_SSR) == 0); + tsstatus (sr); return (0); } @@ -729,101 +668,95 @@ void tsreset(ctlr) int ctlr; { + struct ts_softc *sc = ts_cd.cd_devs[ctlr]; volatile struct tsdevice *tsreg = ts[ctlr].reg; volatile unsigned int sr, timeout; - trace (("tsreset (%d)\n", ctlr)); - /* * reset ctlr by writing into TSSR, then write characteristics */ - timeout = 1000; /* timeout in 10 seconds */ - tsreg->tssr = 0; /* start initialization */ - do { + timeout = 1000; /* timeout in 10 seconds */ + tsreg->tssr = 0; /* start initialization */ + do { DELAY(10000); - sr = tsreg->tssr; - debug10 (("\ttssr: 0x%x\n", sr)); - if (timeout-- > 0) { - if (sr != 0) - printf ("%s%d: timeout waiting for TS_SSR\n", - CTLRNAME, ctlr); - tsstatus (sr); + sr = tsreg->tssr; + debug10 (("\ttssr: 0x%x\n", sr)); + if (timeout-- > 0) { + if (sr != 0) + printf ("%s: timeout waiting for TS_SSR\n", + sc->sc_dev.dv_xname); + tsstatus (sr); return; - } - } while ((sr & TS_SSR) == 0); /* wait until subsystem ready */ - tsstatus (sr); + } + } while ((sr & TS_SSR) == 0); /* wait until subsystem ready */ + tsstatus (sr); return; } -extern struct cfdriver uba_cd; /* * probe for device. If found, try to raise an interrupt. + * XXX - most of this should be done in the attach routine. */ -int -tsprobe (reg, ctlr, um, uh) - caddr_t reg; /* address of TSDB register */ - int ctlr; /* index of the controller */ - struct uba_ctlr *um; /* controller-info */ - struct uba_softc *uh; +int +tsmatch(parent, match, aux) + struct device *parent; + void *match, *aux; { - register struct ts_softc *sc; - register struct tsdevice *tsregs = (struct tsdevice*) reg; + struct ts_softc *sc = match; + struct uba_softc *uh = (void *)parent; + struct uba_attach_args *ua = aux; + struct tsdevice *tsregs = (struct tsdevice*)ua->ua_addr; volatile unsigned int sr, timeout, count; - struct uba_softc *ubasc; - - trace (("tsprobe (%x, %d, %x)\n", reg, ctlr, um)); + int ctlr = sc->sc_dev.dv_unit; ts_wtab[ctlr] = NULL; - sc = &ts_softc[ctlr]; sc->sc_ts = &ts[ctlr]; sc->sc_state = ST_PROBE; sc->sc_flags = 0; - zsinfo[ctlr] = um; - ts[ctlr].reg = (struct tsdevice*) reg; + ts[ctlr].reg = (struct tsdevice*)ua->ua_addr; /* - * Set host-settable interrupt vector. - * Assign 0 to the TSSR register to start the ts-device initialization. - * The device is not really initialized at this point, this is just to - * find out if the device exists. - */ - ubasc = uba_cd.cd_devs[0]; /* XXX */ - sc->sc_ivec = (ubasc->uh_lastiv -= 4); + * Set host-settable interrupt vector. + * Assign 0 to the TSSR register to start the ts-device initialization. + * The device is not really initialized at this point, this is just to + * find out if the device exists. + */ + sc->sc_ivec = (uh->uh_lastiv -= 4); count = 0; again: timeout = 1000; /* timeout in 10 seconds */ - tsregs->tssr = 0; /* start initialization */ + tsregs->tssr = 0; /* start initialization */ do { DELAY(10000); sr = tsregs->tssr; debug10 (("\ttssr-1: 0x%x\n", sr)); if (timeout-- > 0) { if (sr != 0) /* the device exists !!! */ - printf ("%s%d: timeout waiting for TS_SSR\n", - CTLRNAME, ctlr); + printf ("%s: timeout waiting for TS_SSR\n", + sc->sc_dev.dv_xname); tsstatus (sr); goto bad; } } while ((sr & TS_SSR) == 0); /* wait until subsystem ready */ tsstatus (sr); - tswchar (ctlr); /* write charact. to enable interrupts */ + tswchar (ctlr); /* write charact. to enable interrupts */ /* completion of this will raise the intr. */ #ifdef notyet - sc->sc_ipl = br = qbgetpri(); + sc->sc_ipl = br = qbgetpri(); #else - sc->sc_ipl = 0x15; + sc->sc_ipl = 0x15; #endif - return (sizeof (struct tsdevice)); + return (sizeof (struct tsdevice)); bad: if (++count < 3) goto again; #ifdef notyet - splx(s); + splx(s); #endif return (0); } @@ -834,14 +767,14 @@ bad: if (++count < 3) * Since there's only one drive per controller there's nothing to do. * (we could check the status of the drive (online/offline/...) */ -int -tsslave (ui, reg) - struct uba_device *ui; /* ptr to the uba device structure */ - caddr_t reg; /* addr of the device controller */ +void +tsattach(parent, self, aux) + struct device *parent, *self; + void *aux; { - register int ctlr = ui->ui_ctlr; - register struct ts_softc *sc = &ts_softc[ctlr]; - register struct tsmsg *tsmsgp = &ts[ctlr].msg; + struct ts_softc *sc = (void *)self; + int ctlr = sc->sc_dev.dv_unit; + struct tsmsg *tsmsgp = &ts[ctlr].msg; trace (("tsslave (%x, %x)\n", ui, reg)); @@ -852,46 +785,30 @@ tsslave (ui, reg) */ sc->sc_state = ST_SLAVE; /* tsintr() checks this ... */ if (tswchar (ctlr) < 0) { - printf ("%s%d: cannot initialize", CTLRNAME, ctlr); - return (0); /* ??? XXX ??? */ + printf ("%s: cannot initialize", sc->sc_dev.dv_xname); } sc->sc_micro = (tsmsgp->xst2 & TS_SF_MCRL) >> 2; - printf ("%s%d: rev %d, extended features %s, transport %s\n", - CTLRNAME, ctlr, sc->sc_micro, + printf ("%s: rev %d, extended features %s, transport %s\n", + sc->sc_dev.dv_xname, sc->sc_micro, (tsmsgp->xst2 & TS_SF_EFES ? "enabled" : "disabled"), (ts[ctlr].reg->tssr & TS_OFL ? "offline" : "online")); - tsinit (ctlr); /* must be called once, why not here ? */ - - return (1); + tsinit (sc); /* must be called once, why not here ? */ } /* - * Open routine will issue the online command, later. - * Just reset the flags and do nothing ... - */ -void -tsattach (ui) - struct uba_device *ui; -{ - trace (("\ntsattach (%x)", ui)); - ui->ui_flags = 0; /* mark unit offline */ -} - - -/* * TSV05/TS05 interrupt routine */ void tsintr(ctlr) int ctlr; { - register struct ts_softc *sc = &ts_softc[ctlr]; + register struct ts_softc *sc = ts_cd.cd_devs[ctlr]; register struct tsmsg *tsmsgp = &ts[ctlr].msg; register struct tscmd *tscmdp = &ts[ctlr].cmd; volatile struct tsdevice *tsreg = ts[ctlr].reg; - struct uba_ctlr *um = zsinfo[ctlr]; + struct uba_unit *um = &sc->sc_unit; register struct buf *bp; unsigned short sr = tsreg->tssr; /* save TSSR */ @@ -902,12 +819,16 @@ tsintr(ctlr) short cmask = tscmdp->cmdr & TS_CF_CMASK; #ifdef DEBUG - printf ("TSSR: %b, MSG: %x ", sr, TS_TSSR_BITS, mh); + { + char bits[64]; + printf ("TSSR: %s, MSG: %x ", bitmask_snprintf(sr, + TS_TSSR_BITS, bits, sizeof(bits)), mh); + } switch (tsmsgp->hdr & 0x001F) { case 16: printf ("(End)"); break; case 17: printf ("(Fail)"); break; case 18: printf ("(Error)"); break; - case 19: printf ("(Attention)"); break; + case 19: printf ("(Attention)"); break; } #endif @@ -917,8 +838,8 @@ tsintr(ctlr) sc->sc_cmdf |= TS_CF_CVC; #ifdef QBA /* copied from uda.c */ - if(cpunumber == VAX_78032) - splx(sc->sc_ipl); /* Qbus interrupt protocol is odd */ + if(vax_cputype == VAX_78032) + splx(sc->sc_ipl); /* Qbus interrupt protocol is odd */ #endif /* @@ -935,14 +856,12 @@ tsintr(ctlr) switch (sc->sc_state) { case ST_INVALID: - /* - * Ignore unsolicited interrupts. - */ - debug (("%s%d: intr in state ST_INVALID [%x,%x]\n", - CTLRNAME, ctlr, sr, mh)); - log (LOG_WARNING, "%s%d: stray intr [%x,%x]\n", - CTLRNAME, ctlr, sr, mh); - return; + /* + * Ignore unsolicited interrupts. + */ + log (LOG_WARNING, "%s: stray intr [%x,%x]\n", + sc->sc_dev.dv_xname, sr, mh); + return; case ST_SLAVE: /* @@ -950,11 +869,9 @@ tsintr(ctlr) * issued by tsslave() and indicates the end of the * initialization phase. Just ignore it ... */ - debug (("%s%d: intr in state ST_SLAVE [%x,%x]\n", - CTLRNAME, ctlr, sr, mh)); if ((sr & TS_SC) != 0 || (sr & TS_TC) != TS_TC_NORM) { - printf ("%s%d: problem during init [%x,%x]\n", - CTLRNAME, ctlr, sr, mh); + printf("%s: problem during init [%x,%x]\n", + sc->sc_dev.dv_xname, sr, mh); /* return here ??? */ /* break and check the error outside switch ??? */ break; @@ -968,23 +885,18 @@ tsintr(ctlr) * Here we expect interrupts indicating the end of * commands or indicating problems. */ - debug (("%s%d: intr ST_RUN (%s) [%x,%x]\n", - CTLRNAME, ctlr, ((tsmsgp->xst0 & TS_SF_ONL) ? - "online" : "offline"), sr, mh)); /* * Anything else is handled outside this switch ... */ break; case ST_IDLE: - debug (("%s%d: intr ST_IDLE [%x,%x]\n", - CTLRNAME, ctlr, sr, mh)); break; default: - printf ("%s%d: unexpected interrupt during state %d [%x,%x]\n", - CTLRNAME, ctlr, sc->sc_state, sr, mh); + printf ("%s: unexpected interrupt during state %d [%x,%x]\n", + sc->sc_dev.dv_xname, sc->sc_state, sr, mh); return; } @@ -998,7 +910,6 @@ tsintr(ctlr) * Normal termination -- The operation is completed * witout incident. */ - debug (("%s%d: Normal Termination\n", CTLRNAME, ctlr)); sc->sc_state = ST_IDLE; /* XXX ??? */ sc->sc_state = ST_RUNNING; sc->sc_liowf = (ccode == TS_CC_WRITE); @@ -1006,12 +917,16 @@ tsintr(ctlr) if ((bp = ts_wtab[ctlr]) != NULL) { ts_wtab[ctlr] = NULL; /* pseudo-unlink */ - if (bp != &ts_cbuf[ctlr]) { /* no ioctl */ - debug (("ubarelse\n")); - ubarelse (um->um_ubanum, (int *)&bp->b_ubinfo); + if (bp != &ts_cbuf[ctlr]) { /* no ioctl */ + ubarelse((struct uba_softc *) + sc->sc_dev.dv_parent, + (int *)&bp->b_ubinfo); #if defined(VAX750) - if (cpunumber == VAX_750 && um->um_ubinfo != 0) - ubarelse(um->um_ubanum, &um->um_ubinfo); + if (vax_cputype == VAX_750 && + sc->sc_unit.uu_ubinfo != 0) + ubarelse((struct uba_softc *) + sc->sc_dev.dv_parent, + &sc->sc_unit.uu_ubinfo); /* XXX */ #endif } @@ -1030,10 +945,9 @@ tsintr(ctlr) * (Without EAI enabled, no Attention interrupts occur. * drive status changes are signaled by the VCK flag.) */ - debug (("%s%d: Attention\n", CTLRNAME, ctlr)); return; - case TS_TC_TSA: + case TS_TC_TSA: /* * Tape Status Alert -- A status condition is encountered * that may have significance to the program. Bits of @@ -1050,7 +964,7 @@ tsintr(ctlr) } break; - case TS_TC_FR: + case TS_TC_FR: /* * Function Reject -- The specified function was not * initiated. Bits of interest include OFL, VCK, BOT, @@ -1075,7 +989,7 @@ tsintr(ctlr) } break; - case TS_TC_TPD: + case TS_TC_TPD: /* * Recoverable Error -- Tape position is a record beyond * what its position was when the function was initiated. @@ -1096,7 +1010,7 @@ tsintr(ctlr) return; case TS_CMD_WD: /* Write Data (Next) */ debug (("retry write data ...\n")); - sc->sc_rtc = 1; + sc->sc_rtc = 1; tsexec (ctlr, TS_CMD_WDR); return; case TS_CMD_WTM: @@ -1109,7 +1023,7 @@ tsintr(ctlr) } break; - case TS_TC_TNM: + case TS_TC_TNM: /* * Recoverable Error -- Tape position has not changed. * Suggested recovery procedure is to log the error and @@ -1126,7 +1040,7 @@ tsintr(ctlr) } break; - case TS_TC_TPL: + case TS_TC_TPL: /* * Unrecoverable Error -- Tape position has been lost. * No valid recovery procedures exist unless the tape @@ -1135,7 +1049,7 @@ tsintr(ctlr) printf ("Tape position lost\n"); break; - case TS_TC_FCE: + case TS_TC_FCE: /* * Fatal subsytem Error -- The subsytem is incapable * of properly performing commands, or at least its @@ -1146,8 +1060,8 @@ tsintr(ctlr) printf ("Fatal Controller Error\n"); default: - printf ("%s%d: error 0x%x, resetting controller\n", - CTLRNAME, ctlr, sr & TS_TC); + printf ("%s: error 0x%x, resetting controller\n", + sc->sc_dev.dv_xname, sr & TS_TC); tsreset (ctlr); } @@ -1157,14 +1071,13 @@ tsintr(ctlr) if ((bp = ts_wtab[ctlr]) != NULL) { ts_wtab[ctlr] = NULL; /* pseudo unlink */ - if (bp != &ts_cbuf[ctlr]) { /* no ioctl */ - debug (("ubarelse-2\n")); - ubarelse(um->um_ubanum, (int *)&bp->b_ubinfo); - } - if ((sr & TS_TC) != TS_TC_NORM) { + if (bp != &ts_cbuf[ctlr]) /* no ioctl */ + ubarelse((struct uba_softc *)sc->sc_dev.dv_parent, + (int *)&bp->b_ubinfo); + + if ((sr & TS_TC) != TS_TC_NORM) bp->b_flags |= B_ERROR; - debug (("tsintr: bp->b_flags |= B_ERROR\n")); - } + debug (("resid:%d, count:%d, rbpcr:%d\n", bp->b_resid, bp->b_bcount, tsmsgp->rbpcr)); bp->b_resid = tsmsgp->rbpcr; /* XXX */ @@ -1196,27 +1109,27 @@ tsopen (dev, flag, type, p) trace (("tsopen (%x, %x)\n", dev, flag)); - if (unit >= NTS || (ui = tsinfo[unit]) == 0 || ui->ui_alive == 0) { - debug (("ui->ui_alive == 0\n")); - return (ENXIO); - } - sc = &ts_softc[ui->ui_ctlr]; /* unit ??? */ - if (sc->sc_openf) { - debug (("sc->sc_openf\n")); - return (EBUSY); - } + if (unit >= ts_cd.cd_ndevs) + return ENXIO; + + sc = ts_cd.cd_devs[unit]; + if (sc == 0) + return ENXIO; + + if (sc->sc_openf) + return EBUSY; + sc->sc_openf = 1; - sc->sc_tpr = tprintf_open (curproc); + s = splbio (); if (sc->sc_state < ST_RUNNING) { /* XXX */ - printf ("ts%d not running.\n", ui->ui_ctlr); + printf ("%s not running.\n", sc->sc_dev.dv_xname); (void) splx (s); sc->sc_openf = 0; return (ENXIO); } - um = ui->ui_mi; (void) splx (s); -#if 1 + /* * check if transport is really online. * (without attention-interrupts enabled, we really don't know @@ -1224,14 +1137,14 @@ tsopen (dev, flag, type, p) * (ie. MTNOP) once and check the actual status.) */ tscommand (dev, MTNOP, 1); - if (ts[TS_CTLR(dev)].reg->tssr & TS_OFL) { - printf ("ts%d: transport is offline.\n", ui->ui_ctlr); + if (ts[unit].reg->tssr & TS_OFL) { + printf ("%s: transport is offline.\n", sc->sc_dev.dv_xname); sc->sc_openf = 0; - return (EIO); /* transport is offline */ + return EIO; /* transport is offline */ } -#endif + sc->sc_liowf = 0; - return (0); + return 0; } @@ -1246,16 +1159,13 @@ tsopen (dev, flag, type, p) */ int tsclose (dev, flag, type, p) - dev_t dev; - int flag, type; + dev_t dev; + int flag, type; struct proc *p; { - register struct ts_softc *sc = &ts_softc[TS_UNIT(dev)]; - - trace (("tsclose (%x, %d)\n", dev, flag)); + register struct ts_softc *sc = ts_cd.cd_devs[TS_UNIT(dev)]; if (flag == FWRITE || ((flag & FWRITE) && sc->sc_liowf)) { - debug (("tsclose: writing eot\n")); /* * We are writing two tape marks (EOT), but place the tape * before the second one, so that another write operation @@ -1263,18 +1173,15 @@ tsclose (dev, flag, type, p) */ tscommand (dev, MTWEOF, 1); /* Write Tape Mark */ tscommand (dev, MTWEOF, 1); /* Write Tape Mark */ - tscommand (dev, MTBSF, 1); /* Skip Tape Marks Reverse */ + tscommand (dev, MTBSF, 1); /* Skip Tape Marks Reverse */ } - if ((minor(dev)&T_NOREWIND) == 0) { - debug (("tsclose: rewinding\n")); + if ((dev & T_NOREWIND) == 0) tscommand (dev, MTREW, 0); - } - tprintf_close (sc->sc_tpr); sc->sc_openf = 0; sc->sc_liowf = 0; - return (0); + return 0; } @@ -1283,51 +1190,20 @@ tsclose (dev, flag, type, p) */ void tsstrategy (bp) - register struct buf *bp; + register struct buf *bp; { - register struct uba_device *ui; - register struct uba_ctlr *um; register int unit = TS_UNIT(bp->b_dev); + struct ts_softc *sc = (void *)ts_cd.cd_devs[unit]; int s; - trace (("tsstrategy (...)\n")); - if (unit >= NTS) { - debug (("tsstrategy: bad unit # %d\n",unit)); - bp->b_flags |= B_ERROR; - iodone(bp); - return; - } - ui = tsinfo[unit]; - if (ui == 0 || ui->ui_alive == 0) { - debug (("tsstrategy: ui_alive == 0\n")); - bp->b_flags |= B_ERROR; - iodone(bp); - return; - } - s = splbio (); /* * we have only one command at one time, no credits. * thus we don't need buffer management and controller queue * just try to execute the command ... */ -#if 0 - if (ts_wtab[unit] != NULL) { - debug (("tsstrategy: already waiting for something\n")); - ts_wtab[unit]->b_flags |= B_ERROR; - iodone (ts_wtab[unit]); - } - ts_wtab[unit] = bp; -#endif - um = ui->ui_mi; - if (um->um_tab.b_active == 0) { - /* - * If the controller is not active, start it. - */ - } - - tsstart (um, bp); + tsstart (sc, bp); splx(s); return; } @@ -1338,10 +1214,10 @@ tsstrategy (bp) */ int tsioctl (dev, cmd, data, flag, p) - dev_t dev; + dev_t dev; u_long cmd; - caddr_t data; - int flag; + caddr_t data; + int flag; struct proc *p; { register struct buf *bp = &ts_cbuf[TS_UNIT(dev)]; @@ -1413,11 +1289,11 @@ tsioctl (dev, cmd, data, flag, p) return (error); case MTIOCGET: /* get tape status */ - sc = &ts_softc[TS_CTLR(dev)]; + sc = ts_cd.cd_devs[TS_UNIT(dev)]; mtget = (struct mtget *)data; mtget->mt_type = MT_ISTS; - mtget->mt_dsreg = (unsigned)(ts[TS_CTLR(dev)].reg->tssr); - mtget->mt_erreg = (unsigned)(ts[TS_CTLR(dev)].msg.hdr); + mtget->mt_dsreg = (unsigned)(ts[TS_UNIT(dev)].reg->tssr); + mtget->mt_erreg = (unsigned)(ts[TS_UNIT(dev)].msg.hdr); mtget->mt_resid = 0; /* ??? */ mtget->mt_density = 0; /* ??? */ break; @@ -1482,7 +1358,10 @@ tsstatus (sr) int sr; { #ifdef DEBUG - debug (("status: TSSR=%b\n", sr, TS_TSSR_BITS)); + char bits[64]; + + debug (("status: TSSR=%s\n", bitmask_snprintf(sr, TS_TSSR_BITS, + bits, sizeof(bits)))); if (tsdebug < 5) return (0); @@ -1496,7 +1375,7 @@ tsstatus (sr) if (sr & TS_A11) printf ("Address Bits 17-16\n"); if (sr & TS_SSR) printf ("Subsystem Ready\n"); if (sr & TS_OFL) printf ("Off Line\n"); - if (sr & TS_FTC) printf ("Fatal Termination Class Code\n"); + if (sr & TS_FTC) printf ("Fatal Termination Class Code\n"); switch (sr & TS_TC) { case TS_TC_NORM: printf ("Normal Termination\n"); break; case TS_TC_ATTN: printf ("Attention Condition\n"); break; @@ -1516,10 +1395,18 @@ tsxstatus (mp) struct tsmsg *mp; { #ifdef DEBUG - debug (("tsxstatus: xst0=%b, xst1=%b, xst2=%b, xst3=%b, xst4=%b\n", - mp->xst0, TS_XST0_BITS, mp->xst1, TS_XST1_BITS, - mp->xst2, TS_XST2_BITS, mp->xst3, TS_XST3_BITS, - mp->xst4, "\20")); + char bits[64]; + + debug (("tsxstatus: xst0=%s, ", bitmask_snprintf(mp->xst0, + TS_XST0_BITS, bits, sizeof(bits)))); + debug (("xst1=%s, ", bitmask_snprintf(mp->xst1, TS_XST1_BITS, + bits, sizeof(bits)))); + debug (("xst2=%s, ", bitmask_snprintf(mp->xst2, TS_XST2_BITS, + bits, sizeof(bits)))); + debug (("xst3=%s, ", bitmask_snprintf(mp->xst3, TS_XST3_BITS, + bits, sizeof(bits)))); + debug (("xst4=%s\n", bitmask_snprintf(mp->xst4, "\20", + bits, sizeof(bits)))); if (tsdebug < 10) return (0); @@ -1566,23 +1453,3 @@ tsxstatus (mp) if (mp->xst4 & TS_SF_RCX) printf ("Retry Count Exceeded\n"); #endif } - -int -ts_match(parent, match, aux) - struct device *parent; - void *match, *aux; -{ - return 0; -} - -void -ts_attach(parent, self, aux) - struct device *parent, *self; - void *aux; -{ -} - - - -#endif /* #if NTS > 0 */ - diff --git a/sys/arch/vax/uba/uba.c b/sys/arch/vax/uba/uba.c index 2018c4a60bd..fd1a2eadb84 100644 --- a/sys/arch/vax/uba/uba.c +++ b/sys/arch/vax/uba/uba.c @@ -1,8 +1,8 @@ -/* $NetBSD: uba.c,v 1.22 1996/04/08 18:37:34 ragge Exp $ */ - +/* $NetBSD: uba.c,v 1.29 1996/10/13 03:35:24 christos Exp $ */ /* + * Copyright (c) 1996 Jonathan Stone. + * Copyright (c) 1994, 1996 Ludd, University of Lule}, Sweden. * Copyright (c) 1982, 1986 The Regents of the University of California. - * Copyright (c) 1994 Ludd, University of Lule}, Sweden. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -34,7 +34,7 @@ * SUCH DAMAGE. * * @(#)uba.c 7.10 (Berkeley) 12/16/90 - * @(#)autoconf.c 7.20 (Berkeley) 5/9/91 + * @(#)autoconf.c 7.20 (Berkeley) 5/9/91 */ #include <sys/param.h> @@ -66,35 +66,435 @@ #include <vax/uba/ubareg.h> #include <vax/uba/ubavar.h> -extern int cold; - -volatile int rbr,rcvec; +volatile int rbr, rcvec, svec; -int uba_match __P((struct device *, void *, void *)); -void uba_attach __P((struct device *, struct device *, void *)); -void ubascan __P((struct device *, void *)); -int ubaprint __P((void *, const char *)); -void uba_dw780int __P((int)); -void ubaerror __P((int, struct uba_softc *, int *, int *, - struct uba_regs *)); -void ubainit __P((struct uba_softc *)); -void ubastray __P((int)); -void unifind __P((struct uba_softc *, caddr_t)); -void ubapurge __P((struct uba_ctlr *)); -void ubainitmaps __P((struct uba_softc *)); -int qbgetpri __P((void)); -int ubamem __P((int, int, int, int)); -void uba_dw780int __P((int)); +static void ubascan __P((struct device *, void *)); +static int ubaprint __P((void *, const char *)); +static void ubastray __P((int)); +static void ubainitmaps __P((struct uba_softc *)); +static void uba_attach __P((struct uba_softc *, unsigned long)); +static int ubasetup __P((struct uba_softc *, struct buf *, int)); struct cfdriver uba_cd = { NULL, "uba", DV_DULL, 1 }; -struct cfattach uba_ca = { - sizeof(struct uba_softc), uba_match, uba_attach +#define spluba spl7 + +#if defined(DW780) || defined(DW750) + +int dw_match __P((struct device *, void *, void *)); + +int +dw_match(parent, vcf, aux) + struct device *parent; + void *vcf, *aux; +{ + struct sbi_attach_args *sa = (struct sbi_attach_args *)aux; + struct cfdata *cf = vcf; + + if ((cf->cf_loc[0] != sa->nexnum) && (cf->cf_loc[0] > -1 )) + return 0; + + /* + * The uba type is actually only telling where the uba + * space is in nexus space. + */ + if ((sa->type & ~3) != NEX_UBA0) + return 0; + + return 1; +} +#endif + +#ifdef DW780 +/* + * The DW780 are directly connected to the SBI on 11/780 and 8600. + */ +void dw780_attach __P((struct device *, struct device *, void *)); +void dw780_beforescan __P((struct uba_softc *)); +void dw780_afterscan __P((struct uba_softc *)); +int dw780_errchk __P((struct uba_softc *)); +void dw780_init __P((struct uba_softc *)); +void dw780_purge __P((struct uba_softc *, int)); +void uba_dw780int __P((int)); +static void ubaerror __P((struct uba_softc *, int *, int *)); + +struct cfattach uba_sbi_ca = { + sizeof(struct uba_softc), dw_match, dw780_attach +}; + +char ubasr_bits[] = UBASR_BITS; + +void +dw780_attach(parent, self, aux) + struct device *parent, *self; + void *aux; +{ + struct uba_softc *sc = (void *)self; + struct sbi_attach_args *sa = aux; + int ubaddr = sa->type & 3; + + printf(": DW780\n"); + + /* + * Fill in bus specific data. + */ + sc->uh_uba = (void *)sa->nexaddr; + sc->uh_nbdp = NBDP780; + sc->uh_nr = sa->nexnum * (parent->dv_unit + 1); + sc->uh_beforescan = dw780_beforescan; + sc->uh_afterscan = dw780_afterscan; + sc->uh_errchk = dw780_errchk; + sc->uh_ubapurge = dw780_purge; + sc->uh_ubainit = dw780_init; + sc->uh_type = DW780; + sc->uh_memsize = UBAPAGES; + sc->uh_iarea = (void *)scb + NBPG + ubaddr * NBPG; + sc->uh_mr = sc->uh_uba->uba_map; + + bcopy(&idsptch, &sc->uh_dw780, sizeof(struct ivec_dsp)); + sc->uh_dw780.pushlarg = sc->uh_dev.dv_unit; + sc->uh_dw780.hoppaddr = uba_dw780int; + scb->scb_nexvec[0][sa->nexnum] = scb->scb_nexvec[1][sa->nexnum] + = scb->scb_nexvec[2][sa->nexnum] + = scb->scb_nexvec[3][sa->nexnum] = &sc->uh_dw780; + + uba_attach(sc, (parent->dv_unit ? UMEMB8600(ubaddr) : + UMEMA8600(ubaddr)) + (UBAPAGES * NBPG)); +} + +void +dw780_beforescan(sc) + struct uba_softc *sc; +{ + volatile int *hej = &sc->uh_uba->uba_sr; + + if (sc->uh_type == DW780) { + *hej = *hej; + sc->uh_uba->uba_cr = UBACR_IFS|UBACR_BRIE; + } +} + +void +dw780_afterscan(sc) + struct uba_softc *sc; +{ + if (sc->uh_type == DW780) + sc->uh_uba->uba_cr = UBACR_IFS | UBACR_BRIE | + UBACR_USEFIE | UBACR_SUEFIE | + (sc->uh_uba->uba_cr & 0x7c000000); +} + +/* + * On DW780 badaddr() in uba space sets a bit in uba_sr instead of + * doing a machine check. + */ +int +dw780_errchk(sc) + struct uba_softc *sc; +{ + volatile int *hej = &sc->uh_uba->uba_sr; + + if (sc->uh_type == DW780 && *hej) { + *hej = *hej; + return 1; + } + return 0; +} + +void +uba_dw780int(uba) + int uba; +{ + int br, vec, arg; + struct uba_softc *sc = uba_cd.cd_devs[uba]; + struct uba_regs *ur = sc->uh_uba; + void (*func) __P((int)); + + br = mfpr(PR_IPL); + svec = ur->uba_brrvr[br - 0x14]; + if (svec <= 0) { + ubaerror(sc, &br, (int *)&svec); + if (svec == 0) + return; + } + vec = svec >> 2; + if (cold) + rcvec = vec; + func = sc->uh_idsp[vec].hoppaddr; + arg = sc->uh_idsp[vec].pushlarg; + (*func)(arg); +} + +void +dw780_init(sc) + struct uba_softc *sc; +{ + sc->uh_uba->uba_cr = UBACR_ADINIT; + sc->uh_uba->uba_cr = UBACR_IFS|UBACR_BRIE|UBACR_USEFIE|UBACR_SUEFIE; + while ((sc->uh_uba->uba_cnfgr & UBACNFGR_UBIC) == 0) + ; +} + +void +dw780_purge(sc, bdp) + struct uba_softc *sc; + int bdp; +{ + sc->uh_uba->uba_dpr[bdp] |= UBADPR_BNE; +} + +int ubawedgecnt = 10; +int ubacrazy = 500; +int zvcnt_max = 5000; /* in 8 sec */ +int ubaerrcnt; +/* + * This routine is called by the locore code to process a UBA + * error on an 11/780 or 8600. The arguments are passed + * on the stack, and value-result (through some trickery). + * In particular, the uvec argument is used for further + * uba processing so the result aspect of it is very important. + * It must not be declared register. + */ +/*ARGSUSED*/ +void +ubaerror(uh, ipl, uvec) + register struct uba_softc *uh; + int *ipl, *uvec; +{ + struct uba_regs *uba = uh->uh_uba; + register sr, s; + + if (*uvec == 0) { + /* + * Declare dt as unsigned so that negative values + * are handled as >8 below, in case time was set back. + */ + u_long dt = time.tv_sec - uh->uh_zvtime; + + uh->uh_zvtotal++; + if (dt > 8) { + uh->uh_zvtime = time.tv_sec; + uh->uh_zvcnt = 0; + } + if (++uh->uh_zvcnt > zvcnt_max) { + printf("%s: too many zero vectors (%d in <%d sec)\n", + uh->uh_dev.dv_xname, uh->uh_zvcnt, (int)dt + 1); + printf("\tIPL 0x%x\n\tcnfgr: %b Adapter Code: 0x%x\n", + *ipl, uba->uba_cnfgr&(~0xff), UBACNFGR_BITS, + uba->uba_cnfgr&0xff); + printf("\tsr: %b\n\tdcr: %x (MIC %sOK)\n", + uba->uba_sr, ubasr_bits, uba->uba_dcr, + (uba->uba_dcr&0x8000000)?"":"NOT "); + ubareset(uh->uh_dev.dv_unit); + } + return; + } + if (uba->uba_cnfgr & NEX_CFGFLT) { + printf("%s: sbi fault sr=%b cnfgr=%b\n", + uh->uh_dev.dv_xname, uba->uba_sr, ubasr_bits, + uba->uba_cnfgr, NEXFLT_BITS); + ubareset(uh->uh_dev.dv_unit); + *uvec = 0; + return; + } + sr = uba->uba_sr; + s = spluba(); + printf("%s: uba error sr=%b fmer=%x fubar=%o\n", uh->uh_dev.dv_xname, + uba->uba_sr, ubasr_bits, uba->uba_fmer, 4*uba->uba_fubar); + splx(s); + uba->uba_sr = sr; + *uvec &= UBABRRVR_DIV; + if (++ubaerrcnt % ubawedgecnt == 0) { + if (ubaerrcnt > ubacrazy) + panic("uba crazy"); + printf("ERROR LIMIT "); + ubareset(uh->uh_dev.dv_unit); + *uvec = 0; + return; + } + return; +} +#endif + +#ifdef DW750 +/* + * The DW780 and DW750 are quite similar to their function from + * a programmers point of view. Differencies are number of BDP's + * and bus status/command registers, the latter are (partly) IPR's + * on 750. + */ +void dw750_attach __P((struct device *, struct device *, void *)); +void dw750_init __P((struct uba_softc *)); +void dw750_purge __P((struct uba_softc *, int)); + +struct cfattach uba_cmi_ca = { + sizeof(struct uba_softc), dw_match, dw750_attach +}; + +void +dw750_attach(parent, self, aux) + struct device *parent, *self; + void *aux; +{ + struct uba_softc *sc = (void *)self; + struct sbi_attach_args *sa = aux; + int ubaddr = sa->nexinfo & 1; + + printf(": DW750\n"); + + /* + * Fill in bus specific data. + */ + sc->uh_uba = (void *)sa->nexaddr; + sc->uh_nbdp = NBDP750; + sc->uh_nr = sa->nexnum; + sc->uh_ubapurge = dw750_purge; + sc->uh_ubainit = dw750_init; + sc->uh_type = DW750; + sc->uh_memsize = UBAPAGES; + sc->uh_iarea = (void *)scb + NBPG + ubaddr * NBPG; + sc->uh_mr = sc->uh_uba->uba_map; + + uba_attach(sc, UMEM750(ubaddr) + (UBAPAGES * NBPG)); +} + +void +dw750_init(sc) + struct uba_softc *sc; +{ + mtpr(0, PR_IUR); + DELAY(500000); +} + +void +dw750_purge(sc, bdp) + struct uba_softc *sc; + int bdp; +{ + sc->uh_uba->uba_dpr[bdp] |= UBADPR_PURGE | UBADPR_NXM | UBADPR_UCE; +} +#endif + +#ifdef QBA +/* + * The Q22 bus is the main IO bus on MicroVAX II/MicroVAX III systems. + * It has an address space of 4MB (22 address bits), therefore the name, + * and is hardware compatible with all 16 and 18 bits Q-bus devices. + * This driver can only handle map registers up to 1MB due to map info + * storage, but that should be enough for normal purposes. + */ +int qba_match __P((struct device *, void *, void *)); +void qba_attach __P((struct device *, struct device *, void *)); +void qba_beforescan __P((struct uba_softc*)); +void qba_init __P((struct uba_softc*)); + +struct cfattach uba_backplane_ca = { + sizeof(struct uba_softc), qba_match, qba_attach }; +int +qba_match(parent, vcf, aux) + struct device *parent; + void *vcf, *aux; +{ + struct bp_conf *bp = aux; + + if (strcmp(bp->type, "uba")) + return 0; + + return 1; +} + +void +qba_attach(parent, self, aux) + struct device *parent, *self; + void *aux; +{ + struct uba_softc *sc = (void *)self; + vm_offset_t mini, maxi; + + printf(": Q22\n"); + + + /* + * Fill in bus specific data. + */ +/* sc->uh_uba not used; no regs */ +/* sc->uh_nbdp is 0; Qbus has no BDP's */ +/* sc->uh_nr is 0; there can be only one! */ +/* sc->uh_afterscan; not used */ +/* sc->uh_errchk; not used */ + sc->uh_beforescan = qba_beforescan; + sc->uh_ubainit = qba_init; + sc->uh_type = QBA; + sc->uh_memsize = QBAPAGES; + sc->uh_iarea = (void *)scb + NBPG; + /* + * Map in the UBA page map into kernel space. On other UBAs, + * the map registers are in the bus IO space. + */ + (void)kmem_suballoc(kernel_map, &mini, &maxi, + QBAPAGES * sizeof(struct pte), FALSE); + pmap_map(mini, QBAMAP, QBAMAP + QBAPAGES * sizeof(struct pte), + VM_PROT_READ | VM_PROT_WRITE); + sc->uh_mr = (void *)mini; + + uba_attach(sc, QIOPAGE); +} + +/* + * Called when the QBA is set up; to enable DMA access from + * QBA devices to main memory. + */ +void +qba_beforescan(sc) + struct uba_softc *sc; +{ + *((u_short *)(sc->uh_iopage + QIPCR)) = Q_LMEAE; +} + +void +qba_init(sc) + struct uba_softc *sc; +{ + mtpr(0, PR_IUR); + DELAY(500000); + qba_beforescan(sc); +} +#endif +#ifdef DWBUA +int bua_match __P((struct device *, void *, void *)); +void bua_attach __P((struct device *, struct device *, void *)); + +struct cfattach uba_bi_ca = { + sizeof(struct uba_softc), bua_match, bua_attach +}; + +bua_beforescan(sc) + struct uba_softc *sc; +{ + if (sc->uh_type == DWBUA) + BUA(ubar)->bua_offset = (int)sc->uh_vec - (int)&scb[0]; +} + +void +bua_init(sc) + struct uba_softc *sc; +{ + BUA(uba)->bua_csr |= BUACSR_UPI; + /* give devices time to recover from power fail */ + DELAY(500000); + break; +} +#endif +#ifdef DW730 +struct cfattach uba_dw730_ca = { + sizeof(struct uba_softc), dw730_match, dw730_attach +}; +#endif /* * Stray interrupt vector handler, used when nowhere else to go to. */ @@ -104,13 +504,12 @@ ubastray(arg) { struct callsframe *cf = FRAMEOFFSET(arg); struct uba_softc *sc = uba_cd.cd_devs[arg]; - struct uba_regs *ur = sc->uh_uba; int vektor; rbr = mfpr(PR_IPL); #ifdef DW780 if (sc->uh_type == DW780) - vektor = ur->uba_brrvr[rbr - 0x14] >> 2; + vektor = svec >> 2; else #endif vektor = (cf->ca_pc - (unsigned)&sc->uh_idsp[0]) >> 4; @@ -121,131 +520,10 @@ ubastray(arg) #endif rcvec = vektor; } else - printf("uba%d: unexpected interrupt, vector %o, br %d\n", - arg, vektor << 2, rbr - 20); -} - -/* - * 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; - } - } + printf("uba%d: unexpected interrupt, vector 0x%x, br 0x%x\n", + arg, svec, rbr); } - -#ifdef DW780 -char ubasr_bits[] = UBASR_BITS; -#endif - -#define spluba splbio /* IPL 17 */ - /* * Do transfer on device argument. The controller * and uba involved are implied by the device. @@ -253,7 +531,7 @@ char ubasr_bits[] = UBASR_BITS; * We return 1 if the transfer was started, 0 if it was not. * * The onq argument must be zero iff the device is not on the - * queue for this UBA. If onq is set, the device must be at the + * queue for this UBA. If onq is set, the device must be at the * head of the queue. In any case, if the transfer is started, * the device will be off the queue, and if not, it will be on. * @@ -263,82 +541,64 @@ char ubasr_bits[] = UBASR_BITS; * does not now have a BDP. */ int -ubaqueue(ui, onq) - register struct uba_device *ui; - int onq; +ubaqueue(uu, bp) + register struct uba_unit *uu; + struct buf *bp; { - register struct uba_ctlr *um = ui->ui_mi; register struct uba_softc *uh; - register struct uba_driver *ud; - register int s, unit; + register int s; - uh = uba_cd.cd_devs[um->um_ubanum]; - ud = um->um_driver; + uh = (void *)((struct device *)(uu->uu_softc))->dv_parent; s = spluba(); /* * Honor exclusive BDP use requests. */ - if ((ud->ud_xclu && uh->uh_users > 0) || uh->uh_xclu) + if ((uu->uu_xclu && uh->uh_users > 0) || uh->uh_xclu) goto rwait; - if (ud->ud_keepbdp) { + if (uu->uu_keepbdp) { /* * First get just a BDP (though in fact it comes with * one map register too). */ - if (um->um_bdp == 0) { - um->um_bdp = uballoc(um->um_ubanum, - (caddr_t)0, 0, UBA_NEEDBDP|UBA_CANTWAIT); - if (um->um_bdp == 0) + if (uu->uu_bdp == 0) { + uu->uu_bdp = uballoc(uh, (caddr_t)0, 0, + UBA_NEEDBDP|UBA_CANTWAIT); + if (uu->uu_bdp == 0) goto rwait; } /* now share it with this transfer */ - um->um_ubinfo = ubasetup(um->um_ubanum, - um->um_tab.b_actf->b_actf, - um->um_bdp|UBA_HAVEBDP|UBA_CANTWAIT); + uu->uu_ubinfo = ubasetup(uh, bp, + uu->uu_bdp|UBA_HAVEBDP|UBA_CANTWAIT); } else - um->um_ubinfo = ubasetup(um->um_ubanum, - um->um_tab.b_actf->b_actf, UBA_NEEDBDP|UBA_CANTWAIT); - if (um->um_ubinfo == 0) + uu->uu_ubinfo = ubasetup(uh, bp, UBA_NEEDBDP|UBA_CANTWAIT); + if (uu->uu_ubinfo == 0) goto rwait; uh->uh_users++; - if (ud->ud_xclu) + if (uu->uu_xclu) uh->uh_xclu = 1; + splx(s); - if (ui->ui_dk >= 0) { - unit = ui->ui_dk; - dk_busy |= 1<<unit; - dk_xfer[unit]++; - dk_wds[unit] += um->um_tab.b_actf->b_actf->b_bcount>>6; - } - if (onq) - uh->uh_actf = ui->ui_forw; - (*ud->ud_dgo)(um); return (1); + rwait: - if (!onq) { - ui->ui_forw = NULL; - if (uh->uh_actf == NULL) - uh->uh_actf = ui; - else - uh->uh_actl->ui_forw = ui; - uh->uh_actl = ui; - } + SIMPLEQ_INSERT_TAIL(&uh->uh_resq, uu, uu_resq); splx(s); return (0); } void -ubadone(um) - struct uba_ctlr *um; +ubadone(uu) + struct uba_unit *uu; { - struct uba_softc *uh = uba_cd.cd_devs[um->um_ubanum]; + struct uba_softc *uh = (void *)((struct device *) + (uu->uu_softc))->dv_parent; - if (um->um_driver->ud_xclu) + if (uu->uu_xclu) uh->uh_xclu = 0; uh->uh_users--; - if (um->um_driver->ud_keepbdp) - um->um_ubinfo &= ~BDPMASK; /* keep BDP for misers */ - ubarelse(um->um_ubanum, &um->um_ubinfo); + if (uu->uu_keepbdp) + uu->uu_ubinfo &= ~BDPMASK; /* keep BDP for misers */ + ubarelse(uh, &uu->uu_ubinfo); } /* @@ -349,27 +609,19 @@ ubadone(um) * bdp number and number of map registers. */ int -ubasetup(uban, bp, flags) +ubasetup(uh, bp, flags) + struct uba_softc *uh; struct buf *bp; - int uban, flags; + int flags; { - struct uba_softc *uh = uba_cd.cd_devs[uban]; - struct pte *pte, *io; int npf; - int pfnum, temp; + int temp; int reg, bdp; - unsigned v; - struct proc *rp; int a, o, ubinfo; -#ifdef DW730 - if (uh->uh_type == DW730) - flags &= ~UBA_NEEDBDP; -#endif -#ifdef QBA - if (uh->uh_type == QBA) + if (uh->uh_nbdp == 0) flags &= ~UBA_NEEDBDP; -#endif + o = (int)bp->b_un.b_addr & PGOFSET; npf = btoc(bp->b_bcount + o) + 1; if (npf > UBA_MAXNMR) @@ -412,47 +664,9 @@ ubasetup(uban, bp, flags) temp = (bdp << 21) | UBAMR_MRV; if (bdp && (o & 01)) temp |= UBAMR_BO; - if ((bp->b_flags & B_PHYS) == 0) - pte = (struct pte *)kvtopte(bp->b_un.b_addr); - else { - struct pte *hej; - int i; - rp = bp->b_proc; - v = btop((u_int)bp->b_un.b_addr&0x3fffffff); + disk_reallymapin(bp, uh->uh_mr, reg, temp | PG_V); - /* - * It may be better to use pmap_extract() here - * somewhere, but so far we do it "the hard way" :) - */ - if (((u_int)bp->b_un.b_addr < 0x40000000) || - ((u_int)bp->b_un.b_addr > 0x7fffffff)) - hej = rp->p_vmspace->vm_pmap.pm_pcb->P0BR; - else - hej = rp->p_vmspace->vm_pmap.pm_pcb->P1BR; - - pte = &hej[v]; - for (i = 0; i < (npf - 1); i++) { - if ((pte + i)->pg_pfn == 0) { - int rv; - - rv = vm_fault(&rp->p_vmspace->vm_map, - (u_int)bp->b_un.b_addr + i * NBPG, - VM_PROT_READ, FALSE); - if (rv) - panic("DMA to nonexistent page"); - } - } - } - io = &uh->uh_mr[reg]; - while (--npf > 0) { - pfnum = pte->pg_pfn; - if (pfnum == 0) - panic("uba zero uentry"); - pte++; - *(int *)io++ = pfnum | temp; - } - *(int *)io = 0; return (ubinfo); } @@ -460,9 +674,10 @@ ubasetup(uban, bp, flags) * Non buffer setup interface... set up a buffer and call ubasetup. */ int -uballoc(uban, addr, bcnt, flags) +uballoc(uh, addr, bcnt, flags) + struct uba_softc *uh; caddr_t addr; - int uban, bcnt, flags; + int bcnt, flags; { struct buf ubabuf; @@ -470,7 +685,7 @@ uballoc(uban, addr, bcnt, flags) ubabuf.b_flags = B_BUSY; ubabuf.b_bcount = bcnt; /* that's all the fields ubasetup() needs */ - return (ubasetup(uban, &ubabuf, flags)); + return (ubasetup(uh, &ubabuf, flags)); } /* @@ -479,10 +694,11 @@ uballoc(uban, addr, bcnt, flags) * against uba resets on 11/780's. */ void -ubarelse(uban, amr) - int uban, *amr; +ubarelse(uh, amr) + struct uba_softc *uh; + int *amr; { - register struct uba_softc *uh = uba_cd.cd_devs[uban]; + struct uba_unit *uu; register int bdp, reg, npf, s; int mr; @@ -503,26 +719,9 @@ ubarelse(uban, amr) *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; - } + if (uh->uh_ubapurge) + (*uh->uh_ubapurge)(uh, bdp); + uh->uh_bdpfree |= 1 << (bdp-1); /* atomic */ if (uh->uh_bdpwant) { uh->uh_bdpwant = 0; @@ -549,35 +748,10 @@ ubarelse(uban, amr) uh->uh_mrwant = 0; wakeup((caddr_t)&uh->uh_mrwant); } - while (uh->uh_actf && ubaqueue(uh->uh_actf, 1)) - ; -} - -void -ubapurge(um) - register struct uba_ctlr *um; -{ - register struct uba_softc *uh = um->um_hd; - register int bdp = UBAI_BDP(um->um_ubinfo); - - switch (uh->uh_type) { -#ifdef DWBUA - case DWBUA: - BUA(uh->uh_uba)->bua_dpr[bdp] |= BUADPR_PURGE; - break; -#endif -#ifdef DW780 - case DW780: - uh->uh_uba->uba_dpr[bdp] |= UBADPR_BNE; - break; -#endif -#ifdef DW750 - case DW750: - uh->uh_uba->uba_dpr[bdp] |= UBADPR_PURGE|UBADPR_NXM|UBADPR_UCE; - break; -#endif - default: - break; + while ((uu = uh->uh_resq.sqh_first)) { + SIMPLEQ_REMOVE_HEAD(&uh->uh_resq, uu, uu_resq); + if ((*uu->uu_ready)(uu) == 0) + break; } } @@ -589,29 +763,11 @@ ubainitmaps(uhp) if (uhp->uh_memsize > UBA_MAXMR) uhp->uh_memsize = UBA_MAXMR; rminit(uhp->uh_map, (long)uhp->uh_memsize, (long)1, "uba", UAMSIZ); - switch (uhp->uh_type) { -#ifdef DWBUA - case DWBUA: - uhp->uh_bdpfree = (1<<NBDPBUA) - 1; - break; -#endif -#ifdef DW780 - case DW780: - uhp->uh_bdpfree = (1<<NBDP780) - 1; - break; -#endif -#ifdef DW750 - case DW750: - uhp->uh_bdpfree = (1<<NBDP750) - 1; - break; -#endif - default: - break; - } + uhp->uh_bdpfree = (1 << uhp->uh_nbdp) - 1; } /* - * Generate a reset on uba number uban. Then + * Generate a reset on uba number uban. Then * call each device that asked to be called during attach, * giving it a chance to clean up so as to be able to continue. */ @@ -626,82 +782,25 @@ ubareset(uban) uh->uh_users = 0; uh->uh_zvcnt = 0; uh->uh_xclu = 0; - uh->uh_actf = uh->uh_actl = 0; + SIMPLEQ_INIT(&uh->uh_resq); uh->uh_bdpwant = 0; uh->uh_mrwant = 0; ubainitmaps(uh); wakeup((caddr_t)&uh->uh_bdpwant); wakeup((caddr_t)&uh->uh_mrwant); printf("%s: reset", uh->uh_dev.dv_xname); - ubainit(uh); -#ifdef notyet - ubameminit(uban); -#endif + (*uh->uh_ubainit)(uh); + for (i = 0; i < uh->uh_resno; i++) (*uh->uh_reset[i])(uh->uh_resarg[i]); printf("\n"); splx(s); } -/* - * Init a uba. - */ -void -ubainit(uhp) - struct uba_softc *uhp; -{ - volatile struct uba_regs *ur = uhp->uh_uba; - - switch (uhp->uh_type) { -#ifdef DWBUA - case DWBUA: - BUA(uba)->bua_csr |= BUACSR_UPI; - /* give devices time to recover from power fail */ - DELAY(500000); - break; -#endif -#if DW780 - case DW780: - ur->uba_cr = UBACR_ADINIT; - ur->uba_cr = UBACR_IFS|UBACR_BRIE|UBACR_USEFIE|UBACR_SUEFIE; - while ((ur->uba_cnfgr & UBACNFGR_UBIC) == 0) - ; - break; -#endif -#ifdef DW750 - case DW750: -#endif -#ifdef DW730 - case DW730: -#endif -#ifdef QBA - case QBA: -#endif -#if DW750 || DW730 || QBA - mtpr(0, PR_IUR); - /* give devices time to recover from power fail */ - -/* THIS IS PROBABLY UNNECESSARY */ - DELAY(500000); -/* END PROBABLY UNNECESSARY */ - -#ifdef QBA - /* - * Re-enable local memory access - * from the Q-bus. - */ - if (uhp->uh_type == QBA) - *((u_short *)(uhp->uh_iopage + QIPCR)) = Q_LMEAE; -#endif QBA - break; -#endif DW750 || DW730 || QBA - } -} - -#ifdef QBA +#ifdef notyet /* * Determine the interrupt priority of a Q-bus - * peripheral. The device probe routine must spl6(), + * peripheral. The device probe routine must spl6(), * attempt to make the device request an interrupt, * delaying as necessary, then call this routine * before resetting the device. @@ -709,329 +808,45 @@ ubainit(uhp) int qbgetpri() { -#ifdef notyet int pri; - extern int cvec; - panic("qbgetpri"); for (pri = 0x17; pri > 0x14; ) { - if (cvec && cvec != 0x200) /* interrupted at pri */ + if (rcvec && rcvec != 0x200) /* interrupted at pri */ break; pri--; splx(pri - 1); } - (void) spl0(); + spl0(); return (pri); -#else - return 0x17; -#endif -} -#endif - -#ifdef DW780 -int ubawedgecnt = 10; -int ubacrazy = 500; -int zvcnt_max = 5000; /* in 8 sec */ -/* - * This routine is called by the locore code to process a UBA - * error on an 11/780 or 8600. The arguments are passed - * on the stack, and value-result (through some trickery). - * In particular, the uvec argument is used for further - * uba processing so the result aspect of it is very important. - * It must not be declared register. - */ -/*ARGSUSED*/ -void -ubaerror(uban, uh, ipl, uvec, uba) - register int uban; - register struct uba_softc *uh; - int *ipl, *uvec; - register struct uba_regs *uba; -{ - register sr, s; - - if (*uvec == 0) { - /* - * Declare dt as unsigned so that negative values - * are handled as >8 below, in case time was set back. - */ - u_long dt = time.tv_sec - uh->uh_zvtime; - - uh->uh_zvtotal++; - if (dt > 8) { - uh->uh_zvtime = time.tv_sec; - uh->uh_zvcnt = 0; - } - if (++uh->uh_zvcnt > zvcnt_max) { - printf("uba%d: too many zero vectors (%d in <%d sec)\n", - uban, uh->uh_zvcnt, (int)dt + 1); - printf("\tIPL 0x%x\n\tcnfgr: %b Adapter Code: 0x%x\n", - *ipl, uba->uba_cnfgr&(~0xff), UBACNFGR_BITS, - uba->uba_cnfgr&0xff); - printf("\tsr: %b\n\tdcr: %x (MIC %sOK)\n", - uba->uba_sr, ubasr_bits, uba->uba_dcr, - (uba->uba_dcr&0x8000000)?"":"NOT "); - ubareset(uban); - } - return; - } - if (uba->uba_cnfgr & NEX_CFGFLT) { - printf("uba%d: sbi fault sr=%b cnfgr=%b\n", - uban, uba->uba_sr, ubasr_bits, - uba->uba_cnfgr, NEXFLT_BITS); - ubareset(uban); - *uvec = 0; - return; - } - sr = uba->uba_sr; - s = spluba(); - printf("uba%d: uba error sr=%b fmer=%x fubar=%o\n", - uban, uba->uba_sr, ubasr_bits, uba->uba_fmer, 4*uba->uba_fubar); - splx(s); - uba->uba_sr = sr; - *uvec &= UBABRRVR_DIV; - if (++uh->uh_errcnt % ubawedgecnt == 0) { - if (uh->uh_errcnt > ubacrazy) - panic("uba crazy"); - printf("ERROR LIMIT "); - ubareset(uban); - *uvec = 0; - return; - } - return; } #endif /* - * Look for devices with unibus memory, allow them to configure, then disable - * map registers as necessary. Called during autoconfiguration and ubareset. - * The device ubamem routine returns 0 on success, 1 on success if it is fully - * configured (has no csr or interrupt, so doesn't need to be probed), - * and -1 on failure. - */ -#ifdef notyet -ubameminit(uban) -{ - register struct uba_device *ui; - register struct uba_softc *uh = uba_cd.cd_devs[uban]; - caddr_t umembase, addr; -#define ubaoff(off) ((int)(off) & 0x1fff) - - umembase = uh->uh_iopage; - uh->uh_lastmem = 0; - for (ui = ubdinit; ui->ui_driver; ui++) { - if (ui->ui_ubanum != uban && ui->ui_ubanum != '?') - continue; - if (ui->ui_driver->ud_ubamem) { - /* - * During autoconfiguration, need to fudge ui_addr. - */ - addr = ui->ui_addr; - ui->ui_addr = umembase + ubaoff(addr); - switch ((*ui->ui_driver->ud_ubamem)(ui, uban)) { - case 1: - ui->ui_alive = 1; - /* FALLTHROUGH */ - case 0: - ui->ui_ubanum = uban; - break; - } - ui->ui_addr = addr; - } - } -#ifdef DW780 -jdhfgsjdkfhgsdjkfghak - /* - * On a DW780, throw away any map registers disabled by rounding - * the map disable in the configuration register - * up to the next 8K boundary, or below the last unibus memory. - */ - if (uh->uh_type == DW780) { - register i; - - i = btop(((uh->uh_lastmem + 8191) / 8192) * 8192); - while (i) - (void) rmget(uh->uh_map, 1, i--); - } -#endif -} -#endif - -/* - * Allocate UNIBUS memory. Allocates and initializes - * sufficient mapping registers for access. On a 780, - * the configuration register is setup to disable UBA - * response on DMA transfers to addresses controlled - * by the disabled mapping registers. - * On a DW780, should only be called from ubameminit, or in ascending order - * from 0 with 8K-sized and -aligned addresses; freeing memory that isn't - * the last unibus memory would free unusable map registers. - * Doalloc is 1 to allocate, 0 to deallocate. - */ -int -ubamem(uban, addr, npg, doalloc) - int uban, addr, npg, doalloc; -{ - register struct uba_softc *uh = uba_cd.cd_devs[uban]; - register int a; - int s; - - a = (addr >> 9) + 1; - s = spluba(); - if (doalloc) - panic("uba: rmget"); -/* a = rmget(uh->uh_map, npg, a); */ - else - rmfree(uh->uh_map, (long)npg, (long)a); - splx(s); - if (a) { - register int i, *m; - - m = (int *)&uh->uh_mr[a - 1]; - for (i = 0; i < npg; i++) - *m++ = 0; /* All off, especially 'valid' */ - i = addr + npg * 512; - if (doalloc && i > uh->uh_lastmem) - uh->uh_lastmem = i; - else if (doalloc == 0 && i == uh->uh_lastmem) - uh->uh_lastmem = addr; -#ifdef DW780 - /* - * On a 780, set up the map register disable - * field in the configuration register. Beware - * of callers that request memory ``out of order'' - * or in sections other than 8K multiples. - * Ubameminit handles such requests properly, however. - */ - if (uh->uh_type == DW780) { - i = uh->uh_uba->uba_cr &~ 0x7c000000; - i |= ((uh->uh_lastmem + 8191) / 8192) << 26; - uh->uh_uba->uba_cr = i; - } -#endif - } - return (a); -} - -#include "ik.h" -#include "vs.h" -#if NIK > 0 || NVS > 0 -/* - * Map a virtual address into users address space. Actually all we - * do is turn on the user mode write protection bits for the particular - * page of memory involved. - */ -maptouser(vaddress) - caddr_t vaddress; -{ - - kvtopte(vaddress)->pg_prot = (PG_UW >> 27); -} - -unmaptouser(vaddress) - caddr_t vaddress; -{ - - kvtopte(vaddress)->pg_prot = (PG_KW >> 27); -} -#endif - -#ifdef DW780 -void -uba_dw780int(uba) - int uba; -{ - int br, svec, vec, arg; - struct uba_softc *sc = uba_cd.cd_devs[uba]; - struct uba_regs *ur = sc->uh_uba; - void (*func) __P((int)); - - br = mfpr(PR_IPL); - svec = ur->uba_brrvr[br - 0x14]; - if (svec < 0) { - ubaerror(uba, sc, &br, &svec, ur); - if (svec == 0) - return; - } - vec = svec >> 2; - if (cold) - rcvec = vec; - func = sc->uh_idsp[vec].hoppaddr; - arg = sc->uh_idsp[vec].pushlarg; - (*func)(arg); -} -#endif - -/* - * The match routine checks which UBA adapter number it is, to - * be sure to use correct interrupt vectors. - */ -int -uba_match(parent, vcf, aux) - struct device *parent; - void *vcf, *aux; -{ - struct sbi_attach_args *sa = (struct sbi_attach_args *)aux; - struct cfdata *cf = vcf; - - if ((cf->cf_loc[0] != sa->nexnum) && (cf->cf_loc[0] > -1 )) - return 0; - - switch (sa->type) { - case NEX_UBA0: - sa->nexinfo = 0; - break; - case NEX_UBA1: - sa->nexinfo = 1; - break; - case NEX_UBA2: - sa->nexinfo = 2; - break; - case NEX_UBA3: - sa->nexinfo = 3; - break; - - default: - return 0; - } - return 1; -} - -/* - * The attach routines: + * The common attach routines: * Allocates interrupt vectors. - * Puts correct (cpu-specific) addresses in uba_softc. + * Puts correct values in uba_softc. * Calls the scan routine to search for uba devices. */ void -uba_attach(parent, self, aux) - struct device *parent, *self; - void *aux; +uba_attach(sc, iopagephys) + struct uba_softc *sc; + unsigned long iopagephys; { - struct sbi_attach_args *sa = (struct sbi_attach_args *)aux; - struct uba_regs *ubar = (struct uba_regs *)sa->nexaddr; - struct uba_softc *sc = (struct uba_softc *)self; - vm_offset_t min, max, ubaphys, ubaiophys; + vm_offset_t mini, maxi; extern struct ivec_dsp idsptch; - printf("\n"); /* - * Allocate place for unibus memory in virtual space. - * This is done with kmem_suballoc() but after that - * never used in the vm system. Is it OK to do so? + * Set last free interrupt vector for devices with + * programmable interrupt vectors. Use is to decrement + * this number and use result as interrupt vector. */ - (void)kmem_suballoc(kernel_map, &min, &max, - (UBAPAGES + UBAIOPAGES) * NBPG, FALSE); - sc->uh_mem = (caddr_t)min; - sc->uh_uba = (void*)ubar; - sc->uh_memsize = UBAPAGES; - sc->uh_iopage = (void *)min + (sc->uh_memsize * NBPG); - sc->uh_iarea = (void *)scb + NBPG + sa->nexinfo * NBPG; - sc->uh_resno = 0; + sc->uh_lastiv = 0x200; + SIMPLEQ_INIT(&sc->uh_resq); + /* * Create interrupt dispatchers for this uba. */ -#define NO_IVEC 128 +#define NO_IVEC 128 { vm_offset_t iarea; int i; @@ -1048,81 +863,15 @@ uba_attach(parent, self, aux) sc->uh_iarea[i] = (unsigned int)&sc->uh_idsp[i]; } } - - switch (cpunumber) { -#if VAX780 || VAX8600 - case VAX_780: - case VAX_8600: - sc->uh_mr = (void *)ubar->uba_map; - sc->uh_type = DW780; - sc->uh_physuba = (struct uba_regs *)kvtophys(sa->nexaddr); - if (parent->dv_unit == 0) { - ubaphys = UMEMA8600(sa->nexinfo); - ubaiophys = UMEMA8600(sa->nexinfo) + (UBAPAGES * NBPG); - } else { - ubaphys = UMEMB8600(sa->nexinfo); - ubaiophys = UMEMB8600(sa->nexinfo) + (UBAPAGES * NBPG); - } - bcopy(&idsptch, &sc->uh_dw780, sizeof(struct ivec_dsp)); - sc->uh_dw780.pushlarg = sc->uh_dev.dv_unit; - sc->uh_dw780.hoppaddr = uba_dw780int; - scb->scb_nexvec[0][sa->nexnum] = scb->scb_nexvec[1][sa->nexnum] - = scb->scb_nexvec[2][sa->nexnum] - = scb->scb_nexvec[3][sa->nexnum] = &sc->uh_dw780; - break; -#endif -#if VAX750 - case VAX_750: - sc->uh_mr = (void *)ubar->uba_map; - sc->uh_type = DW750; - sc->uh_physuba = (struct uba_regs *)kvtophys(sa->nexaddr); - ubaphys = UMEM750(sa->nexinfo); - ubaiophys = UMEM750(sa->nexinfo) + (UBAPAGES * NBPG); - break; -#endif -#if VAX630 || VAX410 - case VAX_78032: - switch (cpu_type) { -#if VAX630 - case VAX_630: - sc->uh_mr = (void *)sa->nexaddr; - sc->uh_type = QBA; - sc->uh_physuba = (void*)QBAMAP630; - ubaphys = QMEM630; - ubaiophys = QIOPAGE630; - break; -#endif - default: - ubaphys = QMEM630; - ubaiophys = QIOPAGE630; - }; - break; -#endif -#if VAX650 - case VAX_650: - sc->uh_mr = (void *)sa->nexaddr; - sc->uh_type = QBA; - sc->uh_physuba = (void*)QBAMAP630; /* XXX */ - ubaphys = QMEM630; /* XXX */ - ubaiophys = QIOPAGE630; /* XXX */ - break; -#endif - default: - printf("Bad luck, this cputype does not support UBA's\n"); - return; - }; /* - * Map uba space in kernel virtual; especially i/o space. + * Allocate place for unibus memory in virtual space. + * This is done with kmem_suballoc() but after that + * never used in the vm system. Is it OK to do so? */ - pmap_map(min, ubaphys, ubaphys + (UBAPAGES * NBPG), + (void)kmem_suballoc(kernel_map, &mini, &maxi, UBAIOPAGES * NBPG, FALSE); + pmap_map(mini, iopagephys, iopagephys + UBAIOPAGES * NBPG, VM_PROT_READ|VM_PROT_WRITE); - pmap_map(min + (UBAPAGES * NBPG), ubaiophys, ubaiophys + - (UBAIOPAGES * NBPG), VM_PROT_READ|VM_PROT_WRITE); -#if VAX630 || VAX650 - /* Enable access to local memory. */ - if (cpu_type == VAX_630 || cpunumber == VAX_650) - *((u_short *)(sc->uh_iopage + QIPCR)) = Q_LMEAE; -#endif + sc->uh_iopage = (void *)mini; /* * Initialize the UNIBUS, by freeing the map * registers and the buffered data path registers @@ -1133,50 +882,20 @@ uba_attach(parent, self, aux) ubainitmaps(sc); /* - * Set last free interrupt vector for devices with - * programmable interrupt vectors. Use is to decrement - * this number and use result as interrupt vector. - */ - sc->uh_lastiv = 0x200; - -#ifdef DWBUA - if (sc->uh_type == DWBUA) - BUA(ubar)->bua_offset = (int)sc->uh_vec - (int)&scb[0]; -#endif - -#ifdef DW780 - if (sc->uh_type == DW780) { - ubar->uba_sr = ubar->uba_sr; - ubar->uba_cr = UBACR_IFS|UBACR_BRIE; - } -#endif -#ifdef notyet - /* - * First configure devices that have unibus memory, - * allowing them to allocate the correct map registers. - */ - ubameminit(uhp->uh_dev.dv_unit); -#endif - /* * Map the first page of UNIBUS i/o space to the first page of memory - * for devices which will need to dma output to produce an interrupt. - * ??? - Why? This is rpb page... /ragge + * for devices which will need to dma to produce an interrupt. */ *(int *)(&sc->uh_mr[0]) = UBAMR_MRV; + if (sc->uh_beforescan) + (*sc->uh_beforescan)(sc); /* * Now start searching for devices. */ - unifind(sc, (caddr_t)ubaiophys);/* Some devices are not yet converted */ - config_scan(ubascan,self); - -#ifdef DW780 - if (sc->uh_type == DW780) - ubar->uba_cr = UBACR_IFS | UBACR_BRIE | - UBACR_USEFIE | UBACR_SUEFIE | - (ubar->uba_cr & 0x7c000000); -#endif + config_scan(ubascan,(struct device *)sc); + if (sc->uh_afterscan) + (*sc->uh_afterscan)(sc); } void @@ -1187,31 +906,21 @@ ubascan(parent, match) struct device *dev = match; struct cfdata *cf = dev->dv_cfdata; struct uba_softc *sc = (struct uba_softc *)parent; - volatile struct uba_regs *ubar = sc->uh_uba; struct uba_attach_args ua; int i; - ua.ua_addr = (caddr_t)ubaddr(sc, cf->cf_loc[0]); + ua.ua_addr = (caddr_t)((int)sc->uh_iopage + ubdevreg(cf->cf_loc[0])); ua.ua_reset = NULL; - if (badaddr(ua.ua_addr, 2)) + if (badaddr(ua.ua_addr, 2) || (sc->uh_errchk ? (*sc->uh_errchk)(sc):0)) goto forgetit; -#ifdef DW780 - if (sc->uh_type == DW780 && ubar->uba_sr) { - ubar->uba_sr = ubar->uba_sr; - goto forgetit; - } -#endif rcvec = 0x200; i = (*cf->cf_attach->ca_match) (parent, dev, &ua); -#ifdef DW780 - if (sc->uh_type == DW780 && ubar->uba_sr) { - ubar->uba_sr = ubar->uba_sr; - goto forgetit; - } -#endif + if (sc->uh_errchk) + if ((*sc->uh_errchk)(sc)) + goto forgetit; if (i == 0) goto forgetit; @@ -1220,13 +929,21 @@ ubascan(parent, match) sc->uh_idsp[rcvec].hoppaddr = ua.ua_ivec; sc->uh_idsp[rcvec].pushlarg = dev->dv_unit; - if (ua.ua_reset) { /* device wants ubaeset */ + if (ua.ua_reset) { /* device wants ubraeset */ if (sc->uh_resno == 0) { sc->uh_reset = malloc(1024, M_DEVBUF, M_NOWAIT); - sc->uh_resarg = malloc(256, M_DEVBUF, M_NOWAIT); + sc->uh_resarg = (int *)sc->uh_reset + 128; + } +#ifdef DIAGNOSTIC + if (sc->uh_resno > 127) { + printf("%s: Expand reset table, skipping reset %s\n", + sc->uh_dev.dv_xname, dev->dv_xname); + } else +#endif + { + sc->uh_resarg[sc->uh_resno] = dev->dv_unit; + sc->uh_reset[sc->uh_resno++] = ua.ua_reset; } - sc->uh_resarg[sc->uh_resno] = dev->dv_unit; - sc->uh_reset[sc->uh_resno++] = ua.ua_reset; } ua.ua_br = rbr; ua.ua_cvec = rcvec; diff --git a/sys/arch/vax/uba/ubareg.h b/sys/arch/vax/uba/ubareg.h index d63093e5613..823ae525d7f 100644 --- a/sys/arch/vax/uba/ubareg.h +++ b/sys/arch/vax/uba/ubareg.h @@ -1,4 +1,4 @@ -/* $NetBSD: ubareg.h,v 1.7 1996/04/08 18:37:35 ragge Exp $ */ +/* $NetBSD: ubareg.h,v 1.9 1996/08/20 13:38:02 ragge Exp $ */ /*- * Copyright (c) 1982, 1986 The Regents of the University of California. @@ -52,26 +52,26 @@ */ #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 /* @@ -80,20 +80,16 @@ * QBAPAGES should be 8192, but we don't need nearly that much * address space, and the return from the allocation routine * can accommodate at most 2047 (ubavar.h: UBA_MAXMR); - * QBAPAGES must be at least UBAPAGES. Choose pragmatically. + * QBAPAGES must be at least UBAPAGES. Choose pragmatically. * * Is there ever any need to have QBAPAGES != UBAPAGES??? * Wont work now anyway, QBAPAGES _must_ be .eq. UBAPAGES. */ -#define UBAPAGES 496 -#define NUBMREG 496 -/* #if defined(GATEWAY) && !defined(QNIVERT) */ -/* #define QBAPAGES 1024 */ -/* #else */ -#define QBAPAGES UBAPAGES -/* #endif */ -#define UBAIOADDR 0760000 /* start of I/O page */ -#define UBAIOPAGES 16 +#define UBAPAGES 496 +#define NUBMREG 496 +#define QBAPAGES 1024 +#define UBAIOADDR 0760000 /* start of I/O page */ +#define UBAIOPAGES 16 #ifndef _LOCORE /* @@ -112,39 +108,39 @@ struct dwbua_regs { int pad3[10]; int bua_bdps[20]; /* buffered data path space *//*???*/ int pad4[8]; - pt_entry_t bua_map[UBAPAGES]; /* unibus map registers */ + struct pte bua_map[UBAPAGES]; /* unibus map registers */ int pad5[UBAIOPAGES]; /* no maps for device address space */ }; #ifdef DWBUA /* bua_csr */ -#define BUACSR_ERR 0x80000000 /* composite error */ -#define BUACSR_BIF 0x10000000 /* BI failure */ -#define BUACSR_SSYNTO 0x08000000 /* slave sync timeout */ -#define BUACSR_UIE 0x04000000 /* unibus interlock error */ -#define BUACSR_IVMR 0x02000000 /* invalid map register */ -#define BUACSR_BADBDP 0x01000000 /* bad BDP select */ -#define BUACSR_BUAEIE 0x00100000 /* bua error interrupt enable (?) */ -#define BUACSR_UPI 0x00020000 /* unibus power init */ -#define BUACSR_UREGDUMP 0x00010000 /* microdiag register dump */ -#define BUACSR_IERRNO 0x000000ff /* mask for internal errror number */ +#define BUACSR_ERR 0x80000000 /* composite error */ +#define BUACSR_BIF 0x10000000 /* BI failure */ +#define BUACSR_SSYNTO 0x08000000 /* slave sync timeout */ +#define BUACSR_UIE 0x04000000 /* unibus interlock error */ +#define BUACSR_IVMR 0x02000000 /* invalid map register */ +#define BUACSR_BADBDP 0x01000000 /* bad BDP select */ +#define BUACSR_BUAEIE 0x00100000 /* bua error interrupt enable (?) */ +#define BUACSR_UPI 0x00020000 /* unibus power init */ +#define BUACSR_UREGDUMP 0x00010000 /* microdiag register dump */ +#define BUACSR_IERRNO 0x000000ff /* mask for internal errror number */ /* bua_offset */ -#define BUAOFFSET_MASK 0x00003e00 /* hence max offset = 15872 */ +#define BUAOFFSET_MASK 0x00003e00 /* hence max offset = 15872 */ /* bua_dpr */ -#define BUADPR_DPSEL 0x00e00000 /* data path select (?) */ -#define BUADPR_PURGE 0x00000001 /* purge bdp */ +#define BUADPR_DPSEL 0x00e00000 /* data path select (?) */ +#define BUADPR_PURGE 0x00000001 /* purge bdp */ /* bua_map -- in particular, those bits that are not in DW780s & DW750s */ -#define BUAMR_IOADR 0x40000000 /* I/O address space */ -#define BUAMR_LAE 0x04000000 /* longword access enable */ +#define BUAMR_IOADR 0x40000000 /* I/O address space */ +#define BUAMR_LAE 0x04000000 /* longword access enable */ /* I see no reason to use either one, though ... act 6 Aug 1987 */ -#define UBA_PURGEBUA(uba, bdp) \ +#define UBA_PURGEBUA(uba, bdp) \ (((struct dwbua_regs *)(uba))->bua_dpr[bdp] |= BUADPR_PURGE) #else -#define UBA_PURGEBUA(uba, bdp) +#define UBA_PURGEBUA(uba, bdp) #endif /* @@ -162,164 +158,131 @@ struct uba_regs { int uba_brrvr[4]; /* receive vector registers */ int uba_dpr[16]; /* buffered data path register */ int pad2[480]; - pt_entry_t uba_map[UBAPAGES]; /* unibus map register */ + struct pte uba_map[UBAPAGES]; /* unibus map register */ int pad3[UBAIOPAGES]; /* no maps for device address space */ }; #endif #ifdef DW780 /* uba_cnfgr */ -#define UBACNFGR_UBINIT 0x00040000 /* unibus init asserted */ -#define UBACNFGR_UBPDN 0x00020000 /* unibus power down */ -#define UBACNFGR_UBIC 0x00010000 /* unibus init complete */ +#define UBACNFGR_UBINIT 0x00040000 /* unibus init asserted */ +#define UBACNFGR_UBPDN 0x00020000 /* unibus power down */ +#define UBACNFGR_UBIC 0x00010000 /* unibus init complete */ #define UBACNFGR_BITS \ "\40\40PARFLT\37WSQFLT\36URDFLT\35ISQFLT\34MXTFLT\33XMTFLT\30ADPDN\27ADPUP\23UBINIT\22UBPDN\21UBIC" /* uba_cr */ -#define UBACR_MRD16 0x40000000 /* map reg disable bit 4 */ -#define UBACR_MRD8 0x20000000 /* map reg disable bit 3 */ -#define UBACR_MRD4 0x10000000 /* map reg disable bit 2 */ -#define UBACR_MRD2 0x08000000 /* map reg disable bit 1 */ -#define UBACR_MRD1 0x04000000 /* map reg disable bit 0 */ -#define UBACR_IFS 0x00000040 /* interrupt field switch */ -#define UBACR_BRIE 0x00000020 /* BR interrupt enable */ -#define UBACR_USEFIE 0x00000010 /* UNIBUS to SBI error field IE */ -#define UBACR_SUEFIE 0x00000008 /* SBI to UNIBUS error field IE */ -#define UBACR_CNFIE 0x00000004 /* configuration IE */ -#define UBACR_UPF 0x00000002 /* UNIBUS power fail */ -#define UBACR_ADINIT 0x00000001 /* adapter init */ +#define UBACR_MRD16 0x40000000 /* map reg disable bit 4 */ +#define UBACR_MRD8 0x20000000 /* map reg disable bit 3 */ +#define UBACR_MRD4 0x10000000 /* map reg disable bit 2 */ +#define UBACR_MRD2 0x08000000 /* map reg disable bit 1 */ +#define UBACR_MRD1 0x04000000 /* map reg disable bit 0 */ +#define UBACR_IFS 0x00000040 /* interrupt field switch */ +#define UBACR_BRIE 0x00000020 /* BR interrupt enable */ +#define UBACR_USEFIE 0x00000010 /* UNIBUS to SBI error field IE */ +#define UBACR_SUEFIE 0x00000008 /* SBI to UNIBUS error field IE */ +#define UBACR_CNFIE 0x00000004 /* configuration IE */ +#define UBACR_UPF 0x00000002 /* UNIBUS power fail */ +#define UBACR_ADINIT 0x00000001 /* adapter init */ /* uba_sr */ -#define UBASR_BR7FULL 0x08000000 /* BR7 receive vector reg full */ -#define UBASR_BR6FULL 0x04000000 /* BR6 receive vector reg full */ -#define UBASR_BR5FULL 0x02000000 /* BR5 receive vector reg full */ -#define UBASR_BR4FULL 0x01000000 /* BR4 receive vector reg full */ -#define UBASR_RDTO 0x00000400 /* UNIBUS to SBI read data timeout */ -#define UBASR_RDS 0x00000200 /* read data substitute */ -#define UBASR_CRD 0x00000100 /* corrected read data */ -#define UBASR_CXTER 0x00000080 /* command transmit error */ -#define UBASR_CXTMO 0x00000040 /* command transmit timeout */ -#define UBASR_DPPE 0x00000020 /* data path parity error */ -#define UBASR_IVMR 0x00000010 /* invalid map register */ -#define UBASR_MRPF 0x00000008 /* map register parity failure */ -#define UBASR_LEB 0x00000004 /* lost error */ -#define UBASR_UBSTO 0x00000002 /* UNIBUS select timeout */ -#define UBASR_UBSSYNTO 0x00000001 /* UNIBUS slave sync timeout */ - -#define UBASR_BITS \ +#define UBASR_BR7FULL 0x08000000 /* BR7 receive vector reg full */ +#define UBASR_BR6FULL 0x04000000 /* BR6 receive vector reg full */ +#define UBASR_BR5FULL 0x02000000 /* BR5 receive vector reg full */ +#define UBASR_BR4FULL 0x01000000 /* BR4 receive vector reg full */ +#define UBASR_RDTO 0x00000400 /* UNIBUS to SBI read data timeout */ +#define UBASR_RDS 0x00000200 /* read data substitute */ +#define UBASR_CRD 0x00000100 /* corrected read data */ +#define UBASR_CXTER 0x00000080 /* command transmit error */ +#define UBASR_CXTMO 0x00000040 /* command transmit timeout */ +#define UBASR_DPPE 0x00000020 /* data path parity error */ +#define UBASR_IVMR 0x00000010 /* invalid map register */ +#define UBASR_MRPF 0x00000008 /* map register parity failure */ +#define UBASR_LEB 0x00000004 /* lost error */ +#define UBASR_UBSTO 0x00000002 /* UNIBUS select timeout */ +#define UBASR_UBSSYNTO 0x00000001 /* UNIBUS slave sync timeout */ + +#define UBASR_BITS \ "\20\13RDTO\12RDS\11CRD\10CXTER\7CXTMO\6DPPE\5IVMR\4MRPF\3LEB\2UBSTO\1UBSSYNTO" /* uba_brrvr[] */ -#define UBABRRVR_AIRI 0x80000000 /* adapter interrupt request */ -#define UBABRRVR_DIV 0x0000ffff /* device interrupt vector field */ +#define UBABRRVR_AIRI 0x80000000 /* adapter interrupt request */ +#define UBABRRVR_DIV 0x0000ffff /* device interrupt vector field */ #endif /* uba_dpr */ #ifdef DW780 -#define UBADPR_BNE 0x80000000 /* buffer not empty - purge */ -#define UBADPR_BTE 0x40000000 /* buffer transfer error */ -#define UBADPR_DPF 0x20000000 /* DP function (RO) */ -#define UBADPR_BS 0x007f0000 /* buffer state field */ -#define UBADPR_BUBA 0x0000ffff /* buffered UNIBUS address */ -#define UBA_PURGE780(uba, bdp) \ - ((uba)->uba_dpr[(int)bdp] |= UBADPR_BNE) -#else -#define UBA_PURGE780(uba, bdp) +#define UBADPR_BNE 0x80000000 /* buffer not empty - purge */ +#define UBADPR_BTE 0x40000000 /* buffer transfer error */ +#define UBADPR_DPF 0x20000000 /* DP function (RO) */ +#define UBADPR_BS 0x007f0000 /* buffer state field */ +#define UBADPR_BUBA 0x0000ffff /* buffered UNIBUS address */ #endif #ifdef DW750 -#define UBADPR_ERROR 0x80000000 /* error occurred */ -#define UBADPR_NXM 0x40000000 /* nxm from memory */ -#define UBADPR_UCE 0x20000000 /* uncorrectable error */ -#define UBADPR_PURGE 0x00000001 /* purge bdp */ -/* the DELAY is for a hardware problem */ -#define UBA_PURGE750(uba, bdp) { \ - ((uba)->uba_dpr[(int)bdp] |= (UBADPR_PURGE|UBADPR_NXM|UBADPR_UCE)); \ - {volatile int N=8;while(N--);} \ -} -#else -#define UBA_PURGE750(uba, bdp) +#define UBADPR_ERROR 0x80000000 /* error occurred */ +#define UBADPR_NXM 0x40000000 /* nxm from memory */ +#define UBADPR_UCE 0x20000000 /* uncorrectable error */ +#define UBADPR_PURGE 0x00000001 /* purge bdp */ #endif -/* - * Macros for fast buffered data path purging in time-critical routines. - * - * Too bad C pre-processor doesn't have the power of LISP in macro - * expansion... - */ - -/* THIS IS WRONG, should use pointer to uba_hd */ -#if DWBUA || DW780 || DW750 -#define UBAPURGE(uba, bdp) { \ - switch (MACHID(cpu_type)) { \ - case VAX_8200: UBA_PURGEBUA(uba, bdp); break; \ - case VAX_8600: case VAX_780: UBA_PURGE780((uba), (bdp)); break; \ - case VAX_750: UBA_PURGE750((uba), (bdp)); break; \ - } \ -} -#else -#define UBAPURGE(uba, bdp) -#endif - - - /* uba_mr[] */ -#define UBAMR_MRV 0x80000000 /* map register valid */ -#define UBAMR_BO 0x02000000 /* byte offset bit */ -#define UBAMR_DPDB 0x01e00000 /* data path designator field */ -#define UBAMR_SBIPFN 0x001fffff /* SBI page address field */ +#define UBAMR_MRV 0x80000000 /* map register valid */ +#define UBAMR_BO 0x02000000 /* byte offset bit */ +#define UBAMR_DPDB 0x01e00000 /* data path designator field */ +#define UBAMR_SBIPFN 0x001fffff /* SBI page address field */ -#define UBAMR_DPSHIFT 21 /* shift to data path designator */ +#define UBAMR_DPSHIFT 21 /* shift to data path designator */ /* * Number of unibus buffered data paths and possible uba's per cpu type. */ -#define NBDP8600 15 -#define NBDP780 15 -#define NBDPBUA 5 -#define NBDP750 3 -#define NBDP730 0 -#define MAXNBDP 15 +#define NBDP8600 15 +#define NBDP780 15 +#define NBDPBUA 5 +#define NBDP750 3 +#define NBDP730 0 +#define MAXNBDP 15 /* * Symbolic BUS addresses for UBAs. */ #if VAX630 || VAX650 -#define QBAMAP630 ((struct pte *)0x20088000) -#define QMEM630 0x30000000 -#define QIOPAGE630 0x20000000 +#define QBAMAP 0x20088000 +#define QMEM 0x30000000 +#define QIOPAGE 0x20000000 /* * Q-bus control registers */ -#define QIPCR 0x1f40 /* from start of iopage */ +#define QIPCR 0x1f40 /* from start of iopage */ /* bits in QIPCR */ -#define Q_DBIRQ 0x0001 /* doorbell interrupt request */ -#define Q_LMEAE 0x0020 /* local mem external access enable */ -#define Q_DBIIE 0x0040 /* doorbell interrupt enable */ -#define Q_AUXHLT 0x0100 /* auxiliary processor halt */ -#define Q_DMAQPE 0x8000 /* Q22 bus address space parity error */ +#define Q_DBIRQ 0x0001 /* doorbell interrupt request */ +#define Q_LMEAE 0x0020 /* local mem external access enable */ +#define Q_DBIIE 0x0040 /* doorbell interrupt enable */ +#define Q_AUXHLT 0x0100 /* auxiliary processor halt */ +#define Q_DMAQPE 0x8000 /* Q22 bus address space parity error */ #endif #if VAX730 -#define UMEM730 0xfc0000 +#define UMEM730 0xfc0000 #endif #if VAX750 -#define UMEM750(i) (0xfc0000-(i)*0x40000) +#define UMEM750(i) (0xfc0000-(i)*0x40000) #endif #if VAX780 -#define UMEM780(i) (0x20100000+(i)*0x40000) +#define UMEM780(i) (0x20100000+(i)*0x40000) #endif #if VAX8200 /* BEWARE, argument is node, not ubanum */ -#define UMEM8200(i) (0x20400000+(i)*0x40000) +#define UMEM8200(i) (0x20400000+(i)*0x40000) #endif #if VAX8600 || VAX780 -#define UMEMA8600(i) (0x20100000+(i)*0x40000) -#define UMEMB8600(i) (0x22100000+(i)*0x40000) +#define UMEMA8600(i) (0x20100000+(i)*0x40000) +#define UMEMB8600(i) (0x22100000+(i)*0x40000) #endif /* @@ -327,4 +290,4 @@ struct uba_regs { * something like 0172520, by forcing it into the last 8K * of UNIBUS memory space. */ -#define ubdevreg(addr) ((addr) & 017777) +#define ubdevreg(addr) ((addr) & 017777) diff --git a/sys/arch/vax/uba/ubavar.h b/sys/arch/vax/uba/ubavar.h index c179cb4887c..50b84a00afb 100644 --- a/sys/arch/vax/uba/ubavar.h +++ b/sys/arch/vax/uba/ubavar.h @@ -1,4 +1,4 @@ -/* $NetBSD: ubavar.h,v 1.15 1996/04/08 18:37:36 ragge Exp $ */ +/* $NetBSD: ubavar.h,v 1.18 1996/08/20 13:38:04 ragge Exp $ */ /* * Copyright (c) 1982, 1986 Regents of the University of California. @@ -71,129 +71,60 @@ */ struct uba_softc { struct device uh_dev; /* Device struct, autoconfig */ + SIMPLEQ_HEAD(, uba_unit) uh_resq; /* resource wait chain */ int uh_type; /* type of adaptor */ struct uba_regs *uh_uba; /* virt addr of uba adaptor regs */ - struct uba_regs *uh_physuba; /* phys addr of uba adaptor regs */ struct pte *uh_mr; /* start of page map */ int uh_memsize; /* size of uba memory, pages */ - caddr_t uh_mem; /* start of uba memory address space */ caddr_t uh_iopage; /* start of uba io page */ void (**uh_reset) __P((int));/* UBA reset function array */ int *uh_resarg; /* array of ubareset args */ int uh_resno; /* Number of devices to reset */ struct ivec_dsp *uh_idsp; /* Interrupt dispatch area */ u_int *uh_iarea; /* Interrupt vector array */ - struct uba_device *uh_actf; /* head of queue to transfer */ - struct uba_device *uh_actl; /* tail of queue to transfer */ short uh_mrwant; /* someone is waiting for map reg */ short uh_bdpwant; /* someone awaits bdp's */ int uh_bdpfree; /* free bdp's */ - int uh_hangcnt; /* number of ticks hung */ int uh_zvcnt; /* number of recent 0 vectors */ long uh_zvtime; /* time over which zvcnt accumulated */ int uh_zvtotal; /* total number of 0 vectors */ - int uh_errcnt; /* number of errors */ int uh_lastiv; /* last free interrupt vector */ short uh_users; /* transient bdp use count */ short uh_xclu; /* an rk07 is using this uba! */ int uh_lastmem; /* limit of any unibus memory */ -#define UAMSIZ 100 struct map *uh_map; /* register free map */ + int (*uh_errchk) __P((struct uba_softc *)); + void (*uh_beforescan) __P((struct uba_softc *)); + void (*uh_afterscan) __P((struct uba_softc *)); + void (*uh_ubainit) __P((struct uba_softc *)); + void (*uh_ubapurge) __P((struct uba_softc *, int)); +#ifdef DW780 struct ivec_dsp uh_dw780; /* Interrupt handles for DW780 */ +#endif + short uh_nr; /* Unibus sequential number */ + short uh_nbdp; /* # of BDP's */ }; +#define UAMSIZ 100 + /* given a pointer to uba_regs, find DWBUA registers */ /* this should be replaced with a union in uba_softc */ #define BUA(uba) ((struct dwbua_regs *)(uba)) /* * Per-controller structure. - * (E.g. one for each disk and tape controller, and other things - * which use and release buffered data paths.) - * - * If a controller has devices attached, then there are - * cross-referenced uba_drive structures. - * This structure is the one which is queued in unibus resource wait, - * and saves the information about unibus resources which are used. - * The queue of devices waiting to transfer is also attached here. + * The unit struct is common to both the adapter and the controller + * to which it belongs. It is only used on controllers that handles + * BDP's, and calls the adapter queueing subroutines. */ -struct uba_ctlr { - struct uba_driver *um_driver; - short um_ctlr; /* controller index in driver */ - short um_ubanum; /* the uba it is on */ - short um_alive; /* controller exists */ - void (*um_intr) __P((int)); /* interrupt handler(s) XXX */ - caddr_t um_addr; /* address of device in i/o space */ - struct uba_softc *um_hd; -/* the driver saves the prototype command here for use in its go routine */ - int um_cmd; /* communication to dgo() */ - int um_ubinfo; /* save unibus registers, etc */ - int um_bdp; /* for controllers that hang on to bdp's */ - struct buf um_tab; /* queue of devices for this controller */ -}; - -/* - * Per ``device'' structure. - * (A controller has devices or uses and releases buffered data paths). - * (Everything else is a ``device''.) - * - * If a controller has many drives attached, then there will - * be several uba_device structures associated with a single uba_ctlr - * structure. - * - * This structure contains all the information necessary to run - * a unibus device such as a dz or a dh. It also contains information - * for slaves of unibus controllers as to which device on the slave - * this is. A flags field here can also be given in the system specification - * and is used to tell which dz lines are hard wired or other device - * specific parameters. - */ -struct uba_device { - struct uba_driver *ui_driver; - short ui_unit; /* unit number on the system */ - short ui_ctlr; /* mass ctlr number; -1 if none */ - short ui_ubanum; /* the uba it is on */ - short ui_slave; /* slave on controller */ - void (*ui_intr) __P((int)); /* interrupt handler(s) XXX */ - caddr_t ui_addr; /* address of device in i/o space */ - short ui_dk; /* if init 1 set to number for iostat */ - int ui_flags; /* parameter from system specification */ - short ui_alive; /* device exists */ - short ui_type; /* driver specific type information */ - caddr_t ui_physaddr; /* phys addr, for standalone (dump) code */ -/* this is the forward link in a list of devices on a controller */ - struct uba_device *ui_forw; -/* if the device is connected to a controller, this is the controller */ - struct uba_ctlr *ui_mi; - struct uba_softc *ui_hd; -}; - -/* - * Per-driver structure. - * - * Each unibus driver defines entries for a set of routines - * as well as an array of types which are acceptable to it. - * These are used at boot time by the configuration program. - */ -struct uba_driver { - /* see if a driver is really there XXX*/ - int (*ud_probe) __P((caddr_t, int, struct uba_ctlr *, - struct uba_softc *)); - /* see if a slave is there XXX */ - int (*ud_slave) __P((struct uba_device *, caddr_t)); - /* setup driver for a slave XXX */ - void (*ud_attach) __P((struct uba_device *)); - /* fill csr/ba to start transfer XXX */ - void (*ud_dgo) __P((struct uba_ctlr *)); - u_short *ud_addr; /* device csr addresses */ - char *ud_dname; /* name of a device */ - struct uba_device **ud_dinfo; /* backpointers to ubdinit structs */ - char *ud_mname; /* name of a controller */ - struct uba_ctlr **ud_minfo; /* backpointers to ubminit structs */ - short ud_xclu; /* want exclusive use of bdp's */ - short ud_keepbdp; /* hang on to bdp's once allocated */ - int (*ud_ubamem) __P((struct uba_device *, int)); - /* see if dedicated memory is present */ +struct uba_unit { + SIMPLEQ_ENTRY(uba_unit) uu_resq;/* Queue while waiting for resources */ + void *uu_softc; /* Pointer to units softc */ + int uu_ubinfo; /* save unibus registers, etc */ + int uu_bdp; /* for controllers that hang on to bdp's */ + int (*uu_ready) __P((struct uba_unit *)); + short uu_xclu; /* want exclusive use of bdp's */ + short uu_keepbdp; /* hang on to bdp's once allocated */ }; /* @@ -246,25 +177,17 @@ struct ubinfo { #ifndef _LOCORE #ifdef _KERNEL -#define ubago(ui) ubaqueue(ui, 0) - -/* - * Ubminit and ubdinit initialize the mass storage controller and - * device tables specifying possible devices. - */ -extern struct uba_ctlr ubminit[]; -extern struct uba_device ubdinit[]; +#define ubago(ui) ubaqueue(ui) +#define b_forw b_hash.le_next /* Nice to have when handling uba queues */ extern struct cfdriver uba_cd; -void ubainit __P((struct uba_softc *)); void ubasetvec __P((struct device *, int, void (*) __P((int)))); -int uballoc __P((int, caddr_t, int, int)); -void ubarelse __P((int, int *)); -int ubaqueue __P((struct uba_device *, int)); -void ubadone __P((struct uba_ctlr *)); +int uballoc __P((struct uba_softc *, caddr_t, int, int)); +void ubarelse __P((struct uba_softc *, int *)); +int ubaqueue __P((struct uba_unit *, struct buf *)); +void ubadone __P((struct uba_unit *)); void ubareset __P((int)); -int ubasetup __P((int, struct buf *, int)); #endif /* _KERNEL */ #endif !_LOCORE diff --git a/sys/arch/vax/uba/uda.c b/sys/arch/vax/uba/uda.c index c911d3a9b3f..86fa0c20fd2 100644 --- a/sys/arch/vax/uba/uda.c +++ b/sys/arch/vax/uba/uda.c @@ -1,5 +1,6 @@ -/* $NetBSD: uda.c,v 1.16 1996/05/19 16:43:42 ragge Exp $ */ +/* $NetBSD: uda.c,v 1.23 1996/10/13 03:35:26 christos Exp $ */ /* + * Copyright (c) 1996 Ludd, University of Lule}, Sweden. * Copyright (c) 1988 Regents of the University of California. * All rights reserved. * @@ -38,367 +39,133 @@ */ /* - * 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; - -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 */ +static int ivec_no; -struct mscp udaslavereply; /* get unit status response packet, set - for udaslave by udaunconf, via udaintr */ - -static struct uba_ctlr *probeum;/* this is a hack---autoconf should pass ctlr - info to slave routine; instead, we remember - the last ctlr argument to probe */ - -int udawstart; -void udawatch(); /* watchdog timer */ - -/* - * Externals - */ -int hz; +int +udaprint(aux, name) + void *aux; + const char *name; +{ + if (name) + printf("%s: mscpbus", name); + return UNCONF; +} /* * Poke at a supposed UDA50 to see if it is there. - * This routine duplicates some of the code in udainit() only - * because autoconf has not set up the right information yet. - * We have to do everything `by hand'. */ int udamatch(parent, match, aux) - struct device *parent; - void *match, *aux; -{ - return 0; -} - -void -uda_attach(parent, self, aux) - struct device *parent, *self; - void *aux; -{ -} - -udaprobe(reg, ctlr, um, uhp) - caddr_t reg; - int ctlr; - struct uba_ctlr *um; - struct uba_softc *uhp; -{ - struct uda_softc *sc; - volatile struct udadevice *udaddr; - struct mscp_info *mi; - struct uba_softc *ubasc; - extern int cpu_type; - int timeout, tries, count; -#ifdef notyet + struct device *parent; + void *match, *aux; +{ + struct uba_attach_args *ua = aux; + struct device *dev = match; + struct mscp_softc mi; /* Nice hack */ + struct uba_softc *ubasc; + int tries; +#if QBA && notyet + extern volatile int rbr; int s; #endif -#ifdef VAX750 - /* - * The UDA50 wants to share BDPs on 750s, but not on 780s or - * 8600s. (730s have no BDPs anyway.) Toward this end, we - * here set the `keep bdp' flag in the per-driver information - * if this is a 750. (We just need to do it once, but it is - * easiest to do it now, for each UDA50.) - */ - if (MACHID(cpu_type) == VAX_750) - udadriver.ud_keepbdp = 1; -#endif - probeum = um; /* remember for udaslave() */ - /* - * Set up the controller-specific generic MSCP driver info. - * Note that this should really be done in the (nonexistent) - * controller attach routine. - */ - sc = &uda_softc[ctlr]; - mi = &sc->sc_mi; - mi->mi_md = &udamscpdriver; - mi->mi_ctlr = um->um_ctlr; - mi->mi_tab = (void*)&um->um_tab; - mi->mi_ip = udaip[ctlr]; - mi->mi_cmd.mri_size = NCMD; - mi->mi_cmd.mri_desc = sc->sc_uda.uda_ca.ca_cmddsc; - mi->mi_cmd.mri_ring = sc->sc_uda.uda_cmd; - mi->mi_rsp.mri_size = NRSP; - mi->mi_rsp.mri_desc = sc->sc_uda.uda_ca.ca_rspdsc; - mi->mi_rsp.mri_ring = sc->sc_uda.uda_rsp; - mi->mi_wtab.b_actf = &mi->mi_wtab; + /* Get an interrupt vector. */ + ubasc = (void *)parent; + ivec_no = ubasc->uh_lastiv - 4; - /* - * More controller specific variables. Again, this should - * be in the controller attach routine. - */ - if (udaburst[ctlr] == 0) - udaburst[ctlr] = DEFAULT_BURST; - - /* - * Get an interrupt vector. Note that even if the controller - * does not respond, we keep the vector. This is not a serious - * problem; but it would be easily fixed if we had a controller - * attach routine. Sigh. - */ - ubasc = uhp; - sc->sc_ivec = ubasc->uh_lastiv -= 4; - udaddr = (struct udadevice *) reg; + mi.mi_sa = &((struct udadevice *)ua->ua_addr)->udasa; + mi.mi_ip = &((struct udadevice *)ua->ua_addr)->udaip; /* * Initialise the controller (partially). The UDA50 programmer's @@ -408,961 +175,165 @@ udaprobe(reg, ctlr, um, uhp) * initialise within ten seconds. Or so I hear; I have not seen * this manual myself. */ -#ifdef notyet +#if 0 s = spl6(); #endif tries = 0; again: - udaddr->udaip = 0; /* start initialisation */ - - count = 0; - while ( count < DELAYTEN ) { - if ( (udaddr->udasa & UDA_STEP1) != 0 ) - break; - DELAY(10000); - count += 1; - } - /* nothing there */ - if ( count == DELAYTEN ) - return(0); + *mi.mi_ip = 0; + if (mscp_waitstep(&mi, MP_STEP1, MP_STEP1) == 0) + return 0; /* Nothing here... */ - udaddr->udasa = UDA_ERR | (NCMDL2 << 11) | (NRSPL2 << 8) | UDA_IE | - (sc->sc_ivec >> 2); + *mi.mi_sa = MP_ERR | (NCMDL2 << 11) | (NRSPL2 << 8) | MP_IE | + (ivec_no >> 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; +#if 0 + rbr = qbgetpri(); #endif - return (sizeof (struct udadevice)); + 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; -#ifdef notyet +#if 0 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; -#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 (++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); + return 0; } -/* - * 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; +udaattach(parent, self, aux) + struct device *parent, *self; + void *aux; { - register int unit = ui->ui_unit; - - if (udawstart == 0) { - timeout(udawatch, (caddr_t) 0, hz); - udawstart++; - } + 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; - /* - * 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; + printf("\n"); - 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]); + uh->uh_lastiv -= 4; /* remove dynamic interrupt vector */ +#ifdef QBA + sc->sc_ipl = ua->ua_br; #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)); + ctlr = sc->sc_dev.dv_unit; + sc->sc_udadev = (struct udadevice *)ua->ua_addr; + SIMPLEQ_INIT(&sc->sc_bufq); /* - * While we are thinking about it, reset the next command - * and response indicies. + * Fill in the uba_unit struct, so we can communicate with the uba. */ - sc->sc_mi.mi_cmd.mri_next = 0; - sc->sc_mi.mi_rsp.mri_next = 0; + 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; /* - * Start up the hardware initialisation sequence. + * Map the communication area and command and + * response packets into Unibus space. */ -#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); - } + ubinfo = uballoc((struct uba_softc *)sc->sc_dev.dv_parent, + (caddr_t) &sc->sc_uda, sizeof (struct mscp_pack), UBA_CANTWAIT); - 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); +#ifdef DIAGNOSTIC + if (ubinfo == 0) { + printf("%s: uballoc map failed\n", sc->sc_dev.dv_xname); + return; } +#endif + sc->sc_uuda = (struct mscp_pack *) UBAI_ADDR(ubinfo); - /* - * 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); - splx(s); - if (error) - return (error); + bzero(&sc->sc_uda, sizeof (struct mscp_pack)); - 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). + * 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. */ -#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; + ma.ma_type = (strcmp(self->dv_cfdata->cf_driver->cd_name, + mtc_cd.cd_name) ? MSCPBUS_DISK : MSCPBUS_TAPE); - /* - * 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); + 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); } /* - * 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. + * Start a transfer if there are free resources available, otherwise + * let it go in udaready, forget it for now. */ -uda_rainit(ui, flags) - volatile struct uba_device *ui; - int flags; +int +udago(usc, bp) + struct device *usc; + struct buf *bp; { - 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; + struct uda_softc *sc = (void *)usc; + struct uba_unit *uu = &sc->sc_unit; - 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. + * 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. */ - 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; + 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 - 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; + BUFQ_INSERT_TAIL(&sc->sc_bufq, bp) } - 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); + + return 0; } /* - * Work routine for udastrategy. + * 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. */ -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; +udaready(uu) + struct uba_unit *uu; { + struct uda_softc *sc = uu->uu_softc; + struct buf *bp; - return (physio(udastrategy, NULL, dev, B_WRITE, minphys, uio)); -} - -/* - * 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; - - sc->sc_flags |= SC_INSTART; - udaddr = (struct udadevice *) um->um_addr; - -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; - } - - if (udaddr->udasa & UDA_ERR) { /* ctlr fatal error */ - udasaerror(um, 1); - goto out; - } - - /* - * 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. - */ - 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; - } - - /* - * 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. - */ - ui = udadinfo[udaunit(bp->b_dev)]; - if ((ui->ui_flags & UNIT_ONLINE) == 0) { - mp->mscp_opcode = M_OP_ONLINE; - goto common; - } - 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; - } - - 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() */ - - /* - * 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. - */ - um->um_cmd = (int)mp; - if (ubago(ui)) - goto loop; - - /* - * 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; + 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; } - sc->sc_flags &= ~(SC_INSTART | SC_STARTPOLL); -} - -/* - * 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.... - */ -void -udadgo(um) - register struct uba_ctlr *um; -{ - 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 */ - - /* - * 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. - */ - 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); -} - -void -udaiodone(mi, bp, info) - register struct mscp_info *mi; - struct buf *bp; - int info; -{ - 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 */ + return 1; } static struct saerr { @@ -1414,24 +385,26 @@ static struct saerr { * If the error bit was set in the controller status register, gripe, * then (optionally) reset the controller and requeue pending transfers. */ -udasaerror(um, doreset) - register struct uba_ctlr *um; +void +udasaerror(usc, doreset) + struct device *usc; int doreset; { - register int code = ((struct udadevice *)um->um_addr)->udasa; + struct uda_softc *sc = (void *)usc; + register int code = sc->sc_udadev->udasa; register struct saerr *e; -/*printf("udasaerror\n"); */ - if ((code & UDA_ERR) == 0) + + if ((code & MP_ERR) == 0) return; for (e = saerr; e->code; e++) if (e->code == code) break; - printf("uda%d: controller error, sa=0%o (%s%s)\n", - um->um_ctlr, code, e->desc + 1, + printf("%s: controller error, sa=0%o (%s%s)\n", + sc->sc_dev.dv_xname, code, e->desc + 1, *e->desc == 'E' ? " error" : ""); if (doreset) { - mscp_requeue(&uda_softc[um->um_ctlr].sc_mi); - (void) udainit(um->um_ctlr); + mscp_requeue(sc->sc_softc); +/* (void) udainit(sc); XXX */ } } @@ -1440,1034 +413,110 @@ udasaerror(um, doreset) * continue initialisation, or acknowledge command and response * interrupts, and process responses. */ -void +static void udaintr(ctlr) int ctlr; { - struct uba_ctlr *um = udaminfo[ctlr]; - struct uda_softc *sc = &uda_softc[ctlr]; - volatile struct udadevice *udaddr = (struct udadevice *)um->um_addr; - struct uda *ud; - struct mscp *mp; - volatile int i, wait_status; - extern int cpu_type; + intr(uda_cd.cd_devs[ctlr]); +} + +static void +mtcintr(ctlr) + int ctlr; +{ + intr(mtc_cd.cd_devs[ctlr]); +} + +static void +intr(sc) + struct uda_softc *sc; +{ + volatile struct udadevice *udaddr = sc->sc_udadev; + struct uba_softc *uh; + struct mscp_pack *ud; #ifdef QBA - if(cpunumber == VAX_78032) + if(vax_cputype == VAX_TYP_UV2) splx(sc->sc_ipl); /* Qbus interrupt protocol is odd */ #endif sc->sc_wticks = 0; /* reset interrupt watchdog */ - /* - * Combinations during steps 1, 2, and 3: STEPnMASK - * corresponds to which bits should be tested; - * STEPnGOOD corresponds to the pattern that should - * appear after the interrupt from STEPn initialisation. - * All steps test the bits in ALLSTEPS. - */ - - switch (sc->sc_state) { - - case ST_IDLE: - /* - * Ignore unsolicited interrupts. - */ - log(LOG_WARNING, "uda%d: stray intr\n", ctlr); - return; - - case ST_STEP1: - /* - * Begin step two initialisation. - */ - i = 0; - Wait_step(STEP1MASK, STEP1GOOD, wait_status); - if (!wait_status) { -initfailed: - printf("uda%d: init step %d failed, sa=%b\n", - ctlr, i, udaddr->udasa, udasr_bits); - udasaerror(um, 0); - sc->sc_state = ST_IDLE; - if (sc->sc_flags & SC_DOWAKE) { - sc->sc_flags &= ~SC_DOWAKE; - wakeup((caddr_t)sc); - } - return; - } - udaddr->udasa = (int)&sc->sc_uuda->uda_ca.ca_rspdsc[0] | - (MACHID(cpu_type) == VAX_780 || MACHID(cpu_type) - == VAX_8600 ? UDA_PI : 0); - sc->sc_state = ST_STEP2; - return; - - case ST_STEP2: - /* - * Begin step 3 initialisation. - */ - i = 2; - Wait_step(STEP2MASK, STEP2GOOD, wait_status); - if (!wait_status) - goto initfailed; - - udaddr->udasa = ((int)&sc->sc_uuda->uda_ca.ca_rspdsc[0]) >> 16; - sc->sc_state = ST_STEP3; - return; - - case ST_STEP3: - /* - * Set controller characteristics (finish initialisation). - */ - i = 3; - Wait_step(STEP3MASK, STEP3GOOD, wait_status); - if (!wait_status) - goto initfailed; - - i = udaddr->udasa & 0xff; - if (i != sc->sc_micro) { - sc->sc_micro = i; - printf("uda%d: version %d model %d\n", - ctlr, i & 0xf, i >> 4); - } - - /* - * Present the burst size, then remove it. Why this - * should be done this way, I have no idea. - * - * Note that this assumes udaburst[ctlr] > 0. - */ - udaddr->udasa = UDA_GO | (udaburst[ctlr] - 1) << 2; - udaddr->udasa = UDA_GO; - printf("uda%d: DMA burst size set to %d\n", - ctlr, udaburst[ctlr]); - - udainitds(ctlr); /* initialise data structures */ - - /* - * Before we can get a command packet, we need some - * credits. Fake some up to keep mscp_getcp() happy, - * get a packet, and cancel all credits (the right - * number should come back in the response to the - * SCC packet). - */ - sc->sc_mi.mi_credits = MSCP_MINCREDITS + 1; - mp = mscp_getcp(&sc->sc_mi, MSCP_DONTWAIT); - if (mp == NULL) /* `cannot happen' */ - panic("udaintr"); - sc->sc_mi.mi_credits = 0; - mp->mscp_opcode = M_OP_SETCTLRC; - mp->mscp_unit = 0; - mp->mscp_sccc.sccc_ctlrflags = M_CF_ATTN | M_CF_MISC | - M_CF_THIS; - *mp->mscp_addr |= MSCP_OWN | MSCP_INT; - i = udaddr->udaip; - sc->sc_state = ST_SETCHAR; - return; - - case ST_SETCHAR: - case ST_RUN: - /* - * Handle Set Ctlr Characteristics responses and operational - * responses (via mscp_dorsp). - */ - break; - - default: - printf("uda%d: driver bug, state %d\n", ctlr, sc->sc_state); - panic("udastate"); - } - - if (udaddr->udasa & UDA_ERR) { /* ctlr fatal error */ - udasaerror(um, 1); + if (udaddr->udasa & MP_ERR) { /* ctlr fatal error */ + udasaerror(&sc->sc_dev, 1); return; } - ud = &sc->sc_uda; - /* * Handle buffer purge requests. */ - if (ud->uda_ca.ca_bdp) { - UBAPURGE(um->um_hd->uh_uba, ud->uda_ca.ca_bdp); - ud->uda_ca.ca_bdp = 0; + uh = (void *)sc->sc_dev.dv_parent; + if (ud->mp_ca.ca_bdp) { + if (uh->uh_ubapurge) + (*uh->uh_ubapurge)(uh, ud->mp_ca.ca_bdp); + ud->mp_ca.ca_bdp = 0; udaddr->udasa = 0; /* signal purge complete */ } - /* - * Check for response and command ring transitions. - */ - if (ud->uda_ca.ca_rspint) { - ud->uda_ca.ca_rspint = 0; - mscp_dorsp(&sc->sc_mi); - } - if (ud->uda_ca.ca_cmdint) { - ud->uda_ca.ca_cmdint = 0; - MSCP_DOCMD(&sc->sc_mi); - } - udastart(um); -} - -/* - * Initialise the various data structures that control the UDA50. - */ -udainitds(ctlr) - int ctlr; -{ - register struct uda *uud = uda_softc[ctlr].sc_uuda; - register struct uda *ud = &uda_softc[ctlr].sc_uda; - register struct mscp *mp; - register int i; -/* printf("udainitds\n"); */ - for (i = 0, mp = ud->uda_rsp; i < NRSP; i++, mp++) { - ud->uda_ca.ca_rspdsc[i] = MSCP_OWN | MSCP_INT | - (long)&uud->uda_rsp[i].mscp_cmdref; - mp->mscp_addr = &ud->uda_ca.ca_rspdsc[i]; - mp->mscp_msglen = MSCP_MSGLEN; - } - for (i = 0, mp = ud->uda_cmd; i < NCMD; i++, mp++) { - ud->uda_ca.ca_cmddsc[i] = MSCP_INT | - (long)&uud->uda_cmd[i].mscp_cmdref; - mp->mscp_addr = &ud->uda_ca.ca_cmddsc[i]; - mp->mscp_msglen = MSCP_MSGLEN; - } -} - -/* - * Handle an error datagram. - */ -void -udadgram(mi, mp) - struct mscp_info *mi; - struct mscp *mp; -{ -/* printf("udadgram\n"); */ - mscp_decodeerror(mi->mi_md->md_mname, mi->mi_ctlr, mp); - /* - * SDI status information bytes 10 and 11 are the microprocessor - * error code and front panel code respectively. These vary per - * drive type and are printed purely for field service information. - */ - if (mp->mscp_format == M_FM_SDI) - printf("\tsdi uproc error code 0x%x, front panel code 0x%x\n", - mp->mscp_erd.erd_sdistat[10], - mp->mscp_erd.erd_sdistat[11]); -} - -/* - * The Set Controller Characteristics command finished. - * Record the new state of the controller. - */ -void -udactlrdone(mi, mp) - register struct mscp_info *mi; - struct mscp *mp; -{ - register struct uda_softc *sc = &uda_softc[mi->mi_ctlr]; -/* printf("udactlrdone\n"); */ - if ((mp->mscp_status & M_ST_MASK) == M_ST_SUCCESS) - sc->sc_state = ST_RUN; - else { - printf("uda%d: SETCTLRC failed: ", - mi->mi_ctlr, mp->mscp_status); - mscp_printevent(mp); - sc->sc_state = ST_IDLE; - } - if (sc->sc_flags & SC_DOWAKE) { - sc->sc_flags &= ~SC_DOWAKE; - wakeup((caddr_t)sc); - } -} - -/* - * Received a response from an as-yet unconfigured drive. Configure it - * in, if possible. - */ -udaunconf(mi, mp) - struct mscp_info *mi; - register struct mscp *mp; -{ -/* printf("udaunconf\n"); */ - /* - * If it is a slave response, copy it to udaslavereply for - * udaslave() to look at. - */ - if (mp->mscp_opcode == (M_OP_GETUNITST | M_OP_END) && - (uda_softc[mi->mi_ctlr].sc_flags & SC_INSLAVE) != 0) { - bcopy(mp, &udaslavereply, sizeof(struct mscp)); -/* udaslavereply = *mp; */ - return (MSCP_DONE); - } - - /* - * Otherwise, it had better be an available attention response. - */ - if (mp->mscp_opcode != M_OP_AVAILATTN) - return (MSCP_FAILED); - - /* do what autoconf does */ - return (MSCP_FAILED); /* not yet, arwhite, not yet */ -} - -/* - * A drive came on line. Check its type and size. Return DONE if - * we think the drive is truly on line. In any case, awaken anyone - * sleeping on the drive on-line-ness. - */ -udaonline(ui, mp) - register struct uba_device *ui; - struct mscp *mp; -{ - register struct ra_info *ra = &ra_info[ui->ui_unit]; -/* printf("udaonline\n"); */ - wakeup((caddr_t)&ui->ui_flags); - if ((mp->mscp_status & M_ST_MASK) != M_ST_SUCCESS) { - if (!cold) - printf("uda%d: ra%d", ui->ui_ctlr, ui->ui_unit); - printf(": attempt to bring on line failed: "); - mscp_printevent(mp); - ra->ra_state = CLOSED; - return (MSCP_FAILED); - } - - ra->ra_state = OPENRAW; - ra->ra_dsize = (daddr_t)mp->mscp_onle.onle_unitsize; - if (!cold) - printf("ra%d: uda%d, unit %d, size = %d sectors\n", ui->ui_unit, - ui->ui_ctlr, mp->mscp_unit, ra->ra_dsize); - /* can now compute ncyl */ - ra->ra_geom.rg_ncyl = ra->ra_dsize / ra->ra_geom.rg_ntracks / - ra->ra_geom.rg_nsectors; - return (MSCP_DONE); -} - -/* - * We got some (configured) unit's status. Return DONE if it succeeded. - */ -udagotstatus(ui, mp) - register struct uba_device *ui; - register struct mscp *mp; -{ -/* printf("udagotstatus\n"); */ - if ((mp->mscp_status & M_ST_MASK) != M_ST_SUCCESS) { - printf("uda%d: attempt to get status for ra%d failed: ", - ui->ui_ctlr, ui->ui_unit); - mscp_printevent(mp); - return (MSCP_FAILED); - } - /* record for (future) bad block forwarding and whatever else */ - uda_rasave(ui->ui_unit, mp, 1); - return (MSCP_DONE); -} - -/* - * A transfer failed. We get a chance to fix or restart it. - * Need to write the bad block forwaring code first.... - */ -/*ARGSUSED*/ -udaioerror(ui, mp, bp) - register struct uba_device *ui; - register struct mscp *mp; - struct buf *bp; -{ -/* printf("udaioerror\n"); */ - if (mp->mscp_flags & M_EF_BBLKR) { - /* - * A bad block report. Eventually we will - * restart this transfer, but for now, just - * log it and give up. - */ - log(LOG_ERR, "ra%d: bad block report: %d%s\n", - ui->ui_unit, mp->mscp_seq.seq_lbn, - mp->mscp_flags & M_EF_BBLKU ? " + others" : ""); - } else { - /* - * What the heck IS a `serious exception' anyway? - * IT SURE WOULD BE NICE IF DEC SOLD DOCUMENTATION - * FOR THEIR OWN CONTROLLERS. - */ - if (mp->mscp_flags & M_EF_SEREX) - log(LOG_ERR, "ra%d: serious exception reported\n", - ui->ui_unit); - } - return (MSCP_FAILED); -} - -/* - * A replace operation finished. - */ -/*ARGSUSED*/ -void -udareplace(ui, mp) - struct uba_device *ui; - struct mscp *mp; -{ - - panic("udareplace"); -} - -/* - * A bad block related operation finished. - */ -/*ARGSUSED*/ -void -udabb(ui, mp, bp) - struct uba_device *ui; - struct mscp *mp; - struct buf *bp; -{ - - panic("udabb"); -} - - -/* - * I/O controls. - */ -udaioctl(dev, cmd, data, flag) - dev_t dev; - int cmd; - caddr_t data; - int flag; -{ - register int unit = udaunit(dev); - register struct disklabel *lp; - register struct ra_info *ra = &ra_info[unit]; - int error = 0; -/* printf("udaioctl\n"); */ - lp = &udalabel[unit]; - - switch (cmd) { - - case DIOCGDINFO: - *(struct disklabel *)data = *lp; - break; - - case DIOCGPART: - ((struct partinfo *)data)->disklab = lp; - ((struct partinfo *)data)->part = - &lp->d_partitions[udapart(dev)]; - break; - - case DIOCSDINFO: - if ((flag & FWRITE) == 0) - error = EBADF; - else - error = setdisklabel(lp, (struct disklabel *)data, - (ra->ra_state == OPENRAW) ? 0 : ra->ra_openpart,0); - break; - - case DIOCWLABEL: - if ((flag & FWRITE) == 0) - error = EBADF; - else - ra->ra_wlabel = *(int *)data; - break; - - case DIOCWDINFO: - if ((flag & FWRITE) == 0) - error = EBADF; - else if ((error = setdisklabel(lp, (struct disklabel *)data, - (ra->ra_state == OPENRAW) ? 0 : ra->ra_openpart,0)) == 0) { - int wlab; - - ra->ra_state = OPEN; - /* simulate opening partition 0 so write succeeds */ - ra->ra_openpart |= (1 << 0); /* XXX */ - wlab = ra->ra_wlabel; - ra->ra_wlabel = 1; - error = writedisklabel(dev, udastrategy, lp,0); - ra->ra_openpart = ra->ra_copenpart | ra->ra_bopenpart; - ra->ra_wlabel = wlab; - } - break; - -#ifdef notyet - case UDAIOCREPLACE: - /* - * Initiate bad block replacement for the given LBN. - * (Should we allow modifiers?) - */ - error = EOPNOTSUPP; - break; - - case UDAIOCGMICRO: - /* - * Return the microcode revision for the UDA50 running - * this drive. - */ - *(int *)data = uda_softc[uddinfo[unit]->ui_ctlr].sc_micro; - break; -#endif - - default: - error = ENOTTY; - break; - } - return (error); + mscp_intr(sc->sc_softc); } /* * A Unibus reset has occurred on UBA uban. Reinitialise the controller(s) * on that Unibus, and requeue outstanding I/O. */ -udareset(uban) - int uban; +void +udareset(ctlr) + int ctlr; { - register struct uba_ctlr *um; - register struct uda_softc *sc; - register int ctlr; -/* printf("udareset\n"); */ - for (ctlr = 0, sc = uda_softc; ctlr < NUDA; ctlr++, sc++) { - if ((um = udaminfo[ctlr]) == NULL || um->um_ubanum != uban || - um->um_alive == 0) - continue; - printf(" uda%d", ctlr); - - /* - * Our BDP (if any) is gone; our command (if any) is - * flushed; the device is no longer mapped; and the - * UDA50 is not yet initialised. - */ - if (um->um_bdp) { - printf("<%d>", UBAI_BDP(um->um_bdp)); - um->um_bdp = 0; - } - um->um_ubinfo = 0; - um->um_cmd = 0; - sc->sc_flags &= ~SC_MAPPED; - sc->sc_state = ST_IDLE; - - /* reset queues and requeue pending transfers */ - mscp_requeue(&sc->sc_mi); - - /* - * If it fails to initialise we will notice later and - * try again (and again...). Do not call udastart() - * here; it will be done after the controller finishes - * initialisation. - */ - if (udainit(ctlr)) - printf(" (hung)"); - } + reset(uda_cd.cd_devs[ctlr]); } -/* - * Watchdog timer: If the controller is active, and no interrupts - * have occurred for 30 seconds, assume it has gone away. - */ void -udawatch() +mtcreset(ctlr) + int ctlr; { - register int i; - register struct uba_ctlr *um; - register struct uda_softc *sc; - timeout(udawatch, (caddr_t) 0, hz); /* every second */ - for (i = 0, sc = uda_softc; i < NUDA; i++, sc++) { - if ((um = udaminfo[i]) == 0 || !um->um_alive) - continue; - if (sc->sc_state == ST_IDLE) - continue; - if (sc->sc_state == ST_RUN && !um->um_tab.b_active) - sc->sc_wticks = 0; - else if (++sc->sc_wticks >= 30) { - sc->sc_wticks = 0; - printf("uda%d: lost interrupt\n", i); - ubareset(um->um_ubanum); - } - } + reset(mtc_cd.cd_devs[ctlr]); } -/* - * Do a panic dump. We set up the controller for one command packet - * and one response packet, for which we use `struct uda1'. - */ -struct uda1 { - struct uda1ca uda1_ca; /* communications area */ - struct mscp uda1_rsp; /* response packet */ - struct mscp uda1_cmd; /* command packet */ -} uda1; - -#define DBSIZE 32 /* dump 16K at a time */ - -udadump(dev) - dev_t dev; +static void +reset(sc) + struct uda_softc *sc; { - struct udadevice *udaddr; - struct uda1 *ud_ubaddr; - char *start; - int num, blk, unit, maxsz, blkoff, reg; - struct partition *pp; - struct uba_regs *uba; - struct uba_device *ui; - struct uda1 *ud; - struct pte *io; - int i; - - /* - * Make sure the device is a reasonable place on which to dump. - */ - unit = udaunit(dev); - if (unit >= NRA) - return (ENXIO); -#define phys(cast, addr) ((cast) ((int)addr & 0x7fffffff)) - ui = phys(struct uba_device *, udadinfo[unit]); - if (ui == NULL || ui->ui_alive == 0) - return (ENXIO); - - /* - * Find and initialise the UBA; get the physical address of the - * device registers, and of communications area and command and - * response packet. - */ - uba = phys(struct uba_softc *, ui->ui_hd)->uh_physuba; - ubainit(ui->ui_hd); - udaddr = (struct udadevice *)ui->ui_physaddr; - ud = phys(struct uda1 *, &uda1); - /* - * Map the ca+packets into Unibus I/O space so the UDA50 can get - * at them. Use the registers at the end of the Unibus map (since - * we will use the registers at the beginning to map the memory - * we are dumping). - */ - num = btoc(sizeof(struct uda1)) + 1; - reg = NUBMREG - num; - io = (void *)&uba->uba_map[reg]; - for (i = 0; i < num; i++) - *(int *)io++ = UBAMR_MRV | (btop(ud) + i); - ud_ubaddr = (struct uda1 *)(((int)ud & PGOFSET) | (reg << 9)); + printf(" %s", sc->sc_dev.dv_xname); /* - * Initialise the controller, with one command and one response - * packet. + * 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. */ - 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; - - /* - * 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; + 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! */ +/* XXX if (udainit(sc)) */ + printf(" (hung)"); } -/* - * 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); -} - -#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); } diff --git a/sys/arch/vax/uba/udareg.h b/sys/arch/vax/uba/udareg.h index f6107a49605..ebada167582 100644 --- a/sys/arch/vax/uba/udareg.h +++ b/sys/arch/vax/uba/udareg.h @@ -1,4 +1,4 @@ -/* $NetBSD: udareg.h,v 1.2 1994/10/26 08:02:51 cgd Exp $ */ +/* $NetBSD: udareg.h,v 1.3 1996/07/01 21:24:50 ragge Exp $ */ /* * Copyright (c) 1988 Regents of the University of California. @@ -54,22 +54,6 @@ struct udadevice { }; /* - * 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 UDA_GO 0x0001 /* run */ @@ -77,31 +61,3 @@ struct udadevice { #define UDASR_BITS \ "\20\20ERR\17STEP4\16STEP3\15STEP2\14STEP1\13NV\12QB\11DI\10IE\1GO" -/* - * UDA Communications Area. Note that this structure definition - * requires NRSP and NCMD to be defined already. - */ -struct udaca { - short ca_xxx1; /* unused */ - char ca_xxx2; /* unused */ - char ca_bdp; /* BDP to purge */ - short ca_cmdint; /* command ring transition flag */ - short ca_rspint; /* response ring transition flag */ - long ca_rspdsc[NRSP];/* response descriptors */ - long ca_cmddsc[NCMD];/* command descriptors */ -}; - -/* - * Simplified routines (e.g., uddump) reprogram the UDA50 for one command - * and one response at a time; uda1ca is like udaca except that it provides - * exactly one command and response descriptor. - */ -struct uda1ca { - short ca_xxx1; - char ca_xxx2; - char ca_bdp; - short ca_cmdint; - short ca_rspint; - long ca_rspdsc; - long ca_cmddsc; -}; diff --git a/sys/arch/vax/vax/autoconf.c b/sys/arch/vax/vax/autoconf.c index 78b42be263c..29681575364 100644 --- a/sys/arch/vax/vax/autoconf.c +++ b/sys/arch/vax/vax/autoconf.c @@ -1,4 +1,4 @@ -/* $NetBSD: autoconf.c,v 1.13 1996/05/19 16:43:53 ragge Exp $ */ +/* $NetBSD: autoconf.c,v 1.20 1997/01/11 13:50:20 ragge Exp $ */ /* * Copyright (c) 1994 Ludd, University of Lule}, Sweden. @@ -46,119 +46,108 @@ #include <machine/vmparam.h> #include <machine/nexus.h> #include <machine/ioa.h> +#include <machine/ka820.h> #include <machine/ka750.h> #include <machine/ka650.h> -#include <machine/uvaxII.h> +#include <machine/uvax.h> +#include <machine/clock.h> #include <vax/vax/gencons.h> #include <vm/vm.h> -#define BACKPLANE 0 -#define BIBUSS 1 -#define SBIBUSS 2 +struct nexus *nexus; -struct bp_conf { - char *type; - int num; - int partyp; -}; - -extern int cold; +#define BACKPLANE 0 +#define BIBUSS 1 +#define SBIBUSS 2 +#define VSBUSS 4 -void notsupp_steal_pages __P((void)); +int mastercpu; /* chief of the system */ +#if defined(VAX630) || defined(VAX410) || defined(VAX43) || defined(VAX46) +#define VAX_uVAX +#endif #ifdef VAX8600 /* XXX These are in ka860 also */ -void ka86_conf __P((struct device *, struct device *, void *)); -int ka86_clock __P((void)); -void ka86_memenable __P((struct sbi_attach_args *, struct device *)); -void ka86_memerr __P((void)); -int ka86_mchk __P((caddr_t)); -void ka86_steal_pages __P((void)); +void ka86_conf __P((struct device *, struct device *, void *)); +void ka86_memenable __P((struct sbi_attach_args *, struct device *)); +void ka86_memerr __P((void)); +int ka86_mchk __P((caddr_t)); +void ka86_steal_pages __P((void)); #endif #ifdef VAX780 /* XXX These are in ka780 also */ -void ka780_conf __P((struct device *, struct device *, void *)); -int ka780_clock __P((void)); -void ka780_memenable __P((struct sbi_attach_args *, void *)); -void ka780_memerr __P((void)); -int ka780_mchk __P((caddr_t)); -void ka780_steal_pages __P((void)); -#endif -#ifdef VAX750 -int nexty750[]={ NEX_MEM16, NEX_MEM16, NEX_MEM16, NEX_MEM16, - NEX_MBA, NEX_MBA, NEX_MBA, NEX_MBA, - NEX_UBA0, NEX_UBA1, NEX_ANY, NEX_ANY, - NEX_ANY, NEX_ANY, NEX_ANY, NEX_ANY}; -#endif -#if VAX730 -int nexty730[NNEX730] = { - NEX_MEM16, NEX_ANY, NEX_ANY, NEX_ANY, - NEX_ANY, NEX_ANY, NEX_ANY, NEX_ANY, -}; +void ka780_conf __P((struct device *, struct device *, void *)); +void ka780_memenable __P((struct sbi_attach_args *, void *)); +void ka780_memerr __P((void)); +int ka780_mchk __P((caddr_t)); +void ka780_steal_pages __P((void)); #endif -struct cpu_dep cpu_calls[VAX_MAX+1]={ +struct cpu_dep cpu_calls[]={ /* Type 0,noexist */ - {notsupp_steal_pages, NULL, NULL, NULL, NULL }, + {NULL, NULL, NULL, NULL, NULL }, #ifdef VAX780 /* Type 1, 11/{780,782,785} */ - {ka780_steal_pages, ka780_clock, ka780_mchk, ka780_memerr, ka780_conf}, + {ka780_steal_pages,generic_clock, ka780_mchk, ka780_memerr, ka780_conf, + generic_clkread, generic_clkwrite}, #else - {notsupp_steal_pages, NULL, NULL, NULL, NULL }, + {NULL, NULL, NULL, NULL, NULL }, #endif -#ifdef VAX750 /* Type 2, 11/750 */ - {ka750_steal_pages, ka750_clock, ka750_mchk, ka750_memerr, ka750_conf}, +#ifdef VAX750 /* Type 2, 11/750 */ + {ka750_steal_pages,generic_clock, ka750_mchk, ka750_memerr, ka750_conf, + generic_clkread, generic_clkwrite}, #else - {notsupp_steal_pages, NULL, NULL, NULL, NULL }, + {NULL, NULL, NULL, NULL, NULL }, #endif #ifdef VAX730 /* Type 3, 11/{730,725}, ceauciesco-vax */ - {notsupp_steal_pages, NULL, NULL, NULL, NULL }, + {NULL, NULL, NULL, NULL, NULL }, #else - {notsupp_steal_pages, NULL, NULL, NULL, NULL }, + {NULL, NULL, NULL, NULL, NULL }, #endif -#ifdef VAX8600 /* Type 4, 8600/8650 (11/{790,795}) */ - {ka86_steal_pages, ka86_clock, ka86_mchk, ka86_memerr, ka86_conf}, +#ifdef VAX8600 /* Type 4, 8600/8650 (11/{790,795}) */ + {ka86_steal_pages, generic_clock, ka86_mchk, ka86_memerr, ka86_conf, + generic_clkread, generic_clkwrite}, #else - {notsupp_steal_pages, NULL, NULL, NULL, NULL }, + {NULL, NULL, NULL, NULL, NULL }, #endif -#ifdef VAX8200 /* Type 5, 8200, 8300, 8350 */ - {notsupp_steal_pages, NULL, NULL, NULL, NULL }, +#ifdef VAX8200 /* Type 5, 8200, 8300, 8350 */ + {ka820_steal_pages, generic_clock, ka820_mchk, ka820_memerr, NULL, + ka820_clkread, ka820_clkwrite}, #else - {notsupp_steal_pages, NULL, NULL, NULL, NULL }, + {NULL, NULL, NULL, NULL, NULL }, #endif -#ifdef VAX8800 /* Type 6, 85X0, 8700, 88X0 */ - {notsupp_steal_pages, NULL, NULL, NULL, NULL }, +#ifdef VAX8800 /* Type 6, 85X0, 8700, 88X0 */ + {NULL, generic_clock, NULL, NULL, NULL }, #else - {notsupp_steal_pages, NULL, NULL, NULL, NULL }, + {NULL, NULL, NULL, NULL, NULL }, #endif #ifdef VAX610 /* Type 7, KA610 */ - {notsupp_steal_pages, NULL, NULL, NULL, NULL }, + {NULL, NULL, NULL, NULL, NULL }, #else - {notsupp_steal_pages, NULL, NULL, NULL, NULL }, + {NULL, NULL, NULL, NULL, NULL }, #endif -#ifdef VAX630 /* Type 8, KA630 or KA410 (uVAX II) */ - {uvaxII_steal_pages, uvaxII_clock, uvaxII_mchk, uvaxII_memerr, - uvaxII_conf}, +#ifdef VAX630 /* Type 8, KA630 or KA410 (uVAX II) */ + {uvax_steal_pages, no_nicr_clock, uvax_mchk, uvax_memerr, uvax_conf, + uvax_clkread, uvax_clkwrite}, #else - {notsupp_steal_pages, NULL, NULL, NULL, NULL }, + {NULL, NULL, NULL, NULL, NULL }, #endif /* Type 9, not used */ - {notsupp_steal_pages, NULL, NULL, NULL, NULL }, -#ifdef VAX650 /* Type 10, KA65X (uVAX III) */ - {uvaxIII_steal_pages, uvaxIII_clock, uvaxIII_mchk, uvaxIII_memerr, - uvaxIII_conf}, + {NULL, NULL, NULL, NULL, NULL }, +#ifdef VAX650 /* Type 10, KA65X (uVAX III) */ + {uvaxIII_steal_pages, no_nicr_clock, uvaxIII_mchk, uvaxIII_memerr, + uvaxIII_conf, generic_clkread, generic_clkwrite}, +#else + {NULL, NULL, NULL, NULL, NULL }, +#endif +#ifdef VAX_uVAX /* Type 11, RIGEL */ + {uvax_steal_pages, no_nicr_clock, uvax_mchk, uvax_memerr, uvax_conf, + uvax_clkread, uvax_clkwrite}, #else - {notsupp_steal_pages, NULL, NULL, NULL, NULL }, + {NULL, NULL, NULL, NULL, NULL }, #endif }; -void -notsupp_steal_pages() -{ - printf("This cputype not supported.\n"); - asm("halt"); -} - void gencnslask __P((void)); void @@ -182,6 +171,9 @@ configure() * parameter based on device(s) used. */ gencnslask(); /* XXX inte g|ras h{r */ +#if VAX410 || VAX43 + dzcnslask(); /* XXX inte g|ras h{r */ +#endif swapconf(); cold = 0; mtpr(GC_CCF, PR_TXDB); /* Clear cold start flag in cpu */ @@ -206,7 +198,7 @@ backplane_match(parent, gcf, aux) struct device *parent; void *gcf, *aux; { - struct cfdata *cf = gcf; + struct cfdata *cf = gcf; if (cf->cf_unit == 0 && strcmp(cf->cf_driver->cd_name, "backplane") == 0) @@ -215,8 +207,8 @@ backplane_match(parent, gcf, aux) return (0); } -static void find_sbi __P((struct device *, struct bp_conf *, - int (*) __P((void *, char *)))); +static void find_sbi __P((struct device *, struct bp_conf *, + int (*) __P((void *, const char *)))); void @@ -225,52 +217,78 @@ backplane_attach(parent, self, hej) void *hej; { struct bp_conf bp; - int i, ccpu, cmem, cbi, csbi; printf("\n"); + bp.partyp = BACKPLANE; - switch (cpunumber) { - case VAX_750: - case VAX_650: - case VAX_78032: - case VAX_780: - cmem = cbi = 0; - ccpu = csbi = 1; - break; - - case VAX_8600: - cmem = ccpu = 1; - cbi = csbi = 0; - break; - default: - cmem = ccpu = cbi = csbi = 0; + if (vax_bustype & VAX_CPUBUS) { + bp.type = "cpu"; + bp.num = 0; + config_found(self, &bp, printut); } - - bp.partyp = BACKPLANE; - bp.type = "cpu"; - for (i = 0; i < ccpu; i++) { - bp.num = i; + if (vax_bustype & VAX_VSBUS) { + bp.type = "vsbus"; + bp.num = 0; config_found(self, &bp, printut); } - bp.type = "mem"; - for (i = 0; i < cmem; i++) { - bp.num = i; + if (vax_bustype & VAX_SBIBUS) { + bp.type = "sbi"; + bp.num = 0; config_found(self, &bp, printut); } - bp.type = "bi"; - for (i = 0; i < cbi; i++) { - bp.num = i; + if (vax_bustype & VAX_CMIBUS) { + bp.type = "cmi"; + bp.num = 0; config_found(self, &bp, printut); } - bp.type = "sbi"; - for(i = 0; i < csbi; i++) { - bp.num = i; + if (vax_bustype & VAX_UNIBUS) { + bp.type = "uba"; + bp.num = 0; config_found(self, &bp, printut); } #if VAX8600 - if (cpunumber == VAX_8600) + if (vax_bustype & VAX_MEMBUS) { + bp.type = "mem"; + bp.num = 0; + config_found(self, &bp, printut); + } + if (vax_cputype == VAX_8600) find_sbi(self, &bp, printut); #endif + +#if VAX8200 || VAX8800 + bp.type = "bi"; + if (vax_bustype & VAX_BIBUS) { + + switch (vax_cputype) { +#if VAX8200 + case VAX_8200: { + extern void *bi_nodebase; + + bp.bp_addr = (int)bi_nodebase; + config_found(self, &bp, printut); + break; + } +#endif +#ifdef notyet + case VAX_8800: { + int bi, biaddr; + + for (bi = 0; bi < MAXNBI; bi++) { + biaddr = BI_BASE(bi) + BI_PROBE; + if (badaddr((caddr_t)biaddr, 4)) + continue; + + bp.bp_addr = BI_BASE(bi); + config_found(self, &bp, printut); + } + break; + } +#endif + } + } +#endif + } #if VAX8600 @@ -278,10 +296,10 @@ void find_sbi(self, bp, print) struct device *self; struct bp_conf *bp; - int (*print) __P((void *, char *)); + int (*print) __P((void *, const char *)); { volatile int tmp; - volatile struct sbia_regs *sbiar; + volatile struct sbia_regs *sbiar; extern struct ioa *ioa; int type, i; @@ -311,28 +329,29 @@ find_sbi(self, bp, print) } #endif -int cpu_match __P((struct device *, void *, void *)); -void cpu_attach __P((struct device *, struct device *, void *)); +int cpu_match __P((struct device *, void *, void *)); +void cpu_attach __P((struct device *, struct device *, void *)); int cpu_match(parent, gcf, aux) - struct device *parent; - void *gcf, *aux; + struct device *parent; + void *gcf, *aux; { - struct cfdata *cf = gcf; + struct cfdata *cf = gcf; struct bp_conf *bp = aux; if (strcmp(bp->type, "cpu")) return 0; - switch (cpunumber) { -#if VAX750 || VAX630 || VAX650 || VAX780 || VAX8600 + switch (vax_cputype) { +#if VAX750 || VAX630 || VAX650 || VAX780 || VAX8600 || VAX410 case VAX_750: case VAX_78032: case VAX_650: case VAX_780: case VAX_8600: + default: if(cf->cf_unit == 0 && bp->partyp == BACKPLANE) return 1; break; @@ -344,26 +363,26 @@ cpu_match(parent, gcf, aux) void cpu_attach(parent, self, aux) - struct device *parent, *self; - void *aux; + struct device *parent, *self; + void *aux; { - (*cpu_calls[cpunumber].cpu_conf)(parent, self, aux); + (*cpu_calls[vax_cputype].cpu_conf)(parent, self, aux); } -int mem_match __P((struct device *, void *, void *)); -void mem_attach __P((struct device *, struct device *, void *)); +int mem_match __P((struct device *, void *, void *)); +void mem_attach __P((struct device *, struct device *, void *)); int mem_match(parent, gcf, aux) - struct device *parent; - void *gcf, *aux; + struct device *parent; + void *gcf, *aux; { - struct cfdata *cf = gcf; + struct cfdata *cf = gcf; struct sbi_attach_args *sa = (struct sbi_attach_args *)aux; - struct bp_conf *bp = aux; + struct bp_conf *bp = aux; #if VAX8600 - if (cpunumber == VAX_8600 && !strcmp(parent->dv_xname, "backplane0")) { + if (vax_cputype == VAX_8600 && !strcmp(parent->dv_xname, "backplane0")) { if (strcmp(bp->type, "mem")) return 0; return 1; @@ -404,14 +423,14 @@ mem_match(parent, gcf, aux) void mem_attach(parent, self, aux) - struct device *parent, *self; - void *aux; + struct device *parent, *self; + void *aux; { struct sbi_attach_args *sa = (struct sbi_attach_args *)aux; struct mem_softc *sc = (void *)self; #if VAX8600 - if (cpunumber == VAX_8600) { + if (vax_cputype == VAX_8600) { ka86_memenable(0, 0); printf("\n"); return; @@ -420,22 +439,9 @@ mem_attach(parent, self, aux) sc->sc_memaddr = sa->nexaddr; sc->sc_memtype = sa->nexinfo; sc->sc_memnr = sa->type; - - switch (cpunumber) { -#ifdef VAX750 - case VAX_750: - ka750_memenable(sa, (void *)sc); - break; -#endif #ifdef VAX780 - case VAX_780: - ka780_memenable(sa, sc); - break; + ka780_memenable(sa, sc); #endif - default: - break; - } - } struct cfdriver backplane_cd = { @@ -454,14 +460,14 @@ struct cfattach cpu_backplane_ca = { sizeof(struct device), cpu_match, cpu_attach }; -struct cfdriver mem_cd = { +struct cfdriver mem_cd = { NULL, "mem", DV_CPU }; struct cfattach mem_backplane_ca = { - sizeof(struct device), mem_match, mem_attach + sizeof(struct mem_softc), mem_match, mem_attach }; struct cfattach mem_sbi_ca = { - sizeof(struct device), mem_match, mem_attach + sizeof(struct mem_softc), mem_match, mem_attach }; diff --git a/sys/arch/vax/vax/clock.c b/sys/arch/vax/vax/clock.c index 3a1a717edcb..f55c19f0bf1 100644 --- a/sys/arch/vax/vax/clock.c +++ b/sys/arch/vax/vax/clock.c @@ -1,4 +1,4 @@ -/* $NetBSD: clock.c,v 1.14 1996/05/19 16:43:57 ragge Exp $ */ +/* $NetBSD: clock.c,v 1.18 1996/10/13 03:35:33 christos Exp $ */ /* * Copyright (c) 1995 Ludd, University of Lule}, Sweden. * All rights reserved. @@ -37,11 +37,9 @@ #include <machine/mtpr.h> #include <machine/sid.h> -#include <machine/uvaxII.h> - -#define SEC_PER_DAY (60*60*24) - -extern int todrstopped; +#include <machine/uvax.h> +#include <machine/clock.h> +#include <machine/cpu.h> static unsigned long year; /* start of current year in seconds */ static unsigned long year_len; /* length of current year in 100th of seconds */ @@ -62,10 +60,10 @@ microtime(tvp) s = splhigh(); int_time = mfpr(PR_TODR); - asm ("movc3 %0,(%1),(%2)" - : - : "r" (sizeof(struct timeval)),"r" (&time),"r"(tvp) - :"r0","r1","r2","r3","r4","r5"); + asm ("movc3 %0,(%1),(%2)" + : + : "r" (sizeof(struct timeval)),"r" (&time),"r"(tvp) + :"r0","r1","r2","r3","r4","r5"); i = mfpr(PR_ICR) + tick; /* Get current interval count */ tvp->tv_usec += i; @@ -103,69 +101,34 @@ void inittodr(fs_time) time_t fs_time; { + int rv; - unsigned long tmp_year, sluttid, year_ticks; - int clock_stopped = 0; + rv = (*cpu_calls[vax_cputype].cpu_clkread) (fs_time); + switch (rv) { - sluttid = fs_time; - year = (fs_time / SEC_PER_DAY / 365) * 365 * SEC_PER_DAY; - tmp_year = year / SEC_PER_DAY / 365 + 2; - year_len = 100 * SEC_PER_DAY * - ((tmp_year % 4 && tmp_year != 32) ? 365 : 366); - - switch (cpunumber) { -#if VAX750 || VAX650 - case VAX_750: - case VAX_650: - year_ticks = mfpr(PR_TODR); - clock_stopped = todrstopped; + case CLKREAD_BAD: /* No useable information from system clock */ + time.tv_sec = fs_time; + resettodr(); break; -#endif -#if VAX630 || VAX410 - case VAX_78032: - year_ticks = uvaxII_gettodr(&clock_stopped); + + case CLKREAD_WARN: /* Just give the warning */ break; -#endif -#if VAX780 || VAX8600 - case VAX_780: - case VAX_8600: - year_ticks = mfpr(PR_TODR); + + default: /* System clock OK, no warning if we don't want to. */ + if (time.tv_sec > fs_time + 3 * SEC_PER_DAY) { + printf("Clock has gained %d days", + (time.tv_sec - fs_time) / SEC_PER_DAY); + rv = CLKREAD_WARN; + } else if (time.tv_sec + SEC_PER_DAY < fs_time) { + printf("Clock has lost %d day(s)", + (fs_time - time.tv_sec) / SEC_PER_DAY); + rv = CLKREAD_WARN; + } break; -#endif - default: - year_ticks = 0; - clock_stopped = 1; - }; - - if (clock_stopped){ - printf( - "Internal clock not started. Using time from file system.\n"); - switch (cpunumber) { -#if VAX750 || VAX650 - case VAX_750: - case VAX_650: - /* +1 so the clock won't be stopped */ - mtpr((fs_time - year) * 100 + 1, PR_TODR); - break; -#endif -#if VAX630 || VAX410 - case VAX_78032: - uvaxII_settodr((fs_time - year) * 100 + 1); - break; -#endif - }; - todrstopped = 0; - } else if (year_ticks / 100 > fs_time - year + SEC_PER_DAY * 3) { - printf( - "WARNING: Clock has gained %d days - CHECK AND RESET THE DATE.\n", - (int)(year_ticks / 100 - (fs_time - year)) / SEC_PER_DAY); - sluttid = year + (year_ticks / 100); - } else if (year_ticks / 100 < fs_time - year) { - printf( - "WARNING: Clock has lost time - CHECK AND RESET THE DATE.\n"); - } else - sluttid = year + (year_ticks / 100); - time.tv_sec = sluttid; + } + + if (rv < CLKREAD_OK) + printf(" - CHECK AND RESET THE DATE.\n"); } /* @@ -175,30 +138,8 @@ inittodr(fs_time) void resettodr() { - - unsigned long tmp_year; - - year = (time.tv_sec / SEC_PER_DAY / 365) * 365 * SEC_PER_DAY; - tmp_year = year / SEC_PER_DAY / 365 + 2; - year_len = 100 * SEC_PER_DAY * - ((tmp_year % 4 && tmp_year != 32) ? 365 : 366); - switch (cpunumber) { -#if VAX750 - case VAX_750: - mtpr((time.tv_sec - year) * 100 + 1, PR_TODR); - break; -#endif -#if VAX630 || VAX410 - case VAX_78032: - uvaxII_settodr((time.tv_sec - year) * 100 + 1); - break; -#endif - default: - mtpr((time.tv_sec - year) * 100, PR_TODR); - }; - todrstopped = 0; + (*cpu_calls[vax_cputype].cpu_clkwrite)(); } - /* * A delayloop that delays about the number of milliseconds that is * given as argument. @@ -209,14 +150,19 @@ delay(i) { int mul; - switch (cpunumber) { -#if VAX750 || VAX630 || VAX780 + switch (vax_cputype) { +#if VAX750 || VAX630 || VAX410 case VAX_750: case VAX_78032: - case VAX_780: mul = 1; /* <= 1 VUPS */ break; #endif +#if VAX780 || VAX8200 + case VAX_780: + case VAX_8200: + mul = 2; /* <= 2 VUPS */ + break; +#endif #if VAX650 case VAX_650: mul = 3; /* <= 3 VUPS */ @@ -229,3 +175,168 @@ delay(i) } asm ("1: sobgtr %0, 1b" : : "r" (mul * i)); } + +#if VAX750 || VAX780 || VAX8200 || VAX8600 || VAX8800 +/* + * On most VAXen there are a microsecond clock that should + * be used for interval interrupts. Have a generic version here. + */ +void +generic_clock() +{ + mtpr(-10000, PR_NICR); /* Load in count register */ + mtpr(0x800000d1, PR_ICCS); /* Start clock and enable interrupt */ +} +#endif + +#if VAX650 || VAX630 || VAX410 || VAX43 +/* + * Most microvaxen don't have a interval count register. + */ +void +no_nicr_clock() +{ + mtpr(0x800000d1, PR_ICCS); /* Start clock and enable interrupt */ +} +#endif + +/* + * There are two types of real-time battery-backed up clocks on + * VAX computers, one with a register that counts up every 1/100 second, + * one with a clock chip that delivers time. For the register clock + * we have a generic version, and for the chip clock there are + * support routines for time conversion. + */ +/* + * Converts a year to corresponding number of ticks. + */ +int +yeartonum(y) + int y; +{ + int n; + + for (n = 0, y -= 1; y > 69; y--) + n += SECPERYEAR(y); + return n; +} + +/* + * Converts tick number to a year 70 -> + */ +int +numtoyear(num) + int num; +{ + int y = 70, j; + while(num >= (j = SECPERYEAR(y))) { + y++; + num -= j; + } + return y; +} + +#if VAX750 || VAX780 || VAX8600 || VAX650 +/* + * Reads the TODR register; returns a (probably) true tick value, + * or CLKREAD_BAD if failed. The year is based on the argument + * year; the TODR doesn't hold years. + */ +int +generic_clkread(base) + time_t base; +{ + unsigned klocka = mfpr(PR_TODR); + + /* + * Sanity check. + */ + if (klocka < TODRBASE) { + if (klocka == 0) + printf("TODR stopped"); + else + printf("TODR too small"); + return CLKREAD_BAD; + } + + time.tv_sec = yeartonum(numtoyear(base)) + (klocka - TODRBASE) / 100; + return CLKREAD_OK; +} + +/* + * Takes the current system time and writes it to the TODR. + */ +void +generic_clkwrite() +{ + unsigned tid = time.tv_sec, bastid; + + bastid = tid - yeartonum(numtoyear(tid)); + mtpr((bastid * 100) + TODRBASE, PR_TODR); +} +#endif + +#if VAX630 || VAX410 || VAX43 || VAX8200 + +static int dagar[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; + +/* + * Returns the number of days in month based on the current year. + */ +int +daysinmonth(m, y) + int m, y; +{ + if (m == 2 && IS_LEAPYEAR(y)) + return 29; + else + return dagar[m - 1]; +} + +/* + * Converts chiptime (year/month/day/hour/min/sek) and returns ticks. + */ +long +chiptotime(c) + struct chiptime *c; +{ + int num, i; + + num = c->sec; + num += c->min * SEC_PER_MIN; + num += c->hour * SEC_PER_HOUR; + num += (c->day - 1) * SEC_PER_DAY; + for(i = c->mon - 1; i > 0; i--) + num += daysinmonth(i, c->year) * SEC_PER_DAY; + num += yeartonum(c->year); + + return num; +} + +/* + * Reads the system time and puts it into a chiptime struct. + */ +void +timetochip(c) + struct chiptime *c; +{ + int tid = time.tv_sec, i, j; + + c->year = numtoyear(tid); + tid -= yeartonum(c->year); + + c->mon = 1; + while(tid >= (j = (daysinmonth(c->mon, c->year) * SEC_PER_DAY))) { + c->mon++; + tid -= j; + } + c->day = (tid / SEC_PER_DAY) + 1; + tid %= SEC_PER_DAY; + + c->hour = tid / SEC_PER_HOUR; + tid %= SEC_PER_HOUR; + + c->min = tid / SEC_PER_MIN; + c->sec = tid % SEC_PER_MIN; +} +#endif diff --git a/sys/arch/vax/vax/conf.c b/sys/arch/vax/vax/conf.c index d78fe74f5a0..4abb4d74c7c 100644 --- a/sys/arch/vax/vax/conf.c +++ b/sys/arch/vax/vax/conf.c @@ -1,4 +1,5 @@ -/* $NetBSD: conf.c,v 1.21 1996/04/08 18:32:29 ragge Exp $ */ +/* $OpenBSD: conf.c,v 1.10 1997/01/15 23:25:06 maja Exp $ */ +/* $NetBSD: conf.c,v 1.27 1997/01/07 11:35:20 mrg Exp $ */ /*- * Copyright (c) 1982, 1986 The Regents of the University of California. @@ -43,12 +44,6 @@ #include <sys/conf.h> #include <sys/vnode.h> -int ttselect __P((dev_t, int, struct proc *)); - -#ifndef LKM -#define lkmenodev enodev -#endif - #include "hp.h" /* 0 */ bdev_decl(hp); @@ -63,27 +58,24 @@ bdev_decl(sw); #include "te.h" bdev_decl(tm); -#include "tmscp.h" -bdev_decl(tmscp); +#include "mt.h" +bdev_decl(mt); #include "ts.h" bdev_decl(ts); #include "mu.h" -bdev_decl(mt); +bdev_decl(mu); #if defined(VAX750) -#define NCTU 1 +#define NCTU 1 #else -#define NCTU 0 +#define NCTU 0 #endif bdev_decl(ctu); -#include "uda.h" -bdev_decl(uda); - -#include "kdb.h" -bdev_decl(kdb); +#include "ra.h" +bdev_decl(ra); #include "up.h" bdev_decl(up); @@ -109,6 +101,21 @@ bdev_decl(ccd); #include "vnd.h" bdev_decl(vnd); +#include "hdc.h" +bdev_decl(hdc); + +#include "sd.h" +bdev_decl(sd); + +#include "st.h" +bdev_decl(st); + +#include "cd.h" +bdev_decl(cd); + +#include "md.h" +bdev_decl(md); + struct bdevsw bdevsw[] = { bdev_disk_init(NHP,hp), /* 0: RP0?/RM0? */ @@ -118,33 +125,53 @@ struct bdevsw bdevsw[] = bdev_swap_init(1,sw), /* 4: swap pseudo-device */ bdev_tape_init(NTE,tm), /* 5: TM11/TE10 */ bdev_tape_init(NTS,ts), /* 6: TS11 */ - bdev_tape_init(NMU,mt), /* 7: TU78 */ + bdev_tape_init(NMU,mu), /* 7: TU78 */ bdev_tape_init(NCTU,ctu), /* 8: Console TU58 on 730/750 */ - bdev_disk_init(NUDA,uda), /* 9: UDA50/RA?? */ + bdev_disk_init(NRA,ra), /* 9: MSCP disk */ bdev_tape_init(NTJ,ut), /* 10: TU45 */ bdev_disk_init(NRB,idc), /* 11: IDC (RB730) */ bdev_disk_init(NRX,rx), /* 12: RX01/02 on unibus */ bdev_disk_init(NUU,uu), /* 13: TU58 on DL11 */ bdev_disk_init(NRL,rl), /* 14: RL01/02 */ - bdev_tape_init(NTMSCP,tmscp), /* 15: TMSCP tape */ - bdev_disk_init(NKDB,kdb), /* 16: KDB50/RA?? */ + bdev_tape_init(NMT,mt), /* 15: MSCP tape */ + bdev_notdef(), /* 16: was: KDB50/RA?? */ bdev_disk_init(NCCD,ccd), /* 17: concatenated disk driver */ bdev_disk_init(NVND,vnd), /* 18: vnode disk driver */ + bdev_disk_init(NHDC,hdc), /* 19: HDC9224/RD?? */ + bdev_disk_init(NSD,sd), /* 20: SCSI disk */ + bdev_tape_init(NST,st), /* 21: SCSI tape */ + bdev_disk_init(NCD,cd), /* 22: SCSI CD-ROM */ + bdev_disk_init(NMD,md), /* 23: memory disk driver */ }; int nblkdev = sizeof(bdevsw) / sizeof(bdevsw[0]); /* - * Console routines for VAX console. There are always an generic console, - * but maybe we should care about RD, QDSS etc? + * Console routines for VAX console. */ #include <dev/cons.h> -#define gencnpollc nullcnpollc +#define gencnpollc nullcnpollc cons_decl(gen); +#define dzcnpollc nullcnpollc +cons_decl(dz); -struct consdev constab[]={ -/* Generic console, should always be present */ - cons_init(gen), +struct consdev constab[]={ +#if VAX8600 || VAX780 || VAX750 || VAX650 || VAX630 +#define NGEN 1 + cons_init(gen), /* Generic console type; mtpr/mfpr */ +#else +#define NGEN 0 +#endif +#if VAX410 || VAX43 +#define NDZCN 1 + cons_init(dz), /* DZ11-like serial console on VAXstations */ +#else +#define NDZCN 0 +#endif +#if 0 /* VAX410 || VAX43 || VAX650 || VAX630 */ + cons_init(qv), /* QVSS/QDSS bit-mapped console driver */ + cons_init(qd), +#endif #ifdef notyet /* We may not always use builtin console, sometimes RD */ @@ -156,76 +183,73 @@ struct consdev constab[]={ /* Special for console storage */ #define dev_type_rw(n) int n __P((dev_t, int, int, struct proc *)) -/* plotters - open, close, write, ioctl, select */ +/* plotters - open, close, write, ioctl, poll */ #define cdev_plotter_init(c,n) { \ dev_init(c,n,open), dev_init(c,n,close), (dev_type_read((*))) enodev, \ dev_init(c,n,write), dev_init(c,n,ioctl), (dev_type_stop((*))) enodev, \ - 0, dev_init(c,n,select), (dev_type_mmap((*))) enodev } + 0, dev_init(c,n,poll), (dev_type_mmap((*))) enodev } /* console mass storage - open, close, read/write */ -#define cdev_cnstore_init(c,n) { \ +#define cdev_cnstore_init(c,n) { \ dev_init(c,n,open), dev_init(c,n,close), dev_init(c,n,read), \ dev_init(c,n,write), (dev_type_ioctl((*))) enodev, \ - (dev_type_stop((*))) enodev, 0, (dev_type_select((*))) enodev, \ + (dev_type_stop((*))) enodev, 0, (dev_type_poll((*))) enodev, \ (dev_type_mmap((*))) enodev } -#define cdev_lp_init(c,n) { \ +#define cdev_lp_init(c,n) { \ dev_init(c,n,open), dev_init(c,n,close), (dev_type_read((*))) enodev, \ dev_init(c,n,write), (dev_type_ioctl((*))) enodev, \ (dev_type_stop((*))) enodev, 0, seltrue, (dev_type_mmap((*))) enodev } /* graphic display adapters */ -#define cdev_graph_init(c,n) { \ +#define cdev_graph_init(c,n) { \ dev_init(c,n,open), dev_init(c,n,close), dev_init(c,n,read), \ dev_init(c,n,write), dev_init(c,n,ioctl), dev_init(c,n,stop), \ - 0, dev_init(c,n,select), (dev_type_mmap((*))) enodev } + 0, dev_init(c,n,poll), (dev_type_mmap((*))) enodev } /* Ingres */ #define cdev_ingres_init(c,n) { \ dev_init(c,n,open), dev_init(c,n,close), (dev_type_read((*))) nullop, \ (dev_type_write((*))) nullop, dev_init(c,n,ioctl), \ - (dev_type_stop((*))) nullop, 0, (dev_type_select((*))) nullop, \ + (dev_type_stop((*))) nullop, 0, (dev_type_poll((*))) nullop, \ (dev_type_mmap((*))) enodev } cdev_decl(cn); cdev_decl(ctty); -#define mmread mmrw -#define mmwrite mmrw +#define mmread mmrw +#define mmwrite mmrw cdev_decl(mm); cdev_decl(sw); #include "pty.h" -#define ptstty ptytty -#define ptsioctl ptyioctl +#define ptstty ptytty +#define ptsioctl ptyioctl cdev_decl(pts); -#define ptctty ptytty -#define ptcioctl ptyioctl +#define ptctty ptytty +#define ptcioctl ptyioctl cdev_decl(ptc); cdev_decl(log); -#ifdef LKM -#define NLKM 1 -#else -#define NLKM 0 -#endif -cdev_decl(lkm); cdev_decl(hp); cdev_decl(rk); cdev_decl(tm); -cdev_decl(tmscp); -cdev_decl(ts); cdev_decl(mt); -cdev_decl(uda); +cdev_decl(ts); +cdev_decl(mu); +cdev_decl(ra); cdev_decl(up); cdev_decl(ut); cdev_decl(idc); cdev_decl(fd); cdev_decl(gencn); +cdev_decl(dzcn); cdev_decl(rx); cdev_decl(rl); -cdev_decl(kdb); cdev_decl(ccd); +cdev_decl(hdc); +cdev_decl(sd); +cdev_decl(st); #include "ct.h" cdev_decl(ct); @@ -238,31 +262,31 @@ cdev_decl(dmf); cdev_decl(np); #if VAX8600 -#define NCRL 1 +#define NCRL 1 #else #define NCRL 0 #endif -#define crlread crlrw +#define crlread crlrw #define crlwrite crlrw cdev_decl(crl); -#if VAX8200 +#if VAX8200 && 0 #define NCRX 1 #else #define NCRX 0 #endif -#define crxread crxrw -#define crxwrite crxrw +#define crxread crxrw +#define crxwrite crxrw cdev_decl(crx); -#if VAX780 && 0 -#define NFL 1 +#if VAX780 +#define NCFL 1 #else -#define NFL 0 +#define NCFL 0 #endif -#define flread flrw -#define flwrite flrw -cdev_decl(fl); +#define cflread cflrw +#define cflwrite cflrw +cdev_decl(cfl); #include "dz.h" cdev_decl(dz); @@ -303,10 +327,15 @@ cdev_decl(qv); #include "qd.h" cdev_decl(qd); +#ifdef 0 +#include "ipfilter.h" +cdev_decl(ipl); +#endif + #if defined(INGRES) -#define NII 1 +#define NII 1 #else -#define NII 0 +#define NII 0 #endif cdev_decl(ii); @@ -317,6 +346,14 @@ cdev_decl(bpf); #include "tun.h" cdev_decl(tun); +cdev_decl(cd); +#include "ch.h" +cdev_decl(ch); +cdev_decl(md); +#include "ss.h" +cdev_decl(ss); +#include "uk.h" +cdev_decl(uk); cdev_decl(random); @@ -332,8 +369,8 @@ struct cdevsw cdevsw[] = cdev_notdef(), /* 5 */ cdev_plotter_init(NVP,vp), /* 6: Versatec plotter */ cdev_swap_init(1,sw), /* 7 */ - cdev_cnstore_init(NFL,fl), /* 8: 11/780 console floppy */ - cdev_disk_init(NUDA,uda), /* 9: MSCP disk interface */ + cdev_cnstore_init(NCFL,cfl), /* 8: 11/780 console floppy */ + cdev_disk_init(NRA,ra), /* 9: MSCP disk interface */ cdev_plotter_init(NVA,va), /* 10: Benson-Varian plotter */ cdev_disk_init(NRK,rk), /* 11: RK06/07 */ cdev_tty_init(NDH,dh), /* 12: DH-11/DM-11 */ @@ -343,13 +380,13 @@ struct cdevsw cdevsw[] = cdev_tape_init(NTS,ts), /* 16: TS11 */ cdev_tape_init(NTJ,ut), /* 17: TU45 */ cdev_lp_init(NCT,ct), /* 18: phototypesetter interface */ - cdev_tape_init(NMU,mt), /* 19: TU78 */ + cdev_tape_init(NMU,mu), /* 19: TU78 */ cdev_tty_init(NPTY,pts), /* 20: pseudo-tty slave */ cdev_ptc_init(NPTY,ptc), /* 21: pseudo-tty master */ cdev_tty_init(NDMF,dmf), /* 22: DMF32 */ cdev_disk_init(NRB,idc), /* 23: IDC (RB730) */ cdev_lp_init(NDN,dn), /* 24: DN-11 autocall unit */ - cdev_tty_init(1,gencn), /* 25: Generic console (mtpr...) */ + cdev_tty_init(NGEN,gencn), /* 25: Generic console (mtpr...) */ cdev_audio_init(NLPA,lpa), /* 26 ??? */ cdev_graph_init(NPS,ps), /* 27: E/S graphics device */ cdev_lkm_init(NLKM,lkm), /* 28: loadable module driver */ @@ -360,13 +397,17 @@ struct cdevsw cdevsw[] = cdev_log_init(1,log), /* 33: /dev/klog */ cdev_tty_init(NDHU,dhu), /* 34: DHU-11 */ cdev_cnstore_init(NCRL,crl), /* 35: Console RL02 on 8600 */ - cdev_notdef(), /* 36: was vs100 interface. ??? */ + cdev_tty_init(NDZCN,dzcn), /* 36: DZ11-like console on VAXst. */ cdev_tty_init(NDMZ,dmz), /* 37: DMZ32 */ - cdev_tape_init(NTMSCP,tmscp), /* 38: TMSCP tape */ + cdev_tape_init(NMT,mt), /* 38: MSCP tape */ cdev_audio_init(NNP,np), /* 39: NP Intelligent Board */ cdev_graph_init(NQV,qv), /* 40: QVSS graphic display */ cdev_graph_init(NQD,qd), /* 41: QDSS graphic display */ - cdev_notdef(), /* 42 */ +#ifdef 0 + cdev_ipf_init(NIPFILTER,ipl), /* 42: Packet filter */ +#else + cdev_notdef(), +#endif cdev_ingres_init(NII,ii), /* 43: Ingres device */ cdev_notdef(), /* 44 was Datakit */ cdev_notdef(), /* 45 was Datakit */ @@ -376,17 +417,25 @@ struct cdevsw cdevsw[] = cdev_notdef(), /* 49 */ cdev_notdef(), /* 50 */ cdev_cnstore_init(NCRX,crx), /* 51: Console RX50 at 8200 */ - cdev_disk_init(NKDB,kdb), /* 52: KDB50/RA?? */ + cdev_notdef(), /* 52: was: KDB50/RA?? */ cdev_fd_init(1,filedesc), /* 53: file descriptor pseudo-device */ cdev_disk_init(NCCD,ccd), /* 54: concatenated disk driver */ cdev_disk_init(NVND,vnd), /* 55: vnode disk driver */ cdev_bpftun_init(NBPFILTER,bpf),/* 56: berkeley packet filter */ cdev_bpftun_init(NTUN,tun), /* 57: tunnel filter */ - cdev_random_init(1,random), /* 58: random data source */ + cdev_disk_init(NHDC,hdc), /* 58: HDC9224/RD?? */ + cdev_disk_init(NSD,sd), /* 59: SCSI disk */ + cdev_tape_init(NST,st), /* 60: SCSI tape */ + cdev_disk_init(NCD,cd), /* 61: SCSI CD-ROM */ + cdev_disk_init(NMD,md), /* 62: memory disk driver */ + cdev_ch_init(NCH,ch), /* 63: SCSI autochanger */ + cdev_scanner_init(NSS,ss), /* 64: SCSI scanner */ + cdev_uk_init(NUK,uk), /* 65: SCSI unknown */ + cdev_random_init(1,random), /* 66: random data source */ }; int nchrdev = sizeof(cdevsw) / sizeof(cdevsw[0]); -int mem_no = 3; /* major device number of memory special file */ +int mem_no = 3; /* major device number of memory special file */ /* * Swapdev is a fake device implemented @@ -404,16 +453,16 @@ int chrtoblktbl[] = { NODEV, /* 1 */ NODEV, /* 2 */ NODEV, /* 3 */ - 0, /* 4 */ - 1, /* 5 */ + 0, /* 4 */ + 1, /* 5 */ NODEV, /* 6 */ NODEV, /* 7 */ NODEV, /* 8 */ - 9, /* 9 */ + 9, /* 9 */ NODEV, /* 10 */ - 3, /* 11 */ + 3, /* 11 */ NODEV, /* 12 */ - 2, /* 13 */ + 2, /* 13 */ 5, /* 14 */ NODEV, /* 15 */ 6, /* 16 */ @@ -451,11 +500,21 @@ int chrtoblktbl[] = { NODEV, /* 48 */ NODEV, /* 49 */ NODEV, /* 50 */ - NODEV, /* 51 */ + NODEV, /* 51 */ 16, /* 52 */ NODEV, /* 53 */ 17, /* 54 */ 18, /* 55 */ + NODEV, /* 56 */ + NODEV, /* 57 */ + 19, /* 58 */ + 20, /* 59 */ + 21, /* 60 */ + 22, /* 61 */ + 23, /* 62 */ + NODEV, /* 63 */ + NODEV, /* 64 */ + NODEV, /* 65 */ }; int diff --git a/sys/arch/vax/vax/crl.c b/sys/arch/vax/vax/crl.c index c928997904f..9c2c687859b 100644 --- a/sys/arch/vax/vax/crl.c +++ b/sys/arch/vax/vax/crl.c @@ -1,4 +1,4 @@ -/* $NetBSD: crl.c,v 1.2 1996/04/08 18:32:30 ragge Exp $ */ +/* $NetBSD: crl.c,v 1.5 1996/10/13 03:35:35 christos Exp $ */ /*- * Copyright (c) 1982, 1986 The Regents of the University of California. * All rights reserved. @@ -75,17 +75,17 @@ int crlclose __P((dev_t, int, struct proc *)); int crlrw __P((dev_t, struct uio *, int)); -struct ivec_dsp crl_intr; +struct ivec_dsp crl_intr; void crlattach() { - extern struct ivec_dsp idsptch; + extern struct ivec_dsp idsptch; bcopy(&idsptch, &crl_intr, sizeof(struct ivec_dsp)); scb->scb_csrint = &crl_intr; crl_intr.hoppaddr = crlintr; -} +} /*ARGSUSED*/ int @@ -94,7 +94,7 @@ crlopen(dev, flag, p) int flag; struct proc *p; { - if (cpunumber != VAX_8600) + if (vax_cputype != VAX_8600) return (ENXIO); if (crltab.crl_state != CRL_IDLE) return (EALREADY); diff --git a/sys/arch/vax/vax/ctu.c b/sys/arch/vax/vax/ctu.c index 2584aaa194d..1d5727a482f 100644 --- a/sys/arch/vax/vax/ctu.c +++ b/sys/arch/vax/vax/ctu.c @@ -1,4 +1,4 @@ -/* $NetBSD: ctu.c,v 1.3 1996/04/08 18:32:31 ragge Exp $ */ +/* $NetBSD: ctu.c,v 1.5 1996/10/13 03:35:36 christos Exp $ */ /* * Copyright (c) 1996 Ludd, University of Lule}, Sweden. * All rights reserved. diff --git a/sys/arch/vax/vax/db_disasm.c b/sys/arch/vax/vax/db_disasm.c index 26950657de7..a98598206f0 100644 --- a/sys/arch/vax/vax/db_disasm.c +++ b/sys/arch/vax/vax/db_disasm.c @@ -1,4 +1,4 @@ -/* $NetBSD: db_disasm.c,v 1.6 1996/04/08 18:32:32 ragge Exp $ */ +/* $NetBSD: db_disasm.c,v 1.9 1996/10/13 03:35:38 christos Exp $ */ /* * Copyright (c) 1996 Ludd, University of Lule}, Sweden. * All rights reserved. @@ -16,8 +16,8 @@ * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: - * This product includes software developed at Ludd, University of - * Lule}, Sweden and its contributors. + * This product includes software developed at Ludd, University of + * Lule}, Sweden and its contributors. * 4. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission * @@ -35,34 +35,33 @@ #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 */ @@ -70,63 +69,63 @@ /* #define BROKEN_DB_REGS */ -#ifdef BROKEN_DB_REGS -struct { /* Due to order and contents of db_regs[], we can't */ - char *name; /* use this array to extract register-names. */ - void *valuep; /* eg. "psl" vs "pc", "pc" vs "sp" */ +#ifdef BROKEN_DB_REGS +struct { /* Due to order and contents of db_regs[], we can't */ + char *name; /* use this array to extract register-names. */ + void *valuep; /* eg. "psl" vs "pc", "pc" vs "sp" */ } my_db_regs[16] = { - { "r0", NULL }, - { "r1", NULL }, - { "r2", NULL }, - { "r3", NULL }, - { "r4", NULL }, - { "r5", NULL }, - { "r6", NULL }, - { "r7", NULL }, - { "r8", NULL }, - { "r9", NULL }, - { "r10", NULL }, - { "r11", NULL }, - { "ap", NULL }, /* aka "r12" */ - { "fp", NULL }, /* aka "r13" */ - { "sp", NULL }, /* aka "r14" */ - { "pc", NULL }, /* aka "r15" */ + { "r0", NULL }, + { "r1", NULL }, + { "r2", NULL }, + { "r3", NULL }, + { "r4", NULL }, + { "r5", NULL }, + { "r6", NULL }, + { "r7", NULL }, + { "r8", NULL }, + { "r9", NULL }, + { "r10", NULL }, + { "r11", NULL }, + { "ap", NULL }, /* aka "r12" */ + { "fp", NULL }, /* aka "r13" */ + { "sp", NULL }, /* aka "r14" */ + { "pc", NULL }, /* aka "r15" */ }; #else #define my_db_regs db_regs #endif typedef struct { - char dasm[256]; /* disassebled instruction as text */ - char *curp; /* pointer into result */ - char *ppc; /* pseudo PC */ - int opc; /* op-code */ - char *argp; /* pointer into argument-list */ - int itype; /* instruction-type, eg. branch, call, unspec */ - int atype; /* argument-type, eg. byte, long, address */ - int off; /* offset specified by last argument */ - int addr; /* address specified by last argument */ -} inst_buffer; + char dasm[256]; /* disassebled instruction as text */ + char *curp; /* pointer into result */ + char *ppc; /* pseudo PC */ + int opc; /* op-code */ + char *argp; /* pointer into argument-list */ + int itype; /* instruction-type, eg. branch, call, unspec */ + int atype; /* argument-type, eg. byte, long, address */ + int off; /* offset specified by last argument */ + int addr; /* address specified by last argument */ +} inst_buffer; #define ITYPE_INVALID -1 -#define ITYPE_UNSPEC 0 -#define ITYPE_BRANCH 1 -#define ITYPE_CALL 2 +#define ITYPE_UNSPEC 0 +#define ITYPE_BRANCH 1 +#define ITYPE_CALL 2 -int get_byte __P((inst_buffer * ib)); -int get_word __P((inst_buffer * ib)); -int get_long __P((inst_buffer * ib)); +int get_byte __P((inst_buffer * ib)); +int get_word __P((inst_buffer * ib)); +int get_long __P((inst_buffer * ib)); -int get_opcode __P((inst_buffer * ib)); +int get_opcode __P((inst_buffer * ib)); int get_operands __P((inst_buffer * ib)); int get_operand __P((inst_buffer * ib, int size)); -void add_char __P((inst_buffer * ib, int c)); -void add_str __P((inst_buffer * ib, char *s)); -void add_int __P((inst_buffer * ib, int i)); -void add_xint __P((inst_buffer * ib, int i)); -void add_sym __P((inst_buffer * ib, int i)); -void add_off __P((inst_buffer * ib, int i)); +void add_char __P((inst_buffer * ib, int c)); +void add_str __P((inst_buffer * ib, char *s)); +void add_int __P((inst_buffer * ib, int i)); +void add_xint __P((inst_buffer * ib, int i)); +void add_sym __P((inst_buffer * ib, int i)); +void add_off __P((inst_buffer * ib, int i)); #define err_print printf @@ -141,14 +140,14 @@ void add_off __P((inst_buffer * ib, int i)); */ db_addr_t db_disasm(loc, altfmt) - db_addr_t loc; - boolean_t altfmt; + db_addr_t loc; + boolean_t altfmt; { - db_expr_t diff; - db_sym_t sym; - char *symname; + db_expr_t diff; + db_sym_t sym; + char *symname; - inst_buffer ib; + inst_buffer ib; bzero(&ib, sizeof(ib)); ib.ppc = (void *) loc; @@ -160,7 +159,7 @@ db_disasm(loc, altfmt) sym = db_search_symbol(loc, DB_STGY_PROC, &diff); db_symbol_values(sym, &symname, 0); - if (symname && !diff) { /* symbol at loc */ + if (symname && !diff) { /* symbol at loc */ db_printf("function \"%s()\", entry-mask 0x%x\n\t\t", symname, (unsigned short) get_word(&ib)); ib.ppc += 2; @@ -210,8 +209,8 @@ int get_operands(ib) inst_buffer *ib; { - int aa = 0; /* absolute address mode ? */ - int size; + int aa = 0; /* absolute address mode ? */ + int size; if (ib->opc < 0 || ib->opc > 0xFF) { /* invalid or two-byte opcode */ @@ -243,7 +242,7 @@ get_operands(ib) break; case 'a': /* absolute adressing mode */ - aa = 1; /* do not break here ! */ + aa = 1; /* do not break here ! */ default: switch (*(++ib->argp)) { @@ -301,14 +300,14 @@ get_operands(ib) int get_operand(ib, size) inst_buffer *ib; - int size; + int size; { - int c = get_byte(ib); - int mode = c >> 4; - int reg = c & 0x0F; - int lit = c & 0x3F; - int tmp = 0; - char buf[16]; + int c = get_byte(ib); + int mode = c >> 4; + int reg = c & 0x0F; + int lit = c & 0x3F; + int tmp = 0; + char buf[16]; switch (mode) { case 0: /* literal */ @@ -348,6 +347,15 @@ get_operand(ib, size) case 9: /* autoincrement deferred */ add_char(ib, DEFERRED); + if (reg == 0x0F) { /* pc: immediate deferred */ + /* + * addresses are always longwords! + */ + tmp = get_long(ib); + add_off(ib, tmp); + break; + } + /* fall through */ case 8: /* autoincrement */ if (reg == 0x0F) { /* pc: immediate ==> special syntax */ switch (size) { @@ -439,8 +447,8 @@ int get_word(ib) inst_buffer *ib; { - int tmp; - char *p = (void *) &tmp; + int tmp; + char *p = (void *) &tmp; *p++ = get_byte(ib); *p++ = get_byte(ib); return (tmp); @@ -450,8 +458,8 @@ int get_long(ib) inst_buffer *ib; { - int tmp; - char *p = (void *) &tmp; + int tmp; + char *p = (void *) &tmp; *p++ = get_byte(ib); *p++ = get_byte(ib); *p++ = get_byte(ib); @@ -462,7 +470,7 @@ get_long(ib) void add_char(ib, c) inst_buffer *ib; - int c; + int c; { *ib->curp++ = c; } @@ -470,18 +478,18 @@ add_char(ib, c) void add_str(ib, s) inst_buffer *ib; - char *s; + char *s; { - while ((*ib->curp++ = *s++)); + while (*ib->curp++ = *s++); *--ib->curp = '\0'; } void add_int(ib, i) inst_buffer *ib; - int i; + int i; { - char buf[32]; + char buf[32]; if (i < 100 && i > -100) sprintf(buf, "%d", i); else @@ -492,9 +500,9 @@ add_int(ib, i) void add_xint(ib, val) inst_buffer *ib; - int val; + int val; { - char buf[32]; + char buf[32]; sprintf(buf, "0x%x", val); add_str(ib, buf); } @@ -502,11 +510,11 @@ add_xint(ib, val) void add_sym(ib, loc) inst_buffer *ib; - int loc; + int loc; { - db_expr_t diff; - db_sym_t sym; - char *symname; + db_expr_t diff; + db_sym_t sym; + char *symname; if (! loc) return; @@ -528,11 +536,11 @@ add_sym(ib, loc) void add_off(ib, loc) inst_buffer *ib; - int loc; + int loc; { - db_expr_t diff; - db_sym_t sym; - char *symname; + db_expr_t diff; + db_sym_t sym; + char *symname; if (!loc) return; diff --git a/sys/arch/vax/vax/db_machdep.c b/sys/arch/vax/vax/db_machdep.c index 317e005abf8..932683e313e 100644 --- a/sys/arch/vax/vax/db_machdep.c +++ b/sys/arch/vax/vax/db_machdep.c @@ -1,4 +1,4 @@ -/* $NetBSD: db_machdep.c,v 1.6 1996/04/08 18:32:33 ragge Exp $ */ +/* $NetBSD: db_machdep.c,v 1.8 1996/10/13 03:35:39 christos Exp $ */ /* * Mach Operating System diff --git a/sys/arch/vax/vax/disksubr.c b/sys/arch/vax/vax/disksubr.c index 411b5b3f1ab..ecb1b062272 100644 --- a/sys/arch/vax/vax/disksubr.c +++ b/sys/arch/vax/vax/disksubr.c @@ -1,4 +1,4 @@ -/* $NetBSD: disksubr.c,v 1.10 1996/05/19 16:44:02 ragge Exp $ */ +/* $NetBSD: disksubr.c,v 1.11 1997/01/11 11:24:51 ragge Exp $ */ /* * Copyright (c) 1982, 1986, 1988 Regents of the University of California. @@ -41,15 +41,18 @@ #include <sys/dkbad.h> #include <sys/disklabel.h> #include <sys/syslog.h> +#include <sys/proc.h> + +#include <vm/vm.h> +#include <vm/vm_kern.h> #include <machine/macros.h> +#include <machine/pte.h> +#include <machine/pcb.h> -/* XXX encoding of disk minor numbers, should be elsewhere... */ -#define dkunit(dev) (minor(dev) >> 3) -#define dkpart(dev) (minor(dev) & 7) -#define dkminor(unit, part) (((unit) << 3) | (part)) +#include <arch/vax/mscp/mscp.h> /* For disk encoding scheme */ -#define b_cylin b_resid +#define b_cylin b_resid int cpu_setdisklabel __P((struct disklabel *, struct disklabel *, u_long, struct cpu_disklabel *)); @@ -67,38 +70,38 @@ bounds_check_with_label(bp, lp, wlabel) struct disklabel *lp; int wlabel; { - struct partition *p = lp->d_partitions + dkpart(bp->b_dev); + struct partition *p = lp->d_partitions + DISKPART(bp->b_dev); int labelsect = lp->d_partitions[2].p_offset; int maxsz = p->p_size, sz = (bp->b_bcount + DEV_BSIZE - 1) >> DEV_BSHIFT; /* overwriting disk label ? */ - if (bp->b_blkno + p->p_offset <= LABELSECTOR + labelsect && + if (bp->b_blkno + p->p_offset <= LABELSECTOR + labelsect && #if LABELSECTOR != 0 - bp->b_blkno + p->p_offset + sz > LABELSECTOR + labelsect && + bp->b_blkno + p->p_offset + sz > LABELSECTOR + labelsect && #endif - (bp->b_flags & B_READ) == 0 && wlabel == 0) { - bp->b_error = EROFS; - goto bad; - } + (bp->b_flags & B_READ) == 0 && wlabel == 0) { + bp->b_error = EROFS; + goto bad; + } /* beyond partition? */ - if (bp->b_blkno < 0 || bp->b_blkno + sz > maxsz) { - /* if exactly at end of disk, return an EOF */ - if (bp->b_blkno == maxsz) { - bp->b_resid = bp->b_bcount; - return(0); - } - /* or truncate if part of it fits */ - sz = maxsz - bp->b_blkno; - if (sz <= 0) { + if (bp->b_blkno < 0 || bp->b_blkno + sz > maxsz) { + /* if exactly at end of disk, return an EOF */ + if (bp->b_blkno == maxsz) { + bp->b_resid = bp->b_bcount; + return(0); + } + /* or truncate if part of it fits */ + sz = maxsz - bp->b_blkno; + if (sz <= 0) { bp->b_error = EINVAL; - goto bad; + goto bad; } - bp->b_bcount = sz << DEV_BSHIFT; - } + bp->b_bcount = sz << DEV_BSHIFT; + } /* calculate cylinder for disksort to order transfers with */ - bp->b_cylin = (bp->b_blkno + p->p_offset) / lp->d_secpercyl; + bp->b_cylin = (bp->b_blkno + p->p_offset) / lp->d_secpercyl; return(1); bad: @@ -227,16 +230,12 @@ cpu_setdisklabel(olp, nlp, openmask, osdep) npp->p_cpg = opp->p_cpg; } } - nlp->d_checksum = 0; - nlp->d_checksum = dkcksum(nlp); + nlp->d_checksum = 0; + nlp->d_checksum = dkcksum(nlp); *olp = *nlp; return (0); } -/* encoding of disk minor numbers, should be elsewhere... */ -#define dkunit(dev) (minor(dev) >> 3) -#define dkminor(unit, part) (((unit) << 3) | (part)) - /* * Write disk label back to device after modification. */ @@ -252,14 +251,14 @@ cpu_writedisklabel(dev, strat, lp, osdep) int labelpart; int error = 0; - labelpart = dkpart(dev); + labelpart = DISKPART(dev); if (lp->d_partitions[labelpart].p_offset != 0) { if (lp->d_partitions[0].p_offset != 0) return (EXDEV); /* not quite right */ labelpart = 0; } bp = geteblk((int)lp->d_secsize); - bp->b_dev = makedev(major(dev), dkminor(dkunit(dev), labelpart)); + bp->b_dev = MAKEDISKDEV(major(dev), DISKUNIT(dev), labelpart); bp->b_blkno = LABELSECTOR; bp->b_bcount = lp->d_secsize; bp->b_flags = B_READ; @@ -284,3 +283,78 @@ done: brelse(bp); return (error); } + +/* + * Print out the name of the device; ex. TK50, RA80. DEC uses a common + * disk type encoding scheme for most of its disks. + */ +void +disk_printtype(unit, type) + int unit, type; +{ + printf(" drive %d: %c%c", unit, MSCP_MID_CHAR(2, type), + MSCP_MID_CHAR(1, type)); + if (MSCP_MID_ECH(0, type)) + printf("%c", MSCP_MID_CHAR(0, type)); + printf("%d\n", MSCP_MID_NUM(type)); +} + +/* + * Be sure that the pages we want to do DMA to is actually there + * by faking page-faults if necessary. If given a map-register address, + * also map it in. + */ +void +disk_reallymapin(bp, map, reg, flag) + struct buf *bp; + struct pte *map; + int reg, flag; +{ + volatile pt_entry_t *io; + pt_entry_t *pte; + struct pcb *pcb; + int pfnum, npf, o, i; + caddr_t addr; + + o = (int)bp->b_un.b_addr & PGOFSET; + npf = btoc(bp->b_bcount + o) + 1; + addr = bp->b_un.b_addr; + + /* + * Get a pointer to the pte pointing out the first virtual address. + * Use different ways in kernel and user space. + */ + if ((bp->b_flags & B_PHYS) == 0) { + pte = kvtopte(addr); + } else { + pcb = bp->b_proc->p_vmspace->vm_pmap.pm_pcb; + pte = uvtopte(addr, pcb); + } + + /* + * When we are doing DMA to user space, be sure that all pages + * we want to transfer to is mapped. WHY DO WE NEED THIS??? + * SHOULDN'T THEY ALWAYS BE MAPPED WHEN DOING THIS??? + */ + for (i = 0; i < (npf - 1); i++) { + if ((pte + i)->pg_pfn == 0) { + int rv; + rv = vm_fault(&bp->b_proc->p_vmspace->vm_map, + (unsigned)addr + i * NBPG, + VM_PROT_READ|VM_PROT_WRITE, FALSE); + if (rv) + panic("DMA to nonexistent page, %d", rv); + } + } + if (map) { + io = &map[reg]; + while (--npf > 0) { + pfnum = pte->pg_pfn; + if (pfnum == 0) + panic("mapin zero entry"); + pte++; + *(int *)io++ = pfnum | flag; + } + *(int *)io = 0; + } +} diff --git a/sys/arch/vax/vax/dzcons.c b/sys/arch/vax/vax/dzcons.c new file mode 100644 index 00000000000..6002bfe446a --- /dev/null +++ b/sys/arch/vax/vax/dzcons.c @@ -0,0 +1,345 @@ +/* $NetBSD: dzcons.c,v 1.2 1996/09/02 06:44:30 mycroft Exp $ */ +/* + * Copyright (c) 1994 Gordon W. Ross + * Copyright (c) 1994 Ludd, University of Lule}, Sweden. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed at Ludd, University of Lule}. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * kd.c,v 1.2 1994/05/05 04:46:51 gwr Exp $ + */ + +#include <sys/param.h> +#include <sys/proc.h> +#include <sys/systm.h> +#include <sys/ioctl.h> +#include <sys/tty.h> +#include <sys/file.h> +#include <sys/conf.h> +#include <sys/device.h> +#include <sys/reboot.h> + +#include <dev/cons.h> + +#include <machine/mtpr.h> +#include <machine/sid.h> +#include <machine/uvax.h> +#include <machine/ka410.h> +#include <machine/../vax/gencons.h> + +volatile unsigned char *ka410_intreq = (void*)KA410_INTREQ; +volatile unsigned char *ka410_intclr = (void*)KA410_INTCLR; +volatile unsigned char *ka410_intmsk = (void*)KA410_INTMSK; + + + +/*----------------------------------------------------------------------*/ + +int +dzcngetc(dev) + dev_t dev; +{ + int c; + int mapen; + int imsk; + + imsk = *ka410_intmsk; /* save interrupt-mask */ + *ka410_intmsk = 0; /* disable console-receive interrupt! */ + +#if 0 + do { + c = get_fp() & 0xFF; /* 0x7F ??? */ + } while (c == 17 || c == 19); /* ignore XON/XOFF */ + + *ka410_intclr = 0x80; /* clear the interrupt request */ + *ka410_intmsk = imsk; /* restore interrupt-mask */ +#else + for (;;) + ; +#endif + + if (c == 13) + c = 10; + return (c); +} + +#define REG(name) short name; short X##name##X; +static volatile struct {/* base address of DZ-controller: 0x200A0000 */ + REG(csr); /* 00 Csr: control/status register */ + REG(rbuf); /* 04 Rbuf/Lpr: receive buffer/line param reg. */ + REG(tcr); /* 08 Tcr: transmit console register */ + REG(tdr); /* 0C Msr/Tdr: modem status reg/transmit data reg */ + REG(lpr0); /* 10 Lpr0: */ + REG(lpr1); /* 14 Lpr0: */ + REG(lpr2); /* 18 Lpr0: */ + REG(lpr3); /* 1C Lpr0: */ +} *dz = (void*)0x200A0000; +#undef REG + +struct tty *dzcn_tty[1]; + +int dzcnparam(); +void dzcnstart(); + +int ka410_consintr_enable __P((void)); + +int +dzcnopen(dev, flag, mode, p) + dev_t dev; + int flag, mode; + struct proc *p; +{ + int unit; + struct tty *tp; + + unit = minor(dev); + if (unit) return ENXIO; + + tp = dzcn_tty[0]; + + tp->t_oproc = dzcnstart; + tp->t_param = dzcnparam; + tp->t_dev = dev; + if ((tp->t_state & TS_ISOPEN) == 0) { + tp->t_state |= TS_WOPEN; + ttychars(tp); + tp->t_iflag = TTYDEF_IFLAG; + tp->t_oflag = TTYDEF_OFLAG; + tp->t_cflag = TTYDEF_CFLAG; + tp->t_lflag = TTYDEF_LFLAG; + tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED; + dzcnparam(tp, &tp->t_termios); + ttsetwater(tp); + } else if (tp->t_state & TS_XCLUDE && p->p_ucred->cr_uid != 0) + return EBUSY; + tp->t_state |= TS_CARR_ON; + ka410_consintr_enable(); /* Turn on interrupts */ + + + return ((*linesw[tp->t_line].l_open)(dev, tp)); +} + +int +dzcnclose(dev, flag, mode, p) + dev_t dev; + int flag, mode; + struct proc *p; +{ + int unit = minor(dev); + struct tty *tp = dzcn_tty[0]; + + (*linesw[tp->t_line].l_close)(tp, flag); + ttyclose(tp); + return (0); +} + +struct tty * +dzcntty(dev) + dev_t dev; +{ + + return dzcn_tty[0]; /* XXX */ +} + +int +dzcnread(dev, uio, flag) + dev_t dev; + struct uio *uio; + int flag; +{ + int unit = minor(dev); + struct tty *tp = dzcn_tty[0]; + + return ((*linesw[tp->t_line].l_read)(tp, uio, flag)); +} + +int +dzcnwrite(dev, uio, flag) + dev_t dev; + struct uio *uio; + int flag; +{ + int unit = minor(dev); + struct tty *tp = dzcn_tty[0]; + + return ((*linesw[tp->t_line].l_write)(tp, uio, flag)); +} + +int +dzcnioctl(dev, cmd, data, flag, p) + dev_t dev; + int cmd; + caddr_t data; + int flag; + struct proc *p; +{ + int error; + int unit = minor(dev); + struct tty *tp = dzcn_tty[0]; + + error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p); + if (error >= 0) + return error; + error = ttioctl(tp, cmd, data, flag, p); + if (error >= 0) return error; + + return ENOTTY; +} + +void +dzcnstart(tp) + struct tty *tp; +{ + struct clist *cl; + int s, ch; + + s = spltty(); + if (tp->t_state & (TS_BUSY|TS_TTSTOP|TS_TIMEOUT)) + goto out; + cl = &tp->t_outq; + + if(cl->c_cc){ + tp->t_state |= TS_BUSY; + ch = getc(cl); + dz->tdr = ch; + } else { + if (tp->t_state & TS_ASLEEP) { + tp->t_state &= ~TS_ASLEEP; + wakeup((caddr_t)cl); + } + selwakeup(&tp->t_wsel); + } + +out: splx(s); +} + +dzcnrint() +{ + struct tty *tp; + int i, j; + + tp = dzcn_tty[0]; + i = dz->rbuf; + +#ifdef DDB + j = kdbrint(i); + + if (j == 1) /* Escape received, just return */ + return; + + if (j == 2) /* Second char wasn't 'D' */ + (*linesw[tp->t_line].l_rint)(27, tp); +#endif + + (*linesw[tp->t_line].l_rint)(i,tp); + return; +} + +void +dzcnstop(tp, flag) + struct tty *tp; + int flag; +{ + +} + +dzcntint() +{ + struct tty *tp; + + tp = dzcn_tty[0]; + tp->t_state &= ~TS_BUSY; + + dzcnstart(tp); +} + +int +dzcnparam(tp, t) + struct tty *tp; + struct termios *t; +{ + /* XXX - These are ignored... */ + tp->t_ispeed = t->c_ispeed; + tp->t_ospeed = t->c_ospeed; + tp->t_cflag = t->c_cflag; + return 0; +} + +void +dzcnprobe(cndev) + struct consdev *cndev; +{ + int i; + + switch (vax_boardtype) { + case VAX_BTYP_410: + case VAX_BTYP_43: + break; + + default: + cndev->cn_pri = CN_DEAD; + return; + } + + for (i = 0; i < nchrdev; i++) + if (cdevsw[i].d_open == dzcnopen) { + cndev->cn_dev = makedev(i,0); + cndev->cn_pri = CN_NORMAL; + return; + } + cndev->cn_pri = CN_DEAD; + return; +} + +int +dzcninit(cndev) + struct consdev *cndev; +{ +} + +dzcnslask() +{ + dzcn_tty[0] = ttymalloc(); +} + +void +dzcnputc(dev,ch) + dev_t dev; + int ch; +{ + int timeout = 1<<15; /* don't hang the machine! */ + while ((dz->csr & 0x8000) == 0) /* Wait until ready */ + if (--timeout < 0) + break; + dz->tdr = ch; /* Put the character */ +} + +conout(str) + char *str; +{ + while (*str) + gencnputc(0, *str++); +} diff --git a/sys/arch/vax/vax/gencons.c b/sys/arch/vax/vax/gencons.c index 63bd67ec238..6139269ce07 100644 --- a/sys/arch/vax/vax/gencons.c +++ b/sys/arch/vax/vax/gencons.c @@ -1,4 +1,4 @@ -/* $NetBSD: gencons.c,v 1.10 1996/04/08 18:32:36 ragge Exp $ */ +/* $NetBSD: gencons.c,v 1.11 1996/09/02 06:44:32 mycroft Exp $ */ /* * Copyright (c) 1994 Gordon W. Ross @@ -68,7 +68,7 @@ void gencninit __P((struct consdev *)); struct tty *gencntty __P((dev_t)); void gencnrint __P((void)); void gencntint __P((void)); -int gencnstop __P((struct tty *, int)); +void gencnstop __P((struct tty *, int)); void gencnslask __P((void)); int @@ -218,12 +218,12 @@ gencnrint() return; } -int +void gencnstop(tp, flag) struct tty *tp; int flag; { - return 0; + } void diff --git a/sys/arch/vax/vax/in_cksum.c b/sys/arch/vax/vax/in_cksum.c index fa336ba344a..6d24740dfc5 100644 --- a/sys/arch/vax/vax/in_cksum.c +++ b/sys/arch/vax/vax/in_cksum.c @@ -1,4 +1,4 @@ -/* $NetBSD: in_cksum.c,v 1.2 1996/04/08 18:32:38 ragge Exp $ */ +/* $NetBSD: in_cksum.c,v 1.4 1996/10/13 03:35:40 christos Exp $ */ /* * Copyright (c) 1988, 1992, 1993 diff --git a/sys/arch/vax/vax/intvec.s b/sys/arch/vax/vax/intvec.s index 8c0939381f2..333f7de0f0a 100644 --- a/sys/arch/vax/vax/intvec.s +++ b/sys/arch/vax/vax/intvec.s @@ -1,4 +1,4 @@ -/* $NetBSD: intvec.s,v 1.19 1996/03/09 23:36:40 ragge Exp $ */ +/* $NetBSD: intvec.s,v 1.20 1996/07/20 18:20:44 ragge Exp $ */ /* * Copyright (c) 1994 Ludd, University of Lule}, Sweden. @@ -38,31 +38,31 @@ #include <machine/pte.h> #include <machine/trap.h> -#define ENTRY(name) \ +#define ENTRY(name) \ .text ; \ .align 2 ; \ .globl name ; \ name /**/: -#define TRAPCALL(namn, typ) \ +#define TRAPCALL(namn, typ) \ ENTRY(namn) ; \ pushl $0 ; \ pushl $typ ; \ jbr trap -#define TRAPARGC(namn, typ) \ +#define TRAPARGC(namn, typ) \ ENTRY(namn) ; \ pushl $typ ; \ jbr trap -#define FASTINTR(namn, rutin) \ +#define FASTINTR(namn, rutin) \ ENTRY(namn) ; \ pushr $0x3f ; \ calls $0,_/**/rutin ; \ popr $0x3f ; \ rei -#define STRAY(scbnr, vecnr) \ +#define STRAY(scbnr, vecnr) \ ENTRY(stray/**/vecnr) ; \ pushr $0x3f ; \ pushl $/**/0x/**/vecnr ; \ @@ -71,7 +71,7 @@ ENTRY(stray/**/vecnr) ; \ popr $0x3f ; \ rei -#define KSTACK 0 +#define KSTACK 0 #define ISTACK 1 #define INTVEC(label,stack) \ .long label+stack; @@ -87,66 +87,66 @@ _rpb: * and move the SCB later to somewhere else. */ - INTVEC(stray00, ISTACK) # Unused., 0 + INTVEC(stray00, ISTACK) # Unused., 0 INTVEC(mcheck, ISTACK) # Machine Check., 4 - INTVEC(invkstk, ISTACK) # Kernel Stack Invalid., 8 - INTVEC(stray0C, ISTACK) # Power Failed., C + INTVEC(invkstk, ISTACK) # Kernel Stack Invalid., 8 + INTVEC(stray0C, ISTACK) # Power Failed., C INTVEC(privinflt, KSTACK) # Privileged/Reserved Instruction. - INTVEC(stray14, ISTACK) # Customer Reserved Instruction, 14 + INTVEC(stray14, ISTACK) # Customer Reserved Instruction, 14 INTVEC(resopflt, KSTACK) # Reserved Operand/Boot Vector(?), 18 INTVEC(resadflt, KSTACK) # # Reserved Address Mode., 1C INTVEC(access_v, KSTACK) # Access Control Violation, 20 INTVEC(transl_v, KSTACK) # Translation Invalid, 24 INTVEC(tracep, KSTACK) # Trace Pending, 28 INTVEC(breakp, KSTACK) # Breakpoint Instruction, 2C - INTVEC(stray30, ISTACK) # Compatibility Exception, 30 + INTVEC(stray30, ISTACK) # Compatibility Exception, 30 INTVEC(arithflt, KSTACK) # Arithmetic Fault, 34 - INTVEC(stray38, ISTACK) # Unused, 38 - INTVEC(stray3C, ISTACK) # Unused, 3C + INTVEC(stray38, ISTACK) # Unused, 38 + INTVEC(stray3C, ISTACK) # Unused, 3C INTVEC(syscall, KSTACK) # main syscall trap, chmk, 40 INTVEC(resopflt, KSTACK) # chme, 44 INTVEC(resopflt, KSTACK) # chms, 48 INTVEC(resopflt, KSTACK) # chmu, 4C - INTVEC(stray50, ISTACK) # System Backplane Exception, 50 + INTVEC(sbiexc, ISTACK) # System Backplane Exception/BIerror, 50 INTVEC(cmrerr, ISTACK) # Corrected Memory Read, 54 - INTVEC(stray58, ISTACK) # System Backplane Alert, 58 + INTVEC(rxcs, ISTACK) # System Backplane Alert/RXCD, 58 INTVEC(sbiflt, ISTACK) # System Backplane Fault, 5C - INTVEC(stray60, ISTACK) # Memory Write Timeout, 60 - INTVEC(stray64, ISTACK) # Unused, 64 - INTVEC(stray68, ISTACK) # Unused, 68 - INTVEC(stray6C, ISTACK) # Unused, 6C - INTVEC(stray70, ISTACK) # Unused, 70 - INTVEC(stray74, ISTACK) # Unused, 74 - INTVEC(stray78, ISTACK) # Unused, 78 - INTVEC(stray7C, ISTACK) # Unused, 7C - INTVEC(stray80, ISTACK) # Unused, 80 - INTVEC(stray84, ISTACK) # Unused, 84 + INTVEC(stray60, ISTACK) # Memory Write Timeout, 60 + INTVEC(stray64, ISTACK) # Unused, 64 + INTVEC(stray68, ISTACK) # Unused, 68 + INTVEC(stray6C, ISTACK) # Unused, 6C + INTVEC(stray70, ISTACK) # Unused, 70 + INTVEC(stray74, ISTACK) # Unused, 74 + INTVEC(stray78, ISTACK) # Unused, 78 + INTVEC(stray7C, ISTACK) # Unused, 7C + INTVEC(stray80, ISTACK) # Unused, 80 + INTVEC(stray84, ISTACK) # Unused, 84 INTVEC(astintr, KSTACK) # Asynchronous Sustem Trap, AST - INTVEC(stray8C, ISTACK) # Unused, 8C - INTVEC(stray90, ISTACK) # Unused, 90 - INTVEC(stray94, ISTACK) # Unused, 94 - INTVEC(stray98, ISTACK) # Unused, 98 - INTVEC(stray9C, ISTACK) # Unused, 9C + INTVEC(stray8C, ISTACK) # Unused, 8C + INTVEC(stray90, ISTACK) # Unused, 90 + INTVEC(stray94, ISTACK) # Unused, 94 + INTVEC(stray98, ISTACK) # Unused, 98 + INTVEC(stray9C, ISTACK) # Unused, 9C INTVEC(softclock,ISTACK) # Software clock interrupt - INTVEC(strayA4, ISTACK) # Unused, A4 - INTVEC(strayA8, ISTACK) # Unused, A8 - INTVEC(strayAC, ISTACK) # Unused, AC - INTVEC(netint, ISTACK) # Network interrupt - INTVEC(strayB4, ISTACK) # Unused, B4 - INTVEC(strayB8, ISTACK) # Unused, B8 - INTVEC(ddbtrap, ISTACK) # Kernel debugger trap, BC + INTVEC(strayA4, ISTACK) # Unused, A4 + INTVEC(strayA8, ISTACK) # Unused, A8 + INTVEC(strayAC, ISTACK) # Unused, AC + INTVEC(netint, ISTACK) # Network interrupt + INTVEC(strayB4, ISTACK) # Unused, B4 + INTVEC(strayB8, ISTACK) # Unused, B8 + INTVEC(ddbtrap, ISTACK) # Kernel debugger trap, BC INTVEC(hardclock,ISTACK) # Interval Timer - INTVEC(strayC4, ISTACK) # Unused, C4 + INTVEC(strayC4, ISTACK) # Unused, C4 INTVEC(emulate, KSTACK) # Subset instruction emulation - INTVEC(strayCC, ISTACK) # Unused, CC - INTVEC(strayD0, ISTACK) # Unused, D0 - INTVEC(strayD4, ISTACK) # Unused, D4 - INTVEC(strayD8, ISTACK) # Unused, D8 - INTVEC(strayDC, ISTACK) # Unused, DC - INTVEC(strayE0, ISTACK) # Unused, E0 - INTVEC(strayE4, ISTACK) # Unused, E4 - INTVEC(strayE8, ISTACK) # Unused, E8 - INTVEC(strayEC, ISTACK) # Unused, EC + INTVEC(strayCC, ISTACK) # Unused, CC + INTVEC(strayD0, ISTACK) # Unused, D0 + INTVEC(strayD4, ISTACK) # Unused, D4 + INTVEC(strayD8, ISTACK) # Unused, D8 + INTVEC(strayDC, ISTACK) # Unused, DC + INTVEC(strayE0, ISTACK) # Unused, E0 + INTVEC(strayE4, ISTACK) # Unused, E4 + INTVEC(strayE8, ISTACK) # Unused, E8 + INTVEC(strayEC, ISTACK) # Unused, EC INTVEC(strayF0, ISTACK) INTVEC(strayF4, ISTACK) INTVEC(consrint, ISTACK) # Console Terminal Recieve Interrupt @@ -164,7 +164,7 @@ _rpb: # _memtest (memtest in C) holds the address to continue execution # at when returning from a intentional test. # -mcheck: .globl mcheck +mcheck: .globl mcheck tstl _cold # Ar we still in coldstart? bneq L4 # Yes. @@ -174,16 +174,16 @@ mcheck: .globl mcheck popr $0x3f addl2 (sp)+,sp - rei + rei L4: addl2 (sp)+,sp # remove info pushed on stack - cmpl _cpunumber, $1 # Is it a 11/780? + cmpl _vax_cputype,$1 # Is it a 11/780? bneq 1f # No... mtpr $0, $PR_SBIFS # Clear SBI fault register brb 2f -1: cmpl _cpunumber, $4 # Is it a 8600? +1: cmpl _vax_cputype,$4 # Is it a 8600? bneq 3f mtpr $0, $PR_EHSR # Clear Error status register @@ -213,13 +213,13 @@ L2: movl (sp), 4(sp) jbr trap - .align 2 -access_v:.globl access_v # Access cntrl viol fault, 24 + .align 2 +access_v:.globl access_v # Access cntrl viol fault, 24 blbs (sp), ptelen pushl $T_ACCFLT jbr L3 -ptelen: movl $T_PTELEN, (sp) # PTE must expand (or send segv) +ptelen: movl $T_PTELEN, (sp) # PTE must expand (or send segv) jbr trap; TRAPCALL(tracep, T_TRCTRAP) @@ -256,9 +256,33 @@ syscall: STRAY(0,44) STRAY(0,48) STRAY(0,4C) - STRAY(0,50) + +ENTRY(sbiexc) + tstl _cold /* Is it ok to get errs during boot??? */ + bneq 1f + pushr $0x3f + pushl $0x50 + pushl $0 + calls $2,_stray + popr $0x3f +1: rei + FASTINTR(cmrerr,cmrerr) - STRAY(0,58) + +ENTRY(rxcs); /* console interrupt from some other processor */ + pushr $0x3f +#if VAX8200 + cmpl $5,_vax_cputype + bneq 1f + calls $0,_rxcdintr + brb 2f +#endif +1: pushl $0x58 + pushl $0 + calls $2,_stray +2: popr $0x3f + rei + ENTRY(sbiflt); moval sbifltmsg, -(sp) calls $1, _panic @@ -373,35 +397,35 @@ _emtable: /* * The following is called with the stack set up as follows: * - * (sp): Opcode - * 4(sp): Instruction PC - * 8(sp): Operand 1 - * 12(sp): Operand 2 - * 16(sp): Operand 3 - * 20(sp): Operand 4 - * 24(sp): Operand 5 - * 28(sp): Operand 6 - * 32(sp): Operand 7 (unused) - * 36(sp): Operand 8 (unused) - * 40(sp): Return PC - * 44(sp): Return PSL + * (sp): Opcode + * 4(sp): Instruction PC + * 8(sp): Operand 1 + * 12(sp): Operand 2 + * 16(sp): Operand 3 + * 20(sp): Operand 4 + * 24(sp): Operand 5 + * 28(sp): Operand 6 + * 32(sp): Operand 7 (unused) + * 36(sp): Operand 8 (unused) + * 40(sp): Return PC + * 44(sp): Return PSL * 48(sp): TOS before instruction * * Each individual routine is called with the stack set up as follows: * - * (sp): Return address of trap handler - * 4(sp): Opcode (will get return PSL) - * 8(sp): Instruction PC - * 12(sp): Operand 1 - * 16(sp): Operand 2 - * 20(sp): Operand 3 - * 24(sp): Operand 4 - * 28(sp): Operand 5 - * 32(sp): Operand 6 - * 36(sp): saved register 11 - * 40(sp): saved register 10 - * 44(sp): Return PC - * 48(sp): Return PSL + * (sp): Return address of trap handler + * 4(sp): Opcode (will get return PSL) + * 8(sp): Instruction PC + * 12(sp): Operand 1 + * 16(sp): Operand 2 + * 20(sp): Operand 3 + * 24(sp): Operand 4 + * 28(sp): Operand 5 + * 32(sp): Operand 6 + * 36(sp): saved register 11 + * 40(sp): saved register 10 + * 44(sp): Return PC + * 48(sp): Return PSL * 52(sp): TOS before instruction * See the VAX Architecture Reference Manual, Section B-5 for more * information. @@ -429,12 +453,12 @@ noemulate: #endif .word 0xffff # "reserved instruction fault" - .globl _intrnames, _eintrnames, _intrcnt, _eintrcnt + .globl _intrnames, _eintrnames, _intrcnt, _eintrcnt _intrnames: - .long 0 + .long 0 _eintrnames: _intrcnt: - .long 0 + .long 0 _eintrcnt: .data diff --git a/sys/arch/vax/vax/ka410.c b/sys/arch/vax/vax/ka410.c new file mode 100644 index 00000000000..58248739f3e --- /dev/null +++ b/sys/arch/vax/vax/ka410.c @@ -0,0 +1,249 @@ +/* $NetBSD: ka410.c,v 1.3 1996/10/13 03:35:42 christos Exp $ */ +/* + * Copyright (c) 1996 Ludd, University of Lule}, Sweden. + * All rights reserved. + * + * This code is derived from software contributed to Ludd by Bertram Barth. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed at Ludd, University of + * Lule}, Sweden and its contributors. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + + +#include <sys/param.h> +#include <sys/types.h> +#include <sys/device.h> +#include <sys/kernel.h> +#include <vm/vm.h> +#include <vm/vm_kern.h> + +#include <machine/pte.h> +#include <machine/mtpr.h> +#include <machine/sid.h> +#include <machine/pmap.h> +#include <machine/nexus.h> +#include <machine/uvax.h> +#include <machine/ka410.h> +#include <machine/clock.h> + +/* + * Maybe all these variables/functions should be static or "integrate" + */ +void ka410_conf __P((struct device*, struct device*, void*)); +void ka410_memenable __P((struct sbi_attach_args *, struct device *)); +void ka410_steal_pages __P((void)); + +#ifdef notyet +void ka410_memerr __P((void)); +int ka410_mchk __P((caddr_t)); +#endif + +struct ka410_cpu *ka410_cpuptr = (void*)KA410_CPU_BASE; +struct ka410_clock *ka410_clkptr = (void*)KA410_WAT_BASE; + +extern int uVAX_fillmap __P((struct uc_map *)); + +struct uc_map ka410_map[] = { + { KA410_CFGTST, KA410_CFGTST+1023, 1024, 0 }, + { KA410_ROM_BASE, KA410_ROM_END, KA410_ROM_SIZE, 0 }, + { KA410_CPU_BASE, KA410_CPU_END, KA410_CPU_SIZE, 0 }, + { KA410_NWA_BASE, KA410_NWA_END, KA410_NWA_SIZE, 0 }, + { KA410_SER_BASE, KA410_SER_END, KA410_SER_SIZE, 0 }, + { KA410_WAT_BASE, KA410_WAT_END, KA410_WAT_SIZE, 0 }, +#if 0 + { KA410_SCS_BASE, KA410_SCS_END, KA410_SCS_SIZE, 0 }, +#else + { 0x200C0000, 0x200C01FF, 0x200, 0 }, +#endif + { KA410_LAN_BASE, KA410_LAN_END, KA410_LAN_SIZE, 0 }, + { KA410_CUR_BASE, KA410_CUR_END, KA410_CUR_SIZE, 0 }, + { KA410_DMA_BASE, KA410_DMA_END, KA410_DMA_SIZE, 0 }, + /* + * there's more to come, eg. framebuffers (mono + GPX) + */ + {0, 0, 0, 0}, +}; + +int +ka410_setup(uc,flags) + struct uvax_calls *uc; + int flags; +{ + uc->uc_name = "ka410"; + + uc->uc_phys2virt = NULL; /* ka410_mapaddr; */ + uc->uc_physmap = ka410_map; /* ptv_map ? p2v_map */ + + uc->uc_steal_pages = ka410_steal_pages; + uc->uc_conf = ka410_conf; + uc->uc_clkread = ka410_clkread; + uc->uc_clkwrite = ka410_clkwrite; + +#ifdef notyet + uc->uc_memerr = ka410_memerr; + uc->uc_mchk = ka410_mchk; +#endif + + uc->uc_intreq = (void*)KA410_INTREQ; + uc->uc_intclr = (void*)KA410_INTCLR; + uc->uc_intmsk = (void*)KA410_INTMSK; + + uc->uc_busTypes = VAX_VSBUS; +} + +void +ka410_conf(parent, self, aux) + struct device *parent, *self; + void *aux; +{ + extern char cpu_model[]; + + if (vax_confdata & 0x80) /* MSB in CFGTST */ + strcpy(cpu_model,"MicroVAX 2000"); + else + strcpy(cpu_model,"VAXstation 2000"); + + printf(": %s\n", cpu_model); +} + + +/* + * + */ +u_long le_iomem; /* base addr of RAM -- CPU's view */ +u_long le_ioaddr; /* base addr of RAM -- LANCE's view */ + +void +ka410_steal_pages() +{ + extern vm_offset_t avail_start, virtual_avail, avail_end; + int junk; + + int i; + struct { + u_long :2; + u_long data:8; + u_long :22; + } *p; + int *srp; /* Scratch Ram */ + char *q = (void*)&srp; + + srp = NULL; + p = (void*)KA410_SCR; + for (i=0; i<4; i++) { + printf("p[%d] = %x, ", i, p[i].data); + q[i] = p[i].data; + } + p = (void*)KA410_SCRLEN; + printf("\nlen = %d\n", p->data); + printf("srp = 0x%x\n", srp); + + for (i=0; i<0x2; i++) { + printf("%x:0x%x ", i*4, srp[i]); + if ((i & 0x07) == 0x07) + printf("\n"); + } + printf("\n"); + + /* + * SCB is already copied/initialized at addr avail_start + * by pmap_bootstrap(), but it's not yet mapped. Thus we use + * the MAPPHYS() macro to reserve these two pages and to + * perform the mapping. The mapped address is assigned to junk. + */ + MAPPHYS(junk, 2, VM_PROT_READ|VM_PROT_WRITE); + + /* + * At top of physical memory there are some console-prom and/or + * restart-specific data. Make this area unavailable. + */ + avail_end -= 10 * NBPG; + + /* + * If we need to map physical areas also, we can decrease avail_end + * (the highest available memory-address), copy the stuff into the + * gap between and use pmap_map to map it... + * + * Don't use the MAPPHYS macro here, since this uses and changes(!) + * the value of avail_start. Use MAPVIRT even if it's name misleads. + */ + avail_end -= 10 * NBPG; /* paranoid: has been done before */ + + avail_end = (int)srp; + + avail_end &= ~0xffff; /* make avail_end 64K-aligned */ + avail_end -= (64 * 1024); /* steal 64K for LANCE's iobuf */ + le_ioaddr = avail_end; /* ioaddr=phys, iomem=virt */ + MAPVIRT(le_iomem, (64 * 1024)/NBPG); + pmap_map((vm_offset_t)le_iomem, le_ioaddr, le_ioaddr + 0xffff, + VM_PROT_READ|VM_PROT_WRITE); + + printf("le_iomem: %x, le_ioaddr: %x, srp: %x, avail_end: %x\n", + le_iomem, le_ioaddr, srp, avail_end); + + /* + * VAXstation 2000 and MicroVAX 2000: + * since there's no bus, we have to map in anything which + * could be neccessary/used/interesting... + * + * MAPVIRT(ptr,count) reserves a virtual area with the requested size + * and initializes ptr to point at this location + * pmap_map(ptr,...) inserts a pair of virtual/physical addresses + * into the system maptable (Sysmap) + */ + uVAX_fillmap(ka410_map); + + /* + * Clear restart and boot in progress flags + * in the CPMBX. (ie. clear bits 4 and 5) + */ + ka410_clkptr->cpmbx = (ka410_clkptr->cpmbx & ~0x30); + + /* + * Enable memory parity error detection and clear error bits. + */ + ka410_cpuptr->ka410_mser = 1; + /* (UVAXIIMSER_PEN | UVAXIIMSER_MERR | UVAXIIMSER_LEB); */ + + /* + * MM is not yet enabled, thus we still used the physical addresses, + * but before leaving this routine, we need to reset them to virtual. + */ + ka410_cpuptr = (void*)uvax_phys2virt(KA410_CPU_BASE); + ka410_clkptr = (void*)uvax_phys2virt(KA410_WAT_BASE); + +} +/* + * define what we need and overwrite the uVAX_??? names + */ + +#define uVAX_clock ka410_clock +#define uVAX_clkptr ka410_clkptr +#define uVAX_clkread ka410_clkread +#define uVAX_clkwrite ka410_clkwrite + +#include <arch/vax/vax/uvax_proto.c> diff --git a/sys/arch/vax/vax/ka43.c b/sys/arch/vax/vax/ka43.c new file mode 100644 index 00000000000..814f8e82bea --- /dev/null +++ b/sys/arch/vax/vax/ka43.c @@ -0,0 +1,444 @@ +/* $NetBSD: ka43.c,v 1.3 1996/10/13 03:35:43 christos Exp $ */ +/* + * Copyright (c) 1996 Ludd, University of Lule}, Sweden. + * All rights reserved. + * + * This code is derived from software contributed to Ludd by Bertram Barth. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed at Ludd, University of + * Lule}, Sweden and its contributors. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include <sys/param.h> +#include <sys/types.h> +#include <sys/device.h> +#include <sys/kernel.h> + +#include <vm/vm.h> +#include <vm/vm_kern.h> + +#include <machine/pte.h> +#include <machine/mtpr.h> +#include <machine/sid.h> +#include <machine/pmap.h> +#include <machine/nexus.h> +#include <machine/uvax.h> +#include <machine/ka43.h> +#include <machine/clock.h> +#include <machine/ka650.h> /* cache ??? */ + +#define xtrace(x) + +void ka43_conf __P((struct device*, struct device*, void*)); +void ka43_steal_pages __P((void)); + +void ka43_memerr __P((void)); +int ka43_mchk __P((caddr_t)); + +struct ka43_cpu *ka43_cpuptr = (void*)KA43_CPU_BASE; +struct ka43_clock *ka43_clkptr = (void*)KA43_WAT_BASE; + +extern int uVAX_fillmap __P((struct uc_map *)); + +struct uc_map ka43_map[] = { + { KA43_CFGTST, KA43_CFGTST, 4, 0 }, + { KA43_ROM_BASE, KA43_ROM_END, KA43_ROM_SIZE, 0 }, + { KA43_CPU_BASE, KA43_CPU_END, KA43_CPU_SIZE, 0 }, + { KA43_CT2_BASE, KA43_CT2_END, KA43_CT2_SIZE, 0 }, + { KA43_CH2_CREG, KA43_CH2_CREG, 4, 0 }, + { KA43_NWA_BASE, KA43_NWA_END, KA43_NWA_SIZE, 0 }, + { KA43_SER_BASE, KA43_SER_END, KA43_SER_SIZE, 0 }, + { KA43_WAT_BASE, KA43_WAT_END, KA43_WAT_SIZE, 0 }, + { KA43_SCS_BASE, KA43_SCS_END, KA43_SCS_SIZE, 0 }, + { KA43_LAN_BASE, KA43_LAN_END, KA43_LAN_SIZE, 0 }, + { KA43_CUR_BASE, KA43_CUR_END, KA43_CUR_SIZE, 0 }, + { KA43_DMA_BASE, KA43_DMA_END, KA43_DMA_SIZE, 0 }, + { KA43_VME_BASE, KA43_VME_END, KA43_VME_SIZE, 0 }, + /* + * there's more to come, eg. framebuffers (GPX/SPX) + */ + {0, 0, 0, 0}, +}; + +#define CH1_BITS \ + "\020\015BCHIT\014BUSERR\013PPERR\012DPERR\011TPERR\010TRAP1" \ + "\007TRAP2\006INTR\005HIT\004REFRESH\003FLUSH\002ENABLE\001FORCEHIT" + +#define CH2_BITS \ + "\020\010TPE\007DPE\006MISS\005DIRTY\004CERR\003LERR\002SERR\001ENAB" + +void +ka43_memerr() +{ + int mapen; + int *ch2reg; + + printf("memory error!\n"); + printf("primary cache status: %b\n", mfpr(PR_PCSTS), CH1_BITS); + + mapen = mfpr(PR_MAPEN); + if (mapen) + ch2reg = (void*)uvax_phys2virt(KA43_CH2_CREG); + else + ch2reg = (void*)KA43_CH2_CREG; + printf("secondary cache status: %b\n", *ch2reg, CH2_BITS); +} + +static char *mcc43[] = { + "no error (0)", + "FPA signalled protocoll error", + "FPA signalled illegal opcode", + "FPA detected parity error", + "FPA returned unknown status", + "FPA result has parity error", + "unused (6)", + "unused (7)", + "MMU error (TLB miss)", + "MMU error (TLB hit)", + "HW interrupt at unused IPL", + "impossible microcode state", + "undefined trap code (i-box)", + "undefined control store address", + "unused (14)", + "unused (15)", + "PC tag or data parity error", + "data bus parity error", + "data bus error (NXM)", + "undefined data bus state", +}; + +int +ka43_mchk(addr) + caddr_t addr; +{ + struct { + int bcount; /* byte count (0x18) */ + int mcc; /* "R"-flag and machine check code */ + int mrva; /* most recent virtual address */ + int viba; /* contents of VIBA register */ + int sisr; /* ICCS bit 6 and SISR bits 15:0 */ + int isd; /* internal state */ + int scr; /* shift count register */ + int pc; /* program counter */ + int psl; /* processor status longword */ + } *p = (void*)addr; + + printf("machine check: 0x%x\n", p->mcc); + printf("reason: %s\n", mcc43[p->mcc & 0xff]); + + printf("bcount:0x%x, check-code:0x%x, virtaddr:0x%x\n", + p->bcount, p->mcc, p->mrva); + printf("pc:0x%x, psl:0x%x, viba: %x, state: %x\n", + p->pc, p->psl, p->viba, p->isd); + + return (-1); +} + +int +ka43_setup(uc,flags) + struct uvax_calls *uc; + int flags; +{ + uc->uc_name = "ka43"; + + uc->uc_phys2virt = NULL; + uc->uc_physmap = ka43_map; + + uc->uc_steal_pages = ka43_steal_pages; + uc->uc_conf = ka43_conf; + uc->uc_clkread = ka43_clkread; + uc->uc_clkwrite = ka43_clkwrite; + + uc->uc_memerr = ka43_memerr; + uc->uc_mchk = ka43_mchk; + + uc->uc_intreq = (void*)KA43_INTREQ; + uc->uc_intclr = (void*)KA43_INTCLR; + uc->uc_intmsk = (void*)KA43_INTMSK; + + uc->uc_busTypes = VAX_VSBUS; +} + +ka43_discache() +{ + int *ctag; + int *creg; + int mapen; + int i; + + xtrace(("ka43_discache()\n")); + return (0); + + /* + * first disable primary cache + */ +#if 0 + mtpr(0, PR_PCSTS); + mtpr(0, PR_PCERR); + mtpr(0, PR_PCIDX); + mtpr(0, PR_PCTAG); +#else + i = mfpr(PR_PCSTS); + mtpr((i & ~2), PR_PCSTS); + printf("pcsts: %x --> %x\n", i, mfpr(PR_PCSTS)); +#endif + /* + * now secondary cache + */ + mapen = mfpr(PR_MAPEN); + if (mapen) { + ctag = (void*)uvax_phys2virt(KA43_CT2_BASE); + creg = (void*)uvax_phys2virt(KA43_CH2_CREG); + } else { + ctag = (void*)KA43_CT2_BASE; + creg = (void*)KA43_CH2_CREG; + } + i = *creg; + *creg = (i & ~1); + printf("creg: %x --> %x\n", i, *creg); + + xtrace(("ka43_discache() done.\n")); +} + +ka43_encache() +{ + int *ctag; + int *creg; + int mapen; + int i; + + xtrace(("ka43_encache()\n")); + + ka43_discache(); + + /* + * first enable primary cache + */ + printf("P-0"); + i = mfpr(PR_PCSTS); + mtpr((i & ~2), PR_PCSTS); + mtpr(0, PR_PCSTS); + printf("P-1"); +#if 1 + mtpr(KA43_PCS_ENABLE | KA43_PCS_FLUSH | KA43_PCS_REFRESH, PR_PCSTS); +#else + mtpr(KA43_PCS_ENABLE, PR_PCSTS); +#endif + printf("P-2"); + + /* + * now secondary cache + */ + mapen = mfpr(PR_MAPEN); + if (mapen) { + ctag = (void*)uvax_phys2virt(KA43_CT2_BASE); + creg = (void*)uvax_phys2virt(KA43_CH2_CREG); + } else { + ctag = (void*)KA43_CT2_BASE; + creg = (void*)KA43_CH2_CREG; + } + printf("ctag: %x, creg: %x\n", ctag, creg); + printf("S-1"); + i = *creg; + printf("creg=[%x] ", *creg); +#if 0 + *creg = (i & ~1); + printf("creg=[%x] ", *creg); + printf("S-2"); + for (i = 0; i < KA43_CT2_SIZE; i += 4) /* Quadword entries */ + ctag[i/4] = 0; /* reset lower half */ + printf("S-3"); + i = *creg; + printf("creg=[%x] ", *creg); + *creg = (i & ~1); + printf("creg=[%x] ", *creg); + printf("S-4"); + /* *creg = 1; */ + printf("S-5"); +#endif + xtrace(("ka43_encache() done.\n")); + + printf("primary cache status: %b\n", mfpr(PR_PCSTS), CH1_BITS); + printf("secondary cache status: %b\n", *creg, CH2_BITS); +} + +void +ka43_conf(parent, self, aux) + struct device *parent, *self; + void *aux; +{ + extern char cpu_model[]; + extern int vax_siedata; + + if (vax_siedata & 0x02) /* "single-user" flag */ + strcpy(cpu_model,"VAXstation 3100 model 76"); + else if (vax_siedata & 0x01) /* "multiuser" flag */ + strcpy(cpu_model,"MicroVAX 3100 model 76(?)"); + else + strcpy(cpu_model, "unknown KA43 board"); + + printf(": %s\n", cpu_model); + + ka43_encache(); +} + + +/* + * + */ +u_long le_iomem; /* base addr of RAM -- CPU's view */ +u_long le_ioaddr; /* base addr of RAM -- LANCE's view */ + +void +ka43_steal_pages() +{ + extern vm_offset_t avail_start, virtual_avail, avail_end; + int junk; + int i; + struct { + u_long :2; + u_long data:8; + u_long :22; + } *p; + int *srp; /* Scratch Ram */ + int *pctl; /* parity control register */ + char *q = (void*)&srp; + char line[20]; + + ka43_encache(); + + pctl = (void*)KA43_PARCTL; + printf("parctl: 0x%x\n", *pctl); +#if 0 + *pctl = KA43_PCTL_DPEN | KA43_PCTL_CPEN; +#else + *pctl = KA43_PCTL_CPEN; +#endif + printf("new value for parctl: "); + gets(line); + *pctl = *line - '0'; + printf("parctl: 0x%x\n", *pctl); + + srp = NULL; + p = (void*)KA43_SCR; + for (i=0; i<4; i++) { + printf("p[%d] = %x, ", i, p[i].data); + q[i] = p[i].data; + } + p = (void*)KA43_SCRLEN; + printf("\nlen = %d\n", p->data); + printf("srp = 0x%x\n", srp); + + for (i=0; i<0x2; i++) { + printf("%x:0x%x ", i*4, srp[i]); + if ((i & 0x07) == 0x07) + printf("\n"); + } + printf("\n"); + + printf ("ka43_steal_pages: avail_end=0x%x\n", avail_end); + + /* + * SCB is already copied/initialized at addr avail_start + * by pmap_bootstrap(), but it's not yet mapped. Thus we use + * the MAPPHYS() macro to reserve these two pages and to + * perform the mapping. The mapped address is assigned to junk. + */ + MAPPHYS(junk, 2, VM_PROT_READ|VM_PROT_WRITE); + + /* + * At top of physical memory there are some console-prom and/or + * restart-specific data. Make this area unavailable. + */ +#if 1 + avail_end -= 10 * NBPG; +#endif + + /* + * If we need to map physical areas also, we can decrease avail_end + * (the highest available memory-address), copy the stuff into the + * gap between and use pmap_map to map it... + * + * Don't use the MAPPHYS macro here, since this uses and changes(!) + * the value of avail_start. Use MAPVIRT even if it's name misleads. + */ + avail_end &= ~0xffff; + avail_end -= (64 * 1024); + + avail_end = 0xf00000; + le_ioaddr = 0xf40000; + + MAPVIRT(le_iomem, (64 * 1024)/NBPG); + pmap_map((vm_offset_t)le_iomem, le_ioaddr, le_ioaddr + 0xffff, + VM_PROT_READ|VM_PROT_WRITE); + + if (1 || le_ioaddr > 0xffffff) { + le_ioaddr &= 0xffffff; + *pctl |= KA43_PCTL_DMA; + } + printf("le_iomem: %x, le_ioaddr: %x, parctl:%x\n", + le_iomem, le_ioaddr, *pctl); + + /* + * now map in anything listed in ka43_map... + */ + uVAX_fillmap(ka43_map); + + /* + * Clear restart and boot in progress flags in the CPMBX. + */ + ka43_clkptr->cpmbx = ka43_clkptr->cpmbx & 0xF0; + + /* + * Enable memory parity error detection and clear error bits. + */ + ka43_cpuptr->ka43_mser = 0x01; + /* (UVAXIIMSER_PEN | UVAXIIMSER_MERR | UVAXIIMSER_LEB); */ + + /* + * MM is not yet enabled, thus we still used the physical addresses, + * but before leaving this routine, we need to reset them to virtual. + */ + ka43_cpuptr = (void*)uvax_phys2virt(KA43_CPU_BASE); + ka43_clkptr = (void*)uvax_phys2virt(KA43_WAT_BASE); + + printf ("steal_pages done.\n"); +} + +/* + * define what we need and overwrite the uVAX_??? names + */ + +#define NEED_UVAX_GENCLOCK +#define NEED_UVAX_PROTOCLOCK + +#define uVAX_clock ka43_clock +#define uVAX_clkptr ka43_clkptr +#define uVAX_clkread ka43_clkread +#define uVAX_clkwrite ka43_clkwrite +#define uVAX_genclock ka43_genclock + +#include <arch/vax/vax/uvax_proto.c> diff --git a/sys/arch/vax/vax/ka630.c b/sys/arch/vax/vax/ka630.c new file mode 100644 index 00000000000..32121491ecf --- /dev/null +++ b/sys/arch/vax/vax/ka630.c @@ -0,0 +1,193 @@ +/* $NetBSD: ka630.c,v 1.4 1996/10/13 03:35:44 christos Exp $ */ +/*- + * Copyright (c) 1982, 1988, 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)ka630.c 7.8 (Berkeley) 5/9/91 + */ + +#include <sys/param.h> +#include <sys/types.h> +#include <sys/device.h> +#include <sys/kernel.h> +#include <sys/time.h> + +#include <vm/vm.h> +#include <vm/vm_kern.h> + +#include <machine/pte.h> +#include <machine/mtpr.h> +#include <machine/sid.h> +#include <machine/pmap.h> +#include <machine/nexus.h> +#include <machine/uvax.h> +#include <machine/ka630.h> +#include <machine/clock.h> + +struct uvaxIIcpu *uvaxIIcpu_ptr; + +struct ka630clock *ka630_clkptr = KA630CLK; + +static void ka630_conf __P((struct device *, struct device *, void *)); +static void ka630_memerr __P((void)); +static int ka630_mchk __P((caddr_t)); +static void ka630_steal_pages __P((void)); + + +int +ka630_setup(uc,flags) + struct uvax_calls *uc; + int flags; +{ + uc->uc_name = "ka630"; + + uc->uc_phys2virt = NULL; + uc->uc_physmap = NULL; /* ptv_map ? p2v_map */ + + uc->uc_steal_pages = ka630_steal_pages; + uc->uc_conf = ka630_conf; + uc->uc_clkread = ka630_clkread; + uc->uc_clkwrite = ka630_clkwrite; + +#ifdef notyet + uc->uc_memerr = ka630_memerr; + uc->uc_mchk = ka630_mchk; +#endif + + uc->uc_busTypes = VAX_UNIBUS; +} + +/* + * uvaxII_conf() is called by cpu_attach to do the cpu_specific setup. + */ +void +ka630_conf(parent, self, aux) + struct device *parent, *self; + void *aux; +{ + extern char cpu_model[]; + + strcpy(cpu_model,"MicroVAX II"); + printf(": %s\n", cpu_model); +} + +/* log crd errors */ +uvaxII_memerr() +{ + printf("memory err!\n"); +} + +#define NMC78032 10 +char *mc78032[] = { + 0, "immcr (fsd)", "immcr (ssd)", "fpu err 0", + "fpu err 7", "mmu st(tb)", "mmu st(m=0)", "pte in p0", + "pte in p1", "un intr id", +}; + +struct mc78032frame { + int mc63_bcnt; /* byte count == 0xc */ + int mc63_summary; /* summary parameter */ + int mc63_mrvaddr; /* most recent vad */ + int mc63_istate; /* internal state */ + int mc63_pc; /* trapped pc */ + int mc63_psl; /* trapped psl */ +}; + +uvaxII_mchk(cmcf) + caddr_t cmcf; +{ + register struct mc78032frame *mcf = (struct mc78032frame *)cmcf; + register u_int type = mcf->mc63_summary; + + printf("machine check %x", type); + if (type < NMC78032 && mc78032[type]) + printf(": %s", mc78032[type]); + printf("\n\tvap %x istate %x pc %x psl %x\n", + mcf->mc63_mrvaddr, mcf->mc63_istate, + mcf->mc63_pc, mcf->mc63_psl); + if (uvaxIIcpu_ptr && uvaxIIcpu_ptr->uvaxII_mser & UVAXIIMSER_MERR) { + printf("\tmser=0x%x ", uvaxIIcpu_ptr->uvaxII_mser); + if (uvaxIIcpu_ptr->uvaxII_mser & UVAXIIMSER_CPUE) + printf("page=%d", uvaxIIcpu_ptr->uvaxII_cear); + if (uvaxIIcpu_ptr->uvaxII_mser & UVAXIIMSER_DQPE) + printf("page=%d", uvaxIIcpu_ptr->uvaxII_dear); + printf("\n"); + } + return (-1); +} + +void +ka630_steal_pages() +{ + extern vm_offset_t avail_start, virtual_avail, avail_end; + int junk; + + /* + * MicroVAX II: get 10 pages from top of memory, + * map in Qbus map registers, cpu and clock registers. + */ + avail_end -= 10; + + MAPPHYS(junk, 2, VM_PROT_READ|VM_PROT_WRITE); + MAPVIRT(nexus, btoc(0x400000)); + pmap_map((vm_offset_t)nexus, 0x20088000, 0x20090000, + VM_PROT_READ|VM_PROT_WRITE); + + MAPVIRT(uvaxIIcpu_ptr, 1); + pmap_map((vm_offset_t)uvaxIIcpu_ptr, (vm_offset_t)UVAXIICPU, + (vm_offset_t)UVAXIICPU + NBPG, VM_PROT_READ|VM_PROT_WRITE); + + MAPVIRT(ka630_clkptr, 1); + pmap_map((vm_offset_t)ka630_clkptr, (vm_offset_t)KA630CLK, + (vm_offset_t)KA630CLK + NBPG, VM_PROT_READ|VM_PROT_WRITE); + + /* + * Clear restart and boot in progress flags + * in the CPMBX. + / + ka630clk_ptr->cpmbx = (ka630clk_ptr->cpmbx & KA630CLK_LANG); + + /* + * Enable memory parity error detection and clear error bits. + */ + uvaxIIcpu_ptr->uvaxII_mser = (UVAXIIMSER_PEN | UVAXIIMSER_MERR | + UVAXIIMSER_LEB); + +} +#define uVAX_gettodr ka630_gettodr +#define uVAX_settodr ka630_settodr +#define uVAX_clkptr ka630_clkptr +#define uVAX_genclock ka630_genclock +#define uVAX_clock ka630clock +#define uVAX_clkread ka630_clkread +#define uVAX_clkwrite ka630_clkwrite + +#include <arch/vax/vax/uvax_proto.c> diff --git a/sys/arch/vax/vax/ka650.c b/sys/arch/vax/vax/ka650.c index be709787e56..e4a798c90f5 100644 --- a/sys/arch/vax/vax/ka650.c +++ b/sys/arch/vax/vax/ka650.c @@ -1,4 +1,4 @@ -/* $NetBSD: ka650.c,v 1.3 1996/04/08 18:32:41 ragge Exp $ */ +/* $NetBSD: ka650.c,v 1.7 1997/01/11 11:31:57 ragge Exp $ */ /* * Copyright (c) 1988 The Regents of the University of California. * All rights reserved. @@ -80,6 +80,7 @@ uvaxIII_conf(parent, self, aux) * check which here. but that later... */ strcpy(cpu_model,"MicroVAX III"); + printf(": %s\n", cpu_model); ka650encache(); if (ctob(physmem) > ka650merr_ptr->merr_qbmbr) { printf("physmem(0x%x) > qbmbr(0x%x)\n", @@ -131,13 +132,6 @@ uvaxIII_steal_pages() subtyp = *jon; } -int -uvaxIII_clock() -{ - mtpr(0x40, PR_ICCS); /* Start clock and enable interrupt */ - return 1; -} - void uvaxIII_memerr() { @@ -241,9 +235,9 @@ uvaxIII_mchk(cmcf) } if (time.tv_sec - i < 7) { ka650discache(); - printf(" parity error: cacheing disabled\n"); + printf(" parity error: cacheing disabled\n"); } else { - printf(" parity error: flushing cache\n"); + printf(" parity error: flushing cache\n"); ka650encache(); } /* diff --git a/sys/arch/vax/vax/ka750.c b/sys/arch/vax/vax/ka750.c index fbcf608c377..222469672e9 100644 --- a/sys/arch/vax/vax/ka750.c +++ b/sys/arch/vax/vax/ka750.c @@ -1,4 +1,4 @@ -/* $NetBSD: ka750.c,v 1.12 1996/04/08 18:32:42 ragge Exp $ */ +/* $NetBSD: ka750.c,v 1.17 1996/10/13 03:35:48 christos Exp $ */ /*- * Copyright (c) 1982, 1986, 1988 The Regents of the University of California. @@ -34,7 +34,7 @@ * SUCH DAMAGE. * * @(#)ka750.c 7.4 (Berkeley) 5/9/91 - * @(#)autoconf.c 7.20 (Berkeley) 5/9/91 + * @(#)autoconf.c 7.20 (Berkeley) 5/9/91 */ #include <sys/param.h> @@ -48,8 +48,10 @@ #include <machine/ka750.h> #include <machine/pte.h> #include <machine/cpu.h> +#include <machine/sid.h> #include <machine/mtpr.h> #include <machine/scb.h> + #include <vax/uba/ubavar.h> #include <vax/uba/ubareg.h> @@ -60,14 +62,14 @@ void ctuattach __P((void)); */ void ka750_conf(parent, self, aux) - struct device *parent, *self; - void *aux; + struct device *parent, *self; + void *aux; { extern char cpu_model[]; strcpy(cpu_model,"VAX 11/750"); printf(": 11/750, hardware rev %d, ucode rev %d\n", - V750HARDW(cpu_type), V750UCODE(cpu_type)); + V750HARDW(vax_cpudata), V750UCODE(vax_cpudata)); printf("%s: ", self->dv_xname); if (mfpr(PR_ACCS) & 255) { printf("FPA present, enabling.\n"); @@ -79,28 +81,30 @@ ka750_conf(parent, self, aux) ctuattach(); } -/* - * ka750_clock() makes the 11/750 interrupt clock and todr - * register start counting. - */ +static int ka750_memmatch __P((struct device *, void *, void *)); +static void ka750_memenable __P((struct device *, struct device *, void *)); + +struct cfattach mem_cmi_ca = { + sizeof(struct device), ka750_memmatch, ka750_memenable +}; + int -ka750_clock() +ka750_memmatch(parent, gcf, aux) + struct device *parent; + void *gcf, *aux; { + struct sbi_attach_args *sa = (struct sbi_attach_args *)aux; + struct cfdata *cf = gcf; - mtpr(-10000, PR_NICR); /* Load in count register */ - mtpr(0x800000d1, PR_ICCS); /* Start clock and enable interrupt */ - if (mfpr(PR_TODR)) { - /* todr running */ + if ((cf->cf_loc[0] != sa->nexnum) && (cf->cf_loc[0] > -1)) + return 0; + + if (sa->type != NEX_MEM16) return 0; - } else { - /* Start TODR register. */ - mtpr(1, PR_TODR); - return 1; - } + return 1; } - extern volatile caddr_t mcraddr[]; struct mcr750 { @@ -109,26 +113,27 @@ struct mcr750 { int mc_inf; /* info bits */ }; -#define M750_ICRD 0x10000000 /* inhibit crd interrupts, in [1] */ -#define M750_UNCORR 0xc0000000 /* uncorrectable error, in [0] */ -#define M750_CORERR 0x20000000 /* correctable error, in [0] */ +#define M750_ICRD 0x10000000 /* inhibit crd interrupts, in [1] */ +#define M750_UNCORR 0xc0000000 /* uncorrectable error, in [0] */ +#define M750_CORERR 0x20000000 /* correctable error, in [0] */ -#define M750_INH(mcr) ((mcr)->mc_inh = 0) -#define M750_ENA(mcr) ((mcr)->mc_err = (M750_UNCORR|M750_CORERR), \ +#define M750_INH(mcr) ((mcr)->mc_inh = 0) +#define M750_ENA(mcr) ((mcr)->mc_err = (M750_UNCORR|M750_CORERR), \ (mcr)->mc_inh = M750_ICRD) -#define M750_ERR(mcr) ((mcr)->mc_err & (M750_UNCORR|M750_CORERR)) +#define M750_ERR(mcr) ((mcr)->mc_err & (M750_UNCORR|M750_CORERR)) -#define M750_SYN(err) ((err) & 0x7f) -#define M750_ADDR(err) (((err) >> 9) & 0x7fff) +#define M750_SYN(err) ((err) & 0x7f) +#define M750_ADDR(err) (((err) >> 9) & 0x7fff) /* enable crd interrupts */ void -ka750_memenable(sa,self) - struct sbi_attach_args *sa; - struct device *self; +ka750_memenable(parent, self, aux) + struct device *parent, *self; + void *aux; { - int k, l, m, cardinfo; + struct sbi_attach_args *sa = (struct sbi_attach_args *)aux; struct mcr750 *mcr = (struct mcr750 *)sa->nexaddr; + int k, l, m, cardinfo; mcraddr[self->dv_unit] = (caddr_t)sa->nexaddr; @@ -209,7 +214,7 @@ struct mc750frame { }; #define MC750_TBERR 2 /* type code of cp tbuf par */ -#define MC750_TBPAR 4 /* tbuf par bit in mcesr */ +#define MC750_TBPAR 4 /* tbuf par bit in mcesr */ int ka750_mchk(cmcf) @@ -241,7 +246,6 @@ void ka750_steal_pages() { extern vm_offset_t avail_start, virtual_avail; - extern struct nexus *nexus; int junk; /* @@ -255,3 +259,87 @@ ka750_steal_pages() VM_PROT_READ|VM_PROT_WRITE); } +static int cmi_print __P((void *, const char *)); +static int cmi_match __P((struct device *, void *, void *)); +static void cmi_attach __P((struct device *, struct device *, void*)); + +struct cfdriver cmi_cd = { + NULL, "cmi", DV_DULL +}; + +struct cfattach cmi_ca = { + sizeof(struct device), cmi_match, cmi_attach +}; + +int +cmi_print(aux, name) + void *aux; + const char *name; +{ + struct sbi_attach_args *sa = (struct sbi_attach_args *)aux; + + if (name) + printf("unknown device 0x%x at %s", sa->type, name); + + printf(" tr%d", sa->nexnum); + return (UNCONF); +} + + +int +cmi_match(parent, cf, aux) + struct device *parent; + void *cf, *aux; +{ + struct bp_conf *bp = aux; + + if (strcmp(bp->type, "cmi")) + return 0; + return 1; +} + +void +cmi_attach(parent, self, aux) + struct device *parent, *self; + void *aux; +{ + u_int nexnum, maxnex, minnex; + struct sbi_attach_args sa; + + printf("I\n"); + /* + * Probe for memory, can be in the first 4 slots. + */ + for (sa.nexnum = 0; sa.nexnum < 4; sa.nexnum++) { + if (badaddr((caddr_t)&nexus[sa.nexnum], 4)) + continue; + + sa.nexaddr = nexus + sa.nexnum; + sa.type = NEX_MEM16; + config_found(self, (void*)&sa, cmi_print); + } + + /* + * Probe for mba's, can be in slot 4 - 7. + */ + for (sa.nexnum = 4; sa.nexnum < 7; sa.nexnum++) { + if (badaddr((caddr_t)&nexus[sa.nexnum], 4)) + continue; + + sa.nexaddr = nexus + sa.nexnum; + sa.type = NEX_MBA; + config_found(self, (void*)&sa, cmi_print); + } + + /* + * There are always one generic UBA, and maybe an optional. + */ + sa.nexnum = 8; + sa.nexaddr = nexus + sa.nexnum; + sa.type = NEX_UBA0; + config_found(self, (void*)&sa, cmi_print); + sa.type = NEX_UBA1; + if (badaddr((caddr_t)&nexus[++sa.nexnum], 4) == 0) + config_found(self, (void*)&sa, cmi_print); + +} diff --git a/sys/arch/vax/vax/ka780.c b/sys/arch/vax/vax/ka780.c index 7eb7e0569b8..93b47118b50 100644 --- a/sys/arch/vax/vax/ka780.c +++ b/sys/arch/vax/vax/ka780.c @@ -1,4 +1,4 @@ -/* $NetBSD: ka780.c,v 1.3 1996/04/08 18:32:43 ragge Exp $ */ +/* $NetBSD: ka780.c,v 1.6 1996/10/13 03:35:50 christos Exp $ */ /*- * Copyright (c) 1982, 1986, 1988 The Regents of the University of California. * All rights reserved. @@ -51,12 +51,13 @@ #include <machine/mtpr.h> #include <machine/scb.h> #include <machine/nexus.h> +#include <machine/sid.h> + #include <vax/uba/ubavar.h> #include <vax/uba/ubareg.h> /* Prototypes. XXX These should be somewhere else */ void ka780_conf __P((struct device *, struct device *, void *)); -int ka780_clock __P((void)); void ka780_memenable __P((struct sbi_attach_args *, void *)); void ka780_memerr __P((void)); int ka780_mchk __P((caddr_t)); @@ -69,45 +70,45 @@ struct mcr780 { int mc_reg[4]; }; -#define M780_ICRD 0x40000000 /* inhibit crd interrupts, in [2] */ -#define M780_HIER 0x20000000 /* high error rate, in reg[2] */ -#define M780_ERLOG 0x10000000 /* error log request, in reg[2] */ +#define M780_ICRD 0x40000000 /* inhibit crd interrupts, in [2] */ +#define M780_HIER 0x20000000 /* high error rate, in reg[2] */ +#define M780_ERLOG 0x10000000 /* error log request, in reg[2] */ /* on a 780, memory crd's occur only when bit 15 is set in the SBIER */ /* register; bit 14 there is an error bit which we also clear */ /* these bits are in the back of the ``red book'' (or in the VMS code) */ -#define M780C_INH(mcr) \ +#define M780C_INH(mcr) \ ((mcr)->mc_reg[2] = (M780_ICRD|M780_HIER|M780_ERLOG)); \ mtpr(0, PR_SBIER); -#define M780C_ENA(mcr) \ +#define M780C_ENA(mcr) \ ((mcr)->mc_reg[2] = (M780_HIER|M780_ERLOG)); mtpr(3<<14, PR_SBIER); -#define M780C_ERR(mcr) \ +#define M780C_ERR(mcr) \ ((mcr)->mc_reg[2] & (M780_ERLOG)) -#define M780C_SYN(mcr) ((mcr)->mc_reg[2] & 0xff) -#define M780C_ADDR(mcr) (((mcr)->mc_reg[2] >> 8) & 0xfffff) +#define M780C_SYN(mcr) ((mcr)->mc_reg[2] & 0xff) +#define M780C_ADDR(mcr) (((mcr)->mc_reg[2] >> 8) & 0xfffff) -#define M780EL_INH(mcr) \ +#define M780EL_INH(mcr) \ ((mcr)->mc_reg[2] = (M780_ICRD|M780_HIER|M780_ERLOG)); \ mtpr(0, PR_SBIER); -#define M780EL_ENA(mcr) \ +#define M780EL_ENA(mcr) \ ((mcr)->mc_reg[2] = (M780_HIER|M780_ERLOG)); mtpr(3<<14, PR_SBIER); -#define M780EL_ERR(mcr) \ +#define M780EL_ERR(mcr) \ ((mcr)->mc_reg[2] & (M780_ERLOG)) -#define M780EL_SYN(mcr) ((mcr)->mc_reg[2] & 0x7f) -#define M780EL_ADDR(mcr) (((mcr)->mc_reg[2] >> 11) & 0x1ffff) +#define M780EL_SYN(mcr) ((mcr)->mc_reg[2] & 0x7f) +#define M780EL_ADDR(mcr) (((mcr)->mc_reg[2] >> 11) & 0x1ffff) -#define M780EU_INH(mcr) \ +#define M780EU_INH(mcr) \ ((mcr)->mc_reg[3] = (M780_ICRD|M780_HIER|M780_ERLOG)); \ mtpr(0, PR_SBIER); -#define M780EU_ENA(mcr) \ +#define M780EU_ENA(mcr) \ ((mcr)->mc_reg[3] = (M780_HIER|M780_ERLOG)); mtpr(3<<14, PR_SBIER); -#define M780EU_ERR(mcr) \ +#define M780EU_ERR(mcr) \ ((mcr)->mc_reg[3] & (M780_ERLOG)) -#define M780EU_SYN(mcr) ((mcr)->mc_reg[3] & 0x7f) -#define M780EU_ADDR(mcr) (((mcr)->mc_reg[3] >> 11) & 0x1ffff) +#define M780EU_SYN(mcr) ((mcr)->mc_reg[3] & 0x7f) +#define M780EU_ADDR(mcr) (((mcr)->mc_reg[3] >> 11) & 0x1ffff) /* enable crd interrrupts */ void @@ -213,8 +214,8 @@ struct { 0x73, "L19", 0x75, "L21", 0x76, "L22", 0x79, "L25", 0x7A, "L26", 0x7C, "L28", 0x7F, "L31", 0x80, "C07", 0x89, "U01", 0x8A, "U02", 0x8C, "U04", 0x8F, "U07", - 0x91, "U09", 0x92, "U10", 0x94, "U12", 0x97, "U15", - 0x98, "U16", 0x9B, "U19", 0x9D, "U21", 0x9E, "U22", + 0x91, "U09", 0x92, "U10", 0x94, "U12", 0x97, "U15", + 0x98, "U16", 0x9B, "U19", 0x9D, "U21", 0x9E, "U22", 0xA8, "U00", 0xAB, "U03", 0xAD, "U05", 0xAE, "U06", 0xB0, "U08", 0xB3, "U11", 0xB5, "U13", 0xB6, "U14", 0xB9, "U17", 0xBA, "U18", 0xBC, "U20", 0xBF, "U23", @@ -244,7 +245,7 @@ memlog(m, mcr) #endif TRENDATA char *mc780[]={"0","1","2","3","4","5","6","7","8","9","10","11","12","13", - "14","15"}; + "14","15"}; struct mc780frame { int mc8_bcnt; /* byte count == 0x28 */ @@ -296,11 +297,11 @@ struct ka78x { void ka780_conf(parent, self, aux) - struct device *parent, *self; - void *aux; + struct device *parent, *self; + void *aux; { - extern char cpu_model[]; - struct ka78x *ka78 = (void *)&cpu_type; + extern char cpu_model[]; + struct ka78x *ka78 = (void *)&vax_cpudata; /* Enable cache */ mtpr(0x200000, PR_SBIMT); @@ -319,14 +320,6 @@ ka780_conf(parent, self, aux) } -int -ka780_clock() -{ - mtpr(-10000, PR_NICR); /* Load in count register */ - mtpr(0x800000d1, PR_ICCS); /* Start clock and enable interrupt */ - return 0; -} - void ka780_steal_pages() { diff --git a/sys/arch/vax/vax/ka820.c b/sys/arch/vax/vax/ka820.c new file mode 100644 index 00000000000..b3122c80b2e --- /dev/null +++ b/sys/arch/vax/vax/ka820.c @@ -0,0 +1,466 @@ +/* $NetBSD: ka820.c,v 1.3 1996/10/13 03:35:51 christos Exp $ */ +/* + * Copyright (c) 1988 Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Chris Torek. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)ka820.c 7.4 (Berkeley) 12/16/90 + */ + +/* + * KA820 specific CPU code. (Note that the VAX8200 uses a KA820, not + * a KA8200. Sigh.) + */ + +#include <sys/param.h> +#include <sys/time.h> +#include <sys/kernel.h> +#include <sys/device.h> + +#include <vm/vm.h> +#include <vm/vm_kern.h> + +#include <machine/ka820.h> +#include <machine/cpu.h> +#include <machine/mtpr.h> +#include <machine/nexus.h> +#include <machine/clock.h> +#include <machine/scb.h> + +#include <arch/vax/bi/bireg.h> +#include <arch/vax/bi/bivar.h> + +struct ka820clock *ka820clock_ptr; +struct ka820port *ka820port_ptr; +struct rx50device *rx50device_ptr; +void *bi_nodebase; /* virtual base address for all possible bi nodes */ + +static int ka820_match __P((struct device *, void *, void *)); +static void ka820_attach __P((struct device *, struct device *, void*)); + +struct cfattach cpu_bi_ca = { + sizeof(struct device), ka820_match, ka820_attach +}; + +#ifdef notyet +extern struct pte BRAMmap[]; +extern struct pte EEPROMmap[]; +char bootram[KA820_BRPAGES * NBPG]; +char eeprom[KA820_EEPAGES * NBPG]; +#endif + +struct ivec_dsp nollhanterare; + +static void +hant(arg) + int arg; +{ + if (cold == 0) + printf("stray interrupt from vaxbi bus\n"); +} + +void +ka820_steal_pages() +{ + extern vm_offset_t avail_start, virtual_avail, avail_end; + extern struct ivec_dsp idsptch; + struct scb *sb; + int junk, i, j; + + /* + * On the ka820, we map in the port CSR, the clock registers + * and the console RX50 register. We also map in the BI nodespace + * for all possible (16) nodes. It would only be needed with + * the existent nodes, but we only loose 1K so... + */ + sb = (void *)avail_start; + MAPPHYS(junk, j, VM_PROT_READ|VM_PROT_WRITE); /* SCB & vectors */ + MAPVIRT(ka820clock_ptr, 1); + pmap_map((vm_offset_t)ka820clock_ptr, (vm_offset_t)KA820_CLOCKADDR, + KA820_CLOCKADDR + NBPG, VM_PROT_READ|VM_PROT_WRITE); + + MAPVIRT(ka820port_ptr, 1); + pmap_map((vm_offset_t)ka820port_ptr, (vm_offset_t)KA820_PORTADDR, + KA820_PORTADDR + NBPG, VM_PROT_READ|VM_PROT_WRITE); + + MAPVIRT(rx50device_ptr, 1); + pmap_map((vm_offset_t)rx50device_ptr, (vm_offset_t)KA820_RX50ADDR, + KA820_RX50ADDR + NBPG, VM_PROT_READ|VM_PROT_WRITE); + + MAPVIRT(bi_nodebase, NNODEBI * (sizeof(struct bi_node) / NBPG)); + pmap_map((vm_offset_t)bi_nodebase, (vm_offset_t)BI_BASE(0), + BI_BASE(0) + sizeof(struct bi_node) * NNODEBI, + VM_PROT_READ|VM_PROT_WRITE); + bcopy(&idsptch, &nollhanterare, sizeof(struct ivec_dsp)); + nollhanterare.hoppaddr = hant; + for (i = 0; i < 4; i++) + for (j = 0; j < 16; j++) + sb->scb_nexvec[i][j] = &nollhanterare; + +} + +int +ka820_match(parent, match, aux) + struct device *parent; + void *match, *aux; +{ + struct cfdata *cf = match; + struct bi_attach_args *ba = aux; + + if (ba->ba_node->biic.bi_dtype != BIDT_KA820) + return 0; + + if (ba->ba_nodenr != mastercpu) + return 0; + + if (cf->cf_loc[0] != -1 && cf->cf_loc[0] != ba->ba_nodenr) + return 0; + + return 1; +} + +void +ka820_attach(parent, self, aux) + struct device *parent, *self; + void *aux; +{ + struct bi_attach_args *ba = aux; + register int csr; + u_short rev = ba->ba_node->biic.bi_revs; + extern char cpu_model[]; + + strcpy(cpu_model,"VAX 8200"); + cpu_model[6] = rev & 0x8000 ? '5' : '0'; + printf(": ka82%c (%s) cpu rev %d, u patch rev %d, sec patch %d\n", + cpu_model[6], mastercpu == ba->ba_nodenr ? "master" : "slave", + ((rev >> 11) & 15), ((rev >> 1) &1023), rev & 1); + + /* reset the console and enable the RX50 */ + csr = ka820port_ptr->csr; + csr &= ~KA820PORT_RSTHALT; /* ??? */ + csr |= KA820PORT_CONSCLR | KA820PORT_CRDCLR | KA820PORT_CONSEN | + KA820PORT_RXIE; + ka820port_ptr->csr = csr; + ba->ba_node->biic.bi_intrdes = ba->ba_intcpu; + ba->ba_node->biic.bi_csr |= BICSR_SEIE | BICSR_HEIE; +} + +/* Set system time from clock */ +/* ARGSUSED */ +ka820_clkread(base) + time_t base; +{ + struct chiptime c; + int s, rv; + + rv = CLKREAD_OK; + /* I wish I knew the differences between these */ + if ((ka820clock_ptr->csr3 & KA820CLK_3_VALID) == 0) { + printf("WARNING: TOY clock not marked valid\n"); + rv = CLKREAD_WARN; + } + if ((ka820clock_ptr->csr1 & KA820CLK_1_GO) != KA820CLK_1_GO) { + printf("WARNING: TOY clock stopped\n"); + rv = CLKREAD_WARN; + } + /* THIS IS NOT RIGHT (clock may change on us) */ + s = splhigh(); + while (ka820clock_ptr->csr0 & KA820CLK_0_BUSY) + /* void */; + c.sec = ka820clock_ptr->sec; + c.min = ka820clock_ptr->min; + c.hour = ka820clock_ptr->hr; + c.day = ka820clock_ptr->day; + c.mon = ka820clock_ptr->mon; + c.year = ka820clock_ptr->yr; + splx(s); + + /* the darn thing needs tweaking! */ + c.sec >>= 1; /* tweak */ + c.min >>= 1; /* tweak */ + c.hour >>= 1; /* tweak */ + c.day >>= 1; /* tweak */ + c.mon >>= 1; /* tweak */ + c.year >>= 1; /* tweak */ + + time.tv_sec = chiptotime(&c); + return (time.tv_sec ? rv : CLKREAD_BAD); +} + +/* store time into clock */ +void +ka820_clkwrite() +{ + struct chiptime c; + int s; + + timetochip(&c); + + /* play it again, sam (or mike or kirk or ...) */ + c.sec <<= 1; /* tweak */ + c.min <<= 1; /* tweak */ + c.hour <<= 1; /* tweak */ + c.day <<= 1; /* tweak */ + c.mon <<= 1; /* tweak */ + c.year <<= 1; /* tweak */ + + s = splhigh(); + ka820clock_ptr->csr1 = KA820CLK_1_SET; + while (ka820clock_ptr->csr0 & KA820CLK_0_BUSY) + /* void */; + ka820clock_ptr->sec = c.sec; + ka820clock_ptr->min = c.min; + ka820clock_ptr->hr = c.hour; + ka820clock_ptr->day = c.day; + ka820clock_ptr->mon = c.mon; + ka820clock_ptr->yr = c.year; + /* should we set a `rate'? */ + ka820clock_ptr->csr1 = KA820CLK_1_GO; + splx(s); +} + +/* + * MS820 support. + */ +struct ms820regs { + struct biiregs biic; /* BI interface chip */ + u_long ms_gpr[4]; /* the four gprs (unused) */ + int ms_csr1; /* control/status register 1 */ + int ms_csr2; /* control/status register 2 */ +}; + +/* + * Bits in CSR1. + */ +#define MS1_ERRSUM 0x80000000 /* error summary (ro) */ +#define MS1_ECCDIAG 0x40000000 /* ecc diagnostic (rw) */ +#define MS1_ECCDISABLE 0x20000000 /* ecc disable (rw) */ +#define MS1_MSIZEMASK 0x1ffc0000 /* mask for memory size (ro) */ +#define MS1_RAMTYMASK 0x00030000 /* mask for ram type (ro) */ +#define MS1_RAMTY64K 0x00000000 /* 64K chips */ +#define MS1_RAMTY256K 0x00010000 /* 256K chips */ +#define MS1_RAMTY1MB 0x00020000 /* 1MB chips */ + /* type 3 reserved */ +#define MS1_CRDINH 0x00008000 /* inhibit crd interrupts (rw) */ +#define MS1_MEMVALID 0x00004000 /* memory has been written (ro) */ +#define MS1_INTLK 0x00002000 /* interlock flag (ro) */ +#define MS1_BROKE 0x00001000 /* broken (rw) */ +#define MS1_MBZ 0x00000880 /* zero */ +#define MS1_MWRITEERR 0x00000400 /* rds during masked write (rw) */ +#define MS1_CNTLERR 0x00000200 /* internal timing busted (rw) */ +#define MS1_INTLV 0x00000100 /* internally interleaved (ro) */ +#define MS1_DIAGC 0x0000007f /* ecc diagnostic bits (rw) */ + +/* + * Bits in CSR2. + */ +#define MS2_RDSERR 0x80000000 /* rds error (rw) */ +#define MS2_HIERR 0x40000000 /* high error rate (rw) */ +#define MS2_CRDERR 0x20000000 /* crd error (rw) */ +#define MS2_ADRSERR 0x10000000 /* rds due to addr par err (rw) */ +#define MS2_MBZ 0x0f000080 /* zero */ +#define MS2_ADDR 0x00fffe00 /* address in error (relative) (ro) */ +#define MS2_INTLVADDR 0x00000100 /* error was in bank 1 (ro) */ +#define MS2_SYN 0x0000007f /* error syndrome (ro, rw diag) */ + +static int ms820_match __P((struct device *, void *, void *)); +static void ms820_attach __P((struct device *, struct device *, void*)); + +struct mem_bi_softc { + struct device mem_dev; + struct ms820regs *mem_regs; +}; + +struct cfattach mem_bi_ca = { + sizeof(struct mem_bi_softc), ms820_match, ms820_attach +}; + +static int +ms820_match(parent, match, aux) + struct device *parent; + void *match, *aux; +{ + struct cfdata *cf = match; + struct bi_attach_args *ba = aux; + + if (ba->ba_node->biic.bi_dtype != BIDT_MS820) + return 0; + + if (cf->cf_loc[0] != -1 && cf->cf_loc[0] != ba->ba_nodenr) + return 0; + + return 1; +} + +static void +ms820_attach(parent, self, aux) + struct device *parent, *self; + void *aux; +{ + struct mem_bi_softc *ms = (void *)self; + struct bi_attach_args *ba = aux; + + ms->mem_regs = (void *)ba->ba_node; + + if ((ms->mem_regs->biic.bi_csr & BICSR_STS) == 0) + printf(": failed self test\n"); + else + printf(": size %dMB, %s chips\n", ((ms->mem_regs->ms_csr1 & + MS1_MSIZEMASK) >> 20), (ms->mem_regs->ms_csr1&MS1_RAMTYMASK + ?ms->mem_regs->ms_csr1 & MS1_RAMTY256K?"256K":"1M":"64K")); + + ms->mem_regs->biic.bi_intrdes = ba->ba_intcpu; + ms->mem_regs->biic.bi_csr |= BICSR_SEIE | BICSR_HEIE; + + ms->mem_regs->ms_csr1 = MS1_MWRITEERR | MS1_CNTLERR; + ms->mem_regs->ms_csr2 = MS2_RDSERR | MS2_HIERR | + MS2_CRDERR | MS2_ADRSERR; +} + +void +ka820_memerr() +{ + register struct ms820regs *mcr; + struct mem_bi_softc *mc; + extern struct cfdriver mem_cd; + register int m, hard; + register char *type; +static char b1[] = "\20\40ERRSUM\37ECCDIAG\36ECCDISABLE\20CRDINH\17VALID\ +\16INTLK\15BROKE\13MWRITEERR\12CNTLERR\11INTLV"; +static char b2[] = "\20\40RDS\37HIERR\36CRD\35ADRS"; + + for (m = 0; m < mem_cd.cd_ndevs; m++) { + mc = mem_cd.cd_devs[m]; + if (mc == NULL) + continue; + mcr = mc->mem_regs; + printf("%s: csr1=%b csr2=%b\n", mc->mem_dev.dv_xname, + mcr->ms_csr1, b1, mcr->ms_csr2, b2); + if ((mcr->ms_csr1 & MS1_ERRSUM) == 0) + continue; + hard = 1; + if (mcr->ms_csr1 & MS1_BROKE) + type = "broke"; + else if (mcr->ms_csr1 & MS1_CNTLERR) + type = "cntl err"; + else if (mcr->ms_csr2 & MS2_ADRSERR) + type = "address parity err"; + else if (mcr->ms_csr2 & MS2_RDSERR) + type = "rds err"; + else if (mcr->ms_csr2 & MS2_CRDERR) { + hard = 0; + type = ""; + } else + type = "mysterious error"; + printf("%s: %s%s%s addr %x bank %x syn %x\n", + mc->mem_dev.dv_xname, + hard ? "hard error: " : "soft ecc", + type, mcr->ms_csr2 & MS2_HIERR ? + " (+ other rds or crd err)" : "", + ((mcr->ms_csr2 & MS2_ADDR) + mcr->biic.bi_sadr) >> 9, + (mcr->ms_csr2 & MS2_INTLVADDR) != 0, + mcr->ms_csr2 & MS2_SYN); + mcr->ms_csr1 = mcr->ms_csr1 | MS1_CRDINH; + mcr->ms_csr2 = mcr->ms_csr2; + } +} + +/* these are bits 0 to 6 in the summary field */ +char *mc8200[] = { + "cpu bad ipl", "ucode lost err", + "ucode par err", "DAL par err", + "BI bus err", "BTB tag par", + "cache tag par", +}; +#define MC8200_BADIPL 0x01 +#define MC8200_UERR 0x02 +#define MC8200_UPAR 0x04 +#define MC8200_DPAR 0x08 +#define MC8200_BIERR 0x10 +#define MC8200_BTAGPAR 0x20 +#define MC8200_CTAGPAR 0x40 + +struct mc8200frame { + int mc82_bcnt; /* byte count == 0x20 */ + int mc82_summary; /* summary parameter */ + int mc82_param1; /* parameter 1 */ + int mc82_va; /* va register */ + int mc82_vap; /* va prime register */ + int mc82_ma; /* memory address */ + int mc82_status; /* status word */ + int mc82_epc; /* error pc */ + int mc82_upc; /* micro pc */ + int mc82_pc; /* current pc */ + int mc82_psl; /* current psl */ +}; + +int +ka820_mchk(cmcf) + caddr_t cmcf; +{ + register struct mc8200frame *mcf = (struct mc8200frame *)cmcf; + register int i, type = mcf->mc82_summary; + + /* ignore BI bus errors during configuration */ + if (cold && type == MC8200_BIERR) { + mtpr(PR_MCESR, 0xf); + return (MCHK_RECOVERED); + } + + /* + * SOME ERRORS ARE RECOVERABLE + * do it later + */ + printf("machine check %x: ", type); + for (i = 0; i < sizeof (mc8200) / sizeof (mc8200[0]); i++) + if (type & (1 << i)) + printf(" %s,", mc8200[i]); + printf(" param1 %x\n", mcf->mc82_param1); + printf( +"\tva %x va' %x ma %x pc %x psl %x\n\tstatus %x errpc %x upc %x\n", + mcf->mc82_va, mcf->mc82_vap, mcf->mc82_ma, + mcf->mc82_pc, mcf->mc82_psl, + mcf->mc82_status, mcf->mc82_epc, mcf->mc82_upc); + return (MCHK_PANIC); +} + +/* + * Receive a character from logical console. + */ +rxcdintr() +{ + register int c = mfpr(PR_RXCD); + + /* not sure what (if anything) to do with these */ + printf("rxcd node %x c=0x%x\n", (c >> 8) & 0xf, c & 0xff); +} diff --git a/sys/arch/vax/vax/ka860.c b/sys/arch/vax/vax/ka860.c index b41b228b360..43cb0094ff2 100644 --- a/sys/arch/vax/vax/ka860.c +++ b/sys/arch/vax/vax/ka860.c @@ -1,4 +1,4 @@ -/* $NetBSD: ka860.c,v 1.3 1996/04/08 18:32:45 ragge Exp $ */ +/* $NetBSD: ka860.c,v 1.6 1996/10/13 03:35:53 christos Exp $ */ /* * Copyright (c) 1986, 1988 Regents of the University of California. * All rights reserved. @@ -49,32 +49,32 @@ #include <machine/mtpr.h> #include <machine/nexus.h> #include <machine/ioa.h> +#include <machine/sid.h> struct ioa *ioa; /* XXX These are in autoconf.c also */ void ka86_conf __P((struct device *, struct device *, void *)); -int ka86_clock __P((void)); void ka86_memenable __P((struct sbi_attach_args *, struct device *)); void ka86_memerr __P((void)); int ka86_mchk __P((caddr_t)); -void ka86_steal_pages __P((void)); +void ka86_steal_pages __P((void)); void crlattach __P((void)); /* * 8600 memory register (MERG) bit definitions */ -#define M8600_ICRD 0x400 /* inhibit crd interrupts */ +#define M8600_ICRD 0x400 /* inhibit crd interrupts */ #define M8600_TB_ERR 0xf00 /* translation buffer error mask */ /* * MDECC register */ -#define M8600_ADDR_PE 0x080000 /* address parity error */ +#define M8600_ADDR_PE 0x080000 /* address parity error */ #define M8600_DBL_ERR 0x100000 /* data double bit error */ -#define M8600_SNG_ERR 0x200000 /* data single bit error */ -#define M8600_BDT_ERR 0x400000 /* bad data error */ +#define M8600_SNG_ERR 0x200000 /* data single bit error */ +#define M8600_BDT_ERR 0x400000 /* bad data error */ /* * ESPA register is used to address scratch pad registers in the Ebox. @@ -88,7 +88,7 @@ void crlattach __P((void)); * The scratchpad registers that are supplied for a single bit ECC * error are: */ -#define SPAD_MSTAT1 0x25 /* scratch pad mstat1 register */ +#define SPAD_MSTAT1 0x25 /* scratch pad mstat1 register */ #define SPAD_MSTAT2 0x26 /* scratch pad mstat2 register */ #define SPAD_MDECC 0x27 /* scratch pad mdecc register */ #define SPAD_MEAR 0x2a /* scratch pad mear register */ @@ -124,7 +124,7 @@ ka86_memenable(sa, dev) void ka86_memerr() { - register int reg11 = 0; /* known to be r11 below */ + register int reg11 = 0; /* known to be r11 below */ int mdecc, mear, mstat1, mstat2, array; /* @@ -161,25 +161,25 @@ ka86_memerr() } } -#define NMC8600 7 +#define NMC8600 7 char *mc8600[] = { "unkn type", "fbox error", "ebox error", "ibox error", "mbox error", "tbuf error", "mbox 1D error" }; /* codes for above */ -#define MC_FBOX 1 -#define MC_EBOX 2 -#define MC_IBOX 3 -#define MC_MBOX 4 -#define MC_TBUF 5 -#define MC_MBOX1D 6 +#define MC_FBOX 1 +#define MC_EBOX 2 +#define MC_IBOX 3 +#define MC_MBOX 4 +#define MC_TBUF 5 +#define MC_MBOX1D 6 /* error bits */ -#define MBOX_FE 0x8000 /* Mbox fatal error */ -#define FBOX_SERV 0x10000000 /* Fbox service error */ -#define IBOX_ERR 0x2000 /* Ibox error */ -#define EBOX_ERR 0x1e00 /* Ebox error */ -#define MBOX_1D 0x81d0000 /* Mbox 1D error */ +#define MBOX_FE 0x8000 /* Mbox fatal error */ +#define FBOX_SERV 0x10000000 /* Fbox service error */ +#define IBOX_ERR 0x2000 /* Ibox error */ +#define EBOX_ERR 0x1e00 /* Ebox error */ +#define MBOX_1D 0x81d0000 /* Mbox 1D error */ #define EDP_PE 0x200 struct mc8600frame { @@ -257,9 +257,9 @@ ka86_mchk(cmcf) void ka86_steal_pages() { - extern vm_offset_t avail_start, virtual_avail; - extern struct nexus *nexus; - int junk; + extern vm_offset_t avail_start, virtual_avail; + extern struct nexus *nexus; + int junk; /* 8600 may have 2 SBI's == 4 pages */ MAPPHYS(junk, 4, VM_PROT_READ|VM_PROT_WRITE); @@ -293,11 +293,11 @@ struct ka86 { void ka86_conf(parent, self, aux) - struct device *parent, *self; - void *aux; + struct device *parent, *self; + void *aux; { - extern char cpu_model[]; - struct ka86 *ka86 = (void *)&cpu_type; + extern char cpu_model[]; + struct ka86 *ka86 = (void *)&vax_cpudata; /* Enable cache */ mtpr(3, PR_CSWP); @@ -316,12 +316,3 @@ ka86_conf(parent, self, aux) printf("no FPA\n"); crlattach(); } - -int -ka86_clock() -{ - mtpr(-10000, PR_NICR); /* Load in count register */ - mtpr(0x800000d1, PR_ICCS); /* Start clock and enable interrupt */ - return 0; -} - diff --git a/sys/arch/vax/vax/locore.c b/sys/arch/vax/vax/locore.c index 100dd6bd794..443f7b51ad5 100644 --- a/sys/arch/vax/vax/locore.c +++ b/sys/arch/vax/vax/locore.c @@ -1,5 +1,4 @@ -/* $NetBSD: locore.c,v 1.15 1996/05/19 16:44:07 ragge Exp $ */ - +/* $NetBSD: locore.c,v 1.17 1996/08/20 14:13:54 ragge Exp $ */ /* * Copyright (c) 1994 Ludd, University of Lule}, Sweden. * All rights reserved. @@ -48,15 +47,31 @@ #include <machine/vmparam.h> #include <machine/pcb.h> #include <machine/pmap.h> +#include <machine/nexus.h> void start __P((void)); void main __P((void)); u_int proc0paddr; -int cpunumber, *Sysmap, boothowto, cpu_type; +int *Sysmap, boothowto; char *esym; extern int bootdev; +/* + * We set up some information about the machine we're + * running on and thus initializes/uses vax_cputype and vax_boardtype. + * There should be no need to change/reinitialize these variables + * outside of this routine, they should be read only! + */ +int vax_cputype; /* highest byte of SID register */ +int vax_bustype; /* holds/defines all busses on this machine */ +int vax_boardtype; /* machine dependend, combination of SID and SIE */ +int vax_systype; /* machine dependend identification of the system */ + +int vax_cpudata; /* contents of the SID register */ +int vax_siedata; /* contents of the SIE register */ +int vax_confdata; /* machine dependend, configuration/setup data */ + /* * Start is called from boot; the first routine that is called * in kernel. Kernel stack is setup somewhere in a safe place; @@ -116,11 +131,11 @@ tokmem: movw $0xfff, _panic Sysmap = (u_int *)ROUND_PAGE(mfpr(PR_KSP)); /* Be sure some important internal registers have safe values */ - ((struct pcb *)proc0paddr)->P0LR = 0; - ((struct pcb *)proc0paddr)->P0BR = (void *)0x80000000; - ((struct pcb *)proc0paddr)->P1LR = 0; - ((struct pcb *)proc0paddr)->P1BR = (void *)0x80000000; - ((struct pcb *)proc0paddr)->iftrap = NULL; + ((struct pcb *)proc0paddr)->P0LR = 0; + ((struct pcb *)proc0paddr)->P0BR = (void *)0x80000000; + ((struct pcb *)proc0paddr)->P1LR = 0; + ((struct pcb *)proc0paddr)->P1BR = (void *)0x80000000; + ((struct pcb *)proc0paddr)->iftrap = NULL; mtpr(0, PR_P0LR); mtpr(0x80000000, PR_P0BR); mtpr(0, PR_P1LR); @@ -129,13 +144,73 @@ tokmem: movw $0xfff, _panic mtpr(0, PR_SCBB); /* SCB at physical addr */ mtpr(0, PR_ESP); /* Must be zero, used in page fault routine */ mtpr(AST_NO, PR_ASTLVL); - - cninit(); /* Count up memory etc... early machine dependent routines */ - if ((cpunumber = MACHID(mfpr(PR_SID))) > VAX_MAX) - cpunumber = 0; - cpu_type = mfpr(PR_SID); + vax_cputype = ((vax_cpudata = mfpr(PR_SID)) >> 24); + + switch (vax_cputype) { +#if VAX780 + case VAX_TYP_780: + vax_bustype = VAX_SBIBUS | VAX_CPUBUS; + vax_boardtype = VAX_BTYP_780; + break; +#endif +#if VAX750 + case VAX_TYP_750: + vax_bustype = VAX_CMIBUS | VAX_CPUBUS; + vax_boardtype = VAX_BTYP_750; + break; +#endif +#if VAX8600 + case VAX_TYP_790: + vax_bustype = VAX_CPUBUS | VAX_MEMBUS; + vax_boardtype = VAX_BTYP_790; + break; +#endif +#if VAX630 || VAX650 || VAX410 || VAX43 + case VAX_TYP_UV2: + case VAX_TYP_CVAX: + case VAX_TYP_RIGEL: + vax_siedata = *(int *)(0x20040004); /* SIE address */ + vax_boardtype = (vax_cputype<<24) | ((vax_siedata>>24)&0xFF); + + switch (vax_boardtype) { + case VAX_BTYP_410: + case VAX_BTYP_43: + vax_confdata = *(int *)(0x20020000); + vax_bustype = VAX_VSBUS | VAX_CPUBUS; + break; + + case VAX_BTYP_630: + case VAX_BTYP_650: + vax_bustype = VAX_UNIBUS | VAX_CPUBUS; + break; + + default: + break; + } + break; +#endif +#if VAX8200 + case VAX_TYP_8SS: + vax_boardtype = VAX_BTYP_8000; + vax_bustype = VAX_BIBUS; + mastercpu = mfpr(PR_BINID); + break; +#endif + default: + /* CPU not supported, just give up */ + asm("halt"); + } + + /* + * before doing anything else, we need to setup the console + * so that output (eg. debug and error messages) are visible. + * They way console-output is done is different for different + * VAXen, thus vax_cputype and vax_boardtype are setup/used. + */ + cninit(); + pmap_bootstrap(); ((struct pcb *)proc0paddr)->framep = scratch; diff --git a/sys/arch/vax/vax/machdep.c b/sys/arch/vax/vax/machdep.c index 53cbc176d44..1935d85b66b 100644 --- a/sys/arch/vax/vax/machdep.c +++ b/sys/arch/vax/vax/machdep.c @@ -1,4 +1,5 @@ -/* $NetBSD: machdep.c,v 1.30 1996/05/19 16:44:13 ragge Exp $ */ +/* $OpenBSD: machdep.c,v 1.10 1997/01/15 23:25:17 maja Exp $ */ +/* $NetBSD: machdep.c,v 1.35 1997/01/11 11:31:26 ragge Exp $ */ /* * Copyright (c) 1994 Ludd, University of Lule}, Sweden. @@ -23,7 +24,7 @@ * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of - * California, Berkeley and its contributors. + * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. @@ -119,45 +120,44 @@ extern int virtual_avail, virtual_end; * We do these external declarations here, maybe they should be done * somewhere else... */ -int nmcr, nmba, numuba, cold = 1; -caddr_t mcraddr[MAXNMCR]; -int astpending; -int want_resched; -char machine[] = "vax"; -char cpu_model[100]; -int msgbufmapped = 0; +int nmcr, nmba, numuba, cold = 1; +caddr_t mcraddr[MAXNMCR]; +int astpending; +int want_resched; +char machine[] = "vax"; +char cpu_model[100]; +int msgbufmapped = 0; struct msgbuf *msgbufp; -int physmem; +int physmem; struct cfdriver nexuscd; -int todrstopped = 0, glurg; -int dumpsize = 0; +int todrstopped = 0, glurg; +int dumpsize = 0; caddr_t allocsys __P((caddr_t)); #define valloclim(name, type, num, lim) \ (name) = (type *)v; v = (caddr_t)((lim) = ((name)+(num))) -#ifdef BUFPAGES -int bufpages = BUFPAGES; +#ifdef BUFPAGES +int bufpages = BUFPAGES; #else -int bufpages = 0; +int bufpages = 0; #endif -int nswbuf = 0; -#ifdef NBUF -int nbuf = NBUF; +int nswbuf = 0; +#ifdef NBUF +int nbuf = NBUF; #else -int nbuf = 0; +int nbuf = 0; #endif void cpu_startup() { - caddr_t v; - extern char version[]; - int base, residual, i, sz; - vm_offset_t minaddr, maxaddr; - vm_size_t size; - extern int cpu_type, boothowto; + caddr_t v; + extern char version[]; + int base, residual, i, sz; + vm_offset_t minaddr, maxaddr; + vm_size_t size; extern unsigned int avail_end; /* @@ -166,7 +166,7 @@ cpu_startup() msgbufmapped = 1; #if VAX750 || VAX650 - if (cpunumber == VAX_750 || cpunumber == VAX_650) + if (vax_cputype == VAX_750 || vax_cputype == VAX_650) if (!mfpr(PR_TODR)) mtpr(todrstopped = 1, PR_TODR); #endif @@ -194,7 +194,7 @@ cpu_startup() panic("startup: table size inconsistency"); /* - * Now allocate buffers proper. They are different than the above in + * Now allocate buffers proper. They are different than the above in * that they usually occupy more virtual memory than physical. */ size = MAXBSIZE * nbuf; @@ -211,12 +211,12 @@ cpu_startup() base = bufpages / nbuf; residual = bufpages % nbuf; for (i = 0; i < nbuf; i++) { - vm_size_t curbufsize; - vm_offset_t curbuf; + vm_size_t curbufsize; + vm_offset_t curbuf; /* * First <residual> buffers get (base+1) physical pages - * allocated for them. The rest get (base) physical pages. + * allocated for them. The rest get (base) physical pages. * * The rest of each buffer occupies virtual space, but has no * physical memory allocated for it. @@ -235,7 +235,7 @@ cpu_startup() 16 * NCARGS, TRUE); /* - * Finally, allocate mbuf pool. Since mclrefcnt is an off-size we + * Finally, allocate mbuf pool. Since mclrefcnt is an off-size we * use the more space efficient malloc in place of kmem_alloc. */ mclrefcnt = (char *) malloc(NMBCLUSTERS + CLBYTES / MCLBYTES, @@ -243,6 +243,13 @@ cpu_startup() bzero(mclrefcnt, NMBCLUSTERS + CLBYTES / MCLBYTES); mb_map = kmem_suballoc(kernel_map, (vm_offset_t *) & mbutl, &maxaddr, VM_MBUF_SIZE, FALSE); + + /* + * Allocate a submap for physio + */ + phys_map = kmem_suballoc(kernel_map, &minaddr, &maxaddr, + VM_PHYS_SIZE, TRUE); + /* * Initialize callouts */ @@ -290,7 +297,7 @@ allocsys(v) { #define valloc(name, type, num) \ - v = (caddr_t)(((name) = (type *)v) + (num)) + v = (caddr_t)(((name) = (type *)v) + (num)) #ifdef REAL_CLISTS valloc(cfree, struct cblock, nclist); @@ -338,14 +345,14 @@ allocsys(v) return v; } -long dumplo = 0; +long dumplo = 0; long dumpmag = 0x8fca0101; void dumpconf() { - int nblks; - extern int dumpdev; + int nblks; + extern int dumpdev; /* * XXX include the final RAM page which is not included in physmem. @@ -369,7 +376,7 @@ dumpconf() void cpu_initclocks() { - (cpu_calls[cpunumber].cpu_clock) (); + (cpu_calls[vax_cputype].cpu_clock) (); } int @@ -380,7 +387,6 @@ cpu_sysctl(a, b, c, d, e, f, g) size_t *d, f; struct proc *g; { - printf("cpu_sysctl:\n"); return (EOPNOTSUPP); } @@ -443,7 +449,7 @@ struct trampframe { unsigned sig; /* Signal number */ unsigned code; /* Info code */ unsigned scp; /* Pointer to struct sigcontext */ - unsigned r0, r1, r2, r3, r4, r5; /* Registers saved when + unsigned r0, r1, r2, r3, r4, r5; /* Registers saved when * interrupt */ unsigned pc; /* Address of signal handler */ unsigned arg; /* Pointer to first (and only) sigreturn @@ -452,17 +458,17 @@ struct trampframe { void sendsig(catcher, sig, mask, code) - sig_t catcher; - int sig, mask; - u_long code; + sig_t catcher; + int sig, mask; + u_long code; { - struct proc *p = curproc; + struct proc *p = curproc; struct sigacts *psp = p->p_sigacts; struct trapframe *syscf; struct sigcontext *sigctx; struct trampframe *trampf; unsigned cursp; - int oonstack = psp->ps_sigstk.ss_flags & SS_ONSTACK; + int oonstack = psp->ps_sigstk.ss_flags & SS_ONSTACK; extern char sigcode[], esigcode[]; /* * Allocate and validate space for the signal handler context. Note @@ -531,8 +537,9 @@ int waittime = -1; static volatile int showto; /* Must be volatile to survive MM on -> MM off */ void -boot(howto) +boot(howto, bootstr) register howto; + char *bootstr; { showto = howto; if ((howto & RB_NOSYNC) == 0 && waittime < 0) { @@ -574,14 +581,14 @@ boot(howto) asm("movl %0,r5":: "g" (showto)); /* How to boot */ - switch (cpunumber) { + switch (vax_cputype) { int state; #if VAX750 || VAX780 || VAX630 case VAX_780: case VAX_750: - case VAX_630: - mtpr(GC_BOOT, PR_TXDB); /* boot command */ + case VAX_TYP_UV2: + mtpr(GC_BOOT, PR_TXDB); /* boot command */ break; #endif #if VAX8600 @@ -642,16 +649,16 @@ void machinecheck(frame) caddr_t frame; { - if ((*cpu_calls[cpunumber].cpu_mchk) (frame) == 0) + if ((*cpu_calls[vax_cputype].cpu_mchk) (frame) == 0) return; - (*cpu_calls[cpunumber].cpu_memerr) (); + (*cpu_calls[vax_cputype].cpu_memerr) (); panic("machine check"); } void dumpsys() { - extern int dumpdev; + extern int dumpdev; msgbufmapped = 0; if (dumpdev == NODEV) @@ -692,7 +699,7 @@ dumpsys() int fuswintr(addr) - caddr_t addr; + const void *addr; { panic("fuswintr: need to be implemented"); return 0; @@ -701,8 +708,8 @@ fuswintr(addr) int suibyte(base, byte) - int byte; void *base; + short byte; { panic("suibyte: need to be implemented"); return 0; @@ -710,8 +717,8 @@ suibyte(base, byte) int suswintr(addr, cnt) - caddr_t addr; - u_int cnt; + void *addr; + short cnt; { panic("suswintr: need to be implemented"); return 0; @@ -772,7 +779,7 @@ int process_sstep(p, sstep) struct proc *p; { - void *ptr; + void *ptr; struct trapframe *tf; if ((p->p_flag & P_INMEM) == 0) @@ -792,5 +799,5 @@ process_sstep(p, sstep) void cmrerr() { - (*cpu_calls[cpunumber].cpu_memerr) (); + (*cpu_calls[vax_cputype].cpu_memerr) (); } diff --git a/sys/arch/vax/vax/mscp.c b/sys/arch/vax/vax/mscp.c deleted file mode 100644 index 427c0258b88..00000000000 --- a/sys/arch/vax/vax/mscp.c +++ /dev/null @@ -1,980 +0,0 @@ -/* $NetBSD: mscp.c,v 1.9 1996/04/08 18:32:50 ragge Exp $ */ - -/* - * Copyright (c) 1988 Regents of the University of California. - * All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Chris Torek. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)mscp.c 7.5 (Berkeley) 12/16/90 - */ - -/* - * MSCP generic driver routines - */ - -#include <sys/param.h> -#include <sys/systm.h> -#include <sys/buf.h> -#include <sys/errno.h> -#include <sys/dkstat.h> -#include <sys/ioctl.h> -#include <sys/disklabel.h> -#include <sys/syslog.h> -#include <sys/proc.h> - -#include <vax/uba/ubavar.h> - -#include <vax/vax/mscp.h> -#include <vax/vax/mscpvar.h> - -void mscp_hexdump __P((struct mscp *)); - - - - -#define PCMD PSWP /* priority for command packet waits */ - -/* - * During transfers, mapping info is saved in the buffer's b_resid. - */ -#define b_info b_resid - -/* - * Get a command packet. Second argument is true iff we are - * to wait if necessary. Return NULL if none are available and - * we cannot wait. - */ -struct mscp * -mscp_getcp(mi, canwait) - register struct mscp_info *mi; - int canwait; -{ -#define mri (&mi->mi_cmd) - register struct mscp *mp; - register int i; - int s = splbio(); - -again: - /* - * Ensure that we have some command credits, and - * that the next command packet is free. - */ - if (mi->mi_credits <= MSCP_MINCREDITS) { - if (!canwait) { - splx(s); - return (NULL); - } - mi->mi_wantcredits = 1; - sleep((caddr_t) &mi->mi_wantcredits, PCMD); - goto again; - } - i = mri->mri_next; - if (mri->mri_desc[i] & MSCP_OWN) { - if (!canwait) { - splx(s); - return (NULL); - } - mi->mi_wantcmd = 1; - sleep((caddr_t) &mi->mi_wantcmd, PCMD); - goto again; - } - mi->mi_credits--; - mri->mri_desc[i] &= ~MSCP_INT; - mri->mri_next = (mri->mri_next + 1) % mri->mri_size; - splx(s); - mp = &mri->mri_ring[i]; - - /* - * Initialise some often-zero fields. - * ARE THE LAST TWO NECESSARY IN GENERAL? IT SURE WOULD BE - * NICE IF DEC SOLD DOCUMENTATION FOR THEIR OWN CONTROLLERS. - */ - mp->mscp_msglen = MSCP_MSGLEN; - mp->mscp_flags = 0; - mp->mscp_modifier = 0; - mp->mscp_seq.seq_bytecount = 0; - mp->mscp_seq.seq_buffer = 0; - mp->mscp_seq.seq_mapbase = 0; -/*???*/ mp->mscp_sccc.sccc_errlgfl = 0; -/*???*/ mp->mscp_sccc.sccc_copyspd = 0; - return (mp); -#undef mri -} - -#ifdef AVOID_EMULEX_BUG -int mscp_aeb_xor = 0x8000bb80; -#endif - -/* - * Do a device go. The driver calls this once it has allocated - * resources for the transfer. Save the resource information in - * bp->b_ubinfo, and finish the MSCP packet. - * - * N.B.: If we were blocked for some time, the drive could have gone - * off line and might still be that way. We should probably handle - * such a case by changing this command into an on line request and - * not dequeuing the transfer after all. - */ -void -mscp_go(mi, mp, info) - register struct mscp_info *mi; - register struct mscp *mp; - int info; -{ - register struct buf *bp, *dp; - - /* - * Now is also the time to move the transfer off the - * controller and drive queues, and shuffle the drive - * queue on the controller queue. The idea is to try - * to keep as many drives busy as possible---to deal - * the controller's credits out to the drives in a `fair - * share' arrangement. (To do this fully would be more - * trouble than it is worth, though.) - */ - dp = mi->mi_tab->b_actf; - bp = dp->b_actf; - dp->b_actf = bp->b_actf; /* transfer off drive queue */ - mi->mi_tab->b_actf = dp->b_hash.le_next;/* drive off ctlr queue */ - MSCP_APPEND(dp, mi->mi_tab, b_hash.le_next); /* then back again */ - -#ifdef oldway - dp->b_actf = bp->av_forw; /* transfer off drive queue */ - mi->mi_tab->b_actf = dp->b_forw; /* drive off ctlr queue */ - MSCP_APPEND(dp, mi->mi_tab, b_forw); /* then back again */ -#endif - - /* - * Move the buffer to the I/O wait queue. - */ - { - struct buf *tmp; - - bp->b_actf=&mi->mi_wtab; - if(mi->mi_wtab.b_actf==&mi->mi_wtab){ - mi->mi_wtab.b_actf=bp; - } else { - tmp=mi->mi_wtab.b_actf; - while(tmp->b_actf!=&mi->mi_wtab) tmp=tmp->b_actf; - tmp->b_actf=bp; - }} - -#ifdef oldway - bp->av_back = mi->mi_wtab.av_back; - bp->av_forw = &mi->mi_wtab; - mi->mi_wtab.av_back->av_forw = bp; - mi->mi_wtab.av_back = bp; -#endif - - /* - * Save the mapping info, finish the command packet, and give - * it to the device. The device's dgo routine should then - * initiate polling. - */ - bp->b_info = info; -#ifdef AVOID_EMULEX_BUG - /* - * The Emulex SC41/MS will occasionally zero the lower half word - * of the command reference number. The upper half word remains - * intact. To keep running, we convert the buffer address into - * a small but nonzero integer that is unique over all pending - * transfers, and store that value in the upper half word. To - * catch occurrances of the bug (so that we can gripe to Emulex), - * we also put a nonzero value in the lower word. - */ - { - register u_int i = mi->mi_nextbp; - - do { /* find a free value */ - if (mi->mi_bp[i] == 0) - goto found; - i = (i + 1) % AEB_MAX_BP; - } while (i != mi->mi_nextbp); - panic("mscp_go: AEB_MAX_BP too small"); -found: - mi->mi_bp[i++] = bp; - mi->mi_nextbp = i % AEB_MAX_BP; - mp->mscp_cmdref = (i << 16) ^ mscp_aeb_xor; - } -#else - mp->mscp_cmdref = (long) bp; -#endif - *mp->mscp_addr |= MSCP_OWN | MSCP_INT; -} - -/* - * Handle a response ring transition. - */ -void -mscp_dorsp(mi) - register struct mscp_info *mi; -{ - register struct uba_device *ui; - register struct buf *bp; - register struct mscp *mp; - register int nextrsp; - struct mscp_driver *md = mi->mi_md; - char *ctlrname, *drivename; - int st, error, info; - - ctlrname = md->md_mname; - drivename = md->md_dname; - nextrsp = mi->mi_rsp.mri_next; -loop: - if (mi->mi_rsp.mri_desc[nextrsp] & MSCP_OWN) { - /* - * No more responses. Remember the next expected - * response index. Check to see if we have some - * credits back, and wake up sleepers if so. - */ - mi->mi_rsp.mri_next = nextrsp; - if (mi->mi_wantcredits && mi->mi_credits > MSCP_MINCREDITS) { - mi->mi_wantcredits = 0; - wakeup((caddr_t) &mi->mi_wantcredits); - } - return; - } - - /* - * Found a response. Update credit information. If there is - * nothing else to do, jump to `done' to get the next response. - */ - mp = &mi->mi_rsp.mri_ring[nextrsp]; - mi->mi_credits += MSCP_CREDITS(mp->mscp_msgtc); - switch (MSCP_MSGTYPE(mp->mscp_msgtc)) { - - case MSCPT_SEQ: - break; - - case MSCPT_DATAGRAM: - (*md->md_dgram)(mi, mp); - goto done; - - case MSCPT_CREDITS: - goto done; - - case MSCPT_MAINTENANCE: - default: - printf("%s%d: unit %d: unknown message type 0x%x ignored\n", - ctlrname, mi->mi_ctlr, mp->mscp_unit, - MSCP_MSGTYPE(mp->mscp_msgtc)); - goto done; - } - - /* - * Controllers are allowed to interrupt as any drive, so we - * must check the command before checking for a drive. - */ - if (mp->mscp_opcode == (M_OP_SETCTLRC | M_OP_END)) { - (*md->md_ctlrdone)(mi, mp); - goto done; - } - - /* - * Find the drive info. If there is none, and this is an - * available attention response, try configuring a new drive. - */ - if (mp->mscp_unit > md->md_ndpc) { - printf("%s%d: unit %d out of range\n", - ctlrname, mi->mi_ctlr, mp->mscp_unit); - goto done; - } - if ((ui = mi->mi_ip[mp->mscp_unit]) == NULL) { - if ((*md->md_unconf)(mi, mp) != MSCP_DONE) { - printf("%s%d: unit %d not configured, ", - ctlrname, mi->mi_ctlr, mp->mscp_unit); - if (mp->mscp_opcode == M_OP_AVAILATTN) - printf("available attn"); - else - printf("stray response op 0x%x status 0x%x", - mp->mscp_opcode, mp->mscp_status); - printf(" ignored\n"); - } - goto done; - } - - /* - * Handle individual responses. - */ - st = mp->mscp_status & M_ST_MASK; - error = 0; - switch (mp->mscp_opcode) { - - case M_OP_END: - /* - * The controller presents a bogus END packet when - * a read/write command is given with an illegal - * block number. This is contrary to the MSCP - * specification (ENDs are to be given only for - * invalid commands), but that is the way of it. - */ - if (st == M_ST_INVALCMD && mp->mscp_cmdref != 0) { - printf("%s%d: bad lbn (%d)?\n", drivename, - ui->ui_unit, (int)mp->mscp_seq.seq_lbn); - error = EIO; - goto rwend; - } - goto unknown; - - case M_OP_ONLINE | M_OP_END: - /* - * Finished an ON LINE request. Call the driver to - * find out whether it succeeded. If so, mark it on - * line. - */ - if (ui->ui_flags & UNIT_ONLINE) { - printf("%s%d: duplicate ONLINE ignored\n", - drivename, ui->ui_unit); - break; - } - if ((*md->md_online)(ui, mp) == MSCP_DONE) - ui->ui_flags |= UNIT_ONLINE; - break; - - case M_OP_GETUNITST | M_OP_END: - /* - * Got unit status. Call the driver to find out - * whether it succeeded, and if so, mark it. - */ - if ((*md->md_gotstatus)(ui, mp) == MSCP_DONE) - ui->ui_flags |= UNIT_HAVESTATUS; - break; - - case M_OP_AVAILATTN: - /* - * The drive went offline and we did not notice. - * Mark it off line now, to force an on line request - * next, so we can make sure it is still the same - * drive. - * - * IF THE UDA DRIVER HAS A COMMAND AWAITING UNIBUS - * RESOURCES, THAT COMMAND MAY GO OUT BEFORE THE ON - * LINE. IS IT WORTH FIXING?? - */ - ui->ui_flags &= ~(UNIT_ONLINE | UNIT_HAVESTATUS); -#ifdef notyet - (*md->md_offline)(ui, mp); -#endif - break; - - case M_OP_READ | M_OP_END: - case M_OP_WRITE | M_OP_END: - /* - * A transfer finished. Get the buffer, and release its - * map registers via ubadone(). If the command finished - * with an off line or available status, the drive went - * off line (the idiot controller does not tell us until - * it comes back *on* line, or until we try to use it). - */ - if (mp->mscp_cmdref == 0) { - /* - * No buffer means there is a bug somewhere! - */ - printf("%s%d: io done, but no buffer?\n", - drivename, ui->ui_unit); - mscp_hexdump(mp); - break; - } - -rwend: -#ifdef AVOID_EMULEX_BUG - { - register u_short *p = (u_short *) &mp->mscp_cmdref; - - /* - * Note any errors on the part of the controller. - * The lower word should be zero after exclusive - * or'ing with mscp_aeb_xor, and the upper should - * then be in the range [1..AEB_MAX_BP]. - */ - mp->mscp_cmdref ^= mscp_aeb_xor; - p[1]--; - if (p[1] >= AEB_MAX_BP) - panic("unrecoverable Emulex screwup"); - if (p[0] == 0) - mi->mi_ok++; - else { - /* - * Calculate the expected response, - * assuming p[1] is correct. The - * actual response is then the expected - * response xor p[0]. - */ - int sb = ((p[1] + 1) << 16) ^ mscp_aeb_xor; - - log(LOG_WARNING, "\ -Emulex SC41/MS screwup: %s%d, got %d correct, then changed 0x%x to 0x%x\n", - ctlrname, mi->mi_ctlr, - mi->mi_ok, sb, sb ^ p[0]); - mi->mi_ok = 0; - } - /* convert index back to buffer, and mark free */ - bp = mi->mi_bp[p[1]]; - mi->mi_bp[p[1]] = 0; - } -#else - bp = (struct buf *) mp->mscp_cmdref; -#ifdef MSCP_PARANOIA - { - register struct buf *q = mi->mi_wtab.av_forw; - - /* - * Ensure that this response corresponds to - * some outstanding request. If not, ignore - * it entirely. This will likely cause a - * Unibus reset soon, after which the controller - * just might behave. - */ - while (q != bp && q != &mi->mi_wtab) - q = q->av_forw; - if (q != bp) { - printf("%s%d: bad response packet ignored\n", - ctlrname, mi->mi_ctlr); - mscp_hexdump(mp); - goto out; - } - } -#endif MSCP_PARANOIA -#endif AVOID_EMULEX_BUG - - /* - * Mark any error-due-to-bad-LBN (via `goto rwend'). - * WHAT STATUS WILL THESE HAVE? IT SURE WOULD BE NICE - * IF DEC SOLD DOCUMENTATION FOR THEIR OWN CONTROLLERS. - */ - if (error) { - bp->b_flags |= B_ERROR; - bp->b_error = error; - } - if (st == M_ST_OFFLINE || st == M_ST_AVAILABLE) { - ui->ui_flags &= ~(UNIT_ONLINE | UNIT_HAVESTATUS); -#ifdef notyet - (*md->md_offline)(ui, mp); -#endif - } - - /* - * Unlink the transfer from the wait queue mi_wtab. - * If there are no more transfers on the drive queue - * for this drive, and it is a profiled disk, turn - * off its busy bit. - */ - - - { /* Insane */ - struct buf *tmp; - - tmp=bp->b_actf; - if(!tmp){ - printf("Found 0 - bad!\n"); - asm("halt"); - } - while(tmp->b_actf!=bp){ - if(!tmp){ - printf("Got lost in chains...\n"); - asm("halt"); - } - tmp=tmp->b_actf; - } - tmp->b_actf=bp->b_actf; - } - if (ui->ui_dk >= 0 && md->md_utab[ui->ui_unit].b_hash.le_next == NULL) - dk_busy &= ~(1 << ui->ui_dk); - -/* Was: bp->av_back->av_forw = bp->av_forw; - bp->av_forw->av_back = bp->av_back; - if (ui->ui_dk >= 0 && md->md_utab[ui->ui_unit].b_forw == NULL) - dk_busy &= ~(1 << ui->ui_dk); -*/ - /* - * If the transfer has something to do with bad - * block forwarding, let the driver handle the - * rest. - */ - if ((bp->b_flags & B_BAD) != 0 && md->md_bb != NULL) { - (*md->md_bb)(ui, mp, bp); - goto out; - } - - /* - * If the transfer failed, give the driver a crack - * at fixing things up. - */ - if (st != M_ST_SUCCESS) { - switch ((*md->md_ioerr)(ui, mp, bp)) { - - case MSCP_DONE: /* fixed */ - break; - - case MSCP_RESTARTED: /* still working on it */ - goto out; - - case MSCP_FAILED: /* no luck */ - diskerr(bp, drivename, "hard error", - LOG_PRINTF, -1, md->md_lab ? - &md->md_lab[ui->ui_unit] : md->md_lab); - mscp_printevent(mp); - bp->b_flags |= B_ERROR; - bp->b_error = EIO; - break; - } - } - - /* - * Set the residual count and mark the transfer as - * done. If the I/O wait queue is now empty, release - * the shared BDP, if any. - */ - info = bp->b_info; /* we are about to clobber it */ - bp->b_resid = bp->b_bcount - mp->mscp_seq.seq_bytecount; - (*md->md_iodone)(mi, bp, info); -out: - break; - - case M_OP_REPLACE | M_OP_END: - /* - * A replace operation finished. Just let the driver - * handle it (if it does replaces). - */ - if (md->md_replace == NULL) - printf("%s%d: bogus REPLACE end\n", - drivename, ui->ui_unit); - else - (*md->md_replace)(ui, mp); - break; - - default: - /* - * If it is not one of the above, we cannot handle it. - * (And we should not have received it, for that matter.) - */ -unknown: - printf("%s%d: unknown opcode 0x%x status 0x%x ignored\n", - mi->mi_md->md_dname, ui->ui_unit, - mp->mscp_opcode, mp->mscp_status); - mscp_hexdump(mp); - break; - } - - /* - * If the drive needs to be put back in the controller queue, - * do that now. (`bp' below ought to be `dp', but they are all - * struct buf *.) Note that b_active was cleared in the driver; - * we presume that there is something to be done, hence reassert it. - */ - if (ui->ui_flags & UNIT_REQUEUE) { - bp = &md->md_utab[ui->ui_unit]; - if (bp->b_active) panic("mscp_dorsp requeue"); - MSCP_APPEND(bp, mi->mi_tab, b_hash.le_next); -/* Was: MSCP_APPEND(bp, mi->mi_tab, b_forw); */ - bp->b_active = 1; - ui->ui_flags &= ~UNIT_REQUEUE; - } - -done: - /* - * Give back the response packet, and take a look at the next. - */ - mp->mscp_msglen = MSCP_MSGLEN; - mi->mi_rsp.mri_desc[nextrsp] |= MSCP_OWN; - nextrsp = (nextrsp + 1) % mi->mi_rsp.mri_size; - goto loop; -} - -/* - * Dump the entire contents of an MSCP packet in hex. Mainly useful - * for debugging.... - */ -void -mscp_hexdump(mp) - register struct mscp *mp; -{ - register long *p = (long *) mp; - register int i = mp->mscp_msglen; - - if (i > 256) /* sanity */ - i = 256; - i /= sizeof (*p); /* ASSUMES MULTIPLE OF sizeof(long) */ - while (--i >= 0) - printf("0x%x ", (int)*p++); - printf("\n"); -} - -/* - * Requeue outstanding transfers, e.g., after bus reset. - * Also requeue any drives that have on line or unit status - * info pending. - */ -void -mscp_requeue(mi) - struct mscp_info *mi; -{ - register struct uba_device *ui; - register struct mscp_driver *md = mi->mi_md; - register struct buf *bp, *dp; - register int unit; - struct buf *nextbp; - - /* - * Clear the controller chain. Mark everything un-busy; we - * will soon fix any that are in fact busy. - */ - mi->mi_tab->b_actf = NULL; - mi->mi_tab->b_active = 0; - for (unit = 0, dp = md->md_utab; unit < md->md_nunits; unit++, dp++) { - ui = md->md_dinfo[unit]; - if (ui == NULL || !ui->ui_alive || ui->ui_ctlr != mi->mi_ctlr) - continue; /* not ours */ - dp->b_hash.le_next = NULL; - dp->b_active = 0; - } - - /* - * Scan the wait queue, linking buffers onto drive queues. - * Note that these must be put at the front of the drive queue, - * lest we reorder I/O operations. - */ - for (bp = *mi->mi_wtab.b_actb; bp != &mi->mi_wtab; bp = nextbp) { - nextbp = *bp->b_actb; - dp = &md->md_utab[minor(bp->b_dev) >> md->md_unitshift]; - bp->b_actf = dp->b_actf; - if (dp->b_actf == NULL) - dp->b_actb = (void *)bp; - dp->b_actf = bp; - } - mi->mi_wtab.b_actf = *mi->mi_wtab.b_actb = &mi->mi_wtab; - - /* - * Scan for drives waiting for on line or status responses, - * and for drives with pending transfers. Put these on the - * controller queue, and mark the controller busy. - */ - for (unit = 0, dp = md->md_utab; unit < md->md_nunits; unit++, dp++) { - ui = md->md_dinfo[unit]; - if (ui == NULL || !ui->ui_alive || ui->ui_ctlr != mi->mi_ctlr) - continue; - ui->ui_flags &= ~(UNIT_HAVESTATUS | UNIT_ONLINE); - if ((ui->ui_flags & UNIT_REQUEUE) == 0 && dp->b_actf == NULL) - continue; - ui->ui_flags &= ~UNIT_REQUEUE; - MSCP_APPEND(dp, mi->mi_tab, b_hash.le_next); - - dp->b_active = 1; - mi->mi_tab->b_active = 1; - } - -#ifdef AVOID_EMULEX_BUG - /* - * ... and clear the index-to-buffer table. - */ - for (unit = 0; unit < AEB_MAX_BP; unit++) - mi->mi_bp[unit] = 0; -#endif -} - - -/* - * MSCP error reporting - */ - -/* - * Messages for the various subcodes. - */ -static char unknown_msg[] = "unknown subcode"; - -/* - * Subcodes for Success (0) - */ -static char *succ_msgs[] = { - "normal", /* 0 */ - "spin down ignored", /* 1 = Spin-Down Ignored */ - "still connected", /* 2 = Still Connected */ - unknown_msg, - "dup. unit #", /* 4 = Duplicate Unit Number */ - unknown_msg, - unknown_msg, - unknown_msg, - "already online", /* 8 = Already Online */ - unknown_msg, - unknown_msg, - unknown_msg, - unknown_msg, - unknown_msg, - unknown_msg, - unknown_msg, - "still online", /* 16 = Still Online */ -}; - -/* - * Subcodes for Invalid Command (1) - */ -static char *icmd_msgs[] = { - "invalid msg length", /* 0 = Invalid Message Length */ -}; - -/* - * Subcodes for Command Aborted (2) - */ -/* none known */ - -/* - * Subcodes for Unit Offline (3) - */ -static char *offl_msgs[] = { - "unknown drive", /* 0 = Unknown, or online to other ctlr */ - "not mounted", /* 1 = Unmounted, or RUN/STOP at STOP */ - "inoperative", /* 2 = Unit Inoperative */ - unknown_msg, - "duplicate", /* 4 = Duplicate Unit Number */ - unknown_msg, - unknown_msg, - unknown_msg, - "in diagnosis", /* 8 = Disabled by FS or diagnostic */ -}; - -/* - * Subcodes for Unit Available (4) - */ -/* none known */ - -/* - * Subcodes for Media Format Error (5) - */ -static char *media_fmt_msgs[] = { - "fct unread - edc", /* 0 = FCT unreadable */ - "invalid sector header",/* 1 = Invalid Sector Header */ - "not 512 sectors", /* 2 = Not 512 Byte Sectors */ - "not formatted", /* 3 = Not Formatted */ - "fct ecc", /* 4 = FCT ECC */ -}; - -/* - * Subcodes for Write Protected (6) - * N.B.: Code 6 subcodes are 7 bits higher than other subcodes - * (i.e., bits 12-15). - */ -static char *wrprot_msgs[] = { - unknown_msg, - "software", /* 1 = Software Write Protect */ - "hardware", /* 2 = Hardware Write Protect */ -}; - -/* - * Subcodes for Compare Error (7) - */ -/* none known */ - -/* - * Subcodes for Data Error (8) - */ -static char *data_msgs[] = { - "forced error", /* 0 = Forced Error (software) */ - unknown_msg, - "header compare", /* 2 = Header Compare Error */ - "sync timeout", /* 3 = Sync Timeout Error */ - unknown_msg, - unknown_msg, - unknown_msg, - "uncorrectable ecc", /* 7 = Uncorrectable ECC */ - "1 symbol ecc", /* 8 = 1 bit ECC */ - "2 symbol ecc", /* 9 = 2 bit ECC */ - "3 symbol ecc", /* 10 = 3 bit ECC */ - "4 symbol ecc", /* 11 = 4 bit ECC */ - "5 symbol ecc", /* 12 = 5 bit ECC */ - "6 symbol ecc", /* 13 = 6 bit ECC */ - "7 symbol ecc", /* 14 = 7 bit ECC */ - "8 symbol ecc", /* 15 = 8 bit ECC */ -}; - -/* - * Subcodes for Host Buffer Access Error (9) - */ -static char *host_buffer_msgs[] = { - unknown_msg, - "odd xfer addr", /* 1 = Odd Transfer Address */ - "odd xfer count", /* 2 = Odd Transfer Count */ - "non-exist. memory", /* 3 = Non-Existent Memory */ - "memory parity", /* 4 = Memory Parity Error */ -}; - -/* - * Subcodes for Controller Error (10) - */ -static char *cntlr_msgs[] = { - unknown_msg, - "serdes overrun", /* 1 = Serialiser/Deserialiser Overrun */ - "edc", /* 2 = Error Detection Code? */ - "inconsistant internal data struct",/* 3 = Internal Error */ -}; - -/* - * Subcodes for Drive Error (11) - */ -static char *drive_msgs[] = { - unknown_msg, - "sdi command timeout", /* 1 = SDI Command Timeout */ - "ctlr detected protocol",/* 2 = Controller Detected Protocol Error */ - "positioner", /* 3 = Positioner Error */ - "lost rd/wr ready", /* 4 = Lost R/W Ready Error */ - "drive clock dropout", /* 5 = Lost Drive Clock */ - "lost recvr ready", /* 6 = Lost Receiver Ready */ - "drive detected error", /* 7 = Drive Error */ - "ctlr detected pulse or parity",/* 8 = Pulse or Parity Error */ -}; - -/* - * The following table correlates message codes with the - * decoding strings. - */ -struct code_decode { - char *cdc_msg; - int cdc_nsubcodes; - char **cdc_submsgs; -} code_decode[] = { -#define SC(m) sizeof (m) / sizeof (m[0]), m - {"success", SC(succ_msgs)}, - {"invalid command", SC(icmd_msgs)}, - {"command aborted", 0, 0}, - {"unit offline", SC(offl_msgs)}, - {"unit available", 0, 0}, - {"media format error", SC(media_fmt_msgs)}, - {"write protected", SC(wrprot_msgs)}, - {"compare error", 0, 0}, - {"data error", SC(data_msgs)}, - {"host buffer access error", SC(host_buffer_msgs)}, - {"controller error", SC(cntlr_msgs)}, - {"drive error", SC(drive_msgs)}, -#undef SC -}; - -/* - * Print the decoded error event from an MSCP error datagram. - */ -void -mscp_printevent(mp) - struct mscp *mp; -{ - register int event = mp->mscp_event; - register struct code_decode *cdc; - int c, sc; - char *cm, *scm; - - /* - * The code is the lower six bits of the event number (aka - * status). If that is 6 (write protect), the subcode is in - * bits 12-15; otherwise, it is in bits 5-11. - * I WONDER WHAT THE OTHER BITS ARE FOR. IT SURE WOULD BE - * NICE IF DEC SOLD DOCUMENTATION FOR THEIR OWN CONTROLLERS. - */ - c = event & M_ST_MASK; - sc = (c != 6 ? event >> 5 : event >> 12) & 0x7ff; - if (c >= sizeof code_decode / sizeof code_decode[0]) - cm = "- unknown code", scm = "??"; - else { - cdc = &code_decode[c]; - cm = cdc->cdc_msg; - if (sc >= cdc->cdc_nsubcodes) - scm = unknown_msg; - else - scm = cdc->cdc_submsgs[sc]; - } - printf(" %s (%s) (code %d, subcode %d)\n", cm, scm, c, sc); -} - -/* - * Print the code and logical block number for an error packet. - * THIS IS PROBABLY PECULIAR TO DISK DRIVES. IT SURE WOULD BE - * NICE IF DEC SOLD DOCUMENTATION FOR THEIR OWN CONTROLLERS. - */ -void -mscp_decodeerror(name, ctlr, mp) - char *name; - int ctlr; - register struct mscp *mp; -{ - /* - * For bad blocks, mp->mscp_erd.erd_hdr identifies a code and - * the logical block number. Code 0 is a regular block; code 6 - * is a replacement block. The remaining codes are currently - * undefined. The code is in the upper four bits of the header - * (bits 0-27 are the lbn). - */ - int issoft = mp->mscp_flags & (M_LF_SUCC | M_LF_CONT); - static char *codemsg[16] = { - "lbn", "code 1", "code 2", "code 3", - "code 4", "code 5", "rbn", "code 7", - "code 8", "code 9", "code 10", "code 11", - "code 12", "code 13", "code 14", "code 15" - }; -#define BADCODE(h) (codemsg[(unsigned)(h) >> 28]) -#define BADLBN(h) ((h) & 0xfffffff) - - printf("%s%d: %s error datagram%s:", name, ctlr, - issoft ? "soft" : "hard", - mp->mscp_flags & M_LF_CONT ? " (continuing)" : ""); - switch (mp->mscp_format & 0377) { - - case M_FM_CTLRERR: /* controller error */ - break; - - case M_FM_BUSADDR: /* host memory access error */ - printf(" memory addr 0x%x:", (int)mp->mscp_erd.erd_busaddr); - break; - - case M_FM_DISKTRN: - printf(" unit %d: level %d retry %d, %s %d:", - mp->mscp_unit, - mp->mscp_erd.erd_level, mp->mscp_erd.erd_retry, - BADCODE(mp->mscp_erd.erd_hdr), - (int)BADLBN(mp->mscp_erd.erd_hdr)); - break; - - case M_FM_SDI: - printf(" unit %d: %s %d:", mp->mscp_unit, - BADCODE(mp->mscp_erd.erd_hdr), - (int)BADLBN(mp->mscp_erd.erd_hdr)); - break; - - case M_FM_SMLDSK: - printf(" unit %d: small disk error, cyl %d:", - mp->mscp_unit, mp->mscp_erd.erd_sdecyl); - break; - - default: - printf(" unit %d: unknown error, format 0x%x:", - mp->mscp_unit, mp->mscp_format); - } - mscp_printevent(mp); -#undef BADCODE -#undef BADLBN -} diff --git a/sys/arch/vax/vax/mscpvar.h b/sys/arch/vax/vax/mscpvar.h deleted file mode 100644 index 52213fab869..00000000000 --- a/sys/arch/vax/vax/mscpvar.h +++ /dev/null @@ -1,242 +0,0 @@ -/* $NetBSD: mscpvar.h,v 1.7 1996/04/08 18:32:51 ragge Exp $ */ - -/* - * Copyright (c) 1988 Regents of the University of California. - * All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Chris Torek. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)mscpvar.h 7.3 (Berkeley) 6/28/90 - */ - -/* - * MSCP generic driver configuration - */ - -/* - * Enabling MSCP_PARANOIA makes the response code perform various checks - * on the hardware. (Right now it verifies only the buffer pointer in - * mscp_cmdref.) - * - * Enabling AVOID_EMULEX_BUG selects an alternative method of identifying - * transfers in progress, which gets around a rather peculiar bug in the - * SC41/MS. Enabling MSCP_PARANOIA instead should work, but will cause - * `extra' Unibus resets. - * - * Either of these flags can simply be included as an `options' line in - * your configuration file. - */ - -/* #define MSCP_PARANOIA */ -/* #define AVOID_EMULEX_BUG */ - -/* - * Per driver information. - * - * md_ndpc sets the maximum unit number allowed in response packets. - * md_nunits is the number of drives attached to all controllers. - * md_unitshift is the divisor for converting a minor device number - * to a unit index for the device queues in md_utab. - * - * The routines are called from the generic response dispatcher. - * THE FOLLOWING IS OUT OF DATE - * The first three (dgram, ctlrdone, and unconf) get passed a pointer - * to the uba_ctlr and to the packet; the rest get a pointer to the - * uba_device and to the packet (`um, mp' and `ui, mp' respectively). - * The routines unconf, online, gotstatus, and ioerr are functions - * and should return one of the values given below. In addition, - * the ioerr and bb routines get a third argument, `bp': a pointer - * to the buffer describing the transfer in error. - * END OUT OF DATE - */ -struct mscp_info; - -struct mscp_driver { - int md_ndpc; /* number of drives per ctlr */ - int md_nunits; /* total number drives (all ctlrs) */ - int md_unitshift; /* device number to unit: >> count */ - struct buf *md_utab; /* pointer to device queues */ - struct disklabel *md_lab; /* pointer to devicee disklabels */ - struct uba_device **md_dinfo; /* pointer to device info */ - /* error datagram */ - void (*md_dgram) __P((struct mscp_info *, struct mscp *)); - /* controller operation complete */ - void (*md_ctlrdone) __P((struct mscp_info *, struct mscp *)); - /* response from unconfigured drive */ - int (*md_unconf) __P((struct mscp_info *, struct mscp *)); - /* normal I/O is done */ - void (*md_iodone) __P((struct mscp_info *, struct buf *, int)); - /* drive on line */ - int (*md_online) __P((struct uba_device *, struct mscp *));/*XXX*/ - /* got unit status */ - int (*md_gotstatus) __P((struct uba_device *, struct mscp *)); - /* replace done */ - void (*md_replace) __P((struct uba_device *, struct mscp *)); - /* read or write failed */ - int (*md_ioerr) __P((struct uba_device *, struct mscp *, - struct buf *)); - /* B_BAD io done */ - void (*md_bb) __P((struct uba_device *, struct mscp *, - struct buf *)); - char *md_mname; /* name of controllers */ - char *md_dname; /* name of drives */ -}; - -/* - * Return values from functions. - * MSCP_RESTARTED is peculiar to I/O errors. - */ -#define MSCP_DONE 0 /* all ok */ -#define MSCP_FAILED 1 /* no go */ -#define MSCP_RESTARTED 2 /* transfer restarted */ - -/* - * Ring information, per ring (one each for commands and responses). - */ -struct mscp_ri { - int mri_size; /* ring size */ - int mri_next; /* next (expected|free) */ - long *mri_desc; /* base address of descriptors */ - struct mscp *mri_ring; /* base address of packets */ -}; - -/* - * Per device information. - * - * mi_ip is a pointer to the inverting pointers (things that get `ui's - * given unit numbers) FOR THIS CONTROLLER (NOT the whole set!). - * - * mi_wtab holds a queue of those transfers that were started but have - * not yet finished. Other Unibus drivers do not need this as they hand - * out requests one at a time. MSCP devices, however, take a slew of - * requests and pick their own order to execute them. This means that - * we have to have a place to move transfers that were given to the - * controller, so we can tell those apart from those that have not yet - * been handed out; mi_wtab is that place. - */ -struct mscp_info { - struct mscp_driver *mi_md; /* pointer to driver info */ - int mi_ctlr; /* controller index */ - struct buf *mi_tab; /* pointer to ctlr's drive queue */ - struct uba_device **mi_ip; /* pointer to inverting pointers */ - struct mscp_ri mi_cmd; /* MSCP command ring info */ - struct mscp_ri mi_rsp; /* MSCP response ring info */ - short mi_credits; /* transfer credits */ - char mi_wantcmd; /* waiting for command packet */ - char mi_wantcredits; /* waiting for transfer credits */ - struct buf mi_wtab; /* transfer wait queue */ -#ifdef AVOID_EMULEX_BUG -#define AEB_MAX_BP 32 /* max pend xfers (power of 2) XXX */ - volatile struct buf *mi_bp[AEB_MAX_BP]; /* xfer no. to buffer */ - u_int mi_nextbp; /* generates unique xfer no's */ - int mi_ok; /* for error rate statistics */ -#endif AVOID_EMULEX_BUG -}; - -/* - * We have run out of credits when mi_credits is <= MSCP_MINCREDITS. - * It is still possible to issue one command in this case, but it must - * not be a data transfer. E.g., `get command status' or `abort command' - * is legal, while `read' is not. - */ -#define MSCP_MINCREDITS 1 - -/* - * Flags for mscp_getcp(). - */ -#define MSCP_WAIT 1 -#define MSCP_DONTWAIT 0 - - /* get a command packet */ -struct mscp *mscp_getcp __P((struct mscp_info *, int)); - -/* - * Unit flags - */ -#define UNIT_ONLINE 0x01 /* drive is on line */ -#define UNIT_HAVESTATUS 0x02 /* got unit status */ -#define UNIT_REQUEUE 0x04 /* requeue after response */ - -/* - * Handle a command ring transition: wake up sleepers for command packets. - * This is too simple to bother with a function call. - */ -#define MSCP_DOCMD(mi) { \ - if ((mi)->mi_wantcmd) { \ - (mi)->mi_wantcmd = 0; \ - wakeup((caddr_t) &(mi)->mi_wantcmd); \ - } \ -} - -/* - * The following macro appends a buffer to a drive queue or a drive to - * a controller queue, given the name of the forward link. Use as - * `APPEND(dp, &um->um_tab, b_forw)' or `APPEND(bp, dp, av_forw)', - * where `bp' is a transfer request, `dp' is a drive queue, and `um_tab' - * is a controller queue. (That is, the forward link for controller - * queues is `b_forw'; for drive queues, it is `av_forw'.) - * - * Changed to new buf structure 940605/Ragge - */ -#define MSCP_APPEND(bp, queue, link) { \ - struct buf *tmp; \ - \ - (bp)->link = NULL; \ - if ((queue)->b_actf == NULL) \ - (queue)->b_actf = (bp); \ - else { \ - tmp=(queue)->b_actf; \ - while(tmp->link) tmp=tmp->link; \ - tmp->link = (bp); \ - } \ -} - -/* Old APPEND macro */ -/* -#define APPEND(bp, queue, link) { \ - (bp)->link = NULL; \ - if ((queue)->b_actf == NULL) \ - (queue)->b_actf = (bp); \ - else \ - (queue)->b_actl->link = (bp); \ - (queue)->b_actl = (bp); \ -} -*/ - -/* Prototypes */ - -void mscp_printevent __P((struct mscp *)); -void mscp_go __P((struct mscp_info *, struct mscp *, int)); -void mscp_requeue __P((struct mscp_info *)); -void mscp_dorsp __P((struct mscp_info *)); -void mscp_decodeerror __P((char *, int, struct mscp *)); - diff --git a/sys/arch/vax/vax/ns_cksum.c b/sys/arch/vax/vax/ns_cksum.c index 0a7f59bbba7..b6401f8ff37 100644 --- a/sys/arch/vax/vax/ns_cksum.c +++ b/sys/arch/vax/vax/ns_cksum.c @@ -1,4 +1,4 @@ -/* $NetBSD: ns_cksum.c,v 1.1 1996/03/03 11:54:37 ragge Exp $ */ +/* $NetBSD: ns_cksum.c,v 1.3 1996/10/13 03:35:55 christos Exp $ */ /* * Copyright (c) 1985, 1986 Regents of the University of California. * All rights reserved. diff --git a/sys/arch/vax/vax/pmap.c b/sys/arch/vax/vax/pmap.c index 1263ff18a49..4b3338b67ec 100644 --- a/sys/arch/vax/vax/pmap.c +++ b/sys/arch/vax/vax/pmap.c @@ -1,4 +1,5 @@ -/* $NetBSD: pmap.c,v 1.27 1996/05/19 16:44:20 ragge Exp $ */ +/* $OpenBSD: pmap.c,v 1.7 1997/01/15 23:25:20 maja Exp $ */ +/* $NetBSD: pmap.c,v 1.30 1996/10/13 03:35:57 christos Exp $ */ /* * Copyright (c) 1994 Ludd, University of Lule}, Sweden. * All rights reserved. @@ -58,8 +59,8 @@ static void free_pv_entry __P((pv_entry_t)); static int remove_pmap_from_mapping __P((pv_entry_t, pmap_t)); -#define ISTACK_SIZE (4 * NBPG) -#define PTE_TO_PV(pte) (PHYS_TO_PV((pte&PG_FRAME)<<PGSHIFT)) +#define ISTACK_SIZE (4 * NBPG) +#define PTE_TO_PV(pte) (PHYS_TO_PV((pte&PG_FRAME)<<PGSHIFT)) struct pmap kernel_pmap_store; @@ -71,21 +72,55 @@ static int kernel_prot[]={ PG_NONE, PG_KR, PG_KW, PG_KW, static pv_entry_t pv_head = NULL; static unsigned int pv_count = 0; -pv_entry_t pv_table; /* array of entries, - one per LOGICAL page */ +pv_entry_t pv_table; /* array of entries, + one per LOGICAL page */ unsigned *pte_cmap; -void *scratch; +void *scratch; #ifdef PMAPDEBUG int startpmapdebug = 0; -extern int startsysc, faultdebug; +/* extern int startsysc, faultdebug; */ #endif unsigned int vmmap; vm_map_t pte_map; vm_offset_t avail_start, avail_end; -vm_offset_t virtual_avail, virtual_end; /* Available virtual memory */ +vm_offset_t virtual_avail, virtual_end; /* Available virtual memory */ + +/* + * badaddr() doesn't work on some VAXstations + * (I've checked KA410 and KA43, don't know about others yet). + * + * Checking all pages of physical memory starting from address 0x0 and + * waiting for being trapped by badaddr() is not enough on these machines: + * + * on VS2000/KA410 physical memory appears more than once. + * eg. on a machine with 10MB memory (2MB base + 8MB extension) + * the extension memory is mapped to 0x200000, 0xA00000, and so on. + * + * On VS3100/KA43 writing to addresses above the available memory + * is implemented as a nop. + * + * On both of these machines the old check/count routine resulted in an + * endless loop. Thus while checking/counting the memory, we write a + * pattern to all the pages we are visiting. (leaving a hole for kernel). + * If we access a page which already holds a valid pattern, then we've + * seen this page already and thus reached the highest memory-address. + * If the page doesn't hold the pattern directly after having written + * it, then the page is bad or not available and we've reached the end. + * + * VAXen can't have more than 512(?) MB of physical memory, so we also + * have an upper limit for how much pages to check. If we're not trapped + * within this address-range, something went wrong and we're assuming + * some save amount of physical memory. This might be paranoid, but... + */ +#ifndef MAX_PHYSMEM_AVAIL +#define MAX_PHYSMEM_AVAIL 512*1024*1024 +#endif +#ifndef MIN_PHYSMEM_AVAIL +#define MIN_PHYSMEM_AVAIL 8*1024*1024 +#endif /* * pmap_bootstrap(). @@ -104,6 +139,31 @@ pmap_bootstrap() p0pmap = &vmspace0.vm_pmap; sysptsize = SYSPTSIZE; + + /* + * Because of the badaddr() problem with some VAXstations we + * compare the first page of memory (the SCB) with the new + * counted up pages for equality. It's very unlikely that + * another page will hold the same info as the SCB. + * This is neccessary only if badaddr() doesn't work, but on other + * machines checking the pattern doesn't hurt anyway... + */ + + /* Kickoff for memory checking */ + avail_end = 0x200000; /* 2 MB */ + + while (badaddr((caddr_t)avail_end, 4) == 0) { +#if VAX410 || VAX420 || VAX43 || VAX46 || VAX49 || VAX50 + if (bcmp(0, (caddr_t)avail_end, NBPG) == 0) + break; +#endif + avail_end += NBPG * 128;/* Memory is checked in 64K hunks */ + } + +#if VAX410 || VAX420 || VAX43 || VAX46 || VAX49 || VAX50 + sysptsize += (16 * 1024) >> PGSHIFT; /* guc->uc_sysptSpace ?? */ +#endif + /* * Virtual_* and avail_* is used for mapping of system page table. * First set them to their max values and then decrement them. @@ -112,8 +172,6 @@ pmap_bootstrap() * a variable here that is changed dependent of the physical * memory size. */ - while (!badaddr((caddr_t)avail_end, 4)) /* Memory is in 64K hunks */ - avail_end += NBPG * 128; sysptsize += avail_end >> PGSHIFT; virtual_avail = KERNBASE; virtual_end = KERNBASE + sysptsize * NBPG; @@ -137,7 +195,7 @@ pmap_bootstrap() VM_PROT_READ|VM_PROT_WRITE); /* Map System Page Table and zero it, Sysmap already set. */ - mtpr(avail_start, PR_SBR); + mtpr(avail_start, PR_SBR); MAPPHYS(junk, (ROUND_PAGE(sysptsize * 4) >> PGSHIFT), VM_PROT_READ|VM_PROT_WRITE); @@ -176,40 +234,42 @@ pmap_bootstrap() bcopy(0, (void *)avail_start, NBPG >> 1); mtpr(avail_start, PR_SCBB); bzero(0, NBPG >> 1); - (cpu_calls[cpunumber].cpu_steal_pages)(); + (cpu_calls[vax_cputype].cpu_steal_pages)(); + avail_start = ROUND_PAGE(avail_start); + virtual_avail = ROUND_PAGE(virtual_avail); #ifdef PMAPDEBUG - printf("Sysmap %x, istack %x, scratch %x\n",Sysmap,istack,scratch); - printf("etext %x\n", &etext); - printf("SYSPTSIZE %x, USRPTSIZE %x\n",sysptsize,USRPTSIZE); - printf("pv_table %x, vmmap %x, pte_cmap %x\n", - pv_table,vmmap,pte_cmap); - printf("avail_start %x, avail_end %x\n",avail_start,avail_end); - printf("virtual_avail %x,virtual_end %x\n",virtual_avail,virtual_end); - printf("clearomr: %x \n",(uint)vmmap-(uint)Sysmap); - printf("faultdebug %x, startsysc %x\n",&faultdebug, &startsysc); - printf("startpmapdebug %x\n",&startpmapdebug); + printf("Sysmap %x, istack %x, scratch %x\n",Sysmap,istack,scratch); + printf("etext %x\n", &etext); + printf("SYSPTSIZE %x, USRPTSIZE %x\n",sysptsize,USRPTSIZE); + printf("pv_table %x, vmmap %x, pte_cmap %x\n", + pv_table,vmmap,pte_cmap); + printf("avail_start %x, avail_end %x\n",avail_start,avail_end); + printf("virtual_avail %x,virtual_end %x\n",virtual_avail,virtual_end); + printf("clearomr: %x \n",(uint)vmmap-(uint)Sysmap); +/* printf("faultdebug %x, startsysc %x\n",&faultdebug, &startsysc);*/ + printf("startpmapdebug %x\n",&startpmapdebug); #endif - /* Init kernel pmap */ - pmap_kernel()->ref_count = 1; - simple_lock_init(&pmap_kernel()->pm_lock); - p0pmap->pm_pcb = (struct pcb *)proc0paddr; + /* Init kernel pmap */ + pmap_kernel()->ref_count = 1; + simple_lock_init(&pmap_kernel()->pm_lock); + p0pmap->pm_pcb = (struct pcb *)proc0paddr; - p0pmap->pm_pcb->P1BR = (void *)0x80000000; - p0pmap->pm_pcb->P0BR = (void *)0x80000000; - p0pmap->pm_pcb->P1LR = 0x200000; - p0pmap->pm_pcb->P0LR = AST_PCB; - mtpr(0x80000000, PR_P1BR); - mtpr(0x80000000, PR_P0BR); - mtpr(0x200000, PR_P1LR); - mtpr(AST_PCB, PR_P0LR); + p0pmap->pm_pcb->P1BR = (void *)0x80000000; + p0pmap->pm_pcb->P0BR = (void *)0x80000000; + p0pmap->pm_pcb->P1LR = 0x200000; + p0pmap->pm_pcb->P0LR = AST_PCB; + mtpr(0x80000000, PR_P1BR); + mtpr(0x80000000, PR_P0BR); + mtpr(0x200000, PR_P1LR); + mtpr(AST_PCB, PR_P0LR); /* * Now everything should be complete, start virtual memory. */ - mtpr(sysptsize, PR_SLR); - mtpr(1, PR_MAPEN); + mtpr(sysptsize, PR_SLR); + mtpr(1, PR_MAPEN); } @@ -238,7 +298,7 @@ pmap_t pmap_create(phys_size) vm_size_t phys_size; { - pmap_t pmap; + pmap_t pmap; #ifdef PMAPDEBUG if(startpmapdebug)printf("pmap_create: phys_size %x\n",phys_size); @@ -310,10 +370,10 @@ if(startpmapdebug)printf("pmap_destroy: pmap %x\n",pmap); void pmap_enter(pmap, v, p, prot, wired) register pmap_t pmap; - vm_offset_t v; - vm_offset_t p; - vm_prot_t prot; - boolean_t wired; + vm_offset_t v; + vm_offset_t p; + vm_prot_t prot; + boolean_t wired; { u_int i, pte, s, *patch; pv_entry_t pv, tmp; @@ -398,6 +458,10 @@ pmap_bootstrap_alloc(size) { void *mem; +#ifdef PMAPDEBUG +if(startpmapdebug) +printf("pmap_bootstrap_alloc: size 0x %x\n",size); +#endif size = round_page(size); mem = (void *)virtual_avail; virtual_avail = pmap_map(virtual_avail, avail_start, @@ -455,8 +519,8 @@ void pmap_protect(pmap, start, end, prot) pmap_t pmap; vm_offset_t start; - vm_offset_t end; - vm_prot_t prot; + vm_offset_t end; + vm_prot_t prot; { int pte, *patch, s; @@ -690,7 +754,7 @@ free_pv_entry(entry) boolean_t pmap_is_referenced(pa) - vm_offset_t pa; + vm_offset_t pa; { struct pv_entry *pv; u_int *pte,spte=0; @@ -717,9 +781,9 @@ pmap_is_modified(pa) pv=PHYS_TO_PV(pa); if(!pv->pv_pmap) return 0; do { - pte=(u_int *)pmap_virt2pte(pv->pv_pmap,pv->pv_va); - spte|=*pte++; - spte|=*pte; + pte=(u_int *)pmap_virt2pte(pv->pv_pmap,pv->pv_va); + spte|=*pte++; + spte|=*pte; } while((pv=pv->pv_next)); return((spte&PG_M)?1:0); } @@ -731,7 +795,7 @@ pmap_is_modified(pa) void pmap_clear_reference(pa) - vm_offset_t pa; + vm_offset_t pa; { struct pv_entry *pv; int *pte; @@ -758,7 +822,7 @@ if(startpmapdebug) printf("pmap_clear_reference: pa %x, pv %x\n",pa,pv); void pmap_clear_modify(pa) - vm_offset_t pa; + vm_offset_t pa; { struct pv_entry *pv; u_int *pte; @@ -775,8 +839,8 @@ pmap_clear_modify(pa) void pmap_change_wiring(pmap, va, wired) register pmap_t pmap; - vm_offset_t va; - boolean_t wired; + vm_offset_t va; + boolean_t wired; { int *pte; #ifdef PMAPDEBUG @@ -791,14 +855,14 @@ if(startpmapdebug) printf("pmap_change_wiring: pmap %x, va %x, wired %x\n", } /* - * pmap_page_protect: + * pmap_page_protect: * - * Lower the permission for all mappings to a given page. + * Lower the permission for all mappings to a given page. */ void pmap_page_protect(pa, prot) - vm_offset_t pa; - vm_prot_t prot; + vm_offset_t pa; + vm_prot_t prot; { pv_entry_t pv,opv; u_int s,*pte,*pte1,nyprot,kprot; @@ -859,10 +923,10 @@ if(startpmapdebug) printf("pmap_page_protect: pa %x, prot %x\n",pa, prot); } /* - * pmap_zero_page zeros the specified (machine independent) - * page by mapping the page into virtual memory and using - * bzero to clear its contents, one machine dependent page - * at a time. + * pmap_zero_page zeros the specified (machine independent) + * page by mapping the page into virtual memory and using + * bzero to clear its contents, one machine dependent page + * at a time. */ void pmap_zero_page(phys) diff --git a/sys/arch/vax/vax/random.s b/sys/arch/vax/vax/random.s index cf14bbdb292..865c9cd79ba 100644 --- a/sys/arch/vax/vax/random.s +++ b/sys/arch/vax/vax/random.s @@ -1,3 +1,4 @@ +/* $OpenBSD: random.s,v 1.3 1997/01/15 23:25:21 maja Exp $ */ /* $NetBSD: random.s,v 1.2 1994/10/26 08:03:24 cgd Exp $ */ /* diff --git a/sys/arch/vax/vax/rootfil.c b/sys/arch/vax/vax/rootfil.c index 67fab5824c0..c75e0dacd35 100644 --- a/sys/arch/vax/vax/rootfil.c +++ b/sys/arch/vax/vax/rootfil.c @@ -1,4 +1,4 @@ -/* $NetBSD: rootfil.c,v 1.11 1996/04/08 18:32:54 ragge Exp $ */ +/* $NetBSD: rootfil.c,v 1.14 1996/10/13 03:35:58 christos Exp $ */ /* * Copyright (c) 1988 University of Utah. @@ -58,35 +58,13 @@ #include <machine/pte.h> #include <machine/cpu.h> -#include <vax/uba/ubavar.h> - -#include "uda.h" #include "hp.h" +#include "ra.h" #define DOSWAP /* Change swdevt, argdev, and dumpdev too */ u_long bootdev; /* should be dev_t, but not until 32 bits */ extern dev_t rootdev, dumpdev; -static char devname[][2] = { - {'h','p'}, /* 0 = hp */ - {0,0}, /* 1 = ht */ - {'u','p'}, /* 2 = up */ - {'r','k'}, /* 3 = hk */ - {0,0}, /* 4 = sw */ - {0,0}, /* 5 = tm */ - {0,0}, /* 6 = ts */ - {0,0}, /* 7 = mt */ - {0,0}, /* 8 = tu */ - {'r','a'}, /* 9 = ra */ - {0,0}, /* 10 = ut */ - {'r','b'}, /* 11 = rb */ - {0,0}, /* 12 = uu */ - {0,0}, /* 13 = rx */ - {'r','l'}, /* 14 = rl */ - {0,0}, /* 15 = tmscp */ - {'k','r'}, /* 16 = ra on kdb50 */ -}; - #define PARTITIONMASK 0x7 #define PARTITIONSHIFT 3 @@ -100,45 +78,40 @@ setroot() { int majdev, mindev, unit, part, controller, adaptor; dev_t temp = 0, orootdev; -#if NUDA > 0 - extern struct uba_device ubdinit[]; -#endif struct swdevt *swp; extern int boothowto; + char *uname; if (boothowto & RB_DFLTROOT || (bootdev & B_MAGICMASK) != (u_long)B_DEVMAGIC) return; majdev = B_TYPE(bootdev); - if (majdev >= sizeof(devname) / sizeof(devname[0])) + if (majdev >= nblkdev) return; adaptor = B_ADAPTOR(bootdev); controller = B_CONTROLLER(bootdev); part = B_PARTITION(bootdev); unit = B_UNIT(bootdev); - if (majdev == 0) { /* MBA device */ -#if NHP > 0 - mindev = hp_getdev(adaptor, unit); - if (mindev < 0) + + switch (majdev) { + case 0: /* MBA disk */ +#if NHP + if ((mindev = hp_getdev(adaptor, unit, &uname)) < 0) +#endif return; -#else - return; + break; + + case 9: /* MSCP disk */ +#if NRA + if ((mindev = ra_getdev(adaptor, controller, unit, &uname)) < 0) #endif - } else { - register struct uba_device *ubap; - - for (ubap = ubdinit; ubap->ui_driver; ubap++){ - if (ubap->ui_alive && ubap->ui_slave == unit && - ubap->ui_ctlr == controller && - ubap->ui_ubanum == adaptor && - ubap->ui_driver->ud_dname[0] == devname[majdev][0] && - ubap->ui_driver->ud_dname[1] == devname[majdev][1]) - break; - } - if (ubap->ui_driver == 0) - return; - mindev = ubap->ui_unit; - } + return; + break; + + default: + return; + } + mindev = (mindev << PARTITIONSHIFT) + part; orootdev = rootdev; rootdev = makedev(majdev, mindev); @@ -149,9 +122,7 @@ setroot() if (rootdev == orootdev) return; - printf("Changing root device to %c%c%d%c\n", - devname[majdev][0], devname[majdev][1], - mindev >> PARTITIONSHIFT, part + 'a'); + printf("Changing root device to %s%c\n", uname, part + 'a'); #ifdef DOSWAP mindev &= ~PARTITIONMASK; @@ -173,9 +144,6 @@ setroot() */ if (temp == dumpdev) dumpdev = swdevt[0].sw_dev; - panic("autoconf.c: argdev\n"); -/* if (temp == argdev) - argdev = swdevt[0].sw_dev; */ #endif } diff --git a/sys/arch/vax/vax/sbi.c b/sys/arch/vax/vax/sbi.c index 486acc3399b..237087cf641 100644 --- a/sys/arch/vax/vax/sbi.c +++ b/sys/arch/vax/vax/sbi.c @@ -1,4 +1,4 @@ -/* $NetBSD: sbi.c,v 1.9 1996/04/08 18:32:55 ragge Exp $ */ +/* $NetBSD: sbi.c,v 1.14 1996/10/13 03:36:00 christos Exp $ */ /* * Copyright (c) 1994 Ludd, University of Lule}, Sweden. * All rights reserved. @@ -33,26 +33,14 @@ #include <sys/param.h> #include <sys/device.h> #include <sys/systm.h> -#include <vm/vm.h> -#include <vm/vm_kern.h> -#include <vm/vm_page.h> -#include <machine/ka750.h> -#include <machine/pmap.h> + #include <machine/sid.h> #include <machine/cpu.h> - -struct nexus *nexus; +#include <machine/nexus.h> static int sbi_print __P((void *, const char *)); - int sbi_match __P((struct device *, void *, void *)); - void sbi_attach __P((struct device *, struct device *, void*)); - - -struct bp_conf { - char *type; - int num; - int partyp; -}; +static int sbi_match __P((struct device *, void *, void *)); +static void sbi_attach __P((struct device *, struct device *, void*)); int sbi_print(aux, name) @@ -79,8 +67,8 @@ sbi_print(aux, name) int sbi_match(parent, cf, aux) - struct device *parent; - void *cf, *aux; + struct device *parent; + void *cf, *aux; { struct bp_conf *bp = aux; @@ -91,99 +79,36 @@ sbi_match(parent, cf, aux) void sbi_attach(parent, self, aux) - struct device *parent, *self; - void *aux; + struct device *parent, *self; + void *aux; { - u_int nexnum, maxnex, minnex; + u_int nexnum, maxnex, minnex; struct sbi_attach_args sa; - switch (cpunumber) { -#ifdef VAX730 - case VAX_730: - maxnex = NNEX730; - printf(": BL[730\n"); - break; -#endif -#ifdef VAX750 - case VAX_750: - maxnex = NNEX750; - printf(": CMI750\n"); - break; -#endif -#ifdef VAX630 - case VAX_78032: - switch (cpu_type) { - case VAX_630: - maxnex = NNEX630; - printf(": Q22\n"); - break; - default: - panic("Microvax not supported"); - }; - break; -#endif -#ifdef VAX650 - case VAX_650: - maxnex = NNEX630; /* XXX */ - printf(": Q22\n"); - break; -#endif -#if VAX780 || VAX8600 - case VAX_780: - case VAX_8600: - maxnex = NNEXSBI; - printf(": SBI780\n"); - break; -#endif - default: - maxnex = 0; /* Leave it */ - break; - } + printf("\n"); /* * Now a problem: on different machines with SBI units identifies * in different ways (if they identifies themselves at all). * We have to fake identifying depending on different CPUs. */ - minnex = self->dv_unit * maxnex; - for (nexnum = minnex; nexnum < minnex + maxnex; nexnum++) { + minnex = self->dv_unit * NNEXSBI; + for (nexnum = minnex; nexnum < minnex + NNEXSBI; nexnum++) { volatile int tmp; if (badaddr((caddr_t)&nexus[nexnum], 4)) continue; - switch (cpunumber) { -#ifdef VAX750 - case VAX_750: - { extern int nexty750[]; - sa.type = nexty750[nexnum]; - break; - } -#endif -#ifdef VAX730 - case VAX_730: - { extern int nexty730[]; - sa.type = nexty730[nexnum]; - break; - } -#endif -#if VAX630 || VAX650 - case VAX_78032: - case VAX_650: - sa.type = NEX_UBA0; - break; -#endif - default: - tmp = nexus[nexnum].nexcsr.nex_csr; /* no byte reads */ - sa.type = tmp & 255; - } + tmp = nexus[nexnum].nexcsr.nex_csr; /* no byte reads */ + sa.type = tmp & 255; + sa.nexnum = nexnum; sa.nexaddr = nexus + nexnum; config_found(self, (void*)&sa, sbi_print); } } -struct cfdriver sbi_cd = { +struct cfdriver sbi_cd = { NULL, "sbi", DV_DULL }; diff --git a/sys/arch/vax/vax/swapgeneric.c b/sys/arch/vax/vax/swapgeneric.c index 88fc116f2a1..f2bec413318 100644 --- a/sys/arch/vax/vax/swapgeneric.c +++ b/sys/arch/vax/vax/swapgeneric.c @@ -1,4 +1,4 @@ -/* $NetBSD: swapgeneric.c,v 1.9 1996/04/08 18:32:57 ragge Exp $ */ +/* $NetBSD: swapgeneric.c,v 1.13 1996/10/13 03:36:01 christos Exp $ */ /*- * Copyright (c) 1982, 1986 The Regents of the University of California. @@ -35,9 +35,6 @@ * @(#)swapgeneric.c 7.11 (Berkeley) 5/9/91 */ -#include "uda.h" -#include "hp.h" - #include <sys/param.h> #include <sys/conf.h> #include <sys/buf.h> @@ -53,9 +50,11 @@ #include <machine/mtpr.h> #include <machine/cpu.h> -#include <vax/uba/ubareg.h> -#include <vax/uba/ubavar.h> - +#include "hp.h" +#include "ra.h" +#include "hdc.h" +#include "sd.h" +#include "st.h" void gets __P((char *)); @@ -77,14 +76,11 @@ int dmmin, dmmax, dmtext; int (*mountroot) __P((void)) = ffs_mountroot; -extern struct uba_driver scdriver; -extern struct uba_driver hkdriver; -extern struct uba_driver idcdriver; -extern struct uba_driver hldriver; -extern struct uba_driver udadriver; -extern struct uba_driver kdbdriver; - extern struct cfdriver hp_cd; +extern struct cfdriver ra_cd; +extern struct cfdriver rd_cd; +extern struct cfdriver sd_cd; +extern struct cfdriver st_cd; struct ngcconf { struct cfdriver *ng_cf; @@ -93,34 +89,24 @@ struct ngcconf { #if NHP > 0 { &hp_cd, makedev(0, 0), }, #endif - { 0 }, -}; - -struct genericconf { - caddr_t gc_driver; - char *gc_name; - dev_t gc_root; -} genericconf[] = { -/* { (caddr_t)&hp_cd, "hp", makedev(0, 0), }, - { (caddr_t)&scdriver, "up", makedev(2, 0), }, */ -#if NUDA > 0 - { (caddr_t)&udadriver, "ra", makedev(9, 0), }, +#if NRA > 0 + { &ra_cd, makedev(9, 0), }, +#endif +#if NHDC > 0 + { &rd_cd, makedev(19, 0), }, +#endif +#if NSD > 0 + { &sd_cd, makedev(20, 0), }, +#endif +#if NST > 0 + { &st_cd, makedev(21, 0), }, #endif -/* { (caddr_t)&idcdriver, "rb", makedev(11, 0), }, - { (caddr_t)&hldriver, "rl", makedev(14, 0), }, - { (caddr_t)&hkdriver, "hk", makedev(3, 0), }, - { (caddr_t)&hkdriver, "rk", makedev(3, 0), }, - { (caddr_t)&kdbdriver, "kra", makedev(16, 0), }, */ { 0 }, }; void setconf() { -#if NUDA > 0 - register struct uba_device *ui; -#endif - register struct genericconf *gc; struct ngcconf *nc; register char *cp, *gp; int unit, swaponroot = 0, i; @@ -145,13 +131,13 @@ nretry: strcmp(name, ((struct device *) (nc->ng_cf->cd_devs[i]))->dv_xname) == 0) goto ngotit; -#ifdef notyet + printf("Use one of "); for (nc = ngcconf; nc->ng_cf; nc++) printf("%s%%d ", nc->ng_cf->cd_name); printf("\n"); -#endif - goto gc2; + + goto nretry; ngotit: rootdev = makedev(major(nc->ng_root), i * 8); goto doswap; @@ -169,50 +155,9 @@ ngotit: } - if (boothowto & RB_ASKNAME) { -retry: - printf("root device? "); - gets(name); -gc2: - for (gc = genericconf; gc->gc_driver; gc++) - for (cp = name, gp = gc->gc_name; *cp == *gp; cp++) - if (*++gp == 0) - goto gotit; - printf( - "use hp%%d, up%%d, ra%%d, rb%%d, rl%%d, hk%%d or kra%%d\n"); - goto nretry; -gotit: - if (*++cp < '0' || *cp > '9') { - printf("bad/missing unit number\n"); - goto retry; - } - while (*cp >= '0' && *cp <= '9') - unit = 10 * unit + *cp++ - '0'; - if (*cp == '*') - swaponroot++; - goto found; - } - for (gc = genericconf; gc->gc_driver; gc++) { -#if NUDA > 0 - for (ui = ubdinit; ui->ui_driver; ui++) { - if (ui->ui_alive == 0) - continue; - if (ui->ui_unit == unit && ui->ui_driver == - (struct uba_driver *)gc->gc_driver) { - printf("root on %s%d\n", - ui->ui_driver->ud_dname, unit); - goto found; - } - } -#endif - } - printf("no suitable root\n"); asm("halt"); -found: - gc->gc_root = makedev(major(gc->gc_root), unit*8); - rootdev = gc->gc_root; doswap: swdevt[0].sw_dev = argdev = dumpdev = makedev(major(rootdev), minor(rootdev)+1); diff --git a/sys/arch/vax/vax/tmscpinf.h b/sys/arch/vax/vax/tmscpinf.h deleted file mode 100644 index 5d6989995d6..00000000000 --- a/sys/arch/vax/vax/tmscpinf.h +++ /dev/null @@ -1,321 +0,0 @@ -/* $NetBSD: tmscpinf.h,v 1.1 1995/02/23 17:54:06 ragge Exp $ */ - -/* @(#)tmscp.h 7.2 (Berkeley) 5/27/88 */ -/* - * @(#)tmscp.h 1.3 10/21/85 - * Definitions for the Tape Mass Storage Control Protocol - */ - -/**************************************************************** - * * - * Licensed from Digital Equipment Corporation * - * Copyright (c) * - * Digital Equipment Corporation * - * Maynard, Massachusetts * - * 1985, 1986 * - * All rights reserved. * - * * - * The Information in this software is subject to change * - * without notice and should not be construed as a commitment * - * by Digital Equipment Corporation. Digital makes no * - * representations about the suitability of this software for * - * any purpose. It is supplied "As Is" without expressed or * - * implied warranty. * - * * - * If the Regents of the University of California or its * - * licensees modify the software in a manner creating * - * diriviative copyright rights, appropriate copyright * - * legends may be placed on the drivative work in addition * - * to that set forth above. * - * * - **************************************************************** - * - * Modification history: /sys/vax/tmscp.h - * - * 18-Oct-85 - afd - * Added: defines for tape format (density) flag values. - * - * 18-Jul-85 - afd - * Added: #define M_UF_WBKNV 0000100 - * for write back (which enables cache). - ************************************************************************/ - -/* - * Control message opcodes - */ -#define M_OP_ABORT 0001 /* Abort command */ -#define M_OP_GTCMD 0002 /* Get command status command */ -#define M_OP_GTUNT 0003 /* Get unit status command */ -#define M_OP_STCON 0004 /* Set controller characteristics command */ -#define M_OP_AVAIL 0010 /* Available command */ -#define M_OP_ONLIN 0011 /* Online command */ -#define M_OP_STUNT 0012 /* Set unit characteristics command */ -#define M_OP_DTACP 0013 /* Determine access paths command */ -#define M_OP_ACCES 0020 /* Access command */ -#define M_OP_CMPCD 0021 /* Compare controller data command */ -#define M_OP_ERASE 0022 /* Erase command */ -#define M_OP_FLUSH 0023 /* Flush command */ -#define M_OP_ERGAP 0026 /* Erase gap command */ -#define M_OP_COMP 0040 /* Compare host data command */ -#define M_OP_READ 0041 /* Read command */ -#define M_OP_WRITE 0042 /* Write command */ -#define M_OP_WRITM 0044 /* Write tape mark command */ -#define M_OP_REPOS 0045 /* Reposition command */ -#define M_OP_AVATN 0100 /* Available attention message */ -#define M_OP_DUPUN 0101 /* Duplicate unit number attention message */ -#define M_OP_ACPTH 0102 /* Access path attention message */ -#define M_OP_END 0200 /* End message flag */ - - -/* - * Generic command modifiers - */ -#define M_MD_COMP 0040000 /* Compare */ -#define M_MD_CLSEX 0020000 /* Clear serious exception */ -#define M_MD_SECOR 0001000 /* Suppress error correction */ -#define M_MD_SEREC 0000400 /* Suppress error recovery */ -#define M_MD_STWRP 0000004 /* Set write protect */ -#define M_MD_ALLCD 0000002 /* All class drivers */ -#define M_MD_NXUNT 0000001 /* Next unit */ - -/* - * TMSCP command modifiers - */ -#define M_MD_DLEOT 0000200 /* Delete LEOT */ -#define M_MD_IMMED 0000100 /* Immediate completion */ -#define M_MD_EXCAC 0000040 /* Exclusive access */ -#define M_MD_UNLOD 0000020 /* Unload */ -#define M_MD_REVRS 0000010 /* reverse */ -#define M_MD_OBJCT 0000004 /* object count */ -#define M_MD_REWND 0000002 /* rewind */ - -/* - * End message flags - */ -#define M_EF_ERLOG 0040 /* Error log generated */ -#define M_EF_SEREX 0020 /* Serious exception */ -#define M_EF_EOT 0010 /* End of tape encountered */ -#define M_EF_PLS 0004 /* Position lost */ - - -/* - * Controller flags - */ -#define M_CF_ATTN 0200 /* Enable attention messages */ -#define M_CF_MISC 0100 /* Enable miscellaneous error log messages */ -#define M_CF_OTHER 0040 /* Enable other host's error log messages */ -#define M_CF_THIS 0020 /* Enable this host's error log messages */ - - -/* - * Unit flags - */ -#define M_UF_WRTPH 0020000 /* Write protect (hardware) */ -#define M_UF_WRTPS 0010000 /* Write protect (software or volume) */ -#define M_UF_WBKNV 0000100 /* Write back (enables cache) */ -#define M_UF_VSMSU 0000040 /* Variable speed mode suppression */ -#define M_UF_VARSP 0000020 /* Variable speed unit */ -#define M_UF_CMPWR 0000002 /* Compare writes */ -#define M_UF_CMPRD 0000001 /* Compare reads */ - - -/* - * Status codes - */ -#define M_ST_MASK 037 /* Status code mask */ -#define M_ST_SUCC 000 /* Success */ -#define M_ST_ICMD 001 /* Invalid command */ -#define M_ST_ABRTD 002 /* Command aborted */ -#define M_ST_OFFLN 003 /* Unit offline */ -#define M_ST_AVLBL 004 /* Unit available */ -#define M_ST_WRTPR 006 /* Write protected */ -#define M_ST_COMP 007 /* Compare error */ -#define M_ST_DATA 010 /* Data error */ -#define M_ST_HSTBF 011 /* Host buffer access error */ -#define M_ST_CNTLR 012 /* Controller error */ -#define M_ST_DRIVE 013 /* Drive error */ -#define M_ST_FMTER 014 /* Formatter error */ -#define M_ST_BOT 015 /* BOT encountered */ -#define M_ST_TAPEM 016 /* Tape mark encountered */ -#define M_ST_RDTRN 020 /* Record data truncated */ -#define M_ST_PLOST 021 /* Position lost */ -#define M_ST_SEX 022 /* Serious exception */ -#define M_ST_LED 023 /* LEOT detected */ -#define M_ST_DIAG 037 /* Message from an internal diagnostic */ - -/* - * An MSCP packet - */ - -struct mscp { - struct mscp_header mscp_header;/* device specific header */ - long mscp_cmdref; /* command reference number */ - short mscp_unit; /* unit number */ - short mscp_xxx1; /* unused */ - u_char mscp_opcode; /* opcode */ - u_char mscp_flags; /* end message flags */ - short mscp_modifier; /* modifiers */ - union { - struct { - long Mscp_bytecnt; /* byte count */ - long Mscp_buffer; /* buffer descriptor */ - long Mscp_mapbase; /* physical addr of map registers */ - long Mscp_xxx2; /* unused */ - long Mscp_lbn; /* logical block number */ - long Mscp_xxx4; /* unused */ - long *Mscp_dscptr; /* pointer to descriptor (software) */ - long Mscp_sftwds[17];/* software words, padding */ - } mscp_generic; - struct { - short Mscp_version; /* MSCP version */ - short Mscp_cntflgs; /* controller flags */ - short Mscp_hsttmo; /* host timeout */ - short Mscp_usefrac; /* use fraction */ - quad_t Mscp_time; /* time and date */ - long Mscp_cntdep; /* controller dependent parameters */ - } mscp_setcntchar; - struct { - short Mscp_multunt; /* multi-unit code */ - short Mscp_unitflgs; /* unit flags */ - long Mscp_hostid; /* host identifier */ - quad_t Mscp_unitid; /* unit identifier */ - long Mscp_mediaid; /* media type identifier */ - short Mscp_format; /* format (tape density) */ - short Mscp_speed; /* tape speed = (ips * bpi) /1000 */ - short Mscp_fmtmenu; /* format menu */ - short Mscp_group; /* group size */ - short Mscp_cylinder; /* cylinder size */ - short Mscp_xxx3; /* reserved */ - short Mscp_rctsize; /* RCT table size */ - char Mscp_rbns; /* RBNs / track */ - char Mscp_rctcpys; /* RCT copies */ - } mscp_getunitsts; - } mscp_un; - short mscp_fil1; - short mscp_fil2; - short mscp_fil3; -}; - -#define mscp_msglen (sizeof (struct mscp) - sizeof(struct mscp_header)) - -/* - * generic packet - */ - -#define mscp_bytecnt mscp_un.mscp_generic.Mscp_bytecnt -#define mscp_buffer mscp_un.mscp_generic.Mscp_buffer -#define mscp_mapbase mscp_un.mscp_generic.Mscp_mapbase -#define mscp_lbn mscp_un.mscp_generic.Mscp_lbn -#define mscp_dscptr mscp_un.mscp_generic.Mscp_dscptr -#define mscp_sftwds mscp_un.mscp_generic.Mscp_sftwds -#define mscp_status mscp_modifier - -/* - * Abort / Get Command Status packet - */ - -#define mscp_outref mscp_bytecnt - -/* - * Set Controller Characteristics packet - */ - -#define mscp_version mscp_un.mscp_setcntchar.Mscp_version -#define mscp_cntflgs mscp_un.mscp_setcntchar.Mscp_cntflgs -#define mscp_hsttmo mscp_un.mscp_setcntchar.Mscp_hsttmo -#define mscp_usefrac mscp_un.mscp_setcntchar.Mscp_usefrac -#define mscp_time mscp_un.mscp_setcntchar.Mscp_time -#define mscp_cntdep mscp_un.mscp_setcntchar.Mscp_cntdep - -/* - * Reposition command packet fields - */ - -#define mscp_reccnt mscp_bytecnt /* record/object count */ -#define mscp_tmkcnt mscp_buffer /* tape mark count */ - -/* - * Get Unit Status end packet - */ - -#define mscp_multunt mscp_un.mscp_getunitsts.Mscp_multunt -#define mscp_unitflgs mscp_un.mscp_getunitsts.Mscp_unitflgs -#define mscp_hostid mscp_un.mscp_getunitsts.Mscp_hostid -#define mscp_unitid mscp_un.mscp_getunitsts.Mscp_unitid -#define mscp_mediaid mscp_un.mscp_getunitsts.Mscp_mediaid -#define mscp_format mscp_un.mscp_getunitsts.Mscp_format /* density:0=high */ -#define mscp_speed mscp_un.mscp_getunitsts.Mscp_speed /* (ips*bpi)/1000 */ -#define mscp_fmtmenu mscp_un.mscp_getunitsts.Mscp_fmtmenu - -/* - * Online / Set Unit Characteristics end packet - */ - -#define mscp_maxwrt mscp_dscptr /* max write byte count */ -#define mscp_noiserec mscp_cylinder /* noise record */ - -/* - * Set Controller Characteristics end packet - */ - -#define mscp_cnttmo mscp_hsttmo /* controller timeout */ -#define mscp_cntcmdl mscp_usefrac /* controller soft & hardware version */ -#define mscp_cntid mscp_unitid /* controller id */ - - -/* - * Error Log message format codes - */ -#define M_FM_CNTERR 0 /* Controller error */ -#define M_FM_BUSADDR 1 /* Host memory access error */ -#define M_FM_TAPETRN 5 /* Tape transfer error */ -#define M_FM_STIERR 6 /* STI communication or command failure */ -#define M_FM_STIDEL 7 /* STI drive error log */ -#define M_FM_STIFEL 010 /* STI formatter error log */ - -/* - * Error Log message flags - */ -#define M_LF_SUCC 0200 /* Operation successful */ -#define M_LF_CONT 0100 /* Operation continuing */ -#define M_LF_SQNRS 0001 /* Sequence number reset */ - -/* - * Tape Format Flag Values - */ -#define M_TF_800 001 /* NRZI 800 bpi */ -#define M_TF_PE 002 /* Phase Encoded 1600 bpi */ -#define M_TF_GCR 004 /* Group Code Recording 6250 bpi */ -#define M_TF_BLK 010 /* Cartridge Block Mode */ - -/* - * MSCP Error Log packet - * - * NOTE: MSCP packet must be padded to this size. - */ - -struct mslg { - struct mscp_header mslg_header;/* device specific header */ - long mslg_cmdref; /* command reference number */ - short mslg_unit; /* unit number */ - short mslg_seqnum; /* sequence number */ - u_char mslg_format; /* format */ - u_char mslg_flags; /* error log message flags */ - short mslg_event; /* event code */ - quad_t mslg_cntid; /* controller id */ - u_char mslg_cntsvr; /* controller software version */ - u_char mslg_cnthvr; /* controller hardware version */ - short mslg_multunt; /* multi-unit code */ - quad_t mslg_unitid; /* unit id */ - u_char mslg_unitsvr; /* unit software version */ - u_char mslg_unithvr; /* unit hardware version */ - short mslg_group; /* group; retry + level */ - long mslg_position; /* position (object count) */ - u_char mslg_fmtsvr; /* formatter software version */ - u_char mslg_fmthvr; /* formatter hardware version */ - short mslg_xxx2; /* unused */ - char mslg_stiunsucc[62]; /* STI status information */ -}; - -#define mslg_sdecyl mslg_group - diff --git a/sys/arch/vax/vax/trap.c b/sys/arch/vax/vax/trap.c index d81c18dad76..e574f2170ce 100644 --- a/sys/arch/vax/vax/trap.c +++ b/sys/arch/vax/vax/trap.c @@ -1,4 +1,4 @@ -/* $NetBSD: trap.c,v 1.21 1996/05/19 16:44:27 ragge Exp $ */ +/* $NetBSD: trap.c,v 1.24 1996/11/06 20:19:55 cgd Exp $ */ /* * Copyright (c) 1994 Ludd, University of Lule}, Sweden. @@ -89,8 +89,8 @@ userret(p, pc, psl) * Since we are curproc, clock will normally just change * our priority without moving us from one queue to another * (since the running process is not on a queue.) - * If that happened after we setrq ourselves but before we - * swtch()'ed, we might not be on the queue indicated by + * If that happened after we setrunqueue ourselves but before + * we swtch()'ed, we might not be on the queue indicated by * our priority. */ s=splstatclock(); diff --git a/sys/arch/vax/vax/uvax.c b/sys/arch/vax/vax/uvax.c new file mode 100644 index 00000000000..ce9df0e4692 --- /dev/null +++ b/sys/arch/vax/vax/uvax.c @@ -0,0 +1,287 @@ +/* $NetBSD: uvax.c,v 1.3 1996/10/13 03:36:03 christos Exp $ */ +/* + * Copyright (c) 1996 Ludd, University of Lule}, Sweden. + * All rights reserved. + * + * This code is derived from software contributed to Ludd by Bertram Barth. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed at Ludd, University of + * Lule}, Sweden and its contributors. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * generic(?) MicroVAX and VAXstation support + * + * There are similarities to struct cpu_calls[] in autoconf.c + */ + +#include <sys/param.h> +#include <sys/types.h> +#include <sys/device.h> +#include <vm/vm.h> +#include <vm/vm_kern.h> + +#include <machine/pte.h> +#include <machine/mtpr.h> +#include <machine/sid.h> +#include <machine/pmap.h> +#include <machine/nexus.h> +#include <machine/uvax.h> + +#define xtrace(x) +#define xdebug(x) + + +struct uvax_calls guc; /* Generic uVAX Calls */ +/* struct uvax_calls *ucp = &guc; /* not yet public !!! */ +static int uvax_callsSetup = 0; /* not yet setup */ + +u_long uVAX_phys2virt __P((u_long, struct uc_map *)); + +/* u_long uVAX_physmap; /* XXX another ugly hack... */ +int +uvax_notavail(s) + char *s; +{ + printf("\"%s()\" not available for uVAX (%s)\n", s, guc.uc_name); + /* + * should we panic() here??? + */ + return(0); +} + +int +uvax_setup(flags) + int flags; +{ + /* + * insert some defaults here !!! + */ + + /* + * Now call the specific routines to overwrite these defaults + */ + switch (vax_boardtype) { +#ifdef VAX630 + case VAX_BTYP_630: + ka630_setup(&guc, flags); + break; +#endif +#ifdef VAX410 + case VAX_BTYP_410: + ka410_setup(&guc, flags); + break; +#endif +#ifdef VAX43 + case VAX_BTYP_43: + ka43_setup(&guc, flags); + break; +#endif + default: + printf("don't know how to handle 0x%x\n", vax_boardtype); + printf("Let's try using the defaults...\n"); + } + uvax_callsSetup = 1; +} + +/* + * XXX_steal_pages() is the first cpu/board specific function to be called. + * Thus we use this call to setup the dispatch structure for further use. + * + * We should have a special setup-routine !!! + */ +void +uvax_steal_pages() +{ + if (uvax_callsSetup == 0) + uvax_setup(0); + + /* + * now that specific functions are inserted, we can call 'em + */ + if (guc.uc_steal_pages) { + (guc.uc_steal_pages)(); + return; + } + uvax_notavail("uc_steal_pages"); +} + +u_long +uvax_phys2virt(paddr) + u_long paddr; +{ + if (guc.uc_phys2virt) + return ((guc.uc_phys2virt)(paddr)); + if (guc.uc_physmap) + return (uVAX_phys2virt(paddr, guc.uc_physmap)); + uvax_notavail("uc_phys2virt"); + return (0); +} + +void +uvax_conf(parent, self, aux) + struct device *parent, *self; + void *aux; +{ + if (guc.uc_conf) { + (guc.uc_conf)(parent, self, aux); + return; + } + uvax_notavail("uc_conf"); +} + +void +uvax_memerr() +{ + xtrace(("uvax_memerr()\n")); + + if (guc.uc_memerr) { + (guc.uc_memerr)(); + return; + } + uvax_notavail("uc_memerr"); +} + +int +uvax_mchk(addr) + caddr_t addr; +{ + xtrace(("uvax_mchk(0x%x)\n", addr)); + + if (guc.uc_mchk) + return ((guc.uc_mchk)(addr)); + uvax_notavail("uc_mchk"); + return (-1); +} + +int +uvax_clkread(base) + time_t base; +{ + if (guc.uc_clkread) + return ((guc.uc_clkread)(base)); + uvax_notavail("uc_clkread"); +} + +void +uvax_clkwrite() +{ + if (guc.uc_clkwrite) + (guc.uc_clkwrite)(); + else + uvax_notavail("uc_clkwrite"); + return; +} + +/* + * NB: mapping should/must be done in chunks of PAGE_SIZE (ie. 1024), + * while pmap_map() expects size to be in chunks of NBPG (ie. 512). + * + * Thus we round down the start-address to be aligned wrt PAGE_SIZE and + * the end-address up to be just beyond the next multiple of PAGE_SIZE. + * size is the number of bytes between start and end expressed in NBPG. + */ +int +uVAX_old_fillmap(um) + struct uc_map *um; +{ + extern vm_offset_t avail_start, virtual_avail, avail_end; + register struct uc_map *p; + register u_int base, end, size; + + for (p = um; p->um_base != 0; p++) { + base = p->um_base & ~PAGE_SIZE; /* round base down */ + end = ROUND_PAGE(p->um_end + 1) - 1; /* round end up */ + size = (end - base + 1) / NBPG; /* size in pages */ + MAPVIRT(p->um_virt, size); + pmap_map((vm_offset_t)p->um_virt, base, end, + VM_PROT_READ|VM_PROT_WRITE); + + xdebug(("uVAX_fillmap: %x:%x[%x] (%x:%x[%x]) --> %x\n", + p->um_base, p->um_end, p->um_size, + base, end, size, p->um_virt)); + + } +} + +/* + * NB: mapping should/must be done in chunks of PAGE_SIZE (ie. 1024), + * while pmap_map() expects size to be in chunks of NBPG (ie. 512). + * + * Thus we round down the start-address to be aligned wrt PAGE_SIZE and + * the end-address up to be just beyond the next multiple of PAGE_SIZE. + * size is the number of bytes between start and end expressed in NBPG. + */ +int +uVAX_fillmap(um) + struct uc_map *um; +{ + extern vm_offset_t avail_start, virtual_avail, avail_end; + register struct uc_map *p; + register u_int base, end, off, size; + + for (p = um; p->um_base != 0; p++) { + base = TRUNC_PAGE(p->um_base); /* round base down */ + off = p->um_base - base; + size = ROUND_PAGE(off + p->um_size); + if (size < PAGE_SIZE) { + printf("invalid size %d in uVAX_fillmap\n", size); + size = PAGE_SIZE; + } + end = base + size - 1; + MAPVIRT(p->um_virt, size/NBPG); + pmap_map((vm_offset_t)p->um_virt, base, end, + VM_PROT_READ|VM_PROT_WRITE); + + xdebug(("uVAX_fillmap: %x:%x[%x] (%x:%x[%x]) --> %x\n", + p->um_base, p->um_end, p->um_size, + base, end, size, p->um_virt)); + + } +} + +u_long +uVAX_phys2virt(phys,um) + u_long phys; + struct uc_map *um; +{ + register struct uc_map *p; + u_long virt = 0; + + for (p = um; p->um_base != 0; p++) { + if (p->um_base > phys || p->um_end < phys) + continue; + virt = p->um_virt + (phys - trunc_page(p->um_base)); + break; + } + + if (virt == 0) { + printf("invalid argument 0x%x to uvax_phys2virt()\n", phys); + /* should we panic() here ??? */ + } + + return (virt); +} diff --git a/sys/arch/vax/vax/uvaxII.c b/sys/arch/vax/vax/uvaxII.c index fe115911879..57eb4bc4913 100644 --- a/sys/arch/vax/vax/uvaxII.c +++ b/sys/arch/vax/vax/uvaxII.c @@ -1,4 +1,4 @@ -/* $NetBSD: uvaxII.c,v 1.8 1996/04/08 18:32:59 ragge Exp $ */ +/* $NetBSD: uvaxII.c,v 1.10 1996/10/13 03:36:04 christos Exp $ */ /*- * Copyright (c) 1994 Gordon W. Ross diff --git a/sys/arch/vax/vax/uvax_proto.c b/sys/arch/vax/vax/uvax_proto.c new file mode 100644 index 00000000000..4cf9e982105 --- /dev/null +++ b/sys/arch/vax/vax/uvax_proto.c @@ -0,0 +1,142 @@ +/* $NetBSD: uvax_proto.c,v 1.3 1996/10/13 03:36:06 christos Exp $ */ +/*- + * Copyright (c) 1982, 1988, 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + +/* + * MicroVAX and VAXstation and their different models have many + * similarities and also many very specific implementations/solutions. + * Thus this is a trial to have generic and prototypic routines + * which can be used instead of specific routines whenever possible. + * + * usually there are groups of machines using the same CPU chips, eg. + * MicroVAX II + * MicroVAX 2000 + * VAXstation 2000 + * have the same CPU and thus can share the CPU dependent code. + * + * On the other hand the above machines are quite differnet wrt. the + * way the board-specific details (system-bus, NVRAM layout, etc.) + * and thus can't share this code. + * + * It's also possible to find groups of machines which have enough + * similarities wrt. to board-specific implementations, to share some + * code between them. Eg. + * VAXstation 2000 + * VAXstation 3100 (which models ???) + * VAXstation 4000 (which models ???) + * use the same (nonexistent "virtual") system-bus and thus can share + * some pieces of code... + */ + +#include <sys/param.h> +#include <sys/types.h> +#include <sys/device.h> + +#include <machine/mtpr.h> + +static int +uVAX_clkread(base) + time_t base; +{ + register struct uVAX_clock *claddr = uVAX_clkptr; + struct chiptime c; + int timeout = 1<<15, rv; + + claddr->csr1 = uVAX_CLKSET; + while ((claddr->csr0 & uVAX_CLKUIP) != 0) + if (--timeout == 0) { + printf ("TOY clock timed out"); + return CLKREAD_BAD; + } + + c.sec = claddr->sec; + c.min = claddr->min; + c.hour = claddr->hr; + c.day = claddr->day; + c.mon = claddr->mon; + c.year = claddr->yr; + + /* If the clock is valid, use it. */ + if ((claddr->csr3 & uVAX_CLKVRT) != 0 && + (claddr->csr1 & uVAX_CLKENABLE) == uVAX_CLKENABLE) { + /* simple sanity checks */ + time.tv_sec = chiptotime(&c); + if (c.mon < 1 || c.mon > 12 || + c.day < 1 || c.day > 31) { + printf("WARNING: preposterous clock chip time"); + rv = CLKREAD_WARN; + } else + rv = CLKREAD_OK; + + claddr->csr0 = uVAX_CLKRATE; + claddr->csr1 = uVAX_CLKENABLE; + return rv; + } + + printf("WARNING: TOY clock invalid"); + return CLKREAD_BAD; +} + +/* Set the time of day clock, called via. stime system call.. */ +static void +uVAX_clkwrite() +{ + register struct uVAX_clock *claddr = uVAX_clkptr; + struct chiptime c; + int timeout = 1<<15; + int s; + + timetochip(&c); + + s = splhigh(); + + claddr->csr1 = uVAX_CLKSET; + while ((claddr->csr0 & uVAX_CLKUIP) != 0) + if (--timeout == 0) { + printf("Trouble saving date, TOY clock timed out\n"); + break; + } + + claddr->sec = c.sec; + claddr->min = c.min; + claddr->hr = c.hour; + claddr->day = c.day; + claddr->mon = c.mon; + claddr->yr = c.year; + + claddr->csr0 = uVAX_CLKRATE; + claddr->csr1 = uVAX_CLKENABLE; + + splx(s); +} diff --git a/sys/arch/vax/vax/vm_machdep.c b/sys/arch/vax/vax/vm_machdep.c index 60a486bc405..c39957a540b 100644 --- a/sys/arch/vax/vax/vm_machdep.c +++ b/sys/arch/vax/vax/vm_machdep.c @@ -1,4 +1,4 @@ -/* $NetBSD: vm_machdep.c,v 1.25 1996/05/19 16:44:33 ragge Exp $ */ +/* $NetBSD: vm_machdep.c,v 1.30 1997/01/11 11:23:09 ragge Exp $ */ /* * Copyright (c) 1994 Ludd, University of Lule}, Sweden. @@ -56,6 +56,7 @@ #include <machine/pcb.h> #include <machine/frame.h> #include <machine/cpu.h> +#include <machine/sid.h> #include <sys/syscallargs.h> @@ -295,16 +296,19 @@ idle: /* Should check that values is in bounds XXX */ int copyinstr(from, to, maxlen, lencopied) - void *from, *to; - u_int *lencopied,maxlen; + const void *from; + void *to; + size_t *lencopied; + size_t maxlen; { u_int i; void *addr=&curproc->p_addr->u_pcb.iftrap; - char *gfrom=from, *gto=to; + const char *gfrom = from; + char *gto = to; asm("movl $Lstr,(%0)":: "r"(addr)); for(i=0;i<maxlen;i++){ - *(gto+i)=*(gfrom+i); + *(gto +i )=*(gfrom + i); if(!(*(gto+i))) goto ok; } @@ -319,11 +323,14 @@ asm("Lstr: ret"); /* Should check that values is in bounds XXX */ int copyoutstr(from, to, maxlen, lencopied) - void *from, *to; - u_int *lencopied,maxlen; + const void *from; + void *to; + size_t *lencopied; + size_t maxlen; { u_int i; - char *gfrom=from, *gto=to; + const char *gfrom=from; + char *gto=to; void *addr=&curproc->p_addr->u_pcb.iftrap; asm("movl $Lstr,(%0)":: "r"(addr)); @@ -510,13 +517,14 @@ cpu_coredump(p, vp, cred, chdr) return error; } -int locopyout __P((void *, void *, size_t, void *)); -int locopyin __P((void *, void *, size_t, void *)); +int locopyout __P((const void *, void *, size_t, void *)); +int locopyin __P((const void *, void *, size_t, void *)); int copyout(from, to, len) - void *from, *to; - size_t len; + const void *from; + void *to; + size_t len; { void *addr=&curproc->p_addr->u_pcb.iftrap; @@ -525,8 +533,9 @@ copyout(from, to, len) int copyin(from, to, len) - void *from, *to; - size_t len; + const void *from; + void *to; + size_t len; { void *addr = &curproc->p_addr->u_pcb.iftrap; @@ -562,3 +571,60 @@ cpu_swapin(p) *j = 0; /* Set kernel stack red zone */ #endif } + +#if VAX410 || VAX43 +/* + * vmapbuf()/vunmapbuf() only used on some vaxstations without + * any busadapter with MMU. + * XXX - This must be reworked to be effective. + */ +void +vmapbuf(bp, len) + struct buf *bp; + vm_size_t len; +{ + vm_offset_t faddr, taddr, off, pa; + pmap_t fmap, tmap; + + if ((vax_boardtype != VAX_BTYP_43) && (vax_boardtype != VAX_BTYP_410)) + return; + faddr = trunc_page(bp->b_saveaddr = bp->b_data); + off = (vm_offset_t)bp->b_data - faddr; + len = round_page(off + len); + taddr = kmem_alloc_wait(phys_map, len); + bp->b_data = (caddr_t)(taddr + off); + fmap = vm_map_pmap(&bp->b_proc->p_vmspace->vm_map); + tmap = vm_map_pmap(phys_map); + len = len >> PGSHIFT; + while (len--) { + pa = pmap_extract(fmap, faddr); + if (pa == 0) + panic("vmapbuf: null page frame for %x", faddr); + pmap_enter(tmap, taddr, pa & ~(NBPG - 1), + VM_PROT_READ|VM_PROT_WRITE, TRUE); + faddr += NBPG; + taddr += NBPG; + } +} + +/* + * Free the io map PTEs associated with this IO operation. + * We also invalidate the TLB entries and restore the original b_addr. + */ +void +vunmapbuf(bp, len) + struct buf *bp; + vm_size_t len; +{ + vm_offset_t addr, off; + + if ((vax_boardtype != VAX_BTYP_43) && (vax_boardtype != VAX_BTYP_410)) + return; + addr = trunc_page(bp->b_data); + off = (vm_offset_t)bp->b_data - addr; + len = round_page(off + len); + kmem_free_wakeup(phys_map, addr, len); + bp->b_data = bp->b_saveaddr; + bp->b_saveaddr = 0; +} +#endif diff --git a/sys/arch/vax/vsa/dc.c b/sys/arch/vax/vsa/dc.c new file mode 100644 index 00000000000..f9d5de9c776 --- /dev/null +++ b/sys/arch/vax/vsa/dc.c @@ -0,0 +1,1026 @@ +/* $NetBSD: dc.c,v 1.4 1996/10/13 03:36:10 christos Exp $ */ +/*- + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Ralph Campbell and Rick Macklem. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)dc.c 8.2 (Berkeley) 11/30/93 + */ + +/* + * devDC7085.c -- + * + * This file contains machine-dependent routines that handle the + * output queue for the serial lines. + * + * Copyright (C) 1989 Digital Equipment Corporation. + * Permission to use, copy, modify, and distribute this software and + * its documentation for any purpose and without fee is hereby granted, + * provided that the above copyright notice appears in all copies. + * Digital Equipment Corporation makes no representations about the + * suitability of this software for any purpose. It is provided "as is" + * without express or implied warranty. + * + * from: Header: /sprite/src/kernel/dev/ds3100.md/RCS/devDC7085.c, + * v 1.4 89/08/29 11:55:30 nelson Exp SPRITE (DECWRL)"; + */ + +#include "dc.h" +#if NDC > 0 +/* + * DC7085 (DZ-11 look alike) Driver + * + * bertram 13-apr-1996: slightly modfied for DC367B in VS2000 + */ +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/ioctl.h> +#include <sys/tty.h> +#include <sys/proc.h> +#include <sys/map.h> +#include <sys/buf.h> +#include <sys/conf.h> +#include <sys/file.h> +#include <sys/uio.h> +#include <sys/kernel.h> +#include <sys/syslog.h> + +/* + * bertram 17-apr-1996: we could use most of the include files directly + * from the pmax port, only some of the paddings need + * to be changed. For now we use modified copies... + * + * #include <pmax/include/dc7085cons.h> + * #include <pmax/include/pmioctl.h> + * + * #include <pmax/dev/pdma.h> + * #include <pmax/dev/lk201.h> + */ +#include "dc7085cons.h" /* this one is modified !!! */ +#include <pmax/include/pmioctl.h> +#include <pmax/dev/pdma.h> +#include <pmax/dev/lk201.h> + +#include <sys/device.h> + +/* + * here follow some pmax specific includes which we don't need... + */ +#ifdef pmax +#include <machine/autoconf.h> +#include <machine/machConst.h> +#include <pmax/pmax/pmaxtype.h> +#include <pmax/pmax/cons.h> +#endif + +#ifdef vax +#include <machine/sid.h> +#include <machine/uvax.h> +#include <machine/vsbus.h> +#include <pmax/pmax/cons.h> /* we need to modify this for VAXen */ +#define MachEmptyWriteBuffer() /* we don't need this for VAXstation */ +#endif + +#include <pmax/dev/dcvar.h> + +struct dc_softc { + struct device sc_dv; + struct pdma dc_pdma[4]; + void *xmit_cfargs; + void *recv_cfargs; +}; + +/* + * Autoconfiguration data for config. + * + * Use the statically-allocated softc until old autoconfig code and + * config.old are completely gone. + */ +int dcmatch __P((struct device * parent, void *cfdata, void *aux)); +void dcattach __P((struct device *parent, struct device *self, void *aux)); + +int dc_doprobe __P((void *addr, int unit, int flags, int pri)); +int dcintr __P((void * xxxunit)); + +struct cfdriver dc_cd = { + NULL, "dc", DV_TTY +}; +struct cfattach dc_ca = { + sizeof(struct dc_softc), dcmatch, dcattach +}; + + +#define NDCLINE (NDC*4) + +void dcstart __P((struct tty *)); +void dcxint __P((struct tty *)); +void dcPutc __P((dev_t, int)); +void dcscan __P((void *)); +extern void ttrstrt __P((void *)); +int dcGetc __P((dev_t)); +int dcparam __P((struct tty *, struct termios *)); + +struct tty *dc_tty[NDCLINE]; +int dc_cnt = NDCLINE; +void (*dcDivertXInput)(); /* X windows keyboard input routine */ +void (*dcMouseEvent)(); /* X windows mouse motion event routine */ +void (*dcMouseButtons)(); /* X windows mouse buttons event routine */ +#ifdef DEBUG +int debugChar; +#endif + +/* + * Software copy of brk register since it isn't readable + */ +int dc_brk[NDC]; +char dcsoftCAR[NDC]; /* mask of dc's with carrier on (DSR) */ + +/* + * The DC7085 doesn't interrupt on carrier transitions, so + * we have to use a timer to watch it. + */ +int dc_timer; /* true if timer started */ + +/* + * Pdma structures for fast output code + */ +struct pdma dcpdma[NDCLINE]; + +struct speedtab dcspeedtab[] = { + 0, 0, + 50, LPR_B50, + 75, LPR_B75, + 110, LPR_B110, + 134, LPR_B134, + 150, LPR_B150, + 300, LPR_B300, + 600, LPR_B600, + 1200, LPR_B1200, + 1800, LPR_B1800, + 2400, LPR_B2400, + 4800, LPR_B4800, + 9600, LPR_B9600, + 19200, LPR_B19200, + -1, -1 +}; + +#ifndef PORTSELECTOR +#define ISPEED TTYDEF_SPEED +#define LFLAG TTYDEF_LFLAG +#else +#define ISPEED B4800 +#define LFLAG (TTYDEF_LFLAG & ~ECHO) +#endif + +static struct { + void *xmit_cfargs; + void *recv_cfargs; +} vs2000_hack = { NULL, NULL }; + +/* + * Match driver based on name + */ +int +dcmatch(parent, match, aux) + struct device *parent; + void *match; + void *aux; +{ + struct cfdata *cf = match; + struct confargs *ca = aux; + + static int nunits = 0; + + return (0); + + if (strcmp(ca->ca_name, "dc") != 0 && + strcmp(ca->ca_name, "mdc") != 0 && + strcmp(ca->ca_name, "dc367") != 0 && + strcmp(ca->ca_name, "dc7085") != 0) + return (0); + + /* + * Use statically-allocated softc and attach code until + * old config is completely gone. Don't over-run softc. + */ + if (nunits > NDC) { + printf("dc: too many units for old config\n"); + return (0); + } + nunits++; + return (1); +} + +void +dcattach(parent, self, aux) + struct device *parent; + struct device *self; + void *aux; +{ + register struct confargs *ca = aux; + u_long dcaddr; + + dcaddr = (u_long)ca->ca_ioaddr; + (void) dc_doprobe((void*)uvax_phys2virt(dcaddr), + self->dv_unit, self->dv_cfdata->cf_flags, + ca->ca_intslot); + + /* tie pseudo-slot to device */ +#ifdef notyet + vsbus_intr_register(ca, dcintr, self); + vsbus_intr_enable(ca); +#endif + printf("\n"); +} + +/* + * Is there a framebuffer console device using this serial driver? + * XXX used for ugly special-cased console input that should be redone + * more cleanly. + */ +static inline int +raster_console() +{ + return (cn_tab->cn_pri == CN_INTERNAL || + cn_tab->cn_pri == CN_NORMAL); +} + + +/* + * DC7085 (dz-11) probe routine from old-style config. + * This is only here out of intertia. + */ +int +dc_doprobe(addr, unit, flags, priority) + void *addr; + int unit, flags, priority; +{ + register dcregs *dcaddr; + register struct pdma *pdp; + register struct tty *tp; + register int cntr; + int s; + + if (unit >= NDC) + return (0); + if (badaddr(addr, 2)) + return (0); + + /* + * For a remote console, wait a while for previous output to + * complete. + */ + if (major(cn_tab->cn_dev) == DCDEV && unit == 0 && + cn_tab->cn_pri == CN_REMOTE) + DELAY(10000); + + /* reset chip */ + dcaddr = (dcregs *)addr; + dcaddr->dc_csr = CSR_CLR; + MachEmptyWriteBuffer(); + while (dcaddr->dc_csr & CSR_CLR) + ; + dcaddr->dc_csr = CSR_MSE | CSR_TIE | CSR_RIE; + + /* init pseudo DMA structures */ + pdp = &dcpdma[unit * 4]; + for (cntr = 0; cntr < 4; cntr++) { + pdp->p_addr = (void *)dcaddr; + tp = dc_tty[unit * 4 + cntr] = ttymalloc(); + pdp->p_arg = (int) tp; + pdp->p_fcn = dcxint; + pdp++; + } + dcsoftCAR[unit] = flags | 0xB; + + if (dc_timer == 0) { + dc_timer = 1; + timeout(dcscan, (void *)0, hz); + } + + /* + * Special handling for consoles. + */ + if (unit == 0) { + if (cn_tab->cn_pri == CN_INTERNAL || + cn_tab->cn_pri == CN_NORMAL) { + s = spltty(); + dcaddr->dc_lpr = LPR_RXENAB | LPR_8_BIT_CHAR | + LPR_B4800 | DCKBD_PORT; + MachEmptyWriteBuffer(); + dcaddr->dc_lpr = LPR_RXENAB | LPR_B4800 | LPR_OPAR | + LPR_PARENB | LPR_8_BIT_CHAR | DCMOUSE_PORT; + MachEmptyWriteBuffer(); + DELAY(1000); + KBDReset(makedev(DCDEV, DCKBD_PORT), dcPutc); + MouseInit(makedev(DCDEV, DCMOUSE_PORT), dcPutc, dcGetc); + splx(s); + } else if (major(cn_tab->cn_dev) == DCDEV) { + s = spltty(); + dcaddr->dc_lpr = LPR_RXENAB | LPR_8_BIT_CHAR | + LPR_B9600 | minor(cn_tab->cn_dev); + MachEmptyWriteBuffer(); + DELAY(1000); + /*cn_tab.cn_disabled = 0;*/ /* FIXME */ + splx(s); + } + } + + return (1); +} + +dcopen(dev, flag, mode, p) + dev_t dev; + int flag, mode; + struct proc *p; +{ + register struct tty *tp; + register int unit; + int s, error = 0; + + unit = minor(dev); + if (unit >= dc_cnt || dcpdma[unit].p_addr == (void *)0) + return (ENXIO); + tp = dc_tty[unit]; + if (tp == NULL) + tp = dc_tty[unit] = ttymalloc(); + tp->t_oproc = dcstart; + tp->t_param = dcparam; + tp->t_dev = dev; + if ((tp->t_state & TS_ISOPEN) == 0) { + tp->t_state |= TS_WOPEN; + ttychars(tp); +#ifndef PORTSELECTOR + if (tp->t_ispeed == 0) { +#endif + tp->t_iflag = TTYDEF_IFLAG; + tp->t_oflag = TTYDEF_OFLAG; + tp->t_cflag = TTYDEF_CFLAG; + tp->t_lflag = LFLAG; + tp->t_ispeed = tp->t_ospeed = ISPEED; +#ifdef PORTSELECTOR + tp->t_cflag |= HUPCL; +#else + } +#endif + (void) dcparam(tp, &tp->t_termios); + ttsetwater(tp); + } else if ((tp->t_state & TS_XCLUDE) && curproc->p_ucred->cr_uid != 0) + return (EBUSY); + (void) dcmctl(dev, DML_DTR, DMSET); + s = spltty(); + while (!(flag & O_NONBLOCK) && !(tp->t_cflag & CLOCAL) && + !(tp->t_state & TS_CARR_ON)) { + tp->t_state |= TS_WOPEN; + if (error = ttysleep(tp, (caddr_t)&tp->t_rawq, TTIPRI | PCATCH, + ttopen, 0)) + break; + } + splx(s); + if (error) + return (error); + return ((*linesw[tp->t_line].l_open)(dev, tp)); +} + +/*ARGSUSED*/ +dcclose(dev, flag, mode, p) + dev_t dev; + int flag, mode; + struct proc *p; +{ + register struct tty *tp; + register int unit, bit; + + unit = minor(dev); + tp = dc_tty[unit]; + bit = 1 << ((unit & 03) + 8); + if (dc_brk[unit >> 2] & bit) { + dc_brk[unit >> 2] &= ~bit; + ttyoutput(0, tp); + } + (*linesw[tp->t_line].l_close)(tp, flag); + if ((tp->t_cflag & HUPCL) || (tp->t_state & TS_WOPEN) || + !(tp->t_state & TS_ISOPEN)) + (void) dcmctl(dev, 0, DMSET); + return (ttyclose(tp)); +} + +dcread(dev, uio, flag) + dev_t dev; + struct uio *uio; +{ + register struct tty *tp; + + tp = dc_tty[minor(dev)]; + return ((*linesw[tp->t_line].l_read)(tp, uio, flag)); +} + +dcwrite(dev, uio, flag) + dev_t dev; + struct uio *uio; +{ + register struct tty *tp; + + tp = dc_tty[minor(dev)]; + return ((*linesw[tp->t_line].l_write)(tp, uio, flag)); +} + +struct tty * +dctty(dev) + dev_t dev; +{ + struct tty *tp = dc_tty [minor (dev)]; + return (tp); +} + +/*ARGSUSED*/ +dcioctl(dev, cmd, data, flag, p) + dev_t dev; + int cmd; + caddr_t data; + int flag; + struct proc *p; +{ + register struct tty *tp; + register int unit = minor(dev); + register int dc = unit >> 2; + int error; + + tp = dc_tty[unit]; + error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p); + if (error >= 0) + return (error); + error = ttioctl(tp, cmd, data, flag, p); + if (error >= 0) + return (error); + + switch (cmd) { + + case TIOCSBRK: + dc_brk[dc] |= 1 << ((unit & 03) + 8); + ttyoutput(0, tp); + break; + + case TIOCCBRK: + dc_brk[dc] &= ~(1 << ((unit & 03) + 8)); + ttyoutput(0, tp); + break; + + case TIOCSDTR: + (void) dcmctl(dev, DML_DTR|DML_RTS, DMBIS); + break; + + case TIOCCDTR: + (void) dcmctl(dev, DML_DTR|DML_RTS, DMBIC); + break; + + case TIOCMSET: + (void) dcmctl(dev, *(int *)data, DMSET); + break; + + case TIOCMBIS: + (void) dcmctl(dev, *(int *)data, DMBIS); + break; + + case TIOCMBIC: + (void) dcmctl(dev, *(int *)data, DMBIC); + break; + + case TIOCMGET: + *(int *)data = dcmctl(dev, 0, DMGET); + break; + + default: + return (ENOTTY); + } + return (0); +} + +dcparam(tp, t) + register struct tty *tp; + register struct termios *t; +{ + register dcregs *dcaddr; + register int lpr; + register int cflag = t->c_cflag; + int unit = minor(tp->t_dev); + int ospeed = ttspeedtab(t->c_ospeed, dcspeedtab); + + /* check requested parameters */ + if (ospeed < 0 || (t->c_ispeed && t->c_ispeed != t->c_ospeed) || + (cflag & CSIZE) == CS5 || (cflag & CSIZE) == CS6 || + (vax_boardtype == -1 && t->c_ospeed == 19200)) + return (EINVAL); + /* and copy to tty */ + tp->t_ispeed = t->c_ispeed; + tp->t_ospeed = t->c_ospeed; + tp->t_cflag = cflag; + + dcaddr = (dcregs *)dcpdma[unit].p_addr; + + /* + * Handle console cases specially. + */ + if (raster_console()) { + if (unit == DCKBD_PORT) { + dcaddr->dc_lpr = LPR_RXENAB | LPR_8_BIT_CHAR | + LPR_B4800 | DCKBD_PORT; + MachEmptyWriteBuffer(); + return (0); + } else if (unit == DCMOUSE_PORT) { + dcaddr->dc_lpr = LPR_RXENAB | LPR_B4800 | LPR_OPAR | + LPR_PARENB | LPR_8_BIT_CHAR | DCMOUSE_PORT; + MachEmptyWriteBuffer(); + return (0); + } + } else if (tp->t_dev == cn_tab->cn_dev) { + dcaddr->dc_lpr = LPR_RXENAB | LPR_8_BIT_CHAR | + LPR_B9600 | unit; + MachEmptyWriteBuffer(); + return (0); + } + if (ospeed == 0) { + (void) dcmctl(unit, 0, DMSET); /* hang up line */ + return (0); + } + lpr = LPR_RXENAB | ospeed | (unit & 03); + if ((cflag & CSIZE) == CS7) + lpr |= LPR_7_BIT_CHAR; + else + lpr |= LPR_8_BIT_CHAR; + if (cflag & PARENB) + lpr |= LPR_PARENB; + if (cflag & PARODD) + lpr |= LPR_OPAR; + if (cflag & CSTOPB) + lpr |= LPR_2_STOP; + dcaddr->dc_lpr = lpr; + MachEmptyWriteBuffer(); + DELAY(10); + return (0); +} + +/* + * Check for interrupts from all devices. + */ +int +dcintr(xxxunit) + void *xxxunit; +{ + register struct dc_softc *sc = xxxunit; + register dcregs *dcaddr; + register unsigned csr; + + register int unit = sc->sc_dv.dv_unit; + + unit <<= 2; + dcaddr = (dcregs *)dcpdma[unit].p_addr; + while ((csr = dcaddr->dc_csr) & (CSR_RDONE | CSR_TRDY)) { + if (csr & CSR_RDONE) + dcrint(unit); + if (csr & CSR_TRDY) + dcxint(dc_tty[unit + ((csr >> 8) & 03)]); + } + /* XXX check for spurious interrupts */ + return 0; +} + +dcrint(unit) + register int unit; +{ + register dcregs *dcaddr; + register struct tty *tp; + register int c, cc; + int overrun = 0; + + dcaddr = (dcregs *)dcpdma[unit].p_addr; + while ((c = dcaddr->dc_rbuf) < 0) { /* char present */ + cc = c & 0xff; + tp = dc_tty[unit + ((c >> 8) & 03)]; + if ((c & RBUF_OERR) && overrun == 0) { + log(LOG_WARNING, "dc%d,%d: silo overflow\n", unit >> 2, + (c >> 8) & 03); + overrun = 1; + } + /* the keyboard requires special translation */ + if (tp == dc_tty[DCKBD_PORT] && raster_console()) { +#ifdef KADB + if (cc == LK_DO) { + spl0(); + kdbpanic(); + return; + } +#endif +#ifdef DEBUG + debugChar = cc; +#endif + if (dcDivertXInput) { + (*dcDivertXInput)(cc); + return; + } + if ((cc = kbdMapChar(cc)) < 0) + return; +#ifdef notyet + } else if (tp == dc_tty[DCMOUSE_PORT] && dcMouseButtons) { + mouseInput(cc); + return; +#endif + } + if (!(tp->t_state & TS_ISOPEN)) { + wakeup((caddr_t)&tp->t_rawq); +#ifdef PORTSELECTOR + if (!(tp->t_state & TS_WOPEN)) +#endif + return; + } + if (c & RBUF_FERR) + cc |= TTY_FE; + if (c & RBUF_PERR) + cc |= TTY_PE; + (*linesw[tp->t_line].l_rint)(cc, tp); + } + DELAY(10); +} + +void +dcxint(tp) + register struct tty *tp; +{ + register struct pdma *dp; + register dcregs *dcaddr; + int unit = minor(tp->t_dev); + + dp = &dcpdma[unit]; + if (dp->p_mem < dp->p_end) { + dcaddr = (dcregs *)dp->p_addr; + dcaddr->dc_tdr = dc_brk[unit >> 2] | *dp->p_mem++; + MachEmptyWriteBuffer(); + DELAY(10); + return; + } + tp->t_state &= ~TS_BUSY; + if (tp->t_state & TS_FLUSH) + tp->t_state &= ~TS_FLUSH; + else { + ndflush(&tp->t_outq, dp->p_mem - (caddr_t) tp->t_outq.c_cf); + dp->p_end = dp->p_mem = tp->t_outq.c_cf; + } + if (tp->t_line) + (*linesw[tp->t_line].l_start)(tp); + else + dcstart(tp); + if (tp->t_outq.c_cc == 0 || !(tp->t_state & TS_BUSY)) { + dcaddr = (dcregs *)dp->p_addr; + dcaddr->dc_tcr &= ~(1 << (unit & 03)); + MachEmptyWriteBuffer(); + DELAY(10); + } +} + +void +dcstart(tp) + register struct tty *tp; +{ + register struct pdma *dp; + register dcregs *dcaddr; + register int cc; + int s; + + dp = &dcpdma[minor(tp->t_dev)]; + dcaddr = (dcregs *)dp->p_addr; + s = spltty(); + if (tp->t_state & (TS_TIMEOUT|TS_BUSY|TS_TTSTOP)) + goto out; + if (tp->t_outq.c_cc <= tp->t_lowat) { + if (tp->t_state & TS_ASLEEP) { + tp->t_state &= ~TS_ASLEEP; + wakeup((caddr_t)&tp->t_outq); + } + selwakeup(&tp->t_wsel); + } + if (tp->t_outq.c_cc == 0) + goto out; + /* handle console specially */ + if (tp == dc_tty[DCKBD_PORT] && raster_console()) { + while (tp->t_outq.c_cc > 0) { + cc = getc(&tp->t_outq) & 0x7f; + cnputc(cc); + } + /* + * After we flush the output queue we may need to wake + * up the process that made the output. + */ + if (tp->t_outq.c_cc <= tp->t_lowat) { + if (tp->t_state & TS_ASLEEP) { + tp->t_state &= ~TS_ASLEEP; + wakeup((caddr_t)&tp->t_outq); + } + selwakeup(&tp->t_wsel); + } + goto out; + } + cc = ndqb(&tp->t_outq, 0); + if (cc == 0) + goto out; + + tp->t_state |= TS_BUSY; + dp->p_end = dp->p_mem = tp->t_outq.c_cf; + dp->p_end += cc; + dcaddr->dc_tcr |= 1 << (minor(tp->t_dev) & 03); + MachEmptyWriteBuffer(); +out: + splx(s); +} + +/* + * Stop output on a line. + */ +/*ARGSUSED*/ +void +dcstop(tp, flag) + register struct tty *tp; +{ + register struct pdma *dp; + register int s; + + dp = &dcpdma[minor(tp->t_dev)]; + s = spltty(); + if (tp->t_state & TS_BUSY) { + dp->p_end = dp->p_mem; + if (!(tp->t_state & TS_TTSTOP)) + tp->t_state |= TS_FLUSH; + } + splx(s); +} + +dcmctl(dev, bits, how) + dev_t dev; + int bits, how; +{ + register dcregs *dcaddr; + register int unit, mbits; + int b, s; + register int msr; + + unit = minor(dev); + b = 1 << (unit & 03); + dcaddr = (dcregs *)dcpdma[unit].p_addr; + s = spltty(); + /* only channel 2 has modem control (what about line 3?) */ + mbits = DML_DTR | DML_DSR | DML_CAR; + switch (unit & 03) { + case 2: + mbits = 0; + if (dcaddr->dc_tcr & TCR_DTR2) + mbits |= DML_DTR; + msr = dcaddr->dc_msr; + if (msr & MSR_CD2) + mbits |= DML_CAR; + if (msr & MSR_DSR2) { + if (vax_boardtype == -1) + mbits |= DML_CAR | DML_DSR; + else + mbits |= DML_DSR; + } + break; + + case 3: + if (vax_boardtype != -1) { + mbits = 0; + if (dcaddr->dc_tcr & TCR_DTR3) + mbits |= DML_DTR; + msr = dcaddr->dc_msr; + if (msr & MSR_CD3) + mbits |= DML_CAR; + if (msr & MSR_DSR3) + mbits |= DML_DSR; + } + } + switch (how) { + case DMSET: + mbits = bits; + break; + + case DMBIS: + mbits |= bits; + break; + + case DMBIC: + mbits &= ~bits; + break; + + case DMGET: + (void) splx(s); + return (mbits); + } + switch (unit & 03) { + case 2: + if (mbits & DML_DTR) + dcaddr->dc_tcr |= TCR_DTR2; + else + dcaddr->dc_tcr &= ~TCR_DTR2; + break; + + case 3: + if (vax_boardtype != -1) { + if (mbits & DML_DTR) + dcaddr->dc_tcr |= TCR_DTR3; + else + dcaddr->dc_tcr &= ~TCR_DTR3; + } + } + if ((mbits & DML_DTR) && (dcsoftCAR[unit >> 2] & b)) + dc_tty[unit]->t_state |= TS_CARR_ON; + (void) splx(s); + return (mbits); +} + +/* + * This is called by timeout() periodically. + * Check to see if modem status bits have changed. + */ +void +dcscan(arg) + void *arg; +{ + register dcregs *dcaddr; + register struct tty *tp; + register int i, bit, car; + int s; + + s = spltty(); + /* only channel 2 has modem control (what about line 3?) */ + dcaddr = (dcregs *)dcpdma[i = 2].p_addr; + tp = dc_tty[i]; + bit = TCR_DTR2; + if (dcsoftCAR[i >> 2] & bit) + car = 1; + else + car = dcaddr->dc_msr & MSR_DSR2; + if (car) { + /* carrier present */ + if (!(tp->t_state & TS_CARR_ON)) + (void)(*linesw[tp->t_line].l_modem)(tp, 1); + } else if ((tp->t_state & TS_CARR_ON) && + (*linesw[tp->t_line].l_modem)(tp, 0) == 0) + dcaddr->dc_tcr &= ~bit; + splx(s); + timeout(dcscan, (void *)0, hz); +} + +/* + * ---------------------------------------------------------------------------- + * + * dcGetc -- + * + * Read a character from a serial line. + * + * Results: + * A character read from the serial port. + * + * Side effects: + * None. + * + * ---------------------------------------------------------------------------- + */ +int +dcGetc(dev) + dev_t dev; +{ + register dcregs *dcaddr; + register int c; + int s; + + dcaddr = (dcregs *)dcpdma[minor(dev)].p_addr; + if (!dcaddr) + return (0); + s = spltty(); + for (;;) { + if (!(dcaddr->dc_csr & CSR_RDONE)) + continue; + c = dcaddr->dc_rbuf; + DELAY(10); + if (((c >> 8) & 03) == (minor(dev) & 03)) + break; + } + splx(s); + return (c & 0xff); +} + +/* + * Send a char on a port, non interrupt driven. + */ +void +dcPutc(dev, c) + dev_t dev; + int c; +{ + register dcregs *dcaddr; + register u_short tcr; + register int timeout; + int s, line; + + s = spltty(); + + dcaddr = (dcregs *)dcpdma[minor(dev)].p_addr; + tcr = dcaddr->dc_tcr; + dcaddr->dc_tcr = tcr | (1 << minor(dev)); + MachEmptyWriteBuffer(); + DELAY(10); + while (1) { + /* + * Wait for transmitter to be not busy. + */ + timeout = 1000000; + while (!(dcaddr->dc_csr & CSR_TRDY) && timeout > 0) + timeout--; + if (timeout == 0) { + printf("dcPutc: timeout waiting for CSR_TRDY\n"); + break; + } + line = (dcaddr->dc_csr >> 8) & 3; + /* + * Check to be sure its the right port. + */ + if (line != minor(dev)) { + tcr |= 1 << line; + dcaddr->dc_tcr &= ~(1 << line); + MachEmptyWriteBuffer(); + DELAY(10); + continue; + } + /* + * Start sending the character. + */ + dcaddr->dc_tdr = dc_brk[0] | (c & 0xff); + MachEmptyWriteBuffer(); + DELAY(10); + /* + * Wait for character to be sent. + */ + while (1) { + /* + * cc -O bug: this code produces and infinite loop! + * while (!(dcaddr->dc_csr & CSR_TRDY)) + * ; + */ + timeout = 1000000; + while (!(dcaddr->dc_csr & CSR_TRDY) && timeout > 0) + timeout--; + line = (dcaddr->dc_csr >> 8) & 3; + if (line != minor(dev)) { + tcr |= 1 << line; + dcaddr->dc_tcr &= ~(1 << line); + MachEmptyWriteBuffer(); + DELAY(10); + continue; + } + dcaddr->dc_tcr &= ~(1 << minor(dev)); + MachEmptyWriteBuffer(); + DELAY(10); + break; + } + break; + } + /* + * Enable interrupts for other lines which became ready. + */ + if (tcr & 0xF) { + dcaddr->dc_tcr = tcr; + MachEmptyWriteBuffer(); + DELAY(10); + } + + splx(s); +} +#endif /* NDC */ diff --git a/sys/arch/vax/vsa/dc7085cons.h b/sys/arch/vax/vsa/dc7085cons.h new file mode 100644 index 00000000000..1c5a55b19a3 --- /dev/null +++ b/sys/arch/vax/vsa/dc7085cons.h @@ -0,0 +1,170 @@ +/* $NetBSD: dc7085cons.h,v 1.1 1996/07/20 18:55:10 ragge Exp $ */ +/* + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Ralph Campbell and Rick Macklem. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)dc7085cons.h 8.1 (Berkeley) 6/10/93 + * + * dc7085.h -- + * + * Definitions for the dc7085 chip. + * + * Copyright (C) 1989 Digital Equipment Corporation. + * Permission to use, copy, modify, and distribute this software and + * its documentation for any purpose and without fee is hereby granted, + * provided that the above copyright notice appears in all copies. + * Digital Equipment Corporation makes no representations about the + * suitability of this software for any purpose. It is provided "as is" + * without express or implied warranty. + * + * from: Header: /sprite/src/kernel/dev/ds3100.md/RCS/dc7085.h, + * + * v 1.4 89/08/15 19:52:46 rab Exp SPRITE (DECWRL) + */ + +#ifndef _DC7085 +#define _DC7085 + +typedef volatile struct dc7085regs { + u_short dc_csr; /* control and status (R/W) */ + u_short pad0; + short dc_rbuf_lpr; /* receiver data (R), line params (W) */ + u_short pad1; + u_short dc_tcr; /* transmitter control (R/W) */ + u_short pad2; + u_short dc_msr_tdr; /* modem status (R), transmit data (W) */ +} dcregs; +#define dc_rbuf dc_rbuf_lpr +#define dc_lpr dc_rbuf_lpr +#define dc_msr dc_msr_tdr +#define dc_tdr dc_msr_tdr + +/* + * Control status register bits. + */ +#define CSR_TRDY 0x8000 +#define CSR_TIE 0x4000 /* not avail on VS2000 */ +#define CSR_TX_LINE_NUM 0x0300 +#define CSR_RDONE 0x0080 +#define CSR_RIE 0x0040 /* not avail on VS2000 */ +#define CSR_MSE 0x0020 +#define CSR_CLR 0x0010 +#define CSR_MAINT 0x0008 + +/* + * Receiver buffer register bits. + */ +#define RBUF_DVAL 0x8000 +#define RBUF_OERR 0x4000 +#define RBUF_FERR 0x2000 +#define RBUF_PERR 0x1000 +#define RBUF_LINE_NUM 0x0300 +#define RBUF_LINE_NUM_SHIFT 8 +#define RBUF_CHAR 0x00FF + +/* + * Transmit control register values. + */ +#define TCR_DTR2 0x0400 +#define TCR_EN3 0x0008 +#define TCR_EN2 0x0004 +#define TCR_EN1 0x0002 +#define TCR_EN0 0x0001 + +#define TCR_RTS2 0x0800 /* VS2000: LLBK_2 */ +#define TCR_RTS3 0x0200 /* VS2000: DSRS_2 */ +#define TCR_DTR3 0x0100 /* VS2000: RTS_2 */ + +/* + * Line parameter register bits. + */ +#define LPR_RXENAB 0x1000 +#define LPR_B50 0x0000 +#define LPR_B75 0x0100 +#define LPR_B110 0x0200 +#define LPR_B134 0x0300 +#define LPR_B150 0x0400 +#define LPR_B300 0x0500 +#define LPR_B600 0x0600 +#define LPR_B1200 0x0700 +#define LPR_B1800 0x0800 +#define LPR_B2000 0x0900 +#define LPR_B2400 0x0A00 +#define LPR_B3600 0x0B00 +#define LPR_B4800 0x0C00 +#define LPR_B7200 0x0D00 +#define LPR_B9600 0x0E00 +#define LPR_B19200 0x0F00 +#define LPR_B38400 0x0F00 +#define LPR_OPAR 0x0080 +#define LPR_PARENB 0x0040 +#define LPR_2_STOP 0x0020 +#define LPR_8_BIT_CHAR 0x0018 +#define LPR_7_BIT_CHAR 0x0010 +#define LPR_6_BIT_CHAR 0x0008 +#define LPR_5_BIT_CHAR 0x0000 + +/* + * Modem status register bits. + */ +#define MSR_DSR2 0x0200 + +#define MSR_RI2 0x0800 /* VS2000: 0x0004 */ +#define MSR_CD2 0x0400 +#define MSR_CTS2 0x0100 +#define MSR_RI3 0x0008 /* VS2000: not used/available */ +#define MSR_CD3 0x0004 /* VS2000: RI2 */ +#define MSR_DSR3 0x0002 /* VS2000: MBZ */ +#define MSR_CTS3 0x0001 /* VS2000: TMI_2 */ + +/* + * The four serial ports. + */ +#define DCKBD_PORT 0 +#define DCMOUSE_PORT 1 +#define DCCOMM_PORT 2 +#define DCPRINTER_PORT 3 + +/* bits in dm lsr, copied from dmreg.h */ +#define DML_DSR 0000400 /* data set ready, not a real DM bit */ +#define DML_RNG 0000200 /* ring */ +#define DML_CAR 0000100 /* carrier detect */ +#define DML_CTS 0000040 /* clear to send */ +#define DML_SR 0000020 /* secondary receive */ +#define DML_ST 0000010 /* secondary transmit */ +#define DML_RTS 0000004 /* request to send */ +#define DML_DTR 0000002 /* data terminal ready */ +#define DML_LE 0000001 /* line enable */ + +#endif /* _DC7085 */ diff --git a/sys/arch/vax/vsa/hdc9224.c b/sys/arch/vax/vsa/hdc9224.c new file mode 100644 index 00000000000..bb9aaa4326a --- /dev/null +++ b/sys/arch/vax/vsa/hdc9224.c @@ -0,0 +1,1144 @@ +/* $NetBSD: hdc9224.c,v 1.4 1996/10/13 03:36:11 christos Exp $ */ +/* + * Copyright (c) 1996 Ludd, University of Lule}, Sweden. + * All rights reserved. + * + * This code is derived from software contributed to Ludd by Bertram Barth. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed at Ludd, University of + * Lule}, Sweden and its contributors. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * with much help from (in alphabetical order): + * Jeremy + * Roger Ivie + * Rick Macklem + * Mike Young + */ + +/* #define DEBUG /* */ +/* #define TRACE /* */ +static int haveLock = 0; +static int keepLock = 0; + +#define F_READ 11 +#define F_WRITE 12 + +#define trace(x) +#define debug(x) + +#include "hdc.h" +#if NHDC > 0 + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/kernel.h> +#include <sys/conf.h> +#include <sys/file.h> +#include <sys/stat.h> +#include <sys/ioctl.h> +#include <sys/buf.h> +#include <sys/proc.h> +#include <sys/user.h> +#include <sys/map.h> +#include <sys/device.h> +#include <sys/dkstat.h> +#include <sys/disklabel.h> +#include <sys/disk.h> +#include <sys/syslog.h> + +#include <machine/pte.h> +#include <machine/sid.h> +#include <machine/cpu.h> +#include <machine/uvax.h> +#include <machine/ka410.h> +#include <machine/vsbus.h> + +#include <vax/vsa/hdc9224.h> + + +/* + * some definitions + */ +#define CTLRNAME "hdc" +#define UNITNAME "rd" +#define HDC_PRI LOG_INFO + +/* Bits in minor device */ +#define HDCUNIT(dev) DISKUNIT(dev) +#define HDCPART(dev) DISKPART(dev) +#define HDCCTLR(dev) 0 +#define HDCLABELDEV(dev) (MAKEDISKDEV(major(dev),HDCUNIT(dev),RAW_PART)) + +#define MAX_WAIT (1000*1000) /* # of loop-instructions in seconds */ + + +/* + * on-disk geometry block + */ +#define _aP __attribute__ ((packed)) /* force byte-alignment */ +struct rdgeom { + char mbz[10]; /* 10 bytes of zero */ + long xbn_count _aP; /* number of XBNs */ + long dbn_count _aP; /* number of DBNs */ + long lbn_count _aP; /* number of LBNs (Logical-Block-Numbers) */ + long rbn_count _aP; /* number of RBNs (Replacement-Block-Numbers) */ + short nspt; /* number of sectors per track */ + short ntracks; /* number of tracks */ + short ncylinders; /* number of cylinders */ + short precomp; /* first cylinder for write precompensation */ + short reduced; /* first cylinder for reduced write current */ + short seek_rate; /* seek rate or zero for buffered seeks */ + short crc_eec; /* 0 if CRC is being used or 1 if ECC is being used */ + short rct; /* "replacement control table" (RCT) */ + short rct_ncopies; /* number of copies of the RCT */ + long media_id _aP; /* media identifier */ + short interleave; /* sector-to-sector interleave */ + short headskew; /* head-to-head skew */ + short cylskew; /* cylinder-to-cylinder skew */ + short gap0_size; /* size of GAP 0 in the MFM format */ + short gap1_size; /* size of GAP 1 in the MFM format */ + short gap2_size; /* size of GAP 2 in the MFM format */ + short gap3_size; /* size of GAP 3 in the MFM format */ + short sync_value; /* sync value used to start a track when formatting */ + char reserved[32]; /* reserved for use by the RQDX1/2/3 formatter */ + short serial_number; /* serial number */ +#if 0 /* we don't need these 412 useless bytes ... */ + char fill[412-2]; /* Filler bytes to the end of the block */ + short checksum; /* checksum over the XBN */ +#endif +}; + +/* + * Software status + */ +struct rdsoftc { + struct device sc_dev; /* must be here! (pseudo-OOP:) */ + struct disk sc_dk; /* disklabel etc. */ + struct rdgeom sc_xbn; /* on-disk geometry information */ + struct rdparams { + u_short cylinders; /* number of cylinders */ + u_char heads; /* number of heads (tracks) */ + u_char sectors; /* number of sectors/track */ + u_long diskblks; /* number of sectors/disk */ + u_long disklbns; /* number of available sectors */ + u_long blksize; /* number of bytes/sector */ + u_long diskbytes; /* number of bytes/disk */ + char diskname[8]; + } sc_param; + int sc_drive; /* physical unit number */ + int sc_flags; + int sc_state; + int sc_mode; +}; + +struct hdcsoftc { + struct device sc_dev; /* must be here (pseudo-OOP:) */ + struct hdc9224_DKCreg *sc_dkc; /* I/O address of the controller */ + struct hdc9224_UDCreg sc_creg; /* (command) registers to be written */ + struct hdc9224_UDCreg sc_sreg; /* (status) registers being read */ + struct confargs *sc_cfargs; /* remember args being probed with */ + char *sc_dmabase; /* */ + long sc_dmasize; /* */ + long sc_ioaddr; /* unmapped I/O address */ + long sc_ivec; /* interrupt vector address */ + short sc_ibit; /* bit-value in interrupt register */ + short sc_status; /* copy of status register */ + short sc_state; + short sc_flags; + short sc_errors; +}; + +/* + * Device definition for (new) autoconfiguration. + */ +int hdcmatch __P((struct device *parent, void *cfdata, void *aux)); +void hdcattach __P((struct device *parent, struct device *self, void *aux)); +int hdcprint __P((void *aux, const char *name)); + +struct cfdriver hdc_cd = { + NULL, "hdc", DV_DULL +}; +struct cfattach hdc_ca = { + sizeof(struct hdcsoftc), hdcmatch, hdcattach +}; + +int rdmatch __P((struct device *parent, void *cfdata, void *aux)); +void rdattach __P((struct device *parent, struct device *self, void *aux)); +int rdprint __P((void *aux, const char *name)); +void rdstrategy __P((struct buf *bp)); + +struct cfdriver rd_cd = { + NULL, "rd", DV_DISK +}; +struct cfattach rd_ca = { + sizeof(struct rdsoftc), rdmatch, rdattach +}; + +struct dkdriver rddkdriver = { rdstrategy }; + +/* + * prototypes for (almost) all the internal routines + */ +int hdc_reset __P((struct hdcsoftc *sc)); +int hdc_select __P((struct hdcsoftc *sc, int drive)); +int hdc_command __P((struct hdcsoftc *sc, int cmd)); + +int hdc_getdata __P((struct hdcsoftc *hdc, struct rdsoftc *rd, int drive)); +int hdc_getlabel __P((struct hdcsoftc *hdc, struct rdsoftc *rd, int drive)); + +void rdgetlabel __P((struct rdsoftc *sc)); + +/* + * new-config's hdcmatch() is similiar to old-config's hdcprobe(), + * thus we probe for the existence of the controller and reset it. + * NB: we can't initialize the controller yet, since space for hdcsoftc + * is not yet allocated. Thus we do this in hdcattach()... + */ +int +hdcmatch(parent, match, aux) + struct device *parent; + void *match, *aux; +{ + struct cfdata *cf = match; + struct confargs *ca = aux; + + trace(("hdcmatch(0x%x, %d, %s)\n", parent, cf->cf_unit, ca->ca_name)); + + if (strcmp(ca->ca_name, "hdc") && + strcmp(ca->ca_name, "hdc9224") && + strcmp(ca->ca_name, "HDC9224")) + return (0); + + /* + * only(?) VS2000/KA410 has exactly one HDC9224 controller + */ + if (vax_boardtype != VAX_BTYP_410) { + printf ("unexpected boardtype 0x%x in hdcmatch()\n", + vax_boardtype); + return (0); + } + if (cf->cf_unit != 0) + return (0); + + return (1); +} + +struct hdc_attach_args { + int ha_drive; +}; + +int +rdprint(aux, name) + void *aux; + const char *name; +{ + struct hdc_attach_args *ha = aux; + + trace(("rdprint(%d, %s)\n", ha->ha_drive, name)); + + if (!name) + printf (" drive %d", ha->ha_drive); + return (QUIET); +} + +/* + * hdc_attach() probes for all possible devices + */ +void +hdcattach(parent, self, aux) + struct device *parent, *self; + void *aux; +{ + struct hdcsoftc *sc = (void*)self; + struct confargs *ca = aux; + struct hdc_attach_args ha; + + trace(("hdcattach(0x%x, 0x%x, %s)\n", parent, self, ca->ca_name)); + + printf ("\n"); + /* + * first reset/initialize the controller + */ + sc->sc_cfargs = ca; + + sc->sc_ioaddr = ca->ca_ioaddr; + sc->sc_dkc = (void*)uvax_phys2virt(sc->sc_ioaddr); + sc->sc_ibit = ca->ca_intbit; + sc->sc_ivec = ca->ca_intvec; + sc->sc_status = 0; + sc->sc_state = 0; + sc->sc_flags = 0; + sc->sc_errors = 0; + + sc->sc_dkc = (void*)uvax_phys2virt(KA410_DKC_BASE); + sc->sc_dmabase = (void*)uvax_phys2virt(KA410_DMA_BASE); + sc->sc_dmasize = KA410_DMA_SIZE; + + if (hdc_reset(sc) != 0) { + delay(500*1000); /* wait .5 seconds */ + if (hdc_reset(sc) != 0) + printf ("problems with hdc_reset()...\n"); + } + + /* + * now probe for all possible disks + */ + for (ha.ha_drive=0; ha.ha_drive<3; ha.ha_drive++) + (void)config_found(self, (void*)&ha, rdprint); + +#ifdef notyet + /* + * now that probing is done, we can register and enable interrupts + */ + vsbus_intr_register(XXX); + vsbus_intr_enable(XXX); +#endif +} + +/* + * rdmatch() probes for the existence of a RD-type disk/floppy + */ +int +rdmatch(parent, match, aux) + struct device *parent; + void *match, *aux; +{ + struct hdcsoftc *hdc = (void*)parent; + struct cfdata *cf = match; + struct hdc_attach_args *ha = aux; + int drive = ha->ha_drive; + int res; + + trace(("rdmatch(%d, %d)\n", cf->cf_unit, drive)); + + if (cf->cf_unit != ha->ha_drive) + return (0); + + switch (drive) { + case 0: + case 1: + case 2: + res = hdc_select(hdc, drive); + break; + default: + printf ("rdmatch: invalid unit-number %d\n", drive); + return (0); + } + + debug (("cstat: %x dstat: %x\n", hdc->sc_sreg.udc_cstat, + hdc->sc_sreg.udc_dstat)); + if (drive == 1) + return (0); /* XXX */ + + return (1); +} + +void +rdattach(parent, self, aux) + struct device *parent, *self; + void *aux; +{ + struct hdcsoftc *hdc = (void*)parent; + struct rdsoftc *rd = (void*)self; + struct hdc_attach_args *ha = aux; + struct rdparams *rp = &rd->sc_param; + + trace(("rdattach(%d)\n", ha->ha_drive)); + + rd->sc_drive = ha->ha_drive; + /* + * Initialize and attach the disk structure. + */ + rd->sc_dk.dk_driver = &rddkdriver; + rd->sc_dk.dk_name = rd->sc_dev.dv_xname; + disk_attach(&rd->sc_dk); + /* + * if it's not a floppy then evaluate the on-disk geometry. + * if neccessary correct the label... + */ + printf("\n%s: ", rd->sc_dev.dv_xname); + if (rd->sc_drive == 2) { + printf("floppy (RX33)\n"); + } + else { + hdc_getdata(hdc, rd, rd->sc_drive); + printf("%s, %d MB, %d LBN, %d cyl, %d head, %d sect/track\n", + rp->diskname, rp->diskblks/2048, rp->disklbns, + rp->cylinders, rp->heads, rp->sectors); + } +} + +/* + * Read/write routine for a buffer. For now we poll the controller, + * thus this routine waits for the transfer to complete. + */ +void +rdstrategy(bp) + struct buf *bp; +{ + struct rdsoftc *rd = rd_cd.cd_devs[HDCUNIT(bp->b_dev)]; + struct hdcsoftc *hdc = (void *)rd->sc_dev.dv_parent; + struct partition *p; + int blkno, i, s; + + trace (("rdstrategy(#%d/%d)\n", bp->b_blkno, bp->b_bcount)); + + /* XXX should make some checks... */ + + /* + * If it's a null transfer, return immediatly + */ + if (bp->b_bcount == 0) + goto done; + + /* + * what follows now should not be here but in rdstart... + */ + /*------------------------------*/ + blkno = bp->b_blkno / (rd->sc_dk.dk_label->d_secsize / DEV_BSIZE); + if (HDCPART(bp->b_dev) != RAW_PART) { + p = &rd->sc_dk.dk_label->d_partitions[HDCPART(bp->b_dev)]; + blkno += p->p_offset; + } + /* nblks = howmany(bp->b_bcount, sd->sc_dk.dk_label->d_secsize); */ + + if (hdc_strategy(hdc, rd, HDCUNIT(bp->b_dev), + ((bp->b_flags & B_READ) ? F_READ : F_WRITE), + blkno, bp->b_bcount, bp->b_data) == 0) + goto done; + /*------------------------------*/ +bad: + bp->b_flags |= B_ERROR; +done: + /* + * Correctly set the buf to indicate a completed xfer + */ + bp->b_resid = 0; /* ??? bertram */ + biodone(bp); +} + +int +hdc_strategy(hdc, rd, unit, func, dblk, size, buf) + struct hdcsoftc *hdc; + struct rdsoftc *rd; + int unit; + int func; + int dblk; + int size; + char *buf; +{ + struct hdc9224_UDCreg *p = &hdc->sc_creg; + struct disklabel *lp = rd->sc_dk.dk_label; + int sect, head, cyl; + int scount; + int cmd, res = 0; + + trace (("hdc_strategy(%d, %d, %d, %d, 0x%x)\n", + unit, func, dblk, size, buf)); + + hdc_select(hdc, unit); /* select drive right now */ + + if (unit != 2 && dblk == -1) { /* read the on-disk geometry */ + + p->udc_dma7 = 0; + p->udc_dma15 = 0; + p->udc_dma23 = 0; + + p->udc_dsect = 0; + p->udc_dhead = 0; + p->udc_dcyl = 0; + + p->udc_scnt = size/512; + p->udc_rtcnt = 0xF0; + p->udc_mode = 0xC0; + p->udc_term = 0xB4; + + vsbus_lockDMA(hdc->sc_cfargs); /* bertram XXX */ + haveLock = 1; + keepLock = 1; + +#ifdef PARANOID + bzero (hdc->sc_dmabase, size); /* clear disk buffer */ +#endif + cmd = 0x5C | 0x03; /* bypass bad sectors */ + cmd = 0x5C | 0x01; /* terminate if bad sector */ + + res = hdc_command (hdc, cmd); + /* hold the locking ! */ + bcopy (hdc->sc_dmabase, buf, size); /* copy to buf */ + /* now release the locking */ + + vsbus_unlockDMA(hdc->sc_cfargs); + haveLock = 0; + keepLock = 0; + + return (res); + } + + scount = size / 512; + while (scount) { + /* + * prepare drive/operation parameter + */ + cyl = dblk / lp->d_secpercyl; + sect = dblk % lp->d_secpercyl; + head = sect / lp->d_nsectors; + sect = sect % lp->d_nsectors; + if (unit == 2) + sect++; + else + cyl++; /* first cylinder is reserved */ + + size = 512 * min(scount, lp->d_nsectors - sect); + + debug (("hdc_strategy: block #%d ==> s/t/c=%d/%d/%d (%d/%d)\n", + dblk, sect, head, cyl, scount, size)); + + /* + * now initialize the register values ... + */ + p->udc_dma7 = 0; + p->udc_dma15 = 0; + p->udc_dma23 = 0; + + p->udc_dsect = sect; + head |= (cyl >> 4) & 0x70; + p->udc_dhead = head; + p->udc_dcyl = cyl; + + p->udc_scnt = size/512; + + if (unit == 2) { /* floppy */ + p->udc_rtcnt = 0xF2; + p->udc_mode = 0x81; /* RX33 with RX50 media */ + p->udc_mode = 0x82; /* RX33 with RX33 media */ + p->udc_term = 0xB4; + } else { /* disk */ + p->udc_rtcnt = 0xF0; + p->udc_mode = 0xC0; + p->udc_term = 0xB4; + } + + vsbus_lockDMA(hdc->sc_cfargs); + haveLock = 1; + keepLock = 1; + + if (func == F_WRITE) { + bcopy (buf, hdc->sc_dmabase, size); /* copy from buf */ + cmd = 0xA0 | (unit==2 ? 1 : 0); + res = hdc_command (hdc, cmd); + } + else { +#ifdef PARANOID + bzero (hdc->sc_dmabase, size); /* clear disk buffer */ +#endif + cmd = 0x5C | 0x03; /* bypass bad sectors */ + cmd = 0x5C | 0x01; /* terminate if bad sector */ + res = hdc_command (hdc, cmd); + bcopy (hdc->sc_dmabase, buf, size); /* copy to buf */ + } + + vsbus_unlockDMA(hdc->sc_cfargs); + haveLock = 0; + keepLock = 0; + + scount -= size/512; + dblk += size/512; + buf += size; + } + + if (unit != 2) /* deselect drive, if not floppy */ + hdc_command (hdc, DKC_CMD_DRDESELECT); + + return 0; +} + +char hdc_iobuf[17*512]; /* we won't need more */ + +#ifdef DEBUG +/* + * display the contents of the on-disk geometry structure + */ +int +hdc_printgeom(p) + struct rdgeom *p; +{ + char dname[8]; + hdc_mid2str(p->media_id, dname); + + printf ("**DiskData** XBNs: %d, DBNs: %d, LBNs: %d, RBNs: %d\n", + p->xbn_count, p->dbn_count, p->lbn_count, p->rbn_count); + printf ("sec/track: %d, tracks: %d, cyl: %d, precomp/reduced: %d/%d\n", + p->nspt, p->ntracks, p->ncylinders, p->precomp, p->reduced); + printf ("seek-rate: %d, crc/eec: %s, RCT: %d, RCT-copies: %d\n", + p->seek_rate, p->crc_eec?"EEC":"CRC", p->rct, p->rct_ncopies); + printf ("media-ID: %s, interleave: %d, headskew: %d, cylskew: %d\n", + dname, p->interleave, p->headskew, p->cylskew); + printf ("gap0: %d, gap1: %d, gap2: %d, gap3: %d, sync-value: %d\n", + p->gap0_size, p->gap1_size, p->gap2_size, p->gap3_size, + p->sync_value); +} +#endif + +/* + * Convert media_id to string/name (encoding is documented in mscp.h) + */ +int +hdc_mid2str(media_id, name) + long media_id; + char *name; +{ + struct { /* For RD32 this struct holds: */ + u_long mt:7; /* number in name: 0x20 == 32 */ + u_long a2:5; /* ' ' encoded as 0x0 */ + u_long a1:5; /* 'D' encoded with base '@' */ + u_long a0:5; /* 'R' encoded with base '@' */ + u_long d1:5; /* 'U' encoded with base '@' */ + u_long d0:5; /* 'D' encoded with base '@' */ + } *p = (void*)&media_id; + +#define MIDCHR(x) (x ? x + '@' : ' ') + + sprintf (name, "%c%c%d", MIDCHR(p->a0), MIDCHR(p->a1), p->mt); +} + +int +hdc_getdata(hdc, rd, unit) + struct hdcsoftc *hdc; + struct rdsoftc *rd; + int unit; +{ + struct disklabel *lp = rd->sc_dk.dk_label; + struct rdparams *rp = &rd->sc_param; + int res; + + trace (("hdc_getdata(%d)\n", unit)); + + bzero(rd->sc_dk.dk_label, sizeof(struct disklabel)); + bzero(rd->sc_dk.dk_cpulabel, sizeof(struct cpu_disklabel)); + + if (unit == 2) { + lp->d_secsize = DEV_BSIZE; + lp->d_ntracks = 2; + lp->d_nsectors = 15; + lp->d_ncylinders = 80; + lp->d_secpercyl = lp->d_ntracks * lp->d_nsectors; + + return (0); + } + + res = hdc_strategy(hdc, rd, unit, F_READ, -1, 4096, hdc_iobuf); + bcopy (hdc_iobuf, &rd->sc_xbn, sizeof(struct rdgeom)); +#ifdef DEBUG + hdc_printgeom(&rd->sc_xbn); +#endif + lp->d_secsize = DEV_BSIZE; + lp->d_ntracks = rd->sc_xbn.ntracks; + lp->d_nsectors = rd->sc_xbn.nspt; + lp->d_ncylinders = rd->sc_xbn.ncylinders; + lp->d_secpercyl = lp->d_ntracks * lp->d_nsectors; + + rp->cylinders = rd->sc_xbn.ncylinders; + rp->heads = rd->sc_xbn.ntracks; + rp->sectors = rd->sc_xbn.nspt; + rp->diskblks = rp->cylinders * rp->heads * rp->sectors; + rp->disklbns = rd->sc_xbn.lbn_count; + rp->blksize = DEV_BSIZE; + rp->diskbytes = rp->disklbns * rp->blksize; + hdc_mid2str(rd->sc_xbn.media_id, rp->diskname); + + return (0); +} + +int +hdc_getlabel(hdc, rd, unit) + struct hdcsoftc *hdc; + struct rdsoftc *rd; + int unit; +{ + struct disklabel *lp = rd->sc_dk.dk_label; + struct disklabel *xp = (void*)(hdc_iobuf + 64); + int res; + + trace (("hdc_getlabel(%d)\n", unit)); + +#define LBL_CHECK(x) if (xp->x != lp->x) { \ + printf ("%d-->%d\n", xp->x, lp->x); \ + xp->x = lp->x; \ + } + res = hdc_strategy(hdc, rd, unit, F_READ, 0, DEV_BSIZE, hdc_iobuf); + LBL_CHECK(d_secsize); + LBL_CHECK(d_ntracks); + LBL_CHECK(d_nsectors); + LBL_CHECK(d_ncylinders); + LBL_CHECK(d_secpercyl); + bcopy(xp, lp, sizeof(struct disklabel)); + + return (0); +} + +/* + * Return the size of a partition, if known, or -1 if not. + */ +hdcsize(dev) + dev_t dev; +{ + int unit = HDCUNIT(dev); + int part = HDCPART(dev); + struct rdsoftc *rd = rd_cd.cd_devs[unit]; + int size; + + trace (("hdcsize(%x == %d/%d)\n", dev, unit, part)); + + if (hdcopen(dev, 0, S_IFBLK) != 0) + return (-1); +#if 0 + if (rd->sc_dk.dk_label->d_partitions[part].p_fstype != FS_SWAP) + size = -1; + else +#endif + size = rd->sc_dk.dk_label->d_partitions[part].p_size; + if (hdcclose(dev, 0, S_IFBLK) != 0) + return (-1); + debug (("hdcsize: size=%d\n", size)); + return (size); +} + +/* + * + */ +int +hdcopen (dev, flag, fmt) + dev_t dev; + int flag; + int fmt; +{ + int unit = HDCUNIT(dev); + int part = HDCPART(dev); + struct hdcsoftc *hdc; + struct rdsoftc *rd; + int res, error; + + trace (("hdcopen(0x%x = %d/%d)\n", dev, unit, part)); + + if (unit >= rd_cd.cd_ndevs) { + printf ("hdcopen: invalid unit %d\n", unit); + return ENXIO; + } + rd = rd_cd.cd_devs[unit]; + if (!rd) { + printf("hdcopen: null-pointer in rdsoftc.\n"); + return (ENXIO); + } + hdc = (void *)rd->sc_dev.dv_parent; + + /* XXX here's much more to do! XXX */ + + hdc_getdata (hdc, rd, unit); + hdc_getlabel (hdc, rd, unit); + + return (0); +} + +/* + * + */ +int +hdcclose (dev, flag) + dev_t dev; + int flag; +{ + trace (("hdcclose()\n")); + return (0); +} + +/* + * + */ +void +hdcstrategy(bp) + register struct buf *bp; +{ + trace (("hdcstrategy()\n")); + rdstrategy(bp); + debug (("hdcstrategy done.\n")); +} + +/* + * + */ +int +hdcioctl(dev, cmd, data, flag, p) + dev_t dev; + int cmd; + caddr_t data; /* aka: addr */ + int flag; + struct proc *p; +{ + struct rdsoftc *rd = rd_cd.cd_devs[HDCUNIT(dev)]; + struct hdcsoftc *hdc = (void *)rd->sc_dev.dv_parent; + int error; + + trace (("hdcioctl(%x, %x)\n", dev, cmd)); + + /* + * If the device is not valid.. abandon ship + */ + /* XXX */ + + switch (cmd) { + case DIOCGDINFO: + *(struct disklabel *)data = *(rd->sc_dk.dk_label); + return (0); + + case DIOCGPART: + ((struct partinfo *)data)->disklab = rd->sc_dk.dk_label; + ((struct partinfo *)data)->part = + &rd->sc_dk.dk_label->d_partitions[HDCPART(dev)]; + return (0); + + case DIOCWDINFO: + case DIOCSDINFO: +/* XXX + if ((flag & FWRITE) == 0) + return EBADF; + + if ((error = sdlock(sd)) != 0) + return error; + sd->flags |= SDF_LABELLING; +*/ + error = setdisklabel(rd->sc_dk.dk_label, + (struct disklabel *)data, 0, rd->sc_dk.dk_cpulabel); + if (error == 0) { + if (cmd == DIOCWDINFO) + error = writedisklabel(HDCLABELDEV(dev), + rdstrategy, rd->sc_dk.dk_label, + rd->sc_dk.dk_cpulabel); + } +/* XXX + sd->flags &= ~SDF_LABELLING; + sdunlock(sd); +*/ + return (error); + + case DIOCWLABEL: + if ((flag & FWRITE) == 0) + return (EBADF); +/* XXX + if (*(int *)data) + sd->flags |= SDF_WLABEL; + else + sd->flags &= ~SDF_WLABEL; +*/ + return (0); + + default: + if (HDCPART(dev) != RAW_PART) + return ENOTTY; + printf ("IOCTL %x not implemented.\n", cmd); + return (-1); + } +} + +/* + * + */ +int +hdcintr() +{ + trace (("hdcintr()\n")); +} + +/* + * + */ +int +hdcread (dev, uio) + dev_t dev; + struct uio *uio; +{ + trace (("hdcread()\n")); + return (physio (hdcstrategy, NULL, dev, B_READ, minphys, uio)); +} + +/* + * + */ +int +hdcwrite (dev, uio) + dev_t dev; + struct uio *uio; +{ + trace (("hdcwrite()\n")); + return (physio (hdcstrategy, NULL, dev, B_WRITE, minphys, uio)); +} + +/* + * + */ +int +hdcdump(dev) + dev_t dev; +{ + trace (("hdcdump (%x)\n", dev)); +} + +/* + * we have to wait 0.7 usec between two accesses to any of the + * dkc-registers, on a VS2000 with 1 MIPS, this is roughly one + * instruction. Thus the loop-overhead will be enough... + */ +void +hdc_readregs(sc) + struct hdcsoftc *sc; +{ + int i; + char *p; + + trace(("hdc_readregs()\n")); + + sc->sc_dkc->dkc_cmd = 0x40; /* set internal counter to zero */ + p = (void*)&sc->sc_sreg; + for (i=0; i<10; i++) + *p++ = sc->sc_dkc->dkc_reg; /* dkc_reg auto-increments */ +} + +void +hdc_writeregs(sc) + struct hdcsoftc *sc; +{ + int i; + char *p; + + trace(("hdc_writeregs()\n")); + + sc->sc_dkc->dkc_cmd = 0x40; /* set internal counter to zero */ + p = (void*)&sc->sc_creg; + for (i=0; i<10; i++) + sc->sc_dkc->dkc_reg = *p++; /* dkc_reg auto-increments */ +} + +/* + * hdc_command() issues a command and polls the intreq-register + * to find when command has completed + */ +int +hdc_command(sc, cmd) + struct hdcsoftc *sc; + int cmd; +{ + volatile u_char *intreq = (void*)uvax_phys2virt(KA410_INTREQ); + volatile u_char *intclr = (void*)uvax_phys2virt(KA410_INTCLR); + volatile u_char *intmsk = (void*)uvax_phys2virt(KA410_INTMSK); + int i, c; + + trace (("hdc_command(%x)\n", cmd)); + debug (("intr-state: %x %x %x\n", *intreq, *intclr, *intmsk)); + + if (!haveLock) { + vsbus_lockDMA(sc->sc_cfargs); + haveLock = 1; + } + + hdc_writeregs(sc); /* write the prepared registers */ + *intclr = INTR_DC; /* clear any old interrupt */ + sc->sc_dkc->dkc_cmd = cmd; /* issue the command */ + for (i=0; i<MAX_WAIT; i++) { + if ((c = *intreq) & INTR_DC) + break; + } + if ((c & INTR_DC) == 0) { + printf ("hdc_command: timeout in command 0x%x\n", cmd); + } + hdc_readregs(sc); /* read the status registers */ + sc->sc_status = sc->sc_dkc->dkc_stat; + + if (!keepLock) { + vsbus_unlockDMA(sc->sc_cfargs); + haveLock = 0; + } + + if (sc->sc_status != DKC_ST_DONE|DKC_TC_SUCCESS) { + printf ("command 0x%x completed with status 0x%x\n", + cmd, sc->sc_status); + return (-1); + } + return (0); +} + +/* + * writing zero into the command-register will reset the controller. + * This will not interrupt data-transfer commands! + * Also no interrupt is generated, thus we don't use hdc_command() + */ +int +hdc_reset(sc) + struct hdcsoftc *sc; +{ + trace (("hdc_reset()\n")); + + sc->sc_dkc->dkc_cmd = DKC_CMD_RESET; /* issue RESET command */ + hdc_readregs(sc); /* read the status registers */ + sc->sc_status = sc->sc_dkc->dkc_stat; + if (sc->sc_status != DKC_ST_DONE|DKC_TC_SUCCESS) { + printf ("RESET command completed with status 0x%x\n", + sc->sc_status); + return (-1); + } + return (0); +} + +int +hdc_rxselect(sc, unit) + struct hdcsoftc *sc; + int unit; +{ + register struct hdc9224_UDCreg *p = &sc->sc_creg; + register struct hdc9224_UDCreg *q = &sc->sc_sreg; + int error; + + /* + * bring command-regs in some known-to-work state and + * select the drive with the DRIVE SELECT command. + */ + p->udc_dma7 = 0; + p->udc_dma15 = 0; + p->udc_dma23 = 0; + p->udc_dsect = 1; /* sectors are numbered 1..15 !!! */ + p->udc_dhead = 0; + p->udc_dcyl = 0; + p->udc_scnt = 0; + + p->udc_rtcnt = UDC_RC_RX33READ; + p->udc_mode = UDC_MD_RX33; + p->udc_term = UDC_TC_FDD; + + /* + * this is ... + */ + error = hdc_command (sc, DKC_CMD_DRSEL_RX33 | unit); + + if ((error != 0) || (q->udc_dstat & UDC_DS_READY == 0)) { + printf("\nfloppy-drive not ready (new floppy inserted?)\n\n"); + p->udc_rtcnt &= ~UDC_RC_INVRDY; /* clear INVRDY-flag */ + error = hdc_command(sc, DKC_CMD_DRSEL_RX33 | unit); + if ((error != 0) || (q->udc_dstat & UDC_DS_READY == 0)) { + printf("diskette not ready(1): %x/%x\n", error, q->udc_dstat); + printf("floppy-drive offline?\n"); + return (-1); + } + + if (q->udc_dstat & UDC_DS_TRK00) /* if track-0 */ + error = hdc_command(sc, DKC_CMD_STEPIN_FDD); /* step inwards */ + else /* else */ + error = hdc_command(sc, DKC_CMD_STEPOUT_FDD); /* step outwards */ + + if ((error != 0) || (q->udc_dstat & UDC_DS_READY == 1)) { + printf("diskette not ready(2): %x/%x\n", error, q->udc_dstat); + printf("No floppy inserted or drive offline\n"); + /* return (-1); */ + } + + p->udc_rtcnt |= UDC_RC_INVRDY; + error = hdc_command(sc, DKC_CMD_DRSEL_RX33 | unit); + if ((error != 0) || (q->udc_dstat & UDC_DS_READY == 0)) { + printf("diskette not ready(3): %x/%x\n", error, q->udc_dstat); + printf("no floppy inserted or floppy-door open\n"); + return(-1); + } + printf("floppy-drive reselected.\n"); + } + if (error) + error = hdc_command (sc, DKC_CMD_DRSEL_RX33 | unit); + + return (error); +} + +int +hdc_rdselect(sc, unit) + struct hdcsoftc *sc; + int unit; +{ + register struct hdc9224_UDCreg *p = &sc->sc_creg; + register struct hdc9224_UDCreg *q = &sc->sc_sreg; + int error; + + /* + * bring "creg" in some known-to-work state and + * select the drive with the DRIVE SELECT command. + */ + p->udc_dma7 = 0; + p->udc_dma15 = 0; + p->udc_dma23 = 0; + p->udc_dsect = 0; /* sectors are numbered 0..16 */ + p->udc_dhead = 0; + p->udc_dcyl = 0; + p->udc_scnt = 0; + + p->udc_rtcnt = UDC_RC_HDD_READ; + p->udc_mode = UDC_MD_HDD; + p->udc_term = UDC_TC_HDD; + + error = hdc_command (sc, DKC_CMD_DRSEL_HDD | unit); + if (error) + error = hdc_command (sc, DKC_CMD_DRSEL_HDD | unit); + + return (error); +} + +/* + * bring command-regs into some known-to-work state and select + * the drive with the DRIVE SELECT command. + */ +int +hdc_select(sc, unit) + struct hdcsoftc *sc; + int unit; +{ + int error; + + trace (("hdc_select(%x,%d)\n", sc, unit)); + + switch (unit) { + case 0: + case 1: + error = hdc_rdselect(sc, unit); + break; + case 2: + error = hdc_rxselect(sc, unit); + /* bertram: delay ??? XXX */ + break; + default: + printf("invalid unit %d in hdc_select()\n", unit); + error = -1; + } + + return (error); +} + +#endif /* NHDC > 0 */ diff --git a/sys/arch/vax/vsa/hdc9224.h b/sys/arch/vax/vsa/hdc9224.h new file mode 100644 index 00000000000..43fe2cfffe0 --- /dev/null +++ b/sys/arch/vax/vsa/hdc9224.h @@ -0,0 +1,196 @@ +/* $NetBSD: hdc9224.h,v 1.1 1996/07/20 18:55:12 ragge Exp $ */ +/* + * Copyright (c) 1996 Ludd, University of Lule}, Sweden. + * All rights reserved. + * + * This code is derived from software contributed to Ludd by Bertram Barth. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed at Ludd, University of + * Lule}, Sweden and its contributors. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + + +struct hdc9224_DKCreg { + unsigned char dkc_reg; /* Disk Register Data Access Port (rw)*/ + unsigned char fill[3]; /* bytes are longword aligned */ + unsigned char dkc_cmd; /* Disk Controller Command Port (wo) */ +#define dkc_stat dkc_cmd /* Interrupt Status Port (ro) */ +}; + +/* + * definition of some commands (constant bits only, incomplete!) + */ +#define DKC_CMD_RESET 0x00 /* terminate non-data-transfer cmds */ +#define DKC_CMD_DRDESELECT 0x01 /* done when no drive is in use */ +#define DKC_CMD_SETREGPTR 0x40 /* logically or-ed with reg-number */ +#define DKC_CMD_DRSELECT 0x20 +#define DKC_CMD_DRSEL_HDD 0x24 /* select HDD, or-ed with unit-numb. */ +#define DKC_CMD_DRSEL_RX33 0x28 /* or-ed with unit-number of RX33 */ +#define DKC_CMD_DRSEL_RX50 0x2C /* or-ed with unit-number of RX50 */ +#define DKC_CMD_RESTORE 0x02 +#define DKC_CMD_STEP 0x04 +#define DKC_CMD_STEPIN_FDD 0x04 /* one step inward for floppy */ +#define DKC_CMD_STEPOUT_FDD 0x06 /* one step outward (toward cyl #0) */ +#define DKC_CMD_POLLDRIVE 0x10 +#define DKC_CMD_SEEKREADID 0x50 +#define DKC_CMD_FORMATTRACK 0x60 +#define DKC_CMD_READTRACK 0x5A +#define DKC_CMD_READPHYSICAL 0x58 +#define DKC_CMD_READLOGICAL 0x5C +#define DKC_CMD_READ_HDD 0x5D /* read-logical, bypass=0, xfer=1 */ +#define DKC_CMD_READ_RX33 0x5D /* ??? */ +#define DKC_CMD_WRITEPHYSICAL 0x80 +#define DKC_CMD_WRITELOGICAL 0xC0 +#define DKC_CMD_WRITE_HDD 0xA0 /* bypass=0, ddmark=0 */ +#define DKC_CMD_WRITE_RX33 0xA1 /* precompensation differs... */ +#define DKC_CMD_WRITE_RX50 0xA4 + +/* + * Definition of bits in the DKC_STAT register + */ +#define DKC_ST_INTPEND (1<<7) /* interrupt pending */ +#define DKC_ST_DMAREQ (1<<6) /* DMA request */ +#define DKC_ST_DONE (1<<5) /* command done */ +#define DKC_ST_TERMCOD (3<<3) /* termination code (see below) */ +#define DKC_ST_RDYCHNG (1<<2) /* ready change */ +#define DKC_ST_OVRUN (1<<1) /* overrun/underrun */ +#define DKC_ST_BADSECT (1<<0) /* bad sector */ + +/* + * Definition of the termination codes + */ +#define DKC_TC_SUCCESS (0<<3) /* Successful completion */ +#define DKC_TC_RDIDERR (1<<3) /* Error in READ-ID sequence */ +#define DKC_TC_VRFYERR (2<<3) /* Error in VERIFY sequence */ +#define DKC_TC_DATAERR (3<<3) /* Error in DATA-TRANSFER seq. */ + +/* + * Definitions of delays neccessary for floppy-operation + */ +#define DKC_DELAY_MOTOR 500 /* allow 500 ms to reach speed */ +#define DKC_DELAY_SELECT 70 /* 70 ms for data-recovery-circuit */ +#define DKC_DELAY_POSITION 59 /* 59 ms for RX33, 100 ms for RX50 */ +#define DKC_DELAY_HEADSET 18 /* 18 ms when changing head-number */ + +/* + * The HDC9224 has 11/15(?) internal registers which are accessible via + * the Disk-Register-Data-Access-Port DKC_REG + */ +struct hdc9224_UDCreg { /* internal disk controller registers */ + u_char udc_dma7; /* 0: DMA adress bits 0 - 7 */ + u_char udc_dma15; /* 1: DMA adress bits 8 - 15 */ + u_char udc_dma23; /* 2: DMA adress bits 16 - 23 */ + u_char udc_dsect; /* 3: desired/starting sector number */ +#define udc_csect udc_dsect /* current sector number */ + u_char udc_dhead; /* 4: cyl-bits 8-10, desired head number */ +#define udc_chead udc_dhead /* current head number */ + u_char udc_dcyl; /* 5: desired cylinder number */ +#define udc_ccyl udc_dcyl /* current cylinder number */ + u_char udc_scnt; /* 6: sector count register */ + u_char udc_rtcnt; /* 7: retry count register */ + u_char udc_mode; /* 8: operation mode/chip status */ +#define udc_cstat udc_mode /* chip status register */ + u_char udc_term; /* 9: termination conditions/drive status */ +#define udc_dstat udc_term /* drive status register */ + u_char udc_data; /* 10: data */ +}; + +/* + * Definition of bits in the Current-Head register + */ +#define UDC_CH_BADSECT (1<<7) /* indicates a bad sector (if bypass=0) */ +#define UDC_CH_CYLBITS (0x70) /* bits 10-8 of current cylinder number */ +#define UDC_CH_HEADNO (0x0F) /* current head number */ + +/* + * Definition of bits in the Retry-Count register + */ +#define UDC_RC_RTRYCNT (0xF0) /* 1's compl. in read-log, 0 all others */ +#define UDC_RC_RXDISAB (1<<3) /* must/should be 0 for normal operation */ +#define UDC_RC_INVRDY (1<<2) /* polarity of floppy-status, important! */ +#define UDC_RC_MOTOR (1<<1) /* turn on floppy-motor, no effect on HDD */ +#define UDC_RC_LOSPEED (1<<0) /* floppy-speed select, RX33: 0, RX50: 1 */ + +#define UDC_RC_HDD_READ 0xF2 /* 0x72 ??? */ +#define UDC_RC_HDD_WRT 0xF2 /* 0xF0 ??? */ +#define UDC_RC_RX33READ 0x76 /* enable retries when reading floppies */ +#define UDC_RC_RX33WRT 0xF6 +#define UDC_RC_RX50READ 0x77 /* enable retries when reading floppies */ +#define UDC_RC_RX50WRT 0xF7 + +/* + * Definition of bits in the Operating-Mode register + */ +#define UDC_MD_HDMODE (1<<7) /* must be 1 for all FDD and HDD */ +#define UDC_MD_CHKCOD (3<<5) /* error-check: FDD/CRC: 0, HDD/ECC: 1 */ +#define UDC_MD_DENS (1<<4) /* density select, must be 0 */ +#define UDC_MD_UNUSED (1<<3) /* bit 3 is not used and must be 0 */ +#define UDC_MD_SRATE (7<<0) /* seek step rate */ + +#define UDC_MD_HDD 0xC0 +#define UDC_MD_RX33 0x82 +#define UDC_MD_RX50 0x81 + +/* + * Definition of bits in the Chip-Status register + */ +#define UDC_CS_RETREQ (1<<7) /* retry required */ +#define UDC_CS_ECCATT (1<<6) /* error correction attempted */ +#define UDC_CS_ECCERR (1<<5) /* ECC/CRC error */ +#define UDC_CS_DELDATA (1<<4) /* deleted data mark */ +#define UDC_CS_SYNCERR (1<<3) /* synchronization error */ +#define UDC_CS_COMPERR (1<<2) /* compare error */ +#define UDC_CS_PRESDRV (0x3) /* present drive selected */ + +/* + * Definition of bits in the Termination-Conditions register + */ +#define UDC_TC_CRCPRE (1<<7) /* CRC register preset, must be 1 */ +#define UDC_TC_UNUSED (1<<6) /* bit 6 is not used and must be 0 */ +#define UDC_TC_INTDONE (1<<5) /* interrupt on done */ +#define UDC_TC_TDELDAT (1<<4) /* terminate on deleted data */ +#define UDC_TC_TDSTAT3 (1<<3) /* terminate on drive status 3 change */ +#define UDC_TC_TWPROT (1<<2) /* terminate on write-protect (FDD only) */ +#define UDC_TC_INTRDCH (1<<1) /* interrupt on ready change (FDD only) */ +#define UDC_TC_TWRFLT (1<<0) /* interrupt on write-fault (HDD only) */ + +#define UDC_TC_HDD 0xA5 /* 0xB5 ??? */ +#define UDC_TC_FDD 0xA0 /* 0xAA ??? 0xB4 ??? */ + +/* + * Definition of bits in the Disk-Status register + */ +#define UDC_DS_SELACK (1<<7) /* select acknowledge (harddisk only!) */ +#define UDC_DS_INDEX (1<<6) /* index point */ +#define UDC_DS_SKCOM (1<<5) /* seek complete */ +#define UDC_DS_TRK00 (1<<4) /* track 0 */ +#define UDC_DS_DSTAT3 (1<<3) /* drive status 3 (MBZ) */ +#define UDC_DS_WRPROT (1<<2) /* write protect (floppy only!) */ +#define UDC_DS_READY (1<<1) /* drive ready bit */ +#define UDC_DS_WRFAULT (1<<0) /* write fault */ + + diff --git a/sys/arch/vax/vsa/lk201.c b/sys/arch/vax/vsa/lk201.c new file mode 100644 index 00000000000..52e602915cd --- /dev/null +++ b/sys/arch/vax/vsa/lk201.c @@ -0,0 +1,394 @@ +/* + * The LK201 keycode mapping routine is here, along with initialization + * functions for the keyboard and mouse. + */ + + +#include <sys/param.h> +#include <sys/syslog.h> +#include <sys/select.h> +#include <dev/cons.h> + +#include <pmax/include/pmioctl.h> + +#include <pmax/dev/lk201.h> + + +/* Exported functions */ +extern int kbdMapChar __P((int keycode)); + +extern void KBDReset __P(( dev_t dev, void (*putc) (dev_t, int) )); + +/* + * Keyboard to Ascii, unshifted. + */ +static unsigned char unshiftedAscii[] = { +/* 0 */ KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, +/* 4 */ KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, +/* 8 */ KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, +/* c */ KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, +/* 10 */ KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, +/* 14 */ KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, +/* 18 */ KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, +/* 1c */ KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, +/* 20 */ KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, +/* 24 */ KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, +/* 28 */ KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, +/* 2c */ KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, +/* 30 */ KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, +/* 34 */ KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, +/* 38 */ KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, +/* 3c */ KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, +/* 40 */ KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, +/* 44 */ KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, +/* 48 */ KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, +/* 4c */ KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, +/* 50 */ KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, +/* 54 */ KBD_NOKEY, KBD_NOKEY, KBD_F1, KBD_F2, +/* 58 */ KBD_F3, KBD_F4, KBD_F5, KBD_NOKEY, +/* 5c */ KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, +/* 60 */ KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, +/* 64 */ KBD_F6, KBD_F7, KBD_F8, KBD_F9, +/* 68 */ KBD_F10, KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, +/* 6c */ KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, +/* 70 */ KBD_NOKEY, '\033', KBD_F12, KBD_F13, +/* 74 */ KBD_F14, KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, +/* 78 */ KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, +/* 7c */ KBD_HELP, KBD_DO, KBD_NOKEY, KBD_NOKEY, +/* 80 */ KBD_F17, KBD_F18, KBD_F19, KBD_F20, +/* 84 */ KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, +/* 88 */ KBD_NOKEY, KBD_NOKEY, KBD_FIND, KBD_INSERT, +/* 8c */ KBD_REMOVE, KBD_SELECT, KBD_PREVIOUS, KBD_NEXT, +/* 90 */ KBD_NOKEY, KBD_NOKEY, '0', KBD_NOKEY, +/* 94 */ '.', KBD_KP_ENTER, '1', '2', +/* 98 */ '3', '4', '5', '6', +/* 9c */ ',', '7', '8', '9', +/* a0 */ '-', KBD_KP_F1, KBD_KP_F2, KBD_KP_F3, +/* a4 */ KBD_KP_F4, KBD_NOKEY, KBD_NOKEY, KBD_LEFT, +/* a8 */ KBD_RIGHT, KBD_DOWN, KBD_UP, KBD_NOKEY, +/* ac */ KBD_NOKEY, KBD_NOKEY, KBD_SHIFT, KBD_CONTROL, +/* b0 */ KBD_CAPSLOCK, KBD_ALTERNATE, KBD_NOKEY, KBD_NOKEY, +/* b4 */ KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, +/* b8 */ KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, +/* bc */ KBD_DEL, KBD_RET, KBD_TAB, '`', +/* c0 */ '1', 'q', 'a', 'z', +/* c4 */ KBD_NOKEY, '2', 'w', 's', +/* c8 */ 'x', '<', KBD_NOKEY, '3', +/* cc */ 'e', 'd', 'c', KBD_NOKEY, +/* d0 */ '4', 'r', 'f', 'v', +/* d4 */ ' ', KBD_NOKEY, '5', 't', +/* d8 */ 'g', 'b', KBD_NOKEY, '6', +/* dc */ 'y', 'h', 'n', KBD_NOKEY, +/* e0 */ '7', 'u', 'j', 'm', +/* e4 */ KBD_NOKEY, '8', 'i', 'k', +/* e8 */ ',', KBD_NOKEY, '9', 'o', +/* ec */ 'l', '.', KBD_NOKEY, '0', +/* f0 */ 'p', KBD_NOKEY, ';', '/', +/* f4 */ KBD_NOKEY, '=', ']', '\\', +/* f8 */ KBD_NOKEY, '-', '[', '\'', +/* fc */ KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, +}; + +/* + * Keyboard to Ascii, shifted. + */ +static unsigned char shiftedAscii[] = { +/* 0 */ KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, +/* 4 */ KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, +/* 8 */ KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, +/* c */ KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, +/* 10 */ KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, +/* 14 */ KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, +/* 18 */ KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, +/* 1c */ KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, +/* 20 */ KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, +/* 24 */ KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, +/* 28 */ KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, +/* 2c */ KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, +/* 30 */ KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, +/* 34 */ KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, +/* 38 */ KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, +/* 3c */ KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, +/* 40 */ KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, +/* 44 */ KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, +/* 48 */ KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, +/* 4c */ KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, +/* 50 */ KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, +/* 54 */ KBD_NOKEY, KBD_NOKEY, KBD_F1, KBD_F2, +/* 58 */ KBD_F3, KBD_F4, KBD_F5, KBD_NOKEY, +/* 5c */ KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, +/* 60 */ KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, +/* 64 */ KBD_F6, KBD_F7, KBD_F8, KBD_F9, +/* 68 */ KBD_F10, KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, +/* 6c */ KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, +/* 70 */ KBD_NOKEY, KBD_F11, KBD_F12, KBD_F13, +/* 74 */ KBD_F14, KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, +/* 78 */ KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, +/* 7c */ KBD_HELP, KBD_DO, KBD_NOKEY, KBD_NOKEY, +/* 80 */ KBD_F17, KBD_F18, KBD_F19, KBD_F20, +/* 84 */ KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, +/* 88 */ KBD_NOKEY, KBD_NOKEY, KBD_FIND, KBD_INSERT, +/* 8c */ KBD_REMOVE, KBD_SELECT, KBD_PREVIOUS, KBD_NEXT, +/* 90 */ KBD_NOKEY, KBD_NOKEY, '0', KBD_NOKEY, +/* 94 */ '.', KBD_KP_ENTER, '1', '2', +/* 98 */ '3', '4', '5', '6', +/* 9c */ ',', '7', '8', '9', +/* a0 */ '-', KBD_KP_F1, KBD_KP_F2, KBD_KP_F3, +/* a4 */ KBD_KP_F4, KBD_NOKEY, KBD_NOKEY, KBD_LEFT, +/* a8 */ KBD_RIGHT, KBD_DOWN, KBD_UP, KBD_NOKEY, +/* ac */ KBD_NOKEY, KBD_NOKEY, KBD_SHIFT, KBD_CONTROL, +/* b0 */ KBD_CAPSLOCK, KBD_ALTERNATE, KBD_NOKEY, KBD_NOKEY, +/* b4 */ KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, +/* b8 */ KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, +/* bc */ KBD_DEL, KBD_RET, KBD_TAB, '~', +/* c0 */ '!', 'q', 'a', 'z', +/* c4 */ KBD_NOKEY, '@', 'w', 's', +/* c8 */ 'x', '>', KBD_NOKEY, '#', +/* cc */ 'e', 'd', 'c', KBD_NOKEY, +/* d0 */ '$', 'r', 'f', 'v', +/* d4 */ ' ', KBD_NOKEY, '%', 't', +/* d8 */ 'g', 'b', KBD_NOKEY, '^', +/* dc */ 'y', 'h', 'n', KBD_NOKEY, +/* e0 */ '&', 'u', 'j', 'm', +/* e4 */ KBD_NOKEY, '*', 'i', 'k', +/* e8 */ '<', KBD_NOKEY, '(', 'o', +/* ec */ 'l', '>', KBD_NOKEY, ')', +/* f0 */ 'p', KBD_NOKEY, ':', '?', +/* f4 */ KBD_NOKEY, '+', '}', '|', +/* f8 */ KBD_NOKEY, '_', '{', '"', +/* fc */ KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, +}; + +/* + * Keyboard initialization string. + */ +static u_char kbdInitString[] = { + LK_LED_ENABLE, LED_ALL, /* show we are resetting keyboard */ + LK_DEFAULTS, + LK_CMD_MODE(LK_AUTODOWN, 1), + LK_CMD_MODE(LK_AUTODOWN, 2), + LK_CMD_MODE(LK_AUTODOWN, 3), + LK_CMD_MODE(LK_DOWN, 4), /* could also be LK_AUTODOWN */ + LK_CMD_MODE(LK_UPDOWN, 5), + LK_CMD_MODE(LK_UPDOWN, 6), + LK_CMD_MODE(LK_AUTODOWN, 7), + LK_CMD_MODE(LK_AUTODOWN, 8), + LK_CMD_MODE(LK_AUTODOWN, 9), + LK_CMD_MODE(LK_AUTODOWN, 10), + LK_CMD_MODE(LK_AUTODOWN, 11), + LK_CMD_MODE(LK_AUTODOWN, 12), + LK_CMD_MODE(LK_DOWN, 13), + LK_CMD_MODE(LK_AUTODOWN, 14), + LK_AR_ENABLE, /* we want autorepeat by default */ + LK_CL_ENABLE, 0x83, /* keyclick, volume */ + LK_KBD_ENABLE, /* the keyboard itself */ + LK_BELL_ENABLE, 0x83, /* keyboard bell, volume */ + LK_LED_DISABLE, LED_ALL, /* clear keyboard leds */ +}; + + +/* + * Initialize the Keyboard. + */ +void +KBDReset(kbddev, putc) + dev_t kbddev; + void (*putc) __P((dev_t, int)); +{ + register int i; + static int inKBDReset; + + if (inKBDReset) + return; + inKBDReset = 1; + for (i = 0; i < sizeof(kbdInitString); i++) + (*putc)(kbddev, (int)kbdInitString[i]); + inKBDReset = 0; +} + +/* + * ---------------------------------------------------------------------------- + * + * kbdMapChar -- + * + * Map characters from the keyboard to ASCII. Return -1 if there is + * no valid mapping. + * + * Results: + * None. + * + * Side effects: + * Remember state of shift and control keys. + * + * ---------------------------------------------------------------------------- + */ +int +kbdMapChar(cc) + int cc; +{ + static u_char shiftDown; + static u_char ctrlDown; + static u_char lastChar; + + switch (cc) { + case KEY_REPEAT: + cc = lastChar; + goto done; + + case KEY_UP: + shiftDown = 0; + ctrlDown = 0; + return (-1); + + case KEY_SHIFT: + case KEY_R_SHIFT: + if (ctrlDown || shiftDown) + shiftDown = 0; + else + shiftDown = 1; + return (-1); + + case KEY_CONTROL: + if (shiftDown || ctrlDown) + ctrlDown = 0; + else + ctrlDown = 1; + return (-1); + + case LK_POWER_ERROR: + case LK_KDOWN_ERROR: + case LK_INPUT_ERROR: + case LK_OUTPUT_ERROR: + log(LOG_WARNING, + "lk201: keyboard error, code=%x\n", cc); + return (-1); + } + if (shiftDown) + cc = shiftedAscii[cc]; + else + cc = unshiftedAscii[cc]; + if (cc >= KBD_NOKEY) { + /* + * A function key was typed - ignore it. + */ + return (-1); + } + if (cc >= 'a' && cc <= 'z') { + if (ctrlDown) + cc = cc - 'a' + '\1'; /* ^A */ + else if (shiftDown) + cc = cc - 'a' + 'A'; + } else if (ctrlDown) { + if (cc >= '[' && cc <= '_') + cc = cc - '@'; + else if (cc == ' ' || cc == '@') + cc = '\0'; + } + lastChar = cc; +done: + return (cc); +} + + +static int (*raw_kbd_getc) __P((dev_t dev)) = NULL; +static dev_t lk_in_dev = NODEV; + +/* + * Divert input from a serial port to the lk-201 keyboard handler. + */ +void +lk_divert(getfn, in_dev) + int (*getfn) __P ((dev_t dev)) ; + dev_t in_dev; +{ + raw_kbd_getc = getfn; + lk_in_dev = in_dev; +} + +/* + * Get an ASCII character off of the keyboard. + * Simply pass the getc request onto the underlying + * serial driver, and map the resulting LK-201 keycode to ASCII. + * FIXME: this design can't handle cursor or keypad keys, + * and should be thrown away and replaced with a stackable + * "Bstreams"-style driver. + */ +int +LKgetc(dev) + dev_t dev; /* ignored */ +{ + register int c; + + extern sccGetc(); + +#if 0 +/*XXX*/ printf("LK-201 getc 0x%x( [%d %d]) in_dev [%d %d]\n", + raw_kbd_getc, + major(dev), minor(dev), + major(lk_in_dev), minor(lk_in_dev)); +#endif + + if (raw_kbd_getc == NULL) { + panic("Reading from LK-201 before keyboard driver diverted\n"); + return (-1); + } + + for (;;) { + /* c = (*cn_tab.cn_kbdgetc)(cn_tab.cn_dev); */ + c = (*raw_kbd_getc) (lk_in_dev); +#if 0 +/*XXX*/ printf(" 0x%x [%c]", c, c); +#endif + if (c == 0) + return (-1); + if ((c = kbdMapChar(c & 0xff)) >= 0) + break; + } + return (c); +} + + +/* + * Initialize the mouse. (Doesn't really belong here.) + */ +void +MouseInit(mdev, putc, getc) + dev_t mdev; + void (*putc) __P((dev_t, int)); + int (*getc) __P((dev_t)); +{ + int id_byte1, id_byte2, id_byte3, id_byte4; + + /* + * Initialize the mouse. + */ + (*putc)(mdev, MOUSE_SELF_TEST); + id_byte1 = (*getc)(mdev); + if (id_byte1 < 0) { + printf("MouseInit: Timeout on 1st byte of self-test report\n"); + return; + } + id_byte2 = (*getc)(mdev); + if (id_byte2 < 0) { + printf("MouseInit: Timeout on 2nd byte of self-test report\n"); + return; + } + id_byte3 = (*getc)(mdev); + if (id_byte3 < 0) { + printf("MouseInit: Timeout on 3rd byte of self-test report\n"); + return; + } + id_byte4 = (*getc)(mdev); + if (id_byte4 < 0) { + printf("MouseInit: Timeout on 4th byte of self-test report\n"); + return; + } + if ((id_byte2 & 0x0f) != 0x2) + printf("MouseInit: We don't have a mouse!!!\n"); + /* + * For some reason, the mouse doesn't see this command if it comes + * too soon after a self test. + */ + DELAY(100); + (*putc)(mdev, MOUSE_INCREMENTAL); +} diff --git a/sys/arch/vax/vsa/ncr.c b/sys/arch/vax/vsa/ncr.c new file mode 100644 index 00000000000..69e74118c1d --- /dev/null +++ b/sys/arch/vax/vsa/ncr.c @@ -0,0 +1,1283 @@ +/* $NetBSD: ncr.c,v 1.5 1996/10/13 03:36:14 christos Exp $ */ + +/* #define DEBUG /* */ +/* #define TRACE /* */ +/* #define POLL_MODE /* */ +#define USE_VMAPBUF + +/* + * Copyright (c) 1995 David Jones, Gordon W. Ross + * Copyright (c) 1994 Adam Glass + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the authors may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * 4. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by + * Adam Glass, David Jones, and Gordon Ross + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * This file contains only the machine-dependent parts of the + * Sun3 SCSI driver. (Autoconfig stuff and DMA functions.) + * The machine-independent parts are in ncr5380sbc.c + * + * Supported hardware includes: + * Sun SCSI-3 on OBIO (Sun3/50,Sun3/60) + * Sun SCSI-3 on VME (Sun3/160,Sun3/260) + * + * Could be made to support the Sun3/E if someone wanted to. + * + * Note: Both supported variants of the Sun SCSI-3 adapter have + * some really unusual "features" for this driver to deal with, + * generally related to the DMA engine. The OBIO variant will + * ignore any attempt to write the FIFO count register while the + * SCSI bus is in DATA_IN or DATA_OUT phase. This is dealt with + * by setting the FIFO count early in COMMAND or MSG_IN phase. + * + * The VME variant has a bit to enable or disable the DMA engine, + * but that bit also gates the interrupt line from the NCR5380! + * Therefore, in order to get any interrupt from the 5380, (i.e. + * for reselect) one must clear the DMA engine transfer count and + * then enable DMA. This has the further complication that you + * CAN NOT touch the NCR5380 while the DMA enable bit is set, so + * we have to turn DMA back off before we even look at the 5380. + * + * What wonderfully whacky hardware this is! + * + * Credits, history: + * + * David Jones wrote the initial version of this module, which + * included support for the VME adapter only. (no reselection). + * + * Gordon Ross added support for the OBIO adapter, and re-worked + * both the VME and OBIO code to support disconnect/reselect. + * (Required figuring out the hardware "features" noted above.) + * + * The autoconfiguration boilerplate came from Adam Glass. + * + * VS2000: + */ + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/kernel.h> +#include <sys/conf.h> +#include <sys/file.h> +#include <sys/stat.h> +#include <sys/ioctl.h> +#include <sys/buf.h> +#include <sys/proc.h> +#include <sys/user.h> +#include <sys/map.h> +#include <sys/device.h> +#include <sys/dkstat.h> +#include <sys/disklabel.h> +#include <sys/disk.h> +#include <sys/syslog.h> + +/* #include <sys/errno.h> */ + +#include <scsi/scsi_all.h> +#include <scsi/scsi_debug.h> +#include <scsi/scsiconf.h> + +#include <machine/uvax.h> +#include <machine/ka410.h> +#include <machine/ka43.h> +#include <machine/vsbus.h> /* struct confargs */ + +#include <dev/ic/ncr5380reg.h> +#include <dev/ic/ncr5380var.h> + +#define trace(x) +#define debug(x) + +#ifndef NCR5380_CSRBITS +#define NCR5380_CSRBITS \ + "\020\010DEND\007DREQ\006PERR\005IREQ\004MTCH\003DCON\002ATN\001ACK" +#endif + +#ifndef NCR5380_BUSCSRBITS +#define NCR5380_BUSCSRBITS \ + "\020\010RST\007BSY\006REQ\005MSG\004C/D\003I/O\002SEL\001DBP" +#endif + +#include "ncr.h" + +#ifdef DDB +#define integrate +#else +#define integrate static +#endif + +/* + * Transfers smaller than this are done using PIO + * (on assumption they're not worth DMA overhead) + */ +#define MIN_DMA_LEN 128 + +/* + * Transfers lager than 65535 bytes need to be split-up. + * (Some of the FIFO logic has only 16 bits counters.) + * Make the size an integer multiple of the page size + * to avoid buf/cluster remap problems. (paranoid?) + * + * bertram: VS2000 has an DMA-area which is 16KB, thus + * have a maximum DMA-size of 16KB... + */ +#ifdef DMA_SHARED +#define MAX_DMA_LEN 0x2000 /* (8 * 1024) */ +#define DMA_ADDR_HBYTE 0x20 +#define DMA_ADDR_LBYTE 0x00 +#else +#define MAX_DMA_LEN 0x4000 /* (16 * 1024) */ +#define DMA_ADDR_HBYTE 0x00 +#define DMA_ADDR_LBYTE 0x00 +#endif + +#ifdef DEBUG +int si_debug = 3; +static int si_link_flags = 0 /* | SDEV_DB2 */ ; +#endif + +/* + * This structure is used to keep track of mappedpwd DMA requests. + * Note: combined the UDC command block with this structure, so + * the array of these has to be in DVMA space. + */ +struct si_dma_handle { + int dh_flags; +#define SIDH_BUSY 1 /* This DH is in use */ +#define SIDH_OUT 2 /* DMA does data out (write) */ +#define SIDH_PHYS 4 +#define SIDH_DONE 8 + u_char * dh_addr; /* KVA of start of buffer */ + int dh_maplen; /* Length of KVA mapping. */ + u_char * dh_dvma; /* VA of buffer in DVMA space */ + int dh_xlen; +}; + +/* + * The first structure member has to be the ncr5380_softc + * so we can just cast to go back and fourth between them. + */ +struct si_softc { + struct ncr5380_softc ncr_sc; + volatile struct si_regs *sc_regs; /* do we really need this? */ + + struct si_dma_handle *sc_dma; + struct confargs *sc_cfargs; + + int sc_xflags; /* ka410/ka43: resid, sizeof(areg) */ + + char *sc_dbase; + int sc_dsize; + + volatile char *sc_dareg; + volatile short *sc_dcreg; + volatile char *sc_ddreg; + volatile int sc_dflags; + +#define VSDMA_LOCKED 0x80 /* */ +#define VSDMA_WANTED 0x40 /* */ +#define VSDMA_IWANTED 0x20 +#define VSDMA_BLOCKED 0x10 +#define VSDMA_DMABUSY 0x08 /* DMA in progress */ +#define VSDMA_REGBUSY 0x04 /* accessing registers */ +#define VSDMA_WRBUF 0x02 /* writing to bounce-buffer */ +#define VSDMA_RDBUF 0x01 /* reading from bounce-buffer */ + +#define VSDMA_STATUS 0xF0 +#define VSDMA_LCKTYPE 0x0F + +#ifdef POLL_MODE + volatile u_char *intreq; + volatile u_char *intclr; + volatile u_char *intmsk; + volatile int intbit; +#endif +}; + +extern int cold; /* enable polling while cold-flag set */ + +/* Options. Interesting values are: 1,3,7 */ +int si_options = 3; /* bertram: 3 or 7 ??? */ +#define SI_ENABLE_DMA 1 /* Use DMA (maybe polled) */ +#define SI_DMA_INTR 2 /* DMA completion interrupts */ +#define SI_DO_RESELECT 4 /* Allow disconnect/reselect */ + +#define DMA_DIR_IN 1 +#define DMA_DIR_OUT 0 + +/* How long to wait for DMA before declaring an error. */ +int si_dma_intr_timo = 500; /* ticks (sec. X 100) */ + +integrate char si_name[] = "ncr"; +integrate int si_match(); +integrate void si_attach(); +integrate int si_intr __P((void *)); + +integrate void si_minphys __P((struct buf *bp)); +integrate void si_reset_adapter __P((struct ncr5380_softc *sc)); + +void si_dma_alloc __P((struct ncr5380_softc *)); +void si_dma_free __P((struct ncr5380_softc *)); +void si_dma_poll __P((struct ncr5380_softc *)); + +void si_intr_on __P((struct ncr5380_softc *)); +void si_intr_off __P((struct ncr5380_softc *)); + +int si_dmaLockBus __P((struct ncr5380_softc *, int)); +int si_dmaToggleLock __P((struct ncr5380_softc *, int, int)); +int si_dmaReleaseBus __P((struct ncr5380_softc *, int)); + +void si_dma_setup __P((struct ncr5380_softc *)); +void si_dma_start __P((struct ncr5380_softc *)); +void si_dma_eop __P((struct ncr5380_softc *)); +void si_dma_stop __P((struct ncr5380_softc *)); + +static struct scsi_adapter si_ops = { + ncr5380_scsi_cmd, /* scsi_cmd() */ + si_minphys, /* scsi_minphys() */ + NULL, /* open_target_lu() */ + NULL, /* close_target_lu() */ +}; + +/* This is copied from julian's bt driver */ +/* "so we have a default dev struct for our link struct." */ +static struct scsi_device si_dev = { + NULL, /* Use default error handler. */ + NULL, /* Use default start handler. */ + NULL, /* Use default async handler. */ + NULL, /* Use default "done" routine. */ +}; + + +struct cfdriver ncr_cd = { + NULL, si_name, DV_DULL +}; +struct cfattach ncr_ca = { + sizeof(struct si_softc), si_match, si_attach, +}; + +void +dk_establish(p,q) + struct disk *p; + struct device *q; +{ +#if 0 + printf ("faking dk_establish()...\n"); +#endif +} + + +integrate int +si_match(parent, match, aux) + struct device *parent; + void *match, *aux; +{ + struct cfdata *cf = match; + struct confargs *ca = aux; + + trace(("ncr_match(0x%x, %d, %s)\n", parent, cf->cf_unit, ca->ca_name)); + + if (strcmp(ca->ca_name, "ncr") && + strcmp(ca->ca_name, "ncr5380") && + strcmp(ca->ca_name, "NCR5380")) + return (0); + + /* + * we just define it being there ... + */ + return (1); +} + +integrate void +si_set_portid(pid,port) + int pid; + int port; +{ + struct { + u_long :2; + u_long id0:3; + u_long id1:3; + u_long :26; + } *p; + +#ifdef DEBUG + int *ip; + ip = (void*)uvax_phys2virt(KA410_SCSIPORT); + p = (void*)uvax_phys2virt(KA410_SCSIPORT); + printf("scsi-id: (%x/%d) %d / %d\n", *ip, *ip, p->id0, p->id1); +#endif + + p = (void*)uvax_phys2virt(KA410_SCSIPORT); + switch (port) { + case 0: + p->id0 = pid; + printf(": scsi-id %d\n", p->id0); + break; + case 1: + p->id1 = pid; + printf(": scsi-id %d\n", p->id1); + break; + default: + printf("invalid port-number %d\n", port); + } +} + +integrate void +si_attach(parent, self, aux) + struct device *parent, *self; + void *aux; +{ + struct si_softc *sc = (struct si_softc *) self; + struct ncr5380_softc *ncr_sc = (struct ncr5380_softc *)sc; + volatile struct si_regs *regs; + struct confargs *ca = aux; + int i; + int *ip = aux;; + + trace (("ncr_attach(0x%x, 0x%x, %s)\n", parent, self, ca->ca_name)); + + /* + * + */ +#ifdef POLL_MODE + sc->intreq = (void*)uvax_phys2virt(KA410_INTREQ); + sc->intmsk = (void*)uvax_phys2virt(KA410_INTMSK); + sc->intclr = (void*)uvax_phys2virt(KA410_INTCLR); + sc->intbit = ca->ca_intbit; +#endif + + sc->sc_cfargs = ca; /* needed for interrupt-setup */ + + regs = (void*)uvax_phys2virt(ca->ca_ioaddr); + + sc->sc_dareg = (void*)uvax_phys2virt(ca->ca_dareg); + sc->sc_dcreg = (void*)uvax_phys2virt(ca->ca_dcreg); + sc->sc_ddreg = (void*)uvax_phys2virt(ca->ca_ddreg); + sc->sc_dbase = (void*)uvax_phys2virt(ca->ca_dbase); + sc->sc_dsize = ca->ca_dsize; + sc->sc_dflags = 4; /* XXX */ + sc->sc_xflags = ca->ca_dflag; /* should/will be renamed */ + /* + * Fill in the prototype scsi_link. + */ + ncr_sc->sc_link.channel = SCSI_CHANNEL_ONLY_ONE; + ncr_sc->sc_link.adapter_softc = sc; + ncr_sc->sc_link.adapter_target = ca->ca_idval; + ncr_sc->sc_link.adapter = &si_ops; + ncr_sc->sc_link.device = &si_dev; + + si_set_portid(ca->ca_idval, ncr_sc->sc_dev.dv_unit); + + /* + * Initialize fields used by the MI code + */ + ncr_sc->sci_r0 = (void*)®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; +} diff --git a/sys/arch/vax/vsa/ncr.h b/sys/arch/vax/vsa/ncr.h new file mode 100644 index 00000000000..c30cf1e7e81 --- /dev/null +++ b/sys/arch/vax/vsa/ncr.h @@ -0,0 +1,75 @@ +/* $NetBSD: ncr.h,v 1.1 1996/07/20 18:55:15 ragge Exp $ */ + +/* + * Register map for the Sun3 SCSI Interface (si) + * The first part of this register map is an NCR5380 + * SCSI Bus Interface Controller (SBIC). The rest is a + * DMA controller and custom logic in one of two flavors, + * one for the OBIO interface (3/50,3/60) and one for the + * VME interface (3/160,3/260,etc.), where some registers + * are implemented only on one or the other, some on both. + */ + +/* + * Some of these registers apply to only one interface and some + * apply to both. The registers which apply to the Sun3/50 onboard + * version only are udc_rdata and udc_raddr. The registers which + * apply to the Sun3 vme version only are dma_addr, dma_count, bpr, + * iv_am, and bcrh. Thus, the sbc registers, fifo_data, bcr, and csr + * apply to both interfaces. + * One other feature of the vme interface: a write to the dma count + * register also causes a write to the fifo byte count register and + * vis versa. + */ + +/* + * NCR5380 Register map (byte-registers at longword addresses) + */ +struct ncr5380regs { + volatile u_long sci_r0; /* 200C.0080: CUR_DATA/OUT_DATA (rw) */ + volatile u_long sci_r1; /* 200C.0084: INI_CMD (rw) */ + volatile u_long sci_r2; /* 200C.0088: MODE (rw) */ + volatile u_long sci_r3; /* 200C.008C: TAR_CMD (rw) */ + volatile u_long sci_r4; /* 200C.0090: CUR_STAT/SEL_ENA (rw) */ + volatile u_long sci_r5; /* 200C.0094: STATUS/DMA_SEND (rw) */ + volatile u_long sci_r6; /* 200C.0098: IN_DATA/DMA_TRCV (rw) */ + volatile u_long sci_r7; /* 200C.009C: RESET/DMA_IRCV (rw) */ +}; + +struct si_regs { + struct ncr5380regs sci; +}; + +/* possible values for the address modifier, sun3 vme version only */ +#define VME_SUPV_DATA_24 0x3d00 + +/* + * Status Register. + * Note: + * (r) indicates bit is read only. + * (rw) indicates bit is read or write. + * (v) vme host adaptor interface only. + * (o) sun3/50 onboard host adaptor interface only. + * (b) both vme and sun3/50 host adaptor interfaces. + */ +#define SI_CSR_DMA_ACTIVE 0x8000 /* (r,o) dma transfer active */ +#define SI_CSR_DMA_CONFLICT 0x4000 /* (r,b) reg accessed while dmaing */ +#define SI_CSR_DMA_BUS_ERR 0x2000 /* (r,b) bus error during dma */ +#define SI_CSR_ID 0x1000 /* (r,b) 0 for 3/50, 1 for SCSI-3, */ + /* 0 if SCSI-3 unmodified */ +#define SI_CSR_FIFO_FULL 0x0800 /* (r,b) fifo full */ +#define SI_CSR_FIFO_EMPTY 0x0400 /* (r,b) fifo empty */ +#define SI_CSR_SBC_IP 0x0200 /* (r,b) sbc interrupt pending */ +#define SI_CSR_DMA_IP 0x0100 /* (r,b) dma interrupt pending */ +#define SI_CSR_LOB 0x00c0 /* (r,v) number of leftover bytes */ +#define SI_CSR_LOB_THREE 0x00c0 /* (r,v) three leftover bytes */ +#define SI_CSR_LOB_TWO 0x0080 /* (r,v) two leftover bytes */ +#define SI_CSR_LOB_ONE 0x0040 /* (r,v) one leftover byte */ +#define SI_CSR_BPCON 0x0020 /* (rw,v) byte packing control */ + /* dma is in 0=longwords, 1=words */ +#define SI_CSR_DMA_EN 0x0010 /* (rw,v) dma/interrupt enable */ +#define SI_CSR_SEND 0x0008 /* (rw,b) dma dir, 1=to device */ +#define SI_CSR_INTR_EN 0x0004 /* (rw,b) interrupts enable */ +#define SI_CSR_FIFO_RES 0x0002 /* (rw,b) inits fifo, 0=reset */ +#define SI_CSR_SCSI_RES 0x0001 /* (rw,b) reset sbc and udc, 0=reset */ + diff --git a/sys/arch/vax/vsa/vsbus.c b/sys/arch/vax/vsa/vsbus.c new file mode 100644 index 00000000000..3973f5678ba --- /dev/null +++ b/sys/arch/vax/vsa/vsbus.c @@ -0,0 +1,652 @@ +/* $NetBSD: vsbus.c,v 1.4 1996/10/13 03:36:17 christos Exp $ */ +/* + * Copyright (c) 1996 Ludd, University of Lule}, Sweden. + * All rights reserved. + * + * This code is derived from software contributed to Ludd by Bertram Barth. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed at Ludd, University of + * Lule}, Sweden and its contributors. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/buf.h> +#include <sys/conf.h> +#include <sys/file.h> +#include <sys/ioctl.h> +#include <sys/proc.h> +#include <sys/user.h> +#include <sys/map.h> +#include <sys/device.h> +#include <sys/dkstat.h> +#include <sys/disklabel.h> +#include <sys/syslog.h> +#include <sys/stat.h> + +#include <machine/pte.h> +#include <machine/sid.h> +#include <machine/scb.h> +#include <machine/cpu.h> +#include <machine/trap.h> +#include <machine/nexus.h> + +#include <machine/uvax.h> +#include <machine/ka410.h> +#include <machine/ka43.h> + +#include <machine/vsbus.h> + +#define trace(x) +#define debug(x) + +int vsbus_match __P((struct device *, void *, void *)); +void vsbus_attach __P((struct device *, struct device *, void *)); +int vsbus_print __P((void *, const char *)); + +void ka410_attach __P((struct device *, struct device *, void *)); +void ka43_attach __P((struct device *, struct device *, void *)); + +struct cfdriver vsbus_cd = { + NULL, "vsbus", DV_DULL +}; +struct cfattach vsbus_ca = { + sizeof(struct device), vsbus_match, vsbus_attach +}; + +/* +void vsbus_intr_register __P((struct confargs *ca, int (*)(void*), void*)); +void vsbus_intr_unregister __P((struct confargs *)); +*/ + +void vsbus_intr_dispatch __P((int i)); + +#define VSBUS_MAXDEVS 8 +#define VSBUS_MAXINTR 8 + +struct confargs *vsbus_devs = NULL; + +#ifdef VAX410 /* also: KA420 */ +struct confargs ka410_devs[] = { + /* name intslot intpri intvec intbit ioaddr */ + { "dc", 7, 7, 0x2C0, (1<<7), KA410_SER_BASE, + 6, 6, 0x2C4, (1<<6), 0x01, }, + { "dc (xmit)", 6, 6, 0x2C4, (1<<6), KA410_SER_BASE, }, + { "le", 5, 5, 0x250, (1<<5), KA410_LAN_BASE, + KA410_NWA_BASE, 0x00, }, + { "ncr", 1, 1, 0x3F8, (1<<1), KA410_SCS_BASE, + KA410_SCS_DADR, KA410_SCS_DCNT, KA410_SCS_DDIR, + KA410_DMA_BASE, KA410_DMA_SIZE, 0x00, 0x07, }, + { "hdc", 0, 0, 0x3FC, (1<<0), KA410_DKC_BASE, + 0, 0, 0, + KA410_DMA_BASE, KA410_DMA_SIZE, 0x00, }, +#if 0 + { "dc (recv)", 7, 7, 0x2C0, (1<<7), KA410_SER_BASE, }, + { "dc (xmit)", 6, 6, 0x2C4, (1<<6), KA410_SER_BASE, }, + { "hdc9224", 0, 0, 0x3FC, (1<<0), KA410_DKC_BASE, }, + { "ncr5380", 1, 1, 0x3F8, (1<<1), KA410_SCS_BASE, }, + { "am7990", 5, 5, 0x250, (1<<5), KA410_LAN_BASE, }, + { "NETOPT", 4, 4, 0x254, (1<<4), KA410_LAN_BASE, }, +#endif + { "" }, +}; +#endif + +#ifdef VAX43 +struct confargs ka43_devs[] = { + /* name intslot intpri intvec intbit ioaddr */ + { "dc", 7, 7, 0x2C0, (1<<7), KA43_SER_BASE, + 6, 6, 0x2C4, (1<<6), 0x01, }, + { "dc (xmit)", 6, 6, 0x2C4, (1<<6), KA43_SER_BASE, }, + { "le", 5, 5, 0x250, (1<<5), KA43_LAN_BASE, + KA43_NWA_BASE, 0x00, }, + { "ncr", 1, 1, 0x3F8, (1<<1), KA43_SC1_BASE, + KA43_SC1_DADR, KA43_SC1_DCNT, KA43_SC1_DDIR, + KA43_DMA_BASE, KA43_DMA_SIZE, 0x01, 0x06, }, + { "ncr", 0, 0, 0x3FC, (1<<0), KA43_SC2_BASE, + KA43_SC2_DADR, KA43_SC2_DCNT, KA43_SC2_DDIR, + KA43_DMA_BASE, KA43_DMA_SIZE, 0x01, 0x06, }, +#if 0 + { "le (2nd)", 4, 4, 0x254, (1<<4), 0x???, }, + { "NETOPT", 4, 4, 0x254, (1<<4), 0x???, }, +#endif + { "" }, +}; +#endif + +int +vsbus_print(aux, name) + void *aux; + const char *name; +{ + struct confargs *ca = aux; + + trace(("vsbus_print(%x, %s)\n", ca->ca_name, name)); + + if (name) { + printf ("device %s at %s", ca->ca_name, name); + return (UNSUPP); + } + return (UNCONF); +} + +int +vsbus_match(parent, cf, aux) + struct device *parent; + void *cf; + void *aux; +{ + struct bp_conf *bp = aux; + + trace(("vsbus_match: bp->type = \"%s\"\n", bp->type)); + + if (strcmp(bp->type, "vsbus")) + return 0; + /* + * on machines which can have it, the vsbus is always there + */ + if ((vax_bustype & VAX_VSBUS) == 0) + return (0); + + return (1); +} + +#if 1 /*------------------------------------------------------------*/ +#if 1 +#define REG(name) short name; short X##name##X; +#else +#define REG(name) int name; +#endif +static volatile struct {/* base address of DZ-controller: 0x200A0000 */ + REG(csr); /* 00 Csr: control/status register */ + REG(rbuf); /* 04 Rbuf/Lpr: receive buffer/line param reg. */ + REG(tcr); /* 08 Tcr: transmit console register */ + REG(tdr); /* 0C Msr/Tdr: modem status reg/transmit data reg */ + REG(lpr0); /* 10 Lpr0: */ + REG(lpr1); /* 14 Lpr0: */ + REG(lpr2); /* 18 Lpr0: */ + REG(lpr3); /* 1C Lpr0: */ +} *dz = (void*)0x200A0000; +extern int dzcnrint(); +extern int dzcntint(); +int hardclock_count = 0; +int +ka410_consintr_enable() +{ + vsbus_intr_enable(&ka410_devs[0]); + vsbus_intr_enable(&ka410_devs[1]); +} + +int +ka410_consRecv_intr(p) + void *p; +{ + /* printf("ka410_consRecv_intr: hc-count=%d\n", hardclock_count); */ + dzcnrint(); + /* printf("gencnrint() returned.\n"); */ + return(0); +} + +int +ka410_consXmit_intr(p) + void *p; +{ + /* printf("ka410_consXmit_intr: hc-count=%d\n", hardclock_count); */ + dzcntint(); + /* printf("gencntint() returned.\n"); */ + return(0); +} +#endif /*------------------------------------------------------------*/ + +void +vsbus_attach(parent, self, aux) + struct device *parent, *self; + void *aux; +{ + struct confargs *ca; + int i; + + printf("\n"); + trace (("vsbus_attach()\n")); + + printf("vsbus_attach: boardtype = %x\n", vax_boardtype); + + switch (vax_boardtype) { + case VAX_BTYP_410: + case VAX_BTYP_420: + vsbus_devs = ka410_devs; + break; + + case VAX_BTYP_43: + case VAX_BTYP_46: + case VAX_BTYP_49: + vsbus_devs = ka43_devs; + break; + + default: + printf ("unsupported boardtype 0x%x in vsbus_attach()\n", + vax_boardtype); + return; + } + + /* + * first setup interrupt-table, so that devices can register + * their interrupt-routines... + */ + vsbus_intr_setup(); + + /* + * now check for all possible devices on this "bus" + */ + for (i=0; i<VSBUS_MAXDEVS; i++) { + ca = &vsbus_devs[i]; + if (*ca->ca_name == '\0') + break; + config_found(self, (void*)ca, vsbus_print); + } + + /* + * as long as there's no working DZ-driver, we use this dummy + */ + vsbus_intr_register(&ka410_devs[0], ka410_consRecv_intr, NULL); + vsbus_intr_register(&ka410_devs[1], ka410_consXmit_intr, NULL); +} + +#define VSBUS_MAX_INTR 8 /* 64? */ +/* + * interrupt service routines are given an int as argument, which is + * pushed onto stack as LITERAL. Thus the value is between 0-63. + * This array of 64 might be oversized for now, but it's all which + * ever will be possible. + */ +struct vsbus_ivec { + struct ivec_dsp intr_vec; /* this is referenced in SCB */ + int intr_count; /* keep track of interrupts */ + int intr_flags; /* valid, etc. */ + void (*enab)(int); /* enable interrupt */ + void (*disab)(int); /* disable interrupt */ + void (*prep)(int); /* need pre-processing? */ + int (*handler)(void*); /* isr-routine to call */ + void *hndlarg; /* args to this routine */ + void (*postp)(int); /* need post-processing? */ +} vsbus_ivtab[VSBUS_MAX_INTR]; + +/* + * + */ +int +vsbus_intr_setup() +{ + int i; + struct vsbus_ivec *ip; + extern struct ivec_dsp idsptch; /* subr.s */ + + for (i=0; i<VSBUS_MAX_INTR; i++) { + ip = &vsbus_ivtab[i]; + bcopy(&idsptch, &ip->intr_vec, sizeof(struct ivec_dsp)); + ip->intr_vec.pushlarg = i; + ip->intr_vec.hoppaddr = vsbus_intr_dispatch; + ip->intr_count = 0; + ip->intr_flags = 0; + ip->enab = NULL; + ip->disab = NULL; + ip->postp = NULL; + } + switch (vax_boardtype) { + case VAX_BTYP_410: + case VAX_BTYP_420: + case VAX_BTYP_43: + case VAX_BTYP_46: + case VAX_BTYP_49: + ka410_intr_setup(); + return(0); + default: + printf("unsupported board-type 0x%x in vsbus_intr_setup()\n", + vax_boardtype); + return(1); + } +} + +int +vsbus_intr_register(ca, handler, arg) + struct confargs *ca; + int (*handler)(void*); + void *arg; +{ + /* struct device *dev = arg; */ + int i = ca->ca_intslot; + struct vsbus_ivec *ip = &vsbus_ivtab[i]; + + trace (("vsbus_intr_register(%s/%d)\n", ca->ca_name, ca->ca_intslot)); + + ip->handler = handler; + ip->hndlarg = arg; +} + +int +vsbus_intr_enable(ca) + struct confargs *ca; +{ + int i = ca->ca_intslot; + struct vsbus_ivec *ip = &vsbus_ivtab[i]; + + trace (("vsbus_intr_enable(%s/%d)\n", ca->ca_name, ca->ca_intslot)); + + /* XXX check for valid handler etc. !!! */ + if (ip->handler == NULL) { + printf("interrupts for \"%s\"(%d) not enabled: null-handler\n", + ca->ca_name, ca->ca_intslot); + return; + } + + ip->enab(i); +} + +int +vsbus_intr_disable(ca) + struct confargs *ca; +{ + int i = ca->ca_intslot; + struct vsbus_ivec *ip = &vsbus_ivtab[i]; + + trace (("vsbus_intr_disable(%s/%d)\n", ca->ca_name, i)); + + ip->disab(i); +} + +int +vsbus_intr_unregister(ca) + struct confargs *ca; +{ + int i = ca->ca_intslot; + struct vsbus_ivec *ip = &vsbus_ivtab[i]; + + trace (("vsbus_intr_unregister(%s/%d)\n", ca->ca_name, i)); + + ip->handler = NULL; + ip->hndlarg = NULL; +} + +void +vsbus_intr_dispatch(i) + register int i; +{ + register struct vsbus_ivec *ip = &vsbus_ivtab[i]; + + trace (("vsbus_intr_dispatch(%d)", i)); + + if (i < VSBUS_MAX_INTR && ip->handler != NULL) { + ip->intr_count++; + debug (("intr-count[%d] = %d\n", i, ip->intr_count)); + (ip->handler)(ip->hndlarg); + if (ip->postp) + (ip->postp)(i); + return; + } + + if (i < 0 || i >= VSBUS_MAX_INTR) { + printf ("stray interrupt %d on vsbus.\n", i); + return; + } + + if (!ip->handler) { + printf ("unhandled interrupt %d on vsbus.\n", i); + return; + } +} + +/* + * These addresses are invalid and will be updated/corrected by + * ka410_intr_setup(), but having them this way helps debugging + */ +static volatile u_char *ka410_intmsk = (void*)KA410_INTMSK; +static volatile u_char *ka410_intreq = (void*)KA410_INTREQ; +static volatile u_char *ka410_intclr = (void*)KA410_INTCLR; + +static void +ka410_intr_enable(i) + int i; +{ + trace (("ka410_intr_enable(%d)\n", i)); + *ka410_intmsk |= (1<<i); +} + +static void +ka410_intr_disable(i) + int i; +{ + trace (("ka410_intr_disable(%d)\n", i)); + *ka410_intmsk &= ~(1<<i); +} + +static void +ka410_intr_clear(i) + int i; +{ + trace (("ka410_intr_clear(%d)\n", i)); + *ka410_intclr = (1<<i); +} + +ka410_intr_setup() +{ + int i; + struct vsbus_ivec *ip; + void **scbP = (void*)scb; + + trace (("ka410_intr_setup()\n")); + + ka410_intmsk = (void*)uvax_phys2virt(KA410_INTMSK); + ka410_intreq = (void*)uvax_phys2virt(KA410_INTREQ); + ka410_intclr = (void*)uvax_phys2virt(KA410_INTCLR); + + *ka410_intmsk = 0; /* disable all interrupts */ + *ka410_intclr = 0xFF; /* clear all old interrupts */ + + /* + * insert the VS2000-specific routines into ivec-table... + */ + for (i=0; i<8; i++) { + ip = &vsbus_ivtab[i]; + ip->enab = ka410_intr_enable; + ip->disab = ka410_intr_disable; + /* ip->postp = ka410_intr_clear; bertram XXX */ + } + /* + * ...and register the interrupt-vectors in SCB + */ + scbP[IVEC_DC/4] = &vsbus_ivtab[0].intr_vec; + scbP[IVEC_SC/4] = &vsbus_ivtab[1].intr_vec; + scbP[IVEC_VS/4] = &vsbus_ivtab[2].intr_vec; + scbP[IVEC_VF/4] = &vsbus_ivtab[3].intr_vec; + scbP[IVEC_NS/4] = &vsbus_ivtab[4].intr_vec; + scbP[IVEC_NP/4] = &vsbus_ivtab[5].intr_vec; + scbP[IVEC_ST/4] = &vsbus_ivtab[6].intr_vec; + scbP[IVEC_SR/4] = &vsbus_ivtab[7].intr_vec; +} + +/* + * + * + */ + +static volatile struct dma_lock { + int dl_locked; + int dl_wanted; + void *dl_owner; + int dl_count; +} dmalock = { 0, 0, NULL, 0 }; + +int +vsbus_lockDMA(ca) + struct confargs *ca; +{ + while (dmalock.dl_locked) { + dmalock.dl_wanted++; + sleep((caddr_t)&dmalock, PRIBIO); /* PLOCK or PRIBIO ? */ + dmalock.dl_wanted--; + } + dmalock.dl_locked++; + dmalock.dl_owner = ca; + + /* + * no checks yet, no timeouts, nothing... + */ + +#ifdef DEBUG + if ((++dmalock.dl_count % 1000) == 0) + printf("%d locks, owner: %s\n", dmalock.dl_count, ca->ca_name); +#endif + return (0); +} + +int +vsbus_unlockDMA(ca) + struct confargs *ca; +{ + if (dmalock.dl_locked != 1 || dmalock.dl_owner != ca) { + printf("locking-problem: %d, %s\n", dmalock.dl_locked, + (dmalock.dl_owner ? dmalock.dl_owner : "null")); + dmalock.dl_locked = 0; + return (-1); + } + dmalock.dl_owner = NULL; + dmalock.dl_locked = 0; + if (dmalock.dl_wanted) { + wakeup((caddr_t)&dmalock); + } + return (0); +} + +/*----------------------------------------------------------------------*/ +#if 0 +/* + * small set of routines needed for mapping when doing pseudo-DMA, + * quasi-DMA or virtual-DMA (choose whatever name you like). + * + * Once I know how VS3100 is doing real DMA (I hope it does), this + * should be rewritten to present a general interface... + * + */ + +extern u_long uVAX_physmap; + +u_long +vsdma_mapin(bp, len) + struct buf *bp; + int len; +{ + pt_entry_t *pte; /* pointer to Page-Table-Entry */ + struct pcb *pcb; /* pointer to Process-Controll-Block */ + pt_entry_t *xpte; + caddr_t addr; + int pgoff; /* offset into 1st page */ + int pgcnt; /* number of pages needed */ + int pfnum; + int i; + + trace(("mapin(bp=%x, bp->data=%x)\n", bp, bp->b_data)); + + addr = bp->b_data; + pgoff = (int)bp->b_data & PGOFSET; /* get starting offset */ + pgcnt = btoc(bp->b_bcount + pgoff) + 1; /* one more than needed */ + + /* + * Get a pointer to the pte pointing out the first virtual address. + * Use different ways in kernel and user space. + */ + if ((bp->b_flags & B_PHYS) == 0) { + pte = kvtopte(addr); + } else { + pcb = bp->b_proc->p_vmspace->vm_pmap.pm_pcb; + pte = uvtopte(addr, pcb); + } + + /* + * When we are doing DMA to user space, be sure that all pages + * we want to transfer to are mapped. WHY DO WE NEED THIS??? + * SHOULDN'T THEY ALWAYS BE MAPPED WHEN DOING THIS??? + */ + for (i=0; i<(pgcnt-1); i++) { + if ((pte + i)->pg_pfn == 0) { + int rv; + rv = vm_fault(&bp->b_proc->p_vmspace->vm_map, + (unsigned)addr + i * NBPG, + VM_PROT_READ|VM_PROT_WRITE, FALSE); + if (rv) + panic("vs-DMA to nonexistent page, %d", rv); + } + } + + /* + * now insert new mappings for this memory area into kernel's + * mapping-table + */ + xpte = kvtopte(uVAX_physmap); + while (--pgcnt > 0) { + pfnum = pte->pg_pfn; + if (pfnum == 0) + panic("vsbus: zero entry"); + *(int *)xpte++ = *(int *)pte++; + } + *(int *)xpte = 0; /* mark last mapped page as invalid! */ + + debug(("uVAX: 0x%x\n", uVAX_physmap + pgoff)); + + return (uVAX_physmap + pgoff); /* ??? */ +} +#endif +/*----------------------------------------------------------------------*/ +/* + * Here follows some currently(?) unused stuff. Someday this should be removed + */ + +#if 0 +/* + * Configure devices on VS2000/KA410 directly attached to vsbus + */ +void +ka410_attach(parent, self, aux) + struct device *parent; + struct device *self; + void *aux; +{ + struct confargs *ca; + int i; + + for (i=0; i<KA410_MAXDEVS; i++) { + ca = &ka410_devs[i]; + if (*ca->ca_name == '\0') + break; + config_found(self, (void*)ca, vsbus_print); + } + /* + * as long as there's no real DZ-driver, we used this dummy + */ + vsbus_intr_register(&ka410_devs[0], ka410_consRecv_intr, NULL); + vsbus_intr_register(&ka410_devs[1], ka410_consXmit_intr, NULL); +} + +#endif |