summaryrefslogtreecommitdiff
path: root/sys/arch/vax/bi
diff options
context:
space:
mode:
authorHugh Graham <hugh@cvs.openbsd.org>2002-06-11 09:36:25 +0000
committerHugh Graham <hugh@cvs.openbsd.org>2002-06-11 09:36:25 +0000
commit10ca5e5818bb80e596db244327a2663b6703bb18 (patch)
treec7ac330b34d73ea4e0c78d17a9eed0a3b6df63aa /sys/arch/vax/bi
parent180b34af9885b092bee0f67c5b2ac8577d972cfe (diff)
New boot code, mostly from ragge's work in NetBSD.
Some header syncing and a couple network drivers came along for the ride. Assembly files have been renamed from .s to .S to facilitate diffs. Kernel is backwards compat - with manual interaction. OpenBSD features have been preserved.
Diffstat (limited to 'sys/arch/vax/bi')
-rw-r--r--sys/arch/vax/bi/bi.c143
-rw-r--r--sys/arch/vax/bi/bireg.h10
-rw-r--r--sys/arch/vax/bi/bivar.h15
-rw-r--r--sys/arch/vax/bi/if_ni.c909
-rw-r--r--sys/arch/vax/bi/if_nireg.h307
-rw-r--r--sys/arch/vax/bi/kdb.c298
-rw-r--r--sys/arch/vax/bi/kdbreg.h4
7 files changed, 1476 insertions, 210 deletions
diff --git a/sys/arch/vax/bi/bi.c b/sys/arch/vax/bi/bi.c
index 11b69b12087..8c49ceaf503 100644
--- a/sys/arch/vax/bi/bi.c
+++ b/sys/arch/vax/bi/bi.c
@@ -1,5 +1,5 @@
-/* $OpenBSD: bi.c,v 1.4 2002/03/14 03:16:02 millert Exp $ */
-/* $NetBSD: bi.c,v 1.4 1996/10/13 03:34:44 christos Exp $ */
+/* $OpenBSD: bi.c,v 1.5 2002/06/11 09:36:23 hugh Exp $ */
+/* $NetBSD: bi.c,v 1.17 2001/11/13 12:51:34 lukem Exp $ */
/*
* Copyright (c) 1996 Ludd, University of Lule}, Sweden.
* All rights reserved.
@@ -41,44 +41,36 @@
* handle BIbus errors more gracefully.
*/
+#include <sys/cdefs.h>
+__KERNEL_RCSID(0, "$NetBSD: bi.c,v 1.17 2001/11/13 12:51:34 lukem Exp $");
+
#include <sys/param.h>
-#include <sys/device.h>
+#include <sys/systm.h>
-#include <machine/mtpr.h>
-#include <machine/nexus.h>
+#include <machine/bus.h>
#include <machine/cpu.h>
-#include <arch/vax/bi/bireg.h>
-#include <arch/vax/bi/bivar.h>
-
-static int bi_match(struct device *, void *, void *);
-static void bi_attach(struct device *, struct device *, void *);
-static int bi_print(void *, const char *);
+#include <dev/bi/bireg.h>
+#include <dev/bi/bivar.h>
-struct cfdriver bi_cd = {
- NULL, "bi", DV_DULL
-};
-
-struct cfattach bi_ca = {
- sizeof(struct bi_softc), bi_match, bi_attach
-};
+static int bi_print __P((void *, const char *));
struct bi_list bi_list[] = {
- {BIDT_MS820, 1, "ms820"},
- {BIDT_DRB32, 0, "drb32"},
- {BIDT_DWBUA, 0, "dwbua"},
- {BIDT_KLESI, 0, "klesi"},
- {BIDT_KA820, 1, "ka820"},
- {BIDT_DB88, 0, "db88"},
- {BIDT_CIBCA, 0, "cibca"},
- {BIDT_DMB32, 0, "dmb32"},
- {BIDT_CIBCI, 0, "cibci"},
- {BIDT_KA800, 0, "ka800"},
- {BIDT_KDB50, 0, "kdb50"},
- {BIDT_DWMBA, 0, "dwmba"},
- {BIDT_KFBTA, 0, "kfbta"},
- {BIDT_DEBNK, 0, "debnk"},
- {BIDT_DEBNA, 0, "debna"},
+ {BIDT_MS820, DT_HAVDRV, "ms820"},
+ {BIDT_DRB32, DT_UNSUPP, "drb32"},
+ {BIDT_DWBUA, DT_HAVDRV|DT_ADAPT, "dwbua"},
+ {BIDT_KLESI, DT_HAVDRV|DT_ADAPT, "klesi"},
+ {BIDT_KA820, DT_HAVDRV, "ka820"},
+ {BIDT_DB88, DT_HAVDRV|DT_QUIET, "db88"},
+ {BIDT_CIBCA, DT_UNSUPP, "cibca"},
+ {BIDT_DMB32, DT_UNSUPP, "dmb32"},
+ {BIDT_CIBCI, DT_UNSUPP, "cibci"},
+ {BIDT_KA800, DT_UNSUPP, "ka800"},
+ {BIDT_KDB50, DT_HAVDRV|DT_VEC, "kdb50"},
+ {BIDT_DWMBA, DT_HAVDRV|DT_QUIET, "dwmba"},
+ {BIDT_KFBTA, DT_UNSUPP, "kfbta"},
+ {BIDT_DEBNK, DT_HAVDRV|DT_VEC, "debnk"},
+ {BIDT_DEBNA, DT_HAVDRV|DT_VEC, "debna"},
{0,0,0}
};
@@ -89,61 +81,70 @@ bi_print(aux, name)
{
struct bi_attach_args *ba = aux;
struct bi_list *bl;
+ u_int16_t nr;
+
+ nr = bus_space_read_2(ba->ba_iot, ba->ba_ioh, 0);
+ for (bl = &bi_list[0]; bl->bl_nr; bl++)
+ if (bl->bl_nr == nr)
+ break;
if (name) {
- for (bl = &bi_list[0]; bl->bl_nr; bl++)
- if (bl->bl_nr == ba->ba_node->biic.bi_dtype) {
- printf(bl->bl_name);
- break;
- }
if (bl->bl_nr == 0)
- printf("unknown device 0x%x",
- ba->ba_node->biic.bi_dtype);
+ printf("unknown device 0x%x", nr);
+ else
+ printf(bl->bl_name);
printf(" at %s", name);
}
printf(" node %d", ba->ba_nodenr);
- return bl->bl_havedriver ? UNCONF : UNSUPP;
-}
-
-int
-bi_match(parent, match, aux)
- struct device *parent;
- void *match, *aux;
-{
- struct bp_conf *bp = aux;
-
- if (strcmp(bp->type, "bi"))
- return 0;
- return 1;
+ if (bl->bl_havedriver & DT_VEC)
+ printf(" vec %o", ba->ba_ivec & 511);
+#ifdef DEBUG
+ if (bus_space_read_4(ba->ba_iot, ba->ba_ioh, BIREG_SADR) &&
+ bus_space_read_4(ba->ba_iot, ba->ba_ioh, BIREG_EADR))
+ printf(" [sadr %x eadr %x]",
+ bus_space_read_4(ba->ba_iot, ba->ba_ioh, BIREG_SADR),
+ bus_space_read_4(ba->ba_iot, ba->ba_ioh, BIREG_EADR));
+#endif
+ if (bl->bl_havedriver & DT_QUIET)
+ printf("\n");
+ return bl->bl_havedriver & DT_QUIET ? QUIET :
+ bl->bl_havedriver & DT_HAVDRV ? UNCONF : UNSUPP;
}
void
-bi_attach(parent, self, aux)
- struct device *parent, *self;
- void *aux;
+bi_attach(sc)
+ struct bi_softc *sc;
{
- struct bp_conf *bp = aux;
- struct bi_softc *bi = (void *)self;
- struct bi_node *binode;
struct bi_attach_args ba;
int nodenr;
printf("\n");
- binode = bi->bi_base = (struct bi_node *)bp->bp_addr;
- ba.ba_intcpu = 1 << mastercpu;
+ ba.ba_iot = sc->sc_iot;
+ ba.ba_busnr = sc->sc_busnr;
+ ba.ba_dmat = sc->sc_dmat;
+ ba.ba_intcpu = sc->sc_intcpu;
+ ba.ba_icookie = sc;
+ /*
+ * Interrupt numbers. Assign them as described in
+ * VAX 8800 system maintenance manual; this means like nexus
+ * adapters have them assigned.
+ * XXX - must address Unibus adapters.
+ */
for (nodenr = 0; nodenr < NNODEBI; nodenr++) {
- if (badaddr((caddr_t)&binode[nodenr], 4))
+ if (bus_space_map(sc->sc_iot, sc->sc_addr + BI_NODE(nodenr),
+ BI_NODESIZE, 0, &ba.ba_ioh)) {
+ printf("bi_attach: bus_space_map failed, node %d\n",
+ nodenr);
+ return;
+ }
+ if (badaddr((caddr_t)ba.ba_ioh, 4) ||
+ (bus_space_read_2(ba.ba_iot, ba.ba_ioh, 0) == 0)) {
+ bus_space_unmap(ba.ba_iot, ba.ba_ioh, BI_NODESIZE);
continue;
-
- ba.ba_node = &binode[nodenr];
+ }
ba.ba_nodenr = nodenr;
- config_found(self, &ba, bi_print);
+ ba.ba_ivec = sc->sc_lastiv + 64 + 4 * nodenr; /* all on spl5 */
+ config_found(&sc->sc_dev, &ba, bi_print);
}
}
-
-void
-bi_buserr()
-{
- panic("bi_buserr");
-}
diff --git a/sys/arch/vax/bi/bireg.h b/sys/arch/vax/bi/bireg.h
index edc75f91ab7..6b9a68d00c1 100644
--- a/sys/arch/vax/bi/bireg.h
+++ b/sys/arch/vax/bi/bireg.h
@@ -1,5 +1,5 @@
-/* $OpenBSD: bireg.h,v 1.3 2000/04/28 03:42:39 bjc Exp $ */
-/* $NetBSD: bireg.h,v 1.6 1999/08/04 19:12:22 ragge Exp $ */
+/* $OpenBSD: bireg.h,v 1.4 2002/06/11 09:36:23 hugh Exp $ */
+/* $NetBSD: bireg.h,v 1.7 2000/07/06 17:47:02 ragge Exp $ */
/*
* Copyright (c) 1988 Regents of the University of California.
* All rights reserved.
@@ -45,8 +45,8 @@
/*
* BI node addresses
*/
-#define NODESIZE 0x2000 /* Size of one BI node */
-#define BI_NODE(node) (NODESIZE * (node))
+#define BI_NODESIZE 0x2000 /* Size of one BI node */
+#define BI_NODE(node) (BI_NODESIZE * (node))
#define BI_BASE(bi,nod) ((0x20000000 + (bi) * 0x2000000) + BI_NODE(nod))
#define MAXNBI 16 /* Spec says there can be 16 anyway */
#define NNODEBI 16 /* 16 nodes per BI */
@@ -60,6 +60,7 @@
*
* 990712: The structs not used anymore due to conversion to bus.h.
*/
+#ifdef notdef
struct biiregs {
u_short bi_dtype; /* device type */
u_short bi_revs; /* revisions */
@@ -101,6 +102,7 @@ struct bi_cpu {
u_long bi_xxx[63]; /* pad */
u_long bi_rxcd; /* receive console data register */
};
+#endif
#define BIREG_DTYPE 0x00
#define BIREG_VAXBICSR 0x04
diff --git a/sys/arch/vax/bi/bivar.h b/sys/arch/vax/bi/bivar.h
index a44ace650fb..ebd21677460 100644
--- a/sys/arch/vax/bi/bivar.h
+++ b/sys/arch/vax/bi/bivar.h
@@ -1,5 +1,5 @@
-/* $OpenBSD: bivar.h,v 1.5 2002/03/14 03:16:02 millert Exp $ */
-/* $NetBSD: bivar.h,v 1.5 2000/03/26 11:45:04 ragge Exp $ */
+/* $OpenBSD: bivar.h,v 1.6 2002/06/11 09:36:23 hugh Exp $ */
+/* $NetBSD: bivar.h,v 1.8 2000/07/26 12:41:40 ragge Exp $ */
/*
* Copyright (c) 1996, 1999 Ludd, University of Lule}, Sweden.
* All rights reserved.
@@ -69,6 +69,13 @@ struct bi_list {
char *bl_name; /* DEC name */
};
+/* bl_havedriver field meaning */
+#define DT_UNSUPP 0 /* pseudo define */
+#define DT_HAVDRV 1 /* device have driver */
+#define DT_ADAPT 2 /* is an adapter */
+#define DT_QUIET 4 /* don't complain when not conf'ed */
+#define DT_VEC 8 /* uses a interrupt vector */
+
/* Prototype */
-void bi_attach(struct bi_softc *);
-void bi_intr_establish(void *, int, void (*)(void *), void *);
+void bi_attach (struct bi_softc *);
+void bi_intr_establish (void *, int, void (*)(void *), void *, struct evcnt *);
diff --git a/sys/arch/vax/bi/if_ni.c b/sys/arch/vax/bi/if_ni.c
new file mode 100644
index 00000000000..414d84968b0
--- /dev/null
+++ b/sys/arch/vax/bi/if_ni.c
@@ -0,0 +1,909 @@
+/* $OpenBSD: if_ni.c,v 1.1 2002/06/11 09:36:23 hugh Exp $ */
+/* $NetBSD: if_ni.c,v 1.15 2002/05/22 16:03:14 wiz Exp $ */
+/*
+ * Copyright (c) 2000 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 DEBNA/DEBNT/DEBNK ethernet cards.
+ * Things that is still to do:
+ * Collect statistics.
+ */
+
+#include <sys/cdefs.h>
+__KERNEL_RCSID(0, "$NetBSD: if_ni.c,v 1.15 2002/05/22 16:03:14 wiz Exp $");
+
+#include "opt_inet.h"
+#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 <sys/sched.h>
+
+#include <net/if.h>
+#include <net/if_ether.h>
+#include <net/if_dl.h>
+
+#include <netinet/in.h>
+#include <netinet/if_inarp.h>
+
+#if NBPFILTER > 0
+#include <net/bpf.h>
+#include <net/bpfdesc.h>
+#endif
+
+#include <machine/bus.h>
+#ifdef __vax__
+#include <machine/mtpr.h>
+#include <machine/pte.h>
+#endif
+
+#include <dev/bi/bireg.h>
+#include <dev/bi/bivar.h>
+
+#include "ioconf.h"
+#include "locators.h"
+
+/*
+ * Tunable buffer parameters. Good idea to have them as power of 8; then
+ * they will fit into a logical VAX page.
+ */
+#define NMSGBUF 8 /* Message queue entries */
+#define NTXBUF 16 /* Transmit queue entries */
+#define NTXFRAGS 8 /* Number of transmit buffer fragments */
+#define NRXBUF 24 /* Receive queue entries */
+#define NBDESCS (NTXBUF * NTXFRAGS + NRXBUF)
+#define NQUEUES 3 /* RX + TX + MSG */
+#define PKTHDR 18 /* Length of (control) packet header */
+#define RXADD 18 /* Additional length of receive datagram */
+#define TXADD (10+NTXFRAGS*8) /* "" transmit "" */
+#define MSGADD 134 /* "" message "" */
+
+#include <dev/bi/if_nireg.h> /* XXX include earlier */
+
+/*
+ * Macros for (most cases of) insqti/remqhi.
+ * Retry NRETRIES times to do the operation, if it still fails assume
+ * a lost lock and panic.
+ */
+#define NRETRIES 100
+#define INSQTI(e, h) ({ \
+ int ret, i; \
+ for (i = 0; i < NRETRIES; i++) { \
+ if ((ret = insqti(e, h)) != ILCK_FAILED) \
+ break; \
+ } \
+ if (i == NRETRIES) \
+ panic("ni: insqti failed at %d", __LINE__); \
+ ret; \
+})
+#define REMQHI(h) ({ \
+ int i;void *ret; \
+ for (i = 0; i < NRETRIES; i++) { \
+ if ((ret = remqhi(h)) != (void *)ILCK_FAILED) \
+ break; \
+ } \
+ if (i == NRETRIES) \
+ panic("ni: remqhi failed at %d", __LINE__); \
+ ret; \
+})
+
+
+#define nipqb (&sc->sc_gvppqb->nc_pqb)
+#define gvp sc->sc_gvppqb
+#define fqb sc->sc_fqb
+#define bbd sc->sc_bbd
+
+struct ni_softc {
+ struct device sc_dev; /* Configuration common part */
+ struct evcnt sc_intrcnt; /* Interrupt coounting */
+ struct ethercom sc_ec; /* Ethernet common part */
+#define sc_if sc_ec.ec_if /* network-visible interface */
+ bus_space_tag_t sc_iot;
+ bus_addr_t sc_ioh;
+ bus_dma_tag_t sc_dmat;
+ struct ni_gvppqb *sc_gvppqb; /* Port queue block */
+ struct ni_gvppqb *sc_pgvppqb; /* Phys address of PQB */
+ struct ni_fqb *sc_fqb; /* Free Queue block */
+ struct ni_bbd *sc_bbd; /* Buffer descriptors */
+ u_int8_t sc_enaddr[ETHER_ADDR_LEN];
+};
+
+static int nimatch __P((struct device *, struct cfdata *, void *));
+static void niattach __P((struct device *, struct device *, void *));
+static void niinit __P((struct ni_softc *));
+static void nistart __P((struct ifnet *));
+static void niintr __P((void *));
+static int niioctl __P((struct ifnet *, u_long, caddr_t));
+static int ni_add_rxbuf(struct ni_softc *, struct ni_dg *, int);
+static void ni_setup __P((struct ni_softc *));
+static void nitimeout __P((struct ifnet *));
+static void ni_shutdown(void *);
+static void ni_getpgs(struct ni_softc *sc, int size, caddr_t *v, paddr_t *p);
+static int failtest(struct ni_softc *, int, int, int, char *);
+
+volatile int endwait, retry; /* Used during autoconfig */
+
+struct cfattach ni_ca = {
+ sizeof(struct ni_softc), nimatch, niattach
+};
+
+#define NI_WREG(csr, val) \
+ bus_space_write_4(sc->sc_iot, sc->sc_ioh, csr, val)
+#define NI_RREG(csr) \
+ bus_space_read_4(sc->sc_iot, sc->sc_ioh, csr)
+
+#define WAITREG(csr,val) while (NI_RREG(csr) & val);
+/*
+ * Check for present device.
+ */
+int
+nimatch(parent, cf, aux)
+ struct device *parent;
+ struct cfdata *cf;
+ void *aux;
+{
+ struct bi_attach_args *ba = aux;
+ u_short type;
+
+ type = bus_space_read_2(ba->ba_iot, ba->ba_ioh, BIREG_DTYPE);
+ if (type != BIDT_DEBNA && type != BIDT_DEBNT && type != BIDT_DEBNK)
+ return 0;
+
+ if (cf->cf_loc[BICF_NODE] != BICF_NODE_DEFAULT &&
+ cf->cf_loc[BICF_NODE] != ba->ba_nodenr)
+ return 0;
+
+ return 1;
+}
+
+/*
+ * Allocate a bunch of descriptor-safe memory.
+ * We need to get the structures from the beginning of its own pages.
+ */
+static void
+ni_getpgs(struct ni_softc *sc, int size, caddr_t *v, paddr_t *p)
+{
+ bus_dma_segment_t seg;
+ int nsegs, error;
+
+ if ((error = bus_dmamem_alloc(sc->sc_dmat, size, NBPG, 0, &seg, 1,
+ &nsegs, BUS_DMA_NOWAIT)) != 0)
+ panic(" unable to allocate memory: error %d", error);
+
+ if ((error = bus_dmamem_map(sc->sc_dmat, &seg, nsegs, size, v,
+ BUS_DMA_NOWAIT|BUS_DMA_COHERENT)) != 0)
+ panic(" unable to map memory: error %d", error);
+
+ if (p)
+ *p = seg.ds_addr;
+ memset(*v, 0, size);
+}
+
+static int
+failtest(struct ni_softc *sc, int reg, int mask, int test, char *str)
+{
+ int i = 100;
+
+ do {
+ DELAY(100000);
+ } while (((NI_RREG(reg) & mask) != test) && --i);
+
+ if (i == 0) {
+ printf("%s: %s\n", sc->sc_dev.dv_xname, str);
+ 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
+niattach(parent, self, aux)
+ struct device *parent, *self;
+ void *aux;
+{
+ struct bi_attach_args *ba = aux;
+ struct ni_softc *sc = (struct ni_softc *)self;
+ struct ifnet *ifp = (struct ifnet *)&sc->sc_if;
+ struct ni_msg *msg;
+ struct ni_ptdb *ptdb;
+ caddr_t va;
+ int i, j, s, res;
+ u_short type;
+
+ type = bus_space_read_2(ba->ba_iot, ba->ba_ioh, BIREG_DTYPE);
+ printf(": DEBN%c\n", type == BIDT_DEBNA ? 'A' : type == BIDT_DEBNT ?
+ 'T' : 'K');
+ sc->sc_iot = ba->ba_iot;
+ sc->sc_ioh = ba->ba_ioh;
+ sc->sc_dmat = ba->ba_dmat;
+
+ bi_intr_establish(ba->ba_icookie, ba->ba_ivec,
+ niintr, sc, &sc->sc_intrcnt);
+ evcnt_attach_dynamic(&sc->sc_intrcnt, EVCNT_TYPE_INTR, NULL,
+ sc->sc_dev.dv_xname, "intr");
+
+ ni_getpgs(sc, sizeof(struct ni_gvppqb), (caddr_t *)&sc->sc_gvppqb,
+ (paddr_t *)&sc->sc_pgvppqb);
+ ni_getpgs(sc, sizeof(struct ni_fqb), (caddr_t *)&sc->sc_fqb, 0);
+ ni_getpgs(sc, NBDESCS * sizeof(struct ni_bbd),
+ (caddr_t *)&sc->sc_bbd, 0);
+ /*
+ * Zero the newly allocated memory.
+ */
+
+ nipqb->np_veclvl = (ba->ba_ivec << 2) + 2;
+ nipqb->np_node = ba->ba_intcpu;
+ nipqb->np_vpqb = (u_int32_t)gvp;
+#ifdef __vax__
+ nipqb->np_spt = nipqb->np_gpt = mfpr(PR_SBR);
+ nipqb->np_sptlen = nipqb->np_gptlen = mfpr(PR_SLR);
+#else
+#error Must fix support for non-vax.
+#endif
+ nipqb->np_bvplvl = 1;
+ nipqb->np_vfqb = (u_int32_t)fqb;
+ nipqb->np_vbdt = (u_int32_t)bbd;
+ nipqb->np_nbdr = NBDESCS;
+
+ /* Free queue block */
+ nipqb->np_freeq = NQUEUES;
+ fqb->nf_mlen = PKTHDR+MSGADD;
+ fqb->nf_dlen = PKTHDR+TXADD;
+ fqb->nf_rlen = PKTHDR+RXADD;
+
+ 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 = nistart;
+ ifp->if_ioctl = niioctl;
+ ifp->if_watchdog = nitimeout;
+ IFQ_SET_READY(&ifp->if_snd);
+
+ /*
+ * Start init sequence.
+ */
+
+ /* Reset the node */
+ NI_WREG(BIREG_VAXBICSR, NI_RREG(BIREG_VAXBICSR) | BICSR_NRST);
+ DELAY(500000);
+ i = 20;
+ while ((NI_RREG(BIREG_VAXBICSR) & BICSR_BROKE) && --i)
+ DELAY(500000);
+ if (i == 0) {
+ printf("%s: BROKE bit set after reset\n", sc->sc_dev.dv_xname);
+ return;
+ }
+
+ /* Check state */
+ if (failtest(sc, NI_PSR, PSR_STATE, PSR_UNDEF, "not undefined state"))
+ return;
+
+ /* Clear owner bits */
+ NI_WREG(NI_PSR, NI_RREG(NI_PSR) & ~PSR_OWN);
+ NI_WREG(NI_PCR, NI_RREG(NI_PCR) & ~PCR_OWN);
+
+ /* kick off init */
+ NI_WREG(NI_PCR, (u_int32_t)sc->sc_pgvppqb | PCR_INIT | PCR_OWN);
+ while (NI_RREG(NI_PCR) & PCR_OWN)
+ DELAY(100000);
+
+ /* Check state */
+ if (failtest(sc, NI_PSR, PSR_INITED, PSR_INITED, "failed initialize"))
+ return;
+
+ NI_WREG(NI_PSR, NI_RREG(NI_PSR) & ~PSR_OWN);
+
+ WAITREG(NI_PCR, PCR_OWN);
+ NI_WREG(NI_PCR, PCR_OWN|PCR_ENABLE);
+ WAITREG(NI_PCR, PCR_OWN);
+ WAITREG(NI_PSR, PSR_OWN);
+
+ /* Check state */
+ if (failtest(sc, NI_PSR, PSR_STATE, PSR_ENABLED, "failed enable"))
+ return;
+
+ NI_WREG(NI_PSR, NI_RREG(NI_PSR) & ~PSR_OWN);
+
+ /*
+ * The message queue packets must be located on the beginning
+ * of a page. A VAX page is 512 bytes, but it clusters 8 pages.
+ * This knowledge is used here when allocating pages.
+ * !!! How should this be done on MIPS and Alpha??? !!!
+ */
+#if NBPG < 4096
+#error pagesize too small
+#endif
+ s = splvm();
+ /* Set up message free queue */
+ ni_getpgs(sc, NMSGBUF * 512, &va, 0);
+ for (i = 0; i < NMSGBUF; i++) {
+ struct ni_msg *msg;
+
+ msg = (void *)(va + i * 512);
+
+ res = INSQTI(msg, &fqb->nf_mforw);
+ }
+ WAITREG(NI_PCR, PCR_OWN);
+ NI_WREG(NI_PCR, PCR_FREEQNE|PCR_MFREEQ|PCR_OWN);
+ WAITREG(NI_PCR, PCR_OWN);
+
+ /* Set up xmit queue */
+ ni_getpgs(sc, NTXBUF * 512, &va, 0);
+ for (i = 0; i < NTXBUF; i++) {
+ struct ni_dg *data;
+
+ data = (void *)(va + i * 512);
+ data->nd_status = 0;
+ data->nd_len = TXADD;
+ data->nd_ptdbidx = 1;
+ data->nd_opcode = BVP_DGRAM;
+ for (j = 0; j < NTXFRAGS; j++) {
+ data->bufs[j]._offset = 0;
+ data->bufs[j]._key = 1;
+ bbd[i * NTXFRAGS + j].nb_key = 1;
+ bbd[i * NTXFRAGS + j].nb_status = 0;
+ data->bufs[j]._index = i * NTXFRAGS + j;
+ }
+ res = INSQTI(data, &fqb->nf_dforw);
+ }
+ WAITREG(NI_PCR, PCR_OWN);
+ NI_WREG(NI_PCR, PCR_FREEQNE|PCR_DFREEQ|PCR_OWN);
+ WAITREG(NI_PCR, PCR_OWN);
+
+ /* recv buffers */
+ ni_getpgs(sc, NRXBUF * 512, &va, 0);
+ for (i = 0; i < NRXBUF; i++) {
+ struct ni_dg *data;
+ int idx;
+
+ data = (void *)(va + i * 512);
+ data->nd_len = RXADD;
+ data->nd_opcode = BVP_DGRAMRX;
+ data->nd_ptdbidx = 2;
+ data->bufs[0]._key = 1;
+
+ idx = NTXBUF * NTXFRAGS + i;
+ if (ni_add_rxbuf(sc, data, idx))
+ panic("niattach: ni_add_rxbuf: out of mbufs");
+
+ res = INSQTI(data, &fqb->nf_rforw);
+ }
+ WAITREG(NI_PCR, PCR_OWN);
+ NI_WREG(NI_PCR, PCR_FREEQNE|PCR_RFREEQ|PCR_OWN);
+ WAITREG(NI_PCR, PCR_OWN);
+
+ splx(s);
+
+ /* Set initial parameters */
+ msg = REMQHI(&fqb->nf_mforw);
+
+ msg->nm_opcode = BVP_MSG;
+ msg->nm_status = 0;
+ msg->nm_len = sizeof(struct ni_param) + 6;
+ msg->nm_opcode2 = NI_WPARAM;
+ ((struct ni_param *)&msg->nm_text[0])->np_flags = NP_PAD;
+
+ endwait = retry = 0;
+ res = INSQTI(msg, &gvp->nc_forw0);
+
+retry: WAITREG(NI_PCR, PCR_OWN);
+ NI_WREG(NI_PCR, PCR_CMDQNE|PCR_CMDQ0|PCR_OWN);
+ WAITREG(NI_PCR, PCR_OWN);
+ i = 1000;
+ while (endwait == 0 && --i)
+ DELAY(10000);
+
+ if (endwait == 0) {
+ if (++retry < 3)
+ goto retry;
+ printf("%s: no response to set params\n", sc->sc_dev.dv_xname);
+ return;
+ }
+
+ /* Clear counters */
+ msg = REMQHI(&fqb->nf_mforw);
+ msg->nm_opcode = BVP_MSG;
+ msg->nm_status = 0;
+ msg->nm_len = sizeof(struct ni_param) + 6;
+ msg->nm_opcode2 = NI_RCCNTR;
+
+ res = INSQTI(msg, &gvp->nc_forw0);
+
+ WAITREG(NI_PCR, PCR_OWN);
+ NI_WREG(NI_PCR, PCR_CMDQNE|PCR_CMDQ0|PCR_OWN);
+ WAITREG(NI_PCR, PCR_OWN);
+
+ /* Enable transmit logic */
+ msg = REMQHI(&fqb->nf_mforw);
+
+ msg->nm_opcode = BVP_MSG;
+ msg->nm_status = 0;
+ msg->nm_len = 18;
+ msg->nm_opcode2 = NI_STPTDB;
+ ptdb = (struct ni_ptdb *)&msg->nm_text[0];
+ memset(ptdb, 0, sizeof(struct ni_ptdb));
+ ptdb->np_index = 1;
+ ptdb->np_fque = 1;
+
+ res = INSQTI(msg, &gvp->nc_forw0);
+
+ WAITREG(NI_PCR, PCR_OWN);
+ NI_WREG(NI_PCR, PCR_CMDQNE|PCR_CMDQ0|PCR_OWN);
+ WAITREG(NI_PCR, PCR_OWN);
+
+ /* Wait for everything to finish */
+ WAITREG(NI_PSR, PSR_OWN);
+
+ printf("%s: hardware address %s\n", sc->sc_dev.dv_xname,
+ ether_sprintf(sc->sc_enaddr));
+
+ /*
+ * Attach the interface.
+ */
+ if_attach(ifp);
+ ether_ifattach(ifp, sc->sc_enaddr);
+ if (shutdownhook_establish(ni_shutdown, sc) == 0)
+ printf("%s: WARNING: unable to establish shutdown hook\n",
+ sc->sc_dev.dv_xname);
+}
+
+/*
+ * Initialization of interface.
+ */
+void
+niinit(sc)
+ struct ni_softc *sc;
+{
+ struct ifnet *ifp = (struct ifnet *)&sc->sc_if;
+
+ /*
+ * Set flags (so ni_setup() do the right thing).
+ */
+ ifp->if_flags |= IFF_RUNNING;
+ ifp->if_flags &= ~IFF_OACTIVE;
+
+ /*
+ * Send setup messages so that the rx/tx locic starts.
+ */
+ ni_setup(sc);
+
+}
+
+/*
+ * Start output on interface.
+ */
+void
+nistart(ifp)
+ struct ifnet *ifp;
+{
+ struct ni_softc *sc = ifp->if_softc;
+ struct ni_dg *data;
+ struct ni_bbd *bdp;
+ struct mbuf *m, *m0;
+ int i, cnt, res, mlen;
+
+ if (ifp->if_flags & IFF_OACTIVE)
+ return;
+#ifdef DEBUG
+ if (ifp->if_flags & IFF_DEBUG)
+ printf("%s: nistart\n", sc->sc_dev.dv_xname);
+#endif
+
+ while (fqb->nf_dforw) {
+ IFQ_POLL(&ifp->if_snd, m);
+ if (m == 0)
+ break;
+
+ data = REMQHI(&fqb->nf_dforw);
+ if ((int)data == Q_EMPTY) {
+ ifp->if_flags |= IFF_OACTIVE;
+ break;
+ }
+
+ IFQ_DEQUEUE(&ifp->if_snd, m);
+
+ /*
+ * Count number of mbufs in chain.
+ * Always do DMA directly from mbufs, therefore the transmit
+ * ring is really big.
+ */
+ for (m0 = m, cnt = 0; m0; m0 = m0->m_next)
+ if (m0->m_len)
+ cnt++;
+ if (cnt > NTXFRAGS)
+ panic("nistart"); /* XXX */
+
+#if NBPFILTER > 0
+ if (ifp->if_bpf)
+ bpf_mtap(ifp->if_bpf, m);
+#endif
+ bdp = &bbd[(data->bufs[0]._index & 0x7fff)];
+ for (m0 = m, i = 0, mlen = 0; m0; m0 = m0->m_next) {
+ if (m0->m_len == 0)
+ continue;
+ bdp->nb_status = (mtod(m0, u_int32_t) & NIBD_OFFSET) |
+ NIBD_VALID;
+ bdp->nb_pte = (u_int32_t)kvtopte(mtod(m0, void *));
+ bdp->nb_len = m0->m_len;
+ data->bufs[i]._offset = 0;
+ data->bufs[i]._len = bdp->nb_len;
+ data->bufs[i]._index |= NIDG_CHAIN;
+ mlen += bdp->nb_len;
+ bdp++;
+ i++;
+ }
+ data->nd_opcode = BVP_DGRAM;
+ data->nd_pad3 = 1;
+ data->nd_ptdbidx = 1;
+ data->nd_len = 10 + i * 8;
+ data->bufs[i - 1]._index &= ~NIDG_CHAIN;
+ if (mlen < 64)
+ data->bufs[i - 1]._len = bdp[-1].nb_len += (64 - mlen);
+ data->nd_cmdref = (u_int32_t)m;
+#ifdef DEBUG
+ if (ifp->if_flags & IFF_DEBUG)
+ printf("%s: sending %d bytes (%d segments)\n",
+ sc->sc_dev.dv_xname, mlen, i);
+#endif
+
+ res = INSQTI(data, &gvp->nc_forw0);
+ if (res == Q_EMPTY) {
+ WAITREG(NI_PCR, PCR_OWN);
+ NI_WREG(NI_PCR, PCR_CMDQNE|PCR_CMDQ0|PCR_OWN);
+ }
+ }
+}
+
+void
+niintr(void *arg)
+{
+ struct ni_softc *sc = arg;
+ struct ni_dg *data;
+ struct ni_msg *msg;
+ struct ifnet *ifp = &sc->sc_if;
+ struct ni_bbd *bd;
+ struct mbuf *m;
+ int idx, res;
+
+ if ((NI_RREG(NI_PSR) & PSR_STATE) != PSR_ENABLED)
+ return;
+
+ if ((NI_RREG(NI_PSR) & PSR_ERR))
+ printf("%s: PSR %x\n", sc->sc_dev.dv_xname, NI_RREG(NI_PSR));
+
+ KERNEL_LOCK(LK_CANRECURSE|LK_EXCLUSIVE);
+ /* Got any response packets? */
+ while ((NI_RREG(NI_PSR) & PSR_RSQ) && (data = REMQHI(&gvp->nc_forwr))) {
+
+ switch (data->nd_opcode) {
+ case BVP_DGRAMRX: /* Receive datagram */
+ idx = data->bufs[0]._index;
+ bd = &bbd[idx];
+ m = (void *)data->nd_cmdref;
+ m->m_pkthdr.len = m->m_len =
+ data->bufs[0]._len - ETHER_CRC_LEN;
+ m->m_pkthdr.rcvif = ifp;
+ if (ni_add_rxbuf(sc, data, idx)) {
+ bd->nb_len = (m->m_ext.ext_size - 2);
+ bd->nb_pte =
+ (long)kvtopte(m->m_ext.ext_buf);
+ bd->nb_status = 2 | NIBD_VALID;
+ bd->nb_key = 1;
+ }
+ data->nd_len = RXADD;
+ data->nd_status = 0;
+ res = INSQTI(data, &fqb->nf_rforw);
+ if (res == Q_EMPTY) {
+ WAITREG(NI_PCR, PCR_OWN);
+ NI_WREG(NI_PCR, PCR_FREEQNE|PCR_RFREEQ|PCR_OWN);
+ }
+ if (m == (void *)data->nd_cmdref)
+ break; /* Out of mbufs */
+
+#if NBPFILTER > 0
+ if (ifp->if_bpf)
+ bpf_mtap(ifp->if_bpf, m);
+#endif
+ (*ifp->if_input)(ifp, m);
+ break;
+
+ case BVP_DGRAM:
+ m = (struct mbuf *)data->nd_cmdref;
+ ifp->if_flags &= ~IFF_OACTIVE;
+ m_freem(m);
+ res = INSQTI(data, &fqb->nf_dforw);
+ if (res == Q_EMPTY) {
+ WAITREG(NI_PCR, PCR_OWN);
+ NI_WREG(NI_PCR, PCR_FREEQNE|PCR_DFREEQ|PCR_OWN);
+ }
+ break;
+
+ case BVP_MSGRX:
+ msg = (struct ni_msg *)data;
+ switch (msg->nm_opcode2) {
+ case NI_WPARAM:
+ memcpy(sc->sc_enaddr, ((struct ni_param *)&msg->nm_text[0])->np_dpa, ETHER_ADDR_LEN);
+ endwait = 1;
+ break;
+
+ case NI_RCCNTR:
+ case NI_CLPTDB:
+ case NI_STPTDB:
+ break;
+
+ default:
+ printf("Unkn resp %d\n",
+ msg->nm_opcode2);
+ break;
+ }
+ res = INSQTI(data, &fqb->nf_mforw);
+ if (res == Q_EMPTY) {
+ WAITREG(NI_PCR, PCR_OWN);
+ NI_WREG(NI_PCR, PCR_FREEQNE|PCR_MFREEQ|PCR_OWN);
+ }
+ break;
+
+ default:
+ printf("Unknown opcode %d\n", data->nd_opcode);
+ res = INSQTI(data, &fqb->nf_mforw);
+ if (res == Q_EMPTY) {
+ WAITREG(NI_PCR, PCR_OWN);
+ NI_WREG(NI_PCR, PCR_FREEQNE|PCR_MFREEQ|PCR_OWN);
+ }
+ }
+ }
+
+ /* Try to kick on the start routine again */
+ nistart(ifp);
+
+ NI_WREG(NI_PSR, NI_RREG(NI_PSR) & ~(PSR_OWN|PSR_RSQ));
+ KERNEL_UNLOCK();
+}
+
+/*
+ * Process an ioctl request.
+ */
+int
+niioctl(ifp, cmd, data)
+ register struct ifnet *ifp;
+ u_long cmd;
+ caddr_t data;
+{
+ struct ni_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:
+ niinit(sc);
+ arp_ifinit(ifp, 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.
+ */
+ ifp->if_flags &= ~IFF_RUNNING;
+ ni_setup(sc);
+ } 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.
+ */
+ niinit(sc);
+ } else if ((ifp->if_flags & IFF_UP) != 0) {
+ /*
+ * Send a new setup packet to match any new changes.
+ * (Like IFF_PROMISC etc)
+ */
+ ni_setup(sc);
+ }
+ break;
+
+ case SIOCADDMULTI:
+ case SIOCDELMULTI:
+ /*
+ * Update our multicast list.
+ */
+ error = (cmd == SIOCADDMULTI) ?
+ ether_addmulti(ifr, &sc->sc_ec):
+ ether_delmulti(ifr, &sc->sc_ec);
+
+ if (error == ENETRESET) {
+ /*
+ * Multicast list has changed; set the hardware filter
+ * accordingly.
+ */
+ ni_setup(sc);
+ error = 0;
+ }
+ break;
+
+ default:
+ error = EINVAL;
+
+ }
+ splx(s);
+ return (error);
+}
+
+/*
+ * Add a receive buffer to the indicated descriptor.
+ */
+int
+ni_add_rxbuf(struct ni_softc *sc, struct ni_dg *data, int idx)
+{
+ struct ni_bbd *bd = &bbd[idx];
+ struct mbuf *m;
+
+ 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);
+ }
+
+ m->m_data += 2;
+ bd->nb_len = (m->m_ext.ext_size - 2);
+ bd->nb_pte = (long)kvtopte(m->m_ext.ext_buf);
+ bd->nb_status = 2 | NIBD_VALID;
+ bd->nb_key = 1;
+
+ data->bufs[0]._offset = 0;
+ data->bufs[0]._len = bd->nb_len;
+ data->bufs[0]._index = idx;
+ data->nd_cmdref = (long)m;
+
+ return (0);
+}
+
+/*
+ * Create setup packet and put in queue for sending.
+ */
+void
+ni_setup(struct ni_softc *sc)
+{
+ struct ifnet *ifp = &sc->sc_if;
+ struct ni_msg *msg;
+ struct ni_ptdb *ptdb;
+ struct ether_multi *enm;
+ struct ether_multistep step;
+ int i, res;
+
+ msg = REMQHI(&fqb->nf_mforw);
+ if ((int)msg == Q_EMPTY)
+ return; /* What to do? */
+
+ ptdb = (struct ni_ptdb *)&msg->nm_text[0];
+ memset(ptdb, 0, sizeof(struct ni_ptdb));
+
+ msg->nm_opcode = BVP_MSG;
+ msg->nm_len = 18;
+ ptdb->np_index = 2; /* definition type index */
+ ptdb->np_fque = 2; /* Free queue */
+ if (ifp->if_flags & IFF_RUNNING) {
+ msg->nm_opcode2 = NI_STPTDB;
+ ptdb->np_type = ETHERTYPE_IP;
+ ptdb->np_flags = PTDB_UNKN|PTDB_BDC;
+ if (ifp->if_flags & IFF_PROMISC)
+ ptdb->np_flags |= PTDB_PROMISC;
+ memset(ptdb->np_mcast[0], 0xff, ETHER_ADDR_LEN); /* Broadcast */
+ ptdb->np_adrlen = 1;
+ msg->nm_len += 8;
+ ifp->if_flags &= ~IFF_ALLMULTI;
+ if ((ifp->if_flags & IFF_PROMISC) == 0) {
+ ETHER_FIRST_MULTI(step, &sc->sc_ec, enm);
+ i = 1;
+ while (enm != NULL) {
+ if (memcmp(enm->enm_addrlo, enm->enm_addrhi, 6)) {
+ ifp->if_flags |= IFF_ALLMULTI;
+ ptdb->np_flags |= PTDB_AMC;
+ break;
+ }
+ msg->nm_len += 8;
+ ptdb->np_adrlen++;
+ memcpy(ptdb->np_mcast[i++], enm->enm_addrlo,
+ ETHER_ADDR_LEN);
+ ETHER_NEXT_MULTI(step, enm);
+ }
+ }
+ } else
+ msg->nm_opcode2 = NI_CLPTDB;
+
+ res = INSQTI(msg, &gvp->nc_forw0);
+ if (res == Q_EMPTY) {
+ WAITREG(NI_PCR, PCR_OWN);
+ NI_WREG(NI_PCR, PCR_CMDQNE|PCR_CMDQ0|PCR_OWN);
+ }
+}
+
+/*
+ * Check for dead transmit logic. Not uncommon.
+ */
+void
+nitimeout(ifp)
+ struct ifnet *ifp;
+{
+#if 0
+ struct ni_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?
+ */
+ niinit(sc);
+#endif
+}
+
+/*
+ * Shutdown hook. Make sure the interface is stopped at reboot.
+ */
+void
+ni_shutdown(arg)
+ void *arg;
+{
+ struct ni_softc *sc = arg;
+
+ WAITREG(NI_PCR, PCR_OWN);
+ NI_WREG(NI_PCR, PCR_OWN|PCR_SHUTDOWN);
+ WAITREG(NI_PCR, PCR_OWN);
+ WAITREG(NI_PSR, PSR_OWN);
+
+}
+
diff --git a/sys/arch/vax/bi/if_nireg.h b/sys/arch/vax/bi/if_nireg.h
new file mode 100644
index 00000000000..84abcac4e90
--- /dev/null
+++ b/sys/arch/vax/bi/if_nireg.h
@@ -0,0 +1,307 @@
+/* $OpenBSD: if_nireg.h,v 1.1 2002/06/11 09:36:23 hugh Exp $ */
+/* $NetBSD: if_nireg.h,v 1.3 2001/08/20 12:20:07 wiz Exp $ */
+/*
+ * Copyright (c) 1988 Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)nireg.h 7.3 (Berkeley) 6/28/90
+ */
+
+/*
+ * Registers for the DEBNA and DEBNK Ethernet interfaces
+ * (DEC calls these Network Interfaces, hence nireg.h)
+ */
+
+/*
+ * this seems to be intended to be more general, but I have no details,
+ * so it goes here for now
+ *
+ * BI Vax Port (BVP) stuff first:
+ */
+#ifdef notdef
+struct bvpregs {
+ u_long p_pcr; /* port control register */
+ u_long p_psr; /* port status register */
+ u_long p_per; /* port error register */
+ u_long p_pdr; /* port data register */
+};
+
+/*
+ * BI node space registers
+ */
+struct ni_regs {
+ struct biiregs ni_bi; /* BIIC registers, except GPRs */
+ struct bvpregs ni_tkp; /* tk50 port control via BIIC GPRs */
+ u_long ni_xxx[64]; /* unused */
+ u_long ni_rxcd; /* receive console data */
+ struct bvpregs ni_nip; /* NI port control via BCI3 GPRs */
+ u_long ni_pudr; /* power-up diagnostic register */
+};
+#endif
+
+#define NI_PCR 0x204
+#define NI_PSR 0x208
+#define NI_PER 0x20c
+#define NI_PDR 0x210
+#define NI_PUDR 0x204
+
+/* bits in PCR */
+#define PCR_OWN 0x80
+#define PCR_MFREEQ 0x000
+#define PCR_DFREEQ 0x100
+#define PCR_RFREEQ 0x200
+#define PCR_IFREEQ 0x300
+#define PCR_CMDQ0 PCR_MFREEQ
+#define PCR_CMDQ1 PCR_DFREEQ
+#define PCR_CMDQ2 PCR_RFREEQ
+#define PCR_CMDQ3 PCR_IFREEQ
+#define PCR_RESTART 11
+#define PCR_FREEQNE 7
+#define PCR_CMDQNE 6
+#define PCR_SHUTDOWN 4
+#define PCR_ENABLE 2
+#define PCR_INIT 1
+
+/* bits in PSR */
+#define PSR_OWN 0x80000000
+#define PSR_STATE 0x00070000
+#define PSR_STOPPED 0x00060000
+#define PSR_ENABLED 0x00040000
+#define PSR_INITED 0x00020000
+#define PSR_UNDEF 0x00010000
+#define PSR_RSQ 0x00000080
+#define PSR_ERR 0x00000040
+
+/*
+ * The DEBNx uses a very weird (set of) structure(s) to communicate
+ * with something as simple as an ethernet controller. This is not
+ * very different to the way communication is done over CI with disks.
+ */
+
+/* Message packet */
+struct ni_msg {
+ u_int32_t nm_forw;
+ u_int32_t nm_back;
+ u_int32_t nm_pad1;
+ u_int8_t nm_pad2;
+ u_int8_t nm_status;
+ u_int8_t nm_opcode;
+ u_int8_t nm_pad3;
+ u_int16_t nm_len;
+ u_int8_t nm_opcode2;
+ u_int8_t nm_status2;
+ u_int32_t nm_pad4;
+ u_int8_t nm_text[128];
+};
+
+/* Datagram packet */
+struct ni_dg {
+ u_int32_t nd_forw;
+ u_int32_t nd_back;
+ u_int32_t nd_pad1;
+ u_int8_t nd_pad2;
+ u_int8_t nd_status;
+ u_int8_t nd_opcode;
+ u_int8_t nd_pad3;
+ u_int16_t nd_len;
+ u_int16_t nd_status2;
+ u_int32_t nd_cmdref;
+ u_int32_t nd_ptdbidx;
+ struct {
+ u_int16_t _offset;
+ u_int16_t _len;
+ u_int16_t _index;
+ u_int16_t _key;
+ } bufs[NTXFRAGS];
+};
+
+#define NIDG_CHAIN 0x8000
+
+/* NI parameter block */
+struct ni_param {
+ u_int8_t np_dpa[8];
+ u_int8_t np_apa[8];
+ u_int8_t np_lsa[8];
+ u_int8_t np_bvc[8];
+ u_int16_t np_curaddr;
+ u_int16_t np_maxaddr;
+ u_int16_t np_curptt;
+ u_int16_t np_maxptt;
+ u_int16_t np_curfq;
+ u_int16_t np_maxfq;
+ u_int32_t np_sid;
+ u_int32_t np_mop;
+ u_int32_t np_flags;
+ u_int32_t np_rcto;
+ u_int32_t np_xmto;
+};
+
+#define NP_ECT 0x01
+#define NP_PAD 0x02
+#define NP_BOO 0x04
+#define NP_CAR 0x08
+#define NP_ILP 0x10
+#define NP_ELP 0x20
+#define NP_DCRC 0x40
+#define NP_THRU 0x80
+
+/* Protocol type definition block */
+struct ni_ptdb {
+ u_int16_t np_type; /* Protocol type */
+ u_int8_t np_fque; /* Free queue */
+ u_int8_t np_flags; /* See below */
+ u_int32_t np_index; /* protocol type index */
+ u_int16_t np_adrlen; /* # of multicast addresses */
+ u_int16_t np_802; /* for IEEE 802 packets */
+ u_int8_t np_mcast[16][8];/* Multicast (direct match) array */
+};
+
+#define PTDB_PROMISC 0x08
+#define PTDB_802 0x10
+#define PTDB_BDC 0x20
+#define PTDB_UNKN 0x40
+#define PTDB_AMC 0x80
+
+/* Buffer descriptor */
+struct ni_bbd {
+ u_int16_t nb_status; /* Offset, valid etc */
+ u_int16_t nb_key;
+ u_int32_t nb_len; /* Buffer length */
+ u_int32_t nb_pte; /* start (vax) PTE for this buffer */
+ u_int32_t nb_pad;
+};
+#define NIBD_OFFSET 0x1ff
+#define NIBD_VALID 0x8000
+
+
+/* Free Queue Block */
+struct ni_fqb {
+ u_int32_t nf_mlen;
+ u_int32_t nf_mpad;
+ u_int32_t nf_mforw;
+ u_int32_t nf_mback;
+ u_int32_t nf_dlen;
+ u_int32_t nf_dpad;
+ u_int32_t nf_dforw;
+ u_int32_t nf_dback;
+ u_int32_t nf_rlen;
+ u_int32_t nf_rpad;
+ u_int32_t nf_rforw;
+ u_int32_t nf_rback;
+ u_int32_t nf_ilen;
+ u_int32_t nf_ipad;
+ u_int32_t nf_iforw;
+ u_int32_t nf_iback;
+};
+
+/* DEBNx specific part of Generic VAX Port */
+struct ni_pqb {
+ u_int16_t np_veclvl; /* Interrupt vector + level */
+ u_int16_t np_node; /* Where to interrupt */
+ u_int32_t np_freeq;
+ u_int32_t np_vfqb; /* Free queue block pointer */
+ u_int32_t np_pad1[39];
+ u_int32_t np_bvplvl;
+ u_int32_t np_vpqb; /* Virtual address of Generic PQB */
+ u_int32_t np_vbdt; /* Virtual address of descriptors */
+ u_int32_t np_nbdr; /* Number of descriptors */
+ u_int32_t np_spt; /* System Page Table */
+ u_int32_t np_sptlen; /* System Page Table length */
+ u_int32_t np_gpt; /* Global Page Table */
+ u_int32_t np_gptlen; /* Global Page Table length */
+ u_int32_t np_mask;
+ u_int32_t np_pad2[67];
+};
+
+/* "Generic VAX Port Control Block" whatever it means */
+struct ni_gvppqb {
+ u_int32_t nc_forw0;
+ u_int32_t nc_back0;
+ u_int32_t nc_forw1;
+ u_int32_t nc_back1;
+ u_int32_t nc_forw2;
+ u_int32_t nc_back2;
+ u_int32_t nc_forw3;
+ u_int32_t nc_back3;
+ u_int32_t nc_forwr;
+ u_int32_t nc_backr;
+ struct ni_pqb nc_pqb; /* DEBNx specific part of struct */
+};
+
+
+/* BVP opcodes, should be somewhere else */
+#define BVP_DGRAM 1
+#define BVP_MSG 2
+#define BVP_DGRAMI 3
+#define BVP_DGRAMRX 33
+#define BVP_MSGRX 34
+#define BVP_DGRAMIRX 35
+
+/* NI-specific sub-opcodes */
+#define NI_WSYSID 1
+#define NI_RSYSID 2
+#define NI_WPARAM 3
+#define NI_RPARAM 4
+#define NI_RCCNTR 5
+#define NI_RDCNTR 6
+#define NI_STPTDB 7
+#define NI_CLPTDB 8
+
+/* bits in ni_pudr */
+#define PUDR_TAPE 0x40000000 /* tk50 & assoc logic ok */
+#define PUDR_PATCH 0x20000000 /* patch logic ok */
+#define PUDR_VRAM 0x10000000 /* DEBNx onboard RAM ok */
+#define PUDR_VROM1 0x08000000 /* uVax ROM 1 ok */ /* ? */
+#define PUDR_VROM2 0x04000000 /* uVax ROM 2 ok */
+#define PUDR_VROM3 0x02000000 /* uVax ROM 3 ok */
+#define PUDR_VROM4 0x01000000 /* uVax ROM 4 ok */
+#define PUDR_UVAX 0x00800000 /* uVax passes self test */
+#define PUDR_BI 0x00400000 /* BIIC and BCI3 chips ok */
+#define PUDR_TMR 0x00200000 /* interval timer ok */
+#define PUDR_IRQ 0x00100000 /* no IRQ lines stuck */
+#define PUDR_NI 0x00080000 /* Ethernet ctlr ok */
+#define PUDR_TK50 0x00040000 /* tk50 present */
+#define PUDR_PRES 0x00001000 /* tk50 present (again?!) */
+#define PUDR_UVINT 0x00000800 /* uVax-to-80186 intr logic ok */
+#define PUDR_BUSHD 0x00000400 /* no bus hold errors */
+#define PUDR_II32 0x00000200 /* II32 transceivers ok */
+#define PUDR_MPSC 0x00000100 /* MPSC logic ok */
+#define PUDR_GAP 0x00000080 /* gap-detect logic ok */
+#define PUDR_MISC 0x00000040 /* misc. registers ok */
+#define PUDR_UNEXP 0x00000020 /* unexpected interrupt trapped */
+#define PUDR_80186 0x00000010 /* 80186 ok */
+#define PUDR_PATCH2 0x00000008 /* patch logic ok (again) */
+#define PUDR_8RAM 0x00000004 /* 80186 RAM ok */
+#define PUDR_8ROM2 0x00000002 /* 80186 ROM1 ok */
+#define PUDR_8ROM1 0x00000001 /* 80186 ROM2 ok */
diff --git a/sys/arch/vax/bi/kdb.c b/sys/arch/vax/bi/kdb.c
index 0362e0958ca..f03de356ff1 100644
--- a/sys/arch/vax/bi/kdb.c
+++ b/sys/arch/vax/bi/kdb.c
@@ -1,5 +1,5 @@
-/* $OpenBSD: kdb.c,v 1.6 2002/03/14 01:26:47 millert Exp $ */
-/* $NetBSD: kdb.c,v 1.5 1997/01/11 11:34:39 ragge Exp $ */
+/* $OpenBSD: kdb.c,v 1.7 2002/06/11 09:36:23 hugh Exp $ */
+/* $NetBSD: kdb.c,v 1.26 2001/11/13 12:51:34 lukem 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
*
@@ -40,54 +40,64 @@
* Nices hardware error handling.
*/
+#include <sys/cdefs.h>
+__KERNEL_RCSID(0, "$NetBSD: kdb.c,v 1.26 2001/11/13 12:51:34 lukem Exp $");
+
#include <sys/param.h>
#include <sys/kernel.h>
#include <sys/buf.h>
#include <sys/device.h>
#include <sys/proc.h>
+#include <sys/user.h>
#include <sys/malloc.h>
+#include <sys/systm.h>
+#include <sys/sched.h>
#include <uvm/uvm_extern.h>
-#include <machine/sid.h>
+#ifdef __vax__
#include <machine/pte.h>
#include <machine/pcb.h>
-#include <machine/trap.h>
-#include <machine/scb.h>
+#endif
+#include <machine/bus.h>
+
+#include <dev/bi/bireg.h>
+#include <dev/bi/bivar.h>
+#include <dev/bi/kdbreg.h>
+
+#include <dev/mscp/mscp.h>
+#include <dev/mscp/mscpreg.h>
+#include <dev/mscp/mscpvar.h>
-#include <vax/bi/bireg.h>
-#include <vax/bi/bivar.h>
-#include <vax/bi/kdbreg.h>
+#include "locators.h"
-#include <vax/mscp/mscp.h>
-#include <vax/mscp/mscpvar.h>
-#include <vax/mscp/mscpreg.h>
+#define KDB_WL(adr, val) bus_space_write_4(sc->sc_iot, sc->sc_ioh, adr, val)
+#define KDB_RL(adr) bus_space_read_4(sc->sc_iot, sc->sc_ioh, adr)
+#define KDB_RS(adr) bus_space_read_2(sc->sc_iot, sc->sc_ioh, adr)
-#define b_forw b_hash.le_next
+#define b_forw b_hash.le_next
/*
* Software status, per controller.
*/
struct kdb_softc {
struct device sc_dev; /* Autoconfig info */
- struct ivec_dsp sc_ivec; /* Interrupt vector handler */
- struct mscp_pack sc_kdb; /* Struct for kdb communication */
+ struct evcnt sc_intrcnt; /* Interrupt counting */
+ caddr_t sc_kdb; /* Struct for kdb communication */
struct mscp_softc *sc_softc; /* MSCP info (per mscpvar.h) */
- struct kdb_regs *sc_kr; /* KDB controller registers */
- struct mscp *sc_mscp; /* Keep pointer to active mscp */
+ bus_dma_tag_t sc_dmat;
+ bus_dmamap_t sc_cmap; /* Control structures */
+ bus_space_tag_t sc_iot;
+ bus_space_handle_t sc_ioh;
};
-int kdbmatch(struct device *, void *, void *);
-void kdbattach(struct device *, struct device *, void *);
-void kdbreset(int);
-void kdbintr(int);
-void kdbctlrdone(struct device *, int);
-int kdbprint(void *, const char *);
-void kdbsaerror(struct device *, int);
-int kdbgo(struct device *, struct buf *);
-
-struct cfdriver kdb_cd = {
- NULL, "kdb", DV_DULL
-};
+int kdbmatch __P((struct device *, struct cfdata *, void *));
+void kdbattach __P((struct device *, struct device *, void *));
+void kdbreset __P((int));
+void kdbintr __P((void *));
+void kdbctlrdone __P((struct device *));
+int kdbprint __P((void *, const char *));
+void kdbsaerror __P((struct device *, int));
+void kdbgo __P((struct device *, struct mscp_xi *));
struct cfattach kdb_ca = {
sizeof(struct kdb_softc), kdbmatch, kdbattach
@@ -116,20 +126,21 @@ kdbprint(aux, name)
* Poke at a supposed KDB to see if it is there.
*/
int
-kdbmatch(parent, match, aux)
+kdbmatch(parent, cf, aux)
struct device *parent;
- void *match, *aux;
+ struct cfdata *cf;
+ void *aux;
{
- struct cfdata *cf = match;
struct bi_attach_args *ba = aux;
- if (ba->ba_node->biic.bi_dtype != BIDT_KDB50)
- return 0;
+ if (bus_space_read_2(ba->ba_iot, ba->ba_ioh, BIREG_DTYPE) != BIDT_KDB50)
+ return 0;
- if (cf->cf_loc[0] != -1 && cf->cf_loc[0] != ba->ba_nodenr)
- return 0;
+ if (cf->cf_loc[BICF_NODE] != BICF_NODE_DEFAULT &&
+ cf->cf_loc[BICF_NODE] != ba->ba_nodenr)
+ return 0;
- return 1;
+ return 1;
}
void
@@ -140,104 +151,135 @@ kdbattach(parent, self, aux)
struct kdb_softc *sc = (void *)self;
struct bi_attach_args *ba = aux;
struct mscp_attach_args ma;
- extern struct ivec_dsp idsptch;
volatile int i = 10000;
+ int error, rseg;
+ bus_dma_segment_t seg;
printf("\n");
- bcopy(&idsptch, &sc->sc_ivec, sizeof(struct ivec_dsp));
- scb->scb_nexvec[1][ba->ba_nodenr] = &sc->sc_ivec;
- sc->sc_ivec.hoppaddr = kdbintr;
- sc->sc_ivec.pushlarg = self->dv_unit;
- sc->sc_kr = (void *)ba->ba_node;
+ bi_intr_establish(ba->ba_icookie, ba->ba_ivec,
+ kdbintr, sc, &sc->sc_intrcnt);
+ evcnt_attach_dynamic(&sc->sc_intrcnt, EVCNT_TYPE_INTR, NULL,
+ sc->sc_dev.dv_xname, "intr");
- bzero(&sc->sc_kdb, sizeof (struct mscp_pack));
+ sc->sc_iot = ba->ba_iot;
+ sc->sc_ioh = ba->ba_ioh;
+ sc->sc_dmat = ba->ba_dmat;
+
+ /*
+ * 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), &sc->sc_kdb,
+ 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, sc->sc_kdb,
+ sizeof(struct mscp_pack));
+ goto err;
+ }
+ if ((error = bus_dmamap_load(sc->sc_dmat, sc->sc_cmap,
+ sc->sc_kdb, 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;
+ }
+ memset(sc->sc_kdb, 0, sizeof(struct mscp_pack));
ma.ma_mc = &kdb_mscp_ctlr;
ma.ma_type = MSCPBUS_DISK|MSCPBUS_KDB;
- ma.ma_uuda = (struct mscp_pack *)kvtophys(&sc->sc_kdb);
- ma.ma_uda = &sc->sc_kdb;
- ma.ma_ip = &sc->sc_kr->kdb_ip;
- ma.ma_sa = &sc->sc_kr->kdb_sa;
- ma.ma_sw = &sc->sc_kr->kdb_sw;
+ ma.ma_uda = (struct mscp_pack *)sc->sc_kdb;
ma.ma_softc = &sc->sc_softc;
- ma.ma_ivec = (int)&scb->scb_nexvec[1][ba->ba_nodenr] - (int)scb;
+ ma.ma_iot = sc->sc_iot;
+ ma.ma_iph = sc->sc_ioh + KDB_IP;
+ ma.ma_sah = sc->sc_ioh + KDB_SA;
+ ma.ma_swh = sc->sc_ioh + KDB_SW;
+ ma.ma_dmat = sc->sc_dmat;
+ ma.ma_dmam = sc->sc_cmap;
+ ma.ma_ivec = ba->ba_ivec;
ma.ma_ctlrnr = ba->ba_nodenr;
- sc->sc_kr->kdb_bi.bi_csr |= BICSR_NRST;
+ ma.ma_adapnr = ba->ba_busnr;
+
+ KDB_WL(BIREG_VAXBICSR, KDB_RL(BIREG_VAXBICSR) | BICSR_NRST);
while (i--) /* Need delay??? */
;
- sc->sc_kr->kdb_bi.bi_intrdes = ba->ba_intcpu;
- sc->sc_kr->kdb_bi.bi_bcicsr |= BCI_STOPEN | BCI_IDENTEN | BCI_UINTEN |
- BCI_INTEN;
- sc->sc_kr->kdb_bi.bi_uintrcsr = ma.ma_ivec;
+ KDB_WL(BIREG_INTRDES, ba->ba_intcpu); /* Interrupt on CPU # */
+ KDB_WL(BIREG_BCICSR, KDB_RL(BIREG_BCICSR) |
+ BCI_STOPEN | BCI_IDENTEN | BCI_UINTEN | BCI_INTEN);
+ KDB_WL(BIREG_UINTRCSR, ba->ba_ivec);
config_found(&sc->sc_dev, &ma, kdbprint);
}
-int
-kdbgo(usc, bp)
+void
+kdbgo(usc, mxi)
struct device *usc;
- struct buf *bp;
+ struct mscp_xi *mxi;
{
struct kdb_softc *sc = (void *)usc;
- struct mscp_softc *mi = sc->sc_softc;
- struct mscp *mp = (void *)bp->b_actb;
- struct pcb *pcb;
- pt_entry_t *pte;
- int pfnum, npf, o, i;
- unsigned info = 0;
- caddr_t addr;
-
- o = (int)bp->b_un.b_addr & PGOFSET;
- npf = btoc(bp->b_bcount + o) + 1;
- addr = bp->b_un.b_addr;
-
- /*
- * Get a pointer to the pte pointing out the first virtual address.
- * Use different ways in kernel and user space.
- */
- if ((bp->b_flags & B_PHYS) == 0) {
- pte = kvtopte(addr);
- } else {
- pcb = bp->b_proc->p_vmspace->vm_map.pmap->pm_pcb;
- pte = uvtopte(addr, pcb);
- }
-
- /*
- * When we are doing DMA to user space, be sure that all pages
- * we want to transfer to is mapped. WHY DO WE NEED THIS???
- * SHOULDN'T THEY ALWAYS BE MAPPED WHEN DOING THIS???
- */
- for (i = 0; i < (npf - 1); i++) {
- if ((pte + i)->pg_pfn == 0) {
- int rv;
- rv = vm_fault(&bp->b_proc->p_vmspace->vm_map,
- (unsigned)addr + i * NBPG,
- VM_PROT_READ|VM_PROT_WRITE, FALSE);
- if (rv)
- panic("KDB DMA to nonexistent page, %d", rv);
- }
- }
+ struct buf *bp = mxi->mxi_bp;
+ struct mscp *mp = mxi->mxi_mp;
+ u_int32_t addr = (u_int32_t)bp->b_data;
+ u_int32_t mapaddr;
+ int err;
+
+ /*
+ * The KDB50 wants to read VAX Page tables directly, therefore
+ * the result from bus_dmamap_load() is uninteresting. (But it
+ * should never fail!).
+ *
+ * On VAX, point to the corresponding page tables. (user/sys)
+ * On other systems, do something else...
+ */
+ err = bus_dmamap_load(sc->sc_dmat, mxi->mxi_dmam, bp->b_data,
+ bp->b_bcount, (bp->b_flags & B_PHYS ? bp->b_proc : 0),
+ BUS_DMA_NOWAIT);
+
+ if (err) /* Shouldn't happen */
+ panic("kdbgo: bus_dmamap_load: error %d", err);
+
+#ifdef __vax__
/*
- * pte's for userspace isn't necessary positioned
- * in consecutive physical pages. We check if they
- * are, otherwise we need to copy the pte's to a
- * physically contigouos page area.
- * XXX some copying here may be unneccessary. Subject to fix.
+ * Get a pointer to the pte pointing out the first virtual address.
+ * Use different ways in kernel and user space.
*/
- if (bp->b_flags & B_PHYS) {
- int i = kvtophys(pte);
- unsigned k;
-
- if (trunc_page(i) != trunc_page(kvtophys(pte) + npf * 4)) {
- info = (unsigned)malloc(2 * NBPG, M_DEVBUF, M_WAITOK);
- k = (info + PGOFSET) & ~PGOFSET;
- bcopy(pte, (void *)k, NBPG);
- i = kvtophys(k);
+ if ((bp->b_flags & B_PHYS) == 0) {
+ mapaddr = ((u_int32_t)kvtopte(addr)) & ~KERNBASE;
+ } else {
+ struct pcb *pcb;
+ u_int32_t eaddr;
+
+ /*
+ * We check if the PTE's needed crosses a page boundary.
+ * If they do; only transfer the amount of data that is
+ * mapped by the first PTE page and led the system handle
+ * the rest of the data.
+ */
+ pcb = &bp->b_proc->p_addr->u_pcb;
+ mapaddr = (u_int32_t)uvtopte(addr, pcb);
+ eaddr = (u_int32_t)uvtopte(addr + (bp->b_bcount - 1), pcb);
+ if (trunc_page(mapaddr) != trunc_page(eaddr)) {
+ mp->mscp_seq.seq_bytecount =
+ (((round_page(mapaddr) - mapaddr)/4) * 512);
}
- mp->mscp_seq.seq_mapbase = i;
- } else
- mp->mscp_seq.seq_mapbase = (unsigned)pte;
- mscp_dgo(mi, KDB_MAP | o, info, bp);
- return 1;
+ mapaddr = kvtophys(mapaddr);
+ }
+#else
+#error Must write code to handle KDB50 on non-vax.
+#endif
+
+ mp->mscp_seq.seq_mapbase = mapaddr;
+ mxi->mxi_dmam->dm_segs[0].ds_addr = (addr & 511) | KDB_MAP;
+ mscp_dgo(sc->sc_softc, mxi);
}
void
@@ -246,11 +288,11 @@ kdbsaerror(usc, doreset)
int doreset;
{
struct kdb_softc *sc = (void *)usc;
- register int code = sc->sc_kr->kdb_sa;
- if ((code & MP_ERR) == 0)
+ if ((KDB_RS(KDB_SA) & MP_ERR) == 0)
return;
- printf("%s: controller error, sa=0x%x\n", sc->sc_dev.dv_xname, code);
+ printf("%s: controller error, sa=0x%x\n", sc->sc_dev.dv_xname,
+ KDB_RS(KDB_SA));
/* What to do now??? */
}
@@ -260,18 +302,17 @@ kdbsaerror(usc, doreset)
* interrupts, and process responses.
*/
void
-kdbintr(ctlr)
- int ctlr;
+kdbintr(void *arg)
{
- struct kdb_softc *sc = kdb_cd.cd_devs[ctlr];
- struct uba_softc *uh;
- struct mscp_pack *ud;
+ struct kdb_softc *sc = arg;
- if (sc->sc_kr->kdb_sa & MP_ERR) { /* ctlr fatal error */
+ if (KDB_RS(KDB_SA) & MP_ERR) { /* ctlr fatal error */
kdbsaerror(&sc->sc_dev, 1);
return;
}
+ KERNEL_LOCK(LK_CANRECURSE|LK_EXCLUSIVE);
mscp_intr(sc->sc_softc);
+ KERNEL_UNLOCK();
}
#ifdef notyet
@@ -283,7 +324,7 @@ void
kdbreset(ctlr)
int ctlr;
{
- register struct kdb_softc *sc;
+ struct kdb_softc *sc;
sc = kdb_cd.cd_devs[ctlr];
printf(" kdb%d", ctlr);
@@ -304,10 +345,7 @@ kdbreset(ctlr)
#endif
void
-kdbctlrdone(usc, info)
+kdbctlrdone(usc)
struct device *usc;
- int info;
{
- if (info)
- free((void *)info, NBPG * 2);
}
diff --git a/sys/arch/vax/bi/kdbreg.h b/sys/arch/vax/bi/kdbreg.h
index c92bd0bf732..0103bb7e21e 100644
--- a/sys/arch/vax/bi/kdbreg.h
+++ b/sys/arch/vax/bi/kdbreg.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: kdbreg.h,v 1.3 2000/04/28 03:42:39 bjc Exp $ */
+/* $OpenBSD: kdbreg.h,v 1.4 2002/06/11 09:36:23 hugh Exp $ */
/* $NetBSD: kdbreg.h,v 1.3 1999/11/03 21:57:40 ragge Exp $ */
/*
* Copyright (c) 1988 Regents of the University of California.
@@ -42,6 +42,7 @@
* The KDB50 registers are embedded inside the bi interface
* general-purpose registers.
*/
+#ifdef notdef
struct kdb_regs {
struct biiregs kdb_bi;
short kdb_xxx; /* first half of GPR 0 unused */
@@ -49,6 +50,7 @@ struct kdb_regs {
short kdb_sa; /* status & address (r/o half) */
short kdb_sw; /* status & address (w/o half) */
};
+#endif
#define KDB_IP 0xf2
#define KDB_SA 0xf4