summaryrefslogtreecommitdiff
path: root/sys/arch/mvme68k
diff options
context:
space:
mode:
Diffstat (limited to 'sys/arch/mvme68k')
-rw-r--r--sys/arch/mvme68k/Makefile5
-rw-r--r--sys/arch/mvme68k/README152
-rw-r--r--sys/arch/mvme68k/compile/.keep_me1
-rw-r--r--sys/arch/mvme68k/conf/Makefile.mvme68k164
-rw-r--r--sys/arch/mvme68k/conf/VME14751
-rw-r--r--sys/arch/mvme68k/conf/files.mvme68k49
-rw-r--r--sys/arch/mvme68k/dev/if_le.c965
-rw-r--r--sys/arch/mvme68k/dev/if_lereg.h167
-rw-r--r--sys/arch/mvme68k/dev/iio.c114
-rw-r--r--sys/arch/mvme68k/dev/iio.h18
-rw-r--r--sys/arch/mvme68k/dev/pcc.c171
-rw-r--r--sys/arch/mvme68k/dev/pccreg.h130
-rw-r--r--sys/arch/mvme68k/dev/scc.h64
-rw-r--r--sys/arch/mvme68k/dev/zs.c996
-rw-r--r--sys/arch/mvme68k/include/ansi.h4
-rw-r--r--sys/arch/mvme68k/include/asm.h3
-rw-r--r--sys/arch/mvme68k/include/cdefs.h8
-rw-r--r--sys/arch/mvme68k/include/cpu.h230
-rw-r--r--sys/arch/mvme68k/include/db_machdep.h4
-rw-r--r--sys/arch/mvme68k/include/disklabel.h46
-rw-r--r--sys/arch/mvme68k/include/endian.h4
-rw-r--r--sys/arch/mvme68k/include/exec.h48
-rw-r--r--sys/arch/mvme68k/include/float.h8
-rw-r--r--sys/arch/mvme68k/include/frame.h3
-rw-r--r--sys/arch/mvme68k/include/limits.h4
-rw-r--r--sys/arch/mvme68k/include/param.h184
-rw-r--r--sys/arch/mvme68k/include/pcb.h67
-rw-r--r--sys/arch/mvme68k/include/pmap.h159
-rw-r--r--sys/arch/mvme68k/include/proc.h53
-rw-r--r--sys/arch/mvme68k/include/profile.h3
-rw-r--r--sys/arch/mvme68k/include/psl.h3
-rw-r--r--sys/arch/mvme68k/include/pte.h152
-rw-r--r--sys/arch/mvme68k/include/ptrace.h4
-rw-r--r--sys/arch/mvme68k/include/reg.h8
-rw-r--r--sys/arch/mvme68k/include/setjmp.h3
-rw-r--r--sys/arch/mvme68k/include/signal.h4
-rw-r--r--sys/arch/mvme68k/include/stdarg.h4
-rw-r--r--sys/arch/mvme68k/include/trap.h3
-rw-r--r--sys/arch/mvme68k/include/types.h10
-rw-r--r--sys/arch/mvme68k/include/varargs.h4
-rw-r--r--sys/arch/mvme68k/include/vmparam.h246
-rw-r--r--sys/arch/mvme68k/mvme68k/autoconf.c251
-rw-r--r--sys/arch/mvme68k/mvme68k/clock.c367
-rw-r--r--sys/arch/mvme68k/mvme68k/clockreg.h76
-rw-r--r--sys/arch/mvme68k/mvme68k/conf.c284
-rw-r--r--sys/arch/mvme68k/mvme68k/disksubr.c246
-rw-r--r--sys/arch/mvme68k/mvme68k/dkbad.c66
-rw-r--r--sys/arch/mvme68k/mvme68k/genassym.c208
-rw-r--r--sys/arch/mvme68k/mvme68k/isr.h47
-rw-r--r--sys/arch/mvme68k/mvme68k/locore.s1832
-rw-r--r--sys/arch/mvme68k/mvme68k/machdep.c1471
-rw-r--r--sys/arch/mvme68k/mvme68k/mainbus.c29
-rw-r--r--sys/arch/mvme68k/mvme68k/mem.c222
-rw-r--r--sys/arch/mvme68k/mvme68k/pmap.c2659
-rw-r--r--sys/arch/mvme68k/mvme68k/pmap_bootstrap.c505
-rw-r--r--sys/arch/mvme68k/mvme68k/swapgeneric.c170
-rw-r--r--sys/arch/mvme68k/mvme68k/sys_machdep.c269
-rw-r--r--sys/arch/mvme68k/mvme68k/trap.c1087
-rw-r--r--sys/arch/mvme68k/mvme68k/vectors.s160
-rw-r--r--sys/arch/mvme68k/mvme68k/vm_machdep.c446
-rw-r--r--sys/arch/mvme68k/stand/Makefile5
-rw-r--r--sys/arch/mvme68k/stand/Makefile.inc37
-rw-r--r--sys/arch/mvme68k/stand/libsa/Makefile41
-rw-r--r--sys/arch/mvme68k/stand/libsa/SRT0.S86
-rw-r--r--sys/arch/mvme68k/stand/libsa/SRT1.c71
-rw-r--r--sys/arch/mvme68k/stand/libsa/clock.c128
-rw-r--r--sys/arch/mvme68k/stand/libsa/clock.h6
-rw-r--r--sys/arch/mvme68k/stand/libsa/clockreg.h71
-rw-r--r--sys/arch/mvme68k/stand/libsa/config.h10
-rw-r--r--sys/arch/mvme68k/stand/libsa/devopen.c23
-rw-r--r--sys/arch/mvme68k/stand/libsa/exec.c177
-rw-r--r--sys/arch/mvme68k/stand/libsa/gets.c117
-rw-r--r--sys/arch/mvme68k/stand/libsa/if_lereg.h176
-rw-r--r--sys/arch/mvme68k/stand/libsa/machdep.c154
-rw-r--r--sys/arch/mvme68k/stand/libsa/netif.c531
-rw-r--r--sys/arch/mvme68k/stand/libsa/netif.h22
-rw-r--r--sys/arch/mvme68k/stand/libsa/panic.c31
-rw-r--r--sys/arch/mvme68k/stand/netboot/Makefile15
-rw-r--r--sys/arch/mvme68k/stand/netboot/boot.c77
-rw-r--r--sys/arch/mvme68k/stand/netboot/conf.c23
-rw-r--r--sys/arch/mvme68k/stand/netboot/dev_net.c196
-rw-r--r--sys/arch/mvme68k/stand/netboot/dev_net.h6
-rw-r--r--sys/arch/mvme68k/stand/netboot/version.c9
-rw-r--r--sys/arch/mvme68k/stand/sboot/Makefile19
-rw-r--r--sys/arch/mvme68k/stand/sboot/clock.c117
-rw-r--r--sys/arch/mvme68k/stand/sboot/clockreg.h69
-rw-r--r--sys/arch/mvme68k/stand/sboot/console.c139
-rw-r--r--sys/arch/mvme68k/stand/sboot/etherfun.c213
-rw-r--r--sys/arch/mvme68k/stand/sboot/etherfun.h124
-rw-r--r--sys/arch/mvme68k/stand/sboot/if_lereg.h176
-rw-r--r--sys/arch/mvme68k/stand/sboot/le_poll.c320
-rw-r--r--sys/arch/mvme68k/stand/sboot/libc_sa.c348
-rw-r--r--sys/arch/mvme68k/stand/sboot/oc_cksum.s187
-rw-r--r--sys/arch/mvme68k/stand/sboot/sboot.c150
-rw-r--r--sys/arch/mvme68k/stand/sboot/sboot.h96
-rw-r--r--sys/arch/mvme68k/stand/sboot/start.s47
96 files changed, 18728 insertions, 0 deletions
diff --git a/sys/arch/mvme68k/Makefile b/sys/arch/mvme68k/Makefile
new file mode 100644
index 00000000000..0591b09fa2d
--- /dev/null
+++ b/sys/arch/mvme68k/Makefile
@@ -0,0 +1,5 @@
+# $NetBSD: Makefile,v 1.1.1.1 1995/07/25 23:11:53 chuck Exp $
+
+SUBDIR= stand
+
+.include <bsd.subdir.mk>
diff --git a/sys/arch/mvme68k/README b/sys/arch/mvme68k/README
new file mode 100644
index 00000000000..0b1b930c54e
--- /dev/null
+++ b/sys/arch/mvme68k/README
@@ -0,0 +1,152 @@
+ $NetBSD: README,v 1.1.1.1 1995/07/25 23:11:53 chuck Exp $
+
+NetBSD/mvme68k port
+
+supported environment:
+
+ Motorola makes a number of m68k VME cards. This port
+currently only works on the m68030 based VME147 card (diskless only
+for now).
+
+requirements:
+ - VME147 card
+ - a machine to connect the console to
+ - network connection
+ - NFS server (to serve root and swap)
+
+future plans:
+ - VME147 scsi disk support
+ - hopefully, support for the VME162 card
+
+
+how to boot:
+ Booting NetBSD/mvme68k on a VME147 is somewhat painful because
+the ROM doesn't know how to talk to the ethernet chip. I have solved
+this problem by downloading a bootstrap into RAM via the console line.
+
+ First, you will need a m68k8k NFS mountable /usr and root
+directory. NetBSD/sun3 binaries will run fine on the mvme68k system
+for the most part (the exception being kvm stuff). These binaries can
+be ftp'd from ftp.netbsd.org. You will also need a NetBSD/mvme68k
+kernel and related bootstraps. For now these can be obtained from
+dworkin.wustl.edu in /dist/netbsd/mvme68k_boot.tar.gz (once I get set
+up I will put these plus a snapshot on ftp.netbsd.org).
+
+ Put the mvme68k "netbsd" binary in NFS root directory. Put
+boot.vme147 in /tftpboot of your NFS server machine. Make a symbolic
+link from the hex encoding of your IP address to that file. For
+example:
+
+lrwxrwxrwx 1 root 11 Apr 13 17:27 80FCA93F.147 -> boot.vme147
+
+
+[80FCA93F is the IP address (128.252.169.63) of my vme147.]
+
+Make sure you've got the right info in /etc/ethers and /etc/bootparams
+on your server.
+
+
+Now, bring up your 147. You should have the "bug" prompt:
+
+COLD Start
+
+Onboard RAM start = $00000000, stop = $007FFFFF
+
+147-Bug>
+
+
+Make sure the "stop" looks ok (if you've got 8MB you should have the
+same value as I). Also make sure the clock is ticking:
+
+147-Bug>time
+Sunday 5/30/27 16:25:14
+147-Bug>time
+Sunday 5/30/27 16:25:15
+147-Bug>
+
+
+Looks good. you now need to download "sboot" into RAM. you can
+either do that through the console line or through a 2nd serial
+connection. I have my 147 connected to a sun4/110 and I access it via
+"tip". to load that way do this:
+
+lo 0
+~Ccat sboot
+go 4000
+
+which will look like this:
+147-Bug>
+147-Bug>lo 0
+~CLocal command? cat sboot
+
+away for 11 seconds
+!
+
+147-Bug>g 4000
+Effective address: 00004000
+
+sboot: serial line bootstrap program (&end = 5fd8)
+
+>>>
+
+
+Now, if you want to do it through serial line 1, then connect serial
+line one to a machine. At the "147-Bug> " prompt do this "tm
+1"... you should then login to what ever machine it is connected to.
+Then hit "^A" to escape to Bug. do "lo 1;x=cat sboot" ... then when
+that is done you can reconnect "tm 1" and logout. Then do "go 4000"
+and you've got ">>> " prompt of sboot.
+
+
+Once you've got the ">>> " prompt you can do commands such as:
+"b" - boot "netbsd" multiuser
+"b gennetbsd" - boot "gennetbsd" multiuser
+"b -s" - boot "netbsd" single user
+"b gennetbsd -s"- boot "gennetbsd" single user
+
+A typical boot looks like this:
+
+>>> b
+le0: ethernet address: 8:0:3e:20:cb:87
+My ip address is: 128.252.169.63
+Server ip address is: 128.252.169.2
+3800
+Download was a success!
+Start @ 0x8000 ...
+>> NetBSD netboot [$Revision: 1.1 $]
+boot: client IP address: 128.252.169.63
+boot: client name: vme147
+root addr=128.252.169.2 path=/export/root/vme147
+449744+20348+64444+[29268+29051]=0x90f0b
+Start @ 0x88aa ...
+Copyright (c) 1982, 1986, 1989, 1991, 1993
+ The Regents of the University of California. All rights reserved.
+
+NetBSD 1.0A (VME147) #17: Sat Jul 1 00:07:04 CDT 1995
+ chuck@vme147.ccrc.wustl.edu:/um/netbsd/src/sys/arch/mvme68k/compile/VME147
+Motorola MVME147 MC68030 CPU+MMU, ???MHz MC68882 FPU)
+real mem = 8388608
+avail mem = 6832128
+using 102 buffers containing 417792 bytes of memory
+mainbus0 (root)
+iio0 at mainbus0 addr 0xfffe0000
+pcc0 at iio0 offset 0x1000 rev 0 intbvr 0x40
+clock0 at iio0 offset 0x7f8 ipl 5
+zs0 at iio0 offset 0x3000 ipl 4
+le0 at iio0 offset 0x1800 ipl 2 ler2 0x94000 address 08:00:3e:20:cb:87
+nfs_boot: using network interface 'le0'
+nfs_boot: client_addr=0x80fca93f
+nfs_boot: server_addr=0x80fca902
+nfs_boot: hostname=vme147
+root on dworkin:/export/root/vme147
+root time: 0x2ffc6859
+WARNING: clock gained 18 days -- CHECK AND RESET THE DATE!
+swap on dworkin:/export/swap/vme147
+swap size: 0x4000 (blocks)
+init: copying out path `/sbin/init' 11
+Automatic boot in progress: starting file system checks.
+[etc...]
+
+
+good luck!
+
diff --git a/sys/arch/mvme68k/compile/.keep_me b/sys/arch/mvme68k/compile/.keep_me
new file mode 100644
index 00000000000..aedb72a50a7
--- /dev/null
+++ b/sys/arch/mvme68k/compile/.keep_me
@@ -0,0 +1 @@
+This normally empty directory needs to be kept in the distribution.
diff --git a/sys/arch/mvme68k/conf/Makefile.mvme68k b/sys/arch/mvme68k/conf/Makefile.mvme68k
new file mode 100644
index 00000000000..aaa6a67eb23
--- /dev/null
+++ b/sys/arch/mvme68k/conf/Makefile.mvme68k
@@ -0,0 +1,164 @@
+# $NetBSD: Makefile.mvme68k,v 1.3 1995/09/19 23:50:22 thorpej Exp $
+
+# @(#)Makefile.hp300 8.2 (Berkeley) 1/23/94
+#
+# Makefile for NetBSD
+#
+# This makefile is constructed from a machine description:
+# config machineid
+# Most changes should be made in the machine description
+# /sys/arch/mvme68k/conf/``machineid''
+# after which you should do
+# config.new machineid
+# Machine generic makefile changes should be made in
+# /sys/arch/mvme68k/conf/Makefile.mvme68k
+# after which config should be rerun for all machines of that type.
+#
+# N.B.: NO DEPENDENCIES ON FOLLOWING FLAGS ARE VISIBLE TO MAKEFILE
+# IF YOU CHANGE THE DEFINITION OF ANY OF THESE RECOMPILE EVERYTHING
+#
+# -DTRACE compile in kernel tracing hooks
+# -DQUOTA compile in file system quotas
+
+
+# DEBUG is set to -g by config if debugging is requested (config -g).
+# PROF is set to -pg by config if profiling is requested (config -p).
+AS= as ${DEBUG}
+AWK= awk
+CC= cc ${DEBUG}
+CPP= cpp
+LD= ld
+TOUCH= touch -f -c
+
+# source tree is located via $S relative to the compilation directory
+S= ../../../..
+MVME68K= ../..
+
+INCLUDES= -I. -I$S/arch -I$S -I$S/sys
+COPTS= ${INCLUDES} ${IDENT} -D_KERNEL -Dmc68020 -Dmvme68k -DFPCOPROC
+CFLAGS= -O -Werror -fno-builtin ${COPTS}
+
+### find out what to use for libkern
+.include "$S/lib/libkern/Makefile.inc"
+.ifndef PROF
+LIBKERN= ${KERNLIB}
+.else
+LIBKERN= ${KERNLIB_PROF}
+.endif
+
+### find out what to use for libcompat
+.include "$S/compat/common/Makefile.inc"
+.ifndef PROF
+LIBCOMPAT= ${COMPATLIB}
+.else
+LIBCOMPAT= ${COMPATLIB_PROF}
+.endif
+
+### for the Motorola 68040 Floating Point Software Product
+.include "$S/arch/m68k/fpsp/Makefile.inc"
+
+# compile rules: rules are named ${TYPE}_${SUFFIX}${CONFIG_DEP}
+# where TYPE is NORMAL, DRIVER, or PROFILE}; SUFFIX is the file suffix,
+# capitalized (e.g. C for a .c file), and CONFIG_DEP is _C if the file
+# is marked as config-dependent.
+
+NORMAL_C= ${CC} -c ${CFLAGS} ${PROF} $<
+NORMAL_C_C= ${CC} -c ${CFLAGS} ${PROF} ${PARAM} $<
+
+DRIVER_C= ${CC} -c ${CFLAGS} ${PROF} $<
+DRIVER_C_C= ${CC} -c ${CFLAGS} ${PROF} ${PARAM} $<
+
+PROFILE_C= ${CC} -S -c ${COPTS} $<; \
+ sed -e s/_mcount/mcount/ -e s/subrmcount/subr_mcount/ <$*.s | \
+ ${AS} -o $@; \
+ rm -f $*.s
+
+NORMAL_S= ${CPP} ${COPTS} $< | ${AS} -o $@
+NORMAL_S_C= ${CPP} ${COPTS} ${PARAM} $< | ${AS} -o $@
+
+%OBJS
+
+%CFILES
+
+# load lines for config "xxx" will be emitted as:
+# xxx: ${SYSTEM_DEP} swapxxx.o
+# ${SYSTEM_LD_HEAD}
+# ${SYSTEM_LD} swapxxx.o
+# ${SYSTEM_LD_TAIL}
+DEBUG?=
+.if ${DEBUG} == "-g"
+LDX=-X
+.else
+LDX=-x
+.endif
+SYSTEM_OBJ= locore.o ${FPSP} vnode_if.o ${OBJS} param.o ioconf.o \
+ ${LIBKERN} ${LIBCOMPAT}
+SYSTEM_DEP= Makefile ${SYSTEM_OBJ}
+SYSTEM_LD_HEAD= @echo loading $@; rm -f $@
+SYSTEM_LD= @${LD} ${LDX} -Ttext 0x8000 -n -o $@ -e start \
+ ${SYSTEM_OBJ} vers.o
+SYSTEM_LD_TAIL= @echo rearranging symbols; size $@; chmod 755 $@
+
+%LOAD
+
+newvers: vers.o
+
+vers.o: ${SYSTEM_DEP} ${SYSTEM_SWAP_DEP}
+ sh $S/conf/newvers.sh
+ ${CC} ${CFLAGS} -c vers.c
+
+clean::
+ rm -f eddep *netbsd netbsd.gdb tags vnode_if.[ch] *.o locore.i \
+ [a-z]*.s [Ee]rrs linterrs makelinks genassym
+
+lint: /tmp param.c
+ @lint -hbxn -DGENERIC -Dvolatile= ${COPTS} ${PARAM} -UKGDB \
+ ${MVME68K}/mvme68k/Locore.c ${CFILES} ${MVME68K}/mvme68k/swapgeneric.c \
+ ioconf.c param.c | \
+ grep -v 'struct/union .* never defined' | \
+ grep -v 'possible pointer alignment problem'
+
+locore.o: assym.s ${MVME68K}/mvme68k/vectors.s ${MVME68K}/mvme68k/locore.s
+locore.o: ${MVME68K}/include/trap.h ${MVME68K}/include/psl.h ${MVME68K}/include/pte.h
+locore.o: ${MVME68K}/include/cpu.h
+ ${CPP} -DLOCORE ${COPTS} ${MVME68K}/mvme68k/locore.s | ${AS} -o locore.o
+
+# depend on maxusers
+assym.s: Makefile
+
+assym.s: genassym
+ ./genassym > assym.s
+
+genassym: ${MVME68K}/mvme68k/genassym.c Makefile
+ cc ${INCLUDES} ${IDENT} ${PARAM} -Dmc68020 -Dmvme68k -o genassym \
+ ${MVME68K}/mvme68k/genassym.c
+
+depend: assym.s param.c vnode_if.h
+ mkdep ${COPTS} ${CFILES} ioconf.c param.c
+ mkdep -a -p ${INCLUDES} ${IDENT} ${PARAM} ${MVME68K}/mvme68k/genassym.c
+
+links:
+ egrep '#if' ${CFILES} | sed -f $S/conf/defines | \
+ sed -e 's/:.*//' -e 's/\.c/.o/' | sort -u > dontlink
+ echo ${CFILES} | tr -s ' ' '\12' | sed 's/\.c/.o/' | \
+ sort -u | comm -23 - dontlink | \
+ sed 's,../.*/\(.*.o\),rm -f \1;ln -s ../GENERIC/\1 \1,' > makelinks
+ sh makelinks && rm -f dontlink
+
+tags:
+ @echo "see $S/kern/Makefile for tags"
+
+ioconf.o: ioconf.c
+ ${CC} -c ${CFLAGS} ioconf.c
+
+param.c: $S/conf/param.c
+ rm -f param.c
+ cp $S/conf/param.c .
+
+param.o: param.c Makefile
+ ${CC} -c ${CFLAGS} ${PARAM} param.c
+
+vnode_if.c vnode_if.h: $S/kern/vnode_if.sh $S/kern/vnode_if.src
+ AWK="${AWK}" sh $S/kern/vnode_if.sh $S/kern/vnode_if.src
+
+%RULES
diff --git a/sys/arch/mvme68k/conf/VME147 b/sys/arch/mvme68k/conf/VME147
new file mode 100644
index 00000000000..97498fff5ba
--- /dev/null
+++ b/sys/arch/mvme68k/conf/VME147
@@ -0,0 +1,51 @@
+# $NetBSD: VME147,v 1.1.1.1 1995/07/25 23:12:05 chuck Exp $
+
+machine mvme68k m68k
+
+options "M68040" # support for 040
+options FPSP # MC68040 floating point support
+options "M68030" # support for 030
+options FPCOPROC # Support for MC6888[12] (Required)
+
+maxusers 2
+
+# obsolete timezone spec
+options TIMEZONE=0, DST=0
+
+options DIAGNOSTIC, DEBUG
+#options FFS
+options NFSCLIENT
+#options NFSSERVER
+#options SYSVSHM
+options KTRACE
+options COMPAT_43
+options FIFO
+#options MFS
+options DEVPAGER, SWAPPAGER, VNODEPAGER
+#options MSDOSFS
+
+# Networking options
+options INET
+options TCP_COMPAT_42 # compatibility with 4.2BSD TCP/IP
+#options GATEWAY # IP packet forwarding
+#options ISO # OSI networking
+#options TPIP
+#options EON
+options COMPAT_09, COMPAT_10
+options COMPAT_SUNOS
+
+config netbsd root on nfs swap on nfs
+
+pseudo-device sl
+pseudo-device ppp 2
+pseudo-device loop
+pseudo-device bpfilter
+pseudo-device pty
+
+mainbus0 at root
+iio0 at mainbus0
+
+pcc0 at iio0 offset 0x1000
+zs0 at iio0 offset 0x3000 ipl 4
+clock0 at iio0 offset 0x07f8 ipl 5
+le0 at iio0 offset 0x1800 ipl 2
diff --git a/sys/arch/mvme68k/conf/files.mvme68k b/sys/arch/mvme68k/conf/files.mvme68k
new file mode 100644
index 00000000000..9c6e6ce97bd
--- /dev/null
+++ b/sys/arch/mvme68k/conf/files.mvme68k
@@ -0,0 +1,49 @@
+# $NetBSD: files.mvme68k,v 1.1.1.1 1995/07/25 23:12:05 chuck Exp $
+
+# config file for mvme68k
+
+# maxpartitions must be first item in files.${ARCH}.newconf
+maxpartitions 8
+
+device mainbus at root { }
+
+device iio at mainbus { offset = -1, [ ipl = 0 ] }
+file arch/mvme68k/dev/iio.c iio
+
+device clock at iio
+file arch/mvme68k/mvme68k/clock.c clock
+
+device zs at iio: tty
+file arch/mvme68k/dev/zs.c zs needs-count
+
+device pcc at iio
+file arch/mvme68k/dev/pcc.c pcc
+
+device le at iio: ifnet, ether
+file arch/mvme68k/dev/if_le.c le
+
+include "../../../scsi/files.scsi"
+
+major { sd = 7 }
+major { cd = 18 }
+major { vnd = 6 }
+
+file arch/mvme68k/mvme68k/autoconf.c
+file arch/mvme68k/mvme68k/conf.c
+file arch/mvme68k/mvme68k/disksubr.c
+file arch/mvme68k/mvme68k/dkbad.c
+file arch/mvme68k/mvme68k/machdep.c config-dependent
+file arch/mvme68k/mvme68k/mem.c
+file arch/mvme68k/mvme68k/pmap.c
+file arch/mvme68k/mvme68k/pmap_bootstrap.c
+file arch/mvme68k/mvme68k/sys_machdep.c
+file arch/mvme68k/mvme68k/trap.c
+file arch/mvme68k/mvme68k/vm_machdep.c
+file arch/m68k/m68k/copy.s
+file dev/cons.c
+file dev/cninit.c
+
+# SunOS Binary Compatibility (COMPAT_SUNOS)
+include "../../../compat/sunos/files.sunos"
+file arch/m68k/m68k/sunos_machdep.c compat_sunos
+
diff --git a/sys/arch/mvme68k/dev/if_le.c b/sys/arch/mvme68k/dev/if_le.c
new file mode 100644
index 00000000000..cd7fe440304
--- /dev/null
+++ b/sys/arch/mvme68k/dev/if_le.c
@@ -0,0 +1,965 @@
+/* $NetBSD: if_le.c,v 1.1.1.1 1995/07/25 23:12:09 chuck Exp $ */
+
+/*-
+ * Copyright (c) 1982, 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)if_le.c 8.2 (Berkeley) 10/30/93
+ */
+
+#include "bpfilter.h"
+
+/*
+ * AMD 7990 LANCE
+ */
+#include <sys/param.h>
+#include <sys/device.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/mbuf.h>
+#include <sys/buf.h>
+#include <sys/socket.h>
+#include <sys/syslog.h>
+#include <sys/ioctl.h>
+#include <sys/malloc.h>
+#include <sys/errno.h>
+
+#include <vm/vm.h>
+
+#include <net/if.h>
+#include <net/netisr.h>
+#include <net/route.h>
+#if NBPFILTER > 0
+#include <sys/select.h>
+#include <net/bpf.h>
+#include <net/bpfdesc.h>
+#endif
+
+#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 APPLETALK
+#include <netddp/atalk.h>
+#endif
+
+#include <machine/cpu.h>
+#include <machine/pmap.h>
+
+#include <mvme68k/dev/iio.h>
+#include <mvme68k/dev/if_lereg.h>
+#include <mvme68k/dev/pccreg.h>
+
+/* DVMA address to LANCE address -- the Sbus/MMU will resupply the 0xff */
+#define LANCE_ADDR(x) ((int)x)
+
+int ledebug = 0; /* console error messages */
+
+#ifdef PACKETSTATS
+long lexpacketsizes[LEMTU+1];
+long lerpacketsizes[LEMTU+1];
+#endif
+
+/* Per interface statistics */
+/* XXX this should go in something like if_levar.h */
+struct lestats {
+ long lexints; /* transmitter interrupts */
+ long lerints; /* receiver interrupts */
+ long lerbufs; /* total buffers received during interrupts */
+ long lerhits; /* times current rbuf was full */
+ long lerscans; /* rbufs scanned before finding first full */
+};
+
+/*
+ * 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; /* base device */
+ struct evcnt sc_intrcnt; /* # of interrupts, per le */
+ struct evcnt sc_errcnt; /* # of errors, per le */
+
+ 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 */
+ 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;
+ struct lestats sc_lestats; /* per interface statistics */
+};
+
+
+/* autoconfiguration driver */
+void leattach(struct device *, struct device *, void *);
+int lematch(struct device *, void *, void *);
+struct cfdriver lecd =
+ { NULL, "le", lematch, leattach, DV_IFNET, sizeof(struct le_softc) };
+
+/* Forwards */
+void leattach(struct device *, struct device *, void *);
+void lesetladrf(struct le_softc *);
+void lereset(struct device *);
+int leinit(int);
+void lestart(struct ifnet *);
+int leintr(void *);
+void lexint(struct le_softc *);
+void lerint(struct le_softc *);
+void leread(struct le_softc *, char *, int);
+int leput(char *, struct mbuf *);
+struct mbuf *leget(char *, int, int, struct ifnet *);
+int leioctl(struct ifnet *, u_long, caddr_t);
+void leerror(struct le_softc *, int);
+void lererror(struct le_softc *, char *);
+void lexerror(struct le_softc *);
+
+void *ledatabuf; /* XXXCDC hack from pmap bootstrap */
+
+int
+lematch(parent, vcf, args)
+ struct device *parent;
+ void *vcf, *args;
+{
+ struct cfdata *cf = vcf;
+ struct iioargs *ia = args;
+
+ return !badbaddr((caddr_t) IIO_CFLOC_ADDR(cf));
+}
+
+/*
+ * 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 le_softc *sc = (struct le_softc *)self;
+ register struct lereg2 *ler2;
+ struct ifnet *ifp = &sc->sc_if;
+ register int a;
+ int pri = IIO_CFLOC_LEVEL(self->dv_cfdata);
+
+ /* XXX the following declarations should be elsewhere */
+ extern void myetheraddr(u_char *);
+
+ iio_print(self->dv_cfdata);
+
+ /* connect the interrupt */
+ pccintr_establish(PCCV_LE, leintr, pri, sc);
+
+ sc->sc_r1 = (struct lereg1 *) IIO_CFLOC_ADDR(self->dv_cfdata);
+
+
+ ler2 = sc->sc_r2 = (struct lereg2 *) ledatabuf;
+
+ myetheraddr(sc->sc_addr);
+ printf(" ler2 0x%x address %s\n", ler2, ether_sprintf(sc->sc_addr));
+
+ /*
+ * Setup for transmit/receive
+ *
+ * According to Van, some versions of the Lance only use this
+ * address to receive packets; it doesn't put them in
+ * output packets. We'll want to make sure that lestart()
+ * installs the address.
+ */
+ ler2->ler2_padr[0] = sc->sc_addr[1];
+ ler2->ler2_padr[1] = sc->sc_addr[0];
+ ler2->ler2_padr[2] = sc->sc_addr[3];
+ ler2->ler2_padr[3] = sc->sc_addr[2];
+ ler2->ler2_padr[4] = sc->sc_addr[5];
+ ler2->ler2_padr[5] = sc->sc_addr[4];
+ a = LANCE_ADDR(&ler2->ler2_rmd);
+ ler2->ler2_rlen = LE_RLEN | (a >> 16);
+ ler2->ler2_rdra = a;
+ a = LANCE_ADDR(&ler2->ler2_tmd);
+ ler2->ler2_tlen = LE_TLEN | (a >> 16);
+ ler2->ler2_tdra = a;
+
+ /*
+ * Set up event counters.
+ */
+ evcnt_attach(&sc->sc_dev, "intr", &sc->sc_intrcnt);
+ evcnt_attach(&sc->sc_dev, "errs", &sc->sc_errcnt);
+
+ ifp->if_unit = sc->sc_dev.dv_unit;
+ ifp->if_name = "le";
+ ifp->if_ioctl = leioctl;
+ ifp->if_start = lestart;
+ ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
+#ifdef IFF_NOTRAILERS
+ /* XXX still compile when the blasted things are gone... */
+ ifp->if_flags |= IFF_NOTRAILERS;
+#endif
+#if NBPFILTER > 0
+ bpfattach(&ifp->if_bpf, ifp, DLT_EN10MB, sizeof(struct ether_header));
+#endif
+ if_attach(ifp);
+ ether_ifattach(ifp);
+ sys_pcc->le_int = pri | PCC_IENABLE;
+
+}
+
+/*
+ * Setup the logical address filter
+ */
+void
+lesetladrf(sc)
+ register struct le_softc *sc;
+{
+ register struct lereg2 *ler2 = sc->sc_r2;
+ register struct ifnet *ifp = &sc->sc_if;
+ register struct ether_multi *enm;
+ register u_char *cp, c;
+ register u_long crc;
+ register int i, len;
+ struct ether_multistep step;
+
+ /*
+ * Set up multicast address filter by passing all multicast
+ * addresses through a crc generator, and then using the high
+ * order 6 bits as a index into the 64 bit logical address
+ * filter. The high order two bits select the word, while the
+ * rest of the bits select the bit within the word.
+ */
+
+ ler2->ler2_ladrf[0] = 0;
+ ler2->ler2_ladrf[1] = 0;
+ ler2->ler2_ladrf[2] = 0;
+ ler2->ler2_ladrf[3] = 0;
+ ifp->if_flags &= ~IFF_ALLMULTI;
+ ETHER_FIRST_MULTI(step, &sc->sc_ac, enm);
+ while (enm != NULL) {
+ if (bcmp((caddr_t)&enm->enm_addrlo,
+ (caddr_t)&enm->enm_addrhi, sizeof(enm->enm_addrlo)) != 0) {
+ /*
+ * We must listen to a range of multicast
+ * addresses. For now, just accept all
+ * multicasts, rather than trying to set only
+ * those filter bits needed to match the range.
+ * (At this time, the only use of address
+ * ranges is for IP multicast routing, for
+ * which the range is big enough to require all
+ * bits set.)
+ */
+ ler2->ler2_ladrf[0] = 0xffff;
+ ler2->ler2_ladrf[1] = 0xffff;
+ ler2->ler2_ladrf[2] = 0xffff;
+ ler2->ler2_ladrf[3] = 0xffff;
+ ifp->if_flags |= IFF_ALLMULTI;
+ return;
+ }
+
+ /*
+ * One would think, given the AM7990 document's polynomial
+ * of 0x04c11db6, that this should be 0x6db88320 (the bit
+ * reversal of the AMD value), but that is not right. See
+ * the BASIC listing: bit 0 (our bit 31) must then be set.
+ */
+ cp = (unsigned char *)&enm->enm_addrlo;
+ crc = 0xffffffff;
+ for (len = 6; --len >= 0;) {
+ c = *cp++;
+ for (i = 0; i < 8; i++) {
+ if ((c & 0x01) ^ (crc & 0x01)) {
+ crc >>= 1;
+ crc = crc ^ 0xedb88320;
+ } else
+ crc >>= 1;
+ c >>= 1;
+ }
+ }
+ /* Just want the 6 most significant bits. */
+ crc = crc >> 26;
+
+ /* Turn on the corresponding bit in the filter. */
+ ler2->ler2_ladrf[crc >> 4] |= 1 << (crc & 0xf);
+
+ ETHER_NEXT_MULTI(step, enm);
+ }
+}
+
+void
+lereset(dev)
+ struct device *dev;
+{
+ register struct le_softc *sc = (struct le_softc *)dev;
+ register struct lereg1 *ler1 = sc->sc_r1;
+ register struct lereg2 *ler2 = sc->sc_r2;
+ register int i, a, timo, stat;
+
+#if NBPFILTER > 0
+ if (sc->sc_if.if_flags & IFF_PROMISC)
+ ler2->ler2_mode = LE_MODE_NORMAL | LE_MODE_PROM;
+ else
+#endif
+ ler2->ler2_mode = LE_MODE_NORMAL;
+ ler1->ler1_rap = LE_CSR0;
+ ler1->ler1_rdp = LE_C0_STOP;
+
+ /* Setup the logical address filter */
+ lesetladrf(sc);
+
+ /* init receive and transmit rings */
+ for (i = 0; i < LERBUF; i++) {
+ a = LANCE_ADDR(&ler2->ler2_rbuf[i][0]);
+ ler2->ler2_rmd[i].rmd0 = a;
+ ler2->ler2_rmd[i].rmd1_hadr = a >> 16;
+ ler2->ler2_rmd[i].rmd1_bits = LE_R1_OWN;
+ ler2->ler2_rmd[i].rmd2 = -LEMTU | LE_XMD2_ONES;
+ ler2->ler2_rmd[i].rmd3 = 0;
+ }
+ for (i = 0; i < LETBUF; i++) {
+ a = LANCE_ADDR(&ler2->ler2_tbuf[i][0]);
+ ler2->ler2_tmd[i].tmd0 = a;
+ ler2->ler2_tmd[i].tmd1_hadr = a >> 16;
+ ler2->ler2_tmd[i].tmd1_bits = 0;
+ ler2->ler2_tmd[i].tmd2 = LE_XMD2_ONES;
+ ler2->ler2_tmd[i].tmd3 = 0;
+ }
+
+bzero((void *)&ler2->ler2_rbuf[0][0], (LERBUF + LETBUF) * LEMTU);
+ /* lance will stuff packet into receive buffer 0 next */
+ sc->sc_rmd = 0;
+
+ /* tell the chip where to find the initialization block */
+ a = LANCE_ADDR(&ler2->ler2_mode);
+ ler1->ler1_rap = LE_CSR1;
+ ler1->ler1_rdp = a;
+ ler1->ler1_rap = LE_CSR2;
+ ler1->ler1_rdp = a >> 16;
+ ler1->ler1_rap = LE_CSR3;
+ ler1->ler1_rdp = LE_C3_BSWP /*| LE_C3_ACON | LE_C3_BCON*/;
+ ler1->ler1_rap = LE_CSR0;
+ ler1->ler1_rdp = LE_C0_INIT;
+ timo = 100000;
+ while (((stat = ler1->ler1_rdp) & (LE_C0_ERR | LE_C0_IDON)) == 0) {
+ if (--timo == 0) {
+ printf("%s: init timeout, stat=%b\n",
+ sc->sc_dev.dv_xname, stat, LE_C0_BITS);
+ break;
+ }
+ }
+ if (stat & LE_C0_ERR)
+ printf("%s: init failed, ler1=0x%x, stat=%b\n",
+ sc->sc_dev.dv_xname, ler1, stat, LE_C0_BITS);
+ else
+ ler1->ler1_rdp = LE_C0_IDON; /* clear IDON */
+ ler1->ler1_rdp = LE_C0_STRT | LE_C0_INEA;
+ sc->sc_if.if_flags &= ~IFF_OACTIVE;
+}
+
+/*
+ * Initialization of interface
+ */
+int
+leinit(unit)
+ int unit;
+{
+ register struct le_softc *sc = lecd.cd_devs[unit];
+ register struct ifnet *ifp = &sc->sc_if;
+ register int s;
+
+ if ((ifp->if_flags & IFF_RUNNING) == 0) {
+ s = splimp();
+ ifp->if_flags |= IFF_RUNNING;
+ lereset(&sc->sc_dev);
+ lestart(ifp);
+ splx(s);
+ }
+ return (0);
+}
+
+/*
+ * Start output on interface. Get another datagram to send
+ * off of the interface queue, and copy it to the interface
+ * before starting the output.
+ */
+void
+lestart(ifp)
+ register struct ifnet *ifp;
+{
+ register struct le_softc *sc = lecd.cd_devs[ifp->if_unit];
+ register struct letmd *tmd;
+ register struct mbuf *m;
+ register int len;
+ if ((sc->sc_if.if_flags & IFF_RUNNING) == 0)
+ return;
+ IF_DEQUEUE(&sc->sc_if.if_snd, m);
+ if (m == 0)
+ return;
+
+ len = leput((char *)sc->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 (sc->sc_if.if_bpf)
+ bpf_tap(sc->sc_if.if_bpf, (char *)sc->sc_r2->ler2_tbuf[0], len);
+#endif
+
+#ifdef PACKETSTATS
+ if (len <= LEMTU)
+ lexpacketsizes[len]++;
+#endif
+ tmd = sc->sc_r2->ler2_tmd;
+ tmd->tmd3 = 0;
+ tmd->tmd2 = -len | LE_XMD2_ONES;
+ tmd->tmd1_bits = LE_T1_OWN | LE_T1_STP | LE_T1_ENP;
+ sc->sc_if.if_flags |= IFF_OACTIVE;
+ return;
+}
+
+int
+leintr(dev)
+ register void *dev;
+{
+ register struct le_softc *sc = dev;
+ register struct lereg1 *ler1 = sc->sc_r1;
+ register int csr0;
+
+ csr0 = ler1->ler1_rdp;
+ if ((csr0 & LE_C0_INTR) == 0)
+ return (0);
+ sc->sc_intrcnt.ev_count++;
+
+ if (csr0 & LE_C0_ERR) {
+ sc->sc_errcnt.ev_count++;
+ leerror(sc, csr0);
+ if (csr0 & LE_C0_MERR) {
+ sc->sc_merr++;
+ lereset(&sc->sc_dev);
+ return (1);
+ }
+ if (csr0 & LE_C0_BABL)
+ sc->sc_babl++;
+ if (csr0 & LE_C0_CERR)
+ sc->sc_cerr++;
+ if (csr0 & LE_C0_MISS)
+ sc->sc_miss++;
+ ler1->ler1_rdp = LE_C0_BABL|LE_C0_CERR|LE_C0_MISS|LE_C0_INEA;
+ }
+ if ((csr0 & LE_C0_RXON) == 0) {
+ sc->sc_rxoff++;
+ lereset(&sc->sc_dev);
+ return (1);
+ }
+ if ((csr0 & LE_C0_TXON) == 0) {
+ sc->sc_txoff++;
+ lereset(&sc->sc_dev);
+ return (1);
+ }
+ if (csr0 & LE_C0_RINT) {
+ /* interrupt is cleared in lerint */
+ lerint(sc);
+ }
+ if (csr0 & LE_C0_TINT) {
+ ler1->ler1_rdp = LE_C0_TINT|LE_C0_INEA;
+ lexint(sc);
+ }
+ return (1);
+}
+
+/*
+ * Ethernet interface transmitter interrupt.
+ * Start another output if more data to send.
+ */
+void
+lexint(sc)
+ register struct le_softc *sc;
+{
+ register struct letmd *tmd = sc->sc_r2->ler2_tmd;
+
+ sc->sc_lestats.lexints++;
+ if ((sc->sc_if.if_flags & IFF_OACTIVE) == 0) {
+ sc->sc_xint++;
+ return;
+ }
+ if (tmd->tmd1_bits & LE_T1_OWN) {
+ sc->sc_xown++;
+ return;
+ }
+ if (tmd->tmd1_bits & LE_T1_ERR) {
+err:
+ lexerror(sc);
+ sc->sc_if.if_oerrors++;
+ if (tmd->tmd3 & (LE_T3_BUFF|LE_T3_UFLO)) {
+ sc->sc_uflo++;
+ lereset(&sc->sc_dev);
+ } else if (tmd->tmd3 & LE_T3_LCOL)
+ sc->sc_if.if_collisions++;
+ else if (tmd->tmd3 & LE_T3_RTRY)
+ sc->sc_if.if_collisions += 16;
+ }
+ else if (tmd->tmd3 & LE_T3_BUFF)
+ /* XXX documentation says BUFF not included in ERR */
+ goto err;
+ else if (tmd->tmd1_bits & LE_T1_ONE)
+ sc->sc_if.if_collisions++;
+ else if (tmd->tmd1_bits & LE_T1_MORE)
+ /* what is the real number? */
+ sc->sc_if.if_collisions += 2;
+ else
+ sc->sc_if.if_opackets++;
+ sc->sc_if.if_flags &= ~IFF_OACTIVE;
+ lestart(&sc->sc_if);
+}
+
+#define LENEXTRMP \
+ if (++bix == LERBUF) bix = 0, rmd = sc->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.
+ */
+void
+lerint(sc)
+ register struct le_softc *sc;
+{
+ register int bix = sc->sc_rmd;
+ register struct lermd *rmd = &sc->sc_r2->ler2_rmd[bix];
+
+ sc->sc_lestats.lerints++;
+ /*
+ * Out of sync with hardware, should never happen?
+ */
+ if (rmd->rmd1_bits & LE_R1_OWN) {
+ do {
+ sc->sc_lestats.lerscans++;
+ LENEXTRMP;
+ } while ((rmd->rmd1_bits & LE_R1_OWN) && bix != sc->sc_rmd);
+ if (bix == sc->sc_rmd)
+ printf("%s: RINT with no buffer\n",
+ sc->sc_dev.dv_xname);
+ } else
+ sc->sc_lestats.lerhits++;
+
+ /*
+ * Process all buffers with valid data
+ */
+ while ((rmd->rmd1_bits & LE_R1_OWN) == 0) {
+ int len = rmd->rmd3;
+
+ /* Clear interrupt to avoid race condition */
+ sc->sc_r1->ler1_rdp = LE_C0_RINT|LE_C0_INEA;
+
+ if (rmd->rmd1_bits & LE_R1_ERR) {
+ sc->sc_rmd = bix;
+ lererror(sc, "bad packet");
+ sc->sc_if.if_ierrors++;
+ } else if ((rmd->rmd1_bits & (LE_R1_STP|LE_R1_ENP)) !=
+ (LE_R1_STP|LE_R1_ENP)) {
+ /* XXX make a define for LE_R1_STP|LE_R1_ENP? */
+ /*
+ * Find the end of the packet so we can see how long
+ * it was. We still throw it away.
+ */
+ do {
+ sc->sc_r1->ler1_rdp = LE_C0_RINT|LE_C0_INEA;
+ rmd->rmd3 = 0;
+ rmd->rmd1_bits = LE_R1_OWN;
+ LENEXTRMP;
+ } while (!(rmd->rmd1_bits &
+ (LE_R1_OWN|LE_R1_ERR|LE_R1_STP|LE_R1_ENP)));
+ sc->sc_rmd = bix;
+ lererror(sc, "chained buffer");
+ sc->sc_rxlen++;
+ /*
+ * If search terminated without successful completion
+ * we reset the hardware (conservative).
+ */
+ if ((rmd->rmd1_bits &
+ (LE_R1_OWN|LE_R1_ERR|LE_R1_STP|LE_R1_ENP)) !=
+ LE_R1_ENP) {
+ lereset(&sc->sc_dev);
+ return;
+ }
+ } else {
+ leread(sc, (char *)sc->sc_r2->ler2_rbuf[bix], len);
+#ifdef PACKETSTATS
+ lerpacketsizes[len]++;
+#endif
+ sc->sc_lestats.lerbufs++;
+ }
+ rmd->rmd3 = 0;
+ rmd->rmd1_bits = LE_R1_OWN;
+ LENEXTRMP;
+ }
+ sc->sc_rmd = bix;
+}
+
+void
+leread(sc, pkt, len)
+ register struct le_softc *sc;
+ char *pkt;
+ int len;
+{
+ register struct ether_header *et;
+ register struct ifnet *ifp = &sc->sc_if;
+ struct mbuf *m;
+ struct ifqueue *inq;
+ int flags;
+
+ ifp->if_ipackets++;
+ et = (struct ether_header *)pkt;
+ et->ether_type = ntohs((u_short)et->ether_type);
+ /* adjust input length to account for header and CRC */
+ len -= sizeof(struct ether_header) + 4;
+
+ if (len <= 0) {
+ if (ledebug)
+ log(LOG_WARNING,
+ "%s: ierror(runt packet): from %s: len=%d\n",
+ sc->sc_dev.dv_xname,
+ ether_sprintf(et->ether_shost), len);
+ sc->sc_runt++;
+ ifp->if_ierrors++;
+ return;
+ }
+
+ /* Setup mbuf flags we'll need later */
+ flags = 0;
+ if (bcmp((caddr_t)etherbroadcastaddr,
+ (caddr_t)et->ether_dhost, sizeof(etherbroadcastaddr)) == 0)
+ flags |= M_BCAST;
+ if (et->ether_dhost[0] & 1)
+ flags |= M_MCAST;
+
+#if NBPFILTER > 0
+ /*
+ * Check if there's a bpf filter listening on this interface.
+ * If so, hand off the raw packet to enet, then discard things
+ * not destined for us (but be sure to keep broadcast/multicast).
+ */
+ if (sc->sc_if.if_bpf) {
+ bpf_tap(sc->sc_if.if_bpf, pkt,
+ len + sizeof(struct ether_header));
+ if ((flags & (M_BCAST | M_MCAST)) == 0 &&
+ bcmp(et->ether_dhost, sc->sc_addr,
+ sizeof(et->ether_dhost)) != 0)
+ return;
+ }
+#endif
+ m = leget(pkt, len, 0, ifp);
+ if (m == 0)
+ return;
+ ether_input(ifp, et, m);
+}
+
+/*
+ * Routine to copy from mbuf chain to transmit
+ * buffer in board local memory.
+ *
+ * ### this can be done by remapping in some cases
+ */
+int
+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.
+ */
+int
+leioctl(ifp, cmd, data)
+ register struct ifnet *ifp;
+ u_long cmd;
+ caddr_t data;
+{
+ register struct ifaddr *ifa;
+ register struct le_softc *sc = lecd.cd_devs[ifp->if_unit];
+ register struct lereg1 *ler1;
+ int s = splimp(), error = 0;
+
+ switch (cmd) {
+
+ case SIOCSIFADDR:
+ ifa = (struct ifaddr *)data;
+ ifp->if_flags |= IFF_UP;
+ switch (ifa->ifa_addr->sa_family) {
+#ifdef INET
+ case AF_INET:
+ (void)leinit(ifp->if_unit);
+ arp_ifinit(&sc->sc_ac, ifa);
+ break;
+#endif
+#ifdef NS
+ case AF_NS:
+ {
+ register struct ns_addr *ina = &(IA_SNS(ifa)->sns_addr);
+
+ if (ns_nullhost(*ina))
+ ina->x_host = *(union ns_host *)(sc->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)sc->sc_addr, sizeof(sc->sc_addr));
+ }
+ (void)leinit(ifp->if_unit); /* does le_setaddr() */
+ break;
+ }
+#endif
+ default:
+ (void)leinit(ifp->if_unit);
+ break;
+ }
+ break;
+
+ case SIOCSIFFLAGS:
+ ler1 = sc->sc_r1;
+ if ((ifp->if_flags & IFF_UP) == 0 &&
+ ifp->if_flags & IFF_RUNNING) {
+ ler1->ler1_rdp = LE_C0_STOP;
+ ifp->if_flags &= ~IFF_RUNNING;
+ } else if (ifp->if_flags & IFF_UP &&
+ (ifp->if_flags & IFF_RUNNING) == 0)
+ (void)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 ^ sc->sc_iflags) & IFF_PROMISC) &&
+ (ifp->if_flags & IFF_RUNNING)) {
+ sc->sc_iflags = ifp->if_flags;
+ lereset(&sc->sc_dev);
+ lestart(ifp);
+ }
+ break;
+
+ case SIOCADDMULTI:
+ error = ether_addmulti((struct ifreq *)data, &sc->sc_ac);
+ goto update_multicast;
+
+ case SIOCDELMULTI:
+ error = ether_delmulti((struct ifreq *)data, &sc->sc_ac);
+ update_multicast:
+ if (error == ENETRESET) {
+ /*
+ * Multicast list has changed; set the hardware
+ * filter accordingly.
+ */
+ lereset(&sc->sc_dev);
+ error = 0;
+ }
+ break;
+
+ default:
+ error = EINVAL;
+ }
+ splx(s);
+ return (error);
+}
+
+void
+leerror(sc, stat)
+ register struct le_softc *sc;
+ int stat;
+{
+ if (!ledebug)
+ return;
+
+ /*
+ * Not all transceivers implement heartbeat
+ * so we only log CERR once.
+ */
+ if ((stat & LE_C0_CERR) && sc->sc_cerr)
+ return;
+ log(LOG_WARNING, "%s: error: stat=%b\n",
+ sc->sc_dev.dv_xname, stat, LE_C0_BITS);
+}
+
+void
+lererror(sc, msg)
+ register struct le_softc *sc;
+ char *msg;
+{
+ register struct lermd *rmd;
+ int len;
+
+ if (!ledebug)
+ return;
+
+ rmd = &sc->sc_r2->ler2_rmd[sc->sc_rmd];
+ len = rmd->rmd3;
+ log(LOG_WARNING, "%s: ierror(%s): from %s: buf=%d, len=%d, rmd1=%b\n",
+ sc->sc_dev.dv_xname, msg, len > 11 ?
+ ether_sprintf((u_char *)&sc->sc_r2->ler2_rbuf[sc->sc_rmd][6]) :
+ "unknown",
+ sc->sc_rmd, len, rmd->rmd1_bits, LE_R1_BITS);
+}
+
+void
+lexerror(sc)
+ register struct le_softc *sc;
+{
+ register struct letmd *tmd;
+ register int len, tmd3, tdr;
+
+ if (!ledebug)
+ return;
+
+ tmd = sc->sc_r2->ler2_tmd;
+ tmd3 = tmd->tmd3;
+ tdr = tmd3 & LE_T3_TDR_MASK;
+ len = -(tmd->tmd2 & ~LE_XMD2_ONES);
+ log(LOG_WARNING,
+ "%s: oerror: to %s: buf=%d, len=%d, tmd1=%b, tmd3=%b, tdr=%d (%d nsecs)\n",
+ sc->sc_dev.dv_xname, len > 5 ?
+ ether_sprintf((u_char *)&sc->sc_r2->ler2_tbuf[0][0]) : "unknown",
+ 0, len,
+ tmd->tmd1_bits, LE_T1_BITS,
+ tmd3, LE_T3_BITS, tdr, tdr * 100);
+}
diff --git a/sys/arch/mvme68k/dev/if_lereg.h b/sys/arch/mvme68k/dev/if_lereg.h
new file mode 100644
index 00000000000..6e802470966
--- /dev/null
+++ b/sys/arch/mvme68k/dev/if_lereg.h
@@ -0,0 +1,167 @@
+/* $NetBSD: if_lereg.h,v 1.1.1.1 1995/07/25 23:12:10 chuck Exp $ */
+
+/*-
+ * Copyright (c) 1982, 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)if_lereg.h 8.2 (Berkeley) 10/30/93
+ */
+
+#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)
+
+/* Local Area Network Controller for Ethernet (LANCE) registers */
+struct lereg1 {
+ volatile u_short ler1_rdp; /* register data port */
+ volatile u_short ler1_rap; /* register address port */
+};
+
+/* register addresses */
+#define LE_CSR0 0 /* Control and status register */
+#define LE_CSR1 1 /* low address of init block */
+#define LE_CSR2 2 /* high address of init block */
+#define LE_CSR3 3 /* Bus master and control */
+
+/* Control and status register 0 (csr0) */
+#define LE_C0_ERR 0x8000 /* error summary */
+#define LE_C0_BABL 0x4000 /* transmitter timeout error */
+#define LE_C0_CERR 0x2000 /* collision */
+#define LE_C0_MISS 0x1000 /* missed a packet */
+#define LE_C0_MERR 0x0800 /* memory error */
+#define LE_C0_RINT 0x0400 /* receiver interrupt */
+#define LE_C0_TINT 0x0200 /* transmitter interrupt */
+#define LE_C0_IDON 0x0100 /* initalization done */
+#define LE_C0_INTR 0x0080 /* interrupt condition */
+#define LE_C0_INEA 0x0040 /* interrupt enable */
+#define LE_C0_RXON 0x0020 /* receiver on */
+#define LE_C0_TXON 0x0010 /* transmitter on */
+#define LE_C0_TDMD 0x0008 /* transmit demand */
+#define LE_C0_STOP 0x0004 /* disable all external activity */
+#define LE_C0_STRT 0x0002 /* enable external activity */
+#define LE_C0_INIT 0x0001 /* begin initalization */
+
+#define LE_C0_BITS \
+ "\20\20ERR\17BABL\16CERR\15MISS\14MERR\13RINT\
+\12TINT\11IDON\10INTR\07INEA\06RXON\05TXON\04TDMD\03STOP\02STRT\01INIT"
+
+/* Control and status register 3 (csr3) */
+#define LE_C3_BSWP 0x4 /* byte swap */
+#define LE_C3_ACON 0x2 /* ALE control, eh? */
+#define LE_C3_BCON 0x1 /* byte control */
+/*
+ * Current size is 13,758 bytes with 8 x 1518 receive buffers and
+ * 1 x 1518 transmit buffer.
+ */
+struct lereg2 {
+ /* initialization block */
+ volatile u_short ler2_mode; /* mode */
+ volatile u_char ler2_padr[6]; /* physical address */
+ volatile u_short ler2_ladrf[4]; /* logical address filter */
+ volatile u_short ler2_rdra; /* receive descriptor addr */
+ volatile u_short ler2_rlen; /* rda high and ring size */
+ volatile u_short ler2_tdra; /* transmit descriptor addr */
+ volatile u_short ler2_tlen; /* tda high and ring size */
+ /* receive message descriptors. bits/hadr are byte order dependent. */
+ struct lermd {
+ volatile u_short rmd0; /* low address of packet */
+ volatile u_char rmd1_bits; /* descriptor bits */
+ volatile u_char rmd1_hadr; /* high address of packet */
+ volatile short rmd2; /* buffer byte count */
+ volatile u_short rmd3; /* message byte count */
+ } ler2_rmd[LERBUF];
+ /* transmit message descriptors */
+ struct letmd {
+ volatile u_short tmd0; /* low address of packet */
+ volatile u_char tmd1_bits; /* descriptor bits */
+ volatile u_char tmd1_hadr; /* high address of packet */
+ volatile short tmd2; /* buffer byte count */
+ volatile u_short tmd3; /* transmit error bits */
+ } ler2_tmd[LETBUF];
+ volatile char ler2_rbuf[LERBUF][LEMTU];
+ volatile char ler2_tbuf[LETBUF][LEMTU];
+};
+
+/* Initialzation block (mode) */
+#define LE_MODE_PROM 0x8000 /* promiscuous mode */
+/* 0x7f80 reserved, must be zero */
+#define LE_MODE_INTL 0x0040 /* internal loopback */
+#define LE_MODE_DRTY 0x0020 /* disable retry */
+#define LE_MODE_COLL 0x0010 /* force a collision */
+#define LE_MODE_DTCR 0x0008 /* disable transmit CRC */
+#define LE_MODE_LOOP 0x0004 /* loopback mode */
+#define LE_MODE_DTX 0x0002 /* disable transmitter */
+#define LE_MODE_DRX 0x0001 /* disable receiver */
+#define LE_MODE_NORMAL 0 /* none of the above */
+
+
+/* Receive message descriptor 1 (rmd1_bits) */
+#define LE_R1_OWN 0x80 /* LANCE owns the packet */
+#define LE_R1_ERR 0x40 /* error summary */
+#define LE_R1_FRAM 0x20 /* framing error */
+#define LE_R1_OFLO 0x10 /* overflow error */
+#define LE_R1_CRC 0x08 /* CRC error */
+#define LE_R1_BUFF 0x04 /* buffer error */
+#define LE_R1_STP 0x02 /* start of packet */
+#define LE_R1_ENP 0x01 /* end of packet */
+
+#define LE_R1_BITS \
+ "\20\10OWN\7ERR\6FRAM\5OFLO\4CRC\3BUFF\2STP\1ENP"
+
+/* Transmit message descriptor 1 (tmd1_bits) */
+#define LE_T1_OWN 0x80 /* LANCE owns the packet */
+#define LE_T1_ERR 0x40 /* error summary */
+#define LE_T1_MORE 0x10 /* multiple collisions */
+#define LE_T1_ONE 0x08 /* single collision */
+#define LE_T1_DEF 0x04 /* defferred transmit */
+#define LE_T1_STP 0x02 /* start of packet */
+#define LE_T1_ENP 0x01 /* end of packet */
+
+#define LE_T1_BITS \
+ "\20\10OWN\7ERR\6RES\5MORE\4ONE\3DEF\2STP\1ENP"
+
+/* Transmit message descriptor 3 (tmd3) */
+#define LE_T3_BUFF 0x8000 /* buffer error */
+#define LE_T3_UFLO 0x4000 /* underflow error */
+#define LE_T3_LCOL 0x1000 /* late collision */
+#define LE_T3_LCAR 0x0800 /* loss of carrier */
+#define LE_T3_RTRY 0x0400 /* retry error */
+#define LE_T3_TDR_MASK 0x03ff /* time domain reflectometry counter */
+
+#define LE_XMD2_ONES 0xf000
+
+#define LE_T3_BITS \
+ "\20\20BUFF\17UFLO\16RES\15LCOL\14LCAR\13RTRY"
diff --git a/sys/arch/mvme68k/dev/iio.c b/sys/arch/mvme68k/dev/iio.c
new file mode 100644
index 00000000000..ea9abed48b6
--- /dev/null
+++ b/sys/arch/mvme68k/dev/iio.c
@@ -0,0 +1,114 @@
+/* $Id: iio.c,v 1.1 1995/10/18 08:51:10 deraadt Exp $ */
+
+/*
+ *
+ * Copyright (c) 1995 Charles D. Cranor
+ * 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 Charles D. Cranor.
+ * 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.
+ */
+
+/*
+ * peripheral channel controller
+ */
+
+#include <sys/param.h>
+#include <sys/conf.h>
+#include <sys/ioctl.h>
+#include <sys/proc.h>
+#include <sys/user.h>
+#include <sys/tty.h>
+#include <sys/uio.h>
+#include <sys/callout.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/syslog.h>
+#include <sys/fcntl.h>
+#include <sys/device.h>
+#include <machine/cpu.h>
+#include <dev/cons.h>
+#include <mvme68k/mvme68k/isr.h>
+#include <mvme68k/dev/iio.h>
+
+/*
+ * Configuration routines for the internal I/O bus
+ */
+void iioattach __P((struct device *, struct device *, void *));
+int iiomatch __P((struct device *, void *, void *));
+
+struct iiosoftc {
+ struct device sc_dev;
+};
+
+struct cfdriver iiocd = {
+ NULL, "iio", iiomatch, iioattach,
+ DV_DULL, sizeof(struct iiosoftc), 0
+};
+
+int
+iiomatch(parent, cf, args)
+ struct device *parent;
+ void *cf;
+ void *args;
+{
+ return (1);
+}
+
+void
+iioattach(parent, self, args)
+ struct device *parent, *self;
+ void *args;
+{
+ extern struct cfdata cfdata[];
+ extern struct cfdriver pcccd;
+ struct cfdata *cf, *pcccf = NULL;
+
+ printf(" addr 0x%x\n", INTIOBASE);
+
+ /*
+ * attach the pcc first!
+ */
+ for (cf = cfdata; pcccf==NULL && cf->cf_driver; cf++) {
+ if (cf->cf_driver != &pcccd)
+ continue;
+ pcccf = cf;
+ }
+ if (!pcccf)
+ panic("no pcc device configured");
+ config_attach(self, pcccf, NULL, NULL);
+
+ while (config_found(self, NULL, NULL))
+ ;
+}
+
+void
+iio_print(cf)
+ struct cfdata *cf;
+{
+ printf(" offset 0x%x", cf->cf_loc[0]);
+ if (cf->cf_loc[1] > 0)
+ printf(" ipl %d", cf->cf_loc[1]);
+}
diff --git a/sys/arch/mvme68k/dev/iio.h b/sys/arch/mvme68k/dev/iio.h
new file mode 100644
index 00000000000..0a87c698cc7
--- /dev/null
+++ b/sys/arch/mvme68k/dev/iio.h
@@ -0,0 +1,18 @@
+/* $NetBSD: iio.h,v 1.1.1.1 1995/07/25 23:12:11 chuck Exp $ */
+/* $Id: iio.h,v 1.1 1995/10/18 08:51:10 deraadt Exp $ */
+
+struct iioargs {
+ int ic_addr;
+ int ic_lev;
+};
+
+#define IIO_CFLOC_ADDR(cf) (IIOV(INTIOBASE + (cf)->cf_loc[0]))
+#define IIO_CFLOC_LEVEL(cf) ((cf)->cf_loc[1])
+
+/*
+ * for the console we need zs phys addr
+ */
+
+#define ZS0_PHYS (INTIOBASE + 0x3000)
+#define ZS1_PHYS (INTIOBASE + 0x3800)
+
diff --git a/sys/arch/mvme68k/dev/pcc.c b/sys/arch/mvme68k/dev/pcc.c
new file mode 100644
index 00000000000..8ea641b7501
--- /dev/null
+++ b/sys/arch/mvme68k/dev/pcc.c
@@ -0,0 +1,171 @@
+/* $Id: pcc.c,v 1.1 1995/10/18 08:51:10 deraadt Exp $ */
+
+/*
+ *
+ * Copyright (c) 1995 Charles D. Cranor
+ * 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 Charles D. Cranor.
+ * 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.
+ */
+
+/*
+ * peripheral channel controller
+ */
+
+#include <sys/param.h>
+#include <sys/conf.h>
+#include <sys/ioctl.h>
+#include <sys/proc.h>
+#include <sys/user.h>
+#include <sys/tty.h>
+#include <sys/uio.h>
+#include <sys/callout.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/syslog.h>
+#include <sys/fcntl.h>
+#include <sys/device.h>
+#include <machine/cpu.h>
+#include <dev/cons.h>
+#include <mvme68k/mvme68k/isr.h>
+#include <mvme68k/dev/iio.h>
+#include <mvme68k/dev/pccreg.h>
+
+/*
+ * Autoconfiguration stuff.
+ */
+
+struct pccsoftc {
+ struct device sc_dev;
+ struct pcc *sc_pcc;
+};
+
+
+void pccattach __P((struct device *, struct device *, void *));
+int pccmatch __P((struct device *, void *, void *));
+
+struct cfdriver pcccd = {
+ NULL, "pcc", pccmatch, pccattach,
+ DV_DULL, sizeof(struct pccsoftc), 0
+};
+
+/*
+ * globals
+ */
+
+struct pcc *sys_pcc = NULL;
+
+struct {
+ int (*pcc_fn)();
+ void *arg;
+ int lvl;
+} pcc_vecs[PCC_NVEC];
+
+int
+pccmatch(parent, vcf, args)
+ struct device *parent;
+ void *vcf, *args;
+{
+ struct cfdata *cf = vcf;
+
+ return !badbaddr((caddr_t) IIO_CFLOC_ADDR(cf));
+}
+
+void
+pccattach(parent, self, args)
+ struct device *parent, *self;
+ void *args;
+{
+ struct pccsoftc *pccsc;
+
+ if (sys_pcc)
+ panic("pcc already attached!");
+
+ iio_print(self->dv_cfdata);
+
+ /*
+ * link into softc and set up interrupt vector base
+ */
+ pccsc = (struct pccsoftc *) self;
+ sys_pcc = pccsc->sc_pcc = (struct pcc *)IIO_CFLOC_ADDR(self->dv_cfdata);
+ pccsc->sc_pcc->int_vectr = PCC_VECBASE;
+ bzero(pcc_vecs, sizeof(pcc_vecs));
+
+ printf(" rev %d intbvr 0x%x\n", pccsc->sc_pcc->pcc_rev,
+ pccsc->sc_pcc->int_vectr);
+}
+
+
+/*
+ * pccintr: called from locore with the PC and evec from the trap frame.
+ */
+int
+pccintr(pc, evec, frame)
+ int pc;
+ int evec;
+ void *frame;
+{
+ int vec = (evec & 0xfff) >> 2; /* XXX should be m68k macro? */
+ extern u_long intrcnt[]; /* XXX from locore */
+
+ vec = vec & 0xf; /* XXX mask out */
+ if (vec >= PCC_NVEC || pcc_vecs[vec].pcc_fn == NULL)
+ return(straytrap(pc, evec));
+
+ cnt.v_intr++;
+ intrcnt[pcc_vecs[vec].lvl]++;
+
+ /* arg override? only timer1 gets access to frame */
+ if (vec != PCCV_TIMER1)
+ frame = pcc_vecs[vec].arg;
+ return((*pcc_vecs[vec].pcc_fn)(frame));
+}
+
+
+/*
+ * pccintr_establish: establish pcc interrupt
+ */
+int
+pccintr_establish(vec, hand, lvl, arg)
+ u_long vec;
+ int (*hand)(), lvl;
+ void *arg;
+{
+ if (vec >= PCC_NVEC) {
+ printf("pcc: illegal vector: 0x%x\n", vec);
+ panic("pccintr_establish");
+ }
+
+ if (pcc_vecs[vec].pcc_fn) {
+ printf("pcc: vector 0x%x in use: (0x%x,0x%x) (0x%x,0x%x)\n",
+ hand, arg, pcc_vecs[vec].pcc_fn, pcc_vecs[vec].arg);
+ panic("pccintr_establish");
+ }
+
+ pcc_vecs[vec].pcc_fn = hand;
+ pcc_vecs[vec].lvl = lvl;
+ pcc_vecs[vec].arg = arg;
+}
diff --git a/sys/arch/mvme68k/dev/pccreg.h b/sys/arch/mvme68k/dev/pccreg.h
new file mode 100644
index 00000000000..114d42a7dab
--- /dev/null
+++ b/sys/arch/mvme68k/dev/pccreg.h
@@ -0,0 +1,130 @@
+/* $Id: pccreg.h,v 1.1 1995/10/18 08:51:10 deraadt Exp $ */
+
+/*
+ *
+ * Copyright (c) 1995 Charles D. Cranor
+ * 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 Charles D. Cranor.
+ * 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.
+ */
+
+/*
+ * peripheral channel controller (at pa fffe1000)
+ */
+
+struct pcc {
+ volatile u_long dma_taddr; /* dma table address */
+ volatile u_long dma_daddr; /* dma data address */
+ volatile u_long dma_bcnt; /* dma byte count */
+ volatile u_long dma_hold; /* dma data hold register */
+ volatile u_short t1_pload; /* timer1 preload */
+ volatile u_short t1_count; /* timer1 count */
+ volatile u_short t2_pload; /* timer2 preload */
+ volatile u_short t2_count; /* timer2 count */
+ volatile u_char t1_int; /* timer1 interrupt ctrl */
+ volatile u_char t1_cr; /* timer1 ctrl reg */
+ volatile u_char t2_int; /* timer2 interrupt ctrl */
+ volatile u_char t2_cr; /* timer2 ctrl reg */
+ volatile u_char acf_int; /* acfail intr reg */
+ volatile u_char dog_int; /* watchdog intr reg */
+ volatile u_char pr_int; /* printer intr reg */
+ volatile u_char pr_cr; /* printer ctrl */
+ volatile u_char dma_int; /* dma interrupt control */
+ volatile u_char dma_csr; /* dma csr */
+ volatile u_char bus_int; /* bus error interrupt */
+ volatile u_char dma_sr; /* dma status register */
+ volatile u_char abrt_int; /* abort interrupt control reg */
+ volatile u_char ta_fcr; /* table address function code reg */
+ volatile u_char zs_int; /* serial interrupt reg */
+ volatile u_char gen_cr; /* general control register */
+ volatile u_char le_int; /* ethernet interrupt */
+ volatile u_char gen_sr; /* general status */
+ volatile u_char scsi_int; /* scsi interrupt reg */
+ volatile u_char slave_ba; /* slave base addr reg */
+ volatile u_char sw1_int; /* software interrupt #1 cr */
+ volatile u_char int_vectr; /* interrupt base vector register */
+ volatile u_char sw2_int; /* software interrupt #2 cr */
+ volatile u_char pcc_rev; /* revision level */
+};
+
+
+/*
+ * points to system's PCC
+ */
+
+extern struct pcc *sys_pcc;
+
+/*
+ * we lock off our interrupt vector at 0x40. if this is changed
+ * we'll need to change vector.s
+ */
+
+#define PCC_VECBASE 0x40
+#define PCC_NVEC 12
+
+/*
+ * vectors we use
+ */
+
+#define PCCV_ACFAIL 0
+#define PCCV_BERR 1
+#define PCCV_ABORT 2
+#define PCCV_ZS 3
+#define PCCV_LE 4
+#define PCCV_SCSIP 5
+#define PCCV_SCSID 6
+#define PCCV_PRINTER 7
+#define PCCV_TIMER1 8
+#define PCCV_TIMER2 9
+#define PCCV_SOFT1 10
+#define PCCV_SOFT2 11
+
+/*
+ * enable interrupt
+ */
+
+#define PCC_IENABLE 0x08
+
+/*
+ * interrupt mask
+ */
+
+#define PCC_IMASK 0x7
+
+/*
+ * clock/timer
+ */
+
+#define PCC_TIMERACK 0x80 /* ack intr */
+#define PCC_TIMER100HZ 63936 /* load value for 100Hz */
+#define PCC_TIMERCLEAR 0x0 /* reset and clear timer */
+#define PCC_TIMERSTART 0x3 /* start timer */
+
+/*
+ * serial control
+ */
+
+#define PCC_ZSEXTERN 0x10 /* let PCC supply vector */
diff --git a/sys/arch/mvme68k/dev/scc.h b/sys/arch/mvme68k/dev/scc.h
new file mode 100644
index 00000000000..4d94f6c3fde
--- /dev/null
+++ b/sys/arch/mvme68k/dev/scc.h
@@ -0,0 +1,64 @@
+/* $NetBSD: scc.h,v 1.1.1.1 1995/07/25 23:12:07 chuck Exp $ */
+
+/*
+ * Copyright (c) 1993 Paul Mackerras.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software withough 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.
+ */
+/*
+ * SCC I/O register definitions
+ */
+
+#define PCLK_FREQ 8333333 /* XXX */
+
+struct scc {
+ unsigned char cr;
+ unsigned char dr;
+};
+
+struct sccregs {
+ volatile struct scc *s_adr;
+ unsigned char s_val[16];
+};
+
+#define ZREAD0(scc) ((scc)->s_adr->cr)
+#define ZREAD(scc, n) ((scc)->s_adr->cr = n, (scc)->s_adr->cr)
+#define ZREADD(scc) ((scc)->s_adr->dr)
+
+#define ZWRITE0(scc, v) ((scc)->s_adr->cr = v)
+#define ZWRITE(scc, n, v) (ZWRITE0(scc, n), ZWRITE0(scc, (scc)->s_val[n] = v))
+#define ZWRITED(scc, v) ((scc)->s_adr->dr = v)
+
+#define ZBIS(scc, n, v) (ZWRITE(scc, n, (scc)->s_val[n] | (v)))
+#define ZBIC(scc, n, v) (ZWRITE(scc, n, (scc)->s_val[n] & ~(v)))
+
+#define SCC_RXFULL 1 /* bits in rr0 */
+#define SCC_TXRDY 4
+#define SCC_DCD 8
+#define SCC_CTS 0x20
+
+#define SCC_RCVEN 1 /* bits in wr3 */
+
+#define SCC_RTS 2 /* bits in wr5 */
+#define SCC_DTR 0x80
diff --git a/sys/arch/mvme68k/dev/zs.c b/sys/arch/mvme68k/dev/zs.c
new file mode 100644
index 00000000000..9a52dbd8f9c
--- /dev/null
+++ b/sys/arch/mvme68k/dev/zs.c
@@ -0,0 +1,996 @@
+/* $NetBSD: zs.c,v 1.1.1.1 1995/07/25 23:12:07 chuck Exp $ */
+
+/*
+ * Copyright (c) 1993 Paul Mackerras.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software withough 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.
+ */
+/*
+ * Serial I/O via an SCC,
+ */
+#include <sys/param.h>
+#include <sys/conf.h>
+#include <sys/ioctl.h>
+#include <sys/proc.h>
+#include <sys/user.h>
+#include <sys/tty.h>
+#include <sys/uio.h>
+#include <sys/callout.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/syslog.h>
+#include <sys/fcntl.h>
+#include <sys/device.h>
+#include <machine/cpu.h>
+#include <dev/cons.h>
+#include <mvme68k/dev/iio.h>
+#include <mvme68k/dev/scc.h>
+#include <mvme68k/dev/pccreg.h>
+
+#include "zs.h"
+#if NZS > 0
+
+/*#define PCLK_FREQ 8333333*/
+#undef PCLK_FREQ /* XXXCDC */
+#define PCLK_FREQ 5000000
+#define NZSLINE (NZS*2)
+
+#define RECV_BUF 512
+#define ERROR_DET 0xed
+
+#define TS_DRAIN TS_FLUSH/* waiting for output to drain */
+
+#define splzs() spl4()
+
+struct zs {
+ short flags; /* see below */
+ char rr0; /* holds previous CTS, DCD state */
+ unsigned char imask; /* mask for input chars */
+ int nzs_open; /* # opens as /dev/zsn */
+ int nkbd_open; /* # opens as a keyboard */
+ int gsp_unit; /* unit to send kbd chars to */
+ struct tty *tty; /* link to tty structure */
+ struct sccregs scc; /* SCC shadow registers */
+ u_char *rcv_get;
+ u_char *rcv_put;
+ u_char *rcv_end;
+ volatile int rcv_count;
+ int rcv_len;
+ char *send_ptr;
+ int send_count;
+ int sent_count;
+ volatile char modem_state;
+ volatile char modem_change;
+ volatile short hflags;
+ char rcv_buf[RECV_BUF];
+};
+
+/* Bits in flags */
+#define ZS_SIDEA 1
+#define ZS_INITED 2
+#define ZS_INTEN 4
+#define ZS_RESET 8
+#define ZS_CONSOLE 0x20
+
+/* Bits in hflags */
+#define ZH_OBLOCK 1 /* output blocked by CTS */
+#define ZH_SIRQ 2 /* soft interrupt request */
+#define ZH_TXING 4 /* transmitter active */
+#define ZH_RXOVF 8 /* receiver buffer overflow */
+
+struct zssoftc {
+ struct device dev;
+ struct zs zs[2];
+};
+
+struct tty *zs_tty[NZSLINE];
+
+struct termios zs_cons_termios;
+int zs_cons_unit = 0;
+int zs_is_console = 0;
+struct sccregs *zs_cons_scc;
+
+int zsopen __P((dev_t, int, int, struct proc *));
+void zsstart __P((struct tty *));
+int zsparam __P((struct tty *, struct termios *));
+int zsirq __P((int unit));
+void zs_softint __P((void));
+
+unsigned long sir_zs;
+void zs_softint();
+
+#define zsunit(dev) (minor(dev) >> 1)
+#define zsside(dev) (minor(dev) & 1)
+
+/*
+ * Autoconfiguration stuff.
+ */
+void zsattach __P((struct device *, struct device *, void *));
+int zsmatch __P((struct device *, void *, void *));
+
+struct cfdriver zscd = {
+ NULL, "zs", zsmatch, zsattach, DV_TTY, sizeof(struct zssoftc), 0
+};
+
+int
+zsmatch(parent, vcf, args)
+ struct device *parent;
+ void *vcf, *args;
+{
+ struct cfdata *cf = vcf;
+
+ return !badbaddr((caddr_t) IIO_CFLOC_ADDR(cf));
+}
+
+void
+zsattach(parent, self, args)
+ struct device *parent, *self;
+ void *args;
+{
+ struct zssoftc *dv;
+ struct zs *zp, *zc;
+ u_char ir;
+ volatile struct scc *scc;
+ int zs_level = IIO_CFLOC_LEVEL(self->dv_cfdata);
+
+ iio_print(self->dv_cfdata);
+
+ /* connect the interrupt */
+ dv = (struct zssoftc *) self;
+ pccintr_establish(PCCV_ZS, zsirq, zs_level, self->dv_unit);
+ /* XXXCDC: needs some work to handle zs1 */
+
+ zp = &dv->zs[0];
+ scc = (volatile struct scc *) IIO_CFLOC_ADDR(self->dv_cfdata);
+
+ if (zs_is_console && self->dv_unit == zsunit(zs_cons_unit)) {
+ /* SCC is the console - it's already reset */
+ zc = zp + zsside(zs_cons_unit);
+ zc->scc = *zs_cons_scc;
+ zs_cons_scc = &zc->scc;
+ zc->flags |= ZS_CONSOLE;
+ } else {
+ /* reset the SCC */
+ scc->cr = 0;
+ scc->cr = 9;
+ scc->cr = 0xC0; /* hardware reset of SCC, both sides */
+ }
+
+ /* side A */
+ zp->scc.s_adr = scc + 1;
+ zp->flags |= ZS_SIDEA | ZS_RESET;
+
+ /* side B */
+ ++zp;
+ zp->scc.s_adr = scc;
+ zp->flags |= ZS_RESET;
+
+ if (sir_zs == 0)
+ sir_zs = allocate_sir(zs_softint, 0);
+ printf("\n");
+
+ ir = sys_pcc->zs_int;
+ if ((ir & PCC_IMASK) != 0 && (ir & PCC_IMASK) != zs_level)
+ panic("zs configured at different IPLs");
+ sys_pcc->zs_int = zs_level | PCC_IENABLE | PCC_ZSEXTERN;
+}
+
+zs_ttydef(struct zs *zp)
+{
+ struct tty *tp = zp->tty;
+
+ if ((zp->flags & ZS_CONSOLE) == 0) {
+ tp->t_iflag = TTYDEF_IFLAG;
+ tp->t_oflag = TTYDEF_OFLAG;
+ tp->t_cflag = TTYDEF_CFLAG;
+ tp->t_lflag = TTYDEF_LFLAG;
+ tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED;
+ } else
+ tp->t_termios = zs_cons_termios;
+ ttychars(tp);
+ ttsetwater(tp);
+ tp->t_oproc = zsstart;
+ tp->t_param = zsparam;
+
+ zp->rcv_get = zp->rcv_buf;
+ zp->rcv_put = zp->rcv_buf;
+ zp->rcv_end = zp->rcv_buf + sizeof(zp->rcv_buf);
+ zp->rcv_len = sizeof(zp->rcv_buf) / 2;
+}
+
+struct tty *
+zstty(dev)
+ dev_t dev;
+{
+
+ if (minor(dev) < NZSLINE)
+ return (zs_tty[minor(dev)]);
+
+ return (NULL);
+}
+
+/* ARGSUSED */
+zsopen(dev_t dev, int flag, int mode, struct proc * p)
+{
+ register struct tty *tp;
+ int error;
+ struct zs *zp;
+ struct zssoftc *dv;
+
+ if (zsunit(dev) > zscd.cd_ndevs
+ || (dv = (struct zssoftc *) zscd.cd_devs[zsunit(dev)]) == NULL)
+ return ENODEV;
+
+ zp = &dv->zs[zsside(dev)];
+ if (zp->tty == NULL) {
+ zp->tty = ttymalloc();
+ zs_ttydef(zp);
+ if (minor(dev) < NZSLINE)
+ zs_tty[minor(dev)] = zp->tty;
+ }
+ tp = zp->tty;
+ tp->t_dev = dev;
+
+ if ((tp->t_state & TS_ISOPEN) == 0) {
+ tp->t_state |= TS_WOPEN;
+ zs_init(zp);
+ if ((zp->modem_state & SCC_DCD) != 0)
+ tp->t_state |= TS_CARR_ON;
+ } else
+ if (tp->t_state & TS_XCLUDE && p->p_ucred->cr_uid != 0)
+ return (EBUSY);
+
+ error = ((*linesw[tp->t_line].l_open) (dev, tp));
+
+ if (error == 0)
+ ++zp->nzs_open;
+ return error;
+}
+
+int
+zsclose(dev, flag, mode, p)
+ dev_t dev;
+ int flag, mode;
+ struct proc *p;
+{
+ struct zs *zp;
+ struct tty *tp;
+ struct zssoftc *dv;
+ int s;
+
+ if (zsunit(dev) > zscd.cd_ndevs
+ || (dv = (struct zssoftc *) zscd.cd_devs[zsunit(dev)]) == NULL)
+ return ENODEV;
+ zp = &dv->zs[zsside(dev)];
+ tp = zp->tty;
+
+ if (zp->nkbd_open == 0) {
+ (*linesw[tp->t_line].l_close) (tp, flag);
+ s = splzs();
+ if ((zp->flags & ZS_CONSOLE) == 0 && (tp->t_cflag & HUPCL) != 0)
+ ZBIC(&zp->scc, 5, 0x82); /* drop DTR, RTS */
+ ZBIC(&zp->scc, 3, 1); /* disable receiver */
+ splx(s);
+ ttyclose(tp);
+ }
+ zp->nzs_open = 0;
+ return (0);
+}
+
+/*ARGSUSED*/
+zsread(dev, uio, flag)
+ dev_t dev;
+ struct uio *uio;
+ int flag;
+{
+ struct zssoftc *dv = (struct zssoftc *) zscd.cd_devs[zsunit(dev)];
+ struct zs *zp = &dv->zs[zsside(dev)];
+ struct tty *tp = zp->tty;
+
+ return ((*linesw[tp->t_line].l_read) (tp, uio, flag));
+}
+
+/*ARGSUSED*/
+zswrite(dev, uio, flag)
+ dev_t dev;
+ struct uio *uio;
+ int flag;
+{
+ struct zssoftc *dv = (struct zssoftc *) zscd.cd_devs[zsunit(dev)];
+ struct zs *zp = &dv->zs[zsside(dev)];
+ struct tty *tp = zp->tty;
+
+ return ((*linesw[tp->t_line].l_write) (tp, uio, flag));
+}
+
+zsioctl(dev, cmd, data, flag, p)
+ dev_t dev;
+ caddr_t data;
+ int cmd, flag;
+ struct proc *p;
+{
+ struct zssoftc *dv = (struct zssoftc *) zscd.cd_devs[zsunit(dev)];
+ struct zs *zp = &dv->zs[zsside(dev)];
+ struct tty *tp = zp->tty;
+ register struct sccregs *scc = &zp->scc;
+ register int error, s;
+
+ error = (*linesw[tp->t_line].l_ioctl) (tp, cmd, data, flag, p);
+ if (error >= 0)
+ return (error);
+ error = ttioctl(tp, cmd, data, flag, p);
+ if (error >= 0)
+ return (error);
+ error = 0;
+ s = splzs();
+ switch (cmd) {
+ case TIOCSDTR:
+ ZBIS(scc, 5, 0x80);
+ break;
+ case TIOCCDTR:
+ ZBIC(scc, 5, 0x80);
+ break;
+ case TIOCSBRK:
+ splx(s);
+ zs_drain(zp);
+ s = splzs();
+ ZBIS(scc, 5, 0x10);
+ spltty();
+ zs_unblock(tp);
+ break;
+ case TIOCCBRK:
+ ZBIC(scc, 5, 0x10);
+ break;
+ case TIOCMGET:
+ *(int *) data = zscc_mget(scc);
+ break;
+ case TIOCMSET:
+ zscc_mset(scc, *(int *) data);
+ zscc_mclr(scc, ~*(int *) data);
+ break;
+ case TIOCMBIS:
+ zscc_mset(scc, *(int *) data);
+ break;
+ case TIOCMBIC:
+ zscc_mclr(scc, *(int *) data);
+ break;
+ default:
+ error = ENOTTY;
+ }
+ splx(s);
+ return error;
+}
+
+zsparam(tp, t)
+ struct tty *tp;
+ struct termios *t;
+{
+ struct zssoftc *dv = (struct zssoftc *) zscd.cd_devs[zsunit(tp->t_dev)];
+ struct zs *zp = &dv->zs[zsside(tp->t_dev)];
+ register int s;
+
+ zs_drain(zp);
+ s = splzs();
+ zp->imask = zscc_params(&zp->scc, t);
+ tp->t_ispeed = t->c_ispeed;
+ tp->t_ospeed = t->c_ospeed;
+ tp->t_cflag = t->c_cflag;
+ if ((tp->t_cflag & CCTS_OFLOW) == 0)
+ zp->hflags &= ~ZH_OBLOCK;
+ else
+ if ((zp->modem_state & 0x20) == 0)
+ zp->hflags |= ZH_OBLOCK;
+ spltty();
+ zs_unblock(tp);
+ splx(s);
+ return 0;
+}
+
+void
+zsstart(tp)
+ struct tty *tp;
+{
+ struct zssoftc *dv = (struct zssoftc *) zscd.cd_devs[zsunit(tp->t_dev)];
+ struct zs *zp = &dv->zs[zsside(tp->t_dev)];
+ register int s, n;
+
+ s = spltty();
+ if ((tp->t_state & (TS_TIMEOUT | TS_BUSY | TS_TTSTOP | TS_DRAIN)) == 0) {
+ n = ndqb(&tp->t_outq, 0);
+ if (n > 0) {
+ tp->t_state |= TS_BUSY;
+ splzs();
+ zp->hflags |= ZH_TXING;
+ zp->send_ptr = tp->t_outq.c_cf;
+ zp->send_count = n;
+ zp->sent_count = 0;
+ zs_txint(zp);
+ spltty();
+ }
+ }
+ splx(s);
+}
+
+zsstop(struct tty * tp, int flag)
+{
+ struct zssoftc *dv = (struct zssoftc *) zscd.cd_devs[zsunit(tp->t_dev)];
+ struct zs *zp = &dv->zs[zsside(tp->t_dev)];
+ int s, n;
+
+ s = splzs();
+ zp->send_count = 0;
+ n = zp->sent_count;
+ zp->sent_count = 0;
+ if ((tp->t_state & TS_BUSY) != 0 && (flag & FWRITE) == 0) {
+ tp->t_state &= ~TS_BUSY;
+ spltty();
+ ndflush(&tp->t_outq, n);
+ if (tp->t_outq.c_cc <= tp->t_lowat) {
+ if (tp->t_state & TS_ASLEEP) {
+ tp->t_state &= ~TS_ASLEEP;
+ wakeup((caddr_t) & tp->t_outq);
+ }
+ selwakeup(&tp->t_wsel);
+ }
+ }
+ splx(s);
+}
+
+zs_init(zp)
+ struct zs *zp;
+{
+ register int s;
+
+ s = splzs();
+ zscc_init(zp, &zp->tty->t_termios);
+ zp->rr0 = zp->modem_state = ZREAD0(&zp->scc);
+ ZBIS(&zp->scc, 1, 0x13);/* ints on tx, rx and ext/status */
+ ZBIS(&zp->scc, 9, 8); /* enable ints */
+ zp->flags |= ZS_INTEN;
+ splx(s);
+}
+
+zscc_init(zp, par)
+ struct zs *zp;
+ struct termios *par;
+{
+ struct sccregs *scc;
+
+ scc = &zp->scc;
+ ZWRITE(scc, 2, 0);
+ ZWRITE(scc, 10, 0);
+ ZWRITE(scc, 11, 0x50); /* rx & tx clock = brgen */
+ ZWRITE(scc, 14, 3); /* brgen enabled, from pclk */
+ zp->imask = zscc_params(scc, par);
+ ZBIS(scc, 5, 0x82); /* set DTR and RTS */
+ zp->flags |= ZS_INITED;
+}
+
+int
+zscc_params(scc, par)
+ struct sccregs *scc;
+ struct termios *par;
+{
+ unsigned divisor, speed;
+ int spd, imask, ints;
+
+ speed = par->c_ospeed;
+ if (speed == 0) {
+ /* disconnect - drop DTR & RTS, disable receiver */
+ ZBIC(scc, 5, 0x82);
+ ZBIC(scc, 3, 1);
+ return 0xFF;
+ }
+ if ((par->c_cflag & CREAD) == 0)
+ ZBIC(scc, 3, 1);/* disable receiver */
+ divisor = (PCLK_FREQ / 32 + (speed >> 1)) / speed - 2;
+ ZWRITE(scc, 12, divisor);
+ ZWRITE(scc, 13, divisor >> 8);
+ switch (par->c_cflag & CSIZE) {
+ case CS5:
+ spd = 0;
+ imask = 0x1F;
+ break;
+ case CS6:
+ spd = 0x40;
+ imask = 0x3F;
+ break;
+ case CS7:
+ spd = 0x20;
+ imask = 0x7F;
+ break;
+ default:
+ spd = 0x60;
+ imask = 0xFF;
+ }
+ ZWRITE(scc, 5, (scc->s_val[5] & ~0x60) | spd);
+ ZWRITE(scc, 3, (scc->s_val[3] & ~0xC0) | (spd << 1));
+ spd = par->c_cflag & CSTOPB ? 8 : 0;
+ spd |= par->c_cflag & PARENB ? par->c_cflag & PARODD ? 1 : 3 : 0;
+ ZWRITE(scc, 4, 0x44 | spd);
+ ZBIS(scc, 5, 8); /* enable transmitter */
+ if ((par->c_cflag & CREAD) != 0)
+ ZBIS(scc, 3, 1);/* enable receiver */
+ ints = 0;
+ if ((par->c_cflag & CLOCAL) == 0)
+ ints |= SCC_DCD;
+ if ((par->c_cflag & CCTS_OFLOW) != 0)
+ ints |= SCC_CTS;
+ ZWRITE(scc, 15, ints);
+ return imask;
+}
+
+zscc_mget(register struct sccregs * scc)
+{
+ int bits = 0, rr0;
+
+ if ((scc->s_val[3] & SCC_RCVEN) != 0)
+ bits |= TIOCM_LE;
+ if ((scc->s_val[5] & SCC_DTR) != 0)
+ bits |= TIOCM_DTR;
+ if ((scc->s_val[5] & SCC_RTS) != 0)
+ bits |= TIOCM_RTS;
+ rr0 = ZREAD0(scc);
+ if ((rr0 & SCC_CTS) != 0)
+ bits |= TIOCM_CTS;
+ if ((rr0 & SCC_DCD) != 0)
+ bits |= TIOCM_CAR;
+ return bits;
+}
+
+zscc_mset(register struct sccregs * scc, int bits)
+{
+ if ((bits & TIOCM_LE) != 0)
+ ZBIS(scc, 3, SCC_RCVEN);
+ if ((bits & TIOCM_DTR) != 0)
+ ZBIS(scc, 5, SCC_DTR);
+ if ((bits & TIOCM_RTS) != 0)
+ ZBIS(scc, 5, SCC_RTS);
+}
+
+zscc_mclr(register struct sccregs * scc, int bits)
+{
+ if ((bits & TIOCM_LE) != 0)
+ ZBIC(scc, 3, SCC_RCVEN);
+ if ((bits & TIOCM_DTR) != 0)
+ ZBIC(scc, 5, TIOCM_DTR);
+ if ((bits & TIOCM_RTS) != 0)
+ ZBIC(scc, 5, SCC_RTS);
+}
+
+zs_drain(register struct zs * zp)
+{
+ register int s;
+
+ zp->tty->t_state |= TS_DRAIN;
+ /* wait for Tx buffer empty and All sent bits to be set */
+ s = splzs();
+ while ((ZREAD0(&zp->scc) & SCC_TXRDY) == 0
+ || (ZREAD(&zp->scc, 1) & 1) == 0) {
+ splx(s);
+ DELAY(100);
+ s = splzs();
+ }
+ splx(s);
+}
+
+zs_unblock(register struct tty * tp)
+{
+ tp->t_state &= ~TS_DRAIN;
+ if (tp->t_outq.c_cc != 0)
+ zsstart(tp);
+}
+
+/*
+ * Hardware interrupt from an SCC.
+ */
+int
+zsirq(int unit)
+{
+ struct zssoftc *dv = (struct zssoftc *) zscd.cd_devs[unit];
+ register struct zs *zp = &dv->zs[0];
+ register int ipend, x;
+ register volatile struct scc *scc;
+
+ x = splzs();
+ scc = zp->scc.s_adr;
+ scc->cr = 3; /* read int pending from A side */
+ DELAY(5);
+ ipend = scc->cr;
+ if ((ipend & 0x20) != 0)
+ zs_rxint(zp);
+ if ((ipend & 0x10) != 0)
+ zs_txint(zp);
+ if ((ipend & 0x8) != 0)
+ zs_extint(zp);
+ ++zp; /* now look for B side ints */
+ if ((ipend & 0x4) != 0)
+ zs_rxint(zp);
+ if ((ipend & 0x2) != 0)
+ zs_txint(zp);
+ if ((ipend & 0x1) != 0)
+ zs_extint(zp);
+ splx(x);
+ return ipend != 0;
+}
+
+zs_txint(register struct zs * zp)
+{
+ struct tty *tp = zp->tty;
+ struct sccregs *scc;
+ int c;
+ u_char *get;
+
+ scc = &zp->scc;
+ ZWRITE0(scc, 0x28); /* reset Tx interrupt */
+ if ((zp->hflags & ZH_OBLOCK) == 0) {
+ get = zp->send_ptr;
+ while ((ZREAD0(scc) & SCC_TXRDY) != 0 && zp->send_count > 0) {
+ c = *get++;
+ ZWRITED(scc, c);
+ --zp->send_count;
+ ++zp->sent_count;
+ }
+ zp->send_ptr = get;
+ if (zp->send_count == 0 && (zp->hflags & ZH_TXING) != 0) {
+ zp->hflags &= ~ZH_TXING;
+ zp->hflags |= ZH_SIRQ;
+ setsoftint(sir_zs);
+ }
+ }
+}
+
+zs_rxint(register struct zs * zp)
+{
+ register int stat, c, n, extra;
+ u_char *put;
+
+ put = zp->rcv_put;
+ n = zp->rcv_count;
+ for (;;) {
+ if ((ZREAD0(&zp->scc) & SCC_RXFULL) == 0) /* check Rx full */
+ break;
+ stat = ZREAD(&zp->scc, 1) & 0x70;
+ c = ZREADD(&zp->scc) & zp->imask;
+ /* stat encodes parity, overrun, framing errors */
+ if (stat != 0)
+ ZWRITE0(&zp->scc, 0x30); /* reset error */
+ if ((zp->hflags & ZH_RXOVF) != 0) {
+ zp->hflags &= ~ZH_RXOVF;
+ stat |= 0x20;
+ }
+ extra = (stat != 0 || c == ERROR_DET) ? 2 : 0;
+ if (n + extra + 1 < zp->rcv_len) {
+ if (extra != 0) {
+ *put++ = ERROR_DET;
+ if (put >= zp->rcv_end)
+ put = zp->rcv_buf;
+ *put++ = stat;
+ if (put >= zp->rcv_end)
+ put = zp->rcv_buf;
+ n += 2;
+ }
+ *put++ = c;
+ if (put >= zp->rcv_end)
+ put = zp->rcv_buf;
+ ++n;
+ } else
+ zp->hflags |= ZH_RXOVF;
+ }
+ if (n > zp->rcv_count) {
+ zp->rcv_put = put;
+ zp->rcv_count = n;
+ zp->hflags |= ZH_SIRQ;
+ setsoftint(sir_zs);
+ }
+}
+
+/* Ext/status interrupt */
+zs_extint(register struct zs * zp)
+{
+ int rr0;
+ struct tty *tp = zp->tty;
+
+ rr0 = ZREAD0(&zp->scc);
+ ZWRITE0(&zp->scc, 0x10);/* reset ext/status int */
+ if ((tp->t_cflag & CCTS_OFLOW) != 0) {
+ if ((rr0 & 0x20) == 0)
+ zp->hflags |= ZH_OBLOCK;
+ else {
+ zp->hflags &= ~ZH_OBLOCK;
+ if ((rr0 & SCC_TXRDY) != 0)
+ zs_txint(zp);
+ }
+ }
+ zp->modem_change |= rr0 ^ zp->modem_state;
+ zp->modem_state = rr0;
+ zp->hflags |= ZH_SIRQ;
+ setsoftint(sir_zs);
+}
+
+void
+zs_softint()
+{
+ int s, n, n0, c, stat, rr0;
+ struct zs *zp;
+ struct tty *tp;
+ u_char *get;
+ int unit, side;
+
+ s = splzs();
+ for (unit = 0; unit < zscd.cd_ndevs; ++unit) {
+ if (zscd.cd_devs[unit] == NULL)
+ continue;
+ zp = &((struct zssoftc *) zscd.cd_devs[unit])->zs[0];
+ for (side = 0; side < 2; ++side, ++zp) {
+ if ((zp->hflags & ZH_SIRQ) == 0)
+ continue;
+ zp->hflags &= ~ZH_SIRQ;
+ tp = zp->tty;
+
+ /* check for tx done */
+ spltty();
+ if (tp != NULL && zp->send_count == 0
+ && (tp->t_state & TS_BUSY) != 0) {
+ tp->t_state &= ~(TS_BUSY | TS_FLUSH);
+ ndflush(&tp->t_outq, zp->sent_count);
+ if (tp->t_outq.c_cc <= tp->t_lowat) {
+ if (tp->t_state & TS_ASLEEP) {
+ tp->t_state &= ~TS_ASLEEP;
+ wakeup((caddr_t) & tp->t_outq);
+ }
+ selwakeup(&tp->t_wsel);
+ }
+ if (tp->t_line != 0)
+ (*linesw[tp->t_line].l_start) (tp);
+ else
+ zsstart(tp);
+ }
+ splzs();
+
+ /* check for received characters */
+ get = zp->rcv_get;
+ while (zp->rcv_count > 0) {
+ c = *get++;
+ if (get >= zp->rcv_end)
+ get = zp->rcv_buf;
+ if (c == ERROR_DET) {
+ stat = *get++;
+ if (get >= zp->rcv_end)
+ get = zp->rcv_buf;
+ c = *get++;
+ if (get >= zp->rcv_end)
+ get = zp->rcv_buf;
+ zp->rcv_count -= 3;
+ } else {
+ stat = 0;
+ --zp->rcv_count;
+ }
+ spltty();
+ if (tp == NULL || (tp->t_state & TS_ISOPEN) == 0)
+ continue;
+ if (zp->nzs_open == 0) {
+#ifdef notdef
+ if (stat == 0)
+ kbd_newchar(zp->gsp_unit, c);
+#endif
+ } else {
+ if ((stat & 0x10) != 0)
+ c |= TTY_PE;
+ if ((stat & 0x20) != 0) {
+ log(LOG_WARNING, "zs: fifo overflow\n");
+ c |= TTY_FE; /* need some error for
+ * slip stuff */
+ }
+ if ((stat & 0x40) != 0)
+ c |= TTY_FE;
+ (*linesw[tp->t_line].l_rint) (c, tp);
+ }
+ splzs();
+ }
+ zp->rcv_get = get;
+
+ /* check for modem lines changing */
+ while (zp->modem_change != 0 || zp->modem_state != zp->rr0) {
+ rr0 = zp->rr0 ^ zp->modem_change;
+ zp->modem_change = rr0 ^ zp->modem_state;
+
+ /* Check if DCD (carrier detect) has changed */
+ if (tp != NULL && (rr0 & 8) != (zp->rr0 & 8)) {
+ spltty();
+ ttymodem(tp, rr0 & 8);
+ /* XXX possibly should disable line if
+ * return value is 0 */
+ splzs();
+ }
+ zp->rr0 = rr0;
+ }
+ }
+ }
+ splx(s);
+}
+
+/*
+ * Routines to divert an SCC channel to the input side of /dev/gsp
+ * for the keyboard.
+ */
+int
+zs_kbdopen(int unit, int gsp_unit, struct termios * tiop, struct proc * p)
+{
+ struct zssoftc *dv = (struct zssoftc *) zscd.cd_devs[zsunit(unit)];
+ struct zs *zp = &dv->zs[zsside(unit)];
+ int error;
+
+ error = zsopen(unit, 0, 0, p);
+ if (error != 0)
+ return error;
+ ++zp->nkbd_open;
+ --zp->nzs_open;
+ zsparam(zp->tty, tiop);
+ zp->gsp_unit = gsp_unit;
+ return 0;
+}
+
+void
+zs_kbdclose(int unit)
+{
+ struct zssoftc *dv = (struct zssoftc *) zscd.cd_devs[zsunit(unit)];
+ struct zs *zp = &dv->zs[zsside(unit)];
+
+ zp->nkbd_open = 0;
+ if (zp->nzs_open == 0)
+ zsclose(unit, 0, 0, 0);
+}
+
+void
+zs_kbdput(int unit, int c)
+{
+ struct zssoftc *dv = (struct zssoftc *) zscd.cd_devs[zsunit(unit)];
+ struct zs *zp = &dv->zs[zsside(unit)];
+ struct tty *tp = zp->tty;
+
+ putc(c, &tp->t_outq);
+ zsstart(tp);
+}
+
+/*
+ * Routines for using side A of the first SCC as a console.
+ */
+
+/* probe for the SCC; should check hardware */
+zscnprobe(cp)
+ struct consdev *cp;
+{
+ int maj;
+ char *prom_cons;
+ extern char *prom_getvar();
+
+ /* locate the major number */
+ for (maj = 0; maj < nchrdev; maj++)
+ if (cdevsw[maj].d_open == zsopen)
+ break;
+
+ /* initialize required fields */
+ cp->cn_dev = makedev(maj, 0);
+ cp->cn_pri = CN_NORMAL;
+
+ return 1;
+}
+
+/* initialize the keyboard for use as the console */
+struct termios zscn_termios = {
+ TTYDEF_IFLAG,
+ TTYDEF_OFLAG,
+ TTYDEF_CFLAG,
+ TTYDEF_LFLAG,
+ {0},
+ TTYDEF_SPEED,
+ TTYDEF_SPEED
+};
+
+struct sccregs zs_cons_sccregs;
+int zs_cons_imask;
+
+unsigned zs_cons_addrs[] = {ZS0_PHYS, ZS1_PHYS};
+
+
+zscninit()
+{
+ zs_cnsetup(0, &zscn_termios);
+}
+
+/* Polling routine for console input from a serial port. */
+int
+zscngetc(dev_t dev)
+{
+ register struct sccregs *scc = zs_cons_scc;
+ int c, s, stat;
+
+ s = splzs();
+ for (;;) {
+ while ((ZREAD0(scc) & SCC_RXFULL) == 0) /* wait for Rx full */
+ ;
+ stat = ZREAD(scc, 1) & 0x70;
+ c = ZREADD(scc) & zs_cons_imask;
+ /* stat encodes parity, overrun, framing errors */
+ if (stat == 0)
+ break;
+ ZWRITE0(scc, 0x30); /* reset error */
+ }
+ splx(s);
+ return c;
+}
+
+zscnputc(dev_t dev, int c)
+{
+ register struct sccregs *scc = zs_cons_scc;
+ int s;
+
+ s = splzs();
+ while ((ZREAD0(scc) & SCC_TXRDY) == 0);
+ ZWRITED(scc, c);
+ splx(s);
+}
+
+zs_cnsetup(int unit, struct termios * tiop)
+{
+ register volatile struct scc *scc_adr;
+ register struct sccregs *scc;
+
+ zs_cons_unit = unit;
+ zs_is_console = 1;
+ zs_cons_scc = scc = &zs_cons_sccregs;
+
+ scc_adr = (volatile struct scc *) IIOV(zs_cons_addrs[zsunit(unit)]);
+
+ scc_adr[1].cr = 0;
+ scc_adr[1].cr = 9;
+ scc_adr[1].cr = 0xC0; /* hardware reset of SCC, both sides */
+ if (!zsside(unit))
+ ++scc_adr;
+
+ scc->s_adr = scc_adr;
+ ZWRITE(scc, 2, 0);
+ ZWRITE(scc, 10, 0);
+ ZWRITE(scc, 11, 0x50); /* rx & tx clock = brgen */
+ ZWRITE(scc, 14, 3); /* brgen enabled, from pclk */
+ zs_cons_imask = zscc_params(scc, tiop);
+ ZBIS(scc, 5, 0x82); /* set DTR and RTS */
+
+ zs_cons_termios = *tiop;/* save for later */
+}
+
+/*
+ * Routines for using the keyboard SCC as the input side of
+ * the 'gsp' console device.
+ */
+
+/* probe for the keyboard; should check hardware */
+zs_kbdcnprobe(cp, unit)
+ struct consdev *cp;
+ int unit;
+{
+ return (unsigned) unit < NZSLINE;
+}
+#endif /* NZS */
diff --git a/sys/arch/mvme68k/include/ansi.h b/sys/arch/mvme68k/include/ansi.h
new file mode 100644
index 00000000000..745f1b30ca2
--- /dev/null
+++ b/sys/arch/mvme68k/include/ansi.h
@@ -0,0 +1,4 @@
+/* $NetBSD: ansi.h,v 1.1.1.1 1995/07/25 23:12:12 chuck Exp $ */
+
+/* Just use the common m68k definition */
+#include <m68k/ansi.h>
diff --git a/sys/arch/mvme68k/include/asm.h b/sys/arch/mvme68k/include/asm.h
new file mode 100644
index 00000000000..e4f75e3949f
--- /dev/null
+++ b/sys/arch/mvme68k/include/asm.h
@@ -0,0 +1,3 @@
+/* $NetBSD: asm.h,v 1.1.1.1 1995/07/25 23:12:13 chuck Exp $ */
+
+#include <m68k/asm.h>
diff --git a/sys/arch/mvme68k/include/cdefs.h b/sys/arch/mvme68k/include/cdefs.h
new file mode 100644
index 00000000000..641030e3e30
--- /dev/null
+++ b/sys/arch/mvme68k/include/cdefs.h
@@ -0,0 +1,8 @@
+/* $NetBSD: cdefs.h,v 1.1.1.1 1995/07/25 23:12:19 chuck Exp $ */
+
+#ifndef _MACHINE_CDEFS_H_
+#define _MACHINE_CDEFS_H_
+
+#include <m68k/cdefs.h>
+
+#endif
diff --git a/sys/arch/mvme68k/include/cpu.h b/sys/arch/mvme68k/include/cpu.h
new file mode 100644
index 00000000000..aec3e71fbe6
--- /dev/null
+++ b/sys/arch/mvme68k/include/cpu.h
@@ -0,0 +1,230 @@
+/* $NetBSD: cpu.h,v 1.1.1.1 1995/07/25 23:12:13 chuck Exp $ */
+
+/*
+ * Copyright (c) 1988 University of Utah.
+ * Copyright (c) 1982, 1990, 1993
+ * 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: cpu.h 1.16 91/03/25$
+ *
+ * @(#)cpu.h 8.4 (Berkeley) 1/5/94
+ */
+
+/*
+ * Exported definitions unique to mvme68k/68k cpu support.
+ */
+
+/*
+ * definitions of cpu-dependent requirements
+ * referenced in generic code
+ */
+#define cpu_swapin(p) /* nothing */
+#define cpu_wait(p) /* nothing */
+#define cpu_setstack(p, ap) (p)->p_md.md_regs[SP] = ap
+#define cpu_swapout(p) /* nothing */
+
+/*
+ * Arguments to hardclock and gatherstats encapsulate the previous
+ * machine state in an opaque clockframe. One the mvme68k, we use
+ * what the hardware pushes on an interrupt (frame format 0).
+ */
+struct clockframe {
+ u_short sr; /* sr at time of interrupt */
+ u_long pc; /* pc at time of interrupt */
+ u_short vo; /* vector offset (4-word frame) */
+};
+
+#define CLKF_USERMODE(framep) (((framep)->sr & PSL_S) == 0)
+#define CLKF_BASEPRI(framep) (((framep)->sr & PSL_IPL) == 0)
+#define CLKF_PC(framep) ((framep)->pc)
+#if 0
+/* We would like to do it this way... */
+#define CLKF_INTR(framep) (((framep)->sr & PSL_M) == 0)
+#else
+/* but until we start using PSL_M, we have to do this instead */
+#define CLKF_INTR(framep) (0) /* XXX */
+#endif
+
+
+/*
+ * Preempt the current process if in interrupt from user mode,
+ * or after the current trap/syscall if in system mode.
+ */
+#define need_resched() { want_resched++; aston(); }
+
+/*
+ * Give a profiling tick to the current process when the user profiling
+ * buffer pages are invalid. On the hp300, request an ast to send us
+ * through trap, marking the proc as needing a profiling tick.
+ */
+#define need_proftick(p) { (p)->p_flag |= P_OWEUPC; aston(); }
+
+/*
+ * Notify the current process (p) that it has a signal pending,
+ * process as soon as possible.
+ */
+#define signotify(p) aston()
+
+#define aston() (astpending++)
+
+int astpending; /* need to trap before returning to user mode */
+int want_resched; /* resched() was called */
+
+
+/*
+ * simulated software interrupt register
+ */
+extern unsigned char ssir;
+
+#define SIR_NET 0x1
+#define SIR_CLOCK 0x2
+
+#define setsoftint(x) ssir |= (x)
+#define siroff(x) ssir &= ~(x)
+#define setsoftnet() ssir |= SIR_NET
+#define setsoftclock() ssir |= SIR_CLOCK
+
+extern unsigned long allocate_sir();
+
+/*
+ * CTL_MACHDEP definitions.
+ */
+#define CPU_CONSDEV 1 /* dev_t: console terminal device */
+#define CPU_MAXID 2 /* number of valid machdep ids */
+
+#define CTL_MACHDEP_NAMES { \
+ { 0, 0 }, \
+ { "console_device", CTLTYPE_STRUCT }, \
+}
+
+/* values for mmutype (assigned for quick testing) */
+#define MMU_68040 -2 /* 68040 on-chip MMU */
+#define MMU_68030 -1 /* 68030 on-chip subset of 68851 */
+#define MMU_68851 1 /* Motorola 68851 */
+
+/* values for ectype */
+#define EC_PHYS -1 /* external physical address cache */
+#define EC_NONE 0 /* no external cache */
+#define EC_VIRT 1 /* external virtual address cache */
+
+#define MHZ_16 2 /* XXX kill */
+
+
+#ifdef _KERNEL
+extern int mmutype, ectype;
+extern int cpuspeed; /* XXX kill */
+extern char *intiobase, *intiolimit;
+#endif
+
+/* physical memory sections for mvme147 */
+#define INTIOBASE (0xfffe0000)
+#define INTIOTOP (0xfffe5000)
+
+/*
+ * Internal IO space:
+ *
+ * Ranges from 0x800000 to 0x1000000 (IIOMAPSIZE).
+ *
+ * Internal IO space is mapped in the kernel from ``intiobase'' to
+ * ``intiolimit'' (defined in locore.s). Since it is always mapped,
+ * conversion between physical and kernel virtual addresses is easy.
+ */
+#define ISIIOVA(va) \
+ ((char *)(va) >= intiobase && (char *)(va) < intiolimit)
+#define IIOV(pa) ((int)(pa)-INTIOBASE+(int)intiobase)
+#define IIOP(va) ((int)(va)-(int)intiobase+INTIOBASE)
+#define IIOPOFF(pa) ((int)(pa)-INTIOBASE)
+#define IIOMAPSIZE btoc(INTIOTOP-INTIOBASE) /* 1mb */
+
+/*
+ * 68851 and 68030 MMU
+ */
+#define PMMU_LVLMASK 0x0007
+#define PMMU_INV 0x0400
+#define PMMU_WP 0x0800
+#define PMMU_ALV 0x1000
+#define PMMU_SO 0x2000
+#define PMMU_LV 0x4000
+#define PMMU_BE 0x8000
+#define PMMU_FAULT (PMMU_WP|PMMU_INV)
+
+/*
+ * 68040 MMU
+ */
+#define MMU4_RES 0x001
+#define MMU4_TTR 0x002
+#define MMU4_WP 0x004
+#define MMU4_MOD 0x010
+#define MMU4_CMMASK 0x060
+#define MMU4_SUP 0x080
+#define MMU4_U0 0x100
+#define MMU4_U1 0x200
+#define MMU4_GLB 0x400
+#define MMU4_BE 0x800
+
+/* 680X0 function codes */
+#define FC_USERD 1 /* user data space */
+#define FC_USERP 2 /* user program space */
+#define FC_SUPERD 5 /* supervisor data space */
+#define FC_SUPERP 6 /* supervisor program space */
+#define FC_CPU 7 /* CPU space */
+
+/* fields in the 68020 cache control register */
+#define IC_ENABLE 0x0001 /* enable instruction cache */
+#define IC_FREEZE 0x0002 /* freeze instruction cache */
+#define IC_CE 0x0004 /* clear instruction cache entry */
+#define IC_CLR 0x0008 /* clear entire instruction cache */
+
+/* additional fields in the 68030 cache control register */
+#define IC_BE 0x0010 /* instruction burst enable */
+#define DC_ENABLE 0x0100 /* data cache enable */
+#define DC_FREEZE 0x0200 /* data cache freeze */
+#define DC_CE 0x0400 /* clear data cache entry */
+#define DC_CLR 0x0800 /* clear entire data cache */
+#define DC_BE 0x1000 /* data burst enable */
+#define DC_WA 0x2000 /* write allocate */
+
+#define CACHE_ON (DC_WA|DC_BE|DC_CLR|DC_ENABLE|IC_BE|IC_CLR|IC_ENABLE)
+#define CACHE_OFF (DC_CLR|IC_CLR)
+#define CACHE_CLR (CACHE_ON)
+#define IC_CLEAR (DC_WA|DC_BE|DC_ENABLE|IC_BE|IC_CLR|IC_ENABLE)
+#define DC_CLEAR (DC_WA|DC_BE|DC_CLR|DC_ENABLE|IC_BE|IC_ENABLE)
+
+/* 68040 cache control register */
+#define IC4_ENABLE 0x8000 /* instruction cache enable bit */
+#define DC4_ENABLE 0x80000000 /* data cache enable bit */
+
+#define CACHE4_ON (IC4_ENABLE|DC4_ENABLE)
+#define CACHE4_OFF (0)
diff --git a/sys/arch/mvme68k/include/db_machdep.h b/sys/arch/mvme68k/include/db_machdep.h
new file mode 100644
index 00000000000..a736e228618
--- /dev/null
+++ b/sys/arch/mvme68k/include/db_machdep.h
@@ -0,0 +1,4 @@
+/* $NetBSD: db_machdep.h,v 1.1.1.1 1995/07/25 23:12:14 chuck Exp $ */
+
+/* Just use the common m68k definition */
+#include <m68k/db_machdep.h>
diff --git a/sys/arch/mvme68k/include/disklabel.h b/sys/arch/mvme68k/include/disklabel.h
new file mode 100644
index 00000000000..9a0722ee829
--- /dev/null
+++ b/sys/arch/mvme68k/include/disklabel.h
@@ -0,0 +1,46 @@
+/* $NetBSD: disklabel.h,v 1.1.1.1 1995/07/25 23:12:14 chuck Exp $ */
+
+/*
+ * Copyright (c) 1994 Christopher G. Demetriou
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Christopher G. Demetriou.
+ * 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.
+ */
+
+#ifndef _MACHINE_DISKLABEL_H_
+#define _MACHINE_DISKLABEL_H_
+
+#define LABELSECTOR 0 /* sector containing label */
+#define LABELOFFSET 64 /* offset of label in sector */
+#define MAXPARTITIONS 8 /* number of partitions */
+#define RAW_PART 2 /* raw partition: xx?c */
+
+/* Just a dummy */
+struct cpu_disklabel {
+ int cd_dummy; /* must have one element. */
+};
+
+#endif /* _MACHINE_DISKLABEL_H_ */
diff --git a/sys/arch/mvme68k/include/endian.h b/sys/arch/mvme68k/include/endian.h
new file mode 100644
index 00000000000..3876563a9f3
--- /dev/null
+++ b/sys/arch/mvme68k/include/endian.h
@@ -0,0 +1,4 @@
+/* $NetBSD: endian.h,v 1.1.1.1 1995/07/25 23:12:15 chuck Exp $ */
+
+/* Just use the common m68k definition */
+#include <m68k/endian.h>
diff --git a/sys/arch/mvme68k/include/exec.h b/sys/arch/mvme68k/include/exec.h
new file mode 100644
index 00000000000..eea9bf11738
--- /dev/null
+++ b/sys/arch/mvme68k/include/exec.h
@@ -0,0 +1,48 @@
+/* $NetBSD: exec.h,v 1.1.1.1 1995/07/25 23:12:15 chuck Exp $ */
+
+/*
+ * Copyright (c) 1993 Christopher G. Demetriou
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef _MACHINE_EXEC_H_
+#define _MACHINE_EXEC_H_
+
+#define __LDPGSZ 8192
+
+/* Relocation format. */
+struct relocation_info_m68k {
+ int r_address; /* offset in text or data segment */
+ unsigned int r_symbolnum : 24, /* ordinal number of add symbol */
+ r_pcrel : 1, /* 1 if value should be pc-relative */
+ r_length : 2, /* log base 2 of value's width */
+ r_extern : 1, /* 1 if need to add symbol to value */
+ r_baserel : 1, /* linkage table relative */
+ r_jmptable : 1, /* relocate to jump table */
+ r_relative : 1, /* load address relative */
+ r_copy : 1; /* run time copy */
+};
+#define relocation_info relocation_info_m68k
+
+#endif /* _MACHINE_EXEC_H_ */
diff --git a/sys/arch/mvme68k/include/float.h b/sys/arch/mvme68k/include/float.h
new file mode 100644
index 00000000000..5eeebfa7f4b
--- /dev/null
+++ b/sys/arch/mvme68k/include/float.h
@@ -0,0 +1,8 @@
+/* $NetBSD: float.h,v 1.1.1.1 1995/07/25 23:12:15 chuck Exp $ */
+
+#ifndef _MACHINE_FLOAT_H_
+#define _MACHINE_FLOAT_H_
+
+#include <m68k/float.h>
+
+#endif
diff --git a/sys/arch/mvme68k/include/frame.h b/sys/arch/mvme68k/include/frame.h
new file mode 100644
index 00000000000..a6b1f3c584b
--- /dev/null
+++ b/sys/arch/mvme68k/include/frame.h
@@ -0,0 +1,3 @@
+/* $NetBSD: frame.h,v 1.1.1.1 1995/07/25 23:12:15 chuck Exp $ */
+
+#include <m68k/frame.h>
diff --git a/sys/arch/mvme68k/include/limits.h b/sys/arch/mvme68k/include/limits.h
new file mode 100644
index 00000000000..ab36a0f1dc7
--- /dev/null
+++ b/sys/arch/mvme68k/include/limits.h
@@ -0,0 +1,4 @@
+/* $NetBSD: limits.h,v 1.1.1.1 1995/07/25 23:12:16 chuck Exp $ */
+
+/* Just use the common m68k definition */
+#include <m68k/limits.h>
diff --git a/sys/arch/mvme68k/include/param.h b/sys/arch/mvme68k/include/param.h
new file mode 100644
index 00000000000..8c61f93adc9
--- /dev/null
+++ b/sys/arch/mvme68k/include/param.h
@@ -0,0 +1,184 @@
+/* $NetBSD: param.h,v 1.2 1995/08/13 00:27:11 mycroft Exp $ */
+
+/*
+ * Copyright (c) 1988 University of Utah.
+ * Copyright (c) 1982, 1986, 1990, 1993
+ * 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: machparam.h 1.16 92/12/20$
+ *
+ * @(#)param.h 8.1 (Berkeley) 6/10/93
+ */
+
+/*
+ * Machine dependent constants for mvme68k, based on HP9000 series 300.
+ */
+#define MACHINE "mvme68k"
+#define MACHINE_ARCH "m68k"
+#define MID_MACHINE MID_M68K
+
+/*
+ * Round p (pointer or byte index) up to a correctly-aligned value for all
+ * data types (int, long, ...). The result is u_int and must be cast to
+ * any desired pointer type.
+ */
+#define ALIGNBYTES (sizeof(int) - 1)
+#define ALIGN(p) (((u_int)(p) + ALIGNBYTES) &~ ALIGNBYTES)
+
+#define PGSHIFT 12 /* LOG2(NBPG) */
+#define NBPG (1 << PGSHIFT) /* bytes/page */
+#define PGOFSET (NBPG-1) /* byte offset into page */
+#define NPTEPG (NBPG/(sizeof (pt_entry_t)))
+
+#define SEGSHIFT 22 /* LOG2(NBSEG) */
+#define NBSEG (1 << SEGSHIFT) /* bytes/segment */
+#define SEGOFSET (NBSEG-1) /* byte offset into segment */
+
+#define KERNBASE 0x00000000 /* start of kernel virtual */
+#define BTOPKERNBASE ((u_long)KERNBASE >> PGSHIFT)
+
+#define DEV_BSHIFT 9 /* log2(DEV_BSIZE) */
+#define DEV_BSIZE (1 << DEV_BSHIFT)
+#define BLKDEV_IOSIZE 2048
+#define MAXPHYS (64 * 1024) /* max raw I/O transfer size */
+
+#define CLSIZELOG2 0
+#define CLSIZE (1 << CLSIZELOG2)
+
+/* NOTE: SSIZE, SINCR and UPAGES must be multiples of CLSIZE */
+#define SSIZE 1 /* initial stack size/NBPG */
+#define SINCR 1 /* increment of stack/NBPG */
+#define UPAGES 3 /* pages of u-area */
+#define USPACE (UPAGES * NBPG) /* total size of u-area */
+
+/*
+ * Constants related to network buffer management.
+ * MCLBYTES must be no larger than CLBYTES (the software page size), and,
+ * on machines that exchange pages of input or output buffers with mbuf
+ * clusters (MAPPED_MBUFS), MCLBYTES must also be an integral multiple
+ * of the hardware page size.
+ */
+#define MSIZE 128 /* size of an mbuf */
+#define MCLSHIFT 11
+#define MCLBYTES (1 << MCLSHIFT) /* large enough for ether MTU */
+#define MCLOFSET (MCLBYTES - 1)
+
+#ifndef NMBCLUSTERS
+#ifdef GATEWAY
+#define NMBCLUSTERS 512 /* map size, max cluster allocation */
+#else
+#define NMBCLUSTERS 256 /* map size, max cluster allocation */
+#endif
+#endif
+
+/*
+ * Size of kernel malloc arena in CLBYTES-sized logical pages
+ */
+#ifndef NKMEMCLUSTERS
+#define NKMEMCLUSTERS (2048 * 1024 / CLBYTES)
+#endif
+
+/* pages ("clicks") to disk blocks */
+#define ctod(x) ((x) << (PGSHIFT - DEV_BSHIFT))
+#define dtoc(x) ((x) >> (PGSHIFT - DEV_BSHIFT))
+
+/* pages to bytes */
+#define ctob(x) ((x) << PGSHIFT)
+#define btoc(x) (((x) + PGOFSET) >> PGSHIFT)
+
+/* bytes to disk blocks */
+#define dbtob(x) ((x) << DEV_BSHIFT)
+#define btodb(x) ((x) >> DEV_BSHIFT)
+
+/*
+ * Map a ``block device block'' to a file system block.
+ * This should be device dependent, and should use the bsize
+ * field from the disk label.
+ * For now though just use DEV_BSIZE.
+ */
+#define bdbtofsb(bn) ((bn) / (BLKDEV_IOSIZE / DEV_BSIZE))
+
+/*
+ * Mach derived conversion macros
+ */
+#define m68k_round_page(x) ((((unsigned)(x)) + PGOFSET) & ~PGOFSET)
+#define m68k_trunc_page(x) ((unsigned)(x) & ~PGOFSET)
+#define m68k_btop(x) ((unsigned)(x) >> PGSHIFT)
+#define m68k_ptob(x) ((unsigned)(x) << PGSHIFT)
+
+/*
+ * spl functions; all but spl0 are done in-line
+ */
+#include <machine/psl.h>
+
+#define _spl(s) \
+({ \
+ register int _spl_r; \
+\
+ __asm __volatile ("clrl %0; movew sr,%0; movew %1,sr" : \
+ "&=d" (_spl_r) : "di" (s)); \
+ _spl_r; \
+})
+
+/* spl0 requires checking for software interrupts */
+#define spl1() _spl(PSL_S|PSL_IPL1)
+#define spl2() _spl(PSL_S|PSL_IPL2)
+#define spl3() _spl(PSL_S|PSL_IPL3)
+#define spl4() _spl(PSL_S|PSL_IPL4)
+#define spl5() _spl(PSL_S|PSL_IPL5)
+#define spl6() _spl(PSL_S|PSL_IPL6)
+#define spl7() _spl(PSL_S|PSL_IPL7)
+
+#define splsoftclock() spl1()
+#define splsoftnet() spl1()
+#define splbio() spl2()
+#define splnet() spl3()
+#define spltty() spl3()
+#define splimp() spl3()
+#define splclock() spl5()
+#define splstatclock() spl5()
+#define splvm() spl5()
+#define splhigh() spl7()
+#define splsched() spl7()
+
+/* watch out for side effects */
+#define splx(s) (s & PSL_IPL ? _spl(s) : spl0())
+
+#ifdef _KERNEL
+#ifndef LOCORE
+int cpuspeed;
+#define DELAY(n) { register int N = cpuspeed * (n); while (--N > 0); }
+#endif
+#endif
diff --git a/sys/arch/mvme68k/include/pcb.h b/sys/arch/mvme68k/include/pcb.h
new file mode 100644
index 00000000000..001543c03c4
--- /dev/null
+++ b/sys/arch/mvme68k/include/pcb.h
@@ -0,0 +1,67 @@
+/* $NetBSD: pcb.h,v 1.1.1.1 1995/07/25 23:12:16 chuck Exp $ */
+
+/*
+ * Copyright (c) 1988 University of Utah.
+ * Copyright (c) 1982, 1986, 1990, 1993
+ * 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: pcb.h 1.14 91/03/25$
+ *
+ * @(#)pcb.h 8.1 (Berkeley) 6/10/93
+ */
+
+#include <machine/frame.h>
+
+/*
+ * mvme68k process control block
+ */
+struct pcb {
+ short pcb_flags; /* misc. process flags */
+ short pcb_ps; /* processor status word */
+ int pcb_ustp; /* user segment table pointer */
+ int pcb_usp; /* user stack pointer */
+ int pcb_regs[12]; /* D2-D7, A2-A7 */
+ caddr_t pcb_onfault; /* for copyin/out faults */
+ struct fpframe pcb_fpregs; /* 68881/2 context save area */
+};
+
+/*
+ * The pcb is augmented with machine-dependent additional data for
+ * core dumps. For the hp300, this includes an HP-UX exec header
+ * which is dumped for HP-UX processes.
+ */
+struct md_coredump {
+ int md_exec[16]; /* exec structure for HP-UX core dumps */
+};
diff --git a/sys/arch/mvme68k/include/pmap.h b/sys/arch/mvme68k/include/pmap.h
new file mode 100644
index 00000000000..323861224dd
--- /dev/null
+++ b/sys/arch/mvme68k/include/pmap.h
@@ -0,0 +1,159 @@
+/* $NetBSD: pmap.h,v 1.1.1.1 1995/07/25 23:12:16 chuck Exp $ */
+
+/*
+ * Copyright (c) 1987 Carnegie-Mellon University
+ * Copyright (c) 1991, 1993
+ * 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.
+ *
+ * @(#)pmap.h 8.1 (Berkeley) 6/10/93
+ */
+
+#ifndef _MACHINE_PMAP_H_
+#define _MACHINE_PMAP_H_
+
+#include <machine/pte.h>
+
+#if defined(M68040)
+#define HP_SEG_SIZE (mmutype == MMU_68040 ? 0x40000 : NBSEG)
+#else
+#define HP_SEG_SIZE NBSEG
+#endif
+
+#define m68k_trunc_seg(x) (((unsigned)(x)) & ~(HP_SEG_SIZE-1))
+#define m68k_round_seg(x) m68k_trunc_seg((unsigned)(x) + HP_SEG_SIZE-1)
+
+/*
+ * Pmap stuff
+ */
+struct pmap {
+ pt_entry_t *pm_ptab; /* KVA of page table */
+ st_entry_t *pm_stab; /* KVA of segment table */
+ int pm_stchanged; /* ST changed */
+ int pm_stfree; /* 040: free lev2 blocks */
+ st_entry_t *pm_stpa; /* 040: ST phys addr */
+ short pm_sref; /* segment table ref count */
+ short pm_count; /* pmap reference count */
+ simple_lock_data_t pm_lock; /* lock on pmap */
+ struct pmap_statistics pm_stats; /* pmap statistics */
+ long pm_ptpages; /* more stats: PT pages */
+};
+
+typedef struct pmap *pmap_t;
+
+/*
+ * On the 040 we keep track of which level 2 blocks are already in use
+ * with the pm_stfree mask. Bits are arranged from LSB (block 0) to MSB
+ * (block 31). For convenience, the level 1 table is considered to be
+ * block 0.
+ *
+ * MAX[KU]L2SIZE control how many pages of level 2 descriptors are allowed.
+ * for the kernel and users. 8 implies only the initial "segment table"
+ * page is used. WARNING: don't change MAXUL2SIZE unless you can allocate
+ * physically contiguous pages for the ST in pmap.c!
+ */
+#define MAXKL2SIZE 32
+#define MAXUL2SIZE 8
+#define l2tobm(n) (1 << (n))
+#define bmtol2(n) (ffs(n) - 1)
+
+/*
+ * Macros for speed
+ */
+#define PMAP_ACTIVATE(pmapp, pcbp, iscurproc) \
+ if ((pmapp)->pm_stchanged) { \
+ (pcbp)->pcb_ustp = m68k_btop((vm_offset_t)(pmapp)->pm_stpa); \
+ if (iscurproc) \
+ loadustp((pcbp)->pcb_ustp); \
+ (pmapp)->pm_stchanged = FALSE; \
+ }
+#define PMAP_DEACTIVATE(pmapp, pcbp)
+
+/*
+ * For each vm_page_t, there is a list of all currently valid virtual
+ * mappings of that page. An entry is a pv_entry, the list is pv_table.
+ */
+struct pv_entry {
+ struct pv_entry *pv_next; /* next pv_entry */
+ struct pmap *pv_pmap; /* pmap where mapping lies */
+ vm_offset_t pv_va; /* virtual address for mapping */
+ st_entry_t *pv_ptste; /* non-zero if VA maps a PT page */
+ struct pmap *pv_ptpmap; /* if pv_ptste, pmap for PT page */
+ int pv_flags; /* flags */
+};
+
+#define PV_CI 0x01 /* header: all entries are cache inhibited */
+#define PV_PTPAGE 0x02 /* header: entry maps a page table page */
+
+struct pv_page;
+
+struct pv_page_info {
+ TAILQ_ENTRY(pv_page) pgi_list;
+ struct pv_entry *pgi_freelist;
+ int pgi_nfree;
+};
+
+/*
+ * This is basically:
+ * ((NBPG - sizeof(struct pv_page_info)) / sizeof(struct pv_entry))
+ */
+#define NPVPPG 170
+
+struct pv_page {
+ struct pv_page_info pvp_pgi;
+ struct pv_entry pvp_pv[NPVPPG];
+};
+
+#ifdef _KERNEL
+
+extern struct pmap kernel_pmap_store;
+extern vm_offset_t vm_first_phys, vm_num_phys;
+
+#define pmap_kernel() (&kernel_pmap_store)
+#define active_pmap(pm) \
+ ((pm) == pmap_kernel() || (pm) == curproc->p_vmspace->vm_map.pmap)
+
+extern struct pv_entry *pv_table; /* array of entries, one per page */
+
+#define pmap_page_index(pa) atop(pa - vm_first_phys)
+#define pa_to_pvh(pa) (&pv_table[pmap_page_index(pa)])
+
+#define pmap_resident_count(pmap) ((pmap)->pm_stats.resident_count)
+#define pmap_wired_count(pmap) ((pmap)->pm_stats.wired_count)
+
+extern pt_entry_t *Sysmap;
+extern char *vmmap; /* map for mem, dumps, etc. */
+#endif /* _KERNEL */
+
+#endif /* !_MACHINE_PMAP_H_ */
diff --git a/sys/arch/mvme68k/include/proc.h b/sys/arch/mvme68k/include/proc.h
new file mode 100644
index 00000000000..e50f573dea8
--- /dev/null
+++ b/sys/arch/mvme68k/include/proc.h
@@ -0,0 +1,53 @@
+/* $NetBSD: proc.h,v 1.1.1.1 1995/07/25 23:12:16 chuck Exp $ */
+
+/*
+ * Copyright (c) 1991, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)proc.h 8.1 (Berkeley) 6/10/93
+ */
+
+/*
+ * Machine-dependent part of the proc structure for mvme68k.
+ */
+struct mdproc {
+ int *md_regs; /* registers on current frame */
+ int md_flags; /* machine-dependent flags */
+};
+
+/* md_flags */
+#define MDP_STACKADJ 0x0002 /* frame SP adjusted, might have to
+ undo when system call returns
+ ERESTART. */
+#define MDP_HPUXTRACE 0x0004 /* being traced by HP-UX process */
+#define MDP_HPUXMMAP 0x0008 /* VA space is multiply mapped */
+#define MDP_CCBDATA 0x0010 /* copyback caching of data (68040) */
+#define MDP_CCBSTACK 0x0020 /* copyback caching of stack (68040) */
diff --git a/sys/arch/mvme68k/include/profile.h b/sys/arch/mvme68k/include/profile.h
new file mode 100644
index 00000000000..135774c7a25
--- /dev/null
+++ b/sys/arch/mvme68k/include/profile.h
@@ -0,0 +1,3 @@
+/* $NetBSD: profile.h,v 1.1.1.1 1995/07/25 23:12:17 chuck Exp $ */
+
+#include <m68k/profile.h>
diff --git a/sys/arch/mvme68k/include/psl.h b/sys/arch/mvme68k/include/psl.h
new file mode 100644
index 00000000000..e374e95e9bb
--- /dev/null
+++ b/sys/arch/mvme68k/include/psl.h
@@ -0,0 +1,3 @@
+/* $NetBSD: psl.h,v 1.1.1.1 1995/07/25 23:12:17 chuck Exp $ */
+
+#include <m68k/psl.h>
diff --git a/sys/arch/mvme68k/include/pte.h b/sys/arch/mvme68k/include/pte.h
new file mode 100644
index 00000000000..e7c55296f1e
--- /dev/null
+++ b/sys/arch/mvme68k/include/pte.h
@@ -0,0 +1,152 @@
+/* $NetBSD: pte.h,v 1.1.1.1 1995/07/25 23:12:17 chuck Exp $ */
+
+/*
+ * Copyright (c) 1988 University of Utah.
+ * Copyright (c) 1982, 1986, 1990, 1993
+ * 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: pte.h 1.13 92/01/20$
+ *
+ * @(#)pte.h 8.1 (Berkeley) 6/10/93
+ */
+
+#ifndef _MACHINE_PTE_H_
+#define _MACHINE_PTE_H_
+
+/*
+ * m68k hardware segment/page table entries
+ */
+
+#if 0
+struct ste {
+ unsigned int sg_pfnum:20; /* page table frame number */
+ unsigned int :8; /* reserved at 0 */
+ unsigned int :1; /* reserved at 1 */
+ unsigned int sg_prot:1; /* write protect bit */
+ unsigned int sg_v:2; /* valid bits */
+};
+
+struct ste40 {
+ unsigned int sg_ptaddr:24; /* page table page addr */
+ unsigned int :4; /* reserved at 0 */
+ unsigned int sg_u; /* hardware modified (dirty) bit */
+ unsigned int sg_prot:1; /* write protect bit */
+ unsigned int sg_v:2; /* valid bits */
+};
+
+struct pte {
+ unsigned int pg_pfnum:20; /* page frame number or 0 */
+ unsigned int :3;
+ unsigned int pg_w:1; /* is wired */
+ unsigned int :1; /* reserved at zero */
+ unsigned int pg_ci:1; /* cache inhibit bit */
+ unsigned int :1; /* reserved at zero */
+ unsigned int pg_m:1; /* hardware modified (dirty) bit */
+ unsigned int pg_u:1; /* hardware used (reference) bit */
+ unsigned int pg_prot:1; /* write protect bit */
+ unsigned int pg_v:2; /* valid bit */
+};
+#endif
+
+typedef int st_entry_t; /* segment table entry */
+typedef int pt_entry_t; /* Mach page table entry */
+
+#define PT_ENTRY_NULL ((pt_entry_t *) 0)
+#define ST_ENTRY_NULL ((st_entry_t *) 0)
+
+#define SG_V 0x00000002 /* segment is valid */
+#define SG_NV 0x00000000
+#define SG_PROT 0x00000004 /* access protection mask */
+#define SG_RO 0x00000004
+#define SG_RW 0x00000000
+#define SG_U 0x00000008 /* modified bit (68040) */
+#define SG_FRAME 0xfffff000
+#define SG_IMASK 0xffc00000
+#define SG_ISHIFT 22
+#define SG_PMASK 0x003ff000
+#define SG_PSHIFT 12
+
+/* 68040 additions */
+#define SG4_MASK1 0xfe000000
+#define SG4_SHIFT1 25
+#define SG4_MASK2 0x01fc0000
+#define SG4_SHIFT2 18
+#define SG4_MASK3 0x0003f000
+#define SG4_SHIFT3 12
+#define SG4_ADDR1 0xfffffe00
+#define SG4_ADDR2 0xffffff00
+#define SG4_LEV1SIZE 128
+#define SG4_LEV2SIZE 128
+#define SG4_LEV3SIZE 64
+
+#define PG_V 0x00000001
+#define PG_NV 0x00000000
+#define PG_PROT 0x00000004
+#define PG_U 0x00000008
+#define PG_M 0x00000010
+#define PG_W 0x00000100
+#define PG_RO 0x00000004
+#define PG_RW 0x00000000
+#define PG_FRAME 0xfffff000
+#define PG_CI 0x00000040
+#define PG_SHIFT 12
+#define PG_PFNUM(x) (((x) & PG_FRAME) >> PG_SHIFT)
+
+/* 68040 additions */
+#define PG_CMASK 0x00000060 /* cache mode mask */
+#define PG_CWT 0x00000000 /* writethrough caching */
+#define PG_CCB 0x00000020 /* copyback caching */
+#define PG_CIS 0x00000040 /* cache inhibited serialized */
+#define PG_CIN 0x00000060 /* cache inhibited nonserialized */
+#define PG_SO 0x00000080 /* supervisor only */
+
+#define HP_STSIZE (MAXUL2SIZE*SG4_LEV2SIZE*sizeof(st_entry_t))
+ /* user process segment table size */
+#define HP_MAX_PTSIZE 0x400000 /* max size of UPT */
+#define HP_MAX_KPTSIZE 0x100000 /* max memory to allocate to KPT */
+#define HP_PTBASE 0x10000000 /* UPT map base address */
+#define HP_PTMAXSIZE 0x70000000 /* UPT map maximum size */
+
+/*
+ * Kernel virtual address to page table entry and to physical address.
+ */
+#define kvtopte(va) \
+ (&Sysmap[((unsigned)(va) - VM_MIN_KERNEL_ADDRESS) >> PGSHIFT])
+#define ptetokv(pt) \
+ ((((pt_entry_t *)(pt) - Sysmap) << PGSHIFT) + VM_MIN_KERNEL_ADDRESS)
+#define kvtophys(va) \
+ ((kvtopte(va)->pg_pfnum << PGSHIFT) | ((int)(va) & PGOFSET))
+
+#endif /* !_MACHINE_PTE_H_ */
diff --git a/sys/arch/mvme68k/include/ptrace.h b/sys/arch/mvme68k/include/ptrace.h
new file mode 100644
index 00000000000..5a92bbbe410
--- /dev/null
+++ b/sys/arch/mvme68k/include/ptrace.h
@@ -0,0 +1,4 @@
+/* $NetBSD: ptrace.h,v 1.1.1.1 1995/07/25 23:12:17 chuck Exp $ */
+
+/* Just use the common m68k definition */
+#include <m68k/ptrace.h>
diff --git a/sys/arch/mvme68k/include/reg.h b/sys/arch/mvme68k/include/reg.h
new file mode 100644
index 00000000000..a78c3a7c910
--- /dev/null
+++ b/sys/arch/mvme68k/include/reg.h
@@ -0,0 +1,8 @@
+/* $NetBSD: reg.h,v 1.1.1.1 1995/07/25 23:12:18 chuck Exp $ */
+
+#ifndef _MACHINE_REG_H_
+#define _MACHINE_REG_H_
+
+#include <m68k/reg.h>
+
+#endif /* _MACHINE_REG_H_ */
diff --git a/sys/arch/mvme68k/include/setjmp.h b/sys/arch/mvme68k/include/setjmp.h
new file mode 100644
index 00000000000..bccffd9143b
--- /dev/null
+++ b/sys/arch/mvme68k/include/setjmp.h
@@ -0,0 +1,3 @@
+/* $NetBSD: setjmp.h,v 1.1.1.1 1995/07/25 23:12:18 chuck Exp $ */
+
+#include <m68k/setjmp.h>
diff --git a/sys/arch/mvme68k/include/signal.h b/sys/arch/mvme68k/include/signal.h
new file mode 100644
index 00000000000..a00ca454c06
--- /dev/null
+++ b/sys/arch/mvme68k/include/signal.h
@@ -0,0 +1,4 @@
+/* $NetBSD: signal.h,v 1.1.1.1 1995/07/25 23:12:18 chuck Exp $ */
+
+/* Just use the common m68k definition */
+#include <m68k/signal.h>
diff --git a/sys/arch/mvme68k/include/stdarg.h b/sys/arch/mvme68k/include/stdarg.h
new file mode 100644
index 00000000000..5018e7e3993
--- /dev/null
+++ b/sys/arch/mvme68k/include/stdarg.h
@@ -0,0 +1,4 @@
+/* $NetBSD: stdarg.h,v 1.1.1.1 1995/07/25 23:12:18 chuck Exp $ */
+
+/* Just use the common m68k definition */
+#include <m68k/stdarg.h>
diff --git a/sys/arch/mvme68k/include/trap.h b/sys/arch/mvme68k/include/trap.h
new file mode 100644
index 00000000000..881b0ad8e3a
--- /dev/null
+++ b/sys/arch/mvme68k/include/trap.h
@@ -0,0 +1,3 @@
+/* $NetBSD: trap.h,v 1.1.1.1 1995/07/25 23:12:19 chuck Exp $ */
+
+#include <m68k/trap.h>
diff --git a/sys/arch/mvme68k/include/types.h b/sys/arch/mvme68k/include/types.h
new file mode 100644
index 00000000000..0a0c7885eec
--- /dev/null
+++ b/sys/arch/mvme68k/include/types.h
@@ -0,0 +1,10 @@
+/* $NetBSD: types.h,v 1.1.1.1 1995/07/25 23:12:19 chuck Exp $ */
+
+#ifndef _MACHINE_TYPES_H_
+#define _MACHINE_TYPES_H_
+
+#include <m68k/types.h>
+
+#define __BDEVSW_DUMP_OLD_TYPE
+
+#endif
diff --git a/sys/arch/mvme68k/include/varargs.h b/sys/arch/mvme68k/include/varargs.h
new file mode 100644
index 00000000000..797ad3e7e0c
--- /dev/null
+++ b/sys/arch/mvme68k/include/varargs.h
@@ -0,0 +1,4 @@
+/* $NetBSD: varargs.h,v 1.1.1.1 1995/07/25 23:12:19 chuck Exp $ */
+
+/* Just use the common m68k definition */
+#include <m68k/varargs.h>
diff --git a/sys/arch/mvme68k/include/vmparam.h b/sys/arch/mvme68k/include/vmparam.h
new file mode 100644
index 00000000000..7e274b713dc
--- /dev/null
+++ b/sys/arch/mvme68k/include/vmparam.h
@@ -0,0 +1,246 @@
+/* $NetBSD: vmparam.h,v 1.1.1.1 1995/07/25 23:12:19 chuck Exp $ */
+
+/*
+ * Copyright (c) 1988 University of Utah.
+ * Copyright (c) 1982, 1986, 1990, 1993
+ * 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: vmparam.h 1.16 91/01/18$
+ *
+ * @(#)vmparam.h 8.2 (Berkeley) 4/19/94
+ */
+
+/*
+ * Machine dependent constants for MVME68K
+ */
+/*
+ * USRTEXT is the start of the user text/data space, while USRSTACK
+ * is the top (end) of the user stack. LOWPAGES and HIGHPAGES are
+ * the number of pages from the beginning of the P0 region to the
+ * beginning of the text and from the beginning of the P1 region to the
+ * beginning of the stack respectively.
+ *
+ * NOTE: the ONLY reason that HIGHPAGES is 0x100 instead of UPAGES (3)
+ * is for HPUX compatibility. Why?? Because HPUX's debuggers
+ * have the user's stack hard-wired at FFF00000 for post-mortems,
+ * and we must be compatible...
+ */
+#define USRTEXT 8192 /* Must equal __LDPGSZ */
+#define USRSTACK (-HIGHPAGES*NBPG) /* Start of user stack */
+#define BTOPUSRSTACK (0x100000-HIGHPAGES) /* btop(USRSTACK) */
+#define P1PAGES 0x100000
+#define LOWPAGES 0
+#define HIGHPAGES (0x100000/NBPG)
+
+/*
+ * Virtual memory related constants, all in bytes
+ */
+#ifndef MAXTSIZ
+#define MAXTSIZ (8*1024*1024) /* max text size */
+#endif
+#ifndef DFLDSIZ
+#define DFLDSIZ (16*1024*1024) /* initial data size limit */
+#endif
+#ifndef MAXDSIZ
+#define MAXDSIZ (64*1024*1024) /* max data size */
+#endif
+#ifndef DFLSSIZ
+#define DFLSSIZ (512*1024) /* initial stack size limit */
+#endif
+#ifndef MAXSSIZ
+#define MAXSSIZ MAXDSIZ /* max stack size */
+#endif
+
+/*
+ * Default sizes of swap allocation chunks (see dmap.h).
+ * The actual values may be changed in vminit() based on MAXDSIZ.
+ * With MAXDSIZ of 16Mb and NDMAP of 38, dmmax will be 1024.
+ * DMMIN should be at least ctod(1) so that vtod() works.
+ * vminit() insures this.
+ */
+#define DMMIN 32 /* smallest swap allocation */
+#define DMMAX 4096 /* largest potential swap allocation */
+
+/*
+ * Sizes of the system and user portions of the system page table.
+ */
+/* SYSPTSIZE IS SILLY; IT SHOULD BE COMPUTED AT BOOT TIME */
+#define SYSPTSIZE (2 * NPTEPG) /* 8mb */
+#define USRPTSIZE (1 * NPTEPG) /* 4mb */
+
+/*
+ * PTEs for mapping user space into the kernel for phyio operations.
+ * One page is enough to handle 4Mb of simultaneous raw IO operations.
+ */
+#ifndef USRIOSIZE
+#define USRIOSIZE (1 * NPTEPG) /* 4mb */
+#endif
+
+/*
+ * PTEs for system V style shared memory.
+ * This is basically slop for kmempt which we actually allocate (malloc) from.
+ */
+#ifndef SHMMAXPGS
+#define SHMMAXPGS 1024 /* 4mb */
+#endif
+
+/*
+ * External IO space map size.
+ */
+#ifndef EIOMAPSIZE
+#define EIOMAPSIZE 0 /* nothing */
+#endif
+
+/*
+ * Boundary at which to place first MAPMEM segment if not explicitly
+ * specified. Should be a power of two. This allows some slop for
+ * the data segment to grow underneath the first mapped segment.
+ */
+#define MMSEG 0x200000
+
+/*
+ * The size of the clock loop.
+ */
+#define LOOPPAGES (maxfree - firstfree)
+
+/*
+ * The time for a process to be blocked before being very swappable.
+ * This is a number of seconds which the system takes as being a non-trivial
+ * amount of real time. You probably shouldn't change this;
+ * it is used in subtle ways (fractions and multiples of it are, that is, like
+ * half of a ``long time'', almost a long time, etc.)
+ * It is related to human patience and other factors which don't really
+ * change over time.
+ */
+#define MAXSLP 20
+
+/*
+ * A swapped in process is given a small amount of core without being bothered
+ * by the page replacement algorithm. Basically this says that if you are
+ * swapped in you deserve some resources. We protect the last SAFERSS
+ * pages against paging and will just swap you out rather than paging you.
+ * Note that each process has at least UPAGES+CLSIZE pages which are not
+ * paged anyways (this is currently 8+2=10 pages or 5k bytes), so this
+ * number just means a swapped in process is given around 25k bytes.
+ * Just for fun: current memory prices are 4600$ a megabyte on VAX (4/22/81),
+ * so we loan each swapped in process memory worth 100$, or just admit
+ * that we don't consider it worthwhile and swap it out to disk which costs
+ * $30/mb or about $0.75.
+ */
+#define SAFERSS 4 /* nominal ``small'' resident set size
+ protected against replacement */
+
+/*
+ * DISKRPM is used to estimate the number of paging i/o operations
+ * which one can expect from a single disk controller.
+ */
+#define DISKRPM 60
+
+/*
+ * Klustering constants. Klustering is the gathering
+ * of pages together for pagein/pageout, while clustering
+ * is the treatment of hardware page size as though it were
+ * larger than it really is.
+ *
+ * KLMAX gives maximum cluster size in CLSIZE page (cluster-page)
+ * units. Note that ctod(KLMAX*CLSIZE) must be <= DMMIN in dmap.h.
+ * ctob(KLMAX) should also be less than MAXPHYS (in vm_swp.c)
+ * unless you like "big push" panics.
+ */
+
+#define KLMAX (4/CLSIZE)
+#define KLSEQL (2/CLSIZE) /* in klust if vadvise(VA_SEQL) */
+#define KLIN (4/CLSIZE) /* default data/stack in klust */
+#define KLTXT (4/CLSIZE) /* default text in klust */
+#define KLOUT (4/CLSIZE)
+
+/*
+ * KLSDIST is the advance or retard of the fifo reclaim for sequential
+ * processes data space.
+ */
+#define KLSDIST 3 /* klusters advance/retard for seq. fifo */
+
+/*
+ * Paging thresholds (see vm_sched.c).
+ * Strategy of 1/19/85:
+ * lotsfree is 512k bytes, but at most 1/4 of memory
+ * desfree is 200k bytes, but at most 1/8 of memory
+ */
+#define LOTSFREE (512 * 1024)
+#define LOTSFREEFRACT 4
+#define DESFREE (200 * 1024)
+#define DESFREEFRACT 8
+
+/*
+ * There are two clock hands, initially separated by HANDSPREAD bytes
+ * (but at most all of user memory). The amount of time to reclaim
+ * a page once the pageout process examines it increases with this
+ * distance and decreases as the scan rate rises.
+ */
+#define HANDSPREAD (2 * 1024 * 1024)
+
+/*
+ * The number of times per second to recompute the desired paging rate
+ * and poke the pagedaemon.
+ */
+#define RATETOSCHEDPAGING 4
+
+/*
+ * Believed threshold (in megabytes) for which interleaved
+ * swapping area is desirable.
+ */
+#define LOTSOFMEM 2
+
+/*
+ * Mach derived constants
+ */
+
+/* user/kernel map constants */
+#define VM_MIN_ADDRESS ((vm_offset_t)0)
+#define VM_MAXUSER_ADDRESS ((vm_offset_t)0xFFF00000)
+#define VM_MAX_ADDRESS ((vm_offset_t)0xFFF00000)
+#define VM_MIN_KERNEL_ADDRESS ((vm_offset_t)0)
+#define VM_MAX_KERNEL_ADDRESS ((vm_offset_t)0xFFFFF000)
+
+/* virtual sizes (bytes) for various kernel submaps */
+#define VM_MBUF_SIZE (NMBCLUSTERS*MCLBYTES)
+#define VM_KMEM_SIZE (NKMEMCLUSTERS*CLBYTES)
+#define VM_PHYS_SIZE (USRIOSIZE*CLBYTES)
+
+/* # of kernel PT pages (initial only, can grow dynamically) */
+#define VM_KERNEL_PT_PAGES ((vm_size_t)2) /* XXX: SYSPTSIZE */
+
+/* pcb base */
+#define pcbb(p) ((u_int)(p)->p_addr)
diff --git a/sys/arch/mvme68k/mvme68k/autoconf.c b/sys/arch/mvme68k/mvme68k/autoconf.c
new file mode 100644
index 00000000000..02c0758dbc6
--- /dev/null
+++ b/sys/arch/mvme68k/mvme68k/autoconf.c
@@ -0,0 +1,251 @@
+/* $NetBSD: autoconf.c,v 1.1.1.1 1995/07/25 23:11:55 chuck Exp $ */
+
+/*
+ * Copyright (c) 1988 University of Utah.
+ * Copyright (c) 1982, 1986, 1990, 1993
+ * 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.36 92/12/20$
+ *
+ * @(#)autoconf.c 8.2 (Berkeley) 1/12/94
+ */
+
+/*
+ * Setup the system to run on the current machine.
+ *
+ * Configure() is called at boot time. Available
+ * devices are determined (from possibilities mentioned in ioconf.c),
+ * and the drivers are initialized.
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/map.h>
+#include <sys/buf.h>
+#include <sys/dkstat.h>
+#include <sys/conf.h>
+#include <sys/dmap.h>
+#include <sys/reboot.h>
+#include <sys/device.h>
+
+#include <machine/vmparam.h>
+#include <machine/cpu.h>
+#include <machine/pte.h>
+#include <mvme68k/mvme68k/isr.h>
+
+/*
+ * The following several variables are related to
+ * the configuration process, and are used in initializing
+ * the machine.
+ */
+int cold; /* if 1, still working on cold-start */
+int dkn; /* number of iostat dk numbers assigned so far */
+int cpuspeed = MHZ_16; /* relative cpu speed */
+struct isr isrqueue[NISR];
+
+void mainbus_attach __P((struct device *, struct device *, void *));
+int mainbus_match __P((struct device *, void *, void *));
+
+struct mainbus_softc {
+ struct device sc_dev;
+};
+
+struct cfdriver mainbuscd = {
+ NULL, "mainbus", mainbus_match, mainbus_attach,
+ DV_DULL, sizeof(struct mainbus_softc), 0
+};
+
+int
+mainbus_match(parent, cf, args)
+ struct device *parent;
+ void *cf;
+ void *args;
+{
+ return (1);
+}
+
+void
+mainbus_attach(parent, self, args)
+ struct device *parent, *self;
+ void *args;
+{
+ printf("\n");
+
+ while (config_found(self, NULL, NULL))
+ ;
+}
+/*
+ * Determine mass storage and memory configuration for a machine.
+ */
+configure()
+{
+ init_sir();
+ isrinit();
+
+ if (!config_rootfound("mainbus", NULL))
+ panic("autoconfig failed, no root");
+
+#if GENERIC
+ if ((boothowto & RB_ASKNAME) == 0)
+ setroot();
+ setconf();
+#else
+ setroot();
+#endif
+ swapconf();
+ cold = 0;
+}
+
+isrinit()
+{
+ register int i;
+
+ for (i = 0; i < NISR; i++)
+ isrqueue[i].isr_forw = isrqueue[i].isr_back = &isrqueue[i];
+}
+
+void
+isrlink(isr)
+ register struct isr *isr;
+{
+ int i = ISRIPL(isr->isr_ipl);
+
+ if (i < 0 || i >= NISR) {
+ printf("bad IPL %d\n", i);
+ panic("configure");
+ }
+ insque(isr, isrqueue[i].isr_back);
+}
+
+/*
+ * Configure swap space and related parameters.
+ */
+swapconf()
+{
+ register struct swdevt *swp;
+ register int nblks;
+
+ for (swp = swdevt; swp->sw_dev != NODEV; swp++)
+ if (bdevsw[major(swp->sw_dev)].d_psize) {
+ nblks =
+ (*bdevsw[major(swp->sw_dev)].d_psize)(swp->sw_dev);
+ if (nblks != -1 &&
+ (swp->sw_nblks == 0 || swp->sw_nblks > nblks))
+ swp->sw_nblks = nblks;
+ }
+ dumpconf();
+}
+
+#define DOSWAP /* Change swdevt and dumpdev too */
+u_long bootdev; /* should be dev_t, but not until 32 bits */
+
+static char devname[][2] = {
+ 0,0, /* 0 = xx */
+ 's','d', /* 1 = sd */
+ 'w','d', /* 2 = wd */
+ 0,0, /* 3 = sw */
+ 'i','d', /* 4 = id */
+};
+
+#define PARTITIONMASK 0x7
+#define PARTITIONSHIFT 3
+
+/*
+ * Attempt to find the device from which we were booted.
+ * If we can do so, and not instructed not to do so,
+ * change rootdev to correspond to the load device.
+ */
+setroot()
+{
+ register struct hp_ctlr *hc;
+ register struct hp_device *hd;
+ int majdev, mindev, unit, part, controller, adaptor;
+ dev_t temp, orootdev;
+ struct swdevt *swp;
+
+ if (boothowto & RB_DFLTROOT ||
+ (bootdev & B_MAGICMASK) != (u_long)B_DEVMAGIC)
+ return;
+ majdev = (bootdev >> B_TYPESHIFT) & B_TYPEMASK;
+ if (majdev > sizeof(devname) / sizeof(devname[0]))
+ return;
+ adaptor = (bootdev >> B_ADAPTORSHIFT) & B_ADAPTORMASK;
+ part = (bootdev >> B_PARTITIONSHIFT) & B_PARTITIONMASK;
+ unit = (bootdev >> B_UNITSHIFT) & B_UNITMASK;
+ /*
+ * First, find the controller type which supports this device.
+ * Next, find the controller of that type corresponding to
+ * the adaptor number.
+ * Finally, find the device in question attached to that controller.
+ */
+ /*
+ * Form a new rootdev
+ */
+ mindev = (unit << PARTITIONSHIFT) + part;
+ orootdev = rootdev;
+ rootdev = makedev(majdev, mindev);
+ /*
+ * If the original rootdev is the same as the one
+ * just calculated, don't need to adjust the swap configuration.
+ */
+ if (rootdev == orootdev)
+ return;
+
+ printf("Changing root device to %c%c%d%c\n",
+ devname[majdev][0], devname[majdev][1],
+ mindev >> PARTITIONSHIFT, part + 'a');
+
+#ifdef DOSWAP
+ mindev &= ~PARTITIONMASK;
+ for (swp = swdevt; swp->sw_dev != NODEV; swp++) {
+ if (majdev == major(swp->sw_dev) &&
+ mindev == (minor(swp->sw_dev) & ~PARTITIONMASK)) {
+ temp = swdevt[0].sw_dev;
+ swdevt[0].sw_dev = swp->sw_dev;
+ swp->sw_dev = temp;
+ break;
+ }
+ }
+ if (swp->sw_dev == NODEV)
+ return;
+
+ /*
+ * If dumpdev was the same as the old primary swap
+ * device, move it to the new primary swap device.
+ */
+ if (temp == dumpdev)
+ dumpdev = swdevt[0].sw_dev;
+#endif
+}
diff --git a/sys/arch/mvme68k/mvme68k/clock.c b/sys/arch/mvme68k/mvme68k/clock.c
new file mode 100644
index 00000000000..2279e6a066a
--- /dev/null
+++ b/sys/arch/mvme68k/mvme68k/clock.c
@@ -0,0 +1,367 @@
+/* $NetBSD: clock.c,v 1.1.1.1 1995/07/25 23:11:56 chuck Exp $ */
+
+/*
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This software was developed by the Computer Systems Engineering group
+ * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
+ * contributed to Berkeley.
+ *
+ * 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, Lawrence Berkeley Laboratory.
+ *
+ * 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.
+ *
+ * @(#)clock.c 8.1 (Berkeley) 6/11/93
+ */
+
+
+
+#include <sys/param.h>
+#include <sys/kernel.h>
+#include <sys/device.h>
+#include <mvme68k/mvme68k/clockreg.h>
+#include <mvme68k/dev/iio.h>
+#include <mvme68k/dev/pccreg.h>
+
+#include <machine/psl.h>
+#include <machine/cpu.h>
+
+#if defined(GPROF)
+#include <sys/gmon.h>
+#endif
+
+struct clocksc {
+ struct device sc_dev;
+ struct clockreg *sc_creg;
+};
+
+struct clockreg *RTCbase = NULL;
+u_char clock_lvl;
+
+/*
+ * autoconf
+ */
+
+void clockattach __P((struct device *, struct device *, void *));
+int clockmatch __P((struct device *, void *, void *));
+
+struct cfdriver clockcd = {
+ NULL, "clock", clockmatch, clockattach,
+ DV_DULL, sizeof(struct clocksc), 0
+};
+
+void clockintr __P((void *));
+
+int
+clockmatch(parent, vcf, args)
+ struct device *parent;
+ void *vcf, *args;
+{
+ struct cfdata *cf = vcf;
+
+ return RTCbase == NULL && !badbaddr((caddr_t) IIO_CFLOC_ADDR(cf));
+}
+
+void
+clockattach(parent, self, args)
+ struct device *parent, *self;
+ void *args;
+{
+ iio_print(self->dv_cfdata);
+
+ if (RTCbase)
+ panic("too many clocks configured");
+
+ RTCbase = (struct clockreg *) IIO_CFLOC_ADDR(self->dv_cfdata);
+ clock_lvl = IIO_CFLOC_LEVEL(self->dv_cfdata);
+ if (clock_lvl != CLOCK_LEVEL)
+ panic("wrong interrupt level for clock");
+ pccintr_establish(PCCV_TIMER1, clockintr, clock_lvl, NULL);
+ clock_lvl = clock_lvl | PCC_IENABLE | PCC_TIMERACK;
+
+ printf("\n");
+}
+
+/*
+ * clockintr: ack intr and call hardclock
+ */
+void
+clockintr(arg)
+ void *arg;
+{
+ sys_pcc->t1_int = clock_lvl;
+ hardclock(arg);
+}
+
+/*
+ * Set up real-time clock; we don't have a statistics clock at
+ * present.
+ */
+cpu_initclocks()
+{
+ register struct clockreg *rtc = RTCbase;
+
+ if (rtc == NULL)
+ panic("clock not configured");
+ if (hz != 100) {
+ printf("%d Hz clock not available; using 100 Hz\n", hz);
+ hz = 100;
+ }
+ sys_pcc->t1_pload = PCC_TIMER100HZ;
+ sys_pcc->t1_cr = PCC_TIMERCLEAR;
+ sys_pcc->t1_cr = PCC_TIMERSTART;
+ sys_pcc->t1_int = clock_lvl;
+
+ stathz = 0;
+}
+
+void
+setstatclockrate(newhz)
+ int newhz;
+{
+}
+
+void
+statintr(fp)
+ struct clockframe *fp;
+{
+}
+
+/*
+ * Return the best possible estimate of the time in the timeval
+ * to which tvp points. We do this by returning the current time
+ * plus the amount of time since the last clock interrupt (clock.c:clkread).
+ *
+ * Check that this time is no less than any previously-reported time,
+ * which could happen around the time of a clock adjustment. Just for fun,
+ * we guarantee that the time will be greater than the value obtained by a
+ * previous call.
+ */
+
+void microtime(tvp)
+ register struct timeval *tvp;
+{
+ int s = splhigh();
+ static struct timeval lasttime;
+
+ *tvp = time;
+ tvp->tv_usec;
+ while (tvp->tv_usec > 1000000) {
+ tvp->tv_sec++;
+ tvp->tv_usec -= 1000000;
+ }
+ if (tvp->tv_sec == lasttime.tv_sec &&
+ tvp->tv_usec <= lasttime.tv_usec &&
+ (tvp->tv_usec = lasttime.tv_usec + 1) > 1000000) {
+ tvp->tv_sec++;
+ tvp->tv_usec -= 1000000;
+ }
+ lasttime = *tvp;
+ splx(s);
+}
+
+/*
+ * BCD to decimal and decimal to BCD.
+ */
+#define FROMBCD(x) (((x) >> 4) * 10 + ((x) & 0xf))
+#define TOBCD(x) (((x) / 10 * 16) + ((x) % 10))
+
+#define SECDAY (24 * 60 * 60)
+#define SECYR (SECDAY * 365)
+#define LEAPYEAR(y) (((y) & 3) == 0)
+
+/*
+ * This code is defunct after 2068.
+ * Will Unix still be here then??
+ */
+const short dayyr[12] =
+ { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 };
+
+static u_long chiptotime(sec, min, hour, day, mon, year)
+ register int sec, min, hour, day, mon, year;
+{
+ register int days, yr;
+
+ sec = FROMBCD(sec);
+ min = FROMBCD(min);
+ hour = FROMBCD(hour);
+ day = FROMBCD(day);
+ mon = FROMBCD(mon);
+ year = FROMBCD(year) + YEAR0;
+
+ /* simple sanity checks */
+ if (year < 70 || mon < 1 || mon > 12 || day < 1 || day > 31)
+ return (0);
+ days = 0;
+ for (yr = 70; yr < year; yr++)
+ days += LEAPYEAR(yr) ? 366 : 365;
+ days += dayyr[mon - 1] + day - 1;
+ if (LEAPYEAR(yr) && mon > 2)
+ days++;
+ /* now have days since Jan 1, 1970; the rest is easy... */
+ return (days * SECDAY + hour * 3600 + min * 60 + sec);
+}
+
+struct chiptime {
+ int sec;
+ int min;
+ int hour;
+ int wday;
+ int day;
+ int mon;
+ int year;
+};
+
+timetochip(c)
+ register struct chiptime *c;
+{
+ register int t, t2, t3, now = time.tv_sec;
+
+ /* compute the year */
+ t2 = now / SECDAY;
+ t3 = (t2 + 2) % 7; /* day of week */
+ c->wday = TOBCD(t3 + 1);
+
+ t = 69;
+ while (t2 >= 0) { /* whittle off years */
+ t3 = t2;
+ t++;
+ t2 -= LEAPYEAR(t) ? 366 : 365;
+ }
+ c->year = t;
+
+ /* t3 = month + day; separate */
+ t = LEAPYEAR(t);
+ for (t2 = 1; t2 < 12; t2++)
+ if (t3 < dayyr[t2] + (t && t2 > 1))
+ break;
+
+ /* t2 is month */
+ c->mon = t2;
+ c->day = t3 - dayyr[t2 - 1] + 1;
+ if (t && t2 > 2)
+ c->day--;
+
+ /* the rest is easy */
+ t = now % SECDAY;
+ c->hour = t / 3600;
+ t %= 3600;
+ c->min = t / 60;
+ c->sec = t % 60;
+
+ c->sec = TOBCD(c->sec);
+ c->min = TOBCD(c->min);
+ c->hour = TOBCD(c->hour);
+ c->day = TOBCD(c->day);
+ c->mon = TOBCD(c->mon);
+ c->year = TOBCD(c->year - YEAR0);
+}
+
+
+/*
+ * Set up the system's time, given a `reasonable' time value.
+ */
+inittodr(base)
+ time_t base;
+{
+ register struct clockreg *cl = RTCbase;
+ int sec, min, hour, day, mon, year;
+ int badbase = 0, waszero = base == 0;
+
+ if (base < 5 * SECYR) {
+ /*
+ * If base is 0, assume filesystem time is just unknown
+ * in stead of preposterous. Don't bark.
+ */
+ if (base != 0)
+ printf("WARNING: preposterous time in file system\n");
+ /* not going to use it anyway, if the chip is readable */
+ base = 21*SECYR + 186*SECDAY + SECDAY/2;
+ badbase = 1;
+ }
+ cl->cl_csr |= CLK_READ; /* enable read (stop time) */
+ sec = cl->cl_sec;
+ min = cl->cl_min;
+ hour = cl->cl_hour;
+ day = cl->cl_mday;
+ mon = cl->cl_month;
+ year = cl->cl_year;
+ cl->cl_csr &= ~CLK_READ; /* time wears on */
+ if ((time.tv_sec = chiptotime(sec, min, hour, day, mon, year)) == 0) {
+ printf("WARNING: bad date in battery clock");
+ /*
+ * Believe the time in the file system for lack of
+ * anything better, resetting the clock.
+ */
+ time.tv_sec = base;
+ if (!badbase)
+ resettodr();
+ } else {
+ int deltat = time.tv_sec - base;
+
+ if (deltat < 0)
+ deltat = -deltat;
+ if (waszero || deltat < 2 * SECDAY)
+ return;
+ printf("WARNING: clock %s %d days",
+ time.tv_sec < base ? "lost" : "gained", deltat / SECDAY);
+ }
+ printf(" -- CHECK AND RESET THE DATE!\n");
+}
+
+
+/*
+ * Reset the clock based on the current time.
+ * Used when the current clock is preposterous, when the time is changed,
+ * and when rebooting. Do nothing if the time is not yet known, e.g.,
+ * when crashing during autoconfig.
+ */
+resettodr()
+{
+ register struct clockreg *cl;
+ struct chiptime c;
+
+ if (!time.tv_sec || (cl = RTCbase) == NULL)
+ return;
+ timetochip(&c);
+ cl->cl_csr |= CLK_WRITE; /* enable write */
+ cl->cl_sec = c.sec;
+ cl->cl_min = c.min;
+ cl->cl_hour = c.hour;
+ cl->cl_wday = c.wday;
+ cl->cl_mday = c.day;
+ cl->cl_month = c.mon;
+ cl->cl_year = c.year;
+ cl->cl_csr &= ~CLK_WRITE; /* load them up */
+}
+
diff --git a/sys/arch/mvme68k/mvme68k/clockreg.h b/sys/arch/mvme68k/mvme68k/clockreg.h
new file mode 100644
index 00000000000..19998f8265c
--- /dev/null
+++ b/sys/arch/mvme68k/mvme68k/clockreg.h
@@ -0,0 +1,76 @@
+/* $NetBSD: clockreg.h,v 1.1.1.1 1995/07/25 23:11:56 chuck Exp $ */
+
+/*
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This software was developed by the Computer Systems Engineering group
+ * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
+ * contributed to Berkeley.
+ *
+ * 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, Lawrence Berkeley Laboratory.
+ *
+ * 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.
+ *
+ * @(#)clockreg.h 8.1 (Berkeley) 6/11/93
+ */
+
+/*
+ * Mostek MK48T02 clock.
+ */
+struct clockreg {
+ volatile u_char cl_csr; /* control register */
+ volatile u_char cl_sec; /* seconds (0..59; BCD) */
+ volatile u_char cl_min; /* minutes (0..59; BCD) */
+ volatile u_char cl_hour; /* hour (0..23; BCD) */
+ volatile u_char cl_wday; /* weekday (1..7) */
+ volatile u_char cl_mday; /* day in month (1..31; BCD) */
+ volatile u_char cl_month; /* month (1..12; BCD) */
+ volatile u_char cl_year; /* year (0..99; BCD) */
+};
+
+/* bits in cl_csr */
+#define CLK_WRITE 0x80 /* want to write */
+#define CLK_READ 0x40 /* want to read (freeze clock) */
+
+/*
+ * Sun chose the year `68' as their base count, so that
+ * cl_year==0 means 1968.
+ */
+#define YEAR0 68
+
+
+/*
+ * interrupt level for clock
+ */
+
+#define CLOCK_LEVEL 5
diff --git a/sys/arch/mvme68k/mvme68k/conf.c b/sys/arch/mvme68k/mvme68k/conf.c
new file mode 100644
index 00000000000..513db413e64
--- /dev/null
+++ b/sys/arch/mvme68k/mvme68k/conf.c
@@ -0,0 +1,284 @@
+/* $NetBSD: conf.c,v 1.2 1995/08/17 17:40:54 thorpej Exp $ */
+
+/*-
+ * Copyright (c) 1991 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)conf.c 7.9 (Berkeley) 5/28/91
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/buf.h>
+#include <sys/ioctl.h>
+#include <sys/tty.h>
+#include <sys/conf.h>
+#include <sys/vnode.h>
+
+int ttselect __P((dev_t, int, struct proc *));
+
+#ifdef LKM
+int lkmenodev();
+#else
+#define lkmenodev enodev
+#endif
+
+#include "vnd.h"
+bdev_decl(vnd);
+bdev_decl(sw);
+#include "sd.h"
+bdev_decl(sd);
+#include "cd.h"
+bdev_decl(cd);
+#include "st.h"
+bdev_decl(st);
+#include "ccd.h"
+bdev_decl(ccd);
+
+struct bdevsw bdevsw[] =
+{
+ bdev_notdef(), /* 0 */
+ bdev_notdef(), /* 1 */
+ bdev_notdef(), /* 2 */
+ bdev_swap_init(1,sw), /* 3: swap pseudo-device */
+ bdev_disk_init(NSD,sd), /* 4: SCSI disk */
+ bdev_tape_init(NST,st), /* 5: SCSI tape */
+ bdev_disk_init(NVND,vnd), /* 6: vnode disk driver */
+ bdev_disk_init(NCD,cd), /* 7: SCSI CD-ROM */
+ bdev_notdef(), /* 8 */
+ bdev_lkm_dummy(), /* 9 */
+ bdev_lkm_dummy(), /* 10 */
+ bdev_lkm_dummy(), /* 11 */
+ bdev_lkm_dummy(), /* 12 */
+ bdev_lkm_dummy(), /* 13 */
+ bdev_lkm_dummy(), /* 14 */
+ bdev_disk_init(NCCD,ccd), /* 15: concatenated disk driver */
+};
+
+int nblkdev = sizeof (bdevsw) / sizeof (bdevsw[0]);
+
+cdev_decl(cn);
+cdev_decl(ctty);
+#define mmread mmrw
+#define mmwrite mmrw
+cdev_decl(mm);
+cdev_decl(sw);
+
+#include "pty.h"
+#define ptstty ptytty
+#define ptsioctl ptyioctl
+cdev_decl(pts);
+#define ptctty ptytty
+#define ptcioctl ptyioctl
+cdev_decl(ptc);
+
+cdev_decl(log);
+cdev_decl(fd);
+
+#include "zs.h"
+cdev_decl(zs);
+
+cdev_decl(sd);
+cdev_decl(cd);
+cdev_decl(st);
+cdev_decl(vnd);
+cdev_decl(ccd);
+
+#include "bpfilter.h"
+cdev_decl(bpf);
+
+#include "tun.h"
+cdev_decl(tun);
+#ifdef LKM
+#define NLKM 1
+#else
+#define NLKM 0
+#endif
+cdev_decl(lkm);
+
+struct cdevsw cdevsw[] =
+{
+ cdev_cn_init(1,cn), /* 0: virtual console */
+ cdev_ctty_init(1,ctty), /* 1: controlling terminal */
+ cdev_mm_init(1,mm), /* 2: /dev/{null,mem,kmem,...} */
+ cdev_swap_init(1,sw), /* 3: /dev/drum (swap pseudo-device) */
+ cdev_tty_init(NPTY,pts), /* 4: pseudo-tty slave */
+ cdev_ptc_init(NPTY,ptc), /* 5: pseudo-tty master */
+ cdev_log_init(1,log), /* 6: /dev/klog */
+ cdev_notdef(), /* 7 */
+ cdev_disk_init(NSD,sd), /* 8: SCSI disk */
+ cdev_disk_init(NCD,cd), /* 9: SCSI CD-ROM */
+ cdev_notdef(), /* 10 */
+ cdev_notdef(), /* 11: parallel interface */
+ cdev_tty_init(NZS,zs), /* 12: SCC serial ports */
+ cdev_notdef(), /* 13 */
+ cdev_notdef(), /* 14 */
+ cdev_notdef(), /* 15 */
+ cdev_notdef(), /* 16 */
+ cdev_disk_init(NCCD,ccd), /* 17: concatenated disk driver */
+ cdev_notdef(), /* 18 */
+ cdev_disk_init(NVND,vnd), /* 19: vnode disk */
+ cdev_tape_init(NST,st), /* 20: SCSI tape */
+ cdev_fd_init(1,fd), /* 21: file descriptor pseudo-dev */
+ cdev_bpftun_init(NBPFILTER,bpf),/* 22: berkeley packet filter */
+ cdev_bpftun_init(NTUN,tun), /* 23: network tunnel */
+ cdev_lkm_init(NLKM,lkm), /* 24: loadable module driver */
+ cdev_lkm_dummy(), /* 25 */
+ cdev_lkm_dummy(), /* 26 */
+ cdev_lkm_dummy(), /* 27 */
+ cdev_lkm_dummy(), /* 28 */
+ cdev_lkm_dummy(), /* 29 */
+ cdev_lkm_dummy(), /* 30 */
+};
+
+int nchrdev = sizeof (cdevsw) / sizeof (cdevsw[0]);
+
+int mem_no = 2; /* major device number of memory special file */
+
+/*
+ * Swapdev is a fake device implemented
+ * in sw.c used only internally to get to swstrategy.
+ * It cannot be provided to the users, because the
+ * swstrategy routine munches the b_dev and b_blkno entries
+ * before calling the appropriate driver. This would horribly
+ * confuse, e.g. the hashing routines. Instead, /dev/drum is
+ * provided as a character (raw) device.
+ */
+dev_t swapdev = makedev(3, 0);
+
+/*
+ * Returns true if dev is /dev/mem or /dev/kmem.
+ */
+iskmemdev(dev)
+ dev_t dev;
+{
+
+ return (major(dev) == mem_no && minor(dev) < 2);
+}
+
+/*
+ * Returns true if dev is /dev/zero.
+ */
+iszerodev(dev)
+ dev_t dev;
+{
+
+ return (major(dev) == mem_no && minor(dev) == 12);
+}
+
+/*
+ * Returns true if dev is a disk device.
+ */
+isdisk(dev, type)
+ dev_t dev;
+ int type;
+{
+
+ /* XXXX This needs to be dynamic for LKMs. */
+ switch (major(dev)) {
+ case 1:
+ case 2:
+ case 4:
+ case 6:
+ case 15:
+ return (type == VBLK);
+ case 8:
+ case 9:
+ case 10:
+ case 17:
+ case 19:
+ return (type == VCHR);
+ default:
+ return (0);
+ }
+}
+
+static int chrtoblktbl[] = {
+ /* XXXX This needs to be dynamic for LKMs. */
+ /*VCHR*/ /*VBLK*/
+ /* 0 */ NODEV,
+ /* 1 */ NODEV,
+ /* 2 */ NODEV,
+ /* 3 */ NODEV,
+ /* 4 */ NODEV,
+ /* 5 */ NODEV,
+ /* 6 */ NODEV,
+ /* 7 */ NODEV,
+ /* 8 */ 4,
+ /* 9 */ 7,
+ /* 10 */ NODEV,
+ /* 11 */ NODEV,
+ /* 12 */ NODEV,
+ /* 13 */ NODEV,
+ /* 14 */ NODEV,
+ /* 15 */ NODEV,
+ /* 16 */ NODEV,
+ /* 17 */ 15,
+ /* 18 */ NODEV,
+ /* 19 */ 6,
+ /* 20 */ NODEV,
+ /* 21 */ NODEV,
+ /* 22 */ NODEV,
+};
+
+/*
+ * Convert a character device number to a block device number.
+ */
+chrtoblk(dev)
+ dev_t dev;
+{
+ int blkmaj;
+
+ if (major(dev) >= nchrdev)
+ return (NODEV);
+ blkmaj = chrtoblktbl[major(dev)];
+ if (blkmaj == NODEV)
+ return (NODEV);
+ return (makedev(blkmaj, minor(dev)));
+}
+
+/*
+ * This entire table could be autoconfig()ed but that would mean that
+ * the kernel's idea of the console would be out of sync with that of
+ * the standalone boot. I think it best that they both use the same
+ * known algorithm unless we see a pressing need otherwise.
+ */
+#include <dev/cons.h>
+
+#define zscnpollc nullcnpollc
+cons_decl(zs);
+
+struct consdev constab[] = {
+#if NZS > 0
+ cons_init(zs),
+#endif
+ { 0 },
+};
diff --git a/sys/arch/mvme68k/mvme68k/disksubr.c b/sys/arch/mvme68k/mvme68k/disksubr.c
new file mode 100644
index 00000000000..81a995068b2
--- /dev/null
+++ b/sys/arch/mvme68k/mvme68k/disksubr.c
@@ -0,0 +1,246 @@
+/* $NetBSD: disksubr.c,v 1.2 1995/08/10 19:36:41 chuck Exp $ */
+
+/*
+ * Copyright (c) 1982, 1986, 1988, 1993
+ * The Regents of the University of California. All rights reserved.
+ * (c) UNIX System Laboratories, Inc.
+ * All or some portions of this file are derived from material licensed
+ * to the University of California by American Telephone and Telegraph
+ * Co. or Unix System Laboratories, Inc. and are reproduced herein with
+ * the permission of UNIX System Laboratories, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)ufs_disksubr.c 8.5 (Berkeley) 1/21/94
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/buf.h>
+#include <sys/disklabel.h>
+#include <sys/syslog.h>
+
+#define b_cylinder b_resid
+
+/*
+ * Attempt to read a disk label from a device using the indicated stategy
+ * routine. The label must be partly set up before this: secpercyl and
+ * anything required in the strategy routine (e.g., sector size) must be
+ * filled in before calling us. Returns null on success and an error
+ * string on failure.
+ */
+char *
+readdisklabel(dev, strat, lp, osdep)
+ dev_t dev;
+ void (*strat)();
+ register struct disklabel *lp;
+ struct cpu_disklabel *osdep;
+{
+ register struct buf *bp;
+ struct disklabel *dlp;
+ char *msg = NULL;
+
+ if (lp->d_secperunit == 0)
+ lp->d_secperunit = 0x1fffffff;
+ lp->d_npartitions = 1;
+ if (lp->d_partitions[0].p_size == 0)
+ lp->d_partitions[0].p_size = 0x1fffffff;
+ lp->d_partitions[0].p_offset = 0;
+
+ bp = geteblk((int)lp->d_secsize);
+ bp->b_dev = dev;
+ bp->b_blkno = LABELSECTOR;
+ bp->b_bcount = lp->d_secsize;
+ bp->b_flags = B_BUSY | B_READ;
+ bp->b_cylinder = LABELSECTOR / lp->d_secpercyl;
+ (*strat)(bp);
+ if (biowait(bp))
+ msg = "I/O error";
+ else for (dlp = (struct disklabel *)bp->b_data;
+ dlp <= (struct disklabel *)((char *)bp->b_data +
+ DEV_BSIZE - sizeof(*dlp));
+ dlp = (struct disklabel *)((char *)dlp + sizeof(long))) {
+ if (dlp->d_magic != DISKMAGIC || dlp->d_magic2 != DISKMAGIC) {
+ if (msg == NULL)
+ msg = "no disk label";
+ } else if (dlp->d_npartitions > MAXPARTITIONS ||
+ dkcksum(dlp) != 0)
+ msg = "disk label corrupted";
+ else {
+ *lp = *dlp;
+ msg = NULL;
+ break;
+ }
+ }
+ bp->b_flags = B_INVAL | B_AGE;
+ brelse(bp);
+ return (msg);
+}
+
+/*
+ * Check new disk label for sensibility before setting it.
+ */
+int
+setdisklabel(olp, nlp, openmask, osdep)
+ register struct disklabel *olp, *nlp;
+ u_long openmask;
+ struct cpu_disklabel *osdep;
+{
+ register i;
+ register struct partition *opp, *npp;
+
+ if (nlp->d_magic != DISKMAGIC || nlp->d_magic2 != DISKMAGIC ||
+ dkcksum(nlp) != 0)
+ return (EINVAL);
+ while ((i = ffs((long)openmask)) != 0) {
+ i--;
+ openmask &= ~(1 << i);
+ if (nlp->d_npartitions <= i)
+ return (EBUSY);
+ opp = &olp->d_partitions[i];
+ npp = &nlp->d_partitions[i];
+ if (npp->p_offset != opp->p_offset || npp->p_size < opp->p_size)
+ return (EBUSY);
+ /*
+ * Copy internally-set partition information
+ * if new label doesn't include it. XXX
+ */
+ if (npp->p_fstype == FS_UNUSED && opp->p_fstype != FS_UNUSED) {
+ npp->p_fstype = opp->p_fstype;
+ npp->p_fsize = opp->p_fsize;
+ npp->p_frag = opp->p_frag;
+ npp->p_cpg = opp->p_cpg;
+ }
+ }
+ nlp->d_checksum = 0;
+ nlp->d_checksum = dkcksum(nlp);
+ *olp = *nlp;
+ return (0);
+}
+
+/* encoding of disk minor numbers, should be elsewhere... */
+#define dkunit(dev) (minor(dev) >> 3)
+#define dkpart(dev) (minor(dev) & 07)
+#define dkminor(unit, part) (((unit) << 3) | (part))
+
+/*
+ * Write disk label back to device after modification.
+ */
+int
+writedisklabel(dev, strat, lp, osdep)
+ dev_t dev;
+ void (*strat)();
+ register struct disklabel *lp;
+ struct cpu_disklabel *osdep;
+{
+ struct buf *bp;
+ struct disklabel *dlp;
+ int labelpart;
+ int error = 0;
+
+ labelpart = dkpart(dev);
+ if (lp->d_partitions[labelpart].p_offset != 0) {
+ if (lp->d_partitions[0].p_offset != 0)
+ return (EXDEV); /* not quite right */
+ labelpart = 0;
+ }
+ bp = geteblk((int)lp->d_secsize);
+ bp->b_dev = makedev(major(dev), dkminor(dkunit(dev), labelpart));
+ bp->b_blkno = LABELSECTOR;
+ bp->b_bcount = lp->d_secsize;
+ bp->b_flags = B_READ;
+ (*strat)(bp);
+ if (error = biowait(bp))
+ goto done;
+ for (dlp = (struct disklabel *)bp->b_data;
+ dlp <= (struct disklabel *)
+ ((char *)bp->b_data + lp->d_secsize - sizeof(*dlp));
+ dlp = (struct disklabel *)((char *)dlp + sizeof(long))) {
+ if (dlp->d_magic == DISKMAGIC && dlp->d_magic2 == DISKMAGIC &&
+ dkcksum(dlp) == 0) {
+ *dlp = *lp;
+ bp->b_flags = B_WRITE;
+ (*strat)(bp);
+ error = biowait(bp);
+ goto done;
+ }
+ }
+ error = ESRCH;
+done:
+ brelse(bp);
+ return (error);
+}
+
+/*
+ * Determine the size of the transfer, and make sure it is
+ * within the boundaries of the partition. Adjust transfer
+ * if needed, and signal errors or early completion.
+ */
+int
+bounds_check_with_label(bp, lp, wlabel)
+ struct buf *bp;
+ struct disklabel *lp;
+ int wlabel;
+{
+ struct partition *p = &lp->d_partitions[dkpart(bp->b_dev)];
+ int labelsect = lp->d_partitions[0].p_offset;
+ int maxsz = p->p_size;
+ int sz = (bp->b_bcount + DEV_BSIZE - 1) >> DEV_BSHIFT;
+
+ /* Overwriting disk label? */
+ if (bp->b_blkno + p->p_offset <= LABELSECTOR + labelsect &&
+ (bp->b_flags & B_READ) == 0 && !wlabel) {
+ bp->b_error = EROFS;
+ goto bad;
+ }
+
+ /* beyond partition? */
+ if (bp->b_blkno < 0 || bp->b_blkno + sz > maxsz) {
+ if (bp->b_blkno == maxsz) {
+ /* If exactly at end of disk, return EOF. */
+ bp->b_resid = bp->b_bcount;
+ return (0);
+ }
+ /* ...or truncate if part of it fits */
+ sz = maxsz - bp->b_blkno;
+ if (sz <= 0) {
+ bp->b_error = EINVAL;
+ goto bad;
+ }
+ bp->b_bcount = sz << DEV_BSHIFT;
+ }
+
+ /* calculate cylinder for disksort to order transfers with */
+ bp->b_resid = (bp->b_blkno + p->p_offset) / lp->d_secpercyl;
+ return (1);
+
+ bad:
+ bp->b_flags |= B_ERROR;
+ return (-1);
+}
diff --git a/sys/arch/mvme68k/mvme68k/dkbad.c b/sys/arch/mvme68k/mvme68k/dkbad.c
new file mode 100644
index 00000000000..686bc109912
--- /dev/null
+++ b/sys/arch/mvme68k/mvme68k/dkbad.c
@@ -0,0 +1,66 @@
+/* $NetBSD: dkbad.c,v 1.1.1.1 1995/07/25 23:11:57 chuck Exp $ */
+
+/*
+ * Copyright (c) 1982, 1986, 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)dkbad.c 8.2 (Berkeley) 1/12/94
+ */
+
+#ifndef NOBADSECT
+#include <sys/param.h>
+#include <sys/buf.h>
+#include <sys/dkbad.h>
+
+/*
+ * Search the bad sector table looking for
+ * the specified sector. Return index if found.
+ * Return -1 if not found.
+ */
+
+isbad(bt, cyl, trk, sec)
+ register struct dkbad *bt;
+ int cyl, trk, sec;
+{
+ register int i;
+ register long blk, bblk;
+
+ blk = ((long)cyl << 16) + (trk << 8) + sec;
+ for (i = 0; i < 126; i++) {
+ bblk = ((long)bt->bt_bad[i].bt_cyl << 16) + bt->bt_bad[i].bt_trksec;
+ if (blk == bblk)
+ return (i);
+ if (blk < bblk || bblk < 0)
+ break;
+ }
+ return (-1);
+}
+#endif
diff --git a/sys/arch/mvme68k/mvme68k/genassym.c b/sys/arch/mvme68k/mvme68k/genassym.c
new file mode 100644
index 00000000000..ab87485ae4b
--- /dev/null
+++ b/sys/arch/mvme68k/mvme68k/genassym.c
@@ -0,0 +1,208 @@
+/* $NetBSD: genassym.c,v 1.1.1.1 1995/07/25 23:11:57 chuck Exp $ */
+
+/*
+ * Copyright (c) 1982, 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)genassym.c 8.3 (Berkeley) 1/4/94
+ */
+
+/* XXXX */
+#define _VA_LIST_ _BSD_VA_LIST_
+#define _PTRDIFF_T_ _BSD_PTRDIFF_T_
+
+#define _KERNEL
+
+#include <sys/param.h>
+#include <sys/buf.h>
+#include <sys/map.h>
+#include <sys/proc.h>
+#include <sys/mbuf.h>
+#include <sys/msgbuf.h>
+#include <sys/syscall.h>
+#include <sys/user.h>
+
+#include <machine/cpu.h>
+#include <machine/trap.h>
+#include <machine/psl.h>
+#include <machine/reg.h>
+#include <machine/pte.h>
+#include <mvme68k/mvme68k/clockreg.h>
+#include <vm/vm.h>
+
+#include <errno.h>
+#include <stdio.h>
+#include <stddef.h>
+#include <string.h>
+#include <unistd.h>
+
+extern int errno;
+
+void
+def(what, val)
+ char *what;
+ int val;
+{
+
+ if (printf("#define\t%s\t%d\n", what, val) < 0) {
+ (void)fprintf(stderr, "genassym: printf: %s\n",
+ strerror(errno));
+ exit(1);
+ }
+}
+
+void
+flush()
+{
+
+ if (fflush(stdout) || fsync(fileno(stdout)) < 0) {
+ (void)fprintf(stderr, "genassym: flush stdout: %s\n",
+ strerror(errno));
+ exit(1);
+ }
+}
+
+#define off(what, s, m) def(what, (int)offsetof(s, m))
+
+main()
+{
+ /* general constants */
+ def("UPAGES", UPAGES);
+ def("USPACE", USPACE);
+ def("NBPG", NBPG);
+ def("PGSHIFT", PGSHIFT);
+ def("USRSTACK", USRSTACK);
+
+ /* proc fields and values */
+ off("P_FORW", struct proc, p_forw);
+ off("P_BACK", struct proc, p_back);
+ off("P_VMSPACE", struct proc, p_vmspace);
+ off("P_ADDR", struct proc, p_addr);
+ off("P_PRIORITY", struct proc, p_priority);
+ off("P_STAT", struct proc, p_stat);
+ off("P_WCHAN", struct proc, p_wchan);
+ off("P_FLAG", struct proc, p_flag);
+ off("P_MD_FLAGS", struct proc, p_md.md_flags);
+ off("P_MD_REGS", struct proc, p_md.md_regs);
+
+ def("SSLEEP", SSLEEP);
+ def("SRUN", SRUN);
+
+ /* VM structure fields */
+ off("VM_PMAP", struct vmspace, vm_pmap);
+ off("PM_STCHG", struct pmap, pm_stchanged);
+
+ /* interrupt/fault metering */
+ off("V_SWTCH", struct vmmeter, v_swtch);
+ off("V_INTR", struct vmmeter, v_intr);
+
+ /* trap types (should just include trap.h?) */
+ def("T_BUSERR", T_BUSERR);
+ def("T_ADDRERR", T_ADDRERR);
+ def("T_ILLINST", T_ILLINST);
+ def("T_ZERODIV", T_ZERODIV);
+ def("T_CHKINST", T_CHKINST);
+ def("T_TRAPVINST", T_TRAPVINST);
+ def("T_PRIVINST", T_PRIVINST);
+ def("T_TRACE", T_TRACE);
+ def("T_MMUFLT", T_MMUFLT);
+ def("T_SSIR", T_SSIR);
+ def("T_FMTERR", T_FMTERR);
+ def("T_COPERR", T_COPERR);
+ def("T_FPERR", T_FPERR);
+ def("T_ASTFLT", T_ASTFLT);
+ def("T_TRAP15", T_TRAP15);
+ def("T_FPEMULI", T_FPEMULI);
+ def("T_FPEMULD", T_FPEMULD);
+
+ /* PSL values (should just include psl.h?) */
+ def("PSL_S", PSL_S);
+ def("PSL_IPL7", PSL_IPL7);
+ def("PSL_LOWIPL", PSL_LOWIPL);
+ def("PSL_HIGHIPL", PSL_HIGHIPL);
+ def("PSL_USER", PSL_USER);
+ def("SPL1", PSL_S | PSL_IPL1);
+ def("SPL2", PSL_S | PSL_IPL2);
+ def("SPL3", PSL_S | PSL_IPL3);
+ def("SPL4", PSL_S | PSL_IPL4);
+ def("SPL5", PSL_S | PSL_IPL5);
+ def("SPL6", PSL_S | PSL_IPL6);
+
+ /* magic */
+ def("FC_USERD", FC_USERD);
+ def("INTIOBASE", INTIOBASE);
+ def("IIOMAPSIZE", IIOMAPSIZE);
+ def("EIOMAPSIZE", EIOMAPSIZE);
+ def("CACHE_ON", CACHE_ON);
+ def("CACHE_OFF", CACHE_OFF);
+ def("CACHE_CLR", CACHE_CLR);
+ def("IC_CLEAR", IC_CLEAR);
+ def("DC_CLEAR", DC_CLEAR);
+
+ /* pte/ste bits */
+ def("PG_V", PG_V);
+ def("PG_NV", PG_NV);
+ def("PG_RO", PG_RO);
+ def("PG_RW", PG_RW);
+ def("PG_CI", PG_CI);
+ def("PG_PROT", PG_PROT);
+ def("PG_FRAME", PG_FRAME);
+ def("SG_V", SG_V);
+ def("SG_NV", SG_NV);
+ def("SG_RW", SG_RW);
+ def("SG_FRAME", SG_FRAME);
+ def("SG_ISHIFT", SG_ISHIFT);
+
+ /* pcb fields */
+ off("PCB_PS", struct pcb, pcb_ps);
+ off("PCB_USTP", struct pcb, pcb_ustp);
+ off("PCB_USP", struct pcb, pcb_usp);
+ off("PCB_REGS", struct pcb, pcb_regs);
+ off("PCB_ONFAULT", struct pcb, pcb_onfault);
+ off("PCB_FPCTX", struct pcb, pcb_fpregs);
+ def("SIZEOF_PCB", sizeof(struct pcb));
+
+ /* exception frame offset/sizes */
+ off("FR_SP", struct frame, f_regs[15]);
+ off("FR_HW", struct frame, f_sr);
+ off("FR_ADJ", struct frame, f_stackadj);
+
+ /* system calls */
+ def("SYS_exit", SYS_exit);
+ def("SYS_execve", SYS_execve);
+ def("SYS_sigreturn", SYS_sigreturn);
+
+ /* errno */
+ def("EFAULT", EFAULT);
+ def("ENAMETOOLONG", ENAMETOOLONG);
+
+ exit(0);
+}
diff --git a/sys/arch/mvme68k/mvme68k/isr.h b/sys/arch/mvme68k/mvme68k/isr.h
new file mode 100644
index 00000000000..01caf41b0fb
--- /dev/null
+++ b/sys/arch/mvme68k/mvme68k/isr.h
@@ -0,0 +1,47 @@
+/* $NetBSD: isr.h,v 1.1.1.1 1995/07/25 23:11:58 chuck Exp $ */
+
+/*
+ * Copyright (c) 1982, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)isr.h 7.1 (Berkeley) 5/8/90
+ */
+
+struct isr {
+ struct isr *isr_forw;
+ struct isr *isr_back;
+ int (*isr_intr)();
+ int isr_arg;
+ int isr_ipl;
+};
+
+#define NISR 6
+#define ISRIPL(x) ((x) - 1)
diff --git a/sys/arch/mvme68k/mvme68k/locore.s b/sys/arch/mvme68k/mvme68k/locore.s
new file mode 100644
index 00000000000..26a08c31bad
--- /dev/null
+++ b/sys/arch/mvme68k/mvme68k/locore.s
@@ -0,0 +1,1832 @@
+/* $NetBSD: locore.s,v 1.1.1.1.2.1 1995/10/12 20:00:04 chuck Exp $ */
+
+#undef STACKCHECK /* doesn't work any more */
+
+/*
+ * Copyright (c) 1988 University of Utah.
+ * Copyright (c) 1980, 1990, 1993
+ * 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: locore.s 1.66 92/12/22$
+ *
+ * @(#)locore.s 8.6 (Berkeley) 5/27/94
+ */
+
+/*
+ * STACKCHECK enables two types of kernel stack checking:
+ * 1. stack "overflow". On every clock interrupt we ensure that
+ * the current kernel stack has not grown into the user struct
+ * page, i.e. size exceeded UPAGES-1 pages.
+ * 2. stack "underflow". Before every rte to user mode we ensure
+ * that we will be exactly at the base of the stack after the
+ * exception frame has been popped.
+ * Both checks are performed at splclock since they operate on the
+ * global temporary stack.
+ */
+/* #define STACKCHECK */
+
+#include "assym.s"
+#include <mvme68k/mvme68k/vectors.s>
+
+/*
+ * Temporary stack for a variety of purposes.
+ * Try and make this the first thing is the data segment so it
+ * is page aligned. Note that if we overflow here, we run into
+ * our text segment.
+ */
+ .data
+ .space NBPG
+tmpstk:
+
+ .text
+/*
+ * This is where we wind up if the kernel jumps to location 0.
+ * (i.e. a bogus PC) This is known to immediately follow the vector
+ * table and is hence at 0x400 (see reset vector in vectors.s).
+ */
+ .globl _panic
+ pea Ljmp0panic
+ jbsr _panic
+ /* NOTREACHED */
+Ljmp0panic:
+ .asciz "kernel jump to zero"
+ .even
+
+/*
+ * Do a dump.
+ * Called by auto-restart.
+ */
+ .globl _dumpsys
+ .globl _doadump
+_doadump:
+ jbsr _dumpsys
+ jbsr _doboot
+ /*NOTREACHED*/
+
+/*
+ * Trap/interrupt vector routines
+ */
+
+ .globl _trap, _nofault, _longjmp
+_buserr:
+ tstl _nofault | device probe?
+ jeq Lberr | no, handle as usual
+ movl _nofault,sp@- | yes,
+ jbsr _longjmp | longjmp(nofault)
+Lberr:
+#if defined(M68040)
+ cmpl #-2,_mmutype | 68040?
+ jne _addrerr | no, skip
+ clrl sp@- | stack adjust count
+ moveml #0xFFFF,sp@- | save user registers
+ movl usp,a0 | save the user SP
+ movl a0,sp@(FR_SP) | in the savearea
+ lea sp@(FR_HW),a1 | grab base of HW berr frame
+ moveq #0,d0
+ movw a1@(12),d0 | grab SSW
+ movl a1@(20),d1 | and fault VA
+ btst #11,d0 | check for mis-aligned access
+ jeq Lberr2 | no, skip
+ addl #3,d1 | yes, get into next page
+ andl #PG_FRAME,d1 | and truncate
+Lberr2:
+ movl d1,sp@- | push fault VA
+ movl d0,sp@- | and padded SSW
+ btst #10,d0 | ATC bit set?
+ jeq Lisberr | no, must be a real bus error
+ movc dfc,d1 | yes, get MMU fault
+ movc d0,dfc | store faulting function code
+ movl sp@(4),a0 | get faulting address
+ .word 0xf568 | ptestr a0@
+ movc d1,dfc
+ .long 0x4e7a0805 | movc mmusr,d0
+ movw d0,sp@ | save (ONLY LOW 16 BITS!)
+ jra Lismerr
+#endif
+_addrerr:
+ clrl sp@- | stack adjust count
+ moveml #0xFFFF,sp@- | save user registers
+ movl usp,a0 | save the user SP
+ movl a0,sp@(FR_SP) | in the savearea
+ lea sp@(FR_HW),a1 | grab base of HW berr frame
+#if defined(M68040)
+ cmpl #-2,_mmutype | 68040?
+ jne Lbenot040 | no, skip
+ movl a1@(8),sp@- | yes, push fault address
+ clrl sp@- | no SSW for address fault
+ jra Lisaerr | go deal with it
+Lbenot040:
+#endif
+ moveq #0,d0
+ movw a1@(10),d0 | grab SSW for fault processing
+ btst #12,d0 | RB set?
+ jeq LbeX0 | no, test RC
+ bset #14,d0 | yes, must set FB
+ movw d0,a1@(10) | for hardware too
+LbeX0:
+ btst #13,d0 | RC set?
+ jeq LbeX1 | no, skip
+ bset #15,d0 | yes, must set FC
+ movw d0,a1@(10) | for hardware too
+LbeX1:
+ btst #8,d0 | data fault?
+ jeq Lbe0 | no, check for hard cases
+ movl a1@(16),d1 | fault address is as given in frame
+ jra Lbe10 | thats it
+Lbe0:
+ btst #4,a1@(6) | long (type B) stack frame?
+ jne Lbe4 | yes, go handle
+ movl a1@(2),d1 | no, can use save PC
+ btst #14,d0 | FB set?
+ jeq Lbe3 | no, try FC
+ addql #4,d1 | yes, adjust address
+ jra Lbe10 | done
+Lbe3:
+ btst #15,d0 | FC set?
+ jeq Lbe10 | no, done
+ addql #2,d1 | yes, adjust address
+ jra Lbe10 | done
+Lbe4:
+ movl a1@(36),d1 | long format, use stage B address
+ btst #15,d0 | FC set?
+ jeq Lbe10 | no, all done
+ subql #2,d1 | yes, adjust address
+Lbe10:
+ movl d1,sp@- | push fault VA
+ movl d0,sp@- | and padded SSW
+ movw a1@(6),d0 | get frame format/vector offset
+ andw #0x0FFF,d0 | clear out frame format
+ cmpw #12,d0 | address error vector?
+ jeq Lisaerr | yes, go to it
+ movl d1,a0 | fault address
+ ptestr #1,a0@,#7 | do a table search
+ pmove psr,sp@ | save result
+ btst #7,sp@ | bus error bit set?
+ jeq Lismerr | no, must be MMU fault
+ clrw sp@ | yes, re-clear pad word
+ jra Lisberr | and process as normal bus error
+Lismerr:
+ movl #T_MMUFLT,sp@- | show that we are an MMU fault
+ jra Ltrapnstkadj | and deal with it
+Lisaerr:
+ movl #T_ADDRERR,sp@- | mark address error
+ jra Ltrapnstkadj | and deal with it
+Lisberr:
+ movl #T_BUSERR,sp@- | mark bus error
+Ltrapnstkadj:
+ jbsr _trap | handle the error
+ lea sp@(12),sp | pop value args
+ movl sp@(FR_SP),a0 | restore user SP
+ movl a0,usp | from save area
+ movw sp@(FR_ADJ),d0 | need to adjust stack?
+ jne Lstkadj | yes, go to it
+ moveml sp@+,#0x7FFF | no, restore most user regs
+ addql #8,sp | toss SSP and stkadj
+ jra rei | all done
+Lstkadj:
+ lea sp@(FR_HW),a1 | pointer to HW frame
+ addql #8,a1 | source pointer
+ movl a1,a0 | source
+ addw d0,a0 | + hole size = dest pointer
+ movl a1@-,a0@- | copy
+ movl a1@-,a0@- | 8 bytes
+ movl a0,sp@(FR_SP) | new SSP
+ moveml sp@+,#0x7FFF | restore user registers
+ movl sp@,sp | and our SP
+ jra rei | all done
+
+/*
+ * FP exceptions.
+ */
+_fpfline:
+#if defined(M68040)
+ cmpw #0x202c,sp@(6) | format type 2?
+ jne _illinst | no, not an FP emulation
+#ifdef FPSP
+ .globl fpsp_unimp
+ jmp fpsp_unimp | yes, go handle it
+#else
+ clrl sp@- | stack adjust count
+ moveml #0xFFFF,sp@- | save registers
+ moveq #T_FPEMULI,d0 | denote as FP emulation trap
+ jra fault | do it
+#endif
+#else
+ jra _illinst
+#endif
+
+_fpunsupp:
+#if defined(M68040)
+ cmpl #-2,_mmutype | 68040?
+ jne _illinst | no, treat as illinst
+#ifdef FPSP
+ .globl fpsp_unsupp
+ jmp fpsp_unsupp | yes, go handle it
+#else
+ clrl sp@- | stack adjust count
+ moveml #0xFFFF,sp@- | save registers
+ moveq #T_FPEMULD,d0 | denote as FP emulation trap
+ jra fault | do it
+#endif
+#else
+ jra _illinst
+#endif
+
+/*
+ * Handles all other FP coprocessor exceptions.
+ * Note that since some FP exceptions generate mid-instruction frames
+ * and may cause signal delivery, we need to test for stack adjustment
+ * after the trap call.
+ */
+ .globl _fpfault
+_fpfault:
+#ifdef FPCOPROC
+ clrl sp@- | stack adjust count
+ moveml #0xFFFF,sp@- | save user registers
+ movl usp,a0 | and save
+ movl a0,sp@(FR_SP) | the user stack pointer
+ clrl sp@- | no VA arg
+ movl _curpcb,a0 | current pcb
+ lea a0@(PCB_FPCTX),a0 | address of FP savearea
+ fsave a0@ | save state
+ tstb a0@ | null state frame?
+ jeq Lfptnull | yes, safe
+ clrw d0 | no, need to tweak BIU
+ movb a0@(1),d0 | get frame size
+ bset #3,a0@(0,d0:w) | set exc_pend bit of BIU
+Lfptnull:
+ fmovem fpsr,sp@- | push fpsr as code argument
+ frestore a0@ | restore state
+ movl #T_FPERR,sp@- | push type arg
+ jra Ltrapnstkadj | call trap and deal with stack cleanup
+#else
+ jra _badtrap | treat as an unexpected trap
+#endif
+
+/*
+ * Coprocessor and format errors can generate mid-instruction stack
+ * frames and cause signal delivery hence we need to check for potential
+ * stack adjustment.
+ */
+_coperr:
+ clrl sp@- | stack adjust count
+ moveml #0xFFFF,sp@-
+ movl usp,a0 | get and save
+ movl a0,sp@(FR_SP) | the user stack pointer
+ clrl sp@- | no VA arg
+ clrl sp@- | or code arg
+ movl #T_COPERR,sp@- | push trap type
+ jra Ltrapnstkadj | call trap and deal with stack adjustments
+
+_fmterr:
+ clrl sp@- | stack adjust count
+ moveml #0xFFFF,sp@-
+ movl usp,a0 | get and save
+ movl a0,sp@(FR_SP) | the user stack pointer
+ clrl sp@- | no VA arg
+ clrl sp@- | or code arg
+ movl #T_FMTERR,sp@- | push trap type
+ jra Ltrapnstkadj | call trap and deal with stack adjustments
+
+/*
+ * Other exceptions only cause four and six word stack frame and require
+ * no post-trap stack adjustment.
+ */
+_illinst:
+ clrl sp@-
+ moveml #0xFFFF,sp@-
+ moveq #T_ILLINST,d0
+ jra fault
+
+_zerodiv:
+ clrl sp@-
+ moveml #0xFFFF,sp@-
+ moveq #T_ZERODIV,d0
+ jra fault
+
+_chkinst:
+ clrl sp@-
+ moveml #0xFFFF,sp@-
+ moveq #T_CHKINST,d0
+ jra fault
+
+_trapvinst:
+ clrl sp@-
+ moveml #0xFFFF,sp@-
+ moveq #T_TRAPVINST,d0
+ jra fault
+
+_privinst:
+ clrl sp@-
+ moveml #0xFFFF,sp@-
+ moveq #T_PRIVINST,d0
+ jra fault
+
+ .globl fault
+fault:
+ movl usp,a0 | get and save
+ movl a0,sp@(FR_SP) | the user stack pointer
+ clrl sp@- | no VA arg
+ clrl sp@- | or code arg
+ movl d0,sp@- | push trap type
+ jbsr _trap | handle trap
+ lea sp@(12),sp | pop value args
+ movl sp@(FR_SP),a0 | restore
+ movl a0,usp | user SP
+ moveml sp@+,#0x7FFF | restore most user regs
+ addql #8,sp | pop SP and stack adjust
+ jra rei | all done
+
+ .globl _pcctrap
+_pcctrap:
+ moveml #0xC0C0,sp@- | save scratch regs
+ lea sp@(16),a1 | get pointer to frame
+ movl a1,sp@-
+ movw sp@(26),d0
+ movl d0,sp@- | push exception vector info
+ movl sp@(26),sp@- | and PC
+ jbsr _pccintr | doit
+ lea sp@(12),sp | pop value args
+ moveml sp@+,#0x0303 | restore regs
+ jra rei | all done
+
+ .globl _straytrap
+_badtrap:
+ moveml #0xC0C0,sp@- | save scratch regs
+ movw sp@(22),sp@- | push exception vector info
+ clrw sp@-
+ movl sp@(22),sp@- | and PC
+ jbsr _straytrap | report
+ addql #8,sp | pop args
+ moveml sp@+,#0x0303 | restore regs
+ jra rei | all done
+
+ .globl _syscall
+_trap0:
+ clrl sp@- | stack adjust count
+ moveml #0xFFFF,sp@- | save user registers
+ movl usp,a0 | save the user SP
+ movl a0,sp@(FR_SP) | in the savearea
+ movl d0,sp@- | push syscall number
+ jbsr _syscall | handle it
+ addql #4,sp | pop syscall arg
+ tstl _astpending
+ jne Lrei2
+ tstb _ssir
+ jeq Ltrap1
+ movw #SPL1,sr
+ tstb _ssir
+ jne Lsir1
+Ltrap1:
+ movl sp@(FR_SP),a0 | grab and restore
+ movl a0,usp | user SP
+ moveml sp@+,#0x7FFF | restore most registers
+ addql #8,sp | pop SP and stack adjust
+#ifdef STACKCHECK
+ jra Ldorte
+#else
+ rte
+#endif
+
+/*
+ * Routines for traps 1 and 2. The meaning of the two traps depends
+ * on whether we are an HPUX compatible process or a native 4.3 process.
+ * Our native 4.3 implementation uses trap 1 as sigreturn() and trap 2
+ * as a breakpoint trap. HPUX uses trap 1 for a breakpoint, so we have
+ * to make adjustments so that trap 2 is used for sigreturn.
+ */
+_trap1:
+#ifdef COMPAT_HPUX
+ btst #MDP_TRCB,mdpflag | being traced by an HPUX process?
+ jeq sigreturn | no, trap1 is sigreturn
+ jra _trace | yes, trap1 is breakpoint
+#else
+ jra sigreturn | no, trap1 is sigreturn
+#endif
+
+_trap2:
+#ifdef COMPAT_HPUX
+ btst #MDP_TRCB,mdpflag | being traced by an HPUX process?
+ jeq _trace | no, trap2 is breakpoint
+ jra sigreturn | yes, trap2 is sigreturn
+#else
+ jra _trace | no, trap2 is breakpoint
+#endif
+
+/*
+ * Trap 12 is the entry point for the cachectl "syscall" (both HPUX & BSD)
+ * cachectl(command, addr, length)
+ * command in d0, addr in a1, length in d1
+ */
+ .globl _cachectl
+_trap12:
+ movl d1,sp@- | push length
+ movl a1,sp@- | push addr
+ movl d0,sp@- | push command
+ jbsr _cachectl | do it
+ lea sp@(12),sp | pop args
+ jra rei | all done
+
+/*
+ * Trap 15 is used for:
+ * - KGDB traps
+ * - trace traps for SUN binaries (not fully supported yet)
+ * We just pass it on and let trap() sort it all out
+ */
+_trap15:
+ clrl sp@-
+ moveml #0xFFFF,sp@-
+#ifdef KGDB
+ moveq #T_TRAP15,d0
+ movw sp@(FR_HW),d1 | get PSW
+ andw #PSL_S,d1 | from user mode?
+ jeq fault | yes, just a regular fault
+ movl d0,sp@-
+ .globl _kgdb_trap_glue
+ jbsr _kgdb_trap_glue | returns if no debugger
+ addl #4,sp
+#endif
+ moveq #T_TRAP15,d0
+ jra fault
+
+/*
+ * Hit a breakpoint (trap 1 or 2) instruction.
+ * Push the code and treat as a normal fault.
+ */
+_trace:
+ clrl sp@-
+ moveml #0xFFFF,sp@-
+#ifdef KGDB
+ moveq #T_TRACE,d0
+ movw sp@(FR_HW),d1 | get SSW
+ andw #PSL_S,d1 | from user mode?
+ jeq fault | no, regular fault
+ movl d0,sp@-
+ jbsr _kgdb_trap_glue | returns if no debugger
+ addl #4,sp
+#endif
+ moveq #T_TRACE,d0
+ jra fault
+
+/*
+ * The sigreturn() syscall comes here. It requires special handling
+ * because we must open a hole in the stack to fill in the (possibly much
+ * larger) original stack frame.
+ */
+sigreturn:
+ lea sp@(-84),sp | leave enough space for largest frame
+ movl sp@(84),sp@ | move up current 8 byte frame
+ movl sp@(88),sp@(4)
+ movl #84,sp@- | default: adjust by 84 bytes
+ moveml #0xFFFF,sp@- | save user registers
+ movl usp,a0 | save the user SP
+ movl a0,sp@(FR_SP) | in the savearea
+ movl #SYS_sigreturn,sp@- | push syscall number
+ jbsr _syscall | handle it
+ addql #4,sp | pop syscall#
+ movl sp@(FR_SP),a0 | grab and restore
+ movl a0,usp | user SP
+ lea sp@(FR_HW),a1 | pointer to HW frame
+ movw sp@(FR_ADJ),d0 | do we need to adjust the stack?
+ jeq Lsigr1 | no, just continue
+ moveq #92,d1 | total size
+ subw d0,d1 | - hole size = frame size
+ lea a1@(92),a0 | destination
+ addw d1,a1 | source
+ lsrw #1,d1 | convert to word count
+ subqw #1,d1 | minus 1 for dbf
+Lsigrlp:
+ movw a1@-,a0@- | copy a word
+ dbf d1,Lsigrlp | continue
+ movl a0,a1 | new HW frame base
+Lsigr1:
+ movl a1,sp@(FR_SP) | new SP value
+ moveml sp@+,#0x7FFF | restore user registers
+ movl sp@,sp | and our SP
+ jra rei | all done
+
+/*
+ * Interrupt handlers.
+ * All device interrupts are auto-vectored. Most
+ * interrupt in the range IPL1 to IPL6. Here are our assignments:
+ *
+ * Level 0: Spurious: ignored.
+ * Level 1: networking devices (ethernet)
+ * Level 2: bio devices (scsi)
+ * Level 3:
+ * Level 4: Serial (SCC)
+ * Level 5: Clock
+ * Level 6:
+ * Level 7: Non-maskable (none)
+ */
+ .globl _intrhand, _hardclock, _nmihand
+
+_spurintr:
+ addql #1,_intrcnt+0
+ addql #1,_cnt+V_INTR
+ jra rei
+
+_lev1intr:
+_lev2intr:
+_lev3intr:
+_lev4intr:
+_lev5intr:
+_lev6intr:
+ moveml #0xC0C0,sp@-
+ lea _intrcnt,a0
+ movw sp@(22),d0 | use vector offset
+ andw #0xfff,d0 | sans frame type
+ addql #1,a0@(-0x60,d0:w) | to increment apropos counter
+ movw sr,sp@- | push current SR value
+ clrw sp@- | padded to longword
+ jbsr _intrhand | handle interrupt
+ addql #4,sp | pop SR
+ moveml sp@+,#0x0303
+ addql #1,_cnt+V_INTR
+ jra rei
+
+_lev7intr:
+ addql #1,_intrcnt+32
+ clrl sp@-
+ moveml #0xFFFF,sp@- | save registers
+ movl usp,a0 | and save
+ movl a0,sp@(FR_SP) | the user stack pointer
+ jbsr _nmihand | call handler
+ movl sp@(FR_SP),a0 | restore
+ movl a0,usp | user SP
+ moveml sp@+,#0x7FFF | and remaining registers
+ addql #8,sp | pop SP and stack adjust
+ jra rei | all done
+
+/*
+ * Emulation of VAX REI instruction.
+ *
+ * This code deals with checking for and servicing ASTs
+ * (profiling, scheduling) and software interrupts (network, softclock).
+ * We check for ASTs first, just like the VAX. To avoid excess overhead
+ * the T_ASTFLT handling code will also check for software interrupts so we
+ * do not have to do it here. After identifing that we need an AST we
+ * drop the IPL to allow device interrupts.
+ *
+ * This code is complicated by the fact that sendsig may have been called
+ * necessitating a stack cleanup.
+ */
+ .comm _ssir,1
+ .globl _astpending
+ .globl rei
+rei:
+#ifdef STACKCHECK
+ tstl _panicstr | have we paniced?
+ jne Ldorte1 | yes, do not make matters worse
+#endif
+ tstl _astpending | AST pending?
+ jeq Lchksir | no, go check for SIR
+Lrei1:
+ btst #5,sp@ | yes, are we returning to user mode?
+ jne Lchksir | no, go check for SIR
+ movw #PSL_LOWIPL,sr | lower SPL
+ clrl sp@- | stack adjust
+ moveml #0xFFFF,sp@- | save all registers
+ movl usp,a1 | including
+ movl a1,sp@(FR_SP) | the users SP
+Lrei2:
+ clrl sp@- | VA == none
+ clrl sp@- | code == none
+ movl #T_ASTFLT,sp@- | type == async system trap
+ jbsr _trap | go handle it
+ lea sp@(12),sp | pop value args
+ movl sp@(FR_SP),a0 | restore user SP
+ movl a0,usp | from save area
+ movw sp@(FR_ADJ),d0 | need to adjust stack?
+ jne Laststkadj | yes, go to it
+ moveml sp@+,#0x7FFF | no, restore most user regs
+ addql #8,sp | toss SP and stack adjust
+#ifdef STACKCHECK
+ jra Ldorte
+#else
+ rte | and do real RTE
+#endif
+Laststkadj:
+ lea sp@(FR_HW),a1 | pointer to HW frame
+ addql #8,a1 | source pointer
+ movl a1,a0 | source
+ addw d0,a0 | + hole size = dest pointer
+ movl a1@-,a0@- | copy
+ movl a1@-,a0@- | 8 bytes
+ movl a0,sp@(FR_SP) | new SSP
+ moveml sp@+,#0x7FFF | restore user registers
+ movl sp@,sp | and our SP
+#ifdef STACKCHECK
+ jra Ldorte
+#else
+ rte | and do real RTE
+#endif
+Lchksir:
+ tstb _ssir | SIR pending?
+ jeq Ldorte | no, all done
+ movl d0,sp@- | need a scratch register
+ movw sp@(4),d0 | get SR
+ andw #PSL_IPL7,d0 | mask all but IPL
+ jne Lnosir | came from interrupt, no can do
+ movl sp@+,d0 | restore scratch register
+Lgotsir:
+ movw #SPL1,sr | prevent others from servicing int
+ tstb _ssir | too late?
+ jeq Ldorte | yes, oh well...
+ clrl sp@- | stack adjust
+ moveml #0xFFFF,sp@- | save all registers
+ movl usp,a1 | including
+ movl a1,sp@(FR_SP) | the users SP
+Lsir1:
+ clrl sp@- | VA == none
+ clrl sp@- | code == none
+ movl #T_SSIR,sp@- | type == software interrupt
+ jbsr _trap | go handle it
+ lea sp@(12),sp | pop value args
+ movl sp@(FR_SP),a0 | restore
+ movl a0,usp | user SP
+ moveml sp@+,#0x7FFF | and all remaining registers
+ addql #8,sp | pop SP and stack adjust
+#ifdef STACKCHECK
+ jra Ldorte
+#else
+ rte
+#endif
+Lnosir:
+ movl sp@+,d0 | restore scratch register
+Ldorte:
+#ifdef STACKCHECK
+ movw #SPL6,sr | avoid trouble
+ btst #5,sp@ | are we returning to user mode?
+ jne Ldorte1 | no, skip it
+ movl a6,tmpstk-20
+ movl d0,tmpstk-76
+ moveq #0,d0
+ movb sp@(6),d0 | get format/vector
+ lsrl #3,d0 | convert to index
+ lea _exframesize,a6 | into exframesize
+ addl d0,a6 | to get pointer to correct entry
+ movw a6@,d0 | get size for this frame
+ addql #8,d0 | adjust for unaccounted for bytes
+ lea _kstackatbase,a6 | desired stack base
+ subl d0,a6 | - frame size == our stack
+ cmpl a6,sp | are we where we think?
+ jeq Ldorte2 | yes, skip it
+ lea tmpstk,a6 | will be using tmpstk
+ movl sp@(4),a6@- | copy common
+ movl sp@,a6@- | frame info
+ clrl a6@-
+ movl sp,a6@- | save sp
+ subql #4,a6 | skip over already saved a6
+ moveml #0x7FFC,a6@- | push remaining regs (d0/a6/a7 done)
+ lea a6@(-4),sp | switch to tmpstk (skip saved d0)
+ clrl sp@- | is an underflow
+ jbsr _badkstack | badkstack(0, frame)
+ addql #4,sp
+ moveml sp@+,#0x7FFF | restore most registers
+ movl sp@,sp | and SP
+ rte
+Ldorte2:
+ movl tmpstk-76,d0
+ movl tmpstk-20,a6
+Ldorte1:
+#endif
+ rte | real return
+
+#ifdef STACKCHECK
+/*
+ * Kernel access to the current processes kernel stack is via a fixed
+ * virtual address. It is at the same address as in the users VA space.
+ */
+ .data
+ .set _kstack,USRSTACK
+ .set _kstackatbase,USRSTACK+USPACE-4
+ .globl _kstackatbase
+ .globl _kstack
+#endif
+
+#define RELOC(var, ar) \
+ lea var,ar
+
+/*
+ * Initialization
+ *
+ * The bootstrap loader loads us in starting at 0, and VBR is non-zero.
+ * On entry, args on stack are boot device, boot filename, console unit,
+ * boot flags (howto), boot device name, filesystem type name.
+ */
+ .comm _lowram,4
+ .comm _esym,4
+
+ .text
+ .globl _edata
+ .globl _etext,_end
+ .globl start
+start:
+ movw #PSL_HIGHIPL,sr | no interrupts
+ movl #0,d6 | get bootdev
+ movl sp@(4),d7 | get boothowto
+ RELOC(tmpstk, a0)
+ movl a0,sp | give ourselves a temporary stack
+
+ lea _edata,a0 | clear out BSS
+ movl #_end-4,d0 | (must be <= 256 kB)
+ subl #_edata,d0
+ lsrl #2,d0
+1: clrl a0@+
+ dbra d0,1b
+
+ RELOC(_esym, a0)
+#if 1
+ movl a4,a0@ | store end of symbol table
+#else
+ clrl a0@ | no symbol table, yet
+#endif
+ movl #0,a5 | RAM starts at 0
+ RELOC(_lowram, a0)
+ movl a5,a0@ | store start of physical memory
+ movl #CACHE_OFF,d0
+ movc d0,cacr | clear and disable on-chip cache(s)
+
+/* determine our CPU/MMU combo - check for all regardless of kernel config */
+ movl #0x200,d0 | data freeze bit
+ movc d0,cacr | only exists on 68030
+ movc cacr,d0 | read it back
+ tstl d0 | zero?
+ jeq Lnot68030 | yes, we have 68020/68040
+ RELOC(_mmutype, a0) | no, we have 68030
+ movl #-1,a0@ | set to reflect 68030 PMMU
+ jra Lstart1
+Lnot68030:
+ bset #31,d0 | data cache enable bit
+ movc d0,cacr | only exists on 68040
+ movc cacr,d0 | read it back
+ tstl d0 | zero?
+ beq Lis68020 | yes, we have 68020
+ moveq #0,d0 | now turn it back off
+ movec d0,cacr | before we access any data
+ RELOC(_mmutype, a0)
+ movl #-2,a0@ | with a 68040 MMU
+ jra Lstart1
+Lis68020:
+ RELOC(_mmutype, a0)
+ movl #1,a0@ | no, we have PMMU
+
+Lstart1:
+ /* XXXCDC SHUTUP 147 CALL */
+ movb #0, 0xfffe1026 | serial interrupt off
+ movb #0, 0xfffe1018 | timer 1 off
+ movb #0, 0xfffe1028 | ethernet off
+ /* XXXCDC SHUTUP 147 CALL */
+/* initialize source/destination control registers for movs */
+ moveq #FC_USERD,d0 | user space
+ movc d0,sfc | as source
+ movc d0,dfc | and destination of transfers
+/* initialize memory sizes (for pmap_bootstrap) */
+ movl 0xfffe0774,d1 | XXXCDC -- hardwired HEX
+ movl 0xfffe0778,_myea | XXXCDC -- ethernet addr
+ moveq #PGSHIFT,d2
+ lsrl d2,d1 | convert to page (click) number
+ RELOC(_maxmem, a0)
+ movl d1,a0@ | save as maxmem
+ movl a5,d0 | lowram value from ROM via boot
+ lsrl d2,d0 | convert to page number
+ subl d0,d1 | compute amount of RAM present
+ RELOC(_physmem, a0)
+ movl d1,a0@ | and physmem
+/* configure kernel and proc0 VA space so we can get going */
+ .globl _Sysseg, _pmap_bootstrap, _avail_start
+#ifdef DDB
+ RELOC(_esym,a0) | end of static kernel test/data/syms
+ movl a0@,d5
+ jne Lstart2
+#endif
+ movl #_end,d5 | end of static kernel text/data
+Lstart2:
+ addl #NBPG-1,d5
+ andl #PG_FRAME,d5 | round to a page
+ movl d5,a4
+ addl a5,a4 | convert to PA
+ movl #0, sp@- | firstpa
+ pea a4@ | nextpa
+ RELOC(_pmap_bootstrap,a0)
+ jbsr a0@ | pmap_bootstrap(firstpa, nextpa)
+ addql #8,sp
+
+/*
+ * Enable the MMU.
+ * Since the kernel is mapped logical == physical, we just turn it on.
+ */
+ RELOC(_Sysseg, a0) | system segment table addr
+ movl a0@,d1 | read value (a KVA)
+ addl a5,d1 | convert to PA
+ RELOC(_mmutype, a0)
+ cmpl #-2,a0@ | 68040?
+ jne Lmotommu1 | no, skip
+ .long 0x4e7b1807 | movc d1,srp
+ jra Lstploaddone
+Lmotommu1:
+ RELOC(_protorp, a0)
+ movl #0x80000202,a0@ | nolimit + share global + 4 byte PTEs
+ movl d1,a0@(4) | + segtable address
+ pmove a0@,srp | load the supervisor root pointer
+ movl #0x80000002,a0@ | reinit upper half for CRP loads
+Lstploaddone:
+ RELOC(_mmutype, a0)
+ cmpl #-2,a0@ | 68040?
+ jne Lmotommu2 | no, skip
+ moveq #0,d0 | ensure TT regs are disabled
+ .long 0x4e7b0004 | movc d0,itt0
+ .long 0x4e7b0005 | movc d0,itt1
+ .long 0x4e7b0006 | movc d0,dtt0
+ .long 0x4e7b0007 | movc d0,dtt1
+ .word 0xf4d8 | cinva bc
+ .word 0xf518 | pflusha
+ movl #0x8000,d0
+ .long 0x4e7b0003 | movc d0,tc
+ movl #0x80008000,d0
+ movc d0,cacr | turn on both caches
+ jmp Lenab1
+Lmotommu2:
+ movl #0x82c0aa00,a2@ | value to load TC with
+ pmove a2@,tc | load it
+Lenab1:
+
+/*
+ * Should be running mapped from this point on
+ */
+/* select the software page size now */
+ lea tmpstk,sp | temporary stack
+ jbsr _vm_set_page_size | select software page size
+/* set kernel stack, user SP, and initial pcb */
+ movl _proc0paddr,a1 | get proc0 pcb addr
+ lea a1@(USPACE-4),sp | set kernel stack to end of area
+ movl #USRSTACK-4,a2
+ movl a2,usp | init user SP
+ movl a1,_curpcb | proc0 is running
+#ifdef FPCOPROC
+ clrl a1@(PCB_FPCTX) | ensure null FP context
+ movl a1,sp@-
+ jbsr _m68881_restore | restore it (does not kill a1)
+ addql #4,sp
+#endif
+/* flush TLB and turn on caches */
+ jbsr _TBIA | invalidate TLB
+ cmpl #-2,_mmutype | 68040?
+ jeq Lnocache0 | yes, cache already on
+ movl #CACHE_ON,d0
+ movc d0,cacr | clear cache(s)
+Lnocache0:
+/* final setup for C code */
+ movl #0x8000,d0 | set VBR XXXCDC
+ movc d0,vbr
+ jbsr _isrinit | be ready for stray ints
+ movw #PSL_LOWIPL,sr | lower SPL
+ movl d7,_boothowto | save reboot flags
+ movl d6,_bootdev | and boot device
+
+/*
+ * Create a fake exception frame so that cpu_fork() can copy it.
+ * main() nevers returns; we exit to user mode from a forked process
+ * later on.
+ */
+ clrw sp@- | vector offset/frame type
+ clrl sp@- | PC - filled in by "execve"
+ movw #PSL_USER,sp@- | in user mode
+ clrl sp@- | stack adjust count and padding
+ lea sp@(-64),sp | construct space for D0-D7/A0-A7
+ lea _proc0,a0 | save pointer to frame
+ movl sp,a0@(P_MD_REGS) | in proc0.p_md.md_regs
+
+ jra _main | main()
+
+ .globl _proc_trampoline
+_proc_trampoline:
+ movl a3@(P_MD_REGS),sp | process' frame pointer in sp
+ movl a3,sp@-
+ jbsr a2@
+ addql #4,sp
+ movl sp@(FR_SP),a0 | grab and load
+ movl a0,usp | user SP
+ moveml sp@+,#0x7FFF | restore most user regs
+ addql #8,sp | toss SP and stack adjust
+ jra rei | and return
+
+/*
+ * Signal "trampoline" code (18 bytes). Invoked from RTE setup by sendsig().
+ *
+ * Stack looks like:
+ *
+ * sp+0 -> signal number
+ * sp+4 signal specific code
+ * sp+8 pointer to signal context frame (scp)
+ * sp+12 address of handler
+ * sp+16 saved hardware state
+ * .
+ * .
+ * scp+0-> beginning of signal context frame
+ */
+ .globl _sigcode, _esigcode, _sigcodetrap
+ .data
+_sigcode:
+ movl sp@(12),a0 | signal handler addr (4 bytes)
+ jsr a0@ | call signal handler (2 bytes)
+ addql #4,sp | pop signo (2 bytes)
+_sigcodetrap:
+ trap #1 | special syscall entry (2 bytes)
+ movl d0,sp@(4) | save errno (4 bytes)
+ moveq #1,d0 | syscall == exit (2 bytes)
+ trap #0 | exit(errno) (2 bytes)
+ .align 2
+_esigcode:
+
+/*
+ * Primitives
+ */
+
+#ifdef __STDC__
+#define EXPORT(name) .globl _ ## name; _ ## name:
+#else
+#define EXPORT(name) .globl _/**/name; _/**/name:
+#endif
+#ifdef GPROF
+#if __GNUC__ >= 2
+#define ENTRY(name) EXPORT(name) link a6,\#0; jbsr mcount; unlk a6
+#else
+#define ENTRY(name) EXPORT(name) link a6,#0; jbsr mcount; unlk a6
+#endif
+#define ALTENTRY(name, rname) ENTRY(name); jra rname+12
+#else
+#define ENTRY(name) EXPORT(name)
+#define ALTENTRY(name, rname) ENTRY(name)
+#endif
+
+/*
+ * copypage(fromaddr, toaddr)
+ *
+ * Optimized version of bcopy for a single page-aligned NBPG byte copy.
+ */
+ENTRY(copypage)
+ movl sp@(4),a0 | source address
+ movl sp@(8),a1 | destination address
+ movl #NBPG/32,d0 | number of 32 byte chunks
+#if defined(M68040)
+ cmpl #-2,_mmutype | 68040?
+ jne Lmlloop | no, use movl
+Lm16loop:
+ .long 0xf6209000 | move16 a0@+,a1@+
+ .long 0xf6209000 | move16 a0@+,a1@+
+ subql #1,d0
+ jne Lm16loop
+ rts
+#endif
+Lmlloop:
+ movl a0@+,a1@+
+ movl a0@+,a1@+
+ movl a0@+,a1@+
+ movl a0@+,a1@+
+ movl a0@+,a1@+
+ movl a0@+,a1@+
+ movl a0@+,a1@+
+ movl a0@+,a1@+
+ subql #1,d0
+ jne Lmlloop
+ rts
+
+/*
+ * non-local gotos
+ */
+ENTRY(setjmp)
+ movl sp@(4),a0 | savearea pointer
+ moveml #0xFCFC,a0@ | save d2-d7/a2-a7
+ movl sp@,a0@(48) | and return address
+ moveq #0,d0 | return 0
+ rts
+
+ENTRY(longjmp)
+ movl sp@(4),a0
+ moveml a0@+,#0xFCFC
+ movl a0@,sp@
+ moveq #1,d0
+ rts
+
+/*
+ * The following primitives manipulate the run queues. _whichqs tells which
+ * of the 32 queues _qs have processes in them. Setrunqueue puts processes
+ * into queues, Remrq removes them from queues. The running process is on
+ * no queue, other processes are on a queue related to p->p_priority, divided
+ * by 4 actually to shrink the 0-127 range of priorities into the 32 available
+ * queues.
+ */
+
+ .globl _whichqs,_qs,_cnt,_panic
+ .globl _curproc,_want_resched
+
+/*
+ * Setrunqueue(p)
+ *
+ * Call should be made at spl6(), and p->p_stat should be SRUN
+ */
+ENTRY(setrunqueue)
+ movl sp@(4),a0
+#ifdef DIAGNOSTIC
+ tstl a0@(P_BACK)
+ jne Lset1
+ tstl a0@(P_WCHAN)
+ jne Lset1
+ cmpb #SRUN,a0@(P_STAT)
+ jne Lset1
+#endif
+ clrl d0
+ movb a0@(P_PRIORITY),d0
+ lsrb #2,d0
+ movl _whichqs,d1
+ bset d0,d1
+ movl d1,_whichqs
+ lslb #3,d0
+ addl #_qs,d0
+ movl d0,a0@(P_FORW)
+ movl d0,a1
+ movl a1@(P_BACK),a0@(P_BACK)
+ movl a0,a1@(P_BACK)
+ movl a0@(P_BACK),a1
+ movl a0,a1@(P_FORW)
+ rts
+#ifdef DIAGNOSTIC
+Lset1:
+ movl #Lset2,sp@-
+ jbsr _panic
+Lset2:
+ .asciz "setrunqueue"
+ .even
+#endif
+
+/*
+ * Remrq(p)
+ *
+ * Call should be made at spl6().
+ */
+ENTRY(remrq)
+ movl sp@(4),a0
+ movb a0@(P_PRIORITY),d0
+#ifdef DIAGNOSTIC
+ lsrb #2,d0
+ movl _whichqs,d1
+ btst d0,d1
+ jeq Lrem2
+#endif
+ movl a0@(P_BACK),a1
+ clrl a0@(P_BACK)
+ movl a0@(P_FORW),a0
+ movl a0,a1@(P_FORW)
+ movl a1,a0@(P_BACK)
+ cmpal a0,a1
+ jne Lrem1
+#ifndef DIAGNOSTIC
+ lsrb #2,d0
+ movl _whichqs,d1
+#endif
+ bclr d0,d1
+ movl d1,_whichqs
+Lrem1:
+ rts
+#ifdef DIAGNOSTIC
+Lrem2:
+ movl #Lrem3,sp@-
+ jbsr _panic
+Lrem3:
+ .asciz "remrq"
+ .even
+#endif
+
+Lsw0:
+ .asciz "switch"
+ .even
+
+ .globl _curpcb
+ .globl _masterpaddr | XXX compatibility (debuggers)
+ .data
+_masterpaddr: | XXX compatibility (debuggers)
+_curpcb:
+ .long 0
+mdpflag:
+ .byte 0 | copy of proc md_flags low byte
+ .align 2
+ .comm nullpcb,SIZEOF_PCB
+ .text
+
+/*
+ * At exit of a process, do a switch for the last time.
+ * Switch to a safe stack and PCB, and deallocate the process's resources.
+ */
+ENTRY(switch_exit)
+ movl sp@(4),a0
+ movl #nullpcb,_curpcb | save state into garbage pcb
+ lea tmpstk,sp | goto a tmp stack
+
+ /* Free old process's resources. */
+ movl #USPACE,sp@- | size of u-area
+ movl a0@(P_ADDR),sp@- | address of process's u-area
+ movl _kernel_map,sp@- | map it was allocated in
+ jbsr _kmem_free | deallocate it
+ lea sp@(12),sp | pop args
+
+ jra _cpu_switch
+
+/*
+ * When no processes are on the runq, Swtch branches to Idle
+ * to wait for something to come ready.
+ */
+ .globl Idle
+Idle:
+ stop #PSL_LOWIPL
+ movw #PSL_HIGHIPL,sr
+ movl _whichqs,d0
+ jeq Idle
+ jra Lsw1
+
+Lbadsw:
+ movl #Lsw0,sp@-
+ jbsr _panic
+ /*NOTREACHED*/
+
+/*
+ * cpu_switch()
+ *
+ * NOTE: On the mc68851 (318/319/330) we attempt to avoid flushing the
+ * entire ATC. The effort involved in selective flushing may not be
+ * worth it, maybe we should just flush the whole thing?
+ *
+ * NOTE 2: With the new VM layout we now no longer know if an inactive
+ * user's PTEs have been changed (formerly denoted by the SPTECHG p_flag
+ * bit). For now, we just always flush the full ATC.
+ */
+ENTRY(cpu_switch)
+ movl _curpcb,a0 | current pcb
+ movw sr,a0@(PCB_PS) | save sr before changing ipl
+#ifdef notyet
+ movl _curproc,sp@- | remember last proc running
+#endif
+ clrl _curproc
+
+ /*
+ * Find the highest-priority queue that isn't empty,
+ * then take the first proc from that queue.
+ */
+ movw #PSL_HIGHIPL,sr | lock out interrupts
+ movl _whichqs,d0
+ jeq Idle
+Lsw1:
+ movl d0,d1
+ negl d0
+ andl d1,d0
+ bfffo d0{#0:#32},d1
+ eorib #31,d1
+
+ movl d1,d0
+ lslb #3,d1 | convert queue number to index
+ addl #_qs,d1 | locate queue (q)
+ movl d1,a1
+ movl a1@(P_FORW),a0 | p = q->p_forw
+ cmpal d1,a0 | anyone on queue?
+ jeq Lbadsw | no, panic
+ movl a0@(P_FORW),a1@(P_FORW) | q->p_forw = p->p_forw
+ movl a0@(P_FORW),a1 | n = p->p_forw
+ movl d1,a1@(P_BACK) | n->p_back = q
+ cmpal d1,a1 | anyone left on queue?
+ jne Lsw2 | yes, skip
+ movl _whichqs,d1
+ bclr d0,d1 | no, clear bit
+ movl d1,_whichqs
+Lsw2:
+ movl a0,_curproc
+ clrl _want_resched
+#ifdef notyet
+ movl sp@+,a1
+ cmpl a0,a1 | switching to same proc?
+ jeq Lswdone | yes, skip save and restore
+#endif
+ /*
+ * Save state of previous process in its pcb.
+ */
+ movl _curpcb,a1
+ moveml #0xFCFC,a1@(PCB_REGS) | save non-scratch registers
+ movl usp,a2 | grab USP (a2 has been saved)
+ movl a2,a1@(PCB_USP) | and save it
+#ifdef FPCOPROC
+ lea a1@(PCB_FPCTX),a2 | pointer to FP save area
+ fsave a2@ | save FP state
+ tstb a2@ | null state frame?
+ jeq Lswnofpsave | yes, all done
+ fmovem fp0-fp7,a2@(216) | save FP general registers
+ fmovem fpcr/fpsr/fpi,a2@(312) | save FP control registers
+Lswnofpsave:
+#endif
+
+#ifdef DIAGNOSTIC
+ tstl a0@(P_WCHAN)
+ jne Lbadsw
+ cmpb #SRUN,a0@(P_STAT)
+ jne Lbadsw
+#endif
+ clrl a0@(P_BACK) | clear back link
+ movb a0@(P_MD_FLAGS+3),mdpflag | low byte of p_md.md_flags
+ movl a0@(P_ADDR),a1 | get p_addr
+ movl a1,_curpcb
+
+ /* see if pmap_activate needs to be called; should remove this */
+ movl a0@(P_VMSPACE),a0 | vmspace = p->p_vmspace
+#ifdef DIAGNOSTIC
+ tstl a0 | map == VM_MAP_NULL?
+ jeq Lbadsw | panic
+#endif
+ lea a0@(VM_PMAP),a0 | pmap = &vmspace.vm_pmap
+ tstl a0@(PM_STCHG) | pmap->st_changed?
+ jeq Lswnochg | no, skip
+ pea a1@ | push pcb (at p_addr)
+ pea a0@ | push pmap
+ jbsr _pmap_activate | pmap_activate(pmap, pcb)
+ addql #8,sp
+ movl _curpcb,a1 | restore p_addr
+Lswnochg:
+
+ lea tmpstk,sp | now goto a tmp stack for NMI
+#if defined(M68040)
+ cmpl #-2,_mmutype | 68040?
+ jne Lres1a | no, skip
+ .word 0xf518 | yes, pflusha
+ movl a1@(PCB_USTP),d0 | get USTP
+ moveq #PGSHIFT,d1
+ lsll d1,d0 | convert to addr
+ .long 0x4e7b0806 | movc d0,urp
+ jra Lcxswdone
+Lres1a:
+#endif
+ movl #CACHE_CLR,d0
+ movc d0,cacr | invalidate cache(s)
+ pflusha | flush entire TLB
+ movl a1@(PCB_USTP),d0 | get USTP
+ moveq #PGSHIFT,d1
+ lsll d1,d0 | convert to addr
+ lea _protorp,a0 | CRP prototype
+ movl d0,a0@(4) | stash USTP
+ pmove a0@,crp | load new user root pointer
+Lcxswdone:
+ moveml a1@(PCB_REGS),#0xFCFC | and registers
+ movl a1@(PCB_USP),a0
+ movl a0,usp | and USP
+#ifdef FPCOPROC
+ lea a1@(PCB_FPCTX),a0 | pointer to FP save area
+ tstb a0@ | null state frame?
+ jeq Lresfprest | yes, easy
+#if defined(M68040)
+ cmpl #-2,_mmutype | 68040?
+ jne Lresnot040 | no, skip
+ clrl sp@- | yes...
+ frestore sp@+ | ...magic!
+Lresnot040:
+#endif
+ fmovem a0@(312),fpcr/fpsr/fpi | restore FP control registers
+ fmovem a0@(216),fp0-fp7 | restore FP general registers
+Lresfprest:
+ frestore a0@ | restore state
+#endif
+ movw a1@(PCB_PS),sr | no, restore PS
+ moveq #1,d0 | return 1 (for alternate returns)
+ rts
+
+/*
+ * savectx(pcb)
+ * Update pcb, saving current processor state.
+ */
+ENTRY(savectx)
+ movl sp@(4),a1
+ movw sr,a1@(PCB_PS)
+ movl usp,a0 | grab USP
+ movl a0,a1@(PCB_USP) | and save it
+ moveml #0xFCFC,a1@(PCB_REGS) | save non-scratch registers
+#ifdef FPCOPROC
+ lea a1@(PCB_FPCTX),a0 | pointer to FP save area
+ fsave a0@ | save FP state
+ tstb a0@ | null state frame?
+ jeq Lsvnofpsave | yes, all done
+ fmovem fp0-fp7,a0@(216) | save FP general registers
+ fmovem fpcr/fpsr/fpi,a0@(312) | save FP control registers
+Lsvnofpsave:
+#endif
+ moveq #0,d0 | return 0
+ rts
+
+#if defined(M68040)
+ENTRY(suline)
+ movl sp@(4),a0 | address to write
+ movl _curpcb,a1 | current pcb
+ movl #Lslerr,a1@(PCB_ONFAULT) | where to return to on a fault
+ movl sp@(8),a1 | address of line
+ movl a1@+,d0 | get lword
+ movsl d0,a0@+ | put lword
+ nop | sync
+ movl a1@+,d0 | get lword
+ movsl d0,a0@+ | put lword
+ nop | sync
+ movl a1@+,d0 | get lword
+ movsl d0,a0@+ | put lword
+ nop | sync
+ movl a1@+,d0 | get lword
+ movsl d0,a0@+ | put lword
+ nop | sync
+ moveq #0,d0 | indicate no fault
+ jra Lsldone
+Lslerr:
+ moveq #-1,d0
+Lsldone:
+ movl _curpcb,a1 | current pcb
+ clrl a1@(PCB_ONFAULT) | clear fault address
+ rts
+#endif
+
+/*
+ * Invalidate entire TLB.
+ */
+ENTRY(TBIA)
+__TBIA:
+#if defined(M68040)
+ cmpl #-2,_mmutype | 68040?
+ jne Lmotommu3 | no, skip
+ .word 0xf518 | yes, pflusha
+ rts
+Lmotommu3:
+#endif
+ tstl _mmutype | what mmu?
+ jpl Lmc68851a | 68851 implies no d-cache
+ movl #DC_CLEAR,d0
+ movc d0,cacr | invalidate on-chip d-cache
+Lmc68851a:
+ rts
+
+/*
+ * Invalidate any TLB entry for given VA (TB Invalidate Single)
+ */
+ENTRY(TBIS)
+#ifdef DEBUG
+ tstl fulltflush | being conservative?
+ jne __TBIA | yes, flush entire TLB
+#endif
+#if defined(M68040)
+ cmpl #-2,_mmutype | 68040?
+ jne Lmotommu4 | no, skip
+ movl sp@(4),a0
+ movc dfc,d1
+ moveq #1,d0 | user space
+ movc d0,dfc
+ .word 0xf508 | pflush a0@
+ moveq #5,d0 | super space
+ movc d0,dfc
+ .word 0xf508 | pflush a0@
+ movc d1,dfc
+ rts
+Lmotommu4:
+#endif
+ tstl _mmutype | is 68851?
+ jpl Lmc68851b |
+ movl sp@(4),a0 | get addr to flush
+ pflush #0,#0,a0@ | flush address from both sides
+ movl #DC_CLEAR,d0
+ movc d0,cacr | invalidate on-chip data cache
+ rts
+Lmc68851b:
+ pflushs #0,#0,a0@ | flush address from both sides
+ rts
+
+/*
+ * Invalidate supervisor side of TLB
+ */
+ENTRY(TBIAS)
+#ifdef DEBUG
+ tstl fulltflush | being conservative?
+ jne __TBIA | yes, flush everything
+#endif
+#if defined(M68040)
+ cmpl #-2,_mmutype | 68040?
+ jne Lmotommu5 | no, skip
+ .word 0xf518 | yes, pflusha (for now) XXX
+ rts
+Lmotommu5:
+#endif
+ pflush #4,#4 | flush supervisor TLB entries
+ movl #DC_CLEAR,d0
+ movc d0,cacr | invalidate on-chip d-cache
+ rts
+
+/*
+ * Invalidate user side of TLB
+ */
+ENTRY(TBIAU)
+#ifdef DEBUG
+ tstl fulltflush | being conservative?
+ jne __TBIA | yes, flush everything
+#endif
+#if defined(M68040)
+ cmpl #-2,_mmutype | 68040?
+ jne Lmotommu6 | no, skip
+ .word 0xf518 | yes, pflusha (for now) XXX
+ rts
+Lmotommu6:
+#endif
+ pflush #0,#4 | flush user TLB entries
+ movl #DC_CLEAR,d0
+ movc d0,cacr | invalidate on-chip d-cache
+ rts
+
+/*
+ * Invalidate instruction cache
+ */
+ENTRY(ICIA)
+#if defined(M68040)
+ENTRY(ICPA)
+ cmpl #-2,_mmutype | 68040
+ jne Lmotommu7 | no, skip
+ .word 0xf498 | cinva ic
+ rts
+Lmotommu7:
+#endif
+ movl #IC_CLEAR,d0
+ movc d0,cacr | invalidate i-cache
+ rts
+
+/*
+ * Invalidate data cache.
+ * NOTE: we do not flush 68030 on-chip cache as there are no aliasing
+ * problems with DC_WA. The only cases we have to worry about are context
+ * switch and TLB changes, both of which are handled "in-line" in resume
+ * and TBI*.
+ */
+ENTRY(DCIA)
+__DCIA:
+#if defined(M68040)
+ cmpl #-2,_mmutype | 68040
+ jne Lmotommu8 | no, skip
+ /* XXX implement */
+ rts
+Lmotommu8:
+#endif
+ rts
+
+ENTRY(DCIS)
+__DCIS:
+#if defined(M68040)
+ cmpl #-2,_mmutype | 68040
+ jne Lmotommu9 | no, skip
+ /* XXX implement */
+ rts
+Lmotommu9:
+#endif
+ rts
+
+ENTRY(DCIU)
+__DCIU:
+#if defined(M68040)
+ cmpl #-2,_mmutype | 68040
+ jne LmotommuA | no, skip
+ /* XXX implement */
+ rts
+LmotommuA:
+#endif
+ rts
+
+#if defined(M68040)
+ENTRY(ICPL)
+ movl sp@(4),a0 | address
+ .word 0xf488 | cinvl ic,a0@
+ rts
+ENTRY(ICPP)
+ movl sp@(4),a0 | address
+ .word 0xf490 | cinvp ic,a0@
+ rts
+ENTRY(DCPL)
+ movl sp@(4),a0 | address
+ .word 0xf448 | cinvl dc,a0@
+ rts
+ENTRY(DCPP)
+ movl sp@(4),a0 | address
+ .word 0xf450 | cinvp dc,a0@
+ rts
+ENTRY(DCPA)
+ .word 0xf458 | cinva dc
+ rts
+ENTRY(DCFL)
+ movl sp@(4),a0 | address
+ .word 0xf468 | cpushl dc,a0@
+ rts
+ENTRY(DCFP)
+ movl sp@(4),a0 | address
+ .word 0xf470 | cpushp dc,a0@
+ rts
+#endif
+
+ENTRY(PCIA)
+#if defined(M68040)
+ENTRY(DCFA)
+ cmpl #-2,_mmutype | 68040
+ jne LmotommuB | no, skip
+ .word 0xf478 | cpusha dc
+ rts
+LmotommuB:
+#endif
+ movl #DC_CLEAR,d0
+ movc d0,cacr | invalidate on-chip d-cache
+ rts
+
+ENTRY(ecacheon)
+ rts
+
+ENTRY(ecacheoff)
+ rts
+
+/*
+ * Get callers current SP value.
+ * Note that simply taking the address of a local variable in a C function
+ * doesn't work because callee saved registers may be outside the stack frame
+ * defined by A6 (e.g. GCC generated code).
+ */
+ .globl _getsp
+_getsp:
+ movl sp,d0 | get current SP
+ addql #4,d0 | compensate for return address
+ rts
+
+ .globl _getsfc, _getdfc
+_getsfc:
+ movc sfc,d0
+ rts
+_getdfc:
+ movc dfc,d0
+ rts
+
+/*
+ * Load a new user segment table pointer.
+ */
+ENTRY(loadustp)
+ movl sp@(4),d0 | new USTP
+ moveq #PGSHIFT, d1
+ lsll d1,d0 | convert to addr
+#if defined(M68040)
+ cmpl #-2,_mmutype | 68040?
+ jne LmotommuC | no, skip
+ .long 0x4e7b0806 | movc d0,urp
+ rts
+LmotommuC:
+#endif
+ lea _protorp,a0 | CRP prototype
+ movl d0,a0@(4) | stash USTP
+ pmove a0@,crp | load root pointer
+ movl #DC_CLEAR,d0
+ movc d0,cacr | invalidate on-chip d-cache
+ rts | since pmove flushes TLB
+
+ENTRY(ploadw)
+ movl sp@(4),a0 | address to load
+ ploadw #1,a0@ | pre-load translation
+ rts
+
+/*
+ * Set processor priority level calls. Most are implemented with
+ * inline asm expansions. However, spl0 requires special handling
+ * as we need to check for our emulated software interrupts.
+ */
+
+ENTRY(spl0)
+ moveq #0,d0
+ movw sr,d0 | get old SR for return
+ movw #PSL_LOWIPL,sr | restore new SR
+ tstb _ssir | software interrupt pending?
+ jeq Lspldone | no, all done
+ subql #4,sp | make room for RTE frame
+ movl sp@(4),sp@(2) | position return address
+ clrw sp@(6) | set frame type 0
+ movw #PSL_LOWIPL,sp@ | and new SR
+ jra Lgotsir | go handle it
+Lspldone:
+ rts
+
+ENTRY(_insque)
+ movw sr,d0
+ movw #PSL_HIGHIPL,sr | atomic
+ movl sp@(8),a0 | where to insert (after)
+ movl sp@(4),a1 | element to insert (e)
+ movl a0@,a1@ | e->next = after->next
+ movl a0,a1@(4) | e->prev = after
+ movl a1,a0@ | after->next = e
+ movl a1@,a0
+ movl a1,a0@(4) | e->next->prev = e
+ movw d0,sr
+ rts
+
+ENTRY(_remque)
+ movw sr,d0
+ movw #PSL_HIGHIPL,sr | atomic
+ movl sp@(4),a0 | element to remove (e)
+ movl a0@,a1
+ movl a0@(4),a0
+ movl a0,a1@(4) | e->next->prev = e->prev
+ movl a1,a0@ | e->prev->next = e->next
+ movw d0,sr
+ rts
+
+/*
+ * {ov}bcopy(from, to, len)
+ *
+ * Works for counts up to 128K.
+ */
+ALTENTRY(ovbcopy, _bcopy)
+ENTRY(bcopy)
+ movl sp@(12),d0 | get count
+ jeq Lcpyexit | if zero, return
+ movl sp@(4),a0 | src address
+ movl sp@(8),a1 | dest address
+ cmpl a1,a0 | src before dest?
+ jlt Lcpyback | yes, copy backwards (avoids overlap)
+ movl a0,d1
+ btst #0,d1 | src address odd?
+ jeq Lcfeven | no, go check dest
+ movb a0@+,a1@+ | yes, copy a byte
+ subql #1,d0 | update count
+ jeq Lcpyexit | exit if done
+Lcfeven:
+ movl a1,d1
+ btst #0,d1 | dest address odd?
+ jne Lcfbyte | yes, must copy by bytes
+ movl d0,d1 | no, get count
+ lsrl #2,d1 | convert to longwords
+ jeq Lcfbyte | no longwords, copy bytes
+ subql #1,d1 | set up for dbf
+Lcflloop:
+ movl a0@+,a1@+ | copy longwords
+ dbf d1,Lcflloop | til done
+ andl #3,d0 | get remaining count
+ jeq Lcpyexit | done if none
+Lcfbyte:
+ subql #1,d0 | set up for dbf
+Lcfbloop:
+ movb a0@+,a1@+ | copy bytes
+ dbf d0,Lcfbloop | til done
+Lcpyexit:
+ rts
+Lcpyback:
+ addl d0,a0 | add count to src
+ addl d0,a1 | add count to dest
+ movl a0,d1
+ btst #0,d1 | src address odd?
+ jeq Lcbeven | no, go check dest
+ movb a0@-,a1@- | yes, copy a byte
+ subql #1,d0 | update count
+ jeq Lcpyexit | exit if done
+Lcbeven:
+ movl a1,d1
+ btst #0,d1 | dest address odd?
+ jne Lcbbyte | yes, must copy by bytes
+ movl d0,d1 | no, get count
+ lsrl #2,d1 | convert to longwords
+ jeq Lcbbyte | no longwords, copy bytes
+ subql #1,d1 | set up for dbf
+Lcblloop:
+ movl a0@-,a1@- | copy longwords
+ dbf d1,Lcblloop | til done
+ andl #3,d0 | get remaining count
+ jeq Lcpyexit | done if none
+Lcbbyte:
+ subql #1,d0 | set up for dbf
+Lcbbloop:
+ movb a0@-,a1@- | copy bytes
+ dbf d0,Lcbbloop | til done
+ rts
+
+#ifdef FPCOPROC
+/*
+ * Save and restore 68881 state.
+ */
+ENTRY(m68881_save)
+ movl sp@(4),a0 | save area pointer
+ fsave a0@ | save state
+ tstb a0@ | null state frame?
+ jeq Lm68881sdone | yes, all done
+ fmovem fp0-fp7,a0@(216) | save FP general registers
+ fmovem fpcr/fpsr/fpi,a0@(312) | save FP control registers
+Lm68881sdone:
+ rts
+
+ENTRY(m68881_restore)
+ movl sp@(4),a0 | save area pointer
+ tstb a0@ | null state frame?
+ jeq Lm68881rdone | yes, easy
+ fmovem a0@(312),fpcr/fpsr/fpi | restore FP control registers
+ fmovem a0@(216),fp0-fp7 | restore FP general registers
+Lm68881rdone:
+ frestore a0@ | restore state
+ rts
+#endif
+
+/*
+ * Handle the nitty-gritty of rebooting the machine.
+ * Basically we just turn off the MMU and jump to the appropriate ROM routine.
+ */
+ .globl _doboot
+_doboot:
+#if defined(M68040)
+ cmpl #-2,_mmutype | 68040?
+ jeq Lnocache5 | yes, skip
+#endif
+ movl #CACHE_OFF,d0
+ movc d0,cacr | disable on-chip cache(s)
+Lnocache5:
+ movl _boothowto,d1 | load howto
+ movl _bootdev,d0 | and devtype
+ movl sp@(4),d1 | arg
+ lea tmpstk,sp | physical SP in case of NMI
+ movl #0,a7@- | value for pmove to TC (turn off MMU)
+ pmove a7@,tc | disable MMU
+ movl #0, d0
+ movc d0,vbr | ROM VBR
+ cmpl #0, d1 | autoboot?
+ jeq Lauto | yes
+ jmp 0x4000 | back to sboot
+Lauto: jmp 0x400a | tell sboot to reboot us
+
+ .data
+ .globl _mmutype,_protorp
+_mmutype:
+ .long -1 | default to MMU_68030
+_protorp:
+ .long 0,0 | prototype root pointer
+ .globl _cold
+_cold:
+ .long 1 | cold start flag
+ .globl _want_resched
+_want_resched:
+ .long 0
+ .globl _intiobase, _intiolimit, _extiobase, _RTCbase
+ .globl _proc0paddr
+_proc0paddr:
+ .long 0 | KVA of proc0 u-area
+_intiobase:
+ .long 0 | KVA of base of internal IO space
+_intiolimit:
+ .long 0 | KVA of end of internal IO space
+_extiobase:
+ .long 0 | KVA of base of external IO space
+#ifdef DEBUG
+ .globl fulltflush, fullcflush
+fulltflush:
+ .long 0
+fullcflush:
+ .long 0
+#endif
+/* interrupt counters */
+ .globl _intrcnt,_eintrcnt,_intrnames,_eintrnames
+_intrnames:
+ .asciz "spur"
+ .asciz "lev1"
+ .asciz "lev2"
+ .asciz "lev3"
+ .asciz "lev4"
+ .asciz "clock"
+ .asciz "lev6"
+ .asciz "nmi"
+ .asciz "statclock"
+_eintrnames:
+ .even
+_intrcnt:
+ .long 0,0,0,0,0,0,0,0,0,0
+_eintrcnt:
diff --git a/sys/arch/mvme68k/mvme68k/machdep.c b/sys/arch/mvme68k/mvme68k/machdep.c
new file mode 100644
index 00000000000..b89f3a3c58a
--- /dev/null
+++ b/sys/arch/mvme68k/mvme68k/machdep.c
@@ -0,0 +1,1471 @@
+/* $NetBSD: machdep.c,v 1.4 1995/10/07 06:25:54 mycroft Exp $ */
+
+/*
+ * Copyright (c) 1988 University of Utah.
+ * Copyright (c) 1982, 1986, 1990, 1993
+ * 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: machdep.c 1.74 92/12/20$
+ *
+ * @(#)machdep.c 8.10 (Berkeley) 4/20/94
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/signalvar.h>
+#include <sys/kernel.h>
+#include <sys/map.h>
+#include <sys/proc.h>
+#include <sys/buf.h>
+#include <sys/reboot.h>
+#include <sys/conf.h>
+#include <sys/file.h>
+#include <sys/clist.h>
+#include <sys/callout.h>
+#include <sys/malloc.h>
+#include <sys/mbuf.h>
+#include <sys/msgbuf.h>
+#include <sys/ioctl.h>
+#include <sys/tty.h>
+#include <sys/mount.h>
+#include <sys/user.h>
+#include <sys/exec.h>
+#include <sys/vnode.h>
+#include <sys/sysctl.h>
+#include <sys/syscallargs.h>
+#ifdef SYSVMSG
+#include <sys/msg.h>
+#endif
+#ifdef SYSVSEM
+#include <sys/sem.h>
+#endif
+#ifdef SYSVSHM
+#include <sys/shm.h>
+#endif
+
+#include <machine/cpu.h>
+#include <machine/reg.h>
+#include <machine/psl.h>
+#include <machine/pte.h>
+#include <dev/cons.h>
+#include <mvme68k/mvme68k/isr.h>
+#include <net/netisr.h>
+
+#define MAXMEM 64*1024*CLSIZE /* XXX - from cmap.h */
+#include <vm/vm_kern.h>
+
+/* the following is used externally (sysctl_hw) */
+char machine[] = "mvme68k"; /* cpu "architecture" */
+
+vm_map_t buffer_map;
+extern vm_offset_t avail_end;
+
+/*
+ * Declare these as initialized data so we can patch them.
+ */
+int nswbuf = 0;
+#ifdef NBUF
+int nbuf = NBUF;
+#else
+int nbuf = 0;
+#endif
+#ifdef BUFPAGES
+int bufpages = BUFPAGES;
+#else
+int bufpages = 0;
+#endif
+int msgbufmapped; /* set when safe to use msgbuf */
+int maxmem; /* max memory per process */
+int physmem = MAXMEM; /* max supported memory, changes to actual */
+/*
+ * safepri is a safe priority for sleep to set for a spin-wait
+ * during autoconfiguration or after a panic.
+ */
+int safepri = PSL_LOWIPL;
+
+u_long myea; /* from ROM XXXCDC */
+
+extern u_int lowram;
+extern short exframesize[];
+
+#ifdef COMPAT_HPUX
+extern struct emul emul_hpux;
+#endif
+#ifdef COMPAT_SUNOS
+extern struct emul emul_sunos;
+#endif
+#ifdef COMPAT_SVR4
+extern struct emul emul_svr4;
+#endif
+
+/*
+ * Console initialization: called early on from main,
+ * before vm init or startup. Do enough configuration
+ * to choose and initialize a console.
+ */
+consinit()
+{
+
+ /*
+ * Set cpuspeed immediately since cninit() called routines
+ * might use delay. Note that we only set it if a custom value
+ * has not already been specified.
+ */
+ if (cpuspeed == 0) {
+ cpuspeed = MHZ_16;
+ if (mmutype == MMU_68040)
+ cpuspeed *= 2; /* XXX */
+ }
+
+ /*
+ * Initialize the console before we print anything out.
+ */
+ cninit();
+
+#ifdef DDB
+ ddb_init();
+ if (boothowto & RB_KDB)
+ Debugger();
+#endif
+}
+
+/*
+ * cpu_startup: allocate memory for variable-sized tables,
+ * initialize cpu, and do autoconfiguration.
+ */
+void
+cpu_startup()
+{
+ register unsigned i;
+ register caddr_t v, firstaddr;
+ int base, residual;
+ vm_offset_t minaddr, maxaddr;
+ vm_size_t size;
+#ifdef BUFFERS_UNMANAGED
+ vm_offset_t bufmemp;
+ caddr_t buffermem;
+ int ix;
+#endif
+#ifdef DEBUG
+ extern int pmapdebug;
+ int opmapdebug = pmapdebug;
+
+ pmapdebug = 0;
+#endif
+
+ /*
+ * Initialize error message buffer (at end of core).
+ * avail_end was pre-decremented in pmap_bootstrap to compensate.
+ */
+ for (i = 0; i < btoc(sizeof (struct msgbuf)); i++)
+ pmap_enter(pmap_kernel(), (vm_offset_t)msgbufp,
+ avail_end + i * NBPG, VM_PROT_ALL, TRUE);
+ msgbufmapped = 1;
+
+ /*
+ * Good {morning,afternoon,evening,night}.
+ */
+ printf(version);
+ identifycpu();
+ printf("real mem = %d\n", ctob(physmem));
+
+ /*
+ * Allocate space for system data structures.
+ * The first available real memory address is in "firstaddr".
+ * The first available kernel virtual address is in "v".
+ * As pages of kernel virtual memory are allocated, "v" is incremented.
+ * As pages of memory are allocated and cleared,
+ * "firstaddr" is incremented.
+ * An index into the kernel page table corresponding to the
+ * virtual memory address maintained in "v" is kept in "mapaddr".
+ */
+ /*
+ * Make two passes. The first pass calculates how much memory is
+ * needed and allocates it. The second pass assigns virtual
+ * addresses to the various data structures.
+ */
+ firstaddr = 0;
+again:
+ v = (caddr_t)firstaddr;
+
+#define valloc(name, type, num) \
+ (name) = (type *)v; v = (caddr_t)((name)+(num))
+#define valloclim(name, type, num, lim) \
+ (name) = (type *)v; v = (caddr_t)((lim) = ((name)+(num)))
+#ifdef REAL_CLISTS
+ valloc(cfree, struct cblock, nclist);
+#endif
+ valloc(callout, struct callout, ncallout);
+ valloc(swapmap, struct map, nswapmap = maxproc * 2);
+#ifdef SYSVSHM
+ valloc(shmsegs, struct shmid_ds, shminfo.shmmni);
+#endif
+#ifdef SYSVSEM
+ valloc(sema, struct semid_ds, seminfo.semmni);
+ valloc(sem, struct sem, seminfo.semmns);
+ /* This is pretty disgusting! */
+ valloc(semu, int, (seminfo.semmnu * seminfo.semusz) / sizeof(int));
+#endif
+#ifdef SYSVMSG
+ valloc(msgpool, char, msginfo.msgmax);
+ valloc(msgmaps, struct msgmap, msginfo.msgseg);
+ valloc(msghdrs, struct msg, msginfo.msgtql);
+ valloc(msqids, struct msqid_ds, msginfo.msgmni);
+#endif
+
+ /*
+ * Determine how many buffers to allocate.
+ * We just allocate a flat 5%. Insure a minimum of 16 buffers.
+ * We allocate 1/2 as many swap buffer headers as file i/o buffers.
+ */
+ if (bufpages == 0)
+ bufpages = physmem / 20 / CLSIZE;
+ if (nbuf == 0) {
+ nbuf = bufpages;
+ if (nbuf < 16)
+ nbuf = 16;
+ }
+ if (nswbuf == 0) {
+ nswbuf = (nbuf / 2) &~ 1; /* force even */
+ if (nswbuf > 256)
+ nswbuf = 256; /* sanity */
+ }
+ valloc(swbuf, struct buf, nswbuf);
+ valloc(buf, struct buf, nbuf);
+ /*
+ * End of first pass, size has been calculated so allocate memory
+ */
+ if (firstaddr == 0) {
+ 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");
+#ifdef BUFFERS_UNMANAGED
+ buffermem = (caddr_t) kmem_alloc(kernel_map, bufpages*CLBYTES);
+ if (buffermem == 0)
+ panic("startup: no room for buffers");
+#endif
+ goto again;
+ }
+ /*
+ * End of second pass, addresses have been assigned
+ */
+ if ((vm_size_t)(v - firstaddr) != size)
+ panic("startup: table size inconsistency");
+ /*
+ * Now allocate buffers proper. They are different than the above
+ * in that they usually occupy more virtual memory than physical.
+ */
+ size = MAXBSIZE * nbuf;
+ buffer_map = kmem_suballoc(kernel_map, (vm_offset_t *)&buffers,
+ &maxaddr, size, TRUE);
+ minaddr = (vm_offset_t)buffers;
+ if (vm_map_find(buffer_map, vm_object_allocate(size), (vm_offset_t)0,
+ &minaddr, size, FALSE) != KERN_SUCCESS)
+ panic("startup: cannot allocate buffers");
+ base = bufpages / nbuf;
+ residual = bufpages % nbuf;
+#ifdef BUFFERS_UNMANAGED
+ bufmemp = (vm_offset_t) buffermem;
+#endif
+ for (i = 0; i < nbuf; i++) {
+ vm_size_t curbufsize;
+ vm_offset_t curbuf;
+
+ /*
+ * First <residual> buffers get (base+1) physical pages
+ * allocated for them. The rest get (base) physical pages.
+ *
+ * The rest of each buffer occupies virtual space,
+ * but has no physical memory allocated for it.
+ */
+ curbuf = (vm_offset_t)buffers + i * MAXBSIZE;
+ curbufsize = CLBYTES * (i < residual ? base+1 : base);
+#ifdef BUFFERS_UNMANAGED
+ /*
+ * Move the physical pages over from buffermem.
+ */
+ for (ix = 0; ix < curbufsize/CLBYTES; ix++) {
+ vm_offset_t pa;
+
+ pa = pmap_extract(pmap_kernel(), bufmemp);
+ if (pa == 0)
+ panic("startup: unmapped buffer");
+ pmap_remove(pmap_kernel(), bufmemp, bufmemp+CLBYTES);
+ pmap_enter(pmap_kernel(),
+ (vm_offset_t)(curbuf + ix * CLBYTES),
+ pa, VM_PROT_READ|VM_PROT_WRITE, TRUE);
+ bufmemp += CLBYTES;
+ }
+#else
+ vm_map_pageable(buffer_map, curbuf, curbuf+curbufsize, FALSE);
+ vm_map_simplify(buffer_map, curbuf);
+#endif
+ }
+#ifdef BUFFERS_UNMANAGED
+#if 0
+ /*
+ * We would like to free the (now empty) original address range
+ * but too many bad things will happen if we try.
+ */
+ kmem_free(kernel_map, (vm_offset_t)buffermem, bufpages*CLBYTES);
+#endif
+#endif
+ /*
+ * Allocate a submap for exec arguments. This map effectively
+ * limits the number of processes exec'ing at any time.
+ */
+ exec_map = kmem_suballoc(kernel_map, &minaddr, &maxaddr,
+ 16*NCARGS, TRUE);
+ /*
+ * Allocate a submap for physio
+ */
+ phys_map = kmem_suballoc(kernel_map, &minaddr, &maxaddr,
+ VM_PHYS_SIZE, TRUE);
+
+ /*
+ * Finally, allocate mbuf pool. Since mclrefcnt is an off-size
+ * we use the more space efficient malloc in place of kmem_alloc.
+ */
+ mclrefcnt = (char *)malloc(NMBCLUSTERS+CLBYTES/MCLBYTES,
+ M_MBUF, M_NOWAIT);
+ bzero(mclrefcnt, NMBCLUSTERS+CLBYTES/MCLBYTES);
+ mb_map = kmem_suballoc(kernel_map, (vm_offset_t *)&mbutl, &maxaddr,
+ VM_MBUF_SIZE, FALSE);
+ /*
+ * Initialize callouts
+ */
+ callfree = callout;
+ for (i = 1; i < ncallout; i++)
+ callout[i-1].c_next = &callout[i];
+ callout[i-1].c_next = NULL;
+
+#ifdef DEBUG
+ pmapdebug = opmapdebug;
+#endif
+ printf("avail mem = %d\n", ptoa(cnt.v_free_count));
+ printf("using %d buffers containing %d bytes of memory\n",
+ nbuf, bufpages * CLBYTES);
+ /*
+ * Set up CPU-specific registers, cache, etc.
+ */
+ initcpu();
+
+ /*
+ * Set up buffers, so they can be used to read disk labels.
+ */
+ bufinit();
+
+ /*
+ * Configure the system.
+ */
+ configure();
+}
+
+/*
+ * Set registers on exec.
+ * XXX Should clear registers except sp, pc,
+ * but would break init; should be fixed soon.
+ */
+void
+setregs(p, pack, stack, retval)
+ register struct proc *p;
+ struct exec_package *pack;
+ u_long stack;
+ register_t *retval;
+{
+ struct frame *frame = (struct frame *)p->p_md.md_regs;
+
+ frame->f_pc = pack->ep_entry & ~1;
+ frame->f_regs[SP] = stack;
+ frame->f_regs[A2] = (int)PS_STRINGS;
+#ifdef FPCOPROC
+ /* restore a null state frame */
+ p->p_addr->u_pcb.pcb_fpregs.fpf_null = 0;
+ m68881_restore(&p->p_addr->u_pcb.pcb_fpregs);
+#endif
+#ifdef COMPAT_HPUX
+ p->p_md.md_flags &= ~MDP_HPUXMMAP;
+ if (p->p_emul == &emul_hpux) {
+ frame->f_regs[A0] = 0; /* not 68010 (bit 31), no FPA (30) */
+ retval[0] = 0; /* no float card */
+#ifdef FPCOPROC
+ retval[1] = 1; /* yes 68881 */
+#else
+ retval[1] = 0; /* no 68881 */
+#endif
+ }
+ /*
+ * XXX This doesn't have much to do with setting registers but
+ * I didn't want to muck up kern_exec.c with this code, so I
+ * stuck it here.
+ *
+ * Ensure we perform the right action on traps type 1 and 2:
+ * If our parent is an HPUX process and we are being traced, turn
+ * on HPUX style interpretation. Else if we were using the HPUX
+ * style interpretation, revert to the BSD interpretation.
+ *
+ * Note that we do this by changing the trap instruction in the
+ * global "sigcode" array which then gets copied out to the user's
+ * sigcode in the stack. Since we are changing it in the global
+ * array we must always reset it, even for non-HPUX processes.
+ *
+ * Note also that implementing it in this way creates a potential
+ * race where we could have tweaked it for process A which then
+ * blocks in the copyout to the stack and process B comes along
+ * and untweaks it causing A to wind up with the wrong setting
+ * when the copyout continues. However, since we have already
+ * copied something out to this user stack page (thereby faulting
+ * it in), this scenerio is extremely unlikely.
+ */
+ {
+ extern short sigcodetrap[];
+
+ if ((p->p_pptr->p_emul == &emul_hpux) &&
+ (p->p_flag & P_TRACED)) {
+ p->p_md.md_flags |= MDP_HPUXTRACE;
+ *sigcodetrap = 0x4E42;
+ } else {
+ p->p_md.md_flags &= ~MDP_HPUXTRACE;
+ *sigcodetrap = 0x4E41;
+ }
+ }
+#endif
+}
+
+/*
+ * Info for CTL_HW
+ */
+char cpu_model[120];
+extern char version[];
+
+identifycpu()
+{
+ char *t, *mc;
+ int len;
+
+ switch (mmutype) {
+ case MMU_68851:
+ t = "?";
+ break;
+ case MMU_68030:
+ t = "147";
+ break;
+ case MMU_68040:
+ t = "16[27]";
+ break;
+ default:
+ t = "unknown";
+ break;
+ }
+ mc = (mmutype == MMU_68040 ? "40" :
+ (mmutype == MMU_68030 ? "30" : "20"));
+ sprintf(cpu_model, "Motorola MVME%s MC680%s CPU", t, mc);
+ switch (mmutype) {
+ case MMU_68040:
+ case MMU_68030:
+ strcat(cpu_model, "+MMU");
+ break;
+ case MMU_68851:
+ strcat(cpu_model, ", MC68851 MMU");
+ break;
+ default:
+ printf("%s\nunknown MMU type %d\n", cpu_model, mmutype);
+ panic("startup");
+ }
+ len = strlen(cpu_model);
+ if (mmutype == MMU_68040)
+ len += sprintf(cpu_model + len,
+ "+FPU, 4k on-chip physical I/D caches");
+ else if (mmutype == MMU_68030)
+ len += sprintf(cpu_model + len, ", %sMHz MC68882 FPU",
+ "???");
+ else
+ len += sprintf(cpu_model + len, ", %sMHz MC68881 FPU",
+ "???");
+ strcat(cpu_model, ")");
+ printf("%s\n", cpu_model);
+}
+
+/*
+ * machine dependent system variables.
+ */
+cpu_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p)
+ int *name;
+ u_int namelen;
+ void *oldp;
+ size_t *oldlenp;
+ void *newp;
+ size_t newlen;
+ struct proc *p;
+{
+ dev_t consdev;
+
+ /* all sysctl names at this level are terminal */
+ if (namelen != 1)
+ return (ENOTDIR); /* overloaded */
+
+ switch (name[0]) {
+ case CPU_CONSDEV:
+ if (cn_tab != NULL)
+ consdev = cn_tab->cn_dev;
+ else
+ consdev = NODEV;
+ return (sysctl_rdstruct(oldp, oldlenp, newp, &consdev,
+ sizeof consdev));
+ default:
+ return (EOPNOTSUPP);
+ }
+ /* NOTREACHED */
+}
+
+#ifdef USELEDS
+#include <hp300/hp300/led.h>
+
+int inledcontrol = 0; /* 1 if we are in ledcontrol already, cheap mutex */
+char *ledaddr;
+
+/*
+ * Map the LED page and setup the KVA to access it.
+ */
+ledinit()
+{
+ extern caddr_t ledbase;
+
+ pmap_enter(pmap_kernel(), (vm_offset_t)ledbase, (vm_offset_t)LED_ADDR,
+ VM_PROT_READ|VM_PROT_WRITE, TRUE);
+ ledaddr = (char *) ((int)ledbase | (LED_ADDR & PGOFSET));
+}
+
+/*
+ * Do lights:
+ * `ons' is a mask of LEDs to turn on,
+ * `offs' is a mask of LEDs to turn off,
+ * `togs' is a mask of LEDs to toggle.
+ * Note we don't use splclock/splx for mutual exclusion.
+ * They are expensive and we really don't need to be that precise.
+ * Besides we would like to be able to profile this routine.
+ */
+ledcontrol(ons, offs, togs)
+ register int ons, offs, togs;
+{
+ static char currentleds;
+ register char leds;
+
+ inledcontrol = 1;
+ leds = currentleds;
+ if (ons)
+ leds |= ons;
+ if (offs)
+ leds &= ~offs;
+ if (togs)
+ leds ^= togs;
+ currentleds = leds;
+ *ledaddr = ~leds;
+ inledcontrol = 0;
+}
+#endif
+
+#define SS_RTEFRAME 1
+#define SS_FPSTATE 2
+#define SS_USERREGS 4
+
+struct sigstate {
+ int ss_flags; /* which of the following are valid */
+ struct frame ss_frame; /* original exception frame */
+ struct fpframe ss_fpstate; /* 68881/68882 state info */
+};
+
+/*
+ * WARNING: code in locore.s assumes the layout shown for sf_signum
+ * thru sf_handler so... don't screw with them!
+ */
+struct sigframe {
+ int sf_signum; /* signo for handler */
+ int sf_code; /* additional info for handler */
+ struct sigcontext *sf_scp; /* context ptr for handler */
+ sig_t sf_handler; /* handler addr for u_sigc */
+ struct sigstate sf_state; /* state of the hardware */
+ struct sigcontext sf_sc; /* actual context */
+};
+
+#ifdef COMPAT_HPUX
+struct hpuxsigcontext {
+ int hsc_syscall;
+ char hsc_action;
+ char hsc_pad1;
+ char hsc_pad2;
+ char hsc_onstack;
+ int hsc_mask;
+ int hsc_sp;
+ short hsc_ps;
+ int hsc_pc;
+/* the rest aren't part of the context but are included for our convenience */
+ short hsc_pad;
+ u_int hsc_magic; /* XXX sigreturn: cookie */
+ struct sigcontext *hsc_realsc; /* XXX sigreturn: ptr to BSD context */
+};
+
+/*
+ * For an HP-UX process, a partial hpuxsigframe follows the normal sigframe.
+ * Tremendous waste of space, but some HP-UX applications (e.g. LCL) need it.
+ */
+struct hpuxsigframe {
+ int hsf_signum;
+ int hsf_code;
+ struct sigcontext *hsf_scp;
+ struct hpuxsigcontext hsf_sc;
+ int hsf_regs[15];
+};
+#endif
+
+#ifdef DEBUG
+int sigdebug = 0;
+int sigpid = 0;
+#define SDB_FOLLOW 0x01
+#define SDB_KSTACK 0x02
+#define SDB_FPSTATE 0x04
+#endif
+
+/*
+ * Send an interrupt to process.
+ */
+void
+sendsig(catcher, sig, mask, code)
+ sig_t catcher;
+ int sig, mask;
+ u_long code;
+{
+ register struct proc *p = curproc;
+ register struct sigframe *fp, *kfp;
+ register struct frame *frame;
+ register struct sigacts *psp = p->p_sigacts;
+ register short ft;
+ int oonstack, fsize;
+ extern char sigcode[], esigcode[];
+
+ frame = (struct frame *)p->p_md.md_regs;
+ ft = frame->f_format;
+ oonstack = psp->ps_sigstk.ss_flags & SS_ONSTACK;
+ /*
+ * Allocate and validate space for the signal handler
+ * context. Note that if the stack is in P0 space, the
+ * call to grow() is a nop, and the useracc() check
+ * will fail if the process has not already allocated
+ * the space with a `brk'.
+ */
+#ifdef COMPAT_HPUX
+ if (p->p_emul == &emul_hpux)
+ fsize = sizeof(struct sigframe) + sizeof(struct hpuxsigframe);
+ else
+#endif
+ fsize = sizeof(struct sigframe);
+ if ((psp->ps_flags & SAS_ALTSTACK) && !oonstack &&
+ (psp->ps_sigonstack & sigmask(sig))) {
+ fp = (struct sigframe *)(psp->ps_sigstk.ss_base +
+ psp->ps_sigstk.ss_size - fsize);
+ psp->ps_sigstk.ss_flags |= SS_ONSTACK;
+ } else
+ fp = (struct sigframe *)(frame->f_regs[SP] - fsize);
+ if ((unsigned)fp <= USRSTACK - ctob(p->p_vmspace->vm_ssize))
+ (void)grow(p, (unsigned)fp);
+#ifdef DEBUG
+ if ((sigdebug & SDB_KSTACK) && p->p_pid == sigpid)
+ printf("sendsig(%d): sig %d ssp %x usp %x scp %x ft %d\n",
+ p->p_pid, sig, &oonstack, fp, &fp->sf_sc, ft);
+#endif
+ if (useracc((caddr_t)fp, fsize, B_WRITE) == 0) {
+#ifdef DEBUG
+ if ((sigdebug & SDB_KSTACK) && p->p_pid == sigpid)
+ printf("sendsig(%d): useracc failed on sig %d\n",
+ p->p_pid, sig);
+#endif
+ /*
+ * Process has trashed its stack; give it an illegal
+ * instruction to halt it in its tracks.
+ */
+ SIGACTION(p, SIGILL) = SIG_DFL;
+ sig = sigmask(SIGILL);
+ p->p_sigignore &= ~sig;
+ p->p_sigcatch &= ~sig;
+ p->p_sigmask &= ~sig;
+ psignal(p, SIGILL);
+ return;
+ }
+ kfp = (struct sigframe *)malloc((u_long)fsize, M_TEMP, M_WAITOK);
+ /*
+ * Build the argument list for the signal handler.
+ */
+ kfp->sf_signum = sig;
+ kfp->sf_code = code;
+ kfp->sf_scp = &fp->sf_sc;
+ kfp->sf_handler = catcher;
+ /*
+ * Save necessary hardware state. Currently this includes:
+ * - general registers
+ * - original exception frame (if not a "normal" frame)
+ * - FP coprocessor state
+ */
+ kfp->sf_state.ss_flags = SS_USERREGS;
+ bcopy((caddr_t)frame->f_regs,
+ (caddr_t)kfp->sf_state.ss_frame.f_regs, sizeof frame->f_regs);
+ if (ft >= FMT7) {
+#ifdef DEBUG
+ if (ft > 15 || exframesize[ft] < 0)
+ panic("sendsig: bogus frame type");
+#endif
+ kfp->sf_state.ss_flags |= SS_RTEFRAME;
+ kfp->sf_state.ss_frame.f_format = frame->f_format;
+ kfp->sf_state.ss_frame.f_vector = frame->f_vector;
+ bcopy((caddr_t)&frame->F_u,
+ (caddr_t)&kfp->sf_state.ss_frame.F_u, exframesize[ft]);
+ /*
+ * Leave an indicator that we need to clean up the kernel
+ * stack. We do this by setting the "pad word" above the
+ * hardware stack frame to the amount the stack must be
+ * adjusted by.
+ *
+ * N.B. we increment rather than just set f_stackadj in
+ * case we are called from syscall when processing a
+ * sigreturn. In that case, f_stackadj may be non-zero.
+ */
+ frame->f_stackadj += exframesize[ft];
+ frame->f_format = frame->f_vector = 0;
+#ifdef DEBUG
+ if (sigdebug & SDB_FOLLOW)
+ printf("sendsig(%d): copy out %d of frame %d\n",
+ p->p_pid, exframesize[ft], ft);
+#endif
+ }
+#ifdef FPCOPROC
+ kfp->sf_state.ss_flags |= SS_FPSTATE;
+ m68881_save(&kfp->sf_state.ss_fpstate);
+#ifdef DEBUG
+ if ((sigdebug & SDB_FPSTATE) && *(char *)&kfp->sf_state.ss_fpstate)
+ printf("sendsig(%d): copy out FP state (%x) to %x\n",
+ p->p_pid, *(u_int *)&kfp->sf_state.ss_fpstate,
+ &kfp->sf_state.ss_fpstate);
+#endif
+#endif
+ /*
+ * Build the signal context to be used by sigreturn.
+ */
+ kfp->sf_sc.sc_onstack = oonstack;
+ kfp->sf_sc.sc_mask = mask;
+ kfp->sf_sc.sc_sp = frame->f_regs[SP];
+ kfp->sf_sc.sc_fp = frame->f_regs[A6];
+ kfp->sf_sc.sc_ap = (int)&fp->sf_state;
+ kfp->sf_sc.sc_pc = frame->f_pc;
+ kfp->sf_sc.sc_ps = frame->f_sr;
+#ifdef COMPAT_HPUX
+ /*
+ * Create an HP-UX style sigcontext structure and associated goo
+ */
+ if (p->p_emul == &emul_hpux) {
+ register struct hpuxsigframe *hkfp;
+
+ hkfp = (struct hpuxsigframe *)&kfp[1];
+ hkfp->hsf_signum = bsdtohpuxsig(kfp->sf_signum);
+ hkfp->hsf_code = kfp->sf_code;
+ hkfp->hsf_scp = (struct sigcontext *)
+ &((struct hpuxsigframe *)(&fp[1]))->hsf_sc;
+ hkfp->hsf_sc.hsc_syscall = 0; /* XXX */
+ hkfp->hsf_sc.hsc_action = 0; /* XXX */
+ hkfp->hsf_sc.hsc_pad1 = hkfp->hsf_sc.hsc_pad2 = 0;
+ hkfp->hsf_sc.hsc_onstack = kfp->sf_sc.sc_onstack;
+ hkfp->hsf_sc.hsc_mask = kfp->sf_sc.sc_mask;
+ hkfp->hsf_sc.hsc_sp = kfp->sf_sc.sc_sp;
+ hkfp->hsf_sc.hsc_ps = kfp->sf_sc.sc_ps;
+ hkfp->hsf_sc.hsc_pc = kfp->sf_sc.sc_pc;
+ hkfp->hsf_sc.hsc_pad = 0;
+ hkfp->hsf_sc.hsc_magic = 0xdeadbeef;
+ hkfp->hsf_sc.hsc_realsc = kfp->sf_scp;
+ bcopy((caddr_t)frame->f_regs, (caddr_t)hkfp->hsf_regs,
+ sizeof (hkfp->hsf_regs));
+
+ kfp->sf_signum = hkfp->hsf_signum;
+ kfp->sf_scp = hkfp->hsf_scp;
+ }
+#endif
+ (void) copyout((caddr_t)kfp, (caddr_t)fp, fsize);
+ frame->f_regs[SP] = (int)fp;
+#ifdef DEBUG
+ if (sigdebug & SDB_FOLLOW)
+ printf("sendsig(%d): sig %d scp %x fp %x sc_sp %x sc_ap %x\n",
+ p->p_pid, sig, kfp->sf_scp, fp,
+ kfp->sf_sc.sc_sp, kfp->sf_sc.sc_ap);
+#endif
+ /*
+ * Signal trampoline code is at base of user stack.
+ */
+ frame->f_pc = (int)PS_STRINGS - (esigcode - sigcode);
+#ifdef DEBUG
+ if ((sigdebug & SDB_KSTACK) && p->p_pid == sigpid)
+ printf("sendsig(%d): sig %d returns\n",
+ p->p_pid, sig);
+#endif
+ free((caddr_t)kfp, M_TEMP);
+}
+
+/*
+ * System call to cleanup state after a signal
+ * has been taken. Reset signal mask and
+ * stack state from context left by sendsig (above).
+ * Return to previous pc and psl as specified by
+ * context left by sendsig. Check carefully to
+ * make sure that the user has not modified the
+ * psl to gain improper priviledges or to cause
+ * a machine fault.
+ */
+/* ARGSUSED */
+int
+sys_sigreturn(p, v, retval)
+ struct proc *p;
+ void *v;
+ register_t *retval;
+{
+ struct sys_sigreturn_args /* {
+ syscallarg(struct sigcontext *) sigcntxp;
+ } */ *uap = v;
+ register struct sigcontext *scp;
+ register struct frame *frame;
+ register int rf;
+ struct sigcontext tsigc;
+ struct sigstate tstate;
+ int flags;
+
+ scp = SCARG(uap, sigcntxp);
+#ifdef DEBUG
+ if (sigdebug & SDB_FOLLOW)
+ printf("sigreturn: pid %d, scp %x\n", p->p_pid, scp);
+#endif
+ if ((int)scp & 1)
+ return (EINVAL);
+#ifdef COMPAT_HPUX
+ /*
+ * Grab context as an HP-UX style context and determine if it
+ * was one that we contructed in sendsig.
+ */
+ if (p->p_emul == &emul_hpux) {
+ struct hpuxsigcontext *hscp = (struct hpuxsigcontext *)scp;
+ struct hpuxsigcontext htsigc;
+
+ if (useracc((caddr_t)hscp, sizeof (*hscp), B_WRITE) == 0 ||
+ copyin((caddr_t)hscp, (caddr_t)&htsigc, sizeof htsigc))
+ return (EINVAL);
+ /*
+ * If not generated by sendsig or we cannot restore the
+ * BSD-style sigcontext, just restore what we can -- state
+ * will be lost, but them's the breaks.
+ */
+ hscp = &htsigc;
+ if (hscp->hsc_magic != 0xdeadbeef ||
+ (scp = hscp->hsc_realsc) == 0 ||
+ useracc((caddr_t)scp, sizeof (*scp), B_WRITE) == 0 ||
+ copyin((caddr_t)scp, (caddr_t)&tsigc, sizeof tsigc)) {
+ if (hscp->hsc_onstack & 01)
+ p->p_sigacts->ps_sigstk.ss_flags |= SS_ONSTACK;
+ else
+ p->p_sigacts->ps_sigstk.ss_flags &= ~SS_ONSTACK;
+ p->p_sigmask = hscp->hsc_mask &~ sigcantmask;
+ frame = (struct frame *) p->p_md.md_regs;
+ frame->f_regs[SP] = hscp->hsc_sp;
+ frame->f_pc = hscp->hsc_pc;
+ frame->f_sr = hscp->hsc_ps &~ PSL_USERCLR;
+ return (EJUSTRETURN);
+ }
+ /*
+ * Otherwise, overlay BSD context with possibly modified
+ * HP-UX values.
+ */
+ tsigc.sc_onstack = hscp->hsc_onstack;
+ tsigc.sc_mask = hscp->hsc_mask;
+ tsigc.sc_sp = hscp->hsc_sp;
+ tsigc.sc_ps = hscp->hsc_ps;
+ tsigc.sc_pc = hscp->hsc_pc;
+ } else
+#endif
+ /*
+ * Test and fetch the context structure.
+ * We grab it all at once for speed.
+ */
+ if (useracc((caddr_t)scp, sizeof (*scp), B_WRITE) == 0 ||
+ copyin((caddr_t)scp, (caddr_t)&tsigc, sizeof tsigc))
+ return (EINVAL);
+ scp = &tsigc;
+ if ((scp->sc_ps & (PSL_MBZ|PSL_IPL|PSL_S)) != 0)
+ return (EINVAL);
+ /*
+ * Restore the user supplied information
+ */
+ if (scp->sc_onstack & 01)
+ p->p_sigacts->ps_sigstk.ss_flags |= SS_ONSTACK;
+ else
+ p->p_sigacts->ps_sigstk.ss_flags &= ~SS_ONSTACK;
+ p->p_sigmask = scp->sc_mask &~ sigcantmask;
+ frame = (struct frame *) p->p_md.md_regs;
+ frame->f_regs[SP] = scp->sc_sp;
+ frame->f_regs[A6] = scp->sc_fp;
+ frame->f_pc = scp->sc_pc;
+ frame->f_sr = scp->sc_ps;
+ /*
+ * Grab pointer to hardware state information.
+ * If zero, the user is probably doing a longjmp.
+ */
+ if ((rf = scp->sc_ap) == 0)
+ return (EJUSTRETURN);
+ /*
+ * See if there is anything to do before we go to the
+ * expense of copying in close to 1/2K of data
+ */
+ flags = fuword((caddr_t)rf);
+#ifdef DEBUG
+ if (sigdebug & SDB_FOLLOW)
+ printf("sigreturn(%d): sc_ap %x flags %x\n",
+ p->p_pid, rf, flags);
+#endif
+ /*
+ * fuword failed (bogus sc_ap value).
+ */
+ if (flags == -1)
+ return (EINVAL);
+ if (flags == 0 || copyin((caddr_t)rf, (caddr_t)&tstate, sizeof tstate))
+ return (EJUSTRETURN);
+#ifdef DEBUG
+ if ((sigdebug & SDB_KSTACK) && p->p_pid == sigpid)
+ printf("sigreturn(%d): ssp %x usp %x scp %x ft %d\n",
+ p->p_pid, &flags, scp->sc_sp, SCARG(uap, sigcntxp),
+ (flags&SS_RTEFRAME) ? tstate.ss_frame.f_format : -1);
+#endif
+ /*
+ * Restore most of the users registers except for A6 and SP
+ * which were handled above.
+ */
+ if (flags & SS_USERREGS)
+ bcopy((caddr_t)tstate.ss_frame.f_regs,
+ (caddr_t)frame->f_regs, sizeof(frame->f_regs)-2*NBPW);
+ /*
+ * Restore long stack frames. Note that we do not copy
+ * back the saved SR or PC, they were picked up above from
+ * the sigcontext structure.
+ */
+ if (flags & SS_RTEFRAME) {
+ register int sz;
+
+ /* grab frame type and validate */
+ sz = tstate.ss_frame.f_format;
+ if (sz > 15 || (sz = exframesize[sz]) < 0)
+ return (EINVAL);
+ frame->f_stackadj -= sz;
+ frame->f_format = tstate.ss_frame.f_format;
+ frame->f_vector = tstate.ss_frame.f_vector;
+ bcopy((caddr_t)&tstate.ss_frame.F_u, (caddr_t)&frame->F_u, sz);
+#ifdef DEBUG
+ if (sigdebug & SDB_FOLLOW)
+ printf("sigreturn(%d): copy in %d of frame type %d\n",
+ p->p_pid, sz, tstate.ss_frame.f_format);
+#endif
+ }
+#ifdef FPCOPROC
+ /*
+ * Finally we restore the original FP context
+ */
+ if (flags & SS_FPSTATE)
+ m68881_restore(&tstate.ss_fpstate);
+#ifdef DEBUG
+ if ((sigdebug & SDB_FPSTATE) && *(char *)&tstate.ss_fpstate)
+ printf("sigreturn(%d): copied in FP state (%x) at %x\n",
+ p->p_pid, *(u_int *)&tstate.ss_fpstate,
+ &tstate.ss_fpstate);
+#endif
+#endif
+#ifdef DEBUG
+ if ((sigdebug & SDB_FOLLOW) ||
+ ((sigdebug & SDB_KSTACK) && p->p_pid == sigpid))
+ printf("sigreturn(%d): returns\n", p->p_pid);
+#endif
+ return (EJUSTRETURN);
+}
+
+int waittime = -1;
+
+void
+boot(howto)
+ register int howto;
+{
+ /* take a snap shot before clobbering any registers */
+ if (curproc && curproc->p_addr)
+ savectx(curproc->p_addr);
+
+ boothowto = howto;
+ if ((howto&RB_NOSYNC) == 0 && waittime < 0) {
+ waittime = 0;
+ vfs_shutdown();
+ /*
+ * If we've been adjusting the clock, the todr
+ * will be out of synch; adjust it now.
+ */
+ resettodr();
+ }
+ splhigh(); /* extreme priority */
+ if (howto&RB_HALT) {
+ printf("halted\n\n");
+ doboot(RB_HALT);
+ /*NOTREACHED*/
+ } else {
+ if (howto & RB_DUMP)
+ dumpsys();
+ doboot(RB_AUTOBOOT);
+ /*NOTREACHED*/
+ }
+ /*NOTREACHED*/
+}
+
+/*
+ * These variables are needed by /sbin/savecore
+ */
+u_long dumpmag = 0x8fca0101; /* magic number */
+int dumpsize = 0; /* pages */
+long dumplo = 0; /* blocks */
+
+/*
+ * This is called by configure to set dumplo and dumpsize.
+ * Dumps always skip the first CLBYTES of disk space
+ * in case there might be a disk label stored there.
+ * If there is extra space, put dump at the end to
+ * reduce the chance that swapping trashes it.
+ */
+void
+dumpconf()
+{
+ int nblks; /* size of dump area */
+ int maj;
+
+ if (dumpdev == NODEV)
+ return;
+ maj = major(dumpdev);
+ if (maj < 0 || maj >= nblkdev)
+ panic("dumpconf: bad dumpdev=0x%x", dumpdev);
+ if (bdevsw[maj].d_psize == NULL)
+ return;
+ nblks = (*bdevsw[maj].d_psize)(dumpdev);
+ if (nblks <= ctod(1))
+ return;
+
+ /*
+ * XXX include the final RAM page which is not included in physmem.
+ */
+ dumpsize = physmem + 1;
+
+ /* Always skip the first CLBYTES, in case there is a label there. */
+ if (dumplo < ctod(1))
+ dumplo = ctod(1);
+
+ /* Put dump at end of partition, and make it fit. */
+ if (dumpsize > dtoc(nblks - dumplo))
+ dumpsize = dtoc(nblks - dumplo);
+ if (dumplo < nblks - ctod(dumpsize))
+ dumplo = nblks - ctod(dumpsize);
+}
+
+/*
+ * Doadump comes here after turning off memory management and
+ * getting on the dump stack, either when called above, or by
+ * the auto-restart code.
+ */
+dumpsys()
+{
+
+ msgbufmapped = 0;
+ if (dumpdev == NODEV)
+ return;
+ if (dumpsize == 0) {
+ dumpconf();
+ if (dumpsize == 0)
+ return;
+ }
+ printf("\ndumping to dev %x, offset %d\n", dumpdev, dumplo);
+
+ printf("dump ");
+ switch ((*bdevsw[major(dumpdev)].d_dump)(dumpdev)) {
+
+ case ENXIO:
+ printf("device bad\n");
+ break;
+
+ case EFAULT:
+ printf("device not ready\n");
+ break;
+
+ case EINVAL:
+ printf("area improper\n");
+ break;
+
+ case EIO:
+ printf("i/o error\n");
+ break;
+
+ case EINTR:
+ printf("aborted from console\n");
+ break;
+
+ default:
+ printf("succeeded\n");
+ break;
+ }
+}
+
+initcpu()
+{
+#ifdef MAPPEDCOPY
+ extern u_int mappedcopysize;
+
+ /*
+ * Initialize lower bound for doing copyin/copyout using
+ * page mapping (if not already set). We don't do this on
+ * VAC machines as it loses big time.
+ */
+ if (mappedcopysize == 0) {
+ mappedcopysize = NBPG;
+ }
+#endif
+}
+
+straytrap(pc, evec)
+ int pc;
+ u_short evec;
+{
+ printf("unexpected trap (vector offset %x) from %x\n",
+ evec & 0xFFF, pc);
+}
+
+int *nofault;
+
+badaddr(addr)
+ register caddr_t addr;
+{
+ register int i;
+ label_t faultbuf;
+
+#ifdef lint
+ i = *addr; if (i) return(0);
+#endif
+ nofault = (int *) &faultbuf;
+ if (setjmp((label_t *)nofault)) {
+ nofault = (int *) 0;
+ return(1);
+ }
+ i = *(volatile short *)addr;
+ nofault = (int *) 0;
+ return(0);
+}
+
+badbaddr(addr)
+ register caddr_t addr;
+{
+ register int i;
+ label_t faultbuf;
+
+#ifdef lint
+ i = *addr; if (i) return(0);
+#endif
+ nofault = (int *) &faultbuf;
+ if (setjmp((label_t *)nofault)) {
+ nofault = (int *) 0;
+ return(1);
+ }
+ i = *(volatile char *)addr;
+ nofault = (int *) 0;
+ return(0);
+}
+
+netintr()
+{
+#ifdef INET
+ if (netisr & (1 << NETISR_ARP)) {
+ netisr &= ~(1 << NETISR_ARP);
+ arpintr();
+ }
+ 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
+#ifdef CCITT
+ if (netisr & (1 << NETISR_CCITT)) {
+ netisr &= ~(1 << NETISR_CCITT);
+ ccittintr();
+ }
+#endif
+#include "ppp.h"
+#if NPPP > 0
+ if (netisr & (1 << NETISR_PPP)) {
+ netisr &= ~(1 << NETISR_PPP);
+ pppintr();
+ }
+#endif
+}
+
+intrhand(sr)
+ int sr;
+{
+ register struct isr *isr;
+ register int found = 0;
+ register int ipl;
+ extern struct isr isrqueue[];
+ static int straycount;
+
+ ipl = (sr >> 8) & 7;
+printf("intrhand\n");
+ switch (ipl) {
+
+ case 1:
+ case 2:
+ case 3:
+ case 4:
+ case 5:
+ case 6:
+ 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)
+ straycount = 0;
+ else if (++straycount > 50)
+ panic("intrhand: stray interrupt");
+ else
+ printf("stray interrupt, sr 0x%x\n", sr);
+ break;
+
+ case 0:
+ case 7:
+ if (++straycount > 50)
+ panic("intrhand: unexpected sr");
+ else
+ printf("intrhand: unexpected sr 0x%x\n", sr);
+ break;
+ }
+}
+
+#if (defined(DDB) || defined(DEBUG)) && !defined(PANICBUTTON)
+#define PANICBUTTON
+#endif
+
+#ifdef PANICBUTTON
+int panicbutton = 1; /* non-zero if panic buttons are enabled */
+int crashandburn = 0;
+int candbdelay = 50; /* give em half a second */
+
+void
+candbtimer(arg)
+ void *arg;
+{
+
+ crashandburn = 0;
+}
+#endif
+
+/*
+ * Level 7 interrupts can't be caused by anything
+ */
+nmihand(frame)
+ struct frame frame;
+{
+ /* panic?? */
+ printf("unexpected level 7 interrupt ignored\n");
+}
+
+regdump(fp, sbytes)
+ struct frame *fp; /* must not be register */
+ int sbytes;
+{
+ static int doingdump = 0;
+ register int i;
+ int s;
+ extern char *hexstr();
+
+ if (doingdump)
+ return;
+ s = splhigh();
+ doingdump = 1;
+ printf("pid = %d, pc = %s, ",
+ curproc ? curproc->p_pid : -1, hexstr(fp->f_pc, 8));
+ printf("ps = %s, ", hexstr(fp->f_sr, 4));
+ printf("sfc = %s, ", hexstr(getsfc(), 4));
+ printf("dfc = %s\n", hexstr(getdfc(), 4));
+ printf("Registers:\n ");
+ for (i = 0; i < 8; i++)
+ printf(" %d", i);
+ printf("\ndreg:");
+ for (i = 0; i < 8; i++)
+ printf(" %s", hexstr(fp->f_regs[i], 8));
+ printf("\nareg:");
+ for (i = 0; i < 8; i++)
+ printf(" %s", hexstr(fp->f_regs[i+8], 8));
+ if (sbytes > 0) {
+ if (fp->f_sr & PSL_S) {
+ printf("\n\nKernel stack (%s):",
+ hexstr((int)(((int *)&fp)-1), 8));
+ dumpmem(((int *)&fp)-1, sbytes, 0);
+ } else {
+ printf("\n\nUser stack (%s):", hexstr(fp->f_regs[SP], 8));
+ dumpmem((int *)fp->f_regs[SP], sbytes, 1);
+ }
+ }
+ doingdump = 0;
+ splx(s);
+}
+
+#define KSADDR ((int *)((u_int)curproc->p_addr + USPACE - NBPG))
+
+dumpmem(ptr, sz, ustack)
+ register int *ptr;
+ int sz, ustack;
+{
+ register int i, val;
+ extern char *hexstr();
+
+ for (i = 0; i < sz; i++) {
+ if ((i & 7) == 0)
+ printf("\n%s: ", hexstr((int)ptr, 6));
+ else
+ printf(" ");
+ if (ustack == 1) {
+ if ((val = fuword(ptr++)) == -1)
+ break;
+ } else {
+ if (ustack == 0 &&
+ (ptr < KSADDR || ptr > KSADDR+(NBPG/4-1)))
+ break;
+ val = *ptr++;
+ }
+ printf("%s", hexstr(val, 8));
+ }
+ printf("\n");
+}
+
+char *
+hexstr(val, len)
+ register int val;
+ int len;
+{
+ static char nbuf[9];
+ register int x, i;
+
+ if (len > 8)
+ return("");
+ nbuf[len] = '\0';
+ for (i = len-1; i >= 0; --i) {
+ x = val & 0xF;
+ if (x > 9)
+ nbuf[i] = x - 10 + 'A';
+ else
+ nbuf[i] = x + '0';
+ val >>= 4;
+ }
+ return(nbuf);
+}
+
+#ifdef STACKCHECK
+char oflowmsg[] = "k-stack overflow";
+char uflowmsg[] = "k-stack underflow";
+
+badkstack(oflow, fr)
+ int oflow;
+ struct frame fr;
+{
+ extern char kstackatbase[];
+
+ printf("%s: sp should be %x\n",
+ oflow ? oflowmsg : uflowmsg,
+ kstackatbase - (exframesize[fr.f_format] + 8));
+ regdump(&fr, 0);
+ panic(oflow ? oflowmsg : uflowmsg);
+}
+#endif
+
+/*
+ * cpu_exec_aout_makecmds():
+ * cpu-dependent a.out format hook for execve().
+ *
+ * Determine of the given exec package refers to something which we
+ * understand and, if so, set up the vmcmds for it.
+ */
+cpu_exec_aout_makecmds(p, epp)
+ struct proc *p;
+ struct exec_package *epp;
+{
+ int error = ENOEXEC;
+#ifdef COMPAT_SUNOS
+ extern sunos_exec_aout_makecmds
+ __P((struct proc *, struct exec_package *));
+ if ((error = sunos_exec_aout_makecmds(p, epp)) == 0)
+ return 0;
+#endif
+ return error;
+}
+
+void
+myetheraddr(ether)
+ char *ether;
+{
+ int e = myea;
+
+ ether[0] = 0x08;
+ ether[1] = 0x00;
+ ether[2] = 0x3e;
+ e = e >> 8;
+ ether[5] = e & 0xff;
+ e = e >> 8;
+ ether[4] = e & 0xff;
+ e = e >> 8;
+ ether[3] = e;
+}
diff --git a/sys/arch/mvme68k/mvme68k/mainbus.c b/sys/arch/mvme68k/mvme68k/mainbus.c
new file mode 100644
index 00000000000..484e37d9580
--- /dev/null
+++ b/sys/arch/mvme68k/mvme68k/mainbus.c
@@ -0,0 +1,29 @@
+void mainbus_attach __P((struct device *, struct device *, void *));
+int mainbus_match __P((struct device *, void *, void *));
+
+struct mainbus_softc {
+ struct device sc_dev;
+};
+
+struct cfdriver mainbus_cd = {
+ NULL, "mainbus_", mainbus_match, mainbus_attach,
+ DV_DULL, sizeof(struct mainbus_softc), 0
+};
+
+int
+mainbus_match(parent, cf, args)
+ struct device *parent;
+ void *cf;
+ void *args;
+{
+ return 1;
+}
+
+void
+mainbus_attach(parent, self, args)
+ struct device *parent, *self;
+ void *args;
+{
+ while (config_found(self, NULL, NULL))
+ ;
+}
diff --git a/sys/arch/mvme68k/mvme68k/mem.c b/sys/arch/mvme68k/mvme68k/mem.c
new file mode 100644
index 00000000000..52d8123a24c
--- /dev/null
+++ b/sys/arch/mvme68k/mvme68k/mem.c
@@ -0,0 +1,222 @@
+/* $NetBSD: mem.c,v 1.1.1.1 1995/07/25 23:11:58 chuck Exp $ */
+
+/*
+ * Copyright (c) 1988 University of Utah.
+ * Copyright (c) 1982, 1986, 1990, 1993
+ * 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.
+ *
+ * @(#)mem.c 8.3 (Berkeley) 1/12/94
+ */
+
+/*
+ * Memory special file
+ */
+
+#include <sys/param.h>
+#include <sys/conf.h>
+#include <sys/buf.h>
+#include <sys/systm.h>
+#include <sys/uio.h>
+#include <sys/malloc.h>
+
+#include <machine/cpu.h>
+
+#include <vm/vm.h>
+
+extern u_int lowram;
+caddr_t zeropage;
+
+/*ARGSUSED*/
+int
+mmopen(dev, flag, mode)
+ dev_t dev;
+ int flag, mode;
+{
+
+ return (0);
+}
+
+/*ARGSUSED*/
+int
+mmclose(dev, flag, mode)
+ dev_t dev;
+ int flag, mode;
+{
+
+ return (0);
+}
+
+/*ARGSUSED*/
+int
+mmrw(dev, uio, flags)
+ dev_t dev;
+ struct uio *uio;
+ int flags;
+{
+ register vm_offset_t o, v;
+ register int c;
+ register struct iovec *iov;
+ int error = 0;
+ static int physlock;
+
+ if (minor(dev) == 0) {
+ /* lock against other uses of shared vmmap */
+ while (physlock > 0) {
+ physlock++;
+ error = tsleep((caddr_t)&physlock, PZERO | PCATCH,
+ "mmrw", 0);
+ if (error)
+ return (error);
+ }
+ physlock = 1;
+ }
+ while (uio->uio_resid > 0 && error == 0) {
+ iov = uio->uio_iov;
+ if (iov->iov_len == 0) {
+ uio->uio_iov++;
+ uio->uio_iovcnt--;
+ if (uio->uio_iovcnt < 0)
+ panic("mmrw");
+ continue;
+ }
+ switch (minor(dev)) {
+
+/* minor device 0 is physical memory */
+ case 0:
+ v = uio->uio_offset;
+#ifndef DEBUG
+ /* allow reads only in RAM (except for DEBUG) */
+ if (v >= 0xFFFFFFFC || v < lowram) {
+ error = EFAULT;
+ goto unlock;
+ }
+#endif
+ pmap_enter(pmap_kernel(), (vm_offset_t)vmmap,
+ trunc_page(v), uio->uio_rw == UIO_READ ?
+ VM_PROT_READ : VM_PROT_WRITE, TRUE);
+ o = uio->uio_offset & PGOFSET;
+ c = min(uio->uio_resid, (int)(NBPG - o));
+ error = uiomove((caddr_t)vmmap + o, c, uio);
+ pmap_remove(pmap_kernel(), (vm_offset_t)vmmap,
+ (vm_offset_t)vmmap + NBPG);
+ continue;
+
+/* minor device 1 is kernel memory */
+ case 1:
+ v = uio->uio_offset;
+ c = min(iov->iov_len, MAXPHYS);
+ if (!kernacc((caddr_t)v, c,
+ uio->uio_rw == UIO_READ ? B_READ : B_WRITE))
+ return (EFAULT);
+ error = uiomove((caddr_t)v, c, uio);
+ continue;
+
+/* minor device 2 is EOF/RATHOLE */
+ case 2:
+ if (uio->uio_rw == UIO_WRITE)
+ uio->uio_resid = 0;
+ return (0);
+
+/* minor device 12 (/dev/zero) is source of nulls on read, rathole on write */
+ case 12:
+ if (uio->uio_rw == UIO_WRITE) {
+ c = iov->iov_len;
+ break;
+ }
+ /*
+ * On the first call, allocate and zero a page
+ * of memory for use with /dev/zero.
+ *
+ * XXX on the hp300 we already know where there
+ * is a global zeroed page, the null segment table.
+ */
+ if (zeropage == NULL) {
+#if CLBYTES == NBPG
+ extern caddr_t Segtabzero;
+ zeropage = Segtabzero;
+#else
+ zeropage = (caddr_t)
+ malloc(CLBYTES, M_TEMP, M_WAITOK);
+ bzero(zeropage, CLBYTES);
+#endif
+ }
+ c = min(iov->iov_len, CLBYTES);
+ error = uiomove(zeropage, c, uio);
+ continue;
+
+ default:
+ return (ENXIO);
+ }
+ if (error)
+ break;
+ iov->iov_base += c;
+ iov->iov_len -= c;
+ uio->uio_offset += c;
+ uio->uio_resid -= c;
+ }
+ if (minor(dev) == 0) {
+unlock:
+ if (physlock > 1)
+ wakeup((caddr_t)&physlock);
+ physlock = 0;
+ }
+ return (error);
+}
+
+int
+mmmmap(dev, off, prot)
+ dev_t dev;
+ int off, prot;
+{
+ /*
+ * /dev/mem is the only one that makes sense through this
+ * interface. For /dev/kmem any physaddr we return here
+ * could be transient and hence incorrect or invalid at
+ * a later time. /dev/null just doesn't make any sense
+ * and /dev/zero is a hack that is handled via the default
+ * pager in mmap().
+ */
+ if (minor(dev) != 0)
+ return (-1);
+ /*
+ * Allow access only in RAM.
+ *
+ * XXX could be extended to allow access to IO space but must
+ * be very careful.
+ */
+ if ((unsigned)off < lowram || (unsigned)off >= 0xFFFFFFFC)
+ return (-1);
+ return (m68k_btop(off));
+}
diff --git a/sys/arch/mvme68k/mvme68k/pmap.c b/sys/arch/mvme68k/mvme68k/pmap.c
new file mode 100644
index 00000000000..08f720028f3
--- /dev/null
+++ b/sys/arch/mvme68k/mvme68k/pmap.c
@@ -0,0 +1,2659 @@
+/* $NetBSD: pmap.c,v 1.1.1.1.2.1 1995/10/12 20:01:16 chuck Exp $ */
+
+/*
+ * Copyright (c) 1991, 1993
+ * 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.
+ *
+ * @(#)pmap.c 8.6 (Berkeley) 5/27/94
+ */
+
+/*
+ * HP9000/300 series physical map management code.
+ *
+ * Supports:
+ * 68020 with HP MMU models 320, 350
+ * 68020 with 68551 MMU models 318, 319, 330 (all untested)
+ * 68030 with on-chip MMU models 340, 360, 370, 345, 375, 400
+ * 68040 with on-chip MMU models 380, 425, 433
+ *
+ * Notes:
+ * Don't even pay lip service to multiprocessor support.
+ *
+ * We assume TLB entries don't have process tags (except for the
+ * supervisor/user distinction) so we only invalidate TLB entries
+ * when changing mappings for the current (or kernel) pmap. This is
+ * technically not true for the 68551 but we flush the TLB on every
+ * context switch, so it effectively winds up that way.
+ *
+ * Bitwise and/or operations are significantly faster than bitfield
+ * references so we use them when accessing STE/PTEs in the pmap_pte_*
+ * macros. Note also that the two are not always equivalent; e.g.:
+ * (*pte & PG_PROT) [4] != pte->pg_prot [1]
+ * and a couple of routines that deal with protection and wiring take
+ * some shortcuts that assume the and/or definitions.
+ *
+ * This implementation will only work for PAGE_SIZE == NBPG
+ * (i.e. 4096 bytes).
+ */
+
+/*
+ * Manages physical address maps.
+ *
+ * In addition to hardware address maps, this
+ * module is called upon to provide software-use-only
+ * maps which may or may not be stored in the same
+ * form as hardware maps. These pseudo-maps are
+ * used to store intermediate results from copy
+ * operations to and from address spaces.
+ *
+ * Since the information managed by this module is
+ * also stored by the logical address mapping module,
+ * this module may throw away valid virtual-to-physical
+ * mappings at almost any time. However, invalidations
+ * of virtual-to-physical mappings must be done as
+ * requested.
+ *
+ * In order to cope with hardware architectures which
+ * make virtual-to-physical map invalidates expensive,
+ * this module may delay invalidate or reduced protection
+ * operations until such time as they are actually
+ * necessary. This module is given full information as
+ * to which processors are currently using which maps,
+ * and to when physical maps must be made correct.
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/proc.h>
+#include <sys/malloc.h>
+#include <sys/user.h>
+
+#include <machine/pte.h>
+
+#include <vm/vm.h>
+#include <vm/vm_kern.h>
+#include <vm/vm_page.h>
+
+#include <machine/cpu.h>
+
+#ifdef PMAPSTATS
+struct {
+ int collectscans;
+ int collectpages;
+ int kpttotal;
+ int kptinuse;
+ int kptmaxuse;
+} kpt_stats;
+struct {
+ int kernel; /* entering kernel mapping */
+ int user; /* entering user mapping */
+ int ptpneeded; /* needed to allocate a PT page */
+ int nochange; /* no change at all */
+ int pwchange; /* no mapping change, just wiring or protection */
+ int wchange; /* no mapping change, just wiring */
+ int pchange; /* no mapping change, just protection */
+ int mchange; /* was mapped but mapping to different page */
+ int managed; /* a managed page */
+ int firstpv; /* first mapping for this PA */
+ int secondpv; /* second mapping for this PA */
+ int ci; /* cache inhibited */
+ int unmanaged; /* not a managed page */
+ int flushes; /* cache flushes */
+} enter_stats;
+struct {
+ int calls;
+ int removes;
+ int pvfirst;
+ int pvsearch;
+ int ptinvalid;
+ int uflushes;
+ int sflushes;
+} remove_stats;
+struct {
+ int calls;
+ int changed;
+ int alreadyro;
+ int alreadyrw;
+} protect_stats;
+struct chgstats {
+ int setcalls;
+ int sethits;
+ int setmiss;
+ int clrcalls;
+ int clrhits;
+ int clrmiss;
+} changebit_stats[16];
+#endif
+
+#ifdef DEBUG
+int debugmap = 0;
+int pmapdebug = 0x2000;
+#define PDB_FOLLOW 0x0001
+#define PDB_INIT 0x0002
+#define PDB_ENTER 0x0004
+#define PDB_REMOVE 0x0008
+#define PDB_CREATE 0x0010
+#define PDB_PTPAGE 0x0020
+#define PDB_CACHE 0x0040
+#define PDB_BITS 0x0080
+#define PDB_COLLECT 0x0100
+#define PDB_PROTECT 0x0200
+#define PDB_SEGTAB 0x0400
+#define PDB_MULTIMAP 0x0800
+#define PDB_PARANOIA 0x2000
+#define PDB_WIRING 0x4000
+#define PDB_PVDUMP 0x8000
+
+#ifdef HAVEVAC
+int pmapvacflush = 0;
+#define PVF_ENTER 0x01
+#define PVF_REMOVE 0x02
+#define PVF_PROTECT 0x04
+#define PVF_TOTAL 0x80
+#endif
+
+#if defined(M68040)
+int dowriteback = 1; /* 68040: enable writeback caching */
+int dokwriteback = 1; /* 68040: enable writeback caching of kernel AS */
+#endif
+
+extern vm_offset_t pager_sva, pager_eva;
+#endif
+
+/*
+ * Get STEs and PTEs for user/kernel address space
+ */
+#if defined(M68040)
+#define pmap_ste1(m, v) \
+ (&((m)->pm_stab[(vm_offset_t)(v) >> SG4_SHIFT1]))
+/* XXX assumes physically contiguous ST pages (if more than one) */
+#define pmap_ste2(m, v) \
+ (&((m)->pm_stab[(st_entry_t *)(*(u_int *)pmap_ste1(m, v) & SG4_ADDR1) \
+ - (m)->pm_stpa + (((v) & SG4_MASK2) >> SG4_SHIFT2)]))
+#define pmap_ste(m, v) \
+ (&((m)->pm_stab[(vm_offset_t)(v) \
+ >> (mmutype == MMU_68040 ? SG4_SHIFT1 : SG_ISHIFT)]))
+#define pmap_ste_v(m, v) \
+ (mmutype == MMU_68040 \
+ ? ((*pmap_ste1(m, v) & SG_V) && \
+ (*pmap_ste2(m, v) & SG_V)) \
+ : (*pmap_ste(m, v) & SG_V))
+#else
+#define pmap_ste(m, v) (&((m)->pm_stab[(vm_offset_t)(v) >> SG_ISHIFT]))
+#define pmap_ste_v(m, v) (*pmap_ste(m, v) & SG_V)
+#endif
+
+#define pmap_pte(m, v) (&((m)->pm_ptab[(vm_offset_t)(v) >> PG_SHIFT]))
+#define pmap_pte_pa(pte) (*(pte) & PG_FRAME)
+#define pmap_pte_w(pte) (*(pte) & PG_W)
+#define pmap_pte_ci(pte) (*(pte) & PG_CI)
+#define pmap_pte_m(pte) (*(pte) & PG_M)
+#define pmap_pte_u(pte) (*(pte) & PG_U)
+#define pmap_pte_prot(pte) (*(pte) & PG_PROT)
+#define pmap_pte_v(pte) (*(pte) & PG_V)
+
+#define pmap_pte_set_w(pte, v) \
+ if (v) *(pte) |= PG_W; else *(pte) &= ~PG_W
+#define pmap_pte_set_prot(pte, v) \
+ if (v) *(pte) |= PG_PROT; else *(pte) &= ~PG_PROT
+#define pmap_pte_w_chg(pte, nw) ((nw) ^ pmap_pte_w(pte))
+#define pmap_pte_prot_chg(pte, np) ((np) ^ pmap_pte_prot(pte))
+
+/*
+ * Given a map and a machine independent protection code,
+ * convert to an m68k protection code.
+ */
+#define pte_prot(m, p) (protection_codes[p])
+int protection_codes[8];
+
+/*
+ * Kernel page table page management.
+ */
+struct kpt_page {
+ struct kpt_page *kpt_next; /* link on either used or free list */
+ vm_offset_t kpt_va; /* always valid kernel VA */
+ vm_offset_t kpt_pa; /* PA of this page (for speed) */
+};
+struct kpt_page *kpt_free_list, *kpt_used_list;
+struct kpt_page *kpt_pages;
+
+/*
+ * Kernel segment/page table and page table map.
+ * The page table map gives us a level of indirection we need to dynamically
+ * expand the page table. It is essentially a copy of the segment table
+ * with PTEs instead of STEs. All are initialized in locore at boot time.
+ * Sysmap will initially contain VM_KERNEL_PT_PAGES pages of PTEs.
+ * Segtabzero is an empty segment table which all processes share til they
+ * reference something.
+ */
+st_entry_t *Sysseg;
+pt_entry_t *Sysmap, *Sysptmap;
+st_entry_t *Segtabzero, *Segtabzeropa;
+vm_size_t Sysptsize = VM_KERNEL_PT_PAGES;
+
+struct pmap kernel_pmap_store;
+vm_map_t st_map, pt_map;
+
+vm_offset_t avail_start; /* PA of first available physical page */
+vm_offset_t avail_end; /* PA of last available physical page */
+vm_size_t mem_size; /* memory size in bytes */
+vm_offset_t virtual_avail; /* VA of first avail page (after kernel bss)*/
+vm_offset_t virtual_end; /* VA of last avail page (end of kernel AS) */
+vm_offset_t vm_first_phys; /* PA of first managed page */
+vm_offset_t vm_last_phys; /* PA just past last managed page */
+int npages;
+
+boolean_t pmap_initialized = FALSE; /* Has pmap_init completed? */
+struct pv_entry *pv_table;
+char *pmap_attributes; /* reference and modify bits */
+TAILQ_HEAD(pv_page_list, pv_page) pv_page_freelist;
+int pv_nfree;
+
+#ifdef HAVEVAC
+int pmap_aliasmask; /* seperation at which VA aliasing ok */
+#endif
+#if defined(M68040)
+int protostfree; /* prototype (default) free ST map */
+#endif
+
+/*
+ * Internal routines
+ */
+void pmap_remove_mapping __P((pmap_t, vm_offset_t, pt_entry_t *, int));
+boolean_t pmap_testbit __P((vm_offset_t, int));
+void pmap_changebit __P((vm_offset_t, int, boolean_t));
+void pmap_enter_ptpage __P((pmap_t, vm_offset_t));
+#ifdef DEBUG
+void pmap_pvdump __P((vm_offset_t));
+void pmap_check_wiring __P((char *, vm_offset_t));
+#endif
+
+/* pmap_remove_mapping flags */
+#define PRM_TFLUSH 1
+#define PRM_CFLUSH 2
+
+/*
+ * Bootstrap memory allocator. This function allows for early dynamic
+ * memory allocation until the virtual memory system has been bootstrapped.
+ * After that point, either kmem_alloc or malloc should be used. This
+ * function works by stealing pages from the (to be) managed page pool,
+ * stealing virtual address space, then mapping the pages and zeroing them.
+ *
+ * It should be used from pmap_bootstrap till vm_page_startup, afterwards
+ * it cannot be used, and will generate a panic if tried. Note that this
+ * memory will never be freed, and in essence it is wired down.
+ */
+void *
+pmap_bootstrap_alloc(size)
+ int size;
+{
+ extern boolean_t vm_page_startup_initialized;
+ vm_offset_t val;
+
+ if (vm_page_startup_initialized)
+ panic("pmap_bootstrap_alloc: called after startup initialized");
+ size = round_page(size);
+ val = virtual_avail;
+
+ virtual_avail = pmap_map(virtual_avail, avail_start,
+ avail_start + size, VM_PROT_READ|VM_PROT_WRITE);
+ avail_start += size;
+
+ bzero ((caddr_t) val, size);
+ return ((void *) val);
+}
+
+/*
+ * Initialize the pmap module.
+ * Called by vm_init, to initialize any structures that the pmap
+ * system needs to map virtual memory.
+ */
+void
+pmap_init(phys_start, phys_end)
+ vm_offset_t phys_start, phys_end;
+{
+ vm_offset_t addr, addr2;
+ vm_size_t s;
+ int rv;
+
+#ifdef DEBUG
+ if (pmapdebug & PDB_FOLLOW)
+ printf("pmap_init(%x, %x)\n", phys_start, phys_end);
+#endif
+ /*
+ * Now that kernel map has been allocated, we can mark as
+ * unavailable regions which we have mapped in locore.
+ */
+ addr = (vm_offset_t) intiobase;
+ (void) vm_map_find(kernel_map, NULL, (vm_offset_t) 0,
+ &addr, m68k_ptob(IIOMAPSIZE+EIOMAPSIZE), FALSE);
+ if (addr != (vm_offset_t)intiobase)
+ goto bogons;
+ addr = (vm_offset_t) Sysmap;
+ vm_object_reference(kernel_object);
+ (void) vm_map_find(kernel_map, kernel_object, addr,
+ &addr, HP_MAX_PTSIZE, FALSE);
+ /*
+ * If this fails it is probably because the static portion of
+ * the kernel page table isn't big enough and we overran the
+ * page table map. Need to adjust pmap_size() in m68k_init.c.
+ */
+ if (addr != (vm_offset_t)Sysmap)
+bogons:
+ panic("pmap_init: bogons in the VM system!\n");
+
+#ifdef DEBUG
+ if (pmapdebug & PDB_INIT) {
+ printf("pmap_init: Sysseg %x, Sysmap %x, Sysptmap %x\n",
+ Sysseg, Sysmap, Sysptmap);
+ printf(" pstart %x, pend %x, vstart %x, vend %x\n",
+ avail_start, avail_end, virtual_avail, virtual_end);
+ }
+#endif
+
+ /*
+ * Allocate memory for random pmap data structures. Includes the
+ * initial segment table, pv_head_table and pmap_attributes.
+ */
+ npages = atop(phys_end - phys_start);
+ s = (vm_size_t) (HP_STSIZE + sizeof(struct pv_entry) * npages + npages);
+ s = round_page(s);
+ addr = (vm_offset_t) kmem_alloc(kernel_map, s);
+ Segtabzero = (st_entry_t *) addr;
+ Segtabzeropa = (st_entry_t *) pmap_extract(pmap_kernel(), addr);
+ addr += HP_STSIZE;
+ pv_table = (struct pv_entry *) addr;
+ addr += sizeof(struct pv_entry) * npages;
+ pmap_attributes = (char *) addr;
+#ifdef DEBUG
+ if (pmapdebug & PDB_INIT)
+ printf("pmap_init: %x bytes: npages %x s0 %x(%x) tbl %x atr %x\n",
+ s, npages, Segtabzero, Segtabzeropa,
+ pv_table, pmap_attributes);
+#endif
+
+ /*
+ * Allocate physical memory for kernel PT pages and their management.
+ * We need 1 PT page per possible task plus some slop.
+ */
+ npages = min(atop(HP_MAX_KPTSIZE), maxproc+16);
+ s = ptoa(npages) + round_page(npages * sizeof(struct kpt_page));
+
+ /*
+ * Verify that space will be allocated in region for which
+ * we already have kernel PT pages.
+ */
+ addr = 0;
+ rv = vm_map_find(kernel_map, NULL, 0, &addr, s, TRUE);
+ if (rv != KERN_SUCCESS || addr + s >= (vm_offset_t)Sysmap)
+ panic("pmap_init: kernel PT too small");
+ vm_map_remove(kernel_map, addr, addr + s);
+
+ /*
+ * Now allocate the space and link the pages together to
+ * form the KPT free list.
+ */
+ addr = (vm_offset_t) kmem_alloc(kernel_map, s);
+ s = ptoa(npages);
+ addr2 = addr + s;
+ kpt_pages = &((struct kpt_page *)addr2)[npages];
+ kpt_free_list = (struct kpt_page *) 0;
+ do {
+ addr2 -= NBPG;
+ (--kpt_pages)->kpt_next = kpt_free_list;
+ kpt_free_list = kpt_pages;
+ kpt_pages->kpt_va = addr2;
+ kpt_pages->kpt_pa = pmap_extract(pmap_kernel(), addr2);
+ } while (addr != addr2);
+#ifdef PMAPSTATS
+ kpt_stats.kpttotal = atop(s);
+#endif
+#ifdef DEBUG
+ if (pmapdebug & PDB_INIT)
+ printf("pmap_init: KPT: %d pages from %x to %x\n",
+ atop(s), addr, addr + s);
+#endif
+
+ /*
+ * Allocate the segment table map
+ */
+ s = maxproc * HP_STSIZE;
+ st_map = kmem_suballoc(kernel_map, &addr, &addr2, s, TRUE);
+
+ /*
+ * Slightly modified version of kmem_suballoc() to get page table
+ * map where we want it.
+ */
+ addr = HP_PTBASE;
+ s = min(HP_PTMAXSIZE, maxproc*HP_MAX_PTSIZE);
+ addr2 = addr + s;
+ rv = vm_map_find(kernel_map, NULL, 0, &addr, s, TRUE);
+ if (rv != KERN_SUCCESS)
+ panic("pmap_init: cannot allocate space for PT map");
+ pmap_reference(vm_map_pmap(kernel_map));
+ pt_map = vm_map_create(vm_map_pmap(kernel_map), addr, addr2, TRUE);
+ if (pt_map == NULL)
+ panic("pmap_init: cannot create pt_map");
+ rv = vm_map_submap(kernel_map, addr, addr2, pt_map);
+ if (rv != KERN_SUCCESS)
+ panic("pmap_init: cannot map range to pt_map");
+#ifdef DEBUG
+ if (pmapdebug & PDB_INIT)
+ printf("pmap_init: pt_map [%x - %x)\n", addr, addr2);
+#endif
+
+#if defined(M68040)
+ if (mmutype == MMU_68040) {
+ protostfree = ~l2tobm(0);
+ for (rv = MAXUL2SIZE; rv < sizeof(protostfree)*NBBY; rv++)
+ protostfree &= ~l2tobm(rv);
+ }
+#endif
+
+ /*
+ * Now it is safe to enable pv_table recording.
+ */
+ vm_first_phys = phys_start;
+ vm_last_phys = phys_end;
+ pmap_initialized = TRUE;
+}
+
+struct pv_entry *
+pmap_alloc_pv()
+{
+ struct pv_page *pvp;
+ struct pv_entry *pv;
+ int i;
+
+ if (pv_nfree == 0) {
+ pvp = (struct pv_page *)kmem_alloc(kernel_map, NBPG);
+ if (pvp == 0)
+ panic("pmap_alloc_pv: kmem_alloc() failed");
+ pvp->pvp_pgi.pgi_freelist = pv = &pvp->pvp_pv[1];
+ for (i = NPVPPG - 2; i; i--, pv++)
+ pv->pv_next = pv + 1;
+ pv->pv_next = 0;
+ pv_nfree += pvp->pvp_pgi.pgi_nfree = NPVPPG - 1;
+ TAILQ_INSERT_HEAD(&pv_page_freelist, pvp, pvp_pgi.pgi_list);
+ pv = &pvp->pvp_pv[0];
+ } else {
+ --pv_nfree;
+ pvp = pv_page_freelist.tqh_first;
+ if (--pvp->pvp_pgi.pgi_nfree == 0) {
+ TAILQ_REMOVE(&pv_page_freelist, pvp, pvp_pgi.pgi_list);
+ }
+ pv = pvp->pvp_pgi.pgi_freelist;
+#ifdef DIAGNOSTIC
+ if (pv == 0)
+ panic("pmap_alloc_pv: pgi_nfree inconsistent");
+#endif
+ pvp->pvp_pgi.pgi_freelist = pv->pv_next;
+ }
+ return pv;
+}
+
+void
+pmap_free_pv(pv)
+ struct pv_entry *pv;
+{
+ register struct pv_page *pvp;
+ register int i;
+
+ pvp = (struct pv_page *) trunc_page(pv);
+ switch (++pvp->pvp_pgi.pgi_nfree) {
+ case 1:
+ TAILQ_INSERT_TAIL(&pv_page_freelist, pvp, pvp_pgi.pgi_list);
+ default:
+ pv->pv_next = pvp->pvp_pgi.pgi_freelist;
+ pvp->pvp_pgi.pgi_freelist = pv;
+ ++pv_nfree;
+ break;
+ case NPVPPG:
+ pv_nfree -= NPVPPG - 1;
+ TAILQ_REMOVE(&pv_page_freelist, pvp, pvp_pgi.pgi_list);
+ kmem_free(kernel_map, (vm_offset_t)pvp, NBPG);
+ break;
+ }
+}
+
+void
+pmap_collect_pv()
+{
+ struct pv_page_list pv_page_collectlist;
+ struct pv_page *pvp, *npvp;
+ struct pv_entry *ph, *ppv, *pv, *npv;
+ int s;
+
+ TAILQ_INIT(&pv_page_collectlist);
+
+ for (pvp = pv_page_freelist.tqh_first; pvp; pvp = npvp) {
+ if (pv_nfree < NPVPPG)
+ break;
+ npvp = pvp->pvp_pgi.pgi_list.tqe_next;
+ if (pvp->pvp_pgi.pgi_nfree > NPVPPG / 3) {
+ TAILQ_REMOVE(&pv_page_freelist, pvp, pvp_pgi.pgi_list);
+ TAILQ_INSERT_TAIL(&pv_page_collectlist, pvp, pvp_pgi.pgi_list);
+ pv_nfree -= pvp->pvp_pgi.pgi_nfree;
+ pvp->pvp_pgi.pgi_nfree = -1;
+ }
+ }
+
+ if (pv_page_collectlist.tqh_first == 0)
+ return;
+
+ for (ph = &pv_table[npages - 1]; ph >= &pv_table[0]; ph--) {
+ if (ph->pv_pmap == 0)
+ continue;
+ s = splimp();
+ for (ppv = ph; (pv = ppv->pv_next) != 0; ) {
+ pvp = (struct pv_page *) trunc_page(pv);
+ if (pvp->pvp_pgi.pgi_nfree == -1) {
+ pvp = pv_page_freelist.tqh_first;
+ if (--pvp->pvp_pgi.pgi_nfree == 0) {
+ TAILQ_REMOVE(&pv_page_freelist, pvp, pvp_pgi.pgi_list);
+ }
+ npv = pvp->pvp_pgi.pgi_freelist;
+#ifdef DIAGNOSTIC
+ if (npv == 0)
+ panic("pmap_collect_pv: pgi_nfree inconsistent");
+#endif
+ pvp->pvp_pgi.pgi_freelist = npv->pv_next;
+ *npv = *pv;
+ ppv->pv_next = npv;
+ ppv = npv;
+ } else
+ ppv = pv;
+ }
+ splx(s);
+ }
+
+ for (pvp = pv_page_collectlist.tqh_first; pvp; pvp = npvp) {
+ npvp = pvp->pvp_pgi.pgi_list.tqe_next;
+ kmem_free(kernel_map, (vm_offset_t)pvp, NBPG);
+ }
+}
+
+/*
+ * Used to map a range of physical addresses into kernel
+ * virtual address space.
+ *
+ * For now, VM is already on, we only need to map the
+ * specified memory.
+ */
+vm_offset_t
+pmap_map(va, spa, epa, prot)
+ vm_offset_t va, spa, epa;
+ int prot;
+{
+
+#ifdef DEBUG
+ if (pmapdebug & PDB_FOLLOW)
+ printf("pmap_map(%x, %x, %x, %x)\n", va, spa, epa, prot);
+#endif
+
+ while (spa < epa) {
+ pmap_enter(pmap_kernel(), va, spa, prot, FALSE);
+ va += NBPG;
+ spa += NBPG;
+ }
+ return (va);
+}
+
+/*
+ * Create and return a physical map.
+ *
+ * If the size specified for the map
+ * is zero, the map is an actual physical
+ * map, and may be referenced by the
+ * hardware.
+ *
+ * If the size specified is non-zero,
+ * the map will be used in software only, and
+ * is bounded by that size.
+ */
+pmap_t
+pmap_create(size)
+ vm_size_t size;
+{
+ register pmap_t pmap;
+
+#ifdef DEBUG
+ if (pmapdebug & (PDB_FOLLOW|PDB_CREATE))
+ printf("pmap_create(%x)\n", size);
+#endif
+
+ /*
+ * Software use map does not need a pmap
+ */
+ if (size)
+ return (NULL);
+
+ /* XXX: is it ok to wait here? */
+ pmap = (pmap_t) malloc(sizeof *pmap, M_VMPMAP, M_WAITOK);
+#ifdef notifwewait
+ if (pmap == NULL)
+ panic("pmap_create: cannot allocate a pmap");
+#endif
+ bzero(pmap, sizeof(*pmap));
+ pmap_pinit(pmap);
+ return (pmap);
+}
+
+/*
+ * Initialize a preallocated and zeroed pmap structure,
+ * such as one in a vmspace structure.
+ */
+void
+pmap_pinit(pmap)
+ register struct pmap *pmap;
+{
+
+#ifdef DEBUG
+ if (pmapdebug & (PDB_FOLLOW|PDB_CREATE))
+ printf("pmap_pinit(%x)\n", pmap);
+#endif
+
+ /*
+ * No need to allocate page table space yet but we do need a
+ * valid segment table. Initially, we point everyone at the
+ * "null" segment table. On the first pmap_enter, a real
+ * segment table will be allocated.
+ */
+ pmap->pm_stab = Segtabzero;
+ pmap->pm_stpa = Segtabzeropa;
+#if defined(M68040)
+ if (mmutype == MMU_68040)
+ pmap->pm_stfree = protostfree;
+#endif
+ pmap->pm_stchanged = TRUE;
+ pmap->pm_count = 1;
+ simple_lock_init(&pmap->pm_lock);
+}
+
+/*
+ * Retire the given physical map from service.
+ * Should only be called if the map contains
+ * no valid mappings.
+ */
+void
+pmap_destroy(pmap)
+ register pmap_t pmap;
+{
+ int count;
+
+ if (pmap == NULL)
+ return;
+
+#ifdef DEBUG
+ if (pmapdebug & PDB_FOLLOW)
+ printf("pmap_destroy(%x)\n", pmap);
+#endif
+
+ simple_lock(&pmap->pm_lock);
+ count = --pmap->pm_count;
+ simple_unlock(&pmap->pm_lock);
+ if (count == 0) {
+ pmap_release(pmap);
+ free((caddr_t)pmap, M_VMPMAP);
+ }
+}
+
+/*
+ * Release any resources held by the given physical map.
+ * Called when a pmap initialized by pmap_pinit is being released.
+ * Should only be called if the map contains no valid mappings.
+ */
+void
+pmap_release(pmap)
+ register struct pmap *pmap;
+{
+
+#ifdef DEBUG
+ if (pmapdebug & PDB_FOLLOW)
+ printf("pmap_release(%x)\n", pmap);
+#endif
+
+#ifdef notdef /* DIAGNOSTIC */
+ /* count would be 0 from pmap_destroy... */
+ simple_lock(&pmap->pm_lock);
+ if (pmap->pm_count != 1)
+ panic("pmap_release count");
+#endif
+
+ if (pmap->pm_ptab)
+ kmem_free_wakeup(pt_map, (vm_offset_t)pmap->pm_ptab,
+ HP_MAX_PTSIZE);
+ if (pmap->pm_stab != Segtabzero)
+ kmem_free_wakeup(st_map, (vm_offset_t)pmap->pm_stab,
+ HP_STSIZE);
+}
+
+/*
+ * Add a reference to the specified pmap.
+ */
+void
+pmap_reference(pmap)
+ pmap_t pmap;
+{
+
+ if (pmap == NULL)
+ return;
+
+#ifdef DEBUG
+ if (pmapdebug & PDB_FOLLOW)
+ printf("pmap_reference(%x)\n", pmap);
+#endif
+
+ simple_lock(&pmap->pm_lock);
+ pmap->pm_count++;
+ simple_unlock(&pmap->pm_lock);
+}
+
+void
+pmap_activate(pmap, pcb)
+ register pmap_t pmap;
+ struct pcb *pcb;
+{
+
+ if (pmap == NULL)
+ return;
+
+#ifdef DEBUG
+ if (pmapdebug & (PDB_FOLLOW|PDB_SEGTAB))
+ printf("pmap_activate(%x, %x)\n", pmap, pcb);
+#endif
+
+ PMAP_ACTIVATE(pmap, pcb, pmap == curproc->p_vmspace->vm_map.pmap);
+}
+
+void
+pmap_deactivate(pmap, pcb)
+ register pmap_t pmap;
+ struct pcb *pcb;
+{
+}
+
+/*
+ * Remove the given range of addresses from the specified map.
+ *
+ * It is assumed that the start and end are properly
+ * rounded to the page size.
+ */
+void
+pmap_remove(pmap, sva, eva)
+ register pmap_t pmap;
+ register vm_offset_t sva, eva;
+{
+ register vm_offset_t nssva;
+ register pt_entry_t *pte;
+ boolean_t firstpage, needcflush;
+ int flags;
+
+#ifdef DEBUG
+ if (pmapdebug & (PDB_FOLLOW|PDB_REMOVE|PDB_PROTECT))
+ printf("pmap_remove(%x, %x, %x)\n", pmap, sva, eva);
+#endif
+
+ if (pmap == NULL)
+ return;
+
+#ifdef PMAPSTATS
+ remove_stats.calls++;
+#endif
+ firstpage = TRUE;
+ needcflush = FALSE;
+ flags = active_pmap(pmap) ? PRM_TFLUSH : 0;
+ while (sva < eva) {
+ nssva = m68k_trunc_seg(sva) + HP_SEG_SIZE;
+ if (nssva == 0 || nssva > eva)
+ nssva = eva;
+ /*
+ * If VA belongs to an unallocated segment,
+ * skip to the next segment boundary.
+ */
+ if (!pmap_ste_v(pmap, sva)) {
+ sva = nssva;
+ continue;
+ }
+ /*
+ * Invalidate every valid mapping within this segment.
+ */
+ pte = pmap_pte(pmap, sva);
+ while (sva < nssva) {
+ if (pmap_pte_v(pte)) {
+#ifdef HAVEVAC
+ if (pmap_aliasmask) {
+ /*
+ * Purge kernel side of VAC to ensure
+ * we get the correct state of any
+ * hardware maintained bits.
+ */
+ if (firstpage) {
+ DCIS();
+#ifdef PMAPSTATS
+ remove_stats.sflushes++;
+#endif
+ }
+ /*
+ * Remember if we may need to
+ * flush the VAC due to a non-CI
+ * mapping.
+ */
+ if (!needcflush && !pmap_pte_ci(pte))
+ needcflush = TRUE;
+
+ }
+#endif
+ pmap_remove_mapping(pmap, sva, pte, flags);
+ firstpage = FALSE;
+ }
+ pte++;
+ sva += NBPG;
+ }
+ }
+ /*
+ * Didn't do anything, no need for cache flushes
+ */
+ if (firstpage)
+ return;
+#ifdef HAVEVAC
+ /*
+ * In a couple of cases, we don't need to worry about flushing
+ * the VAC:
+ * 1. if this is a kernel mapping,
+ * we have already done it
+ * 2. if it is a user mapping not for the current process,
+ * it won't be there
+ */
+ if (pmap_aliasmask &&
+ (pmap == pmap_kernel() || pmap != curproc->p_vmspace->vm_map.pmap))
+ needcflush = FALSE;
+#ifdef DEBUG
+ if (pmap_aliasmask && (pmapvacflush & PVF_REMOVE)) {
+ if (pmapvacflush & PVF_TOTAL)
+ DCIA();
+ else if (pmap == pmap_kernel())
+ DCIS();
+ else
+ DCIU();
+ } else
+#endif
+ if (needcflush) {
+ if (pmap == pmap_kernel()) {
+ DCIS();
+#ifdef PMAPSTATS
+ remove_stats.sflushes++;
+#endif
+ } else {
+ DCIU();
+#ifdef PMAPSTATS
+ remove_stats.uflushes++;
+#endif
+ }
+ }
+#endif
+}
+
+/*
+ * pmap_page_protect:
+ *
+ * Lower the permission for all mappings to a given page.
+ */
+void
+pmap_page_protect(pa, prot)
+ vm_offset_t pa;
+ vm_prot_t prot;
+{
+ register struct pv_entry *pv;
+ int s;
+
+#ifdef DEBUG
+ if ((pmapdebug & (PDB_FOLLOW|PDB_PROTECT)) ||
+ prot == VM_PROT_NONE && (pmapdebug & PDB_REMOVE))
+ printf("pmap_page_protect(%x, %x)\n", pa, prot);
+#endif
+ if (pa < vm_first_phys || pa >= vm_last_phys)
+ return;
+
+ switch (prot) {
+ case VM_PROT_READ|VM_PROT_WRITE:
+ case VM_PROT_ALL:
+ return;
+ /* copy_on_write */
+ case VM_PROT_READ:
+ case VM_PROT_READ|VM_PROT_EXECUTE:
+ pmap_changebit(pa, PG_RO, TRUE);
+ return;
+ /* remove_all */
+ default:
+ break;
+ }
+ pv = pa_to_pvh(pa);
+ s = splimp();
+ while (pv->pv_pmap != NULL) {
+ register pt_entry_t *pte;
+
+ pte = pmap_pte(pv->pv_pmap, pv->pv_va);
+#ifdef DEBUG
+ if (!pmap_ste_v(pv->pv_pmap, pv->pv_va) ||
+ pmap_pte_pa(pte) != pa)
+ panic("pmap_page_protect: bad mapping");
+#endif
+ if (!pmap_pte_w(pte))
+ pmap_remove_mapping(pv->pv_pmap, pv->pv_va,
+ pte, PRM_TFLUSH|PRM_CFLUSH);
+ else {
+ pv = pv->pv_next;
+#ifdef DEBUG
+ if (pmapdebug & PDB_PARANOIA)
+ printf("%s wired mapping for %x not removed\n",
+ "pmap_page_protect:", pa);
+#endif
+ }
+ }
+ splx(s);
+}
+
+/*
+ * Set the physical protection on the
+ * specified range of this map as requested.
+ */
+void
+pmap_protect(pmap, sva, eva, prot)
+ register pmap_t pmap;
+ register vm_offset_t sva, eva;
+ vm_prot_t prot;
+{
+ register vm_offset_t nssva;
+ register pt_entry_t *pte;
+ boolean_t firstpage, needtflush;
+ int isro;
+
+#ifdef DEBUG
+ if (pmapdebug & (PDB_FOLLOW|PDB_PROTECT))
+ printf("pmap_protect(%x, %x, %x, %x)\n", pmap, sva, eva, prot);
+#endif
+
+ if (pmap == NULL)
+ return;
+
+#ifdef PMAPSTATS
+ protect_stats.calls++;
+#endif
+ if ((prot & VM_PROT_READ) == VM_PROT_NONE) {
+ pmap_remove(pmap, sva, eva);
+ return;
+ }
+ if (prot & VM_PROT_WRITE)
+ return;
+
+ isro = pte_prot(pmap, prot);
+ needtflush = active_pmap(pmap);
+ firstpage = TRUE;
+ while (sva < eva) {
+ nssva = m68k_trunc_seg(sva) + HP_SEG_SIZE;
+ if (nssva == 0 || nssva > eva)
+ nssva = eva;
+ /*
+ * If VA belongs to an unallocated segment,
+ * skip to the next segment boundary.
+ */
+ if (!pmap_ste_v(pmap, sva)) {
+ sva = nssva;
+ continue;
+ }
+ /*
+ * Change protection on mapping if it is valid and doesn't
+ * already have the correct protection.
+ */
+ pte = pmap_pte(pmap, sva);
+ while (sva < nssva) {
+ if (pmap_pte_v(pte) && pmap_pte_prot_chg(pte, isro)) {
+#ifdef HAVEVAC
+ /*
+ * Purge kernel side of VAC to ensure we
+ * get the correct state of any hardware
+ * maintained bits.
+ *
+ * XXX do we need to clear the VAC in
+ * general to reflect the new protection?
+ */
+ if (firstpage && pmap_aliasmask)
+ DCIS();
+#endif
+#if defined(M68040)
+ /*
+ * Clear caches if making RO (see section
+ * "7.3 Cache Coherency" in the manual).
+ */
+ if (isro && mmutype == MMU_68040) {
+ vm_offset_t pa = pmap_pte_pa(pte);
+
+ DCFP(pa);
+ ICPP(pa);
+ }
+#endif
+ pmap_pte_set_prot(pte, isro);
+ if (needtflush)
+ TBIS(sva);
+#ifdef PMAPSTATS
+ protect_stats.changed++;
+#endif
+ firstpage = FALSE;
+ }
+#ifdef PMAPSTATS
+ else if (pmap_pte_v(pte)) {
+ if (isro)
+ protect_stats.alreadyro++;
+ else
+ protect_stats.alreadyrw++;
+ }
+#endif
+ pte++;
+ sva += NBPG;
+ }
+ }
+#if defined(HAVEVAC) && defined(DEBUG)
+ if (pmap_aliasmask && (pmapvacflush & PVF_PROTECT)) {
+ if (pmapvacflush & PVF_TOTAL)
+ DCIA();
+ else if (pmap == pmap_kernel())
+ DCIS();
+ else
+ DCIU();
+ }
+#endif
+}
+
+/*
+ * Insert the given physical page (p) at
+ * the specified virtual address (v) in the
+ * target physical map with the protection requested.
+ *
+ * If specified, the page will be wired down, meaning
+ * that the related pte can not be reclaimed.
+ *
+ * NB: This is the only routine which MAY NOT lazy-evaluate
+ * or lose information. That is, this routine must actually
+ * insert this page into the given map NOW.
+ */
+void
+pmap_enter(pmap, va, pa, prot, wired)
+ register pmap_t pmap;
+ vm_offset_t va;
+ register vm_offset_t pa;
+ vm_prot_t prot;
+ boolean_t wired;
+{
+ register pt_entry_t *pte;
+ register int npte;
+ vm_offset_t opa;
+ boolean_t cacheable = TRUE;
+ boolean_t checkpv = TRUE;
+
+#ifdef DEBUG
+ if (pmapdebug & (PDB_FOLLOW|PDB_ENTER))
+ printf("pmap_enter(%x, %x, %x, %x, %x)\n",
+ pmap, va, pa, prot, wired);
+#endif
+ if (pmap == NULL)
+ return;
+
+#ifdef PMAPSTATS
+ if (pmap == pmap_kernel())
+ enter_stats.kernel++;
+ else
+ enter_stats.user++;
+#endif
+ /*
+ * For user mapping, allocate kernel VM resources if necessary.
+ */
+ if (pmap->pm_ptab == NULL)
+ pmap->pm_ptab = (pt_entry_t *)
+ kmem_alloc_wait(pt_map, HP_MAX_PTSIZE);
+
+ /*
+ * Segment table entry not valid, we need a new PT page
+ */
+ if (!pmap_ste_v(pmap, va))
+ pmap_enter_ptpage(pmap, va);
+
+ pa = m68k_trunc_page(pa);
+ pte = pmap_pte(pmap, va);
+ opa = pmap_pte_pa(pte);
+#ifdef DEBUG
+ if (pmapdebug & PDB_ENTER)
+ printf("enter: pte %x, *pte %x\n", pte, *pte);
+#endif
+
+ /*
+ * Mapping has not changed, must be protection or wiring change.
+ */
+ if (opa == pa) {
+#ifdef PMAPSTATS
+ enter_stats.pwchange++;
+#endif
+ /*
+ * Wiring change, just update stats.
+ * We don't worry about wiring PT pages as they remain
+ * resident as long as there are valid mappings in them.
+ * Hence, if a user page is wired, the PT page will be also.
+ */
+ if (pmap_pte_w_chg(pte, wired ? PG_W : 0)) {
+#ifdef DEBUG
+ if (pmapdebug & PDB_ENTER)
+ printf("enter: wiring change -> %x\n", wired);
+#endif
+ if (wired)
+ pmap->pm_stats.wired_count++;
+ else
+ pmap->pm_stats.wired_count--;
+#ifdef PMAPSTATS
+ if (pmap_pte_prot(pte) == pte_prot(pmap, prot))
+ enter_stats.wchange++;
+#endif
+ }
+#ifdef PMAPSTATS
+ else if (pmap_pte_prot(pte) != pte_prot(pmap, prot))
+ enter_stats.pchange++;
+ else
+ enter_stats.nochange++;
+#endif
+ /*
+ * Retain cache inhibition status
+ */
+ checkpv = FALSE;
+ if (pmap_pte_ci(pte))
+ cacheable = FALSE;
+ goto validate;
+ }
+
+ /*
+ * Mapping has changed, invalidate old range and fall through to
+ * handle validating new mapping.
+ */
+ if (opa) {
+#ifdef DEBUG
+ if (pmapdebug & PDB_ENTER)
+ printf("enter: removing old mapping %x\n", va);
+#endif
+ pmap_remove_mapping(pmap, va, pte, PRM_TFLUSH|PRM_CFLUSH);
+#ifdef PMAPSTATS
+ enter_stats.mchange++;
+#endif
+ }
+
+ /*
+ * If this is a new user mapping, increment the wiring count
+ * on this PT page. PT pages are wired down as long as there
+ * is a valid mapping in the page.
+ */
+ if (pmap != pmap_kernel())
+ (void) vm_map_pageable(pt_map, trunc_page(pte),
+ round_page(pte+1), FALSE);
+
+ /*
+ * Enter on the PV list if part of our managed memory
+ * Note that we raise IPL while manipulating pv_table
+ * since pmap_enter can be called at interrupt time.
+ */
+ if (pa >= vm_first_phys && pa < vm_last_phys) {
+ register struct pv_entry *pv, *npv;
+ int s;
+
+#ifdef PMAPSTATS
+ enter_stats.managed++;
+#endif
+ pv = pa_to_pvh(pa);
+ s = splimp();
+#ifdef DEBUG
+ if (pmapdebug & PDB_ENTER)
+ printf("enter: pv at %x: %x/%x/%x\n",
+ pv, pv->pv_va, pv->pv_pmap, pv->pv_next);
+#endif
+ /*
+ * No entries yet, use header as the first entry
+ */
+ if (pv->pv_pmap == NULL) {
+#ifdef PMAPSTATS
+ enter_stats.firstpv++;
+#endif
+ pv->pv_va = va;
+ pv->pv_pmap = pmap;
+ pv->pv_next = NULL;
+ pv->pv_ptste = NULL;
+ pv->pv_ptpmap = NULL;
+ pv->pv_flags = 0;
+ }
+ /*
+ * There is at least one other VA mapping this page.
+ * Place this entry after the header.
+ */
+ else {
+#ifdef DEBUG
+ for (npv = pv; npv; npv = npv->pv_next)
+ if (pmap == npv->pv_pmap && va == npv->pv_va)
+ panic("pmap_enter: already in pv_tab");
+#endif
+ npv = pmap_alloc_pv();
+ npv->pv_va = va;
+ npv->pv_pmap = pmap;
+ npv->pv_next = pv->pv_next;
+ npv->pv_ptste = NULL;
+ npv->pv_ptpmap = NULL;
+ npv->pv_flags = 0;
+ pv->pv_next = npv;
+#ifdef PMAPSTATS
+ if (!npv->pv_next)
+ enter_stats.secondpv++;
+#endif
+#ifdef HAVEVAC
+ /*
+ * Since there is another logical mapping for the
+ * same page we may need to cache-inhibit the
+ * descriptors on those CPUs with external VACs.
+ * We don't need to CI if:
+ *
+ * - No two mappings belong to the same user pmaps.
+ * Since the cache is flushed on context switches
+ * there is no problem between user processes.
+ *
+ * - Mappings within a single pmap are a certain
+ * magic distance apart. VAs at these appropriate
+ * boundaries map to the same cache entries or
+ * otherwise don't conflict.
+ *
+ * To keep it simple, we only check for these special
+ * cases if there are only two mappings, otherwise we
+ * punt and always CI.
+ *
+ * Note that there are no aliasing problems with the
+ * on-chip data-cache when the WA bit is set.
+ */
+ if (pmap_aliasmask) {
+ if (pv->pv_flags & PV_CI) {
+#ifdef DEBUG
+ if (pmapdebug & PDB_CACHE)
+ printf("enter: pa %x already CI'ed\n",
+ pa);
+#endif
+ checkpv = cacheable = FALSE;
+ } else if (npv->pv_next ||
+ ((pmap == pv->pv_pmap ||
+ pmap == pmap_kernel() ||
+ pv->pv_pmap == pmap_kernel()) &&
+ ((pv->pv_va & pmap_aliasmask) !=
+ (va & pmap_aliasmask)))) {
+#ifdef DEBUG
+ if (pmapdebug & PDB_CACHE)
+ printf("enter: pa %x CI'ing all\n",
+ pa);
+#endif
+ cacheable = FALSE;
+ pv->pv_flags |= PV_CI;
+#ifdef PMAPSTATS
+ enter_stats.ci++;
+#endif
+ }
+ }
+#endif
+ }
+ splx(s);
+ }
+ /*
+ * Assumption: if it is not part of our managed memory
+ * then it must be device memory which may be volitile.
+ */
+ else if (pmap_initialized) {
+ checkpv = cacheable = FALSE;
+#ifdef PMAPSTATS
+ enter_stats.unmanaged++;
+#endif
+ }
+
+ /*
+ * Increment counters
+ */
+ pmap->pm_stats.resident_count++;
+ if (wired)
+ pmap->pm_stats.wired_count++;
+
+validate:
+#ifdef HAVEVAC
+ /*
+ * Purge kernel side of VAC to ensure we get correct state
+ * of HW bits so we don't clobber them.
+ */
+ if (pmap_aliasmask)
+ DCIS();
+#endif
+ /*
+ * Build the new PTE.
+ */
+ npte = pa | pte_prot(pmap, prot) | (*pte & (PG_M|PG_U)) | PG_V;
+ if (wired)
+ npte |= PG_W;
+ if (!checkpv && !cacheable)
+ npte |= PG_CI;
+#if defined(M68040)
+ if (mmutype == MMU_68040 && (npte & (PG_PROT|PG_CI)) == PG_RW)
+#ifdef DEBUG
+ if (dowriteback && (dokwriteback || pmap != pmap_kernel()))
+#endif
+ npte |= PG_CCB;
+#endif
+#ifdef DEBUG
+ if (pmapdebug & PDB_ENTER)
+ printf("enter: new pte value %x\n", npte);
+#endif
+ /*
+ * Remember if this was a wiring-only change.
+ * If so, we need not flush the TLB and caches.
+ */
+ wired = ((*pte ^ npte) == PG_W);
+#if defined(M68040)
+ if (mmutype == MMU_68040 && !wired) {
+ DCFP(pa);
+ ICPP(pa);
+ }
+#endif
+ *pte = npte;
+ if (!wired && active_pmap(pmap))
+ TBIS(va);
+#ifdef HAVEVAC
+ /*
+ * The following is executed if we are entering a second
+ * (or greater) mapping for a physical page and the mappings
+ * may create an aliasing problem. In this case we must
+ * cache inhibit the descriptors involved and flush any
+ * external VAC.
+ */
+ if (checkpv && !cacheable) {
+ pmap_changebit(pa, PG_CI, TRUE);
+ DCIA();
+#ifdef PMAPSTATS
+ enter_stats.flushes++;
+#endif
+#ifdef DEBUG
+ if ((pmapdebug & (PDB_CACHE|PDB_PVDUMP)) ==
+ (PDB_CACHE|PDB_PVDUMP))
+ pmap_pvdump(pa);
+#endif
+ }
+#ifdef DEBUG
+ else if (pmapvacflush & PVF_ENTER) {
+ if (pmapvacflush & PVF_TOTAL)
+ DCIA();
+ else if (pmap == pmap_kernel())
+ DCIS();
+ else
+ DCIU();
+ }
+#endif
+#endif
+#ifdef DEBUG
+ if ((pmapdebug & PDB_WIRING) && pmap != pmap_kernel())
+ pmap_check_wiring("enter", trunc_page(pmap_pte(pmap, va)));
+#endif
+}
+
+/*
+ * Routine: pmap_change_wiring
+ * Function: Change the wiring attribute for a map/virtual-address
+ * pair.
+ * In/out conditions:
+ * The mapping must already exist in the pmap.
+ */
+void
+pmap_change_wiring(pmap, va, wired)
+ register pmap_t pmap;
+ vm_offset_t va;
+ boolean_t wired;
+{
+ register pt_entry_t *pte;
+
+#ifdef DEBUG
+ if (pmapdebug & PDB_FOLLOW)
+ printf("pmap_change_wiring(%x, %x, %x)\n", pmap, va, wired);
+#endif
+ if (pmap == NULL)
+ return;
+
+ pte = pmap_pte(pmap, va);
+#ifdef DEBUG
+ /*
+ * Page table page is not allocated.
+ * Should this ever happen? Ignore it for now,
+ * we don't want to force allocation of unnecessary PTE pages.
+ */
+ if (!pmap_ste_v(pmap, va)) {
+ if (pmapdebug & PDB_PARANOIA)
+ printf("pmap_change_wiring: invalid STE for %x\n", va);
+ return;
+ }
+ /*
+ * Page not valid. Should this ever happen?
+ * Just continue and change wiring anyway.
+ */
+ if (!pmap_pte_v(pte)) {
+ if (pmapdebug & PDB_PARANOIA)
+ printf("pmap_change_wiring: invalid PTE for %x\n", va);
+ }
+#endif
+ /*
+ * If wiring actually changed (always?) set the wire bit and
+ * update the wire count. Note that wiring is not a hardware
+ * characteristic so there is no need to invalidate the TLB.
+ */
+ if (pmap_pte_w_chg(pte, wired ? PG_W : 0)) {
+ pmap_pte_set_w(pte, wired);
+ if (wired)
+ pmap->pm_stats.wired_count++;
+ else
+ pmap->pm_stats.wired_count--;
+ }
+}
+
+/*
+ * Routine: pmap_extract
+ * Function:
+ * Extract the physical page address associated
+ * with the given map/virtual_address pair.
+ */
+
+vm_offset_t
+pmap_extract(pmap, va)
+ register pmap_t pmap;
+ vm_offset_t va;
+{
+ register vm_offset_t pa;
+
+#ifdef DEBUG
+ if (pmapdebug & PDB_FOLLOW)
+ printf("pmap_extract(%x, %x) -> ", pmap, va);
+#endif
+ pa = 0;
+ if (pmap && pmap_ste_v(pmap, va))
+ pa = *pmap_pte(pmap, va);
+ if (pa)
+ pa = (pa & PG_FRAME) | (va & ~PG_FRAME);
+#ifdef DEBUG
+ if (pmapdebug & PDB_FOLLOW)
+ printf("%x\n", pa);
+#endif
+ return(pa);
+}
+
+/*
+ * Copy the range specified by src_addr/len
+ * from the source map to the range dst_addr/len
+ * in the destination map.
+ *
+ * This routine is only advisory and need not do anything.
+ */
+void pmap_copy(dst_pmap, src_pmap, dst_addr, len, src_addr)
+ pmap_t dst_pmap;
+ pmap_t src_pmap;
+ vm_offset_t dst_addr;
+ vm_size_t len;
+ vm_offset_t src_addr;
+{
+#ifdef DEBUG
+ if (pmapdebug & PDB_FOLLOW)
+ printf("pmap_copy(%x, %x, %x, %x, %x)\n",
+ dst_pmap, src_pmap, dst_addr, len, src_addr);
+#endif
+}
+
+/*
+ * Require that all active physical maps contain no
+ * incorrect entries NOW. [This update includes
+ * forcing updates of any address map caching.]
+ *
+ * Generally used to insure that a thread about
+ * to run will see a semantically correct world.
+ */
+void pmap_update()
+{
+#ifdef DEBUG
+ if (pmapdebug & PDB_FOLLOW)
+ printf("pmap_update()\n");
+#endif
+ TBIA();
+}
+
+/*
+ * Routine: pmap_collect
+ * Function:
+ * Garbage collects the physical map system for
+ * pages which are no longer used.
+ * Success need not be guaranteed -- that is, there
+ * may well be pages which are not referenced, but
+ * others may be collected.
+ * Usage:
+ * Called by the pageout daemon when pages are scarce.
+ */
+void
+pmap_collect(pmap)
+ pmap_t pmap;
+{
+ register vm_offset_t pa;
+ register struct pv_entry *pv;
+ register pt_entry_t *pte;
+ vm_offset_t kpa;
+ int s;
+
+#ifdef DEBUG
+ st_entry_t *ste;
+ int opmapdebug;
+#endif
+ if (pmap != pmap_kernel())
+ return;
+
+#ifdef DEBUG
+ if (pmapdebug & PDB_FOLLOW)
+ printf("pmap_collect(%x)\n", pmap);
+#endif
+#ifdef PMAPSTATS
+ kpt_stats.collectscans++;
+#endif
+ s = splimp();
+ for (pa = vm_first_phys; pa < vm_last_phys; pa += NBPG) {
+ register struct kpt_page *kpt, **pkpt;
+
+ /*
+ * Locate physical pages which are being used as kernel
+ * page table pages.
+ */
+ pv = pa_to_pvh(pa);
+ if (pv->pv_pmap != pmap_kernel() || !(pv->pv_flags & PV_PTPAGE))
+ continue;
+ do {
+ if (pv->pv_ptste && pv->pv_ptpmap == pmap_kernel())
+ break;
+ } while (pv = pv->pv_next);
+ if (pv == NULL)
+ continue;
+#ifdef DEBUG
+ if (pv->pv_va < (vm_offset_t)Sysmap ||
+ pv->pv_va >= (vm_offset_t)Sysmap + HP_MAX_PTSIZE)
+ printf("collect: kernel PT VA out of range\n");
+ else
+ goto ok;
+ pmap_pvdump(pa);
+ continue;
+ok:
+#endif
+ pte = (pt_entry_t *)(pv->pv_va + NBPG);
+ while (--pte >= (pt_entry_t *)pv->pv_va && *pte == PG_NV)
+ ;
+ if (pte >= (pt_entry_t *)pv->pv_va)
+ continue;
+
+#ifdef DEBUG
+ if (pmapdebug & (PDB_PTPAGE|PDB_COLLECT)) {
+ printf("collect: freeing KPT page at %x (ste %x@%x)\n",
+ pv->pv_va, *pv->pv_ptste, pv->pv_ptste);
+ opmapdebug = pmapdebug;
+ pmapdebug |= PDB_PTPAGE;
+ }
+
+ ste = pv->pv_ptste;
+#endif
+ /*
+ * If all entries were invalid we can remove the page.
+ * We call pmap_remove_entry to take care of invalidating
+ * ST and Sysptmap entries.
+ */
+ kpa = pmap_extract(pmap, pv->pv_va);
+ pmap_remove_mapping(pmap, pv->pv_va, PT_ENTRY_NULL,
+ PRM_TFLUSH|PRM_CFLUSH);
+ /*
+ * Use the physical address to locate the original
+ * (kmem_alloc assigned) address for the page and put
+ * that page back on the free list.
+ */
+ for (pkpt = &kpt_used_list, kpt = *pkpt;
+ kpt != (struct kpt_page *)0;
+ pkpt = &kpt->kpt_next, kpt = *pkpt)
+ if (kpt->kpt_pa == kpa)
+ break;
+#ifdef DEBUG
+ if (kpt == (struct kpt_page *)0)
+ panic("pmap_collect: lost a KPT page");
+ if (pmapdebug & (PDB_PTPAGE|PDB_COLLECT))
+ printf("collect: %x (%x) to free list\n",
+ kpt->kpt_va, kpa);
+#endif
+ *pkpt = kpt->kpt_next;
+ kpt->kpt_next = kpt_free_list;
+ kpt_free_list = kpt;
+#ifdef PMAPSTATS
+ kpt_stats.kptinuse--;
+ kpt_stats.collectpages++;
+#endif
+#ifdef DEBUG
+ if (pmapdebug & (PDB_PTPAGE|PDB_COLLECT))
+ pmapdebug = opmapdebug;
+
+ if (*ste != SG_NV)
+ printf("collect: kernel STE at %x still valid (%x)\n",
+ ste, *ste);
+ ste = &Sysptmap[ste - pmap_ste(pmap_kernel(), 0)];
+ if (*ste != SG_NV)
+ printf("collect: kernel PTmap at %x still valid (%x)\n",
+ ste, *ste);
+#endif
+ }
+ splx(s);
+}
+
+/*
+ * pmap_zero_page zeros the specified (machine independent)
+ * page by mapping the page into virtual memory and using
+ * bzero to clear its contents, one machine dependent page
+ * at a time.
+ *
+ * XXX this is a bad implementation for virtual cache machines
+ * (320/350) because pmap_enter doesn't cache-inhibit the temporary
+ * kernel mapping and we wind up with data cached for that KVA.
+ * It is probably a win for physical cache machines (370/380)
+ * as the cache loading is not wasted.
+ */
+void
+pmap_zero_page(phys)
+ vm_offset_t phys;
+{
+ register vm_offset_t kva;
+ extern caddr_t CADDR1;
+
+#ifdef DEBUG
+ if (pmapdebug & PDB_FOLLOW)
+ printf("pmap_zero_page(%x)\n", phys);
+#endif
+ kva = (vm_offset_t) CADDR1;
+ pmap_enter(pmap_kernel(), kva, phys, VM_PROT_READ|VM_PROT_WRITE, TRUE);
+ bzero((caddr_t)kva, NBPG);
+ pmap_remove_mapping(pmap_kernel(), kva, PT_ENTRY_NULL,
+ PRM_TFLUSH|PRM_CFLUSH);
+}
+
+/*
+ * pmap_copy_page copies the specified (machine independent)
+ * page by mapping the page into virtual memory and using
+ * bcopy to copy the page, one machine dependent page at a
+ * time.
+ *
+ *
+ * XXX this is a bad implementation for virtual cache machines
+ * (320/350) because pmap_enter doesn't cache-inhibit the temporary
+ * kernel mapping and we wind up with data cached for that KVA.
+ * It is probably a win for physical cache machines (370/380)
+ * as the cache loading is not wasted.
+ */
+void
+pmap_copy_page(src, dst)
+ vm_offset_t src, dst;
+{
+ register vm_offset_t skva, dkva;
+ extern caddr_t CADDR1, CADDR2;
+
+#ifdef DEBUG
+ if (pmapdebug & PDB_FOLLOW)
+ printf("pmap_copy_page(%x, %x)\n", src, dst);
+#endif
+ skva = (vm_offset_t) CADDR1;
+ dkva = (vm_offset_t) CADDR2;
+ pmap_enter(pmap_kernel(), skva, src, VM_PROT_READ, TRUE);
+ pmap_enter(pmap_kernel(), dkva, dst, VM_PROT_READ|VM_PROT_WRITE, TRUE);
+ copypage((caddr_t)skva, (caddr_t)dkva);
+ /* CADDR1 and CADDR2 are virtually contiguous */
+ pmap_remove(pmap_kernel(), skva, skva+2*NBPG);
+}
+
+/*
+ * Routine: pmap_pageable
+ * Function:
+ * Make the specified pages (by pmap, offset)
+ * pageable (or not) as requested.
+ *
+ * A page which is not pageable may not take
+ * a fault; therefore, its page table entry
+ * must remain valid for the duration.
+ *
+ * This routine is merely advisory; pmap_enter
+ * will specify that these pages are to be wired
+ * down (or not) as appropriate.
+ */
+void
+pmap_pageable(pmap, sva, eva, pageable)
+ pmap_t pmap;
+ vm_offset_t sva, eva;
+ boolean_t pageable;
+{
+#ifdef DEBUG
+ if (pmapdebug & PDB_FOLLOW)
+ printf("pmap_pageable(%x, %x, %x, %x)\n",
+ pmap, sva, eva, pageable);
+#endif
+ /*
+ * If we are making a PT page pageable then all valid
+ * mappings must be gone from that page. Hence it should
+ * be all zeros and there is no need to clean it.
+ * Assumptions:
+ * - we are called with only one page at a time
+ * - PT pages have only one pv_table entry
+ */
+ if (pmap == pmap_kernel() && pageable && sva + NBPG == eva) {
+ register struct pv_entry *pv;
+ register vm_offset_t pa;
+
+#ifdef DEBUG
+ if ((pmapdebug & (PDB_FOLLOW|PDB_PTPAGE)) == PDB_PTPAGE)
+ printf("pmap_pageable(%x, %x, %x, %x)\n",
+ pmap, sva, eva, pageable);
+#endif
+ if (!pmap_ste_v(pmap, sva))
+ return;
+ pa = pmap_pte_pa(pmap_pte(pmap, sva));
+ if (pa < vm_first_phys || pa >= vm_last_phys)
+ return;
+ pv = pa_to_pvh(pa);
+ if (pv->pv_ptste == NULL)
+ return;
+#ifdef DEBUG
+ if (pv->pv_va != sva || pv->pv_next) {
+ printf("pmap_pageable: bad PT page va %x next %x\n",
+ pv->pv_va, pv->pv_next);
+ return;
+ }
+#endif
+ /*
+ * Mark it unmodified to avoid pageout
+ */
+ pmap_changebit(pa, PG_M, FALSE);
+#ifdef DEBUG
+ if ((PHYS_TO_VM_PAGE(pa)->flags & PG_CLEAN) == 0) {
+ printf("pa %x: flags=%x: not clean\n",
+ pa, PHYS_TO_VM_PAGE(pa)->flags);
+ PHYS_TO_VM_PAGE(pa)->flags |= PG_CLEAN;
+ }
+ if (pmapdebug & PDB_PTPAGE)
+ printf("pmap_pageable: PT page %x(%x) unmodified\n",
+ sva, *pmap_pte(pmap, sva));
+ if (pmapdebug & PDB_WIRING)
+ pmap_check_wiring("pageable", sva);
+#endif
+ }
+}
+
+/*
+ * Clear the modify bits on the specified physical page.
+ */
+
+void
+pmap_clear_modify(pa)
+ vm_offset_t pa;
+{
+#ifdef DEBUG
+ if (pmapdebug & PDB_FOLLOW)
+ printf("pmap_clear_modify(%x)\n", pa);
+#endif
+ pmap_changebit(pa, PG_M, FALSE);
+}
+
+/*
+ * pmap_clear_reference:
+ *
+ * Clear the reference bit on the specified physical page.
+ */
+
+void pmap_clear_reference(pa)
+ vm_offset_t pa;
+{
+#ifdef DEBUG
+ if (pmapdebug & PDB_FOLLOW)
+ printf("pmap_clear_reference(%x)\n", pa);
+#endif
+ pmap_changebit(pa, PG_U, FALSE);
+}
+
+/*
+ * pmap_is_referenced:
+ *
+ * Return whether or not the specified physical page is referenced
+ * by any physical maps.
+ */
+
+boolean_t
+pmap_is_referenced(pa)
+ vm_offset_t pa;
+{
+#ifdef DEBUG
+ if (pmapdebug & PDB_FOLLOW) {
+ boolean_t rv = pmap_testbit(pa, PG_U);
+ printf("pmap_is_referenced(%x) -> %c\n", pa, "FT"[rv]);
+ return(rv);
+ }
+#endif
+ return(pmap_testbit(pa, PG_U));
+}
+
+/*
+ * pmap_is_modified:
+ *
+ * Return whether or not the specified physical page is modified
+ * by any physical maps.
+ */
+
+boolean_t
+pmap_is_modified(pa)
+ vm_offset_t pa;
+{
+#ifdef DEBUG
+ if (pmapdebug & PDB_FOLLOW) {
+ boolean_t rv = pmap_testbit(pa, PG_M);
+ printf("pmap_is_modified(%x) -> %c\n", pa, "FT"[rv]);
+ return(rv);
+ }
+#endif
+ return(pmap_testbit(pa, PG_M));
+}
+
+vm_offset_t
+pmap_phys_address(ppn)
+ int ppn;
+{
+ return(m68k_ptob(ppn));
+}
+
+#ifdef COMPAT_HPUX
+/*
+ * 'PUX hack for dealing with the so called multi-mapped address space.
+ * The first 256mb is mapped in at every 256mb region from 0x10000000
+ * up to 0xF0000000. This allows for 15 bits of tag information.
+ *
+ * We implement this at the segment table level, the machine independent
+ * VM knows nothing about it.
+ */
+pmap_mapmulti(pmap, va)
+ pmap_t pmap;
+ vm_offset_t va;
+{
+ st_entry_t *ste, *bste;
+
+#ifdef DEBUG
+ if (pmapdebug & PDB_MULTIMAP) {
+ ste = pmap_ste(pmap, HPMMBASEADDR(va));
+ printf("pmap_mapmulti(%x, %x): bste %x(%x)",
+ pmap, va, ste, *ste);
+ ste = pmap_ste(pmap, va);
+ printf(" ste %x(%x)\n", ste, *ste);
+ }
+#endif
+ bste = pmap_ste(pmap, HPMMBASEADDR(va));
+ ste = pmap_ste(pmap, va);
+ if (*ste == SG_NV && (*bste & SG_V)) {
+ *ste = *bste;
+ TBIAU();
+ return (KERN_SUCCESS);
+ }
+ return (KERN_INVALID_ADDRESS);
+}
+#endif
+
+/*
+ * Miscellaneous support routines follow
+ */
+
+/*
+ * Invalidate a single page denoted by pmap/va.
+ * If (pte != NULL), it is the already computed PTE for the page.
+ * If (flags & PRM_TFLUSH), we must invalidate any TLB information.
+ * If (flags & PRM_CFLUSH), we must flush/invalidate any cache information.
+ */
+/* static */
+void
+pmap_remove_mapping(pmap, va, pte, flags)
+ register pmap_t pmap;
+ register vm_offset_t va;
+ register pt_entry_t *pte;
+ int flags;
+{
+ register vm_offset_t pa;
+ register struct pv_entry *pv, *npv;
+ pmap_t ptpmap;
+ st_entry_t *ste;
+ int s, bits;
+#ifdef DEBUG
+ pt_entry_t opte;
+
+ if (pmapdebug & (PDB_FOLLOW|PDB_REMOVE|PDB_PROTECT))
+ printf("pmap_remove_mapping(%x, %x, %x, %x)\n",
+ pmap, va, pte, flags);
+#endif
+
+ /*
+ * PTE not provided, compute it from pmap and va.
+ */
+ if (pte == PT_ENTRY_NULL) {
+ pte = pmap_pte(pmap, va);
+ if (*pte == PG_NV)
+ return;
+ }
+#ifdef HAVEVAC
+ if (pmap_aliasmask && (flags & PRM_CFLUSH)) {
+ /*
+ * Purge kernel side of VAC to ensure we get the correct
+ * state of any hardware maintained bits.
+ */
+ DCIS();
+#ifdef PMAPSTATS
+ remove_stats.sflushes++;
+#endif
+ /*
+ * If this is a non-CI user mapping for the current process,
+ * flush the VAC. Note that the kernel side was flushed
+ * above so we don't worry about non-CI kernel mappings.
+ */
+ if (pmap == curproc->p_vmspace->vm_map.pmap &&
+ !pmap_pte_ci(pte)) {
+ DCIU();
+#ifdef PMAPSTATS
+ remove_stats.uflushes++;
+#endif
+ }
+ }
+#endif
+ pa = pmap_pte_pa(pte);
+#ifdef DEBUG
+ opte = *pte;
+#endif
+#ifdef PMAPSTATS
+ remove_stats.removes++;
+#endif
+ /*
+ * Update statistics
+ */
+ if (pmap_pte_w(pte))
+ pmap->pm_stats.wired_count--;
+ pmap->pm_stats.resident_count--;
+
+ /*
+ * Invalidate the PTE after saving the reference modify info.
+ */
+#ifdef DEBUG
+ if (pmapdebug & PDB_REMOVE)
+ printf("remove: invalidating pte at %x\n", pte);
+#endif
+ bits = *pte & (PG_U|PG_M);
+ *pte = PG_NV;
+ if ((flags & PRM_TFLUSH) && active_pmap(pmap))
+ TBIS(va);
+ /*
+ * For user mappings decrement the wiring count on
+ * the PT page. We do this after the PTE has been
+ * invalidated because vm_map_pageable winds up in
+ * pmap_pageable which clears the modify bit for the
+ * PT page.
+ */
+ if (pmap != pmap_kernel()) {
+ (void) vm_map_pageable(pt_map, trunc_page(pte),
+ round_page(pte+1), TRUE);
+#ifdef DEBUG
+ if (pmapdebug & PDB_WIRING)
+ pmap_check_wiring("remove", trunc_page(pte));
+#endif
+ }
+ /*
+ * If this isn't a managed page, we are all done.
+ */
+ if (pa < vm_first_phys || pa >= vm_last_phys)
+ return;
+ /*
+ * Otherwise remove it from the PV table
+ * (raise IPL since we may be called at interrupt time).
+ */
+ pv = pa_to_pvh(pa);
+ ste = ST_ENTRY_NULL;
+ s = splimp();
+ /*
+ * If it is the first entry on the list, it is actually
+ * in the header and we must copy the following entry up
+ * to the header. Otherwise we must search the list for
+ * the entry. In either case we free the now unused entry.
+ */
+ if (pmap == pv->pv_pmap && va == pv->pv_va) {
+ ste = pv->pv_ptste;
+ ptpmap = pv->pv_ptpmap;
+ npv = pv->pv_next;
+ if (npv) {
+ npv->pv_flags = pv->pv_flags;
+ *pv = *npv;
+ pmap_free_pv(npv);
+ } else
+ pv->pv_pmap = NULL;
+#ifdef PMAPSTATS
+ remove_stats.pvfirst++;
+#endif
+ } else {
+ for (npv = pv->pv_next; npv; npv = npv->pv_next) {
+#ifdef PMAPSTATS
+ remove_stats.pvsearch++;
+#endif
+ if (pmap == npv->pv_pmap && va == npv->pv_va)
+ break;
+ pv = npv;
+ }
+#ifdef DEBUG
+ if (npv == NULL)
+ panic("pmap_remove: PA not in pv_tab");
+#endif
+ ste = npv->pv_ptste;
+ ptpmap = npv->pv_ptpmap;
+ pv->pv_next = npv->pv_next;
+ pmap_free_pv(npv);
+ pv = pa_to_pvh(pa);
+ }
+#ifdef HAVEVAC
+ /*
+ * If only one mapping left we no longer need to cache inhibit
+ */
+ if (pmap_aliasmask &&
+ pv->pv_pmap && pv->pv_next == NULL && (pv->pv_flags & PV_CI)) {
+#ifdef DEBUG
+ if (pmapdebug & PDB_CACHE)
+ printf("remove: clearing CI for pa %x\n", pa);
+#endif
+ pv->pv_flags &= ~PV_CI;
+ pmap_changebit(pa, PG_CI, FALSE);
+#ifdef DEBUG
+ if ((pmapdebug & (PDB_CACHE|PDB_PVDUMP)) ==
+ (PDB_CACHE|PDB_PVDUMP))
+ pmap_pvdump(pa);
+#endif
+ }
+#endif
+ /*
+ * If this was a PT page we must also remove the
+ * mapping from the associated segment table.
+ */
+ if (ste) {
+#ifdef PMAPSTATS
+ remove_stats.ptinvalid++;
+#endif
+#ifdef DEBUG
+ if (pmapdebug & (PDB_REMOVE|PDB_PTPAGE))
+ printf("remove: ste was %x@%x pte was %x@%x\n",
+ *ste, ste, opte, pmap_pte(pmap, va));
+#endif
+#if defined(M68040)
+ if (mmutype == MMU_68040) {
+ st_entry_t *este = &ste[NPTEPG/SG4_LEV3SIZE];
+
+ while (ste < este)
+ *ste++ = SG_NV;
+#ifdef DEBUG
+ ste -= NPTEPG/SG4_LEV3SIZE;
+#endif
+ } else
+#endif
+ *ste = SG_NV;
+ /*
+ * If it was a user PT page, we decrement the
+ * reference count on the segment table as well,
+ * freeing it if it is now empty.
+ */
+ if (ptpmap != pmap_kernel()) {
+#ifdef DEBUG
+ if (pmapdebug & (PDB_REMOVE|PDB_SEGTAB))
+ printf("remove: stab %x, refcnt %d\n",
+ ptpmap->pm_stab, ptpmap->pm_sref - 1);
+ if ((pmapdebug & PDB_PARANOIA) &&
+ ptpmap->pm_stab != (st_entry_t *)trunc_page(ste))
+ panic("remove: bogus ste");
+#endif
+ if (--(ptpmap->pm_sref) == 0) {
+#ifdef DEBUG
+ if (pmapdebug&(PDB_REMOVE|PDB_SEGTAB))
+ printf("remove: free stab %x\n",
+ ptpmap->pm_stab);
+#endif
+ kmem_free_wakeup(st_map,
+ (vm_offset_t)ptpmap->pm_stab,
+ HP_STSIZE);
+ ptpmap->pm_stab = Segtabzero;
+ ptpmap->pm_stpa = Segtabzeropa;
+#if defined(M68040)
+ if (mmutype == MMU_68040)
+ ptpmap->pm_stfree = protostfree;
+#endif
+ ptpmap->pm_stchanged = TRUE;
+ /*
+ * XXX may have changed segment table
+ * pointer for current process so
+ * update now to reload hardware.
+ */
+ if (curproc != NULL &&
+ ptpmap == curproc->p_vmspace->vm_map.pmap)
+ PMAP_ACTIVATE(ptpmap,
+ &curproc->p_addr->u_pcb, 1);
+ }
+#ifdef DEBUG
+ else if (ptpmap->pm_sref < 0)
+ panic("remove: sref < 0");
+#endif
+ }
+#if 0
+ /*
+ * XXX this should be unnecessary as we have been
+ * flushing individual mappings as we go.
+ */
+ if (ptpmap == pmap_kernel())
+ TBIAS();
+ else
+ TBIAU();
+#endif
+ pv->pv_flags &= ~PV_PTPAGE;
+ ptpmap->pm_ptpages--;
+ }
+ /*
+ * Update saved attributes for managed page
+ */
+ pmap_attributes[pmap_page_index(pa)] |= bits;
+ splx(s);
+}
+
+/* static */
+boolean_t
+pmap_testbit(pa, bit)
+ register vm_offset_t pa;
+ int bit;
+{
+ register struct pv_entry *pv;
+ register pt_entry_t *pte;
+ int s;
+
+ if (pa < vm_first_phys || pa >= vm_last_phys)
+ return(FALSE);
+
+ pv = pa_to_pvh(pa);
+ s = splimp();
+ /*
+ * Check saved info first
+ */
+ if (pmap_attributes[pmap_page_index(pa)] & bit) {
+ splx(s);
+ return(TRUE);
+ }
+#ifdef HAVEVAC
+ /*
+ * Flush VAC to get correct state of any hardware maintained bits.
+ */
+ if (pmap_aliasmask && (bit & (PG_U|PG_M)))
+ DCIS();
+#endif
+ /*
+ * Not found, check current mappings returning
+ * immediately if found.
+ */
+ if (pv->pv_pmap != NULL) {
+ for (; pv; pv = pv->pv_next) {
+ pte = pmap_pte(pv->pv_pmap, pv->pv_va);
+ if (*pte & bit) {
+ splx(s);
+ return(TRUE);
+ }
+ }
+ }
+ splx(s);
+ return(FALSE);
+}
+
+/* static */
+void
+pmap_changebit(pa, bit, setem)
+ register vm_offset_t pa;
+ int bit;
+ boolean_t setem;
+{
+ register struct pv_entry *pv;
+ register pt_entry_t *pte, npte;
+ vm_offset_t va;
+ int s;
+ boolean_t firstpage = TRUE;
+#ifdef PMAPSTATS
+ struct chgstats *chgp;
+#endif
+
+#ifdef DEBUG
+ if (pmapdebug & PDB_BITS)
+ printf("pmap_changebit(%x, %x, %s)\n",
+ pa, bit, setem ? "set" : "clear");
+#endif
+ if (pa < vm_first_phys || pa >= vm_last_phys)
+ return;
+
+#ifdef PMAPSTATS
+ chgp = &changebit_stats[(bit>>2)-1];
+ if (setem)
+ chgp->setcalls++;
+ else
+ chgp->clrcalls++;
+#endif
+ pv = pa_to_pvh(pa);
+ s = splimp();
+ /*
+ * Clear saved attributes (modify, reference)
+ */
+ if (!setem)
+ pmap_attributes[pmap_page_index(pa)] &= ~bit;
+ /*
+ * Loop over all current mappings setting/clearing as appropos
+ * If setting RO do we need to clear the VAC?
+ */
+ if (pv->pv_pmap != NULL) {
+#ifdef DEBUG
+ int toflush = 0;
+#endif
+ for (; pv; pv = pv->pv_next) {
+#ifdef DEBUG
+ toflush |= (pv->pv_pmap == pmap_kernel()) ? 2 : 1;
+#endif
+ va = pv->pv_va;
+
+ /*
+ * XXX don't write protect pager mappings
+ */
+ if (bit == PG_RO) {
+ extern vm_offset_t pager_sva, pager_eva;
+
+ if (va >= pager_sva && va < pager_eva)
+ continue;
+ }
+
+ pte = pmap_pte(pv->pv_pmap, va);
+#ifdef HAVEVAC
+ /*
+ * Flush VAC to ensure we get correct state of HW bits
+ * so we don't clobber them.
+ */
+ if (firstpage && pmap_aliasmask) {
+ firstpage = FALSE;
+ DCIS();
+ }
+#endif
+ if (setem)
+ npte = *pte | bit;
+ else
+ npte = *pte & ~bit;
+ if (*pte != npte) {
+#if defined(M68040)
+ /*
+ * If we are changing caching status or
+ * protection make sure the caches are
+ * flushed (but only once).
+ */
+ if (firstpage && mmutype == MMU_68040 &&
+ (bit == PG_RO && setem ||
+ (bit & PG_CMASK))) {
+ firstpage = FALSE;
+ DCFP(pa);
+ ICPP(pa);
+ }
+#endif
+ *pte = npte;
+ if (active_pmap(pv->pv_pmap))
+ TBIS(va);
+#ifdef PMAPSTATS
+ if (setem)
+ chgp->sethits++;
+ else
+ chgp->clrhits++;
+#endif
+ }
+#ifdef PMAPSTATS
+ else {
+ if (setem)
+ chgp->setmiss++;
+ else
+ chgp->clrmiss++;
+ }
+#endif
+ }
+#if defined(HAVEVAC) && defined(DEBUG)
+ if (setem && bit == PG_RO && (pmapvacflush & PVF_PROTECT)) {
+ if ((pmapvacflush & PVF_TOTAL) || toflush == 3)
+ DCIA();
+ else if (toflush == 2)
+ DCIS();
+ else
+ DCIU();
+ }
+#endif
+ }
+ splx(s);
+}
+
+/* static */
+void
+pmap_enter_ptpage(pmap, va)
+ register pmap_t pmap;
+ register vm_offset_t va;
+{
+ register vm_offset_t ptpa;
+ register struct pv_entry *pv;
+ st_entry_t *ste;
+ int s;
+
+#ifdef DEBUG
+ if (pmapdebug & (PDB_FOLLOW|PDB_ENTER|PDB_PTPAGE))
+ printf("pmap_enter_ptpage: pmap %x, va %x\n", pmap, va);
+#endif
+#ifdef PMAPSTATS
+ enter_stats.ptpneeded++;
+#endif
+ /*
+ * Allocate a segment table if necessary. Note that it is allocated
+ * from a private map and not pt_map. This keeps user page tables
+ * aligned on segment boundaries in the kernel address space.
+ * The segment table is wired down. It will be freed whenever the
+ * reference count drops to zero.
+ */
+ if (pmap->pm_stab == Segtabzero) {
+ pmap->pm_stab = (st_entry_t *)
+ kmem_alloc(st_map, HP_STSIZE);
+ pmap->pm_stpa = (st_entry_t *)
+ pmap_extract(pmap_kernel(), (vm_offset_t)pmap->pm_stab);
+#if defined(M68040)
+ if (mmutype == MMU_68040) {
+#ifdef DEBUG
+ if (dowriteback && dokwriteback)
+#endif
+ pmap_changebit((vm_offset_t)pmap->pm_stpa, PG_CCB, 0);
+ pmap->pm_stfree = protostfree;
+ }
+#endif
+ pmap->pm_stchanged = TRUE;
+ /*
+ * XXX may have changed segment table pointer for current
+ * process so update now to reload hardware.
+ */
+ if (pmap == curproc->p_vmspace->vm_map.pmap)
+ PMAP_ACTIVATE(pmap, &curproc->p_addr->u_pcb, 1);
+#ifdef DEBUG
+ if (pmapdebug & (PDB_ENTER|PDB_PTPAGE|PDB_SEGTAB))
+ printf("enter: pmap %x stab %x(%x)\n",
+ pmap, pmap->pm_stab, pmap->pm_stpa);
+#endif
+ }
+
+ ste = pmap_ste(pmap, va);
+#if defined(M68040)
+ /*
+ * Allocate level 2 descriptor block if necessary
+ */
+ if (mmutype == MMU_68040) {
+ if (*ste == SG_NV) {
+ int ix;
+ caddr_t addr;
+
+ ix = bmtol2(pmap->pm_stfree);
+ if (ix == -1)
+ panic("enter: out of address space"); /* XXX */
+ pmap->pm_stfree &= ~l2tobm(ix);
+ addr = (caddr_t)&pmap->pm_stab[ix*SG4_LEV2SIZE];
+ bzero(addr, SG4_LEV2SIZE*sizeof(st_entry_t));
+ addr = (caddr_t)&pmap->pm_stpa[ix*SG4_LEV2SIZE];
+ *ste = (u_int)addr | SG_RW | SG_U | SG_V;
+#ifdef DEBUG
+ if (pmapdebug & (PDB_ENTER|PDB_PTPAGE|PDB_SEGTAB))
+ printf("enter: alloc ste2 %d(%x)\n", ix, addr);
+#endif
+ }
+ ste = pmap_ste2(pmap, va);
+ /*
+ * Since a level 2 descriptor maps a block of SG4_LEV3SIZE
+ * level 3 descriptors, we need a chunk of NPTEPG/SG4_LEV3SIZE
+ * (16) such descriptors (NBPG/SG4_LEV3SIZE bytes) to map a
+ * PT page--the unit of allocation. We set `ste' to point
+ * to the first entry of that chunk which is validated in its
+ * entirety below.
+ */
+ ste = (st_entry_t *)((int)ste & ~(NBPG/SG4_LEV3SIZE-1));
+#ifdef DEBUG
+ if (pmapdebug & (PDB_ENTER|PDB_PTPAGE|PDB_SEGTAB))
+ printf("enter: ste2 %x (%x)\n",
+ pmap_ste2(pmap, va), ste);
+#endif
+ }
+#endif
+ va = trunc_page((vm_offset_t)pmap_pte(pmap, va));
+
+ /*
+ * In the kernel we allocate a page from the kernel PT page
+ * free list and map it into the kernel page table map (via
+ * pmap_enter).
+ */
+ if (pmap == pmap_kernel()) {
+ register struct kpt_page *kpt;
+
+ s = splimp();
+ if ((kpt = kpt_free_list) == (struct kpt_page *)0) {
+ /*
+ * No PT pages available.
+ * Try once to free up unused ones.
+ */
+#ifdef DEBUG
+ if (pmapdebug & PDB_COLLECT)
+ printf("enter: no KPT pages, collecting...\n");
+#endif
+ pmap_collect(pmap_kernel());
+ if ((kpt = kpt_free_list) == (struct kpt_page *)0)
+ panic("pmap_enter_ptpage: can't get KPT page");
+ }
+#ifdef PMAPSTATS
+ if (++kpt_stats.kptinuse > kpt_stats.kptmaxuse)
+ kpt_stats.kptmaxuse = kpt_stats.kptinuse;
+#endif
+ kpt_free_list = kpt->kpt_next;
+ kpt->kpt_next = kpt_used_list;
+ kpt_used_list = kpt;
+ ptpa = kpt->kpt_pa;
+ bzero((caddr_t)kpt->kpt_va, NBPG);
+ pmap_enter(pmap, va, ptpa, VM_PROT_DEFAULT, TRUE);
+#ifdef DEBUG
+ if (pmapdebug & (PDB_ENTER|PDB_PTPAGE)) {
+ int ix = pmap_ste(pmap, va) - pmap_ste(pmap, 0);
+
+ printf("enter: add &Sysptmap[%d]: %x (KPT page %x)\n",
+ ix, Sysptmap[ix], kpt->kpt_va);
+ }
+#endif
+ splx(s);
+ }
+ /*
+ * For user processes we just simulate a fault on that location
+ * letting the VM system allocate a zero-filled page.
+ */
+ else {
+#ifdef DEBUG
+ if (pmapdebug & (PDB_ENTER|PDB_PTPAGE))
+ printf("enter: about to fault UPT pg at %x\n", va);
+#endif
+ s = vm_fault(pt_map, va, VM_PROT_READ|VM_PROT_WRITE, FALSE);
+ if (s != KERN_SUCCESS) {
+ printf("vm_fault(pt_map, %x, RW, 0) -> %d\n", va, s);
+ panic("pmap_enter: vm_fault failed");
+ }
+ ptpa = pmap_extract(pmap_kernel(), va);
+ /*
+ * Mark the page clean now to avoid its pageout (and
+ * hence creation of a pager) between now and when it
+ * is wired; i.e. while it is on a paging queue.
+ */
+ PHYS_TO_VM_PAGE(ptpa)->flags |= PG_CLEAN;
+#ifdef DEBUG
+ PHYS_TO_VM_PAGE(ptpa)->flags |= PG_PTPAGE;
+#endif
+ }
+#if defined(M68040)
+ /*
+ * Turn off copyback caching of page table pages,
+ * could get ugly otherwise.
+ */
+#ifdef DEBUG
+ if (dowriteback && dokwriteback)
+#endif
+ if (mmutype == MMU_68040) {
+ pt_entry_t *pte = pmap_pte(pmap_kernel(), va);
+#ifdef DEBUG
+ if ((pmapdebug & PDB_PARANOIA) && (*pte & PG_CCB) == 0)
+ printf("%s PT no CCB: kva=%x ptpa=%x pte@%x=%x\n",
+ pmap == pmap_kernel() ? "Kernel" : "User",
+ va, ptpa, pte, *pte);
+#endif
+ pmap_changebit(ptpa, PG_CCB, 0);
+ }
+#endif
+ /*
+ * Locate the PV entry in the kernel for this PT page and
+ * record the STE address. This is so that we can invalidate
+ * the STE when we remove the mapping for the page.
+ */
+ pv = pa_to_pvh(ptpa);
+ s = splimp();
+ if (pv) {
+ pv->pv_flags |= PV_PTPAGE;
+ do {
+ if (pv->pv_pmap == pmap_kernel() && pv->pv_va == va)
+ break;
+ } while (pv = pv->pv_next);
+ }
+#ifdef DEBUG
+ if (pv == NULL)
+ panic("pmap_enter_ptpage: PT page not entered");
+#endif
+ pv->pv_ptste = ste;
+ pv->pv_ptpmap = pmap;
+#ifdef DEBUG
+ if (pmapdebug & (PDB_ENTER|PDB_PTPAGE))
+ printf("enter: new PT page at PA %x, ste at %x\n", ptpa, ste);
+#endif
+
+ /*
+ * Map the new PT page into the segment table.
+ * Also increment the reference count on the segment table if this
+ * was a user page table page. Note that we don't use vm_map_pageable
+ * to keep the count like we do for PT pages, this is mostly because
+ * it would be difficult to identify ST pages in pmap_pageable to
+ * release them. We also avoid the overhead of vm_map_pageable.
+ */
+#if defined(M68040)
+ if (mmutype == MMU_68040) {
+ st_entry_t *este;
+
+ for (este = &ste[NPTEPG/SG4_LEV3SIZE]; ste < este; ste++) {
+ *ste = ptpa | SG_U | SG_RW | SG_V;
+ ptpa += SG4_LEV3SIZE * sizeof(st_entry_t);
+ }
+ } else
+#endif
+ *ste = (ptpa & SG_FRAME) | SG_RW | SG_V;
+ if (pmap != pmap_kernel()) {
+ pmap->pm_sref++;
+#ifdef DEBUG
+ if (pmapdebug & (PDB_ENTER|PDB_PTPAGE|PDB_SEGTAB))
+ printf("enter: stab %x refcnt %d\n",
+ pmap->pm_stab, pmap->pm_sref);
+#endif
+ }
+#if 0
+ /*
+ * Flush stale TLB info.
+ */
+ if (pmap == pmap_kernel())
+ TBIAS();
+ else
+ TBIAU();
+#endif
+ pmap->pm_ptpages++;
+ splx(s);
+}
+
+#ifdef DEBUG
+/* static */
+void
+pmap_pvdump(pa)
+ vm_offset_t pa;
+{
+ register struct pv_entry *pv;
+
+ printf("pa %x", pa);
+ for (pv = pa_to_pvh(pa); pv; pv = pv->pv_next)
+ printf(" -> pmap %x, va %x, ptste %x, ptpmap %x, flags %x",
+ pv->pv_pmap, pv->pv_va, pv->pv_ptste, pv->pv_ptpmap,
+ pv->pv_flags);
+ printf("\n");
+}
+
+/* static */
+void
+pmap_check_wiring(str, va)
+ char *str;
+ vm_offset_t va;
+{
+ vm_map_entry_t entry;
+ register int count;
+ register pt_entry_t *pte;
+
+ va = trunc_page(va);
+ if (!pmap_ste_v(pmap_kernel(), va) ||
+ !pmap_pte_v(pmap_pte(pmap_kernel(), va)))
+ return;
+
+ if (!vm_map_lookup_entry(pt_map, va, &entry)) {
+ printf("wired_check: entry for %x not found\n", va);
+ return;
+ }
+ count = 0;
+ for (pte = (pt_entry_t *)va; pte < (pt_entry_t *)(va + NBPG); pte++)
+ if (*pte)
+ count++;
+ if (entry->wired_count != count)
+ printf("*%s*: %x: w%d/a%d\n",
+ str, va, entry->wired_count, count);
+}
+#endif
diff --git a/sys/arch/mvme68k/mvme68k/pmap_bootstrap.c b/sys/arch/mvme68k/mvme68k/pmap_bootstrap.c
new file mode 100644
index 00000000000..bdd0064289a
--- /dev/null
+++ b/sys/arch/mvme68k/mvme68k/pmap_bootstrap.c
@@ -0,0 +1,505 @@
+/* $NetBSD: pmap_bootstrap.c,v 1.1.1.1 1995/07/25 23:12:02 chuck Exp $ */
+
+/*
+ * Copyright (c) 1991, 1993
+ * 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.
+ *
+ * @(#)pmap_bootstrap.c 8.1 (Berkeley) 6/10/93
+ */
+
+#include <sys/param.h>
+#include <sys/msgbuf.h>
+#include <machine/pte.h>
+#include <mvme68k/mvme68k/clockreg.h>
+#include <machine/vmparam.h>
+#include <machine/cpu.h>
+
+#include <vm/vm.h>
+
+#define RELOC(v, t) *((t*)((u_int)&(v) + firstpa))
+
+extern char *etext;
+extern int Sysptsize;
+extern char *extiobase, *proc0paddr;
+extern st_entry_t *Sysseg;
+extern pt_entry_t *Sysptmap, *Sysmap;
+
+extern int maxmem, physmem;
+extern vm_offset_t avail_start, avail_end, virtual_avail, virtual_end;
+extern vm_size_t mem_size;
+extern int protection_codes[];
+#ifdef HAVEVAC
+extern int pmap_aliasmask;
+#endif
+
+/*
+ * Special purpose kernel virtual addresses, used for mapping
+ * physical pages for a variety of temporary or permanent purposes:
+ *
+ * CADDR1, CADDR2: pmap zero/copy operations
+ * vmmap: /dev/mem, crash dumps, parity error checking
+ * ledbase: SPU LEDs
+ * msgbufp: kernel message buffer
+ */
+caddr_t CADDR1, CADDR2, vmmap, ledbase;
+struct msgbuf *msgbufp;
+extern void *ledatabuf; /* XXXCDC */
+
+/*
+ * Bootstrap the VM system.
+ *
+ * Called with MMU off so we must relocate all global references by `firstpa'
+ * (don't call any functions here!) `nextpa' is the first available physical
+ * memory address. Returns an updated first PA reflecting the memory we
+ * have allocated. MMU is still off when we return.
+ *
+ * XXX assumes sizeof(u_int) == sizeof(pt_entry_t)
+ * XXX a PIC compiler would make this much easier.
+ */
+void
+pmap_bootstrap(nextpa, firstpa)
+ vm_offset_t nextpa;
+ register vm_offset_t firstpa;
+{
+ vm_offset_t kstpa, kptpa, iiopa, eiopa, kptmpa, lkptpa, p0upa;
+ u_int nptpages, kstsize;
+ register st_entry_t protoste, *ste;
+ register pt_entry_t protopte, *pte, *epte;
+
+ /*
+ * Calculate important physical addresses:
+ *
+ * kstpa kernel segment table 1 page (!040)
+ * N pages (040)
+ *
+ * kptpa statically allocated
+ * kernel PT pages Sysptsize+ pages
+ *
+ * iiopa internal IO space
+ * PT pages IIOMAPSIZE pages
+ *
+ * eiopa external IO space
+ * PT pages EIOMAPSIZE pages
+ *
+ * [ Sysptsize is the number of pages of PT, IIOMAPSIZE and
+ * EIOMAPSIZE are the number of PTEs, hence we need to round
+ * the total to a page boundary with IO maps at the end. ]
+ *
+ * kptmpa kernel PT map 1 page
+ *
+ * lkptpa last kernel PT page 1 page
+ *
+ * p0upa proc 0 u-area UPAGES pages
+ *
+ * The KVA corresponding to any of these PAs is:
+ * (PA - firstpa + KERNBASE).
+ */
+ if (RELOC(mmutype, int) == MMU_68040)
+ kstsize = MAXKL2SIZE / (NPTEPG/SG4_LEV2SIZE);
+ else
+ kstsize = 1;
+ kstpa = nextpa;
+ nextpa += kstsize * NBPG;
+ kptpa = nextpa;
+ nptpages = RELOC(Sysptsize, int) +
+ (IIOMAPSIZE + EIOMAPSIZE + NPTEPG - 1) / NPTEPG;
+ nextpa += nptpages * NBPG;
+ eiopa = nextpa - EIOMAPSIZE * sizeof(pt_entry_t);
+ iiopa = eiopa - IIOMAPSIZE * sizeof(pt_entry_t);
+ kptmpa = nextpa;
+ nextpa += NBPG;
+ lkptpa = nextpa;
+ nextpa += NBPG;
+ p0upa = nextpa;
+ nextpa += USPACE;
+ { /* XXXCDC */
+ ledatabuf = (void *)nextpa;
+ nextpa += 4 * NBPG;
+ } /* XXXCDC */
+
+ /*
+ * Initialize segment table and kernel page table map.
+ *
+ * On 68030s and earlier MMUs the two are identical except for
+ * the valid bits so both are initialized with essentially the
+ * same values. On the 68040, which has a mandatory 3-level
+ * structure, the segment table holds the level 1 table and part
+ * (or all) of the level 2 table and hence is considerably
+ * different. Here the first level consists of 128 descriptors
+ * (512 bytes) each mapping 32mb of address space. Each of these
+ * points to blocks of 128 second level descriptors (512 bytes)
+ * each mapping 256kb. Note that there may be additional "segment
+ * table" pages depending on how large MAXKL2SIZE is.
+ *
+ * Portions of the last segment of KVA space (0xFFF00000 -
+ * 0xFFFFFFFF) are mapped for a couple of purposes. 0xFFF00000
+ * for UPAGES is used for mapping the current process u-area
+ * (u + kernel stack). The very last page (0xFFFFF000) is mapped
+ * to the last physical page of RAM to give us a region in which
+ * PA == VA. We use the first part of this page for enabling
+ * and disabling mapping. The last part of this page also contains
+ * info left by the boot ROM.
+ *
+ * XXX cramming two levels of mapping into the single "segment"
+ * table on the 68040 is intended as a temporary hack to get things
+ * working. The 224mb of address space that this allows will most
+ * likely be insufficient in the future (at least for the kernel).
+ */
+ if (RELOC(mmutype, int) == MMU_68040) {
+ register int num;
+
+ /*
+ * First invalidate the entire "segment table" pages
+ * (levels 1 and 2 have the same "invalid" value).
+ */
+ pte = (u_int *)kstpa;
+ epte = &pte[kstsize * NPTEPG];
+ while (pte < epte)
+ *pte++ = SG_NV;
+ /*
+ * Initialize level 2 descriptors (which immediately
+ * follow the level 1 table). We need:
+ * NPTEPG / SG4_LEV3SIZE
+ * level 2 descriptors to map each of the nptpages+1
+ * pages of PTEs. Note that we set the "used" bit
+ * now to save the HW the expense of doing it.
+ */
+ num = (nptpages + 1) * (NPTEPG / SG4_LEV3SIZE);
+ pte = &((u_int *)kstpa)[SG4_LEV1SIZE];
+ epte = &pte[num];
+ protoste = kptpa | SG_U | SG_RW | SG_V;
+ while (pte < epte) {
+ *pte++ = protoste;
+ protoste += (SG4_LEV3SIZE * sizeof(st_entry_t));
+ }
+ /*
+ * Initialize level 1 descriptors. We need:
+ * roundup(num, SG4_LEV2SIZE) / SG4_LEV2SIZE
+ * level 1 descriptors to map the `num' level 2's.
+ */
+ pte = (u_int *)kstpa;
+ epte = &pte[roundup(num, SG4_LEV2SIZE) / SG4_LEV2SIZE];
+ protoste = (u_int)&pte[SG4_LEV1SIZE] | SG_U | SG_RW | SG_V;
+ while (pte < epte) {
+ *pte++ = protoste;
+ protoste += (SG4_LEV2SIZE * sizeof(st_entry_t));
+ }
+ /*
+ * Initialize the final level 1 descriptor to map the last
+ * block of level 2 descriptors.
+ */
+ ste = &((u_int *)kstpa)[SG4_LEV1SIZE-1];
+ pte = &((u_int *)kstpa)[kstsize*NPTEPG - SG4_LEV2SIZE];
+ *ste = (u_int)pte | SG_U | SG_RW | SG_V;
+ /*
+ * Now initialize the final portion of that block of
+ * descriptors to map the "last PT page".
+ */
+ pte = &((u_int *)kstpa)[kstsize*NPTEPG - NPTEPG/SG4_LEV3SIZE];
+ epte = &pte[NPTEPG/SG4_LEV3SIZE];
+ protoste = lkptpa | SG_U | SG_RW | SG_V;
+ while (pte < epte) {
+ *pte++ = protoste;
+ protoste += (SG4_LEV3SIZE * sizeof(st_entry_t));
+ }
+ /*
+ * Initialize Sysptmap
+ */
+ pte = (u_int *)kptmpa;
+ epte = &pte[nptpages+1];
+ protopte = kptpa | PG_RW | PG_CI | PG_V;
+ while (pte < epte) {
+ *pte++ = protopte;
+ protopte += NBPG;
+ }
+ pte = &((u_int *)kptmpa)[NPTEPG-1];
+ *pte = lkptpa | PG_RW | PG_CI | PG_V;
+ } else {
+ /*
+ * Map the page table pages in both the HW segment table
+ * and the software Sysptmap. Note that Sysptmap is also
+ * considered a PT page hence the +1.
+ */
+ ste = (u_int *)kstpa;
+ pte = (u_int *)kptmpa;
+ epte = &pte[nptpages+1];
+ protoste = kptpa | SG_RW | SG_V;
+ protopte = kptpa | PG_RW | PG_CI | PG_V;
+ while (pte < epte) {
+ *ste++ = protoste;
+ *pte++ = protopte;
+ protoste += NBPG;
+ protopte += NBPG;
+ }
+ /*
+ * Invalidate all but the last remaining entries in both.
+ */
+ epte = &((u_int *)kptmpa)[NPTEPG-1];
+ while (pte < epte) {
+ *ste++ = SG_NV;
+ *pte++ = PG_NV;
+ }
+ /*
+ * Initialize the last to point to point to the page
+ * table page allocated earlier.
+ */
+ *ste = lkptpa | SG_RW | SG_V;
+ *pte = lkptpa | PG_RW | PG_CI | PG_V;
+ }
+ /*
+ * Invalidate all but the final entry in the last kernel PT page
+ * (u-area PTEs will be validated later). The final entry maps
+ * the last page of physical memory.
+ */
+ pte = (u_int *)lkptpa;
+ epte = &pte[NPTEPG-1];
+ while (pte < epte)
+ *pte++ = PG_NV;
+#ifdef MAXADDR
+ /* tmp double-map for cpu's with physmem at the end of memory */
+ *pte = MAXADDR | PG_RW | PG_CI | PG_V;
+#endif
+ /*
+ * Initialize kernel page table.
+ * Start by invalidating the `nptpages' that we have allocated.
+ */
+ pte = (u_int *)kptpa;
+ epte = &pte[nptpages * NPTEPG];
+ while (pte < epte)
+ *pte++ = PG_NV;
+ /*
+ * Validate PTEs for kernel text (RO)
+ */
+ pte = &((u_int *)kptpa)[m68k_btop(KERNBASE)];
+ epte = &pte[m68k_btop(m68k_trunc_page(&etext))];
+#if defined(KGDB) || defined(DDB)
+ protopte = firstpa | PG_RW | PG_V; /* XXX RW for now */
+#else
+ protopte = firstpa | PG_RO | PG_V;
+#endif
+ while (pte < epte) {
+ *pte++ = protopte;
+ protopte += NBPG;
+ }
+ /*
+ * Validate PTEs for kernel data/bss, dynamic data allocated
+ * by us so far (nextpa - firstpa bytes), and pages for proc0
+ * u-area and page table allocated below (RW).
+ */
+ epte = &((u_int *)kptpa)[m68k_btop(nextpa - firstpa)];
+ protopte = (protopte & ~PG_PROT) | PG_RW;
+ /*
+ * Enable copy-back caching of data pages
+ */
+ if (RELOC(mmutype, int) == MMU_68040)
+ protopte |= PG_CCB;
+ while (pte < epte) {
+ *pte++ = protopte;
+ protopte += NBPG;
+ }
+ { /* XXXCDC -- uncache lebuf */
+ u_int *lepte = &((u_int *)kptpa)[m68k_btop(ledatabuf)];
+
+ lepte[0] = lepte[0] | PG_CI;
+ lepte[1] = lepte[1] | PG_CI;
+ lepte[2] = lepte[2] | PG_CI;
+ lepte[3] = lepte[3] | PG_CI;
+ } /* XXXCDC yuck */
+
+ /*
+ * Finally, validate the internal IO space PTEs (RW+CI).
+ * We do this here since the 320/350 MMU registers (also
+ * used, but to a lesser extent, on other models) are mapped
+ * in this range and it would be nice to be able to access
+ * them after the MMU is turned on.
+ */
+ pte = (u_int *)iiopa;
+ epte = (u_int *)eiopa;
+ protopte = INTIOBASE | PG_RW | PG_CI | PG_V;
+ while (pte < epte) {
+ *pte++ = protopte;
+ protopte += NBPG;
+ }
+
+ /*
+ * Calculate important exported kernel virtual addresses
+ */
+ /*
+ * Sysseg: base of kernel segment table
+ */
+ RELOC(Sysseg, st_entry_t *) =
+ (st_entry_t *)(kstpa - firstpa);
+ /*
+ * Sysptmap: base of kernel page table map
+ */
+ RELOC(Sysptmap, pt_entry_t *) =
+ (pt_entry_t *)(kptmpa - firstpa);
+ /*
+ * Sysmap: kernel page table (as mapped through Sysptmap)
+ * Immediately follows `nptpages' of static kernel page table.
+ */
+ RELOC(Sysmap, pt_entry_t *) =
+ (pt_entry_t *)m68k_ptob(nptpages * NPTEPG);
+ /*
+ * intiobase, intiolimit: base and end of internal (DIO) IO space.
+ * IIOMAPSIZE pages prior to external IO space at end of static
+ * kernel page table.
+ */
+ RELOC(intiobase, char *) =
+ (char *)m68k_ptob(nptpages*NPTEPG - (IIOMAPSIZE+EIOMAPSIZE));
+ RELOC(intiolimit, char *) =
+ (char *)m68k_ptob(nptpages*NPTEPG - EIOMAPSIZE);
+ /*
+ * extiobase: base of external (DIO-II) IO space.
+ * EIOMAPSIZE pages at the end of the static kernel page table.
+ */
+ RELOC(extiobase, char *) =
+ (char *)m68k_ptob(nptpages*NPTEPG - EIOMAPSIZE);
+
+ /*
+ * Setup u-area for process 0.
+ */
+ /*
+ * Zero the u-area.
+ * NOTE: `pte' and `epte' aren't PTEs here.
+ */
+ pte = (u_int *)p0upa;
+ epte = (u_int *)(p0upa + USPACE);
+ while (pte < epte)
+ *pte++ = 0;
+ /*
+ * Remember the u-area address so it can be loaded in the
+ * proc struct p_addr field later.
+ */
+ RELOC(proc0paddr, char *) = (char *)(p0upa - firstpa);
+
+ /*
+ * VM data structures are now initialized, set up data for
+ * the pmap module.
+ */
+ RELOC(avail_start, vm_offset_t) = nextpa;
+ RELOC(avail_end, vm_offset_t) =
+ m68k_ptob(RELOC(maxmem, int))
+ /* XXX allow for msgbuf */
+ - m68k_round_page(sizeof(struct msgbuf));
+ RELOC(mem_size, vm_size_t) = m68k_ptob(RELOC(physmem, int));
+ RELOC(virtual_avail, vm_offset_t) =
+ VM_MIN_KERNEL_ADDRESS + (nextpa - firstpa);
+ RELOC(virtual_end, vm_offset_t) = VM_MAX_KERNEL_ADDRESS;
+
+#ifdef HAVEVAC
+ /*
+ * Determine VA aliasing distance if any
+ */
+ if (RELOC(ectype, int) == EC_VIRT)
+ if (RELOC(machineid, int) == HP_320)
+ RELOC(pmap_aliasmask, int) = 0x3fff; /* 16k */
+ else if (RELOC(machineid, int) == HP_350)
+ RELOC(pmap_aliasmask, int) = 0x7fff; /* 32k */
+#endif
+
+ /*
+ * Initialize protection array.
+ * XXX don't use a switch statement, it might produce an
+ * absolute "jmp" table.
+ */
+ {
+ register int *kp;
+
+ kp = &RELOC(protection_codes, int);
+ kp[VM_PROT_NONE|VM_PROT_NONE|VM_PROT_NONE] = 0;
+ kp[VM_PROT_READ|VM_PROT_NONE|VM_PROT_NONE] = PG_RO;
+ kp[VM_PROT_READ|VM_PROT_NONE|VM_PROT_EXECUTE] = PG_RO;
+ kp[VM_PROT_NONE|VM_PROT_NONE|VM_PROT_EXECUTE] = PG_RO;
+ kp[VM_PROT_NONE|VM_PROT_WRITE|VM_PROT_NONE] = PG_RW;
+ kp[VM_PROT_NONE|VM_PROT_WRITE|VM_PROT_EXECUTE] = PG_RW;
+ kp[VM_PROT_READ|VM_PROT_WRITE|VM_PROT_NONE] = PG_RW;
+ kp[VM_PROT_READ|VM_PROT_WRITE|VM_PROT_EXECUTE] = PG_RW;
+ }
+
+ /*
+ * Kernel page/segment table allocated in locore,
+ * just initialize pointers.
+ */
+ {
+ struct pmap *kpm = &RELOC(kernel_pmap_store, struct pmap);
+
+ kpm->pm_stab = RELOC(Sysseg, st_entry_t *);
+ kpm->pm_ptab = RELOC(Sysmap, pt_entry_t *);
+ simple_lock_init(&kpm->pm_lock);
+ kpm->pm_count = 1;
+ kpm->pm_stpa = (st_entry_t *)kstpa;
+ /*
+ * For the 040 we also initialize the free level 2
+ * descriptor mask noting that we have used:
+ * 0: level 1 table
+ * 1 to `num': map page tables
+ * MAXKL2SIZE-1: maps last-page page table
+ */
+ if (RELOC(mmutype, int) == MMU_68040) {
+ register int num;
+
+ kpm->pm_stfree = ~l2tobm(0);
+ num = roundup((nptpages + 1) * (NPTEPG / SG4_LEV3SIZE),
+ SG4_LEV2SIZE) / SG4_LEV2SIZE;
+ while (num)
+ kpm->pm_stfree &= ~l2tobm(num--);
+ kpm->pm_stfree &= ~l2tobm(MAXKL2SIZE-1);
+ for (num = MAXKL2SIZE;
+ num < sizeof(kpm->pm_stfree)*NBBY;
+ num++)
+ kpm->pm_stfree &= ~l2tobm(num);
+ }
+ }
+
+ /*
+ * Allocate some fixed, special purpose kernel virtual addresses
+ */
+ {
+ vm_offset_t va = RELOC(virtual_avail, vm_offset_t);
+
+ RELOC(CADDR1, caddr_t) = (caddr_t)va;
+ va += NBPG;
+ RELOC(CADDR2, caddr_t) = (caddr_t)va;
+ va += NBPG;
+ RELOC(vmmap, caddr_t) = (caddr_t)va;
+ va += NBPG;
+ RELOC(ledbase, caddr_t) = (caddr_t)va;
+ va += NBPG;
+ RELOC(msgbufp, struct msgbuf *) = (struct msgbuf *)va;
+ va += NBPG;
+ RELOC(virtual_avail, vm_offset_t) = va;
+ }
+}
diff --git a/sys/arch/mvme68k/mvme68k/swapgeneric.c b/sys/arch/mvme68k/mvme68k/swapgeneric.c
new file mode 100644
index 00000000000..a48e0954402
--- /dev/null
+++ b/sys/arch/mvme68k/mvme68k/swapgeneric.c
@@ -0,0 +1,170 @@
+/* $NetBSD: swapgeneric.c,v 1.1.1.1 1995/07/25 23:12:00 chuck Exp $ */
+
+/*
+ * Copyright (c) 1982, 1986 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)swapgeneric.c 7.5 (Berkeley) 5/7/91
+ */
+
+#include <sys/param.h>
+#include <sys/conf.h>
+#include <sys/buf.h>
+#include <sys/systm.h>
+#include <sys/reboot.h>
+#include <sys/device.h>
+
+/*
+ * Generic configuration; all in one
+ */
+dev_t rootdev = NODEV;
+dev_t argdev = NODEV;
+dev_t dumpdev = NODEV;
+int nswap;
+struct swdevt swdevt[] = {
+ { -1, 1, 0 },
+ { 0, 0, 0 },
+};
+int dmmin, dmmax, dmtext;
+
+extern struct cfdriver sdcd;
+extern struct cfdriver wdcd;
+extern struct cfdriver idcd;
+
+struct genericconf {
+ struct cfdriver *gc_driver;
+ char *gc_name;
+ dev_t gc_root;
+} genericconf[] = {
+ { &sdcd, "sd", makedev(1, 0), },
+ { &wdcd, "wd", makedev(2, 0), },
+ { &idcd, "id", makedev(4, 0), },
+ { 0 },
+};
+
+extern int ffs_mountroot();
+int (*mountroot)() = ffs_mountroot;
+
+setconf()
+{
+ register struct genericconf *gc;
+ register struct bus_device *device;
+ register char *cp;
+ int unit, swaponroot = 0;
+
+ if (rootdev != NODEV)
+ goto doswap;
+ unit = 0;
+ if (boothowto & RB_ASKNAME) {
+ char name[128];
+retry:
+ printf("root device? ");
+ gets(name);
+ for (gc = genericconf; gc->gc_driver; gc++)
+ if (gc->gc_name[0] == name[0] &&
+ gc->gc_name[1] == name[1])
+ goto gotit;
+ printf("use one of:");
+ for (gc = genericconf; gc->gc_driver; gc++)
+ printf(" %s%%d", gc->gc_name);
+ printf("\n");
+ goto retry;
+gotit:
+ cp = &name[2];
+ if (*cp < '0' || *cp > '9') {
+ printf("bad/missing unit number\n");
+ goto retry;
+ }
+ while (*cp >= '0' && *cp <= '9')
+ unit = 10 * unit + *cp++ - '0';
+ if (*cp == '*')
+ swaponroot++;
+ goto found;
+ }
+ for (gc = genericconf; gc->gc_driver; gc++) {
+ for (cfp = cfdata; cfp->cf_driver; ++cfp) {
+ if (cfp->state == FSTATE_FOUND && cfp->unit == 0
+ && cfp->cf_driver == gc->gc_driver) {
+ printf("root on %s0\n", device->name);
+ goto found;
+ }
+ }
+ }
+ printf("no suitable root\n");
+ asm("stop #0x2700");
+found:
+ gc->gc_root = makedev(major(gc->gc_root), unit*8);
+ rootdev = gc->gc_root;
+doswap:
+ swdevt[0].sw_dev = argdev = dumpdev =
+ makedev(major(rootdev), minor(rootdev)+1);
+ /* swap size and dumplo set during autoconfigure */
+ if (swaponroot)
+ rootdev = dumpdev;
+}
+
+gets(cp)
+ char *cp;
+{
+ register char *lp;
+ register c;
+
+ lp = cp;
+ for (;;) {
+ cnputc(c = cngetc());
+ switch (c) {
+ case '\n':
+ case '\r':
+ *lp++ = '\0';
+ return;
+ case '\b':
+ case '\177':
+ if (lp > cp) {
+ lp--;
+ cnputc(' ');
+ cnputc('\b');
+ }
+ continue;
+ case '#':
+ lp--;
+ if (lp < cp)
+ lp = cp;
+ continue;
+ case '@':
+ case 'u'&037:
+ lp = cp;
+ cnputc('\n');
+ continue;
+ default:
+ *lp++ = c;
+ }
+ }
+}
diff --git a/sys/arch/mvme68k/mvme68k/sys_machdep.c b/sys/arch/mvme68k/mvme68k/sys_machdep.c
new file mode 100644
index 00000000000..a71befdf312
--- /dev/null
+++ b/sys/arch/mvme68k/mvme68k/sys_machdep.c
@@ -0,0 +1,269 @@
+/* $NetBSD: sys_machdep.c,v 1.3.2.1 1995/10/12 22:39:29 chuck Exp $ */
+
+/*
+ * Copyright (c) 1982, 1986, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)sys_machdep.c 8.2 (Berkeley) 1/13/94
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/ioctl.h>
+#include <sys/file.h>
+#include <sys/time.h>
+#include <sys/proc.h>
+#include <sys/uio.h>
+#include <sys/kernel.h>
+#include <sys/mtio.h>
+#include <sys/buf.h>
+#include <sys/trace.h>
+#include <sys/mount.h>
+
+#include <vm/vm.h>
+
+#include <sys/syscallargs.h>
+
+#ifdef TRACE
+int nvualarm;
+
+vtrace(p, v, retval)
+ struct proc *p;
+ void *v;
+ register_t *retval;
+{
+ register struct vtrace_args /* {
+ syscallarg(int) request;
+ syscallarg(int) value;
+ } */ *uap = v;
+ int vdoualarm();
+
+ switch (SCARG(uap, request)) {
+
+ case VTR_DISABLE: /* disable a trace point */
+ case VTR_ENABLE: /* enable a trace point */
+ if (SCARG(uap, value) < 0 || SCARG(uap, value) >= TR_NFLAGS)
+ return (EINVAL);
+ *retval = traceflags[SCARG(uap, value)];
+ traceflags[SCARG(uap, value)] = SCARG(uap, request);
+ break;
+
+ case VTR_VALUE: /* return a trace point setting */
+ if (SCARG(uap, value) < 0 || SCARG(uap, value) >= TR_NFLAGS)
+ return (EINVAL);
+ *retval = traceflags[SCARG(uap, value)];
+ break;
+
+ case VTR_UALARM: /* set a real-time ualarm, less than 1 min */
+ if (SCARG(uap, value) <= 0 || SCARG(uap, value) > 60 * hz ||
+ nvualarm > 5)
+ return (EINVAL);
+ nvualarm++;
+ timeout(vdoualarm, (void *)p->p_pid, SCARG(uap, value));
+ break;
+
+ case VTR_STAMP:
+ trace(TR_STAMP, SCARG(uap, value), p->p_pid);
+ break;
+ }
+ return (0);
+}
+
+vdoualarm(arg)
+ void *arg;
+{
+ register int pid = (int)arg;
+ register struct proc *p;
+
+ p = pfind(pid);
+ if (p)
+ psignal(p, 16);
+ nvualarm--;
+}
+#endif
+
+#include <machine/cpu.h>
+
+/* XXX should be in an include file somewhere */
+#define CC_PURGE 1
+#define CC_FLUSH 2
+#define CC_IPURGE 4
+#define CC_EXTPURGE 0x80000000
+/* XXX end should be */
+
+/*
+ * Note that what we do here for a 68040 is different than HP-UX.
+ *
+ * In 'pux they either act on a line (len == 16), a page (len == NBPG)
+ * or the whole cache (len == anything else).
+ *
+ * In BSD we attempt to be more optimal when acting on "odd" sizes.
+ * For lengths up to 1024 we do all affected lines, up to 2*NBPG we
+ * do pages, above that we do the entire cache.
+ */
+/*ARGSUSED1*/
+cachectl(req, addr, len)
+ int req;
+ caddr_t addr;
+ int len;
+{
+ int error = 0;
+
+#if defined(M68040)
+ if (mmutype == MMU_68040) {
+ register int inc = 0;
+ int pa = 0, doall = 0;
+ caddr_t end;
+#ifdef COMPAT_HPUX
+ extern struct emul emul_hpux;
+
+ if ((curproc->p_emul == &emul_hpux) &&
+ len != 16 && len != NBPG)
+ doall = 1;
+#endif
+
+ if (addr == 0 ||
+ (req & ~CC_EXTPURGE) != CC_PURGE && len > 2*NBPG)
+ doall = 1;
+
+ if (!doall) {
+ end = addr + len;
+ if (len <= 1024) {
+ addr = (caddr_t)((int)addr & ~0xF);
+ inc = 16;
+ } else {
+ addr = (caddr_t)((int)addr & ~PGOFSET);
+ inc = NBPG;
+ }
+ }
+ do {
+ /*
+ * Convert to physical address if needed.
+ * If translation fails, we perform operation on
+ * entire cache (XXX is this a rational thing to do?)
+ */
+ if (!doall &&
+ (pa == 0 || ((int)addr & PGOFSET) == 0)) {
+ pa = pmap_extract(&curproc->p_vmspace->vm_pmap,
+ (vm_offset_t)addr);
+ if (pa == 0)
+ doall = 1;
+ }
+ switch (req) {
+ case CC_EXTPURGE|CC_IPURGE:
+ case CC_IPURGE:
+ if (doall) {
+ DCFA();
+ ICPA();
+ } else if (inc == 16) {
+ DCFL(pa);
+ ICPL(pa);
+ } else if (inc == NBPG) {
+ DCFP(pa);
+ ICPP(pa);
+ }
+ break;
+
+ case CC_EXTPURGE|CC_PURGE:
+ case CC_PURGE:
+ if (doall)
+ DCFA(); /* note: flush not purge */
+ else if (inc == 16)
+ DCPL(pa);
+ else if (inc == NBPG)
+ DCPP(pa);
+ break;
+
+ case CC_EXTPURGE|CC_FLUSH:
+ case CC_FLUSH:
+ if (doall)
+ DCFA();
+ else if (inc == 16)
+ DCFL(pa);
+ else if (inc == NBPG)
+ DCFP(pa);
+ break;
+
+ default:
+ error = EINVAL;
+ break;
+ }
+ if (doall)
+ break;
+ pa += inc;
+ addr += inc;
+ } while (addr < end);
+ return(error);
+ }
+#endif
+ switch (req) {
+ case CC_EXTPURGE|CC_PURGE:
+ case CC_EXTPURGE|CC_FLUSH:
+#if defined(HP370)
+ if (ectype == EC_PHYS)
+ PCIA();
+ /* fall into... */
+#endif
+ case CC_PURGE:
+ case CC_FLUSH:
+ DCIU();
+ break;
+ case CC_EXTPURGE|CC_IPURGE:
+#if defined(HP370)
+ if (ectype == EC_PHYS)
+ PCIA();
+ else
+#endif
+ DCIU();
+ /* fall into... */
+ case CC_IPURGE:
+ ICIA();
+ break;
+ default:
+ error = EINVAL;
+ break;
+ }
+ return(error);
+}
+
+int
+sys_sysarch(p, v, retval)
+ struct proc *p;
+ void *v;
+ register_t *retval;
+{
+ struct sysarch_args /* {
+ syscallarg(int) op;
+ syscallarg(char *) parms;
+ } */ *uap = v;
+
+ return ENOSYS;
+}
diff --git a/sys/arch/mvme68k/mvme68k/trap.c b/sys/arch/mvme68k/mvme68k/trap.c
new file mode 100644
index 00000000000..3111b80c72c
--- /dev/null
+++ b/sys/arch/mvme68k/mvme68k/trap.c
@@ -0,0 +1,1087 @@
+/* $NetBSD: trap.c,v 1.2.2.1 1995/10/12 00:43:38 chuck Exp $ */
+
+/*
+ * Copyright (c) 1988 University of Utah.
+ * Copyright (c) 1982, 1986, 1990, 1993
+ * 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: trap.c 1.37 92/12/20$
+ *
+ * @(#)trap.c 8.5 (Berkeley) 1/4/94
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/proc.h>
+#include <sys/acct.h>
+#include <sys/kernel.h>
+#include <sys/signalvar.h>
+#include <sys/resourcevar.h>
+#include <sys/syscall.h>
+#include <sys/syslog.h>
+#include <sys/user.h>
+#ifdef KTRACE
+#include <sys/ktrace.h>
+#endif
+
+#include <machine/psl.h>
+#include <machine/trap.h>
+#include <machine/cpu.h>
+#include <machine/reg.h>
+
+#include <vm/vm.h>
+#include <vm/pmap.h>
+
+#ifdef COMPAT_HPUX
+#include <compat/hpux/hpux.h>
+#endif
+#ifdef COMPAT_SUNOS
+#include <compat/sunos/sunos_syscall.h>
+ extern struct emul emul_sunos;
+#endif
+
+char *trap_type[] = {
+ "Bus error",
+ "Address error",
+ "Illegal instruction",
+ "Zero divide",
+ "CHK instruction",
+ "TRAPV instruction",
+ "Privilege violation",
+ "Trace trap",
+ "MMU fault",
+ "SSIR trap",
+ "Format error",
+ "68881 exception",
+ "Coprocessor violation",
+ "Async system trap"
+};
+int trap_types = sizeof trap_type / sizeof trap_type[0];
+
+/*
+ * Size of various exception stack frames (minus the standard 8 bytes)
+ */
+short exframesize[] = {
+ FMT0SIZE, /* type 0 - normal (68020/030/040) */
+ FMT1SIZE, /* type 1 - throwaway (68020/030/040) */
+ FMT2SIZE, /* type 2 - normal 6-word (68020/030/040) */
+ FMT3SIZE, /* type 3 - FP post-instruction (68040) */
+ -1, -1, -1, /* type 4-6 - undefined */
+ FMT7SIZE, /* type 7 - access error (68040) */
+ 58, /* type 8 - bus fault (68010) */
+ FMT9SIZE, /* type 9 - coprocessor mid-instruction (68020/030) */
+ FMTASIZE, /* type A - short bus fault (68020/030) */
+ FMTBSIZE, /* type B - long bus fault (68020/030) */
+ -1, -1, -1, -1 /* type C-F - undefined */
+};
+
+#ifdef M68040
+#define KDFAULT(c) (mmutype == MMU_68040 ? \
+ ((c) & SSW4_TMMASK) == SSW4_TMKD : \
+ ((c) & (SSW_DF|FC_SUPERD)) == (SSW_DF|FC_SUPERD))
+#define WRFAULT(c) (mmutype == MMU_68040 ? \
+ ((c) & SSW4_RW) == 0 : \
+ ((c) & (SSW_DF|SSW_RW)) == SSW_DF)
+#else
+#define KDFAULT(c) (((c) & (SSW_DF|SSW_FCMASK)) == (SSW_DF|FC_SUPERD))
+#define WRFAULT(c) (((c) & (SSW_DF|SSW_RW)) == SSW_DF)
+#endif
+
+#ifdef DEBUG
+int mmudebug = 0;
+int mmupid = -1;
+#define MDB_FOLLOW 1
+#define MDB_WBFOLLOW 2
+#define MDB_WBFAILED 4
+#define MDB_ISPID(p) (p) == mmupid
+#endif
+
+#define NSIR 32
+void (*sir_routines[NSIR])();
+void *sir_args[NSIR];
+int next_sir;
+
+/*
+ * trap and syscall both need the following work done before returning
+ * to user mode.
+ */
+static inline void
+userret(p, fp, oticks, faultaddr, fromtrap)
+ register struct proc *p;
+ register struct frame *fp;
+ u_quad_t oticks;
+ u_int faultaddr;
+ int fromtrap;
+{
+ int sig, s;
+#ifdef M68040
+ int beenhere = 0;
+
+again:
+#endif
+ /* take pending signals */
+ while ((sig = CURSIG(p)) != 0)
+ postsig(sig);
+ p->p_priority = p->p_usrpri;
+ if (want_resched) {
+ /*
+ * Since we are curproc, clock will normally just change
+ * our priority without moving us from one queue to another
+ * (since the running process is not on a queue.)
+ * If that happened after we put ourselves on the run queue
+ * but before we mi_switch()'ed, we might not be on the queue
+ * indicated by our priority.
+ */
+ s = splstatclock();
+ setrunqueue(p);
+ p->p_stats->p_ru.ru_nivcsw++;
+ mi_switch();
+ splx(s);
+ while ((sig = CURSIG(p)) != 0)
+ postsig(sig);
+ }
+
+ /*
+ * If profiling, charge system time to the trapped pc.
+ */
+ if (p->p_flag & P_PROFIL) {
+ extern int psratio;
+
+ addupc_task(p, fp->f_pc,
+ (int)(p->p_sticks - oticks) * psratio);
+ }
+#ifdef M68040
+ /*
+ * Deal with user mode writebacks (from trap, or from sigreturn).
+ * If any writeback fails, go back and attempt signal delivery.
+ * unless we have already been here and attempted the writeback
+ * (e.g. bad address with user ignoring SIGSEGV). In that case
+ * we just return to the user without sucessfully completing
+ * the writebacks. Maybe we should just drop the sucker?
+ */
+ if (mmutype == MMU_68040 && fp->f_format == FMT7) {
+ if (beenhere) {
+#ifdef DEBUG
+ if (mmudebug & MDB_WBFAILED)
+ printf(fromtrap ?
+ "pid %d(%s): writeback aborted, pc=%x, fa=%x\n" :
+ "pid %d(%s): writeback aborted in sigreturn, pc=%x\n",
+ p->p_pid, p->p_comm, fp->f_pc, faultaddr);
+#endif
+ } else if (sig = writeback(fp, fromtrap)) {
+ beenhere = 1;
+ oticks = p->p_sticks;
+ trapsignal(p, sig, faultaddr);
+ goto again;
+ }
+ }
+#endif
+ curpriority = p->p_priority;
+}
+
+/*
+ * Trap is called from locore to handle most types of processor traps,
+ * including events such as simulated software interrupts/AST's.
+ * System calls are broken out for efficiency.
+ */
+/*ARGSUSED*/
+trap(type, code, v, frame)
+ int type;
+ unsigned code;
+ register unsigned v;
+ struct frame frame;
+{
+ extern char fubail[], subail[];
+#ifdef DDB
+ extern char trap0[], trap1[], trap2[], trap12[], trap15[], illinst[];
+#endif
+ register struct proc *p;
+ register int i;
+ u_int ucode;
+ u_quad_t sticks;
+#ifdef COMPAT_HPUX
+ extern struct emul emul_hpux;
+#endif
+ int bit;
+
+ cnt.v_trap++;
+ p = curproc;
+ ucode = 0;
+ if (USERMODE(frame.f_sr)) {
+ type |= T_USER;
+ sticks = p->p_sticks;
+ p->p_md.md_regs = frame.f_regs;
+ }
+ switch (type) {
+
+ default:
+dopanic:
+ printf("trap type %d, code = %x, v = %x\n", type, code, v);
+#ifdef DDB
+ if (kdb_trap(type, &frame))
+ return;
+#endif
+ regdump(&frame, 128);
+ type &= ~T_USER;
+ if ((unsigned)type < trap_types)
+ panic(trap_type[type]);
+ panic("trap");
+
+ case T_BUSERR: /* kernel bus error */
+ if (!p->p_addr->u_pcb.pcb_onfault)
+ goto dopanic;
+ /*
+ * If we have arranged to catch this fault in any of the
+ * copy to/from user space routines, set PC to return to
+ * indicated location and set flag informing buserror code
+ * that it may need to clean up stack frame.
+ */
+copyfault:
+ frame.f_stackadj = exframesize[frame.f_format];
+ frame.f_format = frame.f_vector = 0;
+ frame.f_pc = (int) p->p_addr->u_pcb.pcb_onfault;
+ return;
+
+ case T_BUSERR|T_USER: /* bus error */
+ case T_ADDRERR|T_USER: /* address error */
+ ucode = v;
+ i = SIGBUS;
+ break;
+
+#ifdef FPCOPROC
+ case T_COPERR: /* kernel coprocessor violation */
+#endif
+ case T_FMTERR|T_USER: /* do all RTE errors come in as T_USER? */
+ case T_FMTERR: /* ...just in case... */
+ /*
+ * The user has most likely trashed the RTE or FP state info
+ * in the stack frame of a signal handler.
+ */
+ printf("pid %d: kernel %s exception\n", p->p_pid,
+ type==T_COPERR ? "coprocessor" : "format");
+ type |= T_USER;
+ p->p_sigacts->ps_sigact[SIGILL] = SIG_DFL;
+ i = sigmask(SIGILL);
+ p->p_sigignore &= ~i;
+ p->p_sigcatch &= ~i;
+ p->p_sigmask &= ~i;
+ i = SIGILL;
+ ucode = frame.f_format; /* XXX was ILL_RESAD_FAULT */
+ break;
+
+#ifdef FPCOPROC
+ case T_COPERR|T_USER: /* user coprocessor violation */
+ /* What is a proper response here? */
+ ucode = 0;
+ i = SIGFPE;
+ break;
+
+ case T_FPERR|T_USER: /* 68881 exceptions */
+ /*
+ * We pass along the 68881 status register which locore stashed
+ * in code for us. Note that there is a possibility that the
+ * bit pattern of this register will conflict with one of the
+ * FPE_* codes defined in signal.h. Fortunately for us, the
+ * only such codes we use are all in the range 1-7 and the low
+ * 3 bits of the status register are defined as 0 so there is
+ * no clash.
+ */
+ ucode = code;
+ i = SIGFPE;
+ break;
+#endif
+
+#ifdef M68040
+ case T_FPEMULI|T_USER: /* unimplemented FP instuction */
+ case T_FPEMULD|T_USER: /* unimplemented FP data type */
+ /* XXX need to FSAVE */
+ printf("pid %d(%s): unimplemented FP %s at %x (EA %x)\n",
+ p->p_pid, p->p_comm,
+ frame.f_format == 2 ? "instruction" : "data type",
+ frame.f_pc, frame.f_fmt2.f_iaddr);
+ /* XXX need to FRESTORE */
+ i = SIGFPE;
+ break;
+#endif
+
+ case T_ILLINST|T_USER: /* illegal instruction fault */
+#ifdef COMPAT_HPUX
+ if (p->p_emul == &emul_hpux) {
+ ucode = HPUX_ILL_ILLINST_TRAP;
+ i = SIGILL;
+ break;
+ }
+ /* fall through */
+#endif
+ case T_PRIVINST|T_USER: /* privileged instruction fault */
+#ifdef COMPAT_HPUX
+ if (p->p_emul == &emul_hpux)
+ ucode = HPUX_ILL_PRIV_TRAP;
+ else
+#endif
+ ucode = frame.f_format; /* XXX was ILL_PRIVIN_FAULT */
+ i = SIGILL;
+ break;
+
+ case T_ZERODIV|T_USER: /* Divide by zero */
+#ifdef COMPAT_HPUX
+ if (p->p_emul == &emul_hpux)
+ ucode = HPUX_FPE_INTDIV_TRAP;
+ else
+#endif
+ ucode = frame.f_format; /* XXX was FPE_INTDIV_TRAP */
+ i = SIGFPE;
+ break;
+
+ case T_CHKINST|T_USER: /* CHK instruction trap */
+#ifdef COMPAT_HPUX
+ if (p->p_emul == &emul_hpux) {
+ /* handled differently under hp-ux */
+ i = SIGILL;
+ ucode = HPUX_ILL_CHK_TRAP;
+ break;
+ }
+#endif
+ ucode = frame.f_format; /* XXX was FPE_SUBRNG_TRAP */
+ i = SIGFPE;
+ break;
+
+ case T_TRAPVINST|T_USER: /* TRAPV instruction trap */
+#ifdef COMPAT_HPUX
+ if (p->p_emul == &emul_hpux) {
+ /* handled differently under hp-ux */
+ i = SIGILL;
+ ucode = HPUX_ILL_TRAPV_TRAP;
+ break;
+ }
+#endif
+ ucode = frame.f_format; /* XXX was FPE_INTOVF_TRAP */
+ i = SIGFPE;
+ break;
+
+ /*
+ * XXX: Trace traps are a nightmare.
+ *
+ * HP-UX uses trap #1 for breakpoints,
+ * HPBSD uses trap #2,
+ * SUN 3.x uses trap #15,
+ * KGDB uses trap #15 (for kernel breakpoints; handled elsewhere).
+ *
+ * HPBSD and HP-UX traps both get mapped by locore.s into T_TRACE.
+ * SUN 3.x traps get passed through as T_TRAP15 and are not really
+ * supported yet.
+ */
+ case T_TRACE: /* kernel trace trap */
+ case T_TRAP15: /* SUN trace trap */
+#ifdef DDB
+ if (type == T_TRAP15 ||
+ ((caddr_t)frame.f_pc != trap0 &&
+ (caddr_t)frame.f_pc != trap1 &&
+ (caddr_t)frame.f_pc != trap2 &&
+ (caddr_t)frame.f_pc != trap12 &&
+ (caddr_t)frame.f_pc != trap15 &&
+ (caddr_t)frame.f_pc != illinst)) {
+ if (kdb_trap(type, &frame))
+ return;
+ }
+#endif
+ frame.f_sr &= ~PSL_T;
+ i = SIGTRAP;
+ break;
+
+ case T_TRACE|T_USER: /* user trace trap */
+ case T_TRAP15|T_USER: /* SUN user trace trap */
+ frame.f_sr &= ~PSL_T;
+ i = SIGTRAP;
+ break;
+
+ case T_ASTFLT: /* system async trap, cannot happen */
+ goto dopanic;
+
+ case T_ASTFLT|T_USER: /* user async trap */
+ astpending = 0;
+ /*
+ * We check for software interrupts first. This is because
+ * they are at a higher level than ASTs, and on a VAX would
+ * interrupt the AST. We assume that if we are processing
+ * an AST that we must be at IPL0 so we don't bother to
+ * check. Note that we ensure that we are at least at SIR
+ * IPL while processing the SIR.
+ */
+ spl1();
+ /* fall into... */
+
+ case T_SSIR: /* software interrupt */
+ case T_SSIR|T_USER:
+ while (bit = ffs(ssir)) {
+ --bit;
+ ssir &= ~(1 << bit);
+ cnt.v_soft++;
+ if (sir_routines[bit])
+ sir_routines[bit](sir_args[bit]);
+ }
+
+ /*
+ * If this was not an AST trap, we are all done.
+ */
+ if (type != (T_ASTFLT|T_USER)) {
+ cnt.v_trap--;
+ return;
+ }
+ spl0();
+ if (p->p_flag & P_OWEUPC) {
+ p->p_flag &= ~P_OWEUPC;
+ ADDUPROF(p);
+ }
+ goto out;
+
+ case T_MMUFLT: /* kernel mode page fault */
+ /*
+ * If we were doing profiling ticks or other user mode
+ * stuff from interrupt code, Just Say No.
+ */
+ if (p->p_addr->u_pcb.pcb_onfault == fubail ||
+ p->p_addr->u_pcb.pcb_onfault == subail)
+ goto copyfault;
+ /* fall into ... */
+
+ case T_MMUFLT|T_USER: /* page fault */
+ {
+ register vm_offset_t va;
+ register struct vmspace *vm = p->p_vmspace;
+ register vm_map_t map;
+ int rv;
+ vm_prot_t ftype;
+ extern vm_map_t kernel_map;
+
+#ifdef DEBUG
+ if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid))
+ printf("trap: T_MMUFLT pid=%d, code=%x, v=%x, pc=%x, sr=%x\n",
+ p->p_pid, code, v, frame.f_pc, frame.f_sr);
+#endif
+ /*
+ * It is only a kernel address space fault iff:
+ * 1. (type & T_USER) == 0 and
+ * 2. pcb_onfault not set or
+ * 3. pcb_onfault set but supervisor space data fault
+ * The last can occur during an exec() copyin where the
+ * argument space is lazy-allocated.
+ */
+ if (type == T_MMUFLT &&
+ (!p->p_addr->u_pcb.pcb_onfault || KDFAULT(code)))
+ map = kernel_map;
+ else
+ map = &vm->vm_map;
+ if (WRFAULT(code))
+ ftype = VM_PROT_READ | VM_PROT_WRITE;
+ else
+ ftype = VM_PROT_READ;
+ va = trunc_page((vm_offset_t)v);
+#ifdef DEBUG
+ if (map == kernel_map && va == 0) {
+ printf("trap: bad kernel access at %x\n", v);
+ goto dopanic;
+ }
+#endif
+#ifdef COMPAT_HPUX
+ if (ISHPMMADDR(va)) {
+ vm_offset_t bva;
+
+ rv = pmap_mapmulti(map->pmap, va);
+ if (rv != KERN_SUCCESS) {
+ bva = HPMMBASEADDR(va);
+ rv = vm_fault(map, bva, ftype, FALSE);
+ if (rv == KERN_SUCCESS)
+ (void) pmap_mapmulti(map->pmap, va);
+ }
+ } else
+#endif
+ rv = vm_fault(map, va, ftype, FALSE);
+#ifdef DEBUG
+ if (rv && MDB_ISPID(p->p_pid))
+ printf("vm_fault(%x, %x, %x, 0) -> %x\n",
+ map, va, ftype, rv);
+#endif
+ /*
+ * If this was a stack access we keep track of the maximum
+ * accessed stack size. Also, if vm_fault gets a protection
+ * failure it is due to accessing the stack region outside
+ * the current limit and we need to reflect that as an access
+ * error.
+ */
+ if ((caddr_t)va >= vm->vm_maxsaddr && map != kernel_map) {
+ if (rv == KERN_SUCCESS) {
+ unsigned nss;
+
+ nss = clrnd(btoc(USRSTACK-(unsigned)va));
+ if (nss > vm->vm_ssize)
+ vm->vm_ssize = nss;
+ } else if (rv == KERN_PROTECTION_FAILURE)
+ rv = KERN_INVALID_ADDRESS;
+ }
+ if (rv == KERN_SUCCESS) {
+ if (type == T_MMUFLT) {
+#if defined(M68040)
+ if (mmutype == MMU_68040)
+ (void) writeback(&frame, 1);
+#endif
+ return;
+ }
+ goto out;
+ }
+ if (type == T_MMUFLT) {
+ if (p->p_addr->u_pcb.pcb_onfault)
+ goto copyfault;
+ printf("vm_fault(%x, %x, %x, 0) -> %x\n",
+ map, va, ftype, rv);
+ printf(" type %x, code [mmu,,ssw]: %x\n",
+ type, code);
+ goto dopanic;
+ }
+ ucode = v;
+ i = (rv == KERN_PROTECTION_FAILURE) ? SIGBUS : SIGSEGV;
+ break;
+ }
+ }
+ trapsignal(p, i, ucode);
+ if ((type & T_USER) == 0)
+ return;
+out:
+ userret(p, &frame, sticks, v, 1);
+}
+
+#ifdef M68040
+#ifdef DEBUG
+struct writebackstats {
+ int calls;
+ int cpushes;
+ int move16s;
+ int wb1s, wb2s, wb3s;
+ int wbsize[4];
+} wbstats;
+
+char *f7sz[] = { "longword", "byte", "word", "line" };
+char *f7tt[] = { "normal", "MOVE16", "AFC", "ACK" };
+char *f7tm[] = { "d-push", "u-data", "u-code", "M-data",
+ "M-code", "k-data", "k-code", "RES" };
+char wberrstr[] =
+ "WARNING: pid %d(%s) writeback [%s] failed, pc=%x fa=%x wba=%x wbd=%x\n";
+#endif
+
+writeback(fp, docachepush)
+ struct frame *fp;
+ int docachepush;
+{
+ register struct fmt7 *f = &fp->f_fmt7;
+ register struct proc *p = curproc;
+ int err = 0;
+ u_int fa;
+ caddr_t oonfault = p->p_addr->u_pcb.pcb_onfault;
+
+#ifdef DEBUG
+ if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid)) {
+ printf(" pid=%d, fa=%x,", p->p_pid, f->f_fa);
+ dumpssw(f->f_ssw);
+ }
+ wbstats.calls++;
+#endif
+ /*
+ * Deal with special cases first.
+ */
+ if ((f->f_ssw & SSW4_TMMASK) == SSW4_TMDCP) {
+ /*
+ * Dcache push fault.
+ * Line-align the address and write out the push data to
+ * the indicated physical address.
+ */
+#ifdef DEBUG
+ if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid)) {
+ printf(" pushing %s to PA %x, data %x",
+ f7sz[(f->f_ssw & SSW4_SZMASK) >> 5],
+ f->f_fa, f->f_pd0);
+ if ((f->f_ssw & SSW4_SZMASK) == SSW4_SZLN)
+ printf("/%x/%x/%x",
+ f->f_pd1, f->f_pd2, f->f_pd3);
+ printf("\n");
+ }
+ if (f->f_wb1s & SSW4_WBSV)
+ panic("writeback: cache push with WB1S valid");
+ wbstats.cpushes++;
+#endif
+ /*
+ * XXX there are security problems if we attempt to do a
+ * cache push after a signal handler has been called.
+ */
+ if (docachepush) {
+ pmap_enter(pmap_kernel(), (vm_offset_t)vmmap,
+ trunc_page(f->f_fa), VM_PROT_WRITE, TRUE);
+ fa = (u_int)&vmmap[(f->f_fa & PGOFSET) & ~0xF];
+ bcopy((caddr_t)&f->f_pd0, (caddr_t)fa, 16);
+ DCFL(pmap_extract(pmap_kernel(), (vm_offset_t)fa));
+ pmap_remove(pmap_kernel(), (vm_offset_t)vmmap,
+ (vm_offset_t)&vmmap[NBPG]);
+ } else
+ printf("WARNING: pid %d(%s) uid %d: CPUSH not done\n",
+ p->p_pid, p->p_comm, p->p_ucred->cr_uid);
+ } else if ((f->f_ssw & (SSW4_RW|SSW4_TTMASK)) == SSW4_TTM16) {
+ /*
+ * MOVE16 fault.
+ * Line-align the address and write out the push data to
+ * the indicated virtual address.
+ */
+#ifdef DEBUG
+ if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid))
+ printf(" MOVE16 to VA %x(%x), data %x/%x/%x/%x\n",
+ f->f_fa, f->f_fa & ~0xF, f->f_pd0, f->f_pd1,
+ f->f_pd2, f->f_pd3);
+ if (f->f_wb1s & SSW4_WBSV)
+ panic("writeback: MOVE16 with WB1S valid");
+ wbstats.move16s++;
+#endif
+ if (KDFAULT(f->f_wb1s))
+ bcopy((caddr_t)&f->f_pd0, (caddr_t)(f->f_fa & ~0xF), 16);
+ else
+ err = suline((caddr_t)(f->f_fa & ~0xF), (caddr_t)&f->f_pd0);
+ if (err) {
+ fa = f->f_fa & ~0xF;
+#ifdef DEBUG
+ if (mmudebug & MDB_WBFAILED)
+ printf(wberrstr, p->p_pid, p->p_comm,
+ "MOVE16", fp->f_pc, f->f_fa,
+ f->f_fa & ~0xF, f->f_pd0);
+#endif
+ }
+ } else if (f->f_wb1s & SSW4_WBSV) {
+ /*
+ * Writeback #1.
+ * Position the "memory-aligned" data and write it out.
+ */
+ register u_int wb1d = f->f_wb1d;
+ register int off;
+
+#ifdef DEBUG
+ if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid))
+ dumpwb(1, f->f_wb1s, f->f_wb1a, f->f_wb1d);
+ wbstats.wb1s++;
+ wbstats.wbsize[(f->f_wb2s&SSW4_SZMASK)>>5]++;
+#endif
+ off = (f->f_wb1a & 3) * 8;
+ switch (f->f_wb1s & SSW4_SZMASK) {
+ case SSW4_SZLW:
+ if (off)
+ wb1d = (wb1d >> (32 - off)) | (wb1d << off);
+ if (KDFAULT(f->f_wb1s))
+ *(long *)f->f_wb1a = wb1d;
+ else
+ err = suword((caddr_t)f->f_wb1a, wb1d);
+ break;
+ case SSW4_SZB:
+ off = 24 - off;
+ if (off)
+ wb1d >>= off;
+ if (KDFAULT(f->f_wb1s))
+ *(char *)f->f_wb1a = wb1d;
+ else
+ err = subyte((caddr_t)f->f_wb1a, wb1d);
+ break;
+ case SSW4_SZW:
+ off = (off + 16) % 32;
+ if (off)
+ wb1d = (wb1d >> (32 - off)) | (wb1d << off);
+ if (KDFAULT(f->f_wb1s))
+ *(short *)f->f_wb1a = wb1d;
+ else
+ err = susword((caddr_t)f->f_wb1a, wb1d);
+ break;
+ }
+ if (err) {
+ fa = f->f_wb1a;
+#ifdef DEBUG
+ if (mmudebug & MDB_WBFAILED)
+ printf(wberrstr, p->p_pid, p->p_comm,
+ "#1", fp->f_pc, f->f_fa,
+ f->f_wb1a, f->f_wb1d);
+#endif
+ }
+ }
+ /*
+ * Deal with the "normal" writebacks.
+ *
+ * XXX writeback2 is known to reflect a LINE size writeback after
+ * a MOVE16 was already dealt with above. Ignore it.
+ */
+ if (err == 0 && (f->f_wb2s & SSW4_WBSV) &&
+ (f->f_wb2s & SSW4_SZMASK) != SSW4_SZLN) {
+#ifdef DEBUG
+ if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid))
+ dumpwb(2, f->f_wb2s, f->f_wb2a, f->f_wb2d);
+ wbstats.wb2s++;
+ wbstats.wbsize[(f->f_wb2s&SSW4_SZMASK)>>5]++;
+#endif
+ switch (f->f_wb2s & SSW4_SZMASK) {
+ case SSW4_SZLW:
+ if (KDFAULT(f->f_wb2s))
+ *(long *)f->f_wb2a = f->f_wb2d;
+ else
+ err = suword((caddr_t)f->f_wb2a, f->f_wb2d);
+ break;
+ case SSW4_SZB:
+ if (KDFAULT(f->f_wb2s))
+ *(char *)f->f_wb2a = f->f_wb2d;
+ else
+ err = subyte((caddr_t)f->f_wb2a, f->f_wb2d);
+ break;
+ case SSW4_SZW:
+ if (KDFAULT(f->f_wb2s))
+ *(short *)f->f_wb2a = f->f_wb2d;
+ else
+ err = susword((caddr_t)f->f_wb2a, f->f_wb2d);
+ break;
+ }
+ if (err) {
+ fa = f->f_wb2a;
+#ifdef DEBUG
+ if (mmudebug & MDB_WBFAILED) {
+ printf(wberrstr, p->p_pid, p->p_comm,
+ "#2", fp->f_pc, f->f_fa,
+ f->f_wb2a, f->f_wb2d);
+ dumpssw(f->f_ssw);
+ dumpwb(2, f->f_wb2s, f->f_wb2a, f->f_wb2d);
+ }
+#endif
+ }
+ }
+ if (err == 0 && (f->f_wb3s & SSW4_WBSV)) {
+#ifdef DEBUG
+ if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid))
+ dumpwb(3, f->f_wb3s, f->f_wb3a, f->f_wb3d);
+ wbstats.wb3s++;
+ wbstats.wbsize[(f->f_wb3s&SSW4_SZMASK)>>5]++;
+#endif
+ switch (f->f_wb3s & SSW4_SZMASK) {
+ case SSW4_SZLW:
+ if (KDFAULT(f->f_wb3s))
+ *(long *)f->f_wb3a = f->f_wb3d;
+ else
+ err = suword((caddr_t)f->f_wb3a, f->f_wb3d);
+ break;
+ case SSW4_SZB:
+ if (KDFAULT(f->f_wb3s))
+ *(char *)f->f_wb3a = f->f_wb3d;
+ else
+ err = subyte((caddr_t)f->f_wb3a, f->f_wb3d);
+ break;
+ case SSW4_SZW:
+ if (KDFAULT(f->f_wb3s))
+ *(short *)f->f_wb3a = f->f_wb3d;
+ else
+ err = susword((caddr_t)f->f_wb3a, f->f_wb3d);
+ break;
+#ifdef DEBUG
+ case SSW4_SZLN:
+ panic("writeback: wb3s indicates LINE write");
+#endif
+ }
+ if (err) {
+ fa = f->f_wb3a;
+#ifdef DEBUG
+ if (mmudebug & MDB_WBFAILED)
+ printf(wberrstr, p->p_pid, p->p_comm,
+ "#3", fp->f_pc, f->f_fa,
+ f->f_wb3a, f->f_wb3d);
+#endif
+ }
+ }
+ p->p_addr->u_pcb.pcb_onfault = oonfault;
+ /*
+ * Determine the cause of the failure if any translating to
+ * a signal. If the corresponding VA is valid and RO it is
+ * a protection fault (SIGBUS) otherwise consider it an
+ * illegal reference (SIGSEGV).
+ */
+ if (err) {
+ if (vm_map_check_protection(&p->p_vmspace->vm_map,
+ trunc_page(fa), round_page(fa),
+ VM_PROT_READ) &&
+ !vm_map_check_protection(&p->p_vmspace->vm_map,
+ trunc_page(fa), round_page(fa),
+ VM_PROT_WRITE))
+ err = SIGBUS;
+ else
+ err = SIGSEGV;
+ }
+ return(err);
+}
+
+#ifdef DEBUG
+dumpssw(ssw)
+ register u_short ssw;
+{
+ printf(" SSW: %x: ", ssw);
+ if (ssw & SSW4_CP)
+ printf("CP,");
+ if (ssw & SSW4_CU)
+ printf("CU,");
+ if (ssw & SSW4_CT)
+ printf("CT,");
+ if (ssw & SSW4_CM)
+ printf("CM,");
+ if (ssw & SSW4_MA)
+ printf("MA,");
+ if (ssw & SSW4_ATC)
+ printf("ATC,");
+ if (ssw & SSW4_LK)
+ printf("LK,");
+ if (ssw & SSW4_RW)
+ printf("RW,");
+ printf(" SZ=%s, TT=%s, TM=%s\n",
+ f7sz[(ssw & SSW4_SZMASK) >> 5],
+ f7tt[(ssw & SSW4_TTMASK) >> 3],
+ f7tm[ssw & SSW4_TMMASK]);
+}
+
+dumpwb(num, s, a, d)
+ int num;
+ u_short s;
+ u_int a, d;
+{
+ register struct proc *p = curproc;
+ vm_offset_t pa;
+
+ printf(" writeback #%d: VA %x, data %x, SZ=%s, TT=%s, TM=%s\n",
+ num, a, d, f7sz[(s & SSW4_SZMASK) >> 5],
+ f7tt[(s & SSW4_TTMASK) >> 3], f7tm[s & SSW4_TMMASK]);
+ printf(" PA ");
+ pa = pmap_extract(&p->p_vmspace->vm_pmap, (vm_offset_t)a);
+ if (pa == 0)
+ printf("<invalid address>");
+ else
+ printf("%x, current value %x", pa, fuword((caddr_t)a));
+ printf("\n");
+}
+#endif
+#endif
+
+/*
+ * Process a system call.
+ */
+syscall(code, frame)
+ register_t code;
+ struct frame frame;
+{
+ register caddr_t params;
+ register struct sysent *callp;
+ register struct proc *p;
+ int error, opc, nsys;
+ size_t argsize;
+ register_t args[8], rval[2];
+ u_quad_t sticks;
+
+ cnt.v_syscall++;
+ if (!USERMODE(frame.f_sr))
+ panic("syscall");
+ p = curproc;
+ sticks = p->p_sticks;
+ p->p_md.md_regs = frame.f_regs;
+ opc = frame.f_pc;
+
+ nsys = p->p_emul->e_nsysent;
+ callp = p->p_emul->e_sysent;
+
+#ifdef COMPAT_SUNOS
+ if (p->p_emul == &emul_sunos) {
+ /*
+ * SunOS passes the syscall-number on the stack, whereas
+ * BSD passes it in D0. So, we have to get the real "code"
+ * from the stack, and clean up the stack, as SunOS glue
+ * code assumes the kernel pops the syscall argument the
+ * glue pushed on the stack. Sigh...
+ */
+ code = fuword((caddr_t)frame.f_regs[SP]);
+
+ /*
+ * XXX
+ * Don't do this for sunos_sigreturn, as there's no stored pc
+ * on the stack to skip, the argument follows the syscall
+ * number without a gap.
+ */
+ if (code != SUNOS_SYS_sigreturn) {
+ frame.f_regs[SP] += sizeof (int);
+ /*
+ * remember that we adjusted the SP,
+ * might have to undo this if the system call
+ * returns ERESTART.
+ */
+ p->p_md.md_flags |= MDP_STACKADJ;
+ } else
+ p->p_md.md_flags &= ~MDP_STACKADJ;
+ }
+#endif
+
+ params = (caddr_t)frame.f_regs[SP] + sizeof(int);
+
+ switch (code) {
+ case SYS_syscall:
+ /*
+ * Code is first argument, followed by actual args.
+ */
+ code = fuword(params);
+ params += sizeof(int);
+ /*
+ * XXX sigreturn requires special stack manipulation
+ * that is only done if entered via the sigreturn
+ * trap. Cannot allow it here so make sure we fail.
+ */
+ if (code == SYS_sigreturn)
+ code = nsys;
+ break;
+ case SYS___syscall:
+ /*
+ * Like syscall, but code is a quad, so as to maintain
+ * quad alignment for the rest of the arguments.
+ */
+ if (callp != sysent)
+ break;
+ code = fuword(params + _QUAD_LOWWORD * sizeof(int));
+ params += sizeof(quad_t);
+ break;
+ default:
+ break;
+ }
+ if (code < 0 || code >= nsys)
+ callp += p->p_emul->e_nosys; /* illegal */
+ else
+ callp += code;
+ argsize = callp->sy_argsize;
+ if (argsize)
+ error = copyin(params, (caddr_t)args, argsize);
+ else
+ error = 0;
+#ifdef SYSCALL_DEBUG
+ scdebug_call(p, code, args);
+#endif
+#ifdef KTRACE
+ if (KTRPOINT(p, KTR_SYSCALL))
+ ktrsyscall(p->p_tracep, code, argsize, args);
+#endif
+ if (error)
+ goto bad;
+ rval[0] = 0;
+ rval[1] = frame.f_regs[D1];
+ error = (*callp->sy_call)(p, args, rval);
+ switch (error) {
+ case 0:
+ frame.f_regs[D0] = rval[0];
+ frame.f_regs[D1] = rval[1];
+ frame.f_sr &= ~PSL_C; /* carry bit */
+ break;
+ case ERESTART:
+ /*
+ * We always enter through a `trap' instruction, which is 2
+ * bytes, so adjust the pc by that amount.
+ */
+ frame.f_pc = opc - 2;
+ break;
+ case EJUSTRETURN:
+ /* nothing to do */
+ break;
+ default:
+ bad:
+ if (p->p_emul->e_errno)
+ error = p->p_emul->e_errno[error];
+ frame.f_regs[D0] = error;
+ frame.f_sr |= PSL_C; /* carry bit */
+ break;
+ }
+
+#ifdef SYSCALL_DEBUG
+ scdebug_ret(p, code, error, rval);
+#endif
+#ifdef COMPAT_SUNOS
+ /* need new p-value for this */
+ if (error == ERESTART && (p->p_md.md_flags & MDP_STACKADJ))
+ frame.f_regs[SP] -= sizeof (int);
+#endif
+ userret(p, &frame, sticks, (u_int)0, 0);
+#ifdef KTRACE
+ if (KTRPOINT(p, KTR_SYSRET))
+ ktrsysret(p->p_tracep, code, error, rval[0]);
+#endif
+}
+
+void
+child_return(p, frame)
+ struct proc *p;
+ struct frame frame;
+{
+
+ frame.f_regs[D0] = 0;
+ frame.f_sr &= ~PSL_C;
+ frame.f_format = FMT0;
+
+ userret(p, &frame, p->p_sticks, (u_int)0, 0);
+#ifdef KTRACE
+ if (KTRPOINT(p, KTR_SYSRET))
+ ktrsysret(p->p_tracep, SYS_fork, 0, 0);
+#endif
+}
+
+/*
+ * Allocation routines for software interrupts.
+ */
+u_long
+allocate_sir(proc, arg)
+ void (*proc)();
+ void *arg;
+{
+ int bit;
+
+ if( next_sir >= NSIR )
+ panic("allocate_sir: none left");
+ bit = next_sir++;
+ sir_routines[bit] = proc;
+ sir_args[bit] = arg;
+ return (1 << bit);
+}
+
+void
+init_sir()
+{
+ extern void netintr();
+
+ sir_routines[0] = netintr;
+ sir_routines[1] = softclock;
+ next_sir = 2;
+}
diff --git a/sys/arch/mvme68k/mvme68k/vectors.s b/sys/arch/mvme68k/mvme68k/vectors.s
new file mode 100644
index 00000000000..4dc7abf7ffa
--- /dev/null
+++ b/sys/arch/mvme68k/mvme68k/vectors.s
@@ -0,0 +1,160 @@
+| $NetBSD: vectors.s,v 1.1.1.1 1995/07/25 23:12:01 chuck Exp $
+
+| Copyright (c) 1988 University of Utah
+| Copyright (c) 1990, 1993
+| The Regents of the University of California. All rights reserved.
+|
+| Redistribution and use in source and binary forms, with or without
+| modification, are permitted provided that the following conditions
+| are met:
+| 1. Redistributions of source code must retain the above copyright
+| notice, this list of conditions and the following disclaimer.
+| 2. Redistributions in binary form must reproduce the above copyright
+| notice, this list of conditions and the following disclaimer in the
+| documentation and/or other materials provided with the distribution.
+| 3. All advertising materials mentioning features or use of this software
+| must display the following acknowledgement:
+| This product includes software developed by the University of
+| California, Berkeley and its contributors.
+| 4. Neither the name of the University nor the names of its contributors
+| may be used to endorse or promote products derived from this software
+| without specific prior written permission.
+|
+| THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+| ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+| IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+| ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+| FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+| DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+| OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+| HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+| LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+| OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+| SUCH DAMAGE.
+|
+| @(#)vectors.s 8.2 (Berkeley) 1/21/94
+|
+
+ .text
+ .globl _buserr,_addrerr
+ .globl _illinst,_zerodiv,_chkinst,_trapvinst,_privinst,_trace
+ .globl _badtrap
+ .globl _spurintr,_lev1intr,_lev2intr,_lev3intr
+ .globl _lev4intr,_lev5intr,_lev6intr,_lev7intr
+ .globl _pcctrap
+ .globl _trap0,_trap1,_trap2,_trap15
+ .globl _fpfline, _fpunsupp
+ .globl _trap12
+
+Lvectab:
+ .long 0x4ef88400 /* 0: jmp 0x8400:w (unused reset SSP) */
+ .long 0 /* 1: NOT USED (reset PC) */
+ .long _buserr /* 2: bus error */
+ .long _addrerr /* 3: address error */
+ .long _illinst /* 4: illegal instruction */
+ .long _zerodiv /* 5: zero divide */
+ .long _chkinst /* 6: CHK instruction */
+ .long _trapvinst /* 7: TRAPV instruction */
+ .long _privinst /* 8: privilege violation */
+ .long _trace /* 9: trace */
+ .long _illinst /* 10: line 1010 emulator */
+ .long _fpfline /* 11: line 1111 emulator */
+ .long _badtrap /* 12: unassigned, reserved */
+ .long _coperr /* 13: coprocessor protocol violation */
+ .long _fmterr /* 14: format error */
+ .long _badtrap /* 15: uninitialized interrupt vector */
+ .long _badtrap /* 16: unassigned, reserved */
+ .long _badtrap /* 17: unassigned, reserved */
+ .long _badtrap /* 18: unassigned, reserved */
+ .long _badtrap /* 19: unassigned, reserved */
+ .long _badtrap /* 20: unassigned, reserved */
+ .long _badtrap /* 21: unassigned, reserved */
+ .long _badtrap /* 22: unassigned, reserved */
+ .long _badtrap /* 23: unassigned, reserved */
+ .long _spurintr /* 24: spurious interrupt */
+ .long _lev1intr /* 25: level 1 interrupt autovector */
+ .long _lev2intr /* 26: level 2 interrupt autovector */
+ .long _lev3intr /* 27: level 3 interrupt autovector */
+ .long _lev4intr /* 28: level 4 interrupt autovector */
+ .long _lev5intr /* 29: level 5 interrupt autovector */
+ .long _lev6intr /* 30: level 6 interrupt autovector */
+ .long _lev7intr /* 31: level 7 interrupt autovector */
+ .long _trap0 /* 32: syscalls */
+ .long _trap1 /* 33: sigreturn syscall or breakpoint */
+ .long _trap2 /* 34: breakpoint or sigreturn syscall */
+ .long _illinst /* 35: TRAP instruction vector */
+ .long _illinst /* 36: TRAP instruction vector */
+ .long _illinst /* 37: TRAP instruction vector */
+ .long _illinst /* 38: TRAP instruction vector */
+ .long _illinst /* 39: TRAP instruction vector */
+ .long _illinst /* 40: TRAP instruction vector */
+ .long _illinst /* 41: TRAP instruction vector */
+ .long _illinst /* 42: TRAP instruction vector */
+ .long _illinst /* 43: TRAP instruction vector */
+ .long _trap12 /* 44: TRAP instruction vector */
+ .long _illinst /* 45: TRAP instruction vector */
+ .long _illinst /* 46: TRAP instruction vector */
+ .long _trap15 /* 47: TRAP instruction vector */
+#ifdef FPSP
+ .globl bsun, inex, dz, unfl, operr, ovfl, snan
+ .long bsun /* 48: FPCP branch/set on unordered cond */
+ .long inex /* 49: FPCP inexact result */
+ .long dz /* 50: FPCP divide by zero */
+ .long unfl /* 51: FPCP underflow */
+ .long operr /* 52: FPCP operand error */
+ .long ovfl /* 53: FPCP overflow */
+ .long snan /* 54: FPCP signalling NAN */
+#else
+ .globl _fpfault
+ .long _fpfault /* 48: FPCP branch/set on unordered cond */
+ .long _fpfault /* 49: FPCP inexact result */
+ .long _fpfault /* 50: FPCP divide by zero */
+ .long _fpfault /* 51: FPCP underflow */
+ .long _fpfault /* 52: FPCP operand error */
+ .long _fpfault /* 53: FPCP overflow */
+ .long _fpfault /* 54: FPCP signalling NAN */
+#endif
+
+ .long _fpunsupp /* 55: FPCP unimplemented data type */
+ .long _badtrap /* 56: unassigned, reserved */
+ .long _badtrap /* 57: unassigned, reserved */
+ .long _badtrap /* 58: unassigned, reserved */
+ .long _badtrap /* 59: unassigned, reserved */
+ .long _badtrap /* 60: unassigned, reserved */
+ .long _badtrap /* 61: unassigned, reserved */
+ .long _badtrap /* 62: unassigned, reserved */
+ .long _badtrap /* 63: unassigned, reserved */
+
+ /* PCC traps (0x40 to start, configured from pccreg.h) */
+ .long _pcctrap /* 64: AC fail */
+ .long _pcctrap /* 65: BERR */
+ .long _pcctrap /* 66: abort */
+ .long _pcctrap /* 67: serial port */
+ .long _pcctrap /* 68: lance */
+ .long _pcctrap /* 69: SCSI port */
+ .long _pcctrap /* 70: SCSI dma */
+ .long _pcctrap /* 71: printer port */
+ .long _pcctrap /* 72: timer #1 */
+ .long _pcctrap /* 73: timer #2 */
+ .long _pcctrap /* 74: software intr #1 */
+ .long _pcctrap /* 75: software intr #2 */
+
+ .long _badtrap /* 76: unassigned, reserved */
+ .long _badtrap /* 77: unassigned, reserved */
+ .long _badtrap /* 78: unassigned, reserved */
+ .long _badtrap /* 79: unassigned, reserved */
+#define BADTRAP16 .long _badtrap,_badtrap,_badtrap,_badtrap,\
+ _badtrap,_badtrap,_badtrap,_badtrap,\
+ _badtrap,_badtrap,_badtrap,_badtrap,\
+ _badtrap,_badtrap,_badtrap,_badtrap
+ BADTRAP16 /* 64-255: user interrupt vectors */
+ BADTRAP16 /* 64-255: user interrupt vectors */
+ BADTRAP16 /* 64-255: user interrupt vectors */
+ BADTRAP16 /* 64-255: user interrupt vectors */
+ BADTRAP16 /* 64-255: user interrupt vectors */
+ BADTRAP16 /* 64-255: user interrupt vectors */
+ BADTRAP16 /* 64-255: user interrupt vectors */
+ BADTRAP16 /* 64-255: user interrupt vectors */
+ BADTRAP16 /* 64-255: user interrupt vectors */
+ BADTRAP16 /* 64-255: user interrupt vectors */
+ BADTRAP16 /* 64-255: user interrupt vectors */
diff --git a/sys/arch/mvme68k/mvme68k/vm_machdep.c b/sys/arch/mvme68k/mvme68k/vm_machdep.c
new file mode 100644
index 00000000000..fd9b2229c04
--- /dev/null
+++ b/sys/arch/mvme68k/mvme68k/vm_machdep.c
@@ -0,0 +1,446 @@
+/* $NetBSD: vm_machdep.c,v 1.2 1995/08/10 19:46:45 chuck Exp $ */
+
+/*
+ * Copyright (c) 1988 University of Utah.
+ * Copyright (c) 1982, 1986, 1990, 1993
+ * 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: vm_machdep.c 1.21 91/04/06$
+ *
+ * @(#)vm_machdep.c 8.6 (Berkeley) 1/12/94
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/proc.h>
+#include <sys/malloc.h>
+#include <sys/buf.h>
+#include <sys/vnode.h>
+#include <sys/user.h>
+#include <sys/core.h>
+#include <sys/exec.h>
+
+#include <vm/vm.h>
+#include <vm/vm_kern.h>
+
+#include <machine/cpu.h>
+#include <machine/pte.h>
+#include <machine/reg.h>
+
+/*
+ * Finish a fork operation, with process p2 nearly set up.
+ * Copy and update the kernel stack and pcb, making the child
+ * ready to run, and marking it so that it can return differently
+ * than the parent. Returns 1 in the child process, 0 in the parent.
+ * We currently double-map the user area so that the stack is at the same
+ * address in each process; in the future we will probably relocate
+ * the frame pointers on the stack after copying.
+ */
+int
+cpu_fork(p1, p2)
+ register struct proc *p1, *p2;
+{
+ register struct pcb *pcb = &p2->p_addr->u_pcb;
+ register struct trapframe *tf;
+ register struct switchframe *sf;
+ extern struct pcb *curpcb;
+ extern void proc_trampoline(), child_return();
+
+ p2->p_md.md_flags = p1->p_md.md_flags & ~MDP_HPUXTRACE;
+
+ /* Sync curpcb (which is presumably p1's PCB) and copy it to p2. */
+ savectx(curpcb);
+ *pcb = p1->p_addr->u_pcb;
+
+ PMAP_ACTIVATE(&p2->p_vmspace->vm_pmap, pcb, 0);
+
+ /*
+ * Copy the trap frame, and arrange for the child to return directly
+ * through return_to_user().
+ */
+ tf = (struct trapframe *)((u_int)p2->p_addr + USPACE) - 1;
+ p2->p_md.md_regs = (int *)tf;
+ *tf = *(struct trapframe *)p1->p_md.md_regs;
+ sf = (struct switchframe *)tf - 1;
+ sf->sf_pc = (u_int)proc_trampoline;
+ pcb->pcb_regs[6] = (int)child_return; /* A2 */
+ pcb->pcb_regs[7] = (int)p2; /* A3 */
+ pcb->pcb_regs[11] = (int)sf; /* SSP */
+
+ return (0);
+}
+
+void
+cpu_set_kpc(p, pc)
+ struct proc *p;
+ u_long pc;
+{
+
+ p->p_addr->u_pcb.pcb_regs[6] = pc; /* A2 */
+}
+
+/*
+ * cpu_exit is called as the last action during exit.
+ * We release the address space and machine-dependent resources,
+ * including the memory for the user structure and kernel stack.
+ * Once finished, we call switch_exit, which switches to a temporary
+ * pcb and stack and never returns. We block memory allocation
+ * until switch_exit has made things safe again.
+ */
+void
+cpu_exit(p)
+ struct proc *p;
+{
+
+ vmspace_free(p->p_vmspace);
+
+ (void) splhigh();
+ cnt.v_swtch++;
+ switch_exit(p);
+ /* NOTREACHED */
+}
+
+/*
+ * Dump the machine specific header information at the start of a core dump.
+ */
+struct md_core {
+ struct reg intreg;
+ struct fpreg freg;
+};
+int
+cpu_coredump(p, vp, cred, chdr)
+ struct proc *p;
+ struct vnode *vp;
+ struct ucred *cred;
+ struct core *chdr;
+{
+ struct md_core md_core;
+ struct coreseg cseg;
+ int error;
+
+#ifdef COMPAT_HPUX
+ extern struct emul emul_hpux;
+
+ /*
+ * If we loaded from an HP-UX format binary file we dump enough
+ * of an HP-UX style user struct so that the HP-UX debuggers can
+ * grok it.
+ */
+ if (p->p_emul == &emul_hpux)
+ return (hpux_dumpu(vp, cred));
+#endif
+
+ CORE_SETMAGIC(*chdr, COREMAGIC, MID_M68K, 0);
+ chdr->c_hdrsize = ALIGN(sizeof(*chdr));
+ chdr->c_seghdrsize = ALIGN(sizeof(cseg));
+ chdr->c_cpusize = sizeof(md_core);
+
+ /* Save integer registers. */
+ error = process_read_regs(p, &md_core.intreg);
+ if (error)
+ return error;
+
+ /* Save floating point registers. */
+ error = process_read_fpregs(p, &md_core.freg);
+ if (error)
+ return error;
+
+ CORE_SETMAGIC(cseg, CORESEGMAGIC, MID_M68K, CORE_CPU);
+ cseg.c_addr = 0;
+ cseg.c_size = chdr->c_cpusize;
+
+ error = vn_rdwr(UIO_WRITE, vp, (caddr_t)&cseg, chdr->c_seghdrsize,
+ (off_t)chdr->c_hdrsize, UIO_SYSSPACE, IO_NODELOCKED|IO_UNIT, cred,
+ (int *)0, p);
+ if (error)
+ return error;
+
+ error = vn_rdwr(UIO_WRITE, vp, (caddr_t)&md_core, sizeof(md_core),
+ (off_t)(chdr->c_hdrsize + chdr->c_seghdrsize), UIO_SYSSPACE,
+ IO_NODELOCKED|IO_UNIT, cred, (int *)0, p);
+ if (error)
+ return error;
+
+ chdr->c_nseg++;
+ return 0;
+}
+
+/*
+ * Move pages from one kernel virtual address to another.
+ * Both addresses are assumed to reside in the Sysmap,
+ * and size must be a multiple of CLSIZE.
+ */
+pagemove(from, to, size)
+ register caddr_t from, to;
+ int size;
+{
+ register vm_offset_t pa;
+
+#ifdef DEBUG
+ if (size & CLOFSET)
+ panic("pagemove");
+#endif
+ while (size > 0) {
+ pa = pmap_extract(pmap_kernel(), (vm_offset_t)from);
+#ifdef DEBUG
+ if (pa == 0)
+ panic("pagemove 2");
+ if (pmap_extract(pmap_kernel(), (vm_offset_t)to) != 0)
+ panic("pagemove 3");
+#endif
+ pmap_remove(pmap_kernel(),
+ (vm_offset_t)from, (vm_offset_t)from + PAGE_SIZE);
+ pmap_enter(pmap_kernel(),
+ (vm_offset_t)to, pa, VM_PROT_READ|VM_PROT_WRITE, 1);
+ from += PAGE_SIZE;
+ to += PAGE_SIZE;
+ size -= PAGE_SIZE;
+ }
+}
+
+/*
+ * Map `size' bytes of physical memory starting at `paddr' into
+ * kernel VA space at `vaddr'. Read/write and cache-inhibit status
+ * are specified by `prot'.
+ */
+physaccess(vaddr, paddr, size, prot)
+ caddr_t vaddr, paddr;
+ register int size, prot;
+{
+ register pt_entry_t *pte;
+ register u_int page;
+
+ pte = kvtopte(vaddr);
+ page = (u_int)paddr & PG_FRAME;
+ for (size = btoc(size); size; size--) {
+ *pte++ = PG_V | prot | page;
+ page += NBPG;
+ }
+ TBIAS();
+}
+
+physunaccess(vaddr, size)
+ caddr_t vaddr;
+ register int size;
+{
+ register pt_entry_t *pte;
+
+ pte = kvtopte(vaddr);
+ for (size = btoc(size); size; size--)
+ *pte++ = PG_NV;
+ TBIAS();
+}
+
+/*
+ * Set a red zone in the kernel stack after the u. area.
+ * We don't support a redzone right now. It really isn't clear
+ * that it is a good idea since, if the kernel stack were to roll
+ * into a write protected page, the processor would lock up (since
+ * it cannot create an exception frame) and we would get no useful
+ * post-mortem info. Currently, under the DEBUG option, we just
+ * check at every clock interrupt to see if the current k-stack has
+ * gone too far (i.e. into the "redzone" page) and if so, panic.
+ * Look at _lev6intr in locore.s for more details.
+ */
+/*ARGSUSED*/
+setredzone(pte, vaddr)
+ pt_entry_t *pte;
+ caddr_t vaddr;
+{
+}
+
+/*
+ * Convert kernel VA to physical address
+ */
+kvtop(addr)
+ register caddr_t addr;
+{
+ vm_offset_t va;
+
+ va = pmap_extract(pmap_kernel(), (vm_offset_t)addr);
+ if (va == 0)
+ panic("kvtop: zero page frame");
+ return((int)va);
+}
+
+extern vm_map_t phys_map;
+
+/*
+ * Map an IO request into kernel virtual address space.
+ *
+ * XXX we allocate KVA space by using kmem_alloc_wait which we know
+ * allocates space without backing physical memory. This implementation
+ * is a total crock, the multiple mappings of these physical pages should
+ * be reflected in the higher-level VM structures to avoid problems.
+ */
+vmapbuf(bp)
+ register struct buf *bp;
+{
+ register int npf;
+ register caddr_t addr;
+ register long flags = bp->b_flags;
+ struct proc *p;
+ int off;
+ vm_offset_t kva;
+ register vm_offset_t pa;
+
+ if ((flags & B_PHYS) == 0)
+ panic("vmapbuf");
+ addr = bp->b_saveaddr = bp->b_data;
+ off = (int)addr & PGOFSET;
+ p = bp->b_proc;
+ npf = btoc(round_page(bp->b_bcount + off));
+ kva = kmem_alloc_wait(phys_map, ctob(npf));
+ bp->b_data = (caddr_t)(kva + off);
+ while (npf--) {
+ pa = pmap_extract(vm_map_pmap(&p->p_vmspace->vm_map),
+ (vm_offset_t)addr);
+ if (pa == 0)
+ panic("vmapbuf: null page frame");
+ pmap_enter(vm_map_pmap(phys_map), kva, trunc_page(pa),
+ VM_PROT_READ|VM_PROT_WRITE, TRUE);
+ addr += PAGE_SIZE;
+ kva += PAGE_SIZE;
+ }
+}
+
+/*
+ * Free the io map PTEs associated with this IO operation.
+ */
+vunmapbuf(bp)
+ register struct buf *bp;
+{
+ register caddr_t addr;
+ register int npf;
+ vm_offset_t kva;
+
+ if ((bp->b_flags & B_PHYS) == 0)
+ panic("vunmapbuf");
+ addr = bp->b_data;
+ npf = btoc(round_page(bp->b_bcount + ((int)addr & PGOFSET)));
+ kva = (vm_offset_t)((int)addr & ~PGOFSET);
+ kmem_free_wakeup(phys_map, kva, ctob(npf));
+ bp->b_data = bp->b_saveaddr;
+ bp->b_saveaddr = NULL;
+}
+
+#ifdef MAPPEDCOPY
+u_int mappedcopysize = 4096;
+
+mappedcopyin(fromp, top, count)
+ register char *fromp, *top;
+ register int count;
+{
+ register vm_offset_t kva, upa;
+ register int off, len;
+ int alignable;
+ pmap_t upmap;
+ extern caddr_t CADDR1;
+
+ kva = (vm_offset_t) CADDR1;
+ off = (vm_offset_t)fromp & PAGE_MASK;
+ alignable = (off == ((vm_offset_t)top & PAGE_MASK));
+ upmap = vm_map_pmap(&curproc->p_vmspace->vm_map);
+ while (count > 0) {
+ /*
+ * First access of a page, use fubyte to make sure
+ * page is faulted in and read access allowed.
+ */
+ if (fubyte(fromp) == -1)
+ return (EFAULT);
+ /*
+ * Map in the page and bcopy data in from it
+ */
+ upa = pmap_extract(upmap, trunc_page(fromp));
+ if (upa == 0)
+ panic("mappedcopyin");
+ len = min(count, PAGE_SIZE-off);
+ pmap_enter(pmap_kernel(), kva, upa, VM_PROT_READ, TRUE);
+ if (len == PAGE_SIZE && alignable && off == 0)
+ copypage(kva, top);
+ else
+ bcopy((caddr_t)(kva+off), top, len);
+ fromp += len;
+ top += len;
+ count -= len;
+ off = 0;
+ }
+ pmap_remove(pmap_kernel(), kva, kva+PAGE_SIZE);
+ return (0);
+}
+
+mappedcopyout(fromp, top, count)
+ register char *fromp, *top;
+ register int count;
+{
+ register vm_offset_t kva, upa;
+ register int off, len;
+ int alignable;
+ pmap_t upmap;
+ extern caddr_t CADDR2;
+
+ kva = (vm_offset_t) CADDR2;
+ off = (vm_offset_t)top & PAGE_MASK;
+ alignable = (off == ((vm_offset_t)fromp & PAGE_MASK));
+ upmap = vm_map_pmap(&curproc->p_vmspace->vm_map);
+ while (count > 0) {
+ /*
+ * First access of a page, use subyte to make sure
+ * page is faulted in and write access allowed.
+ */
+ if (subyte(top, *fromp) == -1)
+ return (EFAULT);
+ /*
+ * Map in the page and bcopy data out to it
+ */
+ upa = pmap_extract(upmap, trunc_page(top));
+ if (upa == 0)
+ panic("mappedcopyout");
+ len = min(count, PAGE_SIZE-off);
+ pmap_enter(pmap_kernel(), kva, upa,
+ VM_PROT_READ|VM_PROT_WRITE, TRUE);
+ if (len == PAGE_SIZE && alignable && off == 0)
+ copypage(fromp, kva);
+ else
+ bcopy(fromp, (caddr_t)(kva+off), len);
+ fromp += len;
+ top += len;
+ count -= len;
+ off = 0;
+ }
+ pmap_remove(pmap_kernel(), kva, kva+PAGE_SIZE);
+ return (0);
+}
+#endif
diff --git a/sys/arch/mvme68k/stand/Makefile b/sys/arch/mvme68k/stand/Makefile
new file mode 100644
index 00000000000..a52741c8337
--- /dev/null
+++ b/sys/arch/mvme68k/stand/Makefile
@@ -0,0 +1,5 @@
+# $NetBSD: Makefile,v 1.1.1.1 1995/07/25 23:12:20 chuck Exp $
+
+SUBDIR= libsa netboot
+
+.include <bsd.subdir.mk>
diff --git a/sys/arch/mvme68k/stand/Makefile.inc b/sys/arch/mvme68k/stand/Makefile.inc
new file mode 100644
index 00000000000..8f75687d6d2
--- /dev/null
+++ b/sys/arch/mvme68k/stand/Makefile.inc
@@ -0,0 +1,37 @@
+# $NetBSD: Makefile.inc,v 1.1.1.1 1995/07/25 23:12:21 chuck Exp $
+
+.if defined(SA_PROG)
+
+# Must have S=/usr/src/sys (or equivalent)
+# But note: this is w.r.t. a subdirectory
+S= ../../../..
+
+RELOC?= 240000
+DEFS?= -DSTANDALONE
+INCL?= -I. -I../libsa -I${S}/lib/libsa -I${S}
+COPTS?= -msoft-float ${DEFS} ${INCL}
+
+LIBSA?= ../libsa
+SRTOBJ?= ${LIBSA}/SRT0.o ${LIBSA}/SRT1.o
+LIBS?= ${LIBSA}/libsa.a
+MDEC_DIR?=/usr/mdec
+
+SRCS?= ${SA_PROG}.c
+OBJS?= ${SRTOBJ} ${SRCS:S/.c/.o/g}
+
+${SA_PROG}.bin : ${SA_PROG}
+ cp ${SA_PROG} a.out ; strip a.out
+ dd ibs=32 skip=1 if=a.out of=$@
+ -rm -f a.out
+
+${SA_PROG} : ${OBJS} ${LIBS}
+ ${LD} -N -T ${RELOC} -e start -o $@ ${OBJS} ${LIBS}
+ @size $@
+
+.if !target(clean)
+clean:
+ -rm -f a.out [Ee]rrs mklog core *.core
+ -rm -f ${SA_PROG} ${SA_PROG}.bin ${OBJS} ${CLEANFILES}
+.endif
+
+.endif
diff --git a/sys/arch/mvme68k/stand/libsa/Makefile b/sys/arch/mvme68k/stand/libsa/Makefile
new file mode 100644
index 00000000000..317525bd0e7
--- /dev/null
+++ b/sys/arch/mvme68k/stand/libsa/Makefile
@@ -0,0 +1,41 @@
+# $NetBSD: Makefile,v 1.1.1.1 1995/07/25 23:12:21 chuck Exp $
+
+LIB=sa
+
+NOPIC=nopic
+NOPROFILE=noprofile
+
+# Logically src/sys
+S=${.CURDIR}/../../../..
+DIR_SA=$S/lib/libsa
+DIR_KERN=$S/lib/libkern
+
+SRC_net= nfs.c rpc.c net.c ether.c arp.c in_cksum.c \
+ bootparam.c rarp.c
+
+SRC_sa = alloc.c bcopy.c close.c getfile.c open.c \
+ printf.c read.c strerror.c ufs.c
+
+SRC_kern= ashrdi3.c bcmp.c bzero.c strcmp.c strlen.c
+
+SRC_here= clock.c devopen.c \
+ exec.c gets.c netif.c panic.c \
+ machdep.c
+
+SRCS= ${SRC_net} ${SRC_sa} ${SRC_kern} ${SRC_here}
+
+# DBG= -DDEBUG -DNETIF_DEBUG -DNFS_DEBUG -DRPC_DEBUG \
+# -DNET_DEBUG -DRARP_DEBUG -DETHER_DEBUG
+
+DEFS= -DCOMPAT_UFS
+INCL= -I. -I${S}/lib/libsa -I${S}
+COPTS= -msoft-float -fno-defer-pop -fno-omit-frame-pointer
+CFLAGS= -O ${COPTS} ${DEFS} ${DBG} ${INCL}
+
+.PATH: ${DIR_SA} ${DIR_KERN} ../../sun3
+
+all: libsa.a SRT0.o SRT1.o
+
+install:
+
+.include <bsd.lib.mk>
diff --git a/sys/arch/mvme68k/stand/libsa/SRT0.S b/sys/arch/mvme68k/stand/libsa/SRT0.S
new file mode 100644
index 00000000000..b2114fc3447
--- /dev/null
+++ b/sys/arch/mvme68k/stand/libsa/SRT0.S
@@ -0,0 +1,86 @@
+| $NetBSD: SRT0.S,v 1.1.1.1 1995/07/25 23:12:21 chuck Exp $
+
+| Copyright (c) 1995 Gordon W. Ross
+| All rights reserved.
+|
+| Redistribution and use in source and binary forms, with or without
+| modification, are permitted provided that the following conditions
+| are met:
+| 1. Redistributions of source code must retain the above copyright
+| notice, this list of conditions and the following disclaimer.
+| 2. Redistributions in binary form must reproduce the above copyright
+| notice, this list of conditions and the following disclaimer in the
+| documentation and/or other materials provided with the distribution.
+| 3. The name of the author may not be used to endorse or promote products
+| derived from this software without specific prior written permission.
+| 4. All advertising materials mentioning features or use of this software
+| must display the following acknowledgement:
+| This product includes software developed by Gordon Ross
+|
+| 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.
+
+| SRT0.S - Stand-alone Run-Time startup code, part 0
+ .file "SRT0.S"
+ .text
+ .globl __estack
+__estack:
+ .globl start
+start:
+| Check to see if the code is located correctly.
+| This SHOULD do a PC-relative load into a0, but...
+| lea start, a0 | current location (0x4000)
+| XXX - GAS version 1.93 gets the above lea wrong!
+ .word 0x41fa
+ .word 0xfffe
+| Now force a long (not PC-relative) load to a1 and compare.
+ lea start:l, a1 | desired location (LINKADDR)
+ cmpl a0, a1
+ beqs restart
+
+| Relocate the code and data to where they belong.
+ movl #_edata,d0 | Desired end of program
+ subl a1,d0 | Calculate length, round up.
+ lsrl #2,d0
+Lcp:
+ movl a0@+, a1@+
+ dbra d0, Lcp
+
+| Force a long jump to the relocated code (not pc-relative)
+ lea restart:l, a0
+ jmp a0@
+
+restart:
+| now in the relocated code
+
+ movl a6@(8), __cmd_buf | get cmd_line from sboot
+
+| Set up stack (just before relocated text)
+ lea __estack:l, a0
+ movl a0, sp
+ subl a6, a6
+
+| Call the run-time startup C code, which will:
+| initialize, call main, call exit
+ jsr __start:l
+
+| If _start returns, fall into abort.
+ .globl _abort
+_abort:
+ jsr 0x4000
+
+| If abort returns, fall into reset.
+ .globl _reset
+_reset:
+ reset
+ jmp _reset
+
+| The end.
diff --git a/sys/arch/mvme68k/stand/libsa/SRT1.c b/sys/arch/mvme68k/stand/libsa/SRT1.c
new file mode 100644
index 00000000000..2878cc7f028
--- /dev/null
+++ b/sys/arch/mvme68k/stand/libsa/SRT1.c
@@ -0,0 +1,71 @@
+/* $NetBSD: SRT1.c,v 1.1.1.1.2.1 1995/10/12 22:47:53 chuck Exp $ */
+
+/*
+ * Copyright (c) 1995 Gordon W. Ross
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ * 4. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Gordon Ross
+ *
+ * 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.
+ */
+
+/* SRT1.c - Stand-alone Run-time startup code, part 1 */
+
+#include <stdarg.h>
+#include <sys/types.h>
+
+extern int edata[], end[];
+extern volatile void abort();
+extern void main();
+char *_cmd_buf = (char *)0;
+
+volatile void
+exit()
+{
+ abort();
+}
+
+/*
+ * This is called by SRT0.S
+ * to do final prep for main
+ */
+void
+_start()
+{
+ register int *p;
+
+ /* Clear BSS */
+ p = edata;
+ do *p++ = 0;
+ while (p < end);
+
+ main(_cmd_buf);
+ exit();
+}
+
+/*
+ * Boot programs in C++ ? Not likely!
+ */
+void
+__main() {}
diff --git a/sys/arch/mvme68k/stand/libsa/clock.c b/sys/arch/mvme68k/stand/libsa/clock.c
new file mode 100644
index 00000000000..c937a90085d
--- /dev/null
+++ b/sys/arch/mvme68k/stand/libsa/clock.c
@@ -0,0 +1,128 @@
+/* $NetBSD: clock.c,v 1.1.1.1 1995/07/25 23:12:22 chuck Exp $ */
+
+/*
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ * Copyright (c) 1994 Gordon W. Ross
+ * Copyright (c) 1993 Adam Glass
+ *
+ * This software was developed by the Computer Systems Engineering group
+ * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
+ * contributed to Berkeley.
+ *
+ * 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, Lawrence Berkeley Laboratory.
+ *
+ * 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.
+ *
+ * @(#)clock.c 8.1 (Berkeley) 6/11/93
+ */
+
+/*
+ * Clock driver.
+ */
+
+#include <sys/types.h>
+#include "clockreg.h"
+static struct clockreg *clockreg = (struct clockreg *) CLOCK_ADDR;
+
+int hz = 1; /* XXX ? */
+
+/*
+ * BCD to decimal and decimal to BCD.
+ */
+#define FROMBCD(x) (((x) >> 4) * 10 + ((x) & 0xf))
+#define TOBCD(x) (((x) / 10 * 16) + ((x) % 10))
+
+#define SECDAY (24 * 60 * 60)
+#define SECYR (SECDAY * 365)
+#define LEAPYEAR(y) (((y) & 3) == 0)
+
+/*
+ * This code is defunct after 2068.
+ * Will Unix still be here then??
+ */
+const short dayyr[12] =
+ { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 };
+
+static u_long chiptotime(sec, min, hour, day, mon, year)
+ register int sec, min, hour, day, mon, year;
+{
+ register int days, yr;
+
+ sec = FROMBCD(sec);
+ min = FROMBCD(min);
+ hour = FROMBCD(hour);
+ day = FROMBCD(day);
+ mon = FROMBCD(mon);
+ year = FROMBCD(year) + YEAR0;
+ if (year < 70) year = 70;
+
+ /* simple sanity checks */
+ if (year < 70 || mon < 1 || mon > 12 || day < 1 || day > 31)
+ return (0);
+ days = 0;
+ for (yr = 70; yr < year; yr++)
+ days += LEAPYEAR(yr) ? 366 : 365;
+ days += dayyr[mon - 1] + day - 1;
+ if (LEAPYEAR(yr) && mon > 2)
+ days++;
+ /* now have days since Jan 1, 1970; the rest is easy... */
+ return (days * SECDAY + hour * 3600 + min * 60 + sec);
+}
+
+/*
+ * Set up the system's time, given a `reasonable' time value.
+ */
+time_t getsecs()
+{
+ register struct clockreg *cl = clockreg;
+ int sec, min, hour, day, mon, year;
+
+ cl->cl_csr |= CLK_READ; /* enable read (stop time) */
+ sec = cl->cl_sec;
+ min = cl->cl_min;
+ hour = cl->cl_hour;
+ day = cl->cl_mday;
+ mon = cl->cl_month;
+ year = cl->cl_year;
+ cl->cl_csr &= ~CLK_READ; /* time wears on */
+ return(chiptotime(sec, min, hour, day, mon, year));
+}
+
+/*
+ * delay
+ */
+
+int getticks()
+{
+ return((int)getsecs());
+}
diff --git a/sys/arch/mvme68k/stand/libsa/clock.h b/sys/arch/mvme68k/stand/libsa/clock.h
new file mode 100644
index 00000000000..d61bc9b03b8
--- /dev/null
+++ b/sys/arch/mvme68k/stand/libsa/clock.h
@@ -0,0 +1,6 @@
+
+extern int hz;
+
+time_t getsecs();
+int getticks();
+
diff --git a/sys/arch/mvme68k/stand/libsa/clockreg.h b/sys/arch/mvme68k/stand/libsa/clockreg.h
new file mode 100644
index 00000000000..5ada963e3b9
--- /dev/null
+++ b/sys/arch/mvme68k/stand/libsa/clockreg.h
@@ -0,0 +1,71 @@
+/* $NetBSD: clockreg.h,v 1.1.1.1 1995/07/25 23:12:24 chuck Exp $ */
+
+/*
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This software was developed by the Computer Systems Engineering group
+ * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
+ * contributed to Berkeley.
+ *
+ * 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, Lawrence Berkeley Laboratory.
+ *
+ * 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.
+ *
+ * @(#)clockreg.h 8.1 (Berkeley) 6/11/93
+ */
+
+/*
+ * Mostek MK48T02 clock.
+ */
+struct clockreg {
+ volatile u_char cl_csr; /* control register */
+ volatile u_char cl_sec; /* seconds (0..59; BCD) */
+ volatile u_char cl_min; /* minutes (0..59; BCD) */
+ volatile u_char cl_hour; /* hour (0..23; BCD) */
+ volatile u_char cl_wday; /* weekday (1..7) */
+ volatile u_char cl_mday; /* day in month (1..31; BCD) */
+ volatile u_char cl_month; /* month (1..12; BCD) */
+ volatile u_char cl_year; /* year (0..99; BCD) */
+};
+
+/* bits in cl_csr */
+#define CLK_WRITE 0x80 /* want to write */
+#define CLK_READ 0x40 /* want to read (freeze clock) */
+
+/*
+ * Sun chose the year `68' as their base count, so that
+ * cl_year==0 means 1968.
+ */
+#define YEAR0 68
+
+#define CLOCK_ADDR (0xfffe07f8) /* VME147 PA of clock */
diff --git a/sys/arch/mvme68k/stand/libsa/config.h b/sys/arch/mvme68k/stand/libsa/config.h
new file mode 100644
index 00000000000..9161fd14efd
--- /dev/null
+++ b/sys/arch/mvme68k/stand/libsa/config.h
@@ -0,0 +1,10 @@
+/* $NetBSD: config.h,v 1.1.1.1 1995/07/25 23:12:24 chuck Exp $ */
+
+/* configuration information for base-line code */
+
+#define COMMON_ETHERADDR
+
+#define CONS_ZS_ADDR (0xfffe3002)
+#define ETHER_ADDR (0xfffe0778)
+#define ERAM_ADDR (0xfffe0774)
+#define LANCE_REG_ADDR (0xfffe1800)
diff --git a/sys/arch/mvme68k/stand/libsa/devopen.c b/sys/arch/mvme68k/stand/libsa/devopen.c
new file mode 100644
index 00000000000..2c7e714e430
--- /dev/null
+++ b/sys/arch/mvme68k/stand/libsa/devopen.c
@@ -0,0 +1,23 @@
+
+#include <sys/param.h>
+#include <stand.h>
+
+/*
+ * Open the device
+ */
+int
+devopen(f, fname, file)
+ struct open_file *f;
+ const char *fname;
+ char **file;
+{
+ struct devsw *dp;
+ int error;
+
+ *file = (char*)fname;
+ dp = &devsw[0];
+ f->f_dev = dp;
+ error = (*dp->dv_open)(f, NULL);
+
+ return (error);
+}
diff --git a/sys/arch/mvme68k/stand/libsa/exec.c b/sys/arch/mvme68k/stand/libsa/exec.c
new file mode 100644
index 00000000000..343f4d1a0c0
--- /dev/null
+++ b/sys/arch/mvme68k/stand/libsa/exec.c
@@ -0,0 +1,177 @@
+/* $NetBSD: exec.c,v 1.1.1.1.2.1 1995/10/12 22:47:56 chuck Exp $ */
+
+/*-
+ * Copyright (c) 1982, 1986, 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)boot.c 8.1 (Berkeley) 6/10/93
+ */
+
+#include <sys/param.h>
+#include <a.out.h>
+
+#include "stand.h"
+
+extern int debug;
+
+/*ARGSUSED*/
+int
+exec_mvme(file, loadaddr, boothowto)
+ char *file;
+ char *loadaddr;
+ int boothowto;
+{
+ register int io;
+ struct exec x;
+ int cc, magic;
+ void (*entry)();
+ register char *cp;
+ register int *ip;
+
+#ifdef DEBUG
+ printf("exec: file=%s loadaddr=0x%x\n", file, loadaddr);
+#endif
+
+ io = open(file, 0);
+ if (io < 0)
+ return(-1);
+
+ /*
+ * Read in the exec header, and validate it.
+ */
+ if (read(io, (char *)&x, sizeof(x)) != sizeof(x))
+ goto shread;
+ if (N_BADMAG(x)) {
+ errno = EFTYPE;
+ goto closeout;
+ }
+
+ cp = loadaddr;
+ magic = N_GETMAGIC(x);
+ if (magic == ZMAGIC)
+ cp += sizeof(x);
+ entry = (void (*)())x.a_entry;
+
+ /*
+ * Leave a copy of the exec header before the text.
+ * The kernel may use this to verify that the
+ * symbols were loaded by this boot program.
+ */
+ bcopy(&x, cp - sizeof(x), sizeof(x));
+
+ /*
+ * Read in the text segment.
+ */
+ printf("%d", x.a_text);
+ if (read(io, cp, x.a_text) != x.a_text)
+ goto shread;
+ cp += x.a_text;
+
+ /*
+ * NMAGIC may have a gap between text and data.
+ */
+ if (magic == NMAGIC) {
+ register int mask = N_PAGSIZ(x) - 1;
+ while ((int)cp & mask)
+ *cp++ = 0;
+ }
+
+ /*
+ * Read in the data segment.
+ */
+ printf("+%d", x.a_data);
+ if (read(io, cp, x.a_data) != x.a_data)
+ goto shread;
+ cp += x.a_data;
+
+ /*
+ * Zero out the BSS section.
+ * (Kernel doesn't care, but do it anyway.)
+ */
+ printf("+%d", x.a_bss);
+ cc = x.a_bss;
+ while ((int)cp & 3) {
+ *cp++ = 0;
+ --cc;
+ }
+ ip = (int*)cp;
+ cp += cc;
+ while ((char*)ip < cp)
+ *ip++ = 0;
+
+ /*
+ * Read in the symbol table and strings.
+ * (Always set the symtab size word.)
+ */
+ *ip++ = x.a_syms;
+ cp = (char*) ip;
+
+ if (x.a_syms > 0) {
+
+ /* Symbol table and string table length word. */
+ cc = x.a_syms;
+ printf("+[%d", cc);
+ cc += sizeof(int); /* strtab length too */
+ if (read(io, cp, cc) != cc)
+ goto shread;
+ cp += x.a_syms;
+ ip = (int*)cp; /* points to strtab length */
+ cp += sizeof(int);
+
+ /* String table. Length word includes itself. */
+ cc = *ip;
+ printf("+%d]", cc);
+ cc -= sizeof(int);
+ if (cc <= 0)
+ goto shread;
+ if (read(io, cp, cc) != cc)
+ goto shread;
+ cp += cc;
+ }
+ printf("=0x%x\n", cp - loadaddr);
+ close(io);
+
+ if (debug) {
+ printf("Debug mode - enter c to continue\n");
+ asm(" trap #0");
+ }
+
+ printf("Start @ 0x%x ...\n", (int)entry);
+ (*entry)(boothowto);
+ panic("exec returned");
+
+shread:
+ printf("exec: short read\n");
+ errno = EIO;
+closeout:
+ close(io);
+ return(-1);
+}
diff --git a/sys/arch/mvme68k/stand/libsa/gets.c b/sys/arch/mvme68k/stand/libsa/gets.c
new file mode 100644
index 00000000000..cddf88b7925
--- /dev/null
+++ b/sys/arch/mvme68k/stand/libsa/gets.c
@@ -0,0 +1,117 @@
+/* $NetBSD: gets.c,v 1.1.1.1 1995/07/25 23:12:21 chuck Exp $ */
+
+/*-
+ * Copyright (c) 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)gets.c 8.1 (Berkeley) 6/11/93
+ */
+
+#include "stand.h"
+
+/*
+ * This implementation assumes that getchar() does echo, because
+ * on some machines, it is hard to keep echo from being done.
+ * Those that need it can do echo in their getchar() function.
+ *
+ * Yes, the code below will echo CR, DEL, and other control chars,
+ * but sending CR or DEL here is harmless. All the other editing
+ * characters will be followed by a newline, so it doesn't matter.
+ * (Most terminals will not show them anyway.)
+ */
+#define GETS_MUST_ECHO /* Preserved in case someone wants it... */
+
+void
+gets(buf)
+ char *buf;
+{
+ register int c;
+ register char *lp;
+
+top:
+ lp = buf;
+
+ for (;;) {
+ c = getchar() & 0177;
+
+#ifdef GETS_MUST_ECHO /* Preserved in case someone wants it... */
+ putchar(c);
+#endif
+
+ switch (c) {
+
+ default:
+ *lp++ = c;
+ continue;
+
+ case '\177':
+ putchar('\b');
+ /* fall through */
+ case '\b':
+ putchar(' ');
+ putchar('\b');
+ /* fall through */
+ case '#':
+ if (lp > buf)
+ lp--;
+ continue;
+
+#ifdef GETS_REPRINT
+ /*
+ * This is not very useful in a boot program.
+ * (It costs you 52 bytes on m68k, gcc -O3).
+ */
+ case 'r'&037: {
+ register char *p;
+ putchar('\n');
+ for (p = buf; p < lp; ++p)
+ putchar(*p);
+ continue;
+ }
+#endif
+
+ case '@':
+ case 'u'&037:
+ case 'w'&037:
+ putchar('\n');
+ goto top;
+
+ case '\r':
+ putchar('\n');
+ /* fall through */
+ case '\n':
+ *lp = '\0';
+ return;
+
+ } /* switch */
+ }
+ /*NOTREACHED*/
+}
diff --git a/sys/arch/mvme68k/stand/libsa/if_lereg.h b/sys/arch/mvme68k/stand/libsa/if_lereg.h
new file mode 100644
index 00000000000..3aee758cabc
--- /dev/null
+++ b/sys/arch/mvme68k/stand/libsa/if_lereg.h
@@ -0,0 +1,176 @@
+/* $NetBSD: if_lereg.h,v 1.1.1.1 1995/07/25 23:12:23 chuck Exp $ */
+
+/*-
+ * Copyright (c) 1982, 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)if_lereg.h 8.2 (Berkeley) 10/30/93
+ */
+
+#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)
+
+/* Local Area Network Controller for Ethernet (LANCE) registers */
+struct lereg1 {
+ volatile u_short ler1_rdp; /* register data port */
+ volatile u_short ler1_rap; /* register address port */
+};
+
+/* register addresses */
+#define LE_CSR0 0 /* Control and status register */
+#define LE_CSR1 1 /* low address of init block */
+#define LE_CSR2 2 /* high address of init block */
+#define LE_CSR3 3 /* Bus master and control */
+
+/* Control and status register 0 (csr0) */
+#define LE_C0_ERR 0x8000 /* error summary */
+#define LE_C0_BABL 0x4000 /* transmitter timeout error */
+#define LE_C0_CERR 0x2000 /* collision */
+#define LE_C0_MISS 0x1000 /* missed a packet */
+#define LE_C0_MERR 0x0800 /* memory error */
+#define LE_C0_RINT 0x0400 /* receiver interrupt */
+#define LE_C0_TINT 0x0200 /* transmitter interrupt */
+#define LE_C0_IDON 0x0100 /* initalization done */
+#define LE_C0_INTR 0x0080 /* interrupt condition */
+#define LE_C0_INEA 0x0040 /* interrupt enable */
+#define LE_C0_RXON 0x0020 /* receiver on */
+#define LE_C0_TXON 0x0010 /* transmitter on */
+#define LE_C0_TDMD 0x0008 /* transmit demand */
+#define LE_C0_STOP 0x0004 /* disable all external activity */
+#define LE_C0_STRT 0x0002 /* enable external activity */
+#define LE_C0_INIT 0x0001 /* begin initalization */
+
+#define LE_C0_BITS \
+ "\20\20ERR\17BABL\16CERR\15MISS\14MERR\13RINT\
+\12TINT\11IDON\10INTR\07INEA\06RXON\05TXON\04TDMD\03STOP\02STRT\01INIT"
+
+/* Control and status register 3 (csr3) */
+#define LE_C3_BSWP 0x4 /* byte swap */
+#define LE_C3_ACON 0x2 /* ALE control, eh? */
+#define LE_C3_BCON 0x1 /* byte control */
+/*
+ * Current size is 13,758 bytes with 8 x 1518 receive buffers and
+ * 1 x 1518 transmit buffer.
+ */
+struct lereg2 {
+ /* initialization block */
+ volatile u_short ler2_mode; /* mode */
+ volatile u_char ler2_padr[6]; /* physical address */
+#ifdef new_code
+ volatile u_short ler2_ladrf[4]; /* logical address filter */
+#else
+ volatile u_long ler2_ladrf0; /* logical address filter */
+ volatile u_long ler2_ladrf1; /* logical address filter */
+#endif
+ volatile u_short ler2_rdra; /* receive descriptor addr */
+ volatile u_short ler2_rlen; /* rda high and ring size */
+ volatile u_short ler2_tdra; /* transmit descriptor addr */
+ volatile u_short ler2_tlen; /* tda high and ring size */
+ /* receive message descriptors. bits/hadr are byte order dependent. */
+ struct lermd {
+ volatile u_short rmd0; /* low address of packet */
+ volatile u_char rmd1_bits; /* descriptor bits */
+ volatile u_char rmd1_hadr; /* high address of packet */
+ volatile short rmd2; /* buffer byte count */
+ volatile u_short rmd3; /* message byte count */
+ } ler2_rmd[LERBUF];
+ /* transmit message descriptors */
+ struct letmd {
+ volatile u_short tmd0; /* low address of packet */
+ volatile u_char tmd1_bits; /* descriptor bits */
+ volatile u_char tmd1_hadr; /* high address of packet */
+ volatile short tmd2; /* buffer byte count */
+ volatile u_short tmd3; /* transmit error bits */
+ } ler2_tmd[LETBUF];
+ volatile char ler2_rbuf[LERBUF][LEMTU];
+ volatile char ler2_tbuf[LETBUF][LEMTU];
+};
+
+/* Initialzation block (mode) */
+#define LE_MODE_PROM 0x8000 /* promiscuous mode */
+/* 0x7f80 reserved, must be zero */
+#define LE_MODE_INTL 0x0040 /* internal loopback */
+#define LE_MODE_DRTY 0x0020 /* disable retry */
+#define LE_MODE_COLL 0x0010 /* force a collision */
+#define LE_MODE_DTCR 0x0008 /* disable transmit CRC */
+#define LE_MODE_LOOP 0x0004 /* loopback mode */
+#define LE_MODE_DTX 0x0002 /* disable transmitter */
+#define LE_MODE_DRX 0x0001 /* disable receiver */
+#define LE_MODE_NORMAL 0 /* none of the above */
+
+
+/* Receive message descriptor 1 (rmd1_bits) */
+#define LE_R1_OWN 0x80 /* LANCE owns the packet */
+#define LE_R1_ERR 0x40 /* error summary */
+#define LE_R1_FRAM 0x20 /* framing error */
+#define LE_R1_OFLO 0x10 /* overflow error */
+#define LE_R1_CRC 0x08 /* CRC error */
+#define LE_R1_BUFF 0x04 /* buffer error */
+#define LE_R1_STP 0x02 /* start of packet */
+#define LE_R1_ENP 0x01 /* end of packet */
+
+#define LE_R1_BITS \
+ "\20\10OWN\7ERR\6FRAM\5OFLO\4CRC\3BUFF\2STP\1ENP"
+
+/* Transmit message descriptor 1 (tmd1_bits) */
+#define LE_T1_OWN 0x80 /* LANCE owns the packet */
+#define LE_T1_ERR 0x40 /* error summary */
+#define LE_T1_MORE 0x10 /* multiple collisions */
+#define LE_T1_ONE 0x08 /* single collision */
+#define LE_T1_DEF 0x04 /* defferred transmit */
+#define LE_T1_STP 0x02 /* start of packet */
+#define LE_T1_ENP 0x01 /* end of packet */
+
+#define LE_T1_BITS \
+ "\20\10OWN\7ERR\6RES\5MORE\4ONE\3DEF\2STP\1ENP"
+
+/* Transmit message descriptor 3 (tmd3) */
+#define LE_T3_BUFF 0x8000 /* buffer error */
+#define LE_T3_UFLO 0x4000 /* underflow error */
+#define LE_T3_LCOL 0x1000 /* late collision */
+#define LE_T3_LCAR 0x0800 /* loss of carrier */
+#define LE_T3_RTRY 0x0400 /* retry error */
+#define LE_T3_TDR_MASK 0x03ff /* time domain reflectometry counter */
+
+#define LE_XMD2_ONES 0xf000
+
+#define LE_T3_BITS \
+ "\20\20BUFF\17UFLO\16RES\15LCOL\14LCAR\13RTRY"
+
+
+#define LE_ADDR_LOW_MASK (0xffff)
+
diff --git a/sys/arch/mvme68k/stand/libsa/machdep.c b/sys/arch/mvme68k/stand/libsa/machdep.c
new file mode 100644
index 00000000000..c47d2ecc43e
--- /dev/null
+++ b/sys/arch/mvme68k/stand/libsa/machdep.c
@@ -0,0 +1,154 @@
+/* $NetBSD: machdep.c,v 1.1.1.1 1995/07/25 23:12:22 chuck Exp $ */
+
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/exec.h>
+
+#include <sys/reboot.h>
+
+#include "config.h"
+
+/*
+ * get_boothowto: boothowto for kernel
+ */
+
+static int get_boothowto(cmd_flags)
+
+char *cmd_flags;
+
+{
+ int result = 0;
+
+ if (cmd_flags == NULL) return(0);
+
+ while (*cmd_flags) {
+ switch (*cmd_flags) {
+ case 's': result |= RB_SINGLE; break;
+ case 'a': result |= RB_ASKNAME; break;
+ default: break;
+ }
+ cmd_flags++;
+ }
+
+ return(result);
+}
+
+/*
+ * cmd_parse: parse command line
+ * expected format: "b[oot] [kernel_name] [-flags]"
+ */
+
+char *cmd_parse(cmd_buf, howto)
+char *cmd_buf;
+int *howto;
+{
+ char *cmd_kernel, *cmd_flags;
+ u_char *cp;
+ *howto = 0;
+
+ cp = cmd_buf+1; /* skip 'b' */
+ while (*cp && *cp != ' ') cp++; /* skip to end or space */
+ while (*cp == ' ') cp++; /* skip spaces */
+ if (*cp == '\0') return(NULL); /* no args */
+ if (*cp == '-') { /* only flags? */
+ *howto = get_boothowto(cp);
+ return(NULL);
+ }
+ cmd_kernel = cp; /* got kernel name */
+ while (*cp && *cp != ' ') cp++; /* skip to end or space */
+ if (*cp == ' ') *cp++ = 0; /* null terminate kernel */
+ while (*cp == ' ') cp++; /* skip spaces */
+ if (*cp == '\0') return(cmd_kernel); /* no flags */
+ if (*cp != '-') return(cmd_kernel); /* garbage flags */
+ cmd_flags = cp; /* save flags */
+
+ while (*cp && *cp != ' ') cp++; /* skip to end or space */
+ if (*cp == ' ') *cp++ = 0; /* null terminate flags */
+
+ *howto = get_boothowto(cmd_flags);
+
+ return(cmd_kernel);
+}
+
+
+/*
+ * machdep_common_ether: get ethernet address
+ */
+
+void machdep_common_ether(ether)
+ unsigned char *ether;
+{
+ caddr_t addr;
+ int *ea = (int *) ETHER_ADDR;
+ int e = *ea;
+ if (( e & 0x2fffff00 ) == 0x2fffff00)
+ panic("ERROR: ethernet address not set!\r\n");
+ ether[0] = 0x08;
+ ether[1] = 0x00;
+ ether[2] = 0x3e;
+ e = e >> 8;
+ ether[5] = e & 0xff;
+ e = e >> 8;
+ ether[4] = e & 0xff;
+ e = e >> 8;
+ ether[3] = e;
+}
+
+/*
+ * console i/o
+ */
+
+/*
+ * hardware
+ */
+
+struct zs_hw {
+ volatile u_char ctl;
+ volatile u_char data;
+};
+
+struct zs_hw *zs = (struct zs_hw *)CONS_ZS_ADDR;
+
+/*
+ * putchar: put char to console
+ */
+
+void putchar(char c)
+{
+ if (c == '\n') putchar('\r');
+ zs->ctl = 0;
+ while ((zs->ctl & 0x04) == 0) {
+ zs->ctl = 0;
+ }
+ zs->ctl = 8;
+ zs->ctl = c;
+}
+
+/*
+ * getchar: get char from console
+ */
+
+int
+getchar()
+{
+ int i;
+ while (1) {
+ zs->ctl = 0;
+ if ((zs->ctl & 0x1) != 0) break;
+ for (i = 100 ; i > 0 ; i--)
+ ;
+ }
+ zs->ctl = 8;
+ return(zs->ctl);
+}
+
+/*
+ * peekchar
+ */
+
+peekchar()
+{
+ zs->ctl = 0;
+ return(zs->ctl & 0x1);
+}
+
diff --git a/sys/arch/mvme68k/stand/libsa/netif.c b/sys/arch/mvme68k/stand/libsa/netif.c
new file mode 100644
index 00000000000..e2838521a67
--- /dev/null
+++ b/sys/arch/mvme68k/stand/libsa/netif.c
@@ -0,0 +1,531 @@
+/* $NetBSD: netif.c,v 1.1.1.1.2.1 1995/10/12 22:47:57 chuck Exp $ */
+
+/*
+ * Copyright (c) 1995 Gordon W. Ross
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ * 4. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Gordon W. Ross
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/param.h>
+#include <sys/socket.h>
+#include <string.h>
+#include <time.h>
+
+#include <net/if.h>
+
+#include <netinet/in.h>
+#include <netinet/if_ether.h>
+#include <netinet/in_systm.h>
+
+#include "stand.h"
+#include "net.h"
+#include "netif.h"
+#include "config.h"
+
+static struct netif netif_prom;
+void machdep_common_ether __P((u_char *));
+
+#ifdef NETIF_DEBUG
+int netif_debug;
+#endif
+
+struct iodesc sockets[SOPEN_MAX];
+
+struct iodesc *
+socktodesc(sock)
+ int sock;
+{
+ if (sock != 0) {
+ return(NULL);
+ }
+ return (sockets);
+}
+
+int
+netif_open(machdep_hint)
+ void *machdep_hint;
+{
+ struct saioreq *si;
+ struct iodesc *io;
+ int error;
+
+ /* find a free socket */
+ io = sockets;
+ if (io->io_netif) {
+#ifdef DEBUG
+ printf("netif_open: device busy\n");
+#endif
+ return (-1);
+ }
+ bzero(io, sizeof(*io));
+
+ if ((netif_prom.devdata = le_init(io)) == NULL) {
+ printf("le_init failed\n");
+ return(-1);
+ }
+
+ io->io_netif = &netif_prom;
+
+ return(0);
+}
+
+int
+netif_close(fd)
+ int fd;
+{
+ struct iodesc *io;
+ struct netif *ni;
+
+ if (fd != 0) {
+ errno = EBADF;
+ return(-1);
+ }
+
+ io = sockets;
+ ni = io->io_netif;
+ if (ni != NULL) {
+ le_end(ni);
+ ni->devdata = NULL;
+ io->io_netif = NULL;
+ }
+ return(0);
+}
+
+/*
+ * Send a packet. The ether header is already there.
+ * Return the length sent (or -1 on error).
+ */
+int
+netif_put(desc, pkt, len)
+ struct iodesc *desc;
+ void *pkt;
+ size_t len;
+{
+
+#ifdef NETIF_DEBUG
+ if (netif_debug) {
+ struct ether_header *eh;
+
+ printf("netif_put: desc=0x%x pkt=0x%x len=%d\n",
+ desc, pkt, len);
+ eh = pkt;
+ printf("dst: %s ", ether_sprintf(eh->ether_dhost));
+ printf("src: %s ", ether_sprintf(eh->ether_shost));
+ printf("type: 0x%x\n", eh->ether_type & 0xFFFF);
+ }
+#endif
+
+ return(le_put(desc, pkt, len));
+}
+
+/*
+ * Receive a packet, including the ether header.
+ * Return the total length received (or -1 on error).
+ */
+int
+netif_get(desc, pkt, maxlen, timo)
+ struct iodesc *desc;
+ void *pkt;
+ size_t maxlen;
+ time_t timo;
+{
+ struct saioreq *si;
+ struct saif *sif;
+ char *dmabuf;
+ int tick0, tmo_ticks;
+ int len;
+
+#ifdef NETIF_DEBUG
+ if (netif_debug)
+ printf("netif_get: pkt=0x%x, maxlen=%d, tmo=%d\n",
+ pkt, maxlen, timo);
+#endif
+
+ len = le_get(desc, pkt, maxlen, timo);
+
+#ifdef NETIF_DEBUG
+ if (netif_debug) {
+ struct ether_header *eh = pkt;
+
+ printf("dst: %s ", ether_sprintf(eh->ether_dhost));
+ printf("src: %s ", ether_sprintf(eh->ether_shost));
+ printf("type: 0x%x\n", eh->ether_type & 0xFFFF);
+ }
+#endif
+
+ return len;
+}
+
+/* the rest of this file imported from le_poll.c */
+
+/*
+ * Copyright (c) 1993 Adam Glass
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Adam Glass.
+ * 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 Adam Glass ``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.
+ */
+
+#include "if_lereg.h"
+
+struct {
+ struct lereg1 *sc_r1; /* LANCE registers */
+ struct lereg2 *sc_r2; /* RAM */
+ int next_rmd;
+ int next_tmd;
+} le_softc;
+
+int le_debug = 0;
+
+/*
+ * init le device. return 0 on failure, 1 if ok.
+ */
+
+void *
+le_init(io)
+ struct iodesc *io;
+{
+ u_long *eram = (u_long *) ERAM_ADDR;
+
+ if (le_debug)
+ printf("le: le_init called\n");
+ machdep_common_ether(io->myea);
+ bzero(&le_softc, sizeof(le_softc));
+ le_softc.sc_r1 = (struct lereg1 *) LANCE_REG_ADDR;
+ le_softc.sc_r2 = (struct lereg2 *) (*eram - (1024*1024));
+ le_reset(io->io_netif, io->myea);
+
+ return(&le_softc);
+}
+
+/*
+ * close device
+ * XXX le_softc
+ */
+
+void le_end(nif)
+
+ struct netif *nif;
+{
+ struct lereg1 *ler1 = le_softc.sc_r1;
+
+ if (le_debug)
+ printf("le: le_end called\n");
+ ler1->ler1_rap = LE_CSR0;
+ ler1->ler1_rdp = LE_C0_STOP;
+}
+
+
+/*
+ * reset device
+ * XXX le_softc
+ */
+
+void le_reset(nif, myea)
+ struct netif *nif;
+ u_char *myea;
+{
+ struct lereg1 *ler1 = le_softc.sc_r1;
+ struct lereg2 *ler2 = le_softc.sc_r2;
+ unsigned int a;
+ int timo = 100000, stat, i;
+
+ if (le_debug)
+ printf("le: le_reset called\n");
+ ler1->ler1_rap = LE_CSR0;
+ ler1->ler1_rdp = LE_C0_STOP; /* do nothing until we are finished */
+
+ bzero(ler2, sizeof(*ler2));
+
+ ler2->ler2_mode = LE_MODE_NORMAL;
+ ler2->ler2_padr[0] = myea[1];
+ ler2->ler2_padr[1] = myea[0];
+ ler2->ler2_padr[2] = myea[3];
+ ler2->ler2_padr[3] = myea[2];
+ ler2->ler2_padr[4] = myea[5];
+ ler2->ler2_padr[5] = myea[4];
+
+
+ ler2->ler2_ladrf0 = 0;
+ ler2->ler2_ladrf1 = 0;
+
+ a = (u_int)ler2->ler2_rmd;
+ ler2->ler2_rlen = LE_RLEN | (a >> 16);
+ ler2->ler2_rdra = a & LE_ADDR_LOW_MASK;
+
+ a = (u_int)ler2->ler2_tmd;
+ ler2->ler2_tlen = LE_TLEN | (a >> 16);
+ ler2->ler2_tdra = a & LE_ADDR_LOW_MASK;
+
+ ler1->ler1_rap = LE_CSR1;
+ a = (u_int)ler2;
+ ler1->ler1_rdp = a & LE_ADDR_LOW_MASK;
+ ler1->ler1_rap = LE_CSR2;
+ ler1->ler1_rdp = a >> 16;
+
+ for (i = 0; i < LERBUF; i++) {
+ a = (u_int)&ler2->ler2_rbuf[i];
+ ler2->ler2_rmd[i].rmd0 = a & LE_ADDR_LOW_MASK;
+ ler2->ler2_rmd[i].rmd1_bits = LE_R1_OWN;
+ ler2->ler2_rmd[i].rmd1_hadr = a >> 16;
+ ler2->ler2_rmd[i].rmd2 = -LEMTU;
+ ler2->ler2_rmd[i].rmd3 = 0;
+ }
+ for (i = 0; i < LETBUF; i++) {
+ a = (u_int)&ler2->ler2_tbuf[i];
+ ler2->ler2_tmd[i].tmd0 = a & LE_ADDR_LOW_MASK;
+ ler2->ler2_tmd[i].tmd1_bits = 0;
+ ler2->ler2_tmd[i].tmd1_hadr = a >> 16;
+ ler2->ler2_tmd[i].tmd2 = 0;
+ ler2->ler2_tmd[i].tmd3 = 0;
+ }
+
+ ler1->ler1_rap = LE_CSR3;
+ ler1->ler1_rdp = LE_C3_BSWP;
+
+ ler1->ler1_rap = LE_CSR0;
+ ler1->ler1_rdp = LE_C0_INIT;
+ do {
+ if (--timo == 0) {
+ printf("le: init timeout, stat = 0x%x\n", stat);
+ break;
+ }
+ stat = ler1->ler1_rdp;
+ } while ((stat & LE_C0_IDON) == 0);
+
+ ler1->ler1_rdp = LE_C0_IDON;
+ le_softc.next_rmd = 0;
+ le_softc.next_tmd = 0;
+ ler1->ler1_rap = LE_CSR0;
+ ler1->ler1_rdp = LE_C0_STRT;
+}
+
+/*
+ * le_error
+ * XXX le_softc
+ */
+
+void le_error(nif, str, vler1)
+ struct netif *nif;
+ char *str;
+ volatile void *vler1;
+{
+ volatile struct lereg1 *ler1 = vler1;
+ /* ler1->ler1_rap = LE_CSRO done in caller */
+ if (ler1->ler1_rdp & LE_C0_BABL)
+ panic("le: been babbling, found by '%s'\n", str);
+ if (ler1->ler1_rdp & LE_C0_CERR) {
+ ler1->ler1_rdp = LE_C0_CERR;
+ }
+ if (ler1->ler1_rdp & LE_C0_MISS) {
+ ler1->ler1_rdp = LE_C0_MISS;
+ }
+ if (ler1->ler1_rdp & LE_C0_MERR) {
+ printf("le: memory error in '%s'\n", str);
+ panic("memory error");
+ }
+}
+
+/*
+ * put a packet
+ * XXX le_softc
+ */
+
+int le_put(desc, pkt, len)
+ struct iodesc *desc;
+ void *pkt;
+ int len;
+{
+ volatile struct lereg1 *ler1 = le_softc.sc_r1;
+ volatile struct lereg2 *ler2 = le_softc.sc_r2;
+ volatile struct letmd *tmd;
+ int timo = 100000, stat, i;
+ unsigned int a;
+
+ ler1->ler1_rap = LE_CSR0;
+ if (ler1->ler1_rdp & LE_C0_ERR)
+ le_error(desc->io_netif, "le_put(way before xmit)", ler1);
+ tmd = &ler2->ler2_tmd[le_softc.next_tmd];
+ while(tmd->tmd1_bits & LE_T1_OWN) {
+ printf("le: output buffer busy\n");
+ }
+ bcopy(pkt, ler2->ler2_tbuf[le_softc.next_tmd], len);
+ if (len < 64)
+ tmd->tmd2 = -64;
+ else
+ tmd->tmd2 = -len;
+ tmd->tmd3 = 0;
+ if (ler1->ler1_rdp & LE_C0_ERR)
+ le_error(desc->io_netif, "le_put(before xmit)", ler1);
+ tmd->tmd1_bits = LE_T1_STP | LE_T1_ENP | LE_T1_OWN;
+ a = (u_int)&ler2->ler2_tbuf[le_softc.next_tmd];
+ tmd->tmd0 = a & LE_ADDR_LOW_MASK;
+ tmd->tmd1_hadr = a >> 16;
+ ler1->ler1_rdp = LE_C0_TDMD;
+ if (ler1->ler1_rdp & LE_C0_ERR)
+ le_error(desc->io_netif, "le_put(after xmit)", ler1);
+ do {
+ if (--timo == 0) {
+ printf("le: transmit timeout, stat = 0x%x\n", stat);
+ if (ler1->ler1_rdp & LE_C0_ERR)
+ le_error(desc->io_netif, "le_put(timeout)", ler1);
+ break;
+ }
+ stat = ler1->ler1_rdp;
+ } while ((stat & LE_C0_TINT) == 0);
+ ler1->ler1_rdp = LE_C0_TINT;
+ if (ler1->ler1_rdp & LE_C0_ERR) {
+ if ((ler1->ler1_rdp & (LE_C0_BABL|LE_C0_CERR|LE_C0_MISS|LE_C0_MERR)) !=
+ LE_C0_CERR)
+ printf("le_put: xmit error, buf %d\n", le_softc.next_tmd);
+ le_error(desc->io_netif, "le_put(xmit error)", ler1);
+ }
+ le_softc.next_tmd = 0;
+/* (le_softc.next_tmd == (LETBUF - 1)) ? 0 : le_softc.next_tmd + 1;*/
+ if (tmd->tmd1_bits & LE_T1_ERR) {
+ printf("le: transmit error, error = 0x%x\n", tmd->tmd3);
+ return -1;
+ }
+ if (le_debug) {
+ printf("le: le_put() successful: sent %d\n", len);
+ printf("le: le_put(): tmd1_bits: %x tmd3: %x\n",
+ (unsigned int) tmd->tmd1_bits,
+ (unsigned int) tmd->tmd3);
+ }
+ return len;
+}
+
+
+/*
+ * le_get
+ */
+
+int le_get(desc, pkt, len, timeout)
+ struct iodesc *desc;
+ void *pkt;
+ int len;
+ time_t timeout;
+{
+ time_t t;
+ int cc;
+
+ t = getsecs();
+ cc = 0;
+ while (((getsecs() - t) < timeout) && !cc) {
+ cc = le_poll(desc, pkt, len);
+ }
+ return cc;
+}
+
+
+/*
+ * le_poll
+ * XXX softc
+ */
+
+int le_poll(desc, pkt, len)
+ struct iodesc *desc;
+ void *pkt;
+ int len;
+{
+ struct lereg1 *ler1 = le_softc.sc_r1;
+ struct lereg2 *ler2 = le_softc.sc_r2;
+ unsigned int a;
+ int length;
+ struct lermd *rmd;
+
+
+ ler1->ler1_rap = LE_CSR0;
+ if ((ler1->ler1_rdp & LE_C0_RINT) != 0)
+ ler1->ler1_rdp = LE_C0_RINT;
+ rmd = &ler2->ler2_rmd[le_softc.next_rmd];
+ if (rmd->rmd1_bits & LE_R1_OWN) {
+ return(0);
+ }
+ if (ler1->ler1_rdp & LE_C0_ERR)
+ le_error(desc->io_netif, "le_poll", ler1);
+ if (rmd->rmd1_bits & LE_R1_ERR) {
+ printf("le_poll: rmd status 0x%x\n", rmd->rmd1_bits);
+ length = 0;
+ goto cleanup;
+ }
+ if ((rmd->rmd1_bits & (LE_R1_STP|LE_R1_ENP)) != (LE_R1_STP|LE_R1_ENP))
+ panic("le_poll: chained packet\n");
+
+ length = rmd->rmd3;
+ if (length >= LEMTU) {
+ length = 0;
+ panic("csr0 when bad things happen: %x\n", ler1->ler1_rdp);
+ goto cleanup;
+ }
+ if (!length) goto cleanup;
+ length -= 4;
+ if (length > 0) {
+
+ /*
+ * if buffer is smaller than the packet truncate it.
+ * (is this wise?)
+ */
+ if (length > len)
+ length = len;
+
+ bcopy((void *)&ler2->ler2_rbuf[le_softc.next_rmd], pkt, length);
+ }
+
+ cleanup:
+ a = (u_int)&ler2->ler2_rbuf[le_softc.next_rmd];
+ rmd->rmd0 = a & LE_ADDR_LOW_MASK;
+ rmd->rmd1_hadr = a >> 16;
+ rmd->rmd2 = -LEMTU;
+ le_softc.next_rmd =
+ (le_softc.next_rmd == (LERBUF - 1)) ? 0 : (le_softc.next_rmd + 1);
+ rmd->rmd1_bits = LE_R1_OWN;
+ return length;
+}
diff --git a/sys/arch/mvme68k/stand/libsa/netif.h b/sys/arch/mvme68k/stand/libsa/netif.h
new file mode 100644
index 00000000000..680eed00f63
--- /dev/null
+++ b/sys/arch/mvme68k/stand/libsa/netif.h
@@ -0,0 +1,22 @@
+
+#include "iodesc.h"
+
+struct netif {
+ void *devdata;
+};
+
+ssize_t netif_get __P((struct iodesc *, void *, size_t, time_t));
+ssize_t netif_put __P((struct iodesc *, void *, size_t));
+
+int netif_open __P((void *));
+int netif_close __P((int));
+
+struct iodesc *socktodesc __P((int));
+
+void le_end __P((struct netif *));
+void le_error __P((struct netif *, char *, volatile void *));
+int le_get __P((struct iodesc *, void *, int, time_t));
+void *le_init __P((struct iodesc *));
+int le_poll __P((struct iodesc *, void *, int));
+int le_put __P((struct iodesc *, void *, int));
+void le_reset __P((struct netif *, u_char *));
diff --git a/sys/arch/mvme68k/stand/libsa/panic.c b/sys/arch/mvme68k/stand/libsa/panic.c
new file mode 100644
index 00000000000..41dabf8fbf7
--- /dev/null
+++ b/sys/arch/mvme68k/stand/libsa/panic.c
@@ -0,0 +1,31 @@
+
+#include <stdarg.h>
+#include "stand.h"
+
+extern volatile void abort();
+extern int _estack[];
+
+volatile void
+panic(const char *fmt, ...)
+{
+ va_list ap;
+
+ va_start(ap, fmt);
+ printf(fmt, ap);
+ printf("\n");
+ va_end(ap);
+ stackdump(0);
+ abort();
+}
+
+stackdump(dummy)
+ int dummy;
+{
+ int *ip;
+
+ printf("stackdump:\n");
+ for (ip = &dummy; ip < _estack; ip += 4) {
+ printf("%08x: %08x %08x %08x %08x\n",
+ (int)ip, ip[0], ip[1], ip[2], ip[3]);
+ }
+}
diff --git a/sys/arch/mvme68k/stand/netboot/Makefile b/sys/arch/mvme68k/stand/netboot/Makefile
new file mode 100644
index 00000000000..03fbaa7f787
--- /dev/null
+++ b/sys/arch/mvme68k/stand/netboot/Makefile
@@ -0,0 +1,15 @@
+# $NetBSD: Makefile,v 1.1.1.1 1995/07/25 23:12:24 chuck Exp $
+
+SA_PROG= netboot
+SRCS= boot.c conf.c version.c dev_net.c
+
+DEFS= -DSTANDALONE -DSUN_BOOTPARAMS
+
+all: ${SA_PROG}.bin
+
+.include <bsd.prog.mk>
+
+install: ${SA_PROG}.bin
+ install ${COPY} -o ${LIBOWN} -g ${LIBGRP} -m ${LIBMODE} \
+ ${SA_PROG}.bin ${DESTDIR}${MDEC_DIR}/${SA_PROG}
+
diff --git a/sys/arch/mvme68k/stand/netboot/boot.c b/sys/arch/mvme68k/stand/netboot/boot.c
new file mode 100644
index 00000000000..1c16244e0fe
--- /dev/null
+++ b/sys/arch/mvme68k/stand/netboot/boot.c
@@ -0,0 +1,77 @@
+/* $NetBSD: boot.c,v 1.1.1.1.2.1 1995/10/12 20:38:57 chuck Exp $ */
+
+/*-
+ * Copyright (c) 1982, 1986, 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)boot.c 8.1 (Berkeley) 6/10/93
+ */
+
+#include <sys/param.h>
+#include <sys/reboot.h>
+
+#include "stand.h"
+
+/*
+ * Boot device is derived from ROM provided information.
+ */
+#define LOADADDR 0x8000
+
+extern char *version;
+extern char *cmd_parse();
+char defname[32] = "netbsd";
+char line[80];
+int boothowto;
+
+
+main(cline)
+char *cline;
+{
+ char *cp, *file;
+ int io;
+
+ printf(">> NetBSD netboot [%s]\n", version);
+ file = cmd_parse(cline, &boothowto);
+ if (file == NULL)
+ file = defname;
+
+ for (;;) {
+ if (boothowto & RB_ASKNAME) {
+ printf("boot: ");
+ gets(line);
+ if (line[0])
+ file = line;
+ }
+ exec_mvme(file, LOADADDR, boothowto);
+ printf("boot: %s: %s\n", file, strerror(errno));
+ boothowto |= RB_ASKNAME;
+ }
+}
diff --git a/sys/arch/mvme68k/stand/netboot/conf.c b/sys/arch/mvme68k/stand/netboot/conf.c
new file mode 100644
index 00000000000..a3067798fcb
--- /dev/null
+++ b/sys/arch/mvme68k/stand/netboot/conf.c
@@ -0,0 +1,23 @@
+/* $NetBSD: conf.c,v 1.1.1.1.2.1 1995/10/12 20:38:59 chuck Exp $ */
+
+#include <sys/types.h>
+#include <netinet/in.h>
+
+#include "stand.h"
+#include "nfs.h"
+#include "dev_net.h"
+
+struct fs_ops file_system[] = {
+ { nfs_open, nfs_close, nfs_read, nfs_write, nfs_seek, nfs_stat },
+};
+int nfsys = 1;
+
+struct devsw devsw[] = {
+ { "net", net_strategy, net_open, net_close, net_ioctl },
+};
+int ndevs = 1;
+
+/* XXX */
+int netif_debug;
+int debug;
+int errno;
diff --git a/sys/arch/mvme68k/stand/netboot/dev_net.c b/sys/arch/mvme68k/stand/netboot/dev_net.c
new file mode 100644
index 00000000000..fa6b03de9ce
--- /dev/null
+++ b/sys/arch/mvme68k/stand/netboot/dev_net.c
@@ -0,0 +1,196 @@
+/* $NetBSD: dev_net.c,v 1.2.2.1 1995/10/12 20:39:02 chuck Exp $ */
+
+/*
+ * Copyright (c) 1995 Gordon W. Ross
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ * 4. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Gordon W. Ross
+ *
+ * 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.
+ */
+
+/*
+ * This module implements a "raw device" interface suitable for
+ * use by the stand-alone I/O library NFS code. This interface
+ * does not support any "block" access, and exists only for the
+ * purpose of initializing the network interface, getting boot
+ * parameters, and performing the NFS mount.
+ *
+ * At open time, this does:
+ *
+ * find interface - netif_open()
+ * RARP for IP address - rarp_getipaddress()
+ * RPC/bootparams - callrpc(d, RPC_BOOTPARAMS, ...)
+ * RPC/mountd - nfs_mount(sock, ip, path)
+ *
+ * the root file handle from mountd is saved in a global
+ * for use by the NFS open code (NFS/lookup).
+ */
+
+#include <sys/param.h>
+#include <sys/socket.h>
+#include <net/if.h>
+#include <netinet/in.h>
+#include <netinet/if_ether.h>
+#include <netinet/in_systm.h>
+
+#include "stand.h"
+#include "net.h"
+#include "netif.h"
+#include "bootparam.h"
+
+extern int nfs_root_node[]; /* XXX - get from nfs_mount() */
+
+/*
+ * Various globals needed by the network code:
+ */
+
+/* for arp.c, rarp.c */
+u_char bcea[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
+
+struct in_addr myip; /* my ip address */
+struct in_addr rootip; /* root ip address */
+struct in_addr gateip; /* swap ip address */
+n_long netmask; /* subnet or net mask */
+
+char rootpath[FNAME_SIZE];
+
+int hostnamelen;
+char hostname[FNAME_SIZE];
+
+int domainnamelen;
+char domainname[FNAME_SIZE];
+
+/*
+ * Local things...
+ */
+static int netdev_sock = -1;
+static int open_count;
+
+/*
+ * Called by devopen after it sets f->f_dev to our devsw entry.
+ * This opens the low-level device and sets f->f_devdata.
+ */
+int
+net_open(f, devname)
+ struct open_file *f;
+ char *devname; /* Device part of file name (or NULL). */
+{
+ int error = 0;
+
+ /* On first open, do netif open, mount, etc. */
+ if (open_count == 0) {
+ /* Find network interface. */
+ if ((netdev_sock = netif_open(devname)) < 0)
+ return (error=ENXIO);
+ if ((error = net_mountroot(f, devname)) != 0)
+ return (error);
+ }
+ open_count++;
+ f->f_devdata = nfs_root_node;
+ return (error);
+}
+
+int
+net_close(f)
+ struct open_file *f;
+{
+ /* On last close, do netif close, etc. */
+ if (open_count > 0)
+ if (--open_count == 0)
+ netif_close(netdev_sock);
+ f->f_devdata = NULL;
+}
+
+int
+net_ioctl()
+{
+ return EIO;
+}
+
+int
+net_strategy()
+{
+ return EIO;
+}
+
+int
+net_mountroot(f, devname)
+ struct open_file *f;
+ char *devname; /* Device part of file name (or NULL). */
+{
+ int error;
+
+#ifdef DEBUG
+ printf("net_mountroot: %s\n", devname);
+#endif
+
+ /*
+ * Get info for NFS boot: our IP address, our hostname,
+ * server IP address, and our root path on the server.
+ * There are two ways to do this: The old, Sun way,
+ * and the more modern, BOOTP way. (RFC951, RFC1048)
+ */
+
+#ifdef SUN_BOOTPARAMS
+ /* Get our IP address. (rarp.c) */
+ if (rarp_getipaddress(netdev_sock))
+ return (EIO);
+#else /* BOOTPARAMS */
+ /*
+ * Get boot info using BOOTP. (RFC951, RFC1048)
+ * This also gets the server IP address, gateway,
+ * root path, etc.
+ */
+ bootp(netdev_sock); /* XXX - Error return? */
+#endif /* BOOTPARAMS */
+
+ printf("boot: client addr: %s\n", inet_ntoa(myip));
+
+#ifdef SUN_BOOTPARAMS
+ /* Get our hostname, server IP address, gateway. */
+ if (bp_whoami(netdev_sock))
+ return (EIO);
+#endif /* BOOTPARAMS */
+
+ printf("boot: client name: %s\n", hostname);
+ if (gateip.s_addr) {
+ printf("boot: subnet mask: %s\n", intoa(netmask));
+ printf("boot: net gateway: %s\n", inet_ntoa(gateip));
+ }
+
+#ifdef SUN_BOOTPARAMS
+ /* Get the root pathname. */
+ if (bp_getfile(netdev_sock, "root", &rootip, rootpath))
+ return (EIO);
+#endif /* BOOTPARAMS */
+
+ printf("boot: server addr: %s\n", inet_ntoa(rootip));
+ printf("boot: server path: %s\n", rootpath);
+
+ /* Get the NFS file handle (mount). */
+ error = nfs_mount(netdev_sock, rootip, rootpath);
+
+ return (error);
+}
diff --git a/sys/arch/mvme68k/stand/netboot/dev_net.h b/sys/arch/mvme68k/stand/netboot/dev_net.h
new file mode 100644
index 00000000000..093ba193bfd
--- /dev/null
+++ b/sys/arch/mvme68k/stand/netboot/dev_net.h
@@ -0,0 +1,6 @@
+
+int net_open __P((struct open_file *, ...));
+int net_close __P((struct open_file *));
+int net_ioctl();
+int net_strategy();
+
diff --git a/sys/arch/mvme68k/stand/netboot/version.c b/sys/arch/mvme68k/stand/netboot/version.c
new file mode 100644
index 00000000000..47d99c92cab
--- /dev/null
+++ b/sys/arch/mvme68k/stand/netboot/version.c
@@ -0,0 +1,9 @@
+/* $NetBSD: version.c,v 1.1.1.1 1995/07/25 23:12:26 chuck Exp $ */
+
+/*
+ * NOTE ANY CHANGES YOU MAKE TO THE BOOTBLOCKS HERE.
+ *
+ * 1.1
+ */
+
+char *version = "$Revision: 1.1 $";
diff --git a/sys/arch/mvme68k/stand/sboot/Makefile b/sys/arch/mvme68k/stand/sboot/Makefile
new file mode 100644
index 00000000000..fb80ad4e86f
--- /dev/null
+++ b/sys/arch/mvme68k/stand/sboot/Makefile
@@ -0,0 +1,19 @@
+# $NetBSD: Makefile,v 1.1.1.1 1995/07/25 23:12:28 chuck Exp $
+
+#
+# sboot needs GNU ld because it can generate S-Records
+#
+
+COMPILE.s= $(AS) $(ASFLAGS) -o $*.o
+GNU_LD=/usr/local/bin/ld
+LDFLAGS=-oformat srec -x -N -Ttext 0x4000 -e start
+NOMAN=
+PROG= sboot
+SRCS= start.s clock.c console.c etherfun.c le_poll.c libc_sa.c \
+ oc_cksum.s sboot.c
+
+${PROG}: ${OBJS}
+ ${GNU_LD} ${LDFLAGS} -o ${.TARGET} ${OBJS}
+
+.include <bsd.prog.mk>
+
diff --git a/sys/arch/mvme68k/stand/sboot/clock.c b/sys/arch/mvme68k/stand/sboot/clock.c
new file mode 100644
index 00000000000..f6e344b7b9d
--- /dev/null
+++ b/sys/arch/mvme68k/stand/sboot/clock.c
@@ -0,0 +1,117 @@
+/* $NetBSD: clock.c,v 1.1.1.1 1995/07/25 23:12:28 chuck Exp $ */
+
+/*
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ * Copyright (c) 1994 Gordon W. Ross
+ * Copyright (c) 1993 Adam Glass
+ *
+ * This software was developed by the Computer Systems Engineering group
+ * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
+ * contributed to Berkeley.
+ *
+ * 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, Lawrence Berkeley Laboratory.
+ *
+ * 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.
+ *
+ * @(#)clock.c 8.1 (Berkeley) 6/11/93
+ */
+
+/*
+ * Clock driver.
+ */
+
+#include "sboot.h"
+#include "clockreg.h"
+static struct clockreg *clockreg = (struct clockreg *) CLOCK_ADDR;
+
+/*
+ * BCD to decimal and decimal to BCD.
+ */
+#define FROMBCD(x) (((x) >> 4) * 10 + ((x) & 0xf))
+#define TOBCD(x) (((x) / 10 * 16) + ((x) % 10))
+
+#define SECDAY (24 * 60 * 60)
+#define SECYR (SECDAY * 365)
+#define LEAPYEAR(y) (((y) & 3) == 0)
+
+/*
+ * This code is defunct after 2068.
+ * Will Unix still be here then??
+ */
+const short dayyr[12] =
+ { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 };
+
+static u_long chiptotime(sec, min, hour, day, mon, year)
+ register int sec, min, hour, day, mon, year;
+{
+ register int days, yr;
+
+ sec = FROMBCD(sec);
+ min = FROMBCD(min);
+ hour = FROMBCD(hour);
+ day = FROMBCD(day);
+ mon = FROMBCD(mon);
+ year = FROMBCD(year) + YEAR0;
+ if (year < 70) year = 70;
+
+ /* simple sanity checks */
+ if (year < 70 || mon < 1 || mon > 12 || day < 1 || day > 31)
+ return (0);
+ days = 0;
+ for (yr = 70; yr < year; yr++)
+ days += LEAPYEAR(yr) ? 366 : 365;
+ days += dayyr[mon - 1] + day - 1;
+ if (LEAPYEAR(yr) && mon > 2)
+ days++;
+ /* now have days since Jan 1, 1970; the rest is easy... */
+ return (days * SECDAY + hour * 3600 + min * 60 + sec);
+}
+
+/*
+ * Set up the system's time, given a `reasonable' time value.
+ */
+u_long time()
+{
+ register struct clockreg *cl = clockreg;
+ int sec, min, hour, day, mon, year;
+
+ cl->cl_csr |= CLK_READ; /* enable read (stop time) */
+ sec = cl->cl_sec;
+ min = cl->cl_min;
+ hour = cl->cl_hour;
+ day = cl->cl_mday;
+ mon = cl->cl_month;
+ year = cl->cl_year;
+ cl->cl_csr &= ~CLK_READ; /* time wears on */
+ return(chiptotime(sec, min, hour, day, mon, year));
+}
diff --git a/sys/arch/mvme68k/stand/sboot/clockreg.h b/sys/arch/mvme68k/stand/sboot/clockreg.h
new file mode 100644
index 00000000000..dbbf313f3d1
--- /dev/null
+++ b/sys/arch/mvme68k/stand/sboot/clockreg.h
@@ -0,0 +1,69 @@
+/* $NetBSD: clockreg.h,v 1.1.1.1 1995/07/25 23:12:29 chuck Exp $ */
+
+/*
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This software was developed by the Computer Systems Engineering group
+ * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
+ * contributed to Berkeley.
+ *
+ * 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, Lawrence Berkeley Laboratory.
+ *
+ * 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.
+ *
+ * @(#)clockreg.h 8.1 (Berkeley) 6/11/93
+ */
+
+/*
+ * Mostek MK48T02 clock.
+ */
+struct clockreg {
+ volatile u_char cl_csr; /* control register */
+ volatile u_char cl_sec; /* seconds (0..59; BCD) */
+ volatile u_char cl_min; /* minutes (0..59; BCD) */
+ volatile u_char cl_hour; /* hour (0..23; BCD) */
+ volatile u_char cl_wday; /* weekday (1..7) */
+ volatile u_char cl_mday; /* day in month (1..31; BCD) */
+ volatile u_char cl_month; /* month (1..12; BCD) */
+ volatile u_char cl_year; /* year (0..99; BCD) */
+};
+
+/* bits in cl_csr */
+#define CLK_WRITE 0x80 /* want to write */
+#define CLK_READ 0x40 /* want to read (freeze clock) */
+
+/*
+ * Sun chose the year `68' as their base count, so that
+ * cl_year==0 means 1968.
+ */
+#define YEAR0 68
diff --git a/sys/arch/mvme68k/stand/sboot/console.c b/sys/arch/mvme68k/stand/sboot/console.c
new file mode 100644
index 00000000000..19f01dcada8
--- /dev/null
+++ b/sys/arch/mvme68k/stand/sboot/console.c
@@ -0,0 +1,139 @@
+/*
+ *
+ * Copyright (c) 1995 Charles D. Cranor and Seth Widoff
+ * 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 Charles D. Cranor
+ * and Seth Widoff.
+ * 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.
+ */
+/*
+ * console i/o
+ */
+
+#include "sboot.h"
+
+/*
+ * hardware
+ */
+
+struct zs_hw {
+ volatile u_char ctl;
+ volatile u_char data;
+};
+
+struct zs_hw *zs = (struct zs_hw *)CONS_ZS_ADDR;
+
+/*
+ * consinit: init console
+ */
+
+consinit()
+
+{
+ register int mark = time();
+ register int rr1;
+ while (1) {
+ if (time() > mark + 5) break;
+ zs->ctl = 1; rr1 = zs->ctl;
+ zs->ctl = 0;
+ if ((rr1 & 0x1) == 1 && (zs->ctl & 0x4) == 4) break; /* zs_drain! */
+ }
+ zs->ctl = 9; zs->ctl = 0x00; /* clear interrupt */
+ zs->ctl = 4; zs->ctl = 0x44; /* 16x clk, 1 stop bit */
+ zs->ctl = 5; zs->ctl = 0xea; /* DTR on, 8 bit xmit, xmit on, RTS on */
+ zs->ctl = 3; zs->ctl = 0xc1; /* 8 bit recv, auto cd_cts, recv on */
+ zs->ctl = 1; zs->ctl = 0x00; /* no intrs */
+ zs->ctl = 2; zs->ctl = 0x00; /* no vector */
+ zs->ctl = 10; zs->ctl = 0x00; /* */
+ zs->ctl = 11; zs->ctl = 0x50; /* clocking options */
+ zs->ctl = 12; zs->ctl = 0x0e; /* 9600 baud, part 1 */
+ zs->ctl = 13; zs->ctl = 0x00; /* 9600 baud, part 2 */
+ zs->ctl = 14; zs->ctl = 0x03; /* more clocking options */
+ zs->ctl = 15; zs->ctl = 0x00; /* clear intrs */
+}
+
+/*
+ * putchar: put char to console
+ */
+
+void putchar(char c)
+{
+ if (c == '\n') putchar('\r'); /* avoid the need for \r\n in printf */
+ zs->ctl = 0;
+ while ((zs->ctl & 0x04) == 0) {
+ zs->ctl = 0;
+ }
+ zs->ctl = 8;
+ zs->ctl = c;
+}
+
+/*
+ * cngetc: get 1 char from console
+ */
+
+char cngetc ()
+{
+ zs->ctl = 0;
+ while ((zs->ctl & 0x1) == 0) {
+ zs->ctl = 0;
+ }
+ zs->ctl = 8;
+ return zs->ctl;
+}
+
+/*
+ * puts: put string to console
+ */
+
+void puts ( char * str )
+{
+ while ( *str != '\0' ) {
+ putchar(*str);
+ str++;
+ }
+}
+
+/*
+ * ngets: get string from console
+ */
+
+void ngets ( char * str, int size )
+{
+ int i = 0;
+ while ( (i < size - 1) && (str[i] = cngetc()) != '\r') {
+ if ( str[i] == '\b' || str[i] == 0x7F ) {
+ if ( i == 0) continue;
+ i--;
+ puts("\b \b");
+ continue;
+ }
+ putchar(str[i]);
+ i++;
+ }
+ puts("\n");
+ str[i] = '\0';
+}
+
diff --git a/sys/arch/mvme68k/stand/sboot/etherfun.c b/sys/arch/mvme68k/stand/sboot/etherfun.c
new file mode 100644
index 00000000000..7c107b00e8a
--- /dev/null
+++ b/sys/arch/mvme68k/stand/sboot/etherfun.c
@@ -0,0 +1,213 @@
+/*
+ *
+ * Copyright (c) 1995 Charles D. Cranor and Seth Widoff
+ * 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 Charles D. Cranor
+ * and Seth Widoff.
+ * 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.
+ */
+/* etherfun.c */
+
+#include "sboot.h"
+#include "etherfun.h"
+
+/* Construct and send a rev arp packet */
+void
+do_rev_arp ()
+{
+ int i;
+
+ for ( i = 0; i < 6; i++ ) {
+ eh->ether_dhost[i] = 0xff;
+ }
+ bcopy(myea, eh->ether_shost, 6);
+ eh->ether_type = ETYPE_RARP;
+
+ rarp->ar_hrd = 1; /* hardware type is 1 */
+ rarp->ar_pro = PTYPE_IP;
+ rarp->ar_hln = 6; /* length of hardware address is 6 bytes */
+ rarp->ar_pln = 4; /* length of ip address is 4 byte */
+ rarp->ar_op = OPCODE_RARP;
+ bcopy(myea, rarp->arp_sha, sizeof(myea));
+ bcopy(myea, rarp->arp_tha, sizeof(myea));
+ for ( i = 0; i < 4; i++ ) {
+ rarp->arp_spa[i] = rarp->arp_tpa[i] = 0x00;
+ }
+
+ le_put(buf, 76);
+}
+
+/* Recieve and disassemble the rev_arp reply */
+
+int
+get_rev_arp ()
+{
+ le_get(buf, sizeof(buf), 6);
+ if ( eh->ether_type == ETYPE_RARP && rarp->ar_op == OPCODE_REPLY ) {
+ bcopy(rarp->arp_tpa, myip, sizeof(rarp->arp_tpa));
+ bcopy(rarp->arp_spa, servip, sizeof(rarp->arp_spa));
+ bcopy(rarp->arp_sha, servea, sizeof(rarp->arp_sha));
+ return 1;
+ }
+ return 0;
+}
+
+/* Try to get a reply to a rev arp request */
+
+int
+rev_arp ()
+{
+ int tries = 0;
+ while ( tries < 5 ) {
+ do_rev_arp();
+ if ( get_rev_arp() ) {
+ return 1;
+ }
+ tries++;
+ }
+ return 0;
+}
+
+/* Send a tftp read request or acknowledgement
+ mesgtype 0 is a read request, 1 is an aknowledgement */
+
+void
+do_send_tftp ( int mesgtype )
+{
+ u_long res, iptmp, lcv;
+ char *tot;
+
+ if ( mesgtype == 0 ) {
+ tot = tftp_r + (sizeof(MSG)-1);
+ myport = (u_short)time();
+ if (myport < 1000) myport += 1000;
+ servport = FTP_PORT; /* to start */
+ } else {
+ tot = (char *)tftp_a + 4;
+ }
+
+ bcopy (servea, eh->ether_dhost, sizeof(servea));
+ bcopy (myea, eh->ether_shost, sizeof(myea));
+ eh->ether_type = ETYPE_IP;
+
+ iph->ip_v = IP_VERSION;
+ iph->ip_hl = IP_HLEN;
+ iph->ip_tos = 0; /* type of service is 0 */
+ iph->ip_id = 0; /* id field is 0 */
+ iph->ip_off = IP_DF;
+ iph->ip_ttl = 3; /* time to live is 3 seconds/hops */
+ iph->ip_p = IPP_UDP;
+ bcopy(myip, iph->ip_src, sizeof(myip));
+ bcopy(servip, iph->ip_dst, sizeof(servip));
+ iph->ip_sum = 0;
+ iph->ip_len = tot - (char *)iph;
+ res = oc_cksum(iph, sizeof(struct ip), 0);
+ iph->ip_sum = 0xffff & ~res;
+ udph->uh_sport = myport;
+ udph->uh_dport = servport;
+ udph->uh_sum = 0;
+
+ if ( mesgtype ) {
+ tftp_a->op_code = FTPOP_ACKN;
+ tftp_a->block = (u_short)(mesgtype);
+ } else {
+ bcopy (myip, &iptmp, sizeof(iptmp));
+ bcopy(MSG, tftp_r, (sizeof(MSG)-1));
+ for (lcv = 9; lcv >= 2; lcv--) {
+ tftp_r[lcv] = "0123456789ABCDEF"[iptmp & 0xF];
+
+ iptmp = iptmp >> 4;
+ }
+ }
+
+ udph->uh_ulen = tot - (char *)udph;
+
+ le_put( buf, tot - buf);
+}
+
+/* Attempt to tftp a file and read it into memory */
+
+int
+do_get_file ()
+{
+ int fail = 0, oldlen;
+ char *loadat = (char *)LOAD_ADDR;
+ last_ack = 0;
+
+ do_send_tftp( READ );
+ while (1) {
+ if ( le_get(buf, sizeof(buf), 5) == 0) { /* timeout occured */
+ if ( last_ack ) {
+ do_send_tftp( last_ack );
+ } else {
+ do_send_tftp( READ );
+ }
+ fail++;
+ if ( fail > 5 ) {
+ printf("\n");
+ return 1;
+ }
+ } else {
+ printf("%x \r", tftp->info.block*512);
+ if ((eh->ether_type != ETYPE_IP) || (iph->ip_p != IPP_UDP)) {
+ fail++;
+ continue;
+ }
+ if (servport == FTP_PORT) servport = udph->uh_sport;
+ if (tftp->info.op_code == FTPOP_ERR) {
+ printf("TFTP: Download error %d: %s\n",
+ tftp->info.block, tftp->data);
+ return 1;
+ }
+ if (tftp->info.block != last_ack + 1) { /* we recieved the wrong block */
+ if (tftp->info.block < last_ack +1) {
+ do_send_tftp(tftp->info.block); /* ackn whatever we recieved */
+ } else {
+ do_send_tftp( last_ack ); /* ackn the last confirmed block */
+ }
+ fail++;
+ } else { /* we got the right block */
+ fail = 0;
+ last_ack++;
+ oldlen = udph->uh_ulen;
+ do_send_tftp( last_ack );
+ /*printf("bcopy %x %x %d\n", &tftp->data, loadat, oldlen - 12);*/
+ bcopy(&tftp->data, loadat, oldlen - 12);
+ loadat += oldlen - 12;
+ if (oldlen < (8 + 4 + 512)) {
+ printf("\n");
+ return 0;
+ }
+ }
+ }
+ }
+ printf("\n");
+ return 0;
+}
+
+
+
+
diff --git a/sys/arch/mvme68k/stand/sboot/etherfun.h b/sys/arch/mvme68k/stand/sboot/etherfun.h
new file mode 100644
index 00000000000..2b6a14d69a5
--- /dev/null
+++ b/sys/arch/mvme68k/stand/sboot/etherfun.h
@@ -0,0 +1,124 @@
+/*
+ *
+ * Copyright (c) 1995 Charles D. Cranor and Seth Widoff
+ * 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 Charles D. Cranor
+ * and Seth Widoff.
+ * 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.
+ */
+/* etherfun.h */
+
+/* constants */
+/* ether header */
+#define ETYPE_RARP 0x8035 /* ethertype is RARP */
+#define ETYPE_IP 0x800 /* ethertype is IP */
+
+/* rev arp */
+#define PTYPE_IP 0x800 /* Protocol type is IP */
+#define OPCODE_RARP 3 /* Optype is REVARP request */
+#define OPCODE_REPLY 4 /* Optype is REVARP reply */
+
+/* ip header */
+#define IPP_UDP 17 /* IP Protocol is UDP */
+#define IP_VERSION 4 /* IP version number */
+#define IP_HLEN 5 /* IP header length is a fixed 50 bytes */
+#define N 1536
+
+/* tftp header */
+#define FTPOP_ACKN 4 /* Opcode is acknowledge */
+#define FTPOP_ERR 5 /* Opcode is Error */
+#define FTP_PORT 69 /* Standard TFTP port number */
+#define MSG "\0\1xxxxxxxx.147\0octet\0" /* implicit NULL */
+
+/* data structures */
+
+struct ether_header {
+ u_char ether_dhost[6];
+ u_char ether_shost[6];
+ u_short ether_type;
+};
+
+struct ether_arp {
+ u_short ar_hrd; /* format of hardware address */
+ u_short ar_pro; /* format of protocol address */
+ u_char ar_hln; /* length of hardware address */
+ u_char ar_pln; /* length of protocol address */
+ u_short ar_op;
+ u_char arp_sha[6]; /* sender hardware address */
+ u_char arp_spa[4]; /* sender protocol address */
+ u_char arp_tha[6]; /* target hardware address */
+ u_char arp_tpa[4]; /* target protocol address */
+};
+
+struct ip {
+ u_char ip_v:4, /* version */
+ ip_hl:4; /* header length */
+ u_char ip_tos; /* type of service */
+ short ip_len; /* total length */
+ u_short ip_id; /* identification */
+ short ip_off; /* fragment offset field */
+#define IP_DF 0x4000 /* dont fragment flag */
+#define IP_MF 0x2000 /* more fragments flag */
+#define IP_OFFMASK 0x1fff /* mask for fragmenting bits */
+ u_char ip_ttl; /* time to live */
+ u_char ip_p; /* protocol */
+ u_short ip_sum; /* checksum */
+ u_char ip_src[4];
+ u_char ip_dst[4]; /* source and dest address */
+};
+
+struct udp {
+ u_short uh_sport;
+ u_short uh_dport;
+ short uh_ulen;
+ u_short uh_sum;
+};
+
+struct tftph {
+ u_short op_code;
+ u_short block;
+};
+
+struct tftphr {
+ struct tftph info;
+ char data[1];
+};
+
+/* globals */
+int last_ack;
+char buf[N];
+struct ether_header *eh = (struct ether_header *)buf;
+struct ether_arp *rarp =
+ (struct ether_arp *)(buf + sizeof(struct ether_header));
+struct ip *iph = (struct ip *)(buf + sizeof(struct ether_header));
+struct udp *udph = (struct udp *)(buf + sizeof(struct ether_header) +
+ sizeof(struct ip));
+char *tftp_r = buf + sizeof(struct ether_header) + sizeof(struct ip) +
+ sizeof(struct udp);
+struct tftph *tftp_a = (struct tftph *)(buf + sizeof(struct ether_header) +
+ sizeof(struct ip) + sizeof(struct udp));
+struct tftphr *tftp = (struct tftphr *)(buf + sizeof(struct ether_header) +
+ sizeof(struct ip) + sizeof(struct udp));
diff --git a/sys/arch/mvme68k/stand/sboot/if_lereg.h b/sys/arch/mvme68k/stand/sboot/if_lereg.h
new file mode 100644
index 00000000000..bae9a85fbd5
--- /dev/null
+++ b/sys/arch/mvme68k/stand/sboot/if_lereg.h
@@ -0,0 +1,176 @@
+/* $NetBSD: if_lereg.h,v 1.1.1.1 1995/07/25 23:12:31 chuck Exp $ */
+
+/*-
+ * Copyright (c) 1982, 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)if_lereg.h 8.2 (Berkeley) 10/30/93
+ */
+
+#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)
+
+/* Local Area Network Controller for Ethernet (LANCE) registers */
+struct lereg1 {
+ volatile u_short ler1_rdp; /* register data port */
+ volatile u_short ler1_rap; /* register address port */
+};
+
+/* register addresses */
+#define LE_CSR0 0 /* Control and status register */
+#define LE_CSR1 1 /* low address of init block */
+#define LE_CSR2 2 /* high address of init block */
+#define LE_CSR3 3 /* Bus master and control */
+
+/* Control and status register 0 (csr0) */
+#define LE_C0_ERR 0x8000 /* error summary */
+#define LE_C0_BABL 0x4000 /* transmitter timeout error */
+#define LE_C0_CERR 0x2000 /* collision */
+#define LE_C0_MISS 0x1000 /* missed a packet */
+#define LE_C0_MERR 0x0800 /* memory error */
+#define LE_C0_RINT 0x0400 /* receiver interrupt */
+#define LE_C0_TINT 0x0200 /* transmitter interrupt */
+#define LE_C0_IDON 0x0100 /* initalization done */
+#define LE_C0_INTR 0x0080 /* interrupt condition */
+#define LE_C0_INEA 0x0040 /* interrupt enable */
+#define LE_C0_RXON 0x0020 /* receiver on */
+#define LE_C0_TXON 0x0010 /* transmitter on */
+#define LE_C0_TDMD 0x0008 /* transmit demand */
+#define LE_C0_STOP 0x0004 /* disable all external activity */
+#define LE_C0_STRT 0x0002 /* enable external activity */
+#define LE_C0_INIT 0x0001 /* begin initalization */
+
+#define LE_C0_BITS \
+ "\20\20ERR\17BABL\16CERR\15MISS\14MERR\13RINT\
+\12TINT\11IDON\10INTR\07INEA\06RXON\05TXON\04TDMD\03STOP\02STRT\01INIT"
+
+/* Control and status register 3 (csr3) */
+#define LE_C3_BSWP 0x4 /* byte swap */
+#define LE_C3_ACON 0x2 /* ALE control, eh? */
+#define LE_C3_BCON 0x1 /* byte control */
+/*
+ * Current size is 13,758 bytes with 8 x 1518 receive buffers and
+ * 1 x 1518 transmit buffer.
+ */
+struct lereg2 {
+ /* initialization block */
+ volatile u_short ler2_mode; /* mode */
+ volatile u_char ler2_padr[6]; /* physical address */
+#ifdef new_code
+ volatile u_short ler2_ladrf[4]; /* logical address filter */
+#else
+ volatile u_long ler2_ladrf0; /* logical address filter */
+ volatile u_long ler2_ladrf1; /* logical address filter */
+#endif
+ volatile u_short ler2_rdra; /* receive descriptor addr */
+ volatile u_short ler2_rlen; /* rda high and ring size */
+ volatile u_short ler2_tdra; /* transmit descriptor addr */
+ volatile u_short ler2_tlen; /* tda high and ring size */
+ /* receive message descriptors. bits/hadr are byte order dependent. */
+ struct lermd {
+ volatile u_short rmd0; /* low address of packet */
+ volatile u_char rmd1_bits; /* descriptor bits */
+ volatile u_char rmd1_hadr; /* high address of packet */
+ volatile short rmd2; /* buffer byte count */
+ volatile u_short rmd3; /* message byte count */
+ } ler2_rmd[LERBUF];
+ /* transmit message descriptors */
+ struct letmd {
+ volatile u_short tmd0; /* low address of packet */
+ volatile u_char tmd1_bits; /* descriptor bits */
+ volatile u_char tmd1_hadr; /* high address of packet */
+ volatile short tmd2; /* buffer byte count */
+ volatile u_short tmd3; /* transmit error bits */
+ } ler2_tmd[LETBUF];
+ volatile char ler2_rbuf[LERBUF][LEMTU];
+ volatile char ler2_tbuf[LETBUF][LEMTU];
+};
+
+/* Initialzation block (mode) */
+#define LE_MODE_PROM 0x8000 /* promiscuous mode */
+/* 0x7f80 reserved, must be zero */
+#define LE_MODE_INTL 0x0040 /* internal loopback */
+#define LE_MODE_DRTY 0x0020 /* disable retry */
+#define LE_MODE_COLL 0x0010 /* force a collision */
+#define LE_MODE_DTCR 0x0008 /* disable transmit CRC */
+#define LE_MODE_LOOP 0x0004 /* loopback mode */
+#define LE_MODE_DTX 0x0002 /* disable transmitter */
+#define LE_MODE_DRX 0x0001 /* disable receiver */
+#define LE_MODE_NORMAL 0 /* none of the above */
+
+
+/* Receive message descriptor 1 (rmd1_bits) */
+#define LE_R1_OWN 0x80 /* LANCE owns the packet */
+#define LE_R1_ERR 0x40 /* error summary */
+#define LE_R1_FRAM 0x20 /* framing error */
+#define LE_R1_OFLO 0x10 /* overflow error */
+#define LE_R1_CRC 0x08 /* CRC error */
+#define LE_R1_BUFF 0x04 /* buffer error */
+#define LE_R1_STP 0x02 /* start of packet */
+#define LE_R1_ENP 0x01 /* end of packet */
+
+#define LE_R1_BITS \
+ "\20\10OWN\7ERR\6FRAM\5OFLO\4CRC\3BUFF\2STP\1ENP"
+
+/* Transmit message descriptor 1 (tmd1_bits) */
+#define LE_T1_OWN 0x80 /* LANCE owns the packet */
+#define LE_T1_ERR 0x40 /* error summary */
+#define LE_T1_MORE 0x10 /* multiple collisions */
+#define LE_T1_ONE 0x08 /* single collision */
+#define LE_T1_DEF 0x04 /* defferred transmit */
+#define LE_T1_STP 0x02 /* start of packet */
+#define LE_T1_ENP 0x01 /* end of packet */
+
+#define LE_T1_BITS \
+ "\20\10OWN\7ERR\6RES\5MORE\4ONE\3DEF\2STP\1ENP"
+
+/* Transmit message descriptor 3 (tmd3) */
+#define LE_T3_BUFF 0x8000 /* buffer error */
+#define LE_T3_UFLO 0x4000 /* underflow error */
+#define LE_T3_LCOL 0x1000 /* late collision */
+#define LE_T3_LCAR 0x0800 /* loss of carrier */
+#define LE_T3_RTRY 0x0400 /* retry error */
+#define LE_T3_TDR_MASK 0x03ff /* time domain reflectometry counter */
+
+#define LE_XMD2_ONES 0xf000
+
+#define LE_T3_BITS \
+ "\20\20BUFF\17UFLO\16RES\15LCOL\14LCAR\13RTRY"
+
+
+#define LE_ADDR_LOW_MASK (0xffff)
+
diff --git a/sys/arch/mvme68k/stand/sboot/le_poll.c b/sys/arch/mvme68k/stand/sboot/le_poll.c
new file mode 100644
index 00000000000..a958b746a36
--- /dev/null
+++ b/sys/arch/mvme68k/stand/sboot/le_poll.c
@@ -0,0 +1,320 @@
+/* $NetBSD: le_poll.c,v 1.1.1.1 1995/07/25 23:12:31 chuck Exp $ */
+
+/*
+ * Copyright (c) 1993 Adam Glass
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Adam Glass.
+ * 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 Adam Glass ``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.
+ */
+
+#include "sboot.h"
+#include "if_lereg.h"
+
+struct {
+ struct lereg1 *sc_r1; /* LANCE registers */
+ struct lereg2 *sc_r2; /* RAM */
+ int next_rmd;
+ int next_tmd;
+} le_softc;
+
+void le_error(str, ler1)
+ char *str;
+ struct lereg1 *ler1;
+{
+ /* ler1->ler1_rap = LE_CSRO done in caller */
+ if (ler1->ler1_rdp & LE_C0_BABL) {
+ printf("le0: been babbling, found by '%s'\n", str);
+ callrom();
+ }
+ if (ler1->ler1_rdp & LE_C0_CERR) {
+ ler1->ler1_rdp = LE_C0_CERR;
+ }
+ if (ler1->ler1_rdp & LE_C0_MISS) {
+ ler1->ler1_rdp = LE_C0_MISS;
+ }
+ if (ler1->ler1_rdp & LE_C0_MERR) {
+ printf("le0: memory error in '%s'\n", str);
+ callrom();
+ }
+
+}
+
+void le_reset(myea)
+ u_char *myea;
+{
+ struct lereg1 *ler1 = le_softc.sc_r1;
+ struct lereg2 *ler2 = le_softc.sc_r2;
+ unsigned int a;
+ int timo = 100000, stat, i;
+
+ ler1->ler1_rap = LE_CSR0;
+ ler1->ler1_rdp = LE_C0_STOP; /* do nothing until we are finished */
+
+ bzero(ler2, sizeof(*ler2));
+
+ ler2->ler2_mode = LE_MODE_NORMAL;
+ ler2->ler2_padr[0] = myea[1];
+ ler2->ler2_padr[1] = myea[0];
+ ler2->ler2_padr[2] = myea[3];
+ ler2->ler2_padr[3] = myea[2];
+ ler2->ler2_padr[4] = myea[5];
+ ler2->ler2_padr[5] = myea[4];
+
+
+ ler2->ler2_ladrf0 = 0;
+ ler2->ler2_ladrf1 = 0;
+
+ a = (u_int)ler2->ler2_rmd;
+ ler2->ler2_rlen = LE_RLEN | (a >> 16);
+ ler2->ler2_rdra = a & LE_ADDR_LOW_MASK;
+
+ a = (u_int)ler2->ler2_tmd;
+ ler2->ler2_tlen = LE_TLEN | (a >> 16);
+ ler2->ler2_tdra = a & LE_ADDR_LOW_MASK;
+
+ ler1->ler1_rap = LE_CSR1;
+ a = (u_int)ler2;
+ ler1->ler1_rdp = a & LE_ADDR_LOW_MASK;
+ ler1->ler1_rap = LE_CSR2;
+ ler1->ler1_rdp = a >> 16;
+
+ for (i = 0; i < LERBUF; i++) {
+ a = (u_int)&ler2->ler2_rbuf[i];
+ ler2->ler2_rmd[i].rmd0 = a & LE_ADDR_LOW_MASK;
+ ler2->ler2_rmd[i].rmd1_bits = LE_R1_OWN;
+ ler2->ler2_rmd[i].rmd1_hadr = a >> 16;
+ ler2->ler2_rmd[i].rmd2 = -LEMTU;
+ ler2->ler2_rmd[i].rmd3 = 0;
+ }
+ for (i = 0; i < LETBUF; i++) {
+ a = (u_int)&ler2->ler2_tbuf[i];
+ ler2->ler2_tmd[i].tmd0 = a & LE_ADDR_LOW_MASK;
+ ler2->ler2_tmd[i].tmd1_bits = 0;
+ ler2->ler2_tmd[i].tmd1_hadr = a >> 16;
+ ler2->ler2_tmd[i].tmd2 = 0;
+ ler2->ler2_tmd[i].tmd3 = 0;
+ }
+
+ ler1->ler1_rap = LE_CSR3;
+ ler1->ler1_rdp = LE_C3_BSWP;
+
+ ler1->ler1_rap = LE_CSR0;
+ ler1->ler1_rdp = LE_C0_INIT;
+ do {
+ if (--timo == 0) {
+ printf("le0: init timeout, stat = 0x%x\n", stat);
+ break;
+ }
+ stat = ler1->ler1_rdp;
+ } while ((stat & LE_C0_IDON) == 0);
+
+ ler1->ler1_rdp = LE_C0_IDON;
+ le_softc.next_rmd = 0;
+ le_softc.next_tmd = 0;
+ ler1->ler1_rap = LE_CSR0;
+ ler1->ler1_rdp = LE_C0_STRT;
+}
+
+int le_poll(pkt, len)
+ void *pkt;
+ int len;
+{
+ struct lereg1 *ler1 = le_softc.sc_r1;
+ struct lereg2 *ler2 = le_softc.sc_r2;
+ unsigned int a;
+ int length;
+ struct lermd *rmd;
+
+ ler1->ler1_rap = LE_CSR0;
+ if ((ler1->ler1_rdp & LE_C0_RINT) != 0)
+ ler1->ler1_rdp = LE_C0_RINT;
+ rmd = &ler2->ler2_rmd[le_softc.next_rmd];
+ if (rmd->rmd1_bits & LE_R1_OWN) {
+ return(0);
+ }
+ if (ler1->ler1_rdp & LE_C0_ERR)
+ le_error("le_poll", ler1);
+ if (rmd->rmd1_bits & LE_R1_ERR) {
+ printf("le0_poll: rmd status 0x%x\n", rmd->rmd1_bits);
+ length = 0;
+ goto cleanup;
+ }
+ if ((rmd->rmd1_bits & (LE_R1_STP|LE_R1_ENP)) != (LE_R1_STP|LE_R1_ENP)) {
+ printf("le_poll: chained packet\n");
+ callrom();
+ }
+
+ length = rmd->rmd3;
+ if (length >= LEMTU) {
+ length = 0;
+ printf("csr0 when bad things happen: %x\n", ler1->ler1_rdp);
+ callrom();
+ goto cleanup;
+ }
+ if (!length) goto cleanup;
+ length -= 4;
+ if (length > 0)
+ bcopy((char *)&ler2->ler2_rbuf[le_softc.next_rmd], pkt, length);
+
+ cleanup:
+ a = (u_int)&ler2->ler2_rbuf[le_softc.next_rmd];
+ rmd->rmd0 = a & LE_ADDR_LOW_MASK;
+ rmd->rmd1_hadr = a >> 16;
+ rmd->rmd2 = -LEMTU;
+ le_softc.next_rmd =
+ (le_softc.next_rmd == (LERBUF - 1)) ? 0 : (le_softc.next_rmd + 1);
+ rmd->rmd1_bits = LE_R1_OWN;
+ return length;
+}
+
+int le_put(pkt, len)
+ u_char *pkt;
+ size_t len;
+{
+ struct lereg1 *ler1 = le_softc.sc_r1;
+ struct lereg2 *ler2 = le_softc.sc_r2;
+ struct letmd *tmd;
+ int timo = 100000, stat, i;
+ unsigned int a;
+
+ ler1->ler1_rap = LE_CSR0;
+ if (ler1->ler1_rdp & LE_C0_ERR)
+ le_error("le_put(way before xmit)", ler1);
+ tmd = &ler2->ler2_tmd[le_softc.next_tmd];
+ while(tmd->tmd1_bits & LE_T1_OWN) {
+ printf("le0: output buffer busy\n");
+ }
+ bcopy(pkt, (char *)ler2->ler2_tbuf[le_softc.next_tmd], len);
+ if (len < 64)
+ tmd->tmd2 = -64;
+ else
+ tmd->tmd2 = -len;
+ tmd->tmd3 = 0;
+ if (ler1->ler1_rdp & LE_C0_ERR)
+ le_error("le_put(before xmit)", ler1);
+ tmd->tmd1_bits = LE_T1_STP | LE_T1_ENP | LE_T1_OWN;
+ a = (u_int)&ler2->ler2_tbuf[le_softc.next_tmd];
+ tmd->tmd0 = a & LE_ADDR_LOW_MASK;
+ tmd->tmd1_hadr = a >> 16;
+ ler1->ler1_rdp = LE_C0_TDMD;
+ if (ler1->ler1_rdp & LE_C0_ERR)
+ le_error("le_put(after xmit)", ler1);
+ do {
+ if (--timo == 0) {
+ printf("le0: transmit timeout, stat = 0x%x\n",
+ stat);
+ if (ler1->ler1_rdp & LE_C0_ERR)
+ le_error("le_put(timeout)", ler1);
+ break;
+ }
+ stat = ler1->ler1_rdp;
+ } while ((stat & LE_C0_TINT) == 0);
+ ler1->ler1_rdp = LE_C0_TINT;
+ if (ler1->ler1_rdp & LE_C0_ERR) {
+ if ((ler1->ler1_rdp & (LE_C0_BABL|LE_C0_CERR|LE_C0_MISS|LE_C0_MERR)) !=
+ LE_C0_CERR)
+ printf("le_put: xmit error, buf %d\n", le_softc.next_tmd);
+ le_error("le_put(xmit error)", ler1);
+ }
+ le_softc.next_tmd = 0;
+/* (le_softc.next_tmd == (LETBUF - 1)) ? 0 : le_softc.next_tmd + 1;*/
+ if (tmd->tmd1_bits & LE_T1_ERR) {
+ printf("le0: transmit error, error = 0x%x\n",
+ tmd->tmd3);
+ return -1;
+ }
+ return len;
+}
+
+int le_get(pkt, len, timeout)
+ u_char *pkt;
+ size_t len;
+ u_long timeout;
+{
+ int cc;
+ int now, then;
+ int stopat = time() + timeout;
+ then = 0;
+
+ cc = 0;
+ while ((now = time()) < stopat && !cc) {
+ cc = le_poll(pkt, len);
+ if (then != now) {
+#ifdef LE_DEBUG
+ printf("%d \r", stopat - now);
+#endif
+ then = now;
+ }
+ if (cc && (pkt[0] != myea[0] || pkt[1] != myea[1] ||
+ pkt[2] != myea[2] || pkt[3] != myea[3] ||
+ pkt[4] != myea[4] || pkt[5] != myea[5])) {
+ cc = 0; /* ignore broadcast / multicast */
+#ifdef LE_DEBUG
+ printf("reject (%d sec left)\n", stopat - now);
+#endif
+ }
+ }
+#ifdef LE_DEBUG
+ printf("\n");
+#endif
+ return cc;
+}
+
+void le_init()
+{
+ caddr_t addr;
+ int *ea = (int *) LANCE_ADDR;
+ u_long *eram = (u_long *) ERAM_ADDR;
+ u_long e = *ea;
+ if (( e & 0x2fffff00 ) == 0x2fffff00) {
+ printf("ERROR: ethernet address not set! Use LSAD.\n");
+ callrom();
+ }
+ myea[0] = 0x08;
+ myea[1] = 0x00;
+ myea[2] = 0x3e;
+ e = e >> 8;
+ myea[5] = e & 0xff;
+ e = e >> 8;
+ myea[4] = e & 0xff;
+ e = e >> 8;
+ myea[3] = e;
+ printf("le0: ethernet address: %x:%x:%x:%x:%x:%x\n",
+ myea[0], myea[1], myea[2], myea[3], myea[4], myea[5]);
+ bzero(&le_softc, sizeof(le_softc));
+ le_softc.sc_r1 = (struct lereg1 *) LANCE_REG_ADDR;
+ le_softc.sc_r2 = (struct lereg2 *)(*eram - (1024*1024));
+ le_reset(myea);
+}
+
+void le_end()
+{
+ struct lereg1 *ler1 = le_softc.sc_r1;
+
+ ler1->ler1_rap = LE_CSR0;
+ ler1->ler1_rdp = LE_C0_STOP;
+}
diff --git a/sys/arch/mvme68k/stand/sboot/libc_sa.c b/sys/arch/mvme68k/stand/sboot/libc_sa.c
new file mode 100644
index 00000000000..5a178ad2930
--- /dev/null
+++ b/sys/arch/mvme68k/stand/sboot/libc_sa.c
@@ -0,0 +1,348 @@
+/* $NetBSD: libc_sa.c,v 1.1.1.1 1995/07/25 23:12:33 chuck Exp $ */
+
+/*-
+ * Copyright (c) 1990 The 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.
+ */
+
+#include "sboot.h"
+
+/*
+ * sizeof(word) MUST BE A POWER OF TWO
+ * SO THAT wmask BELOW IS ALL ONES
+ */
+typedef int word; /* "word" used for optimal copy speed */
+
+#define wsize sizeof(word)
+#define wmask (wsize - 1)
+
+/*
+ * Copy a block of memory, handling overlap.
+ * This is the routine that actually implements
+ * (the portable versions of) bcopy, memcpy, and memmove.
+ */
+void
+bcopy(src0, dst0, length)
+ void *dst0;
+ const void *src0;
+ register size_t length;
+{
+ register char *dst = dst0;
+ register const char *src = src0;
+ register size_t t;
+
+ if (length == 0 || dst == src) /* nothing to do */
+ goto done;
+
+ /*
+ * Macros: loop-t-times; and loop-t-times, t>0
+ */
+#define TLOOP(s) if (t) TLOOP1(s)
+#define TLOOP1(s) do { s; } while (--t)
+
+ if ((unsigned long)dst < (unsigned long)src) {
+ /*
+ * Copy forward.
+ */
+ t = (long)src; /* only need low bits */
+ if ((t | (long)dst) & wmask) {
+ /*
+ * Try to align operands. This cannot be done
+ * unless the low bits match.
+ */
+ if ((t ^ (long)dst) & wmask || length < wsize)
+ t = length;
+ else
+ t = wsize - (t & wmask);
+ length -= t;
+ TLOOP1(*dst++ = *src++);
+ }
+ /*
+ * Copy whole words, then mop up any trailing bytes.
+ */
+ t = length / wsize;
+ TLOOP(*(word *)dst = *(word *)src; src += wsize; dst += wsize);
+ t = length & wmask;
+ TLOOP(*dst++ = *src++);
+ } else {
+ /*
+ * Copy backwards. Otherwise essentially the same.
+ * Alignment works as before, except that it takes
+ * (t&wmask) bytes to align, not wsize-(t&wmask).
+ */
+ src += length;
+ dst += length;
+ t = (long)src;
+ if ((t | (long)dst) & wmask) {
+ if ((t ^ (long)dst) & wmask || length <= wsize)
+ t = length;
+ else
+ t &= wmask;
+ length -= t;
+ TLOOP1(*--dst = *--src);
+ }
+ t = length / wsize;
+ TLOOP(src -= wsize; dst -= wsize; *(word *)dst = *(word *)src);
+ t = length & wmask;
+ TLOOP(*--dst = *--src);
+ }
+done:
+ return;
+}
+
+/*-
+ * Copyright (c) 1990 The 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.
+ */
+
+void *
+bzero(dst, n)
+ void *dst;
+ register size_t n;
+{
+
+ if (n != 0) {
+ register char *d = dst;
+
+ do
+ *d++ = 0;
+ while (--n != 0);
+ }
+ return (dst);
+}
+/* $NetBSD: libc_sa.c,v 1.1.1.1 1995/07/25 23:12:33 chuck Exp $ */
+
+/*-
+ * Copyright (c) 1991 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)printf.c 5.6 (Berkeley) 5/25/91
+ */
+
+/*
+ * Scaled down version of printf(3).
+ *
+ * One additional format:
+ *
+ * The format %b is supported to decode error registers.
+ * Its usage is:
+ *
+ * printf("reg=%b\n", regval, "<base><arg>*");
+ *
+ * where <base> is the output base expressed as a control character, e.g.
+ * \10 gives octal; \20 gives hex. Each arg is a sequence of characters,
+ * the first of which gives the bit number to be inspected (origin 1), and
+ * the next characters (up to a control character, i.e. a character <= 32),
+ * give the name of the register. Thus:
+ *
+ * printf("reg=%b\n", 3, "\10\2BITTWO\1BITONE\n");
+ *
+ * would produce output:
+ *
+ * reg=3<BITTWO,BITONE>
+ */
+
+/*
+ * Note that stdarg.h and the ANSI style va_start macro is used for both
+ * ANSI and traditional C compilers.
+ */
+#define _KERNEL
+#include <machine/stdarg.h>
+#undef _KERNEL
+
+static void
+kprintn(ul, base)
+ unsigned long ul;
+ int base;
+{
+ /* hold a long in base 8 */
+ char *p, buf[(sizeof(long) * 8 / 3) + 1];
+
+ p = buf;
+ do {
+ *p++ = "0123456789abcdef"[ul % base];
+ } while (ul /= base);
+ do {
+ putchar(*--p);
+ } while (p > buf);
+}
+
+void
+#if __STDC__
+printf(const char *fmt, ...)
+#else
+printf(fmt /* , va_alist */)
+ char *fmt;
+#endif
+{
+ register char *p;
+ register int ch, n;
+ unsigned long ul;
+ int lflag, set;
+ va_list ap;
+
+ va_start(ap, fmt);
+ for (;;) {
+ while ((ch = *fmt++) != '%') {
+ if (ch == '\0')
+ return;
+ putchar(ch);
+ }
+ lflag = 0;
+reswitch: switch (ch = *fmt++) {
+ case 'l':
+ lflag = 1;
+ goto reswitch;
+ case 'b':
+ ul = va_arg(ap, int);
+ p = va_arg(ap, char *);
+ kprintn(ul, *p++);
+
+ if (!ul)
+ break;
+
+ for (set = 0; n = *p++;) {
+ if (ul & (1 << (n - 1))) {
+ putchar(set ? ',' : '<');
+ for (; (n = *p) > ' '; ++p)
+ putchar(n);
+ set = 1;
+ } else
+ for (; *p > ' '; ++p);
+ }
+ if (set)
+ putchar('>');
+ break;
+ case 'c':
+ ch = va_arg(ap, int);
+ putchar(ch & 0x7f);
+ break;
+ case 's':
+ p = va_arg(ap, char *);
+ while (ch = *p++)
+ putchar(ch);
+ break;
+ case 'd':
+ ul = lflag ?
+ va_arg(ap, long) : va_arg(ap, int);
+ if ((long)ul < 0) {
+ putchar('-');
+ ul = -(long)ul;
+ }
+ kprintn(ul, 10);
+ break;
+ case 'o':
+ ul = lflag ?
+ va_arg(ap, u_long) : va_arg(ap, u_int);
+ kprintn(ul, 8);
+ break;
+ case 'u':
+ ul = lflag ?
+ va_arg(ap, u_long) : va_arg(ap, u_int);
+ kprintn(ul, 10);
+ break;
+ case 'x':
+ ul = lflag ?
+ va_arg(ap, u_long) : va_arg(ap, u_int);
+ kprintn(ul, 16);
+ break;
+ default:
+ putchar('%');
+ if (lflag)
+ putchar('l');
+ putchar(ch);
+ }
+ }
+ va_end(ap);
+}
+
diff --git a/sys/arch/mvme68k/stand/sboot/oc_cksum.s b/sys/arch/mvme68k/stand/sboot/oc_cksum.s
new file mode 100644
index 00000000000..3718a0c4868
--- /dev/null
+++ b/sys/arch/mvme68k/stand/sboot/oc_cksum.s
@@ -0,0 +1,187 @@
+| $NetBSD: oc_cksum.s,v 1.1.1.1 1995/07/25 23:12:31 chuck Exp $
+
+| Copyright (c) 1988 Regents of the University of California.
+| All rights reserved.
+|
+| Redistribution and use in source and binary forms, with or without
+| modification, are permitted provided that the following conditions
+| are met:
+| 1. Redistributions of source code must retain the above copyright
+| notice, this list of conditions and the following disclaimer.
+| 2. Redistributions in binary form must reproduce the above copyright
+| notice, this list of conditions and the following disclaimer in the
+| documentation and/or other materials provided with the distribution.
+| 3. All advertising materials mentioning features or use of this software
+| must display the following acknowledgement:
+| This product includes software developed by the University of
+| California, Berkeley and its contributors.
+| 4. Neither the name of the University nor the names of its contributors
+| may be used to endorse or promote products derived from this software
+| without specific prior written permission.
+|
+| THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+| ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+| IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+| ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+| FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+| DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+| OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+| HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+| LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+| OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+| SUCH DAMAGE.
+|
+| @(#)oc_cksum.s 7.2 (Berkeley) 11/3/90
+|
+|
+| oc_cksum: ones complement 16 bit checksum for MC68020.
+|
+| oc_cksum (buffer, count, strtval)
+|
+| Do a 16 bit one's complement sum of 'count' bytes from 'buffer'.
+| 'strtval' is the starting value of the sum (usually zero).
+|
+| It simplifies life in in_cksum if strtval can be >= 2^16.
+| This routine will work as long as strtval is < 2^31.
+|
+| Performance
+| -----------
+| This routine is intended for MC 68020s but should also work
+| for 68030s. It (deliberately) doesn't worry about the alignment
+| of the buffer so will only work on a 68010 if the buffer is
+| aligned on an even address. (Also, a routine written to use
+| 68010 "loop mode" would almost certainly be faster than this
+| code on a 68010).
+|
+| We don't worry about alignment because this routine is frequently
+| called with small counts: 20 bytes for IP header checksums and 40
+| bytes for TCP ack checksums. For these small counts, testing for
+| bad alignment adds ~10% to the per-call cost. Since, by the nature
+| of the kernel's allocator, the data we're called with is almost
+| always longword aligned, there is no benefit to this added cost
+| and we're better off letting the loop take a big performance hit
+| in the rare cases where we're handed an unaligned buffer.
+|
+| Loop unrolling constants of 2, 4, 8, 16, 32 and 64 times were
+| tested on random data on four different types of processors (see
+| list below -- 64 was the largest unrolling because anything more
+| overflows the 68020 Icache). On all the processors, the
+| throughput asymptote was located between 8 and 16 (closer to 8).
+| However, 16 was substantially better than 8 for small counts.
+| (It's clear why this happens for a count of 40: unroll-8 pays a
+| loop branch cost and unroll-16 doesn't. But the tests also showed
+| that 16 was better than 8 for a count of 20. It's not obvious to
+| me why.) So, since 16 was good for both large and small counts,
+| the loop below is unrolled 16 times.
+|
+| The processors tested and their average time to checksum 1024 bytes
+| of random data were:
+| Sun 3/50 (15MHz) 190 us/KB
+| Sun 3/180 (16.6MHz) 175 us/KB
+| Sun 3/60 (20MHz) 134 us/KB
+| Sun 3/280 (25MHz) 95 us/KB
+|
+| The cost of calling this routine was typically 10% of the per-
+| kilobyte cost. E.g., checksumming zero bytes on a 3/60 cost 9us
+| and each additional byte cost 125ns. With the high fixed cost,
+| it would clearly be a gain to "inline" this routine -- the
+| subroutine call adds 400% overhead to an IP header checksum.
+| However, in absolute terms, inlining would only gain 10us per
+| packet -- a 1% effect for a 1ms ethernet packet. This is not
+| enough gain to be worth the effort.
+
+#include <m68k/asm.h>
+
+ .text
+
+ .text; .even; .globl _oc_cksum; _oc_cksum:
+ movl sp@(4),a0 | get buffer ptr
+ movl sp@(8),d1 | get byte count
+ movl sp@(12),d0 | get starting value
+ movl d2,sp@- | free a reg
+
+ | test for possible 1, 2 or 3 bytes of excess at end
+ | of buffer. The usual case is no excess (the usual
+ | case is header checksums) so we give that the faster
+ | 'not taken' leg of the compare. (We do the excess
+ | first because we're about the trash the low order
+ | bits of the count in d1.)
+
+ btst #0,d1
+ jne L5 | if one or three bytes excess
+ btst #1,d1
+ jne L7 | if two bytes excess
+L1:
+ movl d1,d2
+ lsrl #6,d1 | make cnt into # of 64 byte chunks
+ andl #0x3c,d2 | then find fractions of a chunk
+ negl d2
+ andb #0xf,cc | clear X
+ jmp pc@(L3-.-2:b,d2)
+L2:
+ movl a0@+,d2
+ addxl d2,d0
+ movl a0@+,d2
+ addxl d2,d0
+ movl a0@+,d2
+ addxl d2,d0
+ movl a0@+,d2
+ addxl d2,d0
+ movl a0@+,d2
+ addxl d2,d0
+ movl a0@+,d2
+ addxl d2,d0
+ movl a0@+,d2
+ addxl d2,d0
+ movl a0@+,d2
+ addxl d2,d0
+ movl a0@+,d2
+ addxl d2,d0
+ movl a0@+,d2
+ addxl d2,d0
+ movl a0@+,d2
+ addxl d2,d0
+ movl a0@+,d2
+ addxl d2,d0
+ movl a0@+,d2
+ addxl d2,d0
+ movl a0@+,d2
+ addxl d2,d0
+ movl a0@+,d2
+ addxl d2,d0
+ movl a0@+,d2
+ addxl d2,d0
+L3:
+ dbra d1,L2 | (NB- dbra doesn't affect X)
+
+ movl d0,d1 | fold 32 bit sum to 16 bits
+ swap d1 | (NB- swap doesn't affect X)
+ addxw d1,d0
+ jcc L4
+ addw #1,d0
+L4:
+ andl #0xffff,d0
+ movl sp@+,d2
+ rts
+
+L5: | deal with 1 or 3 excess bytes at the end of the buffer.
+ btst #1,d1
+ jeq L6 | if 1 excess
+
+ | 3 bytes excess
+ clrl d2
+ movw a0@(-3,d1:l),d2 | add in last full word then drop
+ addl d2,d0 | through to pick up last byte
+
+L6: | 1 byte excess
+ clrl d2
+ movb a0@(-1,d1:l),d2
+ lsll #8,d2
+ addl d2,d0
+ jra L1
+
+L7: | 2 bytes excess
+ clrl d2
+ movw a0@(-2,d1:l),d2
+ addl d2,d0
+ jra L1
diff --git a/sys/arch/mvme68k/stand/sboot/sboot.c b/sys/arch/mvme68k/stand/sboot/sboot.c
new file mode 100644
index 00000000000..3a8d1bf8a34
--- /dev/null
+++ b/sys/arch/mvme68k/stand/sboot/sboot.c
@@ -0,0 +1,150 @@
+/*
+ *
+ * Copyright (c) 1995 Charles D. Cranor and Seth Widoff
+ * 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 Charles D. Cranor
+ * and Seth Widoff.
+ * 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.
+ */
+/*
+ * main driver, plus machdep stuff
+ */
+
+#include "sboot.h"
+
+void sboot()
+
+{
+ char * mesg;
+ char buf[128];
+ buf[0] = '0';
+ consinit();
+ printf("\nsboot: serial line bootstrap program (&end = %x)\n\n", &end);
+ if (reboot) { /* global flag from AAstart.s */
+ reboot = 0;
+ printf("[rebooting...]\n");
+ do_cmd("b");
+ }
+ while (1) {
+ printf(">>> ");
+ ngets(buf, sizeof(buf));
+ do_cmd(buf);
+ }
+ /* not reached */
+}
+
+/*
+ * exit to rom
+ */
+
+void callrom ()
+{
+ asm("trap #15; .word 0x0063");
+}
+
+/*
+ * do_cmd: do a command
+ */
+
+void do_cmd(buf)
+
+char *buf;
+
+{
+ switch (*buf) {
+ case '\0':
+ return;
+ case 'a':
+ if ( rev_arp() ) {
+ printf ("My ip address is: %d.%d.%d.%d\n", myip[0],
+ myip[1], myip[2], myip[3]);
+ printf ("Server ip address is: %d.%d.%d.%d\n", servip[0],
+ servip[1], servip[2], servip[3]);
+ } else {
+ printf ("Failed.\n");
+ }
+ return;
+ case 'e':
+ printf("exiting to ROM\n");
+ callrom();
+ return;
+ case 'f':
+ if (do_get_file() == 1) {
+ printf("Download Failed\n");
+ } else {
+ printf("Download was a success!\n");
+ }
+ return;
+ case 'b':
+ le_init();
+ if ( rev_arp() ) {
+ printf ("My ip address is: %d.%d.%d.%d\n", myip[0],
+ myip[1], myip[2], myip[3]);
+ printf ("Server ip address is: %d.%d.%d.%d\n", servip[0],
+ servip[1], servip[2], servip[3]);
+ } else {
+ printf ("REVARP: Failed.\n");
+ return;
+ }
+ if (do_get_file() == 1) {
+ printf("Download Failed\n");
+ return;
+ } else {
+ printf("Download was a success!\n");
+ }
+ go(buf);
+ return;
+ case 'h':
+ case '?':
+ printf("valid commands\n");
+ printf("a - send a RARP\n");
+ printf("b - boot the system\n");
+ printf("e - exit to ROM\n");
+ printf("f - ftp the boot file\n");
+ printf("g - execute the boot file\n");
+ printf("h - help\n");
+ printf("i - init LANCE enet chip\n");
+ return;
+ case 'i':
+ le_init();
+ return;
+ case 'g':
+ go(buf);
+ return;
+ default:
+ printf("sboot: %s: Unknown command\n", buf);
+ }
+}
+
+go(buf)
+char *buf;
+
+{
+ void (*entry)() = (void (*)) LOAD_ADDR ;
+ printf("Start @ 0x%x ... \n", entry);
+ (*entry)(buf);
+}
+
diff --git a/sys/arch/mvme68k/stand/sboot/sboot.h b/sys/arch/mvme68k/stand/sboot/sboot.h
new file mode 100644
index 00000000000..01085b17b90
--- /dev/null
+++ b/sys/arch/mvme68k/stand/sboot/sboot.h
@@ -0,0 +1,96 @@
+/*
+ *
+ * Copyright (c) 1995 Charles D. Cranor and Seth Widoff
+ * 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 Charles D. Cranor
+ * and Seth Widoff.
+ * 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.
+ */
+
+/*
+ * sboot.h: stuff for MVME147's serial line boot
+ */
+
+typedef unsigned short u_short;
+typedef unsigned long u_long;
+typedef unsigned char u_char;
+typedef unsigned int u_int;
+typedef u_long size_t;
+typedef char *caddr_t;
+extern caddr_t end;
+
+#define NULL ((char *)0)
+
+void bcopy(const void *, void *, size_t); /* libc_sa */
+void *memset(void *, int, size_t); /* libc_sa */
+void printf(const char *, ...); /* libc_sa */
+
+/* console */
+void puts(char *);
+void putchar(char);
+char cngetc();
+void ngets(char *, int);
+
+/* sboot */
+void callrom();
+void do_cmd(char *);
+
+/* le */
+#define LANCE_ADDR 0xfffe0778
+#define ERAM_ADDR 0xfffe0774
+#define LANCE_REG_ADDR 0xfffe1800
+void le_end(void);
+void le_init(void);
+int le_get(u_char *, size_t, u_long);
+int le_put(u_char *, size_t);
+
+/* etherfun */
+#define READ 0
+#define ACKN 1
+void do_rev_arp();
+int get_rev_arp();
+int rev_arp();
+void do_send_tftp( int );
+int do_get_file();
+void tftp_file(char *, u_long);
+
+/* clock */
+u_long time(void);
+
+/* checksum */
+u_long oc_cksum (void *, u_long, u_long);
+
+#define CONS_ZS_ADDR (0xfffe3002)
+#define CLOCK_ADDR (0xfffe07f8)
+#define LOAD_ADDR 0x8000
+
+unsigned char myea[6]; /* my ether addr */
+unsigned char myip[4];
+unsigned char servip[4];
+unsigned char servea[6];
+u_short myport;
+u_short servport;
+unsigned char reboot;
diff --git a/sys/arch/mvme68k/stand/sboot/start.s b/sys/arch/mvme68k/stand/sboot/start.s
new file mode 100644
index 00000000000..d878f94ea23
--- /dev/null
+++ b/sys/arch/mvme68k/stand/sboot/start.s
@@ -0,0 +1,47 @@
+/*
+ *
+ * Copyright (c) 1995 Charles D. Cranor
+ * 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 Charles D. Cranor.
+ * 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.
+ */
+/*
+ * start: at address 0x4000, load at 0xa000 (so put stack at 0x9ff0)
+ * note this file is named "AAstart" so that it gets linked FIRST
+ */
+
+.text
+.globl start
+start:
+ movb #0,_reboot
+ jra Ldoit
+restart:
+ movb #1,_reboot | fall through
+
+Ldoit:
+ movl #0x00006ff0,sp
+ jsr _sboot
+