summaryrefslogtreecommitdiff
path: root/sys/arch
diff options
context:
space:
mode:
Diffstat (limited to 'sys/arch')
-rw-r--r--sys/arch/vax/if/if_de.c29
-rw-r--r--sys/arch/vax/if/if_le.c365
-rw-r--r--sys/arch/vax/if/if_qe.c1468
-rw-r--r--sys/arch/vax/if/if_qereg.h47
-rw-r--r--sys/arch/vax/if/if_uba.c30
-rw-r--r--sys/arch/vax/if/if_ze.c128
-rw-r--r--sys/arch/vax/if/if_zereg.h222
-rw-r--r--sys/arch/vax/if/sgec.c752
-rw-r--r--sys/arch/vax/if/sgecreg.h242
-rw-r--r--sys/arch/vax/if/sgecvar.h68
-rw-r--r--sys/arch/vax/mba/hp.c81
-rw-r--r--sys/arch/vax/mba/mba.c47
-rw-r--r--sys/arch/vax/mba/mbavar.h6
-rw-r--r--sys/arch/vax/mscp/files.mscp13
-rw-r--r--sys/arch/vax/mscp/mscp.c136
-rw-r--r--sys/arch/vax/mscp/mscp.h352
-rw-r--r--sys/arch/vax/mscp/mscp_disk.c1179
-rw-r--r--sys/arch/vax/mscp/mscp_subr.c404
-rw-r--r--sys/arch/vax/mscp/mscp_tape.c82
-rw-r--r--sys/arch/vax/mscp/mscpreg.h52
-rw-r--r--sys/arch/vax/mscp/mscpvar.h82
-rw-r--r--sys/arch/vax/qbus/dhu.c (renamed from sys/arch/vax/uba/dhu.c)212
-rw-r--r--sys/arch/vax/qbus/dhureg.h (renamed from sys/arch/vax/uba/dhureg.h)17
-rw-r--r--sys/arch/vax/qbus/dl.c (renamed from sys/arch/vax/uba/dl.c)192
-rw-r--r--sys/arch/vax/qbus/dlreg.h (renamed from sys/arch/vax/uba/dlreg.h)11
-rw-r--r--sys/arch/vax/qbus/dz.c (renamed from sys/arch/vax/uba/dz.c)354
-rw-r--r--sys/arch/vax/qbus/dz_uba.c137
-rw-r--r--sys/arch/vax/qbus/dzreg.h (renamed from sys/arch/vax/uba/dzreg.h)76
-rw-r--r--sys/arch/vax/qbus/dzvar.h (renamed from sys/arch/vax/uba/udareg.h)63
-rw-r--r--sys/arch/vax/qbus/files.uba52
-rw-r--r--sys/arch/vax/qbus/qd.c (renamed from sys/arch/vax/uba/qd.c)1055
-rw-r--r--sys/arch/vax/qbus/qdioctl.h118
-rw-r--r--sys/arch/vax/qbus/qdreg.h381
-rw-r--r--sys/arch/vax/qbus/qduser.h514
-rw-r--r--sys/arch/vax/qbus/qevent.h120
-rw-r--r--sys/arch/vax/qbus/qfont.c3294
-rw-r--r--sys/arch/vax/qbus/uba.c264
-rw-r--r--sys/arch/vax/qbus/ubavar.h148
-rw-r--r--sys/arch/vax/qbus/uda.c509
-rw-r--r--sys/arch/vax/uba/uba.c231
-rw-r--r--sys/arch/vax/uba/uba_cmi.c147
-rw-r--r--sys/arch/vax/uba/uba_common.h88
-rw-r--r--sys/arch/vax/uba/uba_dma.c282
-rw-r--r--sys/arch/vax/uba/uba_ibus.c137
-rw-r--r--sys/arch/vax/uba/uba_mainbus.c137
-rw-r--r--sys/arch/vax/uba/uba_sbi.c327
-rw-r--r--sys/arch/vax/uba/ubareg.h59
-rw-r--r--sys/arch/vax/uba/ubavar.h19
48 files changed, 11389 insertions, 3340 deletions
diff --git a/sys/arch/vax/if/if_de.c b/sys/arch/vax/if/if_de.c
index f9ab288aef9..3a3b16720a2 100644
--- a/sys/arch/vax/if/if_de.c
+++ b/sys/arch/vax/if/if_de.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: if_de.c,v 1.10 1997/09/10 08:28:39 maja Exp $ */
+/* $OpenBSD: if_de.c,v 1.11 2000/04/27 03:14:42 bjc Exp $ */
/* $NetBSD: if_de.c,v 1.27 1997/04/19 15:02:29 ragge Exp $ */
/*
@@ -61,8 +61,7 @@
#include <machine/sid.h>
#include <net/if.h>
-#include <net/netisr.h>
-#include <net/route.h>
+#include <net/if_dl.h>
#ifdef INET
#include <netinet/in.h>
@@ -112,8 +111,7 @@ struct de_softc {
struct device ds_dev; /* Configuration common part */
struct arpcom ds_ac; /* Ethernet common part */
struct dedevice *ds_vaddr; /* Virtual address of this interface */
-#define ds_if ds_ac.ac_if /* network-visible interface */
-#define ds_addr ds_ac.ac_enaddr /* hardware Ethernet address */
+#define ds_if ds_ac.ac_if /* network-visible interface */
int ds_flags;
#define DSF_RUNNING 2 /* board is enabled */
#define DSF_SETADDR 4 /* physical address is changed */
@@ -177,6 +175,7 @@ deattach(parent, self, aux)
struct dedevice *addr;
char *c;
int csr1;
+ u_int8_t myaddr[ETHER_ADDR_LEN];
addr = (struct dedevice *)ua->ua_addr;
ds->ds_vaddr = addr;
@@ -219,10 +218,9 @@ deattach(parent, self, aux)
(void)dewait(ds, "read addr ");
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));
+ bcopy((caddr_t)&ds->ds_pcbb.pcbb2, myaddr, sizeof (myaddr));
printf("%s: hardware address %s\n", ds->ds_dev.dv_xname,
- ether_sprintf(ds->ds_addr));
+ ether_sprintf(myaddr));
ifp->if_ioctl = deioctl;
ifp->if_start = destart;
ds->ds_deuba.iff_flags = UBA_CANTWAIT;
@@ -275,7 +273,7 @@ deinit(ds)
return;
if ((ifp->if_flags & IFF_RUNNING) == 0) {
if (if_ubaminit(&ds->ds_deuba, (void *)ds->ds_dev.dv_parent,
- sizeof (struct ether_header), (int)btoc(ETHERMTU),
+ sizeof (struct ether_header), (int)vax_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;
@@ -347,7 +345,7 @@ deinit(ds)
destart(&ds->ds_if); /* queue output packets */
ds->ds_flags |= DSF_RUNNING; /* need before de_setaddr */
if (ds->ds_flags & DSF_SETADDR)
- de_setaddr(ds->ds_addr, ds);
+ de_setaddr(ds->ds_ac.ac_enaddr, ds);
addr->pclow = CMD_START | PCSR0_INTE;
splx(s);
}
@@ -608,7 +606,8 @@ deioctl(ifp, cmd, data)
register struct ns_addr *ina = &(IA_SNS(ifa)->sns_addr);
if (ns_nullhost(*ina))
- ina->x_host = *(union ns_host *)(ds->ds_addr);
+ ina->x_host =
+ *(union ns_host *)ds->ds_ac.ac_enaddr;
else
de_setaddr(ina->x_host.c_host, ds);
break;
@@ -655,7 +654,7 @@ de_setaddr(physaddr, ds)
addr->pclow = PCSR0_INTE|CMD_GETCMD;
if (dewait(ds, "address change") == 0) {
ds->ds_flags |= DSF_SETADDR;
- bcopy((caddr_t) physaddr, (caddr_t) ds->ds_addr, 6);
+ bcopy((caddr_t) physaddr, ds->ds_ac.ac_enaddr, 6);
}
}
@@ -669,7 +668,7 @@ dewait(ds, fn)
char *fn;
{
volatile struct dedevice *addr = ds->ds_vaddr;
- register csr0;
+ register int csr0;
while ((addr->pcsr0 & PCSR0_INTR) == 0)
;
@@ -684,9 +683,9 @@ dewait(ds, fn)
}
int
-dematch(parent, match, aux)
+dematch(parent, cf, aux)
struct device *parent;
- void *match, *aux;
+ void *cf, *aux;
{
struct uba_attach_args *ua = aux;
volatile struct dedevice *addr = (struct dedevice *)ua->ua_addr;
diff --git a/sys/arch/vax/if/if_le.c b/sys/arch/vax/if/if_le.c
index 3b9528685d1..f370c74eb64 100644
--- a/sys/arch/vax/if/if_le.c
+++ b/sys/arch/vax/if/if_le.c
@@ -1,10 +1,44 @@
-/* $OpenBSD: if_le.c,v 1.4 1998/09/16 22:41:19 jason Exp $ */
-/* $NetBSD: if_le.c,v 1.8 1997/04/21 22:04:23 ragge Exp $ */
+/* $OpenBSD: if_le.c,v 1.5 2000/04/27 03:14:43 bjc Exp $ */
+/* $NetBSD: if_le.c,v 1.14 1999/08/14 18:40:23 ragge Exp $ */
-/* #define LE_CHIP_IS_POKEY /* does VS2000 need this ??? */
+/*-
+ * Copyright (c) 1997, 1998 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Charles M. Hannum and by Jason R. Thorpe of the Numerical Aerospace
+ * Simulation Facility, NASA Ames Research Center.
+ *
+ * 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 NetBSD
+ * Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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.
+ */
/*-
- * Copyright (c) 1995 Charles M. Hannum. All rights reserved.
* Copyright (c) 1992, 1993
* The Regents of the University of California. All rights reserved.
*
@@ -50,177 +84,146 @@
#include <sys/device.h>
#include <sys/reboot.h>
+#include <vm/vm.h>
+#include <vm/vm_kern.h>
+
#include <net/if.h>
+#include <net/if_media.h>
#if INET
#include <netinet/in.h>
-#include <netinet/if_ether.h>
#endif
+#include <netinet/if_ether.h>
-#include <net/if_media.h>
-
-/*
- * 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 <machine/nexus.h>
#include <machine/rpb.h>
+#include <machine/scb.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)
+#define ETHER_MIN_LEN 64 /* minimum frame length, including CRC */
+#define LEVEC 0xd4 /* Interrupt vector on 3300/3400 */
-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
+struct le_softc {
+ struct am7990_softc sc_am7990; /* Must be first */
+ volatile u_short *sc_rap;
+ volatile u_short *sc_rdp;
};
-hide void lewrcsr __P ((struct am7990_softc *, u_int16_t, u_int16_t));
-hide u_int16_t lerdcsr __P ((struct am7990_softc *, u_int16_t));
+int le_ibus_match __P((struct device *, void *, void *));
+void le_ibus_attach __P((struct device *, struct device *, void *));
+void lewrcsr __P((struct am7990_softc *, u_int16_t, u_int16_t));
+u_int16_t lerdcsr __P((struct am7990_softc *, u_int16_t));
+void lance_copytobuf_gap2 __P((struct am7990_softc *, void *, int, int));
+void lance_copyfrombuf_gap2 __P((struct am7990_softc *, void *, int, int));
+void lance_zerobuf_gap2 __P((struct am7990_softc *, int, int));
+void leintr __P((void *));
+
+struct cfattach le_ibus_ca = {
+ sizeof(struct le_softc), le_ibus_match, le_ibus_attach
+};
-hide void
-lewrcsr(sc, port, val)
- struct am7990_softc *sc;
+void
+lewrcsr(ls, port, val)
+ struct am7990_softc *ls;
u_int16_t port, val;
{
- struct lereg1 *ler1 = ((struct le_softc *)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
+ struct le_softc *sc = (void *)ls;
+
+ *sc->sc_rap = port;
+ *sc->sc_rdp = val;
}
-hide u_int16_t
-lerdcsr(sc, port)
- struct am7990_softc *sc;
+u_int16_t
+lerdcsr(ls, port)
+ struct am7990_softc *ls;
u_int16_t port;
{
- struct lereg1 *ler1 = ((struct le_softc *)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);
-}
+ struct le_softc *sc = (void *)ls;
-integrate void
-lehwinit(sc)
- struct am7990_softc *sc;
-{
+ *sc->sc_rap = port;
+ return *sc->sc_rdp;
}
int
-lematch(parent, match, aux)
+le_ibus_match(parent, cf, aux)
struct device *parent;
- void *match, *aux;
+ void *cf;
+ void *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);
+ struct bp_conf *bp = aux;
- return (1);
+ if (strcmp("lance", bp->type))
+ return 0;
+ return 1;
}
-/*
- *
- */
void
-leattach(parent, self, aux)
+le_ibus_attach(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;
+ struct le_softc *sc = (void *)self;
+ int *lance_addr;
+ int i, vec, br;
- sc->sc_r1 = (void*)uvax_phys2virt(ca->ca_ioaddr);
+ sc->sc_rdp = (short *)vax_map_physmem(0x20084400, 1);
+ sc->sc_rap = sc->sc_rdp + 2;
- 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;
- sc->sc_am7990.sc_wrcsr = lewrcsr;
+ /*
+ * Set interrupt vector, by forcing an interrupt.
+ */
+ scb_vecref(0, 0); /* Clear vector ref */
+ *sc->sc_rap = LE_CSR0;
+ *sc->sc_rdp = LE_C0_STOP;
+ DELAY(100);
+ *sc->sc_rdp = LE_C0_INIT|LE_C0_INEA;
+ DELAY(100000);
+ i = scb_vecref(&vec, &br);
+ if (i == 0 || vec == 0)
+ return;
+ scb_vecalloc(vec, (void *)am7990_intr, sc, SCB_ISTACK);
+
+ printf(": vec %o ipl %x\n%s", vec, br, self->dv_xname);
+ /*
+ * MD functions.
+ */
sc->sc_am7990.sc_rdcsr = lerdcsr;
- sc->sc_am7990.sc_hwinit = lehwinit;
+ sc->sc_am7990.sc_wrcsr = lewrcsr;
sc->sc_am7990.sc_nocarrier = NULL;
- 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_mem =
+ (void *)uvm_km_valloc(kernel_map, (128 * 1024));
+ if (sc->sc_am7990.sc_mem == 0)
+ return;
+
+ ioaccess((vaddr_t)sc->sc_am7990.sc_mem, 0x20120000,
+ (128 * 1024) >> VAX_PGSHIFT);
- 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;
+
+ sc->sc_am7990.sc_addr = 0;
+ sc->sc_am7990.sc_memsize = (64 * 1024);
+
+ sc->sc_am7990.sc_copytodesc = lance_copytobuf_gap2;
+ sc->sc_am7990.sc_copyfromdesc = lance_copyfrombuf_gap2;
+ sc->sc_am7990.sc_copytobuf = lance_copytobuf_gap2;
+ sc->sc_am7990.sc_copyfrombuf = lance_copyfrombuf_gap2;
+ sc->sc_am7990.sc_zerobuf = lance_zerobuf_gap2;
/*
* 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];
- }
+ lance_addr = (int *)vax_map_physmem(0x20084200, 1);
+ for (i = 0; i < 6; i++)
+ sc->sc_am7990.sc_arpcom.ac_enaddr[i] = (u_char)lance_addr[i];
+ vax_unmap_physmem((vaddr_t)lance_addr, 1);
- bcopy(self->dv_xname, sc->sc_am7990.sc_arpcom.ac_if.if_xname, IFNAMSIZ);
+ 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);
-
/*
* Register this device as boot device if we booted from it.
* This will fail if there are more than one le in a machine,
@@ -230,28 +233,98 @@ leattach(parent, self, aux)
booted_from = self;
}
-#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.
+ * gap2: two bytes of data followed by two bytes of pad.
+ *
+ * Buffers must be 4-byte aligned. The code doesn't worry about
+ * doing an extra byte.
*/
+
void
-lewritereg(regptr, val)
- register volatile u_short *regptr;
- register u_short val;
+lance_copytobuf_gap2(sc, fromv, boff, len)
+ struct am7990_softc *sc;
+ void *fromv;
+ int boff;
+ register int len;
{
- 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);
+ volatile caddr_t buf = sc->sc_mem;
+ register caddr_t from = fromv;
+ register volatile u_int16_t *bptr;
+
+ if (boff & 0x1) {
+ /* handle unaligned first byte */
+ bptr = ((volatile u_int16_t *)buf) + (boff - 1);
+ *bptr = (*from++ << 8) | (*bptr & 0xff);
+ bptr += 2;
+ len--;
+ } else
+ bptr = ((volatile u_int16_t *)buf) + boff;
+ while (len > 1) {
+ *bptr = (from[1] << 8) | (from[0] & 0xff);
+ bptr += 2;
+ from += 2;
+ len -= 2;
}
+ if (len == 1)
+ *bptr = (u_int16_t)*from;
+}
+
+void
+lance_copyfrombuf_gap2(sc, tov, boff, len)
+ struct am7990_softc *sc;
+ void *tov;
+ int boff, len;
+{
+ volatile caddr_t buf = sc->sc_mem;
+ register caddr_t to = tov;
+ register volatile u_int16_t *bptr;
+ register u_int16_t tmp;
+
+ if (boff & 0x1) {
+ /* handle unaligned first byte */
+ bptr = ((volatile u_int16_t *)buf) + (boff - 1);
+ *to++ = (*bptr >> 8) & 0xff;
+ bptr += 2;
+ len--;
+ } else
+ bptr = ((volatile u_int16_t *)buf) + boff;
+ while (len > 1) {
+ tmp = *bptr;
+ *to++ = tmp & 0xff;
+ *to++ = (tmp >> 8) & 0xff;
+ bptr += 2;
+ len -= 2;
+ }
+ if (len == 1)
+ *to = *bptr & 0xff;
+}
+
+void
+lance_zerobuf_gap2(sc, boff, len)
+ struct am7990_softc *sc;
+ int boff, len;
+{
+ volatile caddr_t buf = sc->sc_mem;
+ register volatile u_int16_t *bptr;
+
+ if ((unsigned)boff & 0x1) {
+ bptr = ((volatile u_int16_t *)buf) + (boff - 1);
+ *bptr &= 0xff;
+ bptr += 2;
+ len--;
+ } else
+ bptr = ((volatile u_int16_t *)buf) + boff;
+ while (len > 0) {
+ *bptr = 0;
+ bptr += 2;
+ len -= 2;
+ }
+}
+
+void
+leintr(arg)
+ void *arg;
+{
+ int unit = (int)arg;
+ am7990_intr(le_cd.cd_devs[unit]);
}
-#endif
diff --git a/sys/arch/vax/if/if_qe.c b/sys/arch/vax/if/if_qe.c
index b114420e4d1..36e90edf0b6 100644
--- a/sys/arch/vax/if/if_qe.c
+++ b/sys/arch/vax/if/if_qe.c
@@ -1,12 +1,7 @@
-/* $OpenBSD: if_qe.c,v 1.10 1999/05/13 15:44:50 jason Exp $ */
-/* $NetBSD: if_qe.c,v 1.22 1997/05/02 17:11:24 ragge Exp $ */
-
+/* $OpenBSD: if_qe.c,v 1.11 2000/04/27 03:14:43 bjc Exp $ */
+/* $NetBSD: if_qe.c,v 1.39 2000/01/24 02:40:29 matt Exp $ */
/*
- * Copyright (c) 1988 Regents of the University of California.
- * All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Digital Equipment Corp.
+ * Copyright (c) 1999 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
@@ -18,348 +13,194 @@
* 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_qe.c 7.20 (Berkeley) 3/28/91
- */
-
-/* from @(#)if_qe.c 1.15 (ULTRIX) 4/16/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 *
- * derivative copyright rights, appropriate copyright *
- * legends may be placed on the derivative work in addition *
- * to that set forth above. *
- * *
- ****************************************************************/
-/* ---------------------------------------------------------------------
- * Modification History
- *
- * 15-Apr-86 -- afd
- * Rename "unused_multi" to "qunused_multi" for extending Generic
- * kernel to MicroVAXen.
- *
- * 18-mar-86 -- jaw br/cvec changed to NOT use registers.
- *
- * 12 March 86 -- Jeff Chase
- * Modified to handle the new MCLGET macro
- * Changed if_qe_data.c to use more receive buffers
- * Added a flag to poke with adb to log qe_restarts on console
- *
- * 19 Oct 85 -- rjl
- * Changed the watch dog timer from 30 seconds to 3. VMS is using
- * less than 1 second in their's. Also turned the printf into an
- * mprintf.
- *
- * 09/16/85 -- Larry Cohen
- * Add 43bsd alpha tape changes for subnet routing
- *
- * 1 Aug 85 -- rjl
- * Panic on a non-existent memory interrupt and the case where a packet
- * was chained. The first should never happen because non-existant
- * memory interrupts cause a bus reset. The second should never happen
- * because we hang 2k input buffers on the device.
- *
- * 1 Aug 85 -- rich
- * Fixed the broadcast loopback code to handle Clusters without
- * wedging the system.
- *
- * 27 Feb. 85 -- ejf
- * Return default hardware address on ioctl request.
- *
- * 12 Feb. 85 -- ejf
- * Added internal extended loopback capability.
- *
- * 27 Dec. 84 -- rjl
- * Fixed bug that caused every other transmit descriptor to be used
- * instead of every descriptor.
- *
- * 21 Dec. 84 -- rjl
- * Added watchdog timer to mask hardware bug that causes device lockup.
+ * 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
*
- * 18 Dec. 84 -- rjl
- * Reworked driver to use q-bus mapping routines. MicroVAX-I now does
- * copying instead of m-buf shuffleing.
- * A number of deficencies in the hardware/firmware were compensated
- * for. See comments in qestart and qerint.
- *
- * 14 Nov. 84 -- jf
- * Added usage counts for multicast addresses.
- * Updated general protocol support to allow access to the Ethernet
- * header.
- *
- * 04 Oct. 84 -- jf
- * Added support for new ioctls to add and delete multicast addresses
- * and set the physical address.
- * Add support for general protocols.
- *
- * 14 Aug. 84 -- rjl
- * Integrated Shannon changes. (allow arp above 1024 and ? )
- *
- * 13 Feb. 84 -- rjl
- *
- * Initial version of driver. derived from IL driver.
- *
- * ---------------------------------------------------------------------
+ * 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.
*/
/*
- * Digital Q-BUS to NI Adapter
- * supports DEQNA and DELQA in DEQNA-mode.
+ * Driver for DEQNA/DELQA ethernet cards.
+ * Things that is still to do:
+ * Have a timeout check for hang transmit logic.
+ * Handle ubaresets. Does not work at all right now.
+ * Fix ALLMULTI reception. But someone must tell me how...
+ * Collect statistics.
*/
#include "bpfilter.h"
#include <sys/param.h>
-#include <sys/systm.h>
#include <sys/mbuf.h>
-#include <sys/buf.h>
-#include <sys/protosw.h>
#include <sys/socket.h>
-#include <sys/ioctl.h>
-#include <sys/errno.h>
-#include <sys/syslog.h>
#include <sys/device.h>
-#include <sys/time.h>
-#include <sys/kernel.h>
+#include <sys/systm.h>
+#include <sys/sockio.h>
#include <net/if.h>
-#include <net/netisr.h>
-#include <net/route.h>
-
-#ifdef INET
+#include <net/if_dl.h>
#include <netinet/in.h>
-#include <netinet/in_systm.h>
-#include <netinet/in_var.h>
-#include <netinet/ip.h>
#include <netinet/if_ether.h>
-#endif
-
-#ifdef NS
-#include <netns/ns.h>
-#include <netns/ns_if.h>
-#endif
-
-#ifdef ISO
-#include <netiso/iso.h>
-#include <netiso/iso_var.h>
-extern char all_es_snpa[], all_is_snpa[], all_l1is_snpa[], all_l2is_snpa[];
-#endif
-
-#if defined(CCITT) && defined(LLC)
-#include <sys/socketvar.h>
-#include <netccitt/x25.h>
-#include <netccitt/pk.h>
-#include <netccitt/pk_var.h>
-#include <netccitt/pk_extern.h>
-#endif
#if NBPFILTER > 0
#include <net/bpf.h>
#include <net/bpfdesc.h>
#endif
-
-#include <machine/pte.h>
-#include <machine/cpu.h>
-#include <vax/if/if_qereg.h>
-#include <vax/if/if_uba.h>
-#include <vax/uba/ubareg.h>
-#include <vax/uba/ubavar.h>
+#include <machine/bus.h>
-#define NRCV 15 /* Receive descriptors */
-#define NXMT 5 /* Transmit descriptors */
-#define NTOT (NXMT + NRCV)
+#include <arch/vax/qbus/ubavar.h>
+#include <arch/vax/qbus/if_qereg.h>
-#define QETIMEOUT 2 /* transmit timeout, must be > 1 */
-#define QESLOWTIMEOUT 40 /* timeout when no xmits in progress */
-
-#define MINDATA 60
+#define RXDESCS 30 /* # of receive descriptors */
+#define TXDESCS 60 /* # transmit descs */
+#define ETHER_MINLEN 64 /* min frame + crc */
/*
- * Ethernet software status per interface.
- *
- * Each interface is referenced by a network interface structure,
- * qe_if, which the routing code uses to locate the interface.
- * This structure contains the output queue for the interface, its address, ...
+ * Structure containing the elements that must be in DMA-safe memory.
*/
-struct qe_softc {
- struct device qe_dev; /* Configuration common part */
- struct arpcom qe_ac; /* Ethernet common part */
-#define qe_if qe_ac.ac_if /* network-visible interface */
-#define qe_addr qe_ac.ac_enaddr /* hardware Ethernet address */
- struct ifubinfo qe_uba; /* Q-bus resources */
- struct ifrw qe_ifr[NRCV]; /* for receive buffers; */
- struct ifxmt qe_ifw[NXMT]; /* for xmit buffers; */
- struct qedevice *qe_vaddr;
- int qe_flags; /* software state */
-#define QEF_RUNNING 0x01
-#define QEF_SETADDR 0x02
-#define QEF_FASTTIMEO 0x04
- int setupaddr; /* mapping info for setup pkts */
- int ipl; /* interrupt priority */
- struct qe_ring *rringaddr; /* mapping info for rings */
- struct qe_ring *tringaddr; /* "" */
- struct qe_ring rring[NRCV+1]; /* Receive ring descriptors */
- struct qe_ring tring[NXMT+1]; /* Xmit ring descriptors */
- u_char setup_pkt[16][8]; /* Setup packet */
- int rindex; /* Receive index */
- int tindex; /* Transmit index */
- int otindex; /* Old transmit index */
- int qe_intvec; /* Interrupt vector */
- struct qedevice *addr; /* device addr */
- int setupqueued; /* setup packet queued */
- int setuplength; /* length if setup packet */
- int nxmit; /* Transmits in progress */
- int qe_restarts; /* timeouts */
+struct qe_cdata {
+ struct qe_ring qc_recv[RXDESCS+1]; /* Receive descriptors */
+ struct qe_ring qc_xmit[TXDESCS+1]; /* Transmit descriptors */
+ u_int8_t qc_setup[128]; /* Setup packet layout */
};
-int qematch __P((struct device *, void *, void *));
-void qeattach __P((struct device *, struct device *, void *));
-void qereset __P((int));
-void qeinit __P((struct qe_softc *));
-void qestart __P((struct ifnet *));
-void qeintr __P((int));
-void qetint __P((int));
-void qerint __P((int));
-int qeioctl __P((struct ifnet *, u_long, caddr_t));
-void qe_setaddr __P((u_char *, struct qe_softc *));
-void qeinitdesc __P((struct qe_ring *, caddr_t, int));
-void qesetup __P((struct qe_softc *));
-void qeread __P((struct qe_softc *, struct ifrw *, int));
-void qetimeout __P((struct ifnet *));
-void qerestart __P((struct qe_softc *));
-
-struct cfdriver qe_cd = {
- NULL, "qe", DV_IFNET
+struct qe_softc {
+ struct device sc_dev; /* Configuration common part */
+ struct arpcom sc_ac; /* Ethernet common part */
+#define sc_if sc_ac.ac_if /* network-visible interface */
+ bus_space_tag_t sc_iot;
+ bus_addr_t sc_ioh;
+ bus_dma_tag_t sc_dmat;
+ struct qe_cdata *sc_qedata; /* Descriptor struct */
+ struct qe_cdata *sc_pqedata; /* Unibus address of above */
+ bus_dmamap_t sc_cmap; /* Map for control structures */
+ struct mbuf* sc_txmbuf[TXDESCS];
+ struct mbuf* sc_rxmbuf[RXDESCS];
+ bus_dmamap_t sc_xmtmap[TXDESCS];
+ bus_dmamap_t sc_rcvmap[RXDESCS];
+ int sc_intvec; /* Interrupt vector */
+ int sc_nexttx;
+ int sc_inq;
+ int sc_lastack;
+ int sc_nextrx;
+ int sc_setup; /* Setup packet in queue */
};
+static int qematch __P((struct device *, struct cfdata *, void *));
+static void qeattach __P((struct device *, struct device *, void *));
+static void qeinit __P((struct qe_softc *));
+static void qestart __P((struct ifnet *));
+static void qeintr __P((void *));
+static int qeioctl __P((struct ifnet *, u_long, caddr_t));
+static int qe_add_rxbuf __P((struct qe_softc *, int));
+static void qe_setup __P((struct qe_softc *));
+static void qetimeout __P((struct ifnet *));
+
struct cfattach qe_ca = {
- sizeof(struct qe_softc), qematch, qeattach
+ sizeof(struct qe_softc), (cfmatch_t)qematch, qeattach
};
-#define QEUNIT(x) minor(x)
-/*
- * The deqna shouldn't receive more than ETHERMTU + sizeof(struct ether_header)
- * but will actually take in up to 2048 bytes. To guard against the receiver
- * chaining buffers (which we aren't prepared to handle) we allocate 2kb
- * size buffers.
- */
-#define MAXPACKETSIZE 2048 /* Should really be ETHERMTU */
+#define QE_WCSR(csr, val) \
+ bus_space_write_2(sc->sc_iot, sc->sc_ioh, csr, val)
+#define QE_RCSR(csr) \
+ bus_space_read_2(sc->sc_iot, sc->sc_ioh, csr)
+
+#define LOWORD(x) ((int)(x) & 0xffff)
+#define HIWORD(x) (((int)(x) >> 16) & 0x3f)
/*
- * Probe the QNA to see if it's there
+ * Check for present DEQNA. Done by sending a fake setup packet
+ * and wait for interrupt.
*/
int
-qematch(parent, match, aux)
+qematch(parent, cf, aux)
struct device *parent;
- void *match, *aux;
+ struct cfdata *cf;
+ void *aux;
{
- struct qe_softc *sc = match;
+ bus_dmamap_t cmap;
+ struct qe_softc ssc;
+ struct qe_softc *sc = &ssc;
struct uba_attach_args *ua = aux;
struct uba_softc *ubasc = (struct uba_softc *)parent;
+
+#define PROBESIZE (sizeof(struct qe_ring) * 4 + 128)
+ struct qe_ring ring[15]; /* For diag purposes only */
struct qe_ring *rp;
- struct qe_ring *prp; /* physical rp */
- volatile struct qedevice *addr = (struct qedevice *)ua->ua_addr;
- int i;
+ int error;
- /*
- * The QNA interrupts on i/o operations. To do an I/O operation
- * we have to setup the interface by transmitting a setup packet.
- */
+ bzero(sc, sizeof(struct qe_softc));
+ bzero(ring, PROBESIZE);
+ sc->sc_iot = ua->ua_iot;
+ sc->sc_ioh = ua->ua_ioh;
+ sc->sc_dmat = ua->ua_dmat;
- addr->qe_csr = QE_RESET;
- addr->qe_csr &= ~QE_RESET;
- addr->qe_vector = (ubasc->uh_lastiv -= 4);
+ ubasc->uh_lastiv -= 4;
+ QE_WCSR(QE_CSR_CSR, QE_RESET);
+ QE_WCSR(QE_CSR_VECTOR, ubasc->uh_lastiv);
/*
- * Map the communications area and the setup packet.
+ * Map the ring area. Actually this is done only to be able to
+ * send and receive a internal packet; some junk is loopbacked
+ * so that the DEQNA has a reason to interrupt.
*/
- sc->setupaddr =
- 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);
+ if ((error = bus_dmamap_create(sc->sc_dmat, PROBESIZE, 1, PROBESIZE, 0,
+ BUS_DMA_NOWAIT, &cmap))) {
+ printf("qematch: bus_dmamap_create failed = %d\n", error);
+ return 0;
+ }
+ if ((error = bus_dmamap_load(sc->sc_dmat, cmap, ring, PROBESIZE, 0,
+ BUS_DMA_NOWAIT))) {
+ printf("qematch: bus_dmamap_load failed = %d\n", error);
+ bus_dmamap_destroy(sc->sc_dmat, cmap);
+ return 0;
+ }
/*
- * The QNA will loop the setup packet back to the receive ring
- * for verification, therefore we initialize the first
- * receive & transmit ring descriptors and link the setup packet
- * to them.
+ * Init a simple "fake" receive and transmit descriptor that
+ * points to some unused area. Send a fake setup packet.
*/
- qeinitdesc(sc->tring, (caddr_t)UBAI_ADDR(sc->setupaddr),
- sizeof(sc->setup_pkt));
- qeinitdesc(sc->rring, (caddr_t)UBAI_ADDR(sc->setupaddr),
- sizeof(sc->setup_pkt));
-
- rp = (struct qe_ring *)sc->tring;
- rp->qe_setup = 1;
- rp->qe_eomsg = 1;
- rp->qe_flag = rp->qe_status1 = QE_NOTYET;
- rp->qe_valid = 1;
+ rp = (void *)cmap->dm_segs[0].ds_addr;
+ ring[0].qe_flag = ring[0].qe_status1 = QE_NOTYET;
+ ring[0].qe_addr_lo = LOWORD(&rp[4]);
+ ring[0].qe_addr_hi = HIWORD(&rp[4]) | QE_VALID | QE_EOMSG | QE_SETUP;
+ ring[0].qe_buf_len = 128;
- rp = (struct qe_ring *)sc->rring;
- rp->qe_flag = rp->qe_status1 = QE_NOTYET;
- rp->qe_valid = 1;
+ ring[2].qe_flag = ring[2].qe_status1 = QE_NOTYET;
+ ring[2].qe_addr_lo = LOWORD(&rp[4]);
+ ring[2].qe_addr_hi = HIWORD(&rp[4]) | QE_VALID;
+ ring[2].qe_buf_len = 128;
- /*
- * Get the addr off of the interface and place it into the setup
- * packet. This code looks strange due to the fact that the address
- * is placed in the setup packet in col. major order.
- */
- for (i = 0; i < 6; i++)
- sc->setup_pkt[i][1] = addr->qe_sta_addr[i];
+ QE_WCSR(QE_CSR_CSR, QE_RCSR(QE_CSR_CSR) & ~QE_RESET);
+ DELAY(1000);
- qesetup(sc);
/*
* Start the interface and wait for the packet.
*/
- addr->qe_csr = QE_INT_ENABLE | QE_XMIT_INT | QE_RCV_INT;
- addr->qe_rcvlist_lo = (short)((int)prp);
- addr->qe_rcvlist_hi = (short)((int)prp >> 16);
- prp += NRCV+1;
- addr->qe_xmtlist_lo = (short)((int)prp);
- addr->qe_xmtlist_hi = (short)((int)prp >> 16);
+ QE_WCSR(QE_CSR_CSR, QE_INT_ENABLE|QE_XMIT_INT|QE_RCV_INT);
+ QE_WCSR(QE_CSR_RCLL, LOWORD(&rp[2]));
+ QE_WCSR(QE_CSR_RCLH, HIWORD(&rp[2]));
+ QE_WCSR(QE_CSR_XMTL, LOWORD(rp));
+ QE_WCSR(QE_CSR_XMTH, HIWORD(rp));
DELAY(10000);
+
/*
* All done with the bus resources.
*/
- ubarelse(ubasc, &sc->setupaddr);
- ubarelse(ubasc, (int *)&sc->rringaddr);
- sc->ipl = 0x15;
- ua->ua_ivec = qeintr;
+ bus_dmamap_unload(sc->sc_dmat, cmap);
+ bus_dmamap_destroy(sc->sc_dmat, cmap);
return 1;
}
@@ -374,63 +215,186 @@ qeattach(parent, self, aux)
void *aux;
{
struct uba_attach_args *ua = aux;
+ struct uba_softc *ubasc = (struct uba_softc *)parent;
struct qe_softc *sc = (struct qe_softc *)self;
- struct ifnet *ifp = (struct ifnet *)&sc->qe_if;
- struct qedevice *addr =(struct qedevice *)ua->ua_addr;
- int i;
+ struct ifnet *ifp = (struct ifnet *)&sc->sc_if;
+ struct qe_ring *rp;
+ u_int8_t enaddr[ETHER_ADDR_LEN];
+ bus_dma_segment_t seg;
+ int i, rseg, error;
+
+ sc->sc_iot = ua->ua_iot;
+ sc->sc_ioh = ua->ua_ioh;
+ sc->sc_dmat = ua->ua_dmat;
+
+ /*
+ * Allocate DMA safe memory for descriptors and setup memory.
+ */
+ if ((error = bus_dmamem_alloc(sc->sc_dmat,
+ sizeof(struct qe_cdata), NBPG, 0, &seg, 1, &rseg,
+ BUS_DMA_NOWAIT)) != 0) {
+ printf(": unable to allocate control data, error = %d\n",
+ error);
+ goto fail_0;
+ }
+
+ if ((error = bus_dmamem_map(sc->sc_dmat, &seg, rseg,
+ sizeof(struct qe_cdata), (caddr_t *)&sc->sc_qedata,
+ BUS_DMA_NOWAIT|BUS_DMA_COHERENT)) != 0) {
+ printf(": unable to map control data, error = %d\n", error);
+ goto fail_1;
+ }
+
+ if ((error = bus_dmamap_create(sc->sc_dmat,
+ sizeof(struct qe_cdata), 1,
+ sizeof(struct qe_cdata), 0, BUS_DMA_NOWAIT,
+ &sc->sc_cmap)) != 0) {
+ printf(": unable to create control data DMA map, error = %d\n",
+ error);
+ goto fail_2;
+ }
+
+ if ((error = bus_dmamap_load(sc->sc_dmat, sc->sc_cmap,
+ sc->sc_qedata, sizeof(struct qe_cdata), NULL,
+ BUS_DMA_NOWAIT)) != 0) {
+ printf(": unable to load control data DMA map, error = %d\n",
+ error);
+ goto fail_3;
+ }
- printf("\n");
- sc->qe_vaddr = addr;
- bcopy(sc->qe_dev.dv_xname, ifp->if_xname, IFNAMSIZ);
- ifp->if_softc = sc;
/*
- * The Deqna is cable of transmitting broadcasts, but
- * doesn't listen to its own.
+ * Zero the newly allocated memory.
*/
- ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_NOTRAILERS |
- IFF_MULTICAST;
+ bzero(sc->sc_qedata, sizeof(struct qe_cdata));
+ /*
+ * Create the transmit descriptor DMA maps. We take advantage
+ * of the fact that the Qbus address space is big, and therefore
+ * allocate map registers for all transmit descriptors also,
+ * so that we can avoid this each time we send a packet.
+ */
+ for (i = 0; i < TXDESCS; i++) {
+ if ((error = bus_dmamap_create(sc->sc_dmat, MCLBYTES,
+ 1, MCLBYTES, 0, BUS_DMA_NOWAIT|BUS_DMA_ALLOCNOW,
+ &sc->sc_xmtmap[i]))) {
+ printf(": unable to create tx DMA map %d, error = %d\n",
+ i, error);
+ goto fail_4;
+ }
+ }
/*
- * Read the address from the prom and save it.
+ * Create receive buffer DMA maps.
*/
- for (i = 0; i < 6; i++)
- sc->setup_pkt[i][1] = sc->qe_addr[i] =
- addr->qe_sta_addr[i] & 0xff;
- addr->qe_vector |= 1;
- printf("qe%d: %s, hardware address %s\n", sc->qe_dev.dv_unit,
- addr->qe_vector&01 ? "delqa":"deqna",
- ether_sprintf(sc->qe_addr));
- addr->qe_vector &= ~1;
+ for (i = 0; i < RXDESCS; i++) {
+ if ((error = bus_dmamap_create(sc->sc_dmat, MCLBYTES, 1,
+ MCLBYTES, 0, BUS_DMA_NOWAIT,
+ &sc->sc_rcvmap[i]))) {
+ printf(": unable to create rx DMA map %d, error = %d\n",
+ i, error);
+ goto fail_5;
+ }
+ }
+ /*
+ * Pre-allocate the receive buffers.
+ */
+ for (i = 0; i < RXDESCS; i++) {
+ if ((error = qe_add_rxbuf(sc, i)) != 0) {
+ printf(": unable to allocate or map rx buffer %d\n,"
+ " error = %d\n", i, error);
+ goto fail_6;
+ }
+ }
+
+ /*
+ * Create ring loops of the buffer chains.
+ * This is only done once.
+ */
+ sc->sc_pqedata = (struct qe_cdata *)sc->sc_cmap->dm_segs[0].ds_addr;
+
+ rp = sc->sc_qedata->qc_recv;
+ rp[RXDESCS].qe_addr_lo = LOWORD(&sc->sc_pqedata->qc_recv[0]);
+ rp[RXDESCS].qe_addr_hi = HIWORD(&sc->sc_pqedata->qc_recv[0]) |
+ QE_VALID | QE_CHAIN;
+ rp[RXDESCS].qe_flag = rp[RXDESCS].qe_status1 = QE_NOTYET;
+
+ rp = sc->sc_qedata->qc_xmit;
+ rp[TXDESCS].qe_addr_lo = LOWORD(&sc->sc_pqedata->qc_xmit[0]);
+ rp[TXDESCS].qe_addr_hi = HIWORD(&sc->sc_pqedata->qc_xmit[0]) |
+ QE_VALID | QE_CHAIN;
+ rp[TXDESCS].qe_flag = rp[TXDESCS].qe_status1 = QE_NOTYET;
/*
- * Save the vector for initialization at reset time.
+ * Get the vector that were set at match time, and remember it.
*/
- sc->qe_intvec = addr->qe_vector;
+ sc->sc_intvec = ubasc->uh_lastiv;
+ QE_WCSR(QE_CSR_CSR, QE_RESET);
+ DELAY(1000);
+ QE_WCSR(QE_CSR_CSR, QE_RCSR(QE_CSR_CSR) & ~QE_RESET);
+ /*
+ * Read out ethernet address and tell which type this card is.
+ */
+ for (i = 0; i < 6; i++)
+ enaddr[i] = QE_RCSR(i * 2) & 0xff;
+
+ QE_WCSR(QE_CSR_VECTOR, sc->sc_intvec | 1);
+ printf("\n%s: %s, hardware address %s\n", sc->sc_dev.dv_xname,
+ QE_RCSR(QE_CSR_VECTOR) & 1 ? "delqa":"deqna",
+ ether_sprintf(enaddr));
+
+ QE_WCSR(QE_CSR_VECTOR, QE_RCSR(QE_CSR_VECTOR) & ~1); /* ??? */
+
+ uba_intr_establish(ua->ua_icookie, ua->ua_cvec, qeintr, sc);
+
+ strcpy(ifp->if_xname, sc->sc_dev.dv_xname);
+ ifp->if_softc = sc;
+ ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
ifp->if_start = qestart;
ifp->if_ioctl = qeioctl;
ifp->if_watchdog = qetimeout;
- sc->qe_uba.iff_flags = UBA_CANTWAIT;
+
+ /*
+ * Attach the interface.
+ */
if_attach(ifp);
ether_ifattach(ifp);
#if NBPFILTER > 0
bpfattach(&ifp->if_bpf, ifp, DLT_EN10MB, sizeof(struct ether_header));
#endif
-}
-
-/*
- * Reset of interface after UNIBUS reset.
- */
-void
-qereset(unit)
- int unit;
-{
- struct qe_softc *sc = qe_cd.cd_devs[unit];
+ return;
- printf(" %s", sc->qe_dev.dv_xname);
- sc->qe_if.if_flags &= ~IFF_RUNNING;
- qeinit(sc);
+ /*
+ * Free any resources we've allocated during the failed attach
+ * attempt. Do this in reverse order and fall through.
+ */
+ fail_6:
+ for (i = 0; i < RXDESCS; i++) {
+ if (sc->sc_rxmbuf[i] != NULL) {
+ bus_dmamap_unload(sc->sc_dmat, sc->sc_xmtmap[i]);
+ m_freem(sc->sc_rxmbuf[i]);
+ }
+ }
+ fail_5:
+ for (i = 0; i < RXDESCS; i++) {
+ if (sc->sc_xmtmap[i] != NULL)
+ bus_dmamap_destroy(sc->sc_dmat, sc->sc_xmtmap[i]);
+ }
+ fail_4:
+ for (i = 0; i < TXDESCS; i++) {
+ if (sc->sc_rcvmap[i] != NULL)
+ bus_dmamap_destroy(sc->sc_dmat, sc->sc_rcvmap[i]);
+ }
+ bus_dmamap_unload(sc->sc_dmat, sc->sc_cmap);
+ fail_3:
+ bus_dmamap_destroy(sc->sc_dmat, sc->sc_cmap);
+ fail_2:
+ bus_dmamem_unmap(sc->sc_dmat, (caddr_t)sc->sc_qedata,
+ sizeof(struct qe_cdata));
+ fail_1:
+ bus_dmamem_free(sc->sc_dmat, &seg, rseg);
+ fail_0:
+ return;
}
/*
@@ -440,347 +404,260 @@ void
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;
+ struct ifnet *ifp = (struct ifnet *)&sc->sc_if;
+ struct qe_cdata *qc = sc->sc_qedata;
int i;
- int s;
- /* address not known */
- if (ifp->if_addrlist.tqh_first == (struct ifaddr *)0)
- return;
- if (sc->qe_flags & QEF_RUNNING)
- return;
- if ((ifp->if_flags & IFF_RUNNING) == 0) {
- /*
- * map the communications area onto the device
- */
- 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(ubasc, (caddr_t)sc->setup_pkt,
- sizeof(sc->setup_pkt), 0);
- if (i == 0)
- goto fail;
- sc->setupaddr = UBAI_ADDR(i);
- /*
- * init buffers and maps
- */
- 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:
- printf("%s: can't allocate uba resources\n",
- sc->qe_dev.dv_xname);
- sc->qe_if.if_flags &= ~IFF_UP;
- return;
- }
- }
/*
- * Init the buffer descriptors and indexes for each of the lists and
- * loop them back to form a ring.
+ * Reset the interface.
*/
- for (i = 0; i < NRCV; i++) {
- qeinitdesc( &sc->rring[i],
- (caddr_t)UBAI_ADDR(sc->qe_ifr[i].ifrw_info), MAXPACKETSIZE);
- sc->rring[i].qe_flag = sc->rring[i].qe_status1 = QE_NOTYET;
- sc->rring[i].qe_valid = 1;
+ QE_WCSR(QE_CSR_CSR, QE_RESET);
+ DELAY(1000);
+ QE_WCSR(QE_CSR_CSR, QE_RCSR(QE_CSR_CSR) & ~QE_RESET);
+ QE_WCSR(QE_CSR_VECTOR, sc->sc_intvec);
+
+ sc->sc_nexttx = sc->sc_inq = sc->sc_lastack = 0;
+ /*
+ * Release and init transmit descriptors.
+ */
+ for (i = 0; i < TXDESCS; i++) {
+ if (sc->sc_txmbuf[i]) {
+ bus_dmamap_unload(sc->sc_dmat, sc->sc_xmtmap[i]);
+ m_freem(sc->sc_txmbuf[i]);
+ sc->sc_txmbuf[i] = 0;
+ }
+ qc->qc_xmit[i].qe_addr_hi = 0; /* Clear valid bit */
+ qc->qc_xmit[i].qe_status1 = qc->qc_xmit[i].qe_flag = QE_NOTYET;
}
- qeinitdesc(&sc->rring[i], (caddr_t)NULL, 0);
- sc->rring[i].qe_addr_lo = (short)((int)sc->rringaddr);
- sc->rring[i].qe_addr_hi = (short)((int)sc->rringaddr >> 16);
- sc->rring[i].qe_chain = 1;
- sc->rring[i].qe_flag = sc->rring[i].qe_status1 = QE_NOTYET;
- sc->rring[i].qe_valid = 1;
- for( i = 0 ; i <= NXMT ; i++ )
- qeinitdesc(&sc->tring[i], (caddr_t)NULL, 0);
- i--;
+ /*
+ * Init receive descriptors.
+ */
+ for (i = 0; i < RXDESCS; i++)
+ qc->qc_recv[i].qe_status1 = qc->qc_recv[i].qe_flag = QE_NOTYET;
+ sc->sc_nextrx = 0;
- sc->tring[i].qe_addr_lo = (short)((int)sc->tringaddr);
- sc->tring[i].qe_addr_hi = (short)((int)sc->tringaddr >> 16);
- sc->tring[i].qe_chain = 1;
- sc->tring[i].qe_flag = sc->tring[i].qe_status1 = QE_NOTYET;
- sc->tring[i].qe_valid = 1;
+ /*
+ * Write the descriptor addresses to the device.
+ * Receiving packets will be enabled in the interrupt routine.
+ */
+ QE_WCSR(QE_CSR_CSR, QE_INT_ENABLE|QE_XMIT_INT|QE_RCV_INT);
+ QE_WCSR(QE_CSR_RCLL, LOWORD(sc->sc_pqedata->qc_recv));
+ QE_WCSR(QE_CSR_RCLH, HIWORD(sc->sc_pqedata->qc_recv));
- sc->nxmit = sc->otindex = sc->tindex = sc->rindex = 0;
+ ifp->if_flags |= IFF_RUNNING;
+ ifp->if_flags &= ~IFF_OACTIVE;
/*
- * Take the interface out of reset, program the vector,
- * enable interrupts, and tell the world we are up.
+ * Send a setup frame.
+ * This will start the transmit machinery as well.
*/
- s = splnet();
- addr->qe_vector = sc->qe_intvec;
- sc->addr = addr;
- addr->qe_csr = QE_RCV_ENABLE | QE_INT_ENABLE | QE_XMIT_INT |
- QE_RCV_INT | QE_ILOOP;
- addr->qe_rcvlist_lo = (short)((int)sc->rringaddr);
- addr->qe_rcvlist_hi = (short)((int)sc->rringaddr >> 16);
- ifp->if_flags |= IFF_UP | IFF_RUNNING;
- sc->qe_flags |= QEF_RUNNING;
- qesetup( sc );
- qestart( ifp );
- sc->qe_if.if_timer = QESLOWTIMEOUT; /* Start watchdog */
- splx( s );
+ qe_setup(sc);
+
}
/*
* Start output on interface.
- *
*/
void
qestart(ifp)
struct ifnet *ifp;
{
- register struct qe_softc *sc = ifp->if_softc;
- volatile struct qedevice *addr = sc->qe_vaddr;
- register struct qe_ring *rp;
- register index;
- struct mbuf *m;
- int buf_addr, len, s;
+ struct qe_softc *sc = ifp->if_softc;
+ struct qe_cdata *qc = sc->sc_qedata;
+ paddr_t buffer;
+ struct mbuf *m, *m0;
+ int idx, len, s, i, totlen, error;
+ short orword;
+ if ((QE_RCSR(QE_CSR_CSR) & QE_RCV_ENABLE) == 0)
+ return;
- s = splnet();
- /*
- * The deqna doesn't look at anything but the valid bit
- * to determine if it should transmit this packet. If you have
- * a ring and fill it the device will loop indefinately on the
- * packet and continue to flood the net with packets until you
- * break the ring. For this reason we never queue more than n-1
- * packets in the transmit ring.
- *
- * The microcoders should have obeyed their own defination of the
- * flag and status words, but instead we have to compensate.
- */
- for( index = sc->tindex;
- sc->tring[index].qe_valid == 0 && sc->nxmit < (NXMT-1) ;
- sc->tindex = index = ++index % NXMT){
- rp = &sc->tring[index];
- if( sc->setupqueued ) {
- buf_addr = sc->setupaddr;
- len = sc->setuplength;
- rp->qe_setup = 1;
- sc->setupqueued = 0;
- } else {
- IF_DEQUEUE(&sc->qe_if.if_snd, m);
- if (m == 0) {
- splx(s);
- return;
- }
-#if NBPFILTER > 0
- if (ifp->if_bpf)
- bpf_mtap(ifp->if_bpf, m);
-#endif
- buf_addr = sc->qe_ifw[index].ifw_info;
- len = if_ubaput(&sc->qe_uba, &sc->qe_ifw[index], m);
+ s = splimp();
+ while (sc->sc_inq < (TXDESCS - 1)) {
+
+ if (sc->sc_setup) {
+ qe_setup(sc);
+ continue;
}
- if( len < MINDATA )
- len = MINDATA;
+ idx = sc->sc_nexttx;
+ IF_DEQUEUE(&sc->sc_if.if_snd, m);
+ if (m == 0)
+ goto out;
/*
- * Does buffer end on odd byte ?
+ * Count number of mbufs in chain.
+ * Always do DMA directly from mbufs, therefore the transmit
+ * ring is really big.
*/
- if( len & 1 ) {
- len++;
- rp->qe_odd_end = 1;
+ for (m0 = m, i = 0; m0; m0 = m0->m_next)
+ if (m0->m_len)
+ i++;
+ if (i >= TXDESCS)
+ panic("qestart");
+
+ if ((i + sc->sc_inq) >= (TXDESCS - 1)) {
+ IF_PREPEND(&sc->sc_if.if_snd, m);
+ ifp->if_flags |= IFF_OACTIVE;
+ goto out;
}
- rp->qe_buf_len = -(len/2);
- buf_addr = UBAI_ADDR(buf_addr);
- rp->qe_flag = rp->qe_status1 = QE_NOTYET;
- rp->qe_addr_lo = (short)buf_addr;
- rp->qe_addr_hi = (short)(buf_addr >> 16);
- rp->qe_eomsg = 1;
- rp->qe_flag = rp->qe_status1 = QE_NOTYET;
- rp->qe_valid = 1;
- if (sc->nxmit++ == 0) {
- sc->qe_flags |= QEF_FASTTIMEO;
- sc->qe_if.if_timer = QETIMEOUT;
+
+#if NBPFILTER > 0
+ if (ifp->if_bpf)
+ bpf_mtap(ifp->if_bpf, m);
+#endif
+ /*
+ * m now points to a mbuf chain that can be loaded.
+ * Loop around and set it.
+ */
+ totlen = 0;
+ for (m0 = m; m0; m0 = m0->m_next) {
+ error = bus_dmamap_load(sc->sc_dmat, sc->sc_xmtmap[idx],
+ mtod(m0, void *), m0->m_len, 0, 0);
+ buffer = sc->sc_xmtmap[idx]->dm_segs[0].ds_addr;
+ len = m0->m_len;
+ if (len == 0)
+ continue;
+
+ totlen += len;
+ /* Word alignment calc */
+ orword = 0;
+ if (totlen == m->m_pkthdr.len) {
+ if (totlen < ETHER_MINLEN)
+ len += (ETHER_MINLEN - totlen);
+ orword |= QE_EOMSG;
+ sc->sc_txmbuf[idx] = m;
+ }
+ if ((buffer & 1) || (len & 1))
+ len += 2;
+ if (buffer & 1)
+ orword |= QE_ODDBEGIN;
+ if ((buffer + len) & 1)
+ orword |= QE_ODDEND;
+ qc->qc_xmit[idx].qe_buf_len = -(len/2);
+ qc->qc_xmit[idx].qe_addr_lo = LOWORD(buffer);
+ qc->qc_xmit[idx].qe_addr_hi = HIWORD(buffer);
+ qc->qc_xmit[idx].qe_flag =
+ qc->qc_xmit[idx].qe_status1 = QE_NOTYET;
+ qc->qc_xmit[idx].qe_addr_hi |= (QE_VALID | orword);
+ if (++idx == TXDESCS)
+ idx = 0;
+ sc->sc_inq++;
}
+#ifdef DIAGNOSTIC
+ if (totlen != m->m_pkthdr.len)
+ panic("qestart: len fault");
+#endif
/*
- * See if the xmit list is invalid.
+ * Kick off the transmit logic, if it is stopped.
*/
- if( addr->qe_csr & QE_XL_INVALID ) {
- buf_addr = (int)(sc->tringaddr+index);
- addr->qe_xmtlist_lo = (short)buf_addr;
- addr->qe_xmtlist_hi = (short)(buf_addr >> 16);
+ if (QE_RCSR(QE_CSR_CSR) & QE_XL_INVALID) {
+ QE_WCSR(QE_CSR_XMTL,
+ LOWORD(&sc->sc_pqedata->qc_xmit[sc->sc_nexttx]));
+ QE_WCSR(QE_CSR_XMTH,
+ HIWORD(&sc->sc_pqedata->qc_xmit[sc->sc_nexttx]));
}
+ sc->sc_nexttx = idx;
}
+ if (sc->sc_inq == (TXDESCS - 1))
+ ifp->if_flags |= IFF_OACTIVE;
+
+out: if (sc->sc_inq)
+ ifp->if_timer = 5; /* If transmit logic dies */
splx(s);
- return;
}
-/*
- * Ethernet interface interrupt processor
- */
-void
-qeintr(unit)
- int unit;
+static void
+qeintr(arg)
+ void *arg;
{
- register struct qe_softc *sc;
- volatile struct qedevice *addr;
- int buf_addr, csr;
-
- sc = qe_cd.cd_devs[unit];
- addr = sc->qe_vaddr;
- splx(sc->ipl);
- if (!(sc->qe_flags & QEF_FASTTIMEO))
- sc->qe_if.if_timer = QESLOWTIMEOUT; /* Restart timer clock */
- csr = addr->qe_csr;
- addr->qe_csr = QE_RCV_ENABLE | QE_INT_ENABLE |
- QE_XMIT_INT | QE_RCV_INT | QE_ILOOP;
- if (csr & QE_RCV_INT)
- qerint(unit);
- if (csr & QE_XMIT_INT)
- qetint(unit );
- if (csr & QE_NEX_MEM_INT)
- printf("qe%d: Nonexistent memory interrupt\n", unit);
-
- if (addr->qe_csr & QE_RL_INVALID && sc->rring[sc->rindex].qe_status1 ==
- QE_NOTYET) {
- buf_addr = (int)&sc->rringaddr[sc->rindex];
- addr->qe_rcvlist_lo = (short)buf_addr;
- addr->qe_rcvlist_hi = (short)(buf_addr >> 16);
- }
-}
+ struct qe_softc *sc = arg;
+ struct qe_cdata *qc = sc->sc_qedata;
+ struct ifnet *ifp = &sc->sc_if;
+ struct ether_header *eh;
+ struct mbuf *m;
+ int csr, status1, status2, len;
-/*
- * Ethernet interface transmit interrupt.
- */
-void
-qetint(unit)
- int unit;
-{
- register struct qe_softc *sc = qe_cd.cd_devs[unit];
- register struct qe_ring *rp;
- register struct ifxmt *ifxp;
- int status1, setupflag;
- short len;
+ csr = QE_RCSR(QE_CSR_CSR);
+ QE_WCSR(QE_CSR_CSR, QE_RCV_ENABLE | QE_INT_ENABLE | QE_XMIT_INT |
+ QE_RCV_INT | QE_ILOOP);
- while (sc->otindex != sc->tindex && sc->tring[sc->otindex].qe_status1
- != QE_NOTYET && sc->nxmit > 0) {
- /*
- * Save the status words from the descriptor so that it can
- * be released.
- */
- rp = &sc->tring[sc->otindex];
- status1 = rp->qe_status1;
- setupflag = rp->qe_setup;
- len = (-rp->qe_buf_len) * 2;
- if( rp->qe_odd_end )
- len++;
- /*
- * Init the buffer descriptor
- */
- bzero((caddr_t)rp, sizeof(struct qe_ring));
- if( --sc->nxmit == 0 ) {
- sc->qe_flags &= ~QEF_FASTTIMEO;
- sc->qe_if.if_timer = QESLOWTIMEOUT;
- }
- if( !setupflag ) {
+ if (csr & QE_RCV_INT)
+ while (qc->qc_recv[sc->sc_nextrx].qe_status1 != QE_NOTYET) {
+ status1 = qc->qc_recv[sc->sc_nextrx].qe_status1;
+ status2 = qc->qc_recv[sc->sc_nextrx].qe_status2;
+ m = sc->sc_rxmbuf[sc->sc_nextrx];
+ len = ((status1 & QE_RBL_HI) |
+ (status2 & QE_RBL_LO)) + 60;
+ qe_add_rxbuf(sc, sc->sc_nextrx);
+ m->m_pkthdr.rcvif = ifp;
+ m->m_pkthdr.len = m->m_len = len;
+ if (++sc->sc_nextrx == RXDESCS)
+ sc->sc_nextrx = 0;
+ eh = mtod(m, struct ether_header *);
+#if NBPFILTER > 0
+ if (ifp->if_bpf) {
+ bpf_mtap(ifp->if_bpf, m);
+ if ((ifp->if_flags & IFF_PROMISC) != 0 &&
+ bcmp(sc->sc_ac.ac_enaddr, eh->ether_dhost,
+ ETHER_ADDR_LEN) != 0 &&
+ ((eh->ether_dhost[0] & 1) == 0)) {
+ m_freem(m);
+ continue;
+ }
+ }
+#endif
/*
- * Do some statistics.
+ * ALLMULTI means PROMISC in this driver.
*/
- sc->qe_if.if_opackets++;
- sc->qe_if.if_collisions += ( status1 & QE_CCNT ) >> 4;
- if (status1 & QE_ERROR)
- sc->qe_if.if_oerrors++;
- ifxp = &sc->qe_ifw[sc->otindex];
- if (ifxp->ifw_xtofree) {
- m_freem(ifxp->ifw_xtofree);
- ifxp->ifw_xtofree = 0;
+ if ((ifp->if_flags & IFF_ALLMULTI) &&
+ ((eh->ether_dhost[0] & 1) == 0) &&
+ bcmp(sc->sc_ac.ac_enaddr, eh->ether_dhost,
+ ETHER_ADDR_LEN)) {
+ m_freem(m);
+ continue;
}
+ ether_input(ifp, eh, m);
}
- sc->otindex = ++sc->otindex % NXMT;
- }
- qestart(&sc->qe_if);
-}
-
-/*
- * Ethernet interface receiver interrupt.
- * If can't determine length from type, then have to drop packet.
- * Othewise decapsulate packet based on type and pass to type specific
- * higher-level input routine.
- */
-void
-qerint(unit)
- int unit;
-{
- register struct qe_softc *sc = qe_cd.cd_devs[unit];
- register struct qe_ring *rp;
- register int nrcv = 0;
- int len, status1, status2;
- int bufaddr;
+ if (csr & QE_XMIT_INT) {
+ while (qc->qc_xmit[sc->sc_lastack].qe_status1 != QE_NOTYET) {
+ int idx = sc->sc_lastack;
+
+ sc->sc_inq--;
+ if (++sc->sc_lastack == TXDESCS)
+ sc->sc_lastack = 0;
+
+ /* XXX collect statistics */
+ qc->qc_xmit[idx].qe_addr_hi &= ~QE_VALID;
+ qc->qc_xmit[idx].qe_status1 =
+ qc->qc_xmit[idx].qe_flag = QE_NOTYET;
+
+ if (qc->qc_xmit[idx].qe_addr_hi & QE_SETUP)
+ continue;
+ bus_dmamap_unload(sc->sc_dmat, sc->sc_xmtmap[idx]);
+ if (sc->sc_txmbuf[idx]) {
+ m_freem(sc->sc_txmbuf[idx]);
+ sc->sc_txmbuf[idx] = 0;
+ }
+ }
+ ifp->if_timer = 0;
+ ifp->if_flags &= ~IFF_OACTIVE;
+ qestart(ifp); /* Put in more in queue */
+ }
/*
- * Traverse the receive ring looking for packets to pass back.
- * The search is complete when we find a descriptor not in use.
- *
- * As in the transmit case the deqna doesn't honor it's own protocols
- * so there exists the possibility that the device can beat us around
- * the ring. The proper way to guard against this is to insure that
- * there is always at least one invalid descriptor. We chose instead
- * to make the ring large enough to minimize the problem. With a ring
- * size of 4 we haven't been able to see the problem. To be safe we
- * doubled that to 8.
- *
+ * How can the receive list get invalid???
+ * Verified that it happens anyway.
*/
- while (sc->rring[sc->rindex].qe_status1 == QE_NOTYET && nrcv < NRCV) {
- /*
- * We got an interrupt but did not find an input packet
- * where we expected one to be, probably because the ring
- * was overrun.
- * We search forward to find a valid packet and start
- * processing from there. If no valid packet is found it
- * means we processed all the packets during a previous
- * interrupt and that the QE_RCV_INT bit was set while
- * we were processing one of these earlier packets. In
- * this case we can safely ignore the interrupt (by dropping
- * through the code below).
- */
- sc->rindex = (sc->rindex + 1) % NRCV;
- nrcv++;
- }
- if (nrcv && nrcv < NRCV)
- log(LOG_ERR, "qe%d: ring overrun, resync'd by skipping %d\n",
- unit, nrcv);
-
- for (; sc->rring[sc->rindex].qe_status1 != QE_NOTYET;
- sc->rindex = ++sc->rindex % NRCV) {
- rp = &sc->rring[sc->rindex];
- status1 = rp->qe_status1;
- status2 = rp->qe_status2;
- bzero((caddr_t)rp, sizeof(struct qe_ring));
- if( (status1 & QE_MASK) == QE_MASK )
- panic("qe: chained packet");
- len = ((status1 & QE_RBL_HI) | (status2 & QE_RBL_LO)) + 60;
- sc->qe_if.if_ipackets++;
-
- if (status1 & QE_ERROR) {
- if ((status1 & QE_RUNT) == 0)
- sc->qe_if.if_ierrors++;
- } else {
- /*
- * We don't process setup packets.
- */
- if (!(status1 & QE_ESETUP))
- qeread(sc, &sc->qe_ifr[sc->rindex],
- len - sizeof(struct ether_header));
- }
- /*
- * Return the buffer to the ring
- */
- bufaddr = (int)UBAI_ADDR(sc->qe_ifr[sc->rindex].ifrw_info);
- rp->qe_buf_len = -((MAXPACKETSIZE)/2);
- rp->qe_addr_lo = (short)bufaddr;
- rp->qe_addr_hi = (short)((int)bufaddr >> 16);
- rp->qe_flag = rp->qe_status1 = QE_NOTYET;
- rp->qe_valid = 1;
+ if ((qc->qc_recv[sc->sc_nextrx].qe_status1 == QE_NOTYET) &&
+ (QE_RCSR(QE_CSR_CSR) & QE_RL_INVALID)) {
+ QE_WCSR(QE_CSR_RCLL,
+ LOWORD(&sc->sc_pqedata->qc_recv[sc->sc_nextrx]));
+ QE_WCSR(QE_CSR_RCLH,
+ HIWORD(&sc->sc_pqedata->qc_recv[sc->sc_nextrx]));
}
}
@@ -794,47 +671,48 @@ qeioctl(ifp, cmd, data)
caddr_t data;
{
struct qe_softc *sc = ifp->if_softc;
- struct ifaddr *ifa = (struct ifaddr *)data;
struct ifreq *ifr = (struct ifreq *)data;
+ struct ifaddr *ifa = (struct ifaddr *)data;
int s = splnet(), error = 0;
switch (cmd) {
case SIOCSIFADDR:
ifp->if_flags |= IFF_UP;
- qeinit(sc);
switch(ifa->ifa_addr->sa_family) {
#ifdef INET
case AF_INET:
- arp_ifinit(&sc->qe_ac, ifa);
- break;
-#endif
-#ifdef NS
- case AF_NS:
- {
- register struct ns_addr *ina = &(IA_SNS(ifa)->sns_addr);
-
- if (ns_nullhost(*ina))
- ina->x_host = *(union ns_host *)(sc->qe_addr);
- else
- qe_setaddr(ina->x_host.c_host, sc);
+ qeinit(sc);
+ arp_ifinit(&sc->sc_ac, ifa);
break;
- }
#endif
}
break;
case SIOCSIFFLAGS:
if ((ifp->if_flags & IFF_UP) == 0 &&
- sc->qe_flags & QEF_RUNNING) {
- sc->qe_vaddr->qe_csr = QE_RESET;
- sc->qe_flags &= ~QEF_RUNNING;
- } else if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) ==
- IFF_RUNNING && (sc->qe_flags & QEF_RUNNING) == 0)
- qerestart(sc);
- else
+ (ifp->if_flags & IFF_RUNNING) != 0) {
+ /*
+ * If interface is marked down and it is running,
+ * stop it. (by disabling receive mechanism).
+ */
+ QE_WCSR(QE_CSR_CSR,
+ QE_RCSR(QE_CSR_CSR) & ~QE_RCV_ENABLE);
+ ifp->if_flags &= ~IFF_RUNNING;
+ } else if ((ifp->if_flags & IFF_UP) != 0 &&
+ (ifp->if_flags & IFF_RUNNING) == 0) {
+ /*
+ * If interface it marked up and it is stopped, then
+ * start it.
+ */
qeinit(sc);
-
+ } else if ((ifp->if_flags & IFF_UP) != 0) {
+ /*
+ * Send a new setup packet to match any new changes.
+ * (Like IFF_PROMISC etc)
+ */
+ qe_setup(sc);
+ }
break;
case SIOCADDMULTI:
@@ -843,15 +721,15 @@ qeioctl(ifp, cmd, data)
* Update our multicast list.
*/
error = (cmd == SIOCADDMULTI) ?
- ether_addmulti(ifr, &sc->qe_ac):
- ether_delmulti(ifr, &sc->qe_ac);
+ ether_addmulti(ifr, &sc->sc_ac):
+ ether_delmulti(ifr, &sc->sc_ac);
if (error == ENETRESET) {
/*
* Multicast list has changed; set the hardware filter
* accordingly.
*/
- qeinit(sc);
+ qe_setup(sc);
error = 0;
}
break;
@@ -865,226 +743,154 @@ qeioctl(ifp, cmd, data)
}
/*
- * set ethernet address for unit
+ * Add a receive buffer to the indicated descriptor.
*/
-void
-qe_setaddr(physaddr, sc)
- u_char *physaddr;
+int
+qe_add_rxbuf(sc, i)
struct qe_softc *sc;
+ int i;
{
- register int i;
+ struct mbuf *m;
+ struct qe_ring *rp;
+ vaddr_t addr;
+ int error;
+
+ MGETHDR(m, M_DONTWAIT, MT_DATA);
+ if (m == NULL)
+ return (ENOBUFS);
+
+ MCLGET(m, M_DONTWAIT);
+ if ((m->m_flags & M_EXT) == 0) {
+ m_freem(m);
+ return (ENOBUFS);
+ }
- for (i = 0; i < 6; i++)
- sc->setup_pkt[i][1] = sc->qe_addr[i] = physaddr[i];
- sc->qe_flags |= QEF_SETADDR;
- if (sc->qe_if.if_flags & IFF_RUNNING)
- qesetup(sc);
- qeinit(sc);
-}
+ if (sc->sc_rxmbuf[i] != NULL)
+ bus_dmamap_unload(sc->sc_dmat, sc->sc_rcvmap[i]);
+ error = bus_dmamap_load(sc->sc_dmat, sc->sc_rcvmap[i],
+ m->m_ext.ext_buf, m->m_ext.ext_size, NULL, BUS_DMA_NOWAIT);
+ if (error)
+ panic("%s: can't load rx DMA map %d, error = %d\n",
+ sc->sc_dev.dv_xname, i, error);
+ sc->sc_rxmbuf[i] = m;
-/*
- * Initialize a ring descriptor with mbuf allocation side effects
- */
-void
-qeinitdesc(rp, addr, len)
- register struct qe_ring *rp;
- caddr_t addr; /* mapped address */
- int len;
-{
- /*
- * clear the entire descriptor
- */
- bzero((caddr_t)rp, sizeof(struct qe_ring));
+ bus_dmamap_sync(sc->sc_dmat, sc->sc_rcvmap[i], 0,
+ sc->sc_rcvmap[i]->dm_mapsize, BUS_DMASYNC_PREREAD);
- if (len) {
- rp->qe_buf_len = -(len/2);
- rp->qe_addr_lo = (short)((int)addr);
- rp->qe_addr_hi = (short)((int)addr >> 16);
- }
-}
-/*
- * Build a setup packet - the physical address will already be present
- * in first column.
- */
-void
-qesetup(sc)
- struct qe_softc *sc;
-{
- register i, j;
-
- /*
- * Copy the target address to the rest of the entries in this row.
- */
- for (j = 0; j < 6; j++)
- for (i = 2; i < 8; i++)
- sc->setup_pkt[j][i] = sc->setup_pkt[j][1];
- /*
- * Duplicate the first half.
- */
- bcopy((caddr_t)sc->setup_pkt[0], (caddr_t)sc->setup_pkt[8], 64);
/*
- * Fill in the broadcast (and ISO multicast) address(es).
+ * We know that the mbuf cluster is page aligned. Also, be sure
+ * that the IP header will be longword aligned.
*/
- for (i = 0; i < 6; i++) {
- sc->setup_pkt[i][2] = 0xff;
-#ifdef ISO
- /*
- * XXX layer violation, should use SIOCADDMULTI.
- * Will definitely break with IPmulticast.
- */
+ m->m_data += 2;
+ addr = sc->sc_rcvmap[i]->dm_segs[0].ds_addr + 2;
+ rp = &sc->sc_qedata->qc_recv[i];
+ rp->qe_flag = rp->qe_status1 = QE_NOTYET;
+ rp->qe_addr_lo = LOWORD(addr);
+ rp->qe_addr_hi = HIWORD(addr) | QE_VALID;
+ rp->qe_buf_len = -(m->m_ext.ext_size - 2)/2;
- sc->setup_pkt[i][3] = all_es_snpa[i];
- sc->setup_pkt[i][4] = all_is_snpa[i];
- sc->setup_pkt[i][5] = all_l1is_snpa[i];
- sc->setup_pkt[i][6] = all_l2is_snpa[i];
-#endif
- }
- if (sc->qe_if.if_flags & IFF_PROMISC) {
- sc->setuplength = QE_PROMISC;
- /* XXX no IFF_ALLMULTI support in 4.4bsd */
- } else if (sc->qe_if.if_flags & IFF_ALLMULTI) {
- sc->setuplength = QE_ALLMULTI;
- } else {
- register k;
- struct ether_multi *enm;
- struct ether_multistep step;
- /*
- * Step through our list of multicast addresses, putting them
- * in the third through fourteenth address slots of the setup
- * packet. (See the DEQNA manual to understand the peculiar
- * layout of the bytes within the setup packet.) If we have
- * too many multicast addresses, or if we have to listen to
- * a range of multicast addresses, turn on reception of all
- * multicasts.
- */
- sc->setuplength = QE_SOMEMULTI;
- i = 2;
- k = 0;
- ETHER_FIRST_MULTI(step, &sc->qe_ac, enm);
- while (enm != NULL) {
- if ((++i > 7 && k != 0) ||
- bcmp(enm->enm_addrlo, enm->enm_addrhi, 6) != 0) {
- sc->setuplength = QE_ALLMULTI;
- break;
- }
- if (i > 7) {
- i = 1;
- k = 8;
- }
- for (j = 0; j < 6; j++)
- sc->setup_pkt[j+k][i] = enm->enm_addrlo[j];
- ETHER_NEXT_MULTI(step, enm);
- }
- }
- sc->setupqueued++;
+ return (0);
}
/*
- * Pass a packet to the higher levels.
- * We deal with the trailer protocol here.
+ * Create a setup packet and put in queue for sending.
*/
void
-qeread(sc, ifrw, len)
- register struct qe_softc *sc;
- struct ifrw *ifrw;
- int len;
+qe_setup(sc)
+ struct qe_softc *sc;
{
- struct ifnet *ifp = (struct ifnet *)&sc->qe_if;
- struct ether_header *eh;
- struct mbuf *m;
-
+ struct ether_multi *enm;
+ struct ether_multistep step;
+ struct qe_cdata *qc = sc->sc_qedata;
+ struct ifnet *ifp = &sc->sc_if;
+ u_int8_t *enaddr = sc->sc_ac.ac_enaddr;
+ int i, j, k, idx, s;
+
+ s = splimp();
+ if (sc->sc_inq == (TXDESCS - 1)) {
+ sc->sc_setup = 1;
+ splx(s);
+ return;
+ }
+ sc->sc_setup = 0;
/*
- * Deal with trailer protocol: if type is INET trailer
- * get true type from first 16-bit word past data.
- * Remember that type was trailer by setting off.
+ * Init the setup packet with valid info.
*/
-
- eh = (struct ether_header *)ifrw->ifrw_addr;
- if (len == 0)
- return;
+ memset(qc->qc_setup, 0xff, sizeof(qc->qc_setup)); /* Broadcast */
+ for (i = 0; i < ETHER_ADDR_LEN; i++)
+ qc->qc_setup[i * 8 + 1] = enaddr[i]; /* Own address */
/*
- * Pull packet off interface. Off is nonzero if packet
- * has trailing header; qeget will then force this header
- * information to be at the front, but we still have to drop
- * the type and length which are at the front of any trailer data.
+ * Multicast handling. The DEQNA can handle up to 12 direct
+ * ethernet addresses.
*/
- m = if_ubaget(&sc->qe_uba, ifrw, len, &sc->qe_if);
-#ifdef notdef
-if (m) {
-*(((u_long *)m->m_data)+0),
-*(((u_long *)m->m_data)+1),
-*(((u_long *)m->m_data)+2),
-*(((u_long *)m->m_data)+3)
-; }
-#endif
+ j = 3; k = 0;
+ ifp->if_flags &= ~IFF_ALLMULTI;
+ ETHER_FIRST_MULTI(step, &sc->sc_ac, enm);
+ while (enm != NULL) {
+ if (bcmp(enm->enm_addrlo, enm->enm_addrhi, 6)) {
+ ifp->if_flags |= IFF_ALLMULTI;
+ break;
+ }
+ for (i = 0; i < ETHER_ADDR_LEN; i++)
+ qc->qc_setup[i * 8 + j + k] = enm->enm_addrlo[i];
+ j++;
+ if (j == 8) {
+ j = 1; k += 64;
+ }
+ if (k > 64) {
+ ifp->if_flags |= IFF_ALLMULTI;
+ break;
+ }
+ ETHER_NEXT_MULTI(step, enm);
+ }
+ idx = sc->sc_nexttx;
+ qc->qc_xmit[idx].qe_buf_len = -64;
-#if NBPFILTER > 0
/*
- * Check for a BPF filter; if so, hand it up.
- * Note that we have to stick an extra mbuf up front, because
- * bpf_mtap expects to have the ether header at the front.
- * It doesn't matter that this results in an ill-formatted mbuf chain,
- * since BPF just looks at the data. (It doesn't try to free the mbuf,
- * tho' it will make a copy for tcpdump.)
+ * How is the DEQNA turned in ALLMULTI mode???
+ * Until someone tells me, fall back to PROMISC when more than
+ * 12 ethernet addresses.
*/
- if (sc->qe_if.if_bpf) {
- struct mbuf m0;
- m0.m_len = sizeof (struct ether_header);
- m0.m_data = (caddr_t)eh;
- m0.m_next = m;
-
- /* Pass it up */
- bpf_mtap(sc->qe_if.if_bpf, &m0);
+ if (ifp->if_flags & (IFF_PROMISC|IFF_ALLMULTI))
+ qc->qc_xmit[idx].qe_buf_len = -65;
+
+ qc->qc_xmit[idx].qe_addr_lo = LOWORD(sc->sc_pqedata->qc_setup);
+ qc->qc_xmit[idx].qe_addr_hi =
+ HIWORD(sc->sc_pqedata->qc_setup) | QE_SETUP | QE_EOMSG;
+ qc->qc_xmit[idx].qe_status1 = qc->qc_xmit[idx].qe_flag = QE_NOTYET;
+ qc->qc_xmit[idx].qe_addr_hi |= QE_VALID;
+
+ if (QE_RCSR(QE_CSR_CSR) & QE_XL_INVALID) {
+ QE_WCSR(QE_CSR_XMTL,
+ LOWORD(&sc->sc_pqedata->qc_xmit[idx]));
+ QE_WCSR(QE_CSR_XMTH,
+ HIWORD(&sc->sc_pqedata->qc_xmit[idx]));
}
-#endif /* NBPFILTER > 0 */
- if (m)
- ether_input((struct ifnet *)&sc->qe_if, eh, m);
+ sc->sc_inq++;
+ if (++sc->sc_nexttx == TXDESCS)
+ sc->sc_nexttx = 0;
+ splx(s);
}
/*
- * Watchdog timeout routine. There is a condition in the hardware that
- * causes the board to lock up under heavy load. This routine detects
- * the hang up and restarts the device.
+ * Check for dead transmit logic. Not uncommon.
*/
void
qetimeout(ifp)
struct ifnet *ifp;
{
- register struct qe_softc *sc = ifp->if_softc;
+ struct qe_softc *sc = ifp->if_softc;
-#ifdef notdef
- log(LOG_ERR, "%s: transmit timeout, restarted %d\n",
- sc->sc_dev.dv_xname, sc->qe_restarts++);
-#endif
- qerestart(sc);
-}
-/*
- * Restart for board lockup problem.
- */
-void
-qerestart(sc)
- struct qe_softc *sc;
-{
- register struct ifnet *ifp = (struct ifnet *)&sc->qe_if;
- register struct qedevice *addr = sc->addr;
- register struct qe_ring *rp;
- register i;
-
- addr->qe_csr = QE_RESET;
- addr->qe_csr &= ~QE_RESET;
- qesetup(sc);
- for (i = 0, rp = sc->tring; i < NXMT; rp++, i++) {
- rp->qe_flag = rp->qe_status1 = QE_NOTYET;
- rp->qe_valid = 0;
- }
- sc->nxmit = sc->otindex = sc->tindex = sc->rindex = 0;
- addr->qe_csr = QE_RCV_ENABLE | QE_INT_ENABLE | QE_XMIT_INT |
- QE_RCV_INT | QE_ILOOP;
- addr->qe_rcvlist_lo = (short)((int)sc->rringaddr);
- addr->qe_rcvlist_hi = (short)((int)sc->rringaddr >> 16);
- sc->qe_flags |= QEF_RUNNING;
- qestart(ifp);
+ if (sc->sc_inq == 0)
+ return;
+
+ printf("%s: xmit logic died, resetting...\n", sc->sc_dev.dv_xname);
+ /*
+ * Do a reset of interface, to get it going again.
+ * Will it work by just restart the transmit logic?
+ */
+ qeinit(sc);
}
diff --git a/sys/arch/vax/if/if_qereg.h b/sys/arch/vax/if/if_qereg.h
index bac037498c8..71e7429fdbb 100644
--- a/sys/arch/vax/if/if_qereg.h
+++ b/sys/arch/vax/if/if_qereg.h
@@ -1,5 +1,5 @@
-/* $OpenBSD: if_qereg.h,v 1.3 1997/09/10 08:28:42 maja Exp $ */
-/* $NetBSD: if_qereg.h,v 1.2 1997/05/15 20:10:23 ragge Exp $ */
+/* $OpenBSD: if_qereg.h,v 1.4 2000/04/27 03:14:43 bjc Exp $ */
+/* $NetBSD: if_qereg.h,v 1.5 1999/06/20 00:04:47 ragge Exp $ */
/*
* Copyright (c) 1988 Regents of the University of California.
* All rights reserved.
@@ -58,8 +58,8 @@
* *
* 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 *
+ * derivative copyright rights, appropriate copyright *
+ * legends may be placed on the derivative work in addition *
* to that set forth above. *
* *
****************************************************************/
@@ -76,6 +76,7 @@
/*
* Digital Q-BUS to NI Adapter
*/
+#ifdef notdef
struct qedevice {
u_short qe_sta_addr[2]; /* Station address (actually 6 */
u_short qe_rcvlist_lo; /* Receive list lo address */
@@ -85,6 +86,19 @@ struct qedevice {
u_short qe_vector; /* Interrupt vector */
u_short qe_csr; /* Command and Status Register */
};
+#endif
+
+/*
+ * Register offsets in register space.
+ */
+#define QE_CSR_ADDR1 0
+#define QE_CSR_ADDR2 2
+#define QE_CSR_RCLL 4
+#define QE_CSR_RCLH 6
+#define QE_CSR_XMTL 8
+#define QE_CSR_XMTH 10
+#define QE_CSR_VECTOR 12
+#define QE_CSR_CSR 14
/*
* Command and status bits (csr)
@@ -117,19 +131,22 @@ struct qedevice {
*/
struct qe_ring {
u_short qe_flag; /* Buffer utilization flags */
- u_short qe_addr_hi:6, /* Hi order bits of buffer addr */
- qe_odd_begin:1, /* Odd byte begin and end (xmit)*/
- qe_odd_end:1,
- qe_fill1:4,
- qe_setup:1, /* Setup packet */
- qe_eomsg:1, /* End of message flag */
- qe_chain:1, /* Chain address instead of buf */
- qe_valid:1; /* Address field is valid */
+ u_short qe_addr_hi;
u_short qe_addr_lo; /* Low order bits of address */
short qe_buf_len; /* Negative buffer length */
u_short qe_status1; /* Status word one */
u_short qe_status2; /* Status word two */
};
+
+/*
+ * High word address control bits.
+ */
+#define QE_VALID 0x8000
+#define QE_CHAIN 0x4000
+#define QE_EOMSG 0x2000
+#define QE_SETUP 0x1000
+#define QE_ODDEND 0x0080
+#define QE_ODDBEGIN 0x0040
/*
* Status word definations (receive)
@@ -175,6 +192,6 @@ struct qe_ring {
/*
* Values for the length of the setup packet that control reception filter.
*/
-#define QE_SOMEMULTI 128 /* Receive up to 12 multicasts */
-#define QE_ALLMULTI 129 /* Receive all multicasts */
-#define QE_PROMISC 130 /* Receive all packets */
+#define QE_SETUPLEN 128 /* Size of setup packet */
+#define QE_ALLMULTI 1 /* Receive all multicasts */
+#define QE_PROMISC 2 /* Receive all packets */
diff --git a/sys/arch/vax/if/if_uba.c b/sys/arch/vax/if/if_uba.c
index f0dd19c6051..34175ed4c18 100644
--- a/sys/arch/vax/if/if_uba.c
+++ b/sys/arch/vax/if/if_uba.c
@@ -1,5 +1,5 @@
-/* $OpenBSD: if_uba.c,v 1.5 1997/05/29 00:04:33 niklas Exp $ */
-/* $NetBSD: if_uba.c,v 1.12 1996/08/20 14:07:46 ragge Exp $ */
+/* $OpenBSD: if_uba.c,v 1.6 2000/04/27 03:14:43 bjc Exp $ */
+/* $NetBSD: if_uba.c,v 1.15 1999/01/01 21:43:18 ragge Exp $ */
/*
* Copyright (c) 1982, 1986, 1988 Regents of the University of California.
@@ -91,7 +91,7 @@ if_ubaminit(ifu, uh, hlen, nmr, ifr, nr, ifw, nw)
off = MCLBYTES - hlen;
else
off = 0;
- nclbytes = roundup(nmr * NBPG, MCLBYTES);
+ nclbytes = roundup(nmr * VAX_NBPG, MCLBYTES);
if (hlen)
nclbytes += MCLBYTES;
if (ifr[0].ifrw_addr)
@@ -159,7 +159,7 @@ if_ubaalloc(ifu, ifrw, nmr)
register int info;
info =
- uballoc(ifu->iff_softc, ifrw->ifrw_addr, nmr*NBPG + ifu->iff_hlen,
+ uballoc(ifu->iff_softc, ifrw->ifrw_addr, nmr*VAX_NBPG + ifu->iff_hlen,
ifu->iff_flags);
if (info == 0)
return (0);
@@ -238,16 +238,16 @@ if_ubaget(ifu, ifr, totlen, ifp)
pp = mtod(m, char *);
cpte = (struct pte *)kvtopte(cp);
ppte = (struct pte *)kvtopte(pp);
- x = btop(cp - ifr->ifrw_addr);
+ x = vax_btop(cp - ifr->ifrw_addr);
ip = (int *)&ifr->ifrw_mr[x];
- for (i = 0; i < MCLBYTES/NBPG; i++) {
+ for (i = 0; i < MCLBYTES/VAX_NBPG; i++) {
struct pte t;
t = *ppte; *ppte++ = *cpte; *cpte = t;
*ip++ = cpte++->pg_pfn|ifr->ifrw_proto;
mtpr(cp,PR_TBIS);
- cp += NBPG;
+ cp += VAX_NBPG;
mtpr((caddr_t)pp,PR_TBIS);
- pp += NBPG;
+ pp += VAX_NBPG;
}
goto nocopy;
}
@@ -290,7 +290,7 @@ rcv_xmtbuf(ifw)
{
register struct mbuf *m;
struct mbuf **mprev;
- register i;
+ register int i;
char *cp;
while ((i = ffs((long)ifw->ifw_xswapd)) != 0) {
@@ -319,7 +319,7 @@ static void
restor_xmtbuf(ifw)
register struct ifxmt *ifw;
{
- register i;
+ register int i;
for (i = 0; i < ifw->ifw_nmr; i++)
ifw->ifw_wmap[i] = ifw->ifw_mr[i];
@@ -353,11 +353,11 @@ if_ubaput(ifu, ifw, m)
int *ip;
pte = (struct pte *)kvtopte(dp);
- x = btop(cp - ifw->ifw_addr);
+ x = vax_btop(cp - ifw->ifw_addr);
ip = (int *)&ifw->ifw_mr[x];
- for (i = 0; i < MCLBYTES/NBPG; i++)
+ for (i = 0; i < MCLBYTES/VAX_NBPG; i++)
*ip++ = ifw->ifw_proto | pte++->pg_pfn;
- xswapd |= 1 << (x>>(MCLSHIFT-PGSHIFT));
+ xswapd |= 1 << (x>>(MCLSHIFT-VAX_PGSHIFT));
mp = m->m_next;
m->m_next = ifw->ifw_xtofree;
ifw->ifw_xtofree = m;
@@ -385,8 +385,8 @@ if_ubaput(ifu, ifw, m)
if (i >= x)
break;
ifw->ifw_xswapd &= ~(1<<i);
- i *= MCLBYTES/NBPG;
- for (t = 0; t < MCLBYTES/NBPG; t++) {
+ i *= MCLBYTES/VAX_NBPG;
+ for (t = 0; t < MCLBYTES/VAX_NBPG; t++) {
ifw->ifw_mr[i] = ifw->ifw_wmap[i];
i++;
}
diff --git a/sys/arch/vax/if/if_ze.c b/sys/arch/vax/if/if_ze.c
new file mode 100644
index 00000000000..66dbe4134a5
--- /dev/null
+++ b/sys/arch/vax/if/if_ze.c
@@ -0,0 +1,128 @@
+/* $OpenBSD: if_ze.c,v 1.1 2000/04/27 03:14:43 bjc Exp $ */
+/* $NetBSD: if_ze.c,v 1.3 2000/01/24 02:54:03 matt Exp $ */
+/*
+ * Copyright (c) 1999 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.
+ */
+
+#include <sys/param.h>
+#include <sys/socket.h>
+#include <sys/device.h>
+#include <sys/systm.h>
+#include <sys/sockio.h>
+
+#include <net/if.h>
+#include <net/if_dl.h>
+#include <netinet/in.h>
+#include <netinet/if_ether.h>
+
+#if NBPFILTER > 0
+#include <net/bpf.h>
+#include <net/bpfdesc.h>
+#endif
+
+#include <machine/bus.h>
+#include <machine/nexus.h>
+#include <machine/cpu.h>
+#include <machine/scb.h>
+
+#include <arch/vax/if/sgecreg.h>
+#include <arch/vax/if/sgecvar.h>
+
+/*
+ * Adresses.
+ */
+#define SGECADDR 0x20008000
+#define NISA_ROM 0x20084000
+#define SGECVEC 0x108
+
+static int zematch __P((struct device *, struct cfdata *, void *));
+static void zeattach __P((struct device *, struct device *, void *));
+
+struct cfattach ze_ibus_ca = {
+ sizeof(struct ze_softc), (cfmatch_t)zematch, zeattach
+};
+
+struct cfdriver ze_cd = {
+ NULL, "ze", DV_IFNET
+};
+
+/*
+ * Check for present SGEC.
+ */
+int
+zematch(parent, cf, aux)
+ struct device *parent;
+ struct cfdata *cf;
+ void *aux;
+{
+ struct bp_conf *bp = aux;
+
+ /*
+ * Should some more intelligent checking be done???
+ */
+ if (strcmp(bp->type, "sgec") == 0)
+ return 1;
+ return 0;
+}
+
+/*
+ * Interface exists: make available by filling in network interface
+ * record. System will initialize the interface when it is ready
+ * to accept packets.
+ */
+void
+zeattach(parent, self, aux)
+ struct device *parent, *self;
+ void *aux;
+{
+ extern struct vax_bus_dma_tag vax_bus_dma_tag;
+ struct ze_softc *sc = (struct ze_softc *)self;
+ int *ea, i;
+
+ /*
+ * Map in SGEC registers.
+ */
+ sc->sc_ioh = vax_map_physmem(SGECADDR, 1);
+ sc->sc_iot = 0; /* :-) */
+ sc->sc_dmat = &vax_bus_dma_tag;
+
+ sc->sc_intvec = SGECVEC;
+
+ /*
+ * Map in, read and release ethernet rom address.
+ */
+ ea = (int *)vax_map_physmem(NISA_ROM, 1);
+ for (i = 0; i < ETHER_ADDR_LEN; i++)
+ sc->sc_ac.ac_enaddr[i] = (ea[i] >> 8) & 0377;
+ vax_unmap_physmem((vaddr_t)ea, 1);
+
+ scb_vecalloc(SGECVEC, (void (*)(void *)) sgec_intr, sc, SCB_ISTACK);
+
+ sgec_attach(sc);
+}
diff --git a/sys/arch/vax/if/if_zereg.h b/sys/arch/vax/if/if_zereg.h
new file mode 100644
index 00000000000..99b1a2bdbaa
--- /dev/null
+++ b/sys/arch/vax/if/if_zereg.h
@@ -0,0 +1,222 @@
+/* $OpenBSD: if_zereg.h,v 1.1 2000/04/27 03:14:43 bjc Exp $ */
+/* $NetBSD: if_zereg.h,v 1.1 1998/07/01 10:52:10 ragge Exp $ */
+/*
+ * Copyright (c) 1988 Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Digital Equipment Corp.
+ *
+ * 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.
+ *
+ */
+
+
+/* Driver for SGEC (second generation Ethernet controller) chip, type DC-541,
+ found on the KA670 (and prob ably other) CPU.
+
+ 17 May 1998...Jay Maynard, jmaynard@phoenix.net
+*/
+
+/* SGEC CSRs */
+struct zedevice {
+ u_long ze_nicsr0; /* vector address, IPL, sync mode */
+ u_long ze_nicsr1; /* TX poll demand */
+ u_long ze_nicsr2; /* RX poll demand */
+ struct ze_rdes *ze_nicsr3; /* RX descriptor list address */
+ struct ze_tdes *ze_nicsr4; /* TX descriptor list address */
+ u_long ze_nicsr5; /* SGEC status */
+ u_long ze_nicsr6; /* SGEC command/mode */
+ u_long ze_nicsr7; /* system page table base address */
+ u_long ze_nivcsr8; /* reserved virtual CSR */
+ u_long ze_nivcsr9; /* watchdog timers (virtual) */
+ u_long ze_nivcsr10; /* revision, missed frame count (v) */
+ u_long ze_nivcsr11; /* boot message verification (low) (v) */
+ u_long ze_nivcsr12; /* boot message verification (high) (v) */
+ u_long ze_nivcsr13; /* boot message processor (v) */
+ u_long ze_nivcsr14; /* diagnostic breakpoint (v) */
+ u_long ze_nicsr15; /* monitor command */
+};
+
+/* SGEC bit definitions */
+/* NICSR0: */
+#define ZE_NICSR0_IPL 0xc0000000 /* interrupt priority level: */
+#define ZE_NICSR0_IPL14 0x00000000 /* 0x14 */
+#define ZE_NICSR0_IPL15 0x40000000 /* 0x15 */
+#define ZE_NICSR0_IPL16 0x80000000 /* 0x16 */
+#define ZE_NICSR0_IPL17 0xc0000000 /* 0x17 */
+#define ZE_NICSR0_SA 0x20000000 /* sync(1)/async mode */
+#define ZE_NICSR0_MBO 0x1fff0003 /* must be set to one on write */
+#define ZE_NICSR0_IV_MASK 0x0000fffc /* bits for the interrupt vector */
+
+/* NICSR1: */
+#define ZE_NICSR1_TXPD 0xffffffff /* transmit polling demand */
+
+/* NICSR2: */
+#define ZE_NICSR2_RXPD 0xffffffff /* receive polling demand */
+
+/* NICSR3 and NICSR4 are pure addresses */
+/* NICSR5: */
+#define ZE_NICSR5_ID 0x80000000 /* init done */
+#define ZE_NICSR5_SF 0x40000000 /* self-test failed */
+#define ZE_NICSR5_SS 0x3c000000 /* self-test status field */
+#define ZE_NICSR5_TS 0x03000000 /* transmission state: */
+#define ZE_NICSR5_TS_STOP 0x00000000 /* stopped */
+#define ZE_NICSR5_TS_RUN 0x01000000 /* running */
+#define ZE_NICSR5_TS_SUSP 0x02000000 /* suspended */
+#define ZE_NICSR5_RS 0x00c00000 /* reception state: */
+#define ZE_NICSR5_RS_STOP 0x00000000 /* stopped */
+#define ZE_NICSR5_RS_RUN 0x00400000 /* running */
+#define ZE_NICSR5_RS_SUSP 0x00800000 /* suspended */
+#define ZE_NICSR5_OM 0x00060000 /* operating mode: */
+#define ZE_NICSR5_OM_NORM 0x00000000 /* normal */
+#define ZE_NICSR5_OM_ILBK 0x00020000 /* internal loopback */
+#define ZE_NICSR5_OM_ELBK 0x00040000 /* external loopback */
+#define ZE_NICSR5_OM_DIAG 0x00060000 /* reserved for diags */
+#define ZE_NICSR5_DN 0x00010000 /* virtual CSR access done */
+#define ZE_NICSR5_MBO 0x0038ff00 /* must be one */
+#define ZE_NICSR5_BO 0x00000080 /* boot message received */
+#define ZE_NICSR5_TW 0x00000040 /* transmit watchdog timeout */
+#define ZE_NICSR5_RW 0x00000020 /* receive watchdog timeout */
+#define ZE_NICSR5_ME 0x00000010 /* memory error */
+#define ZE_NICSR5_RU 0x00000008 /* receive buffer unavailable */
+#define ZE_NICSR5_RI 0x00000004 /* receiver interrupt */
+#define ZE_NICSR5_TI 0x00000002 /* transmitter interrupt */
+#define ZE_NICSR5_IS 0x00000001 /* interrupt summary */
+/* whew! */
+
+/* NICSR6: */
+#define ZE_NICSR6_RE 0x80000000 /* reset */
+#define ZE_NICSR6_IE 0x40000000 /* interrupt enable */
+#define ZE_NICSR6_MBO 0x01e7f000 /* must be one */
+#define ZE_NICSR6_BL 0x1e000000 /* burst limit mask */
+#define ZE_NICSR6_BL_8 0x10000000 /* 8 longwords */
+#define ZE_NICSR6_BL_4 0x08000000 /* 4 longwords */
+#define ZE_NICSR6_BL_2 0x04000000 /* 2 longwords */
+#define ZE_NICSR6_BL_1 0x02000000 /* 1 longword */
+#define ZE_NICSR6_BE 0x00100000 /* boot message enable */
+#define ZE_NICSR6_SE 0x00080000 /* single cycle enable */
+#define ZE_NICSR6_ST 0x00000800 /* start(1)/stop(0) transmission */
+#define ZE_NICSR6_SR 0x00000400 /* start(1)/stop(0) reception */
+#define ZE_NICSR6_OM 0x00000300 /* operating mode: */
+#define ZE_NICSR6_OM_NORM 0x00000000 /* normal */
+#define ZE_NICSR6_OM_ILBK 0x00000100 /* internal loopback */
+#define ZE_NICSR6_OM_ELBK 0x00000200 /* external loopback */
+#define ZE_NICSR6_OM_DIAG 0x00000300 /* reserved for diags */
+#define ZE_NICSR6_DC 0x00000080 /* disable data chaining */
+#define ZE_NICSR6_FC 0x00000040 /* force collision mode */
+#define ZE_NICSR6_PB 0x00000008 /* pass bad frames */
+#define ZE_NICSR6_AF 0x00000006 /* address filtering mode: */
+#define ZE_NICSR6_AF_NORM 0x00000000 /* normal filtering */
+#define ZE_NICSR6_AF_PROM 0x00000002 /* promiscuous mode */
+#define ZE_NICSR6_AF_ALLM 0x00000004 /* all multicasts */
+
+/* NICSR7 is an address, NICSR8 is reserved */
+/* NICSR9: */
+#define ZE_VNICSR9_RT 0xffff0000 /* receiver timeout, *1.6 us */
+#define ZE_VNICSR9_TT 0x0000ffff /* transmitter timeout */
+
+/* NICSR10: */
+#define ZE_VNICSR10_RN 0x001f0000 /* SGEC version */
+#define ZE_VNICSR10_MFC 0x0000ffff /* missed frame counter */
+
+/* if you want to know what's in NICSRs 11-15, define them yourself! */
+
+/* Descriptors: */
+/* Receive descriptor */
+struct ze_rdes {
+ u_short ze_rdes0; /* descriptor word 0 flags */
+ u_short ze_framelen; /* received frame length */
+ u_char ze_rsvd1[3]; /* unused bytes */
+ u_char ze_rdes1; /* descriptor word 1 flags */
+ short ze_pageoffset; /* offset of buffer in page */
+ short ze_bufsize; /* length of data buffer */
+ u_char *ze_bufaddr; /* address of data buffer */
+};
+
+/* Receive descriptor bits */
+#define ZE_FRAMELEN_OW 0x8000 /* SGEC owns this descriptor */
+#define ZE_RDES0_ES 0x8000 /* an error has occurred */
+#define ZE_RDES0_LE 0x4000 /* length error */
+#define ZE_RDES0_DT 0x3000 /* data type: */
+#define ZE_RDES0_DT_NORM 0x0000 /* normal frame */
+#define ZE_RDES0_DT_ILBK 0x1000 /* internally looped back frame */
+#define ZE_RDES0_DT_ELBK 0x2000 /* externally looped back frame */
+#define ZE_RDES0_RF 0x0800 /* runt frame */
+#define ZE_RDES0_BO 0x0400 /* buffer overflow */
+#define ZE_RDES0_FS 0x0200 /* first segment */
+#define ZE_RDES0_LS 0x0100 /* last segment */
+#define ZE_RDES0_TL 0x0080 /* frame too long */
+#define ZE_RDES0_CS 0x0040 /* collision seen */
+#define ZE_RDES0_FT 0x0020 /* Ethernet frame type */
+#define ZE_RDES0_TN 0x0008 /* address translation not valid */
+#define ZE_RDES0_DB 0x0004 /* dribbling bits seen */
+#define ZE_RDES0_CE 0x0002 /* CRC error */
+#define ZE_RDES0_OF 0x0001 /* internal FIFO overflow */
+#define ZE_RDES1_CA 0x80 /* chain address */
+#define ZE_RDES1_VA 0x40 /* virtual address */
+#define ZE_RDES1_VT 0x20 /* virtual(1)/phys PTE address */
+
+/* Transmit descriptor */
+struct ze_tdes {
+ u_short ze_tdes0; /* descriptor word 0 flags */
+ u_short ze_tdr; /* TDR count of cable fault */
+ u_char ze_rsvd1[2]; /* unused bytes */
+ u_short ze_tdes1; /* descriptor word 1 flags */
+ short ze_pageoffset; /* offset of buffer in page */
+ short ze_bufsize; /* length of data buffer */
+ u_char *ze_bufaddr; /* address of data buffer */
+};
+
+/* Receive descriptor bits */
+#define ZE_TDR_OW 0x8000 /* SGEC owns this descriptor */
+#define ZE_TDES0_ES 0x8000 /* an error has occurred */
+#define ZE_TDES0_TO 0x4000 /* transmit watchdog timeout */
+#define ZE_TDES0_LE 0x1000 /* length error */
+#define ZE_TDES0_LO 0x0800 /* loss of carrier */
+#define ZE_TDES0_NC 0x0400 /* no carrier */
+#define ZE_TDES0_LC 0x0200 /* late collision */
+#define ZE_TDES0_EC 0x0100 /* excessive collisions */
+#define ZE_TDES0_HF 0x0080 /* heartbeat fail */
+#define ZE_TDES0_CC 0x0078 /* collision count mask */
+#define ZE_TDES0_TN 0x0004 /* address translation invalid */
+#define ZE_TDES0_UF 0x0002 /* underflow */
+#define ZE_TDES0_DE 0x0001 /* transmission deferred */
+#define ZE_TDES1_CA 0x8000 /* chain address */
+#define ZE_TDES1_VA 0x4000 /* virtual address */
+#define ZE_TDES1_DT 0x3000 /* data type: */
+#define ZE_TDES1_DT_NORM 0x0000 /* normal transmit frame */
+#define ZE_TDES1_DT_SETUP 0x2000 /* setup frame */
+#define ZE_TDES1_DT_DIAG 0x3000 /* diagnostic frame */
+#define ZE_TDES1_AC 0x0800 /* CRC disable */
+#define ZE_TDES1_FS 0x0400 /* first segment */
+#define ZE_TDES1_LS 0x0200 /* last segment */
+#define ZE_TDES1_IC 0x0100 /* interrupt on completion */
+#define ZE_TDES1_VT 0x0080 /* virtual(1)/phys PTE address */
+
diff --git a/sys/arch/vax/if/sgec.c b/sys/arch/vax/if/sgec.c
new file mode 100644
index 00000000000..254e742d82e
--- /dev/null
+++ b/sys/arch/vax/if/sgec.c
@@ -0,0 +1,752 @@
+/* $OpenBSD: sgec.c,v 1.1 2000/04/27 03:14:44 bjc Exp $ */
+/* $NetBSD: sgec.c,v 1.1 1999/08/08 11:41:29 ragge Exp $ */
+/*
+ * Copyright (c) 1999 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.
+ */
+
+/*
+ * Driver for the SGEC (Second Generation Ethernet Controller), sitting
+ * on for example the VAX 4000/300 (KA670).
+ *
+ * The SGEC looks like a mixture of the DEQNA and the TULIP. Fun toy.
+ *
+ * Even though the chip is capable to use virtual addresses (read the
+ * System Page Table directly) this driver doesn't do so, and there
+ * is no benefit in doing it either in NetBSD of today.
+ *
+ * Things that is still to do:
+ * Collect statistics.
+ * Use imperfect filtering when many multicast addresses.
+ */
+
+#include "bpfilter.h"
+
+#include <sys/param.h>
+#include <sys/mbuf.h>
+#include <sys/socket.h>
+#include <sys/device.h>
+#include <sys/systm.h>
+#include <sys/sockio.h>
+
+#include <net/if.h>
+#include <net/if_dl.h>
+
+#include <netinet/in.h>
+#include <netinet/if_ether.h>
+
+#if NBPFILTER > 0
+#include <net/bpf.h>
+#include <net/bpfdesc.h>
+#endif
+
+#include <machine/bus.h>
+
+#include <vax/if/sgecreg.h>
+#include <vax/if/sgecvar.h>
+
+static void zeinit __P((struct ze_softc *));
+static void zestart __P((struct ifnet *));
+static int zeioctl __P((struct ifnet *, u_long, caddr_t));
+static int ze_add_rxbuf __P((struct ze_softc *, int));
+static void ze_setup __P((struct ze_softc *));
+static void zetimeout __P((struct ifnet *));
+static int zereset __P((struct ze_softc *));
+
+#define ZE_WCSR(csr, val) \
+ bus_space_write_4(sc->sc_iot, sc->sc_ioh, csr, val)
+#define ZE_RCSR(csr) \
+ bus_space_read_4(sc->sc_iot, sc->sc_ioh, csr)
+
+/*
+ * Interface exists: make available by filling in network interface
+ * record. System will initialize the interface when it is ready
+ * to accept packets.
+ */
+void
+sgec_attach(sc)
+ struct ze_softc *sc;
+{
+ struct ifnet *ifp = (struct ifnet *)&sc->sc_if;
+ struct ze_tdes *tp;
+ struct ze_rdes *rp;
+ bus_dma_segment_t seg;
+ int i, rseg, error;
+
+ /*
+ * Allocate DMA safe memory for descriptors and setup memory.
+ */
+ if ((error = bus_dmamem_alloc(sc->sc_dmat,
+ sizeof(struct ze_cdata), NBPG, 0, &seg, 1, &rseg,
+ BUS_DMA_NOWAIT)) != 0) {
+ printf(": unable to allocate control data, error = %d\n",
+ error);
+ goto fail_0;
+ }
+
+ if ((error = bus_dmamem_map(sc->sc_dmat, &seg, rseg,
+ sizeof(struct ze_cdata), (caddr_t *)&sc->sc_zedata,
+ BUS_DMA_NOWAIT|BUS_DMA_COHERENT)) != 0) {
+ printf(": unable to map control data, error = %d\n", error);
+ goto fail_1;
+ }
+
+ if ((error = bus_dmamap_create(sc->sc_dmat,
+ sizeof(struct ze_cdata), 1,
+ sizeof(struct ze_cdata), 0, BUS_DMA_NOWAIT,
+ &sc->sc_cmap)) != 0) {
+ printf(": unable to create control data DMA map, error = %d\n",
+ error);
+ goto fail_2;
+ }
+
+ if ((error = bus_dmamap_load(sc->sc_dmat, sc->sc_cmap,
+ sc->sc_zedata, sizeof(struct ze_cdata), NULL,
+ BUS_DMA_NOWAIT)) != 0) {
+ printf(": unable to load control data DMA map, error = %d\n",
+ error);
+ goto fail_3;
+ }
+
+ /*
+ * Zero the newly allocated memory.
+ */
+ bzero(sc->sc_zedata, sizeof(struct ze_cdata));
+ /*
+ * Create the transmit descriptor DMA maps.
+ */
+ for (i = 0; i < TXDESCS; i++) {
+ if ((error = bus_dmamap_create(sc->sc_dmat, MCLBYTES,
+ 1, MCLBYTES, 0, BUS_DMA_NOWAIT|BUS_DMA_ALLOCNOW,
+ &sc->sc_xmtmap[i]))) {
+ printf(": unable to create tx DMA map %d, error = %d\n",
+ i, error);
+ goto fail_4;
+ }
+ }
+
+ /*
+ * Create receive buffer DMA maps.
+ */
+ for (i = 0; i < RXDESCS; i++) {
+ if ((error = bus_dmamap_create(sc->sc_dmat, MCLBYTES, 1,
+ MCLBYTES, 0, BUS_DMA_NOWAIT,
+ &sc->sc_rcvmap[i]))) {
+ printf(": unable to create rx DMA map %d, error = %d\n",
+ i, error);
+ goto fail_5;
+ }
+ }
+ /*
+ * Pre-allocate the receive buffers.
+ */
+ for (i = 0; i < RXDESCS; i++) {
+ if ((error = ze_add_rxbuf(sc, i)) != 0) {
+ printf(": unable to allocate or map rx buffer %d\n,"
+ " error = %d\n", i, error);
+ goto fail_6;
+ }
+ }
+
+ /*
+ * Create ring loops of the buffer chains.
+ * This is only done once.
+ */
+ sc->sc_pzedata = (struct ze_cdata *)sc->sc_cmap->dm_segs[0].ds_addr;
+
+ rp = sc->sc_zedata->zc_recv;
+ rp[RXDESCS].ze_framelen = ZE_FRAMELEN_OW;
+ rp[RXDESCS].ze_rdes1 = ZE_RDES1_CA;
+ rp[RXDESCS].ze_bufaddr = (char *)sc->sc_pzedata->zc_recv;
+
+ tp = sc->sc_zedata->zc_xmit;
+ tp[TXDESCS].ze_tdr = ZE_TDR_OW;
+ tp[TXDESCS].ze_tdes1 = ZE_TDES1_CA;
+ tp[TXDESCS].ze_bufaddr = (char *)sc->sc_pzedata->zc_xmit;
+
+ if (zereset(sc))
+ return;
+
+ strcpy(ifp->if_xname, sc->sc_dev.dv_xname);
+ ifp->if_softc = sc;
+ ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
+ ifp->if_start = zestart;
+ ifp->if_ioctl = zeioctl;
+ ifp->if_watchdog = zetimeout;
+
+ /*
+ * Attach the interface.
+ */
+ if_attach(ifp);
+ ether_ifattach(ifp);
+
+#if NBPFILTER > 0
+ bpfattach(&ifp->if_bpf, ifp, DLT_EN10MB, sizeof(struct ether_header));
+#endif
+ printf("\n%s: hardware address %s\n", sc->sc_dev.dv_xname,
+ ether_sprintf(sc->sc_ac.ac_enaddr));
+ return;
+
+ /*
+ * Free any resources we've allocated during the failed attach
+ * attempt. Do this in reverse order and fall through.
+ */
+ fail_6:
+ for (i = 0; i < RXDESCS; i++) {
+ if (sc->sc_rxmbuf[i] != NULL) {
+ bus_dmamap_unload(sc->sc_dmat, sc->sc_xmtmap[i]);
+ m_freem(sc->sc_rxmbuf[i]);
+ }
+ }
+ fail_5:
+ for (i = 0; i < RXDESCS; i++) {
+ if (sc->sc_xmtmap[i] != NULL)
+ bus_dmamap_destroy(sc->sc_dmat, sc->sc_xmtmap[i]);
+ }
+ fail_4:
+ for (i = 0; i < TXDESCS; i++) {
+ if (sc->sc_rcvmap[i] != NULL)
+ bus_dmamap_destroy(sc->sc_dmat, sc->sc_rcvmap[i]);
+ }
+ bus_dmamap_unload(sc->sc_dmat, sc->sc_cmap);
+ fail_3:
+ bus_dmamap_destroy(sc->sc_dmat, sc->sc_cmap);
+ fail_2:
+ bus_dmamem_unmap(sc->sc_dmat, (caddr_t)sc->sc_zedata,
+ sizeof(struct ze_cdata));
+ fail_1:
+ bus_dmamem_free(sc->sc_dmat, &seg, rseg);
+ fail_0:
+ return;
+}
+
+/*
+ * Initialization of interface.
+ */
+void
+zeinit(sc)
+ struct ze_softc *sc;
+{
+ struct ifnet *ifp = (struct ifnet *)&sc->sc_if;
+ struct ze_cdata *zc = sc->sc_zedata;
+ int i;
+
+ /*
+ * Reset the interface.
+ */
+ if (zereset(sc))
+ return;
+
+ sc->sc_nexttx = sc->sc_inq = sc->sc_lastack = 0;
+ /*
+ * Release and init transmit descriptors.
+ */
+ for (i = 0; i < TXDESCS; i++) {
+ if (sc->sc_txmbuf[i]) {
+ bus_dmamap_unload(sc->sc_dmat, sc->sc_xmtmap[i]);
+ m_freem(sc->sc_txmbuf[i]);
+ sc->sc_txmbuf[i] = 0;
+ }
+ zc->zc_xmit[i].ze_tdr = 0; /* Clear valid bit */
+ }
+
+
+ /*
+ * Init receive descriptors.
+ */
+ for (i = 0; i < RXDESCS; i++)
+ zc->zc_recv[i].ze_framelen = ZE_FRAMELEN_OW;
+ sc->sc_nextrx = 0;
+
+ ZE_WCSR(ZE_CSR6, ZE_NICSR6_IE|ZE_NICSR6_BL_8|ZE_NICSR6_ST|
+ ZE_NICSR6_SR|ZE_NICSR6_DC);
+
+ ifp->if_flags |= IFF_RUNNING;
+ ifp->if_flags &= ~IFF_OACTIVE;
+
+ /*
+ * Send a setup frame.
+ * This will start the transmit machinery as well.
+ */
+ ze_setup(sc);
+
+}
+
+/*
+ * Start output on interface.
+ */
+void
+zestart(ifp)
+ struct ifnet *ifp;
+{
+ struct ze_softc *sc = ifp->if_softc;
+ struct ze_cdata *zc = sc->sc_zedata;
+ paddr_t buffer;
+ struct mbuf *m, *m0;
+ int idx, len, s, i, totlen, error;
+ short orword;
+
+ s = splimp();
+ while (sc->sc_inq < (TXDESCS - 1)) {
+
+ if (sc->sc_setup) {
+ ze_setup(sc);
+ continue;
+ }
+ idx = sc->sc_nexttx;
+ IF_DEQUEUE(&sc->sc_if.if_snd, m);
+ if (m == 0)
+ goto out;
+ /*
+ * Count number of mbufs in chain.
+ * Always do DMA directly from mbufs, therefore the transmit
+ * ring is really big.
+ */
+ for (m0 = m, i = 0; m0; m0 = m0->m_next)
+ if (m0->m_len)
+ i++;
+ if (i >= TXDESCS)
+ panic("zestart"); /* XXX */
+
+ if ((i + sc->sc_inq) >= (TXDESCS - 1)) {
+ IF_PREPEND(&sc->sc_if.if_snd, m);
+ ifp->if_flags |= IFF_OACTIVE;
+ goto out;
+ }
+
+#if NBPFILTER > 0
+ if (ifp->if_bpf)
+ bpf_mtap(ifp->if_bpf, m);
+#endif
+ /*
+ * m now points to a mbuf chain that can be loaded.
+ * Loop around and set it.
+ */
+ totlen = 0;
+ for (m0 = m; m0; m0 = m0->m_next) {
+ error = bus_dmamap_load(sc->sc_dmat, sc->sc_xmtmap[idx],
+ mtod(m0, void *), m0->m_len, 0, 0);
+ buffer = sc->sc_xmtmap[idx]->dm_segs[0].ds_addr;
+ len = m0->m_len;
+ if (len == 0)
+ continue;
+
+ totlen += len;
+ /* Word alignment calc */
+ orword = 0;
+ if (totlen == len)
+ orword = ZE_TDES1_FS;
+ if (totlen == m->m_pkthdr.len) {
+ if (totlen < ETHER_ADDR_LEN)
+ len += (ETHER_ADDR_LEN - totlen);
+ orword |= ZE_TDES1_LS;
+ sc->sc_txmbuf[idx] = m;
+ }
+ zc->zc_xmit[idx].ze_bufsize = len;
+ zc->zc_xmit[idx].ze_bufaddr = (char *)buffer;
+ zc->zc_xmit[idx].ze_tdes1 = orword | ZE_TDES1_IC;
+ zc->zc_xmit[idx].ze_tdr = ZE_TDR_OW;
+
+ if (++idx == TXDESCS)
+ idx = 0;
+ sc->sc_inq++;
+ }
+#ifdef DIAGNOSTIC
+ if (totlen != m->m_pkthdr.len)
+ panic("zestart: len fault");
+#endif
+
+ /*
+ * Kick off the transmit logic, if it is stopped.
+ */
+ if ((ZE_RCSR(ZE_CSR5) & ZE_NICSR5_TS) != ZE_NICSR5_TS_RUN)
+ ZE_WCSR(ZE_CSR1, -1);
+ sc->sc_nexttx = idx;
+ }
+ if (sc->sc_inq == (TXDESCS - 1))
+ ifp->if_flags |= IFF_OACTIVE;
+
+out: if (sc->sc_inq)
+ ifp->if_timer = 5; /* If transmit logic dies */
+ splx(s);
+}
+
+int
+sgec_intr(sc)
+ struct ze_softc *sc;
+{
+ struct ze_cdata *zc = sc->sc_zedata;
+ struct ifnet *ifp = &sc->sc_if;
+ struct ether_header *eh;
+ struct mbuf *m;
+ int csr, len;
+
+ csr = ZE_RCSR(ZE_CSR5);
+ if ((csr & ZE_NICSR5_IS) == 0) /* Wasn't we */
+ return 0;
+ ZE_WCSR(ZE_CSR5, csr);
+
+ if (csr & ZE_NICSR5_RI)
+ while ((zc->zc_recv[sc->sc_nextrx].ze_framelen &
+ ZE_FRAMELEN_OW) == 0) {
+
+ m = sc->sc_rxmbuf[sc->sc_nextrx];
+ len = zc->zc_recv[sc->sc_nextrx].ze_framelen;
+ ze_add_rxbuf(sc, sc->sc_nextrx);
+ m->m_pkthdr.rcvif = ifp;
+ m->m_pkthdr.len = m->m_len = len;
+ if (++sc->sc_nextrx == RXDESCS)
+ sc->sc_nextrx = 0;
+ eh = mtod(m, struct ether_header *);
+#if NBPFILTER > 0
+ if (ifp->if_bpf) {
+ bpf_mtap(ifp->if_bpf, m);
+ if ((ifp->if_flags & IFF_PROMISC) != 0 &&
+ bcmp(sc->sc_ac.ac_enaddr, eh->ether_dhost,
+ ETHER_ADDR_LEN) != 0 &&
+ ((eh->ether_dhost[0] & 1) == 0)) {
+ m_freem(m);
+ continue;
+ }
+ }
+#endif
+ /*
+ * ALLMULTI means PROMISC in this driver.
+ */
+ if ((ifp->if_flags & IFF_ALLMULTI) &&
+ ((eh->ether_dhost[0] & 1) == 0) &&
+ bcmp(sc->sc_ac.ac_enaddr, eh->ether_dhost,
+ ETHER_ADDR_LEN)) {
+ m_freem(m);
+ continue;
+ }
+
+ /* m_adj() the ethernet header out of the way and pass up */
+ m_adj(m, sizeof(struct ether_header));
+ ether_input(ifp, eh, m);
+ }
+
+ if (csr & ZE_NICSR5_TI) {
+ while ((zc->zc_xmit[sc->sc_lastack].ze_tdr & ZE_TDR_OW) == 0) {
+ int idx = sc->sc_lastack;
+
+ if (sc->sc_lastack == sc->sc_nexttx)
+ break;
+ sc->sc_inq--;
+ if (++sc->sc_lastack == TXDESCS)
+ sc->sc_lastack = 0;
+
+ /* XXX collect statistics */
+ if ((zc->zc_xmit[idx].ze_tdes1 & ZE_TDES1_DT) ==
+ ZE_TDES1_DT_SETUP)
+ continue;
+ bus_dmamap_unload(sc->sc_dmat, sc->sc_xmtmap[idx]);
+ if (sc->sc_txmbuf[idx]) {
+ m_freem(sc->sc_txmbuf[idx]);
+ sc->sc_txmbuf[idx] = 0;
+ }
+ }
+ ifp->if_timer = 0;
+ ifp->if_flags &= ~IFF_OACTIVE;
+ zestart(ifp); /* Put in more in queue */
+ }
+ return 1;
+}
+
+/*
+ * Process an ioctl request.
+ */
+int
+zeioctl(ifp, cmd, data)
+ register struct ifnet *ifp;
+ u_long cmd;
+ caddr_t data;
+{
+ struct ze_softc *sc = ifp->if_softc;
+ struct ifreq *ifr = (struct ifreq *)data;
+ struct ifaddr *ifa = (struct ifaddr *)data;
+ int s = splnet(), error = 0;
+
+ switch (cmd) {
+
+ case SIOCSIFADDR:
+ ifp->if_flags |= IFF_UP;
+ switch(ifa->ifa_addr->sa_family) {
+#ifdef INET
+ case AF_INET:
+ zeinit(sc);
+ arp_ifinit(&sc->sc_ac, ifa);
+ break;
+#endif
+ }
+ break;
+
+ case SIOCSIFFLAGS:
+ if ((ifp->if_flags & IFF_UP) == 0 &&
+ (ifp->if_flags & IFF_RUNNING) != 0) {
+ /*
+ * If interface is marked down and it is running,
+ * stop it. (by disabling receive mechanism).
+ */
+ ZE_WCSR(ZE_CSR6, ZE_RCSR(ZE_CSR6) &
+ ~(ZE_NICSR6_ST|ZE_NICSR6_SR));
+ ifp->if_flags &= ~IFF_RUNNING;
+ } else if ((ifp->if_flags & IFF_UP) != 0 &&
+ (ifp->if_flags & IFF_RUNNING) == 0) {
+ /*
+ * If interface it marked up and it is stopped, then
+ * start it.
+ */
+ zeinit(sc);
+ } else if ((ifp->if_flags & IFF_UP) != 0) {
+ /*
+ * Send a new setup packet to match any new changes.
+ * (Like IFF_PROMISC etc)
+ */
+ ze_setup(sc);
+ }
+ break;
+
+ case SIOCADDMULTI:
+ case SIOCDELMULTI:
+ /*
+ * Update our multicast list.
+ */
+ error = (cmd == SIOCADDMULTI) ?
+ ether_addmulti(ifr, &sc->sc_ac):
+ ether_delmulti(ifr, &sc->sc_ac);
+
+ if (error == ENETRESET) {
+ /*
+ * Multicast list has changed; set the hardware filter
+ * accordingly.
+ */
+ ze_setup(sc);
+ error = 0;
+ }
+ break;
+
+ default:
+ error = EINVAL;
+
+ }
+ splx(s);
+ return (error);
+}
+
+/*
+ * Add a receive buffer to the indicated descriptor.
+ */
+int
+ze_add_rxbuf(sc, i)
+ struct ze_softc *sc;
+ int i;
+{
+ struct mbuf *m;
+ struct ze_rdes *rp;
+ int error;
+
+ MGETHDR(m, M_DONTWAIT, MT_DATA);
+ if (m == NULL)
+ return (ENOBUFS);
+
+ MCLGET(m, M_DONTWAIT);
+ if ((m->m_flags & M_EXT) == 0) {
+ m_freem(m);
+ return (ENOBUFS);
+ }
+
+ if (sc->sc_rxmbuf[i] != NULL)
+ bus_dmamap_unload(sc->sc_dmat, sc->sc_rcvmap[i]);
+
+ error = bus_dmamap_load(sc->sc_dmat, sc->sc_rcvmap[i],
+ m->m_ext.ext_buf, m->m_ext.ext_size, NULL, BUS_DMA_NOWAIT);
+ if (error)
+ panic("%s: can't load rx DMA map %d, error = %d\n",
+ sc->sc_dev.dv_xname, i, error);
+ sc->sc_rxmbuf[i] = m;
+
+ bus_dmamap_sync(sc->sc_dmat, sc->sc_rcvmap[i], 0,
+ sc->sc_rcvmap[i]->dm_mapsize, BUS_DMASYNC_PREREAD);
+
+ /*
+ * We know that the mbuf cluster is page aligned. Also, be sure
+ * that the IP header will be longword aligned.
+ */
+ m->m_data += 2;
+ rp = &sc->sc_zedata->zc_recv[i];
+ rp->ze_bufsize = (m->m_ext.ext_size - 2);
+ rp->ze_bufaddr = (char *)sc->sc_rcvmap[i]->dm_segs[0].ds_addr + 2;
+ rp->ze_framelen = ZE_FRAMELEN_OW;
+
+ return (0);
+}
+
+/*
+ * Create a setup packet and put in queue for sending.
+ */
+void
+ze_setup(sc)
+ struct ze_softc *sc;
+{
+ struct ether_multi *enm;
+ struct ether_multistep step;
+ struct ze_cdata *zc = sc->sc_zedata;
+ struct ifnet *ifp = &sc->sc_if;
+ u_int8_t *enaddr = sc->sc_ac.ac_enaddr;
+ int j, idx, s, reg;
+
+ s = splimp();
+ if (sc->sc_inq == (TXDESCS - 1)) {
+ sc->sc_setup = 1;
+ splx(s);
+ return;
+ }
+ sc->sc_setup = 0;
+ /*
+ * Init the setup packet with valid info.
+ */
+ memset(zc->zc_setup, 0xff, sizeof(zc->zc_setup)); /* Broadcast */
+ bcopy(enaddr, zc->zc_setup, ETHER_ADDR_LEN);
+
+ /*
+ * Multicast handling. The SGEC can handle up to 16 direct
+ * ethernet addresses.
+ */
+ j = 16;
+ ifp->if_flags &= ~IFF_ALLMULTI;
+ ETHER_FIRST_MULTI(step, &sc->sc_ac, enm);
+ while (enm != NULL) {
+ if (bcmp(enm->enm_addrlo, enm->enm_addrhi, 6)) {
+ ifp->if_flags |= IFF_ALLMULTI;
+ break;
+ }
+ bcopy(enm->enm_addrlo, &zc->zc_setup[j], ETHER_ADDR_LEN);
+ j += 8;
+ ETHER_NEXT_MULTI(step, enm);
+ if ((enm != NULL)&& (j == 128)) {
+ ifp->if_flags |= IFF_ALLMULTI;
+ break;
+ }
+ }
+
+ /*
+ * Fiddle with the receive logic.
+ */
+ reg = ZE_RCSR(ZE_CSR6);
+ DELAY(10);
+ ZE_WCSR(ZE_CSR6, reg & ~ZE_NICSR6_SR); /* Stop rx */
+ reg &= ~ZE_NICSR6_AF;
+ if (ifp->if_flags & IFF_PROMISC)
+ reg |= ZE_NICSR6_AF_PROM;
+ else if (ifp->if_flags & IFF_ALLMULTI)
+ reg |= ZE_NICSR6_AF_ALLM;
+ DELAY(10);
+ ZE_WCSR(ZE_CSR6, reg);
+ /*
+ * Only send a setup packet if needed.
+ */
+ if ((ifp->if_flags & (IFF_PROMISC|IFF_ALLMULTI)) == 0) {
+ idx = sc->sc_nexttx;
+ zc->zc_xmit[idx].ze_tdes1 = ZE_TDES1_DT_SETUP;
+ zc->zc_xmit[idx].ze_bufsize = 128;
+ zc->zc_xmit[idx].ze_bufaddr = sc->sc_pzedata->zc_setup;
+ zc->zc_xmit[idx].ze_tdr = ZE_TDR_OW;
+
+ if ((ZE_RCSR(ZE_CSR5) & ZE_NICSR5_TS) != ZE_NICSR5_TS_RUN)
+ ZE_WCSR(ZE_CSR1, -1);
+
+ sc->sc_inq++;
+ if (++sc->sc_nexttx == TXDESCS)
+ sc->sc_nexttx = 0;
+ }
+ splx(s);
+}
+
+/*
+ * Check for dead transmit logic.
+ */
+void
+zetimeout(ifp)
+ struct ifnet *ifp;
+{
+ struct ze_softc *sc = ifp->if_softc;
+
+ if (sc->sc_inq == 0)
+ return;
+
+ printf("%s: xmit logic died, resetting...\n", sc->sc_dev.dv_xname);
+ /*
+ * Do a reset of interface, to get it going again.
+ * Will it work by just restart the transmit logic?
+ */
+ zeinit(sc);
+}
+
+/*
+ * Reset chip:
+ * Set/reset the reset flag.
+ * Write interrupt vector.
+ * Write ring buffer addresses.
+ * Write SBR.
+ */
+int
+zereset(sc)
+ struct ze_softc *sc;
+{
+ int reg, i, s;
+
+ ZE_WCSR(ZE_CSR6, ZE_NICSR6_RE);
+ DELAY(50000);
+ if (ZE_RCSR(ZE_CSR6) & ZE_NICSR5_SF) {
+ printf("%s: selftest failed\n", sc->sc_dev.dv_xname);
+ return 1;
+ }
+
+ /*
+ * Get the vector that were set at match time, and remember it.
+ * WHICH VECTOR TO USE? Take one unused. XXX
+ * Funny way to set vector described in the programmers manual.
+ */
+ reg = ZE_NICSR0_IPL14 | sc->sc_intvec | 0x1fff0003; /* SYNC/ASYNC??? */
+ i = 10;
+ s = splimp();
+ do {
+ if (i-- == 0) {
+ printf("Failing SGEC CSR0 init\n");
+ splx(s);
+ return 1;
+ }
+ ZE_WCSR(ZE_CSR0, reg);
+ } while (ZE_RCSR(ZE_CSR0) != reg);
+ splx(s);
+
+ ZE_WCSR(ZE_CSR3, (vaddr_t)sc->sc_pzedata->zc_recv);
+ ZE_WCSR(ZE_CSR4, (vaddr_t)sc->sc_pzedata->zc_xmit);
+ return 0;
+}
diff --git a/sys/arch/vax/if/sgecreg.h b/sys/arch/vax/if/sgecreg.h
new file mode 100644
index 00000000000..c3a2090e314
--- /dev/null
+++ b/sys/arch/vax/if/sgecreg.h
@@ -0,0 +1,242 @@
+/* $OpenBSD: sgecreg.h,v 1.1 2000/04/27 03:14:44 bjc Exp $ */
+/* $NetBSD: sgecreg.h,v 1.1 1999/08/08 11:41:29 ragge Exp $ */
+/*
+ * Copyright (c) 1988 Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Digital Equipment Corp.
+ *
+ * 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.
+ *
+ */
+
+
+/* Driver for SGEC (second generation Ethernet controller) chip, type DC-541,
+ found on the KA670 (and prob ably other) CPU.
+
+ 17 May 1998...Jay Maynard, jmaynard@phoenix.net
+*/
+
+/* SGEC CSRs */
+struct zedevice {
+ u_long ze_nicsr0; /* vector address, IPL, sync mode */
+ u_long ze_nicsr1; /* TX poll demand */
+ u_long ze_nicsr2; /* RX poll demand */
+ struct ze_rdes *ze_nicsr3; /* RX descriptor list address */
+ struct ze_tdes *ze_nicsr4; /* TX descriptor list address */
+ u_long ze_nicsr5; /* SGEC status */
+ u_long ze_nicsr6; /* SGEC command/mode */
+ u_long ze_nicsr7; /* system page table base address */
+ u_long ze_nivcsr8; /* reserved virtual CSR */
+ u_long ze_nivcsr9; /* watchdog timers (virtual) */
+ u_long ze_nivcsr10; /* revision, missed frame count (v) */
+ u_long ze_nivcsr11; /* boot message verification (low) (v) */
+ u_long ze_nivcsr12; /* boot message verification (high) (v) */
+ u_long ze_nivcsr13; /* boot message processor (v) */
+ u_long ze_nivcsr14; /* diagnostic breakpoint (v) */
+ u_long ze_nicsr15; /* monitor command */
+};
+
+/*
+ * Register offsets.
+ */
+#define ZE_CSR0 0
+#define ZE_CSR1 4
+#define ZE_CSR2 8
+#define ZE_CSR3 12
+#define ZE_CSR4 16
+#define ZE_CSR5 20
+#define ZE_CSR6 24
+#define ZE_CSR7 28
+#define ZE_CSR8 32
+#define ZE_CSR9 36
+#define ZE_CSR10 40
+#define ZE_CSR11 44
+#define ZE_CSR12 48
+#define ZE_CSR13 52
+#define ZE_CSR14 56
+#define ZE_CSR15 60
+
+/* SGEC bit definitions */
+/* NICSR0: */
+#define ZE_NICSR0_IPL 0xc0000000 /* interrupt priority level: */
+#define ZE_NICSR0_IPL14 0x00000000 /* 0x14 */
+#define ZE_NICSR0_IPL15 0x40000000 /* 0x15 */
+#define ZE_NICSR0_IPL16 0x80000000 /* 0x16 */
+#define ZE_NICSR0_IPL17 0xc0000000 /* 0x17 */
+#define ZE_NICSR0_SA 0x20000000 /* sync(1)/async mode */
+#define ZE_NICSR0_MBO 0x1fff0003 /* must be set to one on write */
+#define ZE_NICSR0_IV_MASK 0x0000fffc /* bits for the interrupt vector */
+
+/* NICSR1: */
+#define ZE_NICSR1_TXPD 0xffffffff /* transmit polling demand */
+
+/* NICSR2: */
+#define ZE_NICSR2_RXPD 0xffffffff /* receive polling demand */
+
+/* NICSR3 and NICSR4 are pure addresses */
+/* NICSR5: */
+#define ZE_NICSR5_ID 0x80000000 /* init done */
+#define ZE_NICSR5_SF 0x40000000 /* self-test failed */
+#define ZE_NICSR5_SS 0x3c000000 /* self-test status field */
+#define ZE_NICSR5_TS 0x03000000 /* transmission state: */
+#define ZE_NICSR5_TS_STOP 0x00000000 /* stopped */
+#define ZE_NICSR5_TS_RUN 0x01000000 /* running */
+#define ZE_NICSR5_TS_SUSP 0x02000000 /* suspended */
+#define ZE_NICSR5_RS 0x00c00000 /* reception state: */
+#define ZE_NICSR5_RS_STOP 0x00000000 /* stopped */
+#define ZE_NICSR5_RS_RUN 0x00400000 /* running */
+#define ZE_NICSR5_RS_SUSP 0x00800000 /* suspended */
+#define ZE_NICSR5_OM 0x00060000 /* operating mode: */
+#define ZE_NICSR5_OM_NORM 0x00000000 /* normal */
+#define ZE_NICSR5_OM_ILBK 0x00020000 /* internal loopback */
+#define ZE_NICSR5_OM_ELBK 0x00040000 /* external loopback */
+#define ZE_NICSR5_OM_DIAG 0x00060000 /* reserved for diags */
+#define ZE_NICSR5_DN 0x00010000 /* virtual CSR access done */
+#define ZE_NICSR5_MBO 0x0038ff00 /* must be one */
+#define ZE_NICSR5_BO 0x00000080 /* boot message received */
+#define ZE_NICSR5_TW 0x00000040 /* transmit watchdog timeout */
+#define ZE_NICSR5_RW 0x00000020 /* receive watchdog timeout */
+#define ZE_NICSR5_ME 0x00000010 /* memory error */
+#define ZE_NICSR5_RU 0x00000008 /* receive buffer unavailable */
+#define ZE_NICSR5_RI 0x00000004 /* receiver interrupt */
+#define ZE_NICSR5_TI 0x00000002 /* transmitter interrupt */
+#define ZE_NICSR5_IS 0x00000001 /* interrupt summary */
+/* whew! */
+
+/* NICSR6: */
+#define ZE_NICSR6_RE 0x80000000 /* reset */
+#define ZE_NICSR6_IE 0x40000000 /* interrupt enable */
+#define ZE_NICSR6_MBO 0x01e7f000 /* must be one */
+#define ZE_NICSR6_BL 0x1e000000 /* burst limit mask */
+#define ZE_NICSR6_BL_8 0x10000000 /* 8 longwords */
+#define ZE_NICSR6_BL_4 0x08000000 /* 4 longwords */
+#define ZE_NICSR6_BL_2 0x04000000 /* 2 longwords */
+#define ZE_NICSR6_BL_1 0x02000000 /* 1 longword */
+#define ZE_NICSR6_BE 0x00100000 /* boot message enable */
+#define ZE_NICSR6_SE 0x00080000 /* single cycle enable */
+#define ZE_NICSR6_ST 0x00000800 /* start(1)/stop(0) transmission */
+#define ZE_NICSR6_SR 0x00000400 /* start(1)/stop(0) reception */
+#define ZE_NICSR6_OM 0x00000300 /* operating mode: */
+#define ZE_NICSR6_OM_NORM 0x00000000 /* normal */
+#define ZE_NICSR6_OM_ILBK 0x00000100 /* internal loopback */
+#define ZE_NICSR6_OM_ELBK 0x00000200 /* external loopback */
+#define ZE_NICSR6_OM_DIAG 0x00000300 /* reserved for diags */
+#define ZE_NICSR6_DC 0x00000080 /* disable data chaining */
+#define ZE_NICSR6_FC 0x00000040 /* force collision mode */
+#define ZE_NICSR6_PB 0x00000008 /* pass bad frames */
+#define ZE_NICSR6_AF 0x00000006 /* address filtering mode: */
+#define ZE_NICSR6_AF_NORM 0x00000000 /* normal filtering */
+#define ZE_NICSR6_AF_PROM 0x00000002 /* promiscuous mode */
+#define ZE_NICSR6_AF_ALLM 0x00000004 /* all multicasts */
+
+/* NICSR7 is an address, NICSR8 is reserved */
+/* NICSR9: */
+#define ZE_VNICSR9_RT 0xffff0000 /* receiver timeout, *1.6 us */
+#define ZE_VNICSR9_TT 0x0000ffff /* transmitter timeout */
+
+/* NICSR10: */
+#define ZE_VNICSR10_RN 0x001f0000 /* SGEC version */
+#define ZE_VNICSR10_MFC 0x0000ffff /* missed frame counter */
+
+/* if you want to know what's in NICSRs 11-15, define them yourself! */
+
+/* Descriptors: */
+/* Receive descriptor */
+struct ze_rdes {
+ u_short ze_rdes0; /* descriptor word 0 flags */
+ u_short ze_framelen; /* received frame length */
+ u_char ze_rsvd1[3]; /* unused bytes */
+ u_char ze_rdes1; /* descriptor word 1 flags */
+ short ze_pageoffset; /* offset of buffer in page */
+ short ze_bufsize; /* length of data buffer */
+ u_char *ze_bufaddr; /* address of data buffer */
+};
+
+/* Receive descriptor bits */
+#define ZE_FRAMELEN_OW 0x8000 /* SGEC owns this descriptor */
+#define ZE_RDES0_ES 0x8000 /* an error has occurred */
+#define ZE_RDES0_LE 0x4000 /* length error */
+#define ZE_RDES0_DT 0x3000 /* data type: */
+#define ZE_RDES0_DT_NORM 0x0000 /* normal frame */
+#define ZE_RDES0_DT_ILBK 0x1000 /* internally looped back frame */
+#define ZE_RDES0_DT_ELBK 0x2000 /* externally looped back frame */
+#define ZE_RDES0_RF 0x0800 /* runt frame */
+#define ZE_RDES0_BO 0x0400 /* buffer overflow */
+#define ZE_RDES0_FS 0x0200 /* first segment */
+#define ZE_RDES0_LS 0x0100 /* last segment */
+#define ZE_RDES0_TL 0x0080 /* frame too long */
+#define ZE_RDES0_CS 0x0040 /* collision seen */
+#define ZE_RDES0_FT 0x0020 /* Ethernet frame type */
+#define ZE_RDES0_TN 0x0008 /* address translation not valid */
+#define ZE_RDES0_DB 0x0004 /* dribbling bits seen */
+#define ZE_RDES0_CE 0x0002 /* CRC error */
+#define ZE_RDES0_OF 0x0001 /* internal FIFO overflow */
+#define ZE_RDES1_CA 0x80 /* chain address */
+#define ZE_RDES1_VA 0x40 /* virtual address */
+#define ZE_RDES1_VT 0x20 /* virtual(1)/phys PTE address */
+
+/* Transmit descriptor */
+struct ze_tdes {
+ u_short ze_tdes0; /* descriptor word 0 flags */
+ u_short ze_tdr; /* TDR count of cable fault */
+ u_char ze_rsvd1[2]; /* unused bytes */
+ u_short ze_tdes1; /* descriptor word 1 flags */
+ short ze_pageoffset; /* offset of buffer in page */
+ short ze_bufsize; /* length of data buffer */
+ u_char *ze_bufaddr; /* address of data buffer */
+};
+
+/* Receive descriptor bits */
+#define ZE_TDR_OW 0x8000 /* SGEC owns this descriptor */
+#define ZE_TDES0_ES 0x8000 /* an error has occurred */
+#define ZE_TDES0_TO 0x4000 /* transmit watchdog timeout */
+#define ZE_TDES0_LE 0x1000 /* length error */
+#define ZE_TDES0_LO 0x0800 /* loss of carrier */
+#define ZE_TDES0_NC 0x0400 /* no carrier */
+#define ZE_TDES0_LC 0x0200 /* late collision */
+#define ZE_TDES0_EC 0x0100 /* excessive collisions */
+#define ZE_TDES0_HF 0x0080 /* heartbeat fail */
+#define ZE_TDES0_CC 0x0078 /* collision count mask */
+#define ZE_TDES0_TN 0x0004 /* address translation invalid */
+#define ZE_TDES0_UF 0x0002 /* underflow */
+#define ZE_TDES0_DE 0x0001 /* transmission deferred */
+#define ZE_TDES1_CA 0x8000 /* chain address */
+#define ZE_TDES1_VA 0x4000 /* virtual address */
+#define ZE_TDES1_DT 0x3000 /* data type: */
+#define ZE_TDES1_DT_NORM 0x0000 /* normal transmit frame */
+#define ZE_TDES1_DT_SETUP 0x2000 /* setup frame */
+#define ZE_TDES1_DT_DIAG 0x3000 /* diagnostic frame */
+#define ZE_TDES1_AC 0x0800 /* CRC disable */
+#define ZE_TDES1_FS 0x0400 /* first segment */
+#define ZE_TDES1_LS 0x0200 /* last segment */
+#define ZE_TDES1_IC 0x0100 /* interrupt on completion */
+#define ZE_TDES1_VT 0x0080 /* virtual(1)/phys PTE address */
+
diff --git a/sys/arch/vax/if/sgecvar.h b/sys/arch/vax/if/sgecvar.h
new file mode 100644
index 00000000000..7cf93770817
--- /dev/null
+++ b/sys/arch/vax/if/sgecvar.h
@@ -0,0 +1,68 @@
+/* $OpenBSD: sgecvar.h,v 1.1 2000/04/27 03:14:44 bjc Exp $ */
+/* $NetBSD: sgecvar.h,v 1.1 1999/08/08 11:41:30 ragge Exp $ */
+/*
+ * Copyright (c) 1999 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.
+ */
+
+#define RXDESCS 30 /* # of receive descriptors */
+#define TXDESCS 60 /* # transmit descs */
+
+/*
+ * Descriptors must be an even number; optimisation thing.
+ */
+struct ze_cdata {
+ struct ze_rdes zc_recv[RXDESCS+2]; /* Receive descriptors */
+ struct ze_tdes zc_xmit[TXDESCS+2]; /* Transmit descriptors */
+ u_int8_t zc_setup[128]; /* Setup packet layout */
+};
+
+struct ze_softc {
+ struct device sc_dev; /* Configuration common part */
+ struct arpcom sc_ac; /* Ethernet common part */
+#define sc_if sc_ac.ac_if /* network-visible interface */
+ bus_space_tag_t sc_iot;
+ bus_addr_t sc_ioh;
+ bus_dma_tag_t sc_dmat;
+ struct ze_cdata *sc_zedata; /* Descriptor struct */
+ struct ze_cdata *sc_pzedata; /* Physical address of above */
+ bus_dmamap_t sc_cmap; /* Map for control structures */
+ struct mbuf* sc_txmbuf[TXDESCS];
+ struct mbuf* sc_rxmbuf[RXDESCS];
+ bus_dmamap_t sc_xmtmap[TXDESCS];
+ bus_dmamap_t sc_rcvmap[RXDESCS];
+ int sc_intvec; /* Interrupt vector */
+ int sc_nexttx;
+ int sc_inq;
+ int sc_lastack;
+ int sc_nextrx;
+ int sc_setup; /* Setup packet in queue */
+};
+
+void sgec_attach __P((struct ze_softc *));
+int sgec_intr __P((struct ze_softc *));
diff --git a/sys/arch/vax/mba/hp.c b/sys/arch/vax/mba/hp.c
index 633d6a04aa5..962b2c689ee 100644
--- a/sys/arch/vax/mba/hp.c
+++ b/sys/arch/vax/mba/hp.c
@@ -1,5 +1,5 @@
-/* $OpenBSD: hp.c,v 1.9 1998/10/03 21:18:59 millert Exp $ */
-/* $NetBSD: hp.c,v 1.15 1997/06/24 01:09:37 thorpej Exp $ */
+/* $OpenBSD: hp.c,v 1.10 2000/04/27 03:14:44 bjc Exp $ */
+/* $NetBSD: hp.c,v 1.22 2000/02/12 16:09:33 ragge Exp $ */
/*
* Copyright (c) 1996 Ludd, University of Lule}, Sweden.
* All rights reserved.
@@ -74,7 +74,7 @@ struct hp_softc {
int sc_physnr; /* Physical disk number */
};
-int hpmatch __P((struct device *, void *, void *));
+int hpmatch __P((struct device *, struct cfdata *, void *));
void hpattach __P((struct device *, struct device *, void *));
void hpstrategy __P((struct buf *));
void hpstart __P((struct mba_device *));
@@ -88,26 +88,25 @@ int hpread __P((dev_t, struct uio *));
int hpwrite __P((dev_t, struct uio *));
int hpsize __P((dev_t));
-struct cfdriver hp_cd = {
- NULL, "hp", DV_DISK
-};
-
struct cfattach hp_ca = {
sizeof(struct hp_softc), hpmatch, hpattach
};
+extern struct cfdriver hp_cd;
+
/*
* Check if this is a disk drive; done by checking type from mbaattach.
*/
int
-hpmatch(parent, match, aux)
+hpmatch(parent, cf, aux)
struct device *parent;
- void *match, *aux;
+ struct cfdata *cf;
+ void *aux;
{
- struct cfdata *cf = match;
struct mba_attach_args *ma = aux;
- if (cf->cf_loc[0] != -1 && cf->cf_loc[0] != ma->unit)
+ if (cf->cf_loc[MBACF_DRIVE] != MBACF_DRIVE_DEFAULT &&
+ cf->cf_loc[MBACF_DRIVE] != ma->unit)
return 0;
if (ma->devtyp != MB_RP)
@@ -134,6 +133,7 @@ hpattach(parent, self, aux)
/*
* Init the common struct for both the adapter and its slaves.
*/
+ BUFQ_INIT(&sc->sc_md.md_q);
sc->sc_md.md_softc = (void *)sc; /* Pointer to this softc */
sc->sc_md.md_mba = (void *)parent; /* Pointer to parent softc */
sc->sc_md.md_start = hpstart; /* Disk start routine */
@@ -163,7 +163,7 @@ hpattach(parent, self, aux)
* Read in label.
*/
if ((msg = readdisklabel(makedev(0, self->dv_unit * 8), hpstrategy,
- dl, NULL, 0)) != NULL)
+ dl, NULL)) != NULL)
printf(": %s", msg);
printf(": %s, size = %d sectors\n", dl->d_typename, dl->d_secperunit);
/*
@@ -181,18 +181,25 @@ hpstrategy(bp)
{
struct hp_softc *sc;
struct buf *gp;
- int unit, s;
+ int unit, s, err;
+ struct disklabel *lp;
unit = DISKUNIT(bp->b_dev);
sc = hp_cd.cd_devs[unit];
+ lp = sc->sc_disk.dk_label;
- if (bounds_check_with_label(bp, sc->sc_disk.dk_label,
- sc->sc_disk.dk_cpulabel, sc->sc_wlabel) <= 0)
+ err = bounds_check_with_label(bp, lp, sc->sc_wlabel);
+ if (err < 0)
goto done;
+
+ bp->b_rawblkno =
+ bp->b_blkno + lp->d_partitions[DISKPART(bp->b_dev)].p_offset;
+ bp->b_cylinder = bp->b_rawblkno / lp->d_secpercyl;
+
s = splbio();
- gp = sc->sc_md.md_q.b_actf;
- disksort(&sc->sc_md.md_q, bp);
+ gp = BUFQ_FIRST(&sc->sc_md.md_q);
+ disksort_cylinder(&sc->sc_md.md_q, bp);
if (gp == 0)
mbaqueue(&sc->sc_md);
@@ -215,9 +222,8 @@ hpstart(md)
struct mba_regs *mr = md->md_mba->sc_mbareg;
volatile struct hp_regs *hr;
struct disklabel *lp = sc->sc_disk.dk_label;
- struct buf *bp = md->md_q.b_actf;
+ struct buf *bp = BUFQ_FIRST(&md->md_q);
unsigned bn, cn, sn, tn;
- int part = DISKPART(bp->b_dev);
/*
* Collect statistics.
@@ -227,7 +233,7 @@ hpstart(md)
hr = (void *)&mr->mba_md[DISKUNIT(bp->b_dev)];
- bn = bp->b_blkno + lp->d_partitions[part].p_offset;
+ bn = bp->b_rawblkno;
if (bn) {
cn = bn / lp->d_secpercyl;
sn = bn % lp->d_secpercyl;
@@ -368,7 +374,7 @@ hpfinish(md, mbasr, attn)
int mbasr, *attn;
{
struct hp_softc *sc = md->md_softc;
- struct buf *bp = md->md_q.b_actf;
+ struct buf *bp = BUFQ_FIRST(&md->md_q);
volatile struct mba_regs *mr = md->md_mba->sc_mbareg;
volatile struct hp_regs *hr = (void *)&mr->mba_md[DISKUNIT(bp->b_dev)];
int er1, er2;
@@ -407,8 +413,8 @@ hper2:
printf("massbuss error :%s %x\n",
sc->sc_dev.dv_xname, mbasr);
- md->md_q.b_actf->b_resid = 0;
- disk_unbusy(&sc->sc_disk, md->md_q.b_actf->b_bcount);
+ BUFQ_FIRST(&md->md_q)->b_resid = 0;
+ disk_unbusy(&sc->sc_disk, BUFQ_FIRST(&md->md_q)->b_bcount);
return XFER_FINISH;
}
@@ -445,7 +451,8 @@ hpsize(dev)
return -1;
sc = hp_cd.cd_devs[unit];
- size = sc->sc_disk.dk_label->d_partitions[DISKPART(dev)].p_size;
+ size = sc->sc_disk.dk_label->d_partitions[DISKPART(dev)].p_size *
+ (sc->sc_disk.dk_label->d_secsize / DEV_BSIZE);
return size;
}
@@ -475,29 +482,3 @@ hpwrite(dev, uio)
{
return (physio(hpstrategy, NULL, dev, B_WRITE, minphys, uio));
}
-
-/*
- * Convert physical adapternr and unit to the unit number used by kernel.
- */
-int
-hp_getdev(mbanr, unit, uname)
- int mbanr, unit;
- char **uname;
-{
- struct mba_softc *ms;
- struct hp_softc *sc;
- int i;
-
- for (i = 0; i < hp_cd.cd_ndevs; i++) {
- if (hp_cd.cd_devs[i] == 0)
- continue;
-
- sc = hp_cd.cd_devs[i];
- ms = (void *)sc->sc_dev.dv_parent;
- 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 88e269579e9..d11ce0caaa5 100644
--- a/sys/arch/vax/mba/mba.c
+++ b/sys/arch/vax/mba/mba.c
@@ -1,5 +1,5 @@
-/* $OpenBSD: mba.c,v 1.5 1997/05/29 00:04:59 niklas Exp $ */
-/* $NetBSD: mba.c,v 1.10 1996/10/13 03:35:00 christos Exp $ */
+/* $OpenBSD: mba.c,v 1.6 2000/04/27 03:14:45 bjc Exp $ */
+/* $NetBSD: mba.c,v 1.18 2000/01/24 02:40:36 matt Exp $ */
/*
* Copyright (c) 1994, 1996 Ludd, University of Lule}, Sweden.
* All rights reserved.
@@ -54,6 +54,7 @@
#include <machine/pte.h>
#include <machine/pcb.h>
#include <machine/sid.h>
+#include <machine/cpu.h>
#include <vax/mba/mbareg.h>
#include <vax/mba/mbavar.h>
@@ -70,18 +71,14 @@ struct mbaunit mbaunit[] = {
{0, 0, 0}
};
-int mbamatch __P((struct device *, void *, void *));
+int mbamatch __P((struct device *, struct cfdata *, void *));
void mbaattach __P((struct device *, struct device *, void *));
-void mbaintr __P((int));
+void mbaintr __P((void *));
int mbaprint __P((void *, const char *));
void mbaqueue __P((struct mba_device *));
void mbastart __P((struct mba_softc *));
void mbamapregs __P((struct mba_softc *));
-struct cfdriver mba_cd = {
- NULL, "mba", DV_DULL
-};
-
struct cfattach mba_cmi_ca = {
sizeof(struct mba_softc), mbamatch, mbaattach
};
@@ -90,16 +87,18 @@ struct cfattach mba_sbi_ca = {
sizeof(struct mba_softc), mbamatch, mbaattach
};
+extern struct cfdriver mba_cd;
+
/*
* Look if this is a massbuss adapter.
*/
int
-mbamatch(parent, match, aux)
+mbamatch(parent, cf, aux)
struct device *parent;
- void *match, *aux;
+ struct cfdata *cf;
+ void *aux;
{
struct sbi_attach_args *sa = (struct sbi_attach_args *)aux;
- struct cfdata *cf = match;
if ((cf->cf_loc[0] != sa->nexnum) && (cf->cf_loc[0] > -1 ))
return 0;
@@ -123,22 +122,21 @@ mbaattach(parent, self, aux)
struct sbi_attach_args *sa = (struct sbi_attach_args *)aux;
volatile struct mba_regs *mbar = (struct mba_regs *)sa->nexaddr;
struct mba_attach_args ma;
- extern struct ivec_dsp idsptch;
int i, j;
printf("\n");
/*
* Set up interrupt vectors for this MBA.
*/
- bcopy(&idsptch, &sc->sc_dsp, sizeof(struct ivec_dsp));
+ sc->sc_dsp = idsptch;
+ sc->sc_dsp.pushlarg = sc;
+ sc->sc_dsp.hoppaddr = mbaintr;
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->sc_dsp;
- sc->sc_dsp.pushlarg = sc->sc_dev.dv_unit;
- sc->sc_dsp.hoppaddr = mbaintr;
sc->sc_physnr = sa->nexnum - 8; /* MBA's have TR between 8 - 11... */
-#ifdef VAX750
+#if VAX750
if (vax_cputype == VAX_750)
sc->sc_physnr += 4; /* ...but not on 11/750 */
#endif
@@ -171,9 +169,9 @@ mbaattach(parent, self, aux)
*/
void
mbaintr(mba)
- int mba;
+ void *mba;
{
- struct mba_softc *sc = mba_cd.cd_devs[mba];
+ struct mba_softc *sc = mba;
volatile struct mba_regs *mr = sc->sc_mbareg;
struct mba_device *md;
struct buf *bp;
@@ -189,7 +187,7 @@ mbaintr(mba)
return; /* During autoconfig */
md = sc->sc_first;
- bp = md->md_q.b_actf;
+ bp = BUFQ_FIRST(&md->md_q);
/*
* A data-transfer interrupt. Current operation is finished,
* call that device's finish routine to see what to do next.
@@ -206,13 +204,13 @@ mbaintr(mba)
* If more to transfer, start the adapter again
* by calling mbastart().
*/
- md->md_q.b_actf = bp->b_actf;
+ BUFQ_REMOVE(&md->md_q, bp);
sc->sc_first = md->md_back;
md->md_back = 0;
if (sc->sc_first == 0)
sc->sc_last = (void *)&sc->sc_first;
- if (md->md_q.b_actf) {
+ if (BUFQ_FIRST(&md->md_q) != NULL) {
sc->sc_last->md_back = md;
sc->sc_last = md;
}
@@ -287,12 +285,13 @@ mbastart(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 buf *bp = BUFQ_FIRST(&md->md_q);
- disk_reallymapin(md->md_q.b_actf, sc->sc_mbareg->mba_map, 0, PG_V);
+ disk_reallymapin(BUFQ_FIRST(&md->md_q), 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_var = ((u_int)bp->b_un.b_addr & VAX_PGOFSET);
mr->mba_bc = (~bp->b_bcount) + 1;
(*md->md_start)(md); /* machine-dependent start */
}
diff --git a/sys/arch/vax/mba/mbavar.h b/sys/arch/vax/mba/mbavar.h
index e2960d67880..cc1c59a5706 100644
--- a/sys/arch/vax/mba/mbavar.h
+++ b/sys/arch/vax/mba/mbavar.h
@@ -1,5 +1,5 @@
-/* $OpenBSD: mbavar.h,v 1.3 1997/05/29 00:05:00 niklas Exp $ */
-/* $NetBSD: mbavar.h,v 1.4 1996/04/08 18:39:01 ragge Exp $ */
+/* $OpenBSD: mbavar.h,v 1.4 2000/04/27 03:14:45 bjc Exp $ */
+/* $NetBSD: mbavar.h,v 1.5 2000/01/21 23:39:56 thorpej Exp $ */
/*
* Copyright (c) 1994 Ludd, University of Lule}, Sweden
* All rights reserved.
@@ -98,7 +98,7 @@ struct mba_device {
enum xfer_action (*md_finish) __P((struct mba_device *, int, int *));
void *md_softc; /* Backpointer to this units softc. */
struct mba_softc *md_mba;
- struct buf md_q; /* Buffer head for transfers */
+ struct buf_queue md_q; /* queue of I/O requests */
};
struct mba_softc {
diff --git a/sys/arch/vax/mscp/files.mscp b/sys/arch/vax/mscp/files.mscp
index fcf48862246..0791bca132a 100644
--- a/sys/arch/vax/mscp/files.mscp
+++ b/sys/arch/vax/mscp/files.mscp
@@ -1,19 +1,22 @@
-# $OpenBSD: files.mscp,v 1.2 1997/05/29 00:05:01 niklas Exp $
-# $NetBSD: files.mscp,v 1.1 1996/07/01 20:41:30 ragge Exp $
+# $OpenBSD: files.mscp,v 1.3 2000/04/27 03:14:45 bjc Exp $
+# $NetBSD: files.mscp,v 1.7 1999/06/06 19:16:18 ragge Exp $
#
# File and device description for MSCP devices.
#
define mscp {}
-file arch/vax/mscp/mscp.c
-file arch/vax/mscp/mscp_subr.c
+file arch/vax/mscp/mscp.c mscp
+file arch/vax/mscp/mscp_subr.c mscp
device mscpbus {drive = -1}
attach mscpbus at mscp
+device rx: disk
+attach rx at mscpbus
+
device ra: disk
attach ra at mscpbus
-file arch/vax/mscp/mscp_disk.c ra needs-flag
+file arch/vax/mscp/mscp_disk.c ra | rx needs-flag
device mt: tape
attach mt at mscpbus
diff --git a/sys/arch/vax/mscp/mscp.c b/sys/arch/vax/mscp/mscp.c
index 4d1821b29c6..09b46db5145 100644
--- a/sys/arch/vax/mscp/mscp.c
+++ b/sys/arch/vax/mscp/mscp.c
@@ -1,5 +1,5 @@
-/* $OpenBSD: mscp.c,v 1.3 1997/09/12 09:25:47 maja Exp $ */
-/* $NetBSD: mscp.c,v 1.6 1997/07/04 11:58:20 ragge Exp $ */
+/* $OpenBSD: mscp.c,v 1.4 2000/04/27 03:14:45 bjc Exp $ */
+/* $NetBSD: mscp.c,v 1.11 1999/06/06 19:16:18 ragge Exp $ */
/*
* Copyright (c) 1996 Ludd, University of Lule}, Sweden.
@@ -48,16 +48,16 @@
#include <sys/buf.h>
#include <sys/malloc.h>
#include <sys/device.h>
+#include <sys/proc.h>
+#include <sys/systm.h>
-#include <vax/mscp/mscp.h>
-#include <vax/mscp/mscpvar.h>
+#include <machine/bus.h>
-#define PCMD PSWP /* priority for command packet waits */
+#include <arch/vax/mscp/mscp.h>
+#include <arch/vax/mscp/mscpreg.h>
+#include <arch/vax/mscp/mscpvar.h>
-/*
- * During transfers, mapping info is saved in the buffer's b_resid.
- */
-#define b_info b_resid
+#define PCMD PSWP /* priority for command packet waits */
/*
* Get a command packet. Second argument is true iff we are
@@ -69,10 +69,10 @@ mscp_getcp(mi, canwait)
register struct mscp_softc *mi;
int canwait;
{
-#define mri (&mi->mi_cmd)
+#define mri (&mi->mi_cmd)
register struct mscp *mp;
register int i;
- int s = splbio();
+ int s = splimp();
again:
/*
@@ -115,8 +115,8 @@ again:
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;
+/*???*/ mp->mscp_sccc.sccc_errlgfl = 0;
+/*???*/ mp->mscp_sccc.sccc_copyspd = 0;
return (mp);
#undef mri
}
@@ -135,10 +135,11 @@ mscp_dorsp(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;
+ struct buf *bp;
+ struct mscp *mp;
+ struct mscp_xi *mxi;
+ int nextrsp;
+ int st, error;
extern int cold;
extern struct mscp slavereply;
@@ -239,7 +240,7 @@ loop:
case M_OP_ONLINE | M_OP_END:
/*
- * Finished an ON LINE request. Call the driver to
+ * Finished an ON LINE request. Call the driver to
* find out whether it succeeded. If so, mark it on
* line.
*/
@@ -291,6 +292,7 @@ loop:
case M_OP_POS | M_OP_END:
case M_OP_WRITM | M_OP_END:
+ case M_OP_AVAILABLE | M_OP_END:
/*
* A non-data transfer operation completed.
*/
@@ -300,33 +302,36 @@ loop:
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
+ * 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).
*/
rwend:
#ifdef DIAGNOSTIC
- if (mp->mscp_cmdref == 0) {
+ if (mp->mscp_cmdref >= NCMD) {
/*
* No buffer means there is a bug somewhere!
*/
- printf("%s: io done, but no buffer?\n",
+ printf("%s: io done, but bad xfer number?\n",
drive->dv_xname);
mscp_hexdump(mp);
break;
}
#endif
- bp = (struct buf *) mp->mscp_cmdref;
if (mp->mscp_cmdref == -1) {
(*me->me_cmddone)(drive, mp);
break;
}
+ mxi = &mi->mi_xi[mp->mscp_cmdref];
+ if (mxi->mxi_inuse == 0)
+ panic("mxi not inuse");
+ bp = mxi->mxi_bp;
/*
* Mark any error-due-to-bad-LBN (via `goto rwend').
- * WHAT STATUS WILL THESE HAVE? IT SURE WOULD BE NICE
+ * WHAT STATUS WILL THESE HAVE? IT SURE WOULD BE NICE
* IF DEC SOLD DOCUMENTATION FOR THEIR OWN CONTROLLERS.
*/
if (error) {
@@ -340,11 +345,6 @@ rwend:
}
/*
- * 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.
@@ -379,12 +379,14 @@ rwend:
* 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;
+ bus_dmamap_unload(mi->mi_dmat, mxi->mxi_dmam);
- (*mc->mc_ctlrdone)(mi->mi_dev.dv_parent, info);
+ (*mc->mc_ctlrdone)(mi->mi_dev.dv_parent);
(*me->me_iodone)(drive, bp);
out:
+ mxi->mxi_inuse = 0;
+ mi->mi_mxiuse |= (1 << mp->mscp_cmdref);
break;
case M_OP_REPLACE | M_OP_END:
@@ -414,18 +416,13 @@ unknown:
/*
* 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
+ * 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:
@@ -447,67 +444,6 @@ 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
+ panic("mscp_requeue");
}
diff --git a/sys/arch/vax/mscp/mscp.h b/sys/arch/vax/mscp/mscp.h
index ffae864af27..1c74b6f7388 100644
--- a/sys/arch/vax/mscp/mscp.h
+++ b/sys/arch/vax/mscp/mscp.h
@@ -1,5 +1,5 @@
-/* $OpenBSD: mscp.h,v 1.3 1997/09/12 09:25:51 maja Exp $ */
-/* $NetBSD: mscp.h,v 1.3 1997/07/04 11:58:21 ragge Exp $ */
+/* $OpenBSD: mscp.h,v 1.4 2000/04/27 03:14:46 bjc Exp $ */
+/* $NetBSD: mscp.h,v 1.6 1999/05/29 19:11:16 ragge Exp $ */
/*
* Copyright (c) 1988 Regents of the University of California.
@@ -48,178 +48,178 @@
/*
* Control message opcodes
*/
-#define M_OP_ABORT 0x01 /* Abort command */
-#define M_OP_GETCMDST 0x02 /* Get command status command */
-#define M_OP_GETUNITST 0x03 /* Get unit status command */
-#define M_OP_SETCTLRC 0x04 /* Set controller characteristics command */
-#define M_OP_SEREX 0x07 /* Serious exception end message */
-#define M_OP_AVAILABLE 0x08 /* Available command */
-#define M_OP_ONLINE 0x09 /* Online command */
-#define M_OP_SETUNITC 0x0a /* Set unit characteristics command */
-#define M_OP_DTACCPATH 0x0b /* Determine access paths command */
-#define M_OP_ACCESS 0x10 /* Access command */
-#define M_OP_COMPCD 0x11 /* Compare controller data command */
-#define M_OP_ERASE 0x12 /* Erase command */
-#define M_OP_FLUSH 0x13 /* Flush command */
-#define M_OP_REPLACE 0x14 /* Replace command */
-#define M_OP_COMPHD 0x20 /* Compare host data command */
-#define M_OP_READ 0x21 /* Read command */
-#define M_OP_WRITE 0x22 /* Write command */
-#define M_OP_WRITM 0x24 /* Write mark command */
-#define M_OP_POS 0x25 /* Positioning command */
-#define M_OP_AVAILATTN 0x40 /* Available attention message */
-#define M_OP_DUPUNIT 0x41 /* Duplicate unit number attention message */
-#define M_OP_ACCPATH 0x42 /* Access path attention message */
-#define M_OP_END 0x80 /* End message flag */
+#define M_OP_ABORT 0x01 /* Abort command */
+#define M_OP_GETCMDST 0x02 /* Get command status command */
+#define M_OP_GETUNITST 0x03 /* Get unit status command */
+#define M_OP_SETCTLRC 0x04 /* Set controller characteristics command */
+#define M_OP_SEREX 0x07 /* Serious exception end message */
+#define M_OP_AVAILABLE 0x08 /* Available command */
+#define M_OP_ONLINE 0x09 /* Online command */
+#define M_OP_SETUNITC 0x0a /* Set unit characteristics command */
+#define M_OP_DTACCPATH 0x0b /* Determine access paths command */
+#define M_OP_ACCESS 0x10 /* Access command */
+#define M_OP_COMPCD 0x11 /* Compare controller data command */
+#define M_OP_ERASE 0x12 /* Erase command */
+#define M_OP_FLUSH 0x13 /* Flush command */
+#define M_OP_REPLACE 0x14 /* Replace command */
+#define M_OP_COMPHD 0x20 /* Compare host data command */
+#define M_OP_READ 0x21 /* Read command */
+#define M_OP_WRITE 0x22 /* Write command */
+#define M_OP_WRITM 0x24 /* Write mark command */
+#define M_OP_POS 0x25 /* Positioning command */
+#define M_OP_AVAILATTN 0x40 /* Available attention message */
+#define M_OP_DUPUNIT 0x41 /* Duplicate unit number attention message */
+#define M_OP_ACCPATH 0x42 /* Access path attention message */
+#define M_OP_END 0x80 /* End message flag */
/*
* Generic command modifiers
*/
-#define M_MD_EXPRS 0x8000 /* Express request */
-#define M_MD_COMP 0x4000 /* Compare */
-#define M_MD_CLSEX 0x2000 /* Clear serious exception */
-#define M_MD_ERROR 0x1000 /* Force error */
-#define M_MD_SCCHH 0x0800 /* Suppress caching (high speed) */
-#define M_MD_SCCHL 0x0400 /* Suppress caching (low speed) */
-#define M_MD_SECOR 0x0200 /* Suppress error correction */
-#define M_MD_SEREC 0x0100 /* Suppress error recovery */
-#define M_MD_SSHDW 0x0080 /* Suppress shadowing */
-#define M_MD_WBKNV 0x0040 /* Write back (non-volatile) */
-#define M_MD_WBKVL 0x0020 /* Write back (volatile) */
-#define M_MD_WRSEQ 0x0010 /* Write shadow set one unit at a time */
+#define M_MD_EXPRS 0x8000 /* Express request */
+#define M_MD_COMP 0x4000 /* Compare */
+#define M_MD_CLSEX 0x2000 /* Clear serious exception */
+#define M_MD_ERROR 0x1000 /* Force error */
+#define M_MD_SCCHH 0x0800 /* Suppress caching (high speed) */
+#define M_MD_SCCHL 0x0400 /* Suppress caching (low speed) */
+#define M_MD_SECOR 0x0200 /* Suppress error correction */
+#define M_MD_SEREC 0x0100 /* Suppress error recovery */
+#define M_MD_SSHDW 0x0080 /* Suppress shadowing */
+#define M_MD_WBKNV 0x0040 /* Write back (non-volatile) */
+#define M_MD_WBKVL 0x0020 /* Write back (volatile) */
+#define M_MD_WRSEQ 0x0010 /* Write shadow set one unit at a time */
/*
* tape command modifiers
*/
-#define M_MD_IMMEDIATE 0x0040 /* Immediate completion */
-#define M_MD_UNLOAD 0x0010 /* Unload tape */
-#define M_MD_REVERSE 0x0008 /* Reverse action */
-#define M_MD_OBJCOUNT 0x0004 /* Object count */
-#define M_MD_REWIND 0x0002 /* Rewind */
+#define M_MD_IMMEDIATE 0x0040 /* Immediate completion */
+#define M_MD_UNLOAD 0x0010 /* Unload tape */
+#define M_MD_REVERSE 0x0008 /* Reverse action */
+#define M_MD_OBJCOUNT 0x0004 /* Object count */
+#define M_MD_REWIND 0x0002 /* Rewind */
/*
* AVAILABLE command modifiers
*/
-#define M_AVM_ALLCD 0x0002 /* All class drivers */
-#define M_AVM_SPINDOWN 0x0001 /* Spin down */
+#define M_AVM_ALLCD 0x0002 /* All class drivers */
+#define M_AVM_SPINDOWN 0x0001 /* Spin down */
/*
* FLUSH command modifiers
*/
-#define M_FLM_FLUSHENU 0x0001 /* Flush entire unit */
-#define M_FLM_VOLATILE 0x0002 /* Volatile only */
+#define M_FLM_FLUSHENU 0x0001 /* Flush entire unit */
+#define M_FLM_VOLATILE 0x0002 /* Volatile only */
/*
* GET UNIT STATUS command modifiers
*/
-#define M_GUM_NEXTUNIT 0x0001 /* Next unit */
+#define M_GUM_NEXTUNIT 0x0001 /* Next unit */
/*
* ONLINE command modifiers
*/
-#define M_OLM_RIP 0x0001 /* Allow self destruction */
-#define M_OLM_IGNMF 0x0002 /* Ignore media format error */
+#define M_OLM_RIP 0x0001 /* Allow self destruction */
+#define M_OLM_IGNMF 0x0002 /* Ignore media format error */
/*
* ONLINE and SET UNIT CHARACTERISTICS command modifiers
*/
-#define M_OSM_ALTERHI 0x0020 /* Alter host identifier */
-#define M_OSM_SHADOWSP 0x0010 /* Shadow unit specified */
-#define M_OSM_CLEARWBL 0x0008 /* Clear write-back data lost */
-#define M_OSM_SETWRPROT 0x0004 /* Set write protect */
+#define M_OSM_ALTERHI 0x0020 /* Alter host identifier */
+#define M_OSM_SHADOWSP 0x0010 /* Shadow unit specified */
+#define M_OSM_CLEARWBL 0x0008 /* Clear write-back data lost */
+#define M_OSM_SETWRPROT 0x0004 /* Set write protect */
/*
* REPLACE command modifiers
*/
-#define M_RPM_PRIMARY 0x0001 /* Primary replacement block */
+#define M_RPM_PRIMARY 0x0001 /* Primary replacement block */
/*
* End message flags
*/
-#define M_EF_BBLKR 0x80 /* Bad block reported */
-#define M_EF_BBLKU 0x40 /* Bad block unreported */
-#define M_EF_ERLOG 0x20 /* Error log generated */
-#define M_EF_SEREX 0x10 /* Serious exception */
-#define M_EF_EOT 0x08 /* at end-of-tape */
-#define M_EF_POSLOST 0x04 /* position lost */
+#define M_EF_BBLKR 0x80 /* Bad block reported */
+#define M_EF_BBLKU 0x40 /* Bad block unreported */
+#define M_EF_ERLOG 0x20 /* Error log generated */
+#define M_EF_SEREX 0x10 /* Serious exception */
+#define M_EF_EOT 0x08 /* at end-of-tape */
+#define M_EF_POSLOST 0x04 /* position lost */
/*
* Controller flags
*/
-#define M_CF_ATTN 0x80 /* Enable attention messages */
-#define M_CF_MISC 0x40 /* Enable miscellaneous error log messages */
-#define M_CF_OTHER 0x20 /* Enable other host's error log messages */
-#define M_CF_THIS 0x10 /* Enable this host's error log messages */
-#define M_CF_MLTHS 0x04 /* Multi-host */
-#define M_CF_SHADW 0x02 /* Shadowing */
-#define M_CF_576 0x01 /* 576 byte sectors */
+#define M_CF_ATTN 0x80 /* Enable attention messages */
+#define M_CF_MISC 0x40 /* Enable miscellaneous error log messages */
+#define M_CF_OTHER 0x20 /* Enable other host's error log messages */
+#define M_CF_THIS 0x10 /* Enable this host's error log messages */
+#define M_CF_MLTHS 0x04 /* Multi-host */
+#define M_CF_SHADW 0x02 /* Shadowing */
+#define M_CF_576 0x01 /* 576 byte sectors */
/*
* Unit flags
*/
-#define M_UF_REPLC 0x8000 /* Controller initiated bad block replacement */
-#define M_UF_INACT 0x4000 /* Inactive shadow set unit */
-#define M_UF_WRTPH 0x2000 /* Write protect (hardware) */
-#define M_UF_WRTPS 0x1000 /* Write protect (software or volume) */
-#define M_UF_SCCHH 0x8000 /* Suppress caching (high speed) */
-#define M_UF_SCCHL 0x4000 /* Suppress caching (low speed) */
-#define M_UF_RMVBL 0x0080 /* Removable media */
-#define M_UF_WBKNV 0x0040 /* Write back (non-volatile) */
-#define M_UF_576 0x0004 /* 576 byte sectors */
-#define M_UF_CMPWR 0x0002 /* Compare writes */
-#define M_UF_CMPRD 0x0001 /* Compare reads */
+#define M_UF_REPLC 0x8000 /* Controller initiated bad block replacement */
+#define M_UF_INACT 0x4000 /* Inactive shadow set unit */
+#define M_UF_WRTPH 0x2000 /* Write protect (hardware) */
+#define M_UF_WRTPS 0x1000 /* Write protect (software or volume) */
+#define M_UF_SCCHH 0x8000 /* Suppress caching (high speed) */
+#define M_UF_SCCHL 0x4000 /* Suppress caching (low speed) */
+#define M_UF_RMVBL 0x0080 /* Removable media */
+#define M_UF_WBKNV 0x0040 /* Write back (non-volatile) */
+#define M_UF_576 0x0004 /* 576 byte sectors */
+#define M_UF_CMPWR 0x0002 /* Compare writes */
+#define M_UF_CMPRD 0x0001 /* Compare reads */
/*
* Error Log message format codes
*/
-#define M_FM_CTLRERR 0x00 /* Controller error */
-#define M_FM_BUSADDR 0x01 /* Host memory access error */
-#define M_FM_DISKTRN 0x02 /* Disk transfer error */
-#define M_FM_SDI 0x03 /* SDI error */
-#define M_FM_SMLDSK 0x04 /* Small disk error */
-#define M_FM_TAPETRN 0x05 /* Tape transfer error */
-#define M_FM_STIERR 0x06 /* STI communication or command failure */
-#define M_FM_STIDEL 0x07 /* STI drive error log */
-#define M_FM_STIFEL 0x08 /* STI formatter error log */
+#define M_FM_CTLRERR 0x00 /* Controller error */
+#define M_FM_BUSADDR 0x01 /* Host memory access error */
+#define M_FM_DISKTRN 0x02 /* Disk transfer error */
+#define M_FM_SDI 0x03 /* SDI error */
+#define M_FM_SMLDSK 0x04 /* Small disk error */
+#define M_FM_TAPETRN 0x05 /* Tape transfer error */
+#define M_FM_STIERR 0x06 /* STI communication or command failure */
+#define M_FM_STIDEL 0x07 /* STI drive error log */
+#define M_FM_STIFEL 0x08 /* STI formatter error log */
/*
* Error Log message flags
*/
-#define M_LF_SUCC 0x80 /* Operation successful */
-#define M_LF_CONT 0x40 /* Operation continuing */
-#define M_LF_SQNRS 0x01 /* Sequence number reset */
+#define M_LF_SUCC 0x80 /* Operation successful */
+#define M_LF_CONT 0x40 /* Operation continuing */
+#define M_LF_SQNRS 0x01 /* Sequence number reset */
/*
* Status codes
*/
-#define M_ST_MASK 0x1f /* Status code mask */
-#define M_ST_SUCCESS 0x00 /* Success */
-#define M_ST_INVALCMD 0x01 /* Invalid command */
-#define M_ST_ABORTED 0x02 /* Command aborted */
-#define M_ST_OFFLINE 0x03 /* Unit offline */
-#define M_ST_AVAILABLE 0x04 /* Unit available */
-#define M_ST_MFMTERR 0x05 /* Media format error */
-#define M_ST_WRPROT 0x06 /* Write protected */
-#define M_ST_COMPERR 0x07 /* Compare error */
-#define M_ST_DATAERR 0x08 /* Data error */
-#define M_ST_HOSTBUFERR 0x09 /* Host buffer access error */
-#define M_ST_CTLRERR 0x0a /* Controller error */
-#define M_ST_DRIVEERR 0x0b /* Drive error */
-#define M_ST_FORMATTERR 0x0c /* Formatter error */
-#define M_ST_BOT 0x0d /* Beginning-of-tape */
-#define M_ST_TAPEMARK 0x0e /* Tape mark encountered */
-#define M_ST_RDTRUNC 0x10 /* Record data truncated */
-#define M_ST_DIAG 0x1f /* Message from an internal diagnostic */
+#define M_ST_MASK 0x1f /* Status code mask */
+#define M_ST_SUCCESS 0x00 /* Success */
+#define M_ST_INVALCMD 0x01 /* Invalid command */
+#define M_ST_ABORTED 0x02 /* Command aborted */
+#define M_ST_OFFLINE 0x03 /* Unit offline */
+#define M_ST_AVAILABLE 0x04 /* Unit available */
+#define M_ST_MFMTERR 0x05 /* Media format error */
+#define M_ST_WRPROT 0x06 /* Write protected */
+#define M_ST_COMPERR 0x07 /* Compare error */
+#define M_ST_DATAERR 0x08 /* Data error */
+#define M_ST_HOSTBUFERR 0x09 /* Host buffer access error */
+#define M_ST_CTLRERR 0x0a /* Controller error */
+#define M_ST_DRIVEERR 0x0b /* Drive error */
+#define M_ST_FORMATTERR 0x0c /* Formatter error */
+#define M_ST_BOT 0x0d /* Beginning-of-tape */
+#define M_ST_TAPEMARK 0x0e /* Tape mark encountered */
+#define M_ST_RDTRUNC 0x10 /* Record data truncated */
+#define M_ST_DIAG 0x1f /* Message from an internal diagnostic */
/*
* Subcodes of M_ST_OFFLINE
*/
-#define M_OFFLINE_UNKNOWN (0 << 5) /* unknown or on other ctlr */
-#define M_OFFLINE_UNMOUNTED (1 << 5) /* unmounted or RUN/STOP at STOP */
-#define M_OFFLINE_INOPERATIVE (2 << 5) /* inoperative? */
-#define M_OFFLINE_DUPLICATE (4 << 5) /* duplicate unit number */
-#define M_OFFLINE_INDIAGNOSTIC (8 << 5) /* disabled by FS or diagnostic */
+#define M_OFFLINE_UNKNOWN (0 << 5) /* unknown or on other ctlr */
+#define M_OFFLINE_UNMOUNTED (1 << 5) /* unmounted or RUN/STOP at STOP */
+#define M_OFFLINE_INOPERATIVE (2 << 5) /* inoperative? */
+#define M_OFFLINE_DUPLICATE (4 << 5) /* duplicate unit number */
+#define M_OFFLINE_INDIAGNOSTIC (8 << 5) /* disabled by FS or diagnostic */
/*
* An MSCP packet begins with a header giving the length of
@@ -237,13 +237,13 @@
*/
struct mscpv_seq {
long seq_bytecount; /* byte count */
-#define seq_rbn seq_bytecount /* aka RBN (replace) */
-#define seq_outref seq_bytecount /* aka outref (abort/get cmd status) */
+#define seq_rbn seq_bytecount /* aka RBN (replace) */
+#define seq_outref seq_bytecount /* aka outref (abort/get cmd status) */
long seq_buffer; /* buffer descriptor */
long seq_mapbase; /* page map (first PTE) phys address */
- long seq_xxx1; /* ? */ /* unused */
+ long seq_xxx1; /* ? */ /* unused */
long seq_lbn; /* logical block number */
- long seq_xxx2; /* ? */ /* unused */
+ long seq_xxx2; /* ? */ /* unused */
long *seq_addr; /* pointer to cmd descriptor */
long seq_software[4]; /* reserved to software; unused */
};
@@ -252,10 +252,10 @@ struct mscpv_seq {
* Set Controller Characteristics command variant
*/
struct mscpv_sccc {
- u_short sccc_version; /* MSCP version number */
- u_short sccc_ctlrflags; /* controller flags */
- u_short sccc_hosttimo; /* host timeout */
- u_short sccc_usefrac; /* use fraction */
+ u_short sccc_version; /* MSCP version number */
+ u_short sccc_ctlrflags; /* controller flags */
+ u_short sccc_hosttimo; /* host timeout */
+ u_short sccc_usefrac; /* use fraction */
long sccc_time; /* time and date */
long sccc_time1; /* it's a quad field */
long sccc_errlgfl; /* ? */
@@ -267,10 +267,10 @@ struct mscpv_sccc {
* Set Controller Characteristics end variant
*/
struct mscpv_scce {
- u_short scce_version; /* MSCP version number */
- u_short scce_ctlrflags; /* controller flags */
- u_short scce_ctlrtimo; /* controller timeout */
- u_short scce_ctlrcmdl; /* ??? */
+ u_short scce_version; /* MSCP version number */
+ u_short scce_ctlrflags; /* controller flags */
+ u_short scce_ctlrtimo; /* controller timeout */
+ u_short scce_ctlrcmdl; /* ??? */
quad_t scce_ctlrid; /* controller ID */
long scce_xxx[3]; /* ? */
long scce_volser; /* volume serial number */
@@ -291,7 +291,7 @@ struct mscpv_onlc {
*/
struct mscpv_onle {
long onle_xxx1[3]; /* ? */
-/*???*/ short onle_xxx2; /* ? */
+/*???*/ short onle_xxx2; /* ? */
u_char onle_drivetype; /* drive type index (same in guse) */
char onle_xxx3; /* ? */
long onle_mediaid; /* media type id (same in guse) */
@@ -304,8 +304,8 @@ struct mscpv_onle {
* Get Unit Status end variant (and Avail Attn?)
*/
struct mscpv_guse {
- u_short guse_multunit; /* multi-unit code */
- u_short guse_unitflags; /* unit flags */
+ u_short guse_multunit; /* multi-unit code */
+ u_short guse_unitflags; /* unit flags */
long guse_hostid; /* host id */
long guse_unitid0; /*???*/
short guse_unitid1; /*???*/
@@ -314,11 +314,11 @@ struct mscpv_guse {
long guse_mediaid; /* media type id (encoded) */
short guse_shadowunit; /* shadow unit */
short guse_shadowstat; /* shadow status */
- u_short guse_nspt; /* sectors per track */
- u_short guse_group; /* track group size */
- u_short guse_ngpc; /* groups per cylinder */
- u_short guse_xxx; /* reserved */
- u_short guse_rctsize; /* RCT size (sectors) */
+ u_short guse_nspt; /* sectors per track */
+ u_short guse_group; /* track group size */
+ u_short guse_ngpc; /* groups per cylinder */
+ u_short guse_xxx; /* reserved */
+ u_short guse_rctsize; /* RCT size (sectors) */
u_char guse_nrpt; /* RBNs per track */
u_char guse_nrct; /* number of RCTs */
};
@@ -328,23 +328,23 @@ struct mscpv_guse {
* type in the top 10 bits, and the drive type in the remaining 22.
* The 10 bits, and 15 of the 22, are in groups of 5, with the value
* 0 representing space and values 1..26 representing A..Z. The low
- * 7 bits represent a number in 0..127. Hence an RA81 on a UDA50
- * is <D><U><R><A>< >81, or 0x25641051. This encoding scheme is known
+ * 7 bits represent a number in 0..127. Hence an RA81 on a UDA50
+ * is <D><U><R><A>< >81, or 0x25641051. This encoding scheme is known
* in part in uda.c.
*
* The casts below are just to make pcc generate better code.
*/
-#define MSCP_MEDIA_PORT(id) (((long)(id) >> 22) & 0x3ff) /* port */
-#define MSCP_MEDIA_DRIVE(id) ((long)(id) & 0x003fffff) /* drive */
-#define MSCP_MID_ECH(n, id) (((long)(id) >> ((n) * 5 + 7)) & 0x1f)
-#define MSCP_MID_CHAR(n, id) \
+#define MSCP_MEDIA_PORT(id) (((long)(id) >> 22) & 0x3ff) /* port */
+#define MSCP_MEDIA_DRIVE(id) ((long)(id) & 0x003fffff) /* drive */
+#define MSCP_MID_ECH(n, id) (((int)(id) >> ((n) * 5 + 7)) & 0x1f)
+#define MSCP_MID_CHAR(n, id) \
(MSCP_MID_ECH(n, id) ? MSCP_MID_ECH(n, id) + '@' : ' ')
-#define MSCP_MID_NUM(id) ((id) & 0x7f)
+#define MSCP_MID_NUM(id) ((id) & 0x7f)
/* for, e.g., RA81 */
-#define MSCP_MKDRIVE2(a, b, n) \
+#define MSCP_MKDRIVE2(a, b, n) \
(((a) - '@') << 17 | ((b) - '@') << 12 | (n))
/* for, e.g., RRD50 */
-#define MSCP_MKDRIVE3(a, b, c, n) \
+#define MSCP_MKDRIVE3(a, b, c, n) \
(((a) - '@') << 17 | ((b) - '@') << 12 | ((c) - '@') << 7 | (n))
/*
@@ -354,22 +354,22 @@ struct mscpv_erd {
quad_t erd_ctlrid; /* controller ID */
u_char erd_ctlrsoftware; /* controller software version */
u_char erd_ctlrhardware; /* controller hardware version */
- u_short erd_multiunit; /* multi-unit code (?) */
+ u_short erd_multiunit; /* multi-unit code (?) */
union {
u_long un_busaddr; /* bus address, if mem access err */
quad_t un_unitid; /* unit id, otherwise */
} erd_un1;
-#define erd_busaddr erd_un1.un_busaddr
-#define erd_unitid erd_un1.un_unitid
+#define erd_busaddr erd_un1.un_busaddr
+#define erd_unitid erd_un1.un_unitid
u_char erd_unitsoftware; /* unit software version */
u_char erd_unithardware; /* unit hardware version */
union {
u_char un_b[2]; /* level, retry (if disk xfer err) */
- u_short un_s; /* cylinder (if small disk error) */
+ u_short un_s; /* cylinder (if small disk error) */
} erd_un2;
-#define erd_level erd_un2.un_b[0]
-#define erd_retry erd_un2.un_b[1]
-#define erd_sdecyl erd_un2.un_s
+#define erd_level erd_un2.un_b[0]
+#define erd_retry erd_un2.un_b[1]
+#define erd_sdecyl erd_un2.un_s
long erd_volser; /* volume serial number */
u_long erd_hdr; /* `header' (block number) */
u_char erd_sdistat[12]; /* SDI status information (?) */
@@ -378,23 +378,23 @@ struct mscpv_erd {
/*
* I am making brash assumptions about the first four bytes of all
* MSCP packets. These appear to be true for both UDA50s and TMSCP
- * devices (TU81, TA81, TK50). DEC claim that these four bytes are
+ * devices (TU81, TA81, TK50). DEC claim that these four bytes are
* not part of MSCP itself, yet at least the length is necessary
* for, e.g., error checking.
*/
struct mscp {
- u_short mscp_msglen; /* length in bytes */
+ u_short mscp_msglen; /* length in bytes */
u_char mscp_msgtc; /* type (high 4 bits) and credits */
u_char mscp_vcid; /* virtual circuit ID */
long mscp_cmdref; /* command reference number */
- u_short mscp_unit; /* unit number */
- u_short mscp_seqnum; /* sequence number */
+ u_short mscp_unit; /* unit number */
+ u_short mscp_seqnum; /* sequence number */
u_char mscp_opcode; /* opcode */
-#define mscp_format mscp_opcode /* aka format (datagrams) */
+#define mscp_format mscp_opcode /* aka format (datagrams) */
u_char mscp_flags; /* flags */
- u_short mscp_modifier; /* modifier (commands) */
-#define mscp_status mscp_modifier /* aka status (ends) */
-#define mscp_event mscp_modifier /* aka event (datagrams) */
+ u_short mscp_modifier; /* modifier (commands) */
+#define mscp_status mscp_modifier /* aka status (ends) */
+#define mscp_event mscp_modifier /* aka event (datagrams) */
union {
struct mscpv_seq un_seq; /* generic sequential msg */
struct mscpv_sccc un_sccc; /* SCC command */
@@ -404,14 +404,14 @@ struct mscp {
struct mscpv_guse un_guse; /* get unit status */
struct mscpv_erd un_erd; /* error datagram */
} mscp_un;
-/*???*/ long mscp_xxx; /* pad to 64 bytes */
+/*???*/ long mscp_xxx; /* pad to 64 bytes */
};
/*
* Define message length according to the DEC specifications by dropping
* the four byte header.
*/
-#define MSCP_MSGLEN (sizeof (struct mscp) - 4)
+#define MSCP_MSGLEN (sizeof (struct mscp) - 4)
/*
* Shorthand
@@ -420,53 +420,53 @@ struct mscp {
/*
* Generic packet
*/
-#define mscp_seq mscp_un.un_seq
+#define mscp_seq mscp_un.un_seq
/*
* Set Controller Characteristics packet
*/
-#define mscp_sccc mscp_un.un_sccc
+#define mscp_sccc mscp_un.un_sccc
/*
* Set Controller Characteristics end packet
*/
-#define mscp_scce mscp_un.un_scce
+#define mscp_scce mscp_un.un_scce
/*
* Online / Set Unit Characteristics command packet
*/
-#define mscp_onlc mscp_un.un_onlc
+#define mscp_onlc mscp_un.un_onlc
/*
* Online end packet
*/
-#define mscp_onle mscp_un.un_onle
+#define mscp_onle mscp_un.un_onle
/*
* Get Unit Status end packet
*/
-#define mscp_guse mscp_un.un_guse
+#define mscp_guse mscp_un.un_guse
/*
* MSCP Error Log packet
*/
-#define mscp_erd mscp_un.un_erd
+#define mscp_erd mscp_un.un_erd
/*
* MSCP seq_addr field actually belongs to overall packet.
*/
-#define mscp_addr mscp_seq.seq_addr
+#define mscp_addr mscp_seq.seq_addr
/*
* Macros to break up mscp_msgtc, and types.
*/
-#define MSCP_MSGTYPE(m) ((m) & 0xf0)
-#define MSCP_CREDITS(m) ((m) & 0x0f)
+#define MSCP_MSGTYPE(m) ((m) & 0xf0)
+#define MSCP_CREDITS(m) ((m) & 0x0f)
-#define MSCPT_SEQ 0x00 /* sequential message */
-#define MSCPT_DATAGRAM 0x10 /* error datagram */
-#define MSCPT_CREDITS 0x20 /* credit notification */
-#define MSCPT_MAINTENANCE 0xf0 /* who knows */
+#define MSCPT_SEQ 0x00 /* sequential message */
+#define MSCPT_DATAGRAM 0x10 /* error datagram */
+#define MSCPT_CREDITS 0x20 /* credit notification */
+#define MSCPT_MAINTENANCE 0xf0 /* who knows */
/*
@@ -474,7 +474,7 @@ struct mscp {
*/
/*
- * MSCP controllers have `command rings' and `response rings'. A
+ * MSCP controllers have `command rings' and `response rings'. A
* command ring is a pool of MSCP packets that the host uses to give
* commands to the controller; a response ring is a pool of MSCP
* packets that the controller uses to give back responses. Entries
@@ -490,5 +490,5 @@ struct mscp {
* The pool is `described' by a set of pointers to the packets, along
* with the two flags below.
*/
-#define MSCP_OWN 0x80000000 /* controller owns this packet */
-#define MSCP_INT 0x40000000 /* controller should interrupt */
+#define MSCP_OWN 0x80000000 /* controller owns this packet */
+#define MSCP_INT 0x40000000 /* controller should interrupt */
diff --git a/sys/arch/vax/mscp/mscp_disk.c b/sys/arch/vax/mscp/mscp_disk.c
index 24450c28d67..6c61963e064 100644
--- a/sys/arch/vax/mscp/mscp_disk.c
+++ b/sys/arch/vax/mscp/mscp_disk.c
@@ -1,5 +1,5 @@
-/* $OpenBSD: mscp_disk.c,v 1.6 1998/10/03 21:18:59 millert Exp $ */
-/* $NetBSD: mscp_disk.c,v 1.13 1997/06/24 01:12:40 thorpej Exp $ */
+/* $OpenBSD: mscp_disk.c,v 1.7 2000/04/27 03:14:46 bjc Exp $ */
+/* $NetBSD: mscp_disk.c,v 1.21 1999/06/06 19:16:18 ragge Exp $ */
/*
* Copyright (c) 1996 Ludd, University of Lule}, Sweden.
* Copyright (c) 1988 Regents of the University of California.
@@ -41,12 +41,12 @@
/*
* RA disk device driver
+ * RX MSCP floppy disk device driver
*/
/*
* TODO
* write bad block forwarding code
- * split the file into a separate floppy file
*/
#include <sys/param.h>
@@ -57,17 +57,32 @@
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <sys/fcntl.h>
+#include <sys/reboot.h>
#include <sys/proc.h>
#include <sys/systm.h>
-#include <sys/reboot.h>
+#include <ufs/ufs/dinode.h>
+#include <ufs/ffs/fs.h>
+
+#include <machine/bus.h>
#include <machine/cpu.h>
#include <machine/rpb.h>
-#include <ufs/ffs/fs.h> /* For some disklabel stuff */
+#include <arch/vax/mscp/mscp.h>
+#include <arch/vax/mscp/mscpreg.h>
+#include <arch/vax/mscp/mscpvar.h>
+
+#include "ra.h"
+
+struct cfdriver ra_cd = {
+ NULL, "ra", DV_DISK
+};
+
+struct cfdriver rx_cd = {
+ NULL, "rx", DV_DISK
+};
-#include <vax/mscp/mscp.h>
-#include <vax/mscp/mscpvar.h>
+#define RAMAJOR 9 /* RA major device number XXX */
/*
* Drive status, per drive
@@ -80,23 +95,21 @@ struct ra_softc {
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 *));
+#define rx_softc ra_softc
+
+void rxattach __P((struct device *, struct device *, void *));
+int rx_putonline __P((struct rx_softc *));
+void rrmakelabel __P((struct disklabel *, long));
+
+#if NRA
+
+int ramatch __P((struct device *, struct cfdata *, 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 *));
@@ -104,59 +117,32 @@ 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_DISK
-};
-
struct cfattach ra_ca = {
- sizeof(struct ra_softc), ramatch, raattach
+ sizeof(struct ra_softc), (cfmatch_t)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)
+ramatch(parent, cf, aux)
struct device *parent;
- void *match, *aux;
+ struct cfdata *cf;
+ void *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;
+ /*
+ * Check if this disk is a floppy; then don't configure it.
+ * Seems to be a safe way to test it per Chris Torek.
+ */
+ if (MSCP_MID_ECH(1, mp->mscp_guse.guse_mediaid) == 'X' - '@')
return 0;
return 1;
}
@@ -172,28 +158,9 @@ raattach(parent, self, aux)
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;
-
- ra->ra_disk.dk_name = ra->ra_dev.dv_xname;
- 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);
+ rxattach(parent, self, aux);
/*
* Find out if we booted from this disk.
*/
@@ -211,45 +178,29 @@ 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;
+ if (rx_putonline(ra) != MSCP_DONE)
return MSCP_FAILED;
- }
- if (ra->ra_state == RA_OFFLINE)
- return MSCP_FAILED;
- if (ra->ra_isafloppy)
- return MSCP_DONE;
+ dl = ra->ra_disk.dk_label;
+ ra->ra_state = DK_RDLABEL;
printf("%s", ra->ra_dev.dv_xname);
- if ((msg = readdisklabel(raminor(ra->ra_dev.dv_unit, 0),
- rastrategy, dl, NULL, 0)) != NULL)
+ if ((msg = readdisklabel(MAKEDISKDEV(RAMAJOR, ra->ra_dev.dv_unit,
+ RAW_PART), rastrategy, dl, NULL, 0)) != NULL)
printf(": %s", msg);
- else
+ else {
ra->ra_havelabel = 1;
- ra->ra_state = RA_ONLINE;
+ ra->ra_state = DK_OPEN;
+ }
printf(": size %d sectors\n", dl->d_secperunit);
return MSCP_DONE;
}
+
/*
* Open a drive.
*/
@@ -262,11 +213,10 @@ raopen(dev, flag, fmt, p)
{
register struct ra_softc *ra;
int part, unit, mask;
-
/*
* Make sure this is a reasonable open request.
*/
- unit = raunit(dev);
+ unit = DISKUNIT(dev);
if (unit >= ra_cd.cd_ndevs)
return ENXIO;
ra = ra_cd.cd_devs[unit];
@@ -277,24 +227,23 @@ raopen(dev, flag, fmt, p)
* 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->ra_state == DK_CLOSED)
if (ra_putonline(ra) == MSCP_FAILED)
- return EIO;
+ return ENXIO;
/* If the disk has no label; allow writing everywhere */
if (ra->ra_havelabel == 0)
ra->ra_wlabel = 1;
- part = rapart(dev);
- if (ra->ra_isafloppy == 0)
- if (part >= ra->ra_disk.dk_label->d_npartitions)
- return ENXIO;
+ part = DISKPART(dev);
+ 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)
+ while (ra->ra_state != DK_OPEN)
if ((error = tsleep((caddr_t)ra, (PZERO + 1) | PCATCH,
devopn, 0))) {
splx(s);
@@ -323,9 +272,9 @@ raclose(dev, flags, fmt, p)
int flags, fmt;
struct proc *p;
{
- register int unit = raunit(dev);
+ register int unit = DISKUNIT(dev);
register struct ra_softc *ra = ra_cd.cd_devs[unit];
- int mask = (1 << rapart(dev));
+ int mask = (1 << DISKPART(dev));
switch (fmt) {
case S_IFCHR:
@@ -344,7 +293,7 @@ raclose(dev, flags, fmt, p)
*/
#if notyet
if (ra->ra_openpart == 0) {
- s = splbio();
+ s = splimp();
while (udautab[unit].b_actf)
sleep((caddr_t)&udautab[unit], PZERO - 1);
splx(s);
@@ -357,10 +306,6 @@ raclose(dev, flags, fmt, p)
/*
* 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)
@@ -368,11 +313,10 @@ rastrategy(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);
+ unit = DISKUNIT(bp->b_dev);
if (unit > ra_cd.cd_ndevs || (ra = ra_cd.cd_devs[unit]) == NULL) {
bp->b_error = ENXIO;
bp->b_flags |= B_ERROR;
@@ -381,25 +325,26 @@ rastrategy(bp)
/*
* If drive is open `raw' or reading label, let it at it.
*/
- if (ra->ra_state < RA_ONLINE) {
+ if (ra->ra_state == DK_RDLABEL) {
mscp_strategy(bp, ra->ra_dev.dv_parent);
return;
}
- p = rapart(bp->b_dev);
+
+ /* If disk is not online, try to put it online */
+ if (ra->ra_state == DK_CLOSED)
+ if (ra_putonline(ra) == MSCP_FAILED) {
+ bp->b_flags |= B_ERROR;
+ bp->b_error = EIO;
+ goto done;
+ }
/*
* 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_disk.dk_cpulabel, ra->ra_wlabel) <= 0)
- goto done;
+ if (bounds_check_with_label(bp, ra->ra_disk.dk_label,
+ ra->ra_disk.dk_cpulabel, ra->ra_wlabel) <= 0)
+ goto done;
/* Make some statistics... /bqt */
ra->ra_disk.dk_xfer++;
@@ -413,242 +358,401 @@ done:
int
raread(dev, uio)
- dev_t dev;
- struct uio *uio;
+ dev_t dev;
+ struct uio *uio;
{
- return (physio(rastrategy, NULL, dev, B_READ, minphys, uio));
+ return (physio(rastrategy, NULL, dev, B_READ, minphys, uio));
}
int
rawrite(dev, uio)
- dev_t dev;
- struct uio *uio;
+ dev_t dev;
+ struct uio *uio;
{
- return (physio(rastrategy, NULL, dev, B_WRITE, minphys, uio));
+ return (physio(rastrategy, NULL, dev, B_WRITE, minphys, uio));
}
-void
-raiodone(usc, bp)
- struct device *usc;
- struct buf *bp;
+/*
+ * 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 = DISKUNIT(dev);
+ register struct disklabel *lp, *tp;
+ register struct ra_softc *ra = ra_cd.cd_devs[unit];
+ int error = 0;
- biodone(bp);
+ 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[DISKPART(dev)];
+ break;
+
+ case DIOCWDINFO:
+ case DIOCSDINFO:
+ if ((flag & FWRITE) == 0)
+ error = EBADF;
+ else {
+ error = setdisklabel(lp, (struct disklabel *)data,0,0);
+ if ((error == 0) && (cmd == DIOCWDINFO)) {
+ ra->ra_wlabel = 1;
+ error = writedisklabel(dev, rastrategy, lp,0);
+ ra->ra_wlabel = 0;
+ }
+ }
+ break;
+
+ case DIOCWLABEL:
+ if ((flag & FWRITE) == 0)
+ error = EBADF;
+ else
+ ra->ra_wlabel = 1;
+ break;
+
+#ifdef __NetBSD__
+ case DIOCGDEFLABEL:
+ tp = (struct disklabel *)data;
+ bzero(data, sizeof(struct disklabel));
+ tp->d_secsize = lp->d_secsize;
+ tp->d_nsectors = lp->d_nsectors;
+ tp->d_ntracks = lp->d_ntracks;
+ tp->d_ncylinders = lp->d_ncylinders;
+ tp->d_secpercyl = lp->d_secpercyl;
+ tp->d_secperunit = lp->d_secperunit;
+ tp->d_type = DTYPE_MSCP;
+ tp->d_rpm = 3600;
+ rrmakelabel(tp, ra->ra_mediaid);
+ break;
+#endif
+
+ default:
+ error = ENOTTY;
+ break;
+ }
+ return (error);
+}
+
+
+int
+radump(dev, blkno, va, size)
+ dev_t dev;
+ daddr_t blkno;
+ caddr_t va;
+ size_t size;
+{
+ return ENXIO;
}
/*
- * Fill in disk addresses in a mscp packet waiting for transfer.
+ * Return the size of a partition, if known, or -1 if not.
*/
-void
-rafillin(bp, mp)
- struct buf *bp;
- struct mscp *mp;
+int
+rasize(dev)
+ dev_t dev;
{
- 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;
+ register int unit = DISKUNIT(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 == DK_CLOSED)
+ if (ra_putonline(ra) == MSCP_FAILED)
+ return -1;
+
+ return ra->ra_disk.dk_label->d_partitions[DISKPART(dev)].p_size *
+ (ra->ra_disk.dk_label->d_secsize / DEV_BSIZE);
}
+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;
+}
+
+#endif /* NRA */
+
+#if NRX
+
+int rxmatch __P((struct device *, struct cfdata *, void *));
+int rxopen __P((dev_t, int, int, struct proc *));
+int rxclose __P((dev_t, int, int, struct proc *));
+void rxstrategy __P((struct buf *));
+int rxread __P((dev_t, struct uio *));
+int rxwrite __P((dev_t, struct uio *));
+int rxioctl __P((dev_t, int, caddr_t, int, struct proc *));
+int rxdump __P((dev_t, daddr_t, caddr_t, size_t));
+int rxsize __P((dev_t));
+
+struct cfattach rx_ca = {
+ sizeof(struct rx_softc), (cfmatch_t)rxmatch, rxattach
+};
+
/*
- * Handle an error datagram.
- * This can come from an unconfigured drive as well.
+ * More driver definitions, for generic MSCP code.
*/
-void
-radgram(usc, mp, mi)
- struct device *usc;
- struct mscp *mp;
- struct mscp_softc *mi;
+
+int
+rxmatch(parent, cf, aux)
+ struct device *parent;
+ struct cfdata *cf;
+ void *aux;
{
- if (mscp_decodeerror(usc == NULL?"unconf ra" : usc->dv_xname, mp, mi))
- return;
+ 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;
/*
- * 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.
+ * Check if this disk is a floppy; then configure it.
+ * Seems to be a safe way to test it per Chris Torek.
*/
- 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]);
+ if (MSCP_MID_ECH(1, mp->mscp_guse.guse_mediaid) == 'X' - '@')
+ return 1;
+ return 0;
}
+#endif /* NRX */
+
/*
- * 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.
+ * The attach routine only checks and prints drive type.
+ * Bringing the disk online is done when the disk is accessed
+ * the first time.
*/
-int
-raonline(usc, mp)
- struct device *usc;
- struct mscp *mp;
+void
+rxattach(parent, self, aux)
+ struct device *parent, *self;
+ void *aux;
{
- 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);
- }
+ struct rx_softc *rx = (void *)self;
+ struct drive_attach_args *da = aux;
+ struct mscp *mp = da->da_mp;
+ struct mscp_softc *mi = (void *)parent;
+ struct disklabel *dl;
- /*
- * 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;
+ rx->ra_mediaid = mp->mscp_guse.guse_mediaid;
+ rx->ra_state = DK_CLOSED;
+ rx->ra_hwunit = mp->mscp_unit;
+ mi->mi_dp[mp->mscp_unit] = self;
- 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;
+ rx->ra_disk.dk_name = rx->ra_dev.dv_xname;
+ disk_attach((struct disk *)&rx->ra_disk);
- /* 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;
- 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;
- dl->d_interleave = dl->d_headswitch = 1;
- dl->d_magic = dl->d_magic2 = DISKMAGIC;
- dl->d_checksum = dkcksum(dl);
+ /* Fill in what we know. The actual size is gotten later */
+ dl = rx->ra_disk.dk_label;
- return (MSCP_DONE);
+ dl->d_secsize = DEV_BSIZE;
+ dl->d_nsectors = mp->mscp_guse.guse_nspt;
+ dl->d_ntracks = mp->mscp_guse.guse_ngpc * mp->mscp_guse.guse_group;
+ dl->d_secpercyl = dl->d_nsectors * dl->d_ntracks;
+ disk_printtype(mp->mscp_unit, mp->mscp_guse.guse_mediaid);
+#ifdef DEBUG
+ printf("%s: nspt %d group %d ngpc %d rct %d nrpt %d nrct %d\n",
+ self->dv_xname, mp->mscp_guse.guse_nspt, mp->mscp_guse.guse_group,
+ mp->mscp_guse.guse_ngpc, mp->mscp_guse.guse_rctsize,
+ mp->mscp_guse.guse_nrpt, mp->mscp_guse.guse_nrct);
+#endif
}
-/*
- * We got some (configured) unit's status. Return DONE if it succeeded.
+/*
+ * (Try to) put the drive online. This is done the first time the
+ * drive is opened, or if it har fallen offline.
*/
int
-ragotstatus(usc, mp)
- register struct device *usc;
- register struct mscp *mp;
+rx_putonline(rx)
+ struct rx_softc *rx;
{
- 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);
+ struct mscp *mp;
+ struct mscp_softc *mi = (struct mscp_softc *)rx->ra_dev.dv_parent;
+ volatile int i;
+
+ rx->ra_state = DK_CLOSED;
+ mp = mscp_getcp(mi, MSCP_WAIT);
+ mp->mscp_opcode = M_OP_ONLINE;
+ mp->mscp_unit = rx->ra_hwunit;
+ mp->mscp_cmdref = 1;
+ *mp->mscp_addr |= MSCP_OWN | MSCP_INT;
+
+ /* Poll away */
+ i = bus_space_read_2(mi->mi_iot, mi->mi_iph, 0);
+ if (tsleep(&rx->ra_dev.dv_unit, PRIBIO, "rxonline", 100*100))
+ rx->ra_state = DK_CLOSED;
+
+ if (rx->ra_state == DK_CLOSED)
+ return MSCP_FAILED;
+
+ return MSCP_DONE;
}
+#if NRX
+
/*
- * A transfer failed. We get a chance to fix or restart it.
- * Need to write the bad block forwaring code first....
+ * Open a drive.
*/
/*ARGSUSED*/
int
-raioerror(usc, mp, bp)
- register struct device *usc;
- register struct mscp *mp;
- struct buf *bp;
+rxopen(dev, flag, fmt, p)
+ dev_t dev;
+ int flag, fmt;
+ struct proc *p;
{
-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);
+ register struct rx_softc *rx;
+ int unit;
+
+ /*
+ * Make sure this is a reasonable open request.
+ */
+ unit = DISKUNIT(dev);
+ if (unit >= rx_cd.cd_ndevs)
+ return ENXIO;
+ rx = rx_cd.cd_devs[unit];
+ if (rx == 0)
+ return ENXIO;
+
+ /*
+ * If this is the first open; we must first try to put
+ * the disk online (and read the label).
+ */
+ if (rx->ra_state == DK_CLOSED)
+ if (rx_putonline(rx) == MSCP_FAILED)
+ return ENXIO;
+
+ return 0;
+}
+
+/* ARGSUSED */
+int
+rxclose(dev, flags, fmt, p)
+ dev_t dev;
+ int flags, fmt;
+ struct proc *p;
+{
+ return (0);
}
/*
- * A replace operation finished.
+ * 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.
*/
-/*ARGSUSED*/
void
-rareplace(usc, mp)
- struct device *usc;
- struct mscp *mp;
+rxstrategy(bp)
+ register struct buf *bp;
{
+ register int unit;
+ register struct rx_softc *rx;
- panic("udareplace");
+ /*
+ * Make sure this is a reasonable drive to use.
+ */
+ unit = DISKUNIT(bp->b_dev);
+ if (unit > rx_cd.cd_ndevs || (rx = rx_cd.cd_devs[unit]) == NULL) {
+ bp->b_error = ENXIO;
+ bp->b_flags |= B_ERROR;
+ goto done;
+ }
+
+ /* If disk is not online, try to put it online */
+ if (rx->ra_state == DK_CLOSED)
+ if (rx_putonline(rx) == MSCP_FAILED) {
+ bp->b_flags |= B_ERROR;
+ bp->b_error = EIO;
+ goto done;
+ }
+
+ /*
+ * Determine the size of the transfer, and make sure it is
+ * within the boundaries of the partition.
+ */
+ if (bp->b_blkno >= rx->ra_disk.dk_label->d_secperunit) {
+ bp->b_resid = bp->b_bcount;
+ goto done;
+ }
+
+ /* Make some statistics... /bqt */
+ rx->ra_disk.dk_xfer++;
+ rx->ra_disk.dk_bytes += bp->b_bcount;
+ mscp_strategy(bp, rx->ra_dev.dv_parent);
+ return;
+
+done:
+ biodone(bp);
}
-/*
- * A bad block related operation finished.
- */
-/*ARGSUSED*/
-void
-rabb(usc, mp, bp)
- struct device *usc;
- struct mscp *mp;
- struct buf *bp;
+int
+rxread(dev, uio)
+ dev_t dev;
+ struct uio *uio;
{
- panic("udabb");
+ return (physio(rxstrategy, NULL, dev, B_READ, minphys, uio));
}
+int
+rxwrite(dev, uio)
+ dev_t dev;
+ struct uio *uio;
+{
+
+ return (physio(rxstrategy, NULL, dev, B_WRITE, minphys, uio));
+}
/*
* I/O controls.
*/
int
-raioctl(dev, cmd, data, flag, p)
+rxioctl(dev, cmd, data, flag, p)
dev_t dev;
int cmd;
caddr_t data;
int flag;
struct proc *p;
{
- register int unit = raunit(dev);
+ register int unit = DISKUNIT(dev);
register struct disklabel *lp;
- register struct ra_softc *ra = ra_cd.cd_devs[unit];
+ register struct rx_softc *rx = rx_cd.cd_devs[unit];
int error = 0;
- lp = ra->ra_disk.dk_label;
+ lp = rx->ra_disk.dk_label;
switch (cmd) {
@@ -659,28 +763,13 @@ raioctl(dev, cmd, data, flag, p)
case DIOCGPART:
((struct partinfo *)data)->disklab = lp;
((struct partinfo *)data)->part =
- &lp->d_partitions[rapart(dev)];
+ &lp->d_partitions[DISKPART(dev)];
break;
+
case DIOCWDINFO:
case DIOCSDINFO:
- if ((flag & FWRITE) == 0)
- error = EBADF;
- else {
- error = setdisklabel(lp, (struct disklabel *)data,0,0);
- if ((error == 0) && (cmd == DIOCWDINFO)) {
- ra->ra_wlabel = 1;
- error = writedisklabel(dev, rastrategy, lp,0);
- ra->ra_wlabel = 0;
- }
- }
- break;
-
case DIOCWLABEL:
- if ((flag & FWRITE) == 0)
- error = EBADF;
- else
- ra->ra_wlabel = 1;
break;
default:
@@ -690,296 +779,262 @@ raioctl(dev, cmd, data, flag, p)
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
+int
+rxdump(dev, blkno, va, size)
+ dev_t dev;
+ daddr_t blkno;
+ caddr_t va;
+ size_t size;
+{
-#define DBSIZE 32 /* dump 16K at a time */
+ /* Not likely. */
+ return ENXIO;
+}
int
-radump(dev, blkno, va, size)
- dev_t dev;
- daddr_t blkno;
- caddr_t va;
- size_t size;
+rxsize(dev)
+ dev_t dev;
{
-#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);
+ return -1;
+}
- /*
- * 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));
+#endif /* NRX */
- /*
- * 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;
+void rrdgram __P((struct device *, struct mscp *, struct mscp_softc *));
+void rriodone __P((struct device *, struct buf *));
+int rronline __P((struct device *, struct mscp *));
+int rrgotstatus __P((struct device *, struct mscp *));
+void rrreplace __P((struct device *, struct mscp *));
+int rrioerror __P((struct device *, struct mscp *, struct buf *));
+void rrfillin __P((struct buf *, struct mscp *));
+void rrbb __P((struct device *, struct mscp *, struct buf *));
- /*
- * 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;
+struct mscp_device ra_device = {
+ rrdgram,
+ rriodone,
+ rronline,
+ rrgotstatus,
+ rrreplace,
+ rrioerror,
+ rrbb,
+ rrfillin,
+};
+/*
+ * Handle an error datagram.
+ * This can come from an unconfigured drive as well.
+ */
+void
+rrdgram(usc, mp, mi)
+ struct device *usc;
+ struct mscp *mp;
+ struct mscp_softc *mi;
+{
+ if (mscp_decodeerror(usc == NULL?"unconf disk" : usc->dv_xname, mp, mi))
+ return;
/*
- * Write out memory, DBSIZE pages at a time.
- * N.B.: this code depends on the fact that the sector
- * size == the page size.
+ * 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.
*/
- 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! */
+ 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]);
+}
+
+void
+rriodone(usc, bp)
+ struct device *usc;
+ struct buf *bp;
+{
+
+ biodone(bp);
}
/*
- * 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).
+ * 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
-udadumpwait(udaddr, bits)
- struct udadevice *udaddr;
- register int bits;
+rronline(usc, mp)
+ struct device *usc;
+ struct mscp *mp;
{
- 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);
- }
+ struct rx_softc *rx = (struct rx_softc *)usc;
+ struct disklabel *dl;
+
+ wakeup((caddr_t)&usc->dv_unit);
+ if ((mp->mscp_status & M_ST_MASK) != M_ST_SUCCESS) {
+ printf("%s: attempt to bring on line failed: ", usc->dv_xname);
+ mscp_printevent(mp);
+ return (MSCP_FAILED);
}
- return (0);
+
+ rx->ra_state = DK_OPEN;
+
+ dl = rx->ra_disk.dk_label;
+ dl->d_secperunit = (daddr_t)mp->mscp_onle.onle_unitsize;
+
+ if (dl->d_secpercyl) {
+ dl->d_ncylinders = dl->d_secperunit/dl->d_secpercyl;
+ dl->d_type = DTYPE_MSCP;
+ dl->d_rpm = 3600;
+ } else {
+ dl->d_type = DTYPE_FLOPPY;
+ dl->d_rpm = 300;
+ }
+ rrmakelabel(dl, rx->ra_mediaid);
+
+ return (MSCP_DONE);
}
-/*
- * 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;
+void
+rrmakelabel(dl, type)
+ struct disklabel *dl;
+ long type;
{
- 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);
+ int n, p = 0;
+
+ dl->d_bbsize = BBSIZE;
+ dl->d_sbsize = SBSIZE;
+
+ /* Create the disk name for disklabel. Phew... */
+ dl->d_typename[p++] = MSCP_MID_CHAR(2, type);
+ dl->d_typename[p++] = MSCP_MID_CHAR(1, type);
+ if (MSCP_MID_ECH(0, type))
+ dl->d_typename[p++] = MSCP_MID_CHAR(0, type);
+ n = MSCP_MID_NUM(type);
+ if (n > 99) {
+ dl->d_typename[p++] = '1';
+ n -= 100;
}
- 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 (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;
+ 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;
+ dl->d_interleave = dl->d_headswitch = 1;
+ dl->d_magic = dl->d_magic2 = DISKMAGIC;
+ dl->d_checksum = dkcksum(dl);
+}
+
+/*
+ * We got some (configured) unit's status. Return DONE if it succeeded.
+ */
+int
+rrgotstatus(usc, mp)
+ register struct device *usc;
+ register struct mscp *mp;
+{
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);
+ 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 (0);
-#undef mp
+ return (MSCP_DONE);
}
-/*
- * Return the size of a partition, if known, or -1 if not.
+/*
+ * A replace operation finished.
*/
-int
-rasize(dev)
- dev_t dev;
+/*ARGSUSED*/
+void
+rrreplace(usc, mp)
+ struct device *usc;
+ struct mscp *mp;
{
- register int unit = raunit(dev);
- struct ra_softc *ra;
- if (unit >= ra_cd.cd_ndevs || ra_cd.cd_devs[unit] == 0)
- return -1;
+ panic("udareplace");
+}
- ra = ra_cd.cd_devs[unit];
+/*
+ * A transfer failed. We get a chance to fix or restart it.
+ * Need to write the bad block forwaring code first....
+ */
+/*ARGSUSED*/
+int
+rrioerror(usc, mp, bp)
+ register struct device *usc;
+ register struct mscp *mp;
+ struct buf *bp;
+{
+ struct ra_softc *ra = (void *)usc;
+ int code = mp->mscp_event;
- if (ra->ra_state == RA_OFFLINE)
- if (ra_putonline(ra) == MSCP_FAILED)
- return -1;
+ switch (code & M_ST_MASK) {
+ /* The unit has fallen offline. Try to figure out why. */
+ case M_ST_OFFLINE:
+ bp->b_flags |= B_ERROR;
+ bp->b_error = EIO;
+ ra->ra_state = DK_CLOSED;
+ if (code & M_OFFLINE_UNMOUNTED)
+ printf("%s: not mounted/spun down\n", usc->dv_xname);
+ if (code & M_OFFLINE_DUPLICATE)
+ printf("%s: duplicate unit number!!!\n", usc->dv_xname);
+ return MSCP_DONE;
- return ra->ra_disk.dk_label->d_partitions[rapart(dev)].p_size;
+ case M_ST_AVAILABLE:
+ ra->ra_state = DK_CLOSED; /* Force another online */
+ return MSCP_DONE;
+
+ default:
+ printf("%s:", usc->dv_xname);
+ break;
+ }
+ return (MSCP_FAILED);
}
-int
-ra_getdev(adaptor, controller, unit, uname)
- int adaptor, controller, unit;
- char **uname;
+/*
+ * Fill in disk addresses in a mscp packet waiting for transfer.
+ */
+void
+rrfillin(bp, mp)
+ struct buf *bp;
+ struct mscp *mp;
{
- struct mscp_softc *mi;
- struct ra_softc *ra;
- int i;
+ struct rx_softc *rx = 0; /* Wall */
+ struct disklabel *lp;
+ int unit = DISKUNIT(bp->b_dev);
+ int part = DISKPART(bp->b_dev);
+
+#if NRA
+ if (major(bp->b_dev) == RAMAJOR)
+ rx = ra_cd.cd_devs[unit];
+#endif
+#if NRX
+ if (major(bp->b_dev) != RAMAJOR)
+ rx = rx_cd.cd_devs[unit];
+#endif
+ lp = rx->ra_disk.dk_label;
- for (i = 0; i < ra_cd.cd_ndevs; i++) {
- if ((ra = ra_cd.cd_devs[i]) == 0)
- continue;
+ mp->mscp_seq.seq_lbn = lp->d_partitions[part].p_offset + bp->b_blkno;
+ mp->mscp_unit = rx->ra_hwunit;
+ mp->mscp_seq.seq_bytecount = bp->b_bcount;
+}
- 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;
+/*
+ * A bad block related operation finished.
+ */
+/*ARGSUSED*/
+void
+rrbb(usc, mp, bp)
+ struct device *usc;
+ struct mscp *mp;
+ struct buf *bp;
+{
+
+ panic("udabb");
}
diff --git a/sys/arch/vax/mscp/mscp_subr.c b/sys/arch/vax/mscp/mscp_subr.c
index 0452ff14b3e..c94d5919563 100644
--- a/sys/arch/vax/mscp/mscp_subr.c
+++ b/sys/arch/vax/mscp/mscp_subr.c
@@ -1,5 +1,5 @@
-/* $OpenBSD: mscp_subr.c,v 1.2 1997/05/29 00:05:03 niklas Exp $ */
-/* $NetBSD: mscp_subr.c,v 1.6 1997/01/11 11:20:34 ragge Exp $ */
+/* $OpenBSD: mscp_subr.c,v 1.3 2000/04/27 03:14:46 bjc Exp $ */
+/* $NetBSD: mscp_subr.c,v 1.12 1999/06/06 19:16:18 ragge Exp $ */
/*
* Copyright (c) 1996 Ludd, University of Lule}, Sweden.
* Copyright (c) 1988 Regents of the University of California.
@@ -49,32 +49,42 @@
#include <sys/systm.h>
#include <sys/proc.h>
+#include <machine/bus.h>
#include <machine/sid.h>
-#include <vax/mscp/mscp.h>
-#include <vax/mscp/mscpreg.h>
-#include <vax/mscp/mscpvar.h>
+#include <arch/vax/mscp/mscp.h>
+#include <arch/vax/mscp/mscpreg.h>
+#include <arch/vax/mscp/mscpvar.h>
#include "ra.h"
#include "mt.h"
-#define b_forw b_hash.le_next
+#define b_forw b_hash.le_next
-int mscp_match __P((struct device *, void *, void *));
+#ifndef offsetof
+#define offsetof(type, member) ((size_t)(&((type *)0)->member))
+#endif
+
+int mscp_match __P((struct device *, struct cfdata *, void *));
void mscp_attach __P((struct device *, struct device *, void *));
-void mscp_start __P((struct mscp_softc *));
+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
+ sizeof(struct mscp_softc), (cfmatch_t)mscp_match, mscp_attach
};
struct cfdriver mscpbus_cd = {
NULL, "mscpbus", DV_DULL
};
+#define READ_SA (bus_space_read_2(mi->mi_iot, mi->mi_sah, 0))
+#define READ_IP (bus_space_read_2(mi->mi_iot, mi->mi_iph, 0))
+#define WRITE_IP(x) bus_space_write_2(mi->mi_iot, mi->mi_iph, 0, (x))
+#define WRITE_SW(x) bus_space_write_2(mi->mi_iot, mi->mi_swh, 0, (x))
+
struct mscp slavereply;
/*
@@ -91,9 +101,9 @@ mscp_waitstep(mi, mask, result)
{
int status = 1;
- if ((*mi->mi_sa & mask) != result) {
+ if ((READ_SA & mask) != result) {
volatile int count = 0;
- while ((*mi->mi_sa & mask) != result) {
+ while ((READ_SA & mask) != result) {
DELAY(10000);
count += 1;
if (count > DELAYTEN)
@@ -108,11 +118,12 @@ mscp_waitstep(mi, mask, result)
int
mscp_match(parent, match, aux)
struct device *parent;
- void *match, *aux;
+ struct cfdata *match;
+ void *aux;
{
struct mscp_attach_args *ma = aux;
-#if NRA
+#if NRA || NRX
if (ma->ma_type & MSCPBUS_DISK)
return 1;
#endif
@@ -130,18 +141,20 @@ mscp_attach(parent, self, aux)
{
struct mscp_attach_args *ma = aux;
struct mscp_softc *mi = (void *)self;
- volatile struct mscp *mp;
+ 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_dmat = ma->ma_dmat;
+ mi->mi_dmam = ma->ma_dmam;
+ mi->mi_iot = ma->ma_iot;
+ mi->mi_iph = ma->ma_iph;
+ mi->mi_sah = ma->ma_sah;
+ mi->mi_swh = ma->ma_swh;
mi->mi_ivec = ma->ma_ivec;
mi->mi_adapnr = ma->ma_adapnr;
mi->mi_ctlrnr = ma->ma_ctlrnr;
@@ -150,20 +163,28 @@ mscp_attach(parent, self, aux)
* 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;
+ 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;
+ SIMPLEQ_INIT(&mi->mi_resq);
if (mscp_init(mi)) {
printf("%s: can't init, controller hung\n",
mi->mi_dev.dv_xname);
return;
}
+ for (i = 0; i < NCMD; i++) {
+ mi->mi_mxiuse |= (1 << i);
+ if (bus_dmamap_create(mi->mi_dmat, (64*1024), 1, (64*1024),
+ 0, BUS_DMA_NOWAIT, &mi->mi_xi[i].mxi_dmam)) {
+ printf("Couldn't alloc dmamap %d\n", i);
+ return;
+ }
+ }
+
#if NRA
if (ma->ma_type & MSCPBUS_DISK) {
@@ -193,7 +214,7 @@ findunit:
*mp->mscp_addr |= MSCP_OWN | MSCP_INT;
slavereply.mscp_opcode = 0;
- i = *mi->mi_ip; /* Kick off polling */
+ i = bus_space_read_2(mi->mi_iot, mi->mi_iph, 0);
mp = &slavereply;
timeout = 1000;
while (timeout-- > 0) {
@@ -210,65 +231,65 @@ gotit: /*
*/
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_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.
- */
+ * 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);
+ 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
+ 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;
+ */
+ if (mp->mscp_unit < next)
+ return;
next = mp->mscp_unit + 1;
goto findunit;
@@ -289,29 +310,29 @@ mscp_init(mi)
int status, count;
unsigned int j = 0;
- /*
- * While we are thinking about it, reset the next command
- * and response indicies.
- */
+ /*
+ * 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 */
+ WRITE_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) {
+ if (READ_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);
+ WRITE_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);
@@ -319,31 +340,33 @@ mscp_init(mi)
}
/* step2 */
- *mi->mi_sw = (int)&mi->mi_uuda->mp_ca.ca_rspdsc[0] |
- (vax_cputype == VAX_780 || vax_cputype == VAX_8600 ? MP_PI : 0);
+ WRITE_SW(((mi->mi_dmam->dm_segs[0].ds_addr & 0xffff) +
+ offsetof(struct mscp_pack, 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;
- }
+ 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;
+
+ WRITE_SW((mi->mi_dmam->dm_segs[0].ds_addr >> 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;
+ if (status == 0) {
+ (*mi->mi_mc->mc_saerror)(mi->mi_dev.dv_parent, 0);
+ return 1;
+ }
+ i = READ_SA & 0377;
printf(": version %d model %d\n", i & 15, i >> 4);
-#define BURST 4 /* XXX */
+#define BURST 4 /* XXX */
if (mi->mi_type & MSCPBUS_UDA) {
- *mi->mi_sw = MP_GO | (BURST - 1) << 2;
+ WRITE_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;
+ WRITE_SW(MP_GO);
mscp_initds(mi);
mi->mi_flags &= ~MSC_IGNOREINTR;
@@ -363,17 +386,17 @@ mscp_init(mi)
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;
+ i = READ_IP;
- count = 0;
- while (count < DELAYTEN) {
- if (((volatile)mi->mi_flags & MSC_READY) != 0)
- break;
- if ((j = *mi->mi_sa) & MP_ERR)
+ count = 0;
+ while (count < DELAYTEN) {
+ if (((volatile int)mi->mi_flags & MSC_READY) != 0)
+ break;
+ if ((j = READ_SA) & MP_ERR)
goto out;
- DELAY(10000);
- count += 1;
- }
+ DELAY(10000);
+ count += 1;
+ }
if (count == DELAYTEN) {
out:
printf("%s: couldn't set ctlr characteristics, sa=%x\n",
@@ -390,20 +413,21 @@ 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;
+ (mi->mi_dmam->dm_segs[0].ds_addr +
+ offsetof(struct mscp_pack, 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;
+ (mi->mi_dmam->dm_segs[0].ds_addr +
+ offsetof(struct mscp_pack, 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)
@@ -411,6 +435,8 @@ mscp_initds(mi)
}
}
+static void mscp_kickaway(struct mscp_softc *);
+
void
mscp_intr(mi)
struct mscp_softc *mi;
@@ -419,31 +445,23 @@ mscp_intr(mi)
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???
+ * Check for response and command ring transitions.
*/
- 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;
+ 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 request, try them now.
+ */
+ if (SIMPLEQ_FIRST(&mi->mi_resq))
+ mscp_kickaway(mi);
}
int
@@ -451,12 +469,22 @@ mscp_print(aux, name)
void *aux;
const char *name;
{
+ struct drive_attach_args *da = aux;
+ struct mscp *mp = da->da_mp;
+ int type = mp->mscp_guse.guse_mediaid;
+
+ if (name) {
+ printf("%c%c", 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 at %s drive %d", MSCP_MID_NUM(type), name,
+ mp->mscp_unit);
+ }
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)
@@ -464,60 +492,82 @@ mscp_strategy(bp, usc)
struct device *usc;
{
struct mscp_softc *mi = (void *)usc;
+ int s = splimp();
+
+/* SIMPLEQ_INSERT_TAIL(&mi->mi_resq, bp, xxx) */
+ bp->b_actf = NULL;
+ *mi->mi_resq.sqh_last = bp;
+ mi->mi_resq.sqh_last = &bp->b_actf;
+ mscp_kickaway(mi);
+ splx(s);
+}
+
+
+void
+mscp_kickaway(mi)
+ struct mscp_softc *mi;
+{
+ struct buf *bp;
struct mscp *mp;
- int s = spl6();
+ int next;
- /*
- * 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);
+ while ((bp = SIMPLEQ_FIRST(&mi->mi_resq))) {
/*
- * By some (strange) reason we didn't get a MSCP packet.
- * Put it on queue and wait for free packets.
+ * Ok; we are ready to try to start a xfer. Get a MSCP packet
+ * and try to start...
*/
- (void *)bp->b_actb = mi->mi_w;
- mi->mi_w = bp;
- splx(s);
- return;
+ 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.
+ * Just return and wait for free packets.
+ */
+ return;
+ }
+
+ if ((next = (ffs(mi->mi_mxiuse) - 1)) < 0)
+ panic("no mxi buffers");
+ mi->mi_mxiuse &= ~(1 << next);
+ if (mi->mi_xi[next].mxi_inuse)
+ panic("mxi inuse");
+ /*
+ * 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;
+ mp->mscp_cmdref = next;
+ mi->mi_xi[next].mxi_bp = bp;
+ mi->mi_xi[next].mxi_mp = mp;
+ mi->mi_xi[next].mxi_inuse = 1;
+ bp->b_resid = next;
+ (*mi->mi_me->me_fillin)(bp, mp);
+ (*mi->mi_mc->mc_go)(mi->mi_dev.dv_parent, &mi->mi_xi[next]);
+ if ((mi->mi_resq.sqh_first = bp->b_actf) == NULL)
+ mi->mi_resq.sqh_last = &mi->mi_resq.sqh_first;
+#if 0
+ mi->mi_w = bp->b_actf;
+#endif
}
-
- /*
- * 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)
+mscp_dgo(mi, mxi)
struct mscp_softc *mi;
- long buffer, info;
- struct buf *bp;
+ struct mscp_xi *mxi;
{
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);
+ /*
+ * Fill in the MSCP packet and move the buffer to the I/O wait queue.
+ */
+ mp = mxi->mxi_mp;
+ mp->mscp_seq.seq_buffer = mxi->mxi_dmam->dm_segs[0].ds_addr;
- bp->b_resid = info;
- mp->mscp_cmdref = (long) bp;
*mp->mscp_addr |= MSCP_OWN | MSCP_INT;
-
- i = *mi->mi_ip;
+ i = READ_IP;
}
#ifdef DIAGNOSTIC
@@ -686,7 +736,7 @@ static char *drive_msgs[] = {
"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 */
+ "drive detected error", /* 7 = Drive Error */
"ctlr detected pulse or parity",/* 8 = Pulse or Parity Error */
};
@@ -699,7 +749,7 @@ struct code_decode {
int cdc_nsubcodes;
char **cdc_submsgs;
} code_decode[] = {
-#define SC(m) sizeof (m) / sizeof (m[0]), m
+#define SC(m) sizeof (m) / sizeof (m[0]), m
{"success", SC(succ_msgs)},
{"invalid command", SC(icmd_msgs)},
{"command aborted", 0, 0},
diff --git a/sys/arch/vax/mscp/mscp_tape.c b/sys/arch/vax/mscp/mscp_tape.c
index 9e3a23dcf2d..49f53e1df12 100644
--- a/sys/arch/vax/mscp/mscp_tape.c
+++ b/sys/arch/vax/mscp/mscp_tape.c
@@ -1,5 +1,5 @@
-/* $OpenBSD: mscp_tape.c,v 1.3 1997/09/12 09:25:52 maja Exp $ */
-/* $NetBSD: mscp_tape.c,v 1.5 1997/07/04 11:58:22 ragge Exp $ */
+/* $OpenBSD: mscp_tape.c,v 1.4 2000/04/27 03:14:46 bjc Exp $ */
+/* $NetBSD: mscp_tape.c,v 1.14 1999/06/06 19:16:18 ragge Exp $ */
/*
* Copyright (c) 1996 Ludd, University of Lule}, Sweden.
* All rights reserved.
@@ -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 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
*
@@ -52,8 +52,12 @@
#include <sys/systm.h>
#include <sys/proc.h>
-#include <vax/mscp/mscp.h>
-#include <vax/mscp/mscpvar.h>
+#include <machine/bus.h>
+#include <machine/cpu.h>
+
+#include <arch/vax/mscp/mscp.h>
+#include <arch/vax/mscp/mscpreg.h>
+#include <arch/vax/mscp/mscpvar.h>
/*
* Drive status, per drive
@@ -68,10 +72,10 @@ struct mt_softc {
int mt_ioctlerr; /* Error after last ioctl */
};
-#define MT_OFFLINE 0
-#define MT_ONLINE 1
+#define MT_OFFLINE 0
+#define MT_ONLINE 1
-int mtmatch __P((struct device *, void *, void *));
+int mtmatch __P((struct device *, struct cfdata *, 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 *));
@@ -88,6 +92,7 @@ int mtioctl __P((dev_t, int, caddr_t, int, struct proc *));
int mtdump __P((dev_t, daddr_t, caddr_t, size_t));
int mtcmd __P((struct mt_softc *, int, int, int));
void mtcmddone __P((struct device *, struct mscp *));
+int mt_putonline __P((struct mt_softc *));
struct mscp_device mt_device = {
mtdgram,
@@ -102,16 +107,16 @@ struct mscp_device mt_device = {
};
/* 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)
+#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), (cfmatch_t)mtmatch, mtattach
};
-struct cfattach mt_ca = {
- sizeof(struct mt_softc), mtmatch, mtattach
+struct cfdriver mt_cd = {
+ NULL, "mt", DV_TAPE
};
/*
@@ -119,11 +124,11 @@ struct cfattach mt_ca = {
*/
int
-mtmatch(parent, match, aux)
+mtmatch(parent, cf, aux)
struct device *parent;
- void *match, *aux;
+ struct cfdata *cf;
+ void *aux;
{
- struct cfdata *cf = match;
struct drive_attach_args *da = aux;
struct mscp *mp = da->da_mp;
@@ -165,7 +170,7 @@ mt_putonline(mt)
struct mscp_softc *mi = (struct mscp_softc *)mt->mt_dev.dv_parent;
volatile int i;
- (volatile)mt->mt_state = MT_OFFLINE;
+ (volatile int)mt->mt_state = MT_OFFLINE;
mp = mscp_getcp(mi, MSCP_WAIT);
mp->mscp_opcode = M_OP_ONLINE;
mp->mscp_unit = mt->mt_hwunit;
@@ -173,11 +178,11 @@ mt_putonline(mt)
*mp->mscp_addr |= MSCP_OWN | MSCP_INT;
/* Poll away */
- i = *mi->mi_ip;
+ i = bus_space_read_2(mi->mi_iot, mi->mi_iph, 0);
if (tsleep(&mt->mt_state, PRIBIO, "mtonline", 240 * hz))
return MSCP_FAILED;
- if ((volatile)mt->mt_state != MT_ONLINE)
+ if ((volatile int)mt->mt_state != MT_ONLINE)
return MSCP_FAILED;
return MSCP_DONE;
@@ -209,8 +214,10 @@ mtopen(dev, flag, fmt, p)
return EBUSY;
mt->mt_inuse = 1;
- if (mt_putonline(mt) == MSCP_FAILED)
+ if (mt_putonline(mt) == MSCP_FAILED) {
+ mt->mt_inuse = 0;
return EIO;
+ }
return 0;
}
@@ -269,20 +276,20 @@ bad:
int
mtread(dev, uio)
- dev_t dev;
- struct uio *uio;
+ dev_t dev;
+ struct uio *uio;
{
- return (physio(mtstrategy, NULL, dev, B_READ, minphys, uio));
+ return (physio(mtstrategy, NULL, dev, B_READ, minphys, uio));
}
int
mtwrite(dev, uio)
- dev_t dev;
- struct uio *uio;
+ dev_t dev;
+ struct uio *uio;
{
- return (physio(mtstrategy, NULL, dev, B_WRITE, minphys, uio));
+ return (physio(mtstrategy, NULL, dev, B_WRITE, minphys, uio));
}
void
@@ -363,12 +370,12 @@ static char *mt_ioerrs[] = {
"unit offline", /* 3 M_ST_OFFLINE */
"unknown", /* 4 M_ST_AVAILABLE */
"unknown", /* 5 M_ST_MFMTERR */
- "unit write protected", /* 6 M_ST_WRPROT */
+ "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 */
+ "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 */
+ "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 */
@@ -401,6 +408,7 @@ mtioerror(usc, mp, bp)
else
printf("%s: error %d\n", mt->mt_dev.dv_xname, st);
bp->b_flags |= B_ERROR;
+ bp->b_error = EROFS;
}
return (MSCP_DONE);
@@ -421,7 +429,7 @@ mtioctl(dev, cmd, data, flag, p)
register struct mt_softc *mt = mt_cd.cd_devs[unit];
struct mtop *mtop;
struct mtget *mtget;
- int error = 0, i, count;
+ int error = 0, count;
count = mtop->mt_count;
@@ -455,8 +463,8 @@ mtioctl(dev, cmd, data, flag, p)
int
mtdump(dev, blkno, va, size)
dev_t dev;
- daddr_t blkno;
- caddr_t va;
+ daddr_t blkno;
+ caddr_t va;
size_t size;
{
return -1;
@@ -536,7 +544,7 @@ mtcmd(mt, cmd, count, complete)
break;
}
- i = *mi->mi_ip;
+ i = bus_space_read_2(mi->mi_iot, mi->mi_iph, 0);
tsleep(&mt->mt_inuse, PRIBIO, "mtioctl", 0);
return mt->mt_ioctlerr;
}
diff --git a/sys/arch/vax/mscp/mscpreg.h b/sys/arch/vax/mscp/mscpreg.h
index 065996ada8d..660ab4638c9 100644
--- a/sys/arch/vax/mscp/mscpreg.h
+++ b/sys/arch/vax/mscp/mscpreg.h
@@ -1,5 +1,5 @@
-/* $OpenBSD: mscpreg.h,v 1.3 1997/09/10 11:54:42 maja Exp $ */
-/* $NetBSD: mscpreg.h,v 1.2 1997/03/15 16:39:20 ragge Exp $ */
+/* $OpenBSD: mscpreg.h,v 1.4 2000/04/27 03:14:46 bjc Exp $ */
+/* $NetBSD: mscpreg.h,v 1.4 1999/05/29 19:12:53 ragge Exp $ */
/*
* Copyright (c) 1996 Ludd, University of Lule}, Sweden.
* Copyright (c) 1988 Regents of the University of California.
@@ -46,11 +46,11 @@
* If you get warnings about your command ring being too small,
* try increasing the values by one.
*/
-#ifndef NRSP
-#define NRSPL2 5
-#define NCMDL2 5
-#define NRSP (1 << NRSPL2)
-#define NCMD (1 << NCMDL2)
+#ifndef NRSP
+#define NRSPL2 5
+#define NCMDL2 5
+#define NRSP (1 << NRSPL2)
+#define NCMD (1 << NCMDL2)
#endif
/*
@@ -97,30 +97,30 @@ struct mscp_pack {
/*
* 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 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 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 STEP2MASK (ALLSTEPS | MP_IE | MP_IVECMASK)
+#define STEP2GOOD(iv) (MP_STEP3 | MP_IE | (iv))
-#define STEP3MASK ALLSTEPS
-#define STEP3GOOD MP_STEP4
+#define STEP3MASK ALLSTEPS
+#define STEP3GOOD MP_STEP4
diff --git a/sys/arch/vax/mscp/mscpvar.h b/sys/arch/vax/mscp/mscpvar.h
index 3a2b6cd24c3..0e0654be62b 100644
--- a/sys/arch/vax/mscp/mscpvar.h
+++ b/sys/arch/vax/mscp/mscpvar.h
@@ -1,5 +1,5 @@
-/* $OpenBSD: mscpvar.h,v 1.2 1997/05/29 00:05:04 niklas Exp $ */
-/* $NetBSD: mscpvar.h,v 1.4 1997/01/11 11:20:36 ragge Exp $ */
+/* $OpenBSD: mscpvar.h,v 1.3 2000/04/27 03:14:46 bjc Exp $ */
+/* $NetBSD: mscpvar.h,v 1.7 1999/06/06 19:16:18 ragge Exp $ */
/*
* Copyright (c) 1996 Ludd, University of Lule}, Sweden.
* Copyright (c) 1988 Regents of the University of California.
@@ -70,11 +70,21 @@ struct mscp_ri {
struct mscp *mri_ring; /* base address of packets */
};
+/*
+ * Transfer info, one per command packet.
+ */
+struct mscp_xi {
+ bus_dmamap_t mxi_dmam; /* Allocated DMA map for this entry */
+ struct buf * mxi_bp; /* Buffer used in this command */
+ struct mscp * mxi_mp; /* Packet used in this command */
+ int mxi_inuse;
+};
+
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 *));
+ __P((struct device *));
+ void (*mc_go) /* device-specific start routine */
+ __P((struct device *, struct mscp_xi *));
void (*mc_saerror) /* ctlr error handling */
__P((struct device *, int));
};
@@ -88,7 +98,7 @@ struct mscp_device {
__P((struct device *, struct buf *));
int (*me_online) /* drive on line */
__P((struct device *, struct mscp *));
- int (*me_gotstatus) /* got unit status */
+ int (*me_gotstatus) /* got unit status */
__P((struct device *, struct mscp *));
void (*me_replace) /* replace done */
__P((struct device *, struct mscp *));
@@ -109,20 +119,22 @@ 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) */
+ bus_dmamap_t ma_dmam; /* This comm area dma info */
+ bus_dma_tag_t ma_dmat;
+ bus_space_tag_t ma_iot;
+ bus_space_handle_t ma_iph; /* initialisation and polling */
+ bus_space_handle_t ma_sah; /* status & address (read part) */
+ bus_space_handle_t ma_swh; /* 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 */
+#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.
@@ -158,11 +170,13 @@ 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 */
+ bus_dma_tag_t mi_dmat;
+ bus_dmamap_t mi_dmam;
+ struct mscp_xi mi_xi[NCMD];
+ int mi_mxiuse; /* Bitfield of inuse mxi packets */
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 */
@@ -171,21 +185,21 @@ struct mscp_softc {
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 */
+ bus_space_tag_t mi_iot;
+ bus_space_handle_t mi_iph; /* initialisation and polling */
+ bus_space_handle_t mi_sah; /* status & address (read part) */
+ bus_space_handle_t mi_swh; /* status & address (write part) */
+ SIMPLEQ_HEAD(, buf) mi_resq; /* While waiting for packets */
};
/* mi_flags */
-#define MSC_STARTPOLL 1
-#define MSC_INSTART 2
-#define MSC_IGNOREINTR 4
-#define MSC_READY 8
+#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.
@@ -221,24 +235,6 @@ struct mscp_softc {
} \
}
-/*
- * 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 *));
@@ -251,5 +247,5 @@ 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_dgo __P((struct mscp_softc *, struct mscp_xi *));
void mscp_intr __P((struct mscp_softc *));
diff --git a/sys/arch/vax/uba/dhu.c b/sys/arch/vax/qbus/dhu.c
index a3c2089a37a..a28a8b77fc3 100644
--- a/sys/arch/vax/uba/dhu.c
+++ b/sys/arch/vax/qbus/dhu.c
@@ -1,5 +1,5 @@
-/* $OpenBSD: dhu.c,v 1.4 1997/05/29 00:05:05 niklas Exp $ */
-/* $NetBSD: dhu.c,v 1.9 1997/01/11 11:34:41 ragge Exp $ */
+/* $OpenBSD: dhu.c,v 1.1 2000/04/27 03:14:47 bjc Exp $ */
+/* $NetBSD: dhu.c,v 1.17 2000/01/24 02:40:28 matt Exp $ */
/*
* Copyright (c) 1996 Ken C. Wellsch. All rights reserved.
* Copyright (c) 1992, 1993
@@ -51,11 +51,11 @@
#include <sys/syslog.h>
#include <sys/device.h>
-#include <machine/trap.h>
+#include <machine/bus.h>
+#include <machine/scb.h>
-#include <vax/uba/ubavar.h>
-
-#include <vax/uba/dhureg.h>
+#include <arch/vax/qbus/ubavar.h>
+#include <arch/vax/qbus/dhureg.h>
/* A DHU-11 has 16 ports while a DHV-11 has only 8. We use 16 by default */
@@ -66,12 +66,14 @@
struct dhu_softc {
struct device sc_dev; /* Device struct used by config */
- dhuregs * sc_addr; /* controller reg address */
int sc_type; /* controller type, DHU or DHV */
+ bus_space_tag_t sc_iot;
+ bus_space_handle_t sc_ioh;
+ bus_dma_tag_t sc_dmat;
struct {
struct tty *dhu_tty; /* what we work on */
+ bus_dmamap_t dhu_dmah;
int dhu_state; /* to manage TX output status */
- int dhu_txaddr; /* UBA map address to TX buf */
short dhu_cc; /* character count on TX */
short dhu_modem; /* modem bits state */
} sc_dhu[NDHULINE];
@@ -95,6 +97,16 @@ struct dhu_softc {
#define DML_DSR TIOCM_DSR
#define DML_BRK 0100000 /* no equivalent, we will mask */
+#define DHU_READ_WORD(reg) \
+ bus_space_read_2(sc->sc_iot, sc->sc_ioh, reg)
+#define DHU_WRITE_WORD(reg, val) \
+ bus_space_write_2(sc->sc_iot, sc->sc_ioh, reg, val)
+#define DHU_READ_BYTE(reg) \
+ bus_space_read_1(sc->sc_iot, sc->sc_ioh, reg)
+#define DHU_WRITE_BYTE(reg, val) \
+ bus_space_write_1(sc->sc_iot, sc->sc_ioh, reg, val)
+
+
/* On a stock DHV, channel pairs (0/1, 2/3, etc.) must use */
/* a baud rate from the same group. So limiting to B is likely */
/* best, although clone boards like the ABLE QHV allow all settings. */
@@ -120,10 +132,10 @@ static struct speedtab dhuspeedtab[] = {
{ -1, -1 }
};
-static int dhu_match __P((struct device *, void *, void *));
+static int dhu_match __P((struct device *, struct cfdata *, void *));
static void dhu_attach __P((struct device *, struct device *, void *));
-static void dhurint __P((int));
-static void dhuxint __P((int));
+static void dhurint __P((void *));
+static void dhuxint __P((void *));
static void dhustart __P((struct tty *));
static int dhuparam __P((struct tty *, struct termios *));
static int dhuiflow __P((struct tty *, int));
@@ -136,38 +148,38 @@ static unsigned dhumctl __P((struct dhu_softc *,int, int, int));
void dhustop __P((struct tty *, int));
struct tty * dhutty __P((dev_t));
-struct cfdriver dhu_cd = {
- NULL, "dhu", DV_TTY
+struct cfattach dhu_ca = {
+ sizeof(struct dhu_softc), (cfmatch_t)dhu_match, dhu_attach
};
-struct cfattach dhu_ca = {
- sizeof(struct dhu_softc), dhu_match, dhu_attach
+struct cfdriver dhu_cd = {
+ NULL, "dhu", DV_TTY
};
/* Autoconfig handles: setup the controller to interrupt, */
/* then complete the housecleaning for full operation */
static int
-dhu_match(parent, match, aux)
+dhu_match(parent, cf, aux)
struct device *parent;
- void *match, *aux;
+ struct cfdata *cf;
+ void *aux;
{
struct uba_attach_args *ua = aux;
- register dhuregs *dhuaddr;
register int n;
- dhuaddr = (dhuregs *) ua->ua_addr;
-
/* Reset controller to initialize, enable TX/RX interrupts */
/* to catch floating vector info elsewhere when completed */
- dhuaddr->dhu_csr = (DHU_CSR_MASTER_RESET | DHU_CSR_RXIE | DHU_CSR_TXIE);
+ bus_space_write_2(ua->ua_iot, ua->ua_ioh, DHU_UBA_CSR,
+ DHU_CSR_MASTER_RESET | DHU_CSR_RXIE | DHU_CSR_TXIE);
/* Now wait up to 3 seconds for self-test to complete. */
for (n = 0; n < 300; n++) {
DELAY(10000);
- if ((dhuaddr->dhu_csr & DHU_CSR_MASTER_RESET) == 0)
+ if ((bus_space_read_2(ua->ua_iot, ua->ua_ioh, DHU_UBA_CSR) &
+ DHU_CSR_MASTER_RESET) == 0)
break;
}
@@ -179,13 +191,10 @@ dhu_match(parent, match, aux)
/* Check whether diagnostic run has signalled a failure. */
- if ((dhuaddr->dhu_csr & DHU_CSR_DIAG_FAIL) != 0)
+ if ((bus_space_read_2(ua->ua_iot, ua->ua_ioh, DHU_UBA_CSR) &
+ DHU_CSR_DIAG_FAIL) != 0)
return 0;
- /* Register the RX interrupt handler */
-
- ua->ua_ivec = dhurint;
-
return 1;
}
@@ -196,18 +205,18 @@ dhu_attach(parent, self, aux)
{
register struct dhu_softc *sc = (void *)self;
register struct uba_attach_args *ua = aux;
- register dhuregs *dhuaddr;
register unsigned c;
- register int n;
-
- dhuaddr = (dhuregs *) ua->ua_addr;
+ register int n, i;
+ sc->sc_iot = ua->ua_iot;
+ sc->sc_ioh = ua->ua_ioh;
+ sc->sc_dmat = ua->ua_dmat;
/* Process the 8 bytes of diagnostic info put into */
/* the FIFO following the master reset operation. */
printf("\n%s:", self->dv_xname);
for (n = 0; n < 8; n++) {
- c = dhuaddr->dhu_rbuf;
+ c = DHU_READ_WORD(DHU_UBA_RBUF);
if ((c&DHU_DIAG_CODE) == DHU_DIAG_CODE) {
if ((c&0200) == 0000)
@@ -218,35 +227,43 @@ dhu_attach(parent, self, aux)
((c>>1)&01), ((c>>2)&07));
}
}
- printf("\n");
- c = dhuaddr->dhu_stat; /* get flag to distinguish DHU from DHV */
+ c = DHU_READ_WORD(DHU_UBA_STAT);
- sc->sc_addr = dhuaddr;
sc->sc_type = (c & DHU_STAT_DHU)? IS_DHU: IS_DHV;
+ printf("\n%s: DH%s-11\n", self->dv_xname, (c & DHU_STAT_DHU)?"U":"V");
+
+ for (i = 0; i < sc->sc_type; i++) {
+ struct tty *tp;
+ tp = sc->sc_dhu[i].dhu_tty = ttymalloc();
+ sc->sc_dhu[i].dhu_state = STATE_IDLE;
+ bus_dmamap_create(sc->sc_dmat, tp->t_outq.c_cn, 1,
+ tp->t_outq.c_cn, 0, BUS_DMA_ALLOCNOW|BUS_DMA_NOWAIT,
+ &sc->sc_dhu[i].dhu_dmah);
+ bus_dmamap_load(sc->sc_dmat, sc->sc_dhu[i].dhu_dmah,
+ tp->t_outq.c_cs, tp->t_outq.c_cn, 0, BUS_DMA_NOWAIT);
+
+ }
- /* Now stuff TX interrupt handler in place */
+ /* Now establish RX & TX interrupt handlers */
- ubasetvec(self, ua->ua_cvec + 1, dhuxint);
- return;
+ uba_intr_establish(ua->ua_icookie, ua->ua_cvec , dhurint, sc);
+ uba_intr_establish(ua->ua_icookie, ua->ua_cvec + 4, dhuxint, sc);
}
/* Receiver Interrupt */
static void
-dhurint(unit)
- int unit;
+dhurint(arg)
+ void *arg;
{
- struct dhu_softc *sc = dhu_cd.cd_devs[unit];
- register dhuregs *dhuaddr;
+ struct dhu_softc *sc = arg;
register struct tty *tp;
register int cc, line;
register unsigned c, delta;
int overrun = 0;
- dhuaddr = sc->sc_addr;
-
- while ((c = dhuaddr->dhu_rbuf) & DHU_RBUF_DATA_VALID) {
+ while ((c = DHU_READ_WORD(DHU_UBA_RBUF)) & DHU_RBUF_DATA_VALID) {
/* Ignore diagnostic FIFO entries. */
@@ -305,23 +322,19 @@ dhurint(unit)
(*linesw[tp->t_line].l_rint)(cc, tp);
}
- return;
}
/* Transmitter Interrupt */
static void
-dhuxint(unit)
- int unit;
+dhuxint(arg)
+ void *arg;
{
- register struct dhu_softc *sc = dhu_cd.cd_devs[unit];
- register dhuregs *dhuaddr;
+ register struct dhu_softc *sc = arg;
register struct tty *tp;
register int line;
- dhuaddr = sc->sc_addr;
-
- line = DHU_LINE(dhuaddr->dhu_csr_hi);
+ line = DHU_LINE(DHU_READ_BYTE(DHU_UBA_CSR_HI));
tp = sc->sc_dhu[line].dhu_tty;
@@ -330,7 +343,8 @@ dhuxint(unit)
tp->t_state &= ~TS_FLUSH;
else {
if (sc->sc_dhu[line].dhu_state == STATE_DMA_STOPPED)
- sc->sc_dhu[line].dhu_cc -= dhuaddr->dhu_tbufcnt;
+ sc->sc_dhu[line].dhu_cc -=
+ DHU_READ_WORD(DHU_UBA_TBUFCNT);
ndflush(&tp->t_outq, sc->sc_dhu[line].dhu_cc);
sc->sc_dhu[line].dhu_cc = 0;
}
@@ -341,8 +355,6 @@ dhuxint(unit)
(*linesw[tp->t_line].l_start)(tp);
else
dhustart(tp);
-
- return;
}
int
@@ -351,7 +363,6 @@ dhuopen(dev, flag, mode, p)
int flag, mode;
struct proc *p;
{
- register dhuregs *dhuaddr;
register struct tty *tp;
register int unit, line;
struct dhu_softc *sc;
@@ -368,33 +379,18 @@ dhuopen(dev, flag, mode, p)
if (line >= sc->sc_type)
return ENXIO;
- tp = sc->sc_dhu[line].dhu_tty;
- if (tp == NULL) {
-
- tp = sc->sc_dhu[line].dhu_tty = ttymalloc();
- if (tp == NULL)
- return ENXIO;
-
- sc->sc_dhu[line].dhu_state = STATE_IDLE;
-
- 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;
+ s = spltty();
+ DHU_WRITE_BYTE(DHU_UBA_CSR, DHU_CSR_RXIE | line);
+ sc->sc_dhu[line].dhu_modem = DHU_READ_WORD(DHU_UBA_STAT);
+ (void) splx(s);
- s = spltty();
- dhuaddr->dhu_csr_lo = (DHU_CSR_RXIE | line);
- sc->sc_dhu[line].dhu_modem = dhuaddr->dhu_stat;
- (void) splx(s);
- }
+ tp = sc->sc_dhu[line].dhu_tty;
tp->t_oproc = dhustart;
tp->t_param = dhuparam;
tp->t_hwiflow = dhuiflow;
tp->t_dev = dev;
if ((tp->t_state & TS_ISOPEN) == 0) {
- tp->t_state |= TS_WOPEN;
ttychars(tp);
if (tp->t_ispeed == 0) {
tp->t_iflag = TTYDEF_IFLAG;
@@ -413,7 +409,6 @@ dhuopen(dev, flag, mode, p)
s = spltty();
while (!(flag & O_NONBLOCK) && !(tp->t_cflag & CLOCAL) &&
!(tp->t_state & TS_CARR_ON)) {
- tp->t_state |= TS_WOPEN;
error = ttysleep(tp, (caddr_t)&tp->t_rawq,
TTIPRI | PCATCH, ttopen, 0);
if (error)
@@ -451,9 +446,8 @@ dhuclose(dev, flag, mode, p)
/* Do a hangup if so required. */
- if ((tp->t_cflag & HUPCL) || (tp->t_state & TS_WOPEN) ||
- !(tp->t_state & TS_ISOPEN))
- (void) dhumctl(sc, line, 0, DMSET);
+ if ((tp->t_cflag & HUPCL) || !(tp->t_state & TS_ISOPEN))
+ (void) dhumctl(sc, line, 0, DMSET);
return (ttyclose(tp));
}
@@ -567,7 +561,6 @@ dhustop(tp, flag)
register struct tty *tp;
{
register struct dhu_softc *sc;
- register dhuregs *dhuaddr;
register int line;
int s;
@@ -582,9 +575,10 @@ dhustop(tp, flag)
sc->sc_dhu[line].dhu_state = STATE_DMA_STOPPED;
- dhuaddr = sc->sc_addr;
- dhuaddr->dhu_csr_lo = (DHU_CSR_RXIE | line);
- dhuaddr->dhu_lnctrl |= DHU_LNCTRL_DMA_ABORT;
+ DHU_WRITE_BYTE(DHU_UBA_CSR, DHU_CSR_RXIE | line);
+ DHU_WRITE_WORD(DHU_UBA_LNCTRL,
+ DHU_READ_WORD(DHU_UBA_LNCTRL) |
+ DHU_LNCTRL_DMA_ABORT);
}
if (!(tp->t_state & TS_TTSTOP))
@@ -598,7 +592,6 @@ dhustart(tp)
register struct tty *tp;
{
register struct dhu_softc *sc;
- register dhuregs *dhuaddr;
register int line, cc;
register int addr;
int s;
@@ -625,30 +618,32 @@ dhustart(tp)
line = DHU_LINE(minor(tp->t_dev));
- dhuaddr = sc->sc_addr;
- dhuaddr->dhu_csr_lo = (DHU_CSR_RXIE | line);
+ DHU_WRITE_BYTE(DHU_UBA_CSR, DHU_CSR_RXIE | line);
sc->sc_dhu[line].dhu_cc = cc;
if (cc == 1) {
sc->sc_dhu[line].dhu_state = STATE_TX_ONE_CHAR;
- dhuaddr->dhu_txchar = DHU_TXCHAR_DATA_VALID | *tp->t_outq.c_cf;
+
+ DHU_WRITE_WORD(DHU_UBA_TXCHAR,
+ DHU_TXCHAR_DATA_VALID | *tp->t_outq.c_cf);
} else {
sc->sc_dhu[line].dhu_state = STATE_DMA_RUNNING;
- addr = UBAI_ADDR(sc->sc_dhu[line].dhu_txaddr) +
+ addr = sc->sc_dhu[line].dhu_dmah->dm_segs[0].ds_addr +
(tp->t_outq.c_cf - tp->t_outq.c_cs);
- dhuaddr->dhu_tbufcnt = cc;
- dhuaddr->dhu_tbufad1 = (addr & 0xFFFF);
- dhuaddr->dhu_tbufad2 = ((addr>>16) & 0x3F) |
- DHU_TBUFAD2_TX_ENABLE;
-
- dhuaddr->dhu_lnctrl &= ~DHU_LNCTRL_DMA_ABORT;
- dhuaddr->dhu_tbufad2 |= DHU_TBUFAD2_DMA_START;
+ DHU_WRITE_WORD(DHU_UBA_TBUFCNT, cc);
+ DHU_WRITE_WORD(DHU_UBA_TBUFAD1, addr & 0xFFFF);
+ DHU_WRITE_WORD(DHU_UBA_TBUFAD2, ((addr>>16) & 0x3F) |
+ DHU_TBUFAD2_TX_ENABLE);
+ DHU_WRITE_WORD(DHU_UBA_LNCTRL,
+ DHU_READ_WORD(DHU_UBA_LNCTRL) & ~DHU_LNCTRL_DMA_ABORT);
+ DHU_WRITE_WORD(DHU_UBA_TBUFAD2,
+ DHU_READ_WORD(DHU_UBA_TBUFAD2) | DHU_TBUFAD2_DMA_START);
}
out:
(void) splx(s);
@@ -661,7 +656,6 @@ dhuparam(tp, t)
register struct termios *t;
{
struct dhu_softc *sc;
- register dhuregs *dhuaddr;
register int cflag = t->c_cflag;
int ispeed = ttspeedtab(t->c_ispeed, dhuspeedtab);
int ospeed = ttspeedtab(t->c_ospeed, dhuspeedtab);
@@ -688,8 +682,7 @@ dhuparam(tp, t)
}
s = spltty();
- dhuaddr = sc->sc_addr;
- dhuaddr->dhu_csr_lo = (DHU_CSR_RXIE | line);
+ DHU_WRITE_BYTE(DHU_UBA_CSR, DHU_CSR_RXIE | line);
lpr = ((ispeed&017)<<8) | ((ospeed&017)<<12) ;
@@ -719,11 +712,12 @@ dhuparam(tp, t)
if (cflag & CSTOPB)
lpr |= DHU_LPR_2_STOP;
- dhuaddr->dhu_lpr = lpr;
+ DHU_WRITE_WORD(DHU_UBA_LPR, lpr);
- dhuaddr->dhu_tbufad2 |= DHU_TBUFAD2_TX_ENABLE;
+ DHU_WRITE_WORD(DHU_UBA_TBUFAD2,
+ DHU_READ_WORD(DHU_UBA_TBUFAD2) | DHU_TBUFAD2_TX_ENABLE);
- lnctrl = dhuaddr->dhu_lnctrl;
+ lnctrl = DHU_READ_WORD(DHU_UBA_LNCTRL);
/* Setting LINK.TYPE enables modem signal change interrupts. */
@@ -741,7 +735,7 @@ dhuparam(tp, t)
else
lnctrl &= ~DHU_LNCTRL_IAUTO;
- dhuaddr->dhu_lnctrl = lnctrl;
+ DHU_WRITE_WORD(DHU_UBA_LNCTRL, lnctrl);
(void) splx(s);
return (0);
@@ -768,7 +762,6 @@ dhumctl(sc, line, bits, how)
struct dhu_softc *sc;
int line, bits, how;
{
- register dhuregs *dhuaddr;
register unsigned status;
register unsigned lnctrl;
register unsigned mbits;
@@ -776,14 +769,13 @@ dhumctl(sc, line, bits, how)
s = spltty();
- dhuaddr = sc->sc_addr;
- dhuaddr->dhu_csr_lo = (DHU_CSR_RXIE | line);
+ DHU_WRITE_BYTE(DHU_UBA_CSR, DHU_CSR_RXIE | line);
mbits = 0;
/* external signals as seen from the port */
- status = dhuaddr->dhu_stat;
+ status = DHU_READ_WORD(DHU_UBA_STAT);
if (status & DHU_STAT_CTS)
mbits |= DML_CTS;
@@ -799,7 +791,7 @@ dhumctl(sc, line, bits, how)
/* internal signals/state delivered to port */
- lnctrl = dhuaddr->dhu_lnctrl;
+ lnctrl = DHU_READ_WORD(DHU_UBA_LNCTRL);
if (lnctrl & DHU_LNCTRL_RTS)
mbits |= DML_RTS;
@@ -844,7 +836,7 @@ dhumctl(sc, line, bits, how)
else
lnctrl &= ~DHU_LNCTRL_BREAK;
- dhuaddr->dhu_lnctrl = lnctrl;
+ DHU_WRITE_WORD(DHU_UBA_LNCTRL, lnctrl);
(void) splx(s);
return (mbits);
diff --git a/sys/arch/vax/uba/dhureg.h b/sys/arch/vax/qbus/dhureg.h
index 9db5650a392..32b4291d87b 100644
--- a/sys/arch/vax/uba/dhureg.h
+++ b/sys/arch/vax/qbus/dhureg.h
@@ -1,5 +1,5 @@
-/* $OpenBSD: dhureg.h,v 1.2 1997/05/29 00:05:05 niklas Exp $ */
-/* $NetBSD: dhureg.h,v 1.2 1996/03/17 22:51:50 ragge Exp $ */
+/* $OpenBSD: dhureg.h,v 1.1 2000/04/27 03:14:47 bjc Exp $ */
+/* $NetBSD: dhureg.h,v 1.4 1999/05/28 20:17:29 ragge Exp $ */
/*
* Copyright (c) 1996 Ken C. Wellsch. All rights reserved.
*
@@ -32,6 +32,7 @@
* SUCH DAMAGE.
*/
+#ifdef notdef
union w_b
{
u_short word;
@@ -59,6 +60,18 @@ struct DHUregs
#define dhu_csr_hi u_csr.bytes.byte_hi
typedef struct DHUregs dhuregs;
+#endif
+
+#define DHU_UBA_CSR 0
+#define DHU_UBA_CSR_HI 1
+#define DHU_UBA_RBUF 2
+#define DHU_UBA_TXCHAR 2
+#define DHU_UBA_LPR 4
+#define DHU_UBA_STAT 6
+#define DHU_UBA_LNCTRL 8
+#define DHU_UBA_TBUFAD1 10
+#define DHU_UBA_TBUFAD2 12
+#define DHU_UBA_TBUFCNT 14
/* CSR bits */
diff --git a/sys/arch/vax/uba/dl.c b/sys/arch/vax/qbus/dl.c
index 80c8be5d5ad..7bd7d71859c 100644
--- a/sys/arch/vax/uba/dl.c
+++ b/sys/arch/vax/qbus/dl.c
@@ -1,9 +1,45 @@
-/* $OpenBSD: dl.c,v 1.2 1998/05/11 14:59:05 niklas Exp $ */
-/* $NetBSD: dl.c,v 1.1 1997/02/04 19:13:18 ragge Exp $ */
+/* $OpenBSD: dl.c,v 1.1 2000/04/27 03:14:47 bjc Exp $ */
+/* $NetBSD: dl.c,v 1.11 2000/01/24 02:40:29 matt Exp $ */
+
+/*-
+ * Copyright (c) 1996, 1997 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Jason R. Thorpe.
+ *
+ * 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 NetBSD
+ * Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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.
+ */
+
/*
* Copyright (c) 1997 Ben Harris. All rights reserved.
* Copyright (c) 1996 Ken C. Wellsch. All rights reserved.
- * Copyright (c) 1995, 1996 Jason R. Thorpe. All rights reserved.
* Copyright (c) 1982, 1986, 1990, 1992, 1993
* The Regents of the University of California. All rights reserved.
*
@@ -59,27 +95,23 @@
#include <sys/syslog.h>
#include <sys/device.h>
-#include <machine/pte.h>
-#include <machine/trap.h>
-
-#include <vax/uba/ubareg.h>
-#include <vax/uba/ubavar.h>
+#include <machine/bus.h>
+#include <machine/scb.h>
-#include <vax/uba/dlreg.h>
-
-#define DL_I2C(i) (i)
-#define DL_C2I(c) (c)
+#include <arch/vax/qbus/ubavar.h>
+#include <arch/vax/qbus/dlreg.h>
struct dl_softc {
struct device sc_dev;
- dlregs* sc_addr;
- struct tty* sc_tty;
+ bus_space_tag_t sc_iot;
+ bus_space_handle_t sc_ioh;
+ struct tty *sc_tty;
};
-static int dl_match __P((struct device *, void *, void *));
+static int dl_match __P((struct device *, struct cfdata *, void *));
static void dl_attach __P((struct device *, struct device *, void *));
-static void dlrint __P((int));
-static void dlxint __P((int));
+static void dlrint __P((void *));
+static void dlxint __P((void *));
static void dlstart __P((struct tty *));
static int dlparam __P((struct tty *, struct termios *));
static void dlbrk __P((struct dl_softc *, int));
@@ -91,35 +123,43 @@ struct tty * dltty __P((dev_t));
int dlioctl __P((dev_t, int, caddr_t, int, struct proc *));
void dlstop __P((struct tty *, int));
-struct cfdriver dl_cd = {
- NULL, "dl", DV_TTY
+struct cfattach dl_ca = {
+ sizeof(struct dl_softc), (cfmatch_t)dl_match, dl_attach
};
-struct cfattach dl_ca = {
- sizeof(struct dl_softc), dl_match, dl_attach
+struct cfdriver dl_cd = {
+ NULL, "dl", DV_TTY
};
+#define DL_READ_WORD(reg) \
+ bus_space_read_2(sc->sc_iot, sc->sc_ioh, reg)
+#define DL_WRITE_WORD(reg, val) \
+ bus_space_write_2(sc->sc_iot, sc->sc_ioh, reg, val)
+#define DL_WRITE_BYTE(reg, val) \
+ bus_space_write_1(sc->sc_iot, sc->sc_ioh, reg, val)
+
/* Autoconfig handles: setup the controller to interrupt, */
/* then complete the housecleaning for full operation */
static int
-dl_match (parent, match, aux)
+dl_match (parent, cf, aux)
struct device * parent;
- void *match, *aux;
+ struct cfdata *cf;
+ void *aux;
{
struct uba_attach_args *ua = aux;
- register dlregs *dladdr;
- dladdr = (dlregs*) ua->ua_addr;
#ifdef DL_DEBUG
- printf("Probing for dl at %lo ... ", (long)dladdr);
+ printf("Probing for dl at %lo ... ", (long)ua->ua_iaddr);
#endif
- dladdr->dl_xcsr = DL_XCSR_TXIE;
- if (dladdr->dl_xcsr != (DL_XCSR_TXIE | DL_XCSR_TX_READY)) {
+ bus_space_write_2(ua->ua_iot, ua->ua_ioh, DL_UBA_XCSR, DL_XCSR_TXIE);
+ if (bus_space_read_2(ua->ua_iot, ua->ua_ioh, DL_UBA_XCSR) !=
+ (DL_XCSR_TXIE | DL_XCSR_TX_READY)) {
#ifdef DL_DEBUG
- printf("failed (step 1; XCSR = %.4b)\n", dladdr->dl_xcsr,
- DL_XCSR_BITS);
+ printf("failed (step 1; XCSR = %.4b)\n",
+ bus_space_read_2(ua->ua_iot, ua->ua_ioh, DL_UBA_XCSR),
+ DL_XCSR_BITS);
#endif
return 0;
}
@@ -132,7 +172,7 @@ dl_match (parent, match, aux)
* anything.
*/
- dladdr->u_xbuf.bytes.byte_lo = '\0';
+ bus_space_write_1(ua->ua_iot, ua->ua_ioh, DL_UBA_XBUFL, '\0');
#if 0 /* This test seems to fail 2/3 of the time :-( */
if (dladdr->dl_xcsr != (DL_XCSR_TXIE)) {
#ifdef DL_DEBUG
@@ -143,16 +183,16 @@ dl_match (parent, match, aux)
}
#endif
DELAY(100000); /* delay 1/10 s for character to transmit */
- if (dladdr->dl_xcsr != (DL_XCSR_TXIE | DL_XCSR_TX_READY)) {
+ if (bus_space_read_2(ua->ua_iot, ua->ua_ioh, DL_UBA_XCSR) !=
+ (DL_XCSR_TXIE | DL_XCSR_TX_READY)) {
#ifdef DL_DEBUG
- printf("failed (step 3; XCSR = %.4b)\n", dladdr->dl_xcsr,
- DL_XCSR_BITS);
+ printf("failed (step 3; XCSR = %.4b)\n",
+ bus_space_read_2(ua->ua_iot, ua->ua_ioh, DL_UBA_XCSR),
+ DL_XCSR_BITS);
#endif
return 0;
}
- /* Register the TX interrupt handler */
- ua->ua_ivec = dlxint;
/* What else do I need to do? */
@@ -165,47 +205,42 @@ dl_attach (parent, self, aux)
struct device *parent, *self;
void *aux;
{
- struct uba_softc *uh = (void *)parent;
struct dl_softc *sc = (void *)self;
register struct uba_attach_args *ua = aux;
- register dlregs *dladdr;
- dladdr = (dlregs *) ua->ua_addr;
- sc->sc_addr = dladdr;
+ sc->sc_iot = ua->ua_iot;
+ sc->sc_ioh = ua->ua_ioh;
/* Tidy up the device */
- dladdr->dl_rcsr = DL_RCSR_RXIE;
- dladdr->dl_xcsr = DL_XCSR_TXIE;
+ DL_WRITE_WORD(DL_UBA_RCSR, DL_RCSR_RXIE);
+ DL_WRITE_WORD(DL_UBA_XCSR, DL_XCSR_TXIE);
/* Initialize our softc structure. Should be done in open? */
sc->sc_tty = ttymalloc();
tty_attach(sc->sc_tty);
- /* Now register the RX interrupt handler */
- ubasetvec(self, ua->ua_cvec-1, dlrint);
+ /* Now register the TX & RX interrupt handlers */
+ uba_intr_establish(ua->ua_icookie, ua->ua_cvec , dlxint, sc);
+ uba_intr_establish(ua->ua_icookie, ua->ua_cvec - 4, dlrint, sc);
printf("\n");
- return;
}
/* Receiver Interrupt Handler */
static void
-dlrint(cntlr)
- int cntlr;
+dlrint(arg)
+ void *arg;
{
- struct dl_softc *sc = dl_cd.cd_devs[cntlr];
- volatile dlregs *dladdr;
+ struct dl_softc *sc = arg;
register struct tty *tp;
register int cc;
register unsigned c;
- dladdr = sc->sc_addr;
-
- if (dladdr->dl_rcsr & DL_RCSR_RX_DONE) {
- c = dladdr->dl_rbuf;
+ if (DL_READ_WORD(DL_UBA_RCSR) & DL_RCSR_RX_DONE) {
+ c = DL_READ_WORD(DL_UBA_RBUF);
cc = c & 0xFF;
tp = sc->sc_tty;
@@ -236,14 +271,12 @@ dlrint(cntlr)
/* Transmitter Interrupt Handler */
static void
-dlxint(cntlr)
- int cntlr;
+dlxint(arg)
+ void *arg;
{
- struct dl_softc *sc = dl_cd.cd_devs[cntlr];
- volatile dlregs *dladdr;
+ struct dl_softc *sc = arg;
register struct tty *tp;
- dladdr = sc->sc_addr;
tp = sc->sc_tty;
tp->t_state &= ~(TS_BUSY | TS_FLUSH);
if (tp->t_line)
@@ -263,9 +296,8 @@ dlopen(dev, flag, mode, p)
register struct tty *tp;
register int unit;
struct dl_softc *sc;
- int s, error = 0;
- unit = DL_I2C(minor(dev));
+ unit = minor(dev);
if (unit >= dl_cd.cd_ndevs || dl_cd.cd_devs[unit] == NULL)
return ENXIO;
@@ -279,7 +311,6 @@ dlopen(dev, flag, mode, p)
tp->t_dev = dev;
if (!(tp->t_state & TS_ISOPEN)) {
- tp->t_state |= TS_WOPEN;
ttychars(tp);
tp->t_iflag = TTYDEF_IFLAG;
tp->t_oflag = TTYDEF_OFLAG;
@@ -308,7 +339,7 @@ dlclose(dev, flag, mode, p)
register struct tty *tp;
register int unit;
- unit = DL_I2C(minor(dev));
+ unit = minor(dev);
sc = dl_cd.cd_devs[unit];
tp = sc->sc_tty;
@@ -330,7 +361,7 @@ dlread(dev, uio, flag)
struct dl_softc *sc;
register int unit;
- unit = DL_I2C(minor(dev));
+ unit = minor(dev);
sc = dl_cd.cd_devs[unit];
tp = sc->sc_tty;
return ((*linesw[tp->t_line].l_read)(tp, uio, flag));
@@ -346,7 +377,7 @@ dlwrite(dev, uio, flag)
struct dl_softc *sc;
register int unit;
- unit = DL_I2C(minor(dev));
+ unit = minor(dev);
sc = dl_cd.cd_devs[unit];
tp = sc->sc_tty;
return ((*linesw[tp->t_line].l_write)(tp, uio, flag));
@@ -365,7 +396,7 @@ dlioctl(dev, cmd, data, flag, p)
register int unit;
int error;
- unit = DL_I2C(minor(dev));
+ unit = minor(dev);
sc = dl_cd.cd_devs[unit];
tp = sc->sc_tty;
@@ -403,7 +434,7 @@ dltty(dev)
{
register struct dl_softc* sc;
- sc = dl_cd.cd_devs[DL_I2C(minor(dev))];
+ sc = dl_cd.cd_devs[minor(dev)];
return sc->sc_tty;
}
@@ -415,7 +446,7 @@ dlstop(tp, flag)
register struct dl_softc *sc;
int unit, s;
- unit = DL_I2C(minor(tp->t_dev));
+ unit = minor(tp->t_dev);
sc = dl_cd.cd_devs[unit];
s = spltty();
@@ -431,11 +462,10 @@ dlstart(tp)
register struct tty *tp;
{
register struct dl_softc *sc;
- register dlregs *dladdr;
- register int unit, cc;
+ register int unit;
int s;
- unit = DL_I2C(minor(tp->t_dev));
+ unit = minor(tp->t_dev);
sc = dl_cd.cd_devs[unit];
s = spltty();
@@ -451,11 +481,10 @@ dlstart(tp)
if (tp->t_outq.c_cc == 0)
goto out;
- dladdr = sc->sc_addr;
- if (dladdr->dl_xcsr & DL_XCSR_TX_READY) {
+ if (DL_READ_WORD(DL_UBA_XCSR) & DL_XCSR_TX_READY) {
tp->t_state |= TS_BUSY;
- dladdr->u_xbuf.bytes.byte_lo = getc(&tp->t_outq);
+ DL_WRITE_BYTE(DL_UBA_XBUFL, getc(&tp->t_outq));
}
out:
splx(s);
@@ -481,13 +510,14 @@ dlbrk(sc, state)
register struct dl_softc *sc;
int state;
{
- register dlregs *dladdr;
- int s;
- dladdr = sc->sc_addr;
- s = spltty();
- if (state)
- dladdr->dl_xcsr |= DL_XCSR_TX_BREAK;
- else
- dladdr->dl_xcsr &= ~DL_XCSR_TX_BREAK;
+ int s = spltty();
+
+ if (state) {
+ DL_WRITE_WORD(DL_UBA_XCSR, DL_READ_WORD(DL_UBA_XCSR) |
+ DL_XCSR_TX_BREAK);
+ } else {
+ DL_WRITE_WORD(DL_UBA_XCSR, DL_READ_WORD(DL_UBA_XCSR) &
+ ~DL_XCSR_TX_BREAK);
+ }
splx(s);
}
diff --git a/sys/arch/vax/uba/dlreg.h b/sys/arch/vax/qbus/dlreg.h
index 120b283fb75..42462cb38e2 100644
--- a/sys/arch/vax/uba/dlreg.h
+++ b/sys/arch/vax/qbus/dlreg.h
@@ -1,5 +1,5 @@
-/* $OpenBSD: dlreg.h,v 1.2 1998/05/11 14:59:06 niklas Exp $ */
-/* $NetBSD: dlreg.h,v 1.1 1997/02/04 19:13:19 ragge Exp $ */
+/* $OpenBSD: dlreg.h,v 1.1 2000/04/27 03:14:47 bjc Exp $ */
+/* $NetBSD: dlreg.h,v 1.3 1999/05/27 16:02:04 ragge Exp $ */
/*
* Copyright (c) 1997 Ben Harris. All rights reserved.
*
@@ -37,6 +37,7 @@
* Style in imitation of dzreg.h.
*/
+#ifdef notdef
union w_b
{
u_short word;
@@ -56,6 +57,12 @@ struct DLregs
};
typedef struct DLregs dlregs;
+#endif
+
+#define DL_UBA_RCSR 0
+#define DL_UBA_RBUF 2
+#define DL_UBA_XCSR 4
+#define DL_UBA_XBUFL 6
/* RCSR bits */
diff --git a/sys/arch/vax/uba/dz.c b/sys/arch/vax/qbus/dz.c
index 9792b1521b9..a22b0daeaba 100644
--- a/sys/arch/vax/uba/dz.c
+++ b/sys/arch/vax/qbus/dz.c
@@ -1,5 +1,5 @@
-/* $OpenBSD: dz.c,v 1.3 1997/05/29 00:05:06 niklas Exp $ */
-/* $NetBSD: dz.c,v 1.4 1996/10/13 03:35:15 christos Exp $ */
+/* $OpenBSD: dz.c,v 1.1 2000/04/27 03:14:47 bjc Exp $ */
+/* $NetBSD: dz.c,v 1.19 2000/01/24 02:40:29 matt Exp $ */
/*
* Copyright (c) 1996 Ken C. Wellsch. All rights reserved.
* Copyright (c) 1992, 1993
@@ -51,13 +51,26 @@
#include <sys/syslog.h>
#include <sys/device.h>
+#ifdef DDB
+#include <dev/cons.h>
+#endif
+
+#include <machine/bus.h>
#include <machine/pte.h>
#include <machine/trap.h>
+#include <machine/cpu.h>
-#include <vax/uba/ubareg.h>
-#include <vax/uba/ubavar.h>
+#include <arch/vax/qbus/dzreg.h>
+#include <arch/vax/qbus/dzvar.h>
-#include <vax/uba/dzreg.h>
+#define DZ_READ_BYTE(adr) \
+ bus_space_read_1(sc->sc_iot, sc->sc_ioh, sc->sc_dr.adr)
+#define DZ_READ_WORD(adr) \
+ bus_space_read_2(sc->sc_iot, sc->sc_ioh, sc->sc_dr.adr)
+#define DZ_WRITE_BYTE(adr, val) \
+ bus_space_write_1(sc->sc_iot, sc->sc_ioh, sc->sc_dr.adr, val)
+#define DZ_WRITE_WORD(adr, val) \
+ bus_space_write_2(sc->sc_iot, sc->sc_ioh, sc->sc_dr.adr, val)
/* A DZ-11 has 8 ports while a DZV/DZQ-11 has only 4. We use 8 by default */
@@ -67,19 +80,6 @@
#define DZ_I2C(c) ((c)>>3) /* convert minor to controller # */
#define DZ_PORT(u) ((u)&07) /* extract the port # */
-struct dz_softc {
- struct device sc_dev; /* Autoconf blaha */
- dzregs * sc_addr; /* controller reg address */
- int sc_type; /* DZ11 or DZV11? */
- int sc_rxint; /* Receive interrupt count XXX */
- u_char sc_brk; /* Break asserted on some lines */
- struct {
- struct tty * dz_tty; /* what we work on */
- caddr_t dz_mem; /* pointers to clist output */
- caddr_t dz_end; /* allowing pdma action */
- } sc_dz[NDZLINE];
-};
-
/* Flags used to monitor modem bits, make them understood outside driver */
#define DML_DTR TIOCM_DTR
@@ -105,142 +105,65 @@ static struct speedtab dzspeedtab[] =
{ 4800, DZ_LPR_B4800 },
{ 7200, DZ_LPR_B7200 },
{ 9600, DZ_LPR_B9600 },
+ { 19200, DZ_LPR_B19200 },
{ -1, -1 }
};
-static int dz_match __P((struct device *, void *, void *));
-static void dz_attach __P((struct device *, struct device *, void *));
-static void dzrint __P((int));
-static void dzxint __P((int));
static void dzstart __P((struct tty *));
static int dzparam __P((struct tty *, struct termios *));
static unsigned dzmctl __P((struct dz_softc *, int, int, int));
static void dzscan __P((void *));
-struct tty * dztty __P((dev_t));
- int dzopen __P((dev_t, int, int, struct proc *));
- int dzclose __P((dev_t, int, int, struct proc *));
- int dzread __P((dev_t, struct uio *, int));
- int dzwrite __P((dev_t, struct uio *, int));
- int dzioctl __P((dev_t, int, caddr_t, int, struct proc *));
- void dzstop __P((struct tty *, int));
struct cfdriver dz_cd = {
NULL, "dz", DV_TTY
};
-struct cfattach dz_ca = {
- sizeof(struct dz_softc), dz_match, dz_attach
-};
-
+cdev_decl(dz);
/*
* The DZ series doesn't interrupt on carrier transitions,
* so we have to use a timer to watch it.
*/
-static int dz_timer = 0; /* true if timer started */
+int dz_timer = 0; /* true if timer started */
#define DZ_DZ 8 /* Unibus DZ-11 board linecount */
#define DZ_DZV 4 /* Q-bus DZV-11 or DZQ-11 */
-/* Autoconfig handles: setup the controller to interrupt, */
-/* then complete the housecleaning for full operation */
-
-static int
-dz_match (parent, match, aux)
- struct device *parent;
- void *match, *aux;
-{
- struct uba_attach_args *ua = aux;
- register dzregs *dzaddr;
- register int n;
-
- dzaddr = (dzregs *) ua->ua_addr;
-
- /* Reset controller to initialize, enable TX interrupts */
- /* to catch floating vector info elsewhere when completed */
-
- dzaddr->dz_csr = (DZ_CSR_MSE | DZ_CSR_TXIE);
- dzaddr->dz_tcr = 1; /* Force a TX interrupt */
-
- DELAY(100000); /* delay 1/10 second */
-
- dzaddr->dz_csr = DZ_CSR_RESET;
-
- /* Now wait up to 3 seconds for reset/clear to complete. */
-
- for (n = 0; n < 300; n++) {
- DELAY(10000);
- if ((dzaddr->dz_csr & DZ_CSR_RESET) == 0)
- break;
- }
-
- /* If the RESET did not clear after 3 seconds, */
- /* the controller must be broken. */
-
- if (n >= 300)
- return (0);
-
- /* Register the TX interrupt handler */
-
- ua->ua_ivec = dzxint;
-
- return (1);
-}
-
-static void
-dz_attach (parent, self, aux)
- struct device *parent, *self;
- void *aux;
+void
+dzattach(sc)
+ struct dz_softc *sc;
{
- struct uba_softc *uh = (void *)parent;
- struct dz_softc *sc = (void *)self;
- register struct uba_attach_args *ua = aux;
- register dzregs *dzaddr;
register int n;
- dzaddr = (dzregs *) ua->ua_addr;
- sc->sc_addr = dzaddr;
-
-#ifdef QBA
- if (uh->uh_type == QBA)
- sc->sc_type = DZ_DZV;
- else
-#endif
- sc->sc_type = DZ_DZ;
-
sc->sc_rxint = sc->sc_brk = 0;
- dzaddr->dz_csr = (DZ_CSR_MSE | DZ_CSR_RXIE | DZ_CSR_TXIE);
- dzaddr->dz_dtr = 0; /* Make sure DTR bits are zero */
- dzaddr->dz_break = 0; /* Status of BREAK bits, all off */
+ sc->sc_dr.dr_tcrw = sc->sc_dr.dr_tcr;
+ DZ_WRITE_WORD(dr_csr, DZ_CSR_MSE | DZ_CSR_RXIE | DZ_CSR_TXIE);
+ DZ_WRITE_BYTE(dr_dtr, 0);
+ DZ_WRITE_BYTE(dr_break, 0);
/* Initialize our softc structure. Should be done in open? */
for (n = 0; n < sc->sc_type; n++)
sc->sc_dz[n].dz_tty = ttymalloc();
- /* Now register the RX interrupt handler */
- ubasetvec(self, ua->ua_cvec-1, dzrint);
-
/* Alas no interrupt on modem bit changes, so we manually scan */
if (dz_timer == 0) {
dz_timer = 1;
timeout(dzscan, (void *)0, hz);
}
-
printf("\n");
return;
}
/* Receiver Interrupt */
-static void
-dzrint(cntlr)
- int cntlr;
+void
+dzrint(arg)
+ void *arg;
{
- struct dz_softc *sc = dz_cd.cd_devs[cntlr];
- volatile dzregs *dzaddr;
+ struct dz_softc *sc = arg;
register struct tty *tp;
register int cc, line;
register unsigned c;
@@ -248,13 +171,15 @@ dzrint(cntlr)
sc->sc_rxint++;
- dzaddr = sc->sc_addr;
-
- while ((c = dzaddr->dz_rbuf) & DZ_RBUF_DATA_VALID) {
+ while ((c = DZ_READ_WORD(dr_rbuf)) & DZ_RBUF_DATA_VALID) {
cc = c & 0xFF;
line = DZ_PORT(c>>8);
tp = sc->sc_dz[line].dz_tty;
+ /* Must be caught early */
+ if (sc->sc_catch && (*sc->sc_catch)(line, cc))
+ continue;
+
if (!(tp->t_state & TS_ISOPEN)) {
wakeup((caddr_t)&tp->t_rawq);
continue;
@@ -265,30 +190,39 @@ dzrint(cntlr)
sc->sc_dev.dv_xname, line);
overrun = 1;
}
+
/* A BREAK key will appear as a NULL with a framing error */
if (c & DZ_RBUF_FRAMING_ERR)
cc |= TTY_FE;
if (c & DZ_RBUF_PARITY_ERR)
cc |= TTY_PE;
+#if defined(DDB) && (defined(VAX410) || defined(VAX43) || defined(VAX46))
+ if (tp->t_dev == cn_tab->cn_dev) {
+ int j = kdbrint(cc);
+
+ if (j == 1) /* Escape received, just return */
+ continue;
+
+ if (j == 2) /* Second char wasn't 'D' */
+ (*linesw[tp->t_line].l_rint)(27, tp);
+ }
+#endif
(*linesw[tp->t_line].l_rint)(cc, tp);
}
- return;
}
/* Transmitter Interrupt */
-static void
-dzxint(cntlr)
- int cntlr;
+void
+dzxint(arg)
+ void *arg;
{
- volatile dzregs *dzaddr;
- register struct dz_softc *sc = dz_cd.cd_devs[cntlr];
+ register struct dz_softc *sc = arg;
register struct tty *tp;
- register unsigned csr;
- register int line;
-
- dzaddr = sc->sc_addr;
+ register struct clist *cl;
+ register int line, ch, csr;
+ u_char tcr;
/*
* Switch to POLLED mode.
@@ -302,54 +236,45 @@ dzxint(cntlr)
* Each UART is double buffered, so if the scanner
* is quick enough and timing works out, we can even
* feed the same port twice.
+ *
+ * Ragge 980517:
+ * Do not need to turn off interrupts, already at interrupt level.
+ * Remove the pdma stuff; no great need of it right now.
*/
- dzaddr->dz_csr &= ~(DZ_CSR_TXIE);
-
- while (((csr = dzaddr->dz_csr) & DZ_CSR_TX_READY) != 0) {
+ while (((csr = DZ_READ_WORD(dr_csr)) & DZ_CSR_TX_READY) != 0) {
line = DZ_PORT(csr>>8);
- if (sc->sc_dz[line].dz_mem < sc->sc_dz[line].dz_end) {
- dzaddr->dz_tbuf = *sc->sc_dz[line].dz_mem++;
- continue;
- }
-
- /*
- * Turn off this TX port as all pending output
- * has been completed - thus freeing the scanner
- * on the controller to hopefully find another
- * pending TX operation we can service now.
- * (avoiding the overhead of another interrupt)
- */
-
- dzaddr->dz_tcr &= ~(1 << line);
-
tp = sc->sc_dz[line].dz_tty;
-
+ cl = &tp->t_outq;
tp->t_state &= ~TS_BUSY;
+ /* Just send out a char if we have one */
+ /* As long as we can fill the chip buffer, we just loop here */
+ if (cl->c_cc) {
+ tp->t_state |= TS_BUSY;
+ ch = getc(cl);
+ DZ_WRITE_BYTE(dr_tbuf, ch);
+ continue;
+ }
+ /* Nothing to send; clear the scan bit */
+ /* Clear xmit scanner bit; dzstart may set it again */
+ tcr = DZ_READ_WORD(dr_tcrw);
+ tcr &= 255;
+ tcr &= ~(1 << line);
+ DZ_WRITE_BYTE(dr_tcr, tcr);
+
if (tp->t_state & TS_FLUSH)
tp->t_state &= ~TS_FLUSH;
- else {
- ndflush (&tp->t_outq, (sc->sc_dz[line].dz_mem -
- (caddr_t)tp->t_outq.c_cf));
- sc->sc_dz[line].dz_end = sc->sc_dz[line].dz_mem =
- tp->t_outq.c_cf;
- }
+ else
+ ndflush (&tp->t_outq, cl->c_cc);
if (tp->t_line)
(*linesw[tp->t_line].l_start)(tp);
else
dzstart(tp);
}
-
- /*
- * Re-enable TX interrupts.
- */
-
- dzaddr->dz_csr |= (DZ_CSR_TXIE);
- return;
}
int
@@ -365,7 +290,6 @@ dzopen(dev, flag, mode, p)
unit = DZ_I2C(minor(dev));
line = DZ_PORT(minor(dev));
-
if (unit >= dz_cd.cd_ndevs || dz_cd.cd_devs[unit] == NULL)
return (ENXIO);
@@ -381,7 +305,6 @@ dzopen(dev, flag, mode, p)
tp->t_param = dzparam;
tp->t_dev = dev;
if ((tp->t_state & TS_ISOPEN) == 0) {
- tp->t_state |= TS_WOPEN;
ttychars(tp);
if (tp->t_ispeed == 0) {
tp->t_iflag = TTYDEF_IFLAG;
@@ -400,7 +323,6 @@ dzopen(dev, flag, mode, p)
s = spltty();
while (!(flag & O_NONBLOCK) && !(tp->t_cflag & CLOCAL) &&
!(tp->t_state & TS_CARR_ON)) {
- tp->t_state |= TS_WOPEN;
error = ttysleep(tp, (caddr_t)&tp->t_rawq,
TTIPRI | PCATCH, ttopen, 0);
if (error)
@@ -414,7 +336,7 @@ dzopen(dev, flag, mode, p)
/*ARGSUSED*/
int
-dzclose (dev, flag, mode, p)
+dzclose(dev, flag, mode, p)
dev_t dev;
int flag, mode;
struct proc *p;
@@ -436,8 +358,7 @@ dzclose (dev, flag, mode, p)
(void) dzmctl(sc, line, DML_BRK, DMBIC);
/* Do a hangup if so required. */
- if ((tp->t_cflag & HUPCL) || (tp->t_state & TS_WOPEN) ||
- !(tp->t_state & TS_ISOPEN))
+ if ((tp->t_cflag & HUPCL) || !(tp->t_state & TS_ISOPEN))
(void) dzmctl(sc, line, 0, DMSET);
return (ttyclose(tp));
@@ -475,7 +396,7 @@ dzwrite (dev, uio, flag)
int
dzioctl (dev, cmd, data, flag, p)
dev_t dev;
- int cmd;
+ u_long cmd;
caddr_t data;
int flag;
struct proc *p;
@@ -548,36 +469,23 @@ dztty (dev)
}
/*ARGSUSED*/
-void
+int
dzstop(tp, flag)
register struct tty *tp;
{
- register struct dz_softc *sc;
- int unit, line, s;
-
- unit = DZ_I2C(minor(tp->t_dev));
- line = DZ_PORT(minor(tp->t_dev));
- sc = dz_cd.cd_devs[unit];
-
- s = spltty();
-
- if (tp->t_state & TS_BUSY) {
- sc->sc_dz[line].dz_end = sc->sc_dz[line].dz_mem;
+ if (tp->t_state & TS_BUSY)
if (!(tp->t_state & TS_TTSTOP))
tp->t_state |= TS_FLUSH;
- }
- (void) splx(s);
}
-static void
-dzstart (tp)
+void
+dzstart(tp)
register struct tty *tp;
{
register struct dz_softc *sc;
- register dzregs *dzaddr;
- register int unit, line;
- register int cc;
- int s;
+ register struct clist *cl;
+ register int unit, line, s;
+ char state;
unit = DZ_I2C(minor(tp->t_dev));
line = DZ_PORT(minor(tp->t_dev));
@@ -585,31 +493,26 @@ dzstart (tp)
s = spltty();
if (tp->t_state & (TS_TIMEOUT|TS_BUSY|TS_TTSTOP))
- goto out;
- if (tp->t_outq.c_cc <= tp->t_lowat) {
+ return;
+ cl = &tp->t_outq;
+ if (cl->c_cc <= tp->t_lowat) {
if (tp->t_state & TS_ASLEEP) {
tp->t_state &= ~TS_ASLEEP;
- wakeup((caddr_t)&tp->t_outq);
+ wakeup((caddr_t)cl);
}
selwakeup(&tp->t_wsel);
}
- if (tp->t_outq.c_cc == 0)
- goto out;
- cc = ndqb(&tp->t_outq, 0);
- if (cc == 0)
- goto out;
+ if (cl->c_cc == 0)
+ return;
tp->t_state |= TS_BUSY;
- dzaddr = sc->sc_addr;
-
- sc->sc_dz[line].dz_end = sc->sc_dz[line].dz_mem = tp->t_outq.c_cf;
- sc->sc_dz[line].dz_end += cc;
- dzaddr->dz_tcr |= (1 << line); /* Enable this TX port */
-
-out:
- (void) splx(s);
- return;
+ state = DZ_READ_WORD(dr_tcrw) & 255;
+ if ((state & (1 << line)) == 0) {
+ DZ_WRITE_BYTE(dr_tcr, state | (1 << line));
+ }
+ dzxint(sc);
+ splx(s);
}
static int
@@ -618,7 +521,6 @@ dzparam(tp, t)
register struct termios *t;
{
struct dz_softc *sc;
- register dzregs *dzaddr;
register int cflag = t->c_cflag;
int unit, line;
int ispeed = ttspeedtab(t->c_ispeed, dzspeedtab);
@@ -644,7 +546,6 @@ dzparam(tp, t)
}
s = spltty();
- dzaddr = sc->sc_addr;
lpr = DZ_LPR_RX_ENABLE | ((ispeed&0xF)<<8) | line;
@@ -670,7 +571,7 @@ dzparam(tp, t)
if (cflag & CSTOPB)
lpr |= DZ_LPR_2_STOP;
- dzaddr->dz_lpr = lpr;
+ DZ_WRITE_WORD(dr_lpr, lpr);
(void) splx(s);
return (0);
@@ -681,7 +582,6 @@ dzmctl(sc, line, bits, how)
register struct dz_softc *sc;
int line, bits, how;
{
- register dzregs *dzaddr;
register unsigned status;
register unsigned mbits;
register unsigned bit;
@@ -689,27 +589,25 @@ dzmctl(sc, line, bits, how)
s = spltty();
- dzaddr = sc->sc_addr;
-
mbits = 0;
bit = (1 << line);
/* external signals as seen from the port */
- status = dzaddr->dz_dcd;
+ status = DZ_READ_BYTE(dr_dcd) | sc->sc_dsr;
if (status & bit)
mbits |= DML_DCD;
- status = dzaddr->dz_ring;
+ status = DZ_READ_BYTE(dr_ring);
if (status & bit)
mbits |= DML_RI;
/* internal signals/state delivered to port */
- status = dzaddr->dz_dtr;
+ status = DZ_READ_BYTE(dr_dtr);
if (status & bit)
mbits |= DML_DTR;
@@ -736,15 +634,19 @@ dzmctl(sc, line, bits, how)
return (mbits);
}
- if (mbits & DML_DTR)
- dzaddr->dz_dtr |= bit;
- else
- dzaddr->dz_dtr &= ~bit;
+ if (mbits & DML_DTR) {
+ DZ_WRITE_BYTE(dr_dtr, DZ_READ_BYTE(dr_dtr) | bit);
+ } else {
+ DZ_WRITE_BYTE(dr_dtr, DZ_READ_BYTE(dr_dtr) & ~bit);
+ }
- if (mbits & DML_BRK)
- dzaddr->dz_break = (sc->sc_brk |= bit);
- else
- dzaddr->dz_break = (sc->sc_brk &= ~bit);
+ if (mbits & DML_BRK) {
+ sc->sc_brk |= bit;
+ DZ_WRITE_BYTE(dr_break, sc->sc_brk);
+ } else {
+ sc->sc_brk &= ~bit;
+ DZ_WRITE_BYTE(dr_break, sc->sc_brk);
+ }
(void) splx(s);
return (mbits);
@@ -758,7 +660,6 @@ static void
dzscan(arg)
void *arg;
{
- register dzregs *dzaddr;
register struct dz_softc *sc;
register struct tty *tp;
register int n, bit, port;
@@ -776,18 +677,17 @@ dzscan(arg)
for (port = 0; port < sc->sc_type; port++) {
- dzaddr = sc->sc_addr;
tp = sc->sc_dz[port].dz_tty;
bit = (1 << port);
- if (dzaddr->dz_dcd & bit) { /* carrier present */
-
+ if ((DZ_READ_BYTE(dr_dcd) | sc->sc_dsr) & bit) {
if (!(tp->t_state & TS_CARR_ON))
- (void)(*linesw[tp->t_line].l_modem)
- (tp, 1);
+ (*linesw[tp->t_line].l_modem) (tp, 1);
} else if ((tp->t_state & TS_CARR_ON) &&
- (*linesw[tp->t_line].l_modem)(tp, 0) == 0)
- dzaddr->dz_tcr &= ~bit;
+ (*linesw[tp->t_line].l_modem)(tp, 0) == 0) {
+ DZ_WRITE_BYTE(dr_tcr,
+ (DZ_READ_WORD(dr_tcrw) & 255) & ~bit);
+ }
}
/*
@@ -799,16 +699,14 @@ dzscan(arg)
* if off unless the rate is appropriately low.
*/
- dzaddr = sc->sc_addr;
-
- csr = dzaddr->dz_csr;
+ csr = DZ_READ_WORD(dr_csr);
if (sc->sc_rxint > (16*10)) {
if ((csr & DZ_CSR_SAE) == 0)
- dzaddr->dz_csr = (csr | DZ_CSR_SAE);
+ DZ_WRITE_WORD(dr_csr, csr | DZ_CSR_SAE);
} else if ((csr & DZ_CSR_SAE) != 0)
if (sc->sc_rxint < 10)
- dzaddr->dz_csr = (csr & ~(DZ_CSR_SAE));
+ DZ_WRITE_WORD(dr_csr, csr & ~(DZ_CSR_SAE));
sc->sc_rxint = 0;
}
diff --git a/sys/arch/vax/qbus/dz_uba.c b/sys/arch/vax/qbus/dz_uba.c
new file mode 100644
index 00000000000..d9595840a52
--- /dev/null
+++ b/sys/arch/vax/qbus/dz_uba.c
@@ -0,0 +1,137 @@
+/* $OpenBSD: dz_uba.c,v 1.1 2000/04/27 03:14:47 bjc Exp $ */
+/* $NetBSD: dz_uba.c,v 1.8 2000/01/24 02:40:29 matt Exp $ */
+/*
+ * Copyright (c) 1998 Ludd, University of Lule}, Sweden. All rights reserved.
+ * Copyright (c) 1996 Ken C. Wellsch. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed 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/ioctl.h>
+#include <sys/tty.h>
+#include <sys/proc.h>
+#include <sys/map.h>
+#include <sys/buf.h>
+#include <sys/conf.h>
+#include <sys/file.h>
+#include <sys/uio.h>
+#include <sys/kernel.h>
+#include <sys/syslog.h>
+#include <sys/device.h>
+
+#include <machine/bus.h>
+#include <machine/pte.h>
+#include <machine/trap.h>
+#include <machine/scb.h>
+
+#include <arch/vax/qbus/ubavar.h>
+
+#include <arch/vax/qbus/dzreg.h>
+#include <arch/vax/qbus/dzvar.h>
+
+static int dz_uba_match __P((struct device *, struct cfdata *, void *));
+static void dz_uba_attach __P((struct device *, struct device *, void *));
+
+struct cfattach dz_uba_ca = {
+ sizeof(struct dz_softc), (cfmatch_t)dz_uba_match, dz_uba_attach
+};
+
+/* Autoconfig handles: setup the controller to interrupt, */
+/* then complete the housecleaning for full operation */
+
+static int
+dz_uba_match(parent, cf, aux)
+ struct device *parent;
+ struct cfdata *cf;
+ void *aux;
+{
+ struct uba_attach_args *ua = aux;
+ bus_space_tag_t iot = ua->ua_iot;
+ bus_space_handle_t ioh = ua->ua_ioh;
+ register int n;
+
+ iot = iot; /* Silly GCC */
+ /* Reset controller to initialize, enable TX interrupts */
+ /* to catch floating vector info elsewhere when completed */
+
+ bus_space_write_2(iot, ioh, DZ_UBA_CSR, DZ_CSR_MSE | DZ_CSR_TXIE);
+ bus_space_write_1(iot, ioh, DZ_UBA_TCR, 1);
+
+ DELAY(100000); /* delay 1/10 second */
+
+ bus_space_write_2(iot, ioh, DZ_UBA_CSR, DZ_CSR_RESET);
+
+ /* Now wait up to 3 seconds for reset/clear to complete. */
+
+ for (n = 0; n < 300; n++) {
+ DELAY(10000);
+ if ((bus_space_read_2(iot, ioh, DZ_UBA_CSR)&DZ_CSR_RESET) == 0)
+ break;
+ }
+
+ /* If the RESET did not clear after 3 seconds, */
+ /* the controller must be broken. */
+
+ if (n >= 300)
+ return (0);
+
+ /* Register the TX interrupt handler */
+
+
+ return (1);
+}
+
+static void
+dz_uba_attach(parent, self, aux)
+ struct device *parent, *self;
+ void *aux;
+{
+ struct dz_softc *sc = (void *)self;
+ register struct uba_attach_args *ua = aux;
+
+ sc->sc_iot = ua->ua_iot;
+ sc->sc_ioh = ua->ua_ioh;
+
+ sc->sc_dr.dr_csr = DZ_UBA_CSR;
+ sc->sc_dr.dr_rbuf = DZ_UBA_RBUF;
+ sc->sc_dr.dr_dtr = DZ_UBA_DTR;
+ sc->sc_dr.dr_break = DZ_UBA_BREAK;
+ sc->sc_dr.dr_tbuf = DZ_UBA_TBUF;
+ sc->sc_dr.dr_tcr = DZ_UBA_TCR;
+ sc->sc_dr.dr_dcd = DZ_UBA_DCD;
+ sc->sc_dr.dr_ring = DZ_UBA_RING;
+
+ sc->sc_type = DZ_DZ;
+
+ /* Now register the TX & RX interrupt handlers */
+ uba_intr_establish(ua->ua_icookie, ua->ua_cvec, dzxint, sc);
+ uba_intr_establish(ua->ua_icookie, ua->ua_cvec - 4, dzrint, sc);
+
+ dzattach(sc);
+}
diff --git a/sys/arch/vax/uba/dzreg.h b/sys/arch/vax/qbus/dzreg.h
index ee4237a75c8..8f046c50fa0 100644
--- a/sys/arch/vax/uba/dzreg.h
+++ b/sys/arch/vax/qbus/dzreg.h
@@ -1,5 +1,5 @@
-/* $OpenBSD: dzreg.h,v 1.2 1997/05/29 00:05:06 niklas Exp $ */
-/* $NetBSD: dzreg.h,v 1.1 1996/04/08 17:22:21 ragge Exp $ */
+/* $OpenBSD: dzreg.h,v 1.1 2000/04/27 03:14:47 bjc Exp $ */
+/* $NetBSD: dzreg.h,v 1.4 1999/05/27 16:03:13 ragge Exp $ */
/*
* Copyright (c) 1996 Ken C. Wellsch. All rights reserved.
*
@@ -8,28 +8,19 @@
* 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.
+ * 2. 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 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.
+ * 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.
*/
union w_b
@@ -60,6 +51,43 @@ struct DZregs
typedef struct DZregs dzregs;
+#if 0
+struct dz_regs {
+ volatile unsigned short *dr_csr;
+ volatile unsigned short *dr_rbuf;
+#define dr_lpr dr_rbuf
+ volatile unsigned char *dr_dtr;
+ volatile unsigned char *dr_break;
+ volatile unsigned char *dr_tbuf;
+ volatile unsigned char *dr_tcr;
+ volatile unsigned short *dr_tcrw;
+ volatile unsigned char *dr_ring;
+ volatile unsigned char *dr_dcd;
+};
+#else
+struct dz_regs {
+ bus_addr_t dr_csr;
+ bus_addr_t dr_rbuf;
+#define dr_lpr dr_rbuf
+ bus_addr_t dr_dtr;
+ bus_addr_t dr_break;
+ bus_addr_t dr_tbuf;
+ bus_addr_t dr_tcr;
+ bus_addr_t dr_tcrw;
+ bus_addr_t dr_ring;
+ bus_addr_t dr_dcd;
+};
+#define DZ_UBA_CSR 0
+#define DZ_UBA_RBUF 2
+#define DZ_UBA_DTR 5
+#define DZ_UBA_BREAK 7
+#define DZ_UBA_TBUF 6
+#define DZ_UBA_TCR 4
+#define DZ_UBA_DCD 7
+#define DZ_UBA_RING 6
+
+#endif
+
/* CSR bits */
#define DZ_CSR_TX_READY 0100000 /* Transmitter Ready */
@@ -103,7 +131,7 @@ typedef struct DZregs dzregs;
#define DZ_LPR_B4800 0xC
#define DZ_LPR_B7200 0xD
#define DZ_LPR_B9600 0xE
-#define DZ_LPR_ILLEGAL 0xF
+#define DZ_LPR_B19200 0xF
#define DZ_LPR_OPAR 0000200
#define DZ_LPR_PARENB 0000100
diff --git a/sys/arch/vax/uba/udareg.h b/sys/arch/vax/qbus/dzvar.h
index 20c0b995b15..ae183c5f901 100644
--- a/sys/arch/vax/uba/udareg.h
+++ b/sys/arch/vax/qbus/dzvar.h
@@ -1,12 +1,12 @@
-/* $OpenBSD: udareg.h,v 1.3 1997/05/29 00:05:11 niklas Exp $ */
-/* $NetBSD: udareg.h,v 1.3 1996/07/01 21:24:50 ragge Exp $ */
-
+/* $OpenBSD: dzvar.h,v 1.1 2000/04/27 03:14:47 bjc Exp $ */
+/* $NetBSD: dzvar.h,v 1.6 2000/01/24 02:40:29 matt Exp $ */
/*
- * Copyright (c) 1988 Regents of the University of California.
- * All rights reserved.
+ * Copyright (c) 1996 Ken C. Wellsch. All rights reserved.
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
- * Chris Torek.
+ * Ralph Campbell and Rick Macklem.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -35,30 +35,39 @@
* 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
*/
-/*
- * UDA50 registers and structures
- */
+/* A DZ-11 has 8 ports while a DZV/DZQ-11 has only 4. We use 8 by default */
-/*
- * Writing any value to udaip starts initialisation. Reading from it
- * when the UDA is running makes the UDA look through the command ring
- * to find any new commands. Reading udasa gives status; writing it
- * during initialisation sets things up.
- */
-struct udadevice {
- u_short udaip; /* initialisation and polling */
- u_short udasa; /* status and address */
-};
+#define NDZLINE 8
-/*
- * Bits in UDA status register after initialisation
- */
-#define UDA_GO 0x0001 /* run */
+#define DZ_DZ 8
+#define DZ_DZV 4
+#define DZ_DC 4
-#define UDASR_BITS \
-"\20\20ERR\17STEP4\16STEP3\15STEP2\14STEP1\13NV\12QB\11DI\10IE\1GO"
+#define DZ_C2I(c) ((c)<<3) /* convert controller # to index */
+#define DZ_I2C(c) ((c)>>3) /* convert minor to controller # */
+#define DZ_PORT(u) ((u)&07) /* extract the port # */
+
+struct dz_softc {
+ struct device sc_dev; /* Autoconf blaha */
+ struct dz_regs sc_dr; /* reg pointers */
+ bus_space_tag_t sc_iot;
+ bus_space_handle_t sc_ioh;
+ int sc_type; /* DZ11 or DZV11? */
+ int sc_rxint; /* Receive interrupt count XXX */
+ u_char sc_brk; /* Break asserted on some lines */
+ u_char sc_dsr; /* DSR set bits if no mdm ctrl */
+ int (*sc_catch) __P((int, int)); /* Fast catch recv */
+ struct {
+ struct tty * dz_tty; /* what we work on */
+#ifdef notyet
+ caddr_t dz_mem; /* pointers to clist output */
+ caddr_t dz_end; /* allowing pdma action */
+#endif
+ } sc_dz[NDZLINE];
+};
+void dzattach __P((struct dz_softc *));
+void dzrint __P((void *));
+void dzxint __P((void *));
diff --git a/sys/arch/vax/qbus/files.uba b/sys/arch/vax/qbus/files.uba
new file mode 100644
index 00000000000..98761e6bf71
--- /dev/null
+++ b/sys/arch/vax/qbus/files.uba
@@ -0,0 +1,52 @@
+# $OpenBSD: files.uba,v 1.1 2000/04/27 03:14:48 bjc Exp $
+# $NetBSD: files.uba,v 1.6 1999/06/20 18:09:22 ragge Exp $
+#
+# Config file and device description for machine-independent
+# code for devices Digital Equipment Corp. Unibus and Q22 bus.
+# Included by ports that need it.
+device uba { csr }
+
+define qfont
+
+file arch/vax/qbus/uba.c uba
+
+# DZ-11 (-compatible) tty device driver.
+device dz { }: tty
+attach dz at uba with dz_uba
+file arch/vax/qbus/dz.c dz needs-flag
+file arch/vax/qbus/dz_uba.c dz_uba
+
+# DL-11 at UBA
+device dl: tty
+attach dl at uba
+file arch/vax/qbus/dl.c dl needs-flag
+
+# DHU-11 at UBA
+device dhu: tty
+attach dhu at uba
+file arch/vax/qbus/dhu.c dhu needs-flag
+
+# UDA50/whatever disk/tape MSCP controller
+device mtc: mscp
+attach mtc at uba
+device uda: mscp
+attach uda at uba
+file arch/vax/qbus/uda.c uda | mtc
+
+# DEQNA/DELQA Ethernet controller
+device qe: ifnet, ether
+attach qe at uba
+file arch/vax/if/if_qe.c qe
+
+# DEUNA/DELUA Ethernet controller
+device de: ifnet, ether
+attach de at uba
+file arch/vax/if/if_de.c de
+
+# QDSS at UBA
+device qd: qfont
+attach qd at uba
+file arch/vax/qbus/qd.c qd needs-count
+
+# Fontfile for DEC framebuffers, soon to die in favour for MI fontfiles.
+file arch/vax/qbus/qfont.c qfont
diff --git a/sys/arch/vax/uba/qd.c b/sys/arch/vax/qbus/qd.c
index 8e4402a6f35..38eaa483b17 100644
--- a/sys/arch/vax/uba/qd.c
+++ b/sys/arch/vax/qbus/qd.c
@@ -1,5 +1,5 @@
-/* $OpenBSD: qd.c,v 1.2 1997/05/29 00:05:07 niklas Exp $ */
-/* $NetBSD: qd.c,v 1.4 1996/10/13 03:35:17 christos Exp $ */
+/* $OpenBSD: qd.c,v 1.1 2000/04/27 03:14:48 bjc Exp $ */
+/* $NetBSD: qd.c,v 1.17 2000/01/24 02:40:29 matt Exp $ */
/*-
* Copyright (c) 1988 Regents of the University of California.
@@ -64,29 +64,33 @@
#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 */
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/conf.h>
+#include <sys/tty.h>
+#include <sys/kernel.h>
+#include <sys/device.h>
+#include <sys/poll.h>
+#include <sys/buf.h>
+
+#include <vm/vm.h>
+
+#include <dev/cons.h>
+
+#include <machine/bus.h>
+#include <machine/scb.h>
+
+#ifdef __vax__
+#include <machine/sid.h>
+#include <machine/cpu.h>
+#include <machine/pte.h>
+#endif
+
+#include <arch/vax/qbus/ubavar.h>
+
+#include <arch/vax/qbus/qduser.h>
+#include <arch/vax/qbus/qdreg.h>
+#include <arch/vax/qbus/qdioctl.h>
/*
* QDSS driver status flags for tracking operational state
@@ -107,6 +111,16 @@ struct qdflags {
};
/*
+ * Softc struct to keep track of all states in this driver.
+ */
+struct qd_softc {
+ struct device sc_dev;
+ bus_space_tag_t sc_iot;
+ bus_space_handle_t sc_ioh;
+ bus_dma_tag_t sc_dmat;
+};
+
+/*
* bit definitions for 'inuse' entry
*/
#define CONS_DEV 0x01
@@ -144,9 +158,9 @@ struct qdflags {
* 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];
+struct tty *qd_tty[NQD*4]; /* teletype structures for each.. */
+volatile char *qvmem[NQD];
+volatile struct pte *QVmap[NQD];
#define CHUNK (64 * 1024)
#define QMEMSIZE (1024 * 1024 * 4) /* 4 meg */
@@ -154,8 +168,8 @@ extern struct pte QVmap[][128];
* 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 */
+struct qdflags qdflags[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 */
@@ -212,39 +226,32 @@ struct color_buf *color_buf[NQD]; /* pointers to color bufs */
struct mouse_report last_rep[NQD];
struct mouse_report current_rep[NQD];
-struct proc *qdrsel[NQD]; /* process waiting for select */
+struct selinfo 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 */
+/* #define QDSSMAJOR 41 */ /* QDSS major device number. We don't care! */
+
/*
* 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 */
-};
+void qd_attach __P((struct device *, struct device *, void *));
+static int qd_match __P((struct device *, struct cfdata *, void *));
+
+static void qddint __P((void *)); /* DMA gate array intrpt service */
+static void qdaint __P((void *)); /* Dragon ADDER intrpt service */
+static void qdiint __P((void *));
#define QDPRIOR (PZERO-1) /* must be negative */
#define FALSE 0
+#ifdef TRUE
+#undef TRUE
+#endif
#define TRUE ~FALSE
#define BAD -1
#define GOOD 0
@@ -252,7 +259,7 @@ struct uba_driver qddriver = {
/*
* macro to create a system virtual page number from system virtual adrs
*/
-#define VTOP(x) (((int)x & ~0xC0000000) >> PGSHIFT)
+#define VTOP(x) (((int)x & ~0xC0000000) >> VAX_PGSHIFT)
/*
* QDSS register address offsets from start of QDSS address space
@@ -320,16 +327,22 @@ extern char *q_special[];
/*
* 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();
+cons_decl(qd);
+cdev_decl(qd);
+void setup_dragon __P((int));
+void init_shared __P((int));
+void clear_qd_screen __P((int));
+void ldfont __P((int));
+void ldcursor __P((int, short *));
+void setup_input __P((int));
+void blitc __P((int, u_char));
+void scroll_up __P((volatile struct adder *));
+void write_ID __P((volatile struct adder *, short, short));
+int wait_status __P((volatile struct adder *, int));
+void led_control __P((int, int, int));
+void qdstart(struct tty *);
+void qdearly(void);
int qdpolling = 0;
/*
@@ -354,55 +367,122 @@ struct q_keyboard {
#define CFLAG (PARENB|CREAD|CS7|CLOCAL)
/*
- * Init QDSS as console (before probe routine)
+ * Kernel virtual addresses where we can map in the QBUS io page and the
+ * QDSS memory during qdcninit. pmap_bootstrap fills this in.
+ */
+void *qd_ubaio;
+
+/* This is the QDSS unit 0 CSR. It is hard-coded in here so that the
+ * QDSS can be used as the console. The console routines don't get
+ * any config info. The ROM also autodetects at this address, so
+ * the console QDSS should be at this address. Furthermore, nothing
+ * else shuld be at this address instead because that would confuse the
+ * ROM and this driver.
*/
+#define QDSSCSR 0x1F00
+
+volatile u_short *qdaddr; /* Virtual address for QDSS CSR */
+
+/*
+ * This flag is set to 1 if the console initialization (qdcninit)
+ * has been performed on qd0. That initialization is required and must
+ * be done before the device probe routine.
+ */
+int qd0cninited = 0, qd0iscons = 0;
-qdcons_init()
+/*
+ * Do early check if the qdss is console. If not; don't allocate
+ * any memory for it in bootstrap.
+ */
+void
+qdearly()
{
- 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();
+ extern vaddr_t virtual_avail;
+ int tmp;
+
+ /* Make sure we're running on a system that can have a QDSS */
+ if (vax_boardtype == VAX_BTYP_630) {
+ /* Now check some undocumented flag */
+ if ((*(int *)(0x200B801E) & 0x60) == 0)
+ /* The KA630 isn't using a QDSS as the console,
+ * so we won't either */
+ return;
+ } else if (vax_boardtype != VAX_BTYP_650)
+ return;
-#define QDSSCSR 0x1F00
+ /* How to check for console on KA650? We assume that if there is a
+ * QDSS, it is console.
+ */
+#define QIOPAGE 0x20000000 /* XXX */
+#define UBAIOPAGES 16
+ tmp = QIOPAGE + ubdevreg(QDSSCSR);
+ if (badaddr((caddr_t)tmp, sizeof(short)))
+ return;
- if (v_putc != cnputc)
- return 0;
+ MAPVIRT(qvmem[0], 64 * 1024 * NQD / VAX_NBPG);
+ MAPVIRT(qd_ubaio, 16);
+ pmap_map((int)qd_ubaio, QIOPAGE, QIOPAGE + UBAIOPAGES * VAX_NBPG,
+ VM_PROT_READ|VM_PROT_WRITE);
+ qdaddr = (u_short *)((u_int)qd_ubaio + ubdevreg(QDSSCSR));
+ qd0iscons = 1;
+}
- unit = 0;
+void
+qdcnprobe(cndev)
+ struct consdev *cndev;
+{
+ int i;
- /*
- * 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;
+ cndev->cn_pri = CN_DEAD;
+
+ if (mfpr(PR_MAPEN) == 0)
+ return; /* Cannot use qd if vm system is OFF */
- /*
- * 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;
+ if (!qd0iscons)
+ return;
+
+ /* Find the console device corresponding to the console QDSS */
+ for (i = 0; i < nchrdev; i++)
+ if (cdevsw[i].d_open == qdopen) {
+ cndev->cn_dev = makedev(i,0);
+ cndev->cn_pri = CN_INTERNAL;
+ return;
+ }
+ return;
+}
+
+
+/*
+ * Init QDSS as console (before probe routine)
+ */
+void
+qdcninit(cndev)
+ struct consdev *cndev;
+{
+ caddr_t phys_adr; /* physical QDSS base adrs */
+ u_int mapix; /* index into QVmap[] array */
+ int unit;
+
+ /* qdaddr must point to CSR for this unit! */
+
+ /* The console QDSS is QDSS unit 0 */
+ unit = 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));
+#define QMEM 0x30000000
+ (int)phys_adr = QMEM + mapix;
+ pmap_map((int)(qvmem[0]), (int)phys_adr, (int)(phys_adr + (CHUNK*NQD)),
+ VM_PROT_READ|VM_PROT_WRITE);
+ /*
+ * Set QVmap to point to page table entries for what we just
+ * mapped.
+ */
+ QVmap[0] = (struct pte *)kvtopte(qvmem[0]);
+
/*
* tell QDSS which Q memory address base to decode
* (shifted right 16 bits - its in 64K units)
@@ -428,11 +508,7 @@ qdcons_init()
/*
* 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;
@@ -443,16 +519,21 @@ qdcons_init()
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 */
+ /* Set flag so probe knows */
+ qd0cninited = 1;
+} /* qdcninit */
+
+/* see <sys/device.h> */
+struct cfattach qd_ca = {
+ sizeof(struct qd_softc), qd_match, qd_attach
+};
+#define QD_RCSR(reg) \
+ bus_space_read_2(sc->sc_iot, sc->sc_ioh, reg)
+#define QD_WCSR(reg, val) \
+ bus_space_write_2(sc->sc_iot, sc->sc_ioh, reg, val)
+
/*
* Configure QDSS into Q memory and make it intrpt.
*
@@ -464,12 +545,18 @@ qdcons_init()
* registers by UNIX convention.
*
*/
-qdprobe(reg)
- caddr_t reg; /* character pointer to the QDSS I/O page register */
+static int
+qd_match(parent, match, aux)
+ struct device *parent;
+ struct cfdata *match;
+ void *aux;
{
- register int br, cvec;
+ struct qd_softc ssc;
+ struct qd_softc *sc = &ssc;
+ struct uba_attach_args *ua = aux;
+ struct uba_softc *uh = (void *)parent;
register int unit;
- struct dga *dga; /* pointer to gate array structure */
+ volatile struct dga *dga; /* pointer to gate array structure */
int vector;
#ifdef notdef
int *ptep; /* page table entry pointer */
@@ -477,19 +564,18 @@ qdprobe(reg)
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
-
+ /* Create a "fake" softc with only a few fields used. */
+ sc->sc_iot = ua->ua_iot;
+ sc->sc_ioh = ua->ua_ioh;
+ sc->sc_dmat = ua->ua_dmat;
/*
* calculate board unit number from I/O page register address
*/
- unit = (int) (((int)reg >> 1) & 0x0007);
+ unit = (int) (((int)sc->sc_ioh >> 1) & 0x0007);
/*
* QDSS regs must be mapped to Qbus memory space at a 64kb
- * physical boundary. The Qbus memory space is mapped into
+ * 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
@@ -534,7 +620,7 @@ qdprobe(reg)
*/
mapix = (int) (VTOP(qdbase[unit]) - VTOP(qvmem[0]));
ptep = (int *) QVmap[0] + mapix;
- phys_adr = (caddr_t)(((int)*ptep&0x001FFFFF)<<PGSHIFT);
+ phys_adr = (caddr_t)(((int)*ptep&0x001FFFFF)<<VAX_PGSHIFT);
*(u_short *)reg = (u_short) ((int)phys_adr >> 16);
/*
@@ -566,7 +652,35 @@ qdprobe(reg)
*(short *)qdmap[unit].memcsr |= SYNC_ON;
}
#endif /*notdef*/
+ } else {
+ /* We are dealing with qd0 */
+
+ if (!qd0cninited) {
+ /*
+ * qd0 has not been initiallized as the console.
+ * We need to do some initialization now
+ *
+ * XXX
+ * However, if the QDSS is not the console then
+ * that stupid undocumented bit (see qdcnprobe)
+ * is cleared. Then the QDSS refuses to work.
+ * (What did the ROM do to it!?)
+ * XXX
+ */
+ return 0;
+
+#if 0
+ qdaddr = (void *)reg;
+
+ /* Lame probe for QDSS. Should be ok for qd0 */
+ if (badaddr((caddr_t)qdaddr, sizeof(short)))
+ return 0;
+
+ qdcninit(NULL);
+#endif
+ }
}
+
/*
* The QDSS interrupts at HEX vectors xx0 (DMA) xx4
@@ -577,11 +691,11 @@ qdprobe(reg)
* order.
*/
- vector = (uba_hd[0].uh_lastiv -= 4*3); /* take three vectors */
+ vector = (uh->uh_lastiv -= 4*3); /* take three vectors */
while (vector & 0x0F) { /* if lo nibble != 0.. */
/* ..take another vector */
- vector = (uba_hd[0].uh_lastiv -= 4);
+ vector = (uh->uh_lastiv -= 4);
}
/*
@@ -602,24 +716,31 @@ qdprobe(reg)
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 */
-
+ return 1;
} /* qdprobe */
-qdattach(ui)
- struct uba_device *ui;
-{
- register unit; /* QDSS module # for this call */
- unit = ui->ui_unit; /* get QDSS number */
+void qd_attach(parent, self, aux)
+ struct device *parent, *self;
+ void *aux;
+ {
+ register struct uba_attach_args *ua = aux;
+ register int unit; /* QDSS module # for this call */
+
+ printf("\n");
+
+ unit = self->dv_unit; /* get QDSS number */
+
+ /* Set interrupt vectors for interrupt handlers */
+
+ uba_intr_establish(ua->ua_icookie, ua->ua_cvec , qddint, self);
+ uba_intr_establish(ua->ua_icookie, ua->ua_cvec + 4, qdaint, self);
+ uba_intr_establish(ua->ua_icookie, ua->ua_cvec + 8, qdiint, self);
/*
* init "qdflags[]" for this QDSS
@@ -665,15 +786,17 @@ qdattach(ui)
} /* qdattach */
+
/*ARGSUSED*/
-qdopen(dev, flag)
+int
+qdopen(dev, flag, mode, p)
dev_t dev;
- int flag;
+ int flag, mode;
+ struct proc *p;
{
- register struct uba_device *ui; /* ptr to uba structures */
- register struct dga *dga; /* ptr to gate array struct */
+ volatile register struct dga *dga; /* ptr to gate array struct */
register struct tty *tp;
- struct duart *duart;
+ volatile struct duart *duart;
int unit;
int minor_dev;
@@ -683,9 +806,8 @@ qdopen(dev, flag)
/*
* 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 */
+ if (unit >= qd_cd.cd_ndevs || qd_cd.cd_devs[unit] == NULL)
+ return (ENXIO); /* no such device or address */
duart = (struct duart *) qdmap[unit].duart;
dga = (struct dga *) qdmap[unit].dga;
@@ -705,7 +827,17 @@ qdopen(dev, flag)
qdflags[unit].duart_imask |= 0x22;
duart->imask = qdflags[unit].duart_imask;
} else {
- /*
+ /* Only one console */
+ if (minor_dev) return ENXIO;
+
+ /* If not done already, allocate tty structure */
+ if (qd_tty[minor_dev] == NULL)
+ qd_tty[minor_dev] = ttymalloc();
+
+ if (qd_tty[minor_dev] == NULL)
+ return ENXIO;
+
+ /*
* this is the console
*/
qdflags[unit].inuse |= CONS_DEV; /* mark console as open */
@@ -715,9 +847,10 @@ qdopen(dev, flag)
/*
* some setup for tty handling
*/
- tp = &qd_tty[minor_dev];
- tp->t_addr = ui->ui_addr;
+ tp = qd_tty[minor_dev];
+ /* tp->t_addr = ui->ui_addr; */
tp->t_oproc = qdstart;
+ tp->t_dev = dev;
if ((tp->t_state & TS_ISOPEN) == 0) {
ttychars(tp);
tp->t_ispeed = B9600;
@@ -727,6 +860,7 @@ qdopen(dev, flag)
tp->t_oflag = TTYDEF_OFLAG;
tp->t_lflag = TTYDEF_LFLAG;
tp->t_cflag = TTYDEF_CFLAG;
+ ttsetwater(tp);
}
/*
* enable intrpts, open line discipline
@@ -740,6 +874,7 @@ qdopen(dev, flag)
} /* qdopen */
/*ARGSUSED*/
+int
qdclose(dev, flag, mode, p)
dev_t dev;
int flag, mode;
@@ -747,25 +882,30 @@ qdclose(dev, flag, mode, 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;
+ volatile register int *ptep;
+ volatile struct dga *dga; /* gate array register map pointer */
+ volatile struct duart *duart;
+ volatile struct adder *adder;
int unit;
int minor_dev;
u_int mapix;
int i; /* SIGNED index */
-
+ struct uba_softc *uh;
+
minor_dev = minor(dev); /* get minor device number */
unit = minor_dev >> 2; /* get QDSS number */
qd = &qdmap[unit];
+ uh = (struct uba_softc *)
+ (((struct device *)(qd_cd.cd_devs[unit]))->dv_parent);
+
+
if ((minor_dev & 0x03) == 2) {
/*
* this is the graphic device...
*/
if (qdopened[unit] != 1)
- return(EBUSY);
+ return(EBUSY);
else
qdopened[unit] = 0; /* allow it to be re-opened */
/*
@@ -777,21 +917,21 @@ qdclose(dev, flag, mode, p)
*/
mapix = VTOP((int)qd->template) - VTOP(qvmem[0]);
ptep = (int *)(QVmap[0] + mapix);
- for (i = 0; i < btop(TMPSIZE); i++, ptep++)
+ for (i = 0; i < vax_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++)
+ for (i = 0; i < vax_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++)
+ for (i = 0; i < vax_btop(CLRSIZE); i++, ptep++)
*ptep = (*ptep & ~PG_PROT) | PG_V | PG_KW;
}
@@ -799,6 +939,12 @@ qdclose(dev, flag, mode, p)
* re-protect DMA buffer and free the map registers
*/
if (qdflags[unit].mapped & MAPDMA) {
+ panic("Unmapping unmapped buffer");
+#ifdef notyet
+/*
+ * Ragge 990620:
+ * Can't happen because the buffer can't be mapped.
+ */
dga = (struct dga *) qdmap[unit].dga;
adder = (struct adder *) qdmap[unit].adder;
dga->csr &= ~DMA_IE;
@@ -815,10 +961,11 @@ qdclose(dev, flag, mode, p)
dga->csr &= ~DMA_IE;
}
ptep = (int *)
- ((VTOP(DMAheader[unit]*4)) + (mfpr(SBR)|0x80000000));
- for (i = 0; i < btop(DMAbuf_size); i++, ptep++)
+ ((VTOP(DMAheader[unit]*4)) + (mfpr(PR_SBR)|0x80000000));
+ for (i = 0; i < vax_btop(DMAbuf_size); i++, ptep++)
*ptep = (*ptep & ~PG_PROT) | PG_V | PG_KW;
- ubarelse(0, &Qbus_unmap[unit]);
+ ubarelse(uh, &Qbus_unmap[unit]);
+#endif
}
/*
@@ -826,7 +973,7 @@ qdclose(dev, flag, mode, p)
*/
if (qdflags[unit].mapped & MAPEQ) {
ptep = (int *)
- ((VTOP(eq_header[unit])*4) + (mfpr(SBR)|0x80000000));
+ ((VTOP(eq_header[unit])*4) + (mfpr(PR_SBR)|0x80000000));
*ptep = (*ptep & ~PG_PROT) | PG_KW | PG_V; ptep++;
*ptep = (*ptep & ~PG_PROT) | PG_KW | PG_V;
}
@@ -835,7 +982,7 @@ qdclose(dev, flag, mode, p)
*/
if (qdflags[unit].mapped & MAPSCR) {
ptep = (int *) ((VTOP(scroll[unit]) * 4)
- + (mfpr(SBR) | 0x80000000));
+ + (mfpr(PR_SBR) | 0x80000000));
/*
* re-protect 512 scroll param area
*/
@@ -849,7 +996,7 @@ qdclose(dev, flag, mode, p)
*/
if (qdflags[unit].mapped & MAPCOLOR) {
ptep = (int *) ((VTOP(color_buf[unit]) * 4)
- + (mfpr(SBR) | 0x80000000));
+ + (mfpr(PR_SBR) | 0x80000000));
*ptep = (*ptep & ~PG_PROT) | PG_KW | PG_V; ptep++;
*ptep = (*ptep & ~PG_PROT) | PG_KW | PG_V;
color_buf[unit]->status = 0;
@@ -857,7 +1004,7 @@ qdclose(dev, flag, mode, p)
qdflags[unit].adder_ie &= ~VSYNC;
adder->interrupt_enable = qdflags[unit].adder_ie;
}
- mtpr(TBIA, 0);
+ mtpr(0, PR_TBIA);
/* flag everything now unmapped */
qdflags[unit].mapped = 0;
qdflags[unit].inuse &= ~GRAPHIC_DEV;
@@ -907,7 +1054,7 @@ qdclose(dev, flag, mode, p)
/*
* this is the console
*/
- tp = &qd_tty[minor_dev];
+ tp = qd_tty[minor_dev];
(*linesw[tp->t_line].l_close)(tp, flag);
ttyclose(tp);
tp->t_state = 0;
@@ -925,21 +1072,23 @@ qdclose(dev, flag, mode, p)
} /* qdclose */
-qdioctl(dev, cmd, datap, flags)
+int
+qdioctl(dev, cmd, datap, flags, p)
dev_t dev;
- int cmd;
- register caddr_t datap;
+ u_long cmd;
+ caddr_t datap;
int flags;
+ struct proc *p;
{
- register int *ptep; /* page table entry pointer */
+ volatile 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;
+ register int 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 */
+ volatile struct dga *dga; /* Gate Array reg structure pntr */
+ volatile struct duart *duart; /* DUART reg structure pointer */
+ volatile struct adder *adder; /* ADDER reg structure pointer */
struct prgkbd *cmdbuf;
struct prg_cursor *curs;
struct _vs_cursor *pos;
@@ -948,6 +1097,10 @@ qdioctl(dev, cmd, datap, flags)
int error;
int s;
short *temp; /* a pointer to template RAM */
+ struct uba_softc *uh;
+
+ uh = (struct uba_softc *)
+ (((struct device *)(qd_cd.cd_devs[unit]))->dv_parent);
/*
* service graphic device ioctl commands
@@ -1045,7 +1198,7 @@ qdioctl(dev, cmd, datap, flags)
break;
case QD_MAPDEVICE:
- /*
+ /*
* enable 'user write' to device pages
*/
qdflags[unit].mapped |= MAPDEV;
@@ -1055,37 +1208,47 @@ qdioctl(dev, cmd, datap, flags)
*/
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;
- /*
+ for (i = 0; i < vax_btop(TMPSIZE); i++, ptep++)
+ *ptep = (*ptep & ~PG_PROT) | PG_RW | 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;
+ for (i = 0; i < vax_btop(REGSIZE); i++, ptep++)
+ *ptep = (*ptep & ~PG_PROT) | PG_RW | 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;
- /*
+ for (i = 0; i < vax_btop(CLRSIZE); i++, ptep++)
+ *ptep = (*ptep & ~PG_PROT) | PG_RW | 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 */
+ *ptep = (*ptep & ~PG_PROT) | PG_RW | PG_V; /* duart page */
- mtpr(TBIA, 0); /* invalidate translation buffer */
+ mtpr(0, PR_TBIA); /* invalidate translation buffer */
/*
* stuff qdmap structure in return buffer
*/
bcopy((caddr_t)qd, datap, sizeof(struct qdmap));
+
break;
+#ifdef notyet
+/*
+ * Ragge 999620:
+ * Can't map in the graphic buffer into user space for now.
+ * The best way to fix this is to convert this driver to wscons.
+ */
case QD_MAPIOBUF:
/*
* do setup for DMA by user process
@@ -1094,15 +1257,15 @@ qdioctl(dev, cmd, datap, flags)
*/
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 */
+ + (mfpr(PR_SBR) | 0x80000000));
+ for (i = 0; i < vax_btop(DMAbuf_size); i++, ptep++)
+ *ptep = (*ptep & ~PG_PROT) | PG_RW | PG_V;
+ mtpr(0, PR_TBIA); /* invalidate translation buffer */
/*
* set up QBUS map registers for DMA
*/
DMAheader[unit]->QBAreg =
- uballoc(0, (caddr_t)DMAheader[unit], DMAbuf_size, 0);
+ uballoc(uh, (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;
@@ -1112,6 +1275,7 @@ qdioctl(dev, cmd, datap, flags)
*/
*(int *)datap = (int) DMAheader[unit];
break;
+#endif
case QD_MAPSCROLL:
/*
@@ -1119,12 +1283,12 @@ qdioctl(dev, cmd, datap, flags)
*/
qdflags[unit].mapped |= MAPSCR;
ptep = (int *) ((VTOP(scroll[unit]) * 4)
- + (mfpr(SBR) | 0x80000000));
+ + (mfpr(PR_SBR) | 0x80000000));
/*
* allow user write to scroll area
*/
- *ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V;
- mtpr(TBIA, 0); /* invalidate translation buf */
+ *ptep = (*ptep & ~PG_PROT) | PG_RW | PG_V;
+ mtpr(0, PR_TBIA); /* invalidate translation buf */
scroll[unit]->status = 0;
adder = (struct adder *) qdmap[unit].adder;
qdflags[unit].adder_ie |= FRAME_SYNC;
@@ -1139,12 +1303,12 @@ qdioctl(dev, cmd, datap, flags)
if (qdflags[unit].mapped & MAPSCR) {
qdflags[unit].mapped &= ~MAPSCR;
ptep = (int *) ((VTOP(scroll[unit]) * 4)
- + (mfpr(SBR) | 0x80000000));
+ + (mfpr(PR_SBR) | 0x80000000));
/*
* re-protect 512 scroll param area
*/
*ptep = (*ptep & ~PG_PROT) | PG_KW | PG_V;
- mtpr(TBIA, 0); /* smash CPU's translation buf */
+ mtpr(0, PR_TBIA); /* smash CPU's translation buf */
adder = (struct adder *) qdmap[unit].adder;
qdflags[unit].adder_ie &= ~FRAME_SYNC;
adder->interrupt_enable = qdflags[unit].adder_ie;
@@ -1157,13 +1321,13 @@ qdioctl(dev, cmd, datap, flags)
*/
qdflags[unit].mapped |= MAPCOLOR;
ptep = (int *) ((VTOP(color_buf[unit]) * 4)
- + (mfpr(SBR) | 0x80000000));
+ + (mfpr(PR_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 */
+ *ptep = (*ptep & ~PG_PROT) | PG_RW | PG_V; ptep++;
+ *ptep = (*ptep & ~PG_PROT) | PG_RW | PG_V;
+ mtpr(0, PR_TBIA); /* clr CPU translation buf */
adder = (struct adder *) qdmap[unit].adder;
qdflags[unit].adder_ie |= VSYNC;
adder->interrupt_enable = qdflags[unit].adder_ie;
@@ -1180,13 +1344,13 @@ qdioctl(dev, cmd, datap, flags)
if (qdflags[unit].mapped & MAPCOLOR) {
qdflags[unit].mapped &= ~MAPCOLOR;
ptep = (int *) ((VTOP(color_buf[unit]) * 4)
- + (mfpr(SBR) | 0x80000000));
+ + (mfpr(PR_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);
+ mtpr(0, PR_TBIA);
adder = (struct adder *) qdmap[unit].adder;
qdflags[unit].adder_ie &= ~VSYNC;
adder->interrupt_enable = qdflags[unit].adder_ie;
@@ -1199,13 +1363,13 @@ qdioctl(dev, cmd, datap, flags)
*/
qdflags[unit].mapped |= MAPEQ;
ptep = (int *) ((VTOP(eq_header[unit]) * 4)
- + (mfpr(SBR) | 0x80000000));
+ + (mfpr(PR_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 */
+ *ptep = (*ptep & ~PG_PROT) | PG_RW | PG_V; ptep++;
+ *ptep = (*ptep & ~PG_PROT) | PG_RW | PG_V;
+ mtpr(0, PR_TBIA); /* clr CPU translation buf */
/*
* return event queue address
*/
@@ -1322,13 +1486,14 @@ qdioctl(dev, cmd, datap, flags)
* service tty ioctl's
*/
if (!(minor_dev & 0x02)) {
- tp = &qd_tty[minor_dev];
+ tp = qd_tty[minor_dev];
error =
- (*linesw[tp->t_line].l_ioctl)(tp, cmd, datap, flags);
+
+ (*linesw[tp->t_line].l_ioctl)(tp, cmd, datap, flags, p);
if (error >= 0) {
return(error);
}
- error = ttioctl(tp, cmd, datap, flags);
+ error = ttioctl(tp, cmd, datap, flags, p);
if (error >= 0) {
return(error);
}
@@ -1340,96 +1505,110 @@ qdioctl(dev, cmd, datap, flags)
} /* qdioctl */
-qdselect(dev, rw)
+
+int
+qdpoll(dev, events, p)
dev_t dev;
- int rw;
+ int events;
+ struct proc *p;
{
- register s;
- register unit;
+ register int s;
+ register int unit;
register struct tty *tp;
u_int minor_dev = minor(dev);
+ int revents = 0;
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);
- }
+ if ((minor_dev & 0x03) == 2) {
+ /*
+ * This is a graphics device, so check for events.
+ */
- case FWRITE:
- if ((minor(dev) & 0x03) == 2) {
- /*
- * this is a graphics device, so check for dma buffers
- */
+ if (events & (POLLIN | POLLRDNORM))
+ if(!(ISEMPTY(eq_header[unit])))
+ revents |= events & (POLLIN | POLLRDNORM);
+
+ if (events & (POLLOUT | POLLWRNORM))
if (DMA_ISEMPTY(DMAheader[unit]))
- {
- splx(s);
- return(1);
+ revents |= events & (POLLOUT | POLLWRNORM);
+
+ if (revents == 0) {
+ if (events & (POLLIN | POLLRDNORM)) {
+ selrecord(p, &qdrsel[unit]);
+ qdflags[unit].selmask |= SEL_READ;
}
- 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 (events & (POLLOUT | POLLWRNORM)) {
+ selrecord(p, &qdrsel[unit]);
+ qdflags[unit].selmask |= SEL_WRITE;
+ }
+ }
+ } else {
+ /*
+ * this is a tty device
+ */
+ tp = qd_tty[minor_dev];
+
+ if (events & (POLLIN | POLLRDNORM)) {
+ /* This is ttnread. It's static and I don't feel
+ * like altering platform independant parts of NetBSD
+ */
+ int nread;
+ /* if (tp->t_lflag & PENDIN)
+ ttypend(tp); */
+ nread = tp->t_canq.c_cc;
+ if (!(tp->t_lflag & ICANON)) {
+ nread += tp->t_rawq.c_cc;
+ if (nread < tp->t_cc[VMIN] && !tp->t_cc[VTIME])
+ nread = 0;
+ }
+ if (nread > 0)
+ revents |= events & (POLLIN | POLLRDNORM);
+ }
+
+ if (events & (POLLOUT | POLLWRNORM))
if (tp->t_outq.c_cc <= tp->t_lowat)
- return(1);
- tp->t_wsel = u.u_procp;
- splx(s);
- return(0);
+ revents |= events & (POLLOUT | POLLWRNORM);
+
+ if (revents == 0) {
+ if (events & (POLLIN | POLLRDNORM))
+ selrecord(p, &tp->t_rsel);
+
+ if (events & (POLLOUT | POLLWRNORM))
+ selrecord(p, &tp->t_wsel);
}
}
+
splx(s);
- return(0);
+ return (revents);
+} /* qdpoll() */
-} /* qdselect() */
-extern qd_strategy();
+void qd_strategy(struct buf *bp);
-qdwrite(dev, uio)
+/*ARGSUSED*/
+int
+qdwrite(dev, uio, flag)
dev_t dev;
struct uio *uio;
{
register struct tty *tp;
- register minor_dev;
- register unit;
+ register int minor_dev;
+ register int 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));
+ tp = qd_tty[minor_dev];
+ return ((*linesw[tp->t_line].l_write)(tp, uio, flag));
} else if (qdflags[unit].inuse & GRAPHIC_DEV) {
- /*
+ /*
* this is a DMA xfer from user space
*/
return (physio(qd_strategy, &qdbuf[unit],
@@ -1438,25 +1617,27 @@ qdwrite(dev, uio)
return (ENXIO);
}
-qdread(dev, uio)
+/*ARGSUSED*/
+int
+qdread(dev, uio, flag)
dev_t dev;
struct uio *uio;
{
register struct tty *tp;
- register minor_dev;
- register unit;
+ register int minor_dev;
+ register int 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));
+ tp = qd_tty[minor_dev];
+ return ((*linesw[tp->t_line].l_read)(tp, uio, flag));
} else if (qdflags[unit].inuse & GRAPHIC_DEV) {
- /*
+ /*
* this is a bitmap-to-processor xfer
*/
return (physio(qd_strategy, &qdbuf[unit],
@@ -1471,26 +1652,34 @@ qdread(dev, uio)
*
***************************************************************/
+void
qd_strategy(bp)
register struct buf *bp;
{
- register struct dga *dga;
- register struct adder *adder;
- register unit;
+ volatile register struct dga *dga;
+ volatile register struct adder *adder;
+ register int unit;
int QBAreg;
int s;
int cookie;
-
+ struct uba_softc *uh;
+
unit = (minor(bp->b_dev) >> 2) & 0x07;
+ uh = (struct uba_softc *)
+ (((struct device *)(qd_cd.cd_devs[unit]))->dv_parent);
+
/*
* init pointers
*/
- if ((QBAreg = ubasetup(0, bp, 0)) == 0) {
+ dga = (struct dga *) qdmap[unit].dga;
+panic("qd_strategy");
+#ifdef notyet
+ if ((QBAreg = ubasetup(uh, bp, 0)) == 0) {
printf("qd%d: qd_strategy: QBA setup error\n", unit);
goto STRAT_ERR;
}
- dga = (struct dga *) qdmap[unit].dga;
+#endif
s = spl5();
qdflags[unit].user_dma = -1;
dga->csr |= DMA_IE;
@@ -1499,18 +1688,20 @@ qd_strategy(bp)
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);
+#ifdef notyet
+ ubarelse(uh, &QBAreg);
+#endif
if (!(dga->csr & DMA_ERR)) {
- iodone(bp);
+ biodone(bp);
return;
}
-STRAT_ERR:
+/* STRAT_ERR: */
adder = (struct adder *) qdmap[unit].adder;
adder->command = CANCEL; /* cancel adder activity */
dga->csr &= ~DMA_IE;
@@ -1527,17 +1718,17 @@ STRAT_ERR:
DMA_SETIGNORE(DMAheader[unit]);
dga->csr |= DMA_IE;
}
- iodone(bp);
-
+ biodone(bp);
} /* qd_strategy */
+
/*
* Start output to the console screen
*/
-qdstart(tp)
- register struct tty *tp;
+void qdstart(tp)
+ struct tty *tp;
{
- register which_unit, unit, c;
+ register int which_unit, unit, c;
int s;
unit = minor(tp->t_dev);
@@ -1586,30 +1777,31 @@ out:
/*ARGSUSED*/
void
qdstop(tp, flag)
- register struct tty *tp;
+ 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_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
*/
-
+void
blitc(unit, chr)
- register unit;
- register u_char chr;
+ int unit;
+ u_char chr;
{
- register struct adder *adder;
- register struct dga *dga;
+ volatile register struct adder *adder;
+ volatile register struct dga *dga;
register int i;
int nograph = !(qdflags[unit].inuse&GRAPHIC_DEV);
static short inescape[NQD];
@@ -1804,8 +1996,6 @@ blitc(unit, chr)
} /* blitc */
-qdreset() { }
-
/*
* INTERRUPT SERVICE ROUTINES
*/
@@ -1813,13 +2003,16 @@ qdreset() { }
/*
* Service "DMA DONE" interrupt condition
*/
-qddint(qd)
- register qd;
+
+static void
+qddint(arg)
+ void *arg;
{
+ struct device *dv = arg;
register struct DMAreq_header *header;
register struct DMAreq *request;
- register struct dga *dga;
- struct adder *adder;
+ volatile register struct dga *dga;
+ volatile struct adder *adder;
int cookie; /* DMA adrs for QDSS */
(void)spl4(); /* allow interval timer in */
@@ -1827,15 +2020,15 @@ qddint(qd)
/*
* init pointers
*/
- header = DMAheader[qd]; /* register for optimization */
- dga = (struct dga *) qdmap[qd].dga;
- adder = (struct adder *) qdmap[qd].adder;
+ header = DMAheader[dv->dv_unit]; /* register for optimization */
+ dga = (struct dga *) qdmap[dv->dv_unit].dga;
+ adder = (struct adder *) qdmap[dv->dv_unit].adder;
/*
* if this interrupt flagged as bogus for interrupt flushing purposes..
*/
if (DMA_ISIGNORE(header)) {
- DMA_CLRIGNORE(header);
+ DMA_CLRIGNORE(header);
return;
}
@@ -1845,18 +2038,18 @@ qddint(qd)
if (dga->csr & DMA_ERR) {
if (dga->csr & PARITY_ERR)
- printf("qd%d: qddint: DMA hardware parity fault.\n", qd);
+ printf("qd%d: qddint: DMA hardware parity fault.\n", dv->dv_unit);
if (dga->csr & BUS_ERR)
- printf("qd%d: qddint: DMA hardware bus error.\n", qd);
+ printf("qd%d: qddint: DMA hardware bus error.\n", dv->dv_unit);
}
/*
* 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);
+ if (qdflags[dv->dv_unit].user_dma) {
+ qdflags[dv->dv_unit].user_dma = 0;
+ wakeup((caddr_t)&qdflags[dv->dv_unit].user_dma);
return;
}
@@ -1875,10 +2068,10 @@ qddint(qd)
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 (qdrsel[dv->dv_unit].si_pid && qdflags[dv->dv_unit].selmask & SEL_WRITE) {
+ selwakeup(&qdrsel[dv->dv_unit]);
+ qdrsel[dv->dv_unit].si_pid = 0;
+ qdflags[dv->dv_unit].selmask &= ~SEL_WRITE;
}
if (dga->bytcnt_lo != 0) {
@@ -1894,10 +2087,10 @@ qddint(qd)
* 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;
+ if (qdrsel[dv->dv_unit].si_pid && qdflags[dv->dv_unit].selmask & SEL_WRITE) {
+ selwakeup(&qdrsel[dv->dv_unit]);
+ qdrsel[dv->dv_unit].si_pid = 0;
+ qdflags[dv->dv_unit].selmask &= ~SEL_WRITE;
}
}
@@ -1914,13 +2107,11 @@ qddint(qd)
* 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;
+ if (qdrsel[dv->dv_unit].si_pid && qdflags[dv->dv_unit].selmask & SEL_WRITE) {
+ selwakeup(&qdrsel[dv->dv_unit]);
+ qdrsel[dv->dv_unit].si_pid = 0;
+ qdflags[dv->dv_unit].selmask &= ~SEL_WRITE;
}
-
DMA_CLRACTIVE(header); /* flag DMA done */
return;
}
@@ -1968,7 +2159,7 @@ qddint(qd)
}
break;
default:
- printf("qd%d: qddint: illegal DMAtype parameter.\n", qd);
+ printf("qd%d: qddint: illegal DMAtype parameter.\n", dv->dv_unit);
DMA_CLRACTIVE(header); /* flag DMA done */
return;
}
@@ -2002,20 +2193,22 @@ qddint(qd)
/*
* ADDER interrupt service routine
*/
-qdaint(qd)
- register qd;
+static void
+qdaint(arg)
+ void *arg;
{
- register struct adder *adder;
+ struct device *dv = arg;
+ volatile register struct adder *adder;
struct color_buf *cbuf;
int i;
register struct rgb *rgbp;
- register short *red;
- register short *green;
- register short *blue;
+ volatile register short *red;
+ volatile register short *green;
+ volatile register short *blue;
(void)spl4(); /* allow interval timer in */
- adder = (struct adder *) qdmap[qd].adder;
+ adder = (struct adder *) qdmap[dv->dv_unit].adder;
/*
* service the vertical blank interrupt (VSYNC bit) by loading
@@ -2023,12 +2216,12 @@ qdaint(qd)
*/
if (adder->status & VSYNC) {
adder->status &= ~VSYNC; /* clear the interrupt */
- cbuf = color_buf[qd];
+ cbuf = color_buf[dv->dv_unit];
if (cbuf->status & LOAD_COLOR_MAP) {
- red = (short *) qdmap[qd].red;
- green = (short *) qdmap[qd].green;
- blue = (short *) qdmap[qd].blue;
+ red = (short *) qdmap[dv->dv_unit].red;
+ green = (short *) qdmap[dv->dv_unit].green;
+ blue = (short *) qdmap[dv->dv_unit].blue;
for (i = cbuf->count, rgbp = cbuf->rgb;
--i >= 0; rgbp++) {
@@ -2047,7 +2240,7 @@ qdaint(qd)
if (adder->status & FRAME_SYNC) {
adder->status &= ~FRAME_SYNC; /* clear the interrupt */
- if (scroll[qd]->status & LOAD_REGS) {
+ if (scroll[dv->dv_unit]->status & LOAD_REGS) {
for (i = 1000, adder->status = 0; i > 0 &&
!(adder->status&ID_SCROLL_READY); --i)
@@ -2059,22 +2252,22 @@ qdaint(qd)
return;
}
- adder->ID_scroll_data = scroll[qd]->viper_constant;
+ adder->ID_scroll_data = scroll[dv->dv_unit]->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;
+ scroll[dv->dv_unit]->y_scroll_constant;
+ adder->y_offset_pending = scroll[dv->dv_unit]->y_offset;
- if (scroll[qd]->status & LOAD_INDEX) {
+ if (scroll[dv->dv_unit]->status & LOAD_INDEX) {
adder->x_index_pending =
- scroll[qd]->x_index_pending;
+ scroll[dv->dv_unit]->x_index_pending;
adder->y_index_pending =
- scroll[qd]->y_index_pending;
+ scroll[dv->dv_unit]->y_index_pending;
}
- scroll[qd]->status = 0x00;
+ scroll[dv->dv_unit]->status = 0x00;
}
}
}
@@ -2086,15 +2279,16 @@ qdaint(qd)
* straight line code.
*/
-qdiint(qd)
- register qd;
+static void
+qdiint(arg)
+ void *arg;
{
+ struct device *dv = arg;
register struct _vs_event *event;
register struct qdinput *eqh;
- struct dga *dga;
- struct duart *duart;
+ volatile struct dga *dga;
+ volatile struct duart *duart;
struct mouse_report *new_rep;
- struct uba_device *ui;
struct tty *tp;
u_short chr;
u_short status;
@@ -2105,14 +2299,14 @@ qdiint(qd)
(void)spl4(); /* allow interval timer in */
- eqh = eq_header[qd]; /* optimized as a register */
- new_rep = &current_rep[qd];
- duart = (struct duart *) qdmap[qd].duart;
+ eqh = eq_header[dv->dv_unit]; /* optimized as a register */
+ new_rep = &current_rep[dv->dv_unit];
+ duart = (struct duart *) qdmap[dv->dv_unit].duart;
/*
* if the graphic device is turned on..
*/
- if (qdflags[qd].inuse & GRAPHIC_DEV) {
+ if (qdflags[dv->dv_unit].inuse & GRAPHIC_DEV) {
/*
* empty DUART
*/
@@ -2175,7 +2369,7 @@ qdiint(qd)
* pick up the mouse input (if any) */
if ((status = duart->statusB) & RCV_RDY &&
- qdflags[qd].pntr_id == MOUSE_ID) {
+ qdflags[dv->dv_unit].pntr_id == MOUSE_ID) {
if (status & 0x70) {
duart->cmdB = 0x40;
@@ -2230,17 +2424,17 @@ qdiint(qd)
/*
* calculate acceleration factor, if needed */
- if (qdflags[qd].curs_acc > ACC_OFF) {
+ if (qdflags[dv->dv_unit].curs_acc > ACC_OFF) {
- if (qdflags[qd].curs_thr <= new_rep->dx)
+ if (qdflags[dv->dv_unit].curs_thr <= new_rep->dx)
new_rep->dx +=
- (new_rep->dx - qdflags[qd].curs_thr)
- * qdflags[qd].curs_acc;
+ (new_rep->dx - qdflags[dv->dv_unit].curs_thr)
+ * qdflags[dv->dv_unit].curs_acc;
- if (qdflags[qd].curs_thr <= new_rep->dy)
+ if (qdflags[dv->dv_unit].curs_thr <= new_rep->dy)
new_rep->dy +=
- (new_rep->dy - qdflags[qd].curs_thr)
- * qdflags[qd].curs_acc;
+ (new_rep->dy - qdflags[dv->dv_unit].curs_thr)
+ * qdflags[dv->dv_unit].curs_acc;
}
/*
@@ -2271,7 +2465,7 @@ qdiint(qd)
/*
* update cursor screen position */
- dga = (struct dga *) qdmap[qd].dga;
+ dga = (struct dga *) qdmap[dv->dv_unit].dga;
dga->x_cursor = TRANX(eqh->curs_pos.x);
dga->y_cursor = TRANY(eqh->curs_pos.y);
@@ -2308,7 +2502,7 @@ GET_MBUTTON:
* if button state has changed */
a = new_rep->state & 0x07; /*mask nonbutton bits */
- b = last_rep[qd].state & 0x07;
+ b = last_rep[dv->dv_unit].state & 0x07;
if (a ^ b) {
@@ -2356,11 +2550,11 @@ GET_MBUTTON:
/* refresh last report */
- last_rep[qd] = current_rep[qd];
+ last_rep[dv->dv_unit] = current_rep[dv->dv_unit];
} /* get last byte of report */
} else if ((status = duart->statusB)&RCV_RDY &&
- qdflags[qd].pntr_id == TABLET_ID) {
+ qdflags[dv->dv_unit].pntr_id == TABLET_ID) {
/*
* pickup tablet input, if any
*/
@@ -2422,9 +2616,9 @@ GET_MBUTTON:
/*
* update cursor position coordinates */
- new_rep->dx /= qdflags[qd].tab_res;
+ new_rep->dx /= qdflags[dv->dv_unit].tab_res;
new_rep->dy = (2200 - new_rep->dy)
- / qdflags[qd].tab_res;
+ / qdflags[dv->dv_unit].tab_res;
if (new_rep->dx > 1023) {
new_rep->dx = 1023;
@@ -2446,7 +2640,7 @@ GET_MBUTTON:
/*
* update cursor screen position */
- dga = (struct dga *) qdmap[qd].dga;
+ dga = (struct dga *) qdmap[dv->dv_unit].dga;
dga->x_cursor = TRANX(eqh->curs_pos.x);
dga->y_cursor = TRANY(eqh->curs_pos.y);
@@ -2487,7 +2681,7 @@ GET_TBUTTON:
* if button state has changed */
a = new_rep->state & 0x1E; /* mask nonbutton bits */
- b = last_rep[qd].state & 0x1E;
+ b = last_rep[dv->dv_unit].state & 0x1E;
if (a ^ b) {
@@ -2536,7 +2730,7 @@ GET_TBUTTON:
/* refresh last report */
- last_rep[qd] = current_rep[qd];
+ last_rep[dv->dv_unit] = current_rep[dv->dv_unit];
} /* get last byte of report */
} /* pick up tablet input */
@@ -2546,10 +2740,10 @@ GET_TBUTTON:
/*
* 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;
+ if (qdrsel[dv->dv_unit].si_pid && do_wakeup && qdflags[dv->dv_unit].selmask & SEL_READ) {
+ selwakeup(&qdrsel[dv->dv_unit]);
+ qdrsel[dv->dv_unit].si_pid = 0;
+ qdflags[dv->dv_unit].selmask &= ~SEL_READ;
do_wakeup = 0;
}
} else {
@@ -2558,11 +2752,11 @@ GET_TBUTTON:
*/
if (qdpolling)
return;
- ui = qdinfo[qd];
- if (ui == 0 || ui->ui_alive == 0)
- return;
+
+ if (dv->dv_unit >= qd_cd.cd_ndevs || qd_cd.cd_devs[dv->dv_unit] == NULL)
+ return; /* no such device or address */
- tp = &qd_tty[qd << 2];
+ tp = qd_tty[dv->dv_unit << 2];
/*
* Get a character from the keyboard.
@@ -2590,10 +2784,10 @@ GET_TBUTTON:
case LOCK:
q_keyboard.lock ^= 0xffff; /* toggle */
if (q_keyboard.lock)
- (void)led_control(qd, LK_LED_ENABLE,
+ led_control(qd, LK_LED_ENABLE,
LK_LED_LOCK);
else
- (void)led_control(qd, LK_LED_DISABLE,
+ led_control(qd, LK_LED_DISABLE,
LK_LED_LOCK);
return;
@@ -2646,8 +2840,17 @@ GET_TBUTTON:
(*linesw[tp->t_line].l_rint)(*string++, tp);
}
else {
-#ifdef KADB
- if (!kdbrintr(chr&0177, tp))
+#ifdef DDB
+ /* Check for kernel debugger escape here */
+ int j;
+
+ j = kdbrint(chr&0177);
+
+ 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)(chr&0177, tp);
}
@@ -2671,10 +2874,11 @@ GET_TBUTTON:
* bitmap
*
*/
+void
clear_qd_screen(unit)
int unit;
{
- register struct adder *adder;
+ volatile register struct adder *adder;
adder = (struct adder *) qdmap[unit].adder;
adder->x_limit = 1024;
@@ -2703,14 +2907,16 @@ clear_qd_screen(unit)
/*
* kernel console output to the glass tty
*/
-qdputc(chr)
- register char chr;
+void
+qdcnputc(dev, chr)
+ dev_t dev;
+ int chr;
{
/*
* if system is now physical, forget it (ie: crash DUMP)
*/
- if ((mfpr(MAPEN) & 1) == 0)
+ if ((mfpr(PR_MAPEN) & 1) == 0)
return;
blitc(0, (u_char)(chr & 0xff));
@@ -2722,12 +2928,13 @@ qdputc(chr)
/*
* load the mouse cursor's template RAM bitmap
*/
+void
ldcursor(unit, bitmap)
int unit;
- register short *bitmap;
+ short *bitmap;
{
- register struct dga *dga;
- register short *temp;
+ volatile register struct dga *dga;
+ volatile register short *temp;
register int i;
int curs;
@@ -2756,12 +2963,13 @@ ldcursor(unit, bitmap)
/*
* Put the console font in the QDSS off-screen memory
*/
+void
ldfont(unit)
int unit;
{
- register struct adder *adder;
+ volatile register struct adder *adder;
- register i, j, k, max_chars_line;
+ register int i, j, k, max_chars_line;
register short packed;
adder = (struct adder *) qdmap[unit].adder;
@@ -2881,19 +3089,30 @@ ldfont(unit)
} /* ldfont */
-qdpoll(onoff)
+
+/*
+ * Disable or enable polling. This is used when entering or leaving the
+ * kernel debugger.
+ */
+void
+qdcnpollc(dev, onoff)
+ dev_t dev;
+ int onoff;
{
- qdpolling = onoff;
+ qdpolling = onoff;
}
+
/*
* Get a character from the LK201 (polled)
*/
-qdgetc()
+int
+qdcngetc(dev)
+ dev_t dev;
{
register short key;
register char chr;
- register struct duart *duart;
+ volatile register struct duart *duart;
duart = (struct duart *) qdmap[0].duart;
@@ -2927,9 +3146,9 @@ LOOP:
case LOCK:
q_keyboard.lock ^= 0xffff; /* toggle */
if (q_keyboard.lock)
- (void)led_control(0, LK_LED_ENABLE, LK_LED_LOCK);
+ led_control(0, LK_LED_ENABLE, LK_LED_LOCK);
else
- (void)led_control(0, LK_LED_DISABLE, LK_LED_LOCK);
+ led_control(0, LK_LED_DISABLE, LK_LED_LOCK);
goto LOOP;
case SHIFT:
@@ -2985,11 +3204,12 @@ LOOP:
/*
* led_control()... twiddle LK-201 LED's
*/
+void
led_control(unit, cmd, led_mask)
int unit, cmd, led_mask;
{
- register i;
- register struct duart *duart;
+ register int i;
+ volatile register struct duart *duart;
duart = (struct duart *)qdmap[unit].duart;
@@ -3005,17 +3225,16 @@ led_control(unit, cmd, led_mask)
break;
}
}
- if (i == 0)
- return(BAD);
- return(GOOD);
+ return;
} /* led_control */
/*
* scroll_up()... move the screen up one character height
*/
+void
scroll_up(adder)
- register struct adder *adder;
+ volatile struct adder *adder;
{
/*
* setup VIPER operand control registers
@@ -3076,10 +3295,11 @@ scroll_up(adder)
/*
* init shared memory pointers and structures
*/
+void
init_shared(unit)
- register unit;
+ int unit;
{
- register struct dga *dga;
+ volatile register struct dga *dga;
dga = (struct dga *) qdmap[unit].dga;
@@ -3138,21 +3358,22 @@ init_shared(unit)
/*
* init the ADDER, VIPER, bitmaps, & color map
*/
+void
setup_dragon(unit)
int unit;
{
- register struct adder *adder;
- register struct dga *dga;
- short *memcsr;
- register i;
+ volatile register struct adder *adder;
+ volatile register struct dga *dga;
+ volatile short *memcsr;
+ register int i;
short top; /* clipping/scrolling boundaries */
short bottom;
short right;
short left;
- short *red; /* color map pointers */
- short *green;
- short *blue;
+ volatile short *red; /* color map pointers */
+ volatile short *green;
+ volatile short *blue;
/*
* init for setup
@@ -3392,11 +3613,12 @@ setup_dragon(unit)
/*
* Init the DUART and set defaults in input
*/
+void
setup_input(unit)
int unit;
{
- register struct duart *duart; /* DUART register structure pointer */
- register i, bits;
+ volatile register struct duart *duart; /* DUART register structure pointer */
+ register int i, bits;
char id_byte;
duart = (struct duart *) qdmap[unit].duart;
@@ -3558,11 +3780,12 @@ OUT:
* vertical sync status bit
* GOOD otherwise
*/
+int
wait_status(adder, mask)
- register struct adder *adder;
- register int mask;
+ volatile struct adder *adder;
+ int mask;
{
- register i;
+ register int i;
for (i = 10000, adder->status = 0 ; i > 0 &&
!(adder->status&mask) ; --i)
@@ -3580,12 +3803,13 @@ wait_status(adder, mask)
/*
* write out onto the ID bus
*/
+void
write_ID(adder, adrs, data)
- register struct adder *adder;
- register short adrs;
- register short data;
+ volatile struct adder *adder;
+ short adrs;
+ short data;
{
- register i;
+ register int i;
for (i = 100000, adder->status = 0 ;
i > 0 && !(adder->status&ADDRESS_COMPLETE) ; --i)
@@ -3609,4 +3833,3 @@ ERR:
return ;
} /* write_ID */
-#endif
diff --git a/sys/arch/vax/qbus/qdioctl.h b/sys/arch/vax/qbus/qdioctl.h
new file mode 100644
index 00000000000..3e91b891b01
--- /dev/null
+++ b/sys/arch/vax/qbus/qdioctl.h
@@ -0,0 +1,118 @@
+/* $OpenBSD: qdioctl.h,v 1.1 2000/04/27 03:14:48 bjc Exp $ */
+/* $NetBSD: qdioctl.h,v 1.1 1998/03/21 10:02:39 ragge Exp $ */
+/*-
+ * Copyright (c) 1982, 1986
+ * 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.
+ *
+ * @(#)qdioctl.h 7.2 (Berkeley) 1/21/94
+ */
+
+/*
+ * derived from: qdioctl.h 1.1 (ULTRIX) 8/22/85
+ */
+/*
+ * QDSS IOCTL definitions
+ */
+
+
+/************************************************************************
+ * *
+ * 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. *
+ * *
+ ************************************************************************/
+/***************************************************************************
+* revision history: (belongs in sccs)
+****************************************************************************
+*
+* 22 oct 85 longo fixed QD_PRGTABRES cmd number to be 22 instead of 12
+* 14 oct 85 longo added QD_KERN_LOOP and QD_KERN_UNLOOP
+* 02 oct 85 longo added QD_MAPCOLOR and QD_UNMAPCOLOR
+* 17 sep 85 longo made QD_MAPIOBUF a read/write command type
+*
+***************************************************************************/
+
+
+#ifdef KERNEL
+#include "sys/ioctl.h"
+#else
+#include <sys/ioctl.h>
+#endif
+
+
+#define QD_GETEVENT _IOR('g', 1, struct _vs_event) /* get oldest event */
+#define QD_WTCURSOR _IOW('g', 2, short[32]) /* write cursor bitmap */
+#define QD_RDCURSOR _IOR('g', 3, 64) /* read cursor bitmap */
+#define QD_CLRSCRN _IO('g', 4) /* clear the screen */
+#define QD_RDCONFIG _IOR('g', 5, short) /* read QDSS configuration */
+#define QD_PRGMOUSE _IOW('g', 6, char) /* program mouse */
+#define QD_PRGTABLET _IOW('g', 7, char) /* program tablet */
+#define QD_PRGKBD _IOW('g', 8, struct prgkbd) /* program LK201 kbd */
+#define QD_MAPDEVICE _IOR('g', 9, struct qdmap) /* map device to user */
+#define QD_MAPIOBUF _IOWR('g', 10, caddr_t) /* map DMA iobuf to user */
+#define QD_MAPEVENT _IOR('g', 11, caddr_t) /* map event queue to user */
+#define QD_PRGCURSOR _IOW('g', 12, struct prg_cursor) /* program cursor */
+#define QD_RESET _IO('g', 13) /* set device & driver defaults */
+#define QD_POSCURSOR _IOW('g', 14, struct _vs_cursor) /* position cursor */
+#define QD_SET _IO('g', 15) /* set DUART & driver defaults */
+#define QD_MAPSCROLL _IOR('g', 16, caddr_t) /* map scroll param area */
+#define QD_UNMAPSCROLL _IO('g', 17) /* unmap scroll param area */
+#define QD_MAPCOLOR _IOR('g', 18, caddr_t) /* map color map write buf */
+#define QD_UNMAPCOLOR _IO('g', 19) /* unmap color map write buf */
+#define QD_KERN_LOOP _IO('g', 20) /* detour kernel console output */
+#define QD_KERN_UNLOOP _IO('g', 21) /* un-detour kernel console output */
+#define QD_PRGTABRES _IOW('g', 22, short) /* program tablet resolution */
diff --git a/sys/arch/vax/qbus/qdreg.h b/sys/arch/vax/qbus/qdreg.h
new file mode 100644
index 00000000000..d6aa7452ceb
--- /dev/null
+++ b/sys/arch/vax/qbus/qdreg.h
@@ -0,0 +1,381 @@
+/* $OpenBSD: qdreg.h,v 1.1 2000/04/27 03:14:48 bjc Exp $ */
+/* $NetBSD: qdreg.h,v 1.1 1998/03/21 10:02:39 ragge Exp $ */
+/*-
+ * Copyright (c) 1982, 1986 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.
+ *
+ * @(#)qdreg.h 7.1 (Berkeley) 5/9/91
+ */
+
+/************************************************************************
+ * *
+ * Copyright (c) 1985, 1986 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. *
+ * *
+ ************************************************************************/
+
+/* Dragon ADDER reg map */
+/* ADDER register bit definitions */
+/* Y_SCROLL_CONSTANT */
+
+#define SCROLL_ERASE 0x2000
+#define ADDER_SCROLL_DOWN 0x1000
+
+/* ADDER status and interrupt enable registers [1], [2], [3] */
+
+#define DISABLE 0x0000
+#define PAUSE_COMPLETE 0x0001
+#define FRAME_SYNC 0x0002
+#define INIT_COMPLETE 0x0004
+#define RASTEROP_COMPLETE 0x0008
+
+#define ADDRESS_COMPLETE 0x0010
+#define RX_READY 0x0020
+#define TX_READY 0x0040
+#define ID_SCROLL_READY 0x0080
+
+#define TOP_CLIP 0x0100
+#define BOTTOM_CLIP 0x0200
+#define LEFT_CLIP 0x0400
+#define RIGHT_CLIP 0x0800
+#define NO_CLIP 0x1000
+#define VSYNC 0x2000
+
+/* ADDER command register [8], [10] */
+
+#define OCR_zero 0x0000
+#define Z_BLOCK0 0x0000
+#define OCRA 0x0000
+#define OCRB 0x0004
+#define RASTEROP 0x02c0
+#define PBT 0x03c0
+#define BTPZ 0x0bb0
+#define PTBZ 0x07a0
+#define DTE 0x0400
+#define S1E 0x0800
+#define S2E 0x1000
+#define VIPER_Z_LOAD 0x01A0
+#define ID_LOAD 0x0100
+#define CANCEL 0x0000
+#define LF_R1 0x0000
+#define LF_R2 0x0010
+#define LF_R3 0x0020
+#define LF_R4 0x0030
+
+/* ADDER rasterop mode register [9] */
+
+#define NORMAL 0x0000
+#define LINEAR_PATTERN 0x0002
+#define X_FILL 0x0003
+#define Y_FILL 0x0007
+#define BASELINE 0x0008
+#define HOLE_ENABLE 0x0010
+#define SRC_1_INDEX_ENABLE 0x0020
+#define DST_INDEX_ENABLE 0x0040
+#define DST_WRITE_ENABLE 0x0080
+
+/* ADDER source 2 size register */
+
+#define NO_TILE 0x0080
+
+/* External registers base addresses */
+
+#define CS_UPDATE_MASK 0x0060
+#define CS_SCROLL_MASK 0x0040
+
+/* VIPER registers */
+
+#define RESOLUTION_MODE 0x0080
+#define MEMORY_BUS_WIDTH 0x0081
+#define PLANE_ADDRESS 0x0083
+#define LU_FUNCTION_R1 0x0084
+#define LU_FUNCTION_R2 0x0085
+#define LU_FUNCTION_R3 0x0086
+#define LU_FUNCTION_R4 0x0087
+#define MASK_1 0x0088
+#define MASK_2 0x0089
+#define SOURCE 0x008a
+#define SOURCE_Z 0x0000
+#define BACKGROUND_COLOR 0x008e
+#define BACKGROUND_COLOR_Z 0x000C
+#define FOREGROUND_COLOR 0x008f
+#define FOREGROUND_COLOR_Z 0x0004
+#define SRC1_OCR_A 0x0090
+#define SRC2_OCR_A 0x0091
+#define DST_OCR_A 0x0092
+#define SRC1_OCR_B 0x0094
+#define SRC2_OCR_B 0x0095
+#define DST_OCR_B 0x0096
+
+/* VIPER scroll registers */
+
+#define SCROLL_CONSTANT 0x0082
+#define SCROLL_FILL 0x008b
+#define SCROLL_FILL_Z 0x0008
+#define LEFT_SCROLL_MASK 0x008c
+#define RIGHT_SCROLL_MASK 0x008d
+
+/* VIPER register bit definitions */
+
+#define EXT_NONE 0x0000
+#define EXT_SOURCE 0x0001
+#define EXT_M1_M2 0x0002
+#define INT_NONE 0x0000
+#define INT_SOURCE 0x0004
+#define INT_M1_M2 0x0008
+#define ID 0x0010
+#define NO_ID 0x0000
+#define WAIT 0x0020
+#define NO_WAIT 0x0000
+#define BAR_SHIFT_DELAY WAIT
+#define NO_BAR_SHIFT_DELAY NO_WAIT
+
+
+/* VIPER logical function unit codes */
+
+#define LF_ZEROS 0x0000
+#define LF_D_XOR_S 0x0006
+#define LF_SOURCE 0x000A
+#define LF_D_OR_S 0x000E
+#define LF_ONES 0x000F
+#define INV_M1_M2 0x0030
+#define FULL_SRC_RESOLUTION 0X00C0 /* makes second pass like first pass */
+
+/* VIPER scroll register [2] */
+
+#define SCROLL_DISABLE 0x0040
+#define SCROLL_ENABLE 0x0020
+#define VIPER_LEFT 0x0000
+#define VIPER_RIGHT 0x0010
+#define VIPER_UP 0x0040
+#define VIPER_DOWN 0x0000
+
+/* Adder scroll register */
+
+#define ADDER_UP 0x0000
+#define ADDER_DOWN 0x1000
+
+/* Misc scroll definitions */
+
+#define UP 0
+#define DOWN 1
+#define LEFT 2
+#define RIGHT 3
+#define NODIR 4
+#define SCROLL_VMAX 31
+#define SCROLL_HMAX 15
+#define NEW 2
+#define OLD 1
+#define BUSY 1
+#define DRAG 1
+#define SCROLL 0
+
+/* miscellaneous defines */
+
+#define ALL_PLANES 0xffffffff
+#define UNITY 0x1fff /* Adder scale factor */
+#define MAX_SCREEN_X 1024
+#define MAX_SCREEN_Y 864
+#define FONT_HEIGHT 32
+
+ struct adder {
+
+ /* adder control registers */
+
+ u_short register_address; /* ADDER reg pntr for use by DGA */
+ u_short request_enable; /* DMA request enables */
+ u_short interrupt_enable; /* interrupt enables */
+ u_short status; /* ADDER status bits */
+ u_short reserved1; /* test function only */
+ u_short spare1; /* spare address (what else?) */
+
+ u_short reserved2; /* test function only */
+ u_short id_data; /* data path to I/D bus */
+ u_short command; /* ADDER chip command register */
+ u_short rasterop_mode; /* sets rasterop execution modes */
+ u_short cmd; /* duplicate path to above cmd reg */
+ u_short reserved3; /* test function only */
+
+ /* scroll registers */
+
+ u_short ID_scroll_data; /* I/D bus scroll data */
+ u_short ID_scroll_command; /* I/D bus scroll command */
+ u_short scroll_x_min; /* X scroll min - left boundary */
+ u_short scroll_x_max; /* X scroll max - right boundary */
+ u_short scroll_y_min; /* Y scroll min - upper boundary */
+ u_short scroll_y_max; /* Y scroll max - lower boundary */
+ u_short pause; /* Y coord to set stat when scanned */
+ u_short y_offset_pending; /* vertical scroll control */
+ u_short y_scroll_constant;
+
+ /* update control registers */
+
+ u_short x_index_pending; /* x pending index */
+ u_short y_index_pending; /* y pending index */
+ u_short x_index_new; /* new x index */
+ u_short y_index_new; /* new y index */
+ u_short x_index_old; /* old x index */
+ u_short y_index_old; /* old y index */
+ u_short x_clip_min; /* left clipping boundary */
+ u_short x_clip_max; /* right clipping boundary */
+ u_short y_clip_min; /* upper clipping boundary */
+ u_short y_clip_max; /* lower clipping boundary */
+ u_short spare2; /* spare address (another!) */
+
+ /* rasterop control registers */
+
+ u_short source_1_dx; /* source #1 x vector */
+ u_short source_1_dy; /* source #1 y vector*/
+ u_short source_1_x; /* source #1 x origin */
+ u_short source_1_y; /* source #1 y origin */
+ u_short destination_x; /* destination x origin */
+ u_short destination_y; /* destination y origin */
+ u_short fast_dest_dx; /* destination x fast vector */
+ u_short fast_dest_dy; /* destination y fast vector */
+ u_short slow_dest_dx; /* destination x slow vector */
+ u_short slow_dest_dy; /* destination y slow vector */
+ u_short fast_scale; /* scale factor for fast vector */
+ u_short slow_scale; /* scale factor for slow vector */
+ u_short source_2_x; /* source #2 x origin */
+ u_short source_2_y; /* source #2 y origin */
+ u_short source_2_size; /* source #2 height & width */
+ u_short error_1; /* error regs (?) */
+ u_short error_2;
+
+ /* screen format control registers */
+
+ u_short y_scan_count_0; /* y scan counts for vert timing */
+ u_short y_scan_count_1;
+ u_short y_scan_count_2;
+ u_short y_scan_count_3;
+ u_short x_scan_conf; /* x scan configuration */
+ u_short x_limit;
+ u_short y_limit;
+ u_short x_scan_count_0; /* x scan count for horiz timing */
+ u_short x_scan_count_1;
+ u_short x_scan_count_2;
+ u_short x_scan_count_3;
+ u_short x_scan_count_4;
+ u_short x_scan_count_5;
+ u_short x_scan_count_6;
+ u_short sync_phase_adj; /* sync phase (horiz sync count) */
+ };
+
+/*---------------------
+* DUART definitions */
+
+ /* command definitions */
+
+#define EN_RCV 0x01
+#define DIS_RCV 0x02
+#define EN_XMT 0x04
+#define DIS_XMT 0x08
+#define RESET_M 0x10
+#define RESET_RCV 0x20
+#define RESET_XMT 0x30
+#define RESET_ERR 0x40
+#define RESET_BD 0x50
+#define START_BREAK 0x60
+#define STOP_BREAK 0x70
+
+ /* interupt bit definitions */
+
+#define EI_XMT_A 0x01
+#define EI_RCV_A 0x02
+#define EI_XMT_B 0x10
+#define EI_RCV_B 0x20
+
+#define XMT_RDY_A 0x01
+#define RCV_RDY_A 0x02
+#define XMT_RDY_B 0x10
+#define RCV_RDY_B 0x20
+
+ /* status register bit defintions */
+
+#define RCV_RDY 0x01
+#define FIFO_FULL 0x02
+#define XMT_RDY 0x04
+#define XMT_EMT 0x08
+#define OVER_ERR 0x10
+#define ERR_PARITY 0x20
+#define FRAME_ERR 0x40
+#define RCVD_BREAK 0x80
+
+
+ struct duart {
+
+ /* channel A - LK201 */
+
+ short modeA; /* ch.A mode reg (read/write) */
+ short statusA; /* ch.A status reg (read) */
+#define clkselA statusA /* ch.A clock slect reg (write) */
+ short cmdA; /* ch.A command reg (write) */
+ short dataA; /* rcv/xmt data ch.A (read/write) */
+ short inchng; /* input change state reg (read) */
+#define auxctl inchng /* auxiliary control reg (write) */
+ short istatus; /* interrupt status reg (read) */
+#define imask istatus /* interrupt mask reg (write) */
+ short CThi; /* counter/timer hi byte (read) */
+#define CTRhi CThi /* counter/timer hi reg (write) */
+ short CTlo; /* counter/timer lo byte (read) */
+#define CTRlo CTlo /* counter/timer lo reg (write) */
+
+ /* channel B - pointing device */
+
+ short modeB; /* ch.B mode reg (read/write) */
+ short statusB; /* ch.B status reg (read) */
+#define clkselB statusB /* ch.B clock select reg (write) */
+ short cmdB; /* ch.B command reg (write) */
+ short dataB; /* ch.B rcv/xmt data (read/write) */
+ short rsrvd;
+ short inport; /* input port (read) */
+#define outconf inport /* output port config reg (write) */
+ short strctr; /* start counter command (read) */
+#define setbits setctr /* output bits set command (write) */
+ short stpctr; /* stop counter command (read) */
+#define resetbits stpctr /* output bits reset cmd (write) */
+
+};
diff --git a/sys/arch/vax/qbus/qduser.h b/sys/arch/vax/qbus/qduser.h
new file mode 100644
index 00000000000..fbf83c7b095
--- /dev/null
+++ b/sys/arch/vax/qbus/qduser.h
@@ -0,0 +1,514 @@
+/* $OpenBSD: qduser.h,v 1.1 2000/04/27 03:14:48 bjc Exp $ */
+/* $NetBSD: qduser.h,v 1.1 1998/03/21 10:02:39 ragge Exp $ */
+/*-
+ * Copyright (c) 1982, 1986 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.
+ *
+ * @(#)qduser.h 7.1 (Berkeley) 5/9/91
+ */
+
+/* derived from: @(#)qduser.h 6.1 (ULTRIX) 11/24/87 */
+/************************************************************************
+ * *
+ * Copyright (c) 1986 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. *
+ * *
+ ************************************************************************/
+
+/***************************************************************************
+*
+* QDUSER...
+* This file defines values shared between the driver and a client
+*
+***************************************************************************/
+
+/***************************************************************************
+* revision history:
+****************************************************************************
+*
+* 21 jul 86 ram fixed define of CURSOR_MIN_Y
+* 25 nov 85 longo added macro and bit defines for DMA error flags
+* 11 nov 85 longo renamed _vs_eventqueue to "qdinput" struct
+* 23 oct 85 longo added more defines to the DMA stuff
+* 17 oct 85 longo changed "struct rgb" chars to be unsigned
+* 16 oct 85 longo added new TABLET support definitions
+* 15 oct 85 longo re-wrote DMA queue access macros
+* 08 oct 85 longo added status flag manipulation macros to DMA stuff
+* 02 oct 85 longo added support for color map write buffer loading
+* 26 sep 85 longo removed adder sertup params from DMA request struct
+* 23 sep 85 longo added DMA queue access macros
+* 30 aug 85 longo fixed crock in "qdiobuf" struct compile-time sizing. Also
+* removed DMAcontrol struct from DMA buffer for field test
+* 26 aug 85 longo put in conditional include of "qevent.h" for user prg's
+* 18 jul 85 longo changed semantics so that head is tail and tail is head
+* 12 jul 85 longo moved "mouse_report" struct and defs over to qd_data.c
+* 11 jul 85 longo added device coordinate to gate array cursor coordinate
+* transformation macros
+* 03 jul 85 longo changed kernel typdef's for data types to long-hand
+* 10 may 85 longo created
+*
+***************************************************************************/
+
+#ifdef KERNEL
+#include "../include/qevent.h" /* include event struct defs */
+#else
+#include <vax/uba/qevent.h>
+#endif
+
+/*---------------------
+* QDSS device map */
+
+ struct qdmap { /* map of register blocks in QDSS */
+
+ char *template;
+ char *adder;
+ char *dga;
+ char *duart;
+ char *memcsr;
+ char *red;
+ char *blue;
+ char *green;
+ };
+
+/*--------------------------------------------
+* DGA CSR bit definitions and register map */
+
+#define DMADONE 0x8000 /* DMA done status */
+#define SET_DONE_FIFO 0x4000 /* set DMADONE when FIFO empty.. */
+ /* ..AND count = 0 */
+
+#define PTOB_ENB 0x0600 /* host-to-bitmap DMA xfer */
+#define BTOP_ENB 0x0400 /* bitmap-to-host DMA xfer */
+#define DL_ENB 0x0200 /* display list DMA xfer */
+#define HALT 0x0000 /* halt DGA */
+
+#define BYTE_DMA 0x0100 /* byte/word DMA xfer */
+
+#define DMA_ERR 0x0080 /* DMA error bits */
+#define PARITY_ERR 0x0040 /* memory parity error in DMA */
+#define BUS_ERR 0x0020 /* bus timeout error in DMA */
+
+#define GLOBAL_IE 0x0004 /* global interrupt enable */
+#define DMA_IE 0x0002 /* DMA interrupt enable */
+#define CURS_ENB 0x0001 /* cursor enable */
+
+/* QDSS memcsr bit definitions */
+
+#define UNBLANK 0x0020
+#define SYNC_ON 0x0008
+
+ struct dga {
+
+ unsigned short csr;
+ unsigned short adrs_lo; /* destination address of bitmap to */
+ unsigned short adrs_hi; /* host DMA */
+ unsigned short bytcnt_lo; /* byte length of requested DMA */
+ unsigned short bytcnt_hi; /* (WO = bytcnt) (RO = fifo count) */
+ unsigned short fifo; /* FIFO register */
+ unsigned short x_cursor; /* cursor position registers */
+ unsigned short y_cursor;
+ unsigned short ivr; /* interrupt vector register */
+ unsigned short memadr; /* memory base address register */
+ };
+
+/*-------------------------------------------------------------------------
+* macros to transform device coordinates to hardware cursor coordinates */
+
+#define CURS_MIN_X 232 /* device coordinate x = 0 */
+#define CURS_MIN_Y 16 /* device coordinate y = 0 */
+
+#define TRANX(x) ( -(((int)(x)+CURS_MIN_X) & ~0x0003) | \
+ (((int)(x)+CURS_MIN_X) & 0x0003) )
+
+#define TRANY(y) ( -((y)+CURS_MIN_Y) )
+
+/*********************************************************************
+*
+* EVENT QUEUE DEFINITIONS
+*
+**********************************************************************
+* most of the event queue definitions are found in "qevent.h". But a
+* few things not found there are here. */
+
+/* The event queue header */
+
+struct qdinput {
+
+ struct _vs_eventqueue header; /* event queue ring handling */
+
+ /* for VS100 and QVSS compatability reasons, additions to this
+ * structure must be made below this point. */
+
+ struct _vs_cursor curs_pos; /* current mouse position */
+ struct _vs_box curs_box; /* cursor reporting box */
+
+ };
+
+/* vse_key field. definitions for mouse buttons */
+
+#define VSE_LEFT_BUTTON 0
+#define VSE_MIDDLE_BUTTON 1
+#define VSE_RIGHT_BUTTON 2
+
+/* vse_key field. definitions for mouse buttons */
+
+#define VSE_T_LEFT_BUTTON 0
+#define VSE_T_FRONT_BUTTON 1
+#define VSE_T_RIGHT_BUTTON 2
+#define VSE_T_BACK_BUTTON 4
+
+#define VSE_T_BARREL_BUTTON VSE_T_LEFT_BUTTON
+#define VSE_T_TIP_BUTTON VSE_T_FRONT_BUTTON
+
+/*--------------------------------------------------------------------------
+* These are the macros to be used for loading and extracting from the event
+* queue. It is presumed that the macro user will only use the access macros
+* if the event queue is non-empty ( ISEMPTY(eq) == FALSE ), and that the
+* driver will only load the event queue after checking that it is not full
+* ( ISFULL(eq) == FALSE ). ("eq" is a pointer to the event queue header.)
+*
+* Before an event access session for a particular event, the macro users
+* must use the xxxBEGIN macro, and the xxxEND macro after an event is through
+* with. As seen below, the xxxBEGIN and xxxEND macros maintain the event
+* queue access mechanism.
+*
+* First, the macros to be used by the event queue reader
+*/
+
+#define ISEMPTY(eq) ((eq)->header.head == (eq)->header.tail)
+#define GETBEGIN(eq) (&(eq)->header.events[(eq)->header.head])
+
+#define GET_X(event) ((event)->vse_x) /* get x position */
+#define GET_Y(event) ((event)->vse_y) /* get y position */
+#define GET_TIME(event) ((event)->vse_time) /* get time */
+#define GET_TYPE(event) ((event)->vse_type) /* get entry type */
+#define GET_KEY(event) ((event)->vse_key) /* get keycode */
+#define GET_DIR(event) ((event)->vse_direction) /* get direction */
+#define GET_DEVICE(event) ((event)->vse_device) /* get device */
+
+#define GETEND(eq) (++(eq)->header.head >= (eq)->header.size ? \
+ (eq)->header.head = 0 : 0 )
+
+/*------------------------------------------------
+* macros to be used by the event queue loader */
+
+ /* ISFULL yields TRUE if queue is full */
+
+#define ISFULL(eq) ((eq)->header.tail+1 == (eq)->header.head || \
+ ((eq)->header.tail+1 == (eq)->header.size && \
+ (eq)->header.head == 0))
+
+ /* get address of the billet for NEXT event */
+
+#define PUTBEGIN(eq) (&(eq)->header.events[(eq)->header.tail])
+
+#define PUT_X(event, value) ((event)->vse_x = value) /* put X pos */
+#define PUT_Y(event, value) ((event)->vse_y = value) /* put Y pos */
+#define PUT_TIME(event, value) ((event)->vse_time = value) /* put time */
+#define PUT_TYPE(event, value) ((event)->vse_type = value) /* put type */
+#define PUT_KEY(event, value) ((event)->vse_key = value) /* put input key */
+#define PUT_DIR(event, value) ((event)->vse_direction = value) /* put dir */
+#define PUT_DEVICE(event, value) ((event)->vse_device = value) /* put dev */
+
+#define PUTEND(eq) (++(eq)->header.tail >= (eq)->header.size ? \
+ (eq)->header.tail = 0 : 0)
+
+/******************************************************************
+*
+* DMA I/O DEFINITIONS
+*
+******************************************************************/
+
+/*---------------------------------------------------------------------
+* The DMA request queue is implemented as a ring buffer of "DMAreq"
+ structures. The queue is accessed using ring indices located in the
+ "DMAreq_header" structure. Access is implemented using access macros
+ similar to the event queue access macros above. */
+
+ struct DMAreq {
+
+ short DMAtype; /* DMA type code (for QDSS) */
+ short DMAdone; /* DMA done parameter */
+ char *bufp; /* virtual adrs of buffer */
+ int length; /* transfer buffer length */
+ };
+
+/* DMA type command codes */
+
+#define DISPLIST 1 /* display list DMA */
+#define PTOB 2 /* 1 plane Qbus to bitmap DMA */
+#define BTOP 3 /* 1 plane bitmap to Qbus DMA */
+
+/* DMA done notification code */
+
+#define FIFO_EMPTY 0x01 /* DONE when FIFO becomes empty */
+#define COUNT_ZERO 0x02 /* DONE when count becomes zero */
+#define WORD_PACK 0x04 /* program the gate array for word packing */
+#define BYTE_PACK 0x08 /* program gate array for byte packing */
+#define REQUEST_DONE 0x100 /* clear when driver has processed request */
+#define HARD_ERROR 0x200 /* DMA hardware error occurred */
+
+/* DMA request queue is a ring buffer of request structures */
+
+ struct DMAreq_header {
+
+ int QBAreg; /* cookie Qbus map reg for this buffer */
+ short status; /* master DMA status word */
+ int shared_size; /* size of shared memory in bytes */
+ struct DMAreq *DMAreq; /* start address of request queue */
+ int used; /* # of queue entries currently used */
+ int size; /* # of "DMAreq"'s in the request queue */
+ int oldest; /* index to oldest queue'd request */
+ int newest; /* index to newest queue'd request */
+ };
+
+/* bit definitions for DMAstatus word in DMAreq_header */
+
+#define DMA_ACTIVE 0x0004 /* DMA in progress */
+#define DMA_ERROR 0x0080 /* DMA hardware error */
+#define DMA_IGNORE 0x0002 /* flag to ignore this interrupt */
+
+/*------------------------------------------
+* macros for DMA request queue fiddling */
+
+ /* DMA status set/check macros */
+
+#define DMA_SETACTIVE(header) ((header)->status |= DMA_ACTIVE)
+#define DMA_CLRACTIVE(header) ((header)->status &= ~DMA_ACTIVE)
+#define DMA_ISACTIVE(header) ((header)->status & DMA_ACTIVE)
+
+#define DMA_SETERROR(header) ((header)->status |= DMA_ERROR)
+#define DMA_CLRERROR(header) ((header)->status &= ~DMA_ERROR)
+#define DMA_ISERROR(header) ((header)->status & DMA_ERROR)
+
+#define DMA_SETIGNORE(header) ((header)->status |= DMA_IGNORE)
+#define DMA_CLRIGNORE(header) ((header)->status &= ~DMA_IGNORE)
+#define DMA_ISIGNORE(header) ((header)->status & DMA_IGNORE)
+
+ /* yields TRUE if queue is empty (ISEMPTY) or full (ISFULL) */
+
+#define DMA_ISEMPTY(header) ((header)->used == 0)
+#define DMA_ISFULL(header) ((header)->used >= (header)->size)
+
+ /* returns address of the billet for next (PUT)
+ * or oldest (GET) request */
+
+#define DMA_PUTBEGIN(header) (&(header)->DMAreq[(header)->newest])
+#define DMA_GETBEGIN(header) (&(header)->DMAreq[(header)->oldest])
+
+ /* does queue access pointer maintenance */
+
+#define DMA_GETEND(header) (++(header)->oldest >= (header)->size \
+ ? (header)->oldest = 0 : 0); \
+ --(header)->used;
+
+#define DMA_PUTEND(header) (++(header)->newest >= (header)->size \
+ ? (header)->newest = 0 : 0); \
+ ++(header)->used;
+
+/******************************************************************
+*
+* COLOR MAP WRITE BUFFER DEFINITIONS
+*
+******************************************************************/
+
+ struct rgb {
+
+ unsigned char offset; /* color map address for load */
+ unsigned char red; /* data for red map */
+ unsigned char green; /* data for green map */
+ unsigned char blue; /* data for blue map */
+ };
+
+ struct color_buf {
+
+ char status; /* load request/service status */
+ short count; /* number of entries to br loaded */
+ struct rgb rgb[256];
+ };
+
+#define LOAD_COLOR_MAP 0x0001
+
+/******************************************************************
+*
+* SCROLL ASSIST DEFINITIONS
+*
+******************************************************************/
+
+ struct scroll {
+
+ short status;
+ short viper_constant;
+ short y_scroll_constant;
+ short y_offset;
+ short x_index_pending;
+ short y_index_pending;
+ };
+
+#define LOAD_REGS 0x0001
+#define LOAD_INDEX 0x0002
+
+/******************************************************************
+*
+* MOUSE/TABLET/KBD PROGRAMMING DEFINITIONS
+*
+******************************************************************/
+
+/*-----------------------------------
+* LK201 programmming definitions */
+
+#define LK_UPDOWN 0x86 /* bits for setting lk201 modes */
+#define LK_AUTODOWN 0x82
+#define LK_DOWN 0x80
+#define LK_DEFAULTS 0xD3 /* reset (some) default settings */
+#define LK_AR_ENABLE 0xE3 /* global auto repeat enable */
+#define LK_CL_ENABLE 0x1B /* keyclick enable */
+#define LK_KBD_ENABLE 0x8B /* keyboard enable */
+#define LK_BELL_ENABLE 0x23 /* the bell */
+#define LK_RING_BELL 0xA7 /* ring keyboard bell */
+
+#define LK_LED_ENABLE 0x13 /* light led */
+#define LK_LED_DISABLE 0x11 /* turn off led */
+#define LED_1 0x81 /* led bits */
+#define LED_2 0x82
+#define LED_3 0x84
+#define LED_4 0x88
+#define LED_ALL 0x8F
+#define LK_LED_HOLD LED_4
+#define LK_LED_LOCK LED_3
+#define LK_LED_COMPOSE LED_2
+#define LK_LED_WAIT LED_1
+
+#define LK_KDOWN_ERROR 0x3D /* key down on powerup error */
+#define LK_POWER_ERROR 0x3E /* keyboard failure on powerup test */
+#define LK_OUTPUT_ERROR 0xB5 /* keystrokes lost during inhibit */
+#define LK_INPUT_ERROR 0xB6 /* garbage command to keyboard */
+#define LK_LOWEST 0x56 /* lowest significant keycode */
+#define LK_DIV6_START 0xAD /* start of div 6 */
+#define LK_DIV5_END 0xB2 /* end of div 5 */
+
+#define LAST_PARAM 0x80 /* "no more params" bit */
+
+ struct prgkbd {
+
+ short cmd; /* LK201 command opcode */
+ short param1; /* 1st cmd parameter (can be null) */
+ short param2; /* 2nd cmd parameter (can be null) */
+ };
+
+/*-------------------------
+* "special" LK-201 keys */
+
+#define SHIFT 174
+#define LOCK 176
+#define REPEAT 180
+#define CNTRL 175
+#define ALLUP 179
+
+/*--------------------------------
+* cursor programming structure */
+
+ struct prg_cursor {
+
+ unsigned short acc_factor; /* cursor aceleration factor */
+ unsigned short threshold; /* threshold to trigger acc at */
+ };
+
+/*---------------------
+* mouse definitions */
+
+#define INC_STREAM_MODE 'R' /* stream mode reports (55 hz) */
+#define PROMPT_MODE 'D' /* report when prompted */
+#define REQUEST_POS 'P' /* request position report */
+#define SELF_TEST 'T' /* request self test */
+
+#define MOUSE_ID 0x2 /* mouse ID in lo 4 bits */
+
+#define START_FRAME 0x80 /* start of report frame bit */
+#define X_SIGN 0x10 /* position sign bits */
+#define Y_SIGN 0x08
+
+#define RIGHT_BUTTON 0x01 /* mouse buttons */
+#define MIDDLE_BUTTON 0x02
+#define LEFT_BUTTON 0x04
+
+ /* mouse report structure definition */
+
+ struct mouse_report {
+
+ char state; /* buttons and sign bits */
+ short dx; /* delta X since last change */
+ short dy; /* delta Y since last change */
+ char bytcnt; /* mouse report byte count */
+ };
+
+/*-----------------------------------------
+* tablet command/interface definitions */
+
+#define T_STREAM 'R' /* continuous stream report mode */
+#define T_POINT 'D' /* enter report-on-request mode */
+#define T_REQUEST 'P' /* request position report */
+
+#define T_BAUD 'B' /* increase baud to 9600 from 4800 */
+#define T_RATE_55 'K' /* report rate: 55/sec */
+#define T_RATE_72 'L' /* report rate: 72/sec */
+#define T_RATE_120 'M' /* report rate: 120/sec (9600 only) */
+
+#define T_TEST SELF_TEST /* do self test */
+
+#define TABLET_ID 0x4 /* tablet ID in lo 4 bits */
+
+#define T_START_FRAME 0x80 /* start of report frame bit */
+#define T_PROXIMITY 0x01 /* state pointer in proximity */
+
+#define T_LEFT_BUTTON 0x02 /* puck buttons */
+#define T_FRONT_BUTTON 0x04
+#define T_RIGHT_BUTTON 0x08
+#define T_BACK_BUTTON 0x10
+
+#define T_BARREL_BUTTON T_LEFT_BUTTON /* stylus buttons */
+#define T_TIP_BUTTON T_FRONT_BUTTON
+
diff --git a/sys/arch/vax/qbus/qevent.h b/sys/arch/vax/qbus/qevent.h
new file mode 100644
index 00000000000..93e7c30acdd
--- /dev/null
+++ b/sys/arch/vax/qbus/qevent.h
@@ -0,0 +1,120 @@
+/* $OpenBSD: qevent.h,v 1.1 2000/04/27 03:14:48 bjc Exp $ */
+/* $NetBSD: qevent.h,v 1.1 1998/03/21 10:02:39 ragge Exp $ */
+/*-
+ * Copyright (c) 1982, 1986 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.
+ *
+ * @(#)qevent.h 7.1 (Berkeley) 5/9/91
+ */
+
+/************************************************************************
+* *
+* 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. *
+* *
+* 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. *
+* *
+************************************************************************/
+
+/*
+ * Event queue entries
+ */
+
+#ifndef _QEVENT_
+#define _QEVENT_
+
+typedef struct _vs_event {
+ unsigned short vse_x; /* x position */
+ unsigned short vse_y; /* y position */
+ unsigned short vse_time;/* 10 millisecond units (button only) */
+ char vse_type; /* button or motion? */
+ unsigned char vse_key; /* the key (button only) */
+ char vse_direction; /* which direction (button only) */
+ char vse_device; /* which device (button only) */
+} vsEvent;
+
+/* vse_type field */
+#define VSE_BUTTON 0 /* button moved */
+#define VSE_MMOTION 1 /* mouse moved */
+#define VSE_TMOTION 2 /* tablet moved */
+
+/* vse_direction field */
+#define VSE_KBTUP 0 /* up */
+#define VSE_KBTDOWN 1 /* down */
+#define VSE_KBTRAW 2 /* undetermined */
+
+/* vse_device field */
+#define VSE_NULL 0 /* NULL event (for QD_GETEVENT ret) */
+#define VSE_MOUSE 1 /* mouse */
+#define VSE_DKB 2 /* main keyboard */
+#define VSE_TABLET 3 /* graphics tablet */
+#define VSE_AUX 4 /* auxiliary */
+#define VSE_CONSOLE 5 /* console */
+
+/* The event queue */
+
+typedef struct _vs_eventqueue {
+ vsEvent *events; /* input event buffer */
+ int size; /* size of event buffer */
+ int head; /* index into events */
+ int tail; /* index into events */
+} vsEventQueue;
+
+/* mouse cursor position */
+
+typedef struct _vs_cursor {
+ short x;
+ short y;
+} vsCursor;
+
+/* mouse motion rectangle */
+
+typedef struct _vs_box {
+ short bottom;
+ short right;
+ short left;
+ short top;
+} vsBox;
+
+#endif /*_QEVENT_*/
diff --git a/sys/arch/vax/qbus/qfont.c b/sys/arch/vax/qbus/qfont.c
new file mode 100644
index 00000000000..f7abecff5e7
--- /dev/null
+++ b/sys/arch/vax/qbus/qfont.c
@@ -0,0 +1,3294 @@
+/* $OpenBSD: qfont.c,v 1.1 2000/04/27 03:14:48 bjc Exp $ */
+/* $NetBSD: qfont.c,v 1.4 1999/06/20 17:58:57 ragge Exp $ */
+/*-
+ * Copyright (c) 1982, 1986
+ * 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.
+ *
+ * @(#)qfont.c 7.2 (Berkeley) 1/21/94
+ */
+
+/*
+ * derived from: "@(#)qfont.c 6.2 ULTRIX 2/4/88"
+ */
+
+/************************************************************************
+ * *
+ * Copyright (c) 1984, 1987 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. *
+ * *
+ ************************************************************************/
+
+/*
+ * The following tables are used to translate LK201 key strokes
+ * into ascii characters. The tables also support the special
+ * function keys.
+ */
+
+unsigned short q_key[]={
+ 0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 /* 0 */
+ ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 /* 8 */
+ ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 /* 16 */
+ ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 /* 24 */
+ ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 /* 32 */
+ ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 /* 40 */
+ ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 /* 48 */
+ ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 /* 56 */
+ ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 /* 64 */
+ ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 /* 72 */
+ ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x101 ,0x102 /* 80 */
+ ,0x103 ,0x104 ,0x105 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 /* 88 */
+ ,0x00 ,0x00 ,0x00 ,0x00 ,0x106 ,0x107 ,0x108 ,0x109 /* 96 */
+ ,0x10a ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 /* 104 */
+ ,0x00 ,0x1b ,0x08 ,0x0a ,0x10b ,0x00 ,0x00 ,0x00 /* 112 */
+ ,0x00 ,0x00 ,0x00 ,0x00 ,0x10c ,0x10d ,0x00 ,0x00 /* 120 */
+ ,0x10e ,0x10f ,0x110 ,0x111 ,0x00 ,0x00 ,0x00 ,0x00 /* 128 */
+ ,0x00 ,0x00 ,0x112 ,0x113 ,0x114 ,0x115 ,0x116 ,0x117 /* 136 */
+ ,0x00 ,0x00 ,0x120 ,0x00 ,0x121 ,0x122 ,0x123 ,0x124 /* 144 */
+ ,0x125 ,0x126 ,0x127 ,0x128 ,0x129 ,0x12a ,0x12b ,0x12c /* 152 */
+ ,0x12d ,0x118 ,0x119 ,0x11a ,0x11b ,0x00 ,0x00 ,0x11c /* 160 */
+ ,0x11d ,0x11e ,0x11f ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 /* 168 */
+ ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 /* 176 */
+ ,0x00 ,0x00 ,0x00 ,0x00 ,0x7f ,'\r' ,0x09 ,'`' /* 184 */
+ ,'1' ,'q' ,'a' ,'z' ,0x00 ,'2' ,'w' ,'s' /* 192 */
+ ,'x' ,'<' ,0x00 ,'3' ,'e' ,'d' ,'c' ,0x00 /* 200 */
+ ,'4' ,'r' ,'f' ,'v' ,' ' ,0x00 ,'5' ,'t' /* 208 */
+ ,'g' ,'b' ,0x00 ,'6' ,'y' ,'h' ,'n' ,0x00 /* 216 */
+ ,'7' ,'u' ,'j' ,'m' ,0x00 ,'8' ,'i' ,'k' /* 224 */
+ ,',' ,0x00 ,'9' ,'o' ,'l' ,'.' ,0x00 ,'0' /* 232 */
+ ,'p' ,0x00 ,';' ,'/' ,0x00 ,'=' ,']' ,'\\' /* 240 */
+ ,0x00 ,'-' ,'[' ,'\'' ,0x00 ,0x00 ,0x00 ,0x00 /* 248 */
+};
+
+unsigned short q_shift_key[]={
+ 0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 /* 0 */
+ ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 /* 8 */
+ ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 /* 16 */
+ ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 /* 24 */
+ ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 /* 32 */
+ ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 /* 40 */
+ ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 /* 48 */
+ ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 /* 56 */
+ ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 /* 64 */
+ ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 /* 72 */
+ ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x101 ,0x102 /* 80 */
+ ,0x103 ,0x104 ,0x105 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 /* 88 */
+ ,0x00 ,0x00 ,0x00 ,0x00 ,0x106 ,0x107 ,0x108 ,0x109 /* 96 */
+ ,0x10a ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 /* 104 */
+ ,0x00 ,0x1b ,0x08 ,0x0a ,0x10b ,0x00 ,0x00 ,0x00 /* 112 */
+ ,0x00 ,0x00 ,0x00 ,0x00 ,0x10c ,0x10d ,0x00 ,0x00 /* 120 */
+ ,0x10e ,0x10f ,0x110 ,0x111 ,0x00 ,0x00 ,0x00 ,0x00 /* 128 */
+ ,0x00 ,0x00 ,0x112 ,0x113 ,0x114 ,0x115 ,0x116 ,0x117 /* 136 */
+ ,0x00 ,0x00 ,0x120 ,0x00 ,0x121 ,0x122 ,0x123 ,0x124 /* 144 */
+ ,0x125 ,0x126 ,0x127 ,0x128 ,0x129 ,0x12a ,0x12b ,0x12c /* 152 */
+ ,0x12d ,0x118 ,0x119 ,0x11a ,0x11b ,0x00 ,0x00 ,0x11c /* 160 */
+ ,0x11d ,0x11e ,0x11f ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 /* 168 */
+ ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 /* 176 */
+ ,0x00 ,0x00 ,0x00 ,0x00 ,0x7f ,'\r' ,0x09 ,'~' /* 184 */
+ ,'!' ,'Q' ,'A' ,'Z' ,0x00 ,'@' ,'W' ,'S' /* 192 */
+ ,'X' ,'>' ,0x00 ,'#' ,'E' ,'D' ,'C' ,0x00 /* 200 */
+ ,'$' ,'R' ,'F' ,'V' ,' ' ,0x00 ,'%' ,'T' /* 208 */
+ ,'G' ,'B' ,0x00 ,'^' ,'Y' ,'H' ,'N' ,0x00 /* 216 */
+ ,'&' ,'U' ,'J' ,'M' ,0x00 ,'*' ,'I' ,'K' /* 224 */
+ ,',' ,0x00 ,'(' ,'O' ,'L' ,'.' ,0x00 ,')' /* 232 */
+ ,'P' ,0x00 ,':' ,'?' ,0x00 ,'+' ,'}' ,'|' /* 240 */
+ ,0x00 ,'_' ,'{' ,'"' ,0x00 ,0x00 ,0x00 ,0x00 /* 248 */
+};
+
+/*
+ * LK201 special purpose keys. Translations from the tables above
+ * includes codes for the function keys and other goodies. They can
+ * be determined by the presence of the 8th bit being set. The
+ * following table is accessed by removing that bit and using the
+ * result as the index to the following table. Note that table begins
+ * a null entry.
+ */
+char *q_special[]={ 0,
+ "\33[11~", /* f1 */
+ "\33[12~", /* f2 */
+ "\33[13~", /* f3 */
+ "\33[14~", /* f4 */
+ "\33[15~", /* f5 */
+ "\33[17~", /* f6 */
+ "\33[18~", /* f7 */
+ "\33[19~", /* f8 */
+ "\33[20~", /* f9 */
+ "\33[21~", /* f10 */
+ "\33[26~", /* f14 */
+ "\33[28~", /* f15 */
+ "\33[29~", /* f16 */
+ "\33[31~", /* f17 */
+ "\33[32~", /* f18 */
+ "\33[33~", /* f19 */
+ "\33[34~", /* f20 */
+ "\33[1~", /* find */
+ "\33[2~", /* insert */
+ "\33[3~", /* remove */
+ "\33[4~", /* select */
+ "\33[5~", /* prev */
+ "\33[6~", /* next */
+ "\33OP", /* pf1 */
+ "\33OQ", /* pf2 */
+ "\33OR", /* pf3 */
+ "\33OS", /* pf4 */
+ "\33[D", /* left */
+ "\33[C", /* right */
+ "\33[B", /* down */
+ "\33[A", /* up */
+ "\33Op", /* key pad 0 */
+ "\33On", /* key pad . */
+ "\33OM", /* key pad enter */
+ "\33Oq", /* key pad 1 */
+ "\33Or", /* key pad 2 */
+ "\33Os", /* key pad 3 */
+ "\33Ot", /* key pad 4 */
+ "\33Ou", /* key pad 5 */
+ "\33Ov", /* key pad 6 */
+ "\33O/*", /* key pad , */
+ "\33Ow", /* key pad 7 */
+ "\33Ox", /* key pad 8 */
+ "\33Oy", /* key pad 9 */
+ "\33Om", /* key pad - */
+ /*
+ * The following strings are to allow a numeric keypad
+ * mode and still use the same translation tables
+ */
+ "0",
+ ".",
+ "\r",
+ "1",
+ "2",
+ "3",
+ "4",
+ "5",
+ "6",
+ ",",
+ "7",
+ "8",
+ "9",
+ "-"
+};
+
+
+/*
+ * QVSS font table of displayable characters.
+ */
+char q_font[]={
+ 0x00, /* 0x00000000 */
+ 0x00, /* 0x00000000 */
+ 0x00, /* 0x00000000 */
+ 0x00, /* 0x00000000 */
+ 0x00, /* 0x00000000 */
+ 0x00, /* 0x00000000 */
+ 0x00, /* 0x00000000 */
+ 0x00, /* 0x00000000 */
+ 0x00, /* 0x00000000 */
+ 0x00, /* 0x00000000 */
+ 0x00, /* 0x00000000 */
+ 0x00, /* 0x00000000 */
+ 0x00, /* 0x00000000 */
+ 0x00, /* 0x00000000 */
+ 0x00, /* 0x00000000 */
+/* */
+ 0x00, /* 0x00000000 ! */
+ 0x00, /* 0x00000000 ! */
+ 0x08, /* 0x00001000 ! */
+ 0x08, /* 0x00001000 ! */
+ 0x08, /* 0x00001000 ! */
+ 0x08, /* 0x00001000 ! */
+ 0x08, /* 0x00001000 ! */
+ 0x08, /* 0x00001000 ! */
+ 0x08, /* 0x00001000 ! */
+ 0x08, /* 0x00001000 ! */
+ 0x00, /* 0x00000000 ! */
+ 0x08, /* 0x00001000 ! */
+ 0x00, /* 0x00000000 ! */
+ 0x00, /* 0x00000000 ! */
+ 0x00, /* 0x00000000 ! */
+/* */
+ 0x00, /* 0x00000000 " */
+ 0x00, /* 0x00000000 " */
+ 0x24, /* 0x00100100 " */
+ 0x24, /* 0x00100100 " */
+ 0x24, /* 0x00100100 " */
+ 0x00, /* 0x00000000 " */
+ 0x00, /* 0x00000000 " */
+ 0x00, /* 0x00000000 " */
+ 0x00, /* 0x00000000 " */
+ 0x00, /* 0x00000000 " */
+ 0x00, /* 0x00000000 " */
+ 0x00, /* 0x00000000 " */
+ 0x00, /* 0x00000000 " */
+ 0x00, /* 0x00000000 " */
+ 0x00, /* 0x00000000 " */
+/* */
+ 0x00, /* 0x00000000 # */
+ 0x00, /* 0x00000000 # */
+ 0x00, /* 0x00000000 # */
+ 0x12, /* 0x00010010 # */
+ 0x12, /* 0x00010010 # */
+ 0x3f, /* 0x00111111 # */
+ 0x12, /* 0x00010010 # */
+ 0x12, /* 0x00010010 # */
+ 0x3f, /* 0x00111111 # */
+ 0x12, /* 0x00010010 # */
+ 0x12, /* 0x00010010 # */
+ 0x00, /* 0x00000000 # */
+ 0x00, /* 0x00000000 # */
+ 0x00, /* 0x00000000 # */
+ 0x00, /* 0x00000000 # */
+/* */
+ 0x00, /* 0x00000000 $ */
+ 0x00, /* 0x00000000 $ */
+ 0x00, /* 0x00000000 $ */
+ 0x08, /* 0x00001000 $ */
+ 0x3e, /* 0x00111110 $ */
+ 0x09, /* 0x00001001 $ */
+ 0x09, /* 0x00001001 $ */
+ 0x3e, /* 0x00111110 $ */
+ 0x48, /* 0x01001000 $ */
+ 0x48, /* 0x01001000 $ */
+ 0x3e, /* 0x00111110 $ */
+ 0x08, /* 0x00001000 $ */
+ 0x00, /* 0x00000000 $ */
+ 0x00, /* 0x00000000 $ */
+ 0x00, /* 0x00000000 $ */
+/* */
+ 0x00, /* 0x00000000 % */
+ 0x00, /* 0x00000000 % */
+ 0x42, /* 0x01000010 % */
+ 0x25, /* 0x00100101 % */
+ 0x25, /* 0x00100101 % */
+ 0x12, /* 0x00010010 % */
+ 0x08, /* 0x00001000 % */
+ 0x08, /* 0x00001000 % */
+ 0x24, /* 0x00100100 % */
+ 0x52, /* 0x01010010 % */
+ 0x52, /* 0x01010010 % */
+ 0x21, /* 0x00100001 % */
+ 0x00, /* 0x00000000 % */
+ 0x00, /* 0x00000000 % */
+ 0x00, /* 0x00000000 % */
+/* */
+ 0x00, /* 0x00000000 & */
+ 0x00, /* 0x00000000 & */
+ 0x0e, /* 0x00001110 & */
+ 0x11, /* 0x00010001 & */
+ 0x11, /* 0x00010001 & */
+ 0x11, /* 0x00010001 & */
+ 0x0e, /* 0x00001110 & */
+ 0x11, /* 0x00010001 & */
+ 0x51, /* 0x01010001 & */
+ 0x21, /* 0x00100001 & */
+ 0x31, /* 0x00110001 & */
+ 0x4e, /* 0x01001110 & */
+ 0x00, /* 0x00000000 & */
+ 0x00, /* 0x00000000 & */
+ 0x00, /* 0x00000000 & */
+/* */
+ 0x00, /* 0x00000000 ' */
+ 0x00, /* 0x00000000 ' */
+ 0x38, /* 0x00111000 ' */
+ 0x18, /* 0x00011000 ' */
+ 0x04, /* 0x00000100 ' */
+ 0x00, /* 0x00000000 ' */
+ 0x00, /* 0x00000000 ' */
+ 0x00, /* 0x00000000 ' */
+ 0x00, /* 0x00000000 ' */
+ 0x00, /* 0x00000000 ' */
+ 0x00, /* 0x00000000 ' */
+ 0x00, /* 0x00000000 ' */
+ 0x00, /* 0x00000000 ' */
+ 0x00, /* 0x00000000 ' */
+ 0x00, /* 0x00000000 ' */
+/* */
+ 0x00, /* 0x00000000 ( */
+ 0x00, /* 0x00000000 ( */
+ 0x10, /* 0x00010000 ( */
+ 0x08, /* 0x00001000 ( */
+ 0x08, /* 0x00001000 ( */
+ 0x04, /* 0x00000100 ( */
+ 0x04, /* 0x00000100 ( */
+ 0x04, /* 0x00000100 ( */
+ 0x04, /* 0x00000100 ( */
+ 0x08, /* 0x00001000 ( */
+ 0x08, /* 0x00001000 ( */
+ 0x10, /* 0x00010000 ( */
+ 0x00, /* 0x00000000 ( */
+ 0x00, /* 0x00000000 ( */
+ 0x00, /* 0x00000000 ( */
+/* */
+ 0x00, /* 0x00000000 ) */
+ 0x00, /* 0x00000000 ) */
+ 0x04, /* 0x00000100 ) */
+ 0x08, /* 0x00001000 ) */
+ 0x08, /* 0x00001000 ) */
+ 0x10, /* 0x00010000 ) */
+ 0x10, /* 0x00010000 ) */
+ 0x10, /* 0x00010000 ) */
+ 0x10, /* 0x00010000 ) */
+ 0x08, /* 0x00001000 ) */
+ 0x08, /* 0x00001000 ) */
+ 0x04, /* 0x00000100 ) */
+ 0x00, /* 0x00000000 ) */
+ 0x00, /* 0x00000000 ) */
+ 0x00, /* 0x00000000 ) */
+/* */
+ 0x00, /* 0x00000000 * */
+ 0x00, /* 0x00000000 * */
+ 0x00, /* 0x00000000 * */
+ 0x00, /* 0x00000000 * */
+ 0x00, /* 0x00000000 * */
+ 0x22, /* 0x00100010 * */
+ 0x14, /* 0x00010100 * */
+ 0x7f, /* 0x01111111 * */
+ 0x14, /* 0x00010100 * */
+ 0x22, /* 0x00100010 * */
+ 0x00, /* 0x00000000 * */
+ 0x00, /* 0x00000000 * */
+ 0x00, /* 0x00000000 * */
+ 0x00, /* 0x00000000 * */
+ 0x00, /* 0x00000000 * */
+/* */
+ 0x00, /* 0x00000000 + */
+ 0x00, /* 0x00000000 + */
+ 0x00, /* 0x00000000 + */
+ 0x00, /* 0x00000000 + */
+ 0x08, /* 0x00001000 + */
+ 0x08, /* 0x00001000 + */
+ 0x08, /* 0x00001000 + */
+ 0x7f, /* 0x01111111 + */
+ 0x08, /* 0x00001000 + */
+ 0x08, /* 0x00001000 + */
+ 0x08, /* 0x00001000 + */
+ 0x00, /* 0x00000000 + */
+ 0x00, /* 0x00000000 + */
+ 0x00, /* 0x00000000 + */
+ 0x00, /* 0x00000000 + */
+/* */
+ 0x00, /* 0x00000000 , */
+ 0x00, /* 0x00000000 , */
+ 0x00, /* 0x00000000 , */
+ 0x00, /* 0x00000000 , */
+ 0x00, /* 0x00000000 , */
+ 0x00, /* 0x00000000 , */
+ 0x00, /* 0x00000000 , */
+ 0x00, /* 0x00000000 , */
+ 0x00, /* 0x00000000 , */
+ 0x00, /* 0x00000000 , */
+ 0x1c, /* 0x00011100 , */
+ 0x0c, /* 0x00001100 , */
+ 0x02, /* 0x00000010 , */
+ 0x00, /* 0x00000000 , */
+ 0x00, /* 0x00000000 , */
+/* */
+ 0x00, /* 0x00000000 - */
+ 0x00, /* 0x00000000 - */
+ 0x00, /* 0x00000000 - */
+ 0x00, /* 0x00000000 - */
+ 0x00, /* 0x00000000 - */
+ 0x00, /* 0x00000000 - */
+ 0x00, /* 0x00000000 - */
+ 0x7f, /* 0x01111111 - */
+ 0x00, /* 0x00000000 - */
+ 0x00, /* 0x00000000 - */
+ 0x00, /* 0x00000000 - */
+ 0x00, /* 0x00000000 - */
+ 0x00, /* 0x00000000 - */
+ 0x00, /* 0x00000000 - */
+ 0x00, /* 0x00000000 - */
+/* */
+ 0x00, /* 0x00000000 . */
+ 0x00, /* 0x00000000 . */
+ 0x00, /* 0x00000000 . */
+ 0x00, /* 0x00000000 . */
+ 0x00, /* 0x00000000 . */
+ 0x00, /* 0x00000000 . */
+ 0x00, /* 0x00000000 . */
+ 0x00, /* 0x00000000 . */
+ 0x00, /* 0x00000000 . */
+ 0x00, /* 0x00000000 . */
+ 0x08, /* 0x00001000 . */
+ 0x1c, /* 0x00011100 . */
+ 0x08, /* 0x00001000 . */
+ 0x00, /* 0x00000000 . */
+ 0x00, /* 0x00000000 . */
+/* */
+ 0x00, /* 0x00000000 / */
+ 0x00, /* 0x00000000 / */
+ 0x40, /* 0x01000000 / */
+ 0x40, /* 0x01000000 / */
+ 0x20, /* 0x00100000 / */
+ 0x10, /* 0x00010000 / */
+ 0x08, /* 0x00001000 / */
+ 0x04, /* 0x00000100 / */
+ 0x02, /* 0x00000010 / */
+ 0x01, /* 0x00000001 / */
+ 0x01, /* 0x00000001 / */
+ 0x01, /* 0x00000001 / */
+ 0x00, /* 0x00000000 / */
+ 0x00, /* 0x00000000 / */
+ 0x00, /* 0x00000000 / */
+/* */
+ 0x00, /* 0x00000000 0 */
+ 0x00, /* 0x00000000 0 */
+ 0x0c, /* 0x00001100 0 */
+ 0x12, /* 0x00010010 0 */
+ 0x21, /* 0x00100001 0 */
+ 0x21, /* 0x00100001 0 */
+ 0x21, /* 0x00100001 0 */
+ 0x21, /* 0x00100001 0 */
+ 0x21, /* 0x00100001 0 */
+ 0x21, /* 0x00100001 0 */
+ 0x12, /* 0x00010010 0 */
+ 0x0c, /* 0x00001100 0 */
+ 0x00, /* 0x00000000 0 */
+ 0x00, /* 0x00000000 0 */
+ 0x00, /* 0x00000000 0 */
+/* */
+ 0x00, /* 0x00000000 1 */
+ 0x00, /* 0x00000000 1 */
+ 0x08, /* 0x00001000 1 */
+ 0x0c, /* 0x00001100 1 */
+ 0x0a, /* 0x00001010 1 */
+ 0x08, /* 0x00001000 1 */
+ 0x08, /* 0x00001000 1 */
+ 0x08, /* 0x00001000 1 */
+ 0x08, /* 0x00001000 1 */
+ 0x08, /* 0x00001000 1 */
+ 0x08, /* 0x00001000 1 */
+ 0x3e, /* 0x00111110 1 */
+ 0x00, /* 0x00000000 1 */
+ 0x00, /* 0x00000000 1 */
+ 0x00, /* 0x00000000 1 */
+/* */
+ 0x00, /* 0x00000000 2 */
+ 0x00, /* 0x00000000 2 */
+ 0x3e, /* 0x00111110 2 */
+ 0x41, /* 0x01000001 2 */
+ 0x41, /* 0x01000001 2 */
+ 0x40, /* 0x01000000 2 */
+ 0x20, /* 0x00100000 2 */
+ 0x10, /* 0x00010000 2 */
+ 0x0c, /* 0x00001100 2 */
+ 0x02, /* 0x00000010 2 */
+ 0x01, /* 0x00000001 2 */
+ 0x7f, /* 0x01111111 2 */
+ 0x00, /* 0x00000000 2 */
+ 0x00, /* 0x00000000 2 */
+ 0x00, /* 0x00000000 2 */
+/* */
+ 0x00, /* 0x00000000 3 */
+ 0x00, /* 0x00000000 3 */
+ 0x7f, /* 0x01111111 3 */
+ 0x40, /* 0x01000000 3 */
+ 0x20, /* 0x00100000 3 */
+ 0x10, /* 0x00010000 3 */
+ 0x38, /* 0x00111000 3 */
+ 0x40, /* 0x01000000 3 */
+ 0x40, /* 0x01000000 3 */
+ 0x40, /* 0x01000000 3 */
+ 0x41, /* 0x01000001 3 */
+ 0x3e, /* 0x00111110 3 */
+ 0x00, /* 0x00000000 3 */
+ 0x00, /* 0x00000000 3 */
+ 0x00, /* 0x00000000 3 */
+/* */
+ 0x00, /* 0x00000000 4 */
+ 0x00, /* 0x00000000 4 */
+ 0x20, /* 0x00100000 4 */
+ 0x30, /* 0x00110000 4 */
+ 0x28, /* 0x00101000 4 */
+ 0x24, /* 0x00100100 4 */
+ 0x22, /* 0x00100010 4 */
+ 0x21, /* 0x00100001 4 */
+ 0x7f, /* 0x01111111 4 */
+ 0x20, /* 0x00100000 4 */
+ 0x20, /* 0x00100000 4 */
+ 0x20, /* 0x00100000 4 */
+ 0x00, /* 0x00000000 4 */
+ 0x00, /* 0x00000000 4 */
+ 0x00, /* 0x00000000 4 */
+/* */
+ 0x00, /* 0x00000000 5 */
+ 0x00, /* 0x00000000 5 */
+ 0x7f, /* 0x01111111 5 */
+ 0x01, /* 0x00000001 5 */
+ 0x01, /* 0x00000001 5 */
+ 0x3d, /* 0x00111101 5 */
+ 0x43, /* 0x01000011 5 */
+ 0x40, /* 0x01000000 5 */
+ 0x40, /* 0x01000000 5 */
+ 0x40, /* 0x01000000 5 */
+ 0x41, /* 0x01000001 5 */
+ 0x3e, /* 0x00111110 5 */
+ 0x00, /* 0x00000000 5 */
+ 0x00, /* 0x00000000 5 */
+ 0x00, /* 0x00000000 5 */
+/* */
+ 0x00, /* 0x00000000 6 */
+ 0x00, /* 0x00000000 6 */
+ 0x3c, /* 0x00111100 6 */
+ 0x02, /* 0x00000010 6 */
+ 0x01, /* 0x00000001 6 */
+ 0x01, /* 0x00000001 6 */
+ 0x3d, /* 0x00111101 6 */
+ 0x43, /* 0x01000011 6 */
+ 0x41, /* 0x01000001 6 */
+ 0x41, /* 0x01000001 6 */
+ 0x41, /* 0x01000001 6 */
+ 0x3e, /* 0x00111110 6 */
+ 0x00, /* 0x00000000 6 */
+ 0x00, /* 0x00000000 6 */
+ 0x00, /* 0x00000000 6 */
+/* */
+ 0x00, /* 0x00000000 7 */
+ 0x00, /* 0x00000000 7 */
+ 0x7f, /* 0x01111111 7 */
+ 0x40, /* 0x01000000 7 */
+ 0x40, /* 0x01000000 7 */
+ 0x20, /* 0x00100000 7 */
+ 0x10, /* 0x00010000 7 */
+ 0x08, /* 0x00001000 7 */
+ 0x04, /* 0x00000100 7 */
+ 0x04, /* 0x00000100 7 */
+ 0x02, /* 0x00000010 7 */
+ 0x02, /* 0x00000010 7 */
+ 0x00, /* 0x00000000 7 */
+ 0x00, /* 0x00000000 7 */
+ 0x00, /* 0x00000000 7 */
+/* */
+ 0x00, /* 0x00000000 8 */
+ 0x00, /* 0x00000000 8 */
+ 0x3e, /* 0x00111110 8 */
+ 0x41, /* 0x01000001 8 */
+ 0x41, /* 0x01000001 8 */
+ 0x41, /* 0x01000001 8 */
+ 0x3e, /* 0x00111110 8 */
+ 0x41, /* 0x01000001 8 */
+ 0x41, /* 0x01000001 8 */
+ 0x41, /* 0x01000001 8 */
+ 0x41, /* 0x01000001 8 */
+ 0x3e, /* 0x00111110 8 */
+ 0x00, /* 0x00000000 8 */
+ 0x00, /* 0x00000000 8 */
+ 0x00, /* 0x00000000 8 */
+/* */
+ 0x00, /* 0x00000000 9 */
+ 0x00, /* 0x00000000 9 */
+ 0x3e, /* 0x00111110 9 */
+ 0x41, /* 0x01000001 9 */
+ 0x41, /* 0x01000001 9 */
+ 0x41, /* 0x01000001 9 */
+ 0x61, /* 0x01100001 9 */
+ 0x5e, /* 0x01011110 9 */
+ 0x40, /* 0x01000000 9 */
+ 0x40, /* 0x01000000 9 */
+ 0x20, /* 0x00100000 9 */
+ 0x1e, /* 0x00011110 9 */
+ 0x00, /* 0x00000000 9 */
+ 0x00, /* 0x00000000 9 */
+ 0x00, /* 0x00000000 9 */
+/* */
+ 0x00, /* 0x00000000 : */
+ 0x00, /* 0x00000000 : */
+ 0x00, /* 0x00000000 : */
+ 0x00, /* 0x00000000 : */
+ 0x00, /* 0x00000000 : */
+ 0x08, /* 0x00001000 : */
+ 0x1c, /* 0x00011100 : */
+ 0x08, /* 0x00001000 : */
+ 0x00, /* 0x00000000 : */
+ 0x00, /* 0x00000000 : */
+ 0x08, /* 0x00001000 : */
+ 0x1c, /* 0x00011100 : */
+ 0x08, /* 0x00001000 : */
+ 0x00, /* 0x00000000 : */
+ 0x00, /* 0x00000000 : */
+/* */
+ 0x00, /* 0x00000000 ; */
+ 0x00, /* 0x00000000 ; */
+ 0x00, /* 0x00000000 ; */
+ 0x00, /* 0x00000000 ; */
+ 0x00, /* 0x00000000 ; */
+ 0x08, /* 0x00001000 ; */
+ 0x1c, /* 0x00011100 ; */
+ 0x08, /* 0x00001000 ; */
+ 0x00, /* 0x00000000 ; */
+ 0x00, /* 0x00000000 ; */
+ 0x1c, /* 0x00011100 ; */
+ 0x0c, /* 0x00001100 ; */
+ 0x02, /* 0x00000010 ; */
+ 0x00, /* 0x00000000 ; */
+ 0x00, /* 0x00000000 ; */
+/* */
+ 0x00, /* 0x00000000 < */
+ 0x00, /* 0x00000000 < */
+ 0x20, /* 0x00100000 < */
+ 0x10, /* 0x00010000 < */
+ 0x08, /* 0x00001000 < */
+ 0x04, /* 0x00000100 < */
+ 0x02, /* 0x00000010 < */
+ 0x02, /* 0x00000010 < */
+ 0x04, /* 0x00000100 < */
+ 0x08, /* 0x00001000 < */
+ 0x10, /* 0x00010000 < */
+ 0x20, /* 0x00100000 < */
+ 0x00, /* 0x00000000 < */
+ 0x00, /* 0x00000000 < */
+ 0x00, /* 0x00000000 < */
+/* */
+ 0x00, /* 0x00000000 = */
+ 0x00, /* 0x00000000 = */
+ 0x00, /* 0x00000000 = */
+ 0x00, /* 0x00000000 = */
+ 0x00, /* 0x00000000 = */
+ 0x00, /* 0x00000000 = */
+ 0x7f, /* 0x01111111 = */
+ 0x00, /* 0x00000000 = */
+ 0x00, /* 0x00000000 = */
+ 0x7f, /* 0x01111111 = */
+ 0x00, /* 0x00000000 = */
+ 0x00, /* 0x00000000 = */
+ 0x00, /* 0x00000000 = */
+ 0x00, /* 0x00000000 = */
+ 0x00, /* 0x00000000 = */
+/* */
+ 0x00, /* 0x00000000 > */
+ 0x00, /* 0x00000000 > */
+ 0x02, /* 0x00000010 > */
+ 0x04, /* 0x00000100 > */
+ 0x08, /* 0x00001000 > */
+ 0x10, /* 0x00010000 > */
+ 0x20, /* 0x00100000 > */
+ 0x20, /* 0x00100000 > */
+ 0x10, /* 0x00010000 > */
+ 0x08, /* 0x00001000 > */
+ 0x04, /* 0x00000100 > */
+ 0x02, /* 0x00000010 > */
+ 0x00, /* 0x00000000 > */
+ 0x00, /* 0x00000000 > */
+ 0x00, /* 0x00000000 > */
+/* */
+ 0x00, /* 0x00000000 ? */
+ 0x00, /* 0x00000000 ? */
+ 0x3e, /* 0x00111110 ? */
+ 0x41, /* 0x01000001 ? */
+ 0x41, /* 0x01000001 ? */
+ 0x40, /* 0x01000000 ? */
+ 0x20, /* 0x00100000 ? */
+ 0x10, /* 0x00010000 ? */
+ 0x08, /* 0x00001000 ? */
+ 0x08, /* 0x00001000 ? */
+ 0x00, /* 0x00000000 ? */
+ 0x08, /* 0x00001000 ? */
+ 0x00, /* 0x00000000 ? */
+ 0x00, /* 0x00000000 ? */
+ 0x00, /* 0x00000000 ? */
+/* */
+ 0x00, /* 0x00000000 @ */
+ 0x00, /* 0x00000000 @ */
+ 0x3e, /* 0x00111110 @ */
+ 0x41, /* 0x01000001 @ */
+ 0x41, /* 0x01000001 @ */
+ 0x79, /* 0x01111001 @ */
+ 0x45, /* 0x01000101 @ */
+ 0x65, /* 0x01100101 @ */
+ 0x59, /* 0x01011001 @ */
+ 0x01, /* 0x00000001 @ */
+ 0x01, /* 0x00000001 @ */
+ 0x3e, /* 0x00111110 @ */
+ 0x00, /* 0x00000000 @ */
+ 0x00, /* 0x00000000 @ */
+ 0x00, /* 0x00000000 @ */
+/* */
+ 0x00, /* 0x00000000 A */
+ 0x00, /* 0x00000000 A */
+ 0x08, /* 0x00001000 A */
+ 0x14, /* 0x00010100 A */
+ 0x22, /* 0x00100010 A */
+ 0x41, /* 0x01000001 A */
+ 0x41, /* 0x01000001 A */
+ 0x41, /* 0x01000001 A */
+ 0x7f, /* 0x01111111 A */
+ 0x41, /* 0x01000001 A */
+ 0x41, /* 0x01000001 A */
+ 0x41, /* 0x01000001 A */
+ 0x00, /* 0x00000000 A */
+ 0x00, /* 0x00000000 A */
+ 0x00, /* 0x00000000 A */
+/* */
+ 0x00, /* 0x00000000 B */
+ 0x00, /* 0x00000000 B */
+ 0x3f, /* 0x00111111 B */
+ 0x42, /* 0x01000010 B */
+ 0x42, /* 0x01000010 B */
+ 0x42, /* 0x01000010 B */
+ 0x3e, /* 0x00111110 B */
+ 0x42, /* 0x01000010 B */
+ 0x42, /* 0x01000010 B */
+ 0x42, /* 0x01000010 B */
+ 0x42, /* 0x01000010 B */
+ 0x3f, /* 0x00111111 B */
+ 0x00, /* 0x00000000 B */
+ 0x00, /* 0x00000000 B */
+ 0x00, /* 0x00000000 B */
+/* */
+ 0x00, /* 0x00000000 C */
+ 0x00, /* 0x00000000 C */
+ 0x3e, /* 0x00111110 C */
+ 0x41, /* 0x01000001 C */
+ 0x01, /* 0x00000001 C */
+ 0x01, /* 0x00000001 C */
+ 0x01, /* 0x00000001 C */
+ 0x01, /* 0x00000001 C */
+ 0x01, /* 0x00000001 C */
+ 0x01, /* 0x00000001 C */
+ 0x41, /* 0x01000001 C */
+ 0x3e, /* 0x00111110 C */
+ 0x00, /* 0x00000000 C */
+ 0x00, /* 0x00000000 C */
+ 0x00, /* 0x00000000 C */
+/* */
+ 0x00, /* 0x00000000 D */
+ 0x00, /* 0x00000000 D */
+ 0x3f, /* 0x00111111 D */
+ 0x42, /* 0x01000010 D */
+ 0x42, /* 0x01000010 D */
+ 0x42, /* 0x01000010 D */
+ 0x42, /* 0x01000010 D */
+ 0x42, /* 0x01000010 D */
+ 0x42, /* 0x01000010 D */
+ 0x42, /* 0x01000010 D */
+ 0x42, /* 0x01000010 D */
+ 0x3f, /* 0x00111111 D */
+ 0x00, /* 0x00000000 D */
+ 0x00, /* 0x00000000 D */
+ 0x00, /* 0x00000000 D */
+/* */
+ 0x00, /* 0x00000000 E */
+ 0x00, /* 0x00000000 E */
+ 0x7e, /* 0x01111110 E */
+ 0x02, /* 0x00000010 E */
+ 0x02, /* 0x00000010 E */
+ 0x02, /* 0x00000010 E */
+ 0x1e, /* 0x00011110 E */
+ 0x02, /* 0x00000010 E */
+ 0x02, /* 0x00000010 E */
+ 0x02, /* 0x00000010 E */
+ 0x02, /* 0x00000010 E */
+ 0x7e, /* 0x01111110 E */
+ 0x00, /* 0x00000000 E */
+ 0x00, /* 0x00000000 E */
+ 0x00, /* 0x00000000 E */
+/* */
+ 0x00, /* 0x00000000 F */
+ 0x00, /* 0x00000000 F */
+ 0x7e, /* 0x01111110 F */
+ 0x02, /* 0x00000010 F */
+ 0x02, /* 0x00000010 F */
+ 0x02, /* 0x00000010 F */
+ 0x1e, /* 0x00011110 F */
+ 0x02, /* 0x00000010 F */
+ 0x02, /* 0x00000010 F */
+ 0x02, /* 0x00000010 F */
+ 0x02, /* 0x00000010 F */
+ 0x02, /* 0x00000010 F */
+ 0x00, /* 0x00000000 F */
+ 0x00, /* 0x00000000 F */
+ 0x00, /* 0x00000000 F */
+/* */
+ 0x00, /* 0x00000000 G */
+ 0x00, /* 0x00000000 G */
+ 0x3e, /* 0x00111110 G */
+ 0x41, /* 0x01000001 G */
+ 0x01, /* 0x00000001 G */
+ 0x01, /* 0x00000001 G */
+ 0x01, /* 0x00000001 G */
+ 0x71, /* 0x01110001 G */
+ 0x41, /* 0x01000001 G */
+ 0x41, /* 0x01000001 G */
+ 0x41, /* 0x01000001 G */
+ 0x3e, /* 0x00111110 G */
+ 0x00, /* 0x00000000 G */
+ 0x00, /* 0x00000000 G */
+ 0x00, /* 0x00000000 G */
+/* */
+ 0x00, /* 0x00000000 H */
+ 0x00, /* 0x00000000 H */
+ 0x41, /* 0x01000001 H */
+ 0x41, /* 0x01000001 H */
+ 0x41, /* 0x01000001 H */
+ 0x41, /* 0x01000001 H */
+ 0x7f, /* 0x01111111 H */
+ 0x41, /* 0x01000001 H */
+ 0x41, /* 0x01000001 H */
+ 0x41, /* 0x01000001 H */
+ 0x41, /* 0x01000001 H */
+ 0x41, /* 0x01000001 H */
+ 0x00, /* 0x00000000 H */
+ 0x00, /* 0x00000000 H */
+ 0x00, /* 0x00000000 H */
+/* */
+ 0x00, /* 0x00000000 I */
+ 0x00, /* 0x00000000 I */
+ 0x3e, /* 0x00111110 I */
+ 0x08, /* 0x00001000 I */
+ 0x08, /* 0x00001000 I */
+ 0x08, /* 0x00001000 I */
+ 0x08, /* 0x00001000 I */
+ 0x08, /* 0x00001000 I */
+ 0x08, /* 0x00001000 I */
+ 0x08, /* 0x00001000 I */
+ 0x08, /* 0x00001000 I */
+ 0x3e, /* 0x00111110 I */
+ 0x00, /* 0x00000000 I */
+ 0x00, /* 0x00000000 I */
+ 0x00, /* 0x00000000 I */
+/* */
+ 0x00, /* 0x00000000 J */
+ 0x00, /* 0x00000000 J */
+ 0x78, /* 0x01111000 J */
+ 0x20, /* 0x00100000 J */
+ 0x20, /* 0x00100000 J */
+ 0x20, /* 0x00100000 J */
+ 0x20, /* 0x00100000 J */
+ 0x20, /* 0x00100000 J */
+ 0x20, /* 0x00100000 J */
+ 0x20, /* 0x00100000 J */
+ 0x21, /* 0x00100001 J */
+ 0x1e, /* 0x00011110 J */
+ 0x00, /* 0x00000000 J */
+ 0x00, /* 0x00000000 J */
+ 0x00, /* 0x00000000 J */
+/* */
+ 0x00, /* 0x00000000 K */
+ 0x00, /* 0x00000000 K */
+ 0x41, /* 0x01000001 K */
+ 0x21, /* 0x00100001 K */
+ 0x11, /* 0x00010001 K */
+ 0x09, /* 0x00001001 K */
+ 0x07, /* 0x00000111 K */
+ 0x05, /* 0x00000101 K */
+ 0x09, /* 0x00001001 K */
+ 0x11, /* 0x00010001 K */
+ 0x21, /* 0x00100001 K */
+ 0x41, /* 0x01000001 K */
+ 0x00, /* 0x00000000 K */
+ 0x00, /* 0x00000000 K */
+ 0x00, /* 0x00000000 K */
+/* */
+ 0x00, /* 0x00000000 L */
+ 0x00, /* 0x00000000 L */
+ 0x01, /* 0x00000001 L */
+ 0x01, /* 0x00000001 L */
+ 0x01, /* 0x00000001 L */
+ 0x01, /* 0x00000001 L */
+ 0x01, /* 0x00000001 L */
+ 0x01, /* 0x00000001 L */
+ 0x01, /* 0x00000001 L */
+ 0x01, /* 0x00000001 L */
+ 0x01, /* 0x00000001 L */
+ 0x7f, /* 0x01111111 L */
+ 0x00, /* 0x00000000 L */
+ 0x00, /* 0x00000000 L */
+ 0x00, /* 0x00000000 L */
+/* */
+ 0x00, /* 0x00000000 M */
+ 0x00, /* 0x00000000 M */
+ 0x41, /* 0x01000001 M */
+ 0x41, /* 0x01000001 M */
+ 0x63, /* 0x01100011 M */
+ 0x55, /* 0x01010101 M */
+ 0x55, /* 0x01010101 M */
+ 0x49, /* 0x01001001 M */
+ 0x49, /* 0x01001001 M */
+ 0x41, /* 0x01000001 M */
+ 0x41, /* 0x01000001 M */
+ 0x41, /* 0x01000001 M */
+ 0x00, /* 0x00000000 M */
+ 0x00, /* 0x00000000 M */
+ 0x00, /* 0x00000000 M */
+/* */
+ 0x00, /* 0x00000000 N */
+ 0x00, /* 0x00000000 N */
+ 0x41, /* 0x01000001 N */
+ 0x41, /* 0x01000001 N */
+ 0x43, /* 0x01000011 N */
+ 0x45, /* 0x01000101 N */
+ 0x49, /* 0x01001001 N */
+ 0x51, /* 0x01010001 N */
+ 0x61, /* 0x01100001 N */
+ 0x41, /* 0x01000001 N */
+ 0x41, /* 0x01000001 N */
+ 0x41, /* 0x01000001 N */
+ 0x00, /* 0x00000000 N */
+ 0x00, /* 0x00000000 N */
+ 0x00, /* 0x00000000 N */
+/* */
+ 0x00, /* 0x00000000 O */
+ 0x00, /* 0x00000000 O */
+ 0x3e, /* 0x00111110 O */
+ 0x41, /* 0x01000001 O */
+ 0x41, /* 0x01000001 O */
+ 0x41, /* 0x01000001 O */
+ 0x41, /* 0x01000001 O */
+ 0x41, /* 0x01000001 O */
+ 0x41, /* 0x01000001 O */
+ 0x41, /* 0x01000001 O */
+ 0x41, /* 0x01000001 O */
+ 0x3e, /* 0x00111110 O */
+ 0x00, /* 0x00000000 O */
+ 0x00, /* 0x00000000 O */
+ 0x00, /* 0x00000000 O */
+/* */
+ 0x00, /* 0x00000000 P */
+ 0x00, /* 0x00000000 P */
+ 0x3f, /* 0x00111111 P */
+ 0x41, /* 0x01000001 P */
+ 0x41, /* 0x01000001 P */
+ 0x41, /* 0x01000001 P */
+ 0x3f, /* 0x00111111 P */
+ 0x01, /* 0x00000001 P */
+ 0x01, /* 0x00000001 P */
+ 0x01, /* 0x00000001 P */
+ 0x01, /* 0x00000001 P */
+ 0x01, /* 0x00000001 P */
+ 0x00, /* 0x00000000 P */
+ 0x00, /* 0x00000000 P */
+ 0x00, /* 0x00000000 P */
+/* */
+ 0x00, /* 0x00000000 Q */
+ 0x00, /* 0x00000000 Q */
+ 0x3e, /* 0x00111110 Q */
+ 0x41, /* 0x01000001 Q */
+ 0x41, /* 0x01000001 Q */
+ 0x41, /* 0x01000001 Q */
+ 0x41, /* 0x01000001 Q */
+ 0x41, /* 0x01000001 Q */
+ 0x41, /* 0x01000001 Q */
+ 0x49, /* 0x01001001 Q */
+ 0x51, /* 0x01010001 Q */
+ 0x3e, /* 0x00111110 Q */
+ 0x40, /* 0x01000000 Q */
+ 0x00, /* 0x00000000 Q */
+ 0x00, /* 0x00000000 Q */
+/* */
+ 0x00, /* 0x00000000 R */
+ 0x00, /* 0x00000000 R */
+ 0x3f, /* 0x00111111 R */
+ 0x41, /* 0x01000001 R */
+ 0x41, /* 0x01000001 R */
+ 0x41, /* 0x01000001 R */
+ 0x3f, /* 0x00111111 R */
+ 0x09, /* 0x00001001 R */
+ 0x11, /* 0x00010001 R */
+ 0x21, /* 0x00100001 R */
+ 0x41, /* 0x01000001 R */
+ 0x41, /* 0x01000001 R */
+ 0x00, /* 0x00000000 R */
+ 0x00, /* 0x00000000 R */
+ 0x00, /* 0x00000000 R */
+/* */
+ 0x00, /* 0x00000000 S */
+ 0x00, /* 0x00000000 S */
+ 0x3e, /* 0x00111110 S */
+ 0x41, /* 0x01000001 S */
+ 0x01, /* 0x00000001 S */
+ 0x01, /* 0x00000001 S */
+ 0x3e, /* 0x00111110 S */
+ 0x40, /* 0x01000000 S */
+ 0x40, /* 0x01000000 S */
+ 0x40, /* 0x01000000 S */
+ 0x41, /* 0x01000001 S */
+ 0x3e, /* 0x00111110 S */
+ 0x00, /* 0x00000000 S */
+ 0x00, /* 0x00000000 S */
+ 0x00, /* 0x00000000 S */
+/* */
+ 0x00, /* 0x00000000 T */
+ 0x00, /* 0x00000000 T */
+ 0x7f, /* 0x01111111 T */
+ 0x08, /* 0x00001000 T */
+ 0x08, /* 0x00001000 T */
+ 0x08, /* 0x00001000 T */
+ 0x08, /* 0x00001000 T */
+ 0x08, /* 0x00001000 T */
+ 0x08, /* 0x00001000 T */
+ 0x08, /* 0x00001000 T */
+ 0x08, /* 0x00001000 T */
+ 0x08, /* 0x00001000 T */
+ 0x00, /* 0x00000000 T */
+ 0x00, /* 0x00000000 T */
+ 0x00, /* 0x00000000 T */
+/* */
+ 0x00, /* 0x00000000 U */
+ 0x00, /* 0x00000000 U */
+ 0x41, /* 0x01000001 U */
+ 0x41, /* 0x01000001 U */
+ 0x41, /* 0x01000001 U */
+ 0x41, /* 0x01000001 U */
+ 0x41, /* 0x01000001 U */
+ 0x41, /* 0x01000001 U */
+ 0x41, /* 0x01000001 U */
+ 0x41, /* 0x01000001 U */
+ 0x41, /* 0x01000001 U */
+ 0x3e, /* 0x00111110 U */
+ 0x00, /* 0x00000000 U */
+ 0x00, /* 0x00000000 U */
+ 0x00, /* 0x00000000 U */
+/* */
+ 0x00, /* 0x00000000 V */
+ 0x00, /* 0x00000000 V */
+ 0x41, /* 0x01000001 V */
+ 0x41, /* 0x01000001 V */
+ 0x41, /* 0x01000001 V */
+ 0x22, /* 0x00100010 V */
+ 0x22, /* 0x00100010 V */
+ 0x22, /* 0x00100010 V */
+ 0x14, /* 0x00010100 V */
+ 0x14, /* 0x00010100 V */
+ 0x14, /* 0x00010100 V */
+ 0x08, /* 0x00001000 V */
+ 0x00, /* 0x00000000 V */
+ 0x00, /* 0x00000000 V */
+ 0x00, /* 0x00000000 V */
+/* */
+ 0x00, /* 0x00000000 W */
+ 0x00, /* 0x00000000 W */
+ 0x41, /* 0x01000001 W */
+ 0x41, /* 0x01000001 W */
+ 0x41, /* 0x01000001 W */
+ 0x41, /* 0x01000001 W */
+ 0x49, /* 0x01001001 W */
+ 0x49, /* 0x01001001 W */
+ 0x49, /* 0x01001001 W */
+ 0x49, /* 0x01001001 W */
+ 0x55, /* 0x01010101 W */
+ 0x22, /* 0x00100010 W */
+ 0x00, /* 0x00000000 W */
+ 0x00, /* 0x00000000 W */
+ 0x00, /* 0x00000000 W */
+/* */
+ 0x00, /* 0x00000000 X */
+ 0x00, /* 0x00000000 X */
+ 0x41, /* 0x01000001 X */
+ 0x41, /* 0x01000001 X */
+ 0x22, /* 0x00100010 X */
+ 0x14, /* 0x00010100 X */
+ 0x08, /* 0x00001000 X */
+ 0x08, /* 0x00001000 X */
+ 0x14, /* 0x00010100 X */
+ 0x22, /* 0x00100010 X */
+ 0x41, /* 0x01000001 X */
+ 0x41, /* 0x01000001 X */
+ 0x00, /* 0x00000000 X */
+ 0x00, /* 0x00000000 X */
+ 0x00, /* 0x00000000 X */
+/* */
+ 0x00, /* 0x00000000 Y */
+ 0x00, /* 0x00000000 Y */
+ 0x41, /* 0x01000001 Y */
+ 0x41, /* 0x01000001 Y */
+ 0x22, /* 0x00100010 Y */
+ 0x14, /* 0x00010100 Y */
+ 0x08, /* 0x00001000 Y */
+ 0x08, /* 0x00001000 Y */
+ 0x08, /* 0x00001000 Y */
+ 0x08, /* 0x00001000 Y */
+ 0x08, /* 0x00001000 Y */
+ 0x08, /* 0x00001000 Y */
+ 0x00, /* 0x00000000 Y */
+ 0x00, /* 0x00000000 Y */
+ 0x00, /* 0x00000000 Y */
+/* */
+ 0x00, /* 0x00000000 Z */
+ 0x00, /* 0x00000000 Z */
+ 0x7f, /* 0x01111111 Z */
+ 0x40, /* 0x01000000 Z */
+ 0x20, /* 0x00100000 Z */
+ 0x10, /* 0x00010000 Z */
+ 0x08, /* 0x00001000 Z */
+ 0x04, /* 0x00000100 Z */
+ 0x02, /* 0x00000010 Z */
+ 0x01, /* 0x00000001 Z */
+ 0x01, /* 0x00000001 Z */
+ 0x7f, /* 0x01111111 Z */
+ 0x00, /* 0x00000000 Z */
+ 0x00, /* 0x00000000 Z */
+ 0x00, /* 0x00000000 Z */
+/* */
+ 0x00, /* 0x00000000 [ */
+ 0x00, /* 0x00000000 [ */
+ 0x3c, /* 0x00111100 [ */
+ 0x04, /* 0x00000100 [ */
+ 0x04, /* 0x00000100 [ */
+ 0x04, /* 0x00000100 [ */
+ 0x04, /* 0x00000100 [ */
+ 0x04, /* 0x00000100 [ */
+ 0x04, /* 0x00000100 [ */
+ 0x04, /* 0x00000100 [ */
+ 0x04, /* 0x00000100 [ */
+ 0x3c, /* 0x00111100 [ */
+ 0x00, /* 0x00000000 [ */
+ 0x00, /* 0x00000000 [ */
+ 0x00, /* 0x00000000 [ */
+/* */
+ 0x00, /* 0x00000000 \ */
+ 0x00, /* 0x00000000 \ */
+ 0x01, /* 0x00000001 \ */
+ 0x02, /* 0x00000010 \ */
+ 0x02, /* 0x00000010 \ */
+ 0x04, /* 0x00000100 \ */
+ 0x08, /* 0x00001000 \ */
+ 0x08, /* 0x00001000 \ */
+ 0x10, /* 0x00010000 \ */
+ 0x20, /* 0x00100000 \ */
+ 0x20, /* 0x00100000 \ */
+ 0x40, /* 0x01000000 \ */
+ 0x00, /* 0x00000000 \ */
+ 0x00, /* 0x00000000 \ */
+ 0x00, /* 0x00000000 \ */
+/* */
+ 0x00, /* 0x00000000 ] */
+ 0x00, /* 0x00000000 ] */
+ 0x1e, /* 0x00011110 ] */
+ 0x10, /* 0x00010000 ] */
+ 0x10, /* 0x00010000 ] */
+ 0x10, /* 0x00010000 ] */
+ 0x10, /* 0x00010000 ] */
+ 0x10, /* 0x00010000 ] */
+ 0x10, /* 0x00010000 ] */
+ 0x10, /* 0x00010000 ] */
+ 0x10, /* 0x00010000 ] */
+ 0x1e, /* 0x00011110 ] */
+ 0x00, /* 0x00000000 ] */
+ 0x00, /* 0x00000000 ] */
+ 0x00, /* 0x00000000 ] */
+/* */
+ 0x00, /* 0x00000000 ^ */
+ 0x00, /* 0x00000000 ^ */
+ 0x08, /* 0x00001000 ^ */
+ 0x14, /* 0x00010100 ^ */
+ 0x22, /* 0x00100010 ^ */
+ 0x41, /* 0x01000001 ^ */
+ 0x00, /* 0x00000000 ^ */
+ 0x00, /* 0x00000000 ^ */
+ 0x00, /* 0x00000000 ^ */
+ 0x00, /* 0x00000000 ^ */
+ 0x00, /* 0x00000000 ^ */
+ 0x00, /* 0x00000000 ^ */
+ 0x00, /* 0x00000000 ^ */
+ 0x00, /* 0x00000000 ^ */
+ 0x00, /* 0x00000000 ^ */
+/* */
+ 0x00, /* 0x00000000 _ */
+ 0x00, /* 0x00000000 _ */
+ 0x00, /* 0x00000000 _ */
+ 0x00, /* 0x00000000 _ */
+ 0x00, /* 0x00000000 _ */
+ 0x00, /* 0x00000000 _ */
+ 0x00, /* 0x00000000 _ */
+ 0x00, /* 0x00000000 _ */
+ 0x00, /* 0x00000000 _ */
+ 0x00, /* 0x00000000 _ */
+ 0x00, /* 0x00000000 _ */
+ 0x00, /* 0x00000000 _ */
+ 0x7f, /* 0x01111111 _ */
+ 0x00, /* 0x00000000 _ */
+ 0x00, /* 0x00000000 _ */
+/* */
+ 0x00, /* 0x00000000 ` */
+ 0x00, /* 0x00000000 ` */
+ 0x0e, /* 0x00001110 ` */
+ 0x0c, /* 0x00001100 ` */
+ 0x10, /* 0x00010000 ` */
+ 0x00, /* 0x00000000 ` */
+ 0x00, /* 0x00000000 ` */
+ 0x00, /* 0x00000000 ` */
+ 0x00, /* 0x00000000 ` */
+ 0x00, /* 0x00000000 ` */
+ 0x00, /* 0x00000000 ` */
+ 0x00, /* 0x00000000 ` */
+ 0x00, /* 0x00000000 ` */
+ 0x00, /* 0x00000000 ` */
+ 0x00, /* 0x00000000 ` */
+/* */
+ 0x00, /* 0x00000000 a */
+ 0x00, /* 0x00000000 a */
+ 0x00, /* 0x00000000 a */
+ 0x00, /* 0x00000000 a */
+ 0x00, /* 0x00000000 a */
+ 0x3e, /* 0x00111110 a */
+ 0x40, /* 0x01000000 a */
+ 0x40, /* 0x01000000 a */
+ 0x7e, /* 0x01111110 a */
+ 0x41, /* 0x01000001 a */
+ 0x61, /* 0x01100001 a */
+ 0x5e, /* 0x01011110 a */
+ 0x00, /* 0x00000000 a */
+ 0x00, /* 0x00000000 a */
+ 0x00, /* 0x00000000 a */
+/* */
+ 0x00, /* 0x00000000 b */
+ 0x00, /* 0x00000000 b */
+ 0x01, /* 0x00000001 b */
+ 0x01, /* 0x00000001 b */
+ 0x01, /* 0x00000001 b */
+ 0x3d, /* 0x00111101 b */
+ 0x43, /* 0x01000011 b */
+ 0x41, /* 0x01000001 b */
+ 0x41, /* 0x01000001 b */
+ 0x41, /* 0x01000001 b */
+ 0x43, /* 0x01000011 b */
+ 0x3d, /* 0x00111101 b */
+ 0x00, /* 0x00000000 b */
+ 0x00, /* 0x00000000 b */
+ 0x00, /* 0x00000000 b */
+/* */
+ 0x00, /* 0x00000000 c */
+ 0x00, /* 0x00000000 c */
+ 0x00, /* 0x00000000 c */
+ 0x00, /* 0x00000000 c */
+ 0x00, /* 0x00000000 c */
+ 0x3e, /* 0x00111110 c */
+ 0x41, /* 0x01000001 c */
+ 0x01, /* 0x00000001 c */
+ 0x01, /* 0x00000001 c */
+ 0x01, /* 0x00000001 c */
+ 0x41, /* 0x01000001 c */
+ 0x3e, /* 0x00111110 c */
+ 0x00, /* 0x00000000 c */
+ 0x00, /* 0x00000000 c */
+ 0x00, /* 0x00000000 c */
+/* */
+ 0x00, /* 0x00000000 d */
+ 0x00, /* 0x00000000 d */
+ 0x40, /* 0x01000000 d */
+ 0x40, /* 0x01000000 d */
+ 0x40, /* 0x01000000 d */
+ 0x5e, /* 0x01011110 d */
+ 0x61, /* 0x01100001 d */
+ 0x41, /* 0x01000001 d */
+ 0x41, /* 0x01000001 d */
+ 0x41, /* 0x01000001 d */
+ 0x61, /* 0x01100001 d */
+ 0x5e, /* 0x01011110 d */
+ 0x00, /* 0x00000000 d */
+ 0x00, /* 0x00000000 d */
+ 0x00, /* 0x00000000 d */
+/* */
+ 0x00, /* 0x00000000 e */
+ 0x00, /* 0x00000000 e */
+ 0x00, /* 0x00000000 e */
+ 0x00, /* 0x00000000 e */
+ 0x00, /* 0x00000000 e */
+ 0x3e, /* 0x00111110 e */
+ 0x41, /* 0x01000001 e */
+ 0x41, /* 0x01000001 e */
+ 0x7f, /* 0x01111111 e */
+ 0x01, /* 0x00000001 e */
+ 0x01, /* 0x00000001 e */
+ 0x3e, /* 0x00111110 e */
+ 0x00, /* 0x00000000 e */
+ 0x00, /* 0x00000000 e */
+ 0x00, /* 0x00000000 e */
+/* */
+ 0x00, /* 0x00000000 f */
+ 0x00, /* 0x00000000 f */
+ 0x38, /* 0x00111000 f */
+ 0x44, /* 0x01000100 f */
+ 0x44, /* 0x01000100 f */
+ 0x04, /* 0x00000100 f */
+ 0x04, /* 0x00000100 f */
+ 0x1f, /* 0x00011111 f */
+ 0x04, /* 0x00000100 f */
+ 0x04, /* 0x00000100 f */
+ 0x04, /* 0x00000100 f */
+ 0x04, /* 0x00000100 f */
+ 0x00, /* 0x00000000 f */
+ 0x00, /* 0x00000000 f */
+ 0x00, /* 0x00000000 f */
+/* */
+ 0x00, /* 0x00000000 g */
+ 0x00, /* 0x00000000 g */
+ 0x00, /* 0x00000000 g */
+ 0x00, /* 0x00000000 g */
+ 0x00, /* 0x00000000 g */
+ 0x5e, /* 0x01011110 g */
+ 0x21, /* 0x00100001 g */
+ 0x21, /* 0x00100001 g */
+ 0x21, /* 0x00100001 g */
+ 0x1e, /* 0x00011110 g */
+ 0x01, /* 0x00000001 g */
+ 0x3e, /* 0x00111110 g */
+ 0x41, /* 0x01000001 g */
+ 0x41, /* 0x01000001 g */
+ 0x3e, /* 0x00111110 g */
+/* */
+ 0x00, /* 0x00000000 h */
+ 0x00, /* 0x00000000 h */
+ 0x01, /* 0x00000001 h */
+ 0x01, /* 0x00000001 h */
+ 0x01, /* 0x00000001 h */
+ 0x3d, /* 0x00111101 h */
+ 0x43, /* 0x01000011 h */
+ 0x41, /* 0x01000001 h */
+ 0x41, /* 0x01000001 h */
+ 0x41, /* 0x01000001 h */
+ 0x41, /* 0x01000001 h */
+ 0x41, /* 0x01000001 h */
+ 0x00, /* 0x00000000 h */
+ 0x00, /* 0x00000000 h */
+ 0x00, /* 0x00000000 h */
+/* */
+ 0x00, /* 0x00000000 i */
+ 0x00, /* 0x00000000 i */
+ 0x00, /* 0x00000000 i */
+ 0x08, /* 0x00001000 i */
+ 0x00, /* 0x00000000 i */
+ 0x0c, /* 0x00001100 i */
+ 0x08, /* 0x00001000 i */
+ 0x08, /* 0x00001000 i */
+ 0x08, /* 0x00001000 i */
+ 0x08, /* 0x00001000 i */
+ 0x08, /* 0x00001000 i */
+ 0x3e, /* 0x00111110 i */
+ 0x00, /* 0x00000000 i */
+ 0x00, /* 0x00000000 i */
+ 0x00, /* 0x00000000 i */
+/* */
+ 0x00, /* 0x00000000 j */
+ 0x00, /* 0x00000000 j */
+ 0x00, /* 0x00000000 j */
+ 0x20, /* 0x00100000 j */
+ 0x00, /* 0x00000000 j */
+ 0x38, /* 0x00111000 j */
+ 0x20, /* 0x00100000 j */
+ 0x20, /* 0x00100000 j */
+ 0x20, /* 0x00100000 j */
+ 0x20, /* 0x00100000 j */
+ 0x20, /* 0x00100000 j */
+ 0x21, /* 0x00100001 j */
+ 0x21, /* 0x00100001 j */
+ 0x21, /* 0x00100001 j */
+ 0x1e, /* 0x00011110 j */
+/* */
+ 0x00, /* 0x00000000 k */
+ 0x00, /* 0x00000000 k */
+ 0x01, /* 0x00000001 k */
+ 0x01, /* 0x00000001 k */
+ 0x01, /* 0x00000001 k */
+ 0x41, /* 0x01000001 k */
+ 0x31, /* 0x00110001 k */
+ 0x0d, /* 0x00001101 k */
+ 0x03, /* 0x00000011 k */
+ 0x0d, /* 0x00001101 k */
+ 0x31, /* 0x00110001 k */
+ 0x41, /* 0x01000001 k */
+ 0x00, /* 0x00000000 k */
+ 0x00, /* 0x00000000 k */
+ 0x00, /* 0x00000000 k */
+/* */
+ 0x00, /* 0x00000000 l */
+ 0x00, /* 0x00000000 l */
+ 0x0c, /* 0x00001100 l */
+ 0x08, /* 0x00001000 l */
+ 0x08, /* 0x00001000 l */
+ 0x08, /* 0x00001000 l */
+ 0x08, /* 0x00001000 l */
+ 0x08, /* 0x00001000 l */
+ 0x08, /* 0x00001000 l */
+ 0x08, /* 0x00001000 l */
+ 0x08, /* 0x00001000 l */
+ 0x3e, /* 0x00111110 l */
+ 0x00, /* 0x00000000 l */
+ 0x00, /* 0x00000000 l */
+ 0x00, /* 0x00000000 l */
+/* */
+ 0x00, /* 0x00000000 m */
+ 0x00, /* 0x00000000 m */
+ 0x00, /* 0x00000000 m */
+ 0x00, /* 0x00000000 m */
+ 0x00, /* 0x00000000 m */
+ 0x37, /* 0x00110111 m */
+ 0x49, /* 0x01001001 m */
+ 0x49, /* 0x01001001 m */
+ 0x49, /* 0x01001001 m */
+ 0x49, /* 0x01001001 m */
+ 0x49, /* 0x01001001 m */
+ 0x41, /* 0x01000001 m */
+ 0x00, /* 0x00000000 m */
+ 0x00, /* 0x00000000 m */
+ 0x00, /* 0x00000000 m */
+/* */
+ 0x00, /* 0x00000000 n */
+ 0x00, /* 0x00000000 n */
+ 0x00, /* 0x00000000 n */
+ 0x00, /* 0x00000000 n */
+ 0x00, /* 0x00000000 n */
+ 0x3d, /* 0x00111101 n */
+ 0x43, /* 0x01000011 n */
+ 0x41, /* 0x01000001 n */
+ 0x41, /* 0x01000001 n */
+ 0x41, /* 0x01000001 n */
+ 0x41, /* 0x01000001 n */
+ 0x41, /* 0x01000001 n */
+ 0x00, /* 0x00000000 n */
+ 0x00, /* 0x00000000 n */
+ 0x00, /* 0x00000000 n */
+/* */
+ 0x00, /* 0x00000000 o */
+ 0x00, /* 0x00000000 o */
+ 0x00, /* 0x00000000 o */
+ 0x00, /* 0x00000000 o */
+ 0x00, /* 0x00000000 o */
+ 0x3e, /* 0x00111110 o */
+ 0x41, /* 0x01000001 o */
+ 0x41, /* 0x01000001 o */
+ 0x41, /* 0x01000001 o */
+ 0x41, /* 0x01000001 o */
+ 0x41, /* 0x01000001 o */
+ 0x3e, /* 0x00111110 o */
+ 0x00, /* 0x00000000 o */
+ 0x00, /* 0x00000000 o */
+ 0x00, /* 0x00000000 o */
+/* */
+ 0x00, /* 0x00000000 p */
+ 0x00, /* 0x00000000 p */
+ 0x00, /* 0x00000000 p */
+ 0x00, /* 0x00000000 p */
+ 0x00, /* 0x00000000 p */
+ 0x3d, /* 0x00111101 p */
+ 0x43, /* 0x01000011 p */
+ 0x41, /* 0x01000001 p */
+ 0x41, /* 0x01000001 p */
+ 0x41, /* 0x01000001 p */
+ 0x43, /* 0x01000011 p */
+ 0x3d, /* 0x00111101 p */
+ 0x01, /* 0x00000001 p */
+ 0x01, /* 0x00000001 p */
+ 0x01, /* 0x00000001 p */
+/* */
+ 0x00, /* 0x00000000 q */
+ 0x00, /* 0x00000000 q */
+ 0x00, /* 0x00000000 q */
+ 0x00, /* 0x00000000 q */
+ 0x00, /* 0x00000000 q */
+ 0x5e, /* 0x01011110 q */
+ 0x61, /* 0x01100001 q */
+ 0x41, /* 0x01000001 q */
+ 0x41, /* 0x01000001 q */
+ 0x41, /* 0x01000001 q */
+ 0x61, /* 0x01100001 q */
+ 0x5e, /* 0x01011110 q */
+ 0x40, /* 0x01000000 q */
+ 0x40, /* 0x01000000 q */
+ 0x40, /* 0x01000000 q */
+/* */
+ 0x00, /* 0x00000000 r */
+ 0x00, /* 0x00000000 r */
+ 0x00, /* 0x00000000 r */
+ 0x00, /* 0x00000000 r */
+ 0x00, /* 0x00000000 r */
+ 0x39, /* 0x00111001 r */
+ 0x46, /* 0x01000110 r */
+ 0x42, /* 0x01000010 r */
+ 0x02, /* 0x00000010 r */
+ 0x02, /* 0x00000010 r */
+ 0x02, /* 0x00000010 r */
+ 0x02, /* 0x00000010 r */
+ 0x00, /* 0x00000000 r */
+ 0x00, /* 0x00000000 r */
+ 0x00, /* 0x00000000 r */
+/* */
+ 0x00, /* 0x00000000 s */
+ 0x00, /* 0x00000000 s */
+ 0x00, /* 0x00000000 s */
+ 0x00, /* 0x00000000 s */
+ 0x00, /* 0x00000000 s */
+ 0x3e, /* 0x00111110 s */
+ 0x41, /* 0x01000001 s */
+ 0x01, /* 0x00000001 s */
+ 0x3e, /* 0x00111110 s */
+ 0x40, /* 0x01000000 s */
+ 0x41, /* 0x01000001 s */
+ 0x3e, /* 0x00111110 s */
+ 0x00, /* 0x00000000 s */
+ 0x00, /* 0x00000000 s */
+ 0x00, /* 0x00000000 s */
+/* */
+ 0x00, /* 0x00000000 t */
+ 0x00, /* 0x00000000 t */
+ 0x00, /* 0x00000000 t */
+ 0x04, /* 0x00000100 t */
+ 0x04, /* 0x00000100 t */
+ 0x3f, /* 0x00111111 t */
+ 0x04, /* 0x00000100 t */
+ 0x04, /* 0x00000100 t */
+ 0x04, /* 0x00000100 t */
+ 0x04, /* 0x00000100 t */
+ 0x44, /* 0x01000100 t */
+ 0x38, /* 0x00111000 t */
+ 0x00, /* 0x00000000 t */
+ 0x00, /* 0x00000000 t */
+ 0x00, /* 0x00000000 t */
+/* */
+ 0x00, /* 0x00000000 u */
+ 0x00, /* 0x00000000 u */
+ 0x00, /* 0x00000000 u */
+ 0x00, /* 0x00000000 u */
+ 0x00, /* 0x00000000 u */
+ 0x21, /* 0x00100001 u */
+ 0x21, /* 0x00100001 u */
+ 0x21, /* 0x00100001 u */
+ 0x21, /* 0x00100001 u */
+ 0x21, /* 0x00100001 u */
+ 0x21, /* 0x00100001 u */
+ 0x5e, /* 0x01011110 u */
+ 0x00, /* 0x00000000 u */
+ 0x00, /* 0x00000000 u */
+ 0x00, /* 0x00000000 u */
+/* */
+ 0x00, /* 0x00000000 v */
+ 0x00, /* 0x00000000 v */
+ 0x00, /* 0x00000000 v */
+ 0x00, /* 0x00000000 v */
+ 0x00, /* 0x00000000 v */
+ 0x41, /* 0x01000001 v */
+ 0x41, /* 0x01000001 v */
+ 0x22, /* 0x00100010 v */
+ 0x22, /* 0x00100010 v */
+ 0x14, /* 0x00010100 v */
+ 0x14, /* 0x00010100 v */
+ 0x08, /* 0x00001000 v */
+ 0x00, /* 0x00000000 v */
+ 0x00, /* 0x00000000 v */
+ 0x00, /* 0x00000000 v */
+/* */
+ 0x00, /* 0x00000000 w */
+ 0x00, /* 0x00000000 w */
+ 0x00, /* 0x00000000 w */
+ 0x00, /* 0x00000000 w */
+ 0x00, /* 0x00000000 w */
+ 0x41, /* 0x01000001 w */
+ 0x41, /* 0x01000001 w */
+ 0x49, /* 0x01001001 w */
+ 0x49, /* 0x01001001 w */
+ 0x49, /* 0x01001001 w */
+ 0x55, /* 0x01010101 w */
+ 0x22, /* 0x00100010 w */
+ 0x00, /* 0x00000000 w */
+ 0x00, /* 0x00000000 w */
+ 0x00, /* 0x00000000 w */
+/* */
+ 0x00, /* 0x00000000 x */
+ 0x00, /* 0x00000000 x */
+ 0x00, /* 0x00000000 x */
+ 0x00, /* 0x00000000 x */
+ 0x00, /* 0x00000000 x */
+ 0x41, /* 0x01000001 x */
+ 0x22, /* 0x00100010 x */
+ 0x14, /* 0x00010100 x */
+ 0x08, /* 0x00001000 x */
+ 0x14, /* 0x00010100 x */
+ 0x22, /* 0x00100010 x */
+ 0x41, /* 0x01000001 x */
+ 0x00, /* 0x00000000 x */
+ 0x00, /* 0x00000000 x */
+ 0x00, /* 0x00000000 x */
+/* */
+ 0x00, /* 0x00000000 y */
+ 0x00, /* 0x00000000 y */
+ 0x00, /* 0x00000000 y */
+ 0x00, /* 0x00000000 y */
+ 0x00, /* 0x00000000 y */
+ 0x21, /* 0x00100001 y */
+ 0x21, /* 0x00100001 y */
+ 0x21, /* 0x00100001 y */
+ 0x21, /* 0x00100001 y */
+ 0x21, /* 0x00100001 y */
+ 0x31, /* 0x00110001 y */
+ 0x2e, /* 0x00101110 y */
+ 0x20, /* 0x00100000 y */
+ 0x21, /* 0x00100001 y */
+ 0x1e, /* 0x00011110 y */
+/* */
+ 0x00, /* 0x00000000 z */
+ 0x00, /* 0x00000000 z */
+ 0x00, /* 0x00000000 z */
+ 0x00, /* 0x00000000 z */
+ 0x00, /* 0x00000000 z */
+ 0x7f, /* 0x01111111 z */
+ 0x20, /* 0x00100000 z */
+ 0x10, /* 0x00010000 z */
+ 0x08, /* 0x00001000 z */
+ 0x04, /* 0x00000100 z */
+ 0x02, /* 0x00000010 z */
+ 0x7f, /* 0x01111111 z */
+ 0x00, /* 0x00000000 z */
+ 0x00, /* 0x00000000 z */
+ 0x00, /* 0x00000000 z */
+/* */
+ 0x00, /* 0x00000000 { */
+ 0x00, /* 0x00000000 { */
+ 0x70, /* 0x01110000 { */
+ 0x08, /* 0x00001000 { */
+ 0x08, /* 0x00001000 { */
+ 0x10, /* 0x00010000 { */
+ 0x0c, /* 0x00001100 { */
+ 0x0c, /* 0x00001100 { */
+ 0x10, /* 0x00010000 { */
+ 0x08, /* 0x00001000 { */
+ 0x08, /* 0x00001000 { */
+ 0x70, /* 0x01110000 { */
+ 0x00, /* 0x00000000 { */
+ 0x00, /* 0x00000000 { */
+ 0x00, /* 0x00000000 { */
+/* */
+ 0x00, /* 0x00000000 | */
+ 0x00, /* 0x00000000 | */
+ 0x08, /* 0x00001000 | */
+ 0x08, /* 0x00001000 | */
+ 0x08, /* 0x00001000 | */
+ 0x08, /* 0x00001000 | */
+ 0x08, /* 0x00001000 | */
+ 0x08, /* 0x00001000 | */
+ 0x08, /* 0x00001000 | */
+ 0x08, /* 0x00001000 | */
+ 0x08, /* 0x00001000 | */
+ 0x08, /* 0x00001000 | */
+ 0x00, /* 0x00000000 | */
+ 0x00, /* 0x00000000 | */
+ 0x00, /* 0x00000000 | */
+/* */
+ 0x00, /* 0x00000000 } */
+ 0x00, /* 0x00000000 } */
+ 0x07, /* 0x00000111 } */
+ 0x08, /* 0x00001000 } */
+ 0x08, /* 0x00001000 } */
+ 0x04, /* 0x00000100 } */
+ 0x18, /* 0x00011000 } */
+ 0x18, /* 0x00011000 } */
+ 0x04, /* 0x00000100 } */
+ 0x08, /* 0x00001000 } */
+ 0x08, /* 0x00001000 } */
+ 0x07, /* 0x00000111 } */
+ 0x00, /* 0x00000000 } */
+ 0x00, /* 0x00000000 } */
+ 0x00, /* 0x00000000 } */
+/* */
+ 0x00, /* 0x00000000 ~ */
+ 0x00, /* 0x00000000 ~ */
+ 0x46, /* 0x01000110 ~ */
+ 0x49, /* 0x01001001 ~ */
+ 0x31, /* 0x00110001 ~ */
+ 0x00, /* 0x00000000 ~ */
+ 0x00, /* 0x00000000 ~ */
+ 0x00, /* 0x00000000 ~ */
+ 0x00, /* 0x00000000 ~ */
+ 0x00, /* 0x00000000 ~ */
+ 0x00, /* 0x00000000 ~ */
+ 0x00, /* 0x00000000 ~ */
+ 0x00, /* 0x00000000 ~ */
+ 0x00, /* 0x00000000 ~ */
+ 0x00, /* 0x00000000 ~ */
+/* */
+/* ascii0241 */
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x10,
+ 0x00,
+ 0x10,
+ 0x10,
+ 0x10,
+ 0x10,
+ 0x10,
+ 0x10,
+ 0x10,
+ 0x10,
+ 0x00,
+ 0x00,
+/* ascii0242 */
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x10,
+ 0x10,
+ 0x3c,
+ 0x42,
+ 0x02,
+ 0x02,
+ 0x42,
+ 0x3c,
+ 0x10,
+ 0x10,
+ 0x00,
+/* ascii0243 */
+ 0x00,
+ 0x00,
+ 0x70,
+ 0x88,
+ 0x08,
+ 0x08,
+ 0x08,
+ 0x3e,
+ 0x08,
+ 0x08,
+ 0x08,
+ 0xdc,
+ 0x76,
+ 0x00,
+ 0x00,
+/* ascii0244 */
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x3c,
+ 0x42,
+ 0x42,
+ 0x02,
+ 0x04,
+ 0x08,
+ 0x10,
+ 0x10,
+ 0x00,
+ 0x10,
+ 0x00,
+ 0x00,
+/* ascii0245 */
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x44,
+ 0x44,
+ 0x44,
+ 0x28,
+ 0x10,
+ 0x7c,
+ 0x10,
+ 0x7c,
+ 0x10,
+ 0x10,
+ 0x00,
+ 0x00,
+/* ascii0246 */
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x3c,
+ 0x42,
+ 0x42,
+ 0x02,
+ 0x04,
+ 0x08,
+ 0x10,
+ 0x10,
+ 0x00,
+ 0x10,
+ 0x00,
+ 0x00,
+/* ascii0247 */
+ 0x00,
+ 0x1c,
+ 0x22,
+ 0x02,
+ 0x04,
+ 0x1c,
+ 0x22,
+ 0x22,
+ 0x1c,
+ 0x10,
+ 0x20,
+ 0x22,
+ 0x1c,
+ 0x00,
+ 0x00,
+/* ascii0250 */
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x82,
+ 0x44,
+ 0x38,
+ 0x44,
+ 0x44,
+ 0x44,
+ 0x38,
+ 0x44,
+ 0x82,
+ 0x00,
+ 0x00,
+/* ascii0251 */
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x7c,
+ 0x82,
+ 0xb2,
+ 0x8a,
+ 0x8a,
+ 0xb2,
+ 0x82,
+ 0x7c,
+ 0x00,
+ 0x00,
+/* ascii0252 */
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x3c,
+ 0x40,
+ 0x7c,
+ 0x42,
+ 0x42,
+ 0x7c,
+ 0x00,
+ 0x7c,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+/* ascii0253 */
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x48,
+ 0x24,
+ 0x12,
+ 0x09,
+ 0x12,
+ 0x24,
+ 0x48,
+ 0x00,
+ 0x00,
+ 0x00,
+/* ascii0254 */
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x3c,
+ 0x42,
+ 0x42,
+ 0x02,
+ 0x04,
+ 0x08,
+ 0x10,
+ 0x10,
+ 0x00,
+ 0x10,
+ 0x00,
+ 0x00,
+/* ascii0255 */
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x3c,
+ 0x42,
+ 0x42,
+ 0x02,
+ 0x04,
+ 0x08,
+ 0x10,
+ 0x10,
+ 0x00,
+ 0x10,
+ 0x00,
+ 0x00,
+/* ascii0256 */
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x3c,
+ 0x42,
+ 0x42,
+ 0x02,
+ 0x04,
+ 0x08,
+ 0x10,
+ 0x10,
+ 0x00,
+ 0x10,
+ 0x00,
+ 0x00,
+/* ascii0257 */
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x3c,
+ 0x42,
+ 0x42,
+ 0x02,
+ 0x04,
+ 0x08,
+ 0x10,
+ 0x10,
+ 0x00,
+ 0x10,
+ 0x00,
+ 0x00,
+/* ascii0260 */
+ 0x00,
+ 0x18,
+ 0x24,
+ 0x24,
+ 0x18,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+/* ascii0261 */
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x08,
+ 0x08,
+ 0x08,
+ 0x3e,
+ 0x08,
+ 0x08,
+ 0x08,
+ 0x00,
+ 0x3e,
+ 0x00,
+ 0x00,
+ 0x00,
+/* ascii0262 */
+ 0x00,
+ 0x00,
+ 0x0c,
+ 0x12,
+ 0x08,
+ 0x04,
+ 0x02,
+ 0x1e,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+/* ascii0263 */
+ 0x00,
+ 0x00,
+ 0x1e,
+ 0x10,
+ 0x08,
+ 0x10,
+ 0x12,
+ 0x0c,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+/* ascii0264 */
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x3c,
+ 0x42,
+ 0x42,
+ 0x02,
+ 0x04,
+ 0x08,
+ 0x10,
+ 0x10,
+ 0x00,
+ 0x10,
+ 0x00,
+ 0x00,
+/* ascii0265 */
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x44,
+ 0x44,
+ 0x44,
+ 0x44,
+ 0x44,
+ 0x7c,
+ 0xc2,
+ 0x01,
+/* ascii0266 */
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x7c,
+ 0x4e,
+ 0x4e,
+ 0x4e,
+ 0x4e,
+ 0x7c,
+ 0x48,
+ 0x48,
+ 0x48,
+ 0x48,
+ 0x00,
+ 0x00,
+/* ascii0267 */
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x18,
+ 0x18,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+/* ascii0270 */
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x3c,
+ 0x42,
+ 0x42,
+ 0x02,
+ 0x04,
+ 0x08,
+ 0x10,
+ 0x10,
+ 0x00,
+ 0x10,
+ 0x00,
+ 0x00,
+/* ascii0271 */
+ 0x00,
+ 0x00,
+ 0x08,
+ 0x0c,
+ 0x08,
+ 0x08,
+ 0x08,
+ 0x1c,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+/* ascii0272 */
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x3c,
+ 0x42,
+ 0x42,
+ 0x42,
+ 0x42,
+ 0x3c,
+ 0x00,
+ 0x3c,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+/* ascii0273 */
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x12,
+ 0x24,
+ 0x48,
+ 0x90,
+ 0x48,
+ 0x24,
+ 0x12,
+ 0x00,
+ 0x00,
+/* ascii0274 */
+ 0x00,
+ 0x04,
+ 0x06,
+ 0x04,
+ 0x04,
+ 0x4e,
+ 0x20,
+ 0x10,
+ 0x48,
+ 0x64,
+ 0x52,
+ 0xf8,
+ 0x40,
+ 0x40,
+ 0x00,
+/* ascii0275 */
+ 0x00,
+ 0x04,
+ 0x06,
+ 0x04,
+ 0x04,
+ 0x4e,
+ 0x20,
+ 0x10,
+ 0x08,
+ 0x74,
+ 0x82,
+ 0x60,
+ 0x10,
+ 0xf0,
+ 0x00,
+/* ascii0276 */
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x3c,
+ 0x42,
+ 0x42,
+ 0x02,
+ 0x04,
+ 0x08,
+ 0x10,
+ 0x10,
+ 0x00,
+ 0x10,
+ 0x00,
+ 0x00,
+/* ascii0277 */
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x10,
+ 0x00,
+ 0x10,
+ 0x10,
+ 0x08,
+ 0x04,
+ 0x02,
+ 0x42,
+ 0x42,
+ 0x3c,
+ 0x00,
+ 0x00,
+/* ascii0300 */
+ 0x00,
+ 0x08,
+ 0x10,
+ 0x20,
+ 0x18,
+ 0x24,
+ 0x42,
+ 0x42,
+ 0x42,
+ 0x7e,
+ 0x42,
+ 0x42,
+ 0x42,
+ 0x00,
+ 0x00,
+/* ascii0301 */
+ 0x00,
+ 0x10,
+ 0x08,
+ 0x04,
+ 0x18,
+ 0x24,
+ 0x42,
+ 0x42,
+ 0x42,
+ 0x7e,
+ 0x42,
+ 0x42,
+ 0x42,
+ 0x00,
+ 0x00,
+/* ascii0302 */
+ 0x00,
+ 0x18,
+ 0x24,
+ 0x42,
+ 0x18,
+ 0x24,
+ 0x42,
+ 0x42,
+ 0x42,
+ 0x7e,
+ 0x42,
+ 0x42,
+ 0x42,
+ 0x00,
+ 0x00,
+/* ascii0303 */
+ 0x00,
+ 0x4c,
+ 0x32,
+ 0x00,
+ 0x18,
+ 0x24,
+ 0x42,
+ 0x42,
+ 0x42,
+ 0x7e,
+ 0x42,
+ 0x42,
+ 0x42,
+ 0x00,
+ 0x00,
+/* ascii0304 */
+ 0x00,
+ 0x00,
+ 0x66,
+ 0x00,
+ 0x18,
+ 0x24,
+ 0x42,
+ 0x42,
+ 0x42,
+ 0x7e,
+ 0x42,
+ 0x42,
+ 0x42,
+ 0x00,
+ 0x00,
+/* ascii0305 */
+ 0x18,
+ 0x24,
+ 0x18,
+ 0x00,
+ 0x18,
+ 0x24,
+ 0x42,
+ 0x42,
+ 0x42,
+ 0x7e,
+ 0x42,
+ 0x42,
+ 0x42,
+ 0x00,
+ 0x00,
+/* ascii0306 */
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0xf8,
+ 0x14,
+ 0x12,
+ 0x12,
+ 0x7e,
+ 0x12,
+ 0x12,
+ 0x12,
+ 0xf2,
+ 0x00,
+ 0x00,
+/* ascii0307 */
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x3c,
+ 0x42,
+ 0x02,
+ 0x02,
+ 0x02,
+ 0x02,
+ 0x02,
+ 0x42,
+ 0x3c,
+ 0x10,
+ 0x0c,
+/* ascii0310 */
+ 0x08,
+ 0x10,
+ 0x20,
+ 0x00,
+ 0x7e,
+ 0x02,
+ 0x02,
+ 0x02,
+ 0x1e,
+ 0x02,
+ 0x02,
+ 0x02,
+ 0x7e,
+ 0x00,
+ 0x00,
+/* ascii0311 */
+ 0x10,
+ 0x08,
+ 0x04,
+ 0x00,
+ 0x7e,
+ 0x02,
+ 0x02,
+ 0x02,
+ 0x1e,
+ 0x02,
+ 0x02,
+ 0x02,
+ 0x7e,
+ 0x00,
+ 0x00,
+/* ascii0312 */
+ 0x18,
+ 0x24,
+ 0x42,
+ 0x00,
+ 0x7e,
+ 0x02,
+ 0x02,
+ 0x02,
+ 0x1e,
+ 0x02,
+ 0x02,
+ 0x02,
+ 0x7e,
+ 0x00,
+ 0x00,
+/* ascii0313 */
+ 0x00,
+ 0x66,
+ 0x00,
+ 0x00,
+ 0x7e,
+ 0x02,
+ 0x02,
+ 0x02,
+ 0x1e,
+ 0x02,
+ 0x02,
+ 0x02,
+ 0x7e,
+ 0x00,
+ 0x00,
+/* ascii0314 */
+ 0x08,
+ 0x10,
+ 0x20,
+ 0x00,
+ 0x3c,
+ 0x08,
+ 0x08,
+ 0x08,
+ 0x08,
+ 0x08,
+ 0x08,
+ 0x08,
+ 0x3c,
+ 0x00,
+ 0x00,
+/* ascii0315 */
+ 0x40,
+ 0x20,
+ 0x10,
+ 0x00,
+ 0x3c,
+ 0x08,
+ 0x08,
+ 0x08,
+ 0x08,
+ 0x08,
+ 0x08,
+ 0x08,
+ 0x3c,
+ 0x00,
+ 0x00,
+/* ascii0316 */
+ 0x18,
+ 0x24,
+ 0x42,
+ 0x00,
+ 0x3c,
+ 0x08,
+ 0x08,
+ 0x08,
+ 0x08,
+ 0x08,
+ 0x08,
+ 0x08,
+ 0x3c,
+ 0x00,
+ 0x00,
+/* ascii0317 */
+ 0x00,
+ 0x66,
+ 0x00,
+ 0x00,
+ 0x3c,
+ 0x08,
+ 0x08,
+ 0x08,
+ 0x08,
+ 0x08,
+ 0x08,
+ 0x08,
+ 0x3c,
+ 0x00,
+ 0x00,
+/* ascii0320 */
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x3c,
+ 0x42,
+ 0x42,
+ 0x02,
+ 0x04,
+ 0x08,
+ 0x10,
+ 0x10,
+ 0x00,
+ 0x10,
+ 0x00,
+ 0x00,
+/* ascii0321 */
+ 0x00,
+ 0x4c,
+ 0x32,
+ 0x00,
+ 0x42,
+ 0x42,
+ 0x46,
+ 0x4a,
+ 0x52,
+ 0x62,
+ 0x42,
+ 0x42,
+ 0x42,
+ 0x00,
+ 0x00,
+/* ascii0322 */
+ 0x08,
+ 0x10,
+ 0x20,
+ 0x00,
+ 0x3c,
+ 0x42,
+ 0x42,
+ 0x42,
+ 0x42,
+ 0x42,
+ 0x42,
+ 0x42,
+ 0x3c,
+ 0x00,
+ 0x00,
+/* ascii0323 */
+ 0x10,
+ 0x08,
+ 0x04,
+ 0x00,
+ 0x3c,
+ 0x42,
+ 0x42,
+ 0x42,
+ 0x42,
+ 0x42,
+ 0x42,
+ 0x42,
+ 0x3c,
+ 0x00,
+ 0x00,
+/* ascii0324 */
+ 0x18,
+ 0x24,
+ 0x42,
+ 0x00,
+ 0x3c,
+ 0x42,
+ 0x42,
+ 0x42,
+ 0x42,
+ 0x42,
+ 0x42,
+ 0x42,
+ 0x3c,
+ 0x00,
+ 0x00,
+/* ascii0325 */
+ 0x00,
+ 0x4c,
+ 0x32,
+ 0x00,
+ 0x3c,
+ 0x42,
+ 0x42,
+ 0x42,
+ 0x42,
+ 0x42,
+ 0x42,
+ 0x42,
+ 0x3c,
+ 0x00,
+ 0x00,
+/* ascii0326 */
+ 0x00,
+ 0x66,
+ 0x00,
+ 0x00,
+ 0x3c,
+ 0x42,
+ 0x42,
+ 0x42,
+ 0x42,
+ 0x42,
+ 0x42,
+ 0x42,
+ 0x3c,
+ 0x00,
+ 0x00,
+/* ascii0327 */
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0xfc,
+ 0x12,
+ 0x12,
+ 0x12,
+ 0x72,
+ 0x12,
+ 0x12,
+ 0x12,
+ 0xfc,
+ 0x00,
+ 0x00,
+/* ascii0330 */
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0xbc,
+ 0x42,
+ 0x62,
+ 0x52,
+ 0x52,
+ 0x4a,
+ 0x46,
+ 0x42,
+ 0x3d,
+ 0x00,
+ 0x00,
+/* ascii0331 */
+ 0x00,
+ 0x04,
+ 0x08,
+ 0x10,
+ 0x42,
+ 0x42,
+ 0x42,
+ 0x42,
+ 0x42,
+ 0x42,
+ 0x42,
+ 0x42,
+ 0x3c,
+ 0x00,
+ 0x00,
+/* ascii0332 */
+ 0x00,
+ 0x20,
+ 0x10,
+ 0x08,
+ 0x42,
+ 0x42,
+ 0x42,
+ 0x42,
+ 0x42,
+ 0x42,
+ 0x42,
+ 0x42,
+ 0x3c,
+ 0x00,
+ 0x00,
+/* ascii0333 */
+ 0x00,
+ 0x18,
+ 0x24,
+ 0x42,
+ 0x00,
+ 0x42,
+ 0x42,
+ 0x42,
+ 0x42,
+ 0x42,
+ 0x42,
+ 0x42,
+ 0x3c,
+ 0x00,
+ 0x00,
+/* ascii0334 */
+ 0x00,
+ 0x66,
+ 0x00,
+ 0x00,
+ 0x42,
+ 0x42,
+ 0x42,
+ 0x42,
+ 0x42,
+ 0x42,
+ 0x42,
+ 0x42,
+ 0x3c,
+ 0x00,
+ 0x00,
+/* ascii0335 */
+ 0x00,
+ 0xc6,
+ 0x00,
+ 0x00,
+ 0x82,
+ 0x82,
+ 0x44,
+ 0x28,
+ 0x10,
+ 0x10,
+ 0x10,
+ 0x10,
+ 0x10,
+ 0x00,
+ 0x00,
+/* ascii0336 */
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x3c,
+ 0x42,
+ 0x42,
+ 0x02,
+ 0x04,
+ 0x08,
+ 0x10,
+ 0x10,
+ 0x00,
+ 0x10,
+ 0x00,
+ 0x00,
+/* ascii0337 */
+ 0x00,
+ 0x00,
+ 0x70,
+ 0x88,
+ 0x84,
+ 0x84,
+ 0x44,
+ 0x74,
+ 0x84,
+ 0x84,
+ 0x84,
+ 0x94,
+ 0x74,
+ 0x04,
+ 0x02,
+/* ascii0340 */
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x08,
+ 0x10,
+ 0x20,
+ 0x00,
+ 0x3c,
+ 0x40,
+ 0x7c,
+ 0x42,
+ 0x42,
+ 0x7c,
+ 0x00,
+ 0x00,
+/* ascii0341 */
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x10,
+ 0x08,
+ 0x04,
+ 0x00,
+ 0x3c,
+ 0x40,
+ 0x7c,
+ 0x42,
+ 0x42,
+ 0x7c,
+ 0x00,
+ 0x00,
+/* ascii0342 */
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x18,
+ 0x24,
+ 0x42,
+ 0x00,
+ 0x3c,
+ 0x40,
+ 0x7c,
+ 0x42,
+ 0x42,
+ 0x7c,
+ 0x00,
+ 0x00,
+/* ascii0343 */
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x4c,
+ 0x32,
+ 0x00,
+ 0x3c,
+ 0x40,
+ 0x7c,
+ 0x42,
+ 0x42,
+ 0x7c,
+ 0x00,
+ 0x00,
+/* ascii0344 */
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x66,
+ 0x00,
+ 0x00,
+ 0x3c,
+ 0x40,
+ 0x7c,
+ 0x42,
+ 0x42,
+ 0x7c,
+ 0x00,
+ 0x00,
+/* ascii0345 */
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x18,
+ 0x24,
+ 0x18,
+ 0x00,
+ 0x3c,
+ 0x40,
+ 0x7c,
+ 0x42,
+ 0x42,
+ 0x7c,
+ 0x00,
+ 0x00,
+/* ascii0346 */
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x6e,
+ 0x90,
+ 0xfc,
+ 0x12,
+ 0x12,
+ 0xec,
+ 0x00,
+ 0x00,
+/* ascii0347 */
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x3c,
+ 0x42,
+ 0x02,
+ 0x02,
+ 0x42,
+ 0x3c,
+ 0x10,
+ 0x0c,
+/* ascii0350 */
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x08,
+ 0x10,
+ 0x20,
+ 0x00,
+ 0x3c,
+ 0x42,
+ 0x7e,
+ 0x02,
+ 0x02,
+ 0x3c,
+ 0x00,
+ 0x00,
+/* ascii0351 */
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x10,
+ 0x08,
+ 0x04,
+ 0x00,
+ 0x3c,
+ 0x42,
+ 0x7e,
+ 0x02,
+ 0x02,
+ 0x3c,
+ 0x00,
+ 0x00,
+/* ascii0352 */
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x18,
+ 0x24,
+ 0x42,
+ 0x00,
+ 0x3c,
+ 0x42,
+ 0x7e,
+ 0x02,
+ 0x02,
+ 0x3c,
+ 0x00,
+ 0x00,
+/* ascii0353 */
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x66,
+ 0x00,
+ 0x00,
+ 0x3c,
+ 0x42,
+ 0x7e,
+ 0x02,
+ 0x02,
+ 0x3c,
+ 0x00,
+ 0x00,
+/* ascii0354 */
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x04,
+ 0x08,
+ 0x10,
+ 0x00,
+ 0x08,
+ 0x08,
+ 0x08,
+ 0x08,
+ 0x08,
+ 0x3c,
+ 0x00,
+ 0x00,
+/* ascii0355 */
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x10,
+ 0x08,
+ 0x04,
+ 0x00,
+ 0x08,
+ 0x08,
+ 0x08,
+ 0x08,
+ 0x08,
+ 0x3c,
+ 0x00,
+ 0x00,
+/* ascii0356 */
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x18,
+ 0x24,
+ 0x42,
+ 0x00,
+ 0x08,
+ 0x08,
+ 0x08,
+ 0x08,
+ 0x08,
+ 0x3c,
+ 0x00,
+ 0x00,
+/* ascii0357 */
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x66,
+ 0x00,
+ 0x00,
+ 0x08,
+ 0x08,
+ 0x08,
+ 0x08,
+ 0x08,
+ 0x3c,
+ 0x00,
+ 0x00,
+/* ascii0360 */
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x3c,
+ 0x42,
+ 0x42,
+ 0x02,
+ 0x04,
+ 0x08,
+ 0x10,
+ 0x10,
+ 0x00,
+ 0x10,
+ 0x00,
+ 0x00,
+/* ascii0361 */
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x4c,
+ 0x32,
+ 0x00,
+ 0x00,
+ 0x3e,
+ 0x42,
+ 0x42,
+ 0x42,
+ 0x42,
+ 0x42,
+ 0x00,
+ 0x00,
+/* ascii0362 */
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x08,
+ 0x10,
+ 0x20,
+ 0x00,
+ 0x3c,
+ 0x42,
+ 0x42,
+ 0x42,
+ 0x42,
+ 0x3c,
+ 0x00,
+ 0x00,
+/* ascii0363 */
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x10,
+ 0x08,
+ 0x04,
+ 0x00,
+ 0x3c,
+ 0x42,
+ 0x42,
+ 0x42,
+ 0x42,
+ 0x3c,
+ 0x00,
+ 0x00,
+/* ascii0364 */
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x18,
+ 0x24,
+ 0x42,
+ 0x00,
+ 0x3c,
+ 0x42,
+ 0x42,
+ 0x42,
+ 0x42,
+ 0x3c,
+ 0x00,
+ 0x00,
+/* ascii0365 */
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x4c,
+ 0x32,
+ 0x00,
+ 0x00,
+ 0x3c,
+ 0x42,
+ 0x42,
+ 0x42,
+ 0x42,
+ 0x3c,
+ 0x00,
+ 0x00,
+/* ascii0366 */
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x66,
+ 0x00,
+ 0x00,
+ 0x3c,
+ 0x42,
+ 0x42,
+ 0x42,
+ 0x42,
+ 0x3c,
+ 0x00,
+ 0x00,
+/* ascii0367 */
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x6c,
+ 0x92,
+ 0xf2,
+ 0x12,
+ 0x12,
+ 0xec,
+ 0x00,
+ 0x00,
+/* ascii0370 */
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0xbc,
+ 0x62,
+ 0x52,
+ 0x4a,
+ 0x46,
+ 0x3c,
+ 0x02,
+ 0x00,
+/* ascii0371 */
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x04,
+ 0x08,
+ 0x10,
+ 0x00,
+ 0x42,
+ 0x42,
+ 0x42,
+ 0x42,
+ 0x42,
+ 0x3c,
+ 0x00,
+ 0x00,
+/* ascii0372 */
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x20,
+ 0x10,
+ 0x08,
+ 0x00,
+ 0x42,
+ 0x42,
+ 0x42,
+ 0x42,
+ 0x42,
+ 0x3c,
+ 0x00,
+ 0x00,
+/* ascii0373 */
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x18,
+ 0x24,
+ 0x42,
+ 0x00,
+ 0x42,
+ 0x42,
+ 0x42,
+ 0x42,
+ 0x42,
+ 0x3c,
+ 0x00,
+ 0x00,
+/* ascii0374 */
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x66,
+ 0x00,
+ 0x00,
+ 0x42,
+ 0x42,
+ 0x42,
+ 0x42,
+ 0x42,
+ 0x3c,
+ 0x00,
+ 0x00,
+/* ascii0375 */
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x66,
+ 0x00,
+ 0x00,
+ 0x42,
+ 0x42,
+ 0x42,
+ 0x42,
+ 0x3c,
+ 0x40,
+ 0x40,
+ 0x3e,
+/* ascii0376 */
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x3c,
+ 0x42,
+ 0x42,
+ 0x02,
+ 0x04,
+ 0x08,
+ 0x10,
+ 0x10,
+ 0x00,
+ 0x10,
+ 0x00,
+ 0x00,
+/* ascii0377 */
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x3c,
+ 0x42,
+ 0x42,
+ 0x02,
+ 0x04,
+ 0x08,
+ 0x10,
+ 0x10,
+ 0x00,
+ 0x10,
+ 0x00,
+ 0x00,
+
+};
+
+/*
+ * Default Cursor
+ */
+unsigned short q_cursor[] = {
+ 0x0000,
+ 0x0000,
+ 0x00ff,
+ 0x00ff,
+ 0x00ff,
+ 0x00ff,
+ 0x00ff,
+ 0x00ff,
+ 0x00ff,
+ 0x00ff,
+ 0x00ff,
+ 0x00ff,
+ 0x00ff,
+ 0x0000,
+ 0x0000,
+ 0x0000
+};
+
diff --git a/sys/arch/vax/qbus/uba.c b/sys/arch/vax/qbus/uba.c
new file mode 100644
index 00000000000..13844d68105
--- /dev/null
+++ b/sys/arch/vax/qbus/uba.c
@@ -0,0 +1,264 @@
+/* $OpenBSD: uba.c,v 1.1 2000/04/27 03:14:49 bjc Exp $ */
+/* $NetBSD: uba.c,v 1.49 2000/01/24 02:40:30 matt 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.
+ * 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.
+ *
+ * @(#)uba.c 7.10 (Berkeley) 12/16/90
+ * @(#)autoconf.c 7.20 (Berkeley) 5/9/91
+ */
+
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/systm.h>
+#include <sys/map.h>
+#include <sys/buf.h>
+#include <sys/proc.h>
+#include <sys/user.h>
+#include <sys/conf.h>
+#include <sys/dkstat.h>
+#include <sys/kernel.h>
+#include <sys/malloc.h>
+#include <sys/device.h>
+
+#include <vm/vm.h>
+#include <vm/vm_kern.h>
+
+#include <machine/bus.h>
+#include <machine/scb.h>
+#include <machine/cpu.h>
+
+#include <arch/vax/qbus/ubavar.h>
+
+static int ubasearch __P((struct device *, struct cfdata *, void *));
+static int ubaprint __P((void *, const char *));
+
+struct cfdriver uba_cd = {
+ NULL, "uba", DV_DULL
+};
+
+/*
+ * If we failed to allocate uba resources, put us on a queue to wait
+ * until there is available resources. Resources to compete about
+ * are map registers and BDPs. This is normally only a problem on
+ * Unibus systems, Qbus systems have more map registers than usable.
+ */
+void
+uba_enqueue(uu)
+ struct uba_unit *uu;
+{
+ struct uba_softc *uh;
+ int s;
+
+ uh = (void *)((struct device *)(uu->uu_softc))->dv_parent;
+
+ s = splimp();
+ SIMPLEQ_INSERT_TAIL(&uh->uh_resq, uu, uu_resq);
+ splx(s);
+}
+
+/*
+ * When a routine that uses resources is finished, the next device
+ * in queue for map registers etc is called. If it succeeds to get
+ * resources, call next, and next, and next...
+ * This routine must be called at splimp.
+ */
+void
+uba_done(uh)
+ struct uba_softc *uh;
+{
+ struct uba_unit *uu;
+
+ while ((uu = SIMPLEQ_FIRST(&uh->uh_resq))) {
+ SIMPLEQ_REMOVE_HEAD(&uh->uh_resq, uu, uu_resq);
+ if ((*uu->uu_ready)(uu) == 0) {
+ SIMPLEQ_INSERT_HEAD(&uh->uh_resq, uu, uu_resq);
+ break;
+ }
+ }
+}
+
+/*
+ * 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.
+ */
+void
+ubareset(uban)
+ int uban;
+{
+ register struct uba_softc *uh = uba_cd.cd_devs[uban];
+ int s, i;
+
+ s = splimp();
+ SIMPLEQ_INIT(&uh->uh_resq);
+ printf("%s: reset", uh->uh_dev.dv_xname);
+ (*uh->uh_ubainit)(uh);
+
+ for (i = 0; i < uh->uh_resno; i++)
+ (*uh->uh_reset[i])(uh->uh_resarg[i]);
+ printf("\n");
+ splx(s);
+}
+
+/*
+ * The common attach routine:
+ * Calls the scan routine to search for uba devices.
+ */
+void
+uba_attach(sc, iopagephys)
+ struct uba_softc *sc;
+ paddr_t iopagephys;
+{
+
+ /*
+ * 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;
+ SIMPLEQ_INIT(&sc->uh_resq);
+
+ /*
+ * Allocate place for unibus I/O space in virtual space.
+ */
+ if (bus_space_map(sc->uh_iot, iopagephys, UBAIOSIZE, 0, &sc->uh_ioh))
+ return;
+
+ if (sc->uh_beforescan)
+ (*sc->uh_beforescan)(sc);
+ /*
+ * Now start searching for devices.
+ */
+ config_search((cfmatch_t)ubasearch,(struct device *)sc, NULL);
+
+ if (sc->uh_afterscan)
+ (*sc->uh_afterscan)(sc);
+}
+
+int
+ubasearch(parent, cf, aux)
+ struct device *parent;
+ struct cfdata *cf;
+ void *aux;
+{
+ struct uba_softc *sc = (struct uba_softc *)parent;
+ struct uba_attach_args ua;
+ int i, vec, br;
+
+ ua.ua_ioh = ubdevreg(cf->cf_loc[0]) + sc->uh_ioh;
+ ua.ua_iot = sc->uh_iot;
+ ua.ua_dmat = sc->uh_dmat;
+ ua.ua_reset = NULL;
+
+ if (badaddr((caddr_t)ua.ua_ioh, 2) ||
+ (sc->uh_errchk ? (*sc->uh_errchk)(sc):0))
+ goto forgetit;
+
+ scb_vecref(0, 0); /* Clear vector ref */
+ i = (*cf->cf_attach->ca_match) (parent, cf, &ua);
+
+ if (sc->uh_errchk)
+ if ((*sc->uh_errchk)(sc))
+ goto forgetit;
+ if (i == 0)
+ goto forgetit;
+
+ i = scb_vecref(&vec, &br);
+ if (i == 0)
+ goto fail;
+ if (vec == 0)
+ goto fail;
+
+ if (ua.ua_reset) { /* device wants ubareset */
+ if (sc->uh_resno == 0) {
+#define RESETSIXE 128
+ sc->uh_reset = malloc(sizeof(void *) * RESETSIXE,
+ M_DEVBUF, M_NOWAIT);
+ sc->uh_resarg = malloc(sizeof(void *) * RESETSIXE,
+ M_DEVBUF, M_NOWAIT);
+ }
+ if (sc->uh_resno < RESETSIXE) {
+ sc->uh_resarg[sc->uh_resno] = cf->cf_unit;
+ sc->uh_reset[sc->uh_resno++] = ua.ua_reset;
+ } else {
+ printf("%s: Expand reset table, skipping reset %s%d\n",
+ sc->uh_dev.dv_xname, cf->cf_driver->cd_name,
+ cf->cf_unit);
+ }
+ }
+
+ ua.ua_br = br;
+ ua.ua_cvec = vec;
+ ua.ua_iaddr = cf->cf_loc[0];
+
+ config_attach(parent, cf, &ua, ubaprint);
+ return 0;
+
+fail:
+ printf("%s%d at %s csr %o %s\n",
+ cf->cf_driver->cd_name, cf->cf_unit, parent->dv_xname,
+ cf->cf_loc[0], (i ? "zero vector" : "didn't interrupt"));
+
+forgetit:
+ return 0;
+}
+
+/*
+ * Print out some interesting info common to all unibus devices.
+ */
+int
+ubaprint(aux, uba)
+ void *aux;
+ const char *uba;
+{
+ struct uba_attach_args *ua = aux;
+
+ printf(" csr %o vec %o ipl %x", ua->ua_iaddr,
+ ua->ua_cvec & 511, ua->ua_br);
+ return UNCONF;
+}
+
+/*
+ * Move to machdep eventually
+ */
+void
+uba_intr_establish(icookie, vec, ifunc, iarg)
+ void *icookie;
+ int vec;
+ void (*ifunc)(void *iarg);
+ void *iarg;
+{
+ scb_vecalloc(vec, ifunc, iarg, SCB_ISTACK);
+}
diff --git a/sys/arch/vax/qbus/ubavar.h b/sys/arch/vax/qbus/ubavar.h
new file mode 100644
index 00000000000..942b8eb7af7
--- /dev/null
+++ b/sys/arch/vax/qbus/ubavar.h
@@ -0,0 +1,148 @@
+/* $OpenBSD: ubavar.h,v 1.1 2000/04/27 03:14:49 bjc Exp $ */
+/* $NetBSD: ubavar.h,v 1.26 2000/01/24 02:40:30 matt Exp $ */
+
+/*
+ * Copyright (c) 1982, 1986 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.
+ *
+ * @(#)ubavar.h 7.7 (Berkeley) 6/28/90
+ */
+#ifndef _QBUS_UBAVAR_H
+#define _QBUS_UBAVAR_H
+
+/*
+ * This file contains definitions related to the kernel structures
+ * for dealing with the unibus adapters.
+ *
+ * Each uba has a uba_softc structure.
+ * Each unibus controller which is not a device has a uba_ctlr structure.
+ * Each unibus device has a uba_device structure.
+ */
+
+/*
+ * Per-uba structure.
+ *
+ * This structure holds the interrupt vector for the uba,
+ * and its address in physical and virtual space. At boot time
+ * we determine the devices attached to the uba's and their
+ * interrupt vectors, filling in uh_vec. We free the map
+ * register and bdp resources of the uba into the structures
+ * defined here.
+ *
+ * During normal operation, resources are allocated and returned
+ * to the structures here. We watch the number of passive releases
+ * on each uba, and if the number is excessive may reset the uba.
+ *
+ * When uba resources are needed and not available, or if a device
+ * which can tolerate no other uba activity (rk07) gets on the bus,
+ * then device drivers may have to wait to get to the bus and are
+ * queued here. It is also possible for processes to block in
+ * the unibus driver in resource wait (mrwant, bdpwant); these
+ * wait states are also recorded here.
+ */
+struct uba_softc {
+ struct device uh_dev; /* Device struct, autoconfig */
+ SIMPLEQ_HEAD(, uba_unit) uh_resq; /* resource wait chain */
+ void (**uh_reset) __P((int));/* UBA reset function array */
+ int *uh_resarg; /* array of ubareset args */
+ int uh_resno; /* Number of devices to reset */
+ int uh_lastiv; /* last free interrupt vector */
+ 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));
+ short uh_nr; /* Unibus sequential number */
+ bus_space_tag_t uh_iot; /* Tag for this Unibus */
+ bus_space_handle_t uh_ioh; /* Handle for I/O space */
+ bus_dma_tag_t uh_dmat;
+};
+
+/*
+ * Per-controller structure.
+ * 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_unit {
+ SIMPLEQ_ENTRY(uba_unit) uu_resq;/* Queue while waiting for resources */
+ void *uu_softc; /* Pointer to units softc */
+ int uu_bdp; /* for controllers that hang on to bdp's */
+ int (*uu_ready) __P((struct uba_unit *));
+ void *uu_ref; /* Buffer this is related to */
+ short uu_xclu; /* want exclusive use of bdp's */
+ short uu_keepbdp; /* hang on to bdp's once allocated */
+};
+
+/*
+ * uba_attach_args is used during autoconfiguration. It is sent
+ * from ubascan() to each (possible) device.
+ */
+struct uba_attach_args {
+ bus_space_tag_t ua_iot; /* Tag for this bus I/O-space */
+ bus_addr_t ua_ioh; /* I/O regs addr */
+ bus_dma_tag_t ua_dmat;
+ void *ua_icookie; /* Cookie for interrupt establish */
+ /* UBA reset routine, filled in by probe */
+ void (*ua_reset) __P((int));
+ int ua_iaddr; /* Full CSR address of device */
+ int ua_br; /* IPL this dev interrupted on */
+ int ua_cvec; /* Vector for this device */
+};
+
+/*
+ * Flags to UBA map/bdp allocation routines
+ */
+#define UBA_NEEDBDP 0x01 /* transfer needs a bdp */
+#define UBA_CANTWAIT 0x02 /* don't block me */
+#define UBA_NEED16 0x04 /* need 16 bit addresses only */
+#define UBA_HAVEBDP 0x08 /* use bdp specified in high bits */
+#define UBA_DONTQUE 0x10 /* Do not enqueue xfer */
+
+/*
+ * Some common defines for all subtypes of U/Q-buses/adapters.
+ */
+#define MAXUBAXFER (63*1024) /* Max transfer size in bytes */
+#define UBAIOSIZE (8*1024) /* 8K I/O space */
+#define ubdevreg(addr) ((addr) & 017777)
+
+#ifdef _KERNEL
+#define b_forw b_hash.le_next /* Nice to have when handling uba queues */
+
+void uba_intr_establish __P((void *, int, void (*)(void *), void *));
+void uba_attach __P((struct uba_softc *, unsigned long));
+void uba_enqueue __P((struct uba_unit *));
+void uba_done __P((struct uba_softc *));
+void ubareset __P((int));
+
+#endif /* _KERNEL */
+
+#endif /* _QBUS_UBAVAR_H */
diff --git a/sys/arch/vax/qbus/uda.c b/sys/arch/vax/qbus/uda.c
new file mode 100644
index 00000000000..ae91879ef04
--- /dev/null
+++ b/sys/arch/vax/qbus/uda.c
@@ -0,0 +1,509 @@
+/* $OpenBSD: uda.c,v 1.1 2000/04/27 03:14:49 bjc Exp $ */
+/* $NetBSD: uda.c,v 1.32 2000/01/24 02:40:30 matt 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
+ */
+
+/*
+ * UDA50 disk device driver
+ */
+
+#include <sys/param.h>
+#include <sys/kernel.h>
+#include <sys/systm.h>
+#include <sys/device.h>
+#include <sys/buf.h>
+#include <sys/malloc.h>
+
+#include <machine/bus.h>
+#include <machine/sid.h>
+
+#include <arch/vax/qbus/ubavar.h>
+#include <arch/vax/mscp/mscp.h>
+#include <arch/vax/mscp/mscpreg.h>
+#include <arch/vax/mscp/mscpvar.h>
+
+/*
+ * Software status, per controller.
+ */
+struct uda_softc {
+ struct device sc_dev; /* Autoconfig info */
+ struct uba_unit sc_unit; /* Struct common for UBA to communicate */
+ struct mscp_pack *sc_uuda; /* Unibus address of uda struct */
+ struct mscp_pack sc_uda; /* Struct for uda communication */
+ bus_dma_tag_t sc_dmat;
+ bus_space_tag_t sc_iot;
+ bus_space_handle_t sc_iph;
+ bus_space_handle_t sc_sah;
+ bus_dmamap_t sc_cmap;/* Control structures */
+ struct mscp *sc_mscp; /* Keep pointer to active mscp */
+ struct mscp_softc *sc_softc; /* MSCP info (per mscpvar.h) */
+ int sc_wticks; /* watchdog timer ticks */
+ int sc_inq;
+};
+
+static int udamatch __P((struct device *, struct cfdata *, 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 intr __P((void *));
+int udaready __P((struct uba_unit *));
+void udactlrdone __P((struct device *));
+int udaprint __P((void *, const char *));
+void udasaerror __P((struct device *, int));
+void udago __P((struct device *, struct mscp_xi *));
+
+struct cfattach mtc_ca = {
+ sizeof(struct uda_softc), (cfmatch_t)udamatch, udaattach
+};
+
+struct cfdriver mtc_cd = {
+ NULL, "mtc", DV_TAPE
+};
+
+struct cfattach uda_ca = {
+ sizeof(struct uda_softc), (cfmatch_t)udamatch, udaattach
+};
+
+struct cfdriver uda_cd = {
+ NULL, "uda", DV_DISK
+};
+
+/*
+ * More driver definitions, for generic MSCP code.
+ */
+struct mscp_ctlr uda_mscp_ctlr = {
+ udactlrdone,
+ udago,
+ udasaerror,
+};
+
+/*
+ * Miscellaneous private variables.
+ */
+static int ivec_no;
+
+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.
+ */
+int
+udamatch(parent, cf, aux)
+ struct device *parent;
+ struct cfdata *cf;
+ void *aux;
+{
+ struct uba_attach_args *ua = aux;
+ struct mscp_softc mi; /* Nice hack */
+ struct uba_softc *ubasc;
+ int tries;
+
+ /* Get an interrupt vector. */
+ ubasc = (void *)parent;
+ ivec_no = ubasc->uh_lastiv - 4;
+
+ mi.mi_iot = ua->ua_iot;
+ mi.mi_iph = ua->ua_ioh;
+ mi.mi_sah = ua->ua_ioh + 2;
+ mi.mi_swh = ua->ua_ioh + 2;
+
+ /*
+ * Initialise the controller (partially). The UDA50 programmer's
+ * manual states that if initialisation fails, it should be retried
+ * at least once, but after a second failure the port should be
+ * considered `down'; it also mentions that the controller should
+ * initialise within ten seconds. Or so I hear; I have not seen
+ * this manual myself.
+ */
+ tries = 0;
+again:
+
+ bus_space_write_2(mi.mi_iot, mi.mi_iph, 0, 0); /* Start init */
+ if (mscp_waitstep(&mi, MP_STEP1, MP_STEP1) == 0)
+ return 0; /* Nothing here... */
+
+ bus_space_write_2(mi.mi_iot, mi.mi_sah, 0,
+ MP_ERR | (NCMDL2 << 11) | (NRSPL2 << 8) | MP_IE | (ivec_no >> 2));
+
+ if (mscp_waitstep(&mi, MP_STEP2, MP_STEP2) == 0) {
+ printf("udaprobe: init step2 no change. sa=%x\n",
+ bus_space_read_2(mi.mi_iot, mi.mi_sah, 0));
+ goto bad;
+ }
+
+ /* should have interrupted by now */
+ if (strcmp(cf->cf_driver->cd_name, mtc_cd.cd_name)) {
+ ua->ua_reset = udareset;
+ } else {
+ ua->ua_reset = mtcreset;
+ }
+
+ return 1;
+bad:
+ if (++tries < 2)
+ goto again;
+ return 0;
+}
+
+void
+udaattach(parent, self, aux)
+ struct device *parent, *self;
+ void *aux;
+{
+ struct uda_softc *sc = (void *)self;
+ struct uba_attach_args *ua = aux;
+ struct uba_softc *uh = (void *)parent;
+ struct mscp_attach_args ma;
+ int ctlr, error, rseg;
+ bus_dma_segment_t seg;
+
+ printf("\n");
+
+ uh->uh_lastiv -= 4; /* remove dynamic interrupt vector */
+
+ uba_intr_establish(ua->ua_icookie, ua->ua_cvec, intr, sc);
+
+ sc->sc_iot = ua->ua_iot;
+ sc->sc_iph = ua->ua_ioh;
+ sc->sc_sah = ua->ua_ioh + 2;
+ sc->sc_dmat = ua->ua_dmat;
+ ctlr = sc->sc_dev.dv_unit;
+
+ /*
+ * Fill in the uba_unit struct, so we can communicate with the uba.
+ */
+ 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;
+
+ /*
+ * Map the communication area and command and
+ * response packets into Unibus space.
+ */
+ if ((error = bus_dmamem_alloc(sc->sc_dmat, sizeof(struct mscp_pack),
+ NBPG, 0, &seg, 1, &rseg, BUS_DMA_NOWAIT)) != 0) {
+ printf("Alloc ctrl area %d\n", error);
+ return;
+ }
+ if ((error = bus_dmamem_map(sc->sc_dmat, &seg, rseg,
+ sizeof(struct mscp_pack), (caddr_t *) &sc->sc_uda,
+ BUS_DMA_NOWAIT|BUS_DMA_COHERENT)) != 0) {
+ printf("Map ctrl area %d\n", error);
+err: bus_dmamem_free(sc->sc_dmat, &seg, rseg);
+ return;
+ }
+ if ((error = bus_dmamap_create(sc->sc_dmat, sizeof(struct mscp_pack),
+ 1, sizeof(struct mscp_pack), 0, BUS_DMA_NOWAIT, &sc->sc_cmap))) {
+ printf("Create DMA map %d\n", error);
+err2: bus_dmamem_unmap(sc->sc_dmat, (caddr_t)&sc->sc_uda,
+ sizeof(struct mscp_pack));
+ goto err;
+ }
+ if ((error = bus_dmamap_load(sc->sc_dmat, sc->sc_cmap,
+ &sc->sc_uda, sizeof(struct mscp_pack), 0, BUS_DMA_NOWAIT))) {
+ printf("Load ctrl map %d\n", error);
+ bus_dmamap_destroy(sc->sc_dmat, sc->sc_cmap);
+ goto err2;
+ }
+
+ bzero(&sc->sc_uda, sizeof (struct mscp_pack));
+
+ /*
+ * 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.
+ */
+ ma.ma_type = (strcmp(self->dv_cfdata->cf_driver->cd_name,
+ mtc_cd.cd_name) ? MSCPBUS_DISK : MSCPBUS_TAPE);
+
+ ma.ma_mc = &uda_mscp_ctlr;
+ ma.ma_type |= MSCPBUS_UDA;
+ ma.ma_uda = &sc->sc_uda;
+ ma.ma_softc = &sc->sc_softc;
+ ma.ma_iot = sc->sc_iot;
+ ma.ma_iph = sc->sc_iph;
+ ma.ma_sah = sc->sc_sah;
+ ma.ma_swh = sc->sc_sah;
+ ma.ma_dmat = sc->sc_dmat;
+ ma.ma_dmam = sc->sc_cmap;
+ ma.ma_ivec = ivec_no;
+ ma.ma_ctlrnr = (ua->ua_iaddr == 0172150 ? 0 : 1); /* XXX */
+ ma.ma_adapnr = uh->uh_nr;
+ config_found(&sc->sc_dev, &ma, udaprint);
+}
+
+/*
+ * Start a transfer if there are free resources available, otherwise
+ * let it go in udaready, forget it for now.
+ * Called from mscp routines.
+ */
+void
+udago(usc, mxi)
+ struct device *usc;
+ struct mscp_xi *mxi;
+{
+ struct uda_softc *sc = (void *)usc;
+ struct uba_unit *uu;
+ struct buf *bp = mxi->mxi_bp;
+ int err;
+
+ /*
+ * If we already have transfers queued, don't try to load
+ * the map again.
+ */
+ if (sc->sc_inq == 0) {
+ err = bus_dmamap_load(sc->sc_dmat, mxi->mxi_dmam,
+ bp->b_un.b_addr,
+ bp->b_bcount, bp->b_proc, BUS_DMA_NOWAIT);
+ if (err == 0) {
+ mscp_dgo(sc->sc_softc, mxi);
+ return;
+ }
+ }
+ uu = malloc(sizeof(struct uba_unit), M_DEVBUF, M_NOWAIT);
+ if (uu == 0)
+ panic("udago: no mem");
+ uu->uu_ready = udaready;
+ uu->uu_softc = sc;
+ uu->uu_ref = mxi;
+ uba_enqueue(uu);
+ sc->sc_inq++;
+}
+
+/*
+ * 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.
+ * Called from uba resource free routines.
+ */
+int
+udaready(uu)
+ struct uba_unit *uu;
+{
+ struct uda_softc *sc = uu->uu_softc;
+ struct mscp_xi *mxi = uu->uu_ref;
+ struct buf *bp = mxi->mxi_bp;
+ int err;
+
+ err = bus_dmamap_load(sc->sc_dmat, mxi->mxi_dmam, bp->b_un.b_addr,
+ bp->b_bcount, bp->b_proc, BUS_DMA_NOWAIT);
+ if (err)
+ return 0;
+ mscp_dgo(sc->sc_softc, mxi);
+ sc->sc_inq--;
+ free(uu, M_DEVBUF);
+ return 1;
+}
+
+static struct saerr {
+ int code; /* error code (including UDA_ERR) */
+ char *desc; /* what it means: Efoo => foo error */
+} saerr[] = {
+ { 0100001, "Eunibus packet read" },
+ { 0100002, "Eunibus packet write" },
+ { 0100003, "EUDA ROM and RAM parity" },
+ { 0100004, "EUDA RAM parity" },
+ { 0100005, "EUDA ROM parity" },
+ { 0100006, "Eunibus ring read" },
+ { 0100007, "Eunibus ring write" },
+ { 0100010, " unibus interrupt master failure" },
+ { 0100011, "Ehost access timeout" },
+ { 0100012, " host exceeded command limit" },
+ { 0100013, " unibus bus master failure" },
+ { 0100014, " DM XFC fatal error" },
+ { 0100015, " hardware timeout of instruction loop" },
+ { 0100016, " invalid virtual circuit id" },
+ { 0100017, "Eunibus interrupt write" },
+ { 0104000, "Efatal sequence" },
+ { 0104040, " D proc ALU" },
+ { 0104041, "ED proc control ROM parity" },
+ { 0105102, "ED proc w/no BD#2 or RAM parity" },
+ { 0105105, "ED proc RAM buffer" },
+ { 0105152, "ED proc SDI" },
+ { 0105153, "ED proc write mode wrap serdes" },
+ { 0105154, "ED proc read mode serdes, RSGEN & ECC" },
+ { 0106040, "EU proc ALU" },
+ { 0106041, "EU proc control reg" },
+ { 0106042, " U proc DFAIL/cntl ROM parity/BD #1 test CNT" },
+ { 0106047, " U proc const PROM err w/D proc running SDI test" },
+ { 0106055, " unexpected trap" },
+ { 0106071, "EU proc const PROM" },
+ { 0106072, "EU proc control ROM parity" },
+ { 0106200, "Estep 1 data" },
+ { 0107103, "EU proc RAM parity" },
+ { 0107107, "EU proc RAM buffer" },
+ { 0107115, " test count wrong (BD 12)" },
+ { 0112300, "Estep 2" },
+ { 0122240, "ENPR" },
+ { 0122300, "Estep 3" },
+ { 0142300, "Estep 4" },
+ { 0, " unknown error code" }
+};
+
+/*
+ * If the error bit was set in the controller status register, gripe,
+ * then (optionally) reset the controller and requeue pending transfers.
+ */
+void
+udasaerror(usc, doreset)
+ struct device *usc;
+ int doreset;
+{
+ struct uda_softc *sc = (void *)usc;
+ register int code = bus_space_read_2(sc->sc_iot, sc->sc_sah, 0);
+ register struct saerr *e;
+
+ if ((code & MP_ERR) == 0)
+ return;
+ for (e = saerr; e->code; e++)
+ if (e->code == code)
+ break;
+ printf("%s: controller error, sa=0%o (%s%s)\n",
+ sc->sc_dev.dv_xname, code, e->desc + 1,
+ *e->desc == 'E' ? " error" : "");
+#if 0 /* XXX we just avoid panic when autoconfig non-existent KFQSA devices */
+ if (doreset) {
+ mscp_requeue(sc->sc_softc);
+/* (void) udainit(sc); XXX */
+ }
+#endif
+}
+
+/*
+ * Interrupt routine. Depending on the state of the controller,
+ * continue initialisation, or acknowledge command and response
+ * interrupts, and process responses.
+ */
+static void
+intr(arg)
+ void *arg;
+{
+ struct uda_softc *sc = arg;
+ struct uba_softc *uh;
+ struct mscp_pack *ud;
+
+ sc->sc_wticks = 0; /* reset interrupt watchdog */
+
+ /* ctlr fatal error */
+ if (bus_space_read_2(sc->sc_iot, sc->sc_sah, 0) & MP_ERR) {
+ udasaerror(&sc->sc_dev, 1);
+ return;
+ }
+ ud = &sc->sc_uda;
+ /*
+ * Handle buffer purge requests.
+ * XXX - should be done in bus_dma_sync().
+ */
+ 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;
+ /* signal purge complete */
+ bus_space_write_2(sc->sc_iot, sc->sc_sah, 0, 0);
+ }
+
+ 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.
+ */
+void
+udareset(ctlr)
+ int ctlr;
+{
+ reset(uda_cd.cd_devs[ctlr]);
+}
+
+void
+mtcreset(ctlr)
+ int ctlr;
+{
+ reset(mtc_cd.cd_devs[ctlr]);
+}
+
+static void
+reset(sc)
+ struct uda_softc *sc;
+{
+ printf(" %s", sc->sc_dev.dv_xname);
+
+ /*
+ * 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 (sc->sc_unit.uu_bdp) {
+ /* printf("<%d>", UBAI_BDP(sc->sc_unit.uu_bdp)); */
+ sc->sc_unit.uu_bdp = 0;
+ }
+
+ /* 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 udastart()
+ * here; it will be done after the controller finishes
+ * initialisation.
+ */
+/* XXX if (udainit(sc)) */
+ printf(" (hung)");
+}
+
+void
+udactlrdone(usc)
+ struct device *usc;
+{
+ struct uda_softc *sc = (void *)usc;
+
+ uba_done((struct uba_softc *)sc->sc_dev.dv_parent);
+}
diff --git a/sys/arch/vax/uba/uba.c b/sys/arch/vax/uba/uba.c
index 98b8f4b5a1c..5d06ea578aa 100644
--- a/sys/arch/vax/uba/uba.c
+++ b/sys/arch/vax/uba/uba.c
@@ -1,5 +1,5 @@
-/* $OpenBSD: uba.c,v 1.8 1997/05/29 00:05:09 niklas Exp $ */
-/* $NetBSD: uba.c,v 1.29 1996/10/13 03:35:24 christos Exp $ */
+/* $OpenBSD: uba.c,v 1.9 2000/04/27 03:14:51 bjc Exp $ */
+/* $NetBSD: uba.c,v 1.42 1999/02/02 18:37:20 ragge Exp $ */
/*
* Copyright (c) 1996 Jonathan Stone.
* Copyright (c) 1994, 1996 Ludd, University of Lule}, Sweden.
@@ -67,33 +67,30 @@
#include <vax/uba/ubareg.h>
#include <vax/uba/ubavar.h>
-volatile int rbr, rcvec, svec;
+volatile int /* rbr, rcvec,*/ svec;
-static void ubascan __P((struct device *, void *));
+static int ubasearch __P((struct device *, struct cfdata *, void *));
static int ubaprint __P((void *, const char *));
+#if 0
static void ubastray __P((int));
+#endif
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
-};
+extern struct cfdriver uba_cd;
#define spluba spl7
#if defined(DW780) || defined(DW750)
-int dw_match __P((struct device *, void *, void *));
+int dw_match __P((struct device *, struct cfdata *, void *));
int
-dw_match(parent, vcf, aux)
+dw_match(parent, cf, aux)
struct device *parent;
- void *vcf, *aux;
+ struct cfdata *cf;
+ void *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;
@@ -136,6 +133,7 @@ dw780_attach(parent, self, aux)
struct uba_softc *sc = (void *)self;
struct sbi_attach_args *sa = aux;
int ubaddr = sa->type & 3;
+ int i;
printf(": DW780\n");
@@ -152,18 +150,15 @@ dw780_attach(parent, self, aux)
sc->uh_ubainit = dw780_init;
sc->uh_type = DW780;
sc->uh_memsize = UBAPAGES;
- sc->uh_iarea = (void *)scb + NBPG + ubaddr * NBPG;
+ sc->uh_ibase = VAX_NBPG + ubaddr * VAX_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;
+ for (i = 0; i < 4; i++)
+ scb_vecalloc(256 + i * 64 + sa->nexnum * 4, uba_dw780int,
+ sc->uh_dev.dv_unit, SCB_ISTACK);
uba_attach(sc, (parent->dv_unit ? UMEMB8600(ubaddr) :
- UMEMA8600(ubaddr)) + (UBAPAGES * NBPG));
+ UMEMA8600(ubaddr)) + (UBAPAGES * VAX_NBPG));
}
void
@@ -172,20 +167,17 @@ dw780_beforescan(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;
- }
+ *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);
+ sc->uh_uba->uba_cr = UBACR_IFS | UBACR_BRIE |
+ UBACR_USEFIE | UBACR_SUEFIE |
+ (sc->uh_uba->uba_cr & 0x7c000000);
}
/*
@@ -198,7 +190,7 @@ dw780_errchk(sc)
{
volatile int *hej = &sc->uh_uba->uba_sr;
- if (sc->uh_type == DW780 && *hej) {
+ if (*hej) {
*hej = *hej;
return 1;
}
@@ -215,18 +207,20 @@ uba_dw780int(uba)
void (*func) __P((int));
br = mfpr(PR_IPL);
- svec = ur->uba_brrvr[br - 0x14];
- if (svec <= 0) {
- ubaerror(sc, &br, (int *)&svec);
+ vec = ur->uba_brrvr[br - 0x14];
+ if (vec <= 0) {
+ ubaerror(sc, &br, (int *)&vec);
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);
+ scb_fake(vec + sc->uh_ibase, br);
+ else {
+ struct ivec_dsp *scb_vec = (struct ivec_dsp *)((int)scb + 512);
+ func = scb_vec[vec/4].hoppaddr;
+ arg = scb_vec[vec/4].pushlarg;
+ (*func)(arg);
+ }
}
void
@@ -266,7 +260,7 @@ ubaerror(uh, ipl, uvec)
int *ipl, *uvec;
{
struct uba_regs *uba = uh->uh_uba;
- register sr, s;
+ register int sr, s;
if (*uvec == 0) {
/*
@@ -356,10 +350,9 @@ dw750_attach(parent, self, aux)
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));
+ uba_attach(sc, UMEM750(ubaddr) + (UBAPAGES * VAX_NBPG));
}
void
@@ -387,19 +380,20 @@ dw750_purge(sc, bdp)
* 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 *));
+int qba_match __P((struct device *, struct cfdata *, 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 = {
+struct cfattach uba_mainbus_ca = {
sizeof(struct uba_softc), qba_match, qba_attach
};
int
qba_match(parent, vcf, aux)
struct device *parent;
- void *vcf, *aux;
+ struct cfdata *vcf;
+ void *aux;
{
struct bp_conf *bp = aux;
@@ -415,11 +409,8 @@ qba_attach(parent, self, aux)
void *aux;
{
struct uba_softc *sc = (void *)self;
- vm_offset_t mini, maxi;
printf(": Q22\n");
-
-
/*
* Fill in bus specific data.
*/
@@ -432,16 +423,12 @@ qba_attach(parent, self, aux)
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;
+ sc->uh_mr = (void *)vax_map_physmem(QBAMAP,
+ (QBAPAGES * sizeof(struct pte)) / VAX_NBPG);
uba_attach(sc, QIOPAGE);
}
@@ -466,36 +453,12 @@ qba_init(sc)
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
+#if 0
/*
* Stray interrupt vector handler, used when nowhere else to go to.
*/
@@ -524,7 +487,7 @@ ubastray(arg)
printf("uba%d: unexpected interrupt, vector 0x%x, br 0x%x\n",
arg, svec, rbr);
}
-
+#endif
/*
* Do transfer on device argument. The controller
* and uba involved are implied by the device.
@@ -623,8 +586,8 @@ ubasetup(uh, bp, flags)
if (uh->uh_nbdp == 0)
flags &= ~UBA_NEEDBDP;
- o = (int)bp->b_un.b_addr & PGOFSET;
- npf = btoc(bp->b_bcount + o) + 1;
+ o = (int)bp->b_un.b_addr & VAX_PGOFSET;
+ npf = vax_btoc(bp->b_bcount + o) + 1;
if (npf > UBA_MAXNMR)
panic("uba xfer too big");
a = spluba();
@@ -831,10 +794,8 @@ qbgetpri()
void
uba_attach(sc, iopagephys)
struct uba_softc *sc;
- unsigned long iopagephys;
+ paddr_t iopagephys;
{
- vm_offset_t mini, maxi;
- extern struct ivec_dsp idsptch;
/*
* Set last free interrupt vector for devices with
@@ -845,34 +806,11 @@ uba_attach(sc, iopagephys)
SIMPLEQ_INIT(&sc->uh_resq);
/*
- * Create interrupt dispatchers for this uba.
- */
-#define NO_IVEC 128
- {
- vm_offset_t iarea;
- int i;
-
- iarea = kmem_alloc(kernel_map,
- NO_IVEC * sizeof(struct ivec_dsp));
- sc->uh_idsp = (struct ivec_dsp *)iarea;
-
- for (i = 0; i < NO_IVEC; i++) {
- bcopy(&idsptch, &sc->uh_idsp[i],
- sizeof(struct ivec_dsp));
- sc->uh_idsp[i].pushlarg = sc->uh_dev.dv_unit;
- sc->uh_idsp[i].hoppaddr = ubastray;
- sc->uh_iarea[i] = (unsigned int)&sc->uh_idsp[i];
- }
- }
- /*
* 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?
*/
- (void)kmem_suballoc(kernel_map, &mini, &maxi, UBAIOPAGES * NBPG, FALSE);
- pmap_map(mini, iopagephys, iopagephys + UBAIOPAGES * NBPG,
- VM_PROT_READ|VM_PROT_WRITE);
- sc->uh_iopage = (void *)mini;
+ sc->uh_iopage = (caddr_t)vax_map_physmem(iopagephys, UBAIOPAGES);
+ if (sc->uh_iopage == 0)
+ return; /* vax_map_physmem() will complain for us */
/*
* Initialize the UNIBUS, by freeing the map
* registers and the buffered data path registers
@@ -893,22 +831,21 @@ uba_attach(sc, iopagephys)
/*
* Now start searching for devices.
*/
- config_scan(ubascan,(struct device *)sc);
+ config_search(ubasearch,(struct device *)sc, NULL);
if (sc->uh_afterscan)
(*sc->uh_afterscan)(sc);
}
-void
-ubascan(parent, match)
+int
+ubasearch(parent, cf, aux)
struct device *parent;
- void *match;
+ struct cfdata *cf;
+ void *aux;
{
- struct device *dev = match;
- struct cfdata *cf = dev->dv_cfdata;
struct uba_softc *sc = (struct uba_softc *)parent;
struct uba_attach_args ua;
- int i;
+ int i, vec, br;
ua.ua_addr = (caddr_t)((int)sc->uh_iopage + ubdevreg(cf->cf_loc[0]));
ua.ua_reset = NULL;
@@ -916,8 +853,8 @@ ubascan(parent, match)
if (badaddr(ua.ua_addr, 2) || (sc->uh_errchk ? (*sc->uh_errchk)(sc):0))
goto forgetit;
- rcvec = 0x200;
- i = (*cf->cf_attach->ca_match) (parent, dev, &ua);
+ scb_vecref(0, 0); /* Clear vector ref */
+ i = (*cf->cf_attach->ca_match) (parent, cf, &ua);
if (sc->uh_errchk)
if ((*sc->uh_errchk)(sc))
@@ -925,58 +862,44 @@ ubascan(parent, match)
if (i == 0)
goto forgetit;
- if (rcvec == 0 || rcvec == 0x200)
+ i = scb_vecref(&vec, &br);
+ if (i == 0)
+ goto fail;
+ if (vec == 0)
goto fail;
- sc->uh_idsp[rcvec].hoppaddr = ua.ua_ivec;
- sc->uh_idsp[rcvec].pushlarg = dev->dv_unit;
- if (ua.ua_reset) { /* device wants ubraeset */
+ scb_vecalloc(vec, ua.ua_ivec, cf->cf_unit, SCB_ISTACK);
+ if (ua.ua_reset) { /* device wants ubareset */
if (sc->uh_resno == 0) {
sc->uh_reset = malloc(1024, 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);
+ printf("%s: Expand reset table, skipping reset %s%d\n",
+ sc->uh_dev.dv_xname, cf->cf_driver->cd_name,
+ cf->cf_unit);
} else
#endif
{
- sc->uh_resarg[sc->uh_resno] = dev->dv_unit;
+ sc->uh_resarg[sc->uh_resno] = cf->cf_unit;
sc->uh_reset[sc->uh_resno++] = ua.ua_reset;
}
}
- ua.ua_br = rbr;
- ua.ua_cvec = rcvec;
- ua.ua_iaddr = dev->dv_cfdata->cf_loc[0];
+ ua.ua_br = br;
+ ua.ua_cvec = vec;
+ ua.ua_iaddr = cf->cf_loc[0];
- config_attach(parent, dev, &ua, ubaprint);
- return;
+ config_attach(parent, cf, &ua, ubaprint);
+ return 0;
fail:
- printf("%s at %s csr %o %s\n", dev->dv_cfdata->cf_driver->cd_name,
- parent->dv_xname, dev->dv_cfdata->cf_loc[0],
- rcvec ? "didn't interrupt\n" : "zero vector\n");
+ printf("%s%d at %s csr %o %s\n",
+ cf->cf_driver->cd_name, cf->cf_unit, parent->dv_xname,
+ cf->cf_loc[0], (i ? "zero vector" : "didn't interrupt"));
forgetit:
- free(dev, M_DEVBUF);
-}
-
-/*
- * Called when a device needs more than one interrupt vector.
- * (Like DHU11, DMF32). Argument is the device's softc, vector
- * number and a function pointer to the interrupt catcher.
- */
-void
-ubasetvec(dev, vec, func)
- struct device *dev;
- int vec;
- void (*func) __P((int));
-{
- struct uba_softc *sc = (void *)dev->dv_parent;
-
- sc->uh_idsp[vec].hoppaddr = func;
- sc->uh_idsp[vec].pushlarg = dev->dv_unit;
+ return 0;
}
/*
@@ -990,6 +913,6 @@ ubaprint(aux, uba)
struct uba_attach_args *ua = aux;
printf(" csr %o vec %o ipl %x", ua->ua_iaddr,
- ua->ua_cvec << 2, ua->ua_br);
+ ua->ua_cvec & 511, ua->ua_br);
return UNCONF;
}
diff --git a/sys/arch/vax/uba/uba_cmi.c b/sys/arch/vax/uba/uba_cmi.c
new file mode 100644
index 00000000000..22ce4ee8897
--- /dev/null
+++ b/sys/arch/vax/uba/uba_cmi.c
@@ -0,0 +1,147 @@
+/* $OpenBSD: uba_cmi.c,v 1.1 2000/04/27 03:14:51 bjc Exp $ */
+/* $NetBSD: uba_cmi.c,v 1.2 1999/08/14 11:31:48 ragge 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.
+ * 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.
+ *
+ * @(#)uba.c 7.10 (Berkeley) 12/16/90
+ * @(#)autoconf.c 7.20 (Berkeley) 5/9/91
+ */
+
+#include <sys/param.h>
+#include <sys/device.h>
+#include <sys/systm.h>
+
+#define _VAX_BUS_DMA_PRIVATE
+#include <machine/bus.h>
+#include <machine/mtpr.h>
+#include <machine/nexus.h>
+#include <machine/cpu.h>
+#include <machine/sgmap.h>
+
+#include <arch/vax/qbus/ubavar.h>
+
+#include <arch/vax/uba/uba_common.h>
+
+/* Some CMI-specific defines */
+#define UBASIZE ((UBAPAGES + UBAIOPAGES) * VAX_NBPG)
+#define UMEM750(i) (0xfc0000 - (i) * UBASIZE)
+#define UIOPAGE(x) (UMEM750(x) + (UBAPAGES * VAX_NBPG))
+
+/*
+ * 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.
+ */
+static int dw750_match __P((struct device *, struct cfdata *, void *));
+static void dw750_attach __P((struct device *, struct device *, void *));
+static void dw750_init __P((struct uba_softc*));
+#ifdef notyet
+static void dw750_purge __P((struct uba_softc *, int));
+#endif
+
+struct cfattach uba_cmi_ca = {
+ sizeof(struct uba_vsoftc), dw750_match, dw750_attach
+};
+
+extern struct vax_bus_space vax_mem_bus_space;
+
+int
+dw750_match(parent, cf, aux)
+ struct device *parent;
+ struct cfdata *cf;
+ void *aux;
+{
+ struct sbi_attach_args *sa = (struct sbi_attach_args *)aux;
+
+ 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;
+}
+
+void
+dw750_attach(parent, self, aux)
+ struct device *parent, *self;
+ void *aux;
+{
+ struct uba_vsoftc *sc = (void *)self;
+ struct sbi_attach_args *sa = aux;
+ struct uba_regs *uh_uba = (void *)sa->nexaddr;
+ int ubaddr = sa->nexinfo & 1;
+
+ printf(": DW750\n");
+ /*
+ * Fill in bus specific data.
+ */
+ sc->uv_sc.uh_ubainit = dw750_init;
+#ifdef notyet
+ sc->uv_sc.uh_ubapurge = dw750_purge;
+#endif
+ sc->uv_sc.uh_iot = &vax_mem_bus_space;
+ sc->uv_sc.uh_dmat = &sc->uv_dmat;
+
+ /*
+ * Fill in variables used by the sgmap system.
+ */
+ sc->uv_size = UBASIZE; /* Size in bytes of Qbus space */
+ sc->uv_addr = (paddr_t)uh_uba->uba_map; /* Map regs physical address */
+
+ uba_dma_init(sc);
+ uba_attach(&sc->uv_sc, UIOPAGE(ubaddr));
+}
+
+void
+dw750_init(sc)
+ struct uba_softc *sc;
+{
+ mtpr(0, PR_IUR);
+ DELAY(500000);
+}
+
+#ifdef notyet
+void
+dw750_purge(sc, bdp)
+ struct uba_softc *sc;
+ int bdp;
+{
+ sc->uh_uba->uba_dpr[bdp] |= UBADPR_PURGE | UBADPR_NXM | UBADPR_UCE;
+}
+#endif
diff --git a/sys/arch/vax/uba/uba_common.h b/sys/arch/vax/uba/uba_common.h
new file mode 100644
index 00000000000..deafdd2cf20
--- /dev/null
+++ b/sys/arch/vax/uba/uba_common.h
@@ -0,0 +1,88 @@
+/* $OpenBSD: uba_common.h,v 1.1 2000/04/27 03:14:51 bjc Exp $ */
+/* $NetBSD: uba_common.h,v 1.2 1999/06/21 16:23:01 ragge Exp $ */
+/*-
+ * Copyright (c) 1982, 1986 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.
+ *
+ * @(#)ubareg.h 7.8 (Berkeley) 5/9/91
+ */
+
+/*
+ * VAX-specific parts of the Unibus softc.
+ */
+struct uba_regs;
+
+struct uba_vsoftc {
+ struct uba_softc uv_sc;/* Common vars from arch/vax/qbus/ubavar.h */
+ struct vax_bus_dma_tag uv_dmat;
+ struct vax_sgmap uv_sgmap;
+ int uv_size; /* Size of UBA addressable memory */
+ paddr_t uv_addr; /* Physical address of map registers */
+ struct uba_regs *uv_uba;/* Where applicable */
+ int uh_ibase;
+ int uh_zvtime;
+ int uh_zvtotal;
+ int uh_zvcnt;
+};
+
+/*
+ * Size of unibus memory address space in pages
+ * (also number of map registers).
+ */
+#define UBAPAGES 496
+#define UBAIOADDR 0760000 /* start of I/O page */
+#define UBAIOPAGES 16
+
+/*
+ * DW780/DW750 hardware registers
+ */
+struct uba_regs {
+ int uba_cnfgr; /* configuration register */
+ int uba_cr; /* control register */
+ int uba_sr; /* status register */
+ int uba_dcr; /* diagnostic control register */
+ int uba_fmer; /* failed map entry register */
+ int uba_fubar; /* failed UNIBUS address register */
+ int pad1[2];
+ int uba_brsvr[4];
+ int uba_brrvr[4]; /* receive vector registers */
+ int uba_dpr[16]; /* buffered data path register */
+ int pad2[480];
+ struct pte uba_map[UBAPAGES]; /* unibus map register */
+ int pad3[UBAIOPAGES]; /* no maps for device address space */
+};
+
+void uba_dma_init __P((struct uba_vsoftc *));
diff --git a/sys/arch/vax/uba/uba_dma.c b/sys/arch/vax/uba/uba_dma.c
new file mode 100644
index 00000000000..f0344dfff96
--- /dev/null
+++ b/sys/arch/vax/uba/uba_dma.c
@@ -0,0 +1,282 @@
+/* $OpenBSD: uba_dma.c,v 1.1 2000/04/27 03:14:51 bjc Exp $ */
+/* $NetBSD: uba_dma.c,v 1.2 1999/06/20 00:59:55 ragge Exp $ */
+
+/*-
+ * Copyright (c) 1997, 1998 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
+ * NASA Ames Research Center.
+ *
+ * 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 NetBSD
+ * Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation 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 NETBSD FOUNDATION, INC. 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 FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPEUBAL, 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/kernel.h>
+#include <sys/device.h>
+#include <sys/malloc.h>
+#include <vm/vm.h>
+
+#define _VAX_BUS_DMA_PRIVATE
+#include <machine/bus.h>
+#include <machine/cpu.h>
+#include <machine/sgmap.h>
+
+#include <arch/vax/qbus/ubavar.h>
+
+#include <arch/vax/uba/uba_common.h>
+
+int uba_bus_dmamap_create_sgmap __P((bus_dma_tag_t, bus_size_t, int,
+ bus_size_t, bus_size_t, int, bus_dmamap_t *));
+
+void uba_bus_dmamap_destroy_sgmap __P((bus_dma_tag_t, bus_dmamap_t));
+
+int uba_bus_dmamap_load_sgmap __P((bus_dma_tag_t, bus_dmamap_t, void *,
+ bus_size_t, struct proc *, int));
+
+int uba_bus_dmamap_load_mbuf_sgmap __P((bus_dma_tag_t, bus_dmamap_t,
+ struct mbuf *, int));
+
+int uba_bus_dmamap_load_uio_sgmap __P((bus_dma_tag_t, bus_dmamap_t,
+ struct uio *, int));
+
+int uba_bus_dmamap_load_raw_sgmap __P((bus_dma_tag_t, bus_dmamap_t,
+ bus_dma_segment_t *, int, bus_size_t, int));
+
+void uba_bus_dmamap_unload_sgmap __P((bus_dma_tag_t, bus_dmamap_t));
+
+void uba_bus_dmamap_sync __P((bus_dma_tag_t, bus_dmamap_t, bus_addr_t,
+ bus_size_t, int));
+
+void
+uba_dma_init(sc)
+ struct uba_vsoftc *sc;
+{
+ bus_dma_tag_t t;
+ struct pte *pte;
+
+ /*
+ * Initialize the DMA tag used for sgmap-mapped DMA.
+ */
+ t = &sc->uv_dmat;
+ t->_cookie = sc;
+ t->_wbase = 0;
+ t->_wsize = sc->uv_size;
+ t->_boundary = 0;
+ t->_sgmap = &sc->uv_sgmap;
+ t->_dmamap_create = uba_bus_dmamap_create_sgmap;
+ t->_dmamap_destroy = uba_bus_dmamap_destroy_sgmap;
+ t->_dmamap_load = uba_bus_dmamap_load_sgmap;
+ t->_dmamap_load_mbuf = uba_bus_dmamap_load_mbuf_sgmap;
+ t->_dmamap_load_uio = uba_bus_dmamap_load_uio_sgmap;
+ t->_dmamap_load_raw = uba_bus_dmamap_load_raw_sgmap;
+ t->_dmamap_unload = uba_bus_dmamap_unload_sgmap;
+ t->_dmamap_sync = uba_bus_dmamap_sync;
+
+ t->_dmamem_alloc = _bus_dmamem_alloc;
+ t->_dmamem_free = _bus_dmamem_free;
+ t->_dmamem_map = _bus_dmamem_map;
+ t->_dmamem_unmap = _bus_dmamem_unmap;
+ t->_dmamem_mmap = _bus_dmamem_mmap;
+
+ /*
+ * Map in Unibus map registers.
+ */
+ pte = (struct pte *)vax_map_physmem(sc->uv_addr, sc->uv_size/VAX_NBPG);
+ if (pte == 0)
+ panic("uba_dma_init");
+ /*
+ * Initialize the SGMAP.
+ */
+ vax_sgmap_init(t, &sc->uv_sgmap, "uba_sgmap", 0, sc->uv_size, pte, 0);
+
+}
+
+/*
+ * Create a UBA SGMAP-mapped DMA map.
+ */
+int
+uba_bus_dmamap_create_sgmap(t, size, nsegments, maxsegsz, boundary,
+ flags, dmamp)
+ bus_dma_tag_t t;
+ bus_size_t size;
+ int nsegments;
+ bus_size_t maxsegsz;
+ bus_size_t boundary;
+ int flags;
+ bus_dmamap_t *dmamp;
+{
+ bus_dmamap_t map;
+ int error;
+
+ error = _bus_dmamap_create(t, size, nsegments, maxsegsz,
+ boundary, flags, dmamp);
+ if (error)
+ return (error);
+
+ map = *dmamp;
+
+ if (flags & BUS_DMA_ALLOCNOW) {
+ error = vax_sgmap_alloc(map, vax_round_page(size),
+ t->_sgmap, flags);
+ if (error)
+ uba_bus_dmamap_destroy_sgmap(t, map);
+ }
+
+ return (error);
+}
+
+/*
+ * Destroy a UBA SGMAP-mapped DMA map.
+ */
+void
+uba_bus_dmamap_destroy_sgmap(t, map)
+ bus_dma_tag_t t;
+ bus_dmamap_t map;
+{
+
+ if (map->_dm_flags & DMAMAP_HAS_SGMAP)
+ vax_sgmap_free(map, t->_sgmap);
+
+ _bus_dmamap_destroy(t, map);
+}
+
+/*
+ * Load a UBA SGMAP-mapped DMA map with a linear buffer.
+ */
+int
+uba_bus_dmamap_load_sgmap(t, map, buf, buflen, p, flags)
+ bus_dma_tag_t t;
+ bus_dmamap_t map;
+ void *buf;
+ bus_size_t buflen;
+ struct proc *p;
+ int flags;
+{
+ int error;
+
+ error = vax_sgmap_load(t, map, buf, buflen, p, flags, t->_sgmap);
+ /*
+ * XXX - Set up BDPs.
+ */
+
+ return (error);
+}
+
+/*
+ * Load a UBA SGMAP-mapped DMA map with an mbuf chain.
+ */
+int
+uba_bus_dmamap_load_mbuf_sgmap(t, map, m, flags)
+ bus_dma_tag_t t;
+ bus_dmamap_t map;
+ struct mbuf *m;
+ int flags;
+{
+ int error;
+
+ error = vax_sgmap_load_mbuf(t, map, m, flags, t->_sgmap);
+
+ return (error);
+}
+
+/*
+ * Load a UBA SGMAP-mapped DMA map with a uio.
+ */
+int
+uba_bus_dmamap_load_uio_sgmap(t, map, uio, flags)
+ bus_dma_tag_t t;
+ bus_dmamap_t map;
+ struct uio *uio;
+ int flags;
+{
+ int error;
+
+ error = vax_sgmap_load_uio(t, map, uio, flags, t->_sgmap);
+
+ return (error);
+}
+
+/*
+ * Load a UBA SGMAP-mapped DMA map with raw memory.
+ */
+int
+uba_bus_dmamap_load_raw_sgmap(t, map, segs, nsegs, size, flags)
+ bus_dma_tag_t t;
+ bus_dmamap_t map;
+ bus_dma_segment_t *segs;
+ int nsegs;
+ bus_size_t size;
+ int flags;
+{
+ int error;
+
+ error = vax_sgmap_load_raw(t, map, segs, nsegs, size, flags,
+ t->_sgmap);
+
+ return (error);
+}
+
+/*
+ * Unload a UBA DMA map.
+ */
+void
+uba_bus_dmamap_unload_sgmap(t, map)
+ bus_dma_tag_t t;
+ bus_dmamap_t map;
+{
+
+ /*
+ * Invalidate any SGMAP page table entries used by this
+ * mapping.
+ */
+ vax_sgmap_unload(t, map, t->_sgmap);
+
+ /*
+ * Do the generic bits of the unload.
+ */
+ _bus_dmamap_unload(t, map);
+}
+
+/*
+ * Sync the bus map. This is only needed if BDP's are used.
+ */
+void
+uba_bus_dmamap_sync(tag, dmam, offset, len, ops)
+ bus_dma_tag_t tag;
+ bus_dmamap_t dmam;
+ bus_addr_t offset;
+ bus_size_t len;
+ int ops;
+{
+ /* Only BDP handling, but not yet. */
+}
diff --git a/sys/arch/vax/uba/uba_ibus.c b/sys/arch/vax/uba/uba_ibus.c
new file mode 100644
index 00000000000..3b118e1caa1
--- /dev/null
+++ b/sys/arch/vax/uba/uba_ibus.c
@@ -0,0 +1,137 @@
+/* $OpenBSD: uba_ibus.c,v 1.1 2000/04/27 03:14:51 bjc Exp $ */
+/* $NetBSD: uba_ibus.c,v 1.1 1999/08/07 10:36:47 ragge 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.
+ * 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.
+ *
+ * @(#)uba.c 7.10 (Berkeley) 12/16/90
+ * @(#)autoconf.c 7.20 (Berkeley) 5/9/91
+ */
+
+#include <sys/param.h>
+#include <sys/device.h>
+#include <sys/systm.h>
+
+#define _VAX_BUS_DMA_PRIVATE
+#include <machine/bus.h>
+#include <machine/mtpr.h>
+#include <machine/nexus.h>
+#include <machine/cpu.h>
+#include <machine/sgmap.h>
+
+#include <arch/vax/qbus/ubavar.h>
+
+#include <arch/vax/uba/uba_common.h>
+
+/* Some Qbus-specific defines */
+#define QBASIZE (8192 * VAX_NBPG)
+#define QBAMAP 0x20088000
+#define QIOPAGE 0x20000000
+
+/*
+ * 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.
+ */
+static int qba_match __P((struct device *, struct cfdata *, void *));
+static void qba_attach __P((struct device *, struct device *, void *));
+static void qba_beforescan __P((struct uba_softc*));
+static void qba_init __P((struct uba_softc*));
+
+struct cfattach uba_ibus_ca = {
+ sizeof(struct uba_vsoftc), (cfmatch_t)qba_match, qba_attach
+};
+
+extern struct vax_bus_space vax_mem_bus_space;
+
+int
+qba_match(parent, vcf, aux)
+ struct device *parent;
+ struct cfdata *vcf;
+ void *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_vsoftc *sc = (void *)self;
+
+ printf(": Q22\n");
+ /*
+ * Fill in bus specific data.
+ */
+ sc->uv_sc.uh_beforescan = qba_beforescan;
+ sc->uv_sc.uh_ubainit = qba_init;
+ sc->uv_sc.uh_iot = &vax_mem_bus_space;
+ sc->uv_sc.uh_dmat = &sc->uv_dmat;
+
+ /*
+ * Fill in variables used by the sgmap system.
+ */
+ sc->uv_size = QBASIZE; /* Size in bytes of Qbus space */
+ sc->uv_addr = QBAMAP; /* Physical address of map registers */
+
+ uba_dma_init(sc);
+ uba_attach(&sc->uv_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;
+{
+#define QIPCR 0x1f40
+#define Q_LMEAE 0x20
+ bus_space_write_2(sc->uh_tag, sc->uh_ioh, QIPCR, Q_LMEAE);
+}
+
+void
+qba_init(sc)
+ struct uba_softc *sc;
+{
+ mtpr(0, PR_IUR);
+ DELAY(500000);
+ qba_beforescan(sc);
+}
diff --git a/sys/arch/vax/uba/uba_mainbus.c b/sys/arch/vax/uba/uba_mainbus.c
new file mode 100644
index 00000000000..c5f6daa57bd
--- /dev/null
+++ b/sys/arch/vax/uba/uba_mainbus.c
@@ -0,0 +1,137 @@
+/* $OpenBSD: uba_mainbus.c,v 1.1 2000/04/27 03:14:51 bjc Exp $ */
+/* $NetBSD: uba_mainbus.c,v 1.2 1999/06/06 19:00:53 ragge 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.
+ * 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.
+ *
+ * @(#)uba.c 7.10 (Berkeley) 12/16/90
+ * @(#)autoconf.c 7.20 (Berkeley) 5/9/91
+ */
+
+#include <sys/param.h>
+#include <sys/device.h>
+#include <sys/systm.h>
+
+#define _VAX_BUS_DMA_PRIVATE
+#include <machine/bus.h>
+#include <machine/mtpr.h>
+#include <machine/nexus.h>
+#include <machine/cpu.h>
+#include <machine/sgmap.h>
+
+#include <arch/vax/qbus/ubavar.h>
+
+#include <arch/vax/uba/uba_common.h>
+
+/* Some Qbus-specific defines */
+#define QBASIZE (8192 * VAX_NBPG)
+#define QBAMAP 0x20088000
+#define QIOPAGE 0x20000000
+
+/*
+ * 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.
+ */
+static int qba_match __P((struct device *, struct cfdata *, void *));
+static void qba_attach __P((struct device *, struct device *, void *));
+static void qba_beforescan __P((struct uba_softc*));
+static void qba_init __P((struct uba_softc*));
+
+struct cfattach uba_mainbus_ca = {
+ sizeof(struct uba_vsoftc), qba_match, qba_attach
+};
+
+extern struct vax_bus_space vax_mem_bus_space;
+
+int
+qba_match(parent, vcf, aux)
+ struct device *parent;
+ struct cfdata *vcf;
+ void *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_vsoftc *sc = (void *)self;
+
+ printf(": Q22\n");
+ /*
+ * Fill in bus specific data.
+ */
+ sc->uv_sc.uh_beforescan = qba_beforescan;
+ sc->uv_sc.uh_ubainit = qba_init;
+ sc->uv_sc.uh_iot = &vax_mem_bus_space;
+ sc->uv_sc.uh_dmat = &sc->uv_dmat;
+
+ /*
+ * Fill in variables used by the sgmap system.
+ */
+ sc->uv_size = QBASIZE; /* Size in bytes of Qbus space */
+ sc->uv_addr = QBAMAP; /* Physical address of map registers */
+
+ uba_dma_init(sc);
+ uba_attach(&sc->uv_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;
+{
+#define QIPCR 0x1f40
+#define Q_LMEAE 0x20
+ bus_space_write_2(sc->uh_tag, sc->uh_ioh, QIPCR, Q_LMEAE);
+}
+
+void
+qba_init(sc)
+ struct uba_softc *sc;
+{
+ mtpr(0, PR_IUR);
+ DELAY(500000);
+ qba_beforescan(sc);
+}
diff --git a/sys/arch/vax/uba/uba_sbi.c b/sys/arch/vax/uba/uba_sbi.c
new file mode 100644
index 00000000000..6941e261e52
--- /dev/null
+++ b/sys/arch/vax/uba/uba_sbi.c
@@ -0,0 +1,327 @@
+/* $OpenBSD: uba_sbi.c,v 1.1 2000/04/27 03:14:51 bjc Exp $ */
+/* $NetBSD: uba_sbi.c,v 1.1 1999/06/21 16:23:01 ragge 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.
+ * 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.
+ *
+ * @(#)uba.c 7.10 (Berkeley) 12/16/90
+ * @(#)autoconf.c 7.20 (Berkeley) 5/9/91
+ */
+
+#include <sys/param.h>
+#include <sys/device.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+
+#define _VAX_BUS_DMA_PRIVATE
+#include <machine/bus.h>
+#include <machine/mtpr.h>
+#include <machine/nexus.h>
+#include <machine/cpu.h>
+#include <machine/sgmap.h>
+#include <machine/scb.h>
+
+#include <arch/vax/qbus/ubavar.h>
+
+#include <arch/vax/uba/uba_common.h>
+
+/* Some SBI-specific defines */
+#define UBASIZE (UBAPAGES * VAX_NBPG)
+#define UMEMA8600(i) (0x20100000+(i)*0x40000)
+#define UMEMB8600(i) (0x22100000+(i)*0x40000)
+
+/*
+ * Some status registers.
+ */
+#define UBACNFGR_UBIC 0x00010000 /* unibus init complete */
+#define UBACNFGR_BITS \
+"\40\40PARFLT\37WSQFLT\36URDFLT\35ISQFLT\34MXTFLT\33XMTFLT\30ADPDN\27ADPUP\23UBINIT\22UBPDN\21UBIC"
+
+#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_ADINIT 0x00000001 /* adapter init */
+
+#define UBADPR_BNE 0x80000000 /* buffer not empty - purge */
+
+#define UBABRRVR_DIV 0x0000ffff /* device interrupt vector field */
+
+#define UBASR_BITS \
+"\20\13RDTO\12RDS\11CRD\10CXTER\7CXTMO\6DPPE\5IVMR\4MRPF\3LEB\2UBSTO\1UBSSYNTO"
+
+char ubasr_bits[] = UBASR_BITS;
+
+/*
+ * The DW780 are directly connected to the SBI on 11/780 and 8600.
+ */
+static int dw780_match __P((struct device *, struct cfdata *, void *));
+static void dw780_attach __P((struct device *, struct device *, void *));
+static void dw780_init __P((struct uba_softc*));
+static void dw780_beforescan __P((struct uba_softc *));
+static void dw780_afterscan __P((struct uba_softc *));
+static int dw780_errchk __P((struct uba_softc *));
+static void uba_dw780int __P((int));
+static void ubaerror __P((struct uba_softc *, int *, int *));
+#ifdef notyet
+static void dw780_purge __P((struct uba_softc *, int));
+#endif
+
+struct cfattach uba_sbi_ca = {
+ sizeof(struct uba_vsoftc), dw780_match, dw780_attach
+};
+
+extern struct vax_bus_space vax_mem_bus_space;
+
+volatile int svec;
+
+int
+dw780_match(parent, cf, aux)
+ struct device *parent;
+ struct cfdata *cf;
+ void *aux;
+{
+ struct sbi_attach_args *sa = (struct sbi_attach_args *)aux;
+
+ 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;
+}
+
+void
+dw780_attach(parent, self, aux)
+ struct device *parent, *self;
+ void *aux;
+{
+ struct uba_vsoftc *sc = (void *)self;
+ struct sbi_attach_args *sa = aux;
+ int ubaddr = sa->type & 3;
+ int i;
+
+ printf(": DW780\n");
+ /*
+ * Fill in bus specific data.
+ */
+ sc->uv_sc.uh_ubainit = dw780_init;
+#ifdef notyet
+ sc->uv_sc.uh_ubapurge = dw780_purge;
+#endif
+ sc->uv_sc.uh_beforescan = dw780_beforescan;
+ sc->uv_sc.uh_afterscan = dw780_afterscan;
+ sc->uv_sc.uh_errchk = dw780_errchk;
+ sc->uv_sc.uh_iot = &vax_mem_bus_space;
+ sc->uv_sc.uh_dmat = &sc->uv_dmat;
+ sc->uv_uba = (void *)sa->nexaddr;
+ sc->uh_ibase = VAX_NBPG + ubaddr * VAX_NBPG;
+
+ /*
+ * Set up dispatch vectors for DW780.
+ */
+ for (i = 0; i < 4; i++)
+ scb_vecalloc(256 + i * 64 + sa->nexnum * 4, uba_dw780int,
+ sc->uv_sc.uh_dev.dv_unit, SCB_ISTACK);
+ /*
+ * Fill in variables used by the sgmap system.
+ */
+ sc->uv_size = UBASIZE; /* Size in bytes of Qbus space */
+ sc->uv_addr = (paddr_t)sc->uv_uba->uba_map;
+
+ uba_dma_init(sc);
+ uba_attach(&sc->uv_sc, (parent->dv_unit ? UMEMB8600(ubaddr) :
+ UMEMA8600(ubaddr)) + (UBAPAGES * VAX_NBPG));
+}
+
+void
+dw780_beforescan(sc)
+ struct uba_softc *sc;
+{
+ struct uba_vsoftc *vc = (void *)sc;
+ volatile int *hej = &vc->uv_uba->uba_sr;
+
+ *hej = *hej;
+ vc->uv_uba->uba_cr = UBACR_IFS|UBACR_BRIE;
+}
+
+void
+dw780_afterscan(sc)
+ struct uba_softc *sc;
+{
+ struct uba_vsoftc *vc = (void *)sc;
+
+ vc->uv_uba->uba_cr = UBACR_IFS | UBACR_BRIE |
+ UBACR_USEFIE | UBACR_SUEFIE |
+ (vc->uv_uba->uba_cr & 0x7c000000);
+}
+
+
+int
+dw780_errchk(sc)
+ struct uba_softc *sc;
+{
+ struct uba_vsoftc *vc = (void *)sc;
+ volatile int *hej = &vc->uv_uba->uba_sr;
+
+ if (*hej) {
+ *hej = *hej;
+ return 1;
+ }
+ return 0;
+}
+
+void
+uba_dw780int(uba)
+ int uba;
+{
+ int br, vec, arg;
+ struct uba_vsoftc *vc = uba_cd.cd_devs[uba];
+ struct uba_regs *ur = vc->uv_uba;
+ void (*func) __P((int));
+
+ br = mfpr(PR_IPL);
+ vec = ur->uba_brrvr[br - 0x14];
+ if (vec <= 0) {
+ ubaerror(&vc->uv_sc, &br, (int *)&vec);
+ if (svec == 0)
+ return;
+ }
+ if (cold)
+ scb_fake(vec + vc->uh_ibase, br);
+ else {
+ struct ivec_dsp *scb_vec = (struct ivec_dsp *)((int)scb + 512);
+ func = scb_vec[vec/4].hoppaddr;
+ arg = scb_vec[vec/4].pushlarg;
+ (*func)(arg);
+ }
+}
+
+void
+dw780_init(sc)
+ struct uba_softc *sc;
+{
+ struct uba_vsoftc *vc = (void *)sc;
+
+ vc->uv_uba->uba_cr = UBACR_ADINIT;
+ vc->uv_uba->uba_cr = UBACR_IFS|UBACR_BRIE|UBACR_USEFIE|UBACR_SUEFIE;
+ while ((vc->uv_uba->uba_cnfgr & UBACNFGR_UBIC) == 0)
+ ;
+}
+
+#ifdef notyet
+void
+dw780_purge(sc, bdp)
+ struct uba_softc *sc;
+ int bdp;
+{
+ struct uba_vsoftc *vc = (void *)sc;
+
+ vc->uv_uba->uba_dpr[bdp] |= UBADPR_BNE;
+}
+#endif
+
+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_vsoftc *vc = (void *)uh;
+ struct uba_regs *uba = vc->uv_uba;
+ register int 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 - vc->uh_zvtime;
+
+ vc->uh_zvtotal++;
+ if (dt > 8) {
+ vc->uh_zvtime = time.tv_sec;
+ vc->uh_zvcnt = 0;
+ }
+ if (++vc->uh_zvcnt > zvcnt_max) {
+ printf("%s: too many zero vectors (%d in <%d sec)\n",
+ vc->uv_sc.uh_dev.dv_xname, vc->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(vc->uv_sc.uh_dev.dv_unit);
+ }
+ return;
+ }
+ if (uba->uba_cnfgr & NEX_CFGFLT) {
+ printf("%s: sbi fault sr=%b cnfgr=%b\n",
+ vc->uv_sc.uh_dev.dv_xname, uba->uba_sr, ubasr_bits,
+ uba->uba_cnfgr, NEXFLT_BITS);
+ ubareset(vc->uv_sc.uh_dev.dv_unit);
+ *uvec = 0;
+ return;
+ }
+ sr = uba->uba_sr;
+ s = splimp();
+ printf("%s: uba error sr=%b fmer=%x fubar=%o\n", vc->uv_sc.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(vc->uv_sc.uh_dev.dv_unit);
+ *uvec = 0;
+ }
+}
diff --git a/sys/arch/vax/uba/ubareg.h b/sys/arch/vax/uba/ubareg.h
index 2dd5b52f4d2..fc882153aff 100644
--- a/sys/arch/vax/uba/ubareg.h
+++ b/sys/arch/vax/uba/ubareg.h
@@ -1,5 +1,5 @@
-/* $OpenBSD: ubareg.h,v 1.7 1997/05/29 00:05:10 niklas Exp $ */
-/* $NetBSD: ubareg.h,v 1.9 1996/08/20 13:38:02 ragge Exp $ */
+/* $OpenBSD: ubareg.h,v 1.8 2000/04/27 03:14:51 bjc Exp $ */
+/* $NetBSD: ubareg.h,v 1.10 1998/10/18 18:51:30 ragge Exp $ */
/*-
* Copyright (c) 1982, 1986 The Regents of the University of California.
@@ -71,10 +71,6 @@
#define QBA 4 /* 22-bit Q-bus, no adaptor regs: uVAX II */
#endif
-#if 0 /* XXX VAX8200 || VAX8500 || VAX8800 */
-#define DWBUA 5 /* BI UNIBUS adaptor: 8200/8500/8800 */
-#endif
-
/*
* Size of unibus memory address space in pages
* (also number of map registers).
@@ -94,57 +90,6 @@
#ifndef _LOCORE
/*
- * DWBUA hardware registers.
- */
-struct dwbua_regs {
- int pad1[456]; /* actually bii regs + pad */
- int bua_csr; /* control and status register */
- int bua_offset; /* vector offset register */
- int bua_fubar; /* failed UNIBUS address register */
- int bua_bifar; /* BI failed address register */
- int bua_udiag[5]; /* micro diagnostics (R/O) */
- int pad2[3];
-/* dpr[0] is for DDP; dpr's 1 through 5 are for BPD's 1 through 5 */
- int bua_dpr[6]; /* data path registers */
- int pad3[10];
- int bua_bdps[20]; /* buffered data path space *//*???*/
- int pad4[8];
- 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 */
-
-/* bua_offset */
-#define BUAOFFSET_MASK 0x00003e00 /* hence max offset = 15872 */
-
-/* bua_dpr */
-#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 */
- /* I see no reason to use either one, though ... act 6 Aug 1987 */
-
-#define UBA_PURGEBUA(uba, bdp) \
- (((struct dwbua_regs *)(uba))->bua_dpr[bdp] |= BUADPR_PURGE)
-#else
-#define UBA_PURGEBUA(uba, bdp)
-#endif
-
-/*
* DW780/DW750 hardware registers
*/
struct uba_regs {
diff --git a/sys/arch/vax/uba/ubavar.h b/sys/arch/vax/uba/ubavar.h
index 55f72ef2d34..24975cd99eb 100644
--- a/sys/arch/vax/uba/ubavar.h
+++ b/sys/arch/vax/uba/ubavar.h
@@ -1,5 +1,5 @@
-/* $OpenBSD: ubavar.h,v 1.7 1997/05/29 00:05:10 niklas Exp $ */
-/* $NetBSD: ubavar.h,v 1.18 1996/08/20 13:38:04 ragge Exp $ */
+/* $OpenBSD: ubavar.h,v 1.8 2000/04/27 03:14:52 bjc Exp $ */
+/* $NetBSD: ubavar.h,v 1.21 1999/01/19 21:04:48 ragge Exp $ */
/*
* Copyright (c) 1982, 1986 Regents of the University of California.
@@ -81,8 +81,6 @@ struct uba_softc {
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 */
short uh_mrwant; /* someone is waiting for map reg */
short uh_bdpwant; /* someone awaits bdp's */
int uh_bdpfree; /* free bdp's */
@@ -99,19 +97,13 @@ 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 */
+ int uh_ibase; /* Base address for vectors */
};
#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.
* The unit struct is common to both the adapter and the controller
@@ -181,14 +173,13 @@ struct ubinfo {
#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 ubasetvec __P((struct device *, int, void (*) __P((int))));
+void uba_attach __P((struct uba_softc *, unsigned long));
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((struct uba_softc *, struct buf *, int));
#endif /* _KERNEL */
#endif !_LOCORE