summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorglass <glass@NetBSD.org>1993-08-15 23:01:58 +0000
committerglass <glass@NetBSD.org>1993-08-15 23:01:58 +0000
commit8ff8fa8046501b4988a07f02f42f2ffd76fa044e (patch)
tree9bec9eb99be032e892b8c7d3e69a21e52fc504de /sys
parent3e94657cf6dba8425790230daaf8b6770823e2af (diff)
runs up to and including configure().
todo: exceptions, interrupt support, make isrs affect vector table kernel/user stacks
Diffstat (limited to 'sys')
-rw-r--r--sys/arch/sun3/conf/Makefile.sun34
-rw-r--r--sys/arch/sun3/conf/TIMESINK28
-rw-r--r--sys/arch/sun3/conf/files.sun3.newconf35
-rw-r--r--sys/arch/sun3/conf/std.sun39
-rw-r--r--sys/arch/sun3/dev/README35
-rw-r--r--sys/arch/sun3/dev/idprom.c82
-rw-r--r--sys/arch/sun3/dev/if_le.c827
-rw-r--r--sys/arch/sun3/dev/if_le.h34
-rw-r--r--sys/arch/sun3/dev/if_le_subr.c82
-rw-r--r--sys/arch/sun3/dev/if_le_subr.h5
-rw-r--r--sys/arch/sun3/dev/if_lereg.h149
-rw-r--r--sys/arch/sun3/dev/obctl.c38
-rw-r--r--sys/arch/sun3/dev/obio.c78
-rw-r--r--sys/arch/sun3/dev/obmem.c42
-rw-r--r--sys/arch/sun3/dev/prom.c104
-rw-r--r--sys/arch/sun3/include/autoconf.h5
-rw-r--r--sys/arch/sun3/include/idprom.h8
-rw-r--r--sys/arch/sun3/include/isr.h6
-rw-r--r--sys/arch/sun3/include/obctl.h12
-rw-r--r--sys/arch/sun3/include/obio.h20
-rw-r--r--sys/arch/sun3/include/obmem.h9
-rw-r--r--sys/arch/sun3/include/vmparam.h5
-rw-r--r--sys/arch/sun3/include/vmparam3.h5
-rw-r--r--sys/arch/sun3/sun3/TODO5
-rw-r--r--sys/arch/sun3/sun3/autoconf.c96
-rw-r--r--sys/arch/sun3/sun3/idprom.c82
-rw-r--r--sys/arch/sun3/sun3/isr.c89
-rw-r--r--sys/arch/sun3/sun3/locore2.c11
-rw-r--r--sys/arch/sun3/sun3/machdep.c74
-rw-r--r--sys/arch/sun3/sun3/obio.c78
-rw-r--r--sys/arch/sun3/sun3/obio.h20
-rw-r--r--sys/arch/sun3/sun3/obmem.c42
-rw-r--r--sys/arch/sun3/sun3/obmem.h9
-rw-r--r--sys/arch/sun3/sun3/pmap.c40
-rw-r--r--sys/arch/sun3/sun3/sun3_startup.c11
-rw-r--r--sys/arch/sun3/sun3/vm_machdep.c37
-rw-r--r--sys/conf/files.newconf11
-rw-r--r--sys/kern/subr_autoconf.c29
38 files changed, 1948 insertions, 308 deletions
diff --git a/sys/arch/sun3/conf/Makefile.sun3 b/sys/arch/sun3/conf/Makefile.sun3
index 9c35b2b1bb4..63f51fff4db 100644
--- a/sys/arch/sun3/conf/Makefile.sun3
+++ b/sys/arch/sun3/conf/Makefile.sun3
@@ -113,9 +113,7 @@ locore.o: ${SUN3}/include/cpu.h ${SUN3}/include/control.h
# the following is necessary because autoconf.o depends on #if GENERIC
autoconf.o: Makefile
-# the following are necessary because the files depend on the types of
-# hp cpu's included in the system configuration
-clock.o machdep.o autoconf.o conf.o: Makefile
+sun3_startup.o: Makefile
# depend on network configuration
af.o uipc_proto.o locore.o: Makefile
diff --git a/sys/arch/sun3/conf/TIMESINK b/sys/arch/sun3/conf/TIMESINK
index d80d9c347eb..51835983d58 100644
--- a/sys/arch/sun3/conf/TIMESINK
+++ b/sys/arch/sun3/conf/TIMESINK
@@ -1,27 +1,31 @@
#
+# new config file for TIMESINK
#
-machine "sun3"
-cpu "SUN3_50"
-ident TIMESINK
-timezone 8 dst
-maxusers 16
+include "std.sun3"
+
+options "SUN3_50"
+
+makeoptions DEBUG = "-g"
+maxusers 4
+options TIMEZONE = 480, DST = 2, MAXFDESCS=2048
# Standard options
options "COMPAT_43"
options "TCP_COMPAT_42"
# Options for all SUN3 machines
+options SWAPPAGER, VNODEPAGER, DEVPAGER
options KTRACE
-#options DDB
-
+options INET
config netbsd swap generic
-pseudo-device prom
-pseudo-device idprom
+le0 at obio? addr ? level 3
+#zs0 at obio? addr 0x00000 level 3
+#zs1 at obio? addr 0x20000 level 3
-pseudo-device swappager
-pseudo-device vnodepager
-pseudo-device devpager
+idprom0 at obctl? addr ? size ?
+prom0 at mainbus0
+pseudo-device loop
diff --git a/sys/arch/sun3/conf/files.sun3.newconf b/sys/arch/sun3/conf/files.sun3.newconf
index 4e377ea45a1..c83d0baba60 100644
--- a/sys/arch/sun3/conf/files.sun3.newconf
+++ b/sys/arch/sun3/conf/files.sun3.newconf
@@ -1,29 +1,43 @@
#
# new style config file for sun3 architecture
#
-#
+# sun3 config 'files' for new config
#
define sunfb
-#device mainbus at root { }
-device obio at root {addr = -1, [priority = -1]}
-device obmem at root {addr, size, [priority = -1]}
+device mainbus at root {}
+device obio at mainbus {addr = -1, [level = -1]}
+device obmem at mainbus {addr, size, [level = -1]}
+device obctl at mainbus {addr, size}
#define obio { addr = -1, size = -1, priority = -1, dvma = -1, flags = -1}
#define obmem { addr = -1, size = -1}
device le at obio: ifnet, ether
-file arch/sun3/dev/if_le.c le device-driver needs-count
+file arch/sun3/dev/if_le.c le device-driver
+file arch/sun3/dev/if_le_subr.c le
device zs at obio: tty
file arch/sun3/dev/zs.c zs device-driver needs-count
device bwtwo at obmem: sunfb
-file arch/sun3/dev/bwtwo.c bwtwo
+file arch/sun3/dev/bwtwo.c bwtwo device-driver
+
+device idprom at obctl
+file arch/sun3/dev/idprom.c idprom device-driver needs-count
+
+device prom at mainbus: tty
+file arch/sun3/dev/prom.c prom device-driver needs-count
+
+# "Bus" support code
+file arch/sun3/dev/obio.c obio device-driver
+file arch/sun3/dev/obctl.c obctl device-driver
+file arch/sun3/dev/obmem.c obmem device-driver
#
#
+file arch/sun3/sun3/autoconf.c
file arch/sun3/sun3/clock.c
file arch/sun3/sun3/conf.c
file arch/sun3/sun3/cons.c
@@ -32,16 +46,15 @@ file arch/sun3/sun3/control.c
file arch/sun3/sun3/db_interface.c ddb
file arch/sun3/sun3/db_trace.c ddb
file arch/sun3/sun3/disksubr.c
+file arch/sun3/sun3/in_cksum.c inet
+file arch/sun3/sun3/isr.c
file arch/sun3/sun3/machdep.c
file arch/sun3/sun3/mem.c
-file arch/sun3/sun3/obio.c
+file arch/sun3/sun3/ns_cksum.c ns
+file arch/sun3/sun3/oc_cksum.s inet
file arch/sun3/sun3/pmap.c
file arch/sun3/sun3/stub.c
file arch/sun3/sun3/sun3_startup.c
file arch/sun3/sun3/trap.c
file arch/sun3/sun3/vector.c
file arch/sun3/sun3/vm_machdep.c
-file arch/sun3/dev/idprom.c idprom device-driver
-file arch/sun3/dev/prom.c prom device-driver
-file arch/sun3/dev/obmem.c obmem device-driver
-
diff --git a/sys/arch/sun3/conf/std.sun3 b/sys/arch/sun3/conf/std.sun3
index 81e6428462a..d3897a0493e 100644
--- a/sys/arch/sun3/conf/std.sun3
+++ b/sys/arch/sun3/conf/std.sun3
@@ -1,6 +1,9 @@
machine "sun3"
-#mainbus0 at root
+options NEWCONFIG
-obio0 at root
-obmem0 at root
+mainbus0 at root
+
+obio0 at mainbus?
+obmem0 at mainbus?
+obctl0 at mainbus?
diff --git a/sys/arch/sun3/dev/README b/sys/arch/sun3/dev/README
new file mode 100644
index 00000000000..7dafe89e3f6
--- /dev/null
+++ b/sys/arch/sun3/dev/README
@@ -0,0 +1,35 @@
+ <$Revision: 1.1 $>
+
+NetBSD/sun3 supports the following busses:
+
+Bus:
+obio - Devices on the motherboard, accessed by having their "registers"
+ mapped into the kernel's virtual address space
+obctl - Devices on the motherboard accessible only via the 'CONTROL' space,
+ and supporting instructions on the m68k.
+obmem - Devices on the motherboard that are mapped into main memory
+ by the hardware. Only true of some framebuffers.
+mainbus - An imaginary bus on which obio, obctl, obmem, and the prom device
+ all reside.
+
+Devices supported:
+
+'obio' Bus:
+Device Type Description
+---------------------------------------------------------------------------
+zs CHAR zilog 8530 serial ports; used for serial ports, keybd, mouse
+le IFNET lance ethernet driver
+
+'obctl' Bus:
+Device Type Description
+---------------------------------------------------------------------------
+idprom CHAR makes idprom contents accessible in user-space
+
+
+The 'prom' device is just wierd as it isn't a real device, but enough
+wrapping so that the prom input/output routines can be used to make
+the prom's idea of the console both a tty, and a console in the netbsd
+sense.
+
+prom CHAR prom-based tty and console support
+
diff --git a/sys/arch/sun3/dev/idprom.c b/sys/arch/sun3/dev/idprom.c
index f56d3d94369..96846c8c6e5 100644
--- a/sys/arch/sun3/dev/idprom.c
+++ b/sys/arch/sun3/dev/idprom.c
@@ -1,30 +1,71 @@
#include "systm.h"
+#include "device.h"
+
+#include "machine/autoconf.h"
+#include "machine/control.h"
#include "machine/idprom.h"
+#include "machine/obctl.h"
+
#include "idprom.h"
-static int idprom_init = 0;
+extern void idpromattach __P((struct device *, struct device *, void *));
+
+struct idprom_softc {
+ struct device idprom_driver;
+ int idprom_init;
+ struct idprom idprom_copy;
+ char *idprom_addr;
+ int idprom_size;
+};
+
+struct cfdriver idpromcd =
+{ NULL, "idprom", always_match, idpromattach, DV_DULL,
+ sizeof(struct idprom_softc), 0};
-static struct idprom idprom_copy;
+#define IDPROM_CHECK(unit) \
+ if (unit >= idpromcd.cd_ndevs || (idpromcd.cd_devs[unit] == NULL)) \
+ return ENXIO
+#define UNIT_TO_IDP(unit) idpromcd.cd_devs[unit]
+
+
+void idpromattach(parent, self, args)
+ struct device *parent;
+ struct device *self;
+ void *args;
+{
+ struct idprom_softc *idp = (struct idprom_softc *) self;
+ struct obctl_cf_loc *obctl_loc = OBCTL_LOC(self);
-static int idprom_ok = 0;
+ idp->idprom_init = 0;
-int idprom_open(dev, oflags, devtype, p)
+ idp->idprom_addr =
+ OBCTL_DEFAULT_PARAM(char *, obctl_loc->obctl_addr, IDPROM_BASE);
+ idp->idprom_size =
+ OBCTL_DEFAULT_PARAM(int, obctl_loc->obctl_size, IDPROM_SIZE);
+ obctl_print(idp->idprom_addr, idp->idprom_size);
+ printf("\n");
+}
+
+int idpromopen(dev, oflags, devtype, p)
dev_t dev;
int oflags;
int devtype;
struct proc *p;
{
- int unit,s;
+ struct idprom_softc *idp;
+ int unit, idprom_ok;
unit = minor(dev);
- if (unit >= NIDPROM)
- return ENXIO;
- if (!idprom_init) idprom_ok = idprom_fetch(&idprom_copy, IDPROM_VERSION);
+ IDPROM_CHECK(unit);
+ idp = UNIT_TO_IDP(unit);
+ if (!idp->idprom_init)
+ idprom_ok = idprom_fetch(&idp->idprom_copy, IDPROM_VERSION);
if (!idprom_ok) return EIO;
+ idp->idprom_init = 1;
return 0;
}
-int idprom_close(dev, fflag, devtype, p)
+int idpromclose(dev, fflag, devtype, p)
dev_t dev;
int fflag;
int devtype;
@@ -33,30 +74,27 @@ int idprom_close(dev, fflag, devtype, p)
int unit;
unit = minor(dev);
- if (unit >= NIDPROM)
- return ENXIO;
+ IDPROM_CHECK(unit);
return 0;
}
-idprom_read(dev, uio, ioflag)
+idpromread(dev, uio, ioflag)
dev_t dev;
struct uio *uio;
int ioflag;
{
- int error, unit,length;
-
+ int error, unit, length;
+ struct idprom_softc *idp;
unit = minor(dev);
-
- if (unit >= NIDPROM)
- return ENXIO;
-
+ IDPROM_CHECK(unit);
+ idp = UNIT_TO_IDP(unit);
+ if (!idp->idprom_init) return EIO;
error = 0;
while (uio->uio_resid > 0) {
- if (uio->uio_offset >= IDPROM_SIZE) break; /* past or at end */
- length = min(uio->uio_resid, (IDPROM_SIZE-uio->uio_offset));
- error = uiomove((caddr_t) &idprom_copy, length, uio);
+ if (uio->uio_offset >= idp->idprom_size) break; /* past or at end */
+ length = min(uio->uio_resid, (idp->idprom_size - uio->uio_offset));
+ error = uiomove((caddr_t) &idp->idprom_copy, length, uio);
}
return error;
}
-
diff --git a/sys/arch/sun3/dev/if_le.c b/sys/arch/sun3/dev/if_le.c
new file mode 100644
index 00000000000..14a2235a2e5
--- /dev/null
+++ b/sys/arch/sun3/dev/if_le.c
@@ -0,0 +1,827 @@
+/*
+ * Copyright (c) 1982, 1990 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.
+ *
+ * from: @(#)if_le.c 7.6 (Berkeley) 5/8/91
+ * if_le.c,v 1.2 1993/05/22 07:56:23 cgd Exp
+ */
+
+#include "bpfilter.h"
+
+/*
+ * AMD 7990 LANCE
+ *
+ * This driver will generate and accept tailer encapsulated packets even
+ * though it buys us nothing. The motivation was to avoid incompatibilities
+ * with VAXen, SUNs, and others that handle and benefit from them.
+ * This reasoning is dubious.
+ */
+#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/syslog.h"
+#include "sys/ioctl.h"
+#include "sys/errno.h"
+#include "sys/device.h"
+
+#include "net/if.h"
+#include "net/netisr.h"
+#include "net/route.h"
+
+#ifdef INET
+#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 RMP
+#include "netrmp/rmp.h"
+#include "netrmp/rmp_var.h"
+#endif
+
+#include "machine/autoconf.h"
+
+#include "if_lereg.h"
+
+#if NBPFILTER > 0
+#include "../net/bpf.h"
+#include "../net/bpfdesc.h"
+#endif
+
+#include "if_le.h"
+#include "if_le_subr.h"
+
+int ledebug = 0; /* console error messages */
+
+int leintr(), leinit(), leioctl(), lestart(), ether_output();
+struct mbuf *leget();
+extern struct ifnet loif;
+
+/* access LANCE registers */
+
+void leattach __P((struct device *, struct device *, void *));
+int lematch __P((struct device *, struct cfdata *, void *args));
+
+struct cfdriver lecd =
+{ NULL, "le", lematch, leattach, DV_DULL, sizeof(struct le_softc), 0};
+
+int lematch(parent, cf, args)
+ struct device *parent;
+ struct cfdata *cf;
+ void *args;
+{
+ return le_machdep_match(parent, cf, args);
+}
+/*
+ * Interface exists: make available by filling in network interface
+ * record. System will initialize the interface when it is ready
+ * to accept packets.
+ */
+void leattach(parent, self, args)
+ struct device *parent;
+ struct device *self;
+ void *args;
+{
+ register struct lereg2 *ler2;
+ struct lereg2 *lemem = 0;
+ struct le_softc *le = (struct le_softc *) self;
+ struct ifnet *ifp = &le->sc_if;
+ char *cp;
+ int i, unit;
+
+ unit = le->sc_dev.dv_unit;
+ if (le_machdep_attach(parent, self, args)) {
+ printf(": bad attach??\n");
+ return;
+ }
+ ler2 = le->sc_r2;
+ printf(": hardware address %s\n", ether_sprintf(le->sc_addr));
+
+ /*
+ * Setup for transmit/receive
+ */
+ ler2->ler2_mode = LE_MODE;
+ ler2->ler2_padr[0] = le->sc_addr[1];
+ ler2->ler2_padr[1] = le->sc_addr[0];
+ ler2->ler2_padr[2] = le->sc_addr[3];
+ ler2->ler2_padr[3] = le->sc_addr[2];
+ ler2->ler2_padr[4] = le->sc_addr[5];
+ ler2->ler2_padr[5] = le->sc_addr[4];
+#ifdef RMP
+ /*
+ * Set up logical addr filter to accept multicast 9:0:9:0:0:4
+ * This should be an ioctl() to the driver. (XXX)
+ */
+ ler2->ler2_ladrf0 = 0x00100000;
+ ler2->ler2_ladrf1 = 0x0;
+#else
+ ler2->ler2_ladrf0 = 0;
+ ler2->ler2_ladrf1 = 0;
+#endif
+ ler2->ler2_rlen = LE_RLEN;
+ ler2->ler2_rdra = (int)lemem->ler2_rmd;
+ ler2->ler2_tlen = LE_TLEN;
+ ler2->ler2_tdra = (int)lemem->ler2_tmd;
+
+ ifp->if_unit = unit;
+ ifp->if_name = "le";
+ ifp->if_mtu = ETHERMTU;
+ ifp->if_init = leinit;
+ ifp->if_ioctl = leioctl;
+ ifp->if_output = ether_output;
+ ifp->if_start = lestart;
+ ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX;
+#if NBPFILTER > 0
+ bpfattach(&le->sc_bpf, ifp, DLT_EN10MB, sizeof(struct ether_header));
+#endif
+ if_attach(ifp);
+}
+
+ledrinit(ler2)
+ register struct lereg2 *ler2;
+{
+ register struct lereg2 *lemem = 0;
+ register int i;
+
+ for (i = 0; i < LERBUF; i++) {
+ ler2->ler2_rmd[i].rmd0 = (int)lemem->ler2_rbuf[i];
+ ler2->ler2_rmd[i].rmd1 = LE_OWN;
+ ler2->ler2_rmd[i].rmd2 = -LEMTU;
+ ler2->ler2_rmd[i].rmd3 = 0;
+ }
+ for (i = 0; i < LETBUF; i++) {
+ ler2->ler2_tmd[i].tmd0 = (int)lemem->ler2_tbuf[i];
+ ler2->ler2_tmd[i].tmd1 = 0;
+ ler2->ler2_tmd[i].tmd2 = 0;
+ ler2->ler2_tmd[i].tmd3 = 0;
+ }
+}
+
+lereset(unit)
+ register int unit;
+{
+ register struct le_softc *le = (struct le_softc *) &lecd.cd_devs[unit];
+ register struct lereg1 *ler1 = le->sc_r1;
+ register struct lereg2 *lemem = 0;
+ register int timo = 100000;
+ register int stat;
+
+#ifdef lint
+ stat = unit;
+#endif
+#if NBPFILTER > 0
+ if (le->sc_if.if_flags & IFF_PROMISC)
+ /* set the promiscuous bit */
+ le->sc_r2->ler2_mode = LE_MODE|0x8000;
+ else
+ le->sc_r2->ler2_mode = LE_MODE;
+#endif
+ LERDWR(le, LE_CSR0, ler1->ler1_rap);
+ LERDWR(le, LE_STOP, ler1->ler1_rdp);
+ ledrinit(le->sc_r2);
+ le->sc_rmd = 0;
+ LERDWR(le, LE_CSR1, ler1->ler1_rap);
+ LERDWR(le, (int)&lemem->ler2_mode, ler1->ler1_rdp);
+ LERDWR(le, LE_CSR2, ler1->ler1_rap);
+ LERDWR(le, 0, ler1->ler1_rdp);
+ LERDWR(le, LE_CSR0, ler1->ler1_rap);
+ LERDWR(le, LE_INIT, ler1->ler1_rdp);
+ do {
+ if (--timo == 0) {
+ printf("le%d: init timeout, stat = 0x%x\n",
+ unit, stat);
+ break;
+ }
+ LERDWR(le, ler1->ler1_rdp, stat);
+ } while ((stat & LE_IDON) == 0);
+ LERDWR(le, LE_STOP, ler1->ler1_rdp);
+ LERDWR(le, LE_CSR3, ler1->ler1_rap);
+ LERDWR(le, LE_BSWP, ler1->ler1_rdp);
+ LERDWR(le, LE_CSR0, ler1->ler1_rap);
+ LERDWR(le, LE_STRT | LE_INEA, ler1->ler1_rdp);
+ le->sc_if.if_flags &= ~IFF_OACTIVE;
+}
+
+/*
+ * Initialization of interface
+ */
+leinit(unit)
+ int unit;
+{
+ struct le_softc *le = lecd.cd_devs[unit];
+ register struct ifnet *ifp = &le->sc_if;
+ int s;
+
+ /* not yet, if address still unknown */
+ if (ifp->if_addrlist == (struct ifaddr *)0)
+ return;
+ if ((ifp->if_flags & IFF_RUNNING) == 0) {
+ s = splimp();
+ ifp->if_flags |= IFF_RUNNING;
+ lereset(unit);
+ (void) lestart(ifp);
+ splx(s);
+ }
+}
+
+/*
+ * Start output on interface. Get another datagram to send
+ * off of the interface queue, and copy it to the interface
+ * before starting the output.
+ */
+lestart(ifp)
+ struct ifnet *ifp;
+{
+ register struct le_softc *le = lecd.cd_devs[ifp->if_unit];
+ register struct letmd *tmd;
+ register struct mbuf *m;
+ int len;
+
+ if ((le->sc_if.if_flags & IFF_RUNNING) == 0)
+ return (0);
+ IF_DEQUEUE(&le->sc_if.if_snd, m);
+ if (m == 0)
+ return (0);
+ len = leput(le->sc_r2->ler2_tbuf[0], m);
+#if NBPFILTER > 0
+ /*
+ * If bpf is listening on this interface, let it
+ * see the packet before we commit it to the wire.
+ */
+ if (le->sc_bpf)
+ bpf_tap(le->sc_bpf, le->sc_r2->ler2_tbuf[0], len);
+#endif
+ tmd = le->sc_r2->ler2_tmd;
+ tmd->tmd3 = 0;
+ tmd->tmd2 = -len;
+ tmd->tmd1 = LE_OWN | LE_STP | LE_ENP;
+ le->sc_if.if_flags |= IFF_OACTIVE;
+ return (0);
+}
+
+leintr(unit)
+ register int unit;
+{
+ register struct le_softc *le = lecd.cd_devs[unit];
+ register struct lereg1 *ler1;
+ register int stat;
+
+ le_machdep_intrcheck(le, unit);
+ ler1 = le->sc_r1;
+ LERDWR(le, ler1->ler1_rdp, stat);
+ if (stat & LE_SERR) {
+ leerror(unit, stat);
+ if (stat & LE_MERR) {
+ le->sc_merr++;
+ lereset(unit);
+ return(1);
+ }
+ if (stat & LE_BABL)
+ le->sc_babl++;
+ if (stat & LE_CERR)
+ le->sc_cerr++;
+ if (stat & LE_MISS)
+ le->sc_miss++;
+ LERDWR(le, LE_BABL|LE_CERR|LE_MISS|LE_INEA, ler1->ler1_rdp);
+ }
+ if ((stat & LE_RXON) == 0) {
+ le->sc_rxoff++;
+ lereset(unit);
+ return(1);
+ }
+ if ((stat & LE_TXON) == 0) {
+ le->sc_txoff++;
+ lereset(unit);
+ return(1);
+ }
+ if (stat & LE_RINT) {
+ /* interrupt is cleared in lerint */
+ lerint(unit);
+ }
+ if (stat & LE_TINT) {
+ LERDWR(le, LE_TINT|LE_INEA, ler1->ler1_rdp);
+ lexint(unit);
+ }
+ return(1);
+}
+
+/*
+ * Ethernet interface transmitter interrupt.
+ * Start another output if more data to send.
+ */
+lexint(unit)
+ register int unit;
+{
+ register struct le_softc *le = lecd.cd_devs[unit];
+ register struct letmd *tmd = le->sc_r2->ler2_tmd;
+
+ if ((le->sc_if.if_flags & IFF_OACTIVE) == 0) {
+ le->sc_xint++;
+ return;
+ }
+ if (tmd->tmd1 & LE_OWN) {
+ le->sc_xown++;
+ return;
+ }
+ if (tmd->tmd1 & LE_ERR) {
+err:
+ lexerror(unit);
+ le->sc_if.if_oerrors++;
+ if (tmd->tmd3 & (LE_TBUFF|LE_UFLO)) {
+ le->sc_uflo++;
+ lereset(unit);
+ }
+ else if (tmd->tmd3 & LE_LCOL)
+ le->sc_if.if_collisions++;
+ else if (tmd->tmd3 & LE_RTRY)
+ le->sc_if.if_collisions += 16;
+ }
+ else if (tmd->tmd3 & LE_TBUFF)
+ /* XXX documentation says BUFF not included in ERR */
+ goto err;
+ else if (tmd->tmd1 & LE_ONE)
+ le->sc_if.if_collisions++;
+ else if (tmd->tmd1 & LE_MORE)
+ /* what is the real number? */
+ le->sc_if.if_collisions += 2;
+ else
+ le->sc_if.if_opackets++;
+ le->sc_if.if_flags &= ~IFF_OACTIVE;
+ (void) lestart(&le->sc_if);
+}
+
+#define LENEXTRMP \
+ if (++bix == LERBUF) bix = 0, rmd = le->sc_r2->ler2_rmd; else ++rmd
+
+/*
+ * Ethernet interface receiver interrupt.
+ * If input error just drop packet.
+ * Decapsulate packet based on type and pass to type specific
+ * higher-level input routine.
+ */
+lerint(unit)
+ int unit;
+{
+ register struct le_softc *le = lecd.cd_devs[unit];
+ register int bix = le->sc_rmd;
+ register struct lermd *rmd = &le->sc_r2->ler2_rmd[bix];
+
+ /*
+ * Out of sync with hardware, should never happen?
+ */
+ if (rmd->rmd1 & LE_OWN) {
+ LERDWR(le->sc_r0, LE_RINT|LE_INEA, le->sc_r1->ler1_rdp);
+ return;
+ }
+
+ /*
+ * Process all buffers with valid data
+ */
+ while ((rmd->rmd1 & LE_OWN) == 0) {
+ int len = rmd->rmd3;
+
+ /* Clear interrupt to avoid race condition */
+ LERDWR(le->sc_r0, LE_RINT|LE_INEA, le->sc_r1->ler1_rdp);
+
+ if (rmd->rmd1 & LE_ERR) {
+ le->sc_rmd = bix;
+ lererror(unit, "bad packet");
+ le->sc_if.if_ierrors++;
+ } else if ((rmd->rmd1 & (LE_STP|LE_ENP)) != (LE_STP|LE_ENP)) {
+ /*
+ * Find the end of the packet so we can see how long
+ * it was. We still throw it away.
+ */
+ do {
+ LERDWR(le->sc_r0, LE_RINT|LE_INEA,
+ le->sc_r1->ler1_rdp);
+ rmd->rmd3 = 0;
+ rmd->rmd1 = LE_OWN;
+ LENEXTRMP;
+ } while (!(rmd->rmd1 & (LE_OWN|LE_ERR|LE_STP|LE_ENP)));
+ le->sc_rmd = bix;
+ lererror(unit, "chained buffer");
+ le->sc_rxlen++;
+ /*
+ * If search terminated without successful completion
+ * we reset the hardware (conservative).
+ */
+ if ((rmd->rmd1 & (LE_OWN|LE_ERR|LE_STP|LE_ENP)) !=
+ LE_ENP) {
+ lereset(unit);
+ return;
+ }
+ } else
+ leread(unit, le->sc_r2->ler2_rbuf[bix], len);
+ rmd->rmd3 = 0;
+ rmd->rmd1 = LE_OWN;
+ LENEXTRMP;
+ }
+ le->sc_rmd = bix;
+}
+
+leread(unit, buf, len)
+ int unit;
+ char *buf;
+ int len;
+{
+ register struct le_softc *le = lecd.cd_devs[unit];
+ register struct ether_header *et;
+ struct mbuf *m;
+ int off, resid;
+
+ le->sc_if.if_ipackets++;
+ et = (struct ether_header *)buf;
+ et->ether_type = ntohs((u_short)et->ether_type);
+ /* adjust input length to account for header and CRC */
+ len = len - sizeof(struct ether_header) - 4;
+
+#ifdef RMP
+ /* (XXX)
+ *
+ * If Ethernet Type field is < MaxPacketSize, we probably have
+ * a IEEE802 packet here. Make sure that the size is at least
+ * that of the HP LLC. Also do sanity checks on length of LLC
+ * (old Ethernet Type field) and packet length.
+ *
+ * Provided the above checks succeed, change `len' to reflect
+ * the length of the LLC (i.e. et->ether_type) and change the
+ * type field to ETHERTYPE_IEEE so we can switch() on it later.
+ * Yes, this is a hack and will eventually be done "right".
+ */
+ if (et->ether_type <= IEEE802LEN_MAX && len >= sizeof(struct hp_llc) &&
+ len >= et->ether_type && len >= IEEE802LEN_MIN) {
+ len = et->ether_type;
+ et->ether_type = ETHERTYPE_IEEE; /* hack! */
+ }
+#endif
+
+#define ledataaddr(et, off, type) ((type)(((caddr_t)((et)+1)+(off))))
+ if (et->ether_type >= ETHERTYPE_TRAIL &&
+ et->ether_type < ETHERTYPE_TRAIL+ETHERTYPE_NTRAILER) {
+ off = (et->ether_type - ETHERTYPE_TRAIL) * 512;
+ if (off >= ETHERMTU)
+ return; /* sanity */
+ et->ether_type = ntohs(*ledataaddr(et, off, u_short *));
+ resid = ntohs(*(ledataaddr(et, off+2, u_short *)));
+ if (off + resid > len)
+ return; /* sanity */
+ len = off + resid;
+ } else
+ off = 0;
+
+ if (len <= 0) {
+ if (ledebug)
+ log(LOG_WARNING,
+ "le%d: ierror(runt packet): from %s: len=%d\n",
+ unit, ether_sprintf(et->ether_shost), len);
+ le->sc_runt++;
+ le->sc_if.if_ierrors++;
+ return;
+ }
+#if NBPFILTER > 0
+ /*
+ * Check if there's a bpf filter listening on this interface.
+ * If so, hand off the raw packet to bpf, which must deal with
+ * trailers in its own way.
+ */
+ if (le->sc_bpf) {
+ bpf_tap(le->sc_bpf, buf, len + sizeof(struct ether_header));
+
+ /*
+ * Note that the interface cannot be in promiscuous mode if
+ * there are no bpf listeners. And if we are in promiscuous
+ * mode, we have to check if this packet is really ours.
+ *
+ * XXX This test does not support multicasts.
+ */
+ if ((le->sc_if.if_flags & IFF_PROMISC)
+ && bcmp(et->ether_dhost, le->sc_addr,
+ sizeof(et->ether_dhost)) != 0
+ && bcmp(et->ether_dhost, etherbroadcastaddr,
+ sizeof(et->ether_dhost)) != 0)
+ return;
+ }
+#endif
+ /*
+ * Pull packet off interface. Off is nonzero if packet
+ * has trailing header; leget 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.
+ */
+ m = leget(buf, len, off, &le->sc_if);
+ if (m == 0)
+ return;
+#ifdef RMP
+ /*
+ * (XXX)
+ * This needs to be integrated with the ISO stuff in ether_input()
+ */
+ if (et->ether_type == ETHERTYPE_IEEE) {
+ /*
+ * Snag the Logical Link Control header (IEEE 802.2).
+ */
+ struct hp_llc *llc = &(mtod(m, struct rmp_packet *)->hp_llc);
+
+ /*
+ * If the DSAP (and HP's extended DXSAP) indicate this
+ * is an RMP packet, hand it to the raw input routine.
+ */
+ if (llc->dsap == IEEE_DSAP_HP && llc->dxsap == HPEXT_DXSAP) {
+ static struct sockproto rmp_sp = {AF_RMP,RMPPROTO_BOOT};
+ static struct sockaddr rmp_src = {AF_RMP};
+ static struct sockaddr rmp_dst = {AF_RMP};
+
+ bcopy(et->ether_shost, rmp_src.sa_data,
+ sizeof(et->ether_shost));
+ bcopy(et->ether_dhost, rmp_dst.sa_data,
+ sizeof(et->ether_dhost));
+
+ raw_input(m, &rmp_sp, &rmp_src, &rmp_dst);
+ return;
+ }
+ }
+#endif
+ ether_input(&le->sc_if, et, m);
+}
+
+/*
+ * Routine to copy from mbuf chain to transmit
+ * buffer in board local memory.
+ */
+leput(lebuf, m)
+ register char *lebuf;
+ register struct mbuf *m;
+{
+ register struct mbuf *mp;
+ register int len, tlen = 0;
+
+ for (mp = m; mp; mp = mp->m_next) {
+ len = mp->m_len;
+ if (len == 0)
+ continue;
+ tlen += len;
+ bcopy(mtod(mp, char *), lebuf, len);
+ lebuf += len;
+ }
+ m_freem(m);
+ if (tlen < LEMINSIZE) {
+ bzero(lebuf, LEMINSIZE - tlen);
+ tlen = LEMINSIZE;
+ }
+ return(tlen);
+}
+
+/*
+ * Routine to copy from board local memory into mbufs.
+ */
+struct mbuf *
+leget(lebuf, totlen, off0, ifp)
+ char *lebuf;
+ int totlen, off0;
+ struct ifnet *ifp;
+{
+ register struct mbuf *m;
+ struct mbuf *top = 0, **mp = &top;
+ register int off = off0, len;
+ register char *cp;
+ char *epkt;
+
+ lebuf += sizeof (struct ether_header);
+ cp = lebuf;
+ epkt = cp + totlen;
+ if (off) {
+ cp += off + 2 * sizeof(u_short);
+ totlen -= 2 * sizeof(u_short);
+ }
+
+ MGETHDR(m, M_DONTWAIT, MT_DATA);
+ if (m == 0)
+ return (0);
+ m->m_pkthdr.rcvif = ifp;
+ m->m_pkthdr.len = totlen;
+ m->m_len = MHLEN;
+
+ while (totlen > 0) {
+ if (top) {
+ MGET(m, M_DONTWAIT, MT_DATA);
+ if (m == 0) {
+ m_freem(top);
+ return (0);
+ }
+ m->m_len = MLEN;
+ }
+ len = min(totlen, epkt - cp);
+ if (len >= MINCLSIZE) {
+ MCLGET(m, M_DONTWAIT);
+ if (m->m_flags & M_EXT)
+ m->m_len = len = min(len, MCLBYTES);
+ else
+ len = m->m_len;
+ } else {
+ /*
+ * Place initial small packet/header at end of mbuf.
+ */
+ if (len < m->m_len) {
+ if (top == 0 && len + max_linkhdr <= m->m_len)
+ m->m_data += max_linkhdr;
+ m->m_len = len;
+ } else
+ len = m->m_len;
+ }
+ bcopy(cp, mtod(m, caddr_t), (unsigned)len);
+ cp += len;
+ *mp = m;
+ mp = &m->m_next;
+ totlen -= len;
+ if (cp == epkt)
+ cp = lebuf;
+ }
+ return (top);
+}
+
+/*
+ * Process an ioctl request.
+ */
+leioctl(ifp, cmd, data)
+ register struct ifnet *ifp;
+ int cmd;
+ caddr_t data;
+{
+ register struct ifaddr *ifa = (struct ifaddr *)data;
+ struct le_softc *le = (struct le_softc *) lecd.cd_devs[ifp->if_unit];
+ struct lereg1 *ler1 = le->sc_r1;
+ int s = splimp(), error = 0;
+
+ switch (cmd) {
+
+ case SIOCSIFADDR:
+ ifp->if_flags |= IFF_UP;
+ switch (ifa->ifa_addr->sa_family) {
+#ifdef INET
+ case AF_INET:
+ leinit(ifp->if_unit); /* before arpwhohas */
+ ((struct arpcom *)ifp)->ac_ipaddr =
+ IA_SIN(ifa)->sin_addr;
+ arpwhohas((struct arpcom *)ifp, &IA_SIN(ifa)->sin_addr);
+ 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 *)(le->sc_addr);
+ else {
+ /*
+ * The manual says we can't change the address
+ * while the receiver is armed,
+ * so reset everything
+ */
+ ifp->if_flags &= ~IFF_RUNNING;
+ bcopy((caddr_t)ina->x_host.c_host,
+ (caddr_t)le->sc_addr, sizeof(le->sc_addr));
+ }
+ leinit(ifp->if_unit); /* does le_setaddr() */
+ break;
+ }
+#endif
+ default:
+ leinit(ifp->if_unit);
+ break;
+ }
+ break;
+
+ case SIOCSIFFLAGS:
+ if ((ifp->if_flags & IFF_UP) == 0 &&
+ ifp->if_flags & IFF_RUNNING) {
+ LERDWR(le->sc_r0, LE_STOP, ler1->ler1_rdp);
+ ifp->if_flags &= ~IFF_RUNNING;
+ } else if (ifp->if_flags & IFF_UP &&
+ (ifp->if_flags & IFF_RUNNING) == 0)
+ leinit(ifp->if_unit);
+ /*
+ * If the state of the promiscuous bit changes, the interface
+ * must be reset to effect the change.
+ */
+ if (((ifp->if_flags ^ le->sc_iflags) & IFF_PROMISC) &&
+ (ifp->if_flags & IFF_RUNNING)) {
+ le->sc_iflags = ifp->if_flags;
+ lereset(ifp->if_unit);
+ lestart(ifp);
+ }
+ break;
+
+ default:
+ error = EINVAL;
+ }
+ splx(s);
+ return (error);
+}
+
+leerror(unit, stat)
+ int unit;
+ int stat;
+{
+ struct le_softc *le = NULL;
+
+
+ if (!ledebug)
+ return;
+
+ le = (struct le_softc *) lecd.cd_devs[unit];
+ /*
+ * Not all transceivers implement heartbeat
+ * so we only log CERR once.
+ */
+ if ((stat & LE_CERR) && le->sc_cerr)
+ return;
+ log(LOG_WARNING,
+ "le%d: error: stat=%b\n", unit,
+ stat,
+ "\20\20ERR\17BABL\16CERR\15MISS\14MERR\13RINT\12TINT\11IDON\10INTR\07INEA\06RXON\05TXON\04TDMD\03STOP\02STRT\01INIT");
+}
+
+lererror(unit, msg)
+ int unit;
+ char *msg;
+{
+ register struct le_softc *le = lecd.cd_devs[unit];
+ register struct lermd *rmd;
+ int len;
+
+ if (!ledebug)
+ return;
+
+ rmd = &le->sc_r2->ler2_rmd[le->sc_rmd];
+ len = rmd->rmd3;
+ log(LOG_WARNING,
+ "le%d: ierror(%s): from %s: buf=%d, len=%d, rmd1=%b\n",
+ unit, msg,
+ len > 11 ? ether_sprintf(&le->sc_r2->ler2_rbuf[le->sc_rmd][6]) : "unknown",
+ le->sc_rmd, len,
+ rmd->rmd1,
+ "\20\20OWN\17ERR\16FRAM\15OFLO\14CRC\13RBUF\12STP\11ENP");
+}
+
+lexerror(unit)
+ int unit;
+{
+ register struct le_softc *le = lecd.cd_devs[unit];
+ register struct letmd *tmd;
+ int len;
+
+ if (!ledebug)
+ return;
+
+ tmd = le->sc_r2->ler2_tmd;
+ len = -tmd->tmd2;
+ log(LOG_WARNING,
+ "le%d: oerror: to %s: buf=%d, len=%d, tmd1=%b, tmd3=%b\n",
+ unit,
+ len > 5 ? ether_sprintf(&le->sc_r2->ler2_tbuf[0][0]) : "unknown",
+ 0, len,
+ tmd->tmd1,
+ "\20\20OWN\17ERR\16RES\15MORE\14ONE\13DEF\12STP\11ENP",
+ tmd->tmd3,
+ "\20\20BUFF\17UFLO\16RES\15LCOL\14LCAR\13RTRY");
+}
diff --git a/sys/arch/sun3/dev/if_le.h b/sys/arch/sun3/dev/if_le.h
new file mode 100644
index 00000000000..87e04603e0f
--- /dev/null
+++ b/sys/arch/sun3/dev/if_le.h
@@ -0,0 +1,34 @@
+/*
+ * Ethernet software status per interface.
+ *
+ * Each interface is referenced by a network interface structure,
+ * le_if, which the routing code uses to locate the interface.
+ * This structure contains the output queue for the interface, its address, ...
+ */
+struct le_softc {
+ struct device sc_dev;
+ struct arpcom sc_ac; /* common Ethernet structures */
+#define sc_if sc_ac.ac_if /* network-visible interface */
+#define sc_addr sc_ac.ac_enaddr /* hardware Ethernet address */
+ char *sc_machdep; /* machine dependent pointer */
+ struct lereg1 *sc_r1; /* LANCE registers */
+ struct lereg2 *sc_r2; /* dual-port RAM */
+ int sc_rmd; /* predicted next rmd to process */
+ int sc_runt;
+ int sc_jab;
+ int sc_merr;
+ int sc_babl;
+ int sc_cerr;
+ int sc_miss;
+ int sc_xint;
+ int sc_xown;
+ int sc_uflo;
+ int sc_rxlen;
+ int sc_rxoff;
+ int sc_txoff;
+ int sc_busy;
+ short sc_iflags;
+#if NBPFILTER > 0
+ caddr_t sc_bpf;
+#endif
+};
diff --git a/sys/arch/sun3/dev/if_le_subr.c b/sys/arch/sun3/dev/if_le_subr.c
new file mode 100644
index 00000000000..476ec71233c
--- /dev/null
+++ b/sys/arch/sun3/dev/if_le_subr.c
@@ -0,0 +1,82 @@
+#include "sys/param.h"
+#include "sys/systm.h"
+#include "sys/protosw.h"
+#include "sys/socket.h"
+#include "sys/device.h"
+#include "net/if.h"
+
+#ifdef INET
+#include "netinet/in.h"
+#include "netinet/in_systm.h"
+#include "netinet/in_var.h"
+#include "netinet/ip.h"
+#include "netinet/if_ether.h"
+#endif
+
+#include "machine/autoconf.h"
+#include "machine/cpu.h"
+#include "machine/isr.h"
+#include "machine/mtpr.h"
+#include "machine/obio.h"
+#include "machine/idprom.h"
+
+#include "bpfilter.h"
+
+#include "if_lereg.h"
+#include "if_le.h"
+
+/*
+ * things to do:
+ * allocate dvma area memory for dual access
+ * use/default config parameters for lance configuration
+ * setup isr handler
+ * set ethernet address
+ * set meta address
+ *
+ */
+
+int le_machdep_attach(parent, self, args)
+ struct device *parent;
+ struct device *self;
+ void *args;
+{
+ caddr_t dvma_malloc(), le_addr;
+ int level, leintr(), unit = DEVICE_UNIT(self);
+ struct le_softc *le = (struct le_softc *) self;
+ struct obio_cf_loc *obio_loc = OBIO_LOC(self);
+
+ /* allocate "shared" memory */
+ le->sc_r2 =
+ (struct lereg2 *) dvma_malloc(sizeof(struct lereg2));
+ if (!le->sc_r2) {
+ printf(": not enough dvma space\n");
+ return 1;
+ }
+ idprom_etheraddr(le->sc_addr); /* ethernet addr */
+ le_addr = OBIO_DEFAULT_PARAM(caddr_t, obio_loc->obio_addr, OBIO_AMD_ETHER);
+
+ /* register access */
+ le->sc_r1 = (struct lereg1 *)
+ obio_alloc(le_addr, (caddr_t) OBIO_AMD_ETHER_SIZE, OBIO_WRITE);
+ if (!le->sc_r1) {
+ printf(": not enough obio space\n");
+ return 1;
+ }
+ level = OBIO_DEFAULT_PARAM(int, obio_loc->obio_level, 3);
+ obio_print(le_addr, level);
+ le->sc_machdep = NULL;
+ isr_add(level, leintr, unit);
+ return 0;
+}
+
+int le_machdep_match(parent, cf, args)
+ struct device *parent;
+ struct cfdata *cf;
+ void *args;
+{
+ caddr_t le_addr;
+ struct obio_cf_loc *obio_loc = (struct obio_cf_loc *) CFDATA_LOC(cf);
+
+ le_addr = OBIO_DEFAULT_PARAM(caddr_t, obio_loc->obio_addr, OBIO_AMD_ETHER);
+ return /* !obio_probe_byte(le_addr)*/ 1;
+}
diff --git a/sys/arch/sun3/dev/if_le_subr.h b/sys/arch/sun3/dev/if_le_subr.h
new file mode 100644
index 00000000000..1ac7f2f0471
--- /dev/null
+++ b/sys/arch/sun3/dev/if_le_subr.h
@@ -0,0 +1,5 @@
+/* access LANCE registers */
+
+#define LERDWR(cntl, src, dst) (dst) = (src)
+
+#define le_machdep_intrcheck(le, unit)
diff --git a/sys/arch/sun3/dev/if_lereg.h b/sys/arch/sun3/dev/if_lereg.h
new file mode 100644
index 00000000000..6e8bb775b47
--- /dev/null
+++ b/sys/arch/sun3/dev/if_lereg.h
@@ -0,0 +1,149 @@
+/*
+ * Copyright (c) 1982, 1990 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.
+ *
+ * from: @(#)if_lereg.h 7.1 (Berkeley) 5/8/90
+ * if_lereg.h,v 1.2 1993/05/22 07:56:25 cgd Exp
+ */
+
+#define LEID 21
+
+#define LEMTU 1518
+#define LEMINSIZE 60 /* should be 64 if mode DTCR is set */
+#define LERBUF 8
+#define LERBUFLOG2 3
+#define LE_RLEN (LERBUFLOG2 << 13)
+#define LETBUF 1
+#define LETBUFLOG2 0
+#define LE_TLEN (LETBUFLOG2 << 13)
+
+#define vu_char volatile u_char
+
+/*
+ * LANCE registers.
+ */
+
+struct lereg1 {
+ u_short ler1_rdp; /* data port */
+ u_short ler1_rap; /* register select port */
+};
+
+/*
+ * Overlayed on 16K dual-port RAM.
+ * Current size is 13,758 bytes with 8 x 1518 receive buffers and
+ * 1 x 1518 transmit buffer.
+ */
+struct lereg2 {
+ /* init block */
+ u_short ler2_mode; /* +0x0000 */
+ u_char ler2_padr[6]; /* +0x0002 */
+ u_long ler2_ladrf0; /* +0x0008 */
+ u_long ler2_ladrf1; /* +0x000C */
+ u_short ler2_rdra; /* +0x0010 */
+ u_short ler2_rlen; /* +0x0012 */
+ u_short ler2_tdra; /* +0x0014 */
+ u_short ler2_tlen; /* +0x0016 */
+ /* receive message descriptors */
+ struct lermd { /* +0x0018 */
+ u_short rmd0;
+ u_short rmd1;
+ short rmd2;
+ u_short rmd3;
+ } ler2_rmd[LERBUF];
+ /* transmit message descriptors */
+ struct letmd { /* +0x0058 */
+ u_short tmd0;
+ u_short tmd1;
+ short tmd2;
+ u_short tmd3;
+ } ler2_tmd[LETBUF];
+ char ler2_rbuf[LERBUF][LEMTU]; /* +0x0060 */
+ char ler2_tbuf[LETBUF][LEMTU]; /* +0x2FD0 */
+};
+
+/*
+ * Control and status bits -- lereg0
+ */
+#define LE_IE 0x80 /* interrupt enable */
+#define LE_IR 0x40 /* interrupt requested */
+#define LE_LOCK 0x08 /* lock status register */
+#define LE_ACK 0x04 /* ack of lock */
+#define LE_JAB 0x02 /* loss of tx clock (???) */
+#define LE_IPL(x) ((((x) >> 4) & 0x3) + 3)
+
+/*
+ * Control and status bits -- lereg1
+ */
+#define LE_CSR0 0
+#define LE_CSR1 1
+#define LE_CSR2 2
+#define LE_CSR3 3
+
+#define LE_SERR 0x8000
+#define LE_BABL 0x4000
+#define LE_CERR 0x2000
+#define LE_MISS 0x1000
+#define LE_MERR 0x0800
+#define LE_RINT 0x0400
+#define LE_TINT 0x0200
+#define LE_IDON 0x0100
+#define LE_INTR 0x0080
+#define LE_INEA 0x0040
+#define LE_RXON 0x0020
+#define LE_TXON 0x0010
+#define LE_TDMD 0x0008
+#define LE_STOP 0x0004
+#define LE_STRT 0x0002
+#define LE_INIT 0x0001
+
+#define LE_BSWP 0x4
+#define LE_MODE 0x0
+
+/*
+ * Control and status bits -- lereg2
+ */
+#define LE_OWN 0x8000
+#define LE_ERR 0x4000
+#define LE_STP 0x0200
+#define LE_ENP 0x0100
+
+#define LE_FRAM 0x2000
+#define LE_OFLO 0x1000
+#define LE_CRC 0x0800
+#define LE_RBUFF 0x0400
+#define LE_MORE 0x1000
+#define LE_ONE 0x0800
+#define LE_DEF 0x0400
+#define LE_TBUFF 0x8000
+#define LE_UFLO 0x4000
+#define LE_LCOL 0x1000
+#define LE_LCAR 0x0800
+#define LE_RTRY 0x0400
diff --git a/sys/arch/sun3/dev/obctl.c b/sys/arch/sun3/dev/obctl.c
new file mode 100644
index 00000000000..0558f24b73d
--- /dev/null
+++ b/sys/arch/sun3/dev/obctl.c
@@ -0,0 +1,38 @@
+#include "sys/systm.h"
+#include "sys/device.h"
+
+#include "machine/autoconf.h"
+#include "machine/obctl.h"
+#include "machine/param.h"
+
+extern void obctlattach __P((struct device *, struct device *, void *));
+
+struct obctl_softc {
+ struct device obctl_dev;
+};
+
+struct cfdriver obctlcd =
+{ NULL, "obctl", always_match, obctlattach, DV_DULL,
+ sizeof(struct obctl_softc), 0};
+
+void obctl_print(addr, size)
+ caddr_t addr;
+ int size;
+{
+ printf(" addr 0x%x size 0x%x", addr, size);
+}
+
+void obctlattach(parent, self, args)
+ struct device *parent;
+ struct device *self;
+ void *args;
+{
+ struct cfdata *new_match;
+
+ printf("\n");
+ while (1) {
+ new_match = config_search(NULL, self, NULL);
+ if (!new_match) break;
+ config_attach(self, new_match, NULL, NULL);
+ }
+}
diff --git a/sys/arch/sun3/dev/obio.c b/sys/arch/sun3/dev/obio.c
index 944cdee02e4..2b139c9f786 100644
--- a/sys/arch/sun3/dev/obio.c
+++ b/sys/arch/sun3/dev/obio.c
@@ -1,18 +1,20 @@
-#include "systm.h"
+#include "sys/systm.h"
+#include "sys/device.h"
+#include "machine/autoconf.h"
#include "machine/obio.h"
#include "machine/pte.h"
#include "machine/param.h"
#include "machine/mon.h"
+#include "machine/isr.h"
#define ALL 0xFF
extern vm_offset_t intersil_va;
-
-char *interrupt_reg;
-vm_offset_t eeprom_va;
-vm_offset_t memerr_va;
+char *interrupt_reg = NULL;
+vm_offset_t eeprom_va = NULL;
+vm_offset_t memerr_va = NULL;
static struct obio_internal {
vm_offset_t *obio_internal_va;
@@ -29,6 +31,39 @@ static struct obio_internal {
/* {&ecc_va, OBIO_MEMERR, ALL, OBIO_MEMERR_SIZE }, */
};
+extern void obioattach __P((struct device *, struct device *, void *));
+
+struct obio_softc {
+ struct device obio_dev;
+};
+
+struct cfdriver obiocd =
+{ NULL, "obio", always_match, obioattach, DV_DULL,
+ sizeof(struct obio_softc), 0};
+
+void obio_print(addr, level)
+ caddr_t addr;
+ int level;
+{
+ printf(" addr 0x%x", addr);
+ if (level >=0)
+ printf(" level %d", level);
+}
+
+void obioattach(parent, self, args)
+ struct device *parent;
+ struct device *self;
+ void *args;
+{
+ struct cfdata *new_match;
+
+ printf("\n");
+ while (1) {
+ new_match = config_search(NULL, self, NULL);
+ if (!new_match) break;
+ config_attach(self, new_match, NULL, NULL);
+ }
+}
/*
* this routine "configures" any internal OBIO devices which must be
@@ -48,7 +83,7 @@ void obio_internal_configure()
for (oip = obio_internal_dev; oip->obio_internal_va; oip++) {
if ((cpu_machine_id & oip->obio_cpu_mask) == 0) continue;
- npages = (sun3_round_page(oip->obio_size)) >>PGSHIFT;
+ npages = PA_PGNUM(sun3_round_page(oip->obio_size));
va = high_segment_alloc(npages);
if (!va)
mon_panic("obio_internal_configure: short pages for internal devs");
@@ -58,6 +93,35 @@ void obio_internal_configure()
pte_proto |= PG_WRITE;
obio_pa = oip->obio_addr;
for (; npages != 0; npages--, va += NBPG, obio_pa += NBPG)
- set_pte(va, pte_proto | (obio_pa >> PGSHIFT));
+ set_pte(va, pte_proto | PA_PGNUM(obio_pa));
}
}
+
+caddr_t obio_alloc(obio_addr, obio_size, obio_flags)
+ caddr_t obio_addr;
+ caddr_t obio_size;
+ int obio_flags;
+{
+ int npages;
+ vm_offset_t va, high_segment_alloc(), obio_pa, obio_va, pte_proto;
+
+ npages = PA_PGNUM(sun3_round_page(obio_size));
+ if (!npages)
+ panic("obio_alloc: attempt to allocate 0 pages for obio");
+ va = high_segment_alloc(npages);
+ if (!va)
+ va = (vm_offset_t) obio_vm_alloc(npages);
+ if (!va)
+ panic("obio_alloc: unable to allocate va for obio mapping");
+ pte_proto = PG_VALID|PG_SYSTEM|PG_OBIO;
+ if ((obio_flags & OBIO_CACHE) == 0)
+ pte_proto |= PG_NC;
+ if (obio_flags & OBIO_WRITE)
+ pte_proto |= PG_WRITE;
+ obio_va = va;
+ obio_pa = (vm_offset_t) obio_addr;
+ for (; npages ; npages--, obio_va += NBPG, obio_pa += NBPG)
+ set_pte(obio_va, pte_proto | PA_PGNUM(obio_pa));
+ return (caddr_t) va;
+}
+
diff --git a/sys/arch/sun3/dev/obmem.c b/sys/arch/sun3/dev/obmem.c
new file mode 100644
index 00000000000..095cce6bfbd
--- /dev/null
+++ b/sys/arch/sun3/dev/obmem.c
@@ -0,0 +1,42 @@
+#include "sys/systm.h"
+#include "sys/device.h"
+
+#include "machine/autoconf.h"
+#include "machine/obmem.h"
+#include "machine/param.h"
+
+extern void obmemattach __P((struct device *, struct device *, void *));
+
+struct obmem_softc {
+ struct device obmem_dev;
+};
+
+struct cfdriver obmemcd =
+{ NULL, "obmem", always_match, obmemattach, DV_DULL,
+ sizeof(struct obmem_softc), 0};
+
+void obmem_print(addr, size, level)
+ caddr_t addr;
+ int size;
+ int level;
+{
+ printf(" addr 0x%x size 0x%x", addr, size);
+ if (level <0)
+ printf(" level %d\n", level);
+}
+
+void obmemattach(parent, self, args)
+ struct device *parent;
+ struct device *self;
+ void *args;
+{
+ struct cfdata *new_match;
+
+ printf("\n");
+ while (1) {
+ new_match = config_search(NULL, self, NULL);
+ if (!new_match) break;
+ config_attach(self, new_match, NULL, NULL);
+ }
+
+}
diff --git a/sys/arch/sun3/dev/prom.c b/sys/arch/sun3/dev/prom.c
index 46cabadc001..f610dd4d66d 100644
--- a/sys/arch/sun3/dev/prom.c
+++ b/sys/arch/sun3/dev/prom.c
@@ -6,21 +6,43 @@
#include "sys/tty.h"
#include "sys/file.h"
#include "sys/conf.h"
+#include "device.h"
+#include "machine/autoconf.h"
#include "machine/mon.h"
#include "../sun3/cons.h"
#include "prom.h"
+void promattach __P((struct device *, struct device *, void *));
+
struct prom_softc {
int flags;
int nopen;
struct tty t;
-} prom_softc[NPROM];
+};
+
+struct cfdriver promcd =
+{ NULL, "prom", always_match, promattach,
+ DV_TTY, sizeof(struct prom_softc), 0};
-#if NPROM > 1
-error: "Can not configure more than one prom tty"
-#endif
+#define PROM_CHECK(unit) \
+ if (unit >= promcd.cd_ndevs || (promcd.cd_devs[unit] == NULL)) \
+ return ENXIO
+#define UNIT_TO_PROMP(unit) promcd.cd_devs[unit]
+
+void promattach(parent, self, args)
+ struct device *parent;
+ struct device *self;
+ void *args;
+{
+ struct prom_softc *prom;
+
+ prom = (struct prom_softc *) self;
+ prom->flags = 0;
+ prom->nopen = 0;
+ printf("\n");
+}
int promstart __P((struct tty *));
@@ -35,9 +57,8 @@ int promopen(dev, flag, mode, p)
int s,error=0;
unit = minor(dev);
- if (unit >= NPROM)
- return ENXIO;
- prom = &prom_softc[unit];
+ PROM_CHECK(unit);
+ prom = UNIT_TO_PROMP(unit);
bzero(&prom->t, sizeof(struct tty));
tp = &prom->t;
tp->t_oproc = promstart;
@@ -80,9 +101,8 @@ promclose(dev, flag, mode, p)
struct prom_softc *prom;
unit = minor(dev);
- if (unit >= NPROM)
- return ENXIO;
- prom = &prom_softc[unit];
+ PROM_CHECK(unit);
+ prom = UNIT_TO_PROMP(unit);
tp = &prom->t;
(*linesw[tp->t_line].l_close)(tp, flag);
ttyclose(tp);
@@ -93,36 +113,30 @@ promread(dev, uio, flag)
dev_t dev;
struct uio *uio;
{
- register struct tty *tp = &prom_softc[minor(dev)].t;
-
- return ((*linesw[tp->t_line].l_read)(tp, uio, flag));
+ int unit;
+ register struct tty *tp;
+ struct prom_softc *prom;
+
+ unit = minor(dev);
+ PROM_CHECK(unit);
+ prom = UNIT_TO_PROMP(unit);
+ tp = &prom->t;
+ return ((*linesw[tp->t_line].l_read)(tp, uio, flag));
}
promwrite(dev, uio, flag)
dev_t dev;
struct uio *uio;
{
- register struct tty *tp = &prom_softc[minor(dev)].t;
-
- return ((*linesw[tp->t_line].l_write)(tp, uio, flag));
-}
-
-
-promcnprobe(cp)
- struct consdev *cp;
-{
- int prommajor;
-
- mon_printf("prom console probed (start)\n");
- /* locate the major number */
- for (prommajor = 0; prommajor < nchrdev; prommajor++)
- if (cdevsw[prommajor].d_open == promopen)
- break;
+ int unit;
+ register struct tty *tp;
+ struct prom_softc *prom;
- cp->cn_dev = makedev(prommajor, 0);
- cp->cn_pri = CN_NORMAL; /* will always exist but you don't
- * want to use it unless you have to
- */
- mon_printf("prom console probed (end)\n");
+ unit = minor(dev);
+ PROM_CHECK(unit);
+ prom = UNIT_TO_PROMP(unit);
+ tp = &prom->t;
+
+ return ((*linesw[tp->t_line].l_write)(tp, uio, flag));
}
int promstart(tp)
@@ -167,16 +181,33 @@ promstop(tp, flag)
splx(s);
}
+/* prom console support */
+
+promcnprobe(cp)
+ struct consdev *cp;
+{
+ int prommajor;
+
+ mon_printf("prom console probed (start)\n");
+ /* locate the major number */
+ for (prommajor = 0; prommajor < nchrdev; prommajor++)
+ if (cdevsw[prommajor].d_open == promopen)
+ break;
+ cp->cn_dev = makedev(prommajor, 0);
+ cp->cn_pri = CN_NORMAL; /* will always exist but you don't
+ * want to use it unless you have to
+ */
+ mon_printf("prom console probed (end)\n");
+}
promcninit(cp)
struct consdev *cp;
{
- cp->cn_tp = &prom_softc[0].t;
+ cp->cn_tp = NULL;
mon_printf("prom console initialized\n");
}
-
promcngetc(dev)
dev_t dev;
{
@@ -194,4 +225,3 @@ promcnputc(dev, c)
mon_printf("non unit 0 prom console???\n");
mon_putchar(c);
}
-
diff --git a/sys/arch/sun3/include/autoconf.h b/sys/arch/sun3/include/autoconf.h
new file mode 100644
index 00000000000..6a05f015779
--- /dev/null
+++ b/sys/arch/sun3/include/autoconf.h
@@ -0,0 +1,5 @@
+
+int always_match __P((struct device *, struct cfdata *, void *));
+
+#define DEVICE_UNIT(device) (device->dv_unit)
+#define CFDATA_LOC(cfdata) (cfdata->cf_loc)
diff --git a/sys/arch/sun3/include/idprom.h b/sys/arch/sun3/include/idprom.h
index cf1578a84c0..595da273b43 100644
--- a/sys/arch/sun3/include/idprom.h
+++ b/sys/arch/sun3/include/idprom.h
@@ -8,15 +8,15 @@
struct idprom {
unsigned char idp_format;
unsigned char idp_machtype;
- unsigned char idp_etheraddr;
+ unsigned char idp_etheraddr[6];
long idp_date;
unsigned char idp_serialnum[3];
unsigned char idp_checksum;
- unsigned char ipd_reserved[16];
+ unsigned char idp_reserved[16];
};
#define IDPROM_VERSION 1
#define IDPROM_SIZE (sizeof(struct idprom))
-int idprom_fetch __P((struct idprom *, int version));
-
+int idprom_fetch __P((struct idprom *, int));
+void idprom_etheraddr __P((u_char *));
diff --git a/sys/arch/sun3/include/isr.h b/sys/arch/sun3/include/isr.h
index 085ecb2ecd5..60f124cd6f3 100644
--- a/sys/arch/sun3/include/isr.h
+++ b/sys/arch/sun3/include/isr.h
@@ -42,5 +42,7 @@ struct isr {
int isr_ipl;
};
-#define NISR 3
-#define ISRIPL(x) ((x) - 3)
+#define NISR 8
+
+void isr_init __P((void));
+void isr_add __P((int, int (*handler)(), int ));
diff --git a/sys/arch/sun3/include/obctl.h b/sys/arch/sun3/include/obctl.h
new file mode 100644
index 00000000000..de9da66abdd
--- /dev/null
+++ b/sys/arch/sun3/include/obctl.h
@@ -0,0 +1,12 @@
+
+struct obctl_cf_loc {
+ int obctl_addr;
+ int obctl_size;
+};
+
+#define OBCTL_DEFAULT_PARAM(cast, arg, default) \
+ (cast) (arg == -1 ? default : arg)
+
+#define OBCTL_LOC(device) (struct obctl_cf_loc *) device->dv_cfdata->cf_loc
+
+
diff --git a/sys/arch/sun3/include/obio.h b/sys/arch/sun3/include/obio.h
index eea575d230d..84d42087ede 100644
--- a/sys/arch/sun3/include/obio.h
+++ b/sys/arch/sun3/include/obio.h
@@ -39,6 +39,26 @@
#define OBIO_DES_SIZE 0x00004
#define OBIO_ECCREG_SIZE 0x00100
+/* flags to obio_alloc() */
+#define OBIO_CACHE 0x1
+#define OBIO_WRITE 0x2
+
+struct obio_cf_loc {
+ int obio_addr;
+ int obio_level;
+};
+
+caddr_t obio_alloc __P((caddr_t, caddr_t, int));
+caddr_t obio_vm_alloc __P((int));
+void obio_print __P((caddr_t addr, int level));
+void obio_probe __P((caddr_t addr));
+
+
+#define OBIO_DEFAULT_PARAM(cast, arg, default) \
+ (cast) (arg == -1 ? default : arg)
+
+#define OBIO_LOC(device) (struct obio_cf_loc *) device->dv_cfdata->cf_loc
+
#ifdef KERNEL
extern char *interrupt_reg;
diff --git a/sys/arch/sun3/include/obmem.h b/sys/arch/sun3/include/obmem.h
new file mode 100644
index 00000000000..026e84bdba5
--- /dev/null
+++ b/sys/arch/sun3/include/obmem.h
@@ -0,0 +1,9 @@
+/* put something in here about framebuffers... */
+
+struct obmem_cf_loc {
+ int obmem_cf_addr;
+ int obmem_cf_size;
+ int obmem_cf_level;
+};
+
+
diff --git a/sys/arch/sun3/include/vmparam.h b/sys/arch/sun3/include/vmparam.h
index c29d6715cd7..7fa2e065dfd 100644
--- a/sys/arch/sun3/include/vmparam.h
+++ b/sys/arch/sun3/include/vmparam.h
@@ -68,6 +68,9 @@
#define SAFERSS 4 /* nominal ``small'' resident set size
protected against replacement */
+#define DVMA_SPACE_SIZE 0x00100000
+#define DVMA_SPACE_START 0x0FD00000
+#define DVMA_SPACE_END 0x0FE00000 /* mon start */
/*
* Mach derived constants
@@ -78,7 +81,7 @@
#define VM_MAXUSER_ADDRESS ((vm_offset_t)0x0E000000)
#define VM_MAX_ADDRESS ((vm_offset_t)0xFFF00000)
#define VM_MIN_KERNEL_ADDRESS ((vm_offset_t)0x0E004000)
-#define VM_MAX_KERNEL_ADDRESS ((vm_offset_t)0x0FE00000) /* mon start */
+#define VM_MAX_KERNEL_ADDRESS ((vm_offset_t)0x0FD00000) /* mon start */
/* virtual sizes (bytes) for various kernel submaps */
#define VM_MBUF_SIZE (NMBCLUSTERS*MCLBYTES)
diff --git a/sys/arch/sun3/include/vmparam3.h b/sys/arch/sun3/include/vmparam3.h
index c29d6715cd7..7fa2e065dfd 100644
--- a/sys/arch/sun3/include/vmparam3.h
+++ b/sys/arch/sun3/include/vmparam3.h
@@ -68,6 +68,9 @@
#define SAFERSS 4 /* nominal ``small'' resident set size
protected against replacement */
+#define DVMA_SPACE_SIZE 0x00100000
+#define DVMA_SPACE_START 0x0FD00000
+#define DVMA_SPACE_END 0x0FE00000 /* mon start */
/*
* Mach derived constants
@@ -78,7 +81,7 @@
#define VM_MAXUSER_ADDRESS ((vm_offset_t)0x0E000000)
#define VM_MAX_ADDRESS ((vm_offset_t)0xFFF00000)
#define VM_MIN_KERNEL_ADDRESS ((vm_offset_t)0x0E004000)
-#define VM_MAX_KERNEL_ADDRESS ((vm_offset_t)0x0FE00000) /* mon start */
+#define VM_MAX_KERNEL_ADDRESS ((vm_offset_t)0x0FD00000) /* mon start */
/* virtual sizes (bytes) for various kernel submaps */
#define VM_MBUF_SIZE (NMBCLUSTERS*MCLBYTES)
diff --git a/sys/arch/sun3/sun3/TODO b/sys/arch/sun3/sun3/TODO
index 84cbb787da8..b3265726e85 100644
--- a/sys/arch/sun3/sun3/TODO
+++ b/sys/arch/sun3/sun3/TODO
@@ -1,9 +1,4 @@
- move idprom.h into include and out of dev
- start thinking about autoconfig
- add idprom to SOLIPSIST config file
- figure out spl layout
figure out stack issues
- fix sun3_vm_init()->pmap_bootstraping->sys/vm interfacing problems
figure out how much of process.s we are going to rewrite because
we have a different mmu
diff --git a/sys/arch/sun3/sun3/autoconf.c b/sys/arch/sun3/sun3/autoconf.c
index 4de6446a610..959470ba19c 100644
--- a/sys/arch/sun3/sun3/autoconf.c
+++ b/sys/arch/sun3/sun3/autoconf.c
@@ -1,47 +1,4 @@
/*
- * Copyright (c) 1988 University of Utah.
- * Copyright (c) 1982, 1986, 1990 The Regents of the University of California.
- * All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * the Systems Programming Group of the University of Utah Computer
- * Science Department.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * from: Utah $Hdr: autoconf.c 1.31 91/01/21$
- *
- * from: @(#)autoconf.c 7.5 (Berkeley) 5/7/91
- * autoconf.c,v 1.4 1993/07/07 06:26:59 cgd Exp
- */
-
-/*
* Setup the system to run on the current machine.
*
* Configure() is called at boot time. Available
@@ -57,17 +14,54 @@
#include "sys/conf.h"
#include "sys/dmap.h"
#include "sys/reboot.h"
+#include "sys/device.h"
+
+#include "machine/autoconf.h"
+#include "machine/vmparam.h"
+#include "machine/cpu.h"
+#include "machine/pte.h"
+#include "machine/isr.h"
-#include "../include/vmparam.h"
-#include "../include/cpu.h"
-#include "pte.h"
-#include "isr.h"
+extern void mainbusattach __P((struct device *, struct device *, void *));
+
+struct mainbus_softc {
+ struct device mainbus_dev;
+};
+struct cfdriver mainbuscd =
+{ NULL, "mainbus", always_match, mainbusattach, DV_DULL,
+ sizeof(struct mainbus_softc), 0};
-struct isr isrqueue[NISR];
+void mainbusattach(parent, self, args)
+ struct device *parent;
+ struct device *self;
+ void *args;
+{
+ struct cfdata *new_match;
+
+ printf("\n");
+ while (1) {
+ new_match = config_search(NULL, self, NULL);
+ if (!new_match) break;
+ config_attach(self, new_match, NULL, NULL);
+ }
+}
+
+void configure()
+{
+ int root_found;
+
+ isr_init();
+
+ root_found = config_rootfound("mainbus", NULL);
+ if (!root_found)
+ panic("configure: autoconfig failed, no device tree root found");
+}
-void
-configure()
+int always_match(parent, cf, args)
+ struct device *parent;
+ struct cfdata *cf;
+ void *args;
{
- isrinit();
+ return 1;
}
diff --git a/sys/arch/sun3/sun3/idprom.c b/sys/arch/sun3/sun3/idprom.c
index f56d3d94369..96846c8c6e5 100644
--- a/sys/arch/sun3/sun3/idprom.c
+++ b/sys/arch/sun3/sun3/idprom.c
@@ -1,30 +1,71 @@
#include "systm.h"
+#include "device.h"
+
+#include "machine/autoconf.h"
+#include "machine/control.h"
#include "machine/idprom.h"
+#include "machine/obctl.h"
+
#include "idprom.h"
-static int idprom_init = 0;
+extern void idpromattach __P((struct device *, struct device *, void *));
+
+struct idprom_softc {
+ struct device idprom_driver;
+ int idprom_init;
+ struct idprom idprom_copy;
+ char *idprom_addr;
+ int idprom_size;
+};
+
+struct cfdriver idpromcd =
+{ NULL, "idprom", always_match, idpromattach, DV_DULL,
+ sizeof(struct idprom_softc), 0};
-static struct idprom idprom_copy;
+#define IDPROM_CHECK(unit) \
+ if (unit >= idpromcd.cd_ndevs || (idpromcd.cd_devs[unit] == NULL)) \
+ return ENXIO
+#define UNIT_TO_IDP(unit) idpromcd.cd_devs[unit]
+
+
+void idpromattach(parent, self, args)
+ struct device *parent;
+ struct device *self;
+ void *args;
+{
+ struct idprom_softc *idp = (struct idprom_softc *) self;
+ struct obctl_cf_loc *obctl_loc = OBCTL_LOC(self);
-static int idprom_ok = 0;
+ idp->idprom_init = 0;
-int idprom_open(dev, oflags, devtype, p)
+ idp->idprom_addr =
+ OBCTL_DEFAULT_PARAM(char *, obctl_loc->obctl_addr, IDPROM_BASE);
+ idp->idprom_size =
+ OBCTL_DEFAULT_PARAM(int, obctl_loc->obctl_size, IDPROM_SIZE);
+ obctl_print(idp->idprom_addr, idp->idprom_size);
+ printf("\n");
+}
+
+int idpromopen(dev, oflags, devtype, p)
dev_t dev;
int oflags;
int devtype;
struct proc *p;
{
- int unit,s;
+ struct idprom_softc *idp;
+ int unit, idprom_ok;
unit = minor(dev);
- if (unit >= NIDPROM)
- return ENXIO;
- if (!idprom_init) idprom_ok = idprom_fetch(&idprom_copy, IDPROM_VERSION);
+ IDPROM_CHECK(unit);
+ idp = UNIT_TO_IDP(unit);
+ if (!idp->idprom_init)
+ idprom_ok = idprom_fetch(&idp->idprom_copy, IDPROM_VERSION);
if (!idprom_ok) return EIO;
+ idp->idprom_init = 1;
return 0;
}
-int idprom_close(dev, fflag, devtype, p)
+int idpromclose(dev, fflag, devtype, p)
dev_t dev;
int fflag;
int devtype;
@@ -33,30 +74,27 @@ int idprom_close(dev, fflag, devtype, p)
int unit;
unit = minor(dev);
- if (unit >= NIDPROM)
- return ENXIO;
+ IDPROM_CHECK(unit);
return 0;
}
-idprom_read(dev, uio, ioflag)
+idpromread(dev, uio, ioflag)
dev_t dev;
struct uio *uio;
int ioflag;
{
- int error, unit,length;
-
+ int error, unit, length;
+ struct idprom_softc *idp;
unit = minor(dev);
-
- if (unit >= NIDPROM)
- return ENXIO;
-
+ IDPROM_CHECK(unit);
+ idp = UNIT_TO_IDP(unit);
+ if (!idp->idprom_init) return EIO;
error = 0;
while (uio->uio_resid > 0) {
- if (uio->uio_offset >= IDPROM_SIZE) break; /* past or at end */
- length = min(uio->uio_resid, (IDPROM_SIZE-uio->uio_offset));
- error = uiomove((caddr_t) &idprom_copy, length, uio);
+ if (uio->uio_offset >= idp->idprom_size) break; /* past or at end */
+ length = min(uio->uio_resid, (idp->idprom_size - uio->uio_offset));
+ error = uiomove((caddr_t) &idp->idprom_copy, length, uio);
}
return error;
}
-
diff --git a/sys/arch/sun3/sun3/isr.c b/sys/arch/sun3/sun3/isr.c
new file mode 100644
index 00000000000..6532c3079d3
--- /dev/null
+++ b/sys/arch/sun3/sun3/isr.c
@@ -0,0 +1,89 @@
+#include "param.h"
+#include "systm.h"
+#include "malloc.h"
+
+#include "net/netisr.h"
+#include "machine/isr.h"
+
+
+struct isr *isr_array[NISR];
+
+void isr_init()
+{
+ int i;
+
+ for (i = 0; i < NISR; i++)
+ isr_array[i] = NULL;
+}
+
+void isr_add(level, handler, arg)
+ int level;
+ int (*handler)();
+ int arg;
+{
+ struct isr *new_isr;
+
+ if ((level < 0) || (level >= NISR))
+ panic("isr_add: attempt to add handler for bad level");
+ new_isr = (struct isr *)
+ malloc(sizeof(struct isr), M_DEVBUF, M_NOWAIT);
+ if (!new_isr)
+ panic("isr_add: allocation of new 'isr' failed");
+ new_isr->isr_arg = arg;
+ new_isr->isr_ipl = level;
+ new_isr->isr_intr = handler;
+ new_isr->isr_back = NULL;
+ if (isr_array[level])
+ new_isr->isr_forw = isr_array[level];
+ isr_array[level] = new_isr;
+}
+
+void intrhand(sr)
+ int sr;
+{
+ struct isr *isr;
+ int found;
+ int ipl;
+
+ ipl = (sr >> 8) & 7;
+
+ isr = isr_array[ipl];
+ if (!isr) {
+ printf("intrhand: unexpected sr 0x%x\n", sr);
+ return;
+ }
+ if (!ipl) {
+ printf("intrhand: spurious interrupt\n");
+ return;
+ }
+ found = 0;
+ for (; isr != NULL; isr = isr->isr_forw)
+ if (isr->isr_intr(isr->isr_arg)) {
+ found++;
+ break;
+ }
+ if (!found)
+ printf("intrhand: stray interrupt, sr 0x%x\n", sr);
+}
+
+netintr()
+{
+#ifdef INET
+ if (netisr & (1 << NETISR_IP)) {
+ netisr &= ~(1 << NETISR_IP);
+ ipintr();
+ }
+#endif
+#ifdef NS
+ if (netisr & (1 << NETISR_NS)) {
+ netisr &= ~(1 << NETISR_NS);
+ nsintr();
+ }
+#endif
+#ifdef ISO
+ if (netisr & (1 << NETISR_ISO)) {
+ netisr &= ~(1 << NETISR_ISO);
+ clnlintr();
+ }
+#endif
+}
diff --git a/sys/arch/sun3/sun3/locore2.c b/sys/arch/sun3/sun3/locore2.c
index 3a5c8f4754b..11682ad6088 100644
--- a/sys/arch/sun3/sun3/locore2.c
+++ b/sys/arch/sun3/sun3/locore2.c
@@ -274,6 +274,17 @@ void sun3_vm_init()
sun3_context_equiv();
}
+void idprom_etheraddr(eaddrp)
+ u_char *eaddrp;
+{
+ eaddrp[0] = identity_prom.idp_etheraddr[0];
+ eaddrp[1] = identity_prom.idp_etheraddr[1];
+ eaddrp[2] = identity_prom.idp_etheraddr[2];
+ eaddrp[3] = identity_prom.idp_etheraddr[3];
+ eaddrp[4] = identity_prom.idp_etheraddr[4];
+ eaddrp[5] = identity_prom.idp_etheraddr[5];
+}
+
void sun3_verify_hardware()
{
unsigned char arch;
diff --git a/sys/arch/sun3/sun3/machdep.c b/sys/arch/sun3/sun3/machdep.c
index 3a017394331..5aef37e8a62 100644
--- a/sys/arch/sun3/sun3/machdep.c
+++ b/sys/arch/sun3/sun3/machdep.c
@@ -134,14 +134,14 @@ void cpu_startup()
size = (vm_size_t)(v - firstaddr);
firstaddr = (caddr_t) kmem_alloc(kernel_map, round_page(size));
if (firstaddr == 0)
- panic("startup: no room for tables");
+ panic("cpu_startup: no room for tables");
goto again;
}
/*
* End of second pass, addresses have been assigned
*/
if ((vm_size_t)(v - firstaddr) != size)
- panic("startup: table size inconsistency");
+ panic("cpu_startup: table size inconsistency");
/* buffer_map stuff but not used */
/*
* Allocate a submap for exec arguments. This map effectively
@@ -152,10 +152,11 @@ void cpu_startup()
* NOT CURRENTLY USED -- cgd
*/
/*
- * Allocate a submap for physio
+ * Allocate a map for physio and DVMA
*/
- phys_map = kmem_suballoc(kernel_map, &minaddr, &maxaddr,
- VM_PHYS_SIZE, TRUE);
+ phys_map = vm_map_create(kernel_pmap, DVMA_SPACE_START, DVMA_SPACE_END, 0);
+ if (!phys_map)
+ panic("cpu_startup: unable to create physmap");
/*
* Finally, allocate mbuf pool. Since mclrefcnt is an off-size
@@ -183,7 +184,7 @@ void cpu_startup()
* Configure the system.
*/
printf("about to call configure\n");
-/* configure();*/
+ configure();
sun3_stop();
cold = 0;
@@ -840,64 +841,3 @@ hexstr(val, len)
return(nbuf);
}
-netintr()
-{
-#ifdef INET
- if (netisr & (1 << NETISR_IP)) {
- netisr &= ~(1 << NETISR_IP);
- ipintr();
- }
-#endif
-#ifdef NS
- if (netisr & (1 << NETISR_NS)) {
- netisr &= ~(1 << NETISR_NS);
- nsintr();
- }
-#endif
-#ifdef ISO
- if (netisr & (1 << NETISR_ISO)) {
- netisr &= ~(1 << NETISR_ISO);
- clnlintr();
- }
-#endif
-}
-
-intrhand(sr)
- int sr;
-{
-#if 0
- register struct isr *isr;
- register int found = 0;
- register int ipl;
- extern struct isr isrqueue[];
-
- ipl = (sr >> 8) & 7;
- switch (ipl) {
-
- case 1:
- case 2:
- case 3:
- case 4:
- case 5:
- case 6:
- case 7:
- ipl = ISRIPL(ipl);
- isr = isrqueue[ipl].isr_forw;
- for (; isr != &isrqueue[ipl]; isr = isr->isr_forw) {
- if ((isr->isr_intr)(isr->isr_arg)) {
- found++;
- break;
- }
- }
- if (found == 0)
- printf("stray interrupt, sr 0x%x\n", sr);
- break;
-
- case 0:
- default:
- printf("intrhand: unexpected sr 0x%x\n", sr);
- break;
- }
-#endif
-}
-
diff --git a/sys/arch/sun3/sun3/obio.c b/sys/arch/sun3/sun3/obio.c
index 944cdee02e4..2b139c9f786 100644
--- a/sys/arch/sun3/sun3/obio.c
+++ b/sys/arch/sun3/sun3/obio.c
@@ -1,18 +1,20 @@
-#include "systm.h"
+#include "sys/systm.h"
+#include "sys/device.h"
+#include "machine/autoconf.h"
#include "machine/obio.h"
#include "machine/pte.h"
#include "machine/param.h"
#include "machine/mon.h"
+#include "machine/isr.h"
#define ALL 0xFF
extern vm_offset_t intersil_va;
-
-char *interrupt_reg;
-vm_offset_t eeprom_va;
-vm_offset_t memerr_va;
+char *interrupt_reg = NULL;
+vm_offset_t eeprom_va = NULL;
+vm_offset_t memerr_va = NULL;
static struct obio_internal {
vm_offset_t *obio_internal_va;
@@ -29,6 +31,39 @@ static struct obio_internal {
/* {&ecc_va, OBIO_MEMERR, ALL, OBIO_MEMERR_SIZE }, */
};
+extern void obioattach __P((struct device *, struct device *, void *));
+
+struct obio_softc {
+ struct device obio_dev;
+};
+
+struct cfdriver obiocd =
+{ NULL, "obio", always_match, obioattach, DV_DULL,
+ sizeof(struct obio_softc), 0};
+
+void obio_print(addr, level)
+ caddr_t addr;
+ int level;
+{
+ printf(" addr 0x%x", addr);
+ if (level >=0)
+ printf(" level %d", level);
+}
+
+void obioattach(parent, self, args)
+ struct device *parent;
+ struct device *self;
+ void *args;
+{
+ struct cfdata *new_match;
+
+ printf("\n");
+ while (1) {
+ new_match = config_search(NULL, self, NULL);
+ if (!new_match) break;
+ config_attach(self, new_match, NULL, NULL);
+ }
+}
/*
* this routine "configures" any internal OBIO devices which must be
@@ -48,7 +83,7 @@ void obio_internal_configure()
for (oip = obio_internal_dev; oip->obio_internal_va; oip++) {
if ((cpu_machine_id & oip->obio_cpu_mask) == 0) continue;
- npages = (sun3_round_page(oip->obio_size)) >>PGSHIFT;
+ npages = PA_PGNUM(sun3_round_page(oip->obio_size));
va = high_segment_alloc(npages);
if (!va)
mon_panic("obio_internal_configure: short pages for internal devs");
@@ -58,6 +93,35 @@ void obio_internal_configure()
pte_proto |= PG_WRITE;
obio_pa = oip->obio_addr;
for (; npages != 0; npages--, va += NBPG, obio_pa += NBPG)
- set_pte(va, pte_proto | (obio_pa >> PGSHIFT));
+ set_pte(va, pte_proto | PA_PGNUM(obio_pa));
}
}
+
+caddr_t obio_alloc(obio_addr, obio_size, obio_flags)
+ caddr_t obio_addr;
+ caddr_t obio_size;
+ int obio_flags;
+{
+ int npages;
+ vm_offset_t va, high_segment_alloc(), obio_pa, obio_va, pte_proto;
+
+ npages = PA_PGNUM(sun3_round_page(obio_size));
+ if (!npages)
+ panic("obio_alloc: attempt to allocate 0 pages for obio");
+ va = high_segment_alloc(npages);
+ if (!va)
+ va = (vm_offset_t) obio_vm_alloc(npages);
+ if (!va)
+ panic("obio_alloc: unable to allocate va for obio mapping");
+ pte_proto = PG_VALID|PG_SYSTEM|PG_OBIO;
+ if ((obio_flags & OBIO_CACHE) == 0)
+ pte_proto |= PG_NC;
+ if (obio_flags & OBIO_WRITE)
+ pte_proto |= PG_WRITE;
+ obio_va = va;
+ obio_pa = (vm_offset_t) obio_addr;
+ for (; npages ; npages--, obio_va += NBPG, obio_pa += NBPG)
+ set_pte(obio_va, pte_proto | PA_PGNUM(obio_pa));
+ return (caddr_t) va;
+}
+
diff --git a/sys/arch/sun3/sun3/obio.h b/sys/arch/sun3/sun3/obio.h
index eea575d230d..84d42087ede 100644
--- a/sys/arch/sun3/sun3/obio.h
+++ b/sys/arch/sun3/sun3/obio.h
@@ -39,6 +39,26 @@
#define OBIO_DES_SIZE 0x00004
#define OBIO_ECCREG_SIZE 0x00100
+/* flags to obio_alloc() */
+#define OBIO_CACHE 0x1
+#define OBIO_WRITE 0x2
+
+struct obio_cf_loc {
+ int obio_addr;
+ int obio_level;
+};
+
+caddr_t obio_alloc __P((caddr_t, caddr_t, int));
+caddr_t obio_vm_alloc __P((int));
+void obio_print __P((caddr_t addr, int level));
+void obio_probe __P((caddr_t addr));
+
+
+#define OBIO_DEFAULT_PARAM(cast, arg, default) \
+ (cast) (arg == -1 ? default : arg)
+
+#define OBIO_LOC(device) (struct obio_cf_loc *) device->dv_cfdata->cf_loc
+
#ifdef KERNEL
extern char *interrupt_reg;
diff --git a/sys/arch/sun3/sun3/obmem.c b/sys/arch/sun3/sun3/obmem.c
new file mode 100644
index 00000000000..095cce6bfbd
--- /dev/null
+++ b/sys/arch/sun3/sun3/obmem.c
@@ -0,0 +1,42 @@
+#include "sys/systm.h"
+#include "sys/device.h"
+
+#include "machine/autoconf.h"
+#include "machine/obmem.h"
+#include "machine/param.h"
+
+extern void obmemattach __P((struct device *, struct device *, void *));
+
+struct obmem_softc {
+ struct device obmem_dev;
+};
+
+struct cfdriver obmemcd =
+{ NULL, "obmem", always_match, obmemattach, DV_DULL,
+ sizeof(struct obmem_softc), 0};
+
+void obmem_print(addr, size, level)
+ caddr_t addr;
+ int size;
+ int level;
+{
+ printf(" addr 0x%x size 0x%x", addr, size);
+ if (level <0)
+ printf(" level %d\n", level);
+}
+
+void obmemattach(parent, self, args)
+ struct device *parent;
+ struct device *self;
+ void *args;
+{
+ struct cfdata *new_match;
+
+ printf("\n");
+ while (1) {
+ new_match = config_search(NULL, self, NULL);
+ if (!new_match) break;
+ config_attach(self, new_match, NULL, NULL);
+ }
+
+}
diff --git a/sys/arch/sun3/sun3/obmem.h b/sys/arch/sun3/sun3/obmem.h
new file mode 100644
index 00000000000..026e84bdba5
--- /dev/null
+++ b/sys/arch/sun3/sun3/obmem.h
@@ -0,0 +1,9 @@
+/* put something in here about framebuffers... */
+
+struct obmem_cf_loc {
+ int obmem_cf_addr;
+ int obmem_cf_size;
+ int obmem_cf_level;
+};
+
+
diff --git a/sys/arch/sun3/sun3/pmap.c b/sys/arch/sun3/sun3/pmap.c
index 4ccf066b50a..38cd0cd2cae 100644
--- a/sys/arch/sun3/sun3/pmap.c
+++ b/sys/arch/sun3/sun3/pmap.c
@@ -480,8 +480,6 @@ pmeg_t pmeg_allocate_invalid(pmap, va)
pmegp->pmeg_reserved = 0;
pmegp->pmeg_vpages = 0;
enqueue_tail(&pmeg_active_queue, pmegp);
- printf("pmeg_allocate_invalid: pmeg %d allocated to pmap %x\n",
- pmegp->pmeg_index, pmap);
return pmegp;
}
@@ -635,54 +633,39 @@ unsigned char pv_link(pmap, pa, va, flags)
head = pv = pa_to_pvp(pa);
PMAP_LOCK();
- printf("entering pv_link, pv == %x\n", pv);
- printf("entering pv_link, pv_head_table == %x\n", pv_head_table);
- printf("entering pv_link, pa == %x pgnum %x\n", pa, PA_PGNUM(pa));
if (pv->pv_pmap == NULL) { /* not currently "managed" */
pv->pv_va = va;
pv->pv_pmap = pmap,
pv->pv_next = NULL;
pv->pv_flags = flags;
- printf("pv_link: before force_cache_flags\n");
force_cache_flags(pa, flags);
- printf("pv_link: not currently managed\n");
return flags & PV_NC;
}
- printf("entering pv_link loop\n");
for (npv = pv ; npv != NULL; last= npv, npv = npv->pv_next ) {
if ((npv->pv_pmap != pmap) || (npv->pv_va != va)) continue;
- printf("pv_link: found match\n");
if (flags == npv->pv_flags) /* no change */
return get_cache_flags(pa);
npv->pv_flags = flags;
goto recompute;
}
- printf("entering pv_link new entry\n");
/*zalloc(pv_zone);*/
pv = malloc(sizeof(struct pv_entry), M_VMPVENT, M_WAITOK);
pv->pv_va = va;
pv->pv_pmap = pmap,
pv->pv_next = NULL;
pv->pv_flags = flags;
- printf("entering pv_link before last\n");
last->pv_next = pv;
- printf("entering pv_link after last\n");
recompute:
if (get_cache_flags(pa) & PG_NC) return flags & PV_NC; /* already NC */
if (flags & PV_NC) { /* being NCed, wasn't before */
force_cache_flags(pa, flags);
- printf("pv_link: change pte 1\n");
pv_change_pte(head, MAKE_PV_REAL(PV_NC), 0);
- printf("pv_link: change pte 1 end\n");
return flags & PV_NC;
}
- printf("pv_link: cache compute\n");
nflags = pv_compute_cache(head);
force_cache_flags(pa, nflags);
- printf("pv_link: change pte 2 \n");
pv_change_pte(head, MAKE_PV_REAL(nflags), 0); /* */
- printf("pv_link: change pte 2 after\n");
return nflags & PV_NC;
}
void pv_change_pte(pv_list, set_bits, clear_bits)
@@ -798,10 +781,6 @@ void pv_init()
mon_panic("pmap: kmem_alloc() of pv cache table failed");
bzero(pv_cache_table, sizeof(char)* PA_PGNUM(avail_end));
pv_initialized++;
- printf("PV: head: %x\n modified: %x\n cache: %x\n",
- pv_head_table,
- pv_modified_table,
- pv_cache_table);
}
void sun3_protection_init()
@@ -1028,11 +1007,10 @@ void pmap_remove_range_mmu(pmap, sva, eva)
pmeg_t pmegp;
vm_offset_t va,pte;
- printf("entering pmap_remove_range_mmu: %x -> %x\n", sva, eva);
saved_context = get_context();
if (pmap != kernel_pmap)
set_context(pmap->pm_context->context_num);
- printf("pmap_remove_range_mmu: past stupid context thing\n");
+
sme = get_segmap(sva);
if (sme == SEGINV) {
if (pmap == kernel_pmap) return;
@@ -1044,28 +1022,19 @@ void pmap_remove_range_mmu(pmap, sva, eva)
pmegp = pmeg_p(sme);
/* have pmeg, will travel */
if (!pmegp->pmeg_vpages) goto outta_here; /* no valid pages anyway */
- printf("pmap_remove_range_mmu: starting removal");
+
va = sva;
while (va < eva) {
pte = get_pte(va);
if (pte & PG_VALID) {
- printf("before save_modified_bits(): %x\n", pv_modified_table);
- printf("before save_modified_bits(): PG_PGNUM(pte)== %x\n",
- PG_PGNUM(pte));
- printf("before save_modified_bits(): pv_init %d\n",
- pv_initialized);
if (pv_initialized)
save_modified_bits(pte);
- printf("after save_modified_bits()\n");
pv_unlink(pmap, PG_PA(pte), va);
- printf("after after pv_unlink()\n");
pmegp->pmeg_vpages--;
- printf("after pmegp->pmeg_vpages--\n");
set_pte(va, PG_INVAL);
}
va+= NBPG;
}
- printf("pmap_remove_range_mmu: past removal");
if (pmegp->pmeg_vpages <= 0) {
if (is_pmeg_wired(pmegp))
printf("pmap: removing wired pmeg\n");
@@ -1079,7 +1048,6 @@ void pmap_remove_range_mmu(pmap, sva, eva)
else
set_segmap(sva, SEGINV);
}
- printf("pmap_remove_range_mmu: past cleanup");
outta_here:
set_context(saved_context);
}
@@ -1219,8 +1187,6 @@ void pmap_enter_kernel(va, pa, prot, wired, pte_proto, mem_type)
*/
if (va < VM_MIN_KERNEL_ADDRESS)
printf("pmap: kernel trying to allocate virtual space below itself\n");
- if ((va+NBPG) >= VM_MAX_KERNEL_ADDRESS)
- printf("pmap: kernel trying to allocate virtual space above itself\n");
s = splpmap();
sme = get_segmap(va);
/* XXXX -- lots of non-defined routines, need to see if pmap has a
@@ -1270,8 +1236,6 @@ add_pte: /* can be destructive */
else
set_pte(va, pte_proto);
}
- printf("pmap_enter_kernel: va: %x pa: %x pte_proto: %x\n", va, pa,
- pte_proto);
pmegp->pmeg_vpages++; /* assumes pmap_enter can never insert
a non-valid page*/
splx(s);
diff --git a/sys/arch/sun3/sun3/sun3_startup.c b/sys/arch/sun3/sun3/sun3_startup.c
index 3a5c8f4754b..11682ad6088 100644
--- a/sys/arch/sun3/sun3/sun3_startup.c
+++ b/sys/arch/sun3/sun3/sun3_startup.c
@@ -274,6 +274,17 @@ void sun3_vm_init()
sun3_context_equiv();
}
+void idprom_etheraddr(eaddrp)
+ u_char *eaddrp;
+{
+ eaddrp[0] = identity_prom.idp_etheraddr[0];
+ eaddrp[1] = identity_prom.idp_etheraddr[1];
+ eaddrp[2] = identity_prom.idp_etheraddr[2];
+ eaddrp[3] = identity_prom.idp_etheraddr[3];
+ eaddrp[4] = identity_prom.idp_etheraddr[4];
+ eaddrp[5] = identity_prom.idp_etheraddr[5];
+}
+
void sun3_verify_hardware()
{
unsigned char arch;
diff --git a/sys/arch/sun3/sun3/vm_machdep.c b/sys/arch/sun3/sun3/vm_machdep.c
index bfdf4a5e6f8..c9d214d5cfb 100644
--- a/sys/arch/sun3/sun3/vm_machdep.c
+++ b/sys/arch/sun3/sun3/vm_machdep.c
@@ -7,6 +7,7 @@
#include "vm/vm.h"
#include "vm/vm_kern.h"
+#include "vm/vm_map.h"
#include "machine/cpu.h"
#include "machine/pte.h"
@@ -153,3 +154,39 @@ vunmapbuf(bp)
bp->b_un.b_addr = bp->b_saveaddr;
bp->b_saveaddr = NULL;
}
+
+/* idea for implementation borrowed from chris torek */
+
+caddr_t dvma_malloc(size)
+ size_t size;
+{
+ caddr_t new_mem;
+ vm_size_t new_size;
+
+ if (!size)
+ return NULL;
+ new_size = sun3_round_page(size);
+ new_mem = (caddr_t) kmem_alloc(phys_map, new_size);
+ if (!new_mem)
+ panic("dvma_malloc: no space in phys_map");
+ /* uncache this piece of memory :) */
+ return new_mem;
+}
+
+caddr_t obio_vm_alloc(npages)
+ int npages;
+{
+ vm_size_t size;
+ vm_offset_t addr;
+ int result;
+
+ if (npages == 0);
+ size = npages*NBPG;
+ addr = vm_map_min(phys_map);
+ result = vm_map_find(phys_map, NULL, (vm_offset_t) 0, &addr, size, TRUE);
+ if (result != KERN_SUCCESS) return NULL;
+ vm_map_lock(phys_map);
+ vm_map_delete(phys_map, addr, addr+size);
+ vm_map_unlock(phys_map);
+ return (caddr_t) addr;
+}
diff --git a/sys/conf/files.newconf b/sys/conf/files.newconf
index 1b7bf7a044c..34e41c063d1 100644
--- a/sys/conf/files.newconf
+++ b/sys/conf/files.newconf
@@ -34,10 +34,6 @@ pseudo-device sl: ifnet
pseudo-device tun: ifnet
pseudo-device bpfilter: ifnet
-pseudo-device devpager
-pseudo-device swappager
-pseudo-device vnodepager
-
# kernel sources
file ddb/db_access.c ddb
file ddb/db_aout.c ddb
@@ -86,6 +82,7 @@ file kern/kern_time.c
file kern/kern_xxx.c
file kern/spec_vnops.c
file kern/subr_acct.c accounting
+file kern/subr_autoconf.c
file kern/subr_log.c
file kern/subr_mcount.c profiling-routine
file kern/subr_prf.c
@@ -236,9 +233,9 @@ file ufs/ufs_subr.c
file ufs/ufs_tables.c
file ufs/ufs_vfsops.c
file ufs/ufs_vnops.c
-file vm/device_pager.c devpager needs-count
+file vm/device_pager.c devpager
file vm/kern_lock.c
-file vm/swap_pager.c swappager needs-count
+file vm/swap_pager.c swappager
file vm/vm_fault.c
file vm/vm_glue.c
file vm/vm_init.c
@@ -253,4 +250,4 @@ file vm/vm_pager.c
file vm/vm_swap.c
file vm/vm_unix.c
file vm/vm_user.c
-file vm/vnode_pager.c vnodepager needs-count
+file vm/vnode_pager.c vnodepager
diff --git a/sys/kern/subr_autoconf.c b/sys/kern/subr_autoconf.c
index d2e47c6218c..cd5d3a9dcb5 100644
--- a/sys/kern/subr_autoconf.c
+++ b/sys/kern/subr_autoconf.c
@@ -15,7 +15,7 @@
*
* %W% (Berkeley) %G%
*
- * from: $Header: /cvsroot/src/sys/kern/subr_autoconf.c,v 1.2 1993/08/13 22:00:55 glass Exp $ (LBL)
+ * from: $Header: /cvsroot/src/sys/kern/subr_autoconf.c,v 1.3 1993/08/15 23:04:50 glass Exp $ (LBL)
*/
#include "param.h"
@@ -56,8 +56,14 @@ mapply(m, cf)
if (m->fn != NULL)
pri = (*m->fn)(m->parent, cf, m->aux);
- else
+ else {
+ if (!cf->cf_driver->cd_match) {
+ printf("mapply: no match function for '%s' device\n",
+ cf->cf_driver->cd_name);
+ panic("mapply: not match function\n");
+ }
pri = (*cf->cf_driver->cd_match)(m->parent, cf, m->aux);
+ }
if (pri > m->pri) {
m->match = cf;
m->pri = pri;
@@ -157,7 +163,8 @@ config_found(parent, aux, print)
config_attach(parent, cf, aux, print);
return (1);
}
- printf(msgs[(*print)(aux, parent->dv_xname)]);
+ if (print)
+ printf(msgs[(*print)(aux, parent->dv_xname)]);
return (0);
}
@@ -230,8 +237,9 @@ config_attach(parent, cf, aux, print)
panic("config_attach: device name too long");
/* get memory for all device vars */
- dev = (struct device *)malloc(cd->cd_devsize, M_DEVBUF, M_WAITOK);
- /* XXX cannot wait! */
+ dev = (struct device *)malloc(cd->cd_devsize, M_DEVBUF, M_NOWAIT);
+ if (!dev)
+ panic("config_attach: memory allocation for device softc failed");
bzero(dev, cd->cd_devsize);
*nextp = dev; /* link up */
nextp = &dev->dv_next;
@@ -245,7 +253,8 @@ config_attach(parent, cf, aux, print)
printf("%s (root)", dev->dv_xname);
else {
printf("%s at %s", dev->dv_xname, parent->dv_xname);
- (void) (*print)(aux, (char *)0);
+ if (print)
+ (void) (*print)(aux, (char *)0);
}
/* put this device in the devices array */
@@ -257,7 +266,9 @@ config_attach(parent, cf, aux, print)
void **nsp;
if (old == 0) {
- nsp = malloc(MINALLOCSIZE, M_DEVBUF, M_WAITOK); /*XXX*/
+ nsp = malloc(MINALLOCSIZE, M_DEVBUF, M_NOWAIT);
+ if (!nsp)
+ panic("config_attach: expanding dev array");
bzero(nsp, MINALLOCSIZE);
cd->cd_ndevs = MINALLOCSIZE / sizeof(void *);
} else {
@@ -268,7 +279,9 @@ config_attach(parent, cf, aux, print)
cd->cd_ndevs = new;
oldbytes = old * sizeof(void *);
newbytes = new * sizeof(void *);
- nsp = malloc(newbytes, M_DEVBUF, M_WAITOK); /*XXX*/
+ nsp = malloc(newbytes, M_DEVBUF, M_NOWAIT);
+ if (!nsp)
+ panic("config_attach: expanding dev array (2)");
bcopy(cd->cd_devs, nsp, oldbytes);
bzero(&nsp[old], newbytes - oldbytes);
free(cd->cd_devs, M_DEVBUF);