Import of WGRISC port. (Willowglen R3081 board)
authorpefo <pefo@openbsd.org>
Thu, 6 Feb 1997 16:02:41 +0000 (16:02 +0000)
committerpefo <pefo@openbsd.org>
Thu, 6 Feb 1997 16:02:41 +0000 (16:02 +0000)
94 files changed:
sys/arch/wgrisc/Makefile [new file with mode: 0644]
sys/arch/wgrisc/compile/.cvsignore [new file with mode: 0644]
sys/arch/wgrisc/compile/.keep_me [new file with mode: 0644]
sys/arch/wgrisc/conf/DISKLESS [new file with mode: 0644]
sys/arch/wgrisc/conf/GENERIC [new file with mode: 0644]
sys/arch/wgrisc/conf/Makefile.wgrisc [new file with mode: 0644]
sys/arch/wgrisc/conf/files.wgrisc [new file with mode: 0644]
sys/arch/wgrisc/conf/ld.script [new file with mode: 0644]
sys/arch/wgrisc/dev/ace.c [new file with mode: 0644]
sys/arch/wgrisc/dev/asc.c [new file with mode: 0644]
sys/arch/wgrisc/dev/ascreg.h [new file with mode: 0644]
sys/arch/wgrisc/dev/com_risc.c [new file with mode: 0644]
sys/arch/wgrisc/dev/dma.h [new file with mode: 0644]
sys/arch/wgrisc/dev/if_sn.c [new file with mode: 0644]
sys/arch/wgrisc/dev/if_sn.h [new file with mode: 0644]
sys/arch/wgrisc/dev/scsi.h [new file with mode: 0644]
sys/arch/wgrisc/include/ansi.h [new file with mode: 0644]
sys/arch/wgrisc/include/asm.h [new file with mode: 0644]
sys/arch/wgrisc/include/autoconf.h [new file with mode: 0644]
sys/arch/wgrisc/include/bus.h [new file with mode: 0644]
sys/arch/wgrisc/include/cdefs.h [new file with mode: 0644]
sys/arch/wgrisc/include/cpu.h [new file with mode: 0644]
sys/arch/wgrisc/include/disklabel.h [new file with mode: 0644]
sys/arch/wgrisc/include/dlfcn.h [new file with mode: 0644]
sys/arch/wgrisc/include/ecoff.h [new file with mode: 0644]
sys/arch/wgrisc/include/elf_abi.h [new file with mode: 0644]
sys/arch/wgrisc/include/endian.h [new file with mode: 0644]
sys/arch/wgrisc/include/exec.h [new file with mode: 0644]
sys/arch/wgrisc/include/float.h [new file with mode: 0644]
sys/arch/wgrisc/include/ieeefp.h [new file with mode: 0644]
sys/arch/wgrisc/include/intr.h [new file with mode: 0644]
sys/arch/wgrisc/include/kbdreg.h [new file with mode: 0644]
sys/arch/wgrisc/include/kcore.h [new file with mode: 0644]
sys/arch/wgrisc/include/kdbparam.h [new file with mode: 0644]
sys/arch/wgrisc/include/limits.h [new file with mode: 0644]
sys/arch/wgrisc/include/link.h [new file with mode: 0644]
sys/arch/wgrisc/include/memconf.h [new file with mode: 0644]
sys/arch/wgrisc/include/mips_opcode.h [new file with mode: 0644]
sys/arch/wgrisc/include/param.h [new file with mode: 0644]
sys/arch/wgrisc/include/pcb.h [new file with mode: 0644]
sys/arch/wgrisc/include/pio.h [new file with mode: 0644]
sys/arch/wgrisc/include/pmap.h [new file with mode: 0644]
sys/arch/wgrisc/include/proc.h [new file with mode: 0644]
sys/arch/wgrisc/include/profile.h [new file with mode: 0644]
sys/arch/wgrisc/include/psl.h [new file with mode: 0644]
sys/arch/wgrisc/include/pte.h [new file with mode: 0644]
sys/arch/wgrisc/include/ptrace.h [new file with mode: 0644]
sys/arch/wgrisc/include/reg.h [new file with mode: 0644]
sys/arch/wgrisc/include/regdef.h [new file with mode: 0644]
sys/arch/wgrisc/include/regnum.h [new file with mode: 0644]
sys/arch/wgrisc/include/reloc.h [new file with mode: 0644]
sys/arch/wgrisc/include/setjmp.h [new file with mode: 0644]
sys/arch/wgrisc/include/signal.h [new file with mode: 0644]
sys/arch/wgrisc/include/stdarg.h [new file with mode: 0644]
sys/arch/wgrisc/include/trap.h [new file with mode: 0644]
sys/arch/wgrisc/include/types.h [new file with mode: 0644]
sys/arch/wgrisc/include/varargs.h [new file with mode: 0644]
sys/arch/wgrisc/include/vmparam.h [new file with mode: 0644]
sys/arch/wgrisc/isa/isa_machdep.h [new file with mode: 0644]
sys/arch/wgrisc/isa/isabus.c [new file with mode: 0644]
sys/arch/wgrisc/riscbus/riscbus.c [new file with mode: 0644]
sys/arch/wgrisc/riscbus/riscbus.h [new file with mode: 0644]
sys/arch/wgrisc/stand/Makefile [new file with mode: 0644]
sys/arch/wgrisc/stand/boot.c [new file with mode: 0644]
sys/arch/wgrisc/stand/conf.c [new file with mode: 0644]
sys/arch/wgrisc/stand/filesystem.c [new file with mode: 0644]
sys/arch/wgrisc/stand/libsa/Makefile [new file with mode: 0644]
sys/arch/wgrisc/stand/libsa/devopen.c [new file with mode: 0644]
sys/arch/wgrisc/stand/libsa/getenv.c [new file with mode: 0644]
sys/arch/wgrisc/stand/libsa/getputchar.c [new file with mode: 0644]
sys/arch/wgrisc/stand/rz.c [new file with mode: 0644]
sys/arch/wgrisc/stand/start.S [new file with mode: 0644]
sys/arch/wgrisc/wgrisc/autoconf.c [new file with mode: 0644]
sys/arch/wgrisc/wgrisc/clock.c [new file with mode: 0644]
sys/arch/wgrisc/wgrisc/clock_dp.c [new file with mode: 0644]
sys/arch/wgrisc/wgrisc/clockvar.h [new file with mode: 0644]
sys/arch/wgrisc/wgrisc/conf.c [new file with mode: 0644]
sys/arch/wgrisc/wgrisc/cpu.c [new file with mode: 0644]
sys/arch/wgrisc/wgrisc/cpu_exec.c [new file with mode: 0644]
sys/arch/wgrisc/wgrisc/disksubr.c [new file with mode: 0644]
sys/arch/wgrisc/wgrisc/fp.S [new file with mode: 0644]
sys/arch/wgrisc/wgrisc/genassym.c [new file with mode: 0644]
sys/arch/wgrisc/wgrisc/locore.S [new file with mode: 0644]
sys/arch/wgrisc/wgrisc/machdep.c [new file with mode: 0644]
sys/arch/wgrisc/wgrisc/mainbus.c [new file with mode: 0644]
sys/arch/wgrisc/wgrisc/mem.c [new file with mode: 0644]
sys/arch/wgrisc/wgrisc/minidebug.c [new file with mode: 0644]
sys/arch/wgrisc/wgrisc/pmap.c [new file with mode: 0644]
sys/arch/wgrisc/wgrisc/process_machdep.c [new file with mode: 0644]
sys/arch/wgrisc/wgrisc/swapgeneric.c [new file with mode: 0644]
sys/arch/wgrisc/wgrisc/sys_machdep.c [new file with mode: 0644]
sys/arch/wgrisc/wgrisc/trap.c [new file with mode: 0644]
sys/arch/wgrisc/wgrisc/vm_machdep.c [new file with mode: 0644]
sys/arch/wgrisc/wgrisc/wgrisctype.h [new file with mode: 0644]

diff --git a/sys/arch/wgrisc/Makefile b/sys/arch/wgrisc/Makefile
new file mode 100644 (file)
index 0000000..ac6c1d7
--- /dev/null
@@ -0,0 +1,28 @@
+#      from: @(#)Makefile      8.1 (Berkeley) 6/16/93
+#      $Id: Makefile,v 1.1.1.1 1997/02/06 16:02:41 pefo Exp $
+
+# Makefile for pica links, tags file
+
+.include "../../kern/Make.tags.inc"
+
+all:
+       @echo "make links or tags only"
+
+DIRS=  conf dev dist include pica
+
+links::
+       -for i in ${DIRS}; do \
+           (cd $$i && { rm -f tags; ln -s ${SYSTAGS} tags; }) done
+
+PICA=  /sys/pica/dev/*.[ch] /sys/pica/include/*.[ch] \
+       /sys/pica/pica/*.[ch] /sys/pica/ultrix/*.[ch]
+APICA= /sys/pica/pica/*.s
+
+tags::
+       -ctags -wdtif ${COMM} ${PICA}
+       egrep "^LEAF(.*)|^[AN]LEAF(.*)|^NON_LEAF(.*)" ${APICA} | \
+           sed "s;\([^:]*\):\([^(]*\)(\([^, )]*\)\(.*\);\3 \1 /^\2(\3\4$$/;" \
+               >> tags
+       sort -o tags tags
+
+.include <bsd.prog.mk>
diff --git a/sys/arch/wgrisc/compile/.cvsignore b/sys/arch/wgrisc/compile/.cvsignore
new file mode 100644 (file)
index 0000000..db5b0e0
--- /dev/null
@@ -0,0 +1 @@
+GENERIC
diff --git a/sys/arch/wgrisc/compile/.keep_me b/sys/arch/wgrisc/compile/.keep_me
new file mode 100644 (file)
index 0000000..7527019
--- /dev/null
@@ -0,0 +1 @@
+This file must remain so that 'cvs checkout' makes the compile directory.
diff --git a/sys/arch/wgrisc/conf/DISKLESS b/sys/arch/wgrisc/conf/DISKLESS
new file mode 100644 (file)
index 0000000..744607c
--- /dev/null
@@ -0,0 +1,77 @@
+#
+#      Generic configuration file for MIPS R4400 PICA system
+#
+
+machine                riscpc
+
+maxusers       8
+
+# does not really do anything anymore, but this replaces "ident GENERIC"
+#options               GENERIC
+
+# Need to set locally
+options                TIMEZONE="8*60"         # minutes west of GMT (for)
+options                DST=1                   # use daylight savings rules
+
+# Standard system options
+options                SWAPPAGER               # swap pager (anonymous and swap space)
+options                VNODEPAGER              # vnode pager (mapped files)
+options                DEVPAGER                # device pager (mapped devices)
+options                DIAGNOSTIC              # extra kernel debugging checks
+options                DEBUG                   # extra kernel debugging support
+options                "COMPAT_43"             # compatibility with 4.3BSD binaries
+#options       KTRACE                  # system call tracing support
+options                "NKMEMCLUSTERS=1024"    # 4K pages in kernel malloc pool
+#options       KGDB                    # support for kernel gdb
+#options       "KGDBRATE=19200"        # kernel gdb port rate (default 9600)
+#options       "KGDBDEV=15*256+0"      # device for kernel gdb
+
+# System V options
+options                SYSVMSG         # System V-like message queues
+options                SYSVSEM         # System V-like semaphores
+options                SYSVSHM         # System V-like memory sharing
+options                SHMMAXPGS=1024  # 1024 pages is the default
+options                NATIVE_ELF
+
+# Filesystem options
+options                FIFO            # POSIX fifo support (in all filesystems)
+options                FFS,QUOTA       # fast filesystem with user and group quotas
+options                MFS             # memory-based filesystem
+options                NFSCLIENT       # Sun NFS-compatible filesystem (client)
+options                NFSSERVER       # Sun NFS-compatible filesystem (server)
+options                KERNFS          # kernel data-structure filesystem
+#options       MSDOSFS         # Ability to read write MS-Dos filsystem
+#options       CD9660          # ISO 9660 + Rock Ridge file system
+options                FDESC           # user file descriptor filesystem
+#options       UMAPFS          # uid/gid remapping filesystem
+#options       NULLFS          # null layer filesystem
+#options       LFS             # Log-based filesystem (still experimental)
+#options       PORTAL          # portal filesystem (still experimental)
+
+# Networking options
+options                INET            # Internet protocols
+options                "TCP_COMPAT_42" # compatibility with 4.2BSD TCP/IP
+options                GATEWAY         # IP packet forwarding
+#options       MULTICAST       # Multicast support
+#options       MROUTING        # Multicast routing support
+#options       ISO             # OSI networking
+#options       TPIP
+#options       EON
+
+config         bsd root on nfs swap on nfs
+
+mainbus0       at root
+cpu*           at mainbus0
+
+pica*          at mainbus0
+clock0         at pica?
+com0           at pica?
+com1           at pica?
+sn0            at pica?
+
+pseudo-device  sl               2      # serial-line IP ports
+pseudo-device  ppp              2      # serial-line PPP ports
+pseudo-device  pty             64      # pseudo ptys
+pseudo-device  bpfilter        16      # packet filter ports
+pseudo-device  loop
+pseudo-device  vnd             4       # virtual disk
diff --git a/sys/arch/wgrisc/conf/GENERIC b/sys/arch/wgrisc/conf/GENERIC
new file mode 100644 (file)
index 0000000..387282f
--- /dev/null
@@ -0,0 +1,124 @@
+#      $OpenBSD: GENERIC,v 1.1.1.1 1997/02/06 16:02:45 pefo Exp $
+#
+#      Generic configuration file for Willowglen RISC-PC 9100
+#
+
+machine                wgrisc
+
+maxusers       8
+
+# Need to set locally
+options                TIMEZONE=0              # minutes west of GMT (for)
+options                DST=0                   # use daylight savings rules
+
+# Standard system options
+options                SWAPPAGER               # swap pager (anonymous and swap space)
+options                DEVPAGER                # device pager (mapped devices)
+
+options                DIAGNOSTIC              # extra kernel debugging checks
+options        KTRACE                  # system call tracing support
+options                DEBUG                   # extra kernel debugging support
+options                COMPAT_43               # compatibility with 4.3BSD binaries
+
+# System V options
+#options       SYSVMSG         # System V-like message queues
+#options       SYSVSEM         # System V-like semaphores
+#options       SYSVSHM         # System V-like memory sharing
+options                SHMMAXPGS=1024  # 1024 pages is the default
+options                NATIVE_ELF      # Arc systems uses ELF as native format
+
+# Filesystem options
+#options       CD9660          # ISO 9660 + Rock Ridge file system
+#options       FDESC           # user file descriptor filesystem (/dev/fd)
+options                FIFO            # POSIX fifo support (in all filesystems)
+options                FFS,QUOTA       # fast filesystem with user and group quotas
+#options       KERNFS          # kernel data-structure filesystem
+#options       LFS             # Log-based filesystem (still experimental)
+#options       MFS             # memory-based filesystem
+#options       MSDOSFS         # Ability to read write MS-Dos filsystem
+options        NFSCLIENT       # Sun NFS-compatible filesystem (client)
+#options       NFSSERVER       # Sun NFS-compatible filesystem (server)
+#options       NULLFS          # null layer filesystem
+#options       PORTAL          # portal filesystem (still experimental)
+#options       PROCFS          # /proc
+#options       UMAPFS          # uid/gid remapping filesystem
+#options       UNION           # union file system
+
+
+# Networking options
+#options       GATEWAY         # IP packet forwarding
+options        INET            # Internet protocols
+#options        NS              # XNS
+#options        IPX             # IPX+SPX
+#options       ISO,TPIP        # OSI networking
+#options       EON             # OSI tunneling over IP
+#options       CCITT,LLC,HDLC  # X.25
+#options       IPFILTER        # IP packet filter for security
+
+#options       TCP_COMPAT_42   # compatibility with 4.2BSD TCP/IP
+#options       MULTICAST       # Multicast support
+#options       MROUTING        # Multicast routing support
+
+# Special options
+options        MACHINE_NONCONTIG # Support noncontigous memory.
+options        CONADDR=0xae400000 # serial console I/O address.
+
+# Specify storage configuration (its a joke..)
+config         bsd     swap generic
+
+#
+# Definition of system
+#
+mainbus0       at root
+cpu*           at mainbus0
+
+riscbus*       at mainbus0
+isabr*         at mainbus0
+
+clock0         at riscbus?
+com0           at riscbus?
+com1           at riscbus?
+com2           at riscbus?
+com3           at riscbus?
+#sn0           at riscbus?
+
+asc0           at riscbus?
+scsibus*       at asc?
+
+#
+#      ISA Bus.
+#
+
+isa*   at isabr?
+
+com4   at isa? port 0x3e8 irq 4
+com5   at isa? port 0x2e8 irq 3
+
+ep0    at isa? port ? irq ?           # 3C509 ethernet cards
+#ed0   at isa? port 0x280 iomem 0xd0000 irq 9  # WD/SMC, 3C503, and NE[12]000
+#ed1   at isa? port 0x250 iomem 0xd8000 irq 9  #   ethernet cards
+#ed2   at isa? port 0x300 iomem 0xcc000 irq 10 #
+
+#
+#      SCSI Bus devices
+#
+
+sd*            at scsibus? target ? lun ?
+#st*           at scsibus? target ? lun ?
+#cd*           at scsibus? target ? lun ?
+#ch*           at scsibus? target ? lun ?
+#ss*           at scsibus? target ? lun ?
+#uk*           at scsibus? target ? lun ?
+
+#
+pseudo-device  loop             1      # network loopback
+pseudo-device  bpfilter         8      # packet filter ports
+#pseudo-device sl               2      # serial-line IP ports
+#pseudo-device ppp              2      # serial-line PPP ports
+#pseudo-device tun              2      # network tunneling over tty
+
+pseudo-device  pty             64      # pseudo ptys
+pseudo-device  tb               1      # tablet line discipline
+pseudo-device  vnd              4      # paging to files
+#pseudo-device   ccd            4      # concatenated disk devices
+
diff --git a/sys/arch/wgrisc/conf/Makefile.wgrisc b/sys/arch/wgrisc/conf/Makefile.wgrisc
new file mode 100644 (file)
index 0000000..341b1ca
--- /dev/null
@@ -0,0 +1,183 @@
+#      $OpenBSD: Makefile.wgrisc,v 1.1.1.1 1997/02/06 16:02:45 pefo Exp $
+
+#      @(#)Makefile.wgrisc     8.2 (Berkeley) 2/16/94
+#
+# Makefile for 4.4 BSD
+#
+# This makefile is constructed from a machine description:
+#      config machineid
+# Most changes should be made in the machine description
+#      /sys/arch/MACHINE/conf/``machineid''
+# after which you should do
+#       config machineid
+# Machine generic makefile changes should be made in
+#      /sys/arch/MACHINE/conf/Makefile.``machinetype''
+# 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
+CC?=   cc
+CPP?=  cpp
+LD?=   ld
+STRIP?=        strip -d
+TOUCH?=        touch -f -c
+
+# source tree is located via $S relative to the compilation directory
+S=     ../../../..
+WGRISC=        ../..
+
+INCLUDES=      -I. -I$S/arch -I$S
+CPPFLAGS=      ${INCLUDES} ${IDENT} -D_KERNEL -Dwgrisc
+CFLAGS=                ${DEBUG} -O2 -Werror -mno-abicalls -mips1 -mcpu=r3000
+AFLAGS=                -x assembler-with-cpp -traditional-cpp -D_LOCORE
+
+### 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
+
+# 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.
+
+USRLAND_C=     ${CC} ${CFLAGS} ${CPPFLAGS} ${PROF} -c $<
+USRLAND_C_C=   ${CC} ${CFLAGS} ${CPPFLAGS} ${PROF} ${PARAM} -c $<
+
+NORMAL_C=      ${CC} ${CFLAGS} ${CPPFLAGS} ${PROF} -c $<
+NORMAL_C_C=    ${CC} ${CFLAGS} ${CPPFLAGS} ${PROF} ${PARAM} -c $<
+
+DRIVER_C=      ${CC} ${CFLAGS} ${CPPFLAGS} ${PROF} -c $<
+DRIVER_C_C=    ${CC} ${CFLAGS} ${CPPFLAGS} ${PROF} ${PARAM} -c $<
+
+NORMAL_S=      ${CC} ${AFLAGS} ${CPPFLAGS} -c $<
+NORMAL_S_C=    ${AS}  ${COPTS} ${PARAM} $< -o $@
+
+%OBJS
+
+%CFILES
+
+%SFILES
+
+# load lines for config "xxx" will be emitted as:
+# xxx: ${SYSTEM_DEP} swapxxx.o
+#      ${SYSTEM_LD_HEAD}
+#      ${SYSTEM_LD} swapxxx.o
+#      ${SYSTEM_LD_TAIL}
+
+SYSTEM_OBJ=    locore.o fp.o ${OBJS} param.o ioconf.o ${LIBKERN} \
+               ${LIBCOMPAT}
+#
+SYSTEM_DEP=    Makefile ${SYSTEM_OBJ}
+SYSTEM_LD_HEAD=        rm -f $@
+SYSTEM_LD=     -@if [ X${DEBUG} = X-g ]; \
+               then strip=-X; \
+               else strip=-x; \
+               fi; \
+               echo ${LD} $$strip -o $@ -e start -T ../../conf/ld.script \
+                       '$${SYSTEM_OBJ}' vers.o; \
+               ${LD} $$strip -o $@ -e start -T ../../conf/ld.script \
+                       ${SYSTEM_OBJ} vers.o
+#
+SYSTEM_LD_TAIL=        chmod 755 $@; \
+               elf2ecoff $@ $@.ecoff; \
+               size $@
+
+%LOAD
+
+newvers:
+       sh $S/conf/newvers.sh
+       ${CC} $(CFLAGS) -c vers.c
+
+clean::
+       rm -f eddep bsd bsd.gdb bsd.ecoff tags *.o locore.i [a-z]*.s \
+           Errs errs linterrs makelinks genassym
+
+lint: /tmp param.c
+       @lint -hbxn -DGENERIC -Dvolatile= ${COPTS} ${PARAM} -UKGDB \
+           ${WGRISC}/wgrisc/Locore.c ${CFILES} \
+           ioconf.c param.c
+
+symbols.sort: ${WGRISC}/wgrisc/symbols.raw
+       grep -v '^#' ${WGRISC}/wgrisc/symbols.raw \
+           | sed 's/^  //' | sort -u > symbols.sort
+
+locore.o: ${WGRISC}/wgrisc/locore.S ${WGRISC}/include/asm.h \
+       ${WGRISC}/include/cpu.h ${WGRISC}/include/reg.h assym.h
+       ${NORMAL_S} -mips1 ${WGRISC}/wgrisc/locore.S
+
+fp.o: ${WGRISC}/wgrisc/fp.S ${WGRISC}/include/asm.h \
+       ${WGRISC}/include/cpu.h ${WGRISC}/include/reg.h assym.h
+       ${NORMAL_S} -mips1 ${WGRISC}/wgrisc/fp.S
+
+# the following are necessary because the files depend on the types of
+# cpu's included in the system configuration
+clock.o machdep.o autoconf.o conf.o: Makefile
+
+# depend on network configuration
+uipc_domain.o uipc_proto.o vfs_conf.o: Makefile
+if_tun.o if_loop.o if_ethersubr.o: Makefile
+in_proto.o: Makefile
+
+assym.h: genassym
+       ./genassym >assym.h
+
+genassym: genassym.o
+       ${HOSTCC} -o $@ genassym.o
+
+genassym.o: ${WGRISC}/wgrisc/genassym.c
+       ${HOSTCC} ${INCLUDES} ${IDENT} -D_KERNEL -Dwgrisc -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
+       ${NORMAL_C}
+
+param.c: $S/conf/param.c
+       rm -f param.c
+       cp $S/conf/param.c .
+
+param.o: param.c Makefile
+       ${NORMAL_C_C}
+
+newvers: ${SYSTEM_DEP} ${SYSTEM_SWAP_DEP}
+       sh $S/conf/newvers.sh
+       ${CC} ${CFLAGS} ${CPPFLAGS} ${PROF} -c vers.c
+
+depend:: .depend
+.depend: ${SRCS} assym.h param.c
+       mkdep ${AFLAGS} ${CPPFLAGS} ${WGRISC}/wgrisc/locore.s
+       mkdep -a ${CFLAGS} ${CPPFLAGS} param.c ioconf.c ${CFILES}
+       mkdep -a ${AFLAGS} ${CPPFLAGS} ${SFILES}
+       mkdep -a ${CFLAGS} ${CPPFLAGS} ${PARAM} ${WGRISC}/wgrisc/genassym.c
+
+%RULES
+
diff --git a/sys/arch/wgrisc/conf/files.wgrisc b/sys/arch/wgrisc/conf/files.wgrisc
new file mode 100644 (file)
index 0000000..98d094b
--- /dev/null
@@ -0,0 +1,106 @@
+#      $OpenBSD: files.wgrisc,v 1.1.1.1 1997/02/06 16:02:45 pefo Exp $
+#
+# maxpartitions must be first item in files.${ARCH}
+#
+maxpartitions 8
+
+maxusers 2 8 64
+
+#      Required files
+
+
+file   arch/wgrisc/wgrisc/autoconf.c
+file   arch/wgrisc/wgrisc/conf.c
+file   arch/wgrisc/wgrisc/cpu_exec.c
+file   arch/wgrisc/wgrisc/disksubr.c
+file   arch/wgrisc/wgrisc/machdep.c
+file   arch/wgrisc/wgrisc/minidebug.c
+file   arch/wgrisc/wgrisc/mem.c
+file   arch/wgrisc/wgrisc/pmap.c
+file   arch/wgrisc/wgrisc/process_machdep.c
+file   arch/wgrisc/wgrisc/sys_machdep.c
+file   arch/wgrisc/wgrisc/trap.c
+file   arch/wgrisc/wgrisc/vm_machdep.c
+
+#
+#      Machine-independent ATAPI drivers 
+#
+
+include "../../../dev/atapi/files.atapi"
+
+
+#
+#      System BUS types
+#
+
+define mainbus {}
+device mainbus
+attach mainbus at root
+file   arch/wgrisc/wgrisc/mainbus.c    mainbus
+
+#      Our CPU configurator
+device cpu
+attach cpu at mainbus                  # not optional
+file arch/wgrisc/wgrisc/cpu.c                  cpu
+
+#
+#      LOCALBUS bus autoconfiguration devices
+#
+device riscbus {}
+attach riscbus at mainbus                      # { slot = -1, offset = -1 }
+file   arch/wgrisc/riscbus/riscbus.c           riscbus
+
+#      Real time clock, must have one..
+device clock
+attach clock at riscbus
+file   arch/wgrisc/wgrisc/clock.c              clock
+file   arch/wgrisc/wgrisc/clock_dp.c           clock
+
+#      Ethernet chip
+device sn
+attach sn at riscbus: ifnet, ether
+file   arch/wgrisc/dev/if_sn.c         sn      needs-count
+
+#      Use machine independent SCSI driver routines
+include        "../../../scsi/files.scsi"
+major  {sd = 0}
+major  {cd = 3}
+
+#      Machine dependent SCSI interface driver
+device asc: scsi
+attach asc at riscbus
+file   arch/wgrisc/dev/asc.c           asc     needs-count
+
+#
+#      ISA
+#
+device isabr {} : isabus
+attach isabr at mainbus
+file   arch/wgrisc/isa/isabus.c                isabr
+
+#
+#      Stock isa bus support
+#
+define  pcmcia {}                      # XXX dummy decl...
+
+include        "../../../dev/isa/files.isa"
+
+# National Semiconductor DS8390/WD83C690-based boards
+# (WD/SMC 80x3 family, SMC Ultra [8216], 3Com 3C503, NE[12]000, and clones)
+# XXX conflicts with other ports; can't be in files.isa
+device  ed: ether, ifnet
+attach  ed at isa with ed_isa
+attach  ed at pcmcia with ed_pcmcia
+file    dev/isa/if_ed.c                 ed & (ed_isa | ed_pcmcia) needs-flag
+
+# 8250/16[45]50-based "com" ports
+attach  com at riscbus with com_risc
+file    arch/wgrisc/dev/com_risc.c        com_risc
+
+#
+
+file   dev/cons.c
+file   dev/cninit.c
+file   netinet/in_cksum.c
+file   netns/ns_cksum.c                        ns
+
diff --git a/sys/arch/wgrisc/conf/ld.script b/sys/arch/wgrisc/conf/ld.script
new file mode 100644 (file)
index 0000000..3c59f13
--- /dev/null
@@ -0,0 +1,74 @@
+OUTPUT_FORMAT("elf32-littlemips", "elf32-bigmips",
+             "elf32-littlemips")
+OUTPUT_ARCH(mips)
+ENTRY(_start)
+SECTIONS
+{
+  /* Read-only sections, merged into text segment: */
+  . = 0x80100000 + SIZEOF_HEADERS;
+  .text      :
+  {
+    _ftext = . ;
+    *(.text)
+    *(.rodata)
+    *(.rodata1)
+    *(.reginfo)
+    *(.init)
+    *(.stub)
+    /* .gnu.warning sections are handled specially by elf32.em.  */
+    *(.gnu.warning)
+  } =0
+  _etext = .;
+  PROVIDE (etext = .);
+  .fini      : { *(.fini)    } =0
+  .data    :
+  {
+    _fdata = . ;
+    *(.data)
+    CONSTRUCTORS
+  }
+  .data1   : { *(.data1) }
+  .ctors         : { *(.ctors)   }
+  .dtors         : { *(.dtors)   }
+  _gp = ALIGN(16) + 0x7ff0;
+  .got           :
+  {
+    *(.got.plt) *(.got)
+   }
+  /* We want the small data sections together, so single-instruction offsets
+     can access them all, and initialized data all before uninitialized, so
+     we can shorten the on-disk segment size.  */
+  .sdata     : { *(.sdata) }
+  .lit8 : { *(.lit8) }
+  .lit4 : { *(.lit4) }
+  _edata  =  .;
+  PROVIDE (edata = .);
+  __bss_start = .;
+  _fbss = .;
+  .sbss      : { *(.sbss) *(.scommon) }
+  .bss       :
+  {
+   *(.dynbss)
+   *(.bss)
+   *(COMMON)
+  }
+  _end = . ;
+  PROVIDE (end = .);
+  /* These are needed for ELF backends which have not yet been
+     converted to the new style linker.  */
+  .stab 0 : { *(.stab) }
+  .stabstr 0 : { *(.stabstr) }
+  /* DWARF debug sections.
+     Symbols in the .debug DWARF section are relative to the beginning of the
+     section so we begin .debug at 0.  It's not clear yet what needs to happen
+     for the others.   */
+  .debug          0 : { *(.debug) }
+  .debug_srcinfo  0 : { *(.debug_srcinfo) }
+  .debug_aranges  0 : { *(.debug_aranges) }
+  .debug_pubnames 0 : { *(.debug_pubnames) }
+  .debug_sfnames  0 : { *(.debug_sfnames) }
+  .line           0 : { *(.line) }
+  /* These must appear regardless of  .  */
+  .gptab.sdata : { *(.gptab.data) *(.gptab.sdata) }
+  .gptab.sbss : { *(.gptab.bss) *(.gptab.sbss) }
+}
diff --git a/sys/arch/wgrisc/dev/ace.c b/sys/arch/wgrisc/dev/ace.c
new file mode 100644 (file)
index 0000000..0ee5e13
--- /dev/null
@@ -0,0 +1,1653 @@
+/*     $OpenBSD: ace.c,v 1.1.1.1 1997/02/06 16:02:42 pefo Exp $        */
+/*     $NetBSD: com.c,v 1.82.4.1 1996/06/02 09:08:00 mrg Exp $ */
+
+/*-
+ * Copyright (c) 1993, 1994, 1995, 1996
+ *     Charles M. Hannum.  All rights reserved.
+ * 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.
+ *
+ *     @(#)com.c       7.5 (Berkeley) 5/16/91
+ */
+
+/*
+ * ACE driver, based on HP dca driver
+ * uses National Semiconductor NS16450/NS16550AF UART
+ */
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/ioctl.h>
+#include <sys/select.h>
+#include <sys/tty.h>
+#include <sys/proc.h>
+#include <sys/user.h>
+#include <sys/conf.h>
+#include <sys/file.h>
+#include <sys/uio.h>
+#include <sys/kernel.h>
+#include <sys/syslog.h>
+#include <sys/types.h>
+#include <sys/device.h>
+
+#include <wgrisc/wgrisc/wgrisctype.h>
+#include <machine/bus.h>
+#include <machine/intr.h>
+
+#include <dev/isa/isavar.h>
+#include <dev/ic/comreg.h>
+#include <dev/ic/comvar.h>
+#include <dev/ic/ns16550reg.h>
+#ifdef COM_HAYESP
+#include <dev/ic/hayespreg.h>
+#endif
+#define        com_lcr com_cfcr
+
+#include "ace.h"
+
+
+#define        COM_IBUFSIZE    (2 * 512)
+#define        COM_IHIGHWATER  ((3 * COM_IBUFSIZE) / 4)
+
+struct com_softc {
+       struct device sc_dev;
+       void *sc_ih;
+       bus_chipset_tag_t sc_bc;
+       struct tty *sc_tty;
+
+       int sc_overflows;
+       int sc_floods;
+       int sc_errors;
+
+       int sc_halt;
+
+       int sc_iobase;
+#ifdef COM_HAYESP
+       int sc_hayespbase;
+#endif
+
+       bus_io_handle_t sc_ioh;
+       bus_io_handle_t sc_hayespioh;
+
+       u_char sc_hwflags;
+#define        COM_HW_NOIEN    0x01
+#define        COM_HW_FIFO     0x02
+#define        COM_HW_HAYESP   0x04
+#define        COM_HW_ABSENT_PENDING   0x08    /* reattached, awaiting close/reopen */
+#define        COM_HW_ABSENT   0x10            /* configure actually failed, or removed */
+#define        COM_HW_REATTACH 0x20            /* reattaching */
+#define        COM_HW_CONSOLE  0x40
+       u_char sc_swflags;
+#define        COM_SW_SOFTCAR  0x01
+#define        COM_SW_CLOCAL   0x02
+#define        COM_SW_CRTSCTS  0x04
+#define        COM_SW_MDMBUF   0x08
+       u_char sc_msr, sc_mcr, sc_lcr, sc_ier;
+       u_char sc_dtr;
+
+       u_char  sc_cua;
+
+       u_char  sc_initialize;          /* force initialization */
+
+       u_char *sc_ibuf, *sc_ibufp, *sc_ibufhigh, *sc_ibufend;
+       u_char sc_ibufs[2][COM_IBUFSIZE];
+};
+
+#ifdef COM_HAYESP
+int comprobeHAYESP __P((bus_io_handle_t hayespioh, struct com_softc *sc));
+#endif
+void   comdiag         __P((void *));
+int    comspeed        __P((long));
+int    comparam        __P((struct tty *, struct termios *));
+void   comstart        __P((struct tty *));
+void   compoll         __P((void *));
+
+/* XXX: These belong elsewhere */
+cdev_decl(com);
+bdev_decl(com);
+
+struct consdev;
+void   acecnprobe      __P((struct consdev *));
+void   acecninit       __P((struct consdev *));
+int    acecngetc       __P((dev_t));
+void   acecnputc       __P((dev_t, int));
+void   acecnpollc      __P((dev_t, int));
+
+static u_char tiocm_xxx2mcr __P((int));
+
+/*
+ * XXX the following two cfattach structs should be different, and possibly
+ * XXX elsewhere.
+ */
+int    comprobe __P((struct device *, void *, void *));
+void   comattach __P((struct device *, struct device *, void *));
+void   com_absent_notify __P((struct com_softc *sc));
+void   comstart_pending __P((void *));
+
+#if NACE_ISA
+struct cfattach ace_isa_ca = {
+       sizeof(struct com_softc), comprobe, comattach
+};
+#endif
+
+#if NACE_COMMULTI
+struct cfattach ace_commulti_ca = {
+       sizeof(struct com_softc), comprobe, comattach
+};
+#endif
+
+#if NACE_RISCBUS
+#undef  CONADDR         /* This is stupid but using devs before config .. */
+#define CONADDR 0xae400000
+
+struct cfattach ace_riscbus_ca = {
+       sizeof(struct com_softc), comprobe, comattach
+};
+#endif
+
+
+struct cfdriver ace_cd = {
+       NULL, "ace", DV_TTY
+};
+
+void cominit __P((bus_chipset_tag_t, bus_io_handle_t, int));
+
+#ifndef CONSPEED
+#define        CONSPEED B9600
+#endif
+
+#ifdef COMCONSOLE
+int    comdefaultrate = CONSPEED;              /* XXX why set default? */
+#else
+int    comdefaultrate = TTYDEF_SPEED;
+#endif
+int    comconsaddr;
+int    comconsinit;
+int    comconsattached;
+bus_chipset_tag_t comconsbc;
+bus_io_handle_t comconsioh;
+tcflag_t comconscflag = TTYDEF_CFLAG;
+
+int    commajor;
+int    comsopen = 0;
+int    comevents = 0;
+
+#ifdef KGDB
+#include <machine/remote-sl.h>
+extern int kgdb_dev;
+extern int kgdb_rate;
+extern int kgdb_debug_init;
+#endif
+
+#define        DEVUNIT(x)      (minor(x) & 0x7f)
+#define        DEVCUA(x)       (minor(x) & 0x80)
+
+/* Macros to clear/set/test flags. */
+#define        SET(t, f)       (t) |= (f)
+#define        CLR(t, f)       (t) &= ~(f)
+#define        ISSET(t, f)     ((t) & (f))
+
+/*
+ * must be called at spltty() or higher.
+ */
+void
+com_absent_notify(sc)
+       struct com_softc *sc;
+{
+       struct tty *tp = sc->sc_tty;
+
+       if (tp) {
+               CLR(tp->t_state, TS_CARR_ON|TS_BUSY);
+               ttyflush(tp, FREAD|FWRITE);
+       }
+}
+
+int
+comspeed(speed)
+       long speed;
+{
+#define        divrnd(n, q)    (((n)*2/(q)+1)/2)       /* divide and round off */
+
+       int x, err;
+
+       if (speed == 0)
+               return 0;
+       if (speed < 0)
+               return -1;
+       x = divrnd((COM_FREQ / 16), speed);
+       if (x <= 0)
+               return -1;
+       err = divrnd((COM_FREQ / 16) * 1000, speed * x) - 1000;
+       if (err < 0)
+               err = -err;
+       if (err > COM_TOLERANCE)
+               return -1;
+       return x;
+
+#undef divrnd(n, q)
+}
+
+int
+comprobe1(bc, ioh, iobase)
+       bus_chipset_tag_t bc;
+       bus_io_handle_t ioh;
+       int iobase;
+{
+       int i, k;
+
+       /* force access to id reg */
+       bus_io_write_1(bc, ioh, com_lcr, 0);
+       bus_io_write_1(bc, ioh, com_iir, 0);
+       for (i = 0; i < 32; i++) {
+           k = bus_io_read_1(bc, ioh, com_iir);
+           if (k & 0x38) {
+               bus_io_read_1(bc, ioh, com_data); /* cleanup */
+           } else
+               break;
+       }
+       if (i >= 32) 
+           return 0;
+
+       return 1;
+}
+
+#ifdef COM_HAYESP
+int
+comprobeHAYESP(hayespioh, sc)
+       bus_io_handle_t hayespioh;
+       struct com_softc *sc;
+{
+       char    val, dips;
+       int     combaselist[] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8 };
+       bus_chipset_tag_t bc = sc->sc_bc;
+
+       /*
+        * Hayes ESP cards have two iobases.  One is for compatibility with
+        * 16550 serial chips, and at the same ISA PC base addresses.  The
+        * other is for ESP-specific enhanced features, and lies at a
+        * different addressing range entirely (0x140, 0x180, 0x280, or 0x300).
+        */
+
+       /* Test for ESP signature */
+       if ((bus_io_read_1(bc, hayespioh, 0) & 0xf3) == 0)
+               return 0;
+
+       /*
+        * ESP is present at ESP enhanced base address; unknown com port
+        */
+
+       /* Get the dip-switch configurations */
+       bus_io_write_1(bc, hayespioh, HAYESP_CMD1, HAYESP_GETDIPS);
+       dips = bus_io_read_1(bc, hayespioh, HAYESP_STATUS1);
+
+       /* Determine which com port this ESP card services: bits 0,1 of  */
+       /*  dips is the port # (0-3); combaselist[val] is the com_iobase */
+       if (sc->sc_iobase != combaselist[dips & 0x03])
+               return 0;
+
+       printf(": ESP");
+
+       /* Check ESP Self Test bits. */
+       /* Check for ESP version 2.0: bits 4,5,6 == 010 */
+       bus_io_write_1(bc, hayespioh, HAYESP_CMD1, HAYESP_GETTEST);
+       val = bus_io_read_1(bc, hayespioh, HAYESP_STATUS1); /* Clear reg 1 */
+       val = bus_io_read_1(bc, hayespioh, HAYESP_STATUS2);
+       if ((val & 0x70) < 0x20) {
+               printf("-old (%o)", val & 0x70);
+               /* we do not support the necessary features */
+               return 0;
+       }
+
+       /* Check for ability to emulate 16550: bit 8 == 1 */
+       if ((dips & 0x80) == 0) {
+               printf(" slave");
+               /* XXX Does slave really mean no 16550 support?? */
+               return 0;
+       }
+
+       /*
+        * If we made it this far, we are a full-featured ESP v2.0 (or
+        * better), at the correct com port address.
+        */
+
+       SET(sc->sc_hwflags, COM_HW_HAYESP);
+       printf(", 1024 byte fifo\n");
+       return 1;
+}
+#endif
+
+int
+comprobe(parent, match, aux)
+       struct device *parent;
+       void *match, *aux;
+{
+       bus_chipset_tag_t bc;
+       bus_io_handle_t ioh;
+       int iobase, needioh;
+       int rv = 1;
+
+#if NACE_ISA
+#define IS_ISA(parent) \
+       (!strcmp((parent)->dv_cfdata->cf_driver->cd_name, "isa") || \
+        !strcmp((parent)->dv_cfdata->cf_driver->cd_name, "pcmcia"))
+#elif NACE_ISA
+#define IS_ISA(parent) \
+       !strcmp((parent)->dv_cfdata->cf_driver->cd_name, "isa")
+#endif
+#if NACE_RISCBUS
+#define IS_RISCBUS(parent) \
+       !strcmp((parent)->dv_cfdata->cf_driver->cd_name, "riscbus")
+#endif
+       /*
+        * XXX should be broken out into functions for isa probe and
+        * XXX for commulti probe, with a helper function that contains
+        * XXX most of the interesting stuff.
+        */
+#if NACE_ISA
+       if (IS_ISA(parent)) {
+               struct isa_attach_args *ia = aux;
+
+               bc = ia->ia_bc;
+               iobase = ia->ia_iobase;
+               needioh = 1;
+       } else
+#endif
+#if NACE_RISCBUS
+       if(IS_RISCBUS(parent)) {
+               struct confargs *ca = aux;
+               if(!BUS_MATCHNAME(ca, "com"))
+                       return(0);
+               iobase = (long)BUS_CVTADDR(ca);
+               bc = 0;
+               needioh = 1;
+       } else
+#endif
+#if NACE_COMMULTI
+       if (1) {
+               struct cfdata *cf = match;
+               struct commulti_attach_args *ca = aux;
+               if (cf->cf_loc[0] != -1 && cf->cf_loc[0] != ca->ca_slave)
+                       return (0);
+
+               bc = ca->ca_bc;
+               iobase = ca->ca_iobase;
+               ioh = ca->ca_ioh;
+               needioh = 0;
+       } else
+#endif
+               return(0);                      /* This cannot happen */
+
+       /* if it's in use as console, it's there. */
+       if (iobase == comconsaddr && !comconsattached)
+               goto out;
+
+       if (needioh && bus_io_map(bc, iobase, COM_NPORTS, &ioh)) {
+               rv = 0;
+               goto out;
+       }
+       rv = comprobe1(bc, ioh, iobase);
+       if (needioh)
+               bus_io_unmap(bc, ioh, COM_NPORTS);
+
+out:
+#if NACE_ISA
+       if (rv && IS_ISA(parent)) {
+               struct isa_attach_args *ia = aux;
+
+               ia->ia_iosize = COM_NPORTS;
+               ia->ia_msize = 0;
+       }
+#endif
+       return (rv);
+}
+
+void
+comattach(parent, self, aux)
+       struct device *parent, *self;
+       void *aux;
+{
+       struct com_softc *sc = (void *)self;
+       int iobase, irq;
+       bus_chipset_tag_t bc;
+       bus_io_handle_t ioh;
+#ifdef COM_HAYESP
+       int     hayesp_ports[] = { 0x140, 0x180, 0x280, 0x300, 0 };
+       int     *hayespp;
+#endif
+
+       /*
+        * XXX should be broken out into functions for isa attach and
+        * XXX for commulti attach, with a helper function that contains
+        * XXX most of the interesting stuff.
+        */
+       if (ISSET(sc->sc_hwflags, COM_HW_REATTACH)) {
+               int s;
+               s = spltty();
+               com_absent_notify(sc);
+               splx(s);
+       } else
+           sc->sc_hwflags = 0;
+       sc->sc_swflags = 0;
+#if NACE_ISA
+       if (IS_ISA(parent)) {
+               struct isa_attach_args *ia = aux;
+
+               /*
+                * We're living on an isa.
+                */
+               iobase = ia->ia_iobase;
+               bc = ia->ia_bc;
+               if (iobase != comconsaddr) {
+                       if (bus_io_map(bc, iobase, COM_NPORTS, &ioh))
+                               panic("comattach: io mapping failed");
+               } else
+                       ioh = comconsioh;
+               irq = ia->ia_irq;
+       } else
+#endif
+#if NACE_RISCBUS
+       if(IS_RISCBUS(parent)) {
+               struct confargs *ca = aux;
+               iobase = (long)BUS_CVTADDR(ca);
+               bc = 0;
+               irq = 0;
+               ioh = iobase;
+       } else
+#endif
+#if NACE_COMMULTI
+       if (1) {
+               struct commulti_attach_args *ca = aux;
+
+               /*
+                * We're living on a commulti.
+                */
+               iobase = ca->ca_iobase;
+               bc = ca->ca_bc;
+               ioh = ca->ca_ioh;
+               irq = IRQUNK;
+
+               if (ca->ca_noien)
+                       SET(sc->sc_hwflags, COM_HW_NOIEN);
+       } else
+#endif
+               panic("comattach: impossible");
+
+       sc->sc_bc = bc;
+       sc->sc_ioh = ioh;
+       sc->sc_iobase = iobase;
+
+       if (iobase == comconsaddr) {
+               comconsattached = 1;
+
+               /* 
+                * Need to reset baud rate, etc. of next print so reset
+                * comconsinit.  Also make sure console is always "hardwired".
+                */
+               delay(1000);                    /* wait for output to finish */
+               comconsinit = 0;
+               SET(sc->sc_hwflags, COM_HW_CONSOLE);
+               SET(sc->sc_swflags, COM_SW_SOFTCAR);
+       }
+
+#ifdef COM_HAYESP
+       /* Look for a Hayes ESP board. */
+       for (hayespp = hayesp_ports; *hayespp != 0; hayespp++) {
+               bus_io_handle_t hayespioh;
+
+#define        HAYESP_NPORTS   8                       /* XXX XXX XXX ??? ??? ??? */
+               if (bus_io_map(bc, *hayespp, HAYESP_NPORTS, &hayespioh))
+                       continue;
+               if (comprobeHAYESP(hayespioh, sc)) {
+                       sc->sc_hayespbase = *hayespp;
+                       sc->sc_hayespioh = hayespioh;
+                       break;
+               }
+               bus_io_unmap(bc, hayespioh, HAYESP_NPORTS);
+       }
+       /* No ESP; look for other things. */
+       if (*hayespp == 0) {
+#endif
+
+       /* look for a NS 16550AF UART with FIFOs */
+       bus_io_write_1(bc, ioh, com_fifo,
+           FIFO_ENABLE | FIFO_RCV_RST | FIFO_XMT_RST | FIFO_TRIGGER_14);
+       delay(100);
+       if (ISSET(bus_io_read_1(bc, ioh, com_iir), IIR_FIFO_MASK) ==
+           IIR_FIFO_MASK)
+               if (ISSET(bus_io_read_1(bc, ioh, com_fifo), FIFO_TRIGGER_14) ==
+                   FIFO_TRIGGER_14) {
+                       SET(sc->sc_hwflags, COM_HW_FIFO);
+                       printf(": ns16550a, working fifo\n");
+               } else
+                       printf(": ns16550, broken fifo\n");
+       else
+               printf(": ns8250 or ns16450, no fifo\n");
+       bus_io_write_1(bc, ioh, com_fifo, 0);
+#ifdef COM_HAYESP
+       }
+#endif
+
+       /* disable interrupts */
+       bus_io_write_1(bc, ioh, com_ier, 0);
+       bus_io_write_1(bc, ioh, com_mcr, 0);
+
+       if (irq != IRQUNK) {
+#if NACE_ISA
+               if (IS_ISA(parent)) {
+                       struct isa_attach_args *ia = aux;
+
+                       sc->sc_ih = isa_intr_establish(ia->ia_ic, irq,
+                           IST_EDGE, IPL_TTY, comintr, sc,
+                           sc->sc_dev.dv_xname);
+               } else
+#endif
+#if NACE_RISCBUS
+               if (IS_RISCBUS(parent)) {
+                       struct confargs *ca = aux;
+                       BUS_INTR_ESTABLISH(ca, comintr, (void *)(long)sc);
+               } else
+#endif
+                       panic("comattach: IRQ but can't have one");
+       }
+
+#ifdef KGDB
+       if (kgdb_dev == makedev(commajor, unit)) {
+               if (ISSET(sc->sc_hwflags, COM_HW_CONSOLE))
+                       kgdb_dev = -1;  /* can't debug over console port */
+               else {
+                       cominit(bc, ioh, kgdb_rate);
+                       if (kgdb_debug_init) {
+                               /*
+                                * Print prefix of device name,
+                                * let kgdb_connect print the rest.
+                                */
+                               printf("%s: ", sc->sc_dev.dv_xname);
+                               kgdb_connect(1);
+                       } else
+                               printf("%s: kgdb enabled\n",
+                                   sc->sc_dev.dv_xname);
+               }
+       }
+#endif
+
+       /* XXX maybe move up some? */
+       if (ISSET(sc->sc_hwflags, COM_HW_CONSOLE))
+               printf("%s: console\n", sc->sc_dev.dv_xname);
+}
+
+int
+aceopen(dev, flag, mode, p)
+       dev_t dev;
+       int flag, mode;
+       struct proc *p;
+{
+       int unit = DEVUNIT(dev);
+       struct com_softc *sc;
+       bus_chipset_tag_t bc;
+       bus_io_handle_t ioh;
+       struct tty *tp;
+       int s;
+       int error = 0;
+       if (unit >= ace_cd.cd_ndevs)
+               return ENXIO;
+       sc = ace_cd.cd_devs[unit];
+       if (!sc || ISSET(sc->sc_hwflags, COM_HW_ABSENT|COM_HW_ABSENT_PENDING))
+               return ENXIO;
+
+       s = spltty();
+       if (!sc->sc_tty) {
+               tp = sc->sc_tty = ttymalloc();
+               tty_attach(tp);
+       } else
+               tp = sc->sc_tty;
+       splx(s);
+
+       tp->t_oproc = comstart;
+       tp->t_param = comparam;
+       tp->t_dev = dev;
+       if (!ISSET(tp->t_state, TS_ISOPEN)) {
+               SET(tp->t_state, TS_WOPEN);
+               ttychars(tp);
+               tp->t_iflag = TTYDEF_IFLAG;
+               tp->t_oflag = TTYDEF_OFLAG;
+               if (ISSET(sc->sc_hwflags, COM_HW_CONSOLE))
+                       tp->t_cflag = comconscflag;
+               else
+                       tp->t_cflag = TTYDEF_CFLAG;
+               if (ISSET(sc->sc_swflags, COM_SW_CLOCAL))
+                       SET(tp->t_cflag, CLOCAL);
+               if (ISSET(sc->sc_swflags, COM_SW_CRTSCTS))
+                       SET(tp->t_cflag, CRTSCTS);
+               if (ISSET(sc->sc_swflags, COM_SW_MDMBUF))
+                       SET(tp->t_cflag, MDMBUF);
+               tp->t_lflag = TTYDEF_LFLAG;
+               tp->t_ispeed = tp->t_ospeed = comdefaultrate;
+
+               s = spltty();
+
+               sc->sc_initialize = 1;
+               comparam(tp, &tp->t_termios);
+               ttsetwater(tp);
+
+               if (comsopen++ == 0)
+                       timeout(compoll, NULL, 1);
+
+               sc->sc_ibufp = sc->sc_ibuf = sc->sc_ibufs[0];
+               sc->sc_ibufhigh = sc->sc_ibuf + COM_IHIGHWATER;
+               sc->sc_ibufend = sc->sc_ibuf + COM_IBUFSIZE;
+
+               bc = sc->sc_bc;
+               ioh = sc->sc_ioh;
+#ifdef COM_HAYESP
+               /* Setup the ESP board */
+               if (ISSET(sc->sc_hwflags, COM_HW_HAYESP)) {
+                       bus_io_handle_t hayespioh = sc->sc_hayespioh;
+
+                       bus_io_write_1(bc, ioh, com_fifo,
+                            FIFO_DMA_MODE|FIFO_ENABLE|
+                            FIFO_RCV_RST|FIFO_XMT_RST|FIFO_TRIGGER_8);
+
+                       /* Set 16550 compatibility mode */
+                       bus_io_write_1(bc, hayespioh, HAYESP_CMD1, HAYESP_SETMODE);
+                       bus_io_write_1(bc, hayespioh, HAYESP_CMD2, 
+                            HAYESP_MODE_FIFO|HAYESP_MODE_RTS|
+                            HAYESP_MODE_SCALE);
+
+                       /* Set RTS/CTS flow control */
+                       bus_io_write_1(bc, hayespioh, HAYESP_CMD1, HAYESP_SETFLOWTYPE);
+                       bus_io_write_1(bc, hayespioh, HAYESP_CMD2, HAYESP_FLOW_RTS);
+                       bus_io_write_1(bc, hayespioh, HAYESP_CMD2, HAYESP_FLOW_CTS);
+
+                       /* Set flow control levels */
+                       bus_io_write_1(bc, hayespioh, HAYESP_CMD1, HAYESP_SETRXFLOW);
+                       bus_io_write_1(bc, hayespioh, HAYESP_CMD2, 
+                            HAYESP_HIBYTE(HAYESP_RXHIWMARK));
+                       bus_io_write_1(bc, hayespioh, HAYESP_CMD2,
+                            HAYESP_LOBYTE(HAYESP_RXHIWMARK));
+                       bus_io_write_1(bc, hayespioh, HAYESP_CMD2,
+                            HAYESP_HIBYTE(HAYESP_RXLOWMARK));
+                       bus_io_write_1(bc, hayespioh, HAYESP_CMD2,
+                            HAYESP_LOBYTE(HAYESP_RXLOWMARK));
+               } else
+#endif
+               if (ISSET(sc->sc_hwflags, COM_HW_FIFO)) {
+                       /*
+                        * (Re)enable and drain FIFOs.
+                        *
+                        * Certain SMC chips cause problems if the FIFOs are
+                        * enabled while input is ready. Turn off the FIFO
+                        * if necessary to clear the input. Test the input
+                        * ready bit after enabling the FIFOs to handle races
+                        * between enabling and fresh input.
+                        *
+                        * Set the FIFO threshold based on the receive speed.
+                        */
+                       for (;;) {
+                               bus_io_write_1(bc, ioh, com_fifo, 0);
+                               delay(100);
+                               (void) bus_io_read_1(bc, ioh, com_data);
+                               bus_io_write_1(bc, ioh, com_fifo,
+                                   FIFO_ENABLE | FIFO_RCV_RST | FIFO_XMT_RST |
+                                   (tp->t_ispeed <= 1200 ?
+                                   FIFO_TRIGGER_1 : FIFO_TRIGGER_8));
+                               delay(100);
+                               if(!ISSET(bus_io_read_1(bc, ioh,
+                                   com_lsr), LSR_RXRDY))
+                                       break;
+                       }
+               }
+
+               /* flush any pending I/O */
+               while (ISSET(bus_io_read_1(bc, ioh, com_lsr), LSR_RXRDY))
+                       (void) bus_io_read_1(bc, ioh, com_data);
+               /* you turn me on, baby */
+               sc->sc_mcr = MCR_DTR | MCR_RTS;
+               if (!ISSET(sc->sc_hwflags, COM_HW_NOIEN))
+                       SET(sc->sc_mcr, MCR_IENABLE);
+               bus_io_write_1(bc, ioh, com_mcr, sc->sc_mcr);
+               sc->sc_ier = IER_ERXRDY | IER_ERLS | IER_EMSC;
+               bus_io_write_1(bc, ioh, com_ier, sc->sc_ier);
+
+               sc->sc_msr = bus_io_read_1(bc, ioh, com_msr);
+               if (ISSET(sc->sc_swflags, COM_SW_SOFTCAR) || DEVCUA(dev) ||
+                   ISSET(sc->sc_msr, MSR_DCD) || ISSET(tp->t_cflag, MDMBUF))
+                       SET(tp->t_state, TS_CARR_ON);
+               else
+                       CLR(tp->t_state, TS_CARR_ON);
+       } else if (ISSET(tp->t_state, TS_XCLUDE) && p->p_ucred->cr_uid != 0)
+               return EBUSY;
+       else
+               s = spltty();
+
+       if (DEVCUA(dev)) {
+               if (ISSET(tp->t_state, TS_ISOPEN)) {
+                       /* Ah, but someone already is dialed in... */
+                       splx(s);
+                       return EBUSY;
+               }
+               sc->sc_cua = 1;         /* We go into CUA mode */
+       }
+
+       /* wait for carrier if necessary */
+       if (ISSET(flag, O_NONBLOCK)) {
+               if (!DEVCUA(dev) && sc->sc_cua) {
+                       /* Opening TTY non-blocking... but the CUA is busy */
+                       splx(s);
+                       return EBUSY;
+               }
+       } else {
+               while (!(DEVCUA(dev) && sc->sc_cua) &&
+                   !ISSET(tp->t_cflag, CLOCAL) &&
+                   !ISSET(tp->t_state, TS_CARR_ON)) {
+                       SET(tp->t_state, TS_WOPEN);
+                       error = ttysleep(tp, &tp->t_rawq, TTIPRI | PCATCH,
+                           ttopen, 0);
+                       if (error) {
+                               /* XXX should turn off chip if we're the
+                                  only waiter */
+                               if (DEVCUA(dev))
+                                       sc->sc_cua = 0;
+                               splx(s);
+                               return error;
+                       }
+               }
+       }
+       splx(s);
+
+       return (*linesw[tp->t_line].l_open)(dev, tp);
+}
+int
+aceclose(dev, flag, mode, p)
+       dev_t dev;
+       int flag, mode;
+       struct proc *p;
+{
+       int unit = DEVUNIT(dev);
+       struct com_softc *sc = ace_cd.cd_devs[unit];
+       struct tty *tp = sc->sc_tty;
+       bus_chipset_tag_t bc = sc->sc_bc;
+       bus_io_handle_t ioh = sc->sc_ioh;
+       int s;
+
+       /* XXX This is for cons.c. */
+       if (!ISSET(tp->t_state, TS_ISOPEN))
+               return 0;
+
+       (*linesw[tp->t_line].l_close)(tp, flag);
+       s = spltty();
+       if (!ISSET(sc->sc_hwflags, COM_HW_ABSENT|COM_HW_ABSENT_PENDING)) {
+               /* can't do any of this stuff .... */
+               CLR(sc->sc_lcr, LCR_SBREAK);
+               bus_io_write_1(bc, ioh, com_lcr, sc->sc_lcr);
+               bus_io_write_1(bc, ioh, com_ier, 0);
+               if (ISSET(tp->t_cflag, HUPCL) &&
+                   !ISSET(sc->sc_swflags, COM_SW_SOFTCAR)) {
+                       /* XXX perhaps only clear DTR */
+                       bus_io_write_1(bc, ioh, com_mcr, 0);
+               }
+       }
+       CLR(tp->t_state, TS_BUSY | TS_FLUSH);
+       if (--comsopen == 0)
+               untimeout(compoll, NULL);
+       sc->sc_cua = 0;
+       splx(s);
+       ttyclose(tp);
+#ifdef COM_DEBUG
+       /* mark it ready for more use if reattached earlier */
+       if (ISSET(sc->sc_hwflags, COM_HW_ABSENT_PENDING)) {
+           printf("aceclose pending cleared\n");
+       }
+#endif
+       CLR(sc->sc_hwflags, COM_HW_ABSENT_PENDING);
+
+#ifdef notyet /* XXXX */
+       if (ISSET(sc->sc_hwflags, COM_HW_CONSOLE)) {
+               ttyfree(tp);
+               sc->sc_tty = 0;
+       }
+#endif
+       return 0;
+}
+int
+aceread(dev, uio, flag)
+       dev_t dev;
+       struct uio *uio;
+       int flag;
+{
+       struct com_softc *sc = ace_cd.cd_devs[DEVUNIT(dev)];
+       struct tty *tp = sc->sc_tty;
+       if (ISSET(sc->sc_hwflags, COM_HW_ABSENT|COM_HW_ABSENT_PENDING)) {
+               int s = spltty();
+               com_absent_notify(sc);
+               splx(s);
+               return EIO;
+       }
+
+       return ((*linesw[tp->t_line].l_read)(tp, uio, flag));
+}
+int
+acewrite(dev, uio, flag)
+       dev_t dev;
+       struct uio *uio;
+       int flag;
+{
+       struct com_softc *sc = ace_cd.cd_devs[DEVUNIT(dev)];
+       struct tty *tp = sc->sc_tty;
+       if (ISSET(sc->sc_hwflags, COM_HW_ABSENT|COM_HW_ABSENT_PENDING)) {
+               int s = spltty();
+               com_absent_notify(sc);
+               splx(s);
+               return EIO;
+       }
+
+       return ((*linesw[tp->t_line].l_write)(tp, uio, flag));
+}
+
+struct tty *
+acetty(dev)
+       dev_t dev;
+{
+       struct com_softc *sc = ace_cd.cd_devs[DEVUNIT(dev)];
+       struct tty *tp = sc->sc_tty;
+
+       return (tp);
+}
+static u_char
+tiocm_xxx2mcr(data)
+       int data;
+{
+       u_char m = 0;
+
+       if (ISSET(data, TIOCM_DTR))
+               SET(m, MCR_DTR);
+       if (ISSET(data, TIOCM_RTS))
+               SET(m, MCR_RTS);
+       return m;
+}
+
+int
+aceioctl(dev, cmd, data, flag, p)
+       dev_t dev;
+       u_long cmd;
+       caddr_t data;
+       int flag;
+       struct proc *p;
+{
+       int unit = DEVUNIT(dev);
+       struct com_softc *sc = ace_cd.cd_devs[unit];
+       struct tty *tp = sc->sc_tty;
+       bus_chipset_tag_t bc = sc->sc_bc;
+       bus_io_handle_t ioh = sc->sc_ioh;
+       int error;
+
+       if (ISSET(sc->sc_hwflags, COM_HW_ABSENT|COM_HW_ABSENT_PENDING)) {
+               int s = spltty();
+               com_absent_notify(sc);
+               splx(s);
+               return EIO;
+       }
+
+       error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p);
+       if (error >= 0)
+               return error;
+       error = ttioctl(tp, cmd, data, flag, p);
+       if (error >= 0)
+               return error;
+
+       switch (cmd) {
+       case TIOCSBRK:
+               SET(sc->sc_lcr, LCR_SBREAK);
+               bus_io_write_1(bc, ioh, com_lcr, sc->sc_lcr);
+               break;
+       case TIOCCBRK:
+               CLR(sc->sc_lcr, LCR_SBREAK);
+               bus_io_write_1(bc, ioh, com_lcr, sc->sc_lcr);
+               break;
+       case TIOCSDTR:
+               SET(sc->sc_mcr, sc->sc_dtr);
+               bus_io_write_1(bc, ioh, com_mcr, sc->sc_mcr);
+               break;
+       case TIOCCDTR:
+               CLR(sc->sc_mcr, sc->sc_dtr);
+               bus_io_write_1(bc, ioh, com_mcr, sc->sc_mcr);
+               break;
+       case TIOCMSET:
+               CLR(sc->sc_mcr, MCR_DTR | MCR_RTS);
+       case TIOCMBIS:
+               SET(sc->sc_mcr, tiocm_xxx2mcr(*(int *)data));
+               bus_io_write_1(bc, ioh, com_mcr, sc->sc_mcr);
+               break;
+       case TIOCMBIC:
+               CLR(sc->sc_mcr, tiocm_xxx2mcr(*(int *)data));
+               bus_io_write_1(bc, ioh, com_mcr, sc->sc_mcr);
+               break;
+       case TIOCMGET: {
+               u_char m;
+               int bits = 0;
+
+               m = sc->sc_mcr;
+               if (ISSET(m, MCR_DTR))
+                       SET(bits, TIOCM_DTR);
+               if (ISSET(m, MCR_RTS))
+                       SET(bits, TIOCM_RTS);
+               m = sc->sc_msr;
+               if (ISSET(m, MSR_DCD))
+                       SET(bits, TIOCM_CD);
+               if (ISSET(m, MSR_CTS))
+                       SET(bits, TIOCM_CTS);
+               if (ISSET(m, MSR_DSR))
+                       SET(bits, TIOCM_DSR);
+               if (ISSET(m, MSR_RI | MSR_TERI))
+                       SET(bits, TIOCM_RI);
+               if (bus_io_read_1(bc, ioh, com_ier))
+                       SET(bits, TIOCM_LE);
+               *(int *)data = bits;
+               break;
+       }
+       case TIOCGFLAGS: {
+               int driverbits, userbits = 0;
+
+               driverbits = sc->sc_swflags;
+               if (ISSET(driverbits, COM_SW_SOFTCAR))
+                       SET(userbits, TIOCFLAG_SOFTCAR);
+               if (ISSET(driverbits, COM_SW_CLOCAL))
+                       SET(userbits, TIOCFLAG_CLOCAL);
+               if (ISSET(driverbits, COM_SW_CRTSCTS))
+                       SET(userbits, TIOCFLAG_CRTSCTS);
+               if (ISSET(driverbits, COM_SW_MDMBUF))
+                       SET(userbits, TIOCFLAG_MDMBUF);
+
+               *(int *)data = userbits;
+               break;
+       }
+       case TIOCSFLAGS: {
+               int userbits, driverbits = 0;
+
+               error = suser(p->p_ucred, &p->p_acflag); 
+               if (error != 0)
+                       return(EPERM); 
+
+               userbits = *(int *)data;
+               if (ISSET(userbits, TIOCFLAG_SOFTCAR) ||
+                   ISSET(sc->sc_hwflags, COM_HW_CONSOLE))
+                       SET(driverbits, COM_SW_SOFTCAR);
+               if (ISSET(userbits, TIOCFLAG_CLOCAL))
+                       SET(driverbits, COM_SW_CLOCAL);
+               if (ISSET(userbits, TIOCFLAG_CRTSCTS))
+                       SET(driverbits, COM_SW_CRTSCTS);
+               if (ISSET(userbits, TIOCFLAG_MDMBUF))
+                       SET(driverbits, COM_SW_MDMBUF);
+
+               sc->sc_swflags = driverbits;
+               break;
+       }
+       default:
+               return ENOTTY;
+       }
+
+       return 0;
+}
+
+int
+comparam(tp, t)
+       struct tty *tp;
+       struct termios *t;
+{
+       struct com_softc *sc = ace_cd.cd_devs[DEVUNIT(tp->t_dev)];
+       bus_chipset_tag_t bc = sc->sc_bc;
+       bus_io_handle_t ioh = sc->sc_ioh;
+       int ospeed = comspeed(t->c_ospeed);
+       u_char lcr;
+       tcflag_t oldcflag;
+       int s;
+
+       if (ISSET(sc->sc_hwflags, COM_HW_ABSENT|COM_HW_ABSENT_PENDING)) {
+               int s = spltty();
+               com_absent_notify(sc);
+               splx(s);
+               return EIO;
+       }
+
+       /* check requested parameters */
+       if (ospeed < 0 || (t->c_ispeed && t->c_ispeed != t->c_ospeed))
+               return EINVAL;
+
+       lcr = ISSET(sc->sc_lcr, LCR_SBREAK);
+
+       switch (ISSET(t->c_cflag, CSIZE)) {
+       case CS5:
+               SET(lcr, LCR_5BITS);
+               break;
+       case CS6:
+               SET(lcr, LCR_6BITS);
+               break;
+       case CS7:
+               SET(lcr, LCR_7BITS);
+               break;
+       case CS8:
+               SET(lcr, LCR_8BITS);
+               break;
+       }
+       if (ISSET(t->c_cflag, PARENB)) {
+               SET(lcr, LCR_PENAB);
+               if (!ISSET(t->c_cflag, PARODD))
+                       SET(lcr, LCR_PEVEN);
+       }
+       if (ISSET(t->c_cflag, CSTOPB))
+               SET(lcr, LCR_STOPB);
+
+       sc->sc_lcr = lcr;
+
+       s = spltty();
+
+       if (ospeed == 0) {
+               CLR(sc->sc_mcr, MCR_DTR);
+               bus_io_write_1(bc, ioh, com_mcr, sc->sc_mcr);
+       }
+
+       /*
+        * Set the FIFO threshold based on the receive speed, if we are
+        * changing it.
+        */
+       if (sc->sc_initialize || (tp->t_ispeed != t->c_ispeed)) {
+               sc->sc_initialize = 0;
+
+               if (ospeed != 0) {
+                       /*
+                        * Make sure the transmit FIFO is empty before
+                        * proceeding.  If we don't do this, some revisions
+                        * of the UART will hang.  Interestingly enough,
+                        * even if we do this will the last character is
+                        * still being pushed out, they don't hang.  This
+                        * seems good enough.
+                        */
+                       while (ISSET(tp->t_state, TS_BUSY)) {
+                               int error;
+
+                               ++sc->sc_halt;
+                               error = ttysleep(tp, &tp->t_outq,
+                                   TTOPRI | PCATCH, "comprm", 0);
+                               --sc->sc_halt;
+                               if (error) {
+                                       splx(s);
+                                       comstart(tp);
+                                       return (error);
+                               }
+                       }
+
+                       bus_io_write_1(bc, ioh, com_lcr, lcr | LCR_DLAB);
+                       bus_io_write_1(bc, ioh, com_dlbl, ospeed);
+                       bus_io_write_1(bc, ioh, com_dlbh, ospeed >> 8);
+                       bus_io_write_1(bc, ioh, com_lcr, lcr);
+                       SET(sc->sc_mcr, MCR_DTR);
+                       bus_io_write_1(bc, ioh, com_mcr, sc->sc_mcr);
+               } else
+                       bus_io_write_1(bc, ioh, com_lcr, lcr);
+
+               if (!ISSET(sc->sc_hwflags, COM_HW_HAYESP) &&
+                   ISSET(sc->sc_hwflags, COM_HW_FIFO))
+                       bus_io_write_1(bc, ioh, com_fifo,
+                           FIFO_ENABLE |
+                           (t->c_ispeed <= 1200 ? FIFO_TRIGGER_1 : FIFO_TRIGGER_8));
+       } else
+               bus_io_write_1(bc, ioh, com_lcr, lcr);
+
+       /* When not using CRTSCTS, RTS follows DTR. */
+       if (!ISSET(t->c_cflag, CRTSCTS)) {
+               if (ISSET(sc->sc_mcr, MCR_DTR)) {
+                       if (!ISSET(sc->sc_mcr, MCR_RTS)) {
+                               SET(sc->sc_mcr, MCR_RTS);
+                               bus_io_write_1(bc, ioh, com_mcr, sc->sc_mcr);
+                       }
+               } else {
+                       if (ISSET(sc->sc_mcr, MCR_RTS)) {
+                               CLR(sc->sc_mcr, MCR_RTS);
+                               bus_io_write_1(bc, ioh, com_mcr, sc->sc_mcr);
+                       }
+               }
+               sc->sc_dtr = MCR_DTR | MCR_RTS;
+       } else
+               sc->sc_dtr = MCR_DTR;
+
+       /* and copy to tty */
+       tp->t_ispeed = t->c_ispeed;
+       tp->t_ospeed = t->c_ospeed;
+       oldcflag = tp->t_cflag;
+       tp->t_cflag = t->c_cflag;
+
+       /*
+        * If DCD is off and MDMBUF is changed, ask the tty layer if we should
+        * stop the device.
+        */
+       if (!ISSET(sc->sc_msr, MSR_DCD) &&
+           !ISSET(sc->sc_swflags, COM_SW_SOFTCAR) &&
+           ISSET(oldcflag, MDMBUF) != ISSET(tp->t_cflag, MDMBUF) &&
+           (*linesw[tp->t_line].l_modem)(tp, 0) == 0) {
+               CLR(sc->sc_mcr, sc->sc_dtr);
+               bus_io_write_1(bc, ioh, com_mcr, sc->sc_mcr);
+       }
+
+       /* Just to be sure... */
+       splx(s);
+       comstart(tp);
+       return 0;
+}
+
+void
+comstart_pending(arg)
+       void *arg;
+{
+       struct com_softc *sc = arg;
+       int s;
+
+       s = spltty();
+       com_absent_notify(sc);
+       splx(s);
+}
+
+void
+comstart(tp)
+       struct tty *tp;
+{
+       struct com_softc *sc = ace_cd.cd_devs[DEVUNIT(tp->t_dev)];
+       bus_chipset_tag_t bc = sc->sc_bc;
+       bus_io_handle_t ioh = sc->sc_ioh;
+       int s;
+
+       s = spltty();
+       if (ISSET(sc->sc_hwflags, COM_HW_ABSENT|COM_HW_ABSENT_PENDING)) {
+               /*
+                * not quite good enough: if caller is ttywait() it will
+                * go to sleep immediately, so hang out a bit and then
+                * prod caller again.
+                */
+               com_absent_notify(sc);
+               timeout(comstart_pending, sc, 1);
+               goto out;
+       }
+       if (ISSET(tp->t_state, TS_BUSY))
+               goto out;
+       if (ISSET(tp->t_state, TS_TIMEOUT | TS_TTSTOP) ||
+           sc->sc_halt > 0)
+               goto stopped;
+       if (ISSET(tp->t_cflag, CRTSCTS) && !ISSET(sc->sc_msr, MSR_CTS))
+               goto stopped;
+       if (tp->t_outq.c_cc <= tp->t_lowat) {
+               if (ISSET(tp->t_state, TS_ASLEEP)) {
+                       CLR(tp->t_state, TS_ASLEEP);
+                       wakeup(&tp->t_outq);
+               }
+               if (tp->t_outq.c_cc == 0)
+                       goto stopped;
+               selwakeup(&tp->t_wsel);
+       }
+       SET(tp->t_state, TS_BUSY);
+
+       if (!ISSET(sc->sc_ier, IER_ETXRDY)) {
+               SET(sc->sc_ier, IER_ETXRDY);
+               bus_io_write_1(bc, ioh, com_ier, sc->sc_ier);
+       }
+#ifdef COM_HAYESP
+       if (ISSET(sc->sc_hwflags, COM_HW_HAYESP)) {
+               u_char buffer[1024], *cp = buffer;
+               int n = q_to_b(&tp->t_outq, cp, sizeof buffer);
+               do
+                       bus_io_write_1(bc, ioh, com_data, *cp++);
+               while (--n);
+       }
+       else
+#endif
+       if (ISSET(sc->sc_hwflags, COM_HW_FIFO)) {
+               u_char buffer[16], *cp = buffer;
+               int n = q_to_b(&tp->t_outq, cp, sizeof buffer);
+               do {
+                       bus_io_write_1(bc, ioh, com_data, *cp++);
+               } while (--n);
+       } else
+               bus_io_write_1(bc, ioh, com_data, getc(&tp->t_outq));
+out:
+       splx(s);
+       return;
+stopped:
+       if (ISSET(sc->sc_ier, IER_ETXRDY)) {
+               CLR(sc->sc_ier, IER_ETXRDY);
+               bus_io_write_1(bc, ioh, com_ier, sc->sc_ier);
+       }
+       splx(s);
+}
+
+/*
+ * Stop output on a line.
+ */
+int
+acestop(tp, flag)
+       struct tty *tp;
+       int flag;
+{
+       int s;
+
+       s = spltty();
+       if (ISSET(tp->t_state, TS_BUSY))
+               if (!ISSET(tp->t_state, TS_TTSTOP))
+                       SET(tp->t_state, TS_FLUSH);
+       splx(s);
+       return 0;
+}
+
+void
+comdiag(arg)
+       void *arg;
+{
+       struct com_softc *sc = arg;
+       int overflows, floods;
+       int s;
+
+       s = spltty();
+       sc->sc_errors = 0;
+       overflows = sc->sc_overflows;
+       sc->sc_overflows = 0;
+       floods = sc->sc_floods;
+       sc->sc_floods = 0;
+       splx(s);
+
+       log(LOG_WARNING, "%s: %d silo overflow%s, %d ibuf overflow%s\n",
+           sc->sc_dev.dv_xname,
+           overflows, overflows == 1 ? "" : "s",
+           floods, floods == 1 ? "" : "s");
+}
+
+void
+compoll(arg)
+       void *arg;
+{
+       int unit;
+       struct com_softc *sc;
+       struct tty *tp;
+       register u_char *ibufp;
+       u_char *ibufend;
+       register int c;
+       int s;
+       static int lsrmap[8] = {
+               0,      TTY_PE,
+               TTY_FE, TTY_PE|TTY_FE,
+               TTY_FE, TTY_PE|TTY_FE,
+               TTY_FE, TTY_PE|TTY_FE
+       };
+
+       s = spltty();
+       if (comevents == 0) {
+               splx(s);
+               goto out;
+       }
+       comevents = 0;
+       splx(s);
+
+       for (unit = 0; unit < ace_cd.cd_ndevs; unit++) {
+               sc = ace_cd.cd_devs[unit];
+               if (sc == 0 || sc->sc_ibufp == sc->sc_ibuf)
+                       continue;
+
+               tp = sc->sc_tty;
+
+               s = spltty();
+
+               ibufp = sc->sc_ibuf;
+               ibufend = sc->sc_ibufp;
+
+               if (ibufp == ibufend) {
+                       splx(s);
+                       continue;
+               }
+
+               sc->sc_ibufp = sc->sc_ibuf = (ibufp == sc->sc_ibufs[0]) ?
+                                            sc->sc_ibufs[1] : sc->sc_ibufs[0];
+               sc->sc_ibufhigh = sc->sc_ibuf + COM_IHIGHWATER;
+               sc->sc_ibufend = sc->sc_ibuf + COM_IBUFSIZE;
+
+               if (tp == 0 || !ISSET(tp->t_state, TS_ISOPEN)) {
+                       splx(s);
+                       continue;
+               }
+
+               if (ISSET(tp->t_cflag, CRTSCTS) &&
+                   !ISSET(sc->sc_mcr, MCR_RTS)) {
+                       /* XXX */
+                       SET(sc->sc_mcr, MCR_RTS);
+                       bus_io_write_1(sc->sc_bc, sc->sc_ioh, com_mcr,
+                           sc->sc_mcr);
+               }
+
+               splx(s);
+
+               while (ibufp < ibufend) {
+                       c = *ibufp++;
+                       if (*ibufp & LSR_OE) {
+                               sc->sc_overflows++;
+                               if (sc->sc_errors++ == 0)
+                                       timeout(comdiag, sc, 60 * hz);
+                       }
+                       /* This is ugly, but fast. */
+                       c |= lsrmap[(*ibufp++ & (LSR_BI|LSR_FE|LSR_PE)) >> 2];
+                       (*linesw[tp->t_line].l_rint)(c, tp);
+               }
+       }
+
+out:
+       timeout(compoll, NULL, 1);
+}
+
+int
+comintr(arg)
+       void *arg;
+{
+       struct com_softc *sc = arg;
+       bus_chipset_tag_t bc = sc->sc_bc;
+       bus_io_handle_t ioh = sc->sc_ioh;
+       struct tty *tp;
+       u_char lsr, data, msr, delta;
+#ifdef COM_DEBUG
+       int n;
+       struct {
+               u_char iir, lsr, msr;
+       } iter[32];
+#endif
+
+       if (ISSET(sc->sc_hwflags, COM_HW_ABSENT) || !sc->sc_tty)
+               return 0;               /* can't do squat. */
+
+#ifdef COM_DEBUG
+       n = 0;
+       if (ISSET(iter[n].iir = bus_io_read_1(bc, ioh, com_iir), IIR_NOPEND))
+               return (0);
+#else
+       if (ISSET(bus_io_read_1(bc, ioh, com_iir), IIR_NOPEND))
+               return (0);
+#endif
+
+       tp = sc->sc_tty;
+
+       for (;;) {
+#ifdef COM_DEBUG
+               iter[n].lsr =
+#endif
+               lsr = bus_io_read_1(bc, ioh, com_lsr);
+
+               if (ISSET(lsr, LSR_RXRDY)) {
+                       register u_char *p = sc->sc_ibufp;
+
+                       comevents = 1;
+                       do {
+                               data = bus_io_read_1(bc, ioh, com_data);
+                               if (ISSET(lsr, LSR_BI)) {
+#ifdef notdef
+                                       printf("break %02x %02x %02x %02x\n",
+                                           sc->sc_msr, sc->sc_mcr, sc->sc_lcr,
+                                           sc->sc_dtr);
+#endif
+#ifdef DDB
+                                       if (ISSET(sc->sc_hwflags,
+                                           COM_HW_CONSOLE)) {
+                                               Debugger();
+                                               goto next;
+                                       }
+#endif
+                               }
+                               if (p >= sc->sc_ibufend) {
+                                       sc->sc_floods++;
+                                       if (sc->sc_errors++ == 0)
+                                               timeout(comdiag, sc, 60 * hz);
+                               } else {
+                                       *p++ = data;
+                                       *p++ = lsr;
+                                       if (p == sc->sc_ibufhigh &&
+                                           ISSET(tp->t_cflag, CRTSCTS)) {
+                                               /* XXX */
+                                               CLR(sc->sc_mcr, MCR_RTS);
+                                               bus_io_write_1(bc, ioh, com_mcr,
+                                                   sc->sc_mcr);
+                                       }
+                               }
+#ifdef DDB
+                       next:
+#endif
+#ifdef COM_DEBUG
+                               if (++n >= 32)
+                                       goto ohfudge;
+                               iter[n].lsr =
+#endif
+                               lsr = bus_io_read_1(bc, ioh, com_lsr);
+                       } while (ISSET(lsr, LSR_RXRDY));
+
+                       sc->sc_ibufp = p;
+               }
+#ifdef COM_DEBUG
+               else if (ISSET(lsr, LSR_BI|LSR_FE|LSR_PE|LSR_OE))
+                       printf("weird lsr %02x\n", lsr);
+#endif
+
+#ifdef COM_DEBUG
+               iter[n].msr =
+#endif
+               msr = bus_io_read_1(bc, ioh, com_msr);
+
+               if (msr != sc->sc_msr) {
+                       delta = msr ^ sc->sc_msr;
+                       sc->sc_msr = msr;
+                       if (ISSET(delta, MSR_DCD) &&
+                           !ISSET(sc->sc_swflags, COM_SW_SOFTCAR) &&
+                           (*linesw[tp->t_line].l_modem)(tp, ISSET(msr, MSR_DCD)) == 0) {
+                               CLR(sc->sc_mcr, sc->sc_dtr);
+                               bus_io_write_1(bc, ioh, com_mcr, sc->sc_mcr);
+                       }
+                       if (ISSET(delta & msr, MSR_CTS) &&
+                           ISSET(tp->t_cflag, CRTSCTS)) {
+                               /* the line is up and we want to do rts/cts flow control */
+                               (*linesw[tp->t_line].l_start)(tp);
+                       }
+               }
+
+               if (ISSET(lsr, LSR_TXRDY) && ISSET(tp->t_state, TS_BUSY)) {
+                       CLR(tp->t_state, TS_BUSY | TS_FLUSH);
+                       if (sc->sc_halt > 0)
+                               wakeup(&tp->t_outq);
+                       (*linesw[tp->t_line].l_start)(tp);
+               }
+
+#ifdef COM_DEBUG
+               if (++n >= 32)
+                       goto ohfudge;
+               if (ISSET(iter[n].iir = bus_io_read_1(bc, ioh, com_iir), IIR_NOPEND))
+                       return (1);
+#else
+               if (ISSET(bus_io_read_1(bc, ioh, com_iir), IIR_NOPEND))
+                       return (1);
+#endif
+       }
+#ifdef COM_DEBUG
+ohfudge:
+       printf("comintr: too many iterations");
+       for (n = 0; n < 32; n++) {
+               if ((n % 4) == 0)
+                       printf("\ncomintr: iter[%02d]", n);
+               printf("  %02x %02x %02x", iter[n].iir, iter[n].lsr, iter[n].msr);
+       }
+       printf("\n");
+       printf("comintr: msr %02x mcr %02x lcr %02x ier %02x\n",
+           sc->sc_msr, sc->sc_mcr, sc->sc_lcr, sc->sc_ier);
+       printf("comintr: state %08x cc %d\n", sc->sc_tty->t_state,
+           sc->sc_tty->t_outq.c_cc);
+#endif
+}
+
+/*
+ * Following are all routines needed for COM to act as console
+ */
+#include <dev/cons.h>
+
+void
+acecnprobe(cp)
+       struct consdev *cp;
+{
+       /* XXX NEEDS TO BE FIXED XXX */
+       extern int cputype;
+       bus_chipset_tag_t bc = 0;
+       bus_io_handle_t ioh;
+       int found;
+
+       cp->cn_pri = CN_DEAD;
+
+       if (bus_io_map(bc, CONADDR, COM_NPORTS, &ioh)) {
+               cp->cn_pri = CN_DEAD;
+               return;
+       }
+       ioh = CONADDR;
+       found = comprobe1(bc, ioh, CONADDR);
+       if (!found) {
+               return;
+       }
+
+       /* locate the major number */
+       for (commajor = 0; commajor < nchrdev; commajor++)
+               if (cdevsw[commajor].d_open == aceopen)
+                       break;
+
+       /* initialize required fields */
+       cp->cn_dev = makedev(commajor, CONUNIT);
+#ifdef COMCONSOLE
+       cp->cn_pri = CN_REMOTE;         /* Force a serial port console */
+#else
+       cp->cn_pri = CN_NORMAL;
+#endif
+}
+
+void
+acecninit(cp)
+       struct consdev *cp;
+{
+
+#if 0
+       XXX NEEDS TO BE FIXED XXX
+       comconsbc = ???;
+#endif
+       if (bus_io_map(comconsbc, CONADDR, COM_NPORTS, &comconsioh))
+               panic("acecninit: mapping failed");
+
+       cominit(comconsbc, comconsioh, comdefaultrate);
+       comconsaddr = CONADDR;
+       comconsinit = 0;
+}
+
+void
+cominit(bc, ioh, rate)
+       bus_chipset_tag_t bc;
+       bus_io_handle_t ioh;
+       int rate;
+{
+       int s = splhigh();
+       u_char stat;
+
+       bus_io_write_1(bc, ioh, com_lcr, LCR_DLAB);
+       rate = comspeed(comdefaultrate);
+       bus_io_write_1(bc, ioh, com_dlbl, rate);
+       bus_io_write_1(bc, ioh, com_dlbh, rate >> 8);
+       bus_io_write_1(bc, ioh, com_lcr, LCR_8BITS);
+       bus_io_write_1(bc, ioh, com_ier, IER_ERXRDY | IER_ETXRDY);
+       bus_io_write_1(bc, ioh, com_fifo, FIFO_ENABLE | FIFO_RCV_RST | FIFO_XMT_RST | FIFO_TRIGGER_4);
+       stat = bus_io_read_1(bc, ioh, com_iir);
+       splx(s);
+}
+
+int
+acecngetc(dev)
+       dev_t dev;
+{
+       int s = splhigh();
+       bus_chipset_tag_t bc = comconsbc;
+       bus_io_handle_t ioh = comconsioh;
+       u_char stat, c;
+
+       while (!ISSET(stat = bus_io_read_1(bc, ioh, com_lsr), LSR_RXRDY))
+               ;
+       c = bus_io_read_1(bc, ioh, com_data);
+       stat = bus_io_read_1(bc, ioh, com_iir);
+       splx(s);
+       return c;
+}
+
+/*
+ * Console kernel output character routine.
+ */
+void
+acecnputc(dev, c)
+       dev_t dev;
+       int c;
+{
+       int s = splhigh();
+       bus_chipset_tag_t bc = comconsbc;
+       bus_io_handle_t ioh = comconsioh;
+       u_char stat;
+       register int timo;
+
+#ifdef KGDB
+       if (dev != kgdb_dev)
+#endif
+       if (comconsinit == 0) {
+               cominit(bc, ioh, comdefaultrate);
+               comconsinit = 1;
+       }
+       /* wait for any pending transmission to finish */
+       timo = 50000;
+       while (!ISSET(stat = bus_io_read_1(bc, ioh, com_lsr), LSR_TXRDY) && --timo)
+               ;
+       bus_io_write_1(bc, ioh, com_data, c);
+       /* wait for this transmission to complete */
+       timo = 1500000;
+       while (!ISSET(stat = bus_io_read_1(bc, ioh, com_lsr), LSR_TXRDY) && --timo)
+               ;
+       /* clear any interrupts generated by this transmission */
+       stat = bus_io_read_1(bc, ioh, com_iir);
+       splx(s);
+}
+
+void
+acecnpollc(dev, on)
+       dev_t dev;
+       int on;
+{
+
+}
diff --git a/sys/arch/wgrisc/dev/asc.c b/sys/arch/wgrisc/dev/asc.c
new file mode 100644 (file)
index 0000000..c4cdae7
--- /dev/null
@@ -0,0 +1,2096 @@
+/*     $OpenBSD: asc.c,v 1.1.1.1 1997/02/06 16:02:42 pefo Exp $        */
+/*     $NetBSD: asc.c,v 1.10 1994/12/05 19:11:12 dean Exp $    */
+
+/*-
+ * Copyright (c) 1992, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Ralph Campbell and Rick Macklem.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     @(#)asc.c       8.3 (Berkeley) 7/3/94
+ */
+
+/* 
+ * Mach Operating System
+ * Copyright (c) 1991,1990,1989 Carnegie Mellon University
+ * All Rights Reserved.
+ * 
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ * 
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS 
+ * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ * 
+ * Carnegie Mellon requests users of this software to return to
+ * 
+ *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
+ *  School of Computer Science
+ *  Carnegie Mellon University
+ *  Pittsburgh PA 15213-3890
+ * 
+ * any improvements or extensions that they make and grant Carnegie the
+ * rights to redistribute these changes.
+ */
+
+/*
+ * HISTORY
+ * Log:        scsi_53C94_hdw.c,v
+ * Revision 2.5  91/02/05  17:45:07  mrt
+ *     Added author notices
+ *     [91/02/04  11:18:43  mrt]
+ * 
+ *     Changed to use new Mach copyright
+ *     [91/02/02  12:17:20  mrt]
+ * 
+ * Revision 2.4  91/01/08  15:48:24  rpd
+ *     Added continuation argument to thread_block.
+ *     [90/12/27            rpd]
+ * 
+ * Revision 2.3  90/12/05  23:34:48  af
+ *     Recovered from pmax merge.. and from the destruction of a disk.
+ *     [90/12/03  23:40:40  af]
+ * 
+ * Revision 2.1.1.1  90/11/01  03:39:09  af
+ *     Created, from the DEC specs:
+ *     "PMAZ-AA TURBOchannel SCSI Module Functional Specification"
+ *     Workstation Systems Engineering, Palo Alto, CA. Aug 27, 1990.
+ *     And from the NCR data sheets
+ *     "NCR 53C94, 53C95, 53C96 Advances SCSI Controller"
+ *     [90/09/03            af]
+ */
+
+/*
+ *     File: scsi_53C94_hdw.h
+ *     Author: Alessandro Forin, Carnegie Mellon University
+ *     Date:   9/90
+ *
+ *     Bottom layer of the SCSI driver: chip-dependent functions
+ *
+ *     This file contains the code that is specific to the NCR 53C94
+ *     SCSI chip (Host Bus Adapter in SCSI parlance): probing, start
+ *     operation, and interrupt routine.
+ */
+
+/*
+ * This layer works based on small simple 'scripts' that are installed
+ * at the start of the command and drive the chip to completion.
+ * The idea comes from the specs of the NCR 53C700 'script' processor.
+ *
+ * There are various reasons for this, mainly
+ * - Performance: identify the common (successful) path, and follow it;
+ *   at interrupt time no code is needed to find the current status
+ * - Code size: it should be easy to compact common operations
+ * - Adaptability: the code skeleton should adapt to different chips without
+ *   terrible complications.
+ * - Error handling: and it is easy to modify the actions performed
+ *   by the scripts to cope with strange but well identified sequences
+ *
+ */
+
+#include <asc.h>
+#if NASC > 0
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/dkstat.h>
+#include <sys/buf.h>
+#include <sys/proc.h>
+#include <sys/conf.h>
+#include <sys/errno.h>
+#include <sys/device.h>
+
+#include <vm/vm.h>
+#include <vm/vm_kern.h>
+#include <vm/vm_page.h>
+
+#include <scsi/scsi_all.h>
+#include <scsi/scsiconf.h>
+
+#include <machine/cpu.h>
+#include <machine/autoconf.h>
+#include <machine/pio.h>
+
+#include <wgrisc/dev/scsi.h>
+#include <wgrisc/dev/ascreg.h>
+#include <wgrisc/dev/dma.h>
+
+#include <wgrisc/riscbus/riscbus.h>
+#include <wgrisc/wgrisc/wgrisctype.h>
+
+#define        readback(a)     { register int foo; foo = (a); }
+extern int cputype;
+
+/*
+ * In 4ns ticks.
+ */
+int    asc_to_scsi_period[] = {
+       32,
+       33,
+       34,
+       35,
+       5,
+       5,
+       6,
+       7,
+       8,
+       9,
+       10,
+       11,
+       12,
+       13,
+       14,
+       15,
+       16,
+       17,
+       18,
+       19,
+       20,
+       21,
+       22,
+       23,
+       24,
+       25,
+       26,
+       27,
+       28,
+       29,
+       30,
+       31,
+};
+
+/*
+ * Internal forward declarations.
+ */
+static void asc_reset();
+static void asc_startcmd();
+
+#ifdef DEBUG
+int    asc_debug = 1;
+int    asc_debug_cmd;
+int    asc_debug_bn;
+int    asc_debug_sz;
+#define NLOG 16
+struct asc_log {
+       u_int   status;
+       u_char  state;
+       u_char  msg;
+       int     target;
+       int     resid;
+} asc_log[NLOG], *asc_logp = asc_log;
+#define PACK(unit, status, ss, ir) \
+       ((unit << 24) | (status << 16) | (ss << 8) | ir)
+#endif
+
+/*
+ * Scripts are entries in a state machine table.
+ * A script has four parts: a pre-condition, an action, a command to the chip,
+ * and an index into asc_scripts for the next state. The first triggers error
+ * handling if not satisfied and in our case it is formed by the
+ * values of the interrupt register and status register, this
+ * basically captures the phase of the bus and the TC and BS
+ * bits.  The action part is just a function pointer, and the
+ * command is what the 53C94 should be told to do at the end
+ * of the action processing.  This command is only issued and the
+ * script proceeds if the action routine returns TRUE.
+ * See asc_intr() for how and where this is all done.
+ */
+typedef struct script {
+       int             condition;      /* expected state at interrupt time */
+       int             (*action)();    /* extra operations */
+       int             command;        /* command to the chip */
+       struct script   *next;          /* index into asc_scripts for next state */
+} script_t;
+
+/* Matching on the condition value */
+#define        SCRIPT_MATCH(ir, csr)           ((ir) | (((csr) & 0x67) << 8))
+
+/* forward decls of script actions */
+static int script_nop();               /* when nothing needed */
+static int asc_end();                  /* all come to an end */
+static int asc_get_status();           /* get status from target */
+static int asc_dma_in();               /* start reading data from target */
+static int asc_last_dma_in();          /* cleanup after all data is read */
+static int asc_resume_in();            /* resume data in after a message */
+static int asc_resume_dma_in();                /* resume DMA after a disconnect */
+static int asc_dma_out();              /* send data to target via dma */
+static int asc_last_dma_out();         /* cleanup after all data is written */
+static int asc_resume_out();           /* resume data out after a message */
+static int asc_resume_dma_out();       /* resume DMA after a disconnect */
+static int asc_sendsync();             /* negotiate sync xfer */
+static int asc_replysync();            /* negotiate sync xfer */
+static int asc_msg_in();               /* process a message byte */
+static int asc_disconnect();           /* process an expected disconnect */
+
+/* Define the index into asc_scripts for various state transitions */
+#define        SCRIPT_DATA_IN          0
+#define        SCRIPT_CONTINUE_IN      2
+#define        SCRIPT_DATA_OUT         3
+#define        SCRIPT_CONTINUE_OUT     5
+#define        SCRIPT_SIMPLE           6
+#define        SCRIPT_GET_STATUS       7
+#define        SCRIPT_DONE             8
+#define        SCRIPT_MSG_IN           9
+#define        SCRIPT_REPLY_SYNC       11
+#define        SCRIPT_TRY_SYNC         12
+#define        SCRIPT_DISCONNECT       15
+#define        SCRIPT_RESEL            16
+#define        SCRIPT_RESUME_IN        17
+#define        SCRIPT_RESUME_DMA_IN    18
+#define        SCRIPT_RESUME_OUT       19
+#define        SCRIPT_RESUME_DMA_OUT   20
+#define        SCRIPT_RESUME_NO_DATA   21
+
+/*
+ * Scripts
+ */
+script_t asc_scripts[] = {
+       /* start data in */
+       {SCRIPT_MATCH(ASC_INT_FC | ASC_INT_BS, ASC_PHASE_DATAI),        /*  0 */
+               asc_dma_in, ASC_CMD_XFER_INFO | ASC_CMD_DMA,
+               &asc_scripts[SCRIPT_DATA_IN + 1]},
+       {SCRIPT_MATCH(ASC_INT_BS, ASC_PHASE_STATUS),                    /*  1 */
+               asc_last_dma_in, ASC_CMD_I_COMPLETE,
+               &asc_scripts[SCRIPT_GET_STATUS]},
+
+       /* continue data in after a chunk is finished */
+       {SCRIPT_MATCH(ASC_INT_BS, ASC_PHASE_DATAI),                     /*  2 */
+               asc_dma_in, ASC_CMD_XFER_INFO | ASC_CMD_DMA,
+               &asc_scripts[SCRIPT_DATA_IN + 1]},
+
+       /* start data out */
+       {SCRIPT_MATCH(ASC_INT_FC | ASC_INT_BS, ASC_PHASE_DATAO),        /*  3 */
+               asc_dma_out, ASC_CMD_XFER_INFO | ASC_CMD_DMA,
+               &asc_scripts[SCRIPT_DATA_OUT + 1]},
+       {SCRIPT_MATCH(ASC_INT_BS, ASC_PHASE_STATUS),                    /*  4 */
+               asc_last_dma_out, ASC_CMD_I_COMPLETE,
+               &asc_scripts[SCRIPT_GET_STATUS]},
+
+       /* continue data out after a chunk is finished */
+       {SCRIPT_MATCH(ASC_INT_BS, ASC_PHASE_DATAO),                     /*  5 */
+               asc_dma_out, ASC_CMD_XFER_INFO | ASC_CMD_DMA,
+               &asc_scripts[SCRIPT_DATA_OUT + 1]},
+
+       /* simple command with no data transfer */
+       {SCRIPT_MATCH(ASC_INT_FC | ASC_INT_BS, ASC_PHASE_STATUS),       /*  6 */
+               script_nop, ASC_CMD_I_COMPLETE,
+               &asc_scripts[SCRIPT_GET_STATUS]},
+
+       /* get status and finish command */
+       {SCRIPT_MATCH(ASC_INT_FC, ASC_PHASE_MSG_IN),                    /*  7 */
+               asc_get_status, ASC_CMD_MSG_ACPT,
+               &asc_scripts[SCRIPT_DONE]},
+       {SCRIPT_MATCH(ASC_INT_DISC, 0),                                 /*  8 */
+               asc_end, ASC_CMD_NOP,
+               &asc_scripts[SCRIPT_DONE]},
+
+       /* message in */
+       {SCRIPT_MATCH(ASC_INT_FC, ASC_PHASE_MSG_IN),                    /*  9 */
+               asc_msg_in, ASC_CMD_MSG_ACPT,
+               &asc_scripts[SCRIPT_MSG_IN + 1]},
+       {SCRIPT_MATCH(ASC_INT_BS, ASC_PHASE_MSG_IN),                    /* 10 */
+               script_nop, ASC_CMD_XFER_INFO,
+               &asc_scripts[SCRIPT_MSG_IN]},
+
+       /* send synchonous negotiation reply */
+       {SCRIPT_MATCH(ASC_INT_BS, ASC_PHASE_MSG_OUT),                   /* 11 */
+               asc_replysync, ASC_CMD_XFER_INFO,
+               &asc_scripts[SCRIPT_REPLY_SYNC]},
+
+       /* try to negotiate synchonous transfer parameters */
+       {SCRIPT_MATCH(ASC_INT_FC | ASC_INT_BS, ASC_PHASE_MSG_OUT),      /* 12 */
+               asc_sendsync, ASC_CMD_XFER_INFO,
+               &asc_scripts[SCRIPT_TRY_SYNC + 1]},
+       {SCRIPT_MATCH(ASC_INT_BS, ASC_PHASE_MSG_IN),                    /* 13 */
+               script_nop, ASC_CMD_XFER_INFO,
+               &asc_scripts[SCRIPT_MSG_IN]},
+       {SCRIPT_MATCH(ASC_INT_BS, ASC_PHASE_COMMAND),                   /* 14 */
+               script_nop, ASC_CMD_XFER_INFO | ASC_CMD_DMA,
+               &asc_scripts[SCRIPT_RESUME_NO_DATA]},
+
+       /* handle a disconnect */
+       {SCRIPT_MATCH(ASC_INT_DISC, ASC_PHASE_DATAO),                   /* 15 */
+               asc_disconnect, ASC_CMD_ENABLE_SEL,
+               &asc_scripts[SCRIPT_RESEL]},
+
+       /* reselect sequence: this is just a placeholder so match fails */
+       {SCRIPT_MATCH(0, ASC_PHASE_MSG_IN),                             /* 16 */
+               script_nop, ASC_CMD_MSG_ACPT,
+               &asc_scripts[SCRIPT_RESEL]},
+
+       /* resume data in after a message */
+       {SCRIPT_MATCH(ASC_INT_BS, ASC_PHASE_DATAI),                     /* 17 */
+               asc_resume_in, ASC_CMD_XFER_INFO | ASC_CMD_DMA,
+               &asc_scripts[SCRIPT_DATA_IN + 1]},
+
+       /* resume partial DMA data in after a message */
+       {SCRIPT_MATCH(ASC_INT_BS, ASC_PHASE_DATAI),                     /* 18 */
+               asc_resume_dma_in, ASC_CMD_XFER_INFO | ASC_CMD_DMA,
+               &asc_scripts[SCRIPT_DATA_IN + 1]},
+
+       /* resume data out after a message */
+       {SCRIPT_MATCH(ASC_INT_BS, ASC_PHASE_DATAO),                     /* 19 */
+               asc_resume_out, ASC_CMD_XFER_INFO | ASC_CMD_DMA,
+               &asc_scripts[SCRIPT_DATA_OUT + 1]},
+
+       /* resume partial DMA data out after a message */
+       {SCRIPT_MATCH(ASC_INT_BS, ASC_PHASE_DATAO),                     /* 20 */
+               asc_resume_dma_out, ASC_CMD_XFER_INFO | ASC_CMD_DMA,
+               &asc_scripts[SCRIPT_DATA_OUT + 1]},
+
+       /* resume after a message when there is no more data */
+       {SCRIPT_MATCH(ASC_INT_BS, ASC_PHASE_STATUS),                    /* 21 */
+               script_nop, ASC_CMD_I_COMPLETE,
+               &asc_scripts[SCRIPT_GET_STATUS]},
+};
+
+/*
+ * State kept for each active SCSI device.
+ */
+typedef struct scsi_state {
+       script_t *script;       /* saved script while processing error */
+       struct scsi_generic cmd;/* storage for scsi command */
+       int     statusByte;     /* status byte returned during STATUS_PHASE */
+       u_int   dmaBufSize;     /* DMA buffer size */
+       int     dmalen;         /* amount to transfer in this chunk */
+       int     dmaresid;       /* amount not transfered if chunk suspended */
+       int     cmdlen;         /* length of command in cmd */
+       int     buflen;         /* total remaining amount of data to transfer */
+       vm_offset_t buf;        /* current pointer within scsicmd->buf */
+       int     flags;          /* see below */
+       int     msglen;         /* number of message bytes to read */
+       int     msgcnt;         /* number of message bytes received */
+       u_char  sync_period;    /* DMA synchronous period */
+       u_char  sync_offset;    /* DMA synchronous xfer offset or 0 if async */
+       u_char  msg_out;        /* next MSG_OUT byte to send */
+       u_char  msg_in[16];     /* buffer for multibyte messages */
+} State;
+
+/* state flags */
+#define DISCONN                0x001   /* true if currently disconnected from bus */
+#define DMA_IN_PROGRESS        0x002   /* true if data DMA started */
+#define DMA_IN         0x004   /* true if reading from SCSI device */
+#define DMA_OUT                0x010   /* true if writing to SCSI device */
+#define DID_SYNC       0x020   /* true if synchronous offset was negotiated */
+#define TRY_SYNC       0x040   /* true if try neg. synchronous offset */
+#define PARITY_ERR     0x080   /* true if parity error seen */
+#define        CHECK_SENSE     0x100   /* true if doing sense command */
+
+struct dma_softc_t;
+/*
+ * State kept for each active SCSI host interface (53C94).
+ */
+struct asc_softc {
+       struct device   sc_dev;         /* use as a device */
+       asc_regmap_t    *regs;          /* chip address */
+       dma_softc_t     dma;            /* dma control structure */
+       int             sc_id;          /* SCSI ID of this interface */
+       int             myidmask;       /* ~(1 << myid) */
+       int             state;          /* current SCSI connection state */
+       int             target;         /* target SCSI ID if busy */
+       script_t        *script;        /* next expected interrupt & action */
+       struct scsi_xfer *cmdq[ASC_NCMD];/* Pointer to queued commands */
+       struct scsi_xfer *cmd[ASC_NCMD];/* Pointer to current active command */
+       State           st[ASC_NCMD];   /* state info for each active command */
+       int             min_period;     /* Min transfer period clk/byte */
+       int             max_period;     /* Max transfer period clk/byte */
+       int             ccf;            /* CCF, whatever that really is? */
+       int             timeout_250;    /* 250ms timeout */
+       int             tb_ticks;       /* 4ns. ticks/tb channel ticks */
+       struct scsi_link sc_link;       /* scsi link struct */
+};
+
+#define        ASC_STATE_IDLE          0       /* idle state */
+#define        ASC_STATE_BUSY          1       /* selecting or currently connected */
+#define ASC_STATE_TARGET       2       /* currently selected as target */
+#define ASC_STATE_RESEL                3       /* currently waiting for reselect */
+
+typedef struct asc_softc *asc_softc_t;
+
+static char dma_buffer[MAXPHYS];       /*yieek*/ /*XXX*/
+
+/*
+ * Autoconfiguration data for config.
+ */
+int    ascmatch __P((struct device *, void *, void *));
+void   ascattach __P((struct device *, struct device *, void *));
+int    ascprint(void *, const char *);
+
+struct cfattach asc_ca = {
+       sizeof(struct asc_softc), ascmatch, ascattach
+};
+struct cfdriver asc_cd = {
+       NULL, "asc", DV_DULL, NULL, 0
+};
+
+/*
+ *  Glue to the machine dependent scsi
+ */
+int asc_scsi_cmd __P((struct scsi_xfer *));
+void asc_minphys __P((struct buf *));
+
+struct scsi_adapter asc_switch = {
+       asc_scsi_cmd,
+       asc_minphys,
+       NULL,
+       NULL,
+};
+
+struct scsi_device asc_dev = {
+/*XXX*/        NULL,           /* Use default error handler */
+/*XXX*/        NULL,           /* have a queue, served by this */
+/*XXX*/        NULL,           /* have no async handler */
+/*XXX*/        NULL,           /* Use default 'done' routine */
+};
+
+static void    asc_start();
+static int     asc_intr();
+
+/*
+ * Match driver based on name
+ */
+int
+ascmatch(parent, match, aux)
+       struct device *parent;
+       void *match;
+       void *aux;
+{
+       struct cfdata *cf = match;
+       struct confargs *ca = aux;
+
+       if(!BUS_MATCHNAME(ca, "asc"))
+               return(0);
+       return(1);
+}
+
+void
+ascattach(parent, self, aux)
+       struct device *parent;
+       struct device *self;
+       void *aux;
+{
+       register struct confargs *ca = aux;
+       register asc_softc_t asc = (void *)self;
+       register asc_regmap_t *regs;
+       int id, s, i;
+       int bufsiz;
+
+       /*
+        * Initialize hw descriptor, cache some pointers
+        */
+       asc->regs = (asc_regmap_t *)BUS_CVTADDR(ca);
+
+       /*
+        * Set up machine dependencies.
+        * 1) how to do dma
+        * 2) timing based on chip clock frequency
+        */
+       switch (cputype) {
+       case WGRISC9100:
+               bufsiz = MAXPHYS;       /* Scatter gather in software */
+               break;
+       default:
+               bufsiz = 64 * 1024;
+       };
+       /*
+        * Now for timing. WGRISC has a 20Mhz
+        */
+       switch (cputype) {
+       case WGRISC9100:
+               asc->min_period = ASC_MIN_PERIOD20;
+               asc->max_period = ASC_MAX_PERIOD20;
+               asc->ccf = ASC_CCF(20);
+               asc->timeout_250 = ASC_TIMEOUT_250(20, asc->ccf);
+               asc->tb_ticks = 10;
+               asc->dma.dma_ch = DMA_CH0;
+               break;
+       default:
+               asc->min_period = ASC_MIN_PERIOD12;
+               asc->max_period = ASC_MAX_PERIOD12;
+               asc->ccf = ASC_CCF(13);
+               asc->timeout_250 = ASC_TIMEOUT_250(13, asc->ccf);
+               asc->tb_ticks = 20;
+               break;
+       };
+
+       asc->state = ASC_STATE_IDLE;
+       asc->target = -1;
+
+       regs = asc->regs;
+
+       /*
+        * Reset chip, fully.  Note that interrupts are already enabled.
+        */
+       s = splbio();
+
+       /* preserve our ID for now */
+#if 0
+       asc->sc_id = regs->asc_cnfg1 & ASC_CNFG1_MY_BUS_ID;
+#else
+       asc->sc_id = 7; /* XXX Until boot roms set up scsi id */
+#endif
+       asc->myidmask = ~(1 << asc->sc_id);
+
+       asc_reset(asc, regs);
+
+       /*
+        * Our SCSI id on the bus.
+        * The user can set this via the prom on 3maxen/picaen.
+        * If this changes it is easy to fix: make a default that
+        * can be changed as boot arg.
+        */
+#ifdef unneeded
+       regs->asc_cnfg1 = (regs->asc_cnfg1 & ~ASC_CNFG1_MY_BUS_ID) |
+                             (scsi_initiator_id[unit] & 0x7);
+       asc->sc_id = regs->asc_cnfg1 & ASC_CNFG1_MY_BUS_ID;
+#endif
+       id = asc->sc_id;
+       splx(s);
+
+       /*
+        * Give each target its DMA buffer region.
+        * The buffer address is the same for all targets,
+        * the allocated dma viritual scatter/gather space.
+        */
+       for (i = 0; i < ASC_NCMD; i++) {
+               asc->st[i].dmaBufSize = bufsiz;
+       }
+
+       /*
+        * Set up interrupt handler.
+         */
+       BUS_INTR_ESTABLISH(ca, asc_intr, (void *)asc);
+
+       printf(": NCR53C94, target %d\n", id);
+
+       /*
+        * Fill in the prototype scsi link.
+        */
+       asc->sc_link.adapter_softc = asc;
+       asc->sc_link.adapter_target = asc->sc_id;
+       asc->sc_link.adapter = &asc_switch;
+       asc->sc_link.device = &asc_dev;
+       asc->sc_link.openings = 2;
+
+       /*
+        * Now try to attach all the sub devices.
+        */
+       config_found(self, &asc->sc_link, ascprint);
+}
+
+int
+ascprint(aux, name)
+       void *aux;
+       const char *name;
+{
+}
+
+/*
+ *  Driver breaks down request transfer size.
+ */
+void
+asc_minphys(bp)
+       struct buf *bp;
+{
+       minphys(bp);
+}
+
+/*
+ * Start activity on a SCSI device.
+ * We maintain information on each device separately since devices can
+ * connect/disconnect during an operation.
+ */
+int
+asc_scsi_cmd(xs)
+       struct scsi_xfer *xs;
+{
+       struct scsi_link *sc_link = xs->sc_link;
+       struct asc_softc *asc = sc_link->adapter_softc;
+       State *state = &asc->st[sc_link->target];
+
+       int flags, s;
+
+       flags = xs->flags;
+
+       /*
+        *  Flush caches for any data buffer
+        */
+       if(xs->datalen != 0) {
+#ifdef R4K
+               R4K_HitFlushDCache(xs->data, xs->datalen);
+#else
+               R3K_FlushDCache();
+#endif
+       }
+       /*
+        *  The hack on the next few lines are to avoid buffers
+        *  mapped to UADDR. Realloc to the kva uarea address.
+        */
+       if((u_int)(xs->data) >= UADDR) {
+               xs->data = ((u_int)(xs->data) & ~UADDR) + (u_char *)(curproc->p_addr);
+       }
+
+       /*
+        * Check if another command is already in progress.
+        * We may have to change this if we allow SCSI devices with
+        * separate LUNs.
+        */
+       s = splbio();
+       if (asc->cmd[sc_link->target]) {
+               if (asc->cmdq[sc_link->target]) {
+                       splx(s);
+                       printf("asc_scsi_cmd: called when target busy");
+                       xs->error = XS_DRIVER_STUFFUP;
+                       return TRY_AGAIN_LATER;
+               }
+               asc->cmdq[sc_link->target] = xs;
+               splx(s);
+               return SUCCESSFULLY_QUEUED;
+       }
+       asc->cmd[sc_link->target] = xs;
+
+       /*
+        *  Going to launch.
+        *  Make a local copy of the command and some pointers.
+        */
+       asc_startcmd(asc, sc_link->target);
+
+       /*
+        *  If in startup, interrupts not usable yet.
+        */
+       if(flags & SCSI_POLL) {
+               return(asc_poll(asc,sc_link->target));
+       }
+       splx(s);
+       return SUCCESSFULLY_QUEUED;
+}
+
+int
+asc_poll(asc, target)
+       struct asc_softc *asc;
+       int target;
+{
+       struct scsi_xfer *scsicmd = asc->cmd[target];
+       int count = scsicmd->timeout * 10;
+
+       while(count) {
+               if(asc->regs->asc_status &ASC_CSR_INT) {
+                       asc_intr(asc);
+               }
+               if(scsicmd->flags & ITSDONE)
+                       break;
+               DELAY(5);
+               count--;
+       }
+       if(count == 0) {
+               scsicmd->error = XS_TIMEOUT;
+               asc_end(asc, 0, 0, 0);
+       }
+       return COMPLETE;
+}
+
+static void
+asc_reset(asc, regs)
+       asc_softc_t asc;
+       asc_regmap_t *regs;
+{
+       int i;
+
+       /*
+        * Reset chip and SCSI bus. Put everything in a known state.
+        */
+       regs->asc_cmd = ASC_CMD_RESET;
+       wbflush(); DELAY(25);
+       regs->asc_cmd = ASC_CMD_NOP;
+       wbflush(); DELAY(25);
+       regs->asc_cmd = ASC_CMD_BUS_RESET;
+       wbflush();
+       while(!(regs->asc_status & ASC_CSR_INT)) {
+               /*void*/
+       }
+       regs->asc_cmd = ASC_CMD_RESET;
+       wbflush(); DELAY(25);
+       regs->asc_cmd = ASC_CMD_NOP;
+       wbflush(); DELAY(25);
+
+       /*
+        * Set up various chip parameters
+        */
+       regs->asc_ccf = asc->ccf;
+       wbflush(); DELAY(25);
+       regs->asc_sel_timo = asc->timeout_250;
+       /* restore our ID */
+       regs->asc_cnfg1 = asc->sc_id | ASC_CNFG1_P_CHECK;
+       /* include ASC_CNFG2_SCSI2 if you want to allow SCSI II commands */
+       regs->asc_cnfg2 = /* ASC_CNFG2_RFB | ASC_CNFG2_SCSI2 | */ ASC_CNFG2_EPL;
+       regs->asc_cnfg3 = 0;
+       /* zero anything else */
+       ASC_TC_PUT(regs, 0);
+       regs->asc_syn_p = asc->min_period;
+       regs->asc_syn_o = 0;    /* async for now */
+       wbflush();
+}
+
+/*
+ * Start a SCSI command on a target.
+ */
+static void
+asc_startcmd(asc, target)
+       asc_softc_t asc;
+       int target;
+{
+       asc_regmap_t *regs;
+       State *state;
+       struct scsi_xfer *scsicmd;
+       int i, len;
+
+       /*
+        * See if another target is currently selected on this SCSI bus.
+        */
+       if (asc->target >= 0)
+               return;
+
+       regs = asc->regs;
+
+       /*
+        * If a reselection is in progress, it is Ok to ignore it since
+        * the ASC will automatically cancel the command and flush
+        * the FIFO if the ASC is reselected before the command starts.
+        * If we try to use ASC_CMD_DISABLE_SEL, we can hang the system if
+        * a reselect occurs before starting the command.
+        */
+
+       asc->state = ASC_STATE_BUSY;
+       asc->target = target;
+
+       /* cache some pointers */
+       scsicmd = asc->cmd[target];
+       state = &asc->st[target];
+
+       /*
+        * Init the chip and target state.
+        */
+       state->flags = state->flags & (DID_SYNC | CHECK_SENSE);
+       state->script = (script_t *)0;
+       state->msg_out = SCSI_NO_OP;
+
+       /*
+        * Set up for DMA of command output. Also need to flush cache.
+        */
+       if(!(state->flags & CHECK_SENSE)) {
+               bcopy(scsicmd->cmd, &state->cmd, scsicmd->cmdlen);
+               state->cmdlen = scsicmd->cmdlen;
+               state->buf = (vm_offset_t)scsicmd->data;
+               state->buflen = scsicmd->datalen;
+       }
+       len = state->cmdlen;
+       state->dmalen = len;
+       
+#ifdef DEBUG
+       if (asc_debug > 1) {
+               printf("asc_startcmd: %s target %d cmd %x len %d\n",
+                       asc->sc_dev.dv_xname, target,
+                       state->cmd.opcode, state->buflen);
+       }
+#endif
+
+       /* check for simple SCSI command with no data transfer */
+       if(state->flags & CHECK_SENSE) {
+               asc->script = &asc_scripts[SCRIPT_DATA_IN];
+               state->flags |= DMA_IN;
+       }
+       else if (scsicmd->flags & SCSI_DATA_OUT) {
+               asc->script = &asc_scripts[SCRIPT_DATA_OUT];
+               state->flags |= DMA_OUT;
+       }
+       else if (scsicmd->flags & SCSI_DATA_IN) {
+               asc->script = &asc_scripts[SCRIPT_DATA_IN];
+               state->flags |= DMA_IN;
+       }
+       else if (state->buflen == 0) {
+               /* check for sync negotiation */
+               if ((scsicmd->flags & /* SCSICMD_USE_SYNC */ 0) &&
+                   !(state->flags & DID_SYNC)) {
+                       asc->script = &asc_scripts[SCRIPT_TRY_SYNC];
+                       state->flags |= TRY_SYNC;
+               } else
+                       asc->script = &asc_scripts[SCRIPT_SIMPLE];
+               state->buf = (vm_offset_t)0;
+       }
+
+#ifdef DEBUG
+       asc_debug_cmd = state->cmd.opcode;
+       if (state->cmd.opcode == SCSI_READ_EXT) {
+               asc_debug_bn = (state->cmd.bytes[1] << 24) |
+                       (state->cmd.bytes[2] << 16) |
+                       (state->cmd.bytes[3] << 8) |
+                        state->cmd.bytes[4];
+               asc_debug_sz = (state->cmd.bytes[6] << 8) | state->cmd.bytes[7];
+       }
+       asc_logp->status = PACK(asc->sc_dev.dv_unit, 0, 0, asc_debug_cmd);
+       asc_logp->target = asc->target;
+       asc_logp->state = asc->script - asc_scripts;
+       asc_logp->msg = SCSI_DIS_REC_IDENTIFY;
+       asc_logp->resid = scsicmd->datalen;
+       if (++asc_logp >= &asc_log[NLOG])
+               asc_logp = asc_log;
+#endif
+
+       /* preload the FIFO with the message and command to be sent */
+       regs->asc_fifo = SCSI_DIS_REC_IDENTIFY | (scsicmd->sc_link->lun & 0x07);
+
+       for( i = 0; i < len; i++ ) {
+               regs->asc_fifo = ((caddr_t)&state->cmd)[i];
+       }
+       ASC_TC_PUT(regs, 0);
+       readback(regs->asc_cmd);
+       regs->asc_cmd = ASC_CMD_DMA;
+       readback(regs->asc_cmd);
+
+       regs->asc_dbus_id = target;
+       readback(regs->asc_dbus_id);
+       regs->asc_syn_p = state->sync_period;
+       readback(regs->asc_syn_p);
+       regs->asc_syn_o = state->sync_offset;
+       readback(regs->asc_syn_o);
+
+/*XXX PEFO */
+/* we are not using sync transfer now, need to check this if we will */
+
+       if (state->flags & TRY_SYNC)
+               regs->asc_cmd = ASC_CMD_SEL_ATN_STOP;
+       else
+               regs->asc_cmd = ASC_CMD_SEL_ATN;
+       readback(regs->asc_cmd);
+}
+
+/*
+ * Interrupt routine
+ *     Take interrupts from the chip
+ *
+ * Implementation:
+ *     Move along the current command's script if
+ *     all is well, invoke error handler if not.
+ */
+int
+asc_intr(sc)
+       void *sc;
+{
+       asc_softc_t asc = sc;
+       asc_regmap_t *regs = asc->regs;
+       State *state;
+       script_t *scpt;
+       int ss, ir, status;
+
+       /* collect ephemeral information */
+       status = regs->asc_status;
+       ss = regs->asc_ss;
+
+       if ((status & ASC_CSR_INT) == 0) /* Make sure it's a real interrupt */
+                return;
+
+       ir = regs->asc_intr;    /* this resets the previous two */
+       scpt = asc->script;
+
+#ifdef DEBUG
+       asc_logp->status = PACK(asc->sc_dev.dv_unit, status, ss, ir);
+       asc_logp->target = (asc->state == ASC_STATE_BUSY) ? asc->target : -1;
+       asc_logp->state = scpt - asc_scripts;
+       asc_logp->msg = -1;
+       asc_logp->resid = 0;
+       if (++asc_logp >= &asc_log[NLOG])
+               asc_logp = asc_log;
+       if (asc_debug > 2)
+               printf("asc_intr: status %x ss %x ir %x cond %d:%x\n",
+                       status, ss, ir, scpt - asc_scripts, scpt->condition);
+#endif
+
+       /* check the expected state */
+       if (SCRIPT_MATCH(ir, status) == scpt->condition) {
+               /*
+                * Perform the appropriate operation, then proceed.
+                */
+               if ((*scpt->action)(asc, status, ss, ir)) {
+                       regs->asc_cmd = scpt->command;
+                       readback(regs->asc_cmd);
+                       asc->script = scpt->next;
+               }
+               goto done;
+       }
+
+       /*
+        * Check for parity error.
+        * Hardware will automatically set ATN
+        * to request the device for a MSG_OUT phase.
+        */
+       if (status & ASC_CSR_PE) {
+               printf("%s: SCSI device %d: incomming parity error seen\n",
+                       asc->sc_dev.dv_xname, asc->target);
+               asc->st[asc->target].flags |= PARITY_ERR;
+       }
+
+       /*
+        * Check for gross error.
+        * Probably a bug in a device driver.
+        */
+       if (status & ASC_CSR_GE) {
+               printf("%s: SCSI device %d: gross error\n",
+                       asc->sc_dev.dv_xname, asc->target);
+               goto abort;
+       }
+
+       /* check for message in or out */
+       if ((ir & ~ASC_INT_FC) == ASC_INT_BS) {
+               register int len, fifo;
+
+               state = &asc->st[asc->target];
+               switch (ASC_PHASE(status)) {
+               case ASC_PHASE_DATAI:
+               case ASC_PHASE_DATAO:
+                       ASC_TC_GET(regs, len);
+                       fifo = regs->asc_flags & ASC_FLAGS_FIFO_CNT;
+                       printf("asc_intr: data overrun: buflen %d dmalen %d tc %d fifo %d\n",
+                               state->buflen, state->dmalen, len, fifo);
+                       goto abort;
+
+               case ASC_PHASE_MSG_IN:
+                       break;
+
+               case ASC_PHASE_MSG_OUT:
+                       /*
+                        * Check for parity error.
+                        * Hardware will automatically set ATN
+                        * to request the device for a MSG_OUT phase.
+                        */
+                       if (state->flags & PARITY_ERR) {
+                               state->flags &= ~PARITY_ERR;
+                               state->msg_out = SCSI_MESSAGE_PARITY_ERROR;
+                               /* reset message in counter */
+                               state->msglen = 0;
+                       } else
+                               state->msg_out = SCSI_NO_OP;
+                       regs->asc_fifo = state->msg_out;
+                       regs->asc_cmd = ASC_CMD_XFER_INFO;
+                       readback(regs->asc_cmd);
+                       goto done;
+
+               case ASC_PHASE_STATUS:
+                       /* probably an error in the SCSI command */
+                       asc->script = &asc_scripts[SCRIPT_GET_STATUS];
+                       regs->asc_cmd = ASC_CMD_I_COMPLETE;
+                       readback(regs->asc_cmd);
+                       goto done;
+
+               default:
+                       goto abort;
+               }
+
+               if (state->script)
+                       goto abort;
+
+               /*
+                * OK, message coming in clean up whatever is going on.
+                * Get number of bytes left to transfered from byte counter
+                * counter decrements when data is trf on the SCSI bus
+                */
+               ASC_TC_GET(regs, len);
+               fifo = regs->asc_flags & ASC_FLAGS_FIFO_CNT;
+               /* flush any data in the FIFO */
+               if (fifo && !(state->flags & DMA_IN_PROGRESS)) {
+printf("asc_intr: fifo flush %d len %d fifo %x\n", fifo, len, regs->asc_fifo);
+                       regs->asc_cmd = ASC_CMD_FLUSH;
+                       readback(regs->asc_cmd);
+                       DELAY(2);
+               }
+               else if (fifo && state->flags & DMA_IN_PROGRESS) {      
+                       if (state->flags & DMA_OUT) {
+                               len += fifo; /* Bytes dma'ed but not sent */
+                       }
+                       else if (state->flags & DMA_IN) {
+                               u_char *cp;
+
+                               printf("asc_intr: IN: dmalen %d len %d fifo %d\n",
+                                       state->dmalen, len, fifo); /* XXX */
+                       }
+                       regs->asc_cmd = ASC_CMD_FLUSH;
+                       readback(regs->asc_cmd);
+                       DELAY(2);
+               }
+               if (len && (state->flags & DMA_IN_PROGRESS)) {
+                       /* save number of bytes still to be sent or received */
+                       state->dmaresid = len;
+                       state->flags &= ~DMA_IN_PROGRESS;
+                       ASC_TC_PUT(regs, 0);
+#ifdef DEBUG
+                       if (asc_logp == asc_log)
+                               asc_log[NLOG - 1].resid = len;
+                       else
+                               asc_logp[-1].resid = len;
+#endif
+                       /* setup state to resume to */
+                       if (state->flags & DMA_IN) {
+                               /*
+                                * Since the ASC_CNFG3_SRB bit of the
+                                * cnfg3 register bit is not set,
+                                * we just transferred an extra byte.
+                                * Since we can't resume on an odd byte
+                                * boundary, we copy the valid data out
+                                * and resume DMA at the start address.
+                                */
+                               if (len & 1) {
+                                       printf("asc_intr: msg in len %d (fifo %d)\n",
+                                               len, fifo); /* XXX */
+                                       len = state->dmalen - len;
+                                       goto do_in;
+                               }
+                               state->script =
+                                       &asc_scripts[SCRIPT_RESUME_DMA_IN];
+                       } else if (state->flags & DMA_OUT)
+                               state->script =
+                                       &asc_scripts[SCRIPT_RESUME_DMA_OUT];
+                       else
+                               state->script = asc->script;
+               } else if (state->flags & DMA_IN) {
+                       if (len) {
+#ifdef DEBUG
+                               printf("asc_intr: 1: bn %d len %d (fifo %d)\n",
+                                       asc_debug_bn, len, fifo); /* XXX */
+#endif
+                               goto abort;
+                       }
+                       /* setup state to resume to */
+                       if (state->flags & DMA_IN_PROGRESS) {
+                               len = state->dmalen;
+                               state->flags &= ~DMA_IN_PROGRESS;
+                       do_in:
+                               DMA_END(&asc->dma);
+                               state->buf += len;
+                               state->buflen -= len;
+                       }
+                       if (state->buflen)
+                               state->script =
+                                   &asc_scripts[SCRIPT_RESUME_IN];
+                       else
+                               state->script =
+                                   &asc_scripts[SCRIPT_RESUME_NO_DATA];
+               } else if (state->flags & DMA_OUT) {
+                       if (len) {
+                               printf("asc_intr: 2: len %d (fifo %d)\n", len,
+                                       fifo); /* XXX */
+/* XXX THEO */
+#if 1 
+                               regs->asc_cmd = ASC_CMD_FLUSH;
+                               readback(regs->asc_cmd);
+                               DELAY(2);
+                               len = 0;
+#else                                   
+                               goto abort;
+#endif
+                       }
+                       /*
+                        * If this is the last chunk, the next expected
+                        * state is to get status.
+                        */
+                       if (state->flags & DMA_IN_PROGRESS) {
+                               state->flags &= ~DMA_IN_PROGRESS;
+                               DMA_END(&asc->dma);
+                               len = state->dmalen;
+                               state->buf += len;
+                               state->buflen -= len;
+                       }
+                       if (state->buflen)
+                               state->script =
+                                   &asc_scripts[SCRIPT_RESUME_OUT];
+                       else
+                               state->script =
+                                   &asc_scripts[SCRIPT_RESUME_NO_DATA];
+               } else if (asc->script == &asc_scripts[SCRIPT_SIMPLE])
+                       state->script = &asc_scripts[SCRIPT_RESUME_NO_DATA];
+               else
+                       state->script = asc->script;
+
+               /* setup to receive a message */
+               asc->script = &asc_scripts[SCRIPT_MSG_IN];
+               state->msglen = 0;
+               regs->asc_cmd = ASC_CMD_XFER_INFO;
+               readback(regs->asc_cmd);
+               goto done;
+       }
+
+       /* check for SCSI bus reset */
+       if (ir & ASC_INT_RESET) {
+               register int i;
+
+               printf("%s: SCSI bus reset!!\n", asc->sc_dev.dv_xname);
+               /* need to flush any pending commands */
+               for (i = 0; i < ASC_NCMD; i++) {
+                       if (!asc->cmd[i])
+                               continue;
+                       asc->cmd[i]->error = XS_DRIVER_STUFFUP;
+                       asc_end(asc, 0, 0, 0);
+               }
+               /* rearbitrate synchronous offset */
+               for (i = 0; i < ASC_NCMD; i++) {
+                       asc->st[i].sync_offset = 0;
+                       asc->st[i].flags = 0;
+               }
+               asc->target = -1;
+               return;
+       }
+
+       /* check for command errors */
+       if (ir & ASC_INT_ILL)
+               goto abort;
+
+       /* check for disconnect */
+       if (ir & ASC_INT_DISC) {
+               state = &asc->st[asc->target];
+               switch (asc->script - asc_scripts) {
+               case SCRIPT_DONE:
+               case SCRIPT_DISCONNECT:
+                       /*
+                        * Disconnects can happen normally when the
+                        * command is complete with the phase being
+                        * either ASC_PHASE_DATAO or ASC_PHASE_MSG_IN.
+                        * The SCRIPT_MATCH() only checks for one phase
+                        * so we can wind up here.
+                        * Perform the appropriate operation, then proceed.
+                        */
+                       if ((*scpt->action)(asc, status, ss, ir)) {
+                               regs->asc_cmd = scpt->command;
+                               readback(regs->asc_cmd);
+                               asc->script = scpt->next;
+                       }
+                       goto done;
+
+               case SCRIPT_TRY_SYNC:
+               case SCRIPT_SIMPLE:
+               case SCRIPT_DATA_IN:
+               case SCRIPT_DATA_OUT: /* one of the starting scripts */
+                       if (ASC_SS(ss) == 0) {
+                               /* device did not respond */
+                               if (regs->asc_flags & ASC_FLAGS_FIFO_CNT) {
+                                       regs->asc_cmd = ASC_CMD_FLUSH;
+                                       readback(regs->asc_cmd);
+                               }
+                               asc->cmd[asc->target]->error = XS_DRIVER_STUFFUP;
+                               asc_end(asc, status, ss, ir);
+                               return;
+                       }
+                       /* FALLTHROUGH */
+
+               default:
+                       printf("%s: SCSI device %d: unexpected disconnect\n",
+                               asc->sc_dev.dv_xname, asc->target);
+#ifdef DEBUG
+                       asc_DumpLog("asc_disc");
+#endif
+                       /*
+                        * On rare occasions my RZ24 does a disconnect during
+                        * data in phase and the following seems to keep it
+                        * happy.
+                        * XXX Should a scsi disk ever do this??
+                        */
+                       asc->script = &asc_scripts[SCRIPT_RESEL];
+                       asc->state = ASC_STATE_RESEL;
+                       state->flags |= DISCONN;
+                       regs->asc_cmd = ASC_CMD_ENABLE_SEL;
+                       readback(regs->asc_cmd);
+                       return;
+               }
+       }
+
+       /* check for reselect */
+       if (ir & ASC_INT_RESEL) {
+               unsigned fifo, id, msg;
+
+               fifo = regs->asc_flags & ASC_FLAGS_FIFO_CNT;
+               if (fifo < 2)
+                       goto abort;
+               /* read unencoded SCSI ID and convert to binary */
+               msg = regs->asc_fifo & asc->myidmask;
+               for (id = 0; (msg & 1) == 0; id++)
+                       msg >>= 1;
+               /* read identify message */
+               msg = regs->asc_fifo;
+#ifdef DEBUG
+               if (asc_logp == asc_log)
+                       asc_log[NLOG - 1].msg = msg;
+               else
+                       asc_logp[-1].msg = msg;
+#endif
+               asc->state = ASC_STATE_BUSY;
+               asc->target = id;
+               state = &asc->st[id];
+               asc->script = state->script;
+               state->script = (script_t *)0;
+               if (!(state->flags & DISCONN))
+                       goto abort;
+               state->flags &= ~DISCONN;
+               regs->asc_syn_p = state->sync_period;
+               regs->asc_syn_o = state->sync_offset;
+               regs->asc_cmd = ASC_CMD_MSG_ACPT;
+               readback(regs->asc_cmd);
+               goto done;
+       }
+
+       /* check if we are being selected as a target */
+       if (ir & (ASC_INT_SEL | ASC_INT_SEL_ATN))
+               goto abort;
+
+       /*
+        * 'ir' must be just ASC_INT_FC.
+        * This is normal if canceling an ASC_ENABLE_SEL.
+        */
+
+done:
+       wbflush();
+       /*
+        * If the next interrupt comes in immediatly the interrupt
+        * dispatcher (which we are returning to) will catch it
+        * before returning to the interrupted code.
+        */
+       return;
+
+abort:
+#ifdef DEBUG
+       asc_DumpLog("asc_intr");
+#endif
+#if 0
+       panic("asc_intr");
+#else
+       boot(4); /* XXX */
+#endif
+}
+
+/*
+ * All the many little things that the interrupt
+ * routine might switch to.
+ */
+
+/* ARGSUSED */
+static int
+script_nop(asc, status, ss, ir)
+       register asc_softc_t asc;
+       register int status, ss, ir;
+{
+       return (1);
+}
+
+/* ARGSUSED */
+static int
+asc_get_status(asc, status, ss, ir)
+       register asc_softc_t asc;
+       register int status, ss, ir;
+{
+       register asc_regmap_t *regs = asc->regs;
+       register int data;
+
+       /*
+        * Get the last two bytes in the FIFO.
+        */
+       if ((data = regs->asc_flags & ASC_FLAGS_FIFO_CNT) != 2) {
+               printf("asc_get_status: cmdreg %x, fifo cnt %d\n",
+                      regs->asc_cmd, data); /* XXX */
+#ifdef DEBUG
+               asc_DumpLog("get_status"); /* XXX */
+#endif
+               if (data < 2) {
+                       asc->regs->asc_cmd = ASC_CMD_MSG_ACPT;
+                       readback(asc->regs->asc_cmd);
+                       return (0);
+               }
+               do {
+                       data = regs->asc_fifo;
+               } while ((regs->asc_flags & ASC_FLAGS_FIFO_CNT) > 2);
+       }
+
+       /* save the status byte */
+       asc->st[asc->target].statusByte = data = regs->asc_fifo;
+#ifdef DEBUG
+       if (asc_logp == asc_log)
+               asc_log[NLOG - 1].msg = data;
+       else
+               asc_logp[-1].msg = data;
+#endif
+
+       /* get the (presumed) command_complete message */
+       if ((data = regs->asc_fifo) == SCSI_COMMAND_COMPLETE)
+               return (1);
+
+#ifdef DEBUG
+       printf("asc_get_status: status %x cmd %x\n",
+               asc->st[asc->target].statusByte, data);
+       asc_DumpLog("asc_get_status");
+#endif
+       return (0);
+}
+
+/* ARGSUSED */
+static int
+asc_end(asc, status, ss, ir)
+       register asc_softc_t asc;
+       register int status, ss, ir;
+{
+       struct scsi_xfer *scsicmd;
+       struct scsi_link *sc_link;
+       State *state;
+       int i, target;
+
+       asc->state = ASC_STATE_IDLE;
+       target = asc->target;
+       asc->target = -1;
+       scsicmd = asc->cmd[target];
+       sc_link = scsicmd->sc_link;
+       asc->cmd[target] = (struct scsi_xfer *)0;
+       state = &asc->st[target];
+
+#ifdef DEBUG
+       if (asc_debug > 1) {
+               printf("asc_end: %s target %d cmd %x err %d resid %d\n",
+                       asc->sc_dev.dv_xname, target,
+                       state->cmd.opcode, scsicmd->error, state->buflen);
+       }
+#endif
+#ifdef DIAGNOSTIC
+       if (target < 0 || !scsicmd)
+               panic("asc_end");
+#endif
+
+       /* look for disconnected devices */
+       for (i = 0; i < ASC_NCMD; i++) {
+               if (!asc->cmd[i] || !(asc->st[i].flags & DISCONN))
+                       continue;
+               asc->regs->asc_cmd = ASC_CMD_ENABLE_SEL;
+               readback(asc->regs->asc_cmd);
+               asc->state = ASC_STATE_RESEL;
+               asc->script = &asc_scripts[SCRIPT_RESEL];
+               break;
+       }
+
+       if(scsicmd->error == XS_NOERROR && !(state->flags & CHECK_SENSE)) {
+               if((state->statusByte & ST_MASK) == SCSI_CHECK) {
+                       struct scsi_sense *ss = (void *)&state->cmd;
+                       /* Save return values */
+                       scsicmd->resid = state->buflen;
+                       scsicmd->status = state->statusByte;
+                       /* Set up sense request command */
+                       bzero(ss, sizeof(*ss));
+                       ss->opcode = REQUEST_SENSE;
+                       ss->byte2 = sc_link->lun << 5;
+                       ss->length = sizeof(struct scsi_sense_data);
+                       state->cmdlen = sizeof(*ss);
+                       state->buf = (vm_offset_t)&scsicmd->sense;
+                       state->buflen = sizeof(struct scsi_sense_data);
+                       state->flags |= CHECK_SENSE;
+#ifdef R4K
+                       R4K_HitFlushDCache(state->buf, state->buflen);
+#else
+                       R3K_FlushDCache();
+#endif
+                       asc->cmd[target] = scsicmd;
+                       asc_startcmd(asc, target);
+                       return(0);
+               }
+       }
+
+       if(scsicmd->error == XS_NOERROR && (state->flags & CHECK_SENSE)) {
+               scsicmd->error = XS_SENSE;
+       }
+       else {
+               scsicmd->resid = state->buflen;
+       }
+       state->flags &= ~CHECK_SENSE;
+
+       /*
+        * Look for another device that is ready.
+        * May want to keep last one started and increment for fairness
+        * rather than always starting at zero.
+        */
+       for (i = 0; i < ASC_NCMD; i++) {
+               if (asc->cmd[i] == 0 && asc->cmdq[i] != 0) {
+                       asc->cmd[i] = asc->cmdq[i];
+                       asc->cmdq[i] = 0;
+               }
+       }
+       for (i = 0; i < ASC_NCMD; i++) {
+               /* don't restart a disconnected command */
+               if (!asc->cmd[i] || (asc->st[i].flags & DISCONN))
+                       continue;
+               asc_startcmd(asc, i);
+               break;
+       }
+
+       /* signal device driver that the command is done */
+       scsicmd->flags |= ITSDONE;
+       scsi_done(scsicmd);
+
+       return (0);
+}
+
+/* ARGSUSED */
+static int
+asc_dma_in(asc, status, ss, ir)
+       register asc_softc_t asc;
+       register int status, ss, ir;
+{
+       register asc_regmap_t *regs = asc->regs;
+       register State *state = &asc->st[asc->target];
+       register int len;
+
+       /* check for previous chunk in buffer */
+       if (state->flags & DMA_IN_PROGRESS) {
+               /*
+                * Only count bytes that have been copied to memory.
+                * There may be some bytes in the FIFO if synchonous transfers
+                * are in progress.
+                */
+               DMA_END(&asc->dma);
+               ASC_TC_GET(regs, len);
+               len = state->dmalen - len;
+               state->buf += len;
+               state->buflen -= len;
+       }
+
+       /* setup to start reading the next chunk */
+       len = state->buflen;
+#ifdef DEBUG
+       if (asc_logp == asc_log)
+               asc_log[NLOG - 1].resid = len;
+       else
+               asc_logp[-1].resid = len;
+#endif
+       if (len > state->dmaBufSize)
+               len = state->dmaBufSize;
+       state->dmalen = len;
+       DMA_START(&asc->dma, (caddr_t)state->buf, len, DMA_FROM_DEV);
+       ASC_TC_PUT(regs, len);
+#ifdef DEBUG
+       if (asc_debug > 2)
+               printf("asc_dma_in: buflen %d, len %d\n", state->buflen, len);
+#endif
+
+       /* check for next chunk */
+       state->flags |= DMA_IN_PROGRESS;
+       if (len != state->buflen) {
+               regs->asc_cmd = ASC_CMD_XFER_INFO | ASC_CMD_DMA;
+               readback(regs->asc_cmd);
+               asc->script = &asc_scripts[SCRIPT_CONTINUE_IN];
+               return (0);
+       }
+       return (1);
+}
+
+/* ARGSUSED */
+static int
+asc_last_dma_in(asc, status, ss, ir)
+       register asc_softc_t asc;
+       register int status, ss, ir;
+{
+       register asc_regmap_t *regs = asc->regs;
+       register State *state = &asc->st[asc->target];
+       register int len, fifo;
+
+       DMA_END(&asc->dma);
+       ASC_TC_GET(regs, len);
+       fifo = regs->asc_flags & ASC_FLAGS_FIFO_CNT;
+#ifdef DEBUG
+       if (asc_debug > 2)
+               printf("asc_last_dma_in: buflen %d dmalen %d tc %d fifo %d\n",
+                       state->buflen, state->dmalen, len, fifo);
+#endif
+       if (fifo) {
+               /* device must be trying to send more than we expect */
+               regs->asc_cmd = ASC_CMD_FLUSH;
+               readback(regs->asc_cmd);
+       }
+       state->flags &= ~DMA_IN_PROGRESS;
+       len = state->dmalen - len;
+       state->buflen -= len;
+
+       return (1);
+}
+
+/* ARGSUSED */
+static int
+asc_resume_in(asc, status, ss, ir)
+       register asc_softc_t asc;
+       register int status, ss, ir;
+{
+       register asc_regmap_t *regs = asc->regs;
+       register State *state = &asc->st[asc->target];
+       register int len;
+
+       /* setup to start reading the next chunk */
+       len = state->buflen;
+#ifdef DEBUG
+       if (asc_logp == asc_log)
+               asc_log[NLOG - 1].resid = len;
+       else
+               asc_logp[-1].resid = len;
+#endif
+       if (len > state->dmaBufSize)
+               len = state->dmaBufSize;
+       state->dmalen = len;
+#ifdef DEBUG
+       if (asc_logp == asc_log)
+               asc_log[NLOG - 1].resid = len;
+       else
+               asc_logp[-1].resid = len;
+#endif
+       DMA_START(&asc->dma, (caddr_t)state->buf, len, DMA_FROM_DEV);
+       ASC_TC_PUT(regs, len);
+#ifdef DEBUG
+       if (asc_debug > 2)
+               printf("asc_resume_in: buflen %d, len %d\n", state->buflen,
+                       len);
+#endif
+
+       /* check for next chunk */
+       state->flags |= DMA_IN_PROGRESS;
+       if (len != state->buflen) {
+               regs->asc_cmd = ASC_CMD_XFER_INFO | ASC_CMD_DMA;
+               readback(regs->asc_cmd);
+               asc->script = &asc_scripts[SCRIPT_CONTINUE_IN];
+               return (0);
+       }
+       return (1);
+}
+
+/* ARGSUSED */
+static int
+asc_resume_dma_in(asc, status, ss, ir)
+       register asc_softc_t asc;
+       register int status, ss, ir;
+{
+       register asc_regmap_t *regs = asc->regs;
+       register State *state = &asc->st[asc->target];
+       register int len, off;
+
+       /* setup to finish reading the current chunk */
+       len = state->dmaresid;
+       off = state->dmalen - len;
+       if ((off & 1) && state->sync_offset) {
+               printf("asc_resume_dma_in: odd xfer dmalen %d len %d off %d\n",
+                       state->dmalen, len, off); /* XXX */
+               regs->asc_res_fifo = ((u_char *)state->buf)[off];
+/*XXX Need to flush cache ? */
+       }
+       DMA_START(&asc->dma, (caddr_t)state->buf + off, len, DMA_FROM_DEV);
+       ASC_TC_PUT(regs, len);
+#ifdef DEBUG
+       if (asc_debug > 2)
+               printf("asc_resume_dma_in: buflen %d dmalen %d len %d off %d\n",
+                       state->dmalen, state->buflen, len, off);
+#endif
+
+       /* check for next chunk */
+       state->flags |= DMA_IN_PROGRESS;
+       if (state->dmalen != state->buflen) {
+               regs->asc_cmd = ASC_CMD_XFER_INFO | ASC_CMD_DMA;
+               readback(regs->asc_cmd);
+               asc->script = &asc_scripts[SCRIPT_CONTINUE_IN];
+               return (0);
+       }
+       return (1);
+}
+
+/* ARGSUSED */
+static int
+asc_dma_out(asc, status, ss, ir)
+       register asc_softc_t asc;
+       register int status, ss, ir;
+{
+       register asc_regmap_t *regs = asc->regs;
+       register State *state = &asc->st[asc->target];
+       register int len, fifo;
+
+       if (state->flags & DMA_IN_PROGRESS) {
+               /* check to be sure previous chunk was finished */
+               ASC_TC_GET(regs, len);
+               fifo = regs->asc_flags & ASC_FLAGS_FIFO_CNT;
+               if (len || fifo)
+                       printf("asc_dma_out: buflen %d dmalen %d tc %d fifo %d\n",
+                               state->buflen, state->dmalen, len, fifo); /* XXX */
+               len += fifo;
+               len = state->dmalen - len;
+               state->buf += len;
+               state->buflen -= len;
+       }
+
+       /* setup for this chunk */
+       len = state->buflen;
+#ifdef DEBUG
+       if (asc_logp == asc_log)
+               asc_log[NLOG - 1].resid = len;
+       else
+               asc_logp[-1].resid = len;
+#endif
+       if (len > state->dmaBufSize)
+               len = state->dmaBufSize;
+       state->dmalen = len;
+       DMA_START(&asc->dma, (caddr_t)state->buf, len, DMA_TO_DEV);
+       ASC_TC_PUT(regs, len);
+#ifdef DEBUG
+       if (asc_debug > 2)
+               printf("asc_dma_out: buflen %d, len %d\n", state->buflen, len);
+#endif
+
+       /* check for next chunk */
+       state->flags |= DMA_IN_PROGRESS;
+       if (len != state->buflen) {
+               regs->asc_cmd = ASC_CMD_XFER_INFO | ASC_CMD_DMA;
+               readback(regs->asc_cmd);
+               asc->script = &asc_scripts[SCRIPT_CONTINUE_OUT];
+               return (0);
+       }
+       return (1);
+}
+
+/* ARGSUSED */
+static int
+asc_last_dma_out(asc, status, ss, ir)
+       register asc_softc_t asc;
+       register int status, ss, ir;
+{
+       register asc_regmap_t *regs = asc->regs;
+       register State *state = &asc->st[asc->target];
+       register int len, fifo;
+
+       ASC_TC_GET(regs, len);
+       fifo = regs->asc_flags & ASC_FLAGS_FIFO_CNT;
+#ifdef DEBUG
+       if (asc_debug > 2)
+               printf("asc_last_dma_out: buflen %d dmalen %d tc %d fifo %d\n",
+                       state->buflen, state->dmalen, len, fifo);
+#endif
+       if (fifo) {
+               len += fifo;
+               regs->asc_cmd = ASC_CMD_FLUSH;
+               readback(regs->asc_cmd);
+       }
+       state->flags &= ~DMA_IN_PROGRESS;
+       len = state->dmalen - len;
+       state->buflen -= len;
+       return (1);
+}
+
+/* ARGSUSED */
+static int
+asc_resume_out(asc, status, ss, ir)
+       register asc_softc_t asc;
+       register int status, ss, ir;
+{
+       register asc_regmap_t *regs = asc->regs;
+       register State *state = &asc->st[asc->target];
+       register int len;
+
+       /* setup for this chunk */
+       len = state->buflen;
+#ifdef DEBUG
+       if (asc_logp == asc_log)
+               asc_log[NLOG - 1].resid = len;
+       else
+               asc_logp[-1].resid = len;
+#endif
+       if (len > state->dmaBufSize)
+               len = state->dmaBufSize;
+       state->dmalen = len;
+#ifdef DEBUG
+       if (asc_logp == asc_log)
+               asc_log[NLOG - 1].resid = len;
+       else
+               asc_logp[-1].resid = len;
+#endif
+       DMA_START(&asc->dma, (caddr_t)state->buf, len, DMA_TO_DEV);
+       ASC_TC_PUT(regs, len);
+#ifdef DEBUG
+       if (asc_debug > 2)
+               printf("asc_resume_out: buflen %d, len %d\n", state->buflen,
+                       len);
+#endif
+
+       /* check for next chunk */
+       state->flags |= DMA_IN_PROGRESS;
+       if (len != state->buflen) {
+               regs->asc_cmd = ASC_CMD_XFER_INFO | ASC_CMD_DMA;
+               readback(regs->asc_cmd);
+               asc->script = &asc_scripts[SCRIPT_CONTINUE_OUT];
+               return (0);
+       }
+       return (1);
+}
+
+/* ARGSUSED */
+static int
+asc_resume_dma_out(asc, status, ss, ir)
+       register asc_softc_t asc;
+       register int status, ss, ir;
+{
+       register asc_regmap_t *regs = asc->regs;
+       register State *state = &asc->st[asc->target];
+       register int len, off;
+
+       /* setup to finish writing this chunk */
+       len = state->dmaresid;
+       off = state->dmalen - len;
+       if (off & 1) {
+               printf("asc_resume_dma_out: odd xfer dmalen %d len %d off %d\n",
+                       state->dmalen, len, off); /* XXX */
+               regs->asc_fifo = ((u_char *)state->buf)[off];
+/*XXX Need to flush Cache ? */
+               off++;
+               len--;
+       }
+       DMA_START(&asc->dma, (caddr_t)state->buf + off, len, DMA_TO_DEV);
+       ASC_TC_PUT(regs, len);
+#ifdef DEBUG
+       if (asc_debug > 2)
+               printf("asc_resume_dma_out: buflen %d dmalen %d len %d off %d\n",
+                       state->dmalen, state->buflen, len, off);
+#endif
+
+       /* check for next chunk */
+       state->flags |= DMA_IN_PROGRESS;
+       if (state->dmalen != state->buflen) {
+               regs->asc_cmd = ASC_CMD_XFER_INFO | ASC_CMD_DMA;
+               readback(regs->asc_cmd);
+               asc->script = &asc_scripts[SCRIPT_CONTINUE_OUT];
+               return (0);
+       }
+       return (1);
+}
+
+/* ARGSUSED */
+static int
+asc_sendsync(asc, status, ss, ir)
+       register asc_softc_t asc;
+       register int status, ss, ir;
+{
+       register asc_regmap_t *regs = asc->regs;
+       register State *state = &asc->st[asc->target];
+
+       /* send the extended synchronous negotiation message */
+       regs->asc_fifo = SCSI_EXTENDED_MSG;
+       wbflush();
+       regs->asc_fifo = 3;
+       wbflush();
+       regs->asc_fifo = SCSI_SYNCHRONOUS_XFER;
+       wbflush();
+       regs->asc_fifo = SCSI_MIN_PERIOD;
+       wbflush();
+       regs->asc_fifo = ASC_MAX_OFFSET;
+       /* state to resume after we see the sync reply message */
+       state->script = asc->script + 2;
+       state->msglen = 0;
+       return (1);
+}
+
+/* ARGSUSED */
+static int
+asc_replysync(asc, status, ss, ir)
+       register asc_softc_t asc;
+       register int status, ss, ir;
+{
+       register asc_regmap_t *regs = asc->regs;
+       register State *state = &asc->st[asc->target];
+
+#ifdef DEBUG
+       if (asc_debug > 2)
+               printf("asc_replysync: %x %x\n",
+                       asc_to_scsi_period[state->sync_period] * asc->tb_ticks,
+                       state->sync_offset);
+#endif
+       /* send synchronous transfer in response to a request */
+       regs->asc_fifo = SCSI_EXTENDED_MSG;
+       wbflush();
+       regs->asc_fifo = 3;
+       wbflush();
+       regs->asc_fifo = SCSI_SYNCHRONOUS_XFER;
+       wbflush();
+       regs->asc_fifo = asc_to_scsi_period[state->sync_period] * asc->tb_ticks;
+       wbflush();
+       regs->asc_fifo = state->sync_offset;
+       regs->asc_cmd = ASC_CMD_XFER_INFO;
+       readback(regs->asc_cmd);
+
+       /* return to the appropriate script */
+       if (!state->script) {
+#ifdef DEBUG
+               asc_DumpLog("asc_replsync");
+#endif
+               panic("asc_replysync");
+       }
+       asc->script = state->script;
+       state->script = (script_t *)0;
+       return (0);
+}
+
+/* ARGSUSED */
+static int
+asc_msg_in(asc, status, ss, ir)
+       register asc_softc_t asc;
+       register int status, ss, ir;
+{
+       register asc_regmap_t *regs = asc->regs;
+       register State *state = &asc->st[asc->target];
+       register int msg;
+       int i;
+
+       /* read one message byte */
+       msg = regs->asc_fifo;
+#ifdef DEBUG
+       if (asc_logp == asc_log)
+               asc_log[NLOG - 1].msg = msg;
+       else
+               asc_logp[-1].msg = msg;
+#endif
+
+       /* check for multi-byte message */
+       if (state->msglen != 0) {
+               /* first byte is the message length */
+               if (state->msglen < 0) {
+                       state->msglen = msg;
+                       return (1);
+               }
+               if (state->msgcnt >= state->msglen)
+                       goto abort;
+               state->msg_in[state->msgcnt++] = msg;
+
+               /* did we just read the last byte of the message? */
+               if (state->msgcnt != state->msglen)
+                       return (1);
+
+               /* process an extended message */
+#ifdef DEBUG
+               if (asc_debug > 2)
+                       printf("asc_msg_in: msg %x %x %x\n",
+                               state->msg_in[0],
+                               state->msg_in[1],
+                               state->msg_in[2]);
+#endif
+               switch (state->msg_in[0]) {
+               case SCSI_SYNCHRONOUS_XFER:
+                       state->flags |= DID_SYNC;
+                       state->sync_offset = state->msg_in[2];
+
+                       /* convert SCSI period to ASC period */
+                       i = state->msg_in[1] / asc->tb_ticks;
+                       if (i < asc->min_period)
+                               i = asc->min_period;
+                       else if (i >= asc->max_period) {
+                               /* can't do sync transfer, period too long */
+                               printf("%s: SCSI device %d: sync xfer period too long (%d)\n",
+                                       asc->sc_dev.dv_xname, asc->target, i);
+                               i = asc->max_period;
+                               state->sync_offset = 0;
+                       }
+                       if ((i * asc->tb_ticks) != state->msg_in[1])
+                               i++;
+                       state->sync_period = i & 0x1F;
+
+                       /*
+                        * If this is a request, check minimums and
+                        * send back an acknowledge.
+                        */
+                       if (!(state->flags & TRY_SYNC)) {
+                               regs->asc_cmd = ASC_CMD_SET_ATN;
+                               readback(regs->asc_cmd);
+
+                               if (state->sync_period < asc->min_period)
+                                       state->sync_period =
+                                               asc->min_period;
+                               if (state->sync_offset > ASC_MAX_OFFSET)
+                                       state->sync_offset =
+                                               ASC_MAX_OFFSET;
+                               asc->script = &asc_scripts[SCRIPT_REPLY_SYNC];
+                               regs->asc_syn_p = state->sync_period;
+                               readback(regs->asc_syn_p);
+                               regs->asc_syn_o = state->sync_offset;
+                               readback(regs->asc_syn_o);
+                               regs->asc_cmd = ASC_CMD_MSG_ACPT;
+                               readback(regs->asc_cmd);
+                               return (0);
+                       }
+
+                       regs->asc_syn_p = state->sync_period;
+                       readback(regs->asc_syn_p);
+                       regs->asc_syn_o = state->sync_offset;
+                       readback(regs->asc_syn_o);
+                       goto done;
+
+               default:
+                       printf("%s: SCSI device %d: rejecting extended message 0x%x\n",
+                                asc->sc_dev.dv_xname, asc->target,
+                               state->msg_in[0]);
+                       goto reject;
+               }
+       }
+
+       /* process first byte of a message */
+#ifdef DEBUG
+       if (asc_debug > 2)
+               printf("asc_msg_in: msg %x\n", msg);
+#endif
+       switch (msg) {
+#if 0
+       case SCSI_MESSAGE_REJECT:
+               printf(" did not like SYNCH xfer "); /* XXX */
+               state->flags |= DID_SYNC;
+               regs->asc_cmd = ASC_CMD_MSG_ACPT;
+               readback(regs->asc_cmd);
+               status = asc_wait(regs, ASC_CSR_INT);
+               ir = regs->asc_intr;
+               /* some just break out here, some dont */
+               if (ASC_PHASE(status) == ASC_PHASE_MSG_OUT) {
+                       regs->asc_fifo = SCSI_ABORT;
+                       regs->asc_cmd = ASC_CMD_XFER_INFO;
+                       readback(regs->asc_cmd);
+                       status = asc_wait(regs, ASC_CSR_INT);
+                       ir = regs->asc_intr;
+               }
+               if (ir & ASC_INT_DISC) {
+                       asc_end(asc, status, 0, ir);
+                       return (0);
+               }
+               goto status;
+#endif /* 0 */
+
+       case SCSI_EXTENDED_MSG: /* read an extended message */
+               /* setup to read message length next */
+               state->msglen = -1;
+               state->msgcnt = 0;
+               return (1);
+
+       case SCSI_NO_OP:
+               break;
+
+       case SCSI_SAVE_DATA_POINTER:
+               /* expect another message */
+               return (1);
+
+       case SCSI_RESTORE_POINTERS:
+               /*
+                * Need to do the following if resuming synchonous data in
+                * on an odd byte boundary.
+               regs->asc_cnfg2 |= ASC_CNFG2_RFB;
+                */
+               break;
+
+       case SCSI_DISCONNECT:
+               if (state->flags & DISCONN)
+                       goto abort;
+               state->flags |= DISCONN;
+               regs->asc_cmd = ASC_CMD_MSG_ACPT;
+               readback(regs->asc_cmd);
+               asc->script = &asc_scripts[SCRIPT_DISCONNECT];
+               return (0);
+
+       default:
+               printf("%s: SCSI device %d: rejecting message 0x%x\n",
+                       asc->sc_dev.dv_xname, asc->target, msg);
+       reject:
+               /* request a message out before acknowledging this message */
+               state->msg_out = SCSI_MESSAGE_REJECT;
+               regs->asc_cmd = ASC_CMD_SET_ATN;
+               readback(regs->asc_cmd);
+       }
+
+done:
+       /* return to original script */
+       regs->asc_cmd = ASC_CMD_MSG_ACPT;
+       readback(regs->asc_cmd);
+       if (!state->script) {
+       abort:
+#ifdef DEBUG
+               asc_DumpLog("asc_msg_in");
+#endif
+               panic("asc_msg_in");
+       }
+       asc->script = state->script;
+       state->script = (script_t *)0;
+       return (0);
+}
+
+/* ARGSUSED */
+static int
+asc_disconnect(asc, status, ss, ir)
+       register asc_softc_t asc;
+       register int status, ss, ir;
+{
+       register State *state = &asc->st[asc->target];
+
+#ifdef DIAGNOSTIC
+       if (!(state->flags & DISCONN)) {
+               printf("asc_disconnect: device %d: DISCONN not set!\n",
+                       asc->target);
+       }
+#endif /* DIAGNOSTIC */
+       asc->target = -1;
+       asc->state = ASC_STATE_RESEL;
+       return (1);
+}
+
+#ifdef DEBUG
+/*
+ * Dump the log buffer.
+ */
+asc_DumpLog(str)
+       char *str;
+{
+       register struct asc_log *lp;
+       register u_int status;
+
+       printf("asc: %s: cmd %x bn %d cnt %d\n", str, asc_debug_cmd,
+               asc_debug_bn, asc_debug_sz);
+       lp = asc_logp;
+       do {
+               status = lp->status;
+               printf("asc%d tgt %d status %x ss %x ir %x cond %d:%x msg %x resid %d\n",
+                       status >> 24,
+                       lp->target,
+                       (status >> 16) & 0xFF,
+                       (status >> 8) & 0xFF,
+                       status & 0XFF,
+                       lp->state,
+                       asc_scripts[lp->state].condition,
+                       lp->msg, lp->resid);
+               if (++lp >= &asc_log[NLOG])
+                       lp = asc_log;
+       } while (lp != asc_logp);
+}
+#endif /* DEBUG */
+
+#endif /* NASC > 0 */
diff --git a/sys/arch/wgrisc/dev/ascreg.h b/sys/arch/wgrisc/dev/ascreg.h
new file mode 100644 (file)
index 0000000..b975028
--- /dev/null
@@ -0,0 +1,326 @@
+/*     $OpenBSD: ascreg.h,v 1.1.1.1 1997/02/06 16:02:42 pefo Exp $     */
+/*-
+ * Copyright (c) 1992, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Ralph Campbell and Rick Macklem.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     from: @(#)ascreg.h      8.1 (Berkeley) 6/10/93
+ *      $Id: ascreg.h,v 1.1.1.1 1997/02/06 16:02:42 pefo Exp $
+ */
+
+/* 
+ * Mach Operating System
+ * Copyright (c) 1991,1990,1989 Carnegie Mellon University
+ * All Rights Reserved.
+ * 
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ * 
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS 
+ * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ * 
+ * Carnegie Mellon requests users of this software to return to
+ * 
+ *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
+ *  School of Computer Science
+ *  Carnegie Mellon University
+ *  Pittsburgh PA 15213-3890
+ * 
+ * any improvements or extensions that they make and grant Carnegie the
+ * rights to redistribute these changes.
+ */
+
+/*
+ * HISTORY
+ * Log:        scsi_53C94.h,v
+ * Revision 2.4  91/02/05  17:44:59  mrt
+ *     Added author notices
+ *     [91/02/04  11:18:32  mrt]
+ * 
+ *     Changed to use new Mach copyright
+ *     [91/02/02  12:17:11  mrt]
+ * 
+ * Revision 2.3  90/12/05  23:34:46  af
+ *     Documented max DMA xfer size.
+ *     [90/12/03  23:39:36  af]
+ * 
+ * Revision 2.1.1.1  90/11/01  03:38:54  af
+ *     Created, from the DEC specs:
+ *     "PMAZ-AA TURBOchannel SCSI Module Functional Specification"
+ *     Workstation Systems Engineering, Palo Alto, CA. Aug 27, 1990.
+ *     And from the NCR data sheets
+ *     "NCR 53C94, 53C95, 53C96 Advanced SCSI Controller"
+ *     [90/09/03            af]
+ */
+
+/*
+ *     File: scsi_53C94.h
+ *     Author: Alessandro Forin, Carnegie Mellon University
+ *     Date:   9/90
+ *
+ *     Defines for the NCR 53C94 ASC (SCSI interface)
+ *     Some gotcha came from the "86C01/53C94 DMA lab work" written
+ *     by Ken Stewart (NCR MED Logic Products Applications Engineer)
+ *     courtesy of NCR.  Thanks Ken !
+ */
+
+#define ASC_OFFSET_53C94       0x0     /* from module base */
+
+#define ASC_NCMD               7       /* Number of simultaneous cmds */
+
+/*
+ * Synch xfer parameters, and timing conversions
+ */
+#define SCSI_MIN_PERIOD                50      /* in 4 nsecs units */
+#define ASC_MIN_PERIOD40       8       /* in CLKS/BYTE, 1 CLK = 25nsecs */
+#define ASC_MIN_PERIOD25       5       /* in CLKS/BYTE, 1 CLK = 40nsecs */
+#define ASC_MIN_PERIOD20       4       /* in CLKS/BYTE, 1 CLK = 50nsecs */
+#define ASC_MIN_PERIOD12       3       /* in CLKS/BYTE, 1 CLK = 80nsecs */
+#define ASC_MAX_PERIOD40       56      /* in CLKS/BYTE, 1 CLK = 25nsecs */
+#define ASC_MAX_PERIOD25       35      /* in CLKS/BYTE, 1 CLK = 40nsecs */
+#define ASC_MAX_PERIOD20       28      /* in CLKS/BYTE, 1 CLK = 50nsecs */
+#define ASC_MAX_PERIOD12       18      /* in CLKS/BYTE, 1 CLK = 80nsecs */
+#define ASC_MAX_OFFSET         15      /* pure number */
+/*
+ * Register map, padded as needed
+ */
+
+typedef volatile struct {
+       u_char  asc_tc_lsb;     /* 00 rw: Transfer Counter LSB */
+       u_char  asc_tc_msb;     /* 01 rw: Transfer Counter MSB */
+       u_char  asc_fifo;       /* 02 rw: FIFO top */
+       u_char  asc_cmd;        /* 03 rw: Command */
+       u_char  asc_status;     /* 04 r:  Status */
+#define asc_dbus_id asc_status /* 04 w: Destination Bus ID */
+       u_char  asc_intr;       /* 05 r:  Interrupt */
+#define asc_sel_timo asc_intr  /* 05 w: (re)select timeout */
+       u_char  asc_ss;         /* 06 r:  Sequence Step */
+#define asc_syn_p asc_ss       /* 06 w: synchronous period */
+       u_char  asc_flags;      /* 07 r:  FIFO flags + seq step */
+#define asc_syn_o asc_flags    /* 07 w: synchronous offset */
+       u_char  asc_cnfg1;      /* 08 rw: Configuration 1 */
+       u_char  asc_ccf;        /* 09 w:  Clock Conv. Factor */
+       u_char  asc_test;       /* 0a w:  Test Mode */
+       u_char  asc_cnfg2;      /* 0b rw: Configuration 2 */
+       u_char  asc_cnfg3;      /* 0c rw: Configuration 3 */
+       u_char  asc_res_fifo;   /* 0d w: Reserve FIFO byte */
+       u_char  asc_tc_xsb;     /* 0e rw: Transfer Counter Xtended */
+} asc_regmap_t;
+
+/*
+ * Transfer Count: access macros
+ * That a NOP is required after loading the dma counter
+ * I learned on the NCR test code. Sic.
+ */
+
+#define        ASC_TC_MAX      0x10000
+
+#define ASC_TC_GET(ptr, val)                           \
+       val = (ptr)->asc_tc_lsb | ((ptr)->asc_tc_msb << 8) | ((ptr)->asc_tc_xsb << 16)
+#define ASC_TC_PUT(ptr, val)                           \
+       (ptr)->asc_tc_lsb = (val);                      \
+       (ptr)->asc_tc_msb = (val) >> 8;                 \
+       (ptr)->asc_tc_xsb = (val) >> 16;                \
+       (ptr)->asc_cmd = ASC_CMD_NOP | ASC_CMD_DMA;
+
+/*
+ * Command register (command codes)
+ */
+
+#define ASC_CMD_DMA            0x80
+                                       /* Miscellaneous */
+#define ASC_CMD_NOP            0x00
+#define ASC_CMD_FLUSH          0x01
+#define ASC_CMD_RESET          0x02
+#define ASC_CMD_BUS_RESET      0x03
+                                       /* Initiator state */
+#define ASC_CMD_XFER_INFO      0x10
+#define ASC_CMD_I_COMPLETE     0x11
+#define ASC_CMD_MSG_ACPT       0x12
+#define ASC_CMD_XFER_PAD       0x18
+#define ASC_CMD_SET_ATN                0x1a
+#define ASC_CMD_CLR_ATN                0x1b
+                                       /* Target state */
+#define ASC_CMD_SND_MSG                0x20
+#define ASC_CMD_SND_STATUS     0x21
+#define ASC_CMD_SND_DATA       0x22
+#define ASC_CMD_DISC_SEQ       0x23
+#define ASC_CMD_TERM           0x24
+#define ASC_CMD_T_COMPLETE     0x25
+#define ASC_CMD_DISC           0x27
+#define ASC_CMD_RCV_MSG                0x28
+#define ASC_CMD_RCV_CDB                0x29
+#define ASC_CMD_RCV_DATA       0x2a
+#define ASC_CMD_RCV_CMD                0x2b
+#define ASC_CMD_ABRT_DMA       0x04
+                                       /* Disconnected state */
+#define ASC_CMD_RESELECT       0x40
+#define ASC_CMD_SEL            0x41
+#define ASC_CMD_SEL_ATN                0x42
+#define ASC_CMD_SEL_ATN_STOP   0x43
+#define ASC_CMD_ENABLE_SEL     0x44
+#define ASC_CMD_DISABLE_SEL    0x45
+#define ASC_CMD_SEL_ATN3       0x46
+
+/*
+ * Status register, and phase encoding
+ */
+
+#define ASC_CSR_INT            0x80
+#define ASC_CSR_GE             0x40
+#define ASC_CSR_PE             0x20
+#define ASC_CSR_TC             0x10
+#define ASC_CSR_VGC            0x08
+#define ASC_CSR_MSG            0x04
+#define ASC_CSR_CD             0x02
+#define ASC_CSR_IO             0x01
+
+#define        ASC_PHASE(csr)          ((csr) & 0x7)
+#define ASC_PHASE_DATAO                0x0
+#define ASC_PHASE_DATAI                0x1
+#define ASC_PHASE_COMMAND      0x2
+#define ASC_PHASE_STATUS       0x3
+                               /* 4..5 ANSI reserved */
+#define ASC_PHASE_MSG_OUT      0x6
+#define ASC_PHASE_MSG_IN       0x7
+
+/*
+ * Destination Bus ID
+ */
+
+#define ASC_DEST_ID_MASK       0x07
+
+/*
+ * Interrupt register
+ */
+
+#define ASC_INT_RESET          0x80
+#define ASC_INT_ILL            0x40
+#define ASC_INT_DISC           0x20
+#define ASC_INT_BS             0x10
+#define ASC_INT_FC             0x08
+#define ASC_INT_RESEL          0x04
+#define ASC_INT_SEL_ATN                0x02
+#define ASC_INT_SEL            0x01
+
+/*
+ * Timeout register:
+ *
+ *     val = (timeout * CLK_freq) / (8192 * CCF);
+ */
+
+#define        ASC_TIMEOUT_250(clk, ccf)       (((clk) * 31) / (ccf))
+
+/*
+ * Sequence Step register
+ */
+
+#define ASC_SS_RESERVED                0xf0
+#define ASC_SS_SOM             0x08
+#define ASC_SS_MASK            0x07
+#define        ASC_SS(ss)              ((ss) & ASC_SS_MASK)
+
+/*
+ * Synchronous Transfer Period
+ */
+
+#define ASC_STP_MASK           0x1f
+#define ASC_STP_MIN            0x05            /* 5 clk per byte */
+#define ASC_STP_MAX            0x04            /* after ovfl, 35 clk/byte */
+
+/*
+ * FIFO flags
+ */
+
+#define ASC_FLAGS_SEQ_STEP     0xe0
+#define ASC_FLAGS_FIFO_CNT     0x1f
+
+/*
+ * Synchronous offset
+ */
+
+#define ASC_SYNO_MASK          0x0f            /* 0 -> asyn */
+
+/*
+ * Configuration 1
+ */
+
+#define ASC_CNFG1_SLOW         0x80
+#define ASC_CNFG1_SRD          0x40
+#define ASC_CNFG1_P_TEST       0x20
+#define ASC_CNFG1_P_CHECK      0x10
+#define ASC_CNFG1_TEST         0x08
+#define ASC_CNFG1_MY_BUS_ID    0x07
+
+/*
+ * CCF register
+ */
+
+#define        ASC_CCF(clk)            ((((clk) - 1) / 5) + 1)
+
+/*
+ * Test register
+ */
+
+#define ASC_TEST_XXXX          0xf8
+#define ASC_TEST_HI_Z          0x04
+#define ASC_TEST_I             0x02
+#define ASC_TEST_T             0x01
+
+/*
+ * Configuration 2
+ */
+
+#define ASC_CNFG2_RFB          0x80
+#define ASC_CNFG2_EPL          0x40
+#define ASC_CNFG2_EBC          0x20
+#define ASC_CNFG2_DREQ_HIZ     0x10
+#define ASC_CNFG2_SCSI2                0x08
+#define ASC_CNFG2_BPA          0x04
+#define ASC_CNFG2_RPE          0x02
+#define ASC_CNFG2_DPE          0x01
+
+/*
+ * Configuration 3
+ */
+
+#define ASC_CNFG3_RESERVED     0xf8
+#define ASC_CNFG3_SRB          0x04
+#define ASC_CNFG3_ALT_DMA      0x02
+#define ASC_CNFG3_T8           0x01
+
+#define        ST_MASK 0x3e
diff --git a/sys/arch/wgrisc/dev/com_risc.c b/sys/arch/wgrisc/dev/com_risc.c
new file mode 100644 (file)
index 0000000..aae04df
--- /dev/null
@@ -0,0 +1,195 @@
+/*     $OpenBSD: com_risc.c,v 1.1.1.1 1997/02/06 16:02:42 pefo Exp $   */
+
+/*
+ * Copyright (c) 1993, 1994 Charles Hannum.
+ * Copyright (c) 1990 William F. Jolitz, TeleMuse
+ * 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 software is a component of "386BSD" developed by 
+ *     William F. Jolitz, TeleMuse.
+ * 4. Neither the name of the developer nor the name "386BSD"
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS A COMPONENT OF 386BSD DEVELOPED BY WILLIAM F. JOLITZ 
+ * AND IS INTENDED FOR RESEARCH AND EDUCATIONAL PURPOSES ONLY. THIS 
+ * SOFTWARE SHOULD NOT BE CONSIDERED TO BE A COMMERCIAL PRODUCT. 
+ * THE DEVELOPER URGES THAT USERS WHO REQUIRE A COMMERCIAL PRODUCT 
+ * NOT MAKE USE OF THIS WORK.
+ *
+ * FOR USERS WHO WISH TO UNDERSTAND THE 386BSD SYSTEM DEVELOPED
+ * BY WILLIAM F. JOLITZ, WE RECOMMEND THE USER STUDY WRITTEN 
+ * REFERENCES SUCH AS THE  "PORTING UNIX TO THE 386" SERIES 
+ * (BEGINNING JANUARY 1991 "DR. DOBBS JOURNAL", USA AND BEGINNING 
+ * JUNE 1991 "UNIX MAGAZIN", GERMANY) BY WILLIAM F. JOLITZ AND 
+ * LYNNE GREER JOLITZ, AS WELL AS OTHER BOOKS ON UNIX AND THE 
+ * ON-LINE 386BSD USER MANUAL BEFORE USE. A BOOK DISCUSSING THE INTERNALS 
+ * OF 386BSD ENTITLED "386BSD FROM THE INSIDE OUT" WILL BE AVAILABLE LATE 1992.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE DEVELOPER ``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 DEVELOPER 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.
+ */
+
+/*
+ * Device Driver for AT parallel printer port
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/device.h>
+#include <sys/tty.h>
+
+#include <machine/autoconf.h>
+#include <machine/bus.h>
+#include <machine/intr.h>
+
+#include <dev/isa/isavar.h>    /* XXX for isa_chipset_tag_t in com_softc */
+
+#include <dev/ic/comreg.h>
+#include <dev/ic/comvar.h>
+#include <dev/ic/ns16550reg.h>
+
+/* Macros to clear/set/test flags. */
+#define        SET(t, f)       (t) |= (f)
+#define        CLR(t, f)       (t) &= ~(f)
+#define        ISSET(t, f)     ((t) & (f))
+
+#undef  CONADDR         /* This is stupid but using devs before config .. */
+#define CONADDR 0xae400000
+
+int    com_risc_probe __P((struct device *, void *, void *));
+void   com_risc_attach __P((struct device *, struct device *, void *));
+
+struct cfattach com_risc_ca = {
+       sizeof(struct com_softc), com_risc_probe, com_risc_attach
+};
+
+int
+com_risc_probe(parent, match, aux)
+       struct device *parent;
+       void *match, *aux;
+{
+       bus_space_tag_t iot;
+       bus_space_handle_t ioh;
+       int iobase, needioh;
+       int rv = 1;
+       struct confargs *ca = aux;
+
+       if(!BUS_MATCHNAME(ca, "com"))
+               return(0);
+       iobase = (long)BUS_CVTADDR(ca);
+       iot = 0;
+       needioh = 1;
+
+       /* if it's in use as console, it's there. */
+       if (iobase == comconsaddr && !comconsattached)
+               goto out;
+
+       if (needioh && bus_space_map(iot, iobase, COM_NPORTS, 0, &ioh)) {
+               rv = 0;
+               goto out;
+       }
+       rv = comprobe1(iot, ioh, iobase);
+       if (needioh)
+               bus_space_unmap(iot, ioh, COM_NPORTS);
+
+out:
+       return (rv);
+}
+
+void
+com_risc_attach(parent, self, aux)
+       struct device *parent, *self;
+       void *aux;
+{
+       struct com_softc *sc = (void *)self;
+       int iobase;
+       bus_space_tag_t iot;
+       bus_space_handle_t ioh;
+       struct confargs *ca = aux;
+
+       sc->sc_hwflags = 0;
+       sc->sc_swflags = 0;
+       sc->sc_iobase = iobase = (bus_addr_t)BUS_CVTADDR(ca);
+       sc->sc_ioh = ioh = (bus_space_handle_t)iobase;
+       sc->sc_iot = iot = 0;
+
+       if (iobase == comconsaddr) {
+               comconsattached = 1;
+
+               /* 
+                * Need to reset baud rate, etc. of next print so reset
+                * comconsinit.  Also make sure console is always "hardwired".
+                */
+               delay(1000);                    /* wait for output to finish */
+               comconsinit = 0;
+               SET(sc->sc_hwflags, COM_HW_CONSOLE);
+               SET(sc->sc_swflags, COM_SW_SOFTCAR);
+       }
+
+
+       /* look for a NS 16550AF UART with FIFOs */
+       bus_space_write_1(iot, ioh, com_fifo,
+           FIFO_ENABLE | FIFO_RCV_RST | FIFO_XMT_RST | FIFO_TRIGGER_14);
+       delay(100);
+       if (ISSET(bus_space_read_1(iot, ioh, com_iir), IIR_FIFO_MASK) ==
+           IIR_FIFO_MASK)
+               if (ISSET(bus_space_read_1(iot, ioh, com_fifo),
+                   FIFO_TRIGGER_14) == FIFO_TRIGGER_14) {
+                       SET(sc->sc_hwflags, COM_HW_FIFO);
+                       printf(": ns16550a, working fifo\n");
+               } else
+                       printf(": ns16550, broken fifo\n");
+       else
+               printf(": ns8250 or ns16450, no fifo\n");
+       bus_space_write_1(iot, ioh, com_fifo, 0);
+
+       /* disable interrupts */
+       bus_space_write_1(iot, ioh, com_ier, 0);
+       bus_space_write_1(iot, ioh, com_mcr, 0);
+
+       BUS_INTR_ESTABLISH(ca, comintr, (void *)(long)sc);
+
+#ifdef KGDB
+       if (kgdb_dev == makedev(commajor, unit)) {
+               if (ISSET(sc->sc_hwflags, COM_HW_CONSOLE))
+                       kgdb_dev = -1;  /* can't debug over console port */
+               else {
+                       cominit(iot, ioh, kgdb_rate);
+                       if (kgdb_debug_init) {
+                               /*
+                                * Print prefix of device name,
+                                * let kgdb_connect print the rest.
+                                */
+                               printf("%s: ", sc->sc_dev.dv_xname);
+                               kgdb_connect(1);
+                       } else
+                               printf("%s: kgdb enabled\n",
+                                   sc->sc_dev.dv_xname);
+               }
+       }
+#endif
+
+       /* XXX maybe move up some? */
+       if (ISSET(sc->sc_hwflags, COM_HW_CONSOLE))
+               printf("%s: console\n", sc->sc_dev.dv_xname);
+}
diff --git a/sys/arch/wgrisc/dev/dma.h b/sys/arch/wgrisc/dev/dma.h
new file mode 100644 (file)
index 0000000..beb49e3
--- /dev/null
@@ -0,0 +1,147 @@
+/*     $OpenBSD: dma.h,v 1.1.1.1 1997/02/06 16:02:42 pefo Exp $ */
+
+/*
+ * Copyright (c) 1996 Per Fogelstrom
+ * 
+ * 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 under OpenBSD by
+ *     Per Fogelstrom.
+ * 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.
+ *
+ */
+
+extern vm_map_t phys_map;
+
+/*
+ *  Structure used to control dma.
+ */
+
+typedef struct dma_softc {
+       struct device   sc_dev;         /* use as a device */
+       struct esp_softc *sc_esp;
+       int             dma_ch;
+       vm_offset_t     dma_va;         /* Viritual address for transfer */
+       vm_offset_t     req_va;         /* Original request va */
+       int             req_size;       /* Request size */
+       int             mode;           /* Mode register value and direction */
+       int             sc_active;      /* Active flag */
+       char            **sc_dmaaddr;   /* Pointer to dma address in dev */
+       int             *sc_dmalen;     /* Pointer to len counter in dev */
+} dma_softc_t;
+
+#define        DMA_TO_DEV      0
+#define        DMA_FROM_DEV    1
+
+#define        DMA_CH0         0
+#define        DMA_CH1         1
+
+#define        DMA_RESET(r)    
+#if 0
+#define        DMA_START(a, b, c, d)                                           \
+       {                                                               \
+           int dcmd;                                                   \
+           int xcmd;                                                   \
+           int pa;                                                     \
+           int sz;                                                     \
+           if((vm_offset_t)(b) < VM_MIN_KERNEL_ADDRESS) {              \
+               pa = CACHED_TO_PHYS(b);                                 \
+           }                                                           \
+           else {                                                      \
+               pa = pmap_extract(vm_map_pmap(phys_map), (vm_offset_t)(b));\
+           }                                                           \
+           sz = c;                                                     \
+           if(sz + (pa & (NBPG - 1)) > NBPG) {                         \
+               sz = NBPG - (pa & (NBPG - 1));                          \
+           }                                                           \
+           dcmd = ((d) == DMA_FROM_DEV) ? 0x30 : 0x10;                 \
+           if((a)->dma_ch == DMA_CH0) {                                \
+               out32(R3715_DMA_ADR0, pa);                              \
+               out32(R3715_DMA_CNT0, sz - 1);                          \
+               xcmd = ~0x30;                                           \
+           }                                                           \
+           else {                                                      \
+               out32(R3715_DMA_ADR1, pa);                              \
+               out32(R3715_DMA_CNT1, sz - 1);                          \
+               dcmd = dcmd << 6;                                       \
+               xcmd = ~(0x30 << 6);                                    \
+           }                                                           \
+           dcmd |= (1 << 26);                                          \
+           out32(R3715_IO_TIMING, (in32(R3715_IO_TIMING) & xcmd) | dcmd);\
+       }
+#else
+#define        DMA_START(a, b, c, d)                                           \
+       {                                                               \
+           int dcmd;                                                   \
+           int xcmd;                                                   \
+           int pa;                                                     \
+           int sz;                                                     \
+           pa = CACHED_TO_PHYS(dma_buffer);                            \
+           (a)->req_va = (vm_offset_t)(b);                             \
+           (a)->req_size = c;                                          \
+           (a)->mode = d;                                              \
+           sz = c;                                                     \
+           if((d) == DMA_TO_DEV) {                                     \
+               int *_p = (int *)PHYS_TO_UNCACHED(pa);                  \
+               int *_v = (int *)b;                                     \
+               int _n = sz;                                            \
+               while(_n > 0) {                                         \
+                       *_p = htonl(*_v);                               \
+                       _p++; _v++; _n -= 4;                            \
+               }                                                       \
+           }                                                           \
+           dcmd = ((d) == DMA_FROM_DEV) ? 0x30 : 0x10;                 \
+           if((a)->dma_ch == DMA_CH0) {                                \
+               out32(R3715_DMA_ADR0, pa);                              \
+               out32(R3715_DMA_CNT0, sz - 1);                          \
+               xcmd = ~0x30;                                           \
+           }                                                           \
+           else {                                                      \
+               out32(R3715_DMA_ADR1, pa);                              \
+               out32(R3715_DMA_CNT1, sz - 1);                          \
+               dcmd = dcmd << 6;                                       \
+               xcmd = ~(0x30 << 6);                                    \
+           }                                                           \
+           dcmd |= (1 << 26);                                          \
+           out32(R3715_IO_TIMING, (in32(R3715_IO_TIMING) & xcmd) | dcmd);\
+       }
+#endif
+#define        DMA_MAP(a, b, c, d)
+#define        DMA_INTR(r)
+#define        DMA_DRAIN(r)
+#define        DMA_END(c)                                                      \
+       {                                                               \
+           int dcmd;                                                   \
+           dcmd = ((c)->dma_ch == DMA_CH0) ? 0x10 : 0x10000;           \
+           out32(R3715_IO_TIMING, in32(R3715_IO_TIMING) & ~dcmd);      \
+           if((c)->mode == DMA_FROM_DEV) {                             \
+               int *_v = (int *)(c)->req_va;                           \
+               int *_p = (int *)PHYS_TO_UNCACHED(CACHED_TO_PHYS(dma_buffer)); \
+               int _n = (c)->req_size;                                 \
+               while(_n > 0) {                                         \
+                       *_v = htonl(*_p);                               \
+                       _p++; _v++; _n -= 4;                            \
+               }                                                       \
+           }                                                           \
+       }
diff --git a/sys/arch/wgrisc/dev/if_sn.c b/sys/arch/wgrisc/dev/if_sn.c
new file mode 100644 (file)
index 0000000..e11d8c7
--- /dev/null
@@ -0,0 +1,1288 @@
+/*     $OpenBSD: if_sn.c,v 1.1.1.1 1997/02/06 16:02:42 pefo Exp $      */
+/*
+ * National Semiconductor  SONIC Driver
+ * Copyright (c) 1991   Algorithmics Ltd (http://www.algor.co.uk)
+ * You may use, copy, and modify this program so long as you retain the
+ * copyright line.
+ *
+ * This driver has been substantially modified since Algorithmics donated
+ * it.
+ */
+
+#include "sn.h"
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/mbuf.h>
+#include <sys/buf.h>
+#include <sys/protosw.h>
+#include <sys/socket.h>
+#include <sys/syslog.h>
+#include <sys/ioctl.h>
+#include <sys/errno.h>
+#include <sys/device.h>
+#include <machine/autoconf.h>
+
+#include <net/if.h>
+#include <net/netisr.h>
+#include <net/route.h>
+
+#ifdef INET
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/in_var.h>
+#include <netinet/ip.h>
+#include <netinet/if_ether.h>
+#endif
+
+#include <vm/vm.h>
+
+#include "bpfilter.h"
+#if NBPFILTER > 0
+#include <net/bpf.h>
+#include <net/bpfdesc.h>
+#endif
+
+#define SONICDW 32
+typedef unsigned char uchar;
+
+#include <wgrisc/dev/if_sn.h>
+#define SWR(a, x)      (a) = (x)
+#define SRD(a)         ((a) & 0xffff)
+
+#include <machine/cpu.h>
+#include <wgrisc/riscbus/riscbus.h>
+
+/*
+ * Statistics collected over time
+ */
+struct sn_stats {
+       int     ls_opacks;      /* packets transmitted */
+       int     ls_ipacks;      /* packets received */
+       int     ls_tdr;         /* contents of tdr after collision */
+       int     ls_tdef;        /* packets where had to wait */
+       int     ls_tone;        /* packets with one retry */
+       int     ls_tmore;       /* packets with more than one retry */
+       int     ls_tbuff;       /* transmit buff errors */
+       int     ls_tuflo;       /* "      uflo  "     */
+       int     ls_tlcol;
+       int     ls_tlcar;
+       int     ls_trtry;
+       int     ls_rbuff;       /* receive buff errors */
+       int     ls_rfram;       /* framing     */
+       int     ls_roflo;       /* overflow    */
+       int     ls_rcrc;
+       int     ls_rrng;        /* rx ring sequence error */
+       int     ls_babl;        /* chip babl error */
+       int     ls_cerr;        /* collision error */
+       int     ls_miss;        /* missed packet */
+       int     ls_merr;        /* memory error */
+       int     ls_copies;      /* copies due to out of range mbufs */
+       int     ls_maxmbufs;    /* max mbufs on transmit */
+       int     ls_maxslots;    /* max ring slots on transmit */
+};
+
+struct sn_softc {
+       struct  device sc_dev;
+       struct  arpcom sc_ac;
+#define        sc_if           sc_ac.ac_if     /* network visible interface */
+#define        sc_enaddr       sc_ac.ac_enaddr /* hardware ethernet address */
+
+       struct sonic_reg *sc_csr;       /* hardware pointer */
+       int     sc_rxmark;              /* position in rx ring for reading buffs */
+
+       int     sc_rramark;             /* index into rra of wp */
+
+       int     sc_txhead;              /* index of first TDA passed to chip  */
+       int     sc_missed;              /* missed packet counter */
+       struct  RXpkt *sc_lrxp;         /* last RDA available to chip */
+       struct  sn_stats sc_sum;
+       short   sc_iflags;
+} sn_softc;
+
+int snmatch __P((struct device *, void *, void *));
+void snattach __P((struct device *, struct device *, void *));
+
+struct cfattach sn_ca = {
+       sizeof(struct sn_softc), snmatch, snattach
+};
+struct cfdriver sn_cd = {
+       NULL, "sn", DV_IFNET, NULL, 0
+};
+
+#undef assert
+#undef _assert
+
+#ifdef NDEBUG
+#define        assert(e)       ((void)0)
+#define        _assert(e)      ((void)0)
+#else
+#define        _assert(e)      assert(e)
+#ifdef __STDC__
+#define        assert(e)       ((e) ? (void)0 : __assert("sn ", __FILE__, __LINE__, #e))
+#else  /* PCC */
+#define        assert(e)       ((e) ? (void)0 : __assert("sn "__FILE__, __LINE__, "e"))
+#endif
+#endif
+
+void 
+m_check(m)
+       struct mbuf *m;
+{
+       if (m->m_flags & M_EXT) {
+               assert(m->m_len >= 0);
+               assert(m->m_len <= m->m_ext.ext_size);
+               assert(m->m_data >= &m->m_ext.ext_buf[0]);
+               assert(m->m_data <= &m->m_ext.ext_buf[m->m_ext.ext_size]);
+               assert(m->m_data + m->m_len <= &m->m_ext.ext_buf[m->m_ext.ext_size]);
+       } else if (m->m_flags & M_PKTHDR) {
+               assert(m->m_len >= 0);
+               assert(m->m_len <= MHLEN);
+               assert(m->m_data >= m->m_pktdat);
+               assert(m->m_data <= &m->m_pktdat[MHLEN]);
+               assert(m->m_data + m->m_len <= &m->m_pktdat[MHLEN]);
+       } else {
+               assert(m->m_len >= 0);
+               assert(m->m_len <= MLEN);
+               assert(m->m_data >= m->m_dat);
+               assert(m->m_data <= &m->m_dat[MLEN]);
+               assert(m->m_data + m->m_len <= &m->m_dat[MLEN]);
+       }
+}
+
+void 
+m_checkm(m)
+       struct mbuf *m;
+{
+       while (m) {
+               m_check(m);
+               m = m->m_next;
+       }
+}
+
+int ethdebug = 0;
+
+int snintr __P((struct sn_softc *));
+int snioctl __P((struct ifnet *ifp, u_long cmd, caddr_t data));
+void snstart __P((struct ifnet *ifp));
+void snwatchdog __P((struct ifnet *ifp));
+void snreset __P((struct sn_softc *sc));
+
+/*
+ * SONIC buffers need to be aligned 16 or 32 bit aligned.
+ * These macros calculate and verify alignment.
+ */
+#if SONICDW == 32
+#define SONICALIGN 4
+#else
+#define SONICALIGN 2
+#endif
+#define SOALIGN(array) (((int)array+SONICALIGN-1) & ~(SONICALIGN-1))
+#define SOALIGNED(p) (!(((uint)p)&(SONICALIGN-1)))
+
+#define UPPER(x) ((unsigned)(x) >> 16)
+#define LOWER(x) ((unsigned)(x) & 0xffff)
+
+#define NRRA   32              /* # receive resource descriptors */
+#define RRAMASK        0x1f            /* why it must be poer of two */
+
+#define NRBA   16              /* # receive buffers < NRRA */
+#define NRDA   NRBA            /* # receive descriptors */
+#define NTDA   4               /* # transmit descriptors */
+
+#define CDASIZE sizeof(struct CDA)
+#define RRASIZE (NRRA*sizeof(struct RXrsrc))
+#define RDASIZE (NRDA*sizeof(struct RXpkt))
+#define TDASIZE (NTDA*sizeof(struct TXpkt))
+
+#define FCSSIZE        4               /* size of FCS append te received packets */
+
+/*
+ * maximum recieve packet size plus 2 byte pad to make each
+ * one aligned. 4 byte slop (required for eobc)
+ */
+#define RBASIZE        (sizeof(struct ether_header) + ETHERMTU + FCSSIZE + 2 + 4)
+
+/*
+ * space requiered for descriptors
+ */
+#define DESC_SIZE (RRASIZE + CDASIZE + RDASIZE + TDASIZE + SONICALIGN - 1)
+
+/*
+ *  Nicely aligned pointers into the sonicbuffers
+ *  p_ points at physical (K1_SEG) addresses.
+ *  v_ is sonic local address used by sonic.
+ */
+struct RXrsrc  *p_rra; /* receiver resource descriptors */
+struct RXrsrc  *v_rra;
+struct RXpkt   *p_rda; /* receiver desriptors */
+struct RXpkt   *v_rda;
+struct TXpkt   *p_tda; /* transmitter descriptors */
+struct TXpkt   *v_tda;
+struct CDA     *p_cda; /* CAM descriptors */
+struct CDA     *v_cda;
+char           *p_rba; /* receive buffer area base */
+char           *v_rba;
+
+/* Meta transmit descriptors */
+struct mtd {
+       struct  mtd *mtd_link;
+       struct  TXpkt *mtd_txp;
+       struct  mbuf *mtd_mbuf;
+} mtda[NTDA];
+
+struct mtd *mtdfree;           /* list of free meta transmit descriptors */
+struct mtd *mtdhead;           /* head of descriptors assigned to chip */
+struct mtd *mtdtail;           /* tail of descriptors assigned to chip */
+struct mtd *mtdnext;           /* next descriptor to give to chip */
+
+void mtd_free __P((struct mtd *));
+struct mtd *mtd_alloc __P((void));
+
+int sngetaddr __P((struct sn_softc *sc));
+int sninit __P((struct sn_softc *sc));
+int snstop __P((struct sn_softc *sc));
+int sonicput __P((struct sn_softc *sc, struct mbuf *m0));
+
+void camdump __P((struct sn_softc *sc));
+
+int
+snmatch(parent, match, aux)
+       struct device *parent;
+       void *match, *aux;
+{
+       struct cfdata *cf = match;
+       struct confargs *ca = aux;
+
+       /* XXX CHECK BUS */
+       /* make sure that we're looking for this type of device. */
+       if (!BUS_MATCHNAME(ca, "sonic"))
+               return (0);
+
+       return (1);
+}
+
+/*
+ * Interface exists: make available by filling in network interface
+ * record.  System will initialize the interface when it is ready
+ * to accept packets.
+ */
+void
+snattach(parent, self, aux)
+       struct device *parent, *self;
+       void   *aux;
+{
+       struct sn_softc *sc = (void *)self;
+       struct confargs *ca = aux;
+       struct ifnet *ifp = &sc->sc_if;
+       struct cfdata *cf = sc->sc_dev.dv_cfdata;
+       int p, pp;
+
+       sc->sc_csr = (struct sonic_reg *)BUS_CVTADDR(ca);
+
+/*
+ * because the sonic is basicly 16bit device it 'concatenates'
+ * a higher buffer address to a 16 bit offset this will cause wrap
+ * around problems near the end of 64k !!
+ */
+       p = RISC_SONIC_SRAM;
+       pp = RISC_SONIC_SRAM - (FRAGMAX * NTDA * 4096);
+
+       if ((p ^ (p + TDASIZE)) & 0x10000)
+               p = (p + 0x10000) & ~0xffff;
+       p_tda = (struct TXpkt *) p;
+       v_tda = (struct TXpkt *)(p - pp);
+       p += TDASIZE;
+
+       if ((p ^ (p + RRASIZE + CDASIZE)) & 0x10000)
+               p = (p + 0x10000) & ~0xffff;
+       p_rra = (struct RXrsrc *) p;
+       v_rra = (struct RXrsrc *)(p - pp);
+       p += RRASIZE;
+
+       if ((p ^ (p + RDASIZE)) & 0x10000)
+               p = (p + 0x10000) & ~0xffff;
+       p_rda = (struct RXpkt *) p;
+       v_rda = (struct RXpkt *)(p - pp);
+       p += RDASIZE;
+
+       p_cda = (struct CDA *) p;
+       v_cda = (struct CDA *)(p - pp);
+       p += CDASIZE;
+
+       p += 4096 - (p & (4095));
+       p_rba = (char *)p;
+       v_rba = (char *)(p - pp);
+       p += NRBA * RBASIZE;
+
+       printf(": bufsize %d",p - RISC_SONIC_SRAM);
+
+#if 0
+       camdump(sc);
+#endif
+       sngetaddr(sc);
+       printf(" address %s\n", ether_sprintf(sc->sc_enaddr));
+
+#if 0
+printf("\nsonic buffers: rra=0x%x cda=0x%x rda=0x%x tda=0x%x rba=0x%x\n",
+       p_rra, p_cda, p_rda, p_tda, p_rba);
+printf("sonic buffers: rra=0x%x cda=0x%x rda=0x%x tda=0x%x rba=0x%x\n",
+       v_rra, v_cda, v_rda, v_tda, v_rba);
+printf("mapped to offset 0x%x size 0x%x\n", SONICBUF - pp, p - SONICBUF);
+#endif
+
+       BUS_INTR_ESTABLISH(ca, (intr_handler_t)snintr, (void *)sc);
+
+       bcopy(sc->sc_dev.dv_xname, ifp->if_xname, IFNAMSIZ);
+       ifp->if_softc = sc;
+       ifp->if_ioctl = snioctl;
+       ifp->if_start = snstart;
+       ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
+       ifp->if_watchdog = snwatchdog;
+#if NBPFILTER > 0
+       bpfattach(&ifp->if_bpf, ifp, DLT_EN10MB, sizeof(struct ether_header));
+#endif
+       if_attach(ifp);
+       ether_ifattach(ifp);
+}
+
+int
+snioctl(ifp, cmd, data)
+       struct ifnet *ifp;
+       u_long cmd;
+       caddr_t data;
+{
+       struct ifaddr *ifa;
+       struct sn_softc *sc = ifp->if_softc;
+       int     s = splnet(), err = 0;
+       int     temp;
+       int     error;
+
+       if ((error = ether_ioctl(ifp, &sc->sc_ac, cmd, data)) > 0) {
+               splx(s);
+               return error;
+       }
+
+       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)sninit(ifp->if_softc);
+                       arp_ifinit(&sc->sc_ac, ifa);
+                       break;
+#endif
+               default:
+                       (void)sninit(ifp->if_softc);
+                       break;
+               }
+               break;
+
+       case SIOCSIFFLAGS:
+               if ((ifp->if_flags & IFF_UP) == 0 &&
+                   ifp->if_flags & IFF_RUNNING) {
+                       snstop(ifp->if_softc);
+                       ifp->if_flags &= ~IFF_RUNNING;
+               } else if (ifp->if_flags & IFF_UP &&
+                   (ifp->if_flags & IFF_RUNNING) == 0)
+                       (void)sninit(ifp->if_softc);
+               /*
+                * 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;
+                       printf("change in flags\n");
+                       temp = sc->sc_if.if_flags & IFF_UP;
+                       snreset(sc);
+                       sc->sc_if.if_flags |= temp;
+                       snstart(ifp);
+               }
+               break;
+
+       case SIOCADDMULTI:
+       case SIOCDELMULTI:
+               if(cmd == SIOCADDMULTI)
+                       err = ether_addmulti((struct ifreq *)data, &sc->sc_ac);
+               else
+                       err = ether_delmulti((struct ifreq *)data, &sc->sc_ac);
+
+               if (err == ENETRESET) {
+                       /*
+                        * Multicast list has changed; set the hardware
+                        * filter accordingly. But remember UP flag!
+                        */
+                       temp = sc->sc_if.if_flags & IFF_UP;
+                       snreset(sc);
+                       sc->sc_if.if_flags |= temp;
+                       err = 0;
+               }
+               break;
+       default:
+               err = EINVAL;
+       }
+       splx(s);
+       return (err);
+}
+
+/*
+ * Encapsulate a packet of type family for the local net.
+ * Use trailer local net encapsulation if enough data in first
+ * packet leaves a multiple of 512 bytes of data in remainder.
+ */
+void
+snstart(ifp)
+       struct ifnet *ifp;
+{
+       struct sn_softc *sc = ifp->if_softc;
+       struct mbuf *m;
+       int     len;
+
+       if ((sc->sc_if.if_flags & IFF_RUNNING) == 0)
+               return;
+       IF_DEQUEUE(&sc->sc_if.if_snd, m);
+       if (m == 0)
+               return;
+
+       /*
+        * If there is nothing in the o/p queue, and there is room in
+        * the Tx ring, then send the packet directly.  Otherwise append
+        * it to the o/p queue.
+        */
+       if (!sonicput(sc, m)) { /* not enough space */
+               IF_PREPEND(&sc->sc_if.if_snd, 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_mtap(sc->sc_if.if_bpf, m);
+#endif
+
+       sc->sc_if.if_opackets++;        /* # of pkts */
+       sc->sc_sum.ls_opacks++;         /* # of pkts */
+}
+
+/*
+ * This is called from sonicioctl() when /etc/ifconfig is run to set
+ * the address or switch the i/f on.
+ */
+void caminitialise __P((void));
+void camentry __P((int, u_char *ea));
+void camprogram __P((struct sn_softc *));
+void initialise_tda __P((struct sn_softc *));
+void initialise_rda __P((struct sn_softc *));
+void initialise_rra __P((struct sn_softc *));
+
+/*
+ * reset and restart the SONIC.  Called in case of fatal
+ * hardware/software errors.
+ */
+void
+snreset(sc)
+       struct sn_softc *sc;
+{
+       snstop(sc);
+       sninit(sc);
+}
+
+int 
+sninit(sc)
+       struct sn_softc *sc;
+{
+       struct sonic_reg *csr = sc->sc_csr;
+       int s, error;
+
+       if (sc->sc_if.if_flags & IFF_RUNNING)
+               /* already running */
+               return (0);
+
+       s = splnet();
+
+       csr->s_cr = CR_RST;     /* s_dcr only accessable reset mode! */
+
+       /* config it */
+       csr->s_dcr = DCR_LBR | DCR_SYNC | DCR_WAIT0 | DCR_DW32 | DCR_DMABLOCK |
+           DCR_RFT16 | DCR_TFT16;
+       csr->s_rcr = RCR_BRD | RCR_LBNONE;
+       csr->s_imr = IMR_PRXEN | IMR_PTXEN | IMR_TXEREN | IMR_HBLEN | IMR_LCDEN;
+
+       /* clear pending interrupts */
+       csr->s_isr = 0x7fff;
+
+       /* clear tally counters */
+       csr->s_crct = -1;
+       csr->s_faet = -1;
+       csr->s_mpt = -1;
+
+       initialise_tda(sc);
+       initialise_rda(sc);
+       initialise_rra(sc);
+
+       /* enable the chip */
+       csr->s_cr = 0;
+       wbflush();
+
+       /* program the CAM with our address */
+       caminitialise();
+       camentry(0, sc->sc_enaddr);
+       camprogram(sc);
+
+       /* get it to read resource descriptors */
+       csr->s_cr = CR_RRRA;
+       wbflush();
+       while (csr->s_cr & CR_RRRA)
+               continue;
+
+       /* enable rx */
+       csr->s_cr = CR_RXEN;
+       wbflush();
+
+       /* flag interface as "running" */
+       sc->sc_if.if_flags |= IFF_RUNNING;
+
+       splx(s);
+       return (0);
+
+bad:
+       snstop(sc);
+       return (error);
+}
+
+/*
+ * close down an interface and free its buffers
+ * Called on final close of device, or if sninit() fails
+ * part way through.
+ */
+int 
+snstop(sc)
+       struct sn_softc *sc;
+{
+       struct mtd *mtd;
+       int s = splnet();
+
+       /* stick chip in reset */
+       sc->sc_csr->s_cr = CR_RST;
+       wbflush();
+
+       /* free all receive buffers (currently static so nothing to do) */
+
+       /* free all pending transmit mbufs */
+       while (mtd = mtdhead) {
+               mtdhead = mtdhead->mtd_link;
+               if (mtd->mtd_mbuf)
+                       m_freem(mtd->mtd_mbuf);
+               mtd->mtd_mbuf = 0;
+               mtd_free(mtd);
+       }
+       mtdnext = mtd_alloc();
+
+       sc->sc_if.if_timer = 0;
+       sc->sc_if.if_flags &= ~(IFF_RUNNING | IFF_UP);
+
+       splx(s);
+       return (0);
+}
+
+/*
+ * Called if any Tx packets remain unsent after 5 seconds,
+ * In all cases we just reset the chip, and any retransmission
+ * will be handled by higher level protocol timeouts.
+ */
+void
+snwatchdog(ifp)
+       struct ifnet *ifp;
+{
+       struct sn_softc *sc = ifp->if_softc;
+       int temp;
+
+       if (mtdhead && mtdhead->mtd_mbuf) {
+               /* something still pending for transmit */
+               if (mtdhead->mtd_txp->status == 0)
+                       log(LOG_ERR, "%s: Tx - timeout\n",
+                           sc->sc_if.if_xname);
+               else
+                       log(LOG_ERR, "%s: Tx - lost interrupt\n",
+                           sc->sc_if.if_xname);
+               temp = sc->sc_if.if_flags & IFF_UP;
+               snreset(sc);
+               sc->sc_if.if_flags |= temp;
+       }
+}
+/*
+ * stuff packet into sonic (at splnet)
+*/
+int 
+sonicput(sc, m0)
+       struct sn_softc *sc;
+       struct mbuf *m0;
+{
+       struct sonic_reg *csr = sc->sc_csr;
+       struct TXpkt *txp;
+       struct mtd *mtdnew;
+       struct mbuf *m;
+       int len = 0, fr = 0;
+       int i;
+       int fragoffset;         /* Offset in viritual dma space for fragment */
+
+       /* grab the replacement mtd */
+       if ((mtdnew = mtd_alloc()) == 0)
+               return (0);
+
+       /* this packet goes to mdtnext fill in the TDA */
+       mtdnext->mtd_mbuf = m0;
+       txp = mtdnext->mtd_txp;
+       SWR(txp->config, 0);
+       fragoffset = (txp - p_tda) * FRAGMAX * 4096;
+
+       /*
+        * Now fill in the fragments. Each fragment maps to it's
+        * own dma page. Fragments crossing a dma page boundary
+        * are split up in two fragments. This is somewhat stupid
+        * because the dma mapper can do the work, but it helps
+        * keeping the fragments in order. (read lazy programmer).
+        */
+       for (m = m0; m; m = m->m_next) {
+               unsigned va = (unsigned) mtod(m, caddr_t);
+               int resid = m->m_len;
+
+#if has_to_be_fixed
+               if(resid != 0) {
+                       R4K_HitFlushDCache(va, resid);
+               }
+#endif
+               len += resid;
+
+               while (resid) {
+                       unsigned pa;
+                       unsigned n;
+
+                       pa = (va & PGOFSET) + fragoffset;
+                       n = resid;
+                       if (n > NBPG - (va & PGOFSET)) {
+                               n = NBPG - (va & PGOFSET);
+                       }
+                       if (fr < FRAGMAX) {
+                               SWR(txp->u[fr].frag_ptrlo, LOWER(pa));
+                               SWR(txp->u[fr].frag_ptrhi, UPPER(pa));
+                               SWR(txp->u[fr].frag_size, n);
+                       }
+                       fr++;
+                       va += n;
+                       resid -= n;
+                       fragoffset += 4096;
+               }
+       }
+       /*
+        * pad out last fragment for minimum size
+        */
+        if (len < ETHERMIN + sizeof(struct ether_header) && fr < FRAGMAX) {
+                int pad = ETHERMIN + sizeof(struct ether_header) - len;
+                static char zeros[64];
+                unsigned pa;
+
+                pa = ((unsigned)zeros & PGOFSET) + fragoffset;
+                SWR(txp->u[fr].frag_ptrlo, LOWER(pa));
+                SWR(txp->u[fr].frag_ptrhi, UPPER(pa));
+                SWR(txp->u[fr].frag_size, pad);
+                fr++;
+                len = ETHERMIN + sizeof(struct ether_header);
+        }
+
+       if (fr > FRAGMAX) {
+               mtd_free(mtdnew);
+               m_freem(m0);
+               log(LOG_ERR, "%s: tx too many fragments %d\n",
+                   sc->sc_if.if_xname, fr);
+               sc->sc_if.if_oerrors++;
+               return (len);
+       }
+
+       SWR(txp->frag_count, fr);
+       SWR(txp->pkt_size, len);
+
+       /* link onto the next mtd that will be used */
+       SWR(txp->u[fr].tlink, LOWER(v_tda + (mtdnew->mtd_txp - p_tda)) | EOL);
+
+       if (mtdhead == 0) {
+               /* no current transmit list start with this one */
+               mtdtail = mtdhead = mtdnext;
+               csr->s_ctda = LOWER(v_tda + (txp - p_tda));
+       } else {
+               /*
+                * have a transmit list append it to end note
+                * mtdnext is already physicaly linked to mtdtail in
+                * mtdtail->mtd_txp->u[mtdtail->mtd_txp->frag_count].tlink
+                */
+               SWR(mtdtail->mtd_txp->u[mtdtail->mtd_txp->frag_count].tlink,
+                   SRD(mtdtail->mtd_txp->u[mtdtail->mtd_txp->frag_count].tlink) & ~EOL);
+               mtdtail = mtdnext;
+       }
+       mtdnext->mtd_link = mtdnew;
+       mtdnext = mtdnew;
+
+       /* make sure chip is running */
+       wbflush();
+       csr->s_cr = CR_TXP;
+       wbflush();
+       sc->sc_if.if_timer = 5; /* 5 seconds to watch for failing to transmit */
+       return (len);
+}
+
+/*
+ *  Read out the ethernet address from the cam. It is stored
+ *  there by the boot when doing a loopback test. Thus we don't
+ *  have to fetch it from nv ram.
+ */
+int 
+sngetaddr(sc)
+       struct sn_softc *sc;
+{
+       unsigned i, x, y;
+       char   *cp, *ea;
+
+#if 0
+       sc->sc_csr->s_cr = CR_RST;
+       wbflush();
+       sc->sc_csr->s_cep = 0;
+       i = sc->sc_csr->s_cap2;
+       wbflush();
+       sc->sc_enaddr[5] = i >> 8;
+       sc->sc_enaddr[4] = i;
+       i = sc->sc_csr->s_cap1;
+       wbflush();
+       sc->sc_enaddr[3] = i >> 8;
+       sc->sc_enaddr[2] = i;
+       i = sc->sc_csr->s_cap0;
+       wbflush();
+       sc->sc_enaddr[1] = i >> 8;
+       sc->sc_enaddr[0] = i;
+
+       sc->sc_csr->s_cr = 0;
+       wbflush();
+#else
+       sc->sc_enaddr[0] = 0x08;
+       sc->sc_enaddr[1] = 0x00;
+       sc->sc_enaddr[2] = 0x20;
+       sc->sc_enaddr[3] = 0xa0;
+       sc->sc_enaddr[4] = 0x66;
+       sc->sc_enaddr[5] = 0x54;
+#endif 
+       return (0);
+}
+
+void sonictxint __P((struct sn_softc *));
+void sonicrxint __P((struct sn_softc *));
+
+int sonic_read __P((struct sn_softc *, struct RXpkt *));
+struct mbuf *sonic_get __P((struct sn_softc *, struct ether_header *, int));
+
+void 
+mtd_free(mtd)
+       struct mtd *mtd;
+{
+       mtd->mtd_link = mtdfree;
+       mtdfree = mtd;
+}
+
+struct mtd *
+mtd_alloc()
+{
+       struct mtd *mtd = mtdfree;
+
+       if (mtd) {
+               mtdfree = mtd->mtd_link;
+               mtd->mtd_link = 0;
+       }
+       return (mtd);
+}
+
+/*
+ * CAM support
+ */
+void 
+caminitialise()
+{
+       int     i;
+
+       for (i = 0; i < MAXCAM; i++)
+               SWR(p_cda->desc[i].cam_ep, i);
+       SWR(p_cda->enable, 0);
+}
+
+void 
+camentry(entry, ea)
+       int entry;
+       u_char *ea;
+{
+       SWR(p_cda->desc[entry].cam_ep, entry);
+       SWR(p_cda->desc[entry].cam_ap2, (ea[5] << 8) | ea[4]);
+       SWR(p_cda->desc[entry].cam_ap1, (ea[3] << 8) | ea[2]);
+       SWR(p_cda->desc[entry].cam_ap0, (ea[1] << 8) | ea[0]);
+       SWR(p_cda->enable, SRD(p_cda->enable) | (1 << entry));
+}
+
+void 
+camprogram(sc)
+       struct sn_softc *sc;
+{
+       struct sonic_reg *csr;
+       int     timeout;
+       int     i;
+
+       csr = sc->sc_csr;
+       csr->s_cdp = LOWER(v_cda);
+       csr->s_cdc = MAXCAM;
+       csr->s_cr = CR_LCAM;
+       wbflush();
+
+       timeout = 10000;
+       while (csr->s_cr & CR_LCAM && timeout--)
+               continue;
+       if (timeout == 0) {
+               /* XXX */
+               panic("sonic: CAM initialisation failed\n");
+       }
+       timeout = 10000;
+       while ((csr->s_isr & ISR_LCD) == 0 && timeout--)
+               continue;
+
+       if (csr->s_isr & ISR_LCD)
+               csr->s_isr = ISR_LCD;
+       else
+               printf("sonic: CAM initialisation without interrupt\n");
+}
+
+#if 0
+void 
+camdump(sc)
+       struct sn_softc *sc;
+{
+       struct sonic_reg *csr = sc->sc_csr;
+       int i;
+
+       printf("CAM entries:\n");
+       csr->s_cr = CR_RST;
+       wbflush();
+
+       for (i = 0; i < 16; i++) {
+               ushort  ap2, ap1, ap0;
+               csr->s_cep = i;
+               wbflush();
+               ap2 = csr->s_cap2;
+               ap1 = csr->s_cap1;
+               ap0 = csr->s_cap0;
+               printf("%d: ap2=0x%x ap1=0x%x ap0=0x%x\n", i, ap2, ap1, ap0);
+       }
+       printf("CAM enable 0x%x\n", csr->s_cep);
+
+       csr->s_cr = 0;
+       wbflush();
+}
+#endif
+
+void 
+initialise_tda(sc)
+       struct sn_softc *sc;
+{
+       struct sonic_reg *csr;
+       struct mtd *mtd;
+       int     i;
+
+       csr = sc->sc_csr;
+
+       mtdfree = mtdhead = mtdtail = (struct mtd *) 0;
+
+       for (i = 0; i < NTDA; i++) {
+               mtd = &mtda[i];
+               mtd->mtd_txp = &p_tda[i];
+               mtd->mtd_mbuf = (struct mbuf *) 0;
+               mtd_free(mtd);
+       }
+       mtdnext = mtd_alloc();
+
+       csr->s_utda = UPPER(v_tda);
+}
+
+void 
+initialise_rda(sc)
+       struct sn_softc *sc;
+{
+       struct sonic_reg *csr;
+       int     i;
+
+       csr = sc->sc_csr;
+
+       /* link the RDA's together into a circular list */
+       for (i = 0; i < (NRDA - 1); i++) {
+               SWR(p_rda[i].rlink, LOWER(&v_rda[i + 1]));
+               SWR(p_rda[i].in_use, 1);
+       }
+       SWR(p_rda[NRDA - 1].rlink, LOWER(&v_rda[0]) | EOL);
+       SWR(p_rda[NRDA - 1].in_use, 1);
+
+       /* mark end of receive descriptor list */
+       sc->sc_lrxp = &p_rda[NRDA - 1];
+
+       sc->sc_rxmark = 0;
+
+       csr->s_urda = UPPER(&v_rda[0]);
+       csr->s_crda = LOWER(&v_rda[0]);
+       wbflush();
+}
+
+void 
+initialise_rra(sc)
+       struct sn_softc *sc;
+{
+       struct sonic_reg *csr;
+       int     i;
+
+       csr = sc->sc_csr;
+
+       csr->s_eobc = RBASIZE / 2 - 2;  /* must be >= MAXETHERPKT */
+       csr->s_urra = UPPER(v_rra);
+       csr->s_rsa = LOWER(v_rra);
+       csr->s_rea = LOWER(&v_rra[NRRA]);
+       csr->s_rrp = LOWER(v_rra);
+       csr->s_rsc = 0;
+
+       /* fill up SOME of the rra with buffers */
+       for (i = 0; i < NRBA; i++) {
+               SWR(p_rra[i].buff_ptrhi, UPPER(&v_rba[i * RBASIZE]));
+               SWR(p_rra[i].buff_ptrlo, LOWER(&v_rba[i * RBASIZE]));
+               SWR(p_rra[i].buff_wchi, UPPER(RBASIZE / 2));
+               SWR(p_rra[i].buff_wclo, LOWER(RBASIZE / 2));
+       }
+       sc->sc_rramark = NRBA;
+       csr->s_rwp = LOWER(&v_rra[sc->sc_rramark]);
+       wbflush();
+}
+
+int 
+snintr(sc)
+       struct sn_softc *sc;
+{
+       struct sonic_reg *csr = sc->sc_csr;
+       int     isr;
+
+       while (isr = (csr->s_isr & ISR_ALL)) {
+               /* scrub the interrupts that we are going to service */
+               csr->s_isr = isr;
+               wbflush();
+
+               if (isr & (ISR_BR | ISR_LCD | ISR_PINT | ISR_TC))
+                       printf("sonic: unexpected interrupt status 0x%x\n", isr);
+
+               if (isr & (ISR_TXDN | ISR_TXER))
+                       sonictxint(sc);
+
+               if (isr & ISR_PKTRX)
+                       sonicrxint(sc);
+
+               if (isr & (ISR_HBL | ISR_RDE | ISR_RBE | ISR_RBAE | ISR_RFO)) {
+                       if (isr & ISR_HBL)
+                               printf("sonic: no heartbeat\n");
+                       if (isr & ISR_RDE)
+                               printf("sonic: receive descriptors exhausted\n");
+                       if (isr & ISR_RBE)
+                               printf("sonic: receive buffers exhausted\n");
+                       if (isr & ISR_RBAE)
+                               printf("sonic: receive buffer area exhausted\n");
+                       if (isr & ISR_RFO)
+                               printf("sonic: receive FIFO overrun\n");
+               }
+               if (isr & (ISR_CRC | ISR_FAE | ISR_MP)) {
+#ifdef notdef
+                       if (isr & ISR_CRC)
+                               sc->sc_crctally++;
+                       if (isr & ISR_FAE)
+                               sc->sc_faetally++;
+                       if (isr & ISR_MP)
+                               sc->sc_mptally++;
+#endif
+               }
+       }
+       return (1);
+}
+
+/*
+ * Transmit interrupt routine
+ */
+void 
+sonictxint(sc)
+       struct sn_softc *sc;
+{
+       struct TXpkt *txp;
+       struct sonic_reg *csr;
+       struct mtd *mtd;
+
+       if (mtdhead == (struct mtd *) 0)
+               return;
+
+       csr = sc->sc_csr;
+
+       while (mtd = mtdhead) {
+               struct mbuf *m = mtd->mtd_mbuf;
+
+               if (m == 0)
+                       break;
+
+               txp = mtd->mtd_txp;
+
+               if (SRD(txp->status) == 0)      /* it hasn't really gone yet */
+                       return;
+
+               if (ethdebug) {
+                       struct ether_header *eh = mtod(m, struct ether_header *);
+                       printf("xmit status=0x%x len=%d type=0x%x from %s",
+                           txp->status,
+                           txp->pkt_size,
+                           htons(eh->ether_type),
+                           ether_sprintf(eh->ether_shost));
+                       printf(" (to %s)\n", ether_sprintf(eh->ether_dhost));
+               }
+               m_freem(m);
+               mtd->mtd_mbuf = 0;
+               mtdhead = mtd->mtd_link;
+
+               mtd_free(mtd);
+
+               if ((SRD(txp->status) & TCR_PTX) == 0) {
+                       printf("sonic: Tx packet status=0x%x\n", txp->status);
+
+                       if (mtdhead != mtdnext) {
+                               printf("resubmitting remaining packets\n");
+                               csr->s_ctda = LOWER(v_tda + (mtdhead->mtd_txp - p_tda));
+                               csr->s_cr = CR_TXP;
+                               wbflush();
+                               return;
+                       }
+               }
+       }
+       /* mtdhead should be at mtdnext (go) */
+       assert(mtdhead == mtdnext);
+       assert(mtdhead->mtd_link == 0);
+       mtdhead = 0;
+
+       /* and start feeding any queued packets to chip */
+       while (1) {
+               struct mbuf *m;
+
+               IF_DEQUEUE(&sc->sc_if.if_snd, m);
+               if (m == 0)     /* nothing left to send */
+                       break;
+               if (!sonicput(sc, m)) { /* not enough space */
+                       IF_PREPEND(&sc->sc_if.if_snd, m);
+                       break;
+               }
+       }
+}
+
+/*
+ * Receive interrupt routine
+ */
+void 
+sonicrxint(sc)
+       struct sn_softc *sc;
+{
+       struct sonic_reg *csr = sc->sc_csr;
+       struct RXpkt *rxp;
+       u_long  addr;
+       int     orra;
+
+       rxp = &p_rda[sc->sc_rxmark];
+
+       while (SRD(rxp->in_use) == 0) {
+               unsigned status = SRD(rxp->status);
+               if ((status & RCR_LPKT) == 0)
+                       printf("sonic: more than one packet in RBA!\n");
+               assert(PSNSEQ(SRD(rxp->seq_no)) == 0);
+
+               if (status & RCR_PRX) {
+                       if (sonic_read(sc, rxp)) {
+                               sc->sc_if.if_ipackets++;
+                               sc->sc_sum.ls_ipacks++;
+                               sc->sc_missed = 0;
+                       }
+               } else
+                       sc->sc_if.if_ierrors++;
+
+               /*
+                * give receive buffer area back to chip XXX what buffer
+                * did the sonic use for this descriptor answer look at
+                * the rba sequence number !! 
+                */
+               orra = RBASEQ(SRD(rxp->seq_no)) & RRAMASK;
+
+               assert(SRD(rxp->pkt_ptrhi) == SRD(p_rra[orra].buff_ptrhi));
+               assert(SRD(rxp->pkt_ptrlo) == SRD(p_rra[orra].buff_ptrlo));
+if(SRD(rxp->pkt_ptrlo) != SRD(p_rra[orra].buff_ptrlo))
+printf("%x,%x\n",SRD(rxp->pkt_ptrlo),SRD(p_rra[orra].buff_ptrlo));
+               assert(SRD(p_rra[orra].buff_wclo));
+
+               /*
+                * orra is now empty of packets and can be freed if
+                * sonic read didnt copy it out then we would have to
+                * wait !!
+                * (dont bother add it back in again straight away)
+                */
+               p_rra[sc->sc_rramark] = p_rra[orra];
+
+               /* zap old rra for fun */
+               p_rra[orra].buff_wchi = 0;
+               p_rra[orra].buff_wclo = 0;
+
+               sc->sc_rramark = (sc->sc_rramark + 1) & RRAMASK;
+               csr->s_rwp = LOWER(&v_rra[sc->sc_rramark]);
+               wbflush();
+
+               /*
+                * give recieve descriptor back to chip simple
+                * list is circular
+                */
+               SWR(rxp->in_use, 1);
+               SWR(rxp->rlink, SRD(rxp->rlink) | EOL);
+               SWR(sc->sc_lrxp->rlink, SRD(sc->sc_lrxp->rlink) & ~EOL);
+               sc->sc_lrxp = rxp;
+
+               if (++sc->sc_rxmark >= NRDA)
+                       sc->sc_rxmark = 0;
+               rxp = &p_rda[sc->sc_rxmark];
+       }
+}
+
+/*
+ * sonic_read -- pull packet off interface and forward to
+ * appropriate protocol handler
+ */
+int 
+sonic_read(sc, rxp)
+       struct sn_softc *sc;
+       struct RXpkt *rxp;
+{
+       struct ifnet *ifp = &sc->sc_if;
+       /*extern char *ether_sprintf();*/
+       struct ether_header *et;
+       struct mbuf *m;
+       int     len, off, i;
+       caddr_t pkt;
+
+       /*
+         * Get input data length.
+         * Get pointer to ethernet header (in input buffer).
+         * Deal with trailer protocol: if type is PUP trailer
+         * get true type from first 16-bit word past data.
+         * Remember that type was trailer by setting off.
+         */
+
+       len = SRD(rxp->byte_count) - sizeof(struct ether_header) - FCSSIZE;
+       pkt = (caddr_t)((SRD(rxp->pkt_ptrhi) << 16) | SRD(rxp->pkt_ptrlo));
+       pkt = pkt - v_rba + p_rba;
+       et = (struct ether_header *)pkt;
+
+       if (ethdebug) {
+               printf("rcvd 0x%x status=0x%x, len=%d type=0x%x from %s",
+                   et, rxp->status, len, htons(et->ether_type),
+                   ether_sprintf(et->ether_shost));
+               printf(" (to %s)\n", ether_sprintf(et->ether_dhost));
+       }
+       if (len < ETHERMIN || len > ETHERMTU) {
+               printf("sonic: invalid packet length %d bytes\n", len);
+               return (0);
+       }
+
+#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 ((ifp->if_flags & IFF_PROMISC) != 0 &&
+                   (et->ether_dhost[0] & 1) == 0 && /* !mcast and !bcast */
+                   bcmp(et->ether_dhost, sc->sc_enaddr,
+                           sizeof(et->ether_dhost)) != 0)
+                       return;
+       }
+#endif
+       m = sonic_get(sc, et, len);
+       if (m == NULL)
+               return (0);
+       ether_input(ifp, et, m);
+       return(1);
+}
+
+#define sonicdataaddr(eh, off, type)       ((type)(((caddr_t)((eh)+1)+(off))))
+
+/*
+ * munge the recieved packet into an mbuf chain
+ * because we are using stupif buffer management this
+ * is slow.
+*/
+struct mbuf *
+sonic_get(sc, eh, datalen)
+       struct sn_softc *sc;
+       struct ether_header *eh;
+       int datalen;
+{
+       struct mbuf *m;
+       struct mbuf *top = 0, **mp = &top;
+       int     len;
+       char   *spkt = sonicdataaddr(eh, 0, caddr_t);
+       char   *epkt = spkt + datalen;
+       char *cp = spkt;
+
+       epkt = cp + datalen;
+       MGETHDR(m, M_DONTWAIT, MT_DATA);
+       if (m == 0)
+               return (0);
+       m->m_pkthdr.rcvif = &sc->sc_if;
+       m->m_pkthdr.len = datalen;
+       m->m_len = MHLEN;
+
+       while (datalen > 0) {
+               if (top) {
+                       MGET(m, M_DONTWAIT, MT_DATA);
+                       if (m == 0) {
+                               m_freem(top);
+                               return (0);
+                       }
+                       m->m_len = MLEN;
+               }
+               len = min(datalen, 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;
+               datalen -= len;
+               if (cp == epkt)
+                       cp = spkt;
+       }
+       return (top);
+}
diff --git a/sys/arch/wgrisc/dev/if_sn.h b/sys/arch/wgrisc/dev/if_sn.h
new file mode 100644 (file)
index 0000000..37fa3a5
--- /dev/null
@@ -0,0 +1,347 @@
+/*     $OpenBSD: if_sn.h,v 1.1.1.1 1997/02/06 16:02:42 pefo Exp $      */
+/*
+ * Copyright (c) 1991   Algorithmics Ltd (http://www.algor.co.uk)
+ * You may use, copy, and modify this program so long as you retain the
+ * copyright line.
+ */
+
+/*
+ * if_sonic.h -- National Semiconductor DP83932BVF (SONIC)
+ */
+
+/*
+ * Accessing SONIC data structures and registers as 32 bit values
+ * makes code endianess independent.  The SONIC is however always in
+ * bigendian mode so it is necessary to ensure that data structures shared
+ * between the CPU and the SONIC are always in bigendian order.
+ */
+
+/*
+ * Receive Resource Descriptor
+ * This structure describes the buffers into which packets
+ * will be received.  Note that more than one packet may be
+ * packed into a single buffer if constraints permit.
+ */
+#if SONICDW == 32
+struct RXrsrc {
+       u_long  buff_ptrlo;     /* buffer address LO */
+       u_long  buff_ptrhi;     /* buffer address HI */
+       u_long  buff_wclo;      /* buffer size (16bit words) LO */ 
+       u_long  buff_wchi;      /* buffer size (16bit words) HI */
+};
+#endif
+
+/*
+ * Receive Descriptor
+ * This structure holds information about packets received.
+ */
+#if SONICDW == 32
+struct RXpkt {
+       u_long  status;         /* + receive status */
+       u_long  byte_count;     /* + packet byte count (including FCS) */
+       u_long  pkt_ptrlo;      /* + packet data LO (in RBA) */
+       u_long  pkt_ptrhi;      /* + packet data HI (in RBA) */
+       u_long  seq_no;         /* + RBA sequence numbers */
+       u_long  rlink;          /* link to next receive descriptor */
+       u_long  in_use;         /* + packet available to SONIC */
+       u_long  pad;            /* pad to multiple of 16 bytes */
+};
+#endif
+#define RBASEQ(x) (((x)>>8)&0xff)
+#define PSNSEQ(x) ((x) & 0xff)
+
+/*
+ * Transmit Descriptor
+ * This structure holds information about packets to be transmitted.
+ */
+#define FRAGMAX        31              /* maximum number of fragments in a packet */
+#if SONICDW == 32
+struct TXpkt {
+       u_long  status;         /* + transmitted packet status */
+       u_long  config;         /* transmission configuration */
+       u_long  pkt_size;       /* entire packet size in bytes */
+       u_long  frag_count;     /* # fragments in packet */
+       union {
+               struct {
+                       u_long  _frag_ptrlo;    /* pointer to packet fragment LO */
+                       u_long  _frag_ptrhi;    /* pointer to packet fragment HI */
+                       u_long  _frag_size;     /* fragment size */
+               } u_frag;
+               struct {
+                       u_long  _tlink;         /* link to next transmit descriptor */
+               } u_link;
+       } u[FRAGMAX+1]; /* +1 makes tcp->u[FRAGMAX].u_link.link valid! */
+};
+#endif
+
+#define frag_ptrlo u_frag._frag_ptrlo
+#define frag_ptrhi u_frag._frag_ptrhi
+#define frag_size u_frag._frag_size
+#define tlink u_link._tlink
+
+#define EOL    0x0001          /* end of list marker for link fields */
+
+#define MAXCAM 16      /* number of user entries in CAM */
+#if SONICDW == 32
+struct CDA {
+       struct {
+               u_long  cam_ep;         /* CAM Entry Pointer */
+               u_long  cam_ap0;        /* CAM Address Port 0 xx-xx-xx-xx-YY-YY */
+               u_long  cam_ap1;        /* CAM Address Port 1 xx-xx-YY-YY-xxxx */
+               u_long  cam_ap2;        /* CAM Address Port 2 YY-YY-xx-xx-xx-xx */
+       } desc[MAXCAM];
+       u_long  enable;         /* mask enabling CAM entries */
+};
+#endif
+
+/*
+ * SONIC registers as seen by the processor
+ */
+struct sonic_reg {
+       volatile u_long s_cr;           /* 00: Command */
+       volatile u_long s_dcr;          /* 01: Data Configuration */
+       volatile u_long s_rcr;          /* 02: Receive Control */
+       volatile u_long s_tcr;          /* 03: Transmit Control */
+       volatile u_long s_imr;          /* 04: Interrupt Mask */
+       volatile u_long s_isr;          /* 05: Interrupt Status */
+       volatile u_long s_utda;         /* 06: Upper Transmit Descriptor Address */
+       volatile u_long s_ctda;         /* 07: Current Transmit Descriptor Address */
+       volatile u_long _s_tps;         /* 08* Transmit Packet Size */
+       volatile u_long _s_tfc;         /* 09* Transmit Fragment Count */
+       volatile u_long _s_tsa0;        /* 0a* Transmit Start Address 0 */
+       volatile u_long _s_tsa1;        /* 0b* Transmit Start Address 1 */
+       volatile u_long _s_tfs;         /* 0c* Transmit Fragment Size */
+       volatile u_long s_urda;         /* 0d: Upper Receive Descriptor Address */
+       volatile u_long s_crda;         /* 0e: Current Receive Descriptor Address */
+       volatile u_long _s_crba0;       /* 0f* Current Receive Buffer Address 0 */
+       volatile u_long _s_crba1;       /* 10* Current Receive Buffer Address 1 */
+       volatile u_long _s_rbwc0;       /* 11* Remaining Buffer Word Count 0 */
+       volatile u_long _s_rbwc1;       /* 12* Remaining Buffer Word Count 1 */
+       volatile u_long s_eobc;         /* 13: End Of Buffer Word Count */
+       volatile u_long s_urra;         /* 14: Upper Receive Resource Address */
+       volatile u_long s_rsa;          /* 15: Resource Start Address */
+       volatile u_long s_rea;          /* 16: Resource End Address */
+       volatile u_long s_rrp;          /* 17: Resource Read Pointer */
+       volatile u_long s_rwp;          /* 18: Resource Write Pointer */
+       volatile u_long _s_trba0;       /* 19* Temporary Receive Buffer Address 0 */
+       volatile u_long _s_trba1;       /* 1a* Temporary Receive Buffer Address 1 */
+       volatile u_long _s_tbwc0;       /* 1b* Temporary Buffer Word Count 0 */
+       volatile u_long _s_tbwc1;       /* 1c* Temporary Buffer Word Count 1 */
+       volatile u_long _s_addr0;       /* 1d* Address Generator 0 */
+       volatile u_long _s_addr1;       /* 1e* Address Generator 1 */
+       volatile u_long _s_llfa;        /* 1f* Last Link Field Address */
+       volatile u_long _s_ttda;        /* 20* Temp Transmit Descriptor Address */
+       volatile u_long s_cep;          /* 21: CAM Entry Pointer */
+       volatile u_long s_cap2;         /* 22: CAM Address Port 2 */
+       volatile u_long s_cap1;         /* 23: CAM Address Port 1 */
+       volatile u_long s_cap0;         /* 24: CAM Address Port 0 */
+       volatile u_long s_ce;           /* 25: CAM Enable */
+       volatile u_long s_cdp;          /* 26: CAM Descriptor Pointer */
+       volatile u_long s_cdc;          /* 27: CAM Descriptor Count */
+       volatile u_long s_sr;           /* 28: Silicon Revision */
+       volatile u_long s_wt0;          /* 29: Watchdog Timer 0 */
+       volatile u_long s_wt1;          /* 2a: Watchdog Timer 1 */
+       volatile u_long s_rsc;          /* 2b: Receive Sequence Counter */
+       volatile u_long s_crct;         /* 2c: CRC Error Tally */
+       volatile u_long s_faet;         /* 2d: FAE Tally */
+       volatile u_long s_mpt;          /* 2e: Missed Packet Tally */
+       volatile u_long _s_mdt;         /* 2f* Maximum Deferral Timer */
+       volatile u_long _s_rtc;         /* 30* Receive Test Control */
+       volatile u_long _s_ttc;         /* 31* Transmit Test Control */
+       volatile u_long _s_dtc;         /* 32* DMA Test Control */
+       volatile u_long _s_cc0;         /* 33* CAM Comparison 0 */
+       volatile u_long _s_cc1;         /* 34* CAM Comparison 1 */
+       volatile u_long _s_cc2;         /* 35* CAM Comparison 2 */
+       volatile u_long _s_cm;          /* 36* CAM Match */
+       volatile u_long :32;            /* 37* reserved */
+       volatile u_long :32;            /* 38* reserved */
+       volatile u_long _s_rbc;         /* 39* Receiver Byte Count */
+       volatile u_long :32;            /* 3a* reserved */
+       volatile u_long _s_tbo;         /* 3b* Transmitter Backoff Counter */
+       volatile u_long _s_trc;         /* 3c* Transmitter Random Counter */
+       volatile u_long _s_tbm;         /* 3d* Transmitter Backoff Mask */
+       volatile u_long :32;            /* 3e* Reserved */
+       volatile u_long s_dcr2;         /* 3f Data Configuration 2 (AVF) */
+};
+
+/*
+ * Register Interpretations
+ */
+
+/*
+ * The command register is used for issuing commands to the SONIC.
+ * With the exception of CR_RST, the bit is reset when the operation
+ * completes.
+ */
+#define CR_LCAM                0x0200  /* load CAM with descriptor at s_cdp */
+#define CR_RRRA                0x0100  /* read next RRA descriptor at s_rrp */
+#define CR_RST         0x0080  /* software reset */
+#define CR_ST          0x0020  /* start timer */
+#define CR_STP         0x0010  /* stop timer */
+#define CR_RXEN                0x0008  /* receiver enable */
+#define CR_RXDIS       0x0004  /* receiver disable */
+#define CR_TXP         0x0002  /* transmit packets */
+#define CR_HTX         0x0001  /* halt transmission */
+
+/*
+ * The data configuration register establishes the SONIC's bus cycle
+ * operation.  This register can only be accessed when the SONIC is in
+ * reset mode (s_cr.CR_RST is set.)
+ */
+#define DCR_EXBUS      0x8000  /* extended bus mode (AVF) */
+#define DCR_LBR                0x2000  /* latched bus retry */
+#define DCR_PO1                0x1000  /* programmable output 1 */
+#define DCR_PO0                0x0800  /* programmable output 0 */
+#define DCR_STERM      0x0400  /* synchronous termination */
+#define DCR_USR1       0x0200  /* reflects USR1 input pin */
+#define DCR_USR0       0x0100  /* reflects USR0 input pin */
+#define DCR_WC1                0x0080  /* wait state control 1 */
+#define DCR_WC0                0x0040  /* wait state control 0 */
+#define DCR_DW         0x0020  /* data width select */
+#define DCR_BMS                0x0010  /* DMA block mode select */
+#define DCR_RFT1       0x0008  /* receive FIFO threshold control 1 */
+#define DCR_RFT0       0x0004  /* receive FIFO threshold control 0 */
+#define DCR_TFT1       0x0002  /* transmit FIFO threshold control 1 */
+#define DCR_TFT0       0x0001  /* transmit FIFO threshold control 0 */
+
+/* data configuration register aliases */
+#define DCR_SYNC       DCR_STERM /* synchronous (memory cycle 2 clocks) */
+#define DCR_ASYNC      0         /* asynchronous (memory cycle 3 clocks) */
+
+#define DCR_WAIT0      0                 /* 0 wait states added */
+#define DCR_WAIT1      DCR_WC0           /* 1 wait state added */
+#define DCR_WAIT2      DCR_WC1           /* 2 wait states added */
+#define DCR_WAIT3      (DCR_WC1|DCR_WC0) /* 3 wait states added */
+
+#define DCR_DW16       0       /* use 16-bit DMA accesses */
+#define DCR_DW32       DCR_DW  /* use 32-bit DMA accesses */
+
+#define DCR_DMAEF      0       /* DMA until TX/RX FIFO has emptied/filled */
+#define DCR_DMABLOCK   DCR_BMS /* DMA until RX/TX threshold crossed */
+
+#define DCR_RFT4       0               /* receive threshold 4 bytes */
+#define DCR_RFT8       DCR_RFT0        /* receive threshold 8 bytes */
+#define DCR_RFT16      DCR_RFT1        /* receive threshold 16 bytes */
+#define DCR_RFT24      (DCR_RFT1|DCR_RFT0) /* receive threshold 24 bytes */
+
+#define DCR_TFT8       0               /* transmit threshold 8 bytes */
+#define DCR_TFT16      DCR_TFT0        /* transmit threshold 16 bytes */
+#define DCR_TFT24      DCR_TFT1        /* transmit threshold 24 bytes */
+#define DCR_TFT28      (DCR_TFT1|DCR_TFT0) /* transmit threshold 28 bytes */
+
+/*
+ * The receive control register is used to filter incoming packets and
+ * provides status information on packets received.
+ * The contents of the register are copied into the RXpkt.status field
+ * when a packet is received. RCR_MC - RCR_PRX are then reset.
+ */
+#define RCR_ERR                0x8000  /* accept packets with CRC errors */
+#define RCR_RNT                0x4000  /* accept runt (length < 64) packets */
+#define RCR_BRD                0x2000  /* accept broadcast packets */
+#define RCR_PRO                0x1000  /* accept all physical address packets */
+#define RCR_AMC                0x0800  /* accept all multicast packets */
+#define RCR_LB1                0x0400  /* loopback control 1 */
+#define RCR_LB0                0x0200  /* loopback control 0 */
+#define RCR_MC         0x0100  /* multicast packet received */
+#define RCR_BC         0x0080  /* broadcast packet received */
+#define RCR_LPKT       0x0040  /* last packet in RBA (RBWC < EOBC) */
+#define RCR_CRS                0x0020  /* carrier sense activity */
+#define RCR_COL                0x0010  /* collision activity */
+#define RCR_CRC                0x0008  /* CRC error */
+#define RCR_FAE                0x0004  /* frame alignment error */
+#define RCR_LBK                0x0002  /* loopback packet received */
+#define RCR_PRX                0x0001  /* packet received without errors */
+
+/* receiver control register aliases */
+/* the loopback control bits provide the following options */
+#define RCR_LBNONE     0               /* no loopback - normal operation */
+#define RCR_LBMAC      RCR_LB0         /* MAC loopback */
+#define RCR_LBENDEC    RCR_LB1         /* ENDEC loopback */
+#define RCR_LBTRANS    (RCR_LB1|RCR_LB0) /* transceiver loopback */
+
+/*
+ * The transmit control register controls the SONIC's transmit operations.
+ * TCR_PINT - TCR_EXDIS are loaded from the TXpkt.config field at the
+ * start of transmission.  TCR_EXD-TCR_PTX are cleared at the beginning
+ * of transmission and updated when the transmission is completed.
+ */
+#define TCR_PINT       0x8000  /* interrupt when transmission starts */
+#define TCR_POWC       0x4000  /* program out of window collision timer */
+#define TCR_CRCI       0x2000  /* transmit packet without 4 byte FCS */
+#define TCR_EXDIS      0x1000  /* disable excessive deferral timer */
+#define TCR_EXD                0x0400  /* excessive deferrals occurred (>3.2ms) */
+#define TCR_DEF                0x0200  /* deferred transmissions occurred */
+#define TCR_NCRS       0x0100  /* carrier not present during transmission */
+#define TCR_CRSL       0x0080  /* carrier lost during transmission */
+#define TCR_EXC                0x0040  /* excessive collisions (>16) detected */
+#define TCR_OWC                0x0020  /* out of window (bad) collision occurred */
+#define TCR_PMB                0x0008  /* packet monitored bad - the tansmitted
+                                * packet had a bad source address or CRC */
+#define TCR_FU         0x0004  /* FIFO underrun (memory access failed) */
+#define TCR_BCM                0x0002  /* byte count mismatch (TXpkt.pkt_size
+                                * != sum(TXpkt.frag_size) */
+#define TCR_PTX                0x0001  /* packet transmitted without errors */
+
+/* transmit control register aliases */
+#define TCR_OWCSFD     0        /* start after start of frame delimiter */
+#define TCR_OWCPRE     TCR_POWC /* start after first bit of preamble */
+
+
+/*
+ * The interrupt mask register masks the interrupts that
+ * are generated from the interrupt status register.
+ * All reserved bits should be written with 0.
+ */
+#define IMR_BREN       0x4000  /* bus retry occurred enable */
+#define IMR_HBLEN      0x2000  /* heartbeat lost enable */
+#define IMR_LCDEN      0x1000  /* load CAM done interrupt enable */
+#define IMR_PINTEN     0x0800  /* programmable interrupt enable */
+#define IMR_PRXEN      0x0400  /* packet received enable */
+#define IMR_PTXEN      0x0200  /* packet transmitted enable */
+#define IMR_TXEREN     0x0100  /* transmit error enable */
+#define IMR_TCEN       0x0080  /* timer complete enable */
+#define IMR_RDEEN      0x0040  /* receive descriptors exhausted enable */
+#define IMR_RBEEN      0x0020  /* receive buffers exhausted enable */
+#define IMR_RBAEEN     0x0010  /* receive buffer area exceeded enable */
+#define IMR_CRCEN      0x0008  /* CRC tally counter rollover enable */
+#define IMR_FAEEN      0x0004  /* FAE tally counter rollover enable */
+#define IMR_MPEN       0x0002  /* MP tally counter rollover enable */
+#define IMR_RFOEN      0x0001  /* receive FIFO overrun enable */
+
+
+/*
+ * The interrupt status register indicates the source of an interrupt when
+ * the INT pin goes active.  The interrupt is acknowledged by writing
+ * the appropriate bit(s) in this register.
+ */
+#define ISR_ALL                0xffff  /* all interrupts */
+#define ISR_BR         0x4000  /* bus retry occurred */
+#define ISR_HBL                0x2000  /* CD heartbeat lost */
+#define ISR_LCD                0x1000  /* load CAM command has completed */
+#define ISR_PINT       0x0800  /* programmed interrupt from TXpkt.config */
+#define ISR_PKTRX      0x0400  /* packet received */
+#define ISR_TXDN       0x0200  /* no remaining packets to be transmitted */
+#define ISR_TXER       0x0100  /* packet transmission caused error */
+#define ISR_TC         0x0080  /* timer complete */
+#define ISR_RDE                0x0040  /* receive descriptors exhausted */
+#define ISR_RBE                0x0020  /* receive buffers exhausted */
+#define ISR_RBAE       0x0010  /* receive buffer area exceeded */
+#define ISR_CRC                0x0008  /* CRC tally counter rollover */
+#define ISR_FAE                0x0004  /* FAE tally counter rollover */
+#define ISR_MP         0x0002  /* MP tally counter rollover */
+#define ISR_RFO                0x0001  /* receive FIFO overrun */
+
+/*
+ * The second data configuration register allows additional user defined
+ * pins to be controlled.  These bits are only available if s_dcr.DCR_EXBUS
+ * is set.
+ */
+#define DCR2_EXPO3     0x8000  /* EXUSR3 output */
+#define DCR2_EXPO2     0x4000  /* EXUSR2 output */
+#define DCR2_EXPO1     0x2000  /* EXUSR1 output */
+#define DCR2_EXPO0     0x1000  /* EXUSR0 output */
+#define DCR2_PHL       0x0010  /* extend HOLD signal by 1/2 clock */
+#define DCR2_LRDY      0x0008  /* set latched ready mode */
+#define DCR2_PCM       0x0004  /* packet compress on match */
+#define DCR2_PCNM      0x0002  /* packet compress on mismatch */
+#define DCR2_RJM       0x0001  /* reject on match */
diff --git a/sys/arch/wgrisc/dev/scsi.h b/sys/arch/wgrisc/dev/scsi.h
new file mode 100644 (file)
index 0000000..ffbd996
--- /dev/null
@@ -0,0 +1,559 @@
+/*     $OpenBSD: scsi.h,v 1.1.1.1 1997/02/06 16:02:41 pefo Exp $       */
+/*
+ * Copyright (c) 1992, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Ralph Campbell.
+ *
+ * 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: @(#)scsi.h        8.1 (Berkeley) 6/10/93
+ *      $Id: scsi.h,v 1.1.1.1 1997/02/06 16:02:41 pefo Exp $
+ *
+ * scsi.h --
+ *
+ *     Common declarations for SCSI command formaters. This file only covers
+ *     definitions pertaining to the SCSI common command set that are
+ *     common to all SCSI device types (ie disk, tapes, WORM, printers, etc).
+ *     Some of the references from the proceedings of the
+ *     1984 Mini/Micro Northeast conference might help in understanding SCSI. 
+ *
+ * from: Header: /sprite/src/kernel/dev/RCS/scsi.h,
+ *     v 9.1 90/02/13 23:11:24 jhh Exp  SPRITE (Berkeley)
+ * $Id: scsi.h,v 1.1.1.1 1997/02/06 16:02:41 pefo Exp $
+ */
+
+#ifndef _SCSI_H
+#define _SCSI_H
+
+/*
+ * "Standard" SCSI Commands.
+ * SCSI commands are divided into 8 groups as follows:
+ *     Group0  (0x00 - 0x1f).  Basic commands. 6 bytes long
+ *     Group1  (0x20 - 0x3f).  Extended command. 10 bytes.
+ *     Group2  (0x40 - 0x5f).  Reserved.
+ *     Group2  (0x60 - 0x7f).  Reserved.
+ *     Group2  (0x80 - 0x9f).  Reserved.
+ *     Group2  (0xa0 - 0xbf).  Reserved.
+ *     Group6  (0xc0 - 0xdf).  Vendor Unique
+ *     Group7  (0xe0 - 0xff).  Vendor Unique
+ */
+
+/*
+ * Scsi Group0 commands all are 6 bytes and have a format according to 
+ * struct ScsiGroup0Cmd.
+ */
+#define SCSI_TEST_UNIT_READY   0x00
+#define SCSI_REZERO_UNIT       0x01
+#define SCSI_REWIND            0x01
+#define SCSI_REQUEST_SENSE     0x03
+#define        SCSI_FORMAT_UNIT        0x04
+#define        SCSI_READ_BLOCK_LIMITS  0x05
+#define SCSI_REASSIGN_BLOCKS   0x07
+#define SCSI_READ              0x08
+#define SCSI_WRITE             0x0a
+#define SCSI_SEEK              0x0b
+#define        SCSI_TRACK_SELECT       0x0b
+#define        SCSI_READ_REVERSE       0x0f
+#define SCSI_WRITE_EOF         0x10
+#define SCSI_SPACE             0x11
+#define SCSI_INQUIRY           0x12
+#define SCSI_VERIFY            0x13
+#define        SCSI_READ_BUFFER        0x14
+#define SCSI_MODE_SELECT       0x15
+#define        SCSI_RESERVE_UNIT       0x16
+#define        SCSI_RELEASE_UNIT       0x17
+#define SCSI_COPY              0x18
+#define SCSI_ERASE_TAPE                0x19
+#define SCSI_MODE_SENSE                0x1a
+#define SCSI_START_STOP                0x1b
+#define        SCSI_LOAD_UNLOAD        0x1b
+#define        SCSI_RECV_DIAG_RESULTS  0x1c
+#define SCSI_SEND_DIAGNOSTIC   0x1d
+#define SCSI_PREVENT_ALLOW     0x1e
+
+/*
+ * Group1 commands are all 10 bytes and have a format according to
+ * struct ScsiGroup1Cmd.
+ */
+#define SCSI_READ_CAPACITY     0x25    
+#define        SCSI_READ_EXT           0x28
+#define        SCSI_WRITE_EXT          0x2a
+#define        SCSI_SEEK_EXT           0x2b
+#define        SCSI_WRITE_VERIFY       0x2e
+#define        SCSI_VERIFY_EXT         0x2f
+#define        SCSI_SEARCH_HIGH        0x30
+#define SCSI_SEARCH_EQUAL      0x31
+#define        SCSI_SEARCH_LOW         0x32
+#define        SCSI_SET_LIMITS         0x33
+#define        SCSI_COMPARE            0x39
+#define        SCSI_COPY_VERIFY        0x3a
+
+/*
+ * Control byte flags for Group0 and Group1 commands.
+ *
+ * SCSI_CTRL_LINK - This is used to prevent a bus free phase between commands.
+ *     If the command terminates successfully, a SCSI_LINKED_CMD_COMPLETE
+ *     message is returned instead of the normal SCSI_COMMAND_COMPLETE message. *      The last command in a chain should not have this bit set
+ *     (and consequently gets a normal SCSI_COMMAND_COMPLETE message).
+ * SCSI_CTRL_LINK_FLAG - This bit should only set when SCSI_CTRL_LINK is set and
+ *     causes a SCSI_LINKED_FLAGED_CMD_COMPLETE to be returned instead of
+ *     a SCSI_LINKED_CMD_COMPLETE.
+ */
+#define SCSI_CTRL_LINK         0x01    /* Link commands (no bus free phase) */
+#define SCSI_CTRL_LINK_INTR    0x02    /* Interrupt after linked command */
+
+/*
+ * The standard group0 6-byte SCSI control block.  Note that the 
+ * fields between highAddr and blockCount inclusive are command dependent.
+ * The definitions Addr and BlockCount cover most of the commands we will
+ * use.
+ */
+typedef struct ScsiGroup0Cmd {
+       u_char  command;                /* command code, defined below.  The
+                                        * upper three bits of this are zero
+                                        * to indicate the control block is
+                                        * only 6 bytes long */
+#if BYTE_ORDER == BIG_ENDIAN
+       u_char  unitNumber      :3;     /* Logical Unit (LUN) to which to
+                                        * pass the command.  The device
+                                        * has already been selected using
+                                        * the "targetID" bit. */
+       u_char  highAddr        :5;     /* High bits of address */
+#else
+       u_char  highAddr        :5;     /* High bits of address */
+       u_char  unitNumber      :3;     /* Logical Unit (LUN) to which to
+                                        * pass the command.  The device
+                                        * has already been selected using
+                                        * the "targetID" bit. */
+#endif
+       u_char  midAddr;                /* Middle bits of address */
+       u_char  lowAddr;                /* Low bits of address */
+       u_char  blockCount;             /* Blocks to transfer */
+       u_char  control;                /* See flags for common bits */
+} ScsiGroup0Cmd;
+
+/*
+ * Format of a SCSI_START_STOP command. This is a group 0 command, but
+ * the command contents are different.
+ */
+typedef struct ScsiStartStopCmd {
+#if BYTE_ORDER == BIG_ENDIAN
+       u_char  command;                /* command code, defined below.  The
+                                        * upper three bits of this are zero
+                                        * to indicate the control block is
+                                        * only 6 bytes long */
+       u_char  unitNumber      :3;     /* Logical Unit (LUN) to which to
+                                        * pass the command.  The device
+                                        * has already been selected using
+                                        * the "targetID" bit. */
+       u_char  pad1            :4;     /* Reserved */
+       u_char  immed           :1;     /* Immediate status bit */
+       u_char  pad2;                   /* Reserved */
+       u_char  pad3;                   /* Reserved */
+       u_char  pad4            :6;     /* Reserved */
+       u_char  loadEject       :1;     /* Load or eject medium */
+       u_char  start           :1;     /* Start or stop medium */
+       u_char  control;                /* See flags for common bits */
+#else
+       u_char  command;                /* command code, defined below.  The
+                                        * upper three bits of this are zero
+                                        * to indicate the control block is
+                                        * only 6 bytes long */
+       u_char  immed           :1;     /* Immediate status bit */
+       u_char  pad1            :4;     /* Reserved */
+       u_char  unitNumber      :3;     /* Logical Unit (LUN) to which to
+                                        * pass the command.  The device
+                                        * has already been selected using
+                                        * the "targetID" bit. */
+       u_char  pad2;                   /* Reserved */
+       u_char  pad3;                   /* Reserved */
+       u_char  start           :1;     /* Start or stop medium */
+       u_char  loadEject       :1;     /* Load or eject medium */
+       u_char  pad4            :6;     /* Reserved */
+       u_char  control;                /* See flags for common bits */
+#endif
+} ScsiStartStopCmd;
+
+/*
+ * The standard group1 10-byte SCSI control block.  Note that the 
+ * fields between highAddr and blockCount inclusive are command dependent.
+ * The definitions Addr and BlockCount cover most of the commands we will
+ * use.
+ */
+typedef struct ScsiGroup1Cmd {
+       u_char  command;                /* command code, defined below.  The
+                                        * upper three bits of this are zero
+                                        * to indicate the control block is
+                                        * only 6 bytes long */
+#if BYTE_ORDER == BIG_ENDIAN
+       u_char  unitNumber      :3;     /* Logical Unit (LUN) to which to
+                                        * pass the command.  The device
+                                        * has already been selected using
+                                        * the "targetID" bit. */
+       u_char  pad1            :5;     /* Reserved */
+#else
+       u_char  pad1            :5;     /* Reserved */
+       u_char  unitNumber      :3;     /* Logical Unit (LUN) to which to
+                                        * pass the command.  The device
+                                        * has already been selected using
+                                        * the "targetID" bit. */
+#endif
+       u_char  highAddr;               /* High bits of address */
+       u_char  midHighAddr;            /* Middle high bits of address */
+       u_char  midLowAddr;             /* Middle low bits of address */
+       u_char  lowAddr;                /* Low bits of address */
+       u_char  pad2;                   /* Reserved */
+       u_char  highBlockCount; /* High bits of blocks to transfer */
+       u_char  lowBlockCount;  /* Low bits of blocks to transfer */
+       u_char  control;                /* See flags for common bits */
+} ScsiGroup1Cmd;
+
+/*
+ * SCSI status completion information.
+ * This is returned by the device when a command completes. 
+ */
+#define        SCSI_STATUS_CHECKCOND   0x02    /* Check Condition (ie., read sense) */
+#define        SCSI_STATUS_CONDMET     0x04    /* Condition Met (ie., search worked) */
+#define        SCSI_STATUS_BUSY        0x08
+#define        SCSI_STATUS_INTERMED    0x10    /* Intermediate status sent */
+#define        SCSI_STATUS_EXT         0x80    /* Extended status valid */
+
+/*
+ * Sense information provided after some errors.  This is divided into
+ * two kinds, classes 0-6, and class 7.  This is 30 bytes big to allow
+ * for the drive specific sense bytes that follow the standard 4 byte header.
+ *
+ * For extended sense, this buffer may be cast into another type.  Also
+ * The actual size of the sense data returned is used to detect what
+ * kind of tape drive is out there.  Kludgy, but true.
+ */
+typedef struct ScsiClass0Sense {
+#if BYTE_ORDER == BIG_ENDIAN
+       u_char  valid           :1;     /* Sense data is valid */
+       u_char  error           :7;     /* 3 bits class and 4 bits code */
+#else
+       u_char  error           :7;     /* 3 bits class and 4 bits code */
+       u_char  valid           :1;     /* Sense data is valid */
+#endif
+       u_char  highAddr;               /* High byte of block address */
+       u_char  midAddr;                /* Middle byte of block address */
+       u_char  lowAddr;                /* Low byte of block address */
+       u_char  sense[26];              /* Target specific sense data */
+} ScsiClass0Sense;
+
+/*
+ * Definitions for errors in the sense data.  The error field is specified
+ * as a 3 bit class and 4 bit code, but it is easier to treat it as a
+ * single 7 bit field.
+ */
+#define SCSI_NO_SENSE_DATA             0x00
+#define SCSI_NOT_READY                 0x04
+#define SCSI_NOT_LOADED                        0x09
+#define SCSI_INSUF_CAPACITY            0x0a
+#define SCSI_HARD_DATA_ERROR           0x11
+#define SCSI_WRITE_PROTECT             0x17
+#define SCSI_CORRECTABLE_ERROR         0x18
+#define SCSI_FILE_MARK                 0x1c
+#define SCSI_INVALID_COMMAND           0x20
+#define SCSI_UNIT_ATTENTION            0x30
+#define SCSI_END_OF_MEDIA              0x34
+
+/*
+ * The standard "extended" sense data returned by SCSI devices.  This
+ * has an error field of 0x70, for a "class 7" error.
+ */
+typedef struct ScsiClass7Sense {
+#if BYTE_ORDER == BIG_ENDIAN
+       u_char  valid           :1;     /* Sense data is valid */
+       u_char  error7          :7;     /* == 0x70 */
+       u_char  pad1;                   /* Also "segment number" for copy */
+       u_char  fileMark        :1;     /* File mark on device */
+       u_char  endOfMedia      :1;     /* End of media reached */
+       u_char  badBlockLen     :1;     /* Block length mis-match (Exabyte) */
+       u_char  pad2            :1;
+       u_char  key             :4;     /* Sense keys defined below */
+       u_char  info1;                  /* Information byte 1 */
+       u_char  info2;                  /* Information byte 2 */
+       u_char  info3;                  /* Information byte 3 */
+       u_char  info4;                  /* Information byte 4 */
+       u_char  length;                 /* Number of additional info bytes */
+#else
+       u_char  error7          :7;     /* == 0x70 */
+       u_char  valid           :1;     /* Sense data is valid */
+       u_char  pad1;                   /* Also "segment number" for copy */
+       u_char  key             :4;     /* Sense keys defined below */
+       u_char  pad2            :1;
+       u_char  badBlockLen     :1;     /* Block length mis-match (Exabyte) */
+       u_char  endOfMedia      :1;     /* End of media reached */
+       u_char  fileMark        :1;     /* File mark on device */
+       u_char  info1;                  /* Information byte 1 */
+       u_char  info2;                  /* Information byte 2 */
+       u_char  info3;                  /* Information byte 3 */
+       u_char  info4;                  /* Information byte 4 */
+       u_char  length;                 /* Number of additional info bytes */
+#endif
+} ScsiClass7Sense;                     /* 8 Bytes */
+
+/*
+ * Key values for standardized sense class 7. 
+ */
+#define SCSI_CLASS7_NO_SENSE           0
+#define SCSI_CLASS7_RECOVERABLE                1
+#define SCSI_CLASS7_NOT_READY          2
+#define SCSI_CLASS7_MEDIA_ERROR                3
+#define SCSI_CLASS7_HARDWARE_ERROR     4
+#define SCSI_CLASS7_ILLEGAL_REQUEST    5
+
+/*
+ * These seem to have different meanings to different vendors....
+ */
+#define SCSI_CLASS7_MEDIA_CHANGE       6
+#define SCSI_CLASS7_UNIT_ATTN          6
+
+#define SCSI_CLASS7_WRITE_PROTECT      7
+#define SCSI_CLASS7_BLANK_CHECK                8
+#define SCSI_CLASS7_VENDOR             9
+#define SCSI_CLASS7_POWER_UP_FAILURE   10
+#define SCSI_CLASS7_ABORT              11
+#define SCSI_CLASS7_EQUAL              12
+#define SCSI_CLASS7_OVERFLOW           13
+#define SCSI_CLASS7_RESERVED_14                14
+#define SCSI_CLASS7_RESERVED_15                15
+
+/*
+ * Data return by the SCSI inquiry command. 
+ */
+typedef struct ScsiInquiryData {
+#if BYTE_ORDER == BIG_ENDIAN
+       u_char  type;           /* Peripheral Device type. See below. */
+       u_char  rmb:1;          /* Removable Medium bit. */
+       u_char  qualifier:7;    /* Device type qualifier. */
+       u_char  version;        /* Version info. */
+       u_char  reserved:4;     /* reserved. */
+       u_char  format:4;       /* Response format. */
+       u_char  length;         /* length of data returned. */
+       u_char  reserved2[2];   /* Reserved */
+       u_char  flags;          /* SCSI II flags (see below) */
+       u_char  vendorID[8];    /* Vendor ID (ASCII) */
+       u_char  productID[16];  /* Product ID (ASCII) */
+       u_char  revLevel[4];    /* Revision level (ASCII) */
+       u_char  revData[8];     /* Revision data (ASCII) */
+#else
+       u_char  type;           /* Peripheral Device type. See below. */
+       u_char  qualifier:7;    /* Device type qualifier. */
+       u_char  rmb:1;          /* Removable Medium bit. */
+       u_char  version;        /* Version info. */
+       u_char  format:4;       /* Response format. */
+       u_char  reserved:4;     /* reserved. */
+       u_char  length;         /* length of data returned. */
+       u_char  reserved2[2];   /* Reserved */
+       u_char  flags;          /* SCSI II flags (see below) */
+       u_char  vendorID[8];    /* Vendor ID (ASCII) */
+       u_char  productID[16];  /* Product ID (ASCII) */
+       u_char  revLevel[4];    /* Revision level (ASCII) */
+       u_char  revData[8];     /* Revision data (ASCII) */
+#endif
+} ScsiInquiryData;
+
+/*
+ * The SCSI Peripheral type ID codes as return by the SCSI_INQUIRY command.
+ *
+ * SCSI_DISK_TYPE - Direct Access Device.
+ * SCSI_TAPE_TYPE - Sequential Access Device.
+ * SCSI_PRINTER_TYPE - Printer Device.
+ * SCSI_HOST_TYPE - Processor Device.
+ * SCSI_WORM_TYPE - Write-Once Read-Multiple Device.
+ * SCSI_ROM_TYPE - Read-Only Direct Access Device.
+ * SCSI_SCANNER_TYPE - Scanner device.
+ * SCSI_OPTICAL_MEM_TYPE - Optical memory device.
+ * SCSI_MEDIUM_CHANGER_TYPE - Medium changer device.
+ * SCSI_COMMUNICATIONS_TYPE - Communications device.
+ * SCSI_NODEVICE_TYPE - Logical Unit not present or implemented.
+ *
+ * Note that codes 0xa-0x7e are reserved and 0x80-0xff are vendor unique.
+ */
+#define        SCSI_DISK_TYPE                  0
+#define        SCSI_TAPE_TYPE                  1
+#define        SCSI_PRINTER_TYPE               2
+#define        SCSI_HOST_TYPE                  3
+#define        SCSI_WORM_TYPE                  4
+#define        SCSI_ROM_TYPE                   5
+#define        SCSI_SCANNER_TYPE               6
+#define        SCSI_OPTICAL_MEM_TYPE           7
+#define        SCSI_MEDIUM_CHANGER_TYPE        8
+#define        SCSI_COMMUNICATIONS_TYPE        9
+#define        SCSI_NODEVICE_TYPE              0x7f
+
+/*
+ * The SCSI I & II inquiry flags.
+ *
+ * SCSI_REL_ADR - Relative addressing supported.
+ * SCSI_WIDE_32 - 32 bit wide SCSI bus transfers supported.
+ * SCSI_WIDE_16 - 16 bit wide SCSI bus transfers supported.
+ * SCSI_SYNC - Synchronous data transfers supported.
+ * SCSI_LINKED - Linked commands supported.
+ * SCSI_CMD_QUEUE - Tagged command queuing supported.
+ * SCSI_SOFT_RESET - Soft RESET alternative suported.
+ */
+#define SCSI_REL_ADR           0x80
+#define SCSI_WIDE_32           0x40
+#define SCSI_WIDE_16           0x20
+#define SCSI_SYNC              0x10
+#define SCSI_LINKED            0x08
+#define SCSI_CMD_QUEUE         0x02
+#define SCSI_SOFT_RESET                0x01
+
+/*
+ * Standard header for SCSI_MODE_SENSE and SCSI_MODE_SELECT commands for tapes.
+ */
+typedef struct ScsiTapeModeSelectHdr {
+       u_char  len;            /* length */
+       u_char  media;          /* media type */
+#if BYTE_ORDER == BIG_ENDIAN
+       u_char  writeprot:1;    /* Write protected media */
+       u_char  bufferedMode:3; /* Type of buffer to be done. */
+       u_char  speed:4;        /* Drive speed. */
+#else
+       u_char  speed:4;        /* Drive speed. */
+       u_char  bufferedMode:3; /* Type of buffer to be done. */
+       u_char  writeprot:1;    /* Write protected media */
+#endif
+       u_char  length;         /* Block descriptor length. */
+       u_char  density;        /* tape density code */
+       u_char  blocks_2;       /* number of blocks (MSB) */
+       u_char  blocks_1;       /* number of blocks */
+       u_char  blocks_0;       /* number of blocks (LSB) */
+       u_char  reserved;       /* */
+       u_char  block_size2;    /* Tape block size (MSB) */
+       u_char  block_size1;    /* Tape block size */
+       u_char  block_size0;    /* Tape block size (LSB) */
+       u_char  vendor[6];      /* vendor specific data */
+} ScsiTapeModeSelectHdr;
+
+/*
+ * Definitions of SCSI messages.
+ *
+ * SCSI_COMMAND_COMPLETE - After a command has completed, successfully
+ *     or not, this is returned to the host from the target.
+ *
+ * SCSI_EXTENDED_MSG - Indicates that a multi-byte message is being sent.
+ *
+ * The following messages are used with connect/disconnect:
+ * SCSI_SAVE_DATA_POINTER - Sent from target to host to request saving
+ *     of current DMA address and count.  Indicates a pending dis-connect.
+ * SCSI_RESTORE_POINTER - Sent from the target to the host to request
+ *     restoring pointers saved before a disconnect
+ * SCSI_DISCONNECT - Sent from the target to the host to disconnect.
+ * SCSI_ABORT - Sent from the host to the target to abort current request.
+ * SCSI_MESSAGE_REJECT -  Indicates receipt, by either host or target, of
+ *     an unimplemented message.
+ * SCSI_NO_OP - Sent from host to target if it has no real message to send.
+ * SCSI_MESSAGE_PARITY_ERROR - Sent from host to target on message parity error
+ * SCSI_BUS_RESET - Sent from host to target to reset all current I/O
+ *
+ * SCSI_IDENTIFY - The low order two bits of this message type indicate
+ *     the Logical Unit of the Target which is requesting a reconnect.
+ * SCSI_DIS_REC_IDENTIFY - Sent from the host to a target to indicate
+ *     is supports connect/dis-connect
+ *     
+ */
+#define SCSI_COMMAND_COMPLETE          0x00
+#define SCSI_EXTENDED_MSG              0x01
+#define SCSI_SAVE_DATA_POINTER         0x02
+#define SCSI_RESTORE_POINTERS          0x03
+#define SCSI_DISCONNECT                        0x04
+#define SCSI_ABORT                     0x06
+#define SCSI_MESSAGE_REJECT            0x07
+#define SCSI_NO_OP                     0x08
+#define SCSI_MESSAGE_PARITY_ERROR      0x09
+#define SCSI_LINKED_CMD_COMPLETE       0x0A
+#define SCSI_LINKED_FLAGED_CMD_COMPLETE        0x0B
+#define SCSI_BUS_RESET                 0x0C
+
+#define SCSI_IDENTIFY                  0x80
+#define SCSI_DIS_REC_IDENTIFY          0xc0
+
+/*
+ * Extended message types (2nd byte of SCSI_EXTENDED_MSG).
+ */
+#define SCSI_MODIFY_DATA_PTR           0x00
+#define SCSI_SYNCHRONOUS_XFER          0x01
+#define SCSI_EXTENDED_IDENTIFY         0x02 /* only in SCSI I */
+#define SCSI_WIDE_XFER                 0x03
+
+/*
+ * Driver ioctl's for various scsi operations.
+ */
+#ifndef _IOCTL_
+#include <sys/ioctl.h>
+#endif
+
+/*
+ * Control for SCSI "format" mode.
+ *
+ * "Format" mode allows a privileged process to issue direct SCSI
+ * commands to a drive (it is intended primarily to allow on-line
+ * formatting).  SDIOCSFORMAT with a non-zero arg will put the drive
+ * into format mode; a zero arg will take it out.  When in format
+ * mode, only the process that issued the SDIOCFORMAT can read or
+ * write the drive.
+ *
+ * In format mode, process is expected to
+ *     - do SDIOCSCSICOMMAND to supply cdb for next SCSI op
+ *     - do read or write as appropriate for cdb
+ *     - if i/o error, optionally do SDIOCSENSE to get completion
+ *       status and sense data from last scsi operation.
+ */
+
+struct scsi_fmt_cdb {
+       int     len;            /* cdb length (in bytes) */
+       u_char  cdb[28];        /* cdb to use on next read/write */
+};
+
+struct scsi_fmt_sense {
+       u_int   status;         /* completion status of last op */
+       u_char  sense[32];      /* sense data (if any) from last op */
+};
+
+#define        SDIOCSFORMAT            _IOW('S', 0x1, int)
+#define        SDIOCGFORMAT            _IOR('S', 0x2, int)
+#define        SDIOCSCSICOMMAND        _IOW('S', 0x3, struct scsi_fmt_cdb)
+#define        SDIOCSENSE              _IOR('S', 0x4, struct scsi_fmt_sense)
+
+#ifdef _KERNEL
+/*
+ * Routines.
+ */
+extern void scsiGroup0Cmd();
+extern void scsiGroup1Cmd();
+#endif /* _KERNEL */
+
+#endif /* _SCSI_H */
diff --git a/sys/arch/wgrisc/include/ansi.h b/sys/arch/wgrisc/include/ansi.h
new file mode 100644 (file)
index 0000000..8e3a681
--- /dev/null
@@ -0,0 +1,75 @@
+/*     $OpenBSD: ansi.h,v 1.1.1.1 1997/02/06 16:02:44 pefo Exp $       */
+/*     $NetBSD: ansi.h,v 1.5 1994/10/26 21:09:33 cgd Exp $     */
+
+/*-
+ * 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.
+ *
+ *     @(#)ansi.h      8.2 (Berkeley) 1/4/94
+ */
+
+#ifndef        _ANSI_H_
+#define        _ANSI_H_
+
+/*
+ * Types which are fundamental to the implementation and may appear in
+ * more than one standard header are defined here.  Standard headers
+ * then use:
+ *     #ifdef  _BSD_SIZE_T_
+ *     typedef _BSD_SIZE_T_ size_t;
+ *     #undef  _BSD_SIZE_T_
+ *     #endif
+ */
+#define        _BSD_CLOCK_T_   unsigned long           /* clock() */
+#define        _BSD_PTRDIFF_T_ int                     /* ptr1 - ptr2 */
+#define        _BSD_SIZE_T_    unsigned int            /* sizeof() */
+#define        _BSD_SSIZE_T_   int                     /* byte count or error */
+#define        _BSD_TIME_T_    long                    /* time() */
+#define        _BSD_VA_LIST_   char *                  /* va_list */
+
+/*
+ * Runes (wchar_t) is declared to be an ``int'' instead of the more natural
+ * ``unsigned long'' or ``long''.  Two things are happening here.  It is not
+ * unsigned so that EOF (-1) can be naturally assigned to it and used.  Also,
+ * it looks like 10646 will be a 31 bit standard.  This means that if your
+ * ints cannot hold 32 bits, you will be in trouble.  The reason an int was
+ * chosen over a long is that the is*() and to*() routines take ints (says
+ * ANSI C), but they use _RUNE_T_ instead of int.  By changing it here, you
+ * lose a bit of ANSI conformance, but your programs will still work.
+ *    
+ * Note that _WCHAR_T_ and _RUNE_T_ must be of the same type.  When wchar_t
+ * and rune_t are typedef'd, _WCHAR_T_ will be undef'd, but _RUNE_T remains
+ * defined for ctype.h.
+ */
+#define        _BSD_WCHAR_T_   int                     /* wchar_t */
+#define        _BSD_RUNE_T_    int                     /* rune_t */
+
+#endif /* _ANSI_H_ */
diff --git a/sys/arch/wgrisc/include/asm.h b/sys/arch/wgrisc/include/asm.h
new file mode 100644 (file)
index 0000000..8c55248
--- /dev/null
@@ -0,0 +1,198 @@
+/*      $OpenBSD: asm.h,v 1.1.1.1 1997/02/06 16:02:44 pefo Exp $       */
+
+/*
+ * Copyright (c) 1992, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Ralph Campbell.
+ *
+ * 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.
+ *
+ *     Copyright (C) 1989 Digital Equipment Corporation.
+ *     Permission to use, copy, modify, and distribute this software and
+ *     its documentation for any purpose and without fee is hereby granted,
+ *     provided that the above copyright notice appears in all copies.
+ *     Digital Equipment Corporation makes no representations about the
+ *     suitability of this software for any purpose.  It is provided "as is"
+ *     without express or implied warranty.
+ */
+
+#ifndef _MACHASMDEFS
+#define _MACHASMDEFS
+
+#include <machine/regdef.h>
+
+#define        ABICALLS        .abicalls
+
+#if defined(ABICALLS) && !defined(_KERNEL)
+       ABICALLS
+#endif
+
+#define RCSID(x)
+
+#define _C_LABEL(x) x
+
+/*
+ * Define how to access unaligned data word 
+ */
+#ifdef MIPSEL
+#define LWLO    lwl
+#define LWHI    lwr
+#define        SWLO    swl
+#define        SWHI    swr
+#endif
+#ifdef MIPSEB
+#define LWLO    lwr
+#define LWHI    lwl
+#define        SWLO    swr
+#define        SWHI    swl
+#endif
+
+/*
+ * Code for setting gp reg if abicalls are used.
+ */
+#if defined(ABICALLS) && !defined(_KERNEL)
+#define        ABISETUP                \
+       .set    noreorder;      \
+       .cpload t9;             \
+       .set    reorder;
+#else
+#define        ABISETUP
+#endif
+
+/*
+ * Define -pg profile entry code.
+ */
+#if defined(GPROF) || defined(PROF)
+#define        MCOUNT                  \
+       .set noreorder;         \
+       .set noat;              \
+       move $1,$31;            \
+       jal _mcount;            \
+       subu sp,sp,8;           \
+       .set reorder;           \
+       .set at;
+#else
+#define        MCOUNT
+#endif
+
+/*
+ * LEAF(x)
+ *
+ *     Declare a leaf routine.
+ */
+#define LEAF(x)                        \
+       .align  3;              \
+       .globl x;               \
+       .ent x, 0;              \
+x: ;                           \
+       .frame sp, 0, ra;       \
+       ABISETUP                \
+       MCOUNT
+
+#define        ALEAF(x)                \
+       .globl  x;              \
+x:
+
+/*
+ * NLEAF(x)
+ *
+ *     Declare a non-profiled leaf routine.
+ */
+#define NLEAF(x)               \
+       .align  3;              \
+       .globl x;               \
+       .ent x, 0;              \
+x: ;                           \
+       .frame sp, 0, ra;       \
+       ABISETUP
+
+/*
+ * NON_LEAF(x)
+ *
+ *     Declare a non-leaf routine (a routine that makes other C calls).
+ */
+#define NON_LEAF(x, fsize, retpc) \
+       .align  3;              \
+       .globl x;               \
+       .ent x, 0;              \
+x: ;                           \
+       .frame sp, fsize, retpc; \
+       ABISETUP                \
+       MCOUNT
+
+/*
+ * NNON_LEAF(x)
+ *
+ *     Declare a non-profiled non-leaf routine
+ *     (a routine that makes other C calls).
+ */
+#define NNON_LEAF(x, fsize, retpc) \
+       .align  3;              \
+       .globl x;               \
+       .ent x, 0;              \
+x: ;                           \
+       .frame sp, fsize, retpc \
+       ABISETUP
+
+/*
+ * END(x)
+ *
+ *     Mark end of a procedure.
+ */
+#define END(x) \
+       .end x
+
+#define STAND_FRAME_SIZE       24
+#define STAND_RA_OFFSET                20
+
+/*
+ * Macros to panic and printf from assembly language.
+ */
+#define PANIC(msg) \
+       la      a0, 9f; \
+       jal     panic; \
+       MSG(msg)
+
+#define        PRINTF(msg) \
+       la      a0, 9f; \
+       jal     printf; \
+       MSG(msg)
+
+#define        MSG(msg) \
+       .rdata; \
+9:     .asciiz msg; \
+       .text
+
+#define ASMSTR(str) \
+       .asciiz str; \
+       .align  3
+
+#endif /* _MACHASMDEFS */
diff --git a/sys/arch/wgrisc/include/autoconf.h b/sys/arch/wgrisc/include/autoconf.h
new file mode 100644 (file)
index 0000000..43faf8c
--- /dev/null
@@ -0,0 +1,79 @@
+/*     $OpenBSD: autoconf.h,v 1.1.1.1 1997/02/06 16:02:42 pefo Exp $   */
+/*     $NetBSD: autoconf.h,v 1.1 1995/02/13 23:07:31 cgd Exp $ */
+
+/*
+ * Copyright (c) 1994, 1995 Carnegie-Mellon University.
+ * All rights reserved.
+ *
+ * Author: Chris G. Demetriou
+ * 
+ * Permission to use, copy, modify and distribute this software and
+ * its documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ * 
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" 
+ * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND 
+ * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ * 
+ * Carnegie Mellon requests users of this software to return to
+ *
+ *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
+ *  School of Computer Science
+ *  Carnegie Mellon University
+ *  Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie the
+ * rights to redistribute these changes.
+ */
+
+/*
+ * Machine-dependent structures of autoconfiguration
+ */
+
+#ifndef _ARC_AUTOCONF_H_
+#define _ARC_AUTOCONF_H_
+
+struct confargs;
+
+typedef int (*intr_handler_t) __P((void *));
+
+struct abus {
+       struct  device *ab_dv;          /* back-pointer to device */
+       int     ab_type;                /* bus type (see below) */
+       void    (*ab_intr_establish)    /* bus's set-handler function */
+                   __P((struct confargs *, intr_handler_t, void *));
+       void    (*ab_intr_disestablish) /* bus's unset-handler function */
+                   __P((struct confargs *));
+       caddr_t (*ab_cvtaddr)           /* convert slot/offset to address */
+                   __P((struct confargs *));
+       int     (*ab_matchname)         /* see if name matches driver */
+                   __P((struct confargs *, char *));
+};
+
+#define        BUS_MAIN        1               /* mainbus */
+#define        BUS_RISC        2               /* RISC Bus */
+#define        BUS_ISABR       3               /* ISA Bridge Bus */
+
+#define        BUS_INTR_ESTABLISH(ca, handler, val)                            \
+           (*(ca)->ca_bus->ab_intr_establish)((ca), (handler), (val))
+#define        BUS_INTR_DISESTABLISH(ca)                                       \
+           (*(ca)->ca_bus->ab_intr_establish)(ca)
+#define        BUS_CVTADDR(ca)                                                 \
+           (*(ca)->ca_bus->ab_cvtaddr)(ca)
+#define        BUS_MATCHNAME(ca, name)                                         \
+           (*(ca)->ca_bus->ab_matchname)((ca), (name))
+
+struct confargs {
+       char    *ca_name;               /* Device name. */
+       int     ca_slot;                /* Device slot. */
+       int     ca_offset;              /* Offset into slot. */
+       struct  abus *ca_bus;           /* bus device resides on. */
+};
+
+void   set_clockintr __P((void (*)(struct clockframe *)));
+void   set_iointr __P((void (*)(void *, int)));
+int    badaddr                 __P((void *, u_int64_t));
+
+#endif /* _ARC_AUTOCONF_H_ */
diff --git a/sys/arch/wgrisc/include/bus.h b/sys/arch/wgrisc/include/bus.h
new file mode 100644 (file)
index 0000000..b990c5e
--- /dev/null
@@ -0,0 +1,155 @@
+/*     $OpenBSD: bus.h,v 1.1.1.1 1997/02/06 16:02:44 pefo Exp $        */
+
+/*
+ * Copyright (c) 1996 Niklas Hallqvist.  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
+ *     for the NetBSD Project.
+ * 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 _ARC_BUS_H_
+#define _ARC_BUS_H_
+
+#ifdef __STDC__
+#define CAT(a,b)       a##b
+#define CAT3(a,b,c)    a##b##c
+#else
+#define CAT(a,b)       a/**/b
+#define CAT3(a,b,c)    a/**/b/**/c
+#endif
+
+/*
+ * Bus access types.
+ */
+typedef u_int32_t bus_addr_t;
+typedef u_int32_t bus_size_t;
+typedef u_int32_t bus_space_handle_t;
+typedef u_int32_t bus_space_tag_t;
+
+/*
+ * Access methods for bus resources
+ */
+#define bus_space_map(t, addr, size, cacheable, bshp) \
+    ((*(bshp) = (t) + (addr)), 0)
+#define bus_space_unmap(t, bsh, size)
+
+#define bus_space_read(n,m)                                                  \
+static __inline CAT3(u_int,m,_t)                                             \
+CAT(bus_space_read_,n)(bus_space_tag_t bst, bus_space_handle_t bsh,          \
+     bus_addr_t ba)                                                          \
+{                                                                            \
+       wbflush();                                                            \
+       wbflush();                                                            \
+       wbflush();                                                            \
+       return *(volatile CAT3(u_int,m,_t) *)(bsh + ba);                      \
+}
+
+bus_space_read(1,8)
+bus_space_read(2,16)
+bus_space_read(4,32)
+
+#define        bus_space_read_8        !!! bus_space_read_8 unimplemented !!!
+
+#define bus_space_read_multi(n, m)                                           \
+static __inline void                                                         \
+CAT(bus_space_read_multi_,n)(bus_space_tag_t bst, bus_space_handle_t bsh,     \
+    bus_addr_t ba, CAT3(u_int,m,_t) *buf, bus_size_t cnt)                    \
+{                                                                            \
+       while (cnt--)                                                         \
+               *buf++ = CAT(bus_space_read_,n)(bst, bsh, ba);                \
+}
+
+bus_space_read_multi(1,8)
+bus_space_read_multi(2,16)
+bus_space_read_multi(4,32)
+
+#define        bus_space_read_multi_8  !!! bus_space_read_multi_8 not implemented !!!
+
+#define bus_space_write(n,m)                                                 \
+static __inline void                                                         \
+CAT(bus_space_write_,n)(bus_space_tag_t bst, bus_space_handle_t bsh,         \
+     bus_addr_t ba, CAT3(u_int,m,_t) x)                                              \
+{                                                                            \
+       wbflush();                                                            \
+       *(volatile CAT3(u_int,m,_t) *)(bsh + ba) = x;                         \
+       wbflush();                                                            \
+       wbflush();                                                            \
+       wbflush();                                                            \
+}
+
+bus_space_write(1,8)
+bus_space_write(2,16)
+bus_space_write(4,32)
+
+#define        bus_space_write_8       !!! bus_space_write_8 unimplemented !!!
+
+#define bus_space_write_multi(n, m)                                          \
+static __inline void                                                         \
+CAT(bus_space_write_multi_,n)(bus_space_tag_t bst, bus_space_handle_t bsh,    \
+    bus_addr_t ba, const CAT3(u_int,m,_t) *buf, bus_size_t cnt)                      \
+{                                                                            \
+       while (cnt--)                                                         \
+               CAT(bus_space_write_,n)(bst, bsh, ba, *buf++);                \
+}
+
+bus_space_write_multi(1,8)
+bus_space_write_multi(2,16)
+bus_space_write_multi(4,32)
+
+#define        bus_space_write_multi_8 !!! bus_space_write_multi_8 not implemented !!!
+
+/* These are OpenBSD extensions to the general NetBSD bus interface.  */
+#define        bus_space_read_raw_multi(n,m,l)                                       \
+static __inline void                                                         \
+CAT(bus_space_read_raw_multi_,n)(bus_space_tag_t bst, bus_space_handle_t bsh, \
+    bus_addr_t ba, u_int8_t *buf, bus_size_t cnt)                            \
+{                                                                            \
+       CAT(bus_space_read_multi_,n)(bst, bsh, ba, (CAT3(u_int,m,_t) *)buf,   \
+           cnt >> l);                                                        \
+}
+
+bus_space_read_raw_multi(2,16,1)
+bus_space_read_raw_multi(4,32,2)
+
+#define        bus_space_read_raw_multi_8 \
+    !!! bus_space_read_raw_multi_8 not implemented !!!
+
+#define        bus_space_write_raw_multi(n,m,l)                                      \
+static __inline void                                                         \
+CAT(bus_space_write_raw_multi_,n)(bus_space_tag_t bst, bus_space_handle_t bsh,\
+    bus_addr_t ba, const u_int8_t *buf, bus_size_t cnt)                              \
+{                                                                            \
+       CAT(bus_space_write_multi_,n)(bst, bsh, ba,                           \
+           (const CAT3(u_int,m,_t) *)buf, cnt >> l);                         \
+}
+
+bus_space_write_raw_multi(2,16,1)
+bus_space_write_raw_multi(4,32,2)
+
+#define        bus_space_write_raw_multi_8 \
+    !!! bus_space_write_raw_multi_8 not implemented !!!
+
+#endif /* _ARC_BUS_H_ */
diff --git a/sys/arch/wgrisc/include/cdefs.h b/sys/arch/wgrisc/include/cdefs.h
new file mode 100644 (file)
index 0000000..bac7717
--- /dev/null
@@ -0,0 +1,39 @@
+/*     $OpenBSD: cdefs.h,v 1.1.1.1 1997/02/06 16:02:42 pefo Exp $      */
+/*     $NetBSD: cdefs.h,v 1.3 1995/05/03 06:04:54 mellon Exp $ */
+
+/*
+ * Copyright (c) 1995 Carnegie-Mellon University.
+ * All rights reserved.
+ *
+ * Author: Chris G. Demetriou
+ * 
+ * Permission to use, copy, modify and distribute this software and
+ * its documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ * 
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" 
+ * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND 
+ * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ * 
+ * Carnegie Mellon requests users of this software to return to
+ *
+ *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
+ *  School of Computer Science
+ *  Carnegie Mellon University
+ *  Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie the
+ * rights to redistribute these changes.
+ */
+
+#ifndef _MACHINE_CDEFS_H_
+#define        _MACHINE_CDEFS_H_
+
+#define        _C_LABEL(x)     _STRING(x)
+
+#define        __indr_references(sym,msg)      /* nothing */
+#define        __warn_references(sym,msg)      /* nothing */
+
+#endif /* !_MACHINE_CDEFS_H_ */
diff --git a/sys/arch/wgrisc/include/cpu.h b/sys/arch/wgrisc/include/cpu.h
new file mode 100644 (file)
index 0000000..6930cf2
--- /dev/null
@@ -0,0 +1,417 @@
+/*     $OpenBSD: cpu.h,v 1.1.1.1 1997/02/06 16:02:42 pefo Exp $        */
+
+/*-
+ * Copyright (c) 1992, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Ralph Campbell and Rick Macklem.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     Copyright (C) 1989 Digital Equipment Corporation.
+ *     Permission to use, copy, modify, and distribute this software and
+ *     its documentation for any purpose and without fee is hereby granted,
+ *     provided that the above copyright notice appears in all copies.
+ *     Digital Equipment Corporation makes no representations about the
+ *     suitability of this software for any purpose.  It is provided "as is"
+ *     without express or implied warranty.
+ *
+ *     from: @(#)cpu.h 8.4 (Berkeley) 1/4/94
+ */
+
+#ifndef _CPU_H_
+#define _CPU_H_
+
+#define KUSEG_ADDR             0x0
+#define CACHED_MEMORY_ADDR     0x80000000
+#define UNCACHED_MEMORY_ADDR   0xa0000000
+#define KSEG2_ADDR             0xc0000000
+#define MAX_MEM_ADDR           0xbe000000
+#define        RESERVED_ADDR           0xbfc80000
+
+#define        CACHED_TO_PHYS(x)       ((unsigned)(x) & 0x1fffffff)
+#define        PHYS_TO_CACHED(x)       ((unsigned)(x) | CACHED_MEMORY_ADDR)
+#define        UNCACHED_TO_PHYS(x)     ((unsigned)(x) & 0x1fffffff)
+#define        PHYS_TO_UNCACHED(x)     ((unsigned)(x) | UNCACHED_MEMORY_ADDR)
+#define VA_TO_CINDEX(x)        ((unsigned)(x) & 0xffffff | CACHED_MEMORY_ADDR)
+
+#ifdef _KERNEL
+/*
+ * The bits in the cause register. There are actually no diff here
+ * between the R3K and the R4K except from the width of the EXC field.
+ * However the bit 6 and bit 7 of the R3K cause register is always '0'
+ * so we do not make any distinguishing between them.
+ *
+ *
+ *     CR_BR_DELAY     Exception happened in branch delay slot.
+ *     CR_COP_ERR              Coprocessor error.
+ *     CR_IP           Interrupt pending bits defined below.
+ *     CR_EXC_CODE     The exception type (see exception codes below).
+ */
+#define CR_BR_DELAY            0x80000000
+#define CR_COP_ERR             0x30000000
+#define CR_EXC_CODE            0x0000007C
+#define CR_IP                  0x0000FF00
+#define CR_EXC_CODE_SHIFT      2
+
+/*
+ * The bits in the status register.  All bits are active when set to 1.
+ */
+#define SR_COP_USABILITY       0xf0000000      /* R3K - R4K */
+#define SR_COP_0_BIT           0x10000000      /* R3K - R4K */
+#define SR_COP_1_BIT           0x20000000      /* R3K - R4K */
+#define SR_RE                  0x02000000      /* R3K - R4K */
+#define SR_BOOT_EXC_VEC                0x00400000      /* R3K - R4K */
+#define SR_TLB_SHUTDOWN                0x00200000      /* R3K - R4K */
+#define SR_INT_MASK            0x0000ff00      /* R3K - R4K */
+#ifndef R4K
+#define SR_DIAG_CPE            0x00100000      /* R3K */
+#define SR_CACHE_MISS          0x00080000      /* R3K */
+#define SR_DIAG_PZ             0x00040000      /* R3K */
+#define SR_SWAP_CACHES         0x00020000      /* R3K */
+#define SR_ISOL_CACHES         0x00010000      /* R3K */
+#define        SR_KU_OLD               0x00000020      /* R3K */
+#define        SR_INT_ENA_OLD          0x00000010      /* R3K */
+#define        SR_KU_PREV              0x00000008      /* R3K */
+#define        SR_INT_ENA_PREV         0x00000004      /* R3K */
+#define        SR_KU_CUR               0x00000002      /* R3K */
+#else
+#define SR_RP                  0x08000000      /* R4K */
+#define SR_FR_32               0x04000000      /* R4K */
+#define SR_SOFT_RESET          0x00100000      /* R4K */
+#define SR_DIAG_CH             0x00040000      /* R4K */
+#define SR_DIAG_CE             0x00020000      /* R4K */
+#define SR_DIAG_PE             0x00010000      /* R4K */
+#define SR_KX                  0x00000080      /* R4K */
+#define SR_SX                  0x00000040      /* R4K */
+#define SR_UX                  0x00000020      /* R4K */
+#define SR_KSU_MASK            0x00000018      /* R4K */
+#define SR_KSU_USER            0x00000010      /* R4K */
+#define SR_KSU_SUPER           0x00000008      /* R4K */
+#define SR_KSU_KERNEL          0x00000000      /* R4K */
+#define SR_ERL                 0x00000004      /* R4K */
+#define SR_EXL                 0x00000002      /* R4K */
+#endif
+#define SR_INT_ENAB            0x00000001      /* R3K - R4K */
+
+/*
+ * The interrupt masks. These are the same for R3K and R4K.
+ * If a bit in the mask is 1 then the interrupt is enabled (or pending).
+ */
+#define INT_MASK               0xff00  /* Provide MAXIMUM enable set */
+#define HARD_INT_MASK          (0xfc00 & INT_MASK)
+#define INT_MASK_5             0x8000  /* Not used (R4K on chip timer) */
+#define INT_MASK_4             0x4000
+#define INT_MASK_3             0x2000
+#define INT_MASK_2             0x1000
+#define INT_MASK_1             0x0800
+#define INT_MASK_0             0x0400
+#define SOFT_INT_MASK_1                0x0200
+#define SOFT_INT_MASK_0                0x0100
+
+/*
+ * Location of exception vectors.
+ */
+#define R4K_RESET_EXC_VEC      0xBFC00000
+#define R4K_TLB_MISS_EXC_VEC   0x80000000
+#define R4K_XTLB_MISS_EXC_VEC  0x80000080
+#define R4K_CACHE_ERR_EXC_VEC  0x80000100
+#define R4K_GEN_EXC_VEC                0x80000180
+
+#define R3K_RESET_EXC_VEC      0xBFC00000
+#define R3K_TLB_MISS_EXC_VEC   0x80000000
+#define R3K_GEN_EXC_VEC                0x80000080
+
+/*
+ * Coprocessor 0 registers:
+ */
+#define COP_0_TLB_INDEX                $0
+#define COP_0_TLB_RANDOM       $1
+#define COP_0_TLB_LO0          $2
+#define COP_0_TLB_LO1          $3      /* R4K only */
+#define COP_0_R3K_CONF         $3      /* R3K only */
+#define COP_0_TLB_CONTEXT      $4
+#define COP_0_TLB_PG_MASK      $5
+#define COP_0_TLB_WIRED                $6
+#define COP_0_BAD_VADDR                $8
+#define COP_0_TLB_HI           $10
+#define COP_0_STATUS_REG       $12
+#define COP_0_CAUSE_REG                $13
+#define COP_0_EXC_PC           $14
+#define COP_0_PRID             $15
+#define COP_0_CONFIG           $16
+#define COP_0_LLADDR           $17
+#define COP_0_WATCH_LO         $18
+#define COP_0_WATCH_HI         $19
+#define COP_0_TLB_XCONTEXT     $20
+#define COP_0_ECC              $26
+#define COP_0_CACHE_ERR                $27
+#define COP_0_TAG_LO           $28
+#define COP_0_TAG_HI           $29
+#define COP_0_ERROR_PC         $30
+
+/*
+ * Values for the code field in a break instruction.
+ */
+#define BREAK_INSTR            0x0000000d
+#define BREAK_VAL_MASK         0x03ff0000
+#define BREAK_VAL_SHIFT                16
+#define BREAK_KDB_VAL          512
+#define BREAK_SSTEP_VAL                513
+#define BREAK_BRKPT_VAL                514
+#define BREAK_SOVER_VAL                515
+#define BREAK_KDB      (BREAK_INSTR | (BREAK_KDB_VAL << BREAK_VAL_SHIFT))
+#define BREAK_SSTEP    (BREAK_INSTR | (BREAK_SSTEP_VAL << BREAK_VAL_SHIFT))
+#define BREAK_BRKPT    (BREAK_INSTR | (BREAK_BRKPT_VAL << BREAK_VAL_SHIFT))
+#define BREAK_SOVER    (BREAK_INSTR | (BREAK_SOVER_VAL << BREAK_VAL_SHIFT))
+
+/*
+ * Mininum and maximum cache sizes.
+ */
+#define MIN_CACHE_SIZE         (4 * 1024)
+#define MAX_CACHE_SIZE         (256 * 1024)
+
+/*
+ * The floating point version and status registers.
+ */
+#define        FPC_ID                  $0
+#define        FPC_CSR                 $31
+
+/*
+ * The floating point coprocessor status register bits.
+ */
+#define FPC_ROUNDING_BITS              0x00000003
+#define FPC_ROUND_RN                   0x00000000
+#define FPC_ROUND_RZ                   0x00000001
+#define FPC_ROUND_RP                   0x00000002
+#define FPC_ROUND_RM                   0x00000003
+#define FPC_STICKY_BITS                        0x0000007c
+#define FPC_STICKY_INEXACT             0x00000004
+#define FPC_STICKY_UNDERFLOW           0x00000008
+#define FPC_STICKY_OVERFLOW            0x00000010
+#define FPC_STICKY_DIV0                        0x00000020
+#define FPC_STICKY_INVALID             0x00000040
+#define FPC_ENABLE_BITS                        0x00000f80
+#define FPC_ENABLE_INEXACT             0x00000080
+#define FPC_ENABLE_UNDERFLOW           0x00000100
+#define FPC_ENABLE_OVERFLOW            0x00000200
+#define FPC_ENABLE_DIV0                        0x00000400
+#define FPC_ENABLE_INVALID             0x00000800
+#define FPC_EXCEPTION_BITS             0x0003f000
+#define FPC_EXCEPTION_INEXACT          0x00001000
+#define FPC_EXCEPTION_UNDERFLOW                0x00002000
+#define FPC_EXCEPTION_OVERFLOW         0x00004000
+#define FPC_EXCEPTION_DIV0             0x00008000
+#define FPC_EXCEPTION_INVALID          0x00010000
+#define FPC_EXCEPTION_UNIMPL           0x00020000
+#define FPC_COND_BIT                   0x00800000
+#define FPC_FLUSH_BIT                  0x01000000
+#define FPC_MBZ_BITS                   0xfe7c0000
+
+/*
+ * Constants to determine if have a floating point instruction.
+ */
+#define OPCODE_SHIFT           26
+#define OPCODE_C1              0x11
+
+/*
+ * The number of TLB entries and the first one that write random hits.
+ */
+#define R3K_NUM_TLB_ENTRIES    64
+#define R4K_NUM_TLB_ENTRIES    48      /* Pairs, totals 96 */
+#define R3K_NUM_WIRED_ENTRIES  8
+#define R4K_NUM_WIRED_ENTRIES  8
+#define        R3K_PID_SHIFT           6
+#define        R3K_PID_MASK            0xfc00
+#define        R4K_PID_SHIFT           0
+#define        R4K_PID_MASK            0x00ff
+#define        R3K_TLB_INDEX_SHIFT     8
+#define        R4K_TLB_INDEX_SHIFT     0
+
+/*
+ * The number of process id entries.
+ */
+#define        R3K_NUM_PIDS                    32
+#define        R4K_NUM_PIDS                    256
+
+#endif /* _KERNEL */
+
+
+
+/*
+ * Exported definitions unique to mips cpu support.
+ */
+
+/*
+ * definitions of cpu-dependent requirements
+ * referenced in generic code
+ */
+#define        COPY_SIGCODE            /* copy sigcode above user stack in exec */
+
+#define        cpu_wait(p)             /* nothing */
+#define cpu_set_init_frame(p, fp) /* nothing */
+#define cpu_swapout(p)         panic("cpu_swapout: can't get here");
+
+#ifndef _LOCORE
+/*
+ * Arguments to hardclock and gatherstats encapsulate the previous
+ * machine state in an opaque clockframe.
+ */
+struct clockframe {
+       int     pc;     /* program counter at time of interrupt */
+       int     sr;     /* status register at time of interrupt */
+       int     cr;     /* cause register at time of interrupt */
+};
+
+#ifndef R4K
+#define        CLKF_USERMODE(fp)       ((fp)->sr & SR_KU_PREV)
+#define        CLKF_BASEPRI(fp)        ((~(fp)->sr & (INT_MASK|SR_INT_ENA_PREV)) == 0)
+#else
+#define        CLKF_USERMODE(fp)       ((fp)->sr & SR_KSU_USER)
+#define        CLKF_BASEPRI(fp)        ((~(fp)->sr & (INT_MASK|SR_INT_ENAB)) == 0)
+#endif
+#define        CLKF_PC(fp)             ((fp)->pc)
+#define        CLKF_INTR(fp)           (0)
+
+/*
+ * 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 = 1; aston(); }
+
+/*
+ * Give a profiling tick to the current process when the user profiling
+ * buffer pages are invalid.  On the PICA, 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 = 1)
+
+int    astpending;     /* need to trap before returning to user mode */
+int    want_resched;   /* resched() was called */
+
+/*
+ * CPU identification, from PRID register.
+ */
+union cpuprid {
+       int     cpuprid;
+       struct {
+#if BYTE_ORDER == BIG_ENDIAN
+               u_int   pad1:16;        /* reserved */
+               u_int   cp_imp:8;       /* implementation identifier */
+               u_int   cp_majrev:4;    /* major revision identifier */
+               u_int   cp_minrev:4;    /* minor revision identifier */
+#else
+               u_int   cp_minrev:4;    /* minor revision identifier */
+               u_int   cp_majrev:4;    /* major revision identifier */
+               u_int   cp_imp:8;       /* implementation identifier */
+               u_int   pad1:16;        /* reserved */
+#endif
+       } cpu;
+};
+
+/*
+ * 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 }, \
+}
+
+#endif /* !_LOCORE */
+
+/*
+ * MIPS CPU types (cp_imp).
+ */
+#define        MIPS_R2000      0x01    /* MIPS R2000 CPU               ISA I   */
+#define        MIPS_R3000      0x02    /* MIPS R3000 CPU               ISA I   */
+#define        MIPS_R6000      0x03    /* MIPS R6000 CPU               ISA II  */
+#define        MIPS_R4000      0x04    /* MIPS R4000/4400 CPU          ISA III */
+#define MIPS_R3LSI     0x05    /* LSI Logic R3000 derivate     ISA I   */
+#define        MIPS_R6000A     0x06    /* MIPS R6000A CPU              ISA II  */
+#define        MIPS_R3IDT      0x07    /* IDT R3000 derivate           ISA I   */
+#define        MIPS_R10000     0x09    /* MIPS R10000/T5 CPU           ISA IV  */
+#define        MIPS_R4200      0x0a    /* MIPS R4200 CPU (ICE)         ISA III */
+#define MIPS_UNKC1     0x0b    /* unnanounced product cpu      ISA III */
+#define MIPS_UNKC2     0x0c    /* unnanounced product cpu      ISA III */
+#define        MIPS_R8000      0x10    /* MIPS R8000 Blackbird/TFP     ISA IV  */
+#define        MIPS_R4600      0x20    /* QED R4600 Orion              ISA III */
+#define        MIPS_R3SONY     0x21    /* Sony R3000 based CPU         ISA I   */
+#define        MIPS_R3TOSH     0x22    /* Toshiba R3000 based CPU      ISA I   */
+#define        MIPS_R3NKK      0x23    /* NKK R3000 based CPU          ISA I   */
+
+/*
+ * MIPS FPU types
+ */
+#define        MIPS_SOFT       0x00    /* Software emulation           ISA I   */
+#define        MIPS_R2360      0x01    /* MIPS R2360 FPC               ISA I   */
+#define        MIPS_R2010      0x02    /* MIPS R2010 FPC               ISA I   */
+#define        MIPS_R3010      0x03    /* MIPS R3010 FPC               ISA I   */
+#define        MIPS_R6010      0x04    /* MIPS R6010 FPC               ISA II  */
+#define        MIPS_R4010      0x05    /* MIPS R4000/R4400 FPC         ISA II  */
+#define MIPS_R31LSI    0x06    /* LSI Logic derivate           ISA I   */
+#define        MIPS_R10010     0x09    /* MIPS R10000/T5 FPU           ISA IV  */
+#define        MIPS_R4210      0x0a    /* MIPS R4200 FPC (ICE)         ISA III */
+#define MIPS_UNKF1     0x0b    /* unnanounced product cpu      ISA III */
+#define        MIPS_R8000      0x10    /* MIPS R8000 Blackbird/TFP     ISA IV  */
+#define        MIPS_R4600      0x20    /* QED R4600 Orion              ISA III */
+#define        MIPS_R3SONY     0x21    /* Sony R3000 based FPU         ISA I   */
+#define        MIPS_R3TOSH     0x22    /* Toshiba R3000 based FPU      ISA I   */
+#define        MIPS_R3NKK      0x23    /* NKK R3000 based FPU          ISA I   */
+
+#if defined(_KERNEL) && !defined(_LOCORE)
+union  cpuprid cpu_id;
+union  cpuprid fpu_id;
+u_int  CpuPrimaryDataCacheSize;
+u_int  CpuPrimaryInstCacheSize;
+u_int  CpuPrimaryDataCacheLSize;
+u_int  CpuPrimaryInstCacheLSize;
+u_int  CpuCacheAliasMask;
+u_int  CpuTwoWayCache;
+
+extern struct intr_tab intr_tab[];
+#endif
+
+/*
+ * Enable realtime clock (always enabled).
+ */
+#define        enablertclock()
+
+#endif /* _CPU_H_ */
diff --git a/sys/arch/wgrisc/include/disklabel.h b/sys/arch/wgrisc/include/disklabel.h
new file mode 100644 (file)
index 0000000..ad461e6
--- /dev/null
@@ -0,0 +1,88 @@
+/*     $OpenBSD: disklabel.h,v 1.1.1.1 1997/02/06 16:02:42 pefo Exp $  */
+/*     $NetBSD: disklabel.h,v 1.2 1995/01/18 06:37:55 mellon 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     1                       /* sector containing label */
+#define        LABELOFFSET     0                       /* offset of label in sector */
+#define        MAXPARTITIONS   16                      /* number of partitions */
+#define        PARTITIONSHIFT  4                       /* log2 */
+#define        PARTITIONMASK   0xf                     
+#define        RAW_PART        2                       /* raw partition: xx?c */
+
+/* DOS partition table -- used when the system is booted from a dos
+ * partition. This is the case on NT systems.
+ */
+#define        DOSBBSECTOR     0               /* DOS boot block relative sector # */
+#define        DOSPARTOFF      446
+#define        NDOSPART        4
+
+struct dos_partition {
+       unsigned char   dp_flag;        /* bootstrap flags */
+       unsigned char   dp_shd;         /* starting head */
+       unsigned char   dp_ssect;       /* starting sector */
+       unsigned char   dp_scyl;        /* starting cylinder */
+       unsigned char   dp_typ;         /* partition type (see below) */
+       unsigned char   dp_ehd;         /* end head */
+       unsigned char   dp_esect;       /* end sector */
+       unsigned char   dp_ecyl;        /* end cylinder */
+       unsigned long   dp_start;       /* absolute starting sector number */
+       unsigned long   dp_size;        /* partition size in sectors */
+} dos_partitions[NDOSPART];
+
+/* Known DOS partition types. */
+#define DOSPTYP_386BSD 0xa5            /* 386BSD partition type */
+#define DOSPTYP_NETBSD DOSPTYP_386BSD  /* NetBSD partition type (XXX) */
+#define DOSPTYP_OPENBSD        0xa6            /* OpenBSD partition type */
+#define DOSPTYP_FAT12   0x1
+#define DOSPTYP_FAT16S  0x4
+#define DOSPTYP_FAT16B  0x6
+#define DOSPTYP_FAT16C  0xe
+
+#include <sys/dkbad.h>
+struct cpu_disklabel {
+       struct dos_partition dosparts[NDOSPART];
+       struct dkbad bad;
+};
+
+/* Isolate the relevant bits to get sector and cylinder. */
+#define        DPSECT(s)       ((s) & 0x3f)
+#define        DPCYL(c, s)     ((c) + (((s) & 0xc0) << 2))
+
+#ifdef _KERNEL
+struct disklabel;
+int    bounds_check_with_label __P((struct buf *, struct disklabel *, int));
+#endif
+
+#endif /* _MACHINE_DISKLABEL_H_ */
diff --git a/sys/arch/wgrisc/include/dlfcn.h b/sys/arch/wgrisc/include/dlfcn.h
new file mode 100644 (file)
index 0000000..309c712
--- /dev/null
@@ -0,0 +1,42 @@
+/*     $OpenBSD: dlfcn.h,v 1.1.1.1 1997/02/06 16:02:44 pefo Exp $ */
+
+/*
+ * Copyright (c) 1996 Per Fogelstrom
+ * 
+ * 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 under OpenBSD by
+ *     Per Fogelstrom.
+ * 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 _DLFCN_H
+#define _DLFCN_H 1
+/*
+ *     This is a dummy file. Empty until libdl has been done.
+ */
+
+#endif /* _DLFCN_H */
diff --git a/sys/arch/wgrisc/include/ecoff.h b/sys/arch/wgrisc/include/ecoff.h
new file mode 100644 (file)
index 0000000..d2dc03f
--- /dev/null
@@ -0,0 +1,94 @@
+/*     $OpenBSD: ecoff.h,v 1.1.1.1 1997/02/06 16:02:42 pefo Exp $      */
+/*     $NetBSD: ecoff.h,v 1.4 1995/06/16 02:07:33 mellon Exp $ */
+
+/*
+ * Copyright (c) 1994 Adam Glass
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. 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 Adam Glass BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#define ECOFF_LDPGSZ 4096
+
+#define ECOFF_PAD
+
+#define ECOFF_MACHDEP \
+        u_long ea_gprmask; \
+        u_long ea_cprmask[4]; \
+        u_long ea_gp_value
+
+#define ECOFF_MAGIC_MIPSEL 0x0162
+#define ECOFF_BADMAG(ex) ((ex)->f.f_magic != ECOFF_MAGIC_MIPSEL)
+
+#define ECOFF_SEGMENT_ALIGNMENT(ep) ((ep)->a.vstamp < 23 ? 8 : 16)
+
+struct ecoff_symhdr {
+        int16_t         sh_magic;
+        int16_t         sh_vstamp;
+        int32_t         sh_linemax;
+        int32_t         sh_densenummax;
+        int32_t         sh_procmax;
+        int32_t         sh_lsymmax;
+        int32_t         sh_optsymmax;
+        int32_t         sh_auxxymmax;
+        int32_t         sh_lstrmax;
+        int32_t         sh_estrmax;
+        int32_t         sh_fdmax;
+        int32_t         sh_rfdmax;
+        int32_t         sh_esymmax;
+        long            sh_linesize;
+        long            sh_lineoff;
+        long            sh_densenumoff;
+        long            sh_procoff; 
+        long            sh_lsymoff;
+        long            sh_optsymoff;
+        long            sh_auxsymoff;
+        long            sh_lstroff;
+        long            sh_estroff;
+        long            sh_fdoff;
+        long            sh_rfdoff;
+        long            sh_esymoff;
+};
+/* Some day they will make up their minds.... */
+#define        esymMax         sh_esymmax
+#define cbExtOffset    sh_esymoff
+#define        cbSsExtOffset   sh_estroff
+
+struct ecoff_extsym {  
+        long            es_value;
+        int             es_strindex;
+        unsigned        es_type:6;
+        unsigned        es_class:5;
+        unsigned        :1;
+        unsigned        es_symauxindex:20;  
+        unsigned        es_jmptbl:1;
+        unsigned        es_cmain:1;
+        unsigned        es_weakext:1;
+        unsigned        :29;
+        int             es_indexfld; 
+};
+
diff --git a/sys/arch/wgrisc/include/elf_abi.h b/sys/arch/wgrisc/include/elf_abi.h
new file mode 100644 (file)
index 0000000..8f864f2
--- /dev/null
@@ -0,0 +1,57 @@
+/*     $OpenBSD: elf_abi.h,v 1.1.1.1 1997/02/06 16:02:44 pefo Exp $ */
+
+/*
+ * Copyright (c) 1996 Per Fogelstrom
+ * 
+ * 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 under OpenBSD by
+ *     Per Fogelstrom.
+ * 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.
+ *
+ */
+
+/* From MIPS ABI supplemental */
+
+/* Architecture dependent Segment types - p_type */ 
+#define PT_MIPS_REGINFO 0x70000000      /* Register usage information */
+
+/* Architecture dependent d_tag field for Elf32_Dyn.  */
+#define DT_MIPS_RLD_VERSION  0x70000001 /* Runtime Linker Interface ID */
+#define DT_MIPS_TIME_STAMP   0x70000002 /* Timestamp */
+#define DT_MIPS_ICHECKSUM    0x70000003 /* Cksum of ext. str. and com. sizes */
+#define DT_MIPS_IVERSION     0x70000004 /* Version string (string tbl index) */
+#define DT_MIPS_FLAGS        0x70000005 /* Flags */
+#define DT_MIPS_BASE_ADDRESS 0x70000006 /* Segment base address */
+#define DT_MIPS_CONFLICT     0x70000008 /* Adr of .conflict section */
+#define DT_MIPS_LIBLIST      0x70000009 /* Address of .liblist section */
+#define DT_MIPS_LOCAL_GOTNO  0x7000000a /* Number of local .GOT entries */
+#define DT_MIPS_CONFLICTNO   0x7000000b /* Number of .conflict entries */
+#define DT_MIPS_LIBLISTNO    0x70000010 /* Number of .liblist entries */
+#define DT_MIPS_SYMTABNO     0x70000011 /* Number of .dynsym entries */
+#define DT_MIPS_UNREFEXTNO   0x70000012 /* First external DYNSYM */
+#define DT_MIPS_GOTSYM       0x70000013 /* First GOT entry in .dynsym */
+#define DT_MIPS_HIPAGENO     0x70000014 /* Number of GOT page table entries */
+#define DT_MIPS_RLD_MAP      0x70000016 /* Address of debug map pointer */
+
diff --git a/sys/arch/wgrisc/include/endian.h b/sys/arch/wgrisc/include/endian.h
new file mode 100644 (file)
index 0000000..14f00a9
--- /dev/null
@@ -0,0 +1,95 @@
+/*     $OpenBSD: endian.h,v 1.1.1.1 1997/02/06 16:02:43 pefo Exp $     */
+/*     $NetBSD: endian.h,v 1.4 1994/10/26 21:09:38 cgd Exp $   */
+
+/*
+ * Copyright (c) 1987, 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.
+ *
+ *     @(#)endian.h    8.1 (Berkeley) 6/11/93
+ */
+
+#ifndef _ENDIAN_H_
+#define        _ENDIAN_H_
+
+/*
+ * Define _NOQUAD if the compiler does NOT support 64-bit integers.
+ */
+/* #define _NOQUAD */
+
+/*
+ * Define the order of 32-bit words in 64-bit words.
+ */
+#define _QUAD_HIGHWORD 1
+#define _QUAD_LOWWORD 0
+
+#ifndef _POSIX_SOURCE
+/*
+ * Definitions for byte order, according to byte significance from low
+ * address to high.
+ */
+#define        LITTLE_ENDIAN   1234    /* LSB first: i386, vax */
+#define        BIG_ENDIAN      4321    /* MSB first: 68000, ibm, net */
+#define        PDP_ENDIAN      3412    /* LSB first in word, MSW first in long */
+
+#define        BYTE_ORDER      LITTLE_ENDIAN   /* ``... Beautiful SPIIIIM!'' */
+
+#include <sys/cdefs.h>
+
+__BEGIN_DECLS
+unsigned long  htonl __P((unsigned long));
+unsigned short htons __P((unsigned short));
+unsigned long  ntohl __P((unsigned long));
+unsigned short ntohs __P((unsigned short));
+__END_DECLS
+
+/*
+ * Macros for network/external number representation conversion.
+ */
+#if BYTE_ORDER == BIG_ENDIAN && !defined(lint)
+#define        ntohl(x)        (x)
+#define        ntohs(x)        (x)
+#define        htonl(x)        (x)
+#define        htons(x)        (x)
+
+#define        NTOHL(x)        (x)
+#define        NTOHS(x)        (x)
+#define        HTONL(x)        (x)
+#define        HTONS(x)        (x)
+
+#else
+
+#define        NTOHL(x)        (x) = ntohl((u_long)x)
+#define        NTOHS(x)        (x) = ntohs((u_short)x)
+#define        HTONL(x)        (x) = htonl((u_long)x)
+#define        HTONS(x)        (x) = htons((u_short)x)
+#endif
+#endif /* ! _POSIX_SOURCE */
+#endif /* !_ENDIAN_H_ */
diff --git a/sys/arch/wgrisc/include/exec.h b/sys/arch/wgrisc/include/exec.h
new file mode 100644 (file)
index 0000000..e6e30ee
--- /dev/null
@@ -0,0 +1,62 @@
+/*     $OpenBSD: exec.h,v 1.1.1.1 1997/02/06 16:02:43 pefo Exp $       */
+/*     $NetBSD: exec.h,v 1.5 1994/10/26 21:09:39 cgd Exp $     */
+
+/*-
+ * Copyright (c) 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.
+ *
+ *     @(#)exec.h      8.1 (Berkeley) 6/10/93
+ */
+
+#define        __LDPGSZ        4096
+
+/*
+ *  Define what exec "formats" we should handle.
+ */
+#define NATIVE_EXEC_ELF
+#define        EXEC_SCRIPT
+
+#define ELF_TARG_CLASS         ELFCLASS32
+#define ELF_TARG_DATA          ELFDATA2LSB
+#define ELF_TARG_MACH          EM_MIPS
+
+/*
+ *  This is what we want nlist(3) to handle.
+ */
+#define _NLIST_DO_AOUT                 /* support a.out */
+#define _NLIST_DO_ELF                  /* support ELF */
+#define _NLIST_DO_ECOFF                        /* support ECOFF */
+
+/*
+ *  This is what we want the kernel to handle.
+ */
+#define        _KERN_DO_ELF
+
diff --git a/sys/arch/wgrisc/include/float.h b/sys/arch/wgrisc/include/float.h
new file mode 100644 (file)
index 0000000..534e97f
--- /dev/null
@@ -0,0 +1,81 @@
+/*     $OpenBSD: float.h,v 1.1.1.1 1997/02/06 16:02:43 pefo Exp $      */
+/*     $NetBSD: float.h,v 1.7 1995/06/20 20:45:50 jtc Exp $    */
+
+/*
+ * Copyright (c) 1989, 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.
+ *
+ *     @(#)float.h     8.1 (Berkeley) 6/10/93
+ */
+
+#ifndef _MIPS_FLOAT_H_
+#define _MIPS_FLOAT_H_
+
+#include <sys/cdefs.h>
+
+__BEGIN_DECLS
+extern int __flt_rounds();
+__END_DECLS
+
+#define FLT_RADIX      2               /* b */
+#define FLT_ROUNDS     __flt_rounds()
+
+#define FLT_MANT_DIG   24              /* p */
+#define FLT_EPSILON    1.19209290E-07F /* b**(1-p) */
+#define FLT_DIG                6               /* floor((p-1)*log10(b))+(b == 10) */
+#define FLT_MIN_EXP    -125            /* emin */
+#define FLT_MIN                1.17549435E-38F /* b**(emin-1) */
+#define FLT_MIN_10_EXP -37             /* ceil(log10(b**(emin-1))) */
+#define FLT_MAX_EXP    128             /* emax */
+#define FLT_MAX                3.40282347E+38F /* (1-b**(-p))*b**emax */
+#define FLT_MAX_10_EXP 38              /* floor(log10((1-b**(-p))*b**emax)) */
+
+#define DBL_MANT_DIG   53
+#define DBL_EPSILON    2.2204460492503131E-16
+#define DBL_DIG                15
+#define DBL_MIN_EXP    -1021
+#define DBL_MIN                2.225073858507201E-308
+#define DBL_MIN_10_EXP -307
+#define DBL_MAX_EXP    1024
+#define DBL_MAX                1.797693134862316E+308
+#define DBL_MAX_10_EXP 308
+
+#define LDBL_MANT_DIG  DBL_MANT_DIG
+#define LDBL_EPSILON   DBL_EPSILON
+#define LDBL_DIG       DBL_DIG
+#define LDBL_MIN_EXP   DBL_MIN_EXP
+#define LDBL_MIN       DBL_MIN
+#define LDBL_MIN_10_EXP        DBL_MIN_10_EXP
+#define LDBL_MAX_EXP   DBL_MAX_EXP
+#define LDBL_MAX       DBL_MAX
+#define LDBL_MAX_10_EXP        DBL_MAX_10_EXP
+
+#endif /* _MIPS_FLOAT_H_ */
diff --git a/sys/arch/wgrisc/include/ieeefp.h b/sys/arch/wgrisc/include/ieeefp.h
new file mode 100644 (file)
index 0000000..bf46440
--- /dev/null
@@ -0,0 +1,25 @@
+/*     $OpenBSD: ieeefp.h,v 1.1.1.1 1997/02/06 16:02:43 pefo Exp $     */
+
+/* 
+ * Written by J.T. Conklin, Apr 11, 1995
+ * Public domain.
+ */
+
+#ifndef _MIPS_IEEEFP_H_
+#define _MIPS_IEEEFP_H_
+
+typedef int fp_except;
+#define FP_X_IMP       0x01    /* imprecise (loss of precision) */
+#define FP_X_UFL       0x02    /* underflow exception */
+#define FP_X_OFL       0x04    /* overflow exception */
+#define FP_X_DZ                0x08    /* divide-by-zero exception */
+#define FP_X_INV       0x10    /* invalid operation exception */
+
+typedef enum {
+    FP_RN=0,                   /* round to nearest representable number */
+    FP_RZ=1,                   /* round to zero (truncate) */
+    FP_RP=2,                   /* round toward positive infinity */
+    FP_RM=3                    /* round toward negative infinity */
+} fp_rnd;
+
+#endif /* _MIPS_IEEEFP_H_ */
diff --git a/sys/arch/wgrisc/include/intr.h b/sys/arch/wgrisc/include/intr.h
new file mode 100644 (file)
index 0000000..67e7ad7
--- /dev/null
@@ -0,0 +1,164 @@
+/*     $NetBSD: intr.h,v 1.5 1996/05/13 06:11:28 mycroft Exp $ */
+
+/*
+ * Copyright (c) 1996 Charles M. Hannum.  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 M. Hannum.
+ * 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 _ARC_INTR_H_
+#define _ARC_INTR_H_
+
+/* Interrupt priority `levels'; not mutually exclusive. */
+#define        IPL_BIO         0       /* block I/O */
+#define        IPL_NET         1       /* network */
+#define        IPL_TTY         2       /* terminal */
+#define        IPL_CLOCK       3       /* clock */
+#define        IPL_IMP         4       /* memory allocation */
+#define        IPL_NONE        5       /* nothing */
+#define        IPL_HIGH        6       /* everything */
+
+/* Interrupt sharing types. */
+#define        IST_NONE        0       /* none */
+#define        IST_PULSE       1       /* pulsed */
+#define        IST_EDGE        2       /* edge-triggered */
+#define        IST_LEVEL       3       /* level-triggered */
+
+/* Soft interrupt masks. */
+#define        SIR_CLOCK       31
+#define        SIR_CLOCKMASK   ((1 << SIR_CLOCK))
+#define        SIR_NET         30
+#define        SIR_NETMASK     ((1 << SIR_NET) | SIR_CLOCKMASK)
+#define        SIR_TTY         29
+#define        SIR_TTYMASK     ((1 << SIR_TTY) | SIR_CLOCKMASK)
+#define        SIR_ALLMASK     (SIR_CLOCKMASK | SIR_NETMASK | SIR_TTYMASK)
+
+#ifndef _LOCORE
+
+volatile int cpl, ipending, astpending;
+int imask[7];
+
+#if 0
+extern void Xspllower __P((void));
+
+static __inline int splraise __P((int));
+static __inline int spllower __P((int));
+static __inline void splx __P((int));
+static __inline void softintr __P((int));
+
+/*
+ * Add a mask to cpl, and return the old value of cpl.
+ */
+static __inline int
+splraise(ncpl)
+       register int ncpl;
+{
+       register int ocpl = cpl;
+
+       cpl = ocpl | ncpl;
+       return (ocpl);
+}
+
+/*
+ * Restore a value to cpl (unmasking interrupts).  If any unmasked
+ * interrupts are pending, call Xspllower() to process them.
+ */
+static __inline void
+splx(ncpl)
+       register int ncpl;
+{
+
+       cpl = ncpl;
+       if (ipending & ~ncpl)
+               Xspllower();
+}
+
+/*
+ * Same as splx(), but we return the old value of spl, for the
+ * benefit of some splsoftclock() callers.
+ */
+static __inline int
+spllower(ncpl)
+       register int ncpl;
+{
+       register int ocpl = cpl;
+
+       cpl = ncpl;
+       if (ipending & ~ncpl)
+               Xspllower();
+       return (ocpl);
+}
+#endif
+
+/*
+ * Hardware interrupt masks
+ */
+#if 0
+#define        splbio()        splraise(imask[IPL_BIO])
+#define        splnet()        splraise(imask[IPL_NET])
+#define        spltty()        splraise(imask[IPL_TTY])
+#define        splclock()      splraise(imask[IPL_CLOCK])
+#define        splimp()        splraise(imask[IPL_IMP])
+#define        splstatclock()  splclock()
+
+/*
+ * Software interrupt masks
+ *
+ * NOTE: splsoftclock() is used by hardclock() to lower the priority from
+ * clock to softclock before it calls softclock().
+ */
+#define        splsoftclock()  spllower(SIR_CLOCKMASK)
+#define        splsoftnet()    splraise(SIR_NETMASK)
+#define        splsofttty()    splraise(SIR_TTYMASK)
+
+/*
+ * Miscellaneous
+ */
+#define        splhigh()       splraise(-1)
+#define        spl0()          spllower(0)
+
+#endif
+/*
+ * Software interrupt registration
+ *
+ * We hand-code this to ensure that it's atomic.
+ */
+static __inline void
+softintr(mask)
+       register int mask;
+{
+
+       __asm __volatile("orl %0,_ipending" : : "ir" (mask));
+}
+
+#define        setsoftast()    (astpending = 1)
+#define        setsoftclock()  softintr(1 << SIR_CLOCK)
+#define        setsoftnet()    softintr(1 << SIR_NET)
+#define        setsofttty()    softintr(1 << SIR_TTY)
+
+#endif /* _LOCORE */
+
+#endif /* _ARC_INTR_H_ */
diff --git a/sys/arch/wgrisc/include/kbdreg.h b/sys/arch/wgrisc/include/kbdreg.h
new file mode 100644 (file)
index 0000000..0e24cf8
--- /dev/null
@@ -0,0 +1,82 @@
+/*     $OpenBSD: kbdreg.h,v 1.1.1.1 1997/02/06 16:02:43 pefo Exp $     */
+
+/*
+ * Copyright (c) 1996 Per Fogelstrom
+ * 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 Per Fogelstrom.
+ * 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.
+ */
+/*
+ * Keyboard definitions
+ *
+ */
+
+#define        KBSTATP         (0x61)  /* controller status port (I) */
+#define         KBS_DIB        0x01    /* data in buffer */
+#define         KBS_IBF        0x02    /* input buffer low */
+#define         KBS_WARM       0x04    /* input buffer low */
+#define         KBS_OCMD       0x08    /* output buffer has command */
+#define         KBS_NOSEC      0x10    /* security lock not engaged */
+#define         KBS_TERR       0x20    /* transmission error */
+#define         KBS_RERR       0x40    /* receive error */
+#define         KBS_PERR       0x80    /* parity error */
+
+#define        KBCMDP          (0x61)  /* controller port (O) */
+#define        KBDATAP         (0x60)  /* data port (I) */
+#define        KBOUTP          (0x60)  /* data port (O) */
+
+#define        K_RDCMDBYTE     0x20
+#define        K_LDCMDBYTE     0x60
+
+#define        KC8_TRANS       0x40    /* convert to old scan codes */
+#define        KC8_MDISABLE    0x20    /* disable mouse */
+#define        KC8_KDISABLE    0x10    /* disable keyboard */
+#define        KC8_IGNSEC      0x08    /* ignore security lock */
+#define        KC8_CPU         0x04    /* exit from protected mode reset */
+#define        KC8_MENABLE     0x02    /* enable mouse interrupt */
+#define        KC8_KENABLE     0x01    /* enable keyboard interrupt */
+#define        CMDBYTE         (KC8_TRANS|KC8_CPU|KC8_MENABLE|KC8_KENABLE)
+
+/* keyboard commands */
+#define        KBC_RESET       0xFF    /* reset the keyboard */
+#define        KBC_RESEND      0xFE    /* request the keyboard resend the last byte */
+#define        KBC_SETDEFAULT  0xF6    /* resets keyboard to its power-on defaults */
+#define        KBC_DISABLE     0xF5    /* as per KBC_SETDEFAULT, but also disable key scanning */
+#define        KBC_ENABLE      0xF4    /* enable key scanning */
+#define        KBC_TYPEMATIC   0xF3    /* set typematic rate and delay */
+#define        KBC_SETTABLE    0xF0    /* set scancode translation table */
+#define        KBC_MODEIND     0xED    /* set mode indicators (i.e. LEDs) */
+#define        KBC_ECHO        0xEE    /* request an echo from the keyboard */
+
+/* keyboard responses */
+#define        KBR_EXTENDED    0xE0    /* extended key sequence */
+#define        KBR_RESEND      0xFE    /* needs resend of command */
+#define        KBR_ACK         0xFA    /* received a valid command */
+#define        KBR_OVERRUN     0x00    /* flooded */
+#define        KBR_FAILURE     0xFD    /* diagnosic failure */
+#define        KBR_BREAK       0xF0    /* break code prefix - sent on key release */
+#define        KBR_RSTDONE     0xAA    /* reset complete */
+#define        KBR_ECHO        0xEE    /* echo response */
diff --git a/sys/arch/wgrisc/include/kcore.h b/sys/arch/wgrisc/include/kcore.h
new file mode 100644 (file)
index 0000000..e9e9106
--- /dev/null
@@ -0,0 +1,45 @@
+/*     $OpenBSD: kcore.h,v 1.1.1.1 1997/02/06 16:02:44 pefo Exp $      */
+/*     $NetBSD: kcore.h,v 1.1 1996/03/10 21:55:18 leo Exp $    */
+
+/*
+ * Copyright (c) 1996 Leo Weppelman.
+ * 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 Leo Weppelman.
+ * 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 _MIPS_KCORE_H_
+#define        _MIPS_KCORE_H_
+
+#define        NPHYS_RAM_SEGS  8
+
+typedef struct cpu_kcore_hdr {
+       vm_offset_t     kernel_pa;      /* Phys. address of kernel VA 0 */
+       int             mmutype;
+       phys_ram_seg_t  ram_segs[NPHYS_RAM_SEGS];
+} cpu_kcore_hdr_t;
+
+#endif /* _MIPS_KCORE_H_ */
diff --git a/sys/arch/wgrisc/include/kdbparam.h b/sys/arch/wgrisc/include/kdbparam.h
new file mode 100644 (file)
index 0000000..3bc3a5c
--- /dev/null
@@ -0,0 +1,75 @@
+/*     $OpenBSD: kdbparam.h,v 1.1.1.1 1997/02/06 16:02:43 pefo Exp $   */
+/*     $NetBSD: kdbparam.h,v 1.4 1994/10/26 21:09:42 cgd Exp $ */
+
+/*-
+ * Copyright (c) 1992, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Ralph Campbell.
+ *
+ * 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.
+ *
+ *     @(#)kdbparam.h  8.1 (Berkeley) 6/10/93
+ */
+
+/*
+ * Machine dependent definitions for kdb.
+ */
+
+#if BYTE_ORDER == LITTLE_ENDIAN
+#define kdbshorten(w)  ((w) & 0xFFFF)
+#define        kdbbyte(w)      ((w) & 0xFF)
+#define        kdbitol(a,b)    ((long)(((b) << 16) | ((a) & 0xFFFF)))
+#define        kdbbtol(a)      ((long)(a))
+#endif
+
+#define LPRMODE                "%R"
+#define OFFMODE                "+%R"
+
+#define        SETBP(ins)      BREAK_BRKPT
+
+/* return the program counter value modified if we are in a delay slot */
+#define        kdbgetpc(pcb)           (kdbvar[kdbvarchk('t')] < 0 ? \
+       (pcb).pcb_regs[34] + 4 : (pcb).pcb_regs[34])
+#define        kdbishiddenreg(p)       ((p) >= &kdbreglist[33])
+#define        kdbisbreak(type)        (((type) & CR_EXC_CODE) == 0x24)
+
+/* check for address wrap around */
+#define        kdbaddrwrap(addr,newaddr)       (((addr)^(newaddr)) >> 31)
+
+/* declare machine dependent routines defined in kadb.c */
+void   kdbprinttrap __P((unsigned, unsigned));
+void   kdbsetsstep __P((void));
+void   kdbclrsstep __P((void));
+void   kdbreadc __P((char *));
+void   kdbwrite __P((char *, int));
+void   kdbprintins __P((int, long));
+void   kdbstacktrace __P((int));
+char   *kdbmalloc __P((int));
diff --git a/sys/arch/wgrisc/include/limits.h b/sys/arch/wgrisc/include/limits.h
new file mode 100644 (file)
index 0000000..39f2407
--- /dev/null
@@ -0,0 +1,101 @@
+/*     $OpenBSD: limits.h,v 1.1.1.1 1997/02/06 16:02:43 pefo Exp $     */
+/*     $NetBSD: limits.h,v 1.8 1995/03/28 18:19:16 jtc Exp $   */
+
+/*
+ * Copyright (c) 1988, 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.
+ *
+ *     @(#)limits.h    8.3 (Berkeley) 1/4/94
+ */
+
+#define        CHAR_BIT        8               /* number of bits in a char */
+#define        MB_LEN_MAX      6               /* Allow 31 bit UTF2 */
+
+#ifdef _KERNEL
+#define        CLK_TCK         100             /* ticks per second */
+#endif
+
+/*
+ * According to ANSI (section 2.2.4.2), the values below must be usable by
+ * #if preprocessing directives.  Additionally, the expression must have the
+ * same type as would an expression that is an object of the corresponding
+ * type converted according to the integral promotions.  The subtraction for
+ * INT_MIN and LONG_MIN is so the value is not unsigned; 2147483648 is an
+ * unsigned int for 32-bit two's complement ANSI compilers (section 3.1.3.2).
+ * These numbers work for pcc as well.  The UINT_MAX and ULONG_MAX values
+ * are written as hex so that GCC will be quiet about large integer constants.
+ */
+#define        SCHAR_MAX       127             /* min value for a signed char */
+#define        SCHAR_MIN       (-128)          /* max value for a signed char */
+
+#define        UCHAR_MAX       255             /* max value for an unsigned char */
+#define        CHAR_MAX        127             /* max value for a char */
+#define        CHAR_MIN        (-128)          /* min value for a char */
+
+#define        USHRT_MAX       65535           /* max value for an unsigned short */
+#define        SHRT_MAX        32767           /* max value for a short */
+#define        SHRT_MIN        (-32768)        /* min value for a short */
+
+#define        UINT_MAX        0xffffffff      /* max value for an unsigned int */
+#define        INT_MAX         2147483647      /* max value for an int */
+#define        INT_MIN         (-2147483647-1) /* min value for an int */
+
+#define        ULONG_MAX       0xffffffff      /* max value for an unsigned long */
+#define        LONG_MAX        2147483647      /* max value for a long */
+#define        LONG_MIN        (-2147483647-1) /* min value for a long */
+
+#if !defined(_ANSI_SOURCE)
+#define        SSIZE_MAX       INT_MAX         /* max value for a ssize_t */
+
+#if !defined(_POSIX_SOURCE) && !defined(_XOPEN_SOURCE)
+#define        SIZE_T_MAX      UINT_MAX        /* max value for a size_t */
+
+/* GCC requires that quad constants be written as expressions. */
+#define        UQUAD_MAX       ((u_quad_t)0-1) /* max value for a uquad_t */
+                                       /* max value for a quad_t */
+#define        QUAD_MAX        ((quad_t)(UQUAD_MAX >> 1))
+#define        QUAD_MIN        (-QUAD_MAX-1)   /* min value for a quad_t */
+
+#endif /* !_POSIX_SOURCE && !_XOPEN_SOURCE */
+#endif /* !_ANSI_SOURCE */
+
+#if (!defined(_ANSI_SOURCE)&&!defined(_POSIX_SOURCE)) || defined(_XOPEN_SOURCE)
+#define LONG_BIT       32
+#define WORD_BIT       32
+
+#define DBL_DIG                15
+#define DBL_MAX                1.797693134862316E+308
+#define DBL_MIN                2.225073858507201E-308
+
+#define FLT_DIG                6
+#define FLT_MAX                3.40282347E+38F
+#define FLT_MIN                1.17549435E-38F
+#endif
diff --git a/sys/arch/wgrisc/include/link.h b/sys/arch/wgrisc/include/link.h
new file mode 100644 (file)
index 0000000..3b6206c
--- /dev/null
@@ -0,0 +1,68 @@
+/*     $OpenBSD: link.h,v 1.1.1.1 1997/02/06 16:02:44 pefo Exp $ */
+
+/*
+ * Copyright (c) 1996 Per Fogelstrom
+ * 
+ * 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 under OpenBSD by
+ *     Per Fogelstrom.
+ * 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 _LINK_H
+#define _LINK_H 1
+#include <elf.h>
+#include <machine/elf_abi.h>
+
+/*
+ *     Debug rendezvous struct. Pointer to this is set up in the
+ *     target code pointed by the DT_MIPS_RLD_MAP tag. If it is
+ *     defined.
+ */
+
+struct r_debug {
+       int     r_version;              /* Protocol version.    */
+       struct link_map *r_map;         /* Head of list of loaded objects.  */
+
+    /* This is the address of a function internal to the run-time linker,
+       that will always be called when the linker begins to map in a
+       library or unmap it, and again when the mapping change is complete.
+       The debugger can set a breakpoint at this address if it wants to
+       notice shared object mapping changes.  */              
+       Elf32_Addr r_brk;                                            
+       enum {
+        /* This state value describes the mapping change taking place when
+           the `r_brk' address is called.  */                      
+               RT_CONSISTENT,          /* Mapping change is complete.  */
+               RT_ADD,                 /* Adding a new object.  */
+               RT_DELETE,              /* Removing an object mapping.  */
+       } r_state;
+
+       Elf32_Addr r_ldbase;        /* Base address the linker is loaded at.  */
+  };            
+
+#endif /* _LINK_H */
diff --git a/sys/arch/wgrisc/include/memconf.h b/sys/arch/wgrisc/include/memconf.h
new file mode 100644 (file)
index 0000000..eb51c94
--- /dev/null
@@ -0,0 +1,50 @@
+/*     $OpenBSD: memconf.h,v 1.1.1.1 1997/02/06 16:02:44 pefo Exp $    */
+
+/*
+ * Copyright (c) 1996 Per Fogelstrom
+ * 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 Per Fogelstrom.
+ * 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.
+ */
+
+/*
+ * Memory config list used by pmap_bootstrap.
+ */
+
+#ifndef _MEMCONF_H_
+#define _MEMCONF_H_
+
+struct mem_descriptor {
+       vm_offset_t     mem_start;
+       u_int           mem_size;
+};
+
+#ifdef _KERNEL
+#define        MAXMEMSEGS      16
+extern struct mem_descriptor mem_layout[];
+#endif
+
+#endif
diff --git a/sys/arch/wgrisc/include/mips_opcode.h b/sys/arch/wgrisc/include/mips_opcode.h
new file mode 100644 (file)
index 0000000..821a3f0
--- /dev/null
@@ -0,0 +1,260 @@
+/*      $OpenBSD: mips_opcode.h,v 1.1.1.1 1997/02/06 16:02:43 pefo Exp $       */
+
+/*-
+ * Copyright (c) 1992, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Ralph Campbell.
+ *
+ * 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: @(#)mips_opcode.h 8.1 (Berkeley) 6/10/93
+ */
+
+/*
+ * Define the instruction formats and opcode values for the
+ * MIPS instruction set.
+ */
+
+/*
+ * Define the instruction formats.
+ */
+typedef union {
+       unsigned word;
+
+#if BYTE_ORDER == LITTLE_ENDIAN
+       struct {
+               unsigned imm: 16;
+               unsigned rt: 5;
+               unsigned rs: 5;
+               unsigned op: 6;
+       } IType;
+
+       struct {
+               unsigned target: 26;
+               unsigned op: 6;
+       } JType;
+
+       struct {
+               unsigned func: 6;
+               unsigned shamt: 5;
+               unsigned rd: 5;
+               unsigned rt: 5;
+               unsigned rs: 5;
+               unsigned op: 6;
+       } RType;
+
+       struct {
+               unsigned func: 6;
+               unsigned fd: 5;
+               unsigned fs: 5;
+               unsigned ft: 5;
+               unsigned fmt: 4;
+               unsigned : 1;           /* always '1' */
+               unsigned op: 6;         /* always '0x11' */
+       } FRType;
+#endif
+} InstFmt;
+
+/*
+ * Values for the 'op' field.
+ */
+#define OP_SPECIAL     000
+#define OP_BCOND       001
+#define OP_J           002
+#define        OP_JAL          003
+#define OP_BEQ         004
+#define OP_BNE         005
+#define OP_BLEZ                006
+#define OP_BGTZ                007
+
+#define OP_ADDI                010
+#define OP_ADDIU       011
+#define OP_SLTI                012
+#define OP_SLTIU       013
+#define OP_ANDI                014
+#define OP_ORI         015
+#define OP_XORI                016
+#define OP_LUI         017
+
+#define OP_COP0                020
+#define OP_COP1                021
+#define OP_COP2                022
+#define OP_COP3                023
+#define        OP_BEQL         024
+#define        OP_BNEL         025
+#define        OP_BLEZL        026
+#define        OP_BGTZL        027
+
+#define        OP_DADDI        030
+#define        OP_DADDIU       031
+#define        OP_LDL          032
+#define        OP_LDR          033
+
+#define        OP_LB           040
+#define        OP_LH           041
+#define OP_LWL         042
+#define OP_LW          043
+#define OP_LBU         044
+#define OP_LHU         045
+#define OP_LWR         046
+#define        OP_LHU          045
+#define        OP_LWR          046
+#define        OP_LWU          047
+
+#define OP_SB          050
+#define OP_SH          051
+#define OP_SWL         052
+#define OP_SW          053
+#define        OP_SDL          054
+#define        OP_SDR          055
+#define OP_SWR         056
+#define        OP_CACHE        057
+
+#define OP_LL          060
+#define OP_LWC1                061
+#define OP_LWC2                062
+#define OP_LWC3                063
+#define        OP_LLD          064
+#define        OP_LD           067
+
+#define OP_SC          070
+#define OP_SWC1                071
+#define OP_SWC2                072
+#define OP_SWC3                073
+#define        OP_SCD          074
+#define        OP_SD           077
+
+/*
+ * Values for the 'func' field when 'op' == OP_SPECIAL.
+ */
+#define OP_SLL         000
+#define OP_SRL         002
+#define OP_SRA         003
+#define OP_SLLV                004
+#define OP_SRLV                006
+#define OP_SRAV                007
+
+#define OP_JR          010
+#define OP_JALR                011
+#define OP_SYSCALL     014
+#define OP_BREAK       015
+#define        OP_SYNC         017
+
+#define OP_MFHI                020
+#define OP_MTHI                021
+#define OP_MFLO                022
+#define OP_MTLO                023
+#define        OP_DSLLV        024
+#define        OP_DSRLV        026
+#define        OP_DSRAV        027
+
+#define OP_MULT                030
+#define OP_MULTU       031
+#define OP_DIV         032
+#define OP_DIVU                033
+#define        OP_DMULT        034
+#define        OP_DMULTU       035
+#define        OP_DDIV         036
+#define        OP_DDIVU        037
+
+
+#define OP_ADD         040
+#define OP_ADDU                041
+#define OP_SUB         042
+#define OP_SUBU                043
+#define OP_AND         044
+#define OP_OR          045
+#define OP_XOR         046
+#define OP_NOR         047
+
+#define OP_SLT         052
+#define OP_SLTU                053
+#define        OP_DADD         054
+#define        OP_DADDU        055
+#define        OP_DSUB         056
+#define        OP_DSUBU        057
+
+#define        OP_TGE          060
+#define        OP_TGEU         061
+#define        OP_TLT          062
+#define        OP_TLTU         063
+#define        OP_TEQ          064
+#define        OP_TNE          066
+
+#define        OP_DSLL         070
+#define        OP_DSRL         072
+#define        OP_DSRA         073
+#define        OP_DSLL32       074
+#define        OP_DSRL32       076
+#define        OP_DSRA32       077
+
+/*
+ * Values for the 'func' field when 'op' == OP_BCOND.
+ */
+#define OP_BLTZ                000
+#define OP_BGEZ                001
+#define        OP_BLTZL        002
+#define        OP_BGEZL        003
+
+#define        OP_TGEI         010
+#define        OP_TGEIU        011
+#define        OP_TLTI         012
+#define        OP_TLTIU        013
+#define        OP_TEQI         014
+#define        OP_TNEI         016
+
+#define OP_BLTZAL      020
+#define        OP_BLTZAL       020
+#define OP_BGEZAL      021
+#define OP_BLTZALL     022
+#define        OP_BGEZALL      023
+
+/*
+ * Values for the 'rs' field when 'op' == OP_COPz.
+ */
+#define OP_MF          000
+#define        OP_DMF          001
+#define OP_MT          004
+#define        OP_DMT          005
+#define OP_BCx         010
+#define OP_BCy         014
+#define OP_CF          002
+#define OP_CT          006
+
+/*
+ * Values for the 'rt' field when 'op' == OP_COPz.
+ */
+#define COPz_BC_TF_MASK        0x01
+#define COPz_BC_TRUE   0x01
+#define COPz_BC_FALSE  0x00
+#define COPz_BCL_TF_MASK       0x02
+#define COPz_BCL_TRUE  0x02
+#define COPz_BCL_FALSE 0x00
diff --git a/sys/arch/wgrisc/include/param.h b/sys/arch/wgrisc/include/param.h
new file mode 100644 (file)
index 0000000..2978cf3
--- /dev/null
@@ -0,0 +1,165 @@
+/*      $OpenBSD: param.h,v 1.1.1.1 1997/02/06 16:02:43 pefo Exp $ */
+
+/*
+ * Copyright (c) 1988 University of Utah.
+ * Copyright (c) 1992, 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 and Ralph Campbell.
+ *
+ * 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.11 89/08/14
+ *     from: @(#)param.h       8.1 (Berkeley) 6/10/93
+ */
+
+/*
+ * Machine dependent constants for Willowglen Mips RISC machines:
+ */
+#define        MACHINE      "wgrisc"
+#define MACHINE_ARCH "mips"
+#define MID_MACHINE  MID_PMAX  /* XXX Bogus, but we need it for now... */
+
+/*
+ * 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      7
+#define        ALIGN(p)        (((u_int)(p) + ALIGNBYTES) &~ ALIGNBYTES)
+
+#define        NBPG            4096            /* bytes/page */
+#define        PGOFSET         (NBPG-1)        /* byte offset into page */
+#define        PGSHIFT         12              /* LOG2(NBPG) */
+#define        NPTEPG          (NBPG/4)
+
+#define NBSEG          0x400000        /* bytes/segment */
+#define        SEGOFSET        (NBSEG-1)       /* byte offset into segment */
+#define        SEGSHIFT        22              /* LOG2(NBSEG) */
+
+#define        KERNBASE        0x80000000      /* start of kernel virtual */
+#define        BTOPKERNBASE    ((u_long)KERNBASE >> PGSHIFT)
+
+#define        DEV_BSIZE       512
+#define        DEV_BSHIFT      9               /* log2(DEV_BSIZE) */
+#define BLKDEV_IOSIZE  2048
+/* XXX Maxphys temporary changed to 32K while SCSI driver is fixed. */
+#define        MAXPHYS         (32 * 1024)     /* max raw I/O transfer size */
+
+#define        CLSIZE          1
+#define        CLSIZELOG2      0
+
+/* 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          2               /* pages of u-area */
+#define        UADDR           0xffffc000      /* address of u */
+#define USPACE         (UPAGES*NBPG)   /* size of u-area in bytes */
+#define        UVPN            (UADDR>>PGSHIFT)/* virtual page number of u */
+#define        KERNELSTACK     (UADDR+UPAGES*NBPG)     /* top of kernel stack */
+
+/*
+ * 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        MCLBYTES        2048            /* enough for whole Ethernet packet */
+#define        MCLSHIFT        10
+#define        MCLOFSET        (MCLBYTES - 1)
+#ifndef NMBCLUSTERS
+#ifdef GATEWAY
+#define        NMBCLUSTERS     2048            /* map size, max cluster allocation */
+#else
+#define        NMBCLUSTERS     1024            /* map size, max cluster allocation */
+#endif
+#endif
+
+/*
+ * Size of kernel malloc arena in CLBYTES-sized logical pages
+ */ 
+#ifndef NKMEMCLUSTERS
+#define        NKMEMCLUSTERS   (4096*1024/CLBYTES)
+#endif
+
+/* pages ("clicks") (4096 bytes) 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        btodb(x)        ((x) >> DEV_BSHIFT)
+#define dbtob(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 mips_round_page(x)     ((((unsigned)(x)) + NBPG - 1) & ~(NBPG-1))
+#define mips_trunc_page(x)     ((unsigned)(x) & ~(NBPG-1))
+#define mips_btop(x)           ((unsigned)(x) >> PGSHIFT)
+#define mips_ptob(x)           ((unsigned)(x) << PGSHIFT)
+
+#ifdef _KERNEL
+#ifndef _LOCORE
+extern int (*Mach_splnet)(), (*Mach_splbio)(), (*Mach_splimp)(),
+          (*Mach_spltty)(), (*Mach_splclock)(), (*Mach_splstatclock)();
+#define        splnet()        ((*Mach_splnet)())
+#define        splbio()        ((*Mach_splbio)())
+#define        splimp()        ((*Mach_splimp)())
+#define        spltty()        ((*Mach_spltty)())
+#define        splclock()      ((*Mach_splclock)())
+#define        splstatclock()  ((*Mach_splstatclock)())
+
+/*
+ *   Delay is based on an assumtion that each time in the loop
+ *   takes 3 clocks. Three is for branch and subtract in the delay slot.
+ */
+extern int cpuspeed;
+#define        DELAY(n)        { register int N = cpuspeed * (n); while ((N -= 3) > 0); }
+#endif
+
+#else /* !_KERNEL */
+#define        DELAY(n)        { register int N = (n); while (--N > 0); }
+#endif /* !_KERNEL */
diff --git a/sys/arch/wgrisc/include/pcb.h b/sys/arch/wgrisc/include/pcb.h
new file mode 100644 (file)
index 0000000..efcaaf2
--- /dev/null
@@ -0,0 +1,61 @@
+/*      $OpenBSD: pcb.h,v 1.1.1.1 1997/02/06 16:02:43 pefo Exp $       */
+
+/*
+ * Copyright (c) 1988 University of Utah.
+ * Copyright (c) 1992, 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 and Ralph Campbell.
+ *
+ * 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.13 89/04/23
+ *     from: @(#)pcb.h 8.1 (Berkeley) 6/10/93
+ */
+
+/*
+ * ARC process control block
+ */
+struct pcb
+{
+       int     pcb_regs[71];   /* saved CPU and floating point registers */
+       label_t pcb_context;    /* kernel context for resume */
+       int     pcb_onfault;    /* for copyin/copyout faults */
+       void    *pcb_segtab;    /* copy of pmap pm_segtab */
+};
+
+/*
+ * The pcb is augmented with machine-dependent additional data for
+ * core dumps. For the WGRISC, there is nothing to add.
+ */
+struct md_coredump {
+       long    md_pad[8];
+};
diff --git a/sys/arch/wgrisc/include/pio.h b/sys/arch/wgrisc/include/pio.h
new file mode 100644 (file)
index 0000000..2ebf8ab
--- /dev/null
@@ -0,0 +1,46 @@
+/*     $OpenBSD: pio.h,v 1.1.1.1 1997/02/06 16:02:43 pefo Exp $        */
+
+/*
+ * Copyright (c) 1995 Per Fogelstrom.  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 Per Fogelstrom.
+ * 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.
+ */
+
+/*
+ * I/O macros.
+ */
+
+#define        outb(a,v)       (*(volatile unsigned char*)(a) = (v))
+#define        outw(a,v)       (*(volatile unsigned short*)(a) = (v))
+#define        out16(a,v)      outw(a,v)
+#define        outl(a,v)       (*(volatile unsigned int*)(a) = (v))
+#define        out32(a,v)      outl(a,v)
+#define        inb(a)          (*(volatile unsigned char*)(a))
+#define        inw(a)          (*(volatile unsigned short*)(a))
+#define        in16(a)         inw(a)
+#define        inl(a)          (*(volatile unsigned int*)(a))
+#define        in32(a)         inl(a)
+
diff --git a/sys/arch/wgrisc/include/pmap.h b/sys/arch/wgrisc/include/pmap.h
new file mode 100644 (file)
index 0000000..371080a
--- /dev/null
@@ -0,0 +1,109 @@
+/*      $OpenBSD: pmap.h,v 1.1.1.1 1997/02/06 16:02:43 pefo Exp $ */
+
+/* 
+ * Copyright (c) 1987 Carnegie-Mellon University
+ * Copyright (c) 1992, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Ralph Campbell.
+ *
+ * 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: @(#)pmap.h        8.1 (Berkeley) 6/10/93
+ */
+
+#ifndef        _PMAP_MACHINE_
+#define        _PMAP_MACHINE_
+
+/*
+ * The user address space is 2Gb (0x0 - 0x80000000).
+ * User programs are laid out in memory as follows:
+ *                     address
+ *     USRTEXT         0x00400000
+ *     USRDATA         0x10000000
+ *     USRSTACK        0x7FFFFFFF
+ *
+ * The user address space is mapped using a two level structure where
+ * virtual address bits 30..22 are used to index into a segment table which
+ * points to a page worth of PTEs (4096 page can hold 1024 PTEs).
+ * Bits 21..12 are then used to index a PTE which describes a page within 
+ * a segment.
+ *
+ * The wired entries in the TLB will contain the following:
+ *     0-1     (UPAGES)        for curproc user struct and kernel stack.
+ *
+ * Note: The kernel doesn't use the same data structures as user programs.
+ * All the PTE entries are stored in a single array in Sysmap which is
+ * dynamically allocated at boot time.
+ */
+
+#define mips_trunc_seg(x)      ((vm_offset_t)(x) & ~SEGOFSET)
+#define mips_round_seg(x)      (((vm_offset_t)(x) + SEGOFSET) & ~SEGOFSET)
+#define pmap_segmap(m, v)      ((m)->pm_segtab->seg_tab[((v) >> SEGSHIFT)])
+
+#define PMAP_SEGTABSIZE                512
+
+union pt_entry;
+
+struct segtab {
+       union pt_entry  *seg_tab[PMAP_SEGTABSIZE];
+};
+
+/*
+ * Machine dependent pmap structure.
+ */
+typedef struct pmap {
+       int                     pm_count;       /* pmap reference count */
+       simple_lock_data_t      pm_lock;        /* lock on pmap */
+       struct pmap_statistics  pm_stats;       /* pmap statistics */
+       int                     pm_tlbpid;      /* address space tag */
+       u_int                   pm_tlbgen;      /* TLB PID generation number */
+       struct segtab           *pm_segtab;     /* pointers to pages of PTEs */
+} *pmap_t;
+
+/*
+ * Defines for pmap_attributes[phys_mach_page];
+ */
+#define PMAP_ATTR_MOD  0x01    /* page has been modified */
+#define PMAP_ATTR_REF  0x02    /* page has been referenced */
+
+#ifdef _KERNEL
+extern char *pmap_attributes;          /* reference and modify bits */
+extern struct pmap kernel_pmap_store;
+
+#define pmap_resident_count(pmap)       ((pmap)->pm_stats.resident_count)
+#define        pmap_wired_count(pmap)          ((pmap)->pm_stats.wired_count)
+#define pmap_kernel() (&kernel_pmap_store)
+
+#define PMAP_PREFER(pa, va)             pmap_prefer((pa), (va))
+
+#endif /* _KERNEL */
+
+#endif /* _PMAP_MACHINE_ */
diff --git a/sys/arch/wgrisc/include/proc.h b/sys/arch/wgrisc/include/proc.h
new file mode 100644 (file)
index 0000000..b786274
--- /dev/null
@@ -0,0 +1,54 @@
+/*     $OpenBSD: proc.h,v 1.1.1.1 1997/02/06 16:02:43 pefo Exp $       */
+/*     $NetBSD: proc.h,v 1.4 1994/10/26 21:09:52 cgd Exp $     */
+
+/*
+ * Copyright (c) 1992, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Ralph Campbell.
+ *
+ * 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.
+ */
+struct mdproc {
+       int     *md_regs;               /* registers on current frame */
+       int     md_flags;               /* machine-dependent flags */
+       int     md_upte[UPAGES];        /* ptes for mapping u page */
+       int     md_ss_addr;             /* single step address for ptrace */
+       int     md_ss_instr;            /* single step instruction for ptrace */
+};
+
+/* md_flags */
+#define        MDP_FPUSED      0x0001  /* floating point coprocessor used */
diff --git a/sys/arch/wgrisc/include/profile.h b/sys/arch/wgrisc/include/profile.h
new file mode 100644 (file)
index 0000000..61cdbe2
--- /dev/null
@@ -0,0 +1,81 @@
+/*      $OpenBSD: profile.h,v 1.1.1.1 1997/02/06 16:02:43 pefo Exp $   */
+
+/*
+ * Copyright (c) 1992, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Ralph Campbell.
+ *
+ * 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: @(#)profile.h     8.1 (Berkeley) 6/10/93
+ */
+
+#define        _MCOUNT_DECL static void ___mcount
+
+#define        MCOUNT \
+       __asm(".globl _mcount;"         \
+       ".type _mcount,@function;"      \
+       "_mcount:;"                     \
+       ".set noreorder;"               \
+       ".set noat;"                    \
+       ".cpload $25;"                  \
+       "sw $4,8($29);"                 \
+       "sw $5,12($29);"                \
+       "sw $6,16($29);"                \
+       "sw $7,20($29);"                \
+       "sw $1,0($29);"                 \
+       "sw $31,4($29);"                \
+       "move $5,$31;"                  \
+       "jal ___mcount;"                \
+       "move $4,$1;"                   \
+       "lw $4,8($29);"                 \
+       "lw $5,12($29);"                \
+       "lw $6,16($29);"                \
+       "lw $7,20($29);"                \
+       "lw $31,4($29);"                \
+       "lw $1,0($29);"                 \
+       "addu $29,$29,8;"               \
+       "j $31;"                        \
+       "move $31,$1;"                  \
+       ".set reorder;"                 \
+       ".set at");
+
+#ifdef _KERNEL
+/*
+ * The following two macros do splhigh and splx respectively.
+ * They have to be defined this way because these are real
+ * functions on the MIPS, and we do not want to invoke mcount
+ * recursively.
+ */
+#define        MCOUNT_ENTER    s = _splhigh()
+
+#define        MCOUNT_EXIT     _splx(s)
+#endif /* _KERNEL */
diff --git a/sys/arch/wgrisc/include/psl.h b/sys/arch/wgrisc/include/psl.h
new file mode 100644 (file)
index 0000000..0b6d349
--- /dev/null
@@ -0,0 +1,61 @@
+/*      $OpenBSD: psl.h,v 1.1.1.1 1997/02/06 16:02:43 pefo Exp $       */
+
+/*
+ * Copyright (c) 1992, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Ralph Campbell.
+ *
+ * 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: @(#)psl.h 8.1 (Berkeley) 6/10/93
+ */
+
+#include <machine/cpu.h>
+
+#define        PSL_LOWIPL      (INT_MASK | SR_INT_ENAB)
+
+#define R3K_PSL_USERSET ( SR_KU_OLD    | SR_INT_ENA_OLD  |  \
+                         SR_KU_PREV    | SR_INT_ENA_PREV |  \
+                         INT_MASK)
+
+#define        R4K_PSL_USERSET ( SR_KSU_USER |  SR_INT_ENAB |  \
+                         SR_EXL      |  INT_MASK)
+
+/*
+ * Macros to decode processor status word.
+ */
+#define        R3K_USERMODE(ps) ((ps) & SR_KU_PREV)
+#define R3K_BASEPRI(ps)         (((ps) & (INT_MASK | SR_INT_ENA_PREV)) \
+                               == (INT_MASK | SR_INT_ENA_PREV))
+
+#define        R4K_USERMODE(ps) (((ps) & SR_KSU_MASK) == SR_KSU_USER)
+#define        R4K_BASEPRI(ps)  (((ps) & (INT_MASK | SR_INT_ENA_PREV)) \
+                               == (INT_MASK | SR_INT_ENA_PREV))
diff --git a/sys/arch/wgrisc/include/pte.h b/sys/arch/wgrisc/include/pte.h
new file mode 100644 (file)
index 0000000..a6f462b
--- /dev/null
@@ -0,0 +1,176 @@
+/*      $OpenBSD: pte.h,v 1.1.1.1 1997/02/06 16:02:43 pefo Exp $       */
+
+/*
+ * Copyright (c) 1988 University of Utah.
+ * Copyright (c) 1992, 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 and Ralph Campbell.
+ *
+ * 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.11 89/09/03
+ *     from: @(#)pte.h 8.1 (Berkeley) 6/10/93
+ */
+
+#ifndef _LOCORE
+/*
+ * R3000 hardware page table entry
+ * R4000 hardware page table entry
+ */
+struct pte {
+#if BYTE_ORDER == BIG_ENDIAN
+#ifdef R4K
+unsigned int   pg_prot:2,              /* SW: access control */
+               pg_pfnum:24,            /* HW: core page frame number or 0 */
+               pg_attr:3,              /* HW: cache attribute */
+               pg_m:1,                 /* HW: modified (dirty) bit */
+               pg_v:1,                 /* HW: valid bit */
+               pg_g:1;                 /* HW: ignore pid bit */
+#else
+unsigned int   pg_pfnum:20,            /* HW: core page frame number or 0 */
+               pg_n:1,                 /* HW: non-cacheable bit */
+               pg_m:1,                 /* HW: modified (dirty) bit */
+               pg_v:1,                 /* HW: valid bit */
+               pg_g:1,                 /* HW: ignore pid bit */
+               :4,
+               pg_swapm:1,             /* SW: page must be forced to swap */
+               pg_fod:1,               /* SW: is fill on demand (=0) */
+               pg_prot:2;              /* SW: access control */
+#endif
+#endif
+#if BYTE_ORDER == LITTLE_ENDIAN
+#ifdef R4K
+unsigned int   pg_g:1,                 /* HW: ignore pid bit */
+               pg_v:1,                 /* HW: valid bit */
+               pg_m:1,                 /* HW: modified (dirty) bit */
+               pg_attr:3,                      /* HW: cache attribute */
+               pg_pfnum:24,            /* HW: core page frame number or 0 */
+               pg_prot:2;              /* SW: access control */
+#else
+unsigned int   pg_prot:2,              /* SW: access control */
+               pg_fod:1,               /* SW: is fill on demand (=0) */
+               pg_swapm:1,             /* SW: page must be forced to swap */
+               :4,
+               pg_g:1,                 /* HW: ignore pid bit */
+               pg_v:1,                 /* HW: valid bit */
+               pg_m:1,                 /* HW: modified (dirty) bit */
+               pg_n:1,                 /* HW: non-cacheable bit */
+               pg_pfnum:20;            /* HW: core page frame number or 0 */
+#endif
+#endif
+};
+
+/*
+ * Structure defining an tlb entry data set.
+ */
+
+struct tlb {
+       int     tlb_mask;
+       int     tlb_hi;
+       int     tlb_lo0;
+       int     tlb_lo1;
+};
+
+typedef union pt_entry {
+       unsigned int    pt_entry;       /* for copying, etc. */
+       struct pte      pt_pte;         /* for getting to bits by name */
+} pt_entry_t;  /* Mach page table entry */
+#endif /* _LOCORE */
+
+#define        PT_ENTRY_NULL   ((pt_entry_t *) 0)
+
+#ifdef R4K
+#define        PG_SVPN         0xfffff000      /* Software page no mask */
+#define        PG_HVPN         0xffffe000      /* Hardware page no mask */
+#define        PG_ODDPG        0x00001000      /* Odd even pte entry */
+#define        PG_ASID         0x000000ff      /* Address space ID */
+#define        PG_G            0x00000001      /* HW */
+#define        PG_V            0x00000002
+#define        PG_NV           0x00000000
+#define        PG_M            0x00000004
+#define        PG_ATTR         0x0000003f
+#define        PG_UNCACHED     0x00000010
+#define        PG_CACHED       0x00000018
+#define        PG_CACHEMODE    0x00000038
+#define        PG_FRAME        0x3fffffc0
+#define PG_RO          0x40000000      /* SW */
+#define PG_WIRED       0x80000000      /* SW */
+#define PG_SHIFT       6
+#define        PG_SIZE_4K      0x00000000
+#define        PG_SIZE_16K     0x00006000
+#define        PG_SIZE_64K     0x0001e000
+#define        PG_SIZE_256K    0x0007e000
+#define        PG_SIZE_1M      0x001fe000
+#define        PG_SIZE_4M      0x007fe000
+#define        PG_SIZE_16M     0x01ffe000
+
+#else /* R3K */
+#define PG_PROT                0x00000003      /* Software bits */
+#define PG_RW          0x00000000      /* Read/Write mapped */
+#define PG_RO          0x00000001      /* Read only mapped */
+#define PG_WIRED       0x00000002      /* Page is wired down */
+#define PG_G           0x00000100      /* Global mapped */
+#define PG_V           0x00000200      /* Page is valid */
+#define PG_NV          0x00000000      /* Page is NOT valid */
+#define PG_M           0x00000400      /* Page is dirty */
+#define PG_UNCACHED    0x00000800      /* Non cachable page */
+#define PG_CACHED      0x00000000      /* Non cachable page */
+#define        PG_CACHEMODE    0x00000800
+#define PG_FRAME       0xfffff000
+#define PG_SHIFT       0               /* VPN already in place */
+#endif
+
+#define        PG_ROPAGE       (PG_V | PG_RO | PG_CACHED) /* Write protected */
+#define        PG_RWPAGE       (PG_V | PG_M | PG_CACHED)  /* Not wr-prot not clean */
+#define        PG_CWPAGE       (PG_V | PG_CACHED)         /* Not wr-prot but clean */
+#define        PG_IOPAGE       (PG_G | PG_V | PG_M | PG_UNCACHED)
+
+#define vad_to_pfn(x) (((unsigned)(x) >> PG_SHIFT) & PG_FRAME)
+#define vad_to_pfn64(x) (((quad_t)(x) >> PG_SHIFT) & PG_FRAME)
+#define pfn_to_vad(x) (((x) & PG_FRAME) << PG_SHIFT)
+#define vad_to_vpn(x) ((unsigned)(x) & PG_SVPN)
+#define vpn_to_vad(x) ((x) & PG_SVPN)
+/* User viritual to pte page entry */
+#define uvtopte(adr) (((adr) >> PGSHIFT) & (NPTEPG -1))
+
+#if defined(_KERNEL) && !defined(_LOCORE)
+/*
+ * Kernel virtual address to page table entry and visa versa.
+ */
+#define        kvtopte(va) \
+       (Sysmap + (((vm_offset_t)(va) - VM_MIN_KERNEL_ADDRESS) >> PGSHIFT))
+#define        ptetokv(pte) \
+       ((((pt_entry_t *)(pte) - Sysmap) << PGSHIFT) + VM_MIN_KERNEL_ADDRESS)
+
+extern pt_entry_t *Sysmap;             /* kernel pte table */
+extern u_int Sysmapsize;               /* number of pte's in Sysmap */
+#endif
diff --git a/sys/arch/wgrisc/include/ptrace.h b/sys/arch/wgrisc/include/ptrace.h
new file mode 100644 (file)
index 0000000..6503e80
--- /dev/null
@@ -0,0 +1,45 @@
+/*      $OpenBSD: ptrace.h,v 1.1.1.1 1997/02/06 16:02:43 pefo Exp $    */
+
+/*
+ * Copyright (c) 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.
+ *
+ *     from: @(#)ptrace.h      8.1 (Berkeley) 6/10/93
+ */
+
+/*
+ * Machine dependent trace commands.
+ *
+ */
+
+#define        PT_GETREGS       (PT_FIRSTMACH+0)
+#define        PT_SETREGS       (PT_FIRSTMACH+1)
+#define        PT_STEP          (PT_FIRSTMACH+2)
diff --git a/sys/arch/wgrisc/include/reg.h b/sys/arch/wgrisc/include/reg.h
new file mode 100644 (file)
index 0000000..f343120
--- /dev/null
@@ -0,0 +1,62 @@
+/*     $OpenBSD: reg.h,v 1.1.1.1 1997/02/06 16:02:43 pefo Exp $        */
+/*     $NetBSD: reg.h,v 1.6 1995/12/20 02:00:27 jonathan Exp $ */
+
+/*
+ * Copyright (c) 1988 University of Utah.
+ * Copyright (c) 1992, 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 and Ralph Campbell.
+ *
+ * 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: reg.h 1.1 90/07/09
+ *     @(#)reg.h       8.2 (Berkeley) 1/11/94
+ */
+
+#ifndef _MACHINE_REG_H_
+#define _MACHINE_REG_H_
+/*
+ * Location of the users' stored
+ * registers relative to ZERO.
+ * Usage is p->p_regs[XX].
+ *
+ * must be visible to assembly code.
+ */
+#include <machine/regnum.h>
+
+/*
+ * Register set accessible via /proc/$pid/reg
+ */
+struct reg {
+        int     r_regs[71];    /* numbered as above */
+};
+#endif /*_MACHINE_REG_H_*/
diff --git a/sys/arch/wgrisc/include/regdef.h b/sys/arch/wgrisc/include/regdef.h
new file mode 100644 (file)
index 0000000..ac5f6ec
--- /dev/null
@@ -0,0 +1,74 @@
+/*     $OpenBSD: regdef.h,v 1.1.1.1 1997/02/06 16:02:43 pefo Exp $     */
+/*     $NetBSD: regdef.h,v 1.4 1994/10/26 21:09:58 cgd Exp $   */
+
+/*
+ * Copyright (c) 1992, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Ralph Campbell. This file is derived from the MIPS RISC
+ * Architecture book by Gerry Kane.
+ *
+ * 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.
+ *
+ *     @(#)regdef.h    8.1 (Berkeley) 6/10/93
+ */
+
+#define zero   $0      /* always zero */
+#define AT     $at     /* assembler temp */
+#define v0     $2      /* return value */
+#define v1     $3
+#define a0     $4      /* argument registers */
+#define a1     $5
+#define a2     $6
+#define a3     $7
+#define t0     $8      /* temp registers (not saved across subroutine calls) */
+#define t1     $9
+#define t2     $10
+#define t3     $11
+#define t4     $12
+#define t5     $13
+#define t6     $14
+#define t7     $15
+#define s0     $16     /* saved across subroutine calls (callee saved) */
+#define s1     $17
+#define s2     $18
+#define s3     $19
+#define s4     $20
+#define s5     $21
+#define s6     $22
+#define s7     $23
+#define t8     $24     /* two more temp registers */
+#define t9     $25
+#define k0     $26     /* kernel temporary */
+#define k1     $27
+#define gp     $28     /* global pointer */
+#define sp     $29     /* stack pointer */
+#define s8     $30     /* one more callee saved */
+#define ra     $31     /* return address */
diff --git a/sys/arch/wgrisc/include/regnum.h b/sys/arch/wgrisc/include/regnum.h
new file mode 100644 (file)
index 0000000..df346a9
--- /dev/null
@@ -0,0 +1,136 @@
+/*     $OpenBSD: regnum.h,v 1.1.1.1 1997/02/06 16:02:44 pefo Exp $     */
+/*     $NetBSD: reg.h,v 1.5 1995/01/18 06:40:12 mellon Exp $   */
+
+/*
+ * Copyright (c) 1988 University of Utah.
+ * Copyright (c) 1992, 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 and Ralph Campbell.
+ *
+ * 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: reg.h 1.1 90/07/09
+ *     @(#)reg.h       8.2 (Berkeley) 1/11/94
+ */
+
+/*
+ * Location of the users' stored
+ * registers relative to ZERO.
+ * Usage is p->p_regs[XX].
+ */
+#define ZERO   0
+#define AST    1
+#define V0     2
+#define V1     3
+#define A0     4
+#define A1     5
+#define A2     6
+#define A3     7
+#define T0     8
+#define T1     9
+#define T2     10
+#define T3     11
+#define T4     12
+#define T5     13
+#define T6     14
+#define T7     15
+#define S0     16
+#define S1     17
+#define S2     18
+#define S3     19
+#define S4     20
+#define S5     21
+#define S6     22
+#define S7     23
+#define T8     24
+#define T9     25
+#define K0     26
+#define K1     27
+#define GP     28
+#define SP     29
+#define S8     30
+#define RA     31
+#define        SR      32
+#define        PS      SR      /* alias for SR */
+#define MULLO  33
+#define MULHI  34
+#define BADVADDR 35
+#define CAUSE  36
+#define        PC      37
+
+#define FPBASE 38
+#define F0     (FPBASE+0)
+#define F1     (FPBASE+1)
+#define F2     (FPBASE+2)
+#define F3     (FPBASE+3)
+#define F4     (FPBASE+4)
+#define F5     (FPBASE+5)
+#define F6     (FPBASE+6)
+#define F7     (FPBASE+7)
+#define F8     (FPBASE+8)
+#define F9     (FPBASE+9)
+#define F10    (FPBASE+10)
+#define F11    (FPBASE+11)
+#define F12    (FPBASE+12)
+#define F13    (FPBASE+13)
+#define F14    (FPBASE+14)
+#define F15    (FPBASE+15)
+#define F16    (FPBASE+16)
+#define F17    (FPBASE+17)
+#define F18    (FPBASE+18)
+#define F19    (FPBASE+19)
+#define F20    (FPBASE+20)
+#define F21    (FPBASE+21)
+#define F22    (FPBASE+22)
+#define F23    (FPBASE+23)
+#define F24    (FPBASE+24)
+#define F25    (FPBASE+25)
+#define F26    (FPBASE+26)
+#define F27    (FPBASE+27)
+#define F28    (FPBASE+28)
+#define F29    (FPBASE+29)
+#define F30    (FPBASE+30)
+#define F31    (FPBASE+31)
+#define        FSR     (FPBASE+32)
+
+#ifdef IPCREG
+#define        NIPCREG (FSR + 1)
+int ipcreg[NIPCREG] = {
+       ZERO, AST, V0, V1, A0, A1, A2, A3, T0, T1, T2, T3, T4, T5, T6, T7,
+       S0, S1, S2, S3, S4, S5, S6, S7, T8, T9, K0, K1, GP, SP, S8, RA,
+       SR, MULLO, MULHI, BADVADDR, CAUSE, PC,
+       F0, F1, F2, F3, F4, F5, F6, F7,
+       F8, F9, F10, F11, F12, F13, F14, F15,
+       F16, F17, F18, F19, F20, F21, F22, F23,
+       F24, F25, F26, F27, F28, F29, F30, F31, FSR,
+};
+#endif
diff --git a/sys/arch/wgrisc/include/reloc.h b/sys/arch/wgrisc/include/reloc.h
new file mode 100644 (file)
index 0000000..dd75526
--- /dev/null
@@ -0,0 +1,38 @@
+/*      $OpenBSD: reloc.h,v 1.1.1.1 1997/02/06 16:02:44 pefo Exp $     */
+
+/*-
+ * Copyright (c) 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.
+ *
+ *     from: @(#)reloc.h       8.1 (Berkeley) 6/10/93
+ *     from: Header: reloc.h,v 1.6 92/06/20 09:59:37 torek Exp
+ */
+
diff --git a/sys/arch/wgrisc/include/setjmp.h b/sys/arch/wgrisc/include/setjmp.h
new file mode 100644 (file)
index 0000000..6bd6772
--- /dev/null
@@ -0,0 +1,8 @@
+/*     $OpenBSD: setjmp.h,v 1.1.1.1 1997/02/06 16:02:43 pefo Exp $     */
+/*     $NetBSD: setjmp.h,v 1.1 1994/12/20 10:37:05 cgd Exp $   */
+
+/*
+ * machine/setjmp.h: machine dependent setjmp-related information.
+ */
+
+#define        _JBLEN  83              /* size, in longs, of a jmp_buf */
diff --git a/sys/arch/wgrisc/include/signal.h b/sys/arch/wgrisc/include/signal.h
new file mode 100644 (file)
index 0000000..dc1f516
--- /dev/null
@@ -0,0 +1,68 @@
+/*     $OpenBSD: signal.h,v 1.1.1.1 1997/02/06 16:02:43 pefo Exp $     */
+/*     $NetBSD: signal.h,v 1.6 1995/01/18 06:42:01 mellon Exp $        */
+
+/*
+ * Copyright (c) 1992, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Ralph Campbell.
+ *
+ * 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.
+ *
+ *     @(#)signal.h    8.1 (Berkeley) 6/10/93
+ */
+
+/*
+ * Machine-dependent signal definitions
+ */
+
+typedef int sig_atomic_t;
+
+#ifndef _ANSI_SOURCE
+/*
+ * Information pushed on stack when a signal is delivered.
+ * This is used by the kernel to restore state following
+ * execution of the signal handler.  It is also made available
+ * to the handler to allow it to restore state properly if
+ * a non-standard exit is performed.
+ */
+struct sigcontext {
+       int     sc_onstack;     /* sigstack state to restore */
+       int     sc_mask;        /* signal mask to restore */
+       int     sc_pc;          /* pc at time of signal */
+       int     sc_regs[32];    /* processor regs 0 to 31 */
+       int     mullo, mulhi;   /* mullo and mulhi registers... */
+       int     sc_fpused;      /* fp has been used */
+       int     sc_fpregs[33];  /* fp regs 0 to 31 and csr */
+       int     sc_fpc_eir;     /* floating point exception instruction reg */
+       int     xxx[8];         /* XXX reserved */ 
+};
+
+#endif /* !_ANSI_SOURCE */
diff --git a/sys/arch/wgrisc/include/stdarg.h b/sys/arch/wgrisc/include/stdarg.h
new file mode 100644 (file)
index 0000000..26603cf
--- /dev/null
@@ -0,0 +1,65 @@
+/*     $OpenBSD: stdarg.h,v 1.1.1.1 1997/02/06 16:02:43 pefo Exp $     */
+/*     $NetBSD: stdarg.h,v 1.7 1995/03/28 18:19:28 jtc Exp $   */
+
+/*-
+ * Copyright (c) 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.
+ *
+ *     @(#)stdarg.h    8.1 (Berkeley) 6/10/93
+ */
+
+#ifndef _MIPS_STDARG_H_
+#define        _MIPS_STDARG_H_
+
+#include <machine/ansi.h>
+
+typedef _BSD_VA_LIST_  va_list;
+
+#define        __va_promote(type) \
+       (((sizeof(type) + sizeof(int) - 1) / sizeof(int)) * sizeof(int))
+
+#define        va_start(ap, last) \
+       (ap = ((char *)&(last) + __va_promote(last)))
+
+#ifdef _KERNEL
+#define        va_arg(ap, type) \
+       ((type *)(ap += sizeof(type)))[-1]
+#else
+#define        va_arg(ap, type) \
+       ((type *)(ap += sizeof(type) == sizeof(int) ? sizeof(type) : \
+               sizeof(type) > sizeof(int) ? \
+               (-(int)(ap) & (sizeof(type) - 1)) + sizeof(type) : \
+               (abort(), 0)))[-1]
+#endif
+
+#define        va_end(ap)      ((void) 0)
+
+#endif /* !_MIPS_STDARG_H_ */
diff --git a/sys/arch/wgrisc/include/trap.h b/sys/arch/wgrisc/include/trap.h
new file mode 100644 (file)
index 0000000..54e7c76
--- /dev/null
@@ -0,0 +1,68 @@
+/*      $OpenBSD: trap.h,v 1.1.1.1 1997/02/06 16:02:43 pefo Exp $      */
+
+/*
+ * Copyright (c) 1988 University of Utah.
+ * Copyright (c) 1992, 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 and Ralph Campbell.
+ *
+ * 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.h 1.1 90/07/09
+ *     from: @(#)trap.h        8.1 (Berkeley) 6/10/93
+ */
+
+/*
+ * Trap codes
+ * also known in trap.c for name strings
+ */
+
+#define T_INT                  0       /* Interrupt pending */
+#define T_TLB_MOD              1       /* TLB modified fault */
+#define T_TLB_LD_MISS          2       /* TLB miss on load or ifetch */
+#define T_TLB_ST_MISS          3       /* TLB miss on a store */
+#define T_ADDR_ERR_LD          4       /* Address error on a load or ifetch */
+#define T_ADDR_ERR_ST          5       /* Address error on a store */
+#define T_BUS_ERR_IFETCH       6       /* Bus error on an ifetch */
+#define T_BUS_ERR_LD_ST                7       /* Bus error on a load or store */
+#define T_SYSCALL              8       /* System call */
+#define T_BREAK                        9       /* Breakpoint */
+#define T_RES_INST             10      /* Reserved instruction exception */
+#define T_COP_UNUSABLE         11      /* Coprocessor unusable */
+#define T_OVFLOW               12      /* Arithmetic overflow */
+#define        T_TRAP                  13      /* Trap instruction */
+#define        T_VCEI                  14      /* Viritual coherency instruction */
+#define        T_FPE                   15      /* Floating point exception */
+#define        T_WATCH                 23      /* Watch address reference */
+#define T_VCED                 31      /* Viritual coherency data */
+
+#define        T_USER                  0x20    /* user-mode flag or'ed with type */
diff --git a/sys/arch/wgrisc/include/types.h b/sys/arch/wgrisc/include/types.h
new file mode 100644 (file)
index 0000000..157e0b8
--- /dev/null
@@ -0,0 +1,82 @@
+/*     $OpenBSD: types.h,v 1.1.1.1 1997/02/06 16:02:43 pefo Exp $      */
+/*     $NetBSD: types.h,v 1.10 1995/07/06 03:39:43 cgd Exp $   */
+
+/*-
+ * Copyright (c) 1992, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Ralph Campbell.
+ *
+ * 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.
+ *
+ *     @(#)types.h     8.3 (Berkeley) 1/5/94
+ */
+
+#ifndef        _MACHTYPES_H_
+#define        _MACHTYPES_H_
+
+#include <sys/cdefs.h>
+
+#if !defined(_ANSI_SOURCE) && !defined(_POSIX_SOURCE)
+typedef struct _physadr {
+       int r[1];
+} *physadr;
+
+typedef struct label_t {
+       int val[12];
+} label_t;
+#endif
+
+typedef        unsigned long   vm_offset_t;
+typedef        unsigned long   vm_size_t;
+
+/*
+ * Basic integral types.  Omit the typedef if
+ * not possible for a machine/compiler combination.
+ */
+#define        __BIT_TYPES_DEFINED__
+typedef        __signed char              int8_t;
+typedef        unsigned char            u_int8_t;
+typedef        short                     int16_t;
+typedef        unsigned short          u_int16_t;
+typedef        int                       int32_t;
+typedef        unsigned int            u_int32_t;
+/* LONGLONG */
+typedef        long long                 int64_t;
+/* LONGLONG */
+typedef        unsigned long long      u_int64_t;
+
+typedef int32_t                        register_t;
+
+#define        __BDEVSW_DUMP_OLD_TYPE
+#define        __SWAP_BROKEN
+#define __FORK_BRAINDAMAGE
+
+#endif /* _MACHTYPES_H_ */
diff --git a/sys/arch/wgrisc/include/varargs.h b/sys/arch/wgrisc/include/varargs.h
new file mode 100644 (file)
index 0000000..90fb8b0
--- /dev/null
@@ -0,0 +1,69 @@
+/*     $OpenBSD: varargs.h,v 1.1.1.1 1997/02/06 16:02:43 pefo Exp $    */
+/*     $NetBSD: varargs.h,v 1.8 1995/03/28 18:19:30 jtc Exp $  */
+
+/*-
+ * Copyright (c) 1992, 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.
+ *
+ *     @(#)varargs.h   8.2 (Berkeley) 3/22/94
+ */
+
+#ifndef _MIPS_VARARGS_H_
+#define        _MIPS_VARARGS_H_
+
+#include <machine/ansi.h>
+
+typedef _BSD_VA_LIST_  va_list;
+
+#define        va_dcl  int va_alist; ...
+
+#define        va_start(ap) \
+       ap = (char *)&va_alist
+
+#ifdef _KERNEL
+#define        va_arg(ap, type) \
+       ((type *)(ap += sizeof(type)))[-1]
+#else
+#define        va_arg(ap, type) \
+       ((type *)(ap += sizeof(type) == sizeof(int) ? sizeof(type) : \
+               sizeof(type) > sizeof(int) ? \
+               (-(int)(ap) & (sizeof(type) - 1)) + sizeof(type) : \
+               (abort(), 0)))[-1]
+#endif
+
+#define        va_end(ap)      ((void) 0)
+
+#endif /* !_MIPS_VARARGS_H_ */
diff --git a/sys/arch/wgrisc/include/vmparam.h b/sys/arch/wgrisc/include/vmparam.h
new file mode 100644 (file)
index 0000000..d9d55fe
--- /dev/null
@@ -0,0 +1,229 @@
+/*     $OpenBSD: vmparam.h,v 1.1.1.1 1997/02/06 16:02:43 pefo Exp $    */
+/*     $NetBSD: vmparam.h,v 1.5 1994/10/26 21:10:10 cgd Exp $  */
+
+/*
+ * Copyright (c) 1988 University of Utah.
+ * Copyright (c) 1992, 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 and Ralph Campbell.
+ *
+ * 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/22/94
+ */
+
+/*
+ * Machine dependent constants.
+ */
+/*
+ * USRTEXT is the start of the user text/data space, while USRSTACK
+ * is the top (end) of the user stack.
+ */
+#define        USRTEXT         0x00400000
+#define        USRSTACK        0x80000000      /* Start of user stack */
+
+/*
+ * Virtual memory related constants, all in bytes
+ */
+#ifndef MAXTSIZ
+#define        MAXTSIZ         (24*1024*1024)          /* max text size */
+#endif
+#ifndef DFLDSIZ
+#define        DFLDSIZ         (32*1024*1024)          /* initial data size limit */
+#endif
+#ifndef MAXDSIZ
+#define        MAXDSIZ         (32*1024*1024)          /* max data size */
+#endif
+#ifndef        DFLSSIZ
+#define        DFLSSIZ         (1024*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; (really number of buffers for I/O) */
+#define        SYSPTSIZE       1228
+#define        USRPTSIZE       1024
+
+/*
+ * PTEs for mapping user space into the kernel for phyio operations.
+ * 16 pte's are enough to cover 8 disks * MAXBSIZE.
+ */
+#ifndef USRIOSIZE
+#define USRIOSIZE      32
+#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
+
+/*
+ * 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.
+ */
+
+#ifdef notdef /* XXX */
+#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)
+#else
+#define        KLMAX   (1/CLSIZE)
+#define        KLSEQL  (1/CLSIZE)
+#define        KLIN    (1/CLSIZE)
+#define        KLTXT   (1/CLSIZE)
+#define        KLOUT   (1/CLSIZE)
+#endif
+
+/*
+ * 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)0x00000000)
+#define VM_MAXUSER_ADDRESS     ((vm_offset_t)0x80000000)
+#define VM_MAX_ADDRESS         ((vm_offset_t)0x80000000)
+#define VM_MIN_KERNEL_ADDRESS  ((vm_offset_t)0xC0000000)
+#define VM_MAX_KERNEL_ADDRESS  ((vm_offset_t)0xFFFFC000)
+
+/* 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)
diff --git a/sys/arch/wgrisc/isa/isa_machdep.h b/sys/arch/wgrisc/isa/isa_machdep.h
new file mode 100644 (file)
index 0000000..c11655c
--- /dev/null
@@ -0,0 +1,84 @@
+/*      $OpenBSD: isa_machdep.h,v 1.1.1.1 1997/02/06 16:02:42 pefo Exp $  */
+
+/*
+ * Copyright (c) 1996 Per Fogelstrom
+ * 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 Per Fogelstrom
+ * 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 _ISA_MACHDEP_H_
+#define _ISA_MACHDEP_H_
+
+typedef struct wgrisc_isa_bus *isa_chipset_tag_t;
+
+/*
+ *      I/O macros to access isa bus ports/memory.
+ *      At the first glance theese macros may seem inefficient.
+ *      However, the cpu executes an instruction every 7.5ns
+ *      so the bus is much slower so it doesn't matter, really.
+ */
+#define isa_outb(x,y)   outb(isa_io_base + (x), y)
+#define isa_inb(x)      inb(isa_io_base + (x))
+extern int isa_io_base;                /* Base address for ISA I/O space       */ 
+extern int isa_mem_base;       /* Base address for ISA MEM space       */
+
+struct wgrisc_isa_bus {
+        void    *ic_data;
+
+        void    (*ic_attach_hook) __P((struct device *, struct device *,
+                    struct isabus_attach_args *));
+        void    *(*ic_intr_establish) __P((isa_chipset_tag_t, int, int, int,
+                    int (*)(void *), void *, char *));
+        void    (*ic_intr_disestablish) __P((isa_chipset_tag_t, void *));
+};
+
+
+/*
+ * Functions provided to machine-independent ISA code.
+ */
+#define isa_attach_hook(p, s, a)                             /*           \
+    (*(a)->iba_ic->ic_attach_hook)((p), (s), (a)) */
+#define isa_intr_establish(c, i, t, l, f, a, w)                         \
+    (*(c)->ic_intr_establish)((c)->ic_data, (i), (t), (l), (f), (a), (w))
+#define isa_intr_disestablish(c, h)                                     \
+    (*(c)->ic_intr_disestablish)((c)->ic_data, (h))
+
+/*
+ *     Interrupt control struct used to control the ICU setup.
+ */
+
+struct intrhand {
+       struct  intrhand *ih_next;
+       int     (*ih_fun) __P((void *));
+       void    *ih_arg;
+       u_long  ih_count;
+       int     ih_level;
+       int     ih_irq;
+       char    *ih_what;
+};
+
+#endif /* _ISA_MACHDEP_H_ */
diff --git a/sys/arch/wgrisc/isa/isabus.c b/sys/arch/wgrisc/isa/isabus.c
new file mode 100644 (file)
index 0000000..6a64a92
--- /dev/null
@@ -0,0 +1,350 @@
+/*     $OpenBSD: isabus.c,v 1.1.1.1 1997/02/06 16:02:42 pefo Exp $ */
+
+/*
+ * Copyright (c) 1996 Per Fogelstrom
+ * 
+ * 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 under OpenBSD by
+ *     Per Fogelstrom.
+ * 4. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/time.h>
+#include <sys/kernel.h>
+#include <sys/device.h>
+#include <sys/malloc.h>
+
+#include <machine/cpu.h>
+#include <machine/pio.h>
+#include <machine/autoconf.h>
+#include <machine/intr.h>
+#include <machine/bus.h>
+
+#include <wgrisc/wgrisc/wgrisctype.h>
+#include <wgrisc/riscbus/riscbus.h>
+
+#include <dev/isa/isareg.h>
+#include <dev/isa/isavar.h>
+#include <wgrisc/isa/isa_machdep.h>
+
+static int beeping;
+
+struct isabr_softc {
+       struct  device sc_dv;
+       struct  wgrisc_isa_bus wgrisc_isa_cs;
+       struct  abus sc_bus;
+};
+
+/* Definition of the driver for autoconfig. */
+int    isabrmatch(struct device *, void *, void *);
+void   isabrattach(struct device *, struct device *, void *);
+int    isabrprint(void *, const char *);
+
+struct cfattach isabr_ca = {
+       sizeof(struct isabr_softc), isabrmatch, isabrattach
+};
+struct cfdriver isabr_cd = {
+       NULL, "isabr", DV_DULL, NULL, 0
+};
+
+void   *isabr_intr_establish __P((isa_chipset_tag_t, int, int, int,
+                       int (*)(void *), void *, char *));
+void   isabr_intr_disestablish __P((isa_chipset_tag_t, void*));
+int    isabr_iointr __P((unsigned int, struct clockframe *));
+
+extern int cputype;
+
+int
+isabrmatch(parent, cfdata, aux)
+       struct device *parent;
+       void *cfdata;
+       void *aux;
+{
+       struct cfdata *cf = cfdata;
+       struct confargs *ca = aux;
+
+        /* Make sure that we're looking for a ISABR. */
+        if (strcmp(ca->ca_name, isabr_cd.cd_name) != 0)
+                return (0);
+
+       return (1);
+}
+
+void
+isabrattach(parent, self, aux)
+       struct device *parent;
+       struct device *self;
+       void *aux;
+{
+       struct isabr_softc *sc = (struct isabr_softc *)self;
+       struct isabus_attach_args iba;
+
+       printf("\n");
+
+       /* set up interrupt handlers */
+       switch(cputype) {
+       case WGRISC9100:
+               set_intr(INT_MASK_3 | INT_MASK_5, isabr_iointr, 1);
+               break;
+       default:
+               panic("isabrattach: unkown cputype!");
+       }
+
+/*XXX we may remove the abus part of the softc struct... */
+       sc->sc_bus.ab_dv = (struct device *)sc;
+       sc->sc_bus.ab_type = BUS_ISABR;
+
+       sc->wgrisc_isa_cs.ic_intr_establish = isabr_intr_establish;
+       sc->wgrisc_isa_cs.ic_intr_disestablish = isabr_intr_disestablish;
+
+       iba.iba_busname = "isa";
+       iba.iba_iot = (bus_space_tag_t)isa_io_base;
+       iba.iba_memt = (bus_space_tag_t)isa_mem_base;
+       iba.iba_ic = &sc->wgrisc_isa_cs;
+       config_found(self, &iba, isabrprint);
+}
+
+int
+isabrprint(aux, pnp)
+       void *aux;
+       const char *pnp;
+{
+       struct confargs *ca = aux;
+
+        if (pnp)
+                printf("%s at %s", ca->ca_name, pnp);
+        printf(" isa_io_base 0x%lx isa_mem_base 0x%lx", isa_io_base, isa_mem_base);
+        return (UNCONF);
+}
+
+/*
+ *     Interrupt system driver code
+ *     ============================
+ */
+
+int    intmask;
+int    intrmask[16], intrlevel[16];
+struct intrhand *intrhand[16];
+
+int fakeintr(void *a) {return 0;}
+
+/*
+ * Recalculate the interrupt masks from scratch.
+ * We could code special registry and deregistry versions of this function that
+ * would be faster, but the code would be nastier, and we don't expect this to
+ * happen very much anyway.
+ */
+void
+intr_calculatemasks()
+{
+       int irq, level;
+       struct intrhand *q;
+
+       /* First, figure out which levels each IRQ uses. */
+       for (irq = 0; irq < 16; irq++) {
+               register int levels = 0;
+               for (q = intrhand[irq]; q; q = q->ih_next)
+                       levels |= 1 << q->ih_level;
+               intrlevel[irq] = levels;
+       }
+
+       /* Then figure out which IRQs use each level. */
+       for (level = 0; level < 5; level++) {
+               register int irqs = 0;
+               for (irq = 0; irq < 8; irq++)
+                       if (intrlevel[irq] & (1 << level))
+                               irqs |= 1 << irq;
+               imask[level] = irqs | SIR_ALLMASK;
+       }
+
+       /*
+        * There are tty, network and disk drivers that use free() at interrupt
+        * time, so imp > (tty | net | bio).
+        */
+       imask[IPL_IMP] |= imask[IPL_TTY] | imask[IPL_NET] | imask[IPL_BIO];
+
+       /*
+        * Enforce a hierarchy that gives slow devices a better chance at not
+        * dropping data.
+        */
+       imask[IPL_TTY] |= imask[IPL_NET] | imask[IPL_BIO];
+       imask[IPL_NET] |= imask[IPL_BIO];
+
+       /*
+        * These are pseudo-levels.
+        */
+       imask[IPL_NONE] = 0x00000000;
+       imask[IPL_HIGH] = 0xffffffff;
+
+       /* And eventually calculate the complete masks. */
+       for (irq = 0; irq < 16; irq++) {
+               register int irqs = 1 << irq;
+               for (q = intrhand[irq]; q; q = q->ih_next)
+                       irqs |= imask[q->ih_level];
+               intrmask[irq] = irqs | SIR_ALLMASK;
+       }
+
+       /* Lastly, determine which IRQs are actually in use. */
+       {
+               register int irqs = 0;
+               for (irq = 0; irq < 16; irq++)
+                       if (intrhand[irq])
+                               irqs |= 1 << irq;
+               intmask = ~irqs;
+       }
+}
+
+/*
+ *     Establish a ISA bus interrupt.
+ */
+void *   
+isabr_intr_establish(ic, irq, type, level, ih_fun, ih_arg, ih_what)
+        isa_chipset_tag_t ic;
+        int irq;
+        int type;
+        int level;
+        int (*ih_fun) __P((void *));
+        void *ih_arg;
+        char *ih_what;
+{
+       struct intrhand **p, *q, *ih;
+       static struct intrhand fakehand = {NULL, fakeintr};
+       extern int cold;
+
+       /* no point in sleeping unless someone can free memory. */
+       ih = malloc(sizeof *ih, M_DEVBUF, cold ? M_NOWAIT : M_WAITOK);
+       if (ih == NULL)
+               panic("isa_intr_establish: can't malloc handler info");
+
+       /*
+        * Figure out where to put the handler.
+        * This is O(N^2), but we want to preserve the order, and N is
+        * generally small.
+        */
+       for (p = &intrhand[irq]; (q = *p) != NULL; p = &q->ih_next)
+               ;
+
+       /*
+        * Actually install a fake handler momentarily, since we might be doing
+        * this with interrupts enabled and don't want the real routine called
+        * until masking is set up.
+        */
+       fakehand.ih_level = level;
+       *p = &fakehand;
+
+       switch(irq) {
+       case 5:
+               break;
+       case 6:
+               intmask |= R3715_ISAIRQ_6;
+               break;
+       case 7:
+               intmask |= R3715_ISAIRQ_7;
+               break;
+       case 9:
+               intmask |= R3715_ISAIRQ_9;
+               break;
+       case 10:
+               intmask |= R3715_ISAIRQ_10;
+               break;
+       case 11:
+               intmask |= R3715_ISAIRQ_11;
+               break;
+       default:
+               printf("non available irq '%d' requested\n",irq);
+               panic("isa_intr_establish: can't establish");
+       }
+       out32(R3715_INT_MASK, intmask);
+
+       /*
+        * Poke the real handler in now.
+        */
+       ih->ih_fun = ih_fun;
+       ih->ih_arg = ih_arg;
+       ih->ih_count = 0;
+       ih->ih_next = NULL;
+       ih->ih_level = level;
+       ih->ih_irq = irq;
+       ih->ih_what = ih_what;
+       *p = ih;
+
+       return (ih);
+}
+
+void                    
+isabr_intr_disestablish(ic, arg)
+        isa_chipset_tag_t ic;
+        void *arg;      
+{               
+}
+
+/*
+ *     Process an interrupt from the ISA bus.
+ */
+int
+isabr_iointr(mask, cf)
+        unsigned mask;
+        struct clockframe *cf;
+{
+       struct intrhand *ih;
+       int isa_vector;
+       int cause;
+
+       do {
+               switch(cputype) {
+               case WGRISC9100:
+                       cause = in32(R3715_INT_CAUSE) & in32(R3715_INT_MASK);
+                       if(mask & INT_MASK_5) {
+                               isa_vector = 5;
+                               mask = 0;       /* Do this only once */
+                       }
+                       else if(cause & R3715_ISAIRQ_11)
+                               isa_vector = 11;
+                       else if(cause & R3715_ISAIRQ_7)
+                               isa_vector = 7;
+                       else if(cause & R3715_ISAIRQ_6)
+                               isa_vector = 6;
+                       else if(cause & R3715_ISAIRQ_9)
+                               isa_vector = 9;
+                       else if(cause & R3715_ISAIRQ_10)
+                               isa_vector = 10;
+                       else
+                               isa_vector = -1;
+                       break;
+               }
+
+               ih = intrhand[isa_vector];
+               while(ih) {
+                       (*ih->ih_fun)(ih->ih_arg);
+                       ih = ih->ih_next;
+               }
+       } while(isa_vector != -1);
+
+       return(~0);  /* Dont reenable */
+}
+
diff --git a/sys/arch/wgrisc/riscbus/riscbus.c b/sys/arch/wgrisc/riscbus/riscbus.c
new file mode 100644 (file)
index 0000000..97743a9
--- /dev/null
@@ -0,0 +1,318 @@
+/*     $OpenBSD: riscbus.c,v 1.1.1.1 1997/02/06 16:02:44 pefo Exp $ */
+
+/*
+ * Copyright (c) 1996 Per Fogelstrom
+ * 
+ * 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 under OpenBSD by
+ *     Per Fogelstrom.
+ * 4. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+
+#include <sys/param.h>
+#include <sys/device.h>
+
+#include <machine/cpu.h>
+#include <machine/pio.h>
+#include <machine/autoconf.h>
+
+#include <wgrisc/riscbus/riscbus.h>
+#include <wgrisc/wgrisc/wgrisctype.h>
+
+struct riscbus_softc {
+       struct  device sc_dv;
+       struct  abus sc_bus;
+       struct  riscbus_dev *sc_devs;
+};
+
+/* Definition of the driver for autoconfig. */
+int    riscbusmatch(struct device *, void *, void *);
+void   riscbusattach(struct device *, struct device *, void *);
+int    riscbusprint(void *, const char *);
+
+struct cfattach riscbus_ca = {
+       sizeof(struct riscbus_softc), riscbusmatch, riscbusattach
+};
+struct cfdriver riscbus_cd = {
+       NULL, "riscbus", DV_DULL, NULL, 0
+};
+
+void   riscbus_intr_establish __P((struct confargs *, int (*)(void *), void *));
+void   riscbus_intr_disestablish __P((struct confargs *));
+caddr_t        riscbus_cvtaddr __P((struct confargs *));
+int    riscbus_matchname __P((struct confargs *, char *));
+int    riscbus_iointr __P((unsigned, struct clockframe *));
+int    riscbus_clkintr __P((unsigned, struct clockframe *));
+
+extern int cputype;
+
+/*
+ *  Interrupt dispatch table.
+ */
+struct riscbus_int_desc int_table[] = {
+       {0, riscbus_intrnull, (void *)NULL, 0 },  /*  0 */
+       {0, riscbus_intrnull, (void *)NULL, 0 },  /*  1 */
+       {0, riscbus_intrnull, (void *)NULL, 0 },  /*  2 */
+       {0, riscbus_intrnull, (void *)NULL, 0 },  /*  3 */
+       {0, riscbus_intrnull, (void *)NULL, 0 },  /*  4 */
+       {0, riscbus_intrnull, (void *)NULL, 0 },  /*  5 */
+       {0, riscbus_intrnull, (void *)NULL, 0 },  /*  6 */
+       {0, riscbus_intrnull, (void *)NULL, 0 },  /*  7 */
+       {0, riscbus_intrnull, (void *)NULL, 0 },  /*  8 */
+       {0, riscbus_intrnull, (void *)NULL, 0 },  /*  9 */
+       {0, riscbus_intrnull, (void *)NULL, 0 },  /* 10 */
+       {0, riscbus_intrnull, (void *)NULL, 0 },  /* 11 */
+       {0, riscbus_intrnull, (void *)NULL, 0 },  /* 12 */
+       {0, riscbus_intrnull, (void *)NULL, 0 },  /* 13 */
+       {0, riscbus_intrnull, (void *)NULL, 0 },  /* 14 */
+       {0, riscbus_intrnull, (void *)NULL, 0 },  /* 15 */
+};
+
+struct riscbus_dev {
+       struct confargs ps_ca;
+       u_int           ps_mask;
+       intr_handler_t  ps_handler;
+       void            *ps_base;
+};
+#ifdef WGRISC9100
+struct riscbus_dev wgrisc9100_cpu[] = {
+       {{ "dp8571rtc", 0, 0, },
+          INT_MASK_2,  riscbus_intrnull, (void *)RISC_RTC, },
+       {{ "sonic",     1, 0, },
+          INT_MASK_4,  riscbus_intrnull, (void *)RISC_SONIC, },
+       {{ "asc",       2, 0, },
+          INT_MASK_1,  riscbus_intrnull, (void *)RISC_SCSI, },
+       {{ "com",       3, NULL, },
+          INT_MASK_5,  riscbus_intrnull, (void *)RISC_COM0, },
+       {{ "com",       4, 0, },
+          INT_MASK_5,  riscbus_intrnull, (void *)RISC_COM1, },
+       {{ "com",       5, 0, },
+          INT_MASK_5,  riscbus_intrnull, (void *)RISC_COM2, },
+       {{ "com",       6, 0, },
+          INT_MASK_5,  riscbus_intrnull, (void *)RISC_COM3, },
+       {{ NULL,       -1, NULL, },
+          0, NULL, (void *)NULL, },
+};
+#define NUM_RISC_DEVS (sizeof(wgrisc9100_cpu) / sizeof(struct riscbus_dev))
+#endif
+
+struct riscbus_dev *riscbus_cpu_devs[] = {
+        NULL,                   /* 0: Unused */
+#ifdef WGRISC9100
+        wgrisc9100_cpu,                /* 1: WGRISC 9100 R3081 board */
+#else
+       NULL,
+#endif
+};
+int nriscbus_cpu_devs = sizeof riscbus_cpu_devs / sizeof riscbus_cpu_devs[0];
+
+int local_int_mask = 0;        /* Local interrupt enable mask */
+
+int
+riscbusmatch(parent, cfdata, aux)
+       struct device *parent;
+       void *cfdata;
+       void *aux;
+{
+       struct cfdata *cf = cfdata;
+       struct confargs *ca = aux;
+
+        /* Make sure that we're looking for a RISC bus. */
+        if (strcmp(ca->ca_name, riscbus_cd.cd_name) != 0)
+                return (0);
+
+        /* Make sure that unit exists. */
+       if (cf->cf_unit != 0 ||
+           cputype > nriscbus_cpu_devs || riscbus_cpu_devs[cputype] == NULL)
+               return (0);
+
+       return (1);
+}
+
+void
+riscbusattach(parent, self, aux)
+       struct device *parent;
+       struct device *self;
+       void *aux;
+{
+       struct riscbus_softc *sc = (struct riscbus_softc *)self;
+       struct confargs *nca;
+       int i;
+
+       printf("\n");
+
+       /* keep our CPU device description handy */
+       sc->sc_devs = riscbus_cpu_devs[cputype];
+
+       /* set up interrupt handlers */
+       set_intr(INT_MASK_1 | INT_MASK_4 | INT_MASK_5, riscbus_iointr, 2);
+
+       sc->sc_bus.ab_dv = (struct device *)sc;
+       sc->sc_bus.ab_type = BUS_RISC;
+       sc->sc_bus.ab_intr_establish = riscbus_intr_establish;
+       sc->sc_bus.ab_intr_disestablish = riscbus_intr_disestablish;
+       sc->sc_bus.ab_cvtaddr = riscbus_cvtaddr;
+       sc->sc_bus.ab_matchname = riscbus_matchname;
+
+       /* Try to configure each attached device */
+       for (i = 0; sc->sc_devs[i].ps_ca.ca_slot >= 0; i++) {
+
+               if(sc->sc_devs[i].ps_ca.ca_name == NULL)
+                       continue; /* Empty slot */
+
+               nca = &sc->sc_devs[i].ps_ca;
+               nca->ca_bus = &sc->sc_bus;
+
+               /* Tell the autoconfig machinery we've found the hardware. */
+               config_found(self, nca, riscbusprint);
+       }
+}
+
+int
+riscbusprint(aux, pnp)
+       void *aux;
+       const char *pnp;
+{
+       struct confargs *ca = aux;
+
+        if (pnp)
+                printf("%s at %s", ca->ca_name, pnp);
+        printf(" slot %ld offset 0x%lx", ca->ca_slot, ca->ca_offset);
+        return (UNCONF);
+}
+
+caddr_t
+riscbus_cvtaddr(ca)
+       struct confargs *ca;
+{
+       struct riscbus_softc *sc = riscbus_cd.cd_devs[0];
+
+       return(sc->sc_devs[ca->ca_slot].ps_base + ca->ca_offset);
+
+}
+
+void
+riscbus_intr_establish(ca, handler, val)
+       struct confargs *ca;
+       intr_handler_t handler;
+       void *val;
+{
+       struct riscbus_softc *sc = riscbus_cd.cd_devs[0];
+
+       int slot;
+
+       slot = ca->ca_slot;
+
+       if(int_table[slot].int_mask != 0) {
+               panic("riscbus intr already set");
+       }
+       else {
+               int_table[slot].int_mask = sc->sc_devs[slot].ps_mask;
+               local_int_mask |= int_table[slot].int_mask;
+               int_table[slot].int_hand = handler;
+               int_table[slot].param = val;
+       }
+       if(slot == 0) {         /* Slot 0 is special, clock */
+               set_intr(int_table[0].int_mask, riscbus_clkintr, 0);
+       }
+}
+
+void
+riscbus_intr_disestablish(ca)
+       struct confargs *ca;
+{
+       struct riscbus_softc *sc = riscbus_cd.cd_devs[0];
+
+       int slot;
+
+       slot = ca->ca_slot;
+       if(slot = 0) {          /* Slot 0 is special, clock */
+       }
+       else {
+               local_int_mask &= ~int_table[slot].int_mask;
+               int_table[slot].int_mask = 0;
+               int_table[slot].int_hand = riscbus_intrnull;
+               int_table[slot].param = (void *)NULL;
+       }
+}
+
+int
+riscbus_matchname(ca, name)
+       struct confargs *ca;
+       char *name;
+{
+
+       return (strcmp(name, ca->ca_name) == 0);
+}
+
+int
+riscbus_intrnull(val)
+       void *val;
+{
+       panic("uncaught RISCBUS interrupt for slot %d\n", val);
+}
+
+/*
+ *   Handle riscbus i/o interrupt the generic way.
+ */
+int
+riscbus_iointr(mask, cf)
+       unsigned mask;
+       struct clockframe *cf;
+{
+       int i;
+
+       for(i = 0; i < NUM_RISC_DEVS; i++) {
+               if(mask & int_table[i].int_mask)
+                       (*int_table[i].int_hand)(int_table[i].param);
+       }
+       return(~0);  /* Dont reenable */
+}
+
+/*
+ * Handle riscbus interval clock interrupt.
+ */
+int
+riscbus_clkintr(mask, cf)
+       unsigned mask;
+       struct clockframe *cf;
+{
+       int temp;
+
+       switch (cputype) {
+
+       case WGRISC9100:
+               if(dpclock_interrupt())
+                        hardclock(cf); 
+               break;
+       }
+
+       /* Re-enable clock interrupts */
+       splx(int_table[0].int_mask | SR_INT_ENAB);
+
+       return(~int_table[0].int_mask); /* Keep clock interrupts enabled */
+}
+
diff --git a/sys/arch/wgrisc/riscbus/riscbus.h b/sys/arch/wgrisc/riscbus/riscbus.h
new file mode 100644 (file)
index 0000000..fe16a69
--- /dev/null
@@ -0,0 +1,118 @@
+/*     $OpenBSD: riscbus.h,v 1.1.1.1 1997/02/06 16:02:44 pefo Exp $ */
+
+/*
+ * Copyright (c) 1996 Per Fogelstrom
+ * 
+ * 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 under OpenBSD by
+ *     Per Fogelstrom.
+ * 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        RISCBUS_H
+#define        RISCBUS_H 1
+
+#define RISC_PHYS_MIN          0x00000000      /* 256 Meg */
+#define RISC_PHYS_MAX          0x01ffffff
+
+/*
+ * Memory map
+ */
+
+#define RISC_PHYS_MEMORY_START 0x00000000
+#define RISC_PHYS_MEMORY_END   0x01ffffff      /* 256 Meg in 8 slots */
+
+#define        RISC_SRAM_START         0xbfb00000      /* Static ram */
+
+/*
+ * I/O map
+ */
+
+#define        RISC_ISA_IO_BASE        0xac000000      /* ISA I/O base adderss */
+#define        RISC_ISA_MEM_BASE       0xad000000      /* ISA MEM base adderss */
+#define        RISC_LOCAL_IO_BASE      0xae000000      /* I/O Base address */
+
+#define        RISC_COM0               0xae400000      /* 16550 */
+#define        RISC_COM1               0xae410000      /* 16550 */
+#define        RISC_COM2               0xae420000      /* 16550 */
+#define        RISC_COM3               0xae430000      /* 16550 */
+#define        RISC_SCSI               0xae440000      /* AMD53C94 */
+#define        RISC_RTC                0xae450000      /* DP8571 */
+#define        RISC_SONIC              0xae460000      /* DP83932 */
+#define        RISC_SONIC_SRAM         0xae470000      /* 2 * 32KB 70ns sram */
+
+#define        RISC_CTRL1              0xae800000      /* Watchdog control */
+#define        RISC_CTRL2              0xae810000      /* System control */
+#define        RISC_STATUS             0xae820000      /* System status */
+#define        RISC_FLASH_CTRL         0xae840000      /* Flash */
+#define        RISC_FLASH_WRITE        0xae850000      /* Flash */
+#define        RISC_FLASH_READ         0xae860000      /* Flash */
+#define        RISC_LEDS               0xae870000      /* System LEDS */
+
+/*
+ * I/O map of R3715 chip.
+ */
+#define        R3715_ROM_CONF          0xbd000000      /* Rom config reg */
+#define        R3715_PIO_VAL           0xbd000040      /* PIO value reg */
+#define        R3715_PIO_CTRL          0xbd000044      /* PIO control reg */
+#define        R3715_PIO_READ          0xbd00005c      /* PIO read (pin) reg */
+#define        R3715_TC_VAL            0xbd000048      /* Timer/Counter value reg */
+#define        R3715_TC_CTRL           0xbd00004c      /* Timer/Counter control reg */
+#define        R3715_INT_CAUSE         0xbd000050      /* R3715 Interrupt cause */
+#define        R3715_INT_MASK          0xbd000054      /* R3715 Interrupt mask */
+#define        R3715_INT_WRITE         0xbd000060      /* R3715 Interrupt write */
+#define        R3715_DRAM_CTRL         0xbd000058      /* R3715 DRAM Control */
+#define        R3715_DMA_ADR0          0xbd000080      /* R3715 DMA Address 0 */
+#define        R3715_DMA_ADR1          0xbd000084      /* R3715 DMA Address 1 */
+#define        R3715_DMA_CNT0          0xbd000090      /* R3715 DMA Size count 0 */
+#define        R3715_DMA_CNT1          0xbd000044      /* R3715 DMA Size count 1 */
+#define        R3715_IO_TIMING         0xbd0000a0      /* R3715 I/O Timing control */
+
+/*
+ * R3715 Interrupt control register bits.
+ */
+#define        R3715_ISAIRQ_11         0x00100000
+#define        R3715_ISAIRQ_7          0x00200000
+#define        R3715_ISAIRQ_6          0x00400000
+#define        R3715_ISAIRQ_9          0x00800000
+#define        R3715_ISAIRQ_10         0x01000000
+#define        R3715_DSPINT            0x02000000
+#define        R3715_TIMINT            0x00000010
+#define        R3715_DMA_INT0          0x00000020
+#define        R3715_DMA_INT1          0x00000040
+
+/*
+ *  Interrupt vector descriptor for device on risc bus.
+ */
+struct riscbus_int_desc {
+       int             int_mask;       /* Mask to call handler at */
+       intr_handler_t  int_hand;       /* Interrupt handler */
+       void            *param;         /* Parameter to send to handler */
+       int             spl_mask;       /* Spl mask for interrupt */
+};
+
+int    riscbus_intrnull __P((void *));
+#endif /* RISCBUS_H */
diff --git a/sys/arch/wgrisc/stand/Makefile b/sys/arch/wgrisc/stand/Makefile
new file mode 100644 (file)
index 0000000..a7dd638
--- /dev/null
@@ -0,0 +1,96 @@
+#      $NetBSD: Makefile,v 1.5 1995/01/18 06:53:36 mellon Exp $
+#      @(#)Makefile    8.3 (Berkeley) 2/16/94
+
+DESTDIR=
+STAND= ../../stand
+#VPATH=        ${STAND}
+
+# RELOC=80200000 allows for boot prog up to 1D0000 (1900544) bytes long
+RELOC= 80200000
+
+S=      ../../..
+
+DEFS= -DSTANDALONE -DDEBUG
+CFLAGS=        -O2 ${INCPATH} ${DEFS}
+AFLAGS=        -O2 ${INCPATH} ${DEFS} -DLOCORE
+
+.PATH: ${S}/arch/${MACHINE_ARCH}/${MACHINE_ARCH}
+.PATH: ${S}/stand ${S}/lib/libsa
+
+#INCPATH=-I. -I/sys
+INCPATH=-I${.CURDIR} -I${.CURDIR}/../.. -I${S} -I${S}/lib/libsa
+
+### find out what to use for libkern
+.include "$S/lib/libkern/Makefile.inc"
+LIBKERN= ${KERNLIB}
+#KERNLIB= ${.CURDIR}/../compile/libkern.a
+
+.include "$S/lib/libsa/Makefile.inc"
+LIBSA=  ${SA_LIB}
+
+# not yet: need to write libsa/Makefile.inc first
+LIBS=  ${.OBJDIR}/libdrive.a ${.CURDIR}/libsa/libsa.a  ${KERNLIB}
+#LIBS= libdrive.a libsa/libsa.a ../../libkern/obj/libkern.a 
+
+DRIVERS= rz.c
+SRCS=  ${DRIVERS}
+#STUFF=        callvec.c devopen.c getenv.c gets.c strcmp.c
+STUFF=
+
+ALL=   boot
+
+.s.o:
+       ${CPP} -E ${CFLAGS:M-[ID]*} ${AINC} ${.IMPSRC} | \
+           ${AS} -o ${.TARGET}
+
+all: ${ALL}
+
+boot: ${LIBS}
+
+#libsa/libsa.a::
+#      cd libsa; make
+
+${.OBJDIR}/libdrive.a: conf.o ${DRIVERS:.c=.o}
+       ar crv $@ $?
+       ranlib $@
+
+# depend on DEFS
+
+#before other deps on bootconf.o
+bootconf.o: conf.o
+       rm -f bootconf.c
+       ln -s ${.CURDIR}/conf.c bootconf.c
+       ${CC} -c ${CFLAGS} -DBOOT bootconf.c
+       rm -f bootconf.c
+
+
+# bootable from real disks
+
+boot:  start.o boot.o bootconf.o filesystem.o ${LIBS}
+       /usr/gnu/ld -N -Ttext ${RELOC} -e __start start.o boot.o bootconf.o filesystem.o ${LIBS} -o boot.elf
+       elf2ecoff boot.elf boot
+
+start.o: ${.CURDIR}/start.S
+
+#      ${CPP} -E ${CFLAGS:M-[ID]*} -DLOCORE ${AINC} ${.IMPSRC} | \
+#          ${AS} -o ${.TARGET}
+
+mkboot: ${.CURDIR}/mkboot.c
+       ${CC} ${CFLAGS} -o mkboot ${.CURDIR}/mkboot.c
+
+# utilities
+
+clean::
+       rm -f .depend *.o *.exe *.i errs make.out core*
+       rm -f a.out ${ALL}
+       rm -f libdrive.a
+       cd libsa; make cleandir
+
+install:
+
+depend: ${SRCS}
+       mkdep ${INCPATH} ${DEFS} ${SRCS}
+       cd libsa; make depend
+
+.include <bsd.dep.mk>
+.include <bsd.obj.mk>
diff --git a/sys/arch/wgrisc/stand/boot.c b/sys/arch/wgrisc/stand/boot.c
new file mode 100644 (file)
index 0000000..170f6f9
--- /dev/null
@@ -0,0 +1,114 @@
+/*     $NetBSD: boot.c,v 1.6 1995/06/28 10:22:32 jonathan Exp $        */
+
+/*
+ * Copyright (c) 1992, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Ralph Campbell.
+ *
+ * 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/exec.h>
+#include <stand.h>
+
+
+char   line[1024];
+
+/*
+ * This gets arguments from the PROM, calls other routines to open
+ * and load the program to boot, and then transfers execution to that
+ * new program.
+ * Argv[0] should be something like "rz(0,0,0)vmunix" on a DECstation 3100.
+ * Argv[0,1] should be something like "boot 5/rz0/vmunix" on a DECstation 5000.
+ * The argument "-a" means vmunix should do an automatic reboot.
+ */
+int
+main(argc, argv)
+       int argc;
+       char **argv;
+{
+       char *cp;
+       int   ask, entry;
+       int   i;
+
+       ask = 1;
+
+       for(i = 0; i < argc; i++)
+               printf("Arg %d:%s\n",i,argv[i]);
+
+       do {
+               printf("Boot: ");
+               if (ask) {
+                       gets(line);
+                       cp = line;
+                       argv[0] = cp;
+                       argc = 1;
+               } else
+                       printf("%s\n", cp);
+       } while(ask && line[0] == '\0');
+
+       entry = loadfile(cp);
+       if (entry == -1) {
+               gets(line);
+               return 0;
+       }
+
+       printf("Starting at 0x%x\n\n", entry);
+       ((void (*)())entry)(argc, argv, 0, 0);
+}
+
+/*
+ * Open 'filename', read in program and return the entry point or -1 if error.
+ */
+loadfile(fname)
+       register char *fname;
+{
+       struct devices *dp;
+       int fd, i, n;
+       struct exec aout;
+
+       if ((fd = open(fname, 0)) < 0) {
+               printf("open(%s) failed: %d\n", fname, errno);
+               goto err;
+       }
+
+       /* read the exec header */
+       i = read(fd, (char *)&aout, sizeof(aout));
+
+cerr:
+       (void) close(fd);
+err:
+       printf("Can't boot '%s'\n", fname);
+       return (-1);
+}
diff --git a/sys/arch/wgrisc/stand/conf.c b/sys/arch/wgrisc/stand/conf.c
new file mode 100644 (file)
index 0000000..cecbc70
--- /dev/null
@@ -0,0 +1,70 @@
+/*     $NetBSD: conf.c,v 1.5 1995/01/18 06:53:39 mellon Exp $  */
+
+/*
+ * Copyright (c) 1992, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Ralph Campbell.
+ *
+ * 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      8.1 (Berkeley) 6/10/93
+ */
+
+#include <stand.h>
+
+int    errno;
+
+extern void    nullsys();
+extern int     nodev(), noioctl();
+
+int    rzstrategy(), rzopen();
+#ifdef SMALL
+#define rzclose 0
+#else  /*!SMALL*/
+int     rzclose();
+#endif /*!SMALL*/
+
+#define        rzioctl         noioctl
+
+#ifndef BOOT
+int    tzstrategy(), tzopen(), tzclose();
+#endif
+#define        tzioctl         noioctl
+
+
+struct devsw devsw[] = {
+       { "rz", rzstrategy,     rzopen, rzclose,        rzioctl }, /*0*/
+#ifndef BOOT
+       { "tz", tzstrategy,     tzopen, tzclose,        tzioctl }, /*1*/
+#endif
+};
+
+int    ndevs = (sizeof(devsw)/sizeof(devsw[0]));
diff --git a/sys/arch/wgrisc/stand/filesystem.c b/sys/arch/wgrisc/stand/filesystem.c
new file mode 100644 (file)
index 0000000..514e6e8
--- /dev/null
@@ -0,0 +1,44 @@
+/*     $NetBSD: filesystem.c,v 1.2 1995/02/16 02:33:05 cgd Exp $       */
+
+/*
+ * Copyright (c) 1993 Philip A. Nelson.
+ * 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 Philip A. Nelson.
+ * 4. The name of Philip A. Nelson may not be used to endorse or promote
+ *    products derived from this software without specific prior written
+ *    permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY PHILIP NELSON ``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 PHILIP NELSON 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.
+ *
+ *     filesystem.c
+ */
+
+#include <lib/libsa/stand.h>
+#include <lib/libsa/ufs.h>
+struct fs_ops file_system[] = {
+       { ufs_open, ufs_close, ufs_read, ufs_write, ufs_seek, ufs_stat },
+};
+int nfsys = sizeof(file_system)/sizeof(struct fs_ops);
+
diff --git a/sys/arch/wgrisc/stand/libsa/Makefile b/sys/arch/wgrisc/stand/libsa/Makefile
new file mode 100644 (file)
index 0000000..d147171
--- /dev/null
@@ -0,0 +1,14 @@
+#      $NetBSD: Makefile,v 1.5 1995/01/18 06:53:51 mellon Exp $
+#      @(#)Makefile    8.2 (Berkeley) 2/16/94
+
+LIB=   sa
+SRCS=  alloc.c bcopy.c bzero.c close.c dev.c disklabel.c getfile.c \
+       getputchar.c ioctl.c lseek.c open.c printf.c read.c ufs.c write.c \
+       devopen.c getenv.c gets.c strcat.c strcmp.c strcpy.c strlen.c
+
+.PATH: ../../../../lib/libsa ../../../../lib/libkern
+NOPROFILE=noprofile
+
+.include <bsd.lib.mk>
+
+CFLAGS=-O2 -I../../include -I/sys -DSMALL
diff --git a/sys/arch/wgrisc/stand/libsa/devopen.c b/sys/arch/wgrisc/stand/libsa/devopen.c
new file mode 100644 (file)
index 0000000..79b35f8
--- /dev/null
@@ -0,0 +1,128 @@
+/*     $NetBSD: devopen.c,v 1.5 1995/01/18 06:53:54 mellon Exp $       */
+
+/*-
+ * Copyright (c) 1992, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Ralph Campbell.
+ *
+ * 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.
+ *
+ *     @(#)devopen.c   8.1 (Berkeley) 6/10/93
+ */
+
+#include <lib/libsa/stand.h>
+
+/*
+ * Decode the string 'fname', open the device and return the remaining
+ * file name if any.
+ */
+devopen(f, fname, file)
+       struct open_file *f;
+       const char *fname;
+       char **file;    /* out */
+{
+       register char *cp;
+       register char *ncp;
+       register struct devsw *dp;
+       register int c, i;
+       int ctlr = 0, unit = 0, part = 0;
+       char namebuf[20];
+       int rc;
+
+       cp = fname;
+       ncp = namebuf;
+
+               /* expect a string like 'rz(0,0,0)vmunix' */
+               while ((c = *cp) != '\0') {
+                       if (c == '(') {
+                               cp++;
+                               break;
+                       }
+                       if (ncp < namebuf + sizeof(namebuf) - 1)
+                               *ncp++ = c;
+                       cp++;
+               }
+
+               /* get controller number */
+               if ((c = *cp) >= '0' && c <= '9') {
+                       ctlr = c - '0';
+                       c = *++cp;
+               }
+
+               if (c == ',') {
+                       /* get SCSI device number */
+                       if ((c = *++cp) >= '0' && c <= '9') {
+                               unit = c - '0';
+                               c = *++cp;
+                       }
+
+                       if (c == ',') {
+                               /* get partition number */
+                               if ((c = *++cp) >= '0' && c <= '9') {
+                                       part = c - '0';
+                                       c = *++cp;
+                               }
+                       }
+               }
+               if (c != ')')
+                       return (ENXIO);
+               cp++;
+       *ncp = '\0';
+
+#ifdef SMALL
+       if (strcmp (namebuf, "rz")) {
+               printf ("Unknown device: %s\n", namebuf);
+               return ENXIO;
+       }
+       dp = devsw;
+       i = 0;
+#else
+       for (dp = devsw, i = 0; i < ndevs; dp++, i++)
+               if (dp->dv_name && strcmp(namebuf, dp->dv_name) == 0)
+                       goto fnd;
+       printf("Unknown device '%s'\nKnown devices are:", namebuf);
+       for (dp = devsw, i = 0; i < ndevs; dp++, i++)
+               if (dp->dv_name)
+                       printf(" %s", dp->dv_name);
+       printf("\n");
+       return (ENXIO);
+
+fnd:
+#endif
+       rc = (dp->dv_open)(f, ctlr, unit, part);
+       if (rc)
+               return (rc);
+
+       f->f_dev = dp;
+       if (file && *cp != '\0')
+               *file = cp;
+       return (0);
+}
diff --git a/sys/arch/wgrisc/stand/libsa/getenv.c b/sys/arch/wgrisc/stand/libsa/getenv.c
new file mode 100644 (file)
index 0000000..7e063cd
--- /dev/null
@@ -0,0 +1,45 @@
+/*     $NetBSD: getenv.c,v 1.5 1995/01/18 06:53:55 mellon Exp $        */
+
+/*-
+ * Copyright (c) 1992, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Ralph Campbell.
+ *
+ * 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.
+ *
+ *     @(#)getenv.c    8.1 (Berkeley) 6/10/93
+ */
+
+char *
+getenv(s)
+       char *s;
+{
+}
diff --git a/sys/arch/wgrisc/stand/libsa/getputchar.c b/sys/arch/wgrisc/stand/libsa/getputchar.c
new file mode 100644 (file)
index 0000000..dbfae22
--- /dev/null
@@ -0,0 +1,69 @@
+/*     $NetBSD: getenv.c,v 1.5 1995/01/18 06:53:55 mellon Exp $        */
+
+/*-
+ * Copyright (c) 1992, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Ralph Campbell.
+ *
+ * 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.
+ *
+ *     @(#)getenv.c    8.1 (Berkeley) 6/10/93
+ */
+
+getchar()
+{
+       char buf[4];
+       int  cnt;
+
+       if(Bios_Read(0, &buf, 1, &cnt) != 0)
+               return(-1);
+       return(buf[0] & 255);
+}
+
+putchar(c)
+char c;
+{
+       char buf[4];
+       int  cnt;
+
+       if(c == '\n') {
+               buf[0] = '\r';
+               buf[1] = c;
+               cnt = 2;
+       }
+       else {
+               buf[0] = c;
+               cnt = 1;
+       }
+       if(Bios_Write(1, &buf, cnt, &cnt) != 0)
+               return(-1);
+       return(0);
+}
diff --git a/sys/arch/wgrisc/stand/rz.c b/sys/arch/wgrisc/stand/rz.c
new file mode 100644 (file)
index 0000000..1094aef
--- /dev/null
@@ -0,0 +1,174 @@
+/*     $NetBSD: rz.c,v 1.6 1995/06/28 10:22:35 jonathan Exp $  */
+
+/*
+ * Copyright (c) 1992, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Van Jacobson of Lawrence Berkeley Laboratory and Ralph Campbell.
+ *
+ * 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.
+ *
+ *     @(#)rz.c        8.1 (Berkeley) 6/10/93
+ */
+
+#include <stdarg.h>
+
+#include <stand.h>
+#include <sys/param.h>
+#include <sys/disklabel.h>
+
+struct rz_softc {
+       int     sc_fd;                  /* PROM file id */
+       int     sc_ctlr;                /* controller number */
+       int     sc_unit;                /* disk unit number */
+       int     sc_part;                /* disk partition number */
+       struct  disklabel sc_label;     /* disk label for this disk */
+};
+
+int
+rzstrategy(devdata, rw, bn, reqcnt, addr, cnt)
+       void *devdata;
+       int rw;
+       daddr_t bn;
+       u_int reqcnt;
+       char *addr;
+       u_int *cnt;     /* out: number of bytes transfered */
+{
+       register struct rz_softc *sc = (struct rz_softc *)devdata;
+       register int part = sc->sc_part;
+       register struct partition *pp = &sc->sc_label.d_partitions[part];
+       register int s;
+       long offset;
+
+       offset = bn * DEV_BSIZE;
+
+#ifdef DEBUG
+/*XXX*/printf("rz:%x %d\n", offset, reqcnt);
+#endif
+
+       /*
+        * Partial-block transfers not handled.
+        */
+       if (reqcnt & (DEV_BSIZE - 1)) {
+               *cnt = 0;
+               return (EINVAL);
+       }
+
+       offset += pp->p_offset * DEV_BSIZE;
+
+       if (Bios_Seek(sc->sc_fd, &offset, 0) != 0)
+               return (EIO);
+       s = Bios_Read(sc->sc_fd, addr, reqcnt, &reqcnt);
+       if (s != 0)
+               return (EIO);
+
+       *cnt = reqcnt;
+       return (0);
+}
+
+int
+rzopen(struct open_file *f, ...)
+{
+       int ctlr, unit, part;
+
+       struct rz_softc *sc;
+       struct disklabel *lp;
+       int i, fd;
+       char *msg;
+       char buf[DEV_BSIZE];
+       int cnt;
+       static char device[] = "scsi()disk(0)rdisk()";
+       va_list ap;
+
+       va_start(ap, f);
+
+       ctlr = va_arg(ap, int);
+       unit = va_arg(ap, int);
+       part = va_arg(ap, int);
+       if (unit >= 8 || part >= 8)
+               return (ENXIO);
+#if 0
+       device[5] = '0' + unit;
+#endif
+       /* NOTE: only support reads for now */
+
+       i = Bios_Open(device, 0, &fd);
+       if (i != 0) {
+               printf("boot init failed error code %d\n", i);
+               return (ENXIO);
+       }
+
+       sc = alloc(sizeof(struct rz_softc));
+       bzero(sc, sizeof(struct rz_softc));
+       f->f_devdata = (void *)sc;
+
+       sc->sc_fd = fd;
+       sc->sc_ctlr = ctlr;
+       sc->sc_unit = unit;
+       sc->sc_part = part;
+
+       /* try to read disk label and partition table information */
+       lp = &sc->sc_label;
+       lp->d_secsize = DEV_BSIZE;
+       lp->d_secpercyl = 1;
+       lp->d_npartitions = MAXPARTITIONS;
+       lp->d_partitions[part].p_offset = 0;
+       lp->d_partitions[part].p_size = 0x7fffffff;
+       i = rzstrategy(sc, F_READ, (daddr_t)LABELSECTOR, DEV_BSIZE, buf, &cnt);
+       if (i || cnt != DEV_BSIZE) {
+               printf("rz%d: error reading disk label\n", unit);
+               goto bad;
+       } else {
+               msg = getdisklabel(buf, lp);
+               if (msg) {
+                       printf("rz%d: %s\n", unit, msg);
+                       goto bad;
+               }
+       }
+
+       if (part >= lp->d_npartitions || lp->d_partitions[part].p_size == 0) {
+       bad:
+#ifndef SMALL
+               free(sc, sizeof(struct rz_softc));
+#endif
+               return (ENXIO);
+       }
+       return (0);
+}
+
+#ifndef SMALL
+rzclose(f)
+       struct open_file *f;
+{
+       free(f->f_devdata, sizeof(struct rz_softc));
+       f->f_devdata = (void *)0;
+       return (0);
+}
+#endif
diff --git a/sys/arch/wgrisc/stand/start.S b/sys/arch/wgrisc/stand/start.S
new file mode 100644 (file)
index 0000000..09114a9
--- /dev/null
@@ -0,0 +1,129 @@
+/*     $NetBSD: start.S,v 1.1 1995/01/18 06:19:01 mellon Exp $ */
+
+/*
+ * Copyright (c) 1992, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Ralph Campbell.
+ *
+ * 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.
+ *
+ */
+
+/*
+ * start.S -
+ *
+ *     Contains code that is the first executed at boot time.
+ */
+
+#include <machine/regdef.h>
+#include <machine/cpu.h>
+#include <machine/asm.h>
+
+/*
+ * Frame required for the debugger (if we have any)
+ */
+#define START_FRAME    ((4 * 4) + 4 + 4)
+
+       .globl  __start
+__start:
+       .set    noreorder
+#ifdef __GP_SUPPORT__
+       la      gp, _C_LABEL (_gp)
+#endif
+       la      sp, __start - START_FRAME               # Stack below program
+       sw      zero, START_FRAME - 4(sp)       # Zero out old ra for debugger
+       sw      zero, START_FRAME - 8(sp)       # Zero out old fp for debugger
+       move    s0, a0                          # save argc
+       move    s1, a1                          # save argv
+
+       la      a0, _C_LABEL (edata)                    # clear BSS
+       la      a1, _C_LABEL (end)
+       jal     _C_LABEL(bzero)                 # bzero(edata, end - edata)
+       subu    a1, a1, a0
+
+       move    a0, s0                          # restore argc
+       jal     _C_LABEL(main)                  # main(argc, argv)
+       move    a1, s1                          # restore argv
+
+       j       _C_LABEL(Bios_Restart)          # restart...
+       nop
+
+/* dummy routine for gcc2 */
+       .globl  _C_LABEL(__main)
+_C_LABEL(__main):
+       j       ra
+       nop
+
+#define Bios_Call(Name,Offset) \
+LEAF(Name);                    \
+       lw      v0,0x80001020;  \
+       lw      v0,Offset(v0);  \
+       jr      v0      ;       \
+       nop             ;       \
+       END(Name)
+
+Bios_Call(Bios_Load,                   0x00)
+Bios_Call(Bios_Invoke,                 0x04)
+Bios_Call(Bios_Execute,                        0x08)
+Bios_Call(Bios_Halt,                   0x0c)
+Bios_Call(Bios_PowerDown,              0x10)
+Bios_Call(Bios_Restart,                        0x14)
+Bios_Call(Bios_Reboot,                 0x18)
+Bios_Call(Bios_EnterInteractiveMode,   0x1c)
+Bios_Call(Bios_Unused1,                        0x20)
+Bios_Call(Bios_GetPeer,                        0x24)
+Bios_Call(Bios_GetChild,               0x28)
+Bios_Call(Bios_GetParent,              0x2c)
+Bios_Call(Bios_GetConfigurationData,   0x30)
+Bios_Call(Bios_AddChild,               0x34)
+Bios_Call(Bios_DeleteComponent,                0x38)
+Bios_Call(Bios_GetComponent,           0x3c)
+Bios_Call(Bios_SaveConfiguration,      0x40)
+Bios_Call(Bios_GetSystemId,            0x44)
+Bios_Call(Bios_GetMemoryDescriptor,    0x48)
+Bios_Call(Bios_Unused2,                        0x4c)
+Bios_Call(Bios_GetTime,                        0x50)
+Bios_Call(Bios_GetRelativeTime,                0x54)
+Bios_Call(Bios_GetDirectoryEntry,      0x58)
+Bios_Call(Bios_Open,                   0x5c)
+Bios_Call(Bios_Close,                  0x60)
+Bios_Call(Bios_Read,                   0x64)
+Bios_Call(Bios_GetReadStatus,          0x68)
+Bios_Call(Bios_Write,                  0x6c)
+Bios_Call(Bios_Seek,                   0x70)
+Bios_Call(Bios_Mount,                  0x74)
+Bios_Call(Bios_GetEnvironmentVariable, 0x78)
+Bios_Call(Bios_SetEnvironmentVariable, 0x7c)
+Bios_Call(Bios_GetFileInformation,     0x80)
+Bios_Call(Bios_SetFileInformation,     0x84)
+Bios_Call(Bios_FlushAllCaches,         0x88)
+Bios_Call(Bios_TestUnicodeCharacter,   0x8c)
+Bios_Call(Bios_GetDisplayStatus,       0x90)
diff --git a/sys/arch/wgrisc/wgrisc/autoconf.c b/sys/arch/wgrisc/wgrisc/autoconf.c
new file mode 100644 (file)
index 0000000..856f976
--- /dev/null
@@ -0,0 +1,464 @@
+/*     $OpenBSD: autoconf.c,v 1.1.1.1 1997/02/06 16:02:46 pefo Exp $   */
+/*
+ * Copyright (c) 1996 Per Fogelstrom
+ * Copyright (c) 1995 Theo de Raadt
+ * Copyright (c) 1988 University of Utah.
+ * Copyright (c) 1992, 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 and Ralph Campbell.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * from: Utah Hdr: autoconf.c 1.31 91/01/21
+ *
+ *     from: @(#)autoconf.c    8.1 (Berkeley) 6/10/93
+ *      $Id: autoconf.c,v 1.1.1.1 1997/02/06 16:02:46 pefo Exp $
+ */
+
+/*
+ * 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/buf.h>
+#include <sys/disklabel.h>
+#include <sys/conf.h>
+#include <sys/reboot.h>
+#include <sys/device.h>
+
+#include <machine/autoconf.h>
+
+struct  device *parsedisk __P((char *, int, int, dev_t *));
+void    setroot __P((void));
+
+/*
+ * The following several variables are related to
+ * the configuration process, and are used in initializing
+ * the machine.
+ */
+int    cold = 1;       /* if 1, still working on cold-start */
+int    cpuspeed = 25;  /* approx # instr per usec. */
+char   bootdev[16];    /* to hold boot dev name */
+struct device *bootdv = NULL;
+
+/*
+ *  Configure all devices found that we know about.
+ *  This is done at boot time.
+ */
+configure()
+{
+       (void)splhigh();        /* To be really shure.. */
+       if(config_rootfound("mainbus", "mainbus") == 0)
+               panic("no mainbus found");
+       (void)spl0();
+
+       setroot();
+       swapconf();
+       cold = 0;
+}
+
+/*
+ * 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;
+                       swp->sw_nblks = ctod(dtoc(swp->sw_nblks));
+               }
+       }
+       dumpconf();
+}
+
+/*                                                                        
+ * the rest of this file was influenced/copied from Theo de Raadt's
+ * code in the sparc port to nuke the "options GENERIC" stuff.
+ */
+
+static struct nam2blk {
+       char *name;
+       int  maj;
+} nam2blk[] = {
+       { "sd", 0 },    /* 0 = sd */
+       { "fd", 7 },    /* 7 = floppy  (ick!)*/
+};
+
+static int
+findblkmajor(dv)
+       struct device *dv;
+{
+       char *name = dv->dv_xname;
+       register int i;
+
+       for (i = 0; i < sizeof(nam2blk)/sizeof(nam2blk[0]); ++i)
+               if (strncmp(name, nam2blk[i].name, strlen(nam2blk[0].name)) == 0)
+                       return (nam2blk[i].maj);
+        return (-1);
+}
+
+static struct device *
+getdisk(str, len, defpart, devp)
+       char *str;
+       int len, defpart;
+       dev_t *devp;
+{
+       register struct device *dv;
+
+       if ((dv = parsedisk(str, len, defpart, devp)) == NULL) {
+               printf("use one of:");
+               for (dv = alldevs.tqh_first; dv != NULL;
+                   dv = dv->dv_list.tqe_next) {
+                       if (dv->dv_class == DV_DISK)
+                               printf(" %s[a-h]", dv->dv_xname);
+#ifdef NFSCLIENT
+                       if (dv->dv_class == DV_IFNET)
+                               printf(" %s", dv->dv_xname); 
+#endif
+               }
+               printf("\n");
+       }
+       return (dv);
+}
+
+struct device *
+parsedisk(str, len, defpart, devp)
+       char *str;
+       int len, defpart;
+       dev_t *devp;
+{
+       register struct device *dv;
+       register char *cp, c;
+       int majdev, mindev, part;
+
+       if (len == 0)
+               return (NULL);
+       cp = str + len - 1;
+       c = *cp;
+       if (c >= 'a' && c <= 'h') {
+               part = c - 'a';
+               *cp = '\0';
+       } else
+               part = defpart;
+
+       for (dv = alldevs.tqh_first; dv != NULL; dv = dv->dv_list.tqe_next) {
+               if (dv->dv_class == DV_DISK &&
+                   strcmp(str, dv->dv_xname) == 0) {
+                       majdev = findblkmajor(dv);
+                       if (majdev < 0)
+                               panic("parsedisk");
+                       mindev = (dv->dv_unit << PARTITIONSHIFT) + part;
+                       *devp = makedev(majdev, mindev);
+                       break;
+               }
+#ifdef NFSCLIENT
+               if (dv->dv_class == DV_IFNET &&
+                   strcmp(str, dv->dv_xname) == 0) {
+                       *devp = NODEV;
+                       break;
+               }
+#endif
+       }
+
+       *cp = c;
+       return (dv);
+}
+
+/*
+ * 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.
+ */
+void
+setroot()
+{
+       int  majdev, mindev, unit, part, len;
+       dev_t temp;
+       struct swdevt *swp;
+       struct device *dv;
+       dev_t nrootdev, nswapdev = NODEV;
+       char buf[128];
+
+#if defined(NFSCLIENT)
+       extern char *nfsbootdevname;
+#endif
+#if defined(FFS)
+       extern int ffs_mountroot __P((void));
+#endif
+
+       /* Lookup boot device from boot if not set by configuration */
+       if(bootdv == NULL) {
+               bootdv = parsedisk(bootdev, strlen(bootdev), 0, &temp);
+       }
+       if(bootdv == NULL) {
+               printf("boot device: lookup '%s' failed.\n", bootdev);
+               boothowto |= RB_ASKNAME; /* Don't Panic :-) */
+       }
+       else {
+               printf("boot device: %s.\n", bootdv->dv_xname);
+       }
+
+       if (boothowto & RB_ASKNAME) {
+               for (;;) {
+                        printf("root device ");
+                       if (bootdv != NULL)
+                                printf("(default %s%c)",
+                                       bootdv->dv_xname,
+                                       bootdv->dv_class == DV_DISK
+                                               ? 'a' : ' ');
+                       printf(": ");
+                       len = getsn(buf, sizeof(buf));
+                       if (len == 0 && bootdv != NULL) {
+                               strcpy(buf, bootdv->dv_xname);
+                               len = strlen(buf);
+                       }
+                       if (len > 0 && buf[len - 1] == '*') {
+                               buf[--len] = '\0';
+                               dv = getdisk(buf, len, 1, &nrootdev);
+                               if (dv != NULL) {
+                                       bootdv = dv;
+                                       nswapdev = nrootdev;
+                                       goto gotswap;
+                               }
+                       }
+                       dv = getdisk(buf, len, 0, &nrootdev);
+                       if (dv != NULL) {
+                               bootdv = dv;
+                               break;
+                       }
+               }
+               /*
+                * because swap must be on same device as root, for
+                * network devices this is easy.
+                */
+               if (bootdv->dv_class == DV_IFNET) {
+                       goto gotswap;
+               }
+               for (;;) {
+                       printf("swap device ");
+                       if (bootdv != NULL)
+                               printf("(default %s%c)",
+                                       bootdv->dv_xname,
+                                       bootdv->dv_class == DV_DISK?'b':' ');
+                       printf(": ");
+                       len = getsn(buf, sizeof(buf));
+                       if (len == 0 && bootdv != NULL) {
+                               switch (bootdv->dv_class) {
+                               case DV_IFNET:
+                                       nswapdev = NODEV;
+                                       break;
+                               case DV_DISK:
+                                       nswapdev = makedev(major(nrootdev),
+                                           (minor(nrootdev) & ~ PARTITIONMASK)
+| 1);
+                                       break;
+                               case DV_TAPE:
+                               case DV_TTY:
+                               case DV_DULL:
+                               case DV_CPU:
+                                       break;
+                               }
+                               break;
+                       }
+                       dv = getdisk(buf, len, 1, &nswapdev);
+                       if (dv) {
+                               if (dv->dv_class == DV_IFNET)
+                                       nswapdev = NODEV;
+                               break;
+                       }
+               }
+
+gotswap:
+               rootdev = nrootdev;
+               dumpdev = nswapdev;
+               swdevt[0].sw_dev = nswapdev;
+               swdevt[1].sw_dev = NODEV;
+       }
+       else if(mountroot == NULL) {
+               /*
+                * `swap generic': Use the device the ROM told us to use.
+                */
+               if (bootdv == NULL)
+                       panic("boot device not known");
+
+               majdev = findblkmajor(bootdv);
+
+               if (majdev >= 0) {
+                       /*
+                        * Root and Swap are on disk.
+                        * Boot is always from partition 0.
+                        */
+                       rootdev = MAKEDISKDEV(majdev, bootdv->dv_unit, 0);
+                       nswapdev = MAKEDISKDEV(majdev, bootdv->dv_unit, 1);
+                       dumpdev = nswapdev;
+               }
+               else {
+                       /*
+                        *  Root and Swap are on net.
+                        */     
+                       nswapdev = dumpdev = NODEV;
+               }
+               swdevt[0].sw_dev = nswapdev;
+               swdevt[1].sw_dev = NODEV;
+
+       } else {
+
+               /*
+                * `root DEV swap DEV': honour rootdev/swdevt.
+                * rootdev/swdevt/mountroot already properly set.
+                */
+               return;
+       }
+
+       switch (bootdv->dv_class) {
+#if defined(NFSCLIENT)
+       case DV_IFNET:
+               mountroot = nfs_mountroot;
+               nfsbootdevname = bootdv->dv_xname;
+               return;
+#endif
+#if defined(FFS)
+       case DV_DISK:
+               mountroot = ffs_mountroot;
+               majdev = major(rootdev);
+               mindev = minor(rootdev);
+               printf("root on %s%c\n", bootdv->dv_xname,
+                   (mindev & PARTITIONMASK) + 'a');
+               break;
+#endif
+       default:
+               printf("can't figure root, hope your kernel is right\n");
+               return;
+       }
+
+       /*
+        * XXX: What is this doing?
+        */
+       mindev &= ~PARTITIONMASK;
+       temp = NODEV;
+       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;
+}
+
+/*
+ * find a device matching "name" and unit number
+ */
+struct device *
+getdevunit(name, unit)
+       char *name;
+       int unit;
+{
+       struct device *dev = alldevs.tqh_first;
+       char num[10], fullname[16];
+       int lunit;
+
+       /* compute length of name and decimal expansion of unit number */
+       sprintf(num, "%d", unit);
+       lunit = strlen(num);
+       if (strlen(name) + lunit >= sizeof(fullname) - 1)
+               panic("config_attach: device name too long");
+
+       strcpy(fullname, name);
+       strcat(fullname, num);
+
+       while (strcmp(dev->dv_xname, fullname) != 0) {
+               if ((dev = dev->dv_list.tqe_next) == NULL)
+                       return NULL;
+       }
+       return dev;
+}
+
+/*
+ * Look at the string 'cp' and decode the boot device.
+ * Boot names look like: scsi()disk(n)rdisk()partition(1)\bsd
+ * (beware for empty scsi id's...)
+ */
+void
+makebootdev(cp)
+       char *cp;
+{
+       int     unit, part, ctrl;
+
+       bootdev[0] = *cp;
+       ctrl = getpno(&cp);
+       if(*cp++ == ')') {
+               bootdev[1] = *cp;
+               unit = getpno(&cp);
+       }
+       sprintf(&bootdev[2], "%d", ctrl*16 + unit);
+}
+getpno(cp)
+       char **cp;
+{
+       int val = 0;
+       char *cx = *cp;
+
+       while(*cx && *cx != '(')
+               cx++;
+       if(*cx == '(') {
+               cx++;
+               while(*cx && *cx != ')') {
+                       val = val * 10 + *cx - '0';
+                       cx++;
+               }
+       }
+       *cp = cx;
+       return val;
+}
diff --git a/sys/arch/wgrisc/wgrisc/clock.c b/sys/arch/wgrisc/wgrisc/clock.c
new file mode 100644 (file)
index 0000000..0f5d151
--- /dev/null
@@ -0,0 +1,327 @@
+/*     $OpenBSD: clock.c,v 1.1.1.1 1997/02/06 16:02:45 pefo Exp $      */
+/*
+ * Copyright (c) 1988 University of Utah.
+ * Copyright (c) 1992, 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 and Ralph Campbell.
+ *
+ * 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: clock.c 1.18 91/01/21
+ *
+ *     from: @(#)clock.c       8.1 (Berkeley) 6/10/93
+ *      $Id: clock.c,v 1.1.1.1 1997/02/06 16:02:45 pefo Exp $
+ */
+
+#include <sys/param.h>
+#include <sys/kernel.h>
+#include <sys/systm.h>
+#include <sys/device.h>
+
+#include <machine/autoconf.h>
+#include <machine/cpu.h>
+#include <wgrisc/wgrisc/clockvar.h>
+#include <wgrisc/wgrisc/wgrisctype.h>
+
+#include <dev/isa/isavar.h>
+#include <wgrisc/isa/isa_machdep.h>
+
+extern int cputype;    /* What kind of cpu we are running on */
+
+int    clock_started = 0;
+
+/* Definition of the driver for autoconfig. */
+static int     clockmatch __P((struct device *, void *, void *));
+static void    clockattach __P((struct device *, struct device *, void *));
+
+struct cfdriver clock_cd = {
+       NULL, "clock", DV_DULL, NULL, 0
+};
+
+struct cfattach clock_ca = {
+       sizeof(struct clock_softc), clockmatch, clockattach
+};
+
+void   dpclock_attach __P((struct device *, struct device *, void *));
+
+#define        SECMIN  ((unsigned)60)                  /* seconds per minute */
+#define        SECHOUR ((unsigned)(60*SECMIN))         /* seconds per hour */
+#define        SECDAY  ((unsigned)(24*SECHOUR))        /* seconds per day */
+#define        SECYR   ((unsigned)(365*SECDAY))        /* seconds per common year */
+
+#define        LEAPYEAR(year)  (((year) % 4) == 0)
+
+static int
+clockmatch(parent, cfdata, aux)
+       struct device *parent;
+       void *cfdata;
+       void *aux;
+{
+       struct cfdata *cf = cfdata;
+       struct confargs *ca = aux;
+
+       /* See how many clocks this system has */       
+       switch (cputype) {
+
+       case WGRISC9100:
+               /* make sure that we're looking for this type of device. */
+               if (!BUS_MATCHNAME(ca, "dp8571rtc"))
+                       return (0);
+
+               break;
+
+       default:
+               panic("unknown CPU");
+       }
+
+       if (cf->cf_unit >= 1)
+               return (0);
+
+       return (1);
+}
+
+int
+clockintr(cf)
+       void *cf;
+{
+       if(clock_started)
+               hardclock((struct clockframe *)cf);
+       return(1);
+}
+
+static void
+clockattach(parent, self, aux)
+       struct device *parent;
+       struct device *self;
+       void *aux;
+{
+       struct isa_attach_args *ia = aux;
+
+       dpclock_attach(parent, self, aux);
+
+       switch (cputype) {
+
+       case WGRISC9100:
+               BUS_INTR_ESTABLISH((struct confargs *)aux,
+                       (intr_handler_t)hardclock, self);
+               break;
+
+       default:
+               panic("clockattach: it didn't get here.  really.");
+       }
+
+       printf("\n");
+}
+
+/*
+ * Wait "n" microseconds.  This doesn't belong here.  XXX.
+ */
+void
+delay(n)
+       int n;
+{
+       DELAY(n);
+}
+
+/*
+ * Machine-dependent clock routines.
+ *
+ * Startrtclock restarts the real-time clock, which provides
+ * hardclock interrupts to kern_clock.c.
+ *
+ * Inittodr initializes the time of day hardware which provides
+ * date functions.  Its primary function is to use some file
+ * system information in case the hardare clock lost state.
+ *
+ * Resettodr restores the time of day hardware after a time change.
+ */
+
+
+/*
+ * Start the real-time and statistics clocks. Leave stathz 0 since there
+ * are no other timers available.
+ */
+void
+cpu_initclocks()
+{
+       extern int tickadj;
+       struct clock_softc *csc = (struct clock_softc *)clock_cd.cd_devs[0];
+
+       hz = 100;               /* 100 Hz */
+       tick = 1000000 / hz;    /* number of micro-seconds between interrupts */
+
+       /*
+        * Start the clock.
+        */
+       (*csc->sc_init)(csc);
+       clock_started++;
+}
+
+/*
+ * We assume newhz is either stathz or profhz, and that neither will
+ * change after being set up above.  Could recalculate intervals here
+ * but that would be a drag.
+ */
+void
+setstatclockrate(newhz)
+       int newhz;
+{
+}
+
+/*
+ * This code is defunct after 2099.
+ * Will Unix still be here then??
+ */
+static short dayyr[12] = {
+       0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334
+};
+
+/*
+ * Initialze the time of day register, based on the time base which is, e.g.
+ * from a filesystem.  Base provides the time to within six months,
+ * and the time of year clock (if any) provides the rest.
+ */
+void
+inittodr(base)
+       time_t base;
+{
+       struct tod_time c;
+       struct clock_softc *csc = (struct clock_softc *)clock_cd.cd_devs[0];
+       register int days, yr;
+       long deltat;
+       int badbase, s;
+
+       if (base < 5*SECYR) {
+               printf("WARNING: preposterous time in file system");
+               /* read the system clock anyway */
+               base = 6*SECYR + 186*SECDAY + SECDAY/2;
+               badbase = 1;
+       } else
+               badbase = 0;
+
+       /* Read RTC chip registers */ 
+       (*csc->sc_get)(csc, base, &c);
+
+       csc->sc_initted = 1;
+
+       /* simple sanity checks */
+       c.year = c.year+80; /* must be multiple of 4 because chip knows leap */
+       if (c.year < 70 || c.mon < 1 || c.mon > 12 || c.day < 1 ||
+           c.day > 31 || c.hour > 23 || c.min > 59 || c.sec > 59) {
+               /*
+                * Believe the time in the file system for lack of
+                * anything better, resetting the TODR.
+                */
+               time.tv_sec = base;
+               if (!badbase) {
+                       printf("WARNING: preposterous clock chip time\n");
+                       resettodr();
+               }
+               goto bad;
+       }
+       days = 0;
+       for (yr = 70; yr < c.year; yr++)
+               days += LEAPYEAR(yr) ? 366 : 365;
+       days += dayyr[c.mon - 1] + c.day - 1;
+       if (LEAPYEAR(yr) && c.mon > 2)
+               days++;
+       /* now have days since Jan 1, 1970; the rest is easy... */
+       time.tv_sec = days * SECDAY + c.hour * 3600 + c.min * 60 + c.sec;
+
+       if (!badbase) {
+               /*
+                * See if we gained/lost two or more days;
+                * if so, assume something is amiss.
+                */
+               deltat = time.tv_sec - base;
+               if (deltat < 0)
+                       deltat = -deltat;
+               if (deltat < 2 * SECDAY)
+                       return;
+               printf("WARNING: clock %s %d days",
+                   time.tv_sec < base ? "lost" : "gained", deltat / SECDAY);
+       }
+bad:
+       printf(" -- CHECK AND RESET THE DATE!\n");
+}
+
+/*
+ * Reset the TODR based on the time value; used when the TODR
+ * has a preposterous value and also when the time is reset
+ * by the stime system call.  Also called when the TODR goes past
+ * TODRZERO + 100*(SECYEAR+2*SECDAY) (e.g. on Jan 2 just after midnight)
+ * to wrap the TODR around.
+ */
+void
+resettodr()
+{
+       struct tod_time c;
+       struct clock_softc *csc = (struct clock_softc *)clock_cd.cd_devs[0];
+       register int t, t2;
+       int s;
+
+       if(!csc->sc_initted)
+               return;
+
+       /* compute the day of week. 1 is Sunday*/
+       t2 = time.tv_sec / SECDAY;
+       c.dow = (t2 + 5) % 7;   /* 1/1/1970 was thursday */
+
+       /* compute the year */
+       t2 = time.tv_sec / SECDAY;
+       c.year = 69;
+       while (t2 >= 0) {       /* whittle off years */
+               t = t2;
+               c.year++;
+               t2 -= LEAPYEAR(c.year) ? 366 : 365;
+       }
+
+       /* t = month + day; separate */
+       t2 = LEAPYEAR(c.year);
+       for (c.mon = 1; c.mon < 12; c.mon++)
+               if (t < dayyr[c.mon] + (t2 && c.mon > 1))
+                       break;
+
+       c.day = t - dayyr[c.mon - 1] + 1;
+       if (t2 && c.mon > 2)
+               c.day--;
+
+       /* the rest is easy */
+       t = time.tv_sec % SECDAY;
+       c.hour = t / 3600;
+       t %= 3600;
+       c.min = t / 60;
+       c.sec = t % 60;
+       c.year = c.year-80; /* must be multiple of 4 because chip knows leap */
+
+       (*csc->sc_set)(csc, &c);
+}
diff --git a/sys/arch/wgrisc/wgrisc/clock_dp.c b/sys/arch/wgrisc/wgrisc/clock_dp.c
new file mode 100644 (file)
index 0000000..90e7155
--- /dev/null
@@ -0,0 +1,227 @@
+/*     $OpenBSD: clock_dp.c,v 1.1.1.1 1997/02/06 16:02:47 pefo Exp $   */
+/*     $NetBSD: clock_mc.c,v 1.2 1995/06/28 04:30:30 cgd Exp $ */
+
+/*
+ * Copyright (c) 1988 University of Utah.
+ * Copyright (c) 1992, 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 and Ralph Campbell.
+ *
+ * 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: clock.c 1.18 91/01/21
+ *
+ *     @(#)clock.c     8.1 (Berkeley) 6/10/93
+ */
+
+#include <sys/param.h>
+#include <sys/kernel.h>
+#include <sys/systm.h>
+#include <sys/device.h>
+
+#include <machine/autoconf.h>
+#include <machine/pio.h>
+
+#include <dev/isa/isareg.h>
+#include <dev/isa/isavar.h>
+#include <dev/ic/dp857xreg.h>
+
+#include <wgrisc/wgrisc/clockvar.h>
+#include <wgrisc/wgrisc/wgrisctype.h>
+#include <wgrisc/riscbus/riscbus.h>
+#include <wgrisc/isa/isa_machdep.h>
+
+extern u_int   cputype;
+extern int     cpu_int_mask;
+
+void           dpclock_attach __P((struct device *parent,
+                   struct device *self, void *aux));
+static void    dpclock_init_riscbus __P((struct clock_softc *csc));
+static void    dpclock_get __P((struct clock_softc *csc, time_t base,
+                   struct tod_time *ct));
+static void    dpclock_set __P((struct clock_softc *csc,
+                   struct tod_time *ct));
+
+struct dpclockdata {
+       void    (*dp_write) __P((struct clock_softc *csc, u_int reg,
+                   u_int datum));
+       u_int   (*dp_read) __P((struct clock_softc *csc, u_int reg));
+       void    *dp_addr;
+};
+
+#define        dp857x_write(sc, reg, datum)                                    \
+           (*((struct dpclockdata *)sc->sc_data)->dp_write)(sc, reg, datum)
+#define        dp857x_read(sc, reg)                                            \
+           (*((struct dpclockdata *)sc->sc_data)->dp_read)(sc, reg)
+
+/* riscbus clock read code */
+static void    dp_write_riscbus __P((struct clock_softc *csc, u_int reg,
+                   u_int datum));
+static u_int   dp_read_riscbus __P((struct clock_softc *csc, u_int reg));
+static struct dpclockdata dpclockdata_riscbus = { dp_write_riscbus, dp_read_riscbus };
+
+void
+dpclock_attach(parent, self, aux)
+       struct device *parent;
+       struct device *self;
+       void *aux;
+{
+       struct clock_softc *csc = (struct clock_softc *)self;
+
+       register volatile struct chiptime *c;
+       struct confargs *ca = aux;
+
+       printf(": dp857[012] or compatible");
+
+       csc->sc_get = dpclock_get;
+       csc->sc_set = dpclock_set;
+
+        switch (cputype) {
+
+        case WGRISC9100:
+               csc->sc_init = dpclock_init_riscbus;
+               csc->sc_data = &dpclockdata_riscbus;
+               dpclockdata_riscbus.dp_addr = BUS_CVTADDR(ca);
+               break;
+
+       default:
+               printf("\n");
+               panic("don't know how to set up for other system types.");
+       }
+
+       /* Initialize and turn interrupts off, just in case. */
+
+       dp857x_write(csc, MAIN_STATUS, 0x40);
+       dp857x_write(csc, INTERRUPT_CTRL0, 0);
+       dp857x_write(csc, INTERRUPT_CTRL1, 0);
+       dp857x_write(csc, OUTPUT_MODE, 0x08);
+       dp857x_write(csc, REAL_TIME_MODE,
+               (dp857x_read(csc, REAL_TIME_MODE) & 3) |  0x08);
+
+       dp857x_write(csc, MAIN_STATUS, 0x3c);   /* clears pending ints */
+       dp857x_write(csc, INTERRUPT_ROUT, 0);
+       dp857x_write(csc, TIMER0_CTRL, 0);
+       dp857x_write(csc, TIMER1_CTRL, 0);
+}
+/*
+ * TOD clock also used for periodic interrupts.
+ */
+static struct clock_softc *int_csc;
+
+static void
+dpclock_init_riscbus(csc)
+       struct clock_softc *csc;
+{
+       int_csc = csc;
+       dp857x_write(csc, MAIN_STATUS, 0x40);
+       dp857x_write(csc, INTERRUPT_CTRL0, 0x10);       /* 100 Hz */
+       dp857x_write(csc, MAIN_STATUS, 0);
+}
+
+int
+dpclock_interrupt()
+{
+       if(dp857x_read(int_csc, MAIN_STATUS) & 0x04) { /* periodic interrupt */
+               dp857x_write(int_csc, MAIN_STATUS, 0x04);
+               return(1);
+       }
+       return(0);
+}
+
+/*
+ * Get the time of day, based on the clock's value and/or the base value.
+ */
+static void
+dpclock_get(csc, base, ct)
+       struct clock_softc *csc;
+       time_t base;
+       struct tod_time *ct;
+{
+       dp_todregs regs;
+       int s;
+
+       s = splclock();
+       DP857X_GETTOD(csc, &regs)
+       splx(s);
+
+       ct->sec = regs[CLK_SECONDS];
+       ct->min = regs[CLK_MINUTES];
+       ct->hour = regs[CLK_HOURS];
+       ct->dow = regs[CLK_WEEKDAY];
+       ct->day = regs[CLK_DAY];
+       ct->mon = regs[CLK_MONTH];
+       ct->year = regs[CLK_YEAR];
+}
+
+/*
+ * Reset the TODR based on the time value.
+ */
+static void
+dpclock_set(csc, ct)
+       struct clock_softc *csc;
+       struct tod_time *ct;
+{
+       dp_todregs regs;
+       int s;
+
+       s = splclock();
+       DP857X_GETTOD(csc, &regs)
+
+       regs[CLK_SECONDS] = ct->sec;
+       regs[CLK_MINUTES] = ct->min;
+       regs[CLK_HOURS] = ct->hour;
+       regs[CLK_WEEKDAY] = ct->dow;
+       regs[CLK_DAY] = ct->day;
+       regs[CLK_MONTH] = ct->mon;
+       regs[CLK_YEAR] = ct->year;
+
+       DP857X_PUTTOD(csc, &regs);
+       splx(s);
+}
+
+static void
+dp_write_riscbus(csc, reg, datum)
+       struct clock_softc *csc;
+       u_int reg, datum;
+{
+       outb(((struct dpclockdata *)csc->sc_data)->dp_addr + reg, datum);
+}
+
+static u_int
+dp_read_riscbus(csc, reg)
+       struct clock_softc *csc;
+       u_int reg;
+{
+       int i;
+       i = inb(((struct dpclockdata *)csc->sc_data)->dp_addr + reg);
+       return(i);
+}
diff --git a/sys/arch/wgrisc/wgrisc/clockvar.h b/sys/arch/wgrisc/wgrisc/clockvar.h
new file mode 100644 (file)
index 0000000..f63b51a
--- /dev/null
@@ -0,0 +1,82 @@
+/*     $OpenBSD: clockvar.h,v 1.1.1.1 1997/02/06 16:02:45 pefo Exp $ */
+
+/*
+ * Copyright (c) 1996 Per Fogelstrom
+ * 
+ * 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 under OpenBSD by
+ *     Per Fogelstrom.
+ * 4. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+
+/*
+ * Definitions for "cpu-independent" clock handling for the mips wgrisc arch.
+ */
+
+/*
+ * clocktime structure:
+ *
+ * structure passed to TOY clocks when setting them.  broken out this
+ * way, so that the time_t -> field conversion can be shared.
+ */
+struct tod_time {
+       int     year;                   /* year - 1900 */
+       int     mon;                    /* month (1 - 12) */
+       int     day;                    /* day (1 - 31) */
+       int     hour;                   /* hour (0 - 23) */
+       int     min;                    /* minute (0 - 59) */
+       int     sec;                    /* second (0 - 59) */
+       int     dow;                    /* day of week (0 - 6; 0 = Sunday) */
+};
+
+/*
+ * clockdesc structure:
+ *
+ * provides clock-specific functions to do necessary operations.
+ */
+struct clock_softc {
+       struct  device sc_dev;
+
+       /*
+        * The functions that all types of clock provide.
+        */
+       void    (*sc_attach) __P((struct device *parent, struct device *self,
+                   void *aux));
+       void    (*sc_init) __P((struct clock_softc *csc));
+       void    (*sc_get) __P((struct clock_softc *csc, time_t base,
+                   struct tod_time *ct));
+       void    (*sc_set) __P((struct clock_softc *csc, struct tod_time *ct));
+
+       /*
+        * Private storage for particular clock types.
+        */
+       void    *sc_data;
+
+       /*
+        * Has the time been initialized?
+        */
+       int     sc_initted;
+};
diff --git a/sys/arch/wgrisc/wgrisc/conf.c b/sys/arch/wgrisc/wgrisc/conf.c
new file mode 100644 (file)
index 0000000..796489d
--- /dev/null
@@ -0,0 +1,365 @@
+/*     $OpenBSD: conf.c,v 1.1.1.1 1997/02/06 16:02:45 pefo Exp $ */
+
+/*
+ * Copyright (c) 1992, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Ralph Campbell.
+ *
+ * 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: @(#)conf.c        8.2 (Berkeley) 11/14/93
+ *      $Id: conf.c,v 1.1.1.1 1997/02/06 16:02:45 pefo Exp $
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/buf.h>
+#include <sys/ioctl.h>
+#include <sys/proc.h>
+#include <sys/vnode.h>
+#include <sys/tty.h>
+#include <sys/conf.h>
+
+int    ttselect        __P((dev_t, int, struct proc *));
+
+/*
+ *     Block devices.
+ */
+
+#include "vnd.h"
+bdev_decl(vnd);
+bdev_decl(sw);
+#include "sd.h"
+bdev_decl(sd);
+#include "cd.h"
+bdev_decl(cd);
+#if notyet
+#include "fdc.h"
+bdev_decl(fd);
+#endif
+#include "wdc.h"
+bdev_decl(wd);
+#include "acd.h"
+bdev_decl(acd);
+
+struct bdevsw  bdevsw[] =
+{
+       bdev_disk_init(NSD,sd),         /* 0: SCSI disk */
+       bdev_swap_init(1,sw),           /* 1: should be here swap pseudo-dev */
+       bdev_disk_init(NVND,vnd),       /* 2: vnode disk driver */
+       bdev_disk_init(NCD,cd),         /* 3: SCSI CD-ROM */
+       bdev_disk_init(NWDC,wd),        /* 4: ST506/ESDI/IDE disk */
+       bdev_disk_init(NACD,cd),        /* 5: ATAPI CD-ROM */
+       bdev_notdef(),                  /* 6:  */
+       bdev_notdef(),                  /* 7: Floppy disk driver */
+       bdev_notdef(),                  /* 8:  */
+       bdev_notdef(),                  /* 9:  */
+       bdev_notdef(),                  /* 10:  */
+       bdev_notdef(),                  /* 11:  */
+       bdev_notdef(),                  /* 12:  */
+       bdev_notdef(),                  /* 13:  */
+       bdev_notdef(),                  /* 14:  */
+       bdev_notdef(),                  /* 15:  */
+};
+
+int    nblkdev = sizeof (bdevsw) / sizeof (bdevsw[0]);
+
+/*
+ *     Character devices.
+ */
+
+/* open, close, read, write, ioctl, tty, mmap */
+#define cdev_pc_init(c,n) { \
+       dev_init(c,n,open), dev_init(c,n,close), dev_init(c,n,read), \
+       dev_init(c,n,write), dev_init(c,n,ioctl), dev_init(c,n,stop), \
+       dev_init(c,n,tty), ttselect, dev_init(c,n,mmap), D_TTY }
+
+/* open, close, write, ioctl */
+#define        cdev_lpt_init(c,n) { \
+       dev_init(c,n,open), dev_init(c,n,close), (dev_type_read((*))) enodev, \
+       dev_init(c,n,write), dev_init(c,n,ioctl), (dev_type_stop((*))) enodev, \
+       0, seltrue, (dev_type_mmap((*))) enodev }
+
+/* open, close, write, ioctl */
+#define        cdev_spkr_init(c,n) { \
+       dev_init(c,n,open), dev_init(c,n,close), (dev_type_read((*))) enodev, \
+       dev_init(c,n,write), dev_init(c,n,ioctl), (dev_type_stop((*))) enodev, \
+       0, seltrue, (dev_type_mmap((*))) enodev }
+
+cdev_decl(cn);
+cdev_decl(sw);
+cdev_decl(ctty);
+cdev_decl(random);
+#define mmread mmrw
+#define mmwrite mmrw
+dev_type_read(mmrw);
+cdev_decl(mm);
+#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 "st.h"
+cdev_decl(st);
+#ifdef notyet
+#include "fdc.h"
+bdev_decl(fd);
+#endif
+cdev_decl(vnd);
+#include "bpfilter.h"
+cdev_decl(bpf);
+#include "com.h"
+cdev_decl(com);
+#include "lpt.h"
+cdev_decl(lpt);
+cdev_decl(sd);
+#ifdef notyet
+#include "pc.h"
+cdev_decl(pc);
+cdev_decl(pms);
+#endif
+cdev_decl(cd);
+#include "uk.h"
+cdev_decl(uk);
+cdev_decl(wd);
+cdev_decl(acd);
+
+/* open, close, read, ioctl */
+cdev_decl(ipl);
+#ifdef IPFILTER
+#define NIPF 1
+#else
+#define NIPF 0
+#endif
+
+struct cdevsw  cdevsw[] =
+{
+       cdev_cn_init(1,cn),             /* 0: virtual console */
+       cdev_swap_init(1,sw),           /* 1: /dev/drum (swap pseudo-device) */
+       cdev_ctty_init(1,ctty),         /* 2: controlling terminal */
+       cdev_mm_init(1,mm),             /* 3: /dev/{null,mem,kmem,...} */
+       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_fd_init(1,filedesc),       /* 7: file descriptor pseudo-dev */
+       cdev_disk_init(NCD,cd),         /* 8: SCSI CD */
+       cdev_disk_init(NSD,sd),         /* 9: SCSI disk */
+       cdev_tape_init(NST,st),         /* 10: SCSI tape */
+       cdev_disk_init(NVND,vnd),       /* 11: vnode disk */
+       cdev_bpftun_init(NBPFILTER,bpf),/* 12: berkeley packet filter */
+       cdev_notdef(),                  /* 13: Floppy disk */
+       cdev_notdef(),                  /* 14: builtin pc style console dev */
+       cdev_notdef(),                  /* 15: builtin PS2 style mouse */
+       cdev_lpt_init(NLPT,lpt),        /* 16: lpt paralell printer interface */
+       cdev_tty_init(NCOM,com),        /* 17: com 16C450 serial interface */
+       cdev_disk_init(NWDC,wd),        /* 18: ST506/ESDI/IDE disk */
+       cdev_disk_init(NACD,acd),       /* 19: ATAPI CD-ROM */
+       cdev_tty_init(NPTY,pts),        /* 20: pseudo-tty slave */
+       cdev_ptc_init(NPTY,ptc),        /* 21: pseudo-tty master */
+       cdev_notdef(),                  /* 22: */
+       cdev_notdef(),                  /* 23: */
+       cdev_notdef(),                  /* 24: */
+       cdev_notdef(),                  /* 25: */
+       cdev_notdef(),                  /* 26: */
+       cdev_notdef(),                  /* 27: */
+       cdev_notdef(),                  /* 28: */
+       cdev_notdef(),                  /* 29: */
+       cdev_notdef(),                  /* 30: */
+       cdev_gen_ipf(NIPF,ipl),         /* 31: IP filter log */
+       cdev_uk_init(NUK,uk),           /* 32: unknown SCSI */
+       cdev_random_init(1,random),     /* 33: random data source */
+};
+
+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(1, 0);
+
+/*
+ * Routine that identifies /dev/mem and /dev/kmem.
+ *
+ * A minimal stub routine can always return 0.
+ */
+iskmemdev(dev)
+       dev_t dev;
+{
+
+#ifdef COMPAT_BSD44
+       if (major(dev) == 2 && (minor(dev) == 0 || minor(dev) == 1))
+#else
+       if (major(dev) == 3 && (minor(dev) == 0 || minor(dev) == 1))
+#endif
+               return (1);
+       return (0);
+}
+
+/*
+ * Returns true if def is /dev/zero
+ */
+iszerodev(dev)
+       dev_t dev;
+{
+#ifdef COMPAT_BSD44
+       return (major(dev) == 2 && minor(dev) == 12);
+#else
+       return (major(dev) == 3 && minor(dev) == 12);
+#endif
+}
+
+
+#define MAXDEV 57
+static int chrtoblktbl[MAXDEV] =  {
+      /* VCHR */      /* VBLK */
+       /* 0 */         NODEV,
+       /* 1 */         NODEV,
+       /* 2 */         NODEV,
+       /* 3 */         NODEV,
+       /* 4 */         NODEV,
+       /* 5 */         NODEV,
+       /* 6 */         NODEV,
+       /* 7 */         NODEV,
+       /* 8 */         NODEV,
+       /* 9 */         0,
+       /* 10 */        NODEV,
+       /* 11 */        2,
+       /* 12 */        NODEV,
+       /* 13 */        7,
+       /* 14 */        NODEV,
+       /* 15 */        NODEV,
+       /* 16 */        NODEV,
+       /* 17 */        NODEV,
+       /* 18 */        4,
+       /* 19 */        5,
+       /* 20 */        NODEV,
+       /* 21 */        NODEV,
+       /* 22 */        NODEV,
+       /* 23 */        NODEV,
+       /* 24 */        NODEV,
+       /* 25 */        NODEV,
+       /* 26 */        NODEV,
+       /* 27 */        NODEV,
+       /* 28 */        NODEV,
+       /* 29 */        NODEV,
+       /* 30 */        NODEV,
+       /* 31 */        NODEV,
+       /* 32 */        NODEV,
+       /* 33 */        NODEV,
+       /* 34 */        NODEV,
+       /* 35 */        NODEV,
+       /* 36 */        NODEV,
+       /* 37 */        NODEV,
+       /* 38 */        NODEV,
+       /* 39 */        NODEV,
+       /* 40 */        NODEV,
+       /* 41 */        NODEV,
+       /* 42 */        NODEV,
+       /* 43 */        NODEV,
+       /* 44 */        NODEV,
+       /* 45 */        NODEV,
+       /* 46 */        NODEV,
+       /* 47 */        NODEV,
+       /* 48 */        NODEV,
+       /* 49 */        NODEV,
+       /* 50 */        NODEV,
+       /* 51 */        NODEV,
+       /* 52 */        NODEV,
+       /* 53 */        NODEV,
+       /* 54 */        NODEV,
+       /* 55 */        NODEV,
+       /* 56 */        NODEV,
+};
+/*
+ * Routine to convert from character to block device number.
+ *
+ * A minimal stub routine can always return NODEV.
+ */
+chrtoblk(dev)
+       dev_t dev;
+{
+       int blkmaj;
+
+       if (major(dev) >= MAXDEV || (blkmaj = chrtoblktbl[major(dev)]) == NODEV)
+               return (NODEV);
+       return (makedev(blkmaj, minor(dev)));
+}
+
+/*
+ * Convert a character device number to a block device number.
+ */
+dev_t
+blktochr(dev)
+       dev_t dev;
+{
+       int blkmaj = major(dev);
+       int i;
+
+       if (blkmaj >= nblkdev)
+               return (NODEV);
+       for (i = 0; i < sizeof(chrtoblktbl)/sizeof(chrtoblktbl[0]); i++)
+               if (blkmaj == chrtoblktbl[i])
+                       return (makedev(i, minor(dev)));
+       return (NODEV);
+}
+
+/*
+ * 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>
+
+cons_decl(pc);
+cons_decl(com);
+
+struct consdev constab[] = {
+#if NPC + NVT > 0
+       cons_init(pc),
+#endif
+#if NCOM > 0
+       cons_init(com),
+#endif
+       { 0 },
+};
diff --git a/sys/arch/wgrisc/wgrisc/cpu.c b/sys/arch/wgrisc/wgrisc/cpu.c
new file mode 100644 (file)
index 0000000..c7bf7a0
--- /dev/null
@@ -0,0 +1,192 @@
+/*     $OpenBSD: cpu.c,v 1.1.1.1 1997/02/06 16:02:45 pefo Exp $        */
+
+/*
+ * Copyright (c) 1994, 1995 Carnegie-Mellon University.
+ * All rights reserved.
+ *
+ * Author: Per Fogelstrom
+ * 
+ * Permission to use, copy, modify and distribute this software and
+ * its documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ * 
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" 
+ * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND 
+ * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ * 
+ * Carnegie Mellon requests users of this software to return to
+ *
+ *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
+ *  School of Computer Science
+ *  Carnegie Mellon University
+ *  Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie the
+ * rights to redistribute these changes.
+ */
+
+#include <sys/param.h>
+#include <sys/device.h>
+
+#include <machine/cpu.h>
+#include <machine/autoconf.h>
+
+
+/* Definition of the driver for autoconfig. */
+static int     cpumatch(struct device *, void *, void *);
+static void    cpuattach(struct device *, struct device *, void *);
+
+struct cfattach cpu_ca = {
+       sizeof(struct device), cpumatch, cpuattach
+};
+struct cfdriver cpu_cd = {
+       NULL, "cpu", DV_DULL, NULL, 0
+};
+
+static int     cpuprint __P((void *, char *pnp));
+
+static int
+cpumatch(parent, cfdata, aux)
+       struct device *parent;
+       void *cfdata;
+       void *aux;
+{
+       struct cfdata *cf = cfdata;
+       struct confargs *ca = aux;
+
+       /* make sure that we're looking for a CPU. */
+       if (strcmp(ca->ca_name, cpu_cd.cd_name) != 0)
+               return (0);
+
+       return (1);
+}
+
+static void
+cpuattach(parent, dev, aux)
+       struct device *parent;
+       struct device *dev;
+       void *aux;
+{
+        struct pcs *p;
+       int needcomma, needrev, i;
+
+       printf(": ");
+
+       switch(cpu_id.cpu.cp_imp) {
+
+       case MIPS_R2000:
+               printf("MIPS R2000 CPU");
+               break;
+       case MIPS_R3000:
+               printf("MIPS R3000 CPU");
+               break;
+       case MIPS_R6000:
+               printf("MIPS R6000 CPU");
+               break;
+       case MIPS_R4000:
+               if(CpuPrimaryInstCacheSize == 16384)
+                       printf("MIPS R4400 CPU");
+               else
+                       printf("MIPS R4000 CPU");
+               break;
+       case MIPS_R3LSI:
+               printf("LSI Logic R3000 derivate");
+               break;
+       case MIPS_R6000A:
+               printf("MIPS R6000A CPU");
+               break;
+       case MIPS_R3IDT:
+               printf("IDT R3000 derivate");
+               break;
+       case MIPS_R10000:
+               printf("MIPS R10000 CPU");
+               break;
+       case MIPS_R4200:
+               printf("MIPS R4200 CPU (ICE)");
+               break;
+       case MIPS_R8000:
+               printf("MIPS R8000 Blackbird/TFP CPU");
+               break;
+       case MIPS_R4600:
+               printf("QED R4600 Orion CPU");
+               break;
+       case MIPS_R3SONY:
+               printf("Sony R3000 based CPU");
+               break;
+       case MIPS_R3TOSH:
+               printf("Toshiba R3000 based CPU");
+               break;
+       case MIPS_R3NKK:
+               printf("NKK R3000 based CPU");
+               break;
+       case MIPS_UNKC1:
+       case MIPS_UNKC2:
+       default:
+               printf("Unknown CPU type (0x%x)",cpu_id.cpu.cp_imp);
+               break;
+       }
+       printf(" Rev. %d.%d with ", cpu_id.cpu.cp_majrev, cpu_id.cpu.cp_minrev);
+
+
+       switch(fpu_id.cpu.cp_imp) {
+
+       case MIPS_SOFT:
+               printf("Software emulation float");
+               break;
+       case MIPS_R2360:
+               printf("MIPS R2360 FPC");
+               break;
+       case MIPS_R2010:
+               printf("MIPS R2010 FPC");
+               break;
+       case MIPS_R3010:
+               printf("MIPS R3010 FPC");
+               break;
+       case MIPS_R6010:
+               printf("MIPS R6010 FPC");
+               break;
+       case MIPS_R4010:
+               printf("MIPS R4010 FPC");
+               break;
+       case MIPS_R31LSI:
+               printf("FPC");
+               break;
+       case MIPS_R10010:
+               printf("MIPS R10000 FPU");
+               break;
+       case MIPS_R4210:
+               printf("MIPS R4200 FPC (ICE)");
+       case MIPS_R8000:
+               printf("MIPS R8000 Blackbird/TFP");
+               break;
+       case MIPS_R4600:
+               printf("QED R4600 Orion FPC");
+               break;
+       case MIPS_R3SONY:
+               printf("Sony R3000 based FPC");
+               break;
+       case MIPS_R3TOSH:
+               printf("Toshiba R3000 based FPC");
+               break;
+       case MIPS_R3NKK:
+               printf("NKK R3000 based FPC");
+               break;
+       case MIPS_UNKF1:
+       default:
+               printf("Unknown FPU type (0x%x)", fpu_id.cpu.cp_imp);
+               break;
+       }
+       printf(" Rev. %d.%d", fpu_id.cpu.cp_majrev, fpu_id.cpu.cp_minrev);
+       printf("\n");
+
+       printf("Primary cache size: %dkb Instruction, %dkb Data.",
+               CpuPrimaryInstCacheSize / 1024,
+               CpuPrimaryDataCacheSize / 1024);
+       if(CpuTwoWayCache)
+               printf(" Two way set associative.\n");
+       else
+               printf(" Direct mapped.\n");
+}
+
diff --git a/sys/arch/wgrisc/wgrisc/cpu_exec.c b/sys/arch/wgrisc/wgrisc/cpu_exec.c
new file mode 100644 (file)
index 0000000..4e3e657
--- /dev/null
@@ -0,0 +1,104 @@
+/*     $NetBSD: cpu_exec.c,v 1.4 1995/04/25 19:16:46 mellon Exp $      */
+
+/*
+ * Copyright (c) 1992, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by Ralph
+ * Campbell.
+ *
+ * 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.
+ *
+ *     @(#)machdep.c   8.3 (Berkeley) 1/12/94
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/proc.h>
+#include <sys/malloc.h>
+#include <sys/vnode.h>
+#include <sys/exec.h>
+#include <sys/resourcevar.h>
+#include <vm/vm.h>
+
+#include <sys/exec_ecoff.h>
+#include <machine/reg.h>
+
+/*
+ * 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.
+ *
+ */
+int
+cpu_exec_aout_makecmds(p, epp)
+       struct proc *p;
+       struct exec_package *epp;
+{
+       return ENOEXEC;
+}
+
+#ifdef COMPAT_ULTRIX
+extern struct emul emul_ultrix;
+
+void
+cpu_exec_ecoff_setregs(p, pack, stack, retval)
+       struct proc *p;
+       struct exec_package *pack;
+       u_long stack;
+       register_t *retval;
+{
+       struct ecoff_aouthdr *eap;
+
+       setregs(p, pack, stack, retval);
+       eap = (struct ecoff_aouthdr *)
+           ((caddr_t)pack->ep_hdr + sizeof(struct ecoff_filehdr));
+       p->p_md.md_regs[GP] = eap->ea_gp_value;
+}
+
+/*
+ * cpu_exec_ecoff_hook():
+ *     cpu-dependent ECOFF format hook for execve().
+ * 
+ * Do any machine-dependent diddling of the exec package when doing ECOFF.
+ *
+ */
+int
+cpu_exec_ecoff_hook(p, epp, eap)
+       struct proc *p;
+       struct exec_package *epp;
+       struct ecoff_aouthdr *eap;
+{
+
+       epp->ep_emul = &emul_ultrix;
+       return 0;
+}
+#endif
diff --git a/sys/arch/wgrisc/wgrisc/disksubr.c b/sys/arch/wgrisc/wgrisc/disksubr.c
new file mode 100644 (file)
index 0000000..8f42365
--- /dev/null
@@ -0,0 +1,355 @@
+/*     $OpenBSD: disksubr.c,v 1.1.1.1 1997/02/06 16:02:45 pefo Exp $   */
+
+/*
+ * Copyright (c) 1994, 1995 Carnegie-Mellon University.
+ * All rights reserved.
+ *
+ * Authors: Keith Bostic, Chris G. Demetriou, Per Fogelstrom (R4000)
+ * 
+ * Permission to use, copy, modify and distribute this software and
+ * its documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ * 
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" 
+ * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND 
+ * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ * 
+ * Carnegie Mellon requests users of this software to return to
+ *
+ *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
+ *  School of Computer Science
+ *  Carnegie Mellon University
+ *  Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie the
+ * rights to redistribute these changes.
+ */
+
+#include <sys/param.h>
+#include <sys/buf.h>
+#include <sys/ioccom.h>
+#include <sys/device.h>
+#include <sys/disklabel.h>
+#include <sys/disk.h>
+
+#include <scsi/scsi_all.h>
+#include <scsi/scsiconf.h>
+
+#include <machine/cpu.h>
+#include <machine/autoconf.h>
+
+extern struct device *bootdv;
+
+int fat_types[] = { DOSPTYP_FAT12, DOSPTYP_FAT16S,
+                   DOSPTYP_FAT16B, DOSPTYP_FAT16C, -1 };
+
+/* was this the boot device ? */
+void
+dk_establish(dk, dev)
+       struct disk *dk;
+       struct device *dev;
+{
+}
+
+/*
+ * 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, clp)
+       dev_t dev;
+       void (*strat)();
+       struct disklabel *lp;
+       struct cpu_disklabel *clp;
+{
+       struct buf *bp;
+       struct disklabel *dlp;
+       struct dos_partition *dp = clp->dosparts;
+       char *msg = NULL;
+       int dospart, dospartoff, i, *ip;
+
+       /* minimal requirements for archtypal disk label */
+       if (lp->d_secperunit == 0)
+               lp->d_secperunit = 0x1fffffff; 
+       lp->d_npartitions = RAW_PART + 1;
+       for(i = 0; i < RAW_PART; i++) {
+               lp->d_partitions[i].p_size = 0;
+               lp->d_partitions[i].p_offset = 0;
+       }
+       if (lp->d_partitions[RAW_PART].p_size == 0)
+               lp->d_partitions[RAW_PART].p_size = 0x1fffffff;
+       lp->d_partitions[RAW_PART].p_offset = 0;
+
+       /* obtain buffer to probe drive with */
+       bp = geteblk((int)lp->d_secsize);
+       bp->b_dev = dev;
+       dospartoff = 0;
+       dospart = -1;
+
+       /* do dos partitions in the process of getting disklabel? */
+       if (dp) {
+               /* read master boot record */
+               bp->b_blkno = DOSBBSECTOR;
+               bp->b_bcount = lp->d_secsize;
+               bp->b_flags = B_BUSY | B_READ;
+               bp->b_resid = 0;
+               (*strat)(bp);
+
+               /* if successful, wander through dos partition table */
+               if (biowait(bp)) {
+                       msg = "dos partition I/O error";
+                       goto done;
+               }
+               if (*(unsigned int *)(bp->b_data) == 0x8efac033) {
+                       /* XXX how do we check veracity/bounds of this? */
+                       bcopy(bp->b_data + DOSPARTOFF, dp, NDOSPART * sizeof(*dp));
+
+                       for (i = 0, dp = clp->dosparts; i < NDOSPART; i++, dp++) {
+                               if (dp->dp_size && dp->dp_typ == DOSPTYP_OPENBSD
+                                   && dospart < 0)
+                                       dospart = i;
+                       }
+                       for (i = 0, dp = clp->dosparts; i < NDOSPART; i++, dp++) {
+                               if (dp->dp_size && dp->dp_typ == DOSPTYP_386BSD
+                                   && dospart < 0)
+                                       dospart = i;
+                       }
+                       if(dospart >= 0) {
+                               /*
+                                * set part a to show OpenBSD part
+                                */
+                               dp = clp->dosparts+dospart;
+                               dospartoff = dp->dp_start;
+
+                               lp->d_partitions[0].p_size = dp->dp_size;
+                               lp->d_partitions[0].p_offset = dp->dp_start;
+                               lp->d_partitions[RAW_PART].p_size = dp->dp_size;
+                               lp->d_partitions[RAW_PART].p_offset = dp->dp_start;
+                               lp->d_ntracks = dp->dp_ehd + 1;
+                               lp->d_nsectors = DPSECT(dp->dp_esect);
+                               lp->d_secpercyl = lp->d_ntracks * lp->d_nsectors;
+                       }
+                       /*
+                        * In case the disklabel read below fails, we want to provide
+                        * a fake label in which m/n/o/p are MBR partitions 0/1/2/3
+                        */
+                       for (i=0, dp = clp->dosparts; i < NDOSPART; i++, dp++) {
+                               lp->d_partitions[MAXPARTITIONS - NDOSPART + i].p_size = dp->dp_size;
+                               lp->d_partitions[MAXPARTITIONS - NDOSPART + i].p_offset = dp->dp_start;
+                               for (ip = fat_types; *ip != -1; ip++) {
+                                       if (dp->dp_typ != *ip)
+                                               continue;
+                                       lp->d_partitions[MAXPARTITIONS - NDOSPART +i].p_fstype = FS_MSDOS;
+                               }
+                       }
+                       lp->d_bbsize = 8192;
+                       lp->d_sbsize = 64*1024;         /* XXX ? */
+                       lp->d_npartitions = MAXPARTITIONS;
+               }
+                       
+       }
+       /* next, dig out disk label */
+       bp->b_blkno = dospartoff + LABELSECTOR;
+       bp->b_resid = 0;
+       bp->b_bcount = lp->d_secsize;
+       bp->b_flags = B_BUSY | B_READ;
+       (*strat)(bp);  
+
+       /* if successful, locate disk label within block and validate */
+       if (biowait(bp)) {
+               msg = "disk label read error";
+               goto done;
+       }
+
+       dlp = (struct disklabel *)(bp->b_un.b_addr + LABELOFFSET);
+       if (dlp->d_magic == DISKMAGIC) {
+               if (dkcksum(dlp)) {
+                       msg = "OpenBSD disk label corrupted";
+                       goto done;
+               }
+               *lp = *dlp;
+               goto done;
+       }
+       msg = "no disk label";
+done:
+       bp->b_flags = B_INVAL | B_AGE | B_READ;
+       brelse(bp);
+       return (msg);
+}
+
+/*
+ * Check new disk label for sensibility before setting it.
+ */
+int
+setdisklabel(olp, nlp, openmask, clp)
+       register struct disklabel *olp, *nlp;
+       u_long openmask;
+       struct cpu_disklabel *clp;
+{
+       register i;
+       register struct partition *opp, *npp;
+
+       /* sanity clause */
+       if (nlp->d_secpercyl == 0 || nlp->d_secsize == 0 ||
+           (nlp->d_secsize % DEV_BSIZE) != 0)
+               return(EINVAL);
+
+       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);     
+}
+
+/*
+ * Write disk label back to device after modification.
+ * this means write out the Rigid disk blocks to represent the 
+ * label.  Hope the user was carefull.
+ */
+int
+writedisklabel(dev, strat, lp, clp)
+       dev_t dev;
+       void (*strat)();
+       register struct disklabel *lp;
+       struct cpu_disklabel *clp;
+{
+       struct buf *bp; 
+       struct disklabel *dlp;
+       struct dos_partition *dp = clp->dosparts;
+       int error = 0, i;
+       int dospart, dospartoff;
+
+       bp = geteblk((int)lp->d_secsize);
+       bp->b_dev = dev;
+       dospart = -1;
+       dospartoff = 0;
+
+       /* do dos partitions in the process of getting disklabel? */
+       if (dp) {
+               /* read master boot record */
+               bp->b_blkno = DOSBBSECTOR;
+               bp->b_bcount = lp->d_secsize;
+               bp->b_flags = B_BUSY | B_READ;
+               bp->b_resid = 0;
+               (*strat)(bp);
+
+               if (((error = biowait(bp)) == 0) 
+                  && *(unsigned int *)(bp->b_data) == 0x8efac033) {
+                       /* XXX how do we check veracity/bounds of this? */
+                       bcopy(bp->b_data + DOSPARTOFF, dp, NDOSPART * sizeof(*dp));
+
+                       for (i = 0, dp = clp->dosparts; i < NDOSPART; i++, dp++) {
+                               if (dp->dp_size && dp->dp_typ == DOSPTYP_OPENBSD
+                                   && dospart < 0) {
+                                       dospart = i;
+                                       dospartoff = dp->dp_start;
+                               }
+                       }
+                       for (i = 0, dp = clp->dosparts; i < NDOSPART; i++, dp++) {
+                               if (dp->dp_size && dp->dp_typ == DOSPTYP_386BSD
+                                   && dospart < 0) {
+                                       dospart = i;
+                                       dospartoff = dp->dp_start;
+                               }
+                       }
+               }
+                       
+       }
+       bp->b_blkno = dospartoff + LABELSECTOR;
+       bp->b_resid = 0;
+       bp->b_bcount = lp->d_secsize;
+       bp->b_flags = B_READ;           /* get current label */
+       (*strat)(bp);
+       if (error = biowait(bp))
+               goto done;
+
+       dlp = (struct disklabel *)(bp->b_un.b_addr + LABELOFFSET);
+       *dlp = *lp;     /* struct assignment */
+
+       bp->b_flags = B_WRITE;
+       (*strat)(bp);
+       error = biowait(bp);
+
+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;
+{
+#define dkpart(dev) (minor(dev) % MAXPARTITIONS )
+
+       struct partition *p = lp->d_partitions + dkpart(bp->b_dev);
+       int labelsect = lp->d_partitions[RAW_PART].p_offset;
+       int maxsz = p->p_size;
+       int sz = (bp->b_bcount + DEV_BSIZE - 1) >> DEV_BSHIFT;
+
+       /* overwriting disk label ? */
+       /* XXX should also protect bootstrap in first 8K */ 
+       if (bp->b_blkno + p->p_offset == LABELSECTOR + labelsect &&
+           (bp->b_flags & B_READ) == 0 && wlabel == 0) {
+               bp->b_error = EROFS;
+               goto bad;
+       }
+
+       /* beyond partition? */ 
+       if (bp->b_blkno < 0 || bp->b_blkno + sz > maxsz) {
+               /* if exactly at end of disk, return an EOF */
+               if (bp->b_blkno == maxsz) {
+                       bp->b_resid = bp->b_bcount;
+                       return(0);
+               }
+               /* or truncate if part of it fits */
+               sz = maxsz - bp->b_blkno;
+               if (sz <= 0) {
+                       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/wgrisc/wgrisc/fp.S b/sys/arch/wgrisc/wgrisc/fp.S
new file mode 100644 (file)
index 0000000..3251298
--- /dev/null
@@ -0,0 +1,3611 @@
+/*     $OpenBSD: fp.S,v 1.1.1.1 1997/02/06 16:02:45 pefo Exp $ */
+/*
+ * Copyright (c) 1992, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Ralph Campbell.
+ *
+ * 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: @(#)fp.s  8.1 (Berkeley) 6/10/93
+ *      $Id: fp.S,v 1.1.1.1 1997/02/06 16:02:45 pefo Exp $
+ */
+
+/*
+ * Standard header stuff.
+ */
+
+#include <machine/regdef.h>
+#include <machine/asm.h>
+#include <machine/cpu.h>
+
+#include "assym.h"
+
+#define SEXP_INF       0xff
+#define DEXP_INF       0x7ff
+#define SEXP_BIAS      127
+#define DEXP_BIAS      1023
+#define SEXP_MIN       -126
+#define DEXP_MIN       -1022
+#define SEXP_MAX       127
+#define DEXP_MAX       1023
+#define WEXP_MAX       30              /* maximum unbiased exponent for int */
+#define WEXP_MIN       -1              /* minimum unbiased exponent for int */
+#define SFRAC_BITS     23
+#define DFRAC_BITS     52
+#define SIMPL_ONE      0x00800000
+#define DIMPL_ONE      0x00100000
+#define SLEAD_ZEROS    31 - 23
+#define DLEAD_ZEROS    31 - 20
+#define STICKYBIT      1
+#define GUARDBIT       0x80000000
+#define SSIGNAL_NAN    0x00400000
+#define DSIGNAL_NAN    0x00080000
+#define SQUIET_NAN     0x003fffff
+#define DQUIET_NAN0    0x0007ffff
+#define DQUIET_NAN1    0xffffffff
+#define INT_MIN                0x80000000
+#define INT_MAX                0x7fffffff
+
+#define COND_UNORDERED 0x1
+#define COND_EQUAL     0x2
+#define COND_LESS      0x4
+#define COND_SIGNAL    0x8
+
+/*----------------------------------------------------------------------------
+ *
+ * CPU_EmulateFP --
+ *
+ *     Emulate unimplemented floating point operations.
+ *     This routine should only be called by CPU_FPInterrupt().
+ *
+ *     CPU_EmulateFP(instr)
+ *             unsigned instr;
+ *
+ * Results:
+ *     None.
+ *
+ * Side effects:
+ *     Floating point registers are modified according to instruction.
+ *
+ *----------------------------------------------------------------------------
+ */
+NON_LEAF(CPU_EmulateFP, STAND_FRAME_SIZE, ra)
+       subu    sp, sp, STAND_FRAME_SIZE
+       sw      ra, STAND_RA_OFFSET(sp)
+/*
+ * Decode the FMT field (bits 24-21) and FUNCTION field (bits 5-0).
+ */
+       srl     v0, a0, 21 - 2                  # get FMT field
+       and     v0, v0, 0xF << 2                # mask FMT field
+       and     v1, a0, 0x3F                    # mask FUNC field
+       sll     v1, v1, 5                       # align for table lookup
+       bgt     v0, 4 << 2, ill                 # illegal format
+
+       or      v1, v1, v0
+       cfc1    a1, FPC_CSR             # get exception register
+       lw      a3, func_fmt_tbl(v1)            # switch on FUNC & FMT
+       and     a1, a1, ~FPC_EXCEPTION_UNIMPL   # clear exception
+       ctc1    a1, FPC_CSR
+       j       a3
+
+       .rdata
+func_fmt_tbl:
+       .word   add_s           # 0
+       .word   add_d           # 0
+       .word   ill             # 0
+       .word   ill             # 0
+       .word   ill             # 0
+       .word   ill             # 0
+       .word   ill             # 0
+       .word   ill             # 0
+       .word   sub_s           # 1
+       .word   sub_d           # 1
+       .word   ill             # 1
+       .word   ill             # 1
+       .word   ill             # 1
+       .word   ill             # 1
+       .word   ill             # 1
+       .word   ill             # 1
+       .word   mul_s           # 2
+       .word   mul_d           # 2
+       .word   ill             # 2
+       .word   ill             # 2
+       .word   ill             # 2
+       .word   ill             # 2
+       .word   ill             # 2
+       .word   ill             # 2
+       .word   div_s           # 3
+       .word   div_d           # 3
+       .word   ill             # 3
+       .word   ill             # 3
+       .word   ill             # 3
+       .word   ill             # 3
+       .word   ill             # 3
+       .word   ill             # 3
+       .word   ill             # 4
+       .word   ill             # 4
+       .word   ill             # 4
+       .word   ill             # 4
+       .word   ill             # 4
+       .word   ill             # 4
+       .word   ill             # 4
+       .word   ill             # 4
+       .word   abs_s           # 5
+       .word   abs_d           # 5
+       .word   ill             # 5
+       .word   ill             # 5
+       .word   ill             # 5
+       .word   ill             # 5
+       .word   ill             # 5
+       .word   ill             # 5
+       .word   mov_s           # 6
+       .word   mov_d           # 6
+       .word   ill             # 6
+       .word   ill             # 6
+       .word   ill             # 6
+       .word   ill             # 6
+       .word   ill             # 6
+       .word   ill             # 6
+       .word   neg_s           # 7
+       .word   neg_d           # 7
+       .word   ill             # 7
+       .word   ill             # 7
+       .word   ill             # 7
+       .word   ill             # 7
+       .word   ill             # 7
+       .word   ill             # 7
+       .word   ill             # 8
+       .word   ill             # 8
+       .word   ill             # 8
+       .word   ill             # 8
+       .word   ill             # 8
+       .word   ill             # 8
+       .word   ill             # 8
+       .word   ill             # 8
+       .word   ill             # 9
+       .word   ill             # 9
+       .word   ill             # 9
+       .word   ill             # 9
+       .word   ill             # 9
+       .word   ill             # 9
+       .word   ill             # 9
+       .word   ill             # 9
+       .word   ill             # 10
+       .word   ill             # 10
+       .word   ill             # 10
+       .word   ill             # 10
+       .word   ill             # 10
+       .word   ill             # 10
+       .word   ill             # 10
+       .word   ill             # 10
+       .word   ill             # 11
+       .word   ill             # 11
+       .word   ill             # 11
+       .word   ill             # 11
+       .word   ill             # 11
+       .word   ill             # 11
+       .word   ill             # 11
+       .word   ill             # 11
+       .word   ill             # 12
+       .word   ill             # 12
+       .word   ill             # 12
+       .word   ill             # 12
+       .word   ill             # 12
+       .word   ill             # 12
+       .word   ill             # 12
+       .word   ill             # 12
+       .word   ill             # 13
+       .word   ill             # 13
+       .word   ill             # 13
+       .word   ill             # 13
+       .word   ill             # 13
+       .word   ill             # 13
+       .word   ill             # 13
+       .word   ill             # 13
+       .word   ill             # 14
+       .word   ill             # 14
+       .word   ill             # 14
+       .word   ill             # 14
+       .word   ill             # 14
+       .word   ill             # 14
+       .word   ill             # 14
+       .word   ill             # 14
+       .word   ill             # 15
+       .word   ill             # 15
+       .word   ill             # 15
+       .word   ill             # 15
+       .word   ill             # 15
+       .word   ill             # 15
+       .word   ill             # 15
+       .word   ill             # 15
+       .word   ill             # 16
+       .word   ill             # 16
+       .word   ill             # 16
+       .word   ill             # 16
+       .word   ill             # 16
+       .word   ill             # 16
+       .word   ill             # 16
+       .word   ill             # 16
+       .word   ill             # 17
+       .word   ill             # 17
+       .word   ill             # 17
+       .word   ill             # 17
+       .word   ill             # 17
+       .word   ill             # 17
+       .word   ill             # 17
+       .word   ill             # 17
+       .word   ill             # 18
+       .word   ill             # 18
+       .word   ill             # 18
+       .word   ill             # 18
+       .word   ill             # 18
+       .word   ill             # 18
+       .word   ill             # 18
+       .word   ill             # 18
+       .word   ill             # 19
+       .word   ill             # 19
+       .word   ill             # 19
+       .word   ill             # 19
+       .word   ill             # 19
+       .word   ill             # 19
+       .word   ill             # 19
+       .word   ill             # 19
+       .word   ill             # 20
+       .word   ill             # 20
+       .word   ill             # 20
+       .word   ill             # 20
+       .word   ill             # 20
+       .word   ill             # 20
+       .word   ill             # 20
+       .word   ill             # 20
+       .word   ill             # 21
+       .word   ill             # 21
+       .word   ill             # 21
+       .word   ill             # 21
+       .word   ill             # 21
+       .word   ill             # 21
+       .word   ill             # 21
+       .word   ill             # 21
+       .word   ill             # 22
+       .word   ill             # 22
+       .word   ill             # 22
+       .word   ill             # 22
+       .word   ill             # 22
+       .word   ill             # 22
+       .word   ill             # 22
+       .word   ill             # 22
+       .word   ill             # 23
+       .word   ill             # 23
+       .word   ill             # 23
+       .word   ill             # 23
+       .word   ill             # 23
+       .word   ill             # 23
+       .word   ill             # 23
+       .word   ill             # 23
+       .word   ill             # 24
+       .word   ill             # 24
+       .word   ill             # 24
+       .word   ill             # 24
+       .word   ill             # 24
+       .word   ill             # 24
+       .word   ill             # 24
+       .word   ill             # 24
+       .word   ill             # 25
+       .word   ill             # 25
+       .word   ill             # 25
+       .word   ill             # 25
+       .word   ill             # 25
+       .word   ill             # 25
+       .word   ill             # 25
+       .word   ill             # 25
+       .word   ill             # 26
+       .word   ill             # 26
+       .word   ill             # 26
+       .word   ill             # 26
+       .word   ill             # 26
+       .word   ill             # 26
+       .word   ill             # 26
+       .word   ill             # 26
+       .word   ill             # 27
+       .word   ill             # 27
+       .word   ill             # 27
+       .word   ill             # 27
+       .word   ill             # 27
+       .word   ill             # 27
+       .word   ill             # 27
+       .word   ill             # 27
+       .word   ill             # 28
+       .word   ill             # 28
+       .word   ill             # 28
+       .word   ill             # 28
+       .word   ill             # 28
+       .word   ill             # 28
+       .word   ill             # 28
+       .word   ill             # 28
+       .word   ill             # 29
+       .word   ill             # 29
+       .word   ill             # 29
+       .word   ill             # 29
+       .word   ill             # 29
+       .word   ill             # 29
+       .word   ill             # 29
+       .word   ill             # 29
+       .word   ill             # 30
+       .word   ill             # 30
+       .word   ill             # 30
+       .word   ill             # 30
+       .word   ill             # 30
+       .word   ill             # 30
+       .word   ill             # 30
+       .word   ill             # 30
+       .word   ill             # 31
+       .word   ill             # 31
+       .word   ill             # 31
+       .word   ill             # 31
+       .word   ill             # 31
+       .word   ill             # 31
+       .word   ill             # 31
+       .word   ill             # 31
+       .word   ill             # 32
+       .word   cvt_s_d         # 32
+       .word   ill             # 32
+       .word   ill             # 32
+       .word   cvt_s_w         # 32
+       .word   ill             # 32
+       .word   ill             # 32
+       .word   ill             # 32
+       .word   cvt_d_s         # 33
+       .word   ill             # 33
+       .word   ill             # 33
+       .word   ill             # 33
+       .word   cvt_d_w         # 33
+       .word   ill             # 33
+       .word   ill             # 33
+       .word   ill             # 33
+       .word   ill             # 34
+       .word   ill             # 34
+       .word   ill             # 34
+       .word   ill             # 34
+       .word   ill             # 34
+       .word   ill             # 34
+       .word   ill             # 34
+       .word   ill             # 34
+       .word   ill             # 35
+       .word   ill             # 35
+       .word   ill             # 35
+       .word   ill             # 35
+       .word   ill             # 35
+       .word   ill             # 35
+       .word   ill             # 35
+       .word   ill             # 35
+       .word   cvt_w_s         # 36
+       .word   cvt_w_d         # 36
+       .word   ill             # 36
+       .word   ill             # 36
+       .word   ill             # 36
+       .word   ill             # 36
+       .word   ill             # 36
+       .word   ill             # 36
+       .word   ill             # 37
+       .word   ill             # 37
+       .word   ill             # 37
+       .word   ill             # 37
+       .word   ill             # 37
+       .word   ill             # 37
+       .word   ill             # 37
+       .word   ill             # 37
+       .word   ill             # 38
+       .word   ill             # 38
+       .word   ill             # 38
+       .word   ill             # 38
+       .word   ill             # 38
+       .word   ill             # 38
+       .word   ill             # 38
+       .word   ill             # 38
+       .word   ill             # 39
+       .word   ill             # 39
+       .word   ill             # 39
+       .word   ill             # 39
+       .word   ill             # 39
+       .word   ill             # 39
+       .word   ill             # 39
+       .word   ill             # 39
+       .word   ill             # 40
+       .word   ill             # 40
+       .word   ill             # 40
+       .word   ill             # 40
+       .word   ill             # 40
+       .word   ill             # 40
+       .word   ill             # 40
+       .word   ill             # 40
+       .word   ill             # 41
+       .word   ill             # 41
+       .word   ill             # 41
+       .word   ill             # 41
+       .word   ill             # 41
+       .word   ill             # 41
+       .word   ill             # 41
+       .word   ill             # 41
+       .word   ill             # 42
+       .word   ill             # 42
+       .word   ill             # 42
+       .word   ill             # 42
+       .word   ill             # 42
+       .word   ill             # 42
+       .word   ill             # 42
+       .word   ill             # 42
+       .word   ill             # 43
+       .word   ill             # 43
+       .word   ill             # 43
+       .word   ill             # 43
+       .word   ill             # 43
+       .word   ill             # 43
+       .word   ill             # 43
+       .word   ill             # 43
+       .word   ill             # 44
+       .word   ill             # 44
+       .word   ill             # 44
+       .word   ill             # 44
+       .word   ill             # 44
+       .word   ill             # 44
+       .word   ill             # 44
+       .word   ill             # 44
+       .word   ill             # 45
+       .word   ill             # 45
+       .word   ill             # 45
+       .word   ill             # 45
+       .word   ill             # 45
+       .word   ill             # 45
+       .word   ill             # 45
+       .word   ill             # 45
+       .word   ill             # 46
+       .word   ill             # 46
+       .word   ill             # 46
+       .word   ill             # 46
+       .word   ill             # 46
+       .word   ill             # 46
+       .word   ill             # 46
+       .word   ill             # 46
+       .word   ill             # 47
+       .word   ill             # 47
+       .word   ill             # 47
+       .word   ill             # 47
+       .word   ill             # 47
+       .word   ill             # 47
+       .word   ill             # 47
+       .word   ill             # 47
+       .word   cmp_s           # 48
+       .word   cmp_d           # 48
+       .word   ill             # 48
+       .word   ill             # 48
+       .word   ill             # 48
+       .word   ill             # 48
+       .word   ill             # 48
+       .word   ill             # 48
+       .word   cmp_s           # 49
+       .word   cmp_d           # 49
+       .word   ill             # 49
+       .word   ill             # 49
+       .word   ill             # 49
+       .word   ill             # 49
+       .word   ill             # 49
+       .word   ill             # 49
+       .word   cmp_s           # 50
+       .word   cmp_d           # 50
+       .word   ill             # 50
+       .word   ill             # 50
+       .word   ill             # 50
+       .word   ill             # 50
+       .word   ill             # 50
+       .word   ill             # 50
+       .word   cmp_s           # 51
+       .word   cmp_d           # 51
+       .word   ill             # 51
+       .word   ill             # 51
+       .word   ill             # 51
+       .word   ill             # 51
+       .word   ill             # 51
+       .word   ill             # 51
+       .word   cmp_s           # 52
+       .word   cmp_d           # 52
+       .word   ill             # 52
+       .word   ill             # 52
+       .word   ill             # 52
+       .word   ill             # 52
+       .word   ill             # 52
+       .word   ill             # 52
+       .word   cmp_s           # 53
+       .word   cmp_d           # 53
+       .word   ill             # 53
+       .word   ill             # 53
+       .word   ill             # 53
+       .word   ill             # 53
+       .word   ill             # 53
+       .word   ill             # 53
+       .word   cmp_s           # 54
+       .word   cmp_d           # 54
+       .word   ill             # 54
+       .word   ill             # 54
+       .word   ill             # 54
+       .word   ill             # 54
+       .word   ill             # 54
+       .word   ill             # 54
+       .word   cmp_s           # 55
+       .word   cmp_d           # 55
+       .word   ill             # 55
+       .word   ill             # 55
+       .word   ill             # 55
+       .word   ill             # 55
+       .word   ill             # 55
+       .word   ill             # 55
+       .word   cmp_s           # 56
+       .word   cmp_d           # 56
+       .word   ill             # 56
+       .word   ill             # 56
+       .word   ill             # 56
+       .word   ill             # 56
+       .word   ill             # 56
+       .word   ill             # 56
+       .word   cmp_s           # 57
+       .word   cmp_d           # 57
+       .word   ill             # 57
+       .word   ill             # 57
+       .word   ill             # 57
+       .word   ill             # 57
+       .word   ill             # 57
+       .word   ill             # 57
+       .word   cmp_s           # 58
+       .word   cmp_d           # 58
+       .word   ill             # 58
+       .word   ill             # 58
+       .word   ill             # 58
+       .word   ill             # 58
+       .word   ill             # 58
+       .word   ill             # 58
+       .word   cmp_s           # 59
+       .word   cmp_d           # 59
+       .word   ill             # 59
+       .word   ill             # 59
+       .word   ill             # 59
+       .word   ill             # 59
+       .word   ill             # 59
+       .word   ill             # 59
+       .word   cmp_s           # 60
+       .word   cmp_d           # 60
+       .word   ill             # 60
+       .word   ill             # 60
+       .word   ill             # 60
+       .word   ill             # 60
+       .word   ill             # 60
+       .word   ill             # 60
+       .word   cmp_s           # 61
+       .word   cmp_d           # 61
+       .word   ill             # 61
+       .word   ill             # 61
+       .word   ill             # 61
+       .word   ill             # 61
+       .word   ill             # 61
+       .word   ill             # 61
+       .word   cmp_s           # 62
+       .word   cmp_d           # 62
+       .word   ill             # 62
+       .word   ill             # 62
+       .word   ill             # 62
+       .word   ill             # 62
+       .word   ill             # 62
+       .word   ill             # 62
+       .word   cmp_s           # 63
+       .word   cmp_d           # 63
+       .word   ill             # 63
+       .word   ill             # 63
+       .word   ill             # 63
+       .word   ill             # 63
+       .word   ill             # 63
+       .word   ill             # 63
+       .text
+
+/*
+ * Single precision subtract.
+ */
+sub_s:
+       jal     get_ft_fs_s
+       xor     t4, t4, 1                       # negate FT sign bit
+       b       add_sub_s
+/*
+ * Single precision add.
+ */
+add_s:
+       jal     get_ft_fs_s
+add_sub_s:
+       bne     t1, SEXP_INF, 1f                # is FS an infinity?
+       bne     t5, SEXP_INF, result_fs_s       # if FT is not inf, result=FS
+       bne     t2, zero, result_fs_s           # if FS is NAN, result is FS
+       bne     t6, zero, result_ft_s           # if FT is NAN, result is FT
+       bne     t0, t4, invalid_s               # both infinities same sign?
+       b       result_fs_s                     # result is in FS
+1:
+       beq     t5, SEXP_INF, result_ft_s       # if FT is inf, result=FT
+       bne     t1, zero, 4f                    # is FS a denormalized num?
+       beq     t2, zero, 3f                    # is FS zero?
+       bne     t5, zero, 2f                    # is FT a denormalized num?
+       beq     t6, zero, result_fs_s           # FT is zero, result=FS
+       jal     renorm_fs_s
+       jal     renorm_ft_s
+       b       5f
+2:
+       jal     renorm_fs_s
+       subu    t5, t5, SEXP_BIAS               # unbias FT exponent
+       or      t6, t6, SIMPL_ONE               # set implied one bit
+       b       5f
+3:
+       bne     t5, zero, result_ft_s           # if FT != 0, result=FT
+       bne     t6, zero, result_ft_s
+       and     v0, a1, FPC_ROUNDING_BITS       # get rounding mode
+       bne     v0, FPC_ROUND_RM, 1f    # round to -infinity?
+       or      t0, t0, t4                      # compute result sign
+       b       result_fs_s
+1:
+       and     t0, t0, t4                      # compute result sign
+       b       result_fs_s
+4:
+       bne     t5, zero, 2f                    # is FT a denormalized num?
+       beq     t6, zero, result_fs_s           # FT is zero, result=FS
+       subu    t1, t1, SEXP_BIAS               # unbias FS exponent
+       or      t2, t2, SIMPL_ONE               # set implied one bit
+       jal     renorm_ft_s
+       b       5f
+2:
+       subu    t1, t1, SEXP_BIAS               # unbias FS exponent
+       or      t2, t2, SIMPL_ONE               # set implied one bit
+       subu    t5, t5, SEXP_BIAS               # unbias FT exponent
+       or      t6, t6, SIMPL_ONE               # set implied one bit
+/*
+ * Perform the addition.
+ */
+5:
+       move    t8, zero                        # no shifted bits (sticky reg)
+       beq     t1, t5, 4f                      # no shift needed
+       subu    v0, t1, t5                      # v0 = difference of exponents
+       move    v1, v0                          # v1 = abs(difference)
+       bge     v0, zero, 1f
+       negu    v1
+1:
+       ble     v1, SFRAC_BITS+2, 2f            # is difference too great?
+       li      t8, STICKYBIT                   # set the sticky bit
+       bge     v0, zero, 1f                    # check which exp is larger
+       move    t1, t5                          # result exp is FTs
+       move    t2, zero                        # FSs fraction shifted is zero
+       b       4f
+1:
+       move    t6, zero                        # FTs fraction shifted is zero
+       b       4f
+2:
+       li      t9, 32                          # compute 32 - abs(exp diff)
+       subu    t9, t9, v1
+       bgt     v0, zero, 3f                    # if FS > FT, shift FTs frac
+       move    t1, t5                          # FT > FS, result exp is FTs
+       sll     t8, t2, t9                      # save bits shifted out
+       srl     t2, t2, v1                      # shift FSs fraction
+       b       4f
+3:
+       sll     t8, t6, t9                      # save bits shifted out
+       srl     t6, t6, v1                      # shift FTs fraction
+4:
+       bne     t0, t4, 1f                      # if signs differ, subtract
+       addu    t2, t2, t6                      # add fractions
+       b       norm_s
+1:
+       blt     t2, t6, 3f                      # subtract larger from smaller
+       bne     t2, t6, 2f                      # if same, result=0
+       move    t1, zero                        # result=0
+       move    t2, zero
+       and     v0, a1, FPC_ROUNDING_BITS       # get rounding mode
+       bne     v0, FPC_ROUND_RM, 1f    # round to -infinity?
+       or      t0, t0, t4                      # compute result sign
+       b       result_fs_s
+1:
+       and     t0, t0, t4                      # compute result sign
+       b       result_fs_s
+2:
+       sltu    t9, zero, t8                    # compute t2:zero - t6:t8
+       subu    t8, zero, t8
+       subu    t2, t2, t6                      # subtract fractions
+       subu    t2, t2, t9                      # subtract barrow
+       b       norm_s
+3:
+       move    t0, t4                          # sign of result = FTs
+       sltu    t9, zero, t8                    # compute t6:zero - t2:t8
+       subu    t8, zero, t8
+       subu    t2, t6, t2                      # subtract fractions
+       subu    t2, t2, t9                      # subtract barrow
+       b       norm_s
+
+/*
+ * Double precision subtract.
+ */
+sub_d:
+       jal     get_ft_fs_d
+       xor     t4, t4, 1                       # negate sign bit
+       b       add_sub_d
+/*
+ * Double precision add.
+ */
+add_d:
+       jal     get_ft_fs_d
+add_sub_d:
+       bne     t1, DEXP_INF, 1f                # is FS an infinity?
+       bne     t5, DEXP_INF, result_fs_d       # if FT is not inf, result=FS
+       bne     t2, zero, result_fs_d           # if FS is NAN, result is FS
+       bne     t3, zero, result_fs_d
+       bne     t6, zero, result_ft_d           # if FT is NAN, result is FT
+       bne     t7, zero, result_ft_d
+       bne     t0, t4, invalid_d               # both infinities same sign?
+       b       result_fs_d                     # result is in FS
+1:
+       beq     t5, DEXP_INF, result_ft_d       # if FT is inf, result=FT
+       bne     t1, zero, 4f                    # is FS a denormalized num?
+       bne     t2, zero, 1f                    # is FS zero?
+       beq     t3, zero, 3f
+1:
+       bne     t5, zero, 2f                    # is FT a denormalized num?
+       bne     t6, zero, 1f
+       beq     t7, zero, result_fs_d           # FT is zero, result=FS
+1:
+       jal     renorm_fs_d
+       jal     renorm_ft_d
+       b       5f
+2:
+       jal     renorm_fs_d
+       subu    t5, t5, DEXP_BIAS               # unbias FT exponent
+       or      t6, t6, DIMPL_ONE               # set implied one bit
+       b       5f
+3:
+       bne     t5, zero, result_ft_d           # if FT != 0, result=FT
+       bne     t6, zero, result_ft_d
+       bne     t7, zero, result_ft_d
+       and     v0, a1, FPC_ROUNDING_BITS       # get rounding mode
+       bne     v0, FPC_ROUND_RM, 1f    # round to -infinity?
+       or      t0, t0, t4                      # compute result sign
+       b       result_fs_d
+1:
+       and     t0, t0, t4                      # compute result sign
+       b       result_fs_d
+4:
+       bne     t5, zero, 2f                    # is FT a denormalized num?
+       bne     t6, zero, 1f
+       beq     t7, zero, result_fs_d           # FT is zero, result=FS
+1:
+       subu    t1, t1, DEXP_BIAS               # unbias FS exponent
+       or      t2, t2, DIMPL_ONE               # set implied one bit
+       jal     renorm_ft_d
+       b       5f
+2:
+       subu    t1, t1, DEXP_BIAS               # unbias FS exponent
+       or      t2, t2, DIMPL_ONE               # set implied one bit
+       subu    t5, t5, DEXP_BIAS               # unbias FT exponent
+       or      t6, t6, DIMPL_ONE               # set implied one bit
+/*
+ * Perform the addition.
+ */
+5:
+       move    t8, zero                        # no shifted bits (sticky reg)
+       beq     t1, t5, 4f                      # no shift needed
+       subu    v0, t1, t5                      # v0 = difference of exponents
+       move    v1, v0                          # v1 = abs(difference)
+       bge     v0, zero, 1f
+       negu    v1
+1:
+       ble     v1, DFRAC_BITS+2, 2f            # is difference too great?
+       li      t8, STICKYBIT                   # set the sticky bit
+       bge     v0, zero, 1f                    # check which exp is larger
+       move    t1, t5                          # result exp is FTs
+       move    t2, zero                        # FSs fraction shifted is zero
+       move    t3, zero
+       b       4f
+1:
+       move    t6, zero                        # FTs fraction shifted is zero
+       move    t7, zero
+       b       4f
+2:
+       li      t9, 32
+       bge     v0, zero, 3f                    # if FS > FT, shift FTs frac
+       move    t1, t5                          # FT > FS, result exp is FTs
+       blt     v1, t9, 1f                      # shift right by < 32?
+       subu    v1, v1, t9
+       subu    t9, t9, v1
+       sll     t8, t2, t9                      # save bits shifted out
+       sltu    t9, zero, t3                    # dont lose any one bits
+       or      t8, t8, t9                      # save sticky bit
+       srl     t3, t2, v1                      # shift FSs fraction
+       move    t2, zero
+       b       4f
+1:
+       subu    t9, t9, v1
+       sll     t8, t3, t9                      # save bits shifted out
+       srl     t3, t3, v1                      # shift FSs fraction
+       sll     t9, t2, t9                      # save bits shifted out of t2
+       or      t3, t3, t9                      # and put into t3
+       srl     t2, t2, v1
+       b       4f
+3:
+       blt     v1, t9, 1f                      # shift right by < 32?
+       subu    v1, v1, t9
+       subu    t9, t9, v1
+       sll     t8, t6, t9                      # save bits shifted out
+       srl     t7, t6, v1                      # shift FTs fraction
+       move    t6, zero
+       b       4f
+1:
+       subu    t9, t9, v1
+       sll     t8, t7, t9                      # save bits shifted out
+       srl     t7, t7, v1                      # shift FTs fraction
+       sll     t9, t6, t9                      # save bits shifted out of t2
+       or      t7, t7, t9                      # and put into t3
+       srl     t6, t6, v1
+4:
+       bne     t0, t4, 1f                      # if signs differ, subtract
+       addu    t3, t3, t7                      # add fractions
+       sltu    t9, t3, t7                      # compute carry
+       addu    t2, t2, t6                      # add fractions
+       addu    t2, t2, t9                      # add carry
+       b       norm_d
+1:
+       blt     t2, t6, 3f                      # subtract larger from smaller
+       bne     t2, t6, 2f
+       bltu    t3, t7, 3f
+       bne     t3, t7, 2f                      # if same, result=0
+       move    t1, zero                        # result=0
+       move    t2, zero
+       move    t3, zero
+       and     v0, a1, FPC_ROUNDING_BITS       # get rounding mode
+       bne     v0, FPC_ROUND_RM, 1f    # round to -infinity?
+       or      t0, t0, t4                      # compute result sign
+       b       result_fs_d
+1:
+       and     t0, t0, t4                      # compute result sign
+       b       result_fs_d
+2:
+       beq     t8, zero, 1f                    # compute t2:t3:zero - t6:t7:t8
+       subu    t8, zero, t8
+       sltu    v0, t3, 1                       # compute barrow out
+       subu    t3, t3, 1                       # subtract barrow
+       subu    t2, t2, v0
+1:
+       sltu    v0, t3, t7
+       subu    t3, t3, t7                      # subtract fractions
+       subu    t2, t2, t6                      # subtract fractions
+       subu    t2, t2, v0                      # subtract barrow
+       b       norm_d
+3:
+       move    t0, t4                          # sign of result = FTs
+       beq     t8, zero, 1f                    # compute t6:t7:zero - t2:t3:t8
+       subu    t8, zero, t8
+       sltu    v0, t7, 1                       # compute barrow out
+       subu    t7, t7, 1                       # subtract barrow
+       subu    t6, t6, v0
+1:
+       sltu    v0, t7, t3
+       subu    t3, t7, t3                      # subtract fractions
+       subu    t2, t6, t2                      # subtract fractions
+       subu    t2, t2, v0                      # subtract barrow
+       b       norm_d
+
+/*
+ * Single precision multiply.
+ */
+mul_s:
+       jal     get_ft_fs_s
+       xor     t0, t0, t4                      # compute sign of result
+       move    t4, t0
+       bne     t1, SEXP_INF, 2f                # is FS an infinity?
+       bne     t2, zero, result_fs_s           # if FS is a NAN, result=FS
+       bne     t5, SEXP_INF, 1f                # FS is inf, is FT an infinity?
+       bne     t6, zero, result_ft_s           # if FT is a NAN, result=FT
+       b       result_fs_s                     # result is infinity
+1:
+       bne     t5, zero, result_fs_s           # inf * zero? if no, result=FS
+       bne     t6, zero, result_fs_s
+       b       invalid_s                       # infinity * zero is invalid
+2:
+       bne     t5, SEXP_INF, 1f                # FS != inf, is FT an infinity?
+       bne     t1, zero, result_ft_s           # zero * inf? if no, result=FT
+       bne     t2, zero, result_ft_s
+       bne     t6, zero, result_ft_s           # if FT is a NAN, result=FT
+       b       invalid_s                       # zero * infinity is invalid
+1:
+       bne     t1, zero, 1f                    # is FS zero?
+       beq     t2, zero, result_fs_s           # result is zero
+       jal     renorm_fs_s
+       b       2f
+1:
+       subu    t1, t1, SEXP_BIAS               # unbias FS exponent
+       or      t2, t2, SIMPL_ONE               # set implied one bit
+2:
+       bne     t5, zero, 1f                    # is FT zero?
+       beq     t6, zero, result_ft_s           # result is zero
+       jal     renorm_ft_s
+       b       2f
+1:
+       subu    t5, t5, SEXP_BIAS               # unbias FT exponent
+       or      t6, t6, SIMPL_ONE               # set implied one bit
+2:
+       addu    t1, t1, t5                      # compute result exponent
+       addu    t1, t1, 9                       # account for binary point
+       multu   t2, t6                          # multiply fractions
+       mflo    t8
+       mfhi    t2
+       b       norm_s
+
+/*
+ * Double precision multiply.
+ */
+mul_d:
+       jal     get_ft_fs_d
+       xor     t0, t0, t4                      # compute sign of result
+       move    t4, t0
+       bne     t1, DEXP_INF, 2f                # is FS an infinity?
+       bne     t2, zero, result_fs_d           # if FS is a NAN, result=FS
+       bne     t3, zero, result_fs_d
+       bne     t5, DEXP_INF, 1f                # FS is inf, is FT an infinity?
+       bne     t6, zero, result_ft_d           # if FT is a NAN, result=FT
+       bne     t7, zero, result_ft_d
+       b       result_fs_d                     # result is infinity
+1:
+       bne     t5, zero, result_fs_d           # inf * zero? if no, result=FS
+       bne     t6, zero, result_fs_d
+       bne     t7, zero, result_fs_d
+       b       invalid_d                       # infinity * zero is invalid
+2:
+       bne     t5, DEXP_INF, 1f                # FS != inf, is FT an infinity?
+       bne     t1, zero, result_ft_d           # zero * inf? if no, result=FT
+       bne     t2, zero, result_ft_d           # if FS is a NAN, result=FS
+       bne     t3, zero, result_ft_d
+       bne     t6, zero, result_ft_d           # if FT is a NAN, result=FT
+       bne     t7, zero, result_ft_d
+       b       invalid_d                       # zero * infinity is invalid
+1:
+       bne     t1, zero, 2f                    # is FS zero?
+       bne     t2, zero, 1f
+       beq     t3, zero, result_fs_d           # result is zero
+1:
+       jal     renorm_fs_d
+       b       3f
+2:
+       subu    t1, t1, DEXP_BIAS               # unbias FS exponent
+       or      t2, t2, DIMPL_ONE               # set implied one bit
+3:
+       bne     t5, zero, 2f                    # is FT zero?
+       bne     t6, zero, 1f
+       beq     t7, zero, result_ft_d           # result is zero
+1:
+       jal     renorm_ft_d
+       b       3f
+2:
+       subu    t5, t5, DEXP_BIAS               # unbias FT exponent
+       or      t6, t6, DIMPL_ONE               # set implied one bit
+3:
+       addu    t1, t1, t5                      # compute result exponent
+       addu    t1, t1, 12                      # ???
+       multu   t3, t7                          # multiply fractions (low * low)
+       move    t4, t2                          # free up t2,t3 for result
+       move    t5, t3
+       mflo    a3                              # save low order bits
+       mfhi    t8
+       not     v0, t8
+       multu   t4, t7                          # multiply FS(high) * FT(low)
+       mflo    v1
+       mfhi    t3                              # init low result
+       sltu    v0, v0, v1                      # compute carry
+       addu    t8, v1
+       multu   t5, t6                          # multiply FS(low) * FT(high)
+       addu    t3, t3, v0                      # add carry
+       not     v0, t8
+       mflo    v1
+       mfhi    t2
+       sltu    v0, v0, v1
+       addu    t8, v1
+       multu   t4, t6                          # multiply FS(high) * FT(high)
+       addu    t3, v0
+       not     v1, t3
+       sltu    v1, v1, t2
+       addu    t3, t2
+       not     v0, t3
+       mfhi    t2
+       addu    t2, v1
+       mflo    v1
+       sltu    v0, v0, v1
+       addu    t2, v0
+       addu    t3, v1
+       sltu    a3, zero, a3                    # reduce t8,a3 to just t8
+       or      t8, a3
+       b       norm_d
+
+/*
+ * Single precision divide.
+ */
+div_s:
+       jal     get_ft_fs_s
+       xor     t0, t0, t4                      # compute sign of result
+       move    t4, t0
+       bne     t1, SEXP_INF, 1f                # is FS an infinity?
+       bne     t2, zero, result_fs_s           # if FS is NAN, result is FS
+       bne     t5, SEXP_INF, result_fs_s       # is FT an infinity?
+       bne     t6, zero, result_ft_s           # if FT is NAN, result is FT
+       b       invalid_s                       # infinity/infinity is invalid
+1:
+       bne     t5, SEXP_INF, 1f                # is FT an infinity?
+       bne     t6, zero, result_ft_s           # if FT is NAN, result is FT
+       move    t1, zero                        # x / infinity is zero
+       move    t2, zero
+       b       result_fs_s
+1:
+       bne     t1, zero, 2f                    # is FS zero?
+       bne     t2, zero, 1f
+       bne     t5, zero, result_fs_s           # FS=zero, is FT zero?
+       beq     t6, zero, invalid_s             # 0 / 0
+       b       result_fs_s                     # result = zero
+1:
+       jal     renorm_fs_s
+       b       3f
+2:
+       subu    t1, t1, SEXP_BIAS               # unbias FS exponent
+       or      t2, t2, SIMPL_ONE               # set implied one bit
+3:
+       bne     t5, zero, 2f                    # is FT zero?
+       bne     t6, zero, 1f
+       or      a1, a1, FPC_EXCEPTION_DIV0 | FPC_STICKY_DIV0
+       and     v0, a1, FPC_ENABLE_DIV0 # trap enabled?
+       bne     v0, zero, fpe_trap
+       ctc1    a1, FPC_CSR             # save exceptions
+       li      t1, SEXP_INF                    # result is infinity
+       move    t2, zero
+       b       result_fs_s
+1:
+       jal     renorm_ft_s
+       b       3f
+2:
+       subu    t5, t5, SEXP_BIAS               # unbias FT exponent
+       or      t6, t6, SIMPL_ONE               # set implied one bit
+3:
+       subu    t1, t1, t5                      # compute exponent
+       subu    t1, t1, 3                       # compensate for result position
+       li      v0, SFRAC_BITS+3                # number of bits to divide
+       move    t8, t2                          # init dividend
+       move    t2, zero                        # init result
+1:
+       bltu    t8, t6, 3f                      # is dividend >= divisor?
+2:
+       subu    t8, t8, t6                      # subtract divisor from dividend
+       or      t2, t2, 1                       # remember that we did
+       bne     t8, zero, 3f                    # if not done, continue
+       sll     t2, t2, v0                      # shift result to final position
+       b       norm_s
+3:
+       sll     t8, t8, 1                       # shift dividend
+       sll     t2, t2, 1                       # shift result
+       subu    v0, v0, 1                       # are we done?
+       bne     v0, zero, 1b                    # no, continue
+       b       norm_s
+
+/*
+ * Double precision divide.
+ */
+div_d:
+       jal     get_ft_fs_d
+       xor     t0, t0, t4                      # compute sign of result
+       move    t4, t0
+       bne     t1, DEXP_INF, 1f                # is FS an infinity?
+       bne     t2, zero, result_fs_d           # if FS is NAN, result is FS
+       bne     t3, zero, result_fs_d
+       bne     t5, DEXP_INF, result_fs_d       # is FT an infinity?
+       bne     t6, zero, result_ft_d           # if FT is NAN, result is FT
+       bne     t7, zero, result_ft_d
+       b       invalid_d                       # infinity/infinity is invalid
+1:
+       bne     t5, DEXP_INF, 1f                # is FT an infinity?
+       bne     t6, zero, result_ft_d           # if FT is NAN, result is FT
+       bne     t7, zero, result_ft_d
+       move    t1, zero                        # x / infinity is zero
+       move    t2, zero
+       move    t3, zero
+       b       result_fs_d
+1:
+       bne     t1, zero, 2f                    # is FS zero?
+       bne     t2, zero, 1f
+       bne     t3, zero, 1f
+       bne     t5, zero, result_fs_d           # FS=zero, is FT zero?
+       bne     t6, zero, result_fs_d
+       beq     t7, zero, invalid_d             # 0 / 0
+       b       result_fs_d                     # result = zero
+1:
+       jal     renorm_fs_d
+       b       3f
+2:
+       subu    t1, t1, DEXP_BIAS               # unbias FS exponent
+       or      t2, t2, DIMPL_ONE               # set implied one bit
+3:
+       bne     t5, zero, 2f                    # is FT zero?
+       bne     t6, zero, 1f
+       bne     t7, zero, 1f
+       or      a1, a1, FPC_EXCEPTION_DIV0 | FPC_STICKY_DIV0
+       and     v0, a1, FPC_ENABLE_DIV0 # trap enabled?
+       bne     v0, zero, fpe_trap
+       ctc1    a1, FPC_CSR             # Save exceptions
+       li      t1, DEXP_INF                    # result is infinity
+       move    t2, zero
+       move    t3, zero
+       b       result_fs_d
+1:
+       jal     renorm_ft_d
+       b       3f
+2:
+       subu    t5, t5, DEXP_BIAS               # unbias FT exponent
+       or      t6, t6, DIMPL_ONE               # set implied one bit
+3:
+       subu    t1, t1, t5                      # compute exponent
+       subu    t1, t1, 3                       # compensate for result position
+       li      v0, DFRAC_BITS+3                # number of bits to divide
+       move    t8, t2                          # init dividend
+       move    t9, t3
+       move    t2, zero                        # init result
+       move    t3, zero
+1:
+       bltu    t8, t6, 3f                      # is dividend >= divisor?
+       bne     t8, t6, 2f
+       bltu    t9, t7, 3f
+2:
+       sltu    v1, t9, t7                      # subtract divisor from dividend
+       subu    t9, t9, t7
+       subu    t8, t8, t6
+       subu    t8, t8, v1
+       or      t3, t3, 1                       # remember that we did
+       bne     t8, zero, 3f                    # if not done, continue
+       bne     t9, zero, 3f
+       li      v1, 32                          # shift result to final position
+       blt     v0, v1, 2f                      # shift < 32 bits?
+       subu    v0, v0, v1                      # shift by > 32 bits
+       sll     t2, t3, v0                      # shift upper part
+       move    t3, zero
+       b       norm_d
+2:
+       subu    v1, v1, v0                      # shift by < 32 bits
+       sll     t2, t2, v0                      # shift upper part
+       srl     t9, t3, v1                      # save bits shifted out
+       or      t2, t2, t9                      # and put into upper part
+       sll     t3, t3, v0
+       b       norm_d
+3:
+       sll     t8, t8, 1                       # shift dividend
+       srl     v1, t9, 31                      # save bit shifted out
+       or      t8, t8, v1                      # and put into upper part
+       sll     t9, t9, 1
+       sll     t2, t2, 1                       # shift result
+       srl     v1, t3, 31                      # save bit shifted out
+       or      t2, t2, v1                      # and put into upper part
+       sll     t3, t3, 1
+       subu    v0, v0, 1                       # are we done?
+       bne     v0, zero, 1b                    # no, continue
+       sltu    v0, zero, t9                    # be sure to save any one bits
+       or      t8, t8, v0                      # from the lower remainder
+       b       norm_d
+
+/*
+ * Single precision absolute value.
+ */
+abs_s:
+       jal     get_fs_s
+       move    t0, zero                        # set sign positive
+       b       result_fs_s
+
+/*
+ * Double precision absolute value.
+ */
+abs_d:
+       jal     get_fs_d
+       move    t0, zero                        # set sign positive
+       b       result_fs_d
+
+/*
+ * Single precision move.
+ */
+mov_s:
+       jal     get_fs_s
+       b       result_fs_s
+
+/*
+ * Double precision move.
+ */
+mov_d:
+       jal     get_fs_d
+       b       result_fs_d
+
+/*
+ * Single precision negate.
+ */
+neg_s:
+       jal     get_fs_s
+       xor     t0, t0, 1                       # reverse sign
+       b       result_fs_s
+
+/*
+ * Double precision negate.
+ */
+neg_d:
+       jal     get_fs_d
+       xor     t0, t0, 1                       # reverse sign
+       b       result_fs_d
+
+/*
+ * Convert double to single.
+ */
+cvt_s_d:
+       jal     get_fs_d
+       bne     t1, DEXP_INF, 1f                # is FS an infinity?
+       li      t1, SEXP_INF                    # convert to single
+       sll     t2, t2, 3                       # convert D fraction to S
+       srl     t8, t3, 32 - 3
+       or      t2, t2, t8
+       b       result_fs_s
+1:
+       bne     t1, zero, 2f                    # is FS zero?
+       bne     t2, zero, 1f
+       beq     t3, zero, result_fs_s           # result=0
+1:
+       jal     renorm_fs_d
+       subu    t1, t1, 3                       # correct exp for shift below
+       b       3f
+2:
+       subu    t1, t1, DEXP_BIAS               # unbias exponent
+       or      t2, t2, DIMPL_ONE               # add implied one bit
+3:
+       sll     t2, t2, 3                       # convert D fraction to S
+       srl     t8, t3, 32 - 3
+       or      t2, t2, t8
+       sll     t8, t3, 3
+       b       norm_noshift_s
+
+/*
+ * Convert integer to single.
+ */
+cvt_s_w:
+       jal     get_fs_int
+       bne     t2, zero, 1f                    # check for zero
+       move    t1, zero
+       b       result_fs_s
+/*
+ * Find out how many leading zero bits are in t2 and put in t9.
+ */
+1:
+       move    v0, t2
+       move    t9, zero
+       srl     v1, v0, 16
+       bne     v1, zero, 1f
+       addu    t9, 16
+       sll     v0, 16
+1:
+       srl     v1, v0, 24
+       bne     v1, zero, 1f
+       addu    t9, 8
+       sll     v0, 8
+1:
+       srl     v1, v0, 28
+       bne     v1, zero, 1f
+       addu    t9, 4
+       sll     v0, 4
+1:
+       srl     v1, v0, 30
+       bne     v1, zero, 1f
+       addu    t9, 2
+       sll     v0, 2
+1:
+       srl     v1, v0, 31
+       bne     v1, zero, 1f
+       addu    t9, 1
+/*
+ * Now shift t2 the correct number of bits.
+ */
+1:
+       subu    t9, t9, SLEAD_ZEROS             # dont count leading zeros
+       li      t1, 23                          # init exponent
+       subu    t1, t1, t9                      # compute exponent
+       beq     t9, zero, 1f
+       li      v0, 32
+       blt     t9, zero, 2f                    # if shift < 0, shift right
+       subu    v0, v0, t9
+       sll     t2, t2, t9                      # shift left
+1:
+       add     t1, t1, SEXP_BIAS               # bias exponent
+       and     t2, t2, ~SIMPL_ONE              # clear implied one bit
+       b       result_fs_s
+2:
+       negu    t9                              # shift right by t9
+       subu    v0, v0, t9
+       sll     t8, t2, v0                      # save bits shifted out
+       srl     t2, t2, t9
+       b       norm_noshift_s
+
+/*
+ * Convert single to double.
+ */
+cvt_d_s:
+       jal     get_fs_s
+       move    t3, zero
+       bne     t1, SEXP_INF, 1f                # is FS an infinity?
+       li      t1, DEXP_INF                    # convert to double
+       b       result_fs_d
+1:
+       bne     t1, zero, 2f                    # is FS denormalized or zero?
+       beq     t2, zero, result_fs_d           # is FS zero?
+       jal     renorm_fs_s
+       move    t8, zero
+       b       norm_d
+2:
+       addu    t1, t1, DEXP_BIAS - SEXP_BIAS   # bias exponent correctly
+       sll     t3, t2, 32 - 3                  # convert S fraction to D
+       srl     t2, t2, 3
+       b       result_fs_d
+
+/*
+ * Convert integer to double.
+ */
+cvt_d_w:
+       jal     get_fs_int
+       bne     t2, zero, 1f                    # check for zero
+       move    t1, zero                        # result=0
+       move    t3, zero
+       b       result_fs_d
+/*
+ * Find out how many leading zero bits are in t2 and put in t9.
+ */
+1:
+       move    v0, t2
+       move    t9, zero
+       srl     v1, v0, 16
+       bne     v1, zero, 1f
+       addu    t9, 16
+       sll     v0, 16
+1:
+       srl     v1, v0, 24
+       bne     v1, zero, 1f
+       addu    t9, 8
+       sll     v0, 8
+1:
+       srl     v1, v0, 28
+       bne     v1, zero, 1f
+       addu    t9, 4
+       sll     v0, 4
+1:
+       srl     v1, v0, 30
+       bne     v1, zero, 1f
+       addu    t9, 2
+       sll     v0, 2
+1:
+       srl     v1, v0, 31
+       bne     v1, zero, 1f
+       addu    t9, 1
+/*
+ * Now shift t2 the correct number of bits.
+ */
+1:
+       subu    t9, t9, DLEAD_ZEROS             # dont count leading zeros
+       li      t1, DEXP_BIAS + 20              # init exponent
+       subu    t1, t1, t9                      # compute exponent
+       beq     t9, zero, 1f
+       li      v0, 32
+       blt     t9, zero, 2f                    # if shift < 0, shift right
+       subu    v0, v0, t9
+       sll     t2, t2, t9                      # shift left
+1:
+       and     t2, t2, ~DIMPL_ONE              # clear implied one bit
+       move    t3, zero
+       b       result_fs_d
+2:
+       negu    t9                              # shift right by t9
+       subu    v0, v0, t9
+       sll     t3, t2, v0
+       srl     t2, t2, t9
+       and     t2, t2, ~DIMPL_ONE              # clear implied one bit
+       b       result_fs_d
+
+/*
+ * Convert single to integer.
+ */
+cvt_w_s:
+       jal     get_fs_s
+       bne     t1, SEXP_INF, 1f                # is FS an infinity?
+       bne     t2, zero, invalid_w             # invalid conversion
+1:
+       bne     t1, zero, 1f                    # is FS zero?
+       beq     t2, zero, result_fs_w           # result is zero
+       move    t2, zero                        # result is an inexact zero
+       b       inexact_w
+1:
+       subu    t1, t1, SEXP_BIAS               # unbias exponent
+       or      t2, t2, SIMPL_ONE               # add implied one bit
+       sll     t3, t2, 32 - 3                  # convert S fraction to D
+       srl     t2, t2, 3
+       b       cvt_w
+
+/*
+ * Convert double to integer.
+ */
+cvt_w_d:
+       jal     get_fs_d
+       bne     t1, DEXP_INF, 1f                # is FS an infinity?
+       bne     t2, zero, invalid_w             # invalid conversion
+       bne     t3, zero, invalid_w             # invalid conversion
+1:
+       bne     t1, zero, 2f                    # is FS zero?
+       bne     t2, zero, 1f
+       beq     t3, zero, result_fs_w           # result is zero
+1:
+       move    t2, zero                        # result is an inexact zero
+       b       inexact_w
+2:
+       subu    t1, t1, DEXP_BIAS               # unbias exponent
+       or      t2, t2, DIMPL_ONE               # add implied one bit
+cvt_w:
+       blt     t1, WEXP_MIN, underflow_w       # is exponent too small?
+       li      v0, WEXP_MAX+1
+       bgt     t1, v0, overflow_w              # is exponent too large?
+       bne     t1, v0, 1f                      # special check for INT_MIN
+       beq     t0, zero, overflow_w            # if positive, overflow
+       bne     t2, DIMPL_ONE, overflow_w
+       bne     t3, zero, overflow_w
+       li      t2, INT_MIN                     # result is INT_MIN
+       b       result_fs_w
+1:
+       subu    v0, t1, 20                      # compute amount to shift
+       beq     v0, zero, 2f                    # is shift needed?
+       li      v1, 32
+       blt     v0, zero, 1f                    # if shift < 0, shift right
+       subu    v1, v1, v0                      # shift left
+       sll     t2, t2, v0
+       srl     t9, t3, v1                      # save bits shifted out of t3
+       or      t2, t2, t9                      # and put into t2
+       sll     t3, t3, v0                      # shift FSs fraction
+       b       2f
+1:
+       negu    v0                              # shift right by v0
+       subu    v1, v1, v0
+       sll     t8, t3, v1                      # save bits shifted out
+       sltu    t8, zero, t8                    # dont lose any ones
+       srl     t3, t3, v0                      # shift FSs fraction
+       or      t3, t3, t8
+       sll     t9, t2, v1                      # save bits shifted out of t2
+       or      t3, t3, t9                      # and put into t3
+       srl     t2, t2, v0
+/*
+ * round result (t0 is sign, t2 is integer part, t3 is fractional part).
+ */
+2:
+       and     v0, a1, FPC_ROUNDING_BITS       # get rounding mode
+       beq     v0, FPC_ROUND_RN, 3f    # round to nearest
+       beq     v0, FPC_ROUND_RZ, 5f    # round to zero (truncate)
+       beq     v0, FPC_ROUND_RP, 1f    # round to +infinity
+       beq     t0, zero, 5f                    # if sign is positive, truncate
+       b       2f
+1:
+       bne     t0, zero, 5f                    # if sign is negative, truncate
+2:
+       beq     t3, zero, 5f                    # if no fraction bits, continue
+       addu    t2, t2, 1                       # add rounding bit
+       blt     t2, zero, overflow_w            # overflow?
+       b       5f
+3:
+       li      v0, GUARDBIT                    # load guard bit for rounding
+       addu    v0, v0, t3                      # add remainder
+       sltu    v1, v0, t3                      # compute carry out
+       beq     v1, zero, 4f                    # if no carry, continue
+       addu    t2, t2, 1                       # add carry to result
+       blt     t2, zero, overflow_w            # overflow?
+4:
+       bne     v0, zero, 5f                    # if rounded remainder is zero
+       and     t2, t2, ~1                      #  clear LSB (round to nearest)
+5:
+       beq     t0, zero, 1f                    # result positive?
+       negu    t2                              # convert to negative integer
+1:
+       beq     t3, zero, result_fs_w           # is result exact?
+/*
+ * Handle inexact exception.
+ */
+inexact_w:
+       or      a1, a1, FPC_EXCEPTION_INEXACT | FPC_STICKY_INEXACT
+       and     v0, a1, FPC_ENABLE_INEXACT
+       bne     v0, zero, fpe_trap
+       ctc1    a1, FPC_CSR             # save exceptions
+       b       result_fs_w
+
+/*
+ * Conversions to integer which overflow will trap (if enabled),
+ * or generate an inexact trap (if enabled),
+ * or generate an invalid exception.
+ */
+overflow_w:
+       or      a1, a1, FPC_EXCEPTION_OVERFLOW | FPC_STICKY_OVERFLOW
+       and     v0, a1, FPC_ENABLE_OVERFLOW
+       bne     v0, zero, fpe_trap
+       and     v0, a1, FPC_ENABLE_INEXACT
+       bne     v0, zero, inexact_w             # inexact traps enabled?
+       b       invalid_w
+
+/*
+ * Conversions to integer which underflow will trap (if enabled),
+ * or generate an inexact trap (if enabled),
+ * or generate an invalid exception.
+ */
+underflow_w:
+       or      a1, a1, FPC_EXCEPTION_UNDERFLOW | FPC_STICKY_UNDERFLOW
+       and     v0, a1, FPC_ENABLE_UNDERFLOW
+       bne     v0, zero, fpe_trap
+       and     v0, a1, FPC_ENABLE_INEXACT
+       bne     v0, zero, inexact_w             # inexact traps enabled?
+       b       invalid_w
+
+/*
+ * Compare single.
+ */
+cmp_s:
+       jal     get_cmp_s
+       bne     t1, SEXP_INF, 1f                # is FS an infinity?
+       bne     t2, zero, unordered             # FS is a NAN
+1:
+       bne     t5, SEXP_INF, 2f                # is FT an infinity?
+       bne     t6, zero, unordered             # FT is a NAN
+2:
+       sll     t1, t1, 23                      # reassemble exp & frac
+       or      t1, t1, t2
+       sll     t5, t5, 23                      # reassemble exp & frac
+       or      t5, t5, t6
+       beq     t0, zero, 1f                    # is FS positive?
+       negu    t1
+1:
+       beq     t4, zero, 1f                    # is FT positive?
+       negu    t5
+1:
+       li      v0, COND_LESS
+       blt     t1, t5, test_cond               # is FS < FT?
+       li      v0, COND_EQUAL
+       beq     t1, t5, test_cond               # is FS == FT?
+       move    v0, zero                        # FS > FT
+       b       test_cond
+
+/*
+ * Compare double.
+ */
+cmp_d:
+       jal     get_cmp_d
+       bne     t1, DEXP_INF, 1f                # is FS an infinity?
+       bne     t2, zero, unordered
+       bne     t3, zero, unordered             # FS is a NAN
+1:
+       bne     t5, DEXP_INF, 2f                # is FT an infinity?
+       bne     t6, zero, unordered
+       bne     t7, zero, unordered             # FT is a NAN
+2:
+       sll     t1, t1, 20                      # reassemble exp & frac
+       or      t1, t1, t2
+       sll     t5, t5, 20                      # reassemble exp & frac
+       or      t5, t5, t6
+       beq     t0, zero, 1f                    # is FS positive?
+       not     t3                              # negate t1,t3
+       not     t1
+       addu    t3, t3, 1
+       seq     v0, t3, zero                    # compute carry
+       addu    t1, t1, v0
+1:
+       beq     t4, zero, 1f                    # is FT positive?
+       not     t7                              # negate t5,t7
+       not     t5
+       addu    t7, t7, 1
+       seq     v0, t7, zero                    # compute carry
+       addu    t5, t5, v0
+1:
+       li      v0, COND_LESS
+       blt     t1, t5, test_cond               # is FS(MSW) < FT(MSW)?
+       move    v0, zero
+       bne     t1, t5, test_cond               # is FS(MSW) > FT(MSW)?
+       li      v0, COND_LESS
+       bltu    t3, t7, test_cond               # is FS(LSW) < FT(LSW)?
+       li      v0, COND_EQUAL
+       beq     t3, t7, test_cond               # is FS(LSW) == FT(LSW)?
+       move    v0, zero                        # FS > FT
+test_cond:
+       and     v0, v0, a0                      # condition match instruction?
+set_cond:
+       bne     v0, zero, 1f
+       and     a1, a1, ~FPC_COND_BIT   # clear condition bit
+       b       2f
+1:
+       or      a1, a1, FPC_COND_BIT    # set condition bit
+2:
+       ctc1    a1, FPC_CSR             # save condition bit
+       b       done
+
+unordered:
+       and     v0, a0, COND_UNORDERED          # this cmp match unordered?
+       bne     v0, zero, 1f
+       and     a1, a1, ~FPC_COND_BIT   # clear condition bit
+       b       2f
+1:
+       or      a1, a1, FPC_COND_BIT    # set condition bit
+2:
+       and     v0, a0, COND_SIGNAL
+       beq     v0, zero, 1f                    # is this a signaling cmp?
+       or      a1, a1, FPC_EXCEPTION_INVALID | FPC_STICKY_INVALID
+       and     v0, a1, FPC_ENABLE_INVALID
+       bne     v0, zero, fpe_trap
+1:
+       ctc1    a1, FPC_CSR             # save condition bit
+       b       done
+
+/*
+ * Determine the amount to shift the fraction in order to restore the
+ * normalized position. After that, round and handle exceptions.
+ */
+norm_s:
+       move    v0, t2
+       move    t9, zero                        # t9 = num of leading zeros
+       bne     t2, zero, 1f
+       move    v0, t8
+       addu    t9, 32
+1:
+       srl     v1, v0, 16
+       bne     v1, zero, 1f
+       addu    t9, 16
+       sll     v0, 16
+1:
+       srl     v1, v0, 24
+       bne     v1, zero, 1f
+       addu    t9, 8
+       sll     v0, 8
+1:
+       srl     v1, v0, 28
+       bne     v1, zero, 1f
+       addu    t9, 4
+       sll     v0, 4
+1:
+       srl     v1, v0, 30
+       bne     v1, zero, 1f
+       addu    t9, 2
+       sll     v0, 2
+1:
+       srl     v1, v0, 31
+       bne     v1, zero, 1f
+       addu    t9, 1
+/*
+ * Now shift t2,t8 the correct number of bits.
+ */
+1:
+       subu    t9, t9, SLEAD_ZEROS             # dont count leading zeros
+       subu    t1, t1, t9                      # adjust the exponent
+       beq     t9, zero, norm_noshift_s
+       li      v1, 32
+       blt     t9, zero, 1f                    # if shift < 0, shift right
+       subu    v1, v1, t9
+       sll     t2, t2, t9                      # shift t2,t8 left
+       srl     v0, t8, v1                      # save bits shifted out
+       or      t2, t2, v0
+       sll     t8, t8, t9
+       b       norm_noshift_s
+1:
+       negu    t9                              # shift t2,t8 right by t9
+       subu    v1, v1, t9
+       sll     v0, t8, v1                      # save bits shifted out
+       sltu    v0, zero, v0                    # be sure to save any one bits
+       srl     t8, t8, t9
+       or      t8, t8, v0
+       sll     v0, t2, v1                      # save bits shifted out
+       or      t8, t8, v0
+       srl     t2, t2, t9
+norm_noshift_s:
+       move    t5, t1                          # save unrounded exponent
+       move    t6, t2                          # save unrounded fraction
+       and     v0, a1, FPC_ROUNDING_BITS       # get rounding mode
+       beq     v0, FPC_ROUND_RN, 3f    # round to nearest
+       beq     v0, FPC_ROUND_RZ, 5f    # round to zero (truncate)
+       beq     v0, FPC_ROUND_RP, 1f    # round to +infinity
+       beq     t0, zero, 5f                    # if sign is positive, truncate
+       b       2f
+1:
+       bne     t0, zero, 5f                    # if sign is negative, truncate
+2:
+       beq     t8, zero, 5f                    # if exact, continue
+       addu    t2, t2, 1                       # add rounding bit
+       bne     t2, SIMPL_ONE<<1, 5f            # need to adjust exponent?
+       addu    t1, t1, 1                       # adjust exponent
+       srl     t2, t2, 1                       # renormalize fraction
+       b       5f
+3:
+       li      v0, GUARDBIT                    # load guard bit for rounding
+       addu    v0, v0, t8                      # add remainder
+       sltu    v1, v0, t8                      # compute carry out
+       beq     v1, zero, 4f                    # if no carry, continue
+       addu    t2, t2, 1                       # add carry to result
+       bne     t2, SIMPL_ONE<<1, 4f            # need to adjust exponent?
+       addu    t1, t1, 1                       # adjust exponent
+       srl     t2, t2, 1                       # renormalize fraction
+4:
+       bne     v0, zero, 5f                    # if rounded remainder is zero
+       and     t2, t2, ~1                      #  clear LSB (round to nearest)
+5:
+       bgt     t1, SEXP_MAX, overflow_s        # overflow?
+       blt     t1, SEXP_MIN, underflow_s       # underflow?
+       bne     t8, zero, inexact_s             # is result inexact?
+       addu    t1, t1, SEXP_BIAS               # bias exponent
+       and     t2, t2, ~SIMPL_ONE              # clear implied one bit
+       b       result_fs_s
+
+/*
+ * Handle inexact exception.
+ */
+inexact_s:
+       addu    t1, t1, SEXP_BIAS               # bias exponent
+       and     t2, t2, ~SIMPL_ONE              # clear implied one bit
+inexact_nobias_s:
+       jal     set_fd_s                        # save result
+       or      a1, a1, FPC_EXCEPTION_INEXACT | FPC_STICKY_INEXACT
+       and     v0, a1, FPC_ENABLE_INEXACT
+       bne     v0, zero, fpe_trap
+       ctc1    a1, FPC_CSR             # save exceptions
+       b       done
+
+/*
+ * Overflow will trap (if enabled),
+ * or generate an inexact trap (if enabled),
+ * or generate an infinity.
+ */
+overflow_s:
+       or      a1, a1, FPC_EXCEPTION_OVERFLOW | FPC_STICKY_OVERFLOW
+       and     v0, a1, FPC_ENABLE_OVERFLOW
+       beq     v0, zero, 1f
+       subu    t1, t1, 192                     # bias exponent
+       and     t2, t2, ~SIMPL_ONE              # clear implied one bit
+       jal     set_fd_s                        # save result
+       b       fpe_trap
+1:
+       and     v0, a1, FPC_ROUNDING_BITS       # get rounding mode
+       beq     v0, FPC_ROUND_RN, 3f    # round to nearest
+       beq     v0, FPC_ROUND_RZ, 1f    # round to zero (truncate)
+       beq     v0, FPC_ROUND_RP, 2f    # round to +infinity
+       bne     t0, zero, 3f
+1:
+       li      t1, SEXP_MAX                    # result is max finite
+       li      t2, 0x007fffff
+       b       inexact_s
+2:
+       bne     t0, zero, 1b
+3:
+       li      t1, SEXP_MAX + 1                # result is infinity
+       move    t2, zero
+       b       inexact_s
+
+/*
+ * In this implementation, "tininess" is detected "after rounding" and
+ * "loss of accuracy" is detected as "an inexact result".
+ */
+underflow_s:
+       and     v0, a1, FPC_ENABLE_UNDERFLOW
+       beq     v0, zero, 1f
+/*
+ * Underflow is enabled so compute the result and trap.
+ */
+       addu    t1, t1, 192                     # bias exponent
+       and     t2, t2, ~SIMPL_ONE              # clear implied one bit
+       jal     set_fd_s                        # save result
+       or      a1, a1, FPC_EXCEPTION_UNDERFLOW | FPC_STICKY_UNDERFLOW
+       b       fpe_trap
+/*
+ * Underflow is not enabled so compute the result,
+ * signal inexact result (if it is) and trap (if enabled).
+ */
+1:
+       move    t1, t5                          # get unrounded exponent
+       move    t2, t6                          # get unrounded fraction
+       li      t9, SEXP_MIN                    # compute shift amount
+       subu    t9, t9, t1                      # shift t2,t8 right by t9
+       blt     t9, SFRAC_BITS+2, 3f            # shift all the bits out?
+       move    t1, zero                        # result is inexact zero
+       move    t2, zero
+       or      a1, a1, FPC_EXCEPTION_UNDERFLOW | FPC_STICKY_UNDERFLOW
+/*
+ * Now round the zero result.
+ * Only need to worry about rounding to +- infinity when the sign matches.
+ */
+       and     v0, a1, FPC_ROUNDING_BITS       # get rounding mode
+       beq     v0, FPC_ROUND_RN, inexact_nobias_s      # round to nearest
+       beq     v0, FPC_ROUND_RZ, inexact_nobias_s      # round to zero
+       beq     v0, FPC_ROUND_RP, 1f    # round to +infinity
+       beq     t0, zero, inexact_nobias_s      # if sign is positive, truncate
+       b       2f
+1:
+       bne     t0, zero, inexact_nobias_s      # if sign is negative, truncate
+2:
+       addu    t2, t2, 1                       # add rounding bit
+       b       inexact_nobias_s
+3:
+       li      v1, 32
+       subu    v1, v1, t9
+       sltu    v0, zero, t8                    # be sure to save any one bits
+       sll     t8, t2, v1                      # save bits shifted out
+       or      t8, t8, v0                      # include sticky bits
+       srl     t2, t2, t9
+/*
+ * Now round the denormalized result.
+ */
+       and     v0, a1, FPC_ROUNDING_BITS       # get rounding mode
+       beq     v0, FPC_ROUND_RN, 3f    # round to nearest
+       beq     v0, FPC_ROUND_RZ, 5f    # round to zero (truncate)
+       beq     v0, FPC_ROUND_RP, 1f    # round to +infinity
+       beq     t0, zero, 5f                    # if sign is positive, truncate
+       b       2f
+1:
+       bne     t0, zero, 5f                    # if sign is negative, truncate
+2:
+       beq     t8, zero, 5f                    # if exact, continue
+       addu    t2, t2, 1                       # add rounding bit
+       b       5f
+3:
+       li      v0, GUARDBIT                    # load guard bit for rounding
+       addu    v0, v0, t8                      # add remainder
+       sltu    v1, v0, t8                      # compute carry out
+       beq     v1, zero, 4f                    # if no carry, continue
+       addu    t2, t2, 1                       # add carry to result
+4:
+       bne     v0, zero, 5f                    # if rounded remainder is zero
+       and     t2, t2, ~1                      #  clear LSB (round to nearest)
+5:
+       move    t1, zero                        # denorm or zero exponent
+       jal     set_fd_s                        # save result
+       beq     t8, zero, done                  # check for exact result
+       or      a1, a1, FPC_EXCEPTION_UNDERFLOW | FPC_STICKY_UNDERFLOW
+       or      a1, a1, FPC_EXCEPTION_INEXACT | FPC_STICKY_INEXACT
+       and     v0, a1, FPC_ENABLE_INEXACT
+       bne     v0, zero, fpe_trap
+       ctc1    a1, FPC_CSR             # save exceptions
+       b       done
+
+/*
+ * Determine the amount to shift the fraction in order to restore the
+ * normalized position. After that, round and handle exceptions.
+ */
+norm_d:
+       move    v0, t2
+       move    t9, zero                        # t9 = num of leading zeros
+       bne     t2, zero, 1f
+       move    v0, t3
+       addu    t9, 32
+       bne     t3, zero, 1f
+       move    v0, t8
+       addu    t9, 32
+1:
+       srl     v1, v0, 16
+       bne     v1, zero, 1f
+       addu    t9, 16
+       sll     v0, 16
+1:
+       srl     v1, v0, 24
+       bne     v1, zero, 1f
+       addu    t9, 8
+       sll     v0, 8
+1:
+       srl     v1, v0, 28
+       bne     v1, zero, 1f
+       addu    t9, 4
+       sll     v0, 4
+1:
+       srl     v1, v0, 30
+       bne     v1, zero, 1f
+       addu    t9, 2
+       sll     v0, 2
+1:
+       srl     v1, v0, 31
+       bne     v1, zero, 1f
+       addu    t9, 1
+/*
+ * Now shift t2,t3,t8 the correct number of bits.
+ */
+1:
+       subu    t9, t9, DLEAD_ZEROS             # dont count leading zeros
+       subu    t1, t1, t9                      # adjust the exponent
+       beq     t9, zero, norm_noshift_d
+       li      v1, 32
+       blt     t9, zero, 2f                    # if shift < 0, shift right
+       blt     t9, v1, 1f                      # shift by < 32?
+       subu    t9, t9, v1                      # shift by >= 32
+       subu    v1, v1, t9
+       sll     t2, t3, t9                      # shift left by t9
+       srl     v0, t8, v1                      # save bits shifted out
+       or      t2, t2, v0
+       sll     t3, t8, t9
+       move    t8, zero
+       b       norm_noshift_d
+1:
+       subu    v1, v1, t9
+       sll     t2, t2, t9                      # shift left by t9
+       srl     v0, t3, v1                      # save bits shifted out
+       or      t2, t2, v0
+       sll     t3, t3, t9
+       srl     v0, t8, v1                      # save bits shifted out
+       or      t3, t3, v0
+       sll     t8, t8, t9
+       b       norm_noshift_d
+2:
+       negu    t9                              # shift right by t9
+       subu    v1, v1, t9                      #  (known to be < 32 bits)
+       sll     v0, t8, v1                      # save bits shifted out
+       sltu    v0, zero, v0                    # be sure to save any one bits
+       srl     t8, t8, t9
+       or      t8, t8, v0
+       sll     v0, t3, v1                      # save bits shifted out
+       or      t8, t8, v0
+       srl     t3, t3, t9
+       sll     v0, t2, v1                      # save bits shifted out
+       or      t3, t3, v0
+       srl     t2, t2, t9
+norm_noshift_d:
+       move    t5, t1                          # save unrounded exponent
+       move    t6, t2                          # save unrounded fraction (MS)
+       move    t7, t3                          # save unrounded fraction (LS)
+       and     v0, a1, FPC_ROUNDING_BITS       # get rounding mode
+       beq     v0, FPC_ROUND_RN, 3f    # round to nearest
+       beq     v0, FPC_ROUND_RZ, 5f    # round to zero (truncate)
+       beq     v0, FPC_ROUND_RP, 1f    # round to +infinity
+       beq     t0, zero, 5f                    # if sign is positive, truncate
+       b       2f
+1:
+       bne     t0, zero, 5f                    # if sign is negative, truncate
+2:
+       beq     t8, zero, 5f                    # if exact, continue
+       addu    t3, t3, 1                       # add rounding bit
+       bne     t3, zero, 5f                    # branch if no carry
+       addu    t2, t2, 1                       # add carry
+       bne     t2, DIMPL_ONE<<1, 5f            # need to adjust exponent?
+       addu    t1, t1, 1                       # adjust exponent
+       srl     t2, t2, 1                       # renormalize fraction
+       b       5f
+3:
+       li      v0, GUARDBIT                    # load guard bit for rounding
+       addu    v0, v0, t8                      # add remainder
+       sltu    v1, v0, t8                      # compute carry out
+       beq     v1, zero, 4f                    # branch if no carry
+       addu    t3, t3, 1                       # add carry
+       bne     t3, zero, 4f                    # branch if no carry
+       addu    t2, t2, 1                       # add carry to result
+       bne     t2, DIMPL_ONE<<1, 4f            # need to adjust exponent?
+       addu    t1, t1, 1                       # adjust exponent
+       srl     t2, t2, 1                       # renormalize fraction
+4:
+       bne     v0, zero, 5f                    # if rounded remainder is zero
+       and     t3, t3, ~1                      #  clear LSB (round to nearest)
+5:
+       bgt     t1, DEXP_MAX, overflow_d        # overflow?
+       blt     t1, DEXP_MIN, underflow_d       # underflow?
+       bne     t8, zero, inexact_d             # is result inexact?
+       addu    t1, t1, DEXP_BIAS               # bias exponent
+       and     t2, t2, ~DIMPL_ONE              # clear implied one bit
+       b       result_fs_d
+
+/*
+ * Handle inexact exception.
+ */
+inexact_d:
+       addu    t1, t1, DEXP_BIAS               # bias exponent
+       and     t2, t2, ~DIMPL_ONE              # clear implied one bit
+inexact_nobias_d:
+       jal     set_fd_d                        # save result
+       or      a1, a1, FPC_EXCEPTION_INEXACT | FPC_STICKY_INEXACT
+       and     v0, a1, FPC_ENABLE_INEXACT
+       bne     v0, zero, fpe_trap
+       ctc1    a1, FPC_CSR             # save exceptions
+       b       done
+
+/*
+ * Overflow will trap (if enabled),
+ * or generate an inexact trap (if enabled),
+ * or generate an infinity.
+ */
+overflow_d:
+       or      a1, a1, FPC_EXCEPTION_OVERFLOW | FPC_STICKY_OVERFLOW
+       and     v0, a1, FPC_ENABLE_OVERFLOW
+       beq     v0, zero, 1f
+       subu    t1, t1, 1536                    # bias exponent
+       and     t2, t2, ~DIMPL_ONE              # clear implied one bit
+       jal     set_fd_d                        # save result
+       b       fpe_trap
+1:
+       and     v0, a1, FPC_ROUNDING_BITS       # get rounding mode
+       beq     v0, FPC_ROUND_RN, 3f    # round to nearest
+       beq     v0, FPC_ROUND_RZ, 1f    # round to zero (truncate)
+       beq     v0, FPC_ROUND_RP, 2f    # round to +infinity
+       bne     t0, zero, 3f
+1:
+       li      t1, DEXP_MAX                    # result is max finite
+       li      t2, 0x000fffff
+       li      t3, 0xffffffff
+       b       inexact_d
+2:
+       bne     t0, zero, 1b
+3:
+       li      t1, DEXP_MAX + 1                # result is infinity
+       move    t2, zero
+       move    t3, zero
+       b       inexact_d
+
+/*
+ * In this implementation, "tininess" is detected "after rounding" and
+ * "loss of accuracy" is detected as "an inexact result".
+ */
+underflow_d:
+       and     v0, a1, FPC_ENABLE_UNDERFLOW
+       beq     v0, zero, 1f
+/*
+ * Underflow is enabled so compute the result and trap.
+ */
+       addu    t1, t1, 1536                    # bias exponent
+       and     t2, t2, ~DIMPL_ONE              # clear implied one bit
+       jal     set_fd_d                        # save result
+       or      a1, a1, FPC_EXCEPTION_UNDERFLOW | FPC_STICKY_UNDERFLOW
+       b       fpe_trap
+/*
+ * Underflow is not enabled so compute the result,
+ * signal inexact result (if it is) and trap (if enabled).
+ */
+1:
+       move    t1, t5                          # get unrounded exponent
+       move    t2, t6                          # get unrounded fraction (MS)
+       move    t3, t7                          # get unrounded fraction (LS)
+       li      t9, DEXP_MIN                    # compute shift amount
+       subu    t9, t9, t1                      # shift t2,t8 right by t9
+       blt     t9, DFRAC_BITS+2, 3f            # shift all the bits out?
+       move    t1, zero                        # result is inexact zero
+       move    t2, zero
+       move    t3, zero
+       or      a1, a1, FPC_EXCEPTION_UNDERFLOW | FPC_STICKY_UNDERFLOW
+/*
+ * Now round the zero result.
+ * Only need to worry about rounding to +- infinity when the sign matches.
+ */
+       and     v0, a1, FPC_ROUNDING_BITS       # get rounding mode
+       beq     v0, FPC_ROUND_RN, inexact_nobias_d      # round to nearest
+       beq     v0, FPC_ROUND_RZ, inexact_nobias_d      # round to zero
+       beq     v0, FPC_ROUND_RP, 1f    # round to +infinity
+       beq     t0, zero, inexact_nobias_d      # if sign is positive, truncate
+       b       2f
+1:
+       bne     t0, zero, inexact_nobias_d      # if sign is negative, truncate
+2:
+       addu    t3, t3, 1                       # add rounding bit
+       b       inexact_nobias_d
+3:
+       li      v1, 32
+       blt     t9, v1, 1f                      # shift by < 32?
+       subu    t9, t9, v1                      # shift right by >= 32
+       subu    v1, v1, t9
+       sltu    v0, zero, t8                    # be sure to save any one bits
+       sll     t8, t2, v1                      # save bits shifted out
+       or      t8, t8, v0                      # include sticky bits
+       srl     t3, t2, t9
+       move    t2, zero
+       b       2f
+1:
+       subu    v1, v1, t9                      # shift right by t9
+       sltu    v0, zero, t8                    # be sure to save any one bits
+       sll     t8, t3, v1                      # save bits shifted out
+       or      t8, t8, v0                      # include sticky bits
+       srl     t3, t3, t9
+       sll     v0, t2, v1                      # save bits shifted out
+       or      t3, t3, v0
+       srl     t2, t2, t9
+/*
+ * Now round the denormalized result.
+ */
+2:
+       and     v0, a1, FPC_ROUNDING_BITS       # get rounding mode
+       beq     v0, FPC_ROUND_RN, 3f    # round to nearest
+       beq     v0, FPC_ROUND_RZ, 5f    # round to zero (truncate)
+       beq     v0, FPC_ROUND_RP, 1f    # round to +infinity
+       beq     t0, zero, 5f                    # if sign is positive, truncate
+       b       2f
+1:
+       bne     t0, zero, 5f                    # if sign is negative, truncate
+2:
+       beq     t8, zero, 5f                    # if exact, continue
+       addu    t3, t3, 1                       # add rounding bit
+       bne     t3, zero, 5f                    # if no carry, continue
+       addu    t2, t2, 1                       # add carry
+       b       5f
+3:
+       li      v0, GUARDBIT                    # load guard bit for rounding
+       addu    v0, v0, t8                      # add remainder
+       sltu    v1, v0, t8                      # compute carry out
+       beq     v1, zero, 4f                    # if no carry, continue
+       addu    t3, t3, 1                       # add rounding bit
+       bne     t3, zero, 4f                    # if no carry, continue
+       addu    t2, t2, 1                       # add carry
+4:
+       bne     v0, zero, 5f                    # if rounded remainder is zero
+       and     t3, t3, ~1                      #  clear LSB (round to nearest)
+5:
+       move    t1, zero                        # denorm or zero exponent
+       jal     set_fd_d                        # save result
+       beq     t8, zero, done                  # check for exact result
+       or      a1, a1, FPC_EXCEPTION_UNDERFLOW | FPC_STICKY_UNDERFLOW
+       or      a1, a1, FPC_EXCEPTION_INEXACT | FPC_STICKY_INEXACT
+       and     v0, a1, FPC_ENABLE_INEXACT
+       bne     v0, zero, fpe_trap
+       ctc1    a1, FPC_CSR             # save exceptions
+       b       done
+
+/*
+ * Signal an invalid operation if the trap is enabled; otherwise,
+ * the result is a quiet NAN.
+ */
+invalid_s:                                     # trap invalid operation
+       or      a1, a1, FPC_EXCEPTION_INVALID | FPC_STICKY_INVALID
+       and     v0, a1, FPC_ENABLE_INVALID
+       bne     v0, zero, fpe_trap
+       ctc1    a1, FPC_CSR             # save exceptions
+       move    t0, zero                        # result is a quiet NAN
+       li      t1, SEXP_INF
+       li      t2, SQUIET_NAN
+       jal     set_fd_s                        # save result (in t0,t1,t2)
+       b       done
+
+/*
+ * Signal an invalid operation if the trap is enabled; otherwise,
+ * the result is a quiet NAN.
+ */
+invalid_d:                                     # trap invalid operation
+       or      a1, a1, FPC_EXCEPTION_INVALID | FPC_STICKY_INVALID
+       and     v0, a1, FPC_ENABLE_INVALID
+       bne     v0, zero, fpe_trap
+       ctc1    a1, FPC_CSR             # save exceptions
+       move    t0, zero                        # result is a quiet NAN
+       li      t1, DEXP_INF
+       li      t2, DQUIET_NAN0
+       li      t3, DQUIET_NAN1
+       jal     set_fd_d                        # save result (in t0,t1,t2,t3)
+       b       done
+
+/*
+ * Signal an invalid operation if the trap is enabled; otherwise,
+ * the result is INT_MAX or INT_MIN.
+ */
+invalid_w:                                     # trap invalid operation
+       or      a1, a1, FPC_EXCEPTION_INVALID | FPC_STICKY_INVALID
+       and     v0, a1, FPC_ENABLE_INVALID
+       bne     v0, zero, fpe_trap
+       ctc1    a1, FPC_CSR             # save exceptions
+       bne     t0, zero, 1f
+       li      t2, INT_MAX                     # result is INT_MAX
+       b       result_fs_w
+1:
+       li      t2, INT_MIN                     # result is INT_MIN
+       b       result_fs_w
+
+/*
+ * Trap if the hardware should have handled this case.
+ */
+fpe_trap:
+       move    a2, a1                          # code = FP CSR
+       ctc1    a1, FPC_CSR             # save exceptions
+       break   0
+
+/*
+ * Send an illegal instruction signal to the current process.
+ */
+ill:
+       ctc1    a1, FPC_CSR             # save exceptions
+       move    a2, a0                          # code = FP instruction
+       break   0
+
+result_ft_s:
+       move    t0, t4                          # result is FT
+       move    t1, t5
+       move    t2, t6
+result_fs_s:                                   # result is FS
+       jal     set_fd_s                        # save result (in t0,t1,t2)
+       b       done
+
+result_fs_w:
+       jal     set_fd_word                     # save result (in t2)
+       b       done
+
+result_ft_d:
+       move    t0, t4                          # result is FT
+       move    t1, t5
+       move    t2, t6
+       move    t3, t7
+result_fs_d:                                   # result is FS
+       jal     set_fd_d                        # save result (in t0,t1,t2,t3)
+
+done:
+       lw      ra, STAND_RA_OFFSET(sp)
+       addu    sp, sp, STAND_FRAME_SIZE
+       j       ra
+END(CPU_EmulateFP)
+
+/*----------------------------------------------------------------------------
+ * get_fs_int --
+ *
+ *     Read (integer) the FS register (bits 15-11).
+ *     This is an internal routine used by CPU_EmulateFP only.
+ *
+ * Results:
+ *     t0      contains the sign
+ *     t2      contains the fraction
+ *
+ *----------------------------------------------------------------------------
+ */
+LEAF(get_fs_int)
+       srl     a3, a0, 12 - 2                  # get FS field (even regs only)
+       and     a3, a3, 0xF << 2                # mask FS field
+       lw      a3, get_fs_int_tbl(a3)          # switch on register number
+       j       a3
+
+       .rdata
+get_fs_int_tbl:
+       .word   get_fs_int_f0
+       .word   get_fs_int_f2
+       .word   get_fs_int_f4
+       .word   get_fs_int_f6
+       .word   get_fs_int_f8
+       .word   get_fs_int_f10
+       .word   get_fs_int_f12
+       .word   get_fs_int_f14
+       .word   get_fs_int_f16
+       .word   get_fs_int_f18
+       .word   get_fs_int_f20
+       .word   get_fs_int_f22
+       .word   get_fs_int_f24
+       .word   get_fs_int_f26
+       .word   get_fs_int_f28
+       .word   get_fs_int_f30
+       .text
+
+get_fs_int_f0:
+       mfc1    t2, $f0
+       b       get_fs_int_done
+get_fs_int_f2:
+       mfc1    t2, $f2
+       b       get_fs_int_done
+get_fs_int_f4:
+       mfc1    t2, $f4
+       b       get_fs_int_done
+get_fs_int_f6:
+       mfc1    t2, $f6
+       b       get_fs_int_done
+get_fs_int_f8:
+       mfc1    t2, $f8
+       b       get_fs_int_done
+get_fs_int_f10:
+       mfc1    t2, $f10
+       b       get_fs_int_done
+get_fs_int_f12:
+       mfc1    t2, $f12
+       b       get_fs_int_done
+get_fs_int_f14:
+       mfc1    t2, $f14
+       b       get_fs_int_done
+get_fs_int_f16:
+       mfc1    t2, $f16
+       b       get_fs_int_done
+get_fs_int_f18:
+       mfc1    t2, $f18
+       b       get_fs_int_done
+get_fs_int_f20:
+       mfc1    t2, $f20
+       b       get_fs_int_done
+get_fs_int_f22:
+       mfc1    t2, $f22
+       b       get_fs_int_done
+get_fs_int_f24:
+       mfc1    t2, $f24
+       b       get_fs_int_done
+get_fs_int_f26:
+       mfc1    t2, $f26
+       b       get_fs_int_done
+get_fs_int_f28:
+       mfc1    t2, $f28
+       b       get_fs_int_done
+get_fs_int_f30:
+       mfc1    t2, $f30
+get_fs_int_done:
+       srl     t0, t2, 31              # init the sign bit
+       bge     t2, zero, 1f
+       negu    t2
+1:
+       j       ra
+END(get_fs_int)
+
+/*----------------------------------------------------------------------------
+ * get_ft_fs_s --
+ *
+ *     Read (single precision) the FT register (bits 20-16) and
+ *     the FS register (bits 15-11) and break up into fields.
+ *     This is an internal routine used by CPU_EmulateFP only.
+ *
+ * Results:
+ *     t0      contains the FS sign
+ *     t1      contains the FS (biased) exponent
+ *     t2      contains the FS fraction
+ *     t4      contains the FT sign
+ *     t5      contains the FT (biased) exponent
+ *     t6      contains the FT fraction
+ *
+ *----------------------------------------------------------------------------
+ */
+LEAF(get_ft_fs_s)
+       srl     a3, a0, 17 - 2                  # get FT field (even regs only)
+       and     a3, a3, 0xF << 2                # mask FT field
+       lw      a3, get_ft_s_tbl(a3)            # switch on register number
+       j       a3
+
+       .rdata
+get_ft_s_tbl:
+       .word   get_ft_s_f0
+       .word   get_ft_s_f2
+       .word   get_ft_s_f4
+       .word   get_ft_s_f6
+       .word   get_ft_s_f8
+       .word   get_ft_s_f10
+       .word   get_ft_s_f12
+       .word   get_ft_s_f14
+       .word   get_ft_s_f16
+       .word   get_ft_s_f18
+       .word   get_ft_s_f20
+       .word   get_ft_s_f22
+       .word   get_ft_s_f24
+       .word   get_ft_s_f26
+       .word   get_ft_s_f28
+       .word   get_ft_s_f30
+       .text
+
+get_ft_s_f0:
+       mfc1    t4, $f0
+       b       get_ft_s_done
+get_ft_s_f2:
+       mfc1    t4, $f2
+       b       get_ft_s_done
+get_ft_s_f4:
+       mfc1    t4, $f4
+       b       get_ft_s_done
+get_ft_s_f6:
+       mfc1    t4, $f6
+       b       get_ft_s_done
+get_ft_s_f8:
+       mfc1    t4, $f8
+       b       get_ft_s_done
+get_ft_s_f10:
+       mfc1    t4, $f10
+       b       get_ft_s_done
+get_ft_s_f12:
+       mfc1    t4, $f12
+       b       get_ft_s_done
+get_ft_s_f14:
+       mfc1    t4, $f14
+       b       get_ft_s_done
+get_ft_s_f16:
+       mfc1    t4, $f16
+       b       get_ft_s_done
+get_ft_s_f18:
+       mfc1    t4, $f18
+       b       get_ft_s_done
+get_ft_s_f20:
+       mfc1    t4, $f20
+       b       get_ft_s_done
+get_ft_s_f22:
+       mfc1    t4, $f22
+       b       get_ft_s_done
+get_ft_s_f24:
+       mfc1    t4, $f24
+       b       get_ft_s_done
+get_ft_s_f26:
+       mfc1    t4, $f26
+       b       get_ft_s_done
+get_ft_s_f28:
+       mfc1    t4, $f28
+       b       get_ft_s_done
+get_ft_s_f30:
+       mfc1    t4, $f30
+get_ft_s_done:
+       srl     t5, t4, 23                      # get exponent
+       and     t5, t5, 0xFF
+       and     t6, t4, 0x7FFFFF                # get fraction
+       srl     t4, t4, 31                      # get sign
+       bne     t5, SEXP_INF, 1f                # is it a signaling NAN?
+       and     v0, t6, SSIGNAL_NAN
+       bne     v0, zero, invalid_s
+1:
+       /* fall through to get FS */
+
+/*----------------------------------------------------------------------------
+ * get_fs_s --
+ *
+ *     Read (single precision) the FS register (bits 15-11) and
+ *     break up into fields.
+ *     This is an internal routine used by CPU_EmulateFP only.
+ *
+ * Results:
+ *     t0      contains the sign
+ *     t1      contains the (biased) exponent
+ *     t2      contains the fraction
+ *
+ *----------------------------------------------------------------------------
+ */
+ALEAF(get_fs_s)
+       srl     a3, a0, 12 - 2                  # get FS field (even regs only)
+       and     a3, a3, 0xF << 2                # mask FS field
+       lw      a3, get_fs_s_tbl(a3)            # switch on register number
+       j       a3
+
+       .rdata
+get_fs_s_tbl:
+       .word   get_fs_s_f0
+       .word   get_fs_s_f2
+       .word   get_fs_s_f4
+       .word   get_fs_s_f6
+       .word   get_fs_s_f8
+       .word   get_fs_s_f10
+       .word   get_fs_s_f12
+       .word   get_fs_s_f14
+       .word   get_fs_s_f16
+       .word   get_fs_s_f18
+       .word   get_fs_s_f20
+       .word   get_fs_s_f22
+       .word   get_fs_s_f24
+       .word   get_fs_s_f26
+       .word   get_fs_s_f28
+       .word   get_fs_s_f30
+       .text
+
+get_fs_s_f0:
+       mfc1    t0, $f0
+       b       get_fs_s_done
+get_fs_s_f2:
+       mfc1    t0, $f2
+       b       get_fs_s_done
+get_fs_s_f4:
+       mfc1    t0, $f4
+       b       get_fs_s_done
+get_fs_s_f6:
+       mfc1    t0, $f6
+       b       get_fs_s_done
+get_fs_s_f8:
+       mfc1    t0, $f8
+       b       get_fs_s_done
+get_fs_s_f10:
+       mfc1    t0, $f10
+       b       get_fs_s_done
+get_fs_s_f12:
+       mfc1    t0, $f12
+       b       get_fs_s_done
+get_fs_s_f14:
+       mfc1    t0, $f14
+       b       get_fs_s_done
+get_fs_s_f16:
+       mfc1    t0, $f16
+       b       get_fs_s_done
+get_fs_s_f18:
+       mfc1    t0, $f18
+       b       get_fs_s_done
+get_fs_s_f20:
+       mfc1    t0, $f20
+       b       get_fs_s_done
+get_fs_s_f22:
+       mfc1    t0, $f22
+       b       get_fs_s_done
+get_fs_s_f24:
+       mfc1    t0, $f24
+       b       get_fs_s_done
+get_fs_s_f26:
+       mfc1    t0, $f26
+       b       get_fs_s_done
+get_fs_s_f28:
+       mfc1    t0, $f28
+       b       get_fs_s_done
+get_fs_s_f30:
+       mfc1    t0, $f30
+get_fs_s_done:
+       srl     t1, t0, 23                      # get exponent
+       and     t1, t1, 0xFF
+       and     t2, t0, 0x7FFFFF                # get fraction
+       srl     t0, t0, 31                      # get sign
+       bne     t1, SEXP_INF, 1f                # is it a signaling NAN?
+       and     v0, t2, SSIGNAL_NAN
+       bne     v0, zero, invalid_s
+1:
+       j       ra
+END(get_ft_fs_s)
+
+/*----------------------------------------------------------------------------
+ * get_ft_fs_d --
+ *
+ *     Read (double precision) the FT register (bits 20-16) and
+ *     the FS register (bits 15-11) and break up into fields.
+ *     This is an internal routine used by CPU_EmulateFP only.
+ *
+ * Results:
+ *     t0      contains the FS sign
+ *     t1      contains the FS (biased) exponent
+ *     t2      contains the FS fraction
+ *     t3      contains the FS remaining fraction
+ *     t4      contains the FT sign
+ *     t5      contains the FT (biased) exponent
+ *     t6      contains the FT fraction
+ *     t7      contains the FT remaining fraction
+ *
+ *----------------------------------------------------------------------------
+ */
+LEAF(get_ft_fs_d)
+       srl     a3, a0, 17 - 2                  # get FT field (even regs only)
+       and     a3, a3, 0xF << 2                # mask FT field
+       lw      a3, get_ft_d_tbl(a3)            # switch on register number
+       j       a3
+
+       .rdata
+get_ft_d_tbl:
+       .word   get_ft_d_f0
+       .word   get_ft_d_f2
+       .word   get_ft_d_f4
+       .word   get_ft_d_f6
+       .word   get_ft_d_f8
+       .word   get_ft_d_f10
+       .word   get_ft_d_f12
+       .word   get_ft_d_f14
+       .word   get_ft_d_f16
+       .word   get_ft_d_f18
+       .word   get_ft_d_f20
+       .word   get_ft_d_f22
+       .word   get_ft_d_f24
+       .word   get_ft_d_f26
+       .word   get_ft_d_f28
+       .word   get_ft_d_f30
+       .text
+
+get_ft_d_f0:
+       mfc1    t7, $f0
+       mfc1    t4, $f1
+       b       get_ft_d_done
+get_ft_d_f2:
+       mfc1    t7, $f2
+       mfc1    t4, $f3
+       b       get_ft_d_done
+get_ft_d_f4:
+       mfc1    t7, $f4
+       mfc1    t4, $f5
+       b       get_ft_d_done
+get_ft_d_f6:
+       mfc1    t7, $f6
+       mfc1    t4, $f7
+       b       get_ft_d_done
+get_ft_d_f8:
+       mfc1    t7, $f8
+       mfc1    t4, $f9
+       b       get_ft_d_done
+get_ft_d_f10:
+       mfc1    t7, $f10
+       mfc1    t4, $f11
+       b       get_ft_d_done
+get_ft_d_f12:
+       mfc1    t7, $f12
+       mfc1    t4, $f13
+       b       get_ft_d_done
+get_ft_d_f14:
+       mfc1    t7, $f14
+       mfc1    t4, $f15
+       b       get_ft_d_done
+get_ft_d_f16:
+       mfc1    t7, $f16
+       mfc1    t4, $f17
+       b       get_ft_d_done
+get_ft_d_f18:
+       mfc1    t7, $f18
+       mfc1    t4, $f19
+       b       get_ft_d_done
+get_ft_d_f20:
+       mfc1    t7, $f20
+       mfc1    t4, $f21
+       b       get_ft_d_done
+get_ft_d_f22:
+       mfc1    t7, $f22
+       mfc1    t4, $f23
+       b       get_ft_d_done
+get_ft_d_f24:
+       mfc1    t7, $f24
+       mfc1    t4, $f25
+       b       get_ft_d_done
+get_ft_d_f26:
+       mfc1    t7, $f26
+       mfc1    t4, $f27
+       b       get_ft_d_done
+get_ft_d_f28:
+       mfc1    t7, $f28
+       mfc1    t4, $f29
+       b       get_ft_d_done
+get_ft_d_f30:
+       mfc1    t7, $f30
+       mfc1    t4, $f31
+get_ft_d_done:
+       srl     t5, t4, 20                      # get exponent
+       and     t5, t5, 0x7FF
+       and     t6, t4, 0xFFFFF                 # get fraction
+       srl     t4, t4, 31                      # get sign
+       bne     t5, DEXP_INF, 1f                # is it a signaling NAN?
+       and     v0, t6, DSIGNAL_NAN
+       bne     v0, zero, invalid_d
+1:
+       /* fall through to get FS */
+
+/*----------------------------------------------------------------------------
+ * get_fs_d --
+ *
+ *     Read (double precision) the FS register (bits 15-11) and
+ *     break up into fields.
+ *     This is an internal routine used by CPU_EmulateFP only.
+ *
+ * Results:
+ *     t0      contains the sign
+ *     t1      contains the (biased) exponent
+ *     t2      contains the fraction
+ *     t3      contains the remaining fraction
+ *
+ *----------------------------------------------------------------------------
+ */
+ALEAF(get_fs_d)
+       srl     a3, a0, 12 - 2                  # get FS field (even regs only)
+       and     a3, a3, 0xF << 2                # mask FS field
+       lw      a3, get_fs_d_tbl(a3)            # switch on register number
+       j       a3
+
+       .rdata
+get_fs_d_tbl:
+       .word   get_fs_d_f0
+       .word   get_fs_d_f2
+       .word   get_fs_d_f4
+       .word   get_fs_d_f6
+       .word   get_fs_d_f8
+       .word   get_fs_d_f10
+       .word   get_fs_d_f12
+       .word   get_fs_d_f14
+       .word   get_fs_d_f16
+       .word   get_fs_d_f18
+       .word   get_fs_d_f20
+       .word   get_fs_d_f22
+       .word   get_fs_d_f24
+       .word   get_fs_d_f26
+       .word   get_fs_d_f28
+       .word   get_fs_d_f30
+       .text
+
+get_fs_d_f0:
+       mfc1    t3, $f0
+       mfc1    t0, $f1
+       b       get_fs_d_done
+get_fs_d_f2:
+       mfc1    t3, $f2
+       mfc1    t0, $f3
+       b       get_fs_d_done
+get_fs_d_f4:
+       mfc1    t3, $f4
+       mfc1    t0, $f5
+       b       get_fs_d_done
+get_fs_d_f6:
+       mfc1    t3, $f6
+       mfc1    t0, $f7
+       b       get_fs_d_done
+get_fs_d_f8:
+       mfc1    t3, $f8
+       mfc1    t0, $f9
+       b       get_fs_d_done
+get_fs_d_f10:
+       mfc1    t3, $f10
+       mfc1    t0, $f11
+       b       get_fs_d_done
+get_fs_d_f12:
+       mfc1    t3, $f12
+       mfc1    t0, $f13
+       b       get_fs_d_done
+get_fs_d_f14:
+       mfc1    t3, $f14
+       mfc1    t0, $f15
+       b       get_fs_d_done
+get_fs_d_f16:
+       mfc1    t3, $f16
+       mfc1    t0, $f17
+       b       get_fs_d_done
+get_fs_d_f18:
+       mfc1    t3, $f18
+       mfc1    t0, $f19
+       b       get_fs_d_done
+get_fs_d_f20:
+       mfc1    t3, $f20
+       mfc1    t0, $f21
+       b       get_fs_d_done
+get_fs_d_f22:
+       mfc1    t3, $f22
+       mfc1    t0, $f23
+       b       get_fs_d_done
+get_fs_d_f24:
+       mfc1    t3, $f24
+       mfc1    t0, $f25
+       b       get_fs_d_done
+get_fs_d_f26:
+       mfc1    t3, $f26
+       mfc1    t0, $f27
+       b       get_fs_d_done
+get_fs_d_f28:
+       mfc1    t3, $f28
+       mfc1    t0, $f29
+       b       get_fs_d_done
+get_fs_d_f30:
+       mfc1    t3, $f30
+       mfc1    t0, $f31
+get_fs_d_done:
+       srl     t1, t0, 20                      # get exponent
+       and     t1, t1, 0x7FF
+       and     t2, t0, 0xFFFFF                 # get fraction
+       srl     t0, t0, 31                      # get sign
+       bne     t1, DEXP_INF, 1f                # is it a signaling NAN?
+       and     v0, t2, DSIGNAL_NAN
+       bne     v0, zero, invalid_d
+1:
+       j       ra
+END(get_ft_fs_d)
+
+/*----------------------------------------------------------------------------
+ * get_cmp_s --
+ *
+ *     Read (single precision) the FS register (bits 15-11) and
+ *     the FT register (bits 20-16) and break up into fields.
+ *     This is an internal routine used by CPU_EmulateFP only.
+ *
+ * Results:
+ *     t0      contains the sign
+ *     t1      contains the (biased) exponent
+ *     t2      contains the fraction
+ *     t4      contains the sign
+ *     t5      contains the (biased) exponent
+ *     t6      contains the fraction
+ *
+ *----------------------------------------------------------------------------
+ */
+LEAF(get_cmp_s)
+       srl     a3, a0, 12 - 2                  # get FS field (even regs only)
+       and     a3, a3, 0xF << 2                # mask FS field
+       lw      a3, cmp_fs_s_tbl(a3)            # switch on register number
+       j       a3
+
+       .rdata
+cmp_fs_s_tbl:
+       .word   cmp_fs_s_f0
+       .word   cmp_fs_s_f2
+       .word   cmp_fs_s_f4
+       .word   cmp_fs_s_f6
+       .word   cmp_fs_s_f8
+       .word   cmp_fs_s_f10
+       .word   cmp_fs_s_f12
+       .word   cmp_fs_s_f14
+       .word   cmp_fs_s_f16
+       .word   cmp_fs_s_f18
+       .word   cmp_fs_s_f20
+       .word   cmp_fs_s_f22
+       .word   cmp_fs_s_f24
+       .word   cmp_fs_s_f26
+       .word   cmp_fs_s_f28
+       .word   cmp_fs_s_f30
+       .text
+
+cmp_fs_s_f0:
+       mfc1    t0, $f0
+       b       cmp_fs_s_done
+cmp_fs_s_f2:
+       mfc1    t0, $f2
+       b       cmp_fs_s_done
+cmp_fs_s_f4:
+       mfc1    t0, $f4
+       b       cmp_fs_s_done
+cmp_fs_s_f6:
+       mfc1    t0, $f6
+       b       cmp_fs_s_done
+cmp_fs_s_f8:
+       mfc1    t0, $f8
+       b       cmp_fs_s_done
+cmp_fs_s_f10:
+       mfc1    t0, $f10
+       b       cmp_fs_s_done
+cmp_fs_s_f12:
+       mfc1    t0, $f12
+       b       cmp_fs_s_done
+cmp_fs_s_f14:
+       mfc1    t0, $f14
+       b       cmp_fs_s_done
+cmp_fs_s_f16:
+       mfc1    t0, $f16
+       b       cmp_fs_s_done
+cmp_fs_s_f18:
+       mfc1    t0, $f18
+       b       cmp_fs_s_done
+cmp_fs_s_f20:
+       mfc1    t0, $f20
+       b       cmp_fs_s_done
+cmp_fs_s_f22:
+       mfc1    t0, $f22
+       b       cmp_fs_s_done
+cmp_fs_s_f24:
+       mfc1    t0, $f24
+       b       cmp_fs_s_done
+cmp_fs_s_f26:
+       mfc1    t0, $f26
+       b       cmp_fs_s_done
+cmp_fs_s_f28:
+       mfc1    t0, $f28
+       b       cmp_fs_s_done
+cmp_fs_s_f30:
+       mfc1    t0, $f30
+cmp_fs_s_done:
+       srl     t1, t0, 23                      # get exponent
+       and     t1, t1, 0xFF
+       and     t2, t0, 0x7FFFFF                # get fraction
+       srl     t0, t0, 31                      # get sign
+
+       srl     a3, a0, 17 - 2                  # get FT field (even regs only)
+       and     a3, a3, 0xF << 2                # mask FT field
+       lw      a3, cmp_ft_s_tbl(a3)            # switch on register number
+       j       a3
+
+       .rdata
+cmp_ft_s_tbl:
+       .word   cmp_ft_s_f0
+       .word   cmp_ft_s_f2
+       .word   cmp_ft_s_f4
+       .word   cmp_ft_s_f6
+       .word   cmp_ft_s_f8
+       .word   cmp_ft_s_f10
+       .word   cmp_ft_s_f12
+       .word   cmp_ft_s_f14
+       .word   cmp_ft_s_f16
+       .word   cmp_ft_s_f18
+       .word   cmp_ft_s_f20
+       .word   cmp_ft_s_f22
+       .word   cmp_ft_s_f24
+       .word   cmp_ft_s_f26
+       .word   cmp_ft_s_f28
+       .word   cmp_ft_s_f30
+       .text
+
+cmp_ft_s_f0:
+       mfc1    t4, $f0
+       b       cmp_ft_s_done
+cmp_ft_s_f2:
+       mfc1    t4, $f2
+       b       cmp_ft_s_done
+cmp_ft_s_f4:
+       mfc1    t4, $f4
+       b       cmp_ft_s_done
+cmp_ft_s_f6:
+       mfc1    t4, $f6
+       b       cmp_ft_s_done
+cmp_ft_s_f8:
+       mfc1    t4, $f8
+       b       cmp_ft_s_done
+cmp_ft_s_f10:
+       mfc1    t4, $f10
+       b       cmp_ft_s_done
+cmp_ft_s_f12:
+       mfc1    t4, $f12
+       b       cmp_ft_s_done
+cmp_ft_s_f14:
+       mfc1    t4, $f14
+       b       cmp_ft_s_done
+cmp_ft_s_f16:
+       mfc1    t4, $f16
+       b       cmp_ft_s_done
+cmp_ft_s_f18:
+       mfc1    t4, $f18
+       b       cmp_ft_s_done
+cmp_ft_s_f20:
+       mfc1    t4, $f20
+       b       cmp_ft_s_done
+cmp_ft_s_f22:
+       mfc1    t4, $f22
+       b       cmp_ft_s_done
+cmp_ft_s_f24:
+       mfc1    t4, $f24
+       b       cmp_ft_s_done
+cmp_ft_s_f26:
+       mfc1    t4, $f26
+       b       cmp_ft_s_done
+cmp_ft_s_f28:
+       mfc1    t4, $f28
+       b       cmp_ft_s_done
+cmp_ft_s_f30:
+       mfc1    t4, $f30
+cmp_ft_s_done:
+       srl     t5, t4, 23                      # get exponent
+       and     t5, t5, 0xFF
+       and     t6, t4, 0x7FFFFF                # get fraction
+       srl     t4, t4, 31                      # get sign
+       j       ra
+END(get_cmp_s)
+
+/*----------------------------------------------------------------------------
+ * get_cmp_d --
+ *
+ *     Read (double precision) the FS register (bits 15-11) and
+ *     the FT register (bits 20-16) and break up into fields.
+ *     This is an internal routine used by CPU_EmulateFP only.
+ *
+ * Results:
+ *     t0      contains the sign
+ *     t1      contains the (biased) exponent
+ *     t2      contains the fraction
+ *     t3      contains the remaining fraction
+ *     t4      contains the sign
+ *     t5      contains the (biased) exponent
+ *     t6      contains the fraction
+ *     t7      contains the remaining fraction
+ *
+ *----------------------------------------------------------------------------
+ */
+LEAF(get_cmp_d)
+       srl     a3, a0, 12 - 2                  # get FS field (even regs only)
+       and     a3, a3, 0xF << 2                # mask FS field
+       lw      a3, cmp_fs_d_tbl(a3)            # switch on register number
+       j       a3
+
+       .rdata
+cmp_fs_d_tbl:
+       .word   cmp_fs_d_f0
+       .word   cmp_fs_d_f2
+       .word   cmp_fs_d_f4
+       .word   cmp_fs_d_f6
+       .word   cmp_fs_d_f8
+       .word   cmp_fs_d_f10
+       .word   cmp_fs_d_f12
+       .word   cmp_fs_d_f14
+       .word   cmp_fs_d_f16
+       .word   cmp_fs_d_f18
+       .word   cmp_fs_d_f20
+       .word   cmp_fs_d_f22
+       .word   cmp_fs_d_f24
+       .word   cmp_fs_d_f26
+       .word   cmp_fs_d_f28
+       .word   cmp_fs_d_f30
+       .text
+
+cmp_fs_d_f0:
+       mfc1    t3, $f0
+       mfc1    t0, $f1
+       b       cmp_fs_d_done
+cmp_fs_d_f2:
+       mfc1    t3, $f2
+       mfc1    t0, $f3
+       b       cmp_fs_d_done
+cmp_fs_d_f4:
+       mfc1    t3, $f4
+       mfc1    t0, $f5
+       b       cmp_fs_d_done
+cmp_fs_d_f6:
+       mfc1    t3, $f6
+       mfc1    t0, $f7
+       b       cmp_fs_d_done
+cmp_fs_d_f8:
+       mfc1    t3, $f8
+       mfc1    t0, $f9
+       b       cmp_fs_d_done
+cmp_fs_d_f10:
+       mfc1    t3, $f10
+       mfc1    t0, $f11
+       b       cmp_fs_d_done
+cmp_fs_d_f12:
+       mfc1    t3, $f12
+       mfc1    t0, $f13
+       b       cmp_fs_d_done
+cmp_fs_d_f14:
+       mfc1    t3, $f14
+       mfc1    t0, $f15
+       b       cmp_fs_d_done
+cmp_fs_d_f16:
+       mfc1    t3, $f16
+       mfc1    t0, $f17
+       b       cmp_fs_d_done
+cmp_fs_d_f18:
+       mfc1    t3, $f18
+       mfc1    t0, $f19
+       b       cmp_fs_d_done
+cmp_fs_d_f20:
+       mfc1    t3, $f20
+       mfc1    t0, $f21
+       b       cmp_fs_d_done
+cmp_fs_d_f22:
+       mfc1    t3, $f22
+       mfc1    t0, $f23
+       b       cmp_fs_d_done
+cmp_fs_d_f24:
+       mfc1    t3, $f24
+       mfc1    t0, $f25
+       b       cmp_fs_d_done
+cmp_fs_d_f26:
+       mfc1    t3, $f26
+       mfc1    t0, $f27
+       b       cmp_fs_d_done
+cmp_fs_d_f28:
+       mfc1    t3, $f28
+       mfc1    t0, $f29
+       b       cmp_fs_d_done
+cmp_fs_d_f30:
+       mfc1    t3, $f30
+       mfc1    t0, $f31
+cmp_fs_d_done:
+       srl     t1, t0, 20                      # get exponent
+       and     t1, t1, 0x7FF
+       and     t2, t0, 0xFFFFF                 # get fraction
+       srl     t0, t0, 31                      # get sign
+
+       srl     a3, a0, 17 - 2                  # get FT field (even regs only)
+       and     a3, a3, 0xF << 2                # mask FT field
+       lw      a3, cmp_ft_d_tbl(a3)            # switch on register number
+       j       a3
+
+       .rdata
+cmp_ft_d_tbl:
+       .word   cmp_ft_d_f0
+       .word   cmp_ft_d_f2
+       .word   cmp_ft_d_f4
+       .word   cmp_ft_d_f6
+       .word   cmp_ft_d_f8
+       .word   cmp_ft_d_f10
+       .word   cmp_ft_d_f12
+       .word   cmp_ft_d_f14
+       .word   cmp_ft_d_f16
+       .word   cmp_ft_d_f18
+       .word   cmp_ft_d_f20
+       .word   cmp_ft_d_f22
+       .word   cmp_ft_d_f24
+       .word   cmp_ft_d_f26
+       .word   cmp_ft_d_f28
+       .word   cmp_ft_d_f30
+       .text
+
+cmp_ft_d_f0:
+       mfc1    t7, $f0
+       mfc1    t4, $f1
+       b       cmp_ft_d_done
+cmp_ft_d_f2:
+       mfc1    t7, $f2
+       mfc1    t4, $f3
+       b       cmp_ft_d_done
+cmp_ft_d_f4:
+       mfc1    t7, $f4
+       mfc1    t4, $f5
+       b       cmp_ft_d_done
+cmp_ft_d_f6:
+       mfc1    t7, $f6
+       mfc1    t4, $f7
+       b       cmp_ft_d_done
+cmp_ft_d_f8:
+       mfc1    t7, $f8
+       mfc1    t4, $f9
+       b       cmp_ft_d_done
+cmp_ft_d_f10:
+       mfc1    t7, $f10
+       mfc1    t4, $f11
+       b       cmp_ft_d_done
+cmp_ft_d_f12:
+       mfc1    t7, $f12
+       mfc1    t4, $f13
+       b       cmp_ft_d_done
+cmp_ft_d_f14:
+       mfc1    t7, $f14
+       mfc1    t4, $f15
+       b       cmp_ft_d_done
+cmp_ft_d_f16:
+       mfc1    t7, $f16
+       mfc1    t4, $f17
+       b       cmp_ft_d_done
+cmp_ft_d_f18:
+       mfc1    t7, $f18
+       mfc1    t4, $f19
+       b       cmp_ft_d_done
+cmp_ft_d_f20:
+       mfc1    t7, $f20
+       mfc1    t4, $f21
+       b       cmp_ft_d_done
+cmp_ft_d_f22:
+       mfc1    t7, $f22
+       mfc1    t4, $f23
+       b       cmp_ft_d_done
+cmp_ft_d_f24:
+       mfc1    t7, $f24
+       mfc1    t4, $f25
+       b       cmp_ft_d_done
+cmp_ft_d_f26:
+       mfc1    t7, $f26
+       mfc1    t4, $f27
+       b       cmp_ft_d_done
+cmp_ft_d_f28:
+       mfc1    t7, $f28
+       mfc1    t4, $f29
+       b       cmp_ft_d_done
+cmp_ft_d_f30:
+       mfc1    t7, $f30
+       mfc1    t4, $f31
+cmp_ft_d_done:
+       srl     t5, t4, 20                      # get exponent
+       and     t5, t5, 0x7FF
+       and     t6, t4, 0xFFFFF                 # get fraction
+       srl     t4, t4, 31                      # get sign
+       j       ra
+END(get_cmp_d)
+
+/*----------------------------------------------------------------------------
+ * set_fd_s --
+ *
+ *     Write (single precision) the FD register (bits 10-6).
+ *     This is an internal routine used by CPU_EmulateFP only.
+ *
+ * Arguments:
+ *     a0      contains the FP instruction
+ *     t0      contains the sign
+ *     t1      contains the (biased) exponent
+ *     t2      contains the fraction
+ *
+ * set_fd_word --
+ *
+ *     Write (integer) the FD register (bits 10-6).
+ *     This is an internal routine used by CPU_EmulateFP only.
+ *
+ * Arguments:
+ *     a0      contains the FP instruction
+ *     t2      contains the integer
+ *
+ *----------------------------------------------------------------------------
+ */
+LEAF(set_fd_s)
+       sll     t0, t0, 31                      # position sign
+       sll     t1, t1, 23                      # position exponent
+       or      t2, t2, t0
+       or      t2, t2, t1
+ALEAF(set_fd_word)
+       srl     a3, a0, 7 - 2                   # get FD field (even regs only)
+       and     a3, a3, 0xF << 2                # mask FT field
+       lw      a3, set_fd_s_tbl(a3)            # switch on register number
+       j       a3
+
+       .rdata
+set_fd_s_tbl:
+       .word   set_fd_s_f0
+       .word   set_fd_s_f2
+       .word   set_fd_s_f4
+       .word   set_fd_s_f6
+       .word   set_fd_s_f8
+       .word   set_fd_s_f10
+       .word   set_fd_s_f12
+       .word   set_fd_s_f14
+       .word   set_fd_s_f16
+       .word   set_fd_s_f18
+       .word   set_fd_s_f20
+       .word   set_fd_s_f22
+       .word   set_fd_s_f24
+       .word   set_fd_s_f26
+       .word   set_fd_s_f28
+       .word   set_fd_s_f30
+       .text
+
+set_fd_s_f0:
+       mtc1    t2, $f0
+       j       ra
+set_fd_s_f2:
+       mtc1    t2, $f2
+       j       ra
+set_fd_s_f4:
+       mtc1    t2, $f4
+       j       ra
+set_fd_s_f6:
+       mtc1    t2, $f6
+       j       ra
+set_fd_s_f8:
+       mtc1    t2, $f8
+       j       ra
+set_fd_s_f10:
+       mtc1    t2, $f10
+       j       ra
+set_fd_s_f12:
+       mtc1    t2, $f12
+       j       ra
+set_fd_s_f14:
+       mtc1    t2, $f14
+       j       ra
+set_fd_s_f16:
+       mtc1    t2, $f16
+       j       ra
+set_fd_s_f18:
+       mtc1    t2, $f18
+       j       ra
+set_fd_s_f20:
+       mtc1    t2, $f20
+       j       ra
+set_fd_s_f22:
+       mtc1    t2, $f22
+       j       ra
+set_fd_s_f24:
+       mtc1    t2, $f24
+       j       ra
+set_fd_s_f26:
+       mtc1    t2, $f26
+       j       ra
+set_fd_s_f28:
+       mtc1    t2, $f28
+       j       ra
+set_fd_s_f30:
+       mtc1    t2, $f30
+       j       ra
+END(set_fd_s)
+
+/*----------------------------------------------------------------------------
+ * set_fd_d --
+ *
+ *     Write (double precision) the FT register (bits 10-6).
+ *     This is an internal routine used by CPU_EmulateFP only.
+ *
+ * Arguments:
+ *     a0      contains the FP instruction
+ *     t0      contains the sign
+ *     t1      contains the (biased) exponent
+ *     t2      contains the fraction
+ *     t3      contains the remaining fraction
+ *
+ *----------------------------------------------------------------------------
+ */
+LEAF(set_fd_d)
+       sll     t0, t0, 31                      # set sign
+       sll     t1, t1, 20                      # set exponent
+       or      t0, t0, t1
+       or      t0, t0, t2                      # set fraction
+       srl     a3, a0, 7 - 2                   # get FD field (even regs only)
+       and     a3, a3, 0xF << 2                # mask FD field
+       lw      a3, set_fd_d_tbl(a3)            # switch on register number
+       j       a3
+
+       .rdata
+set_fd_d_tbl:
+       .word   set_fd_d_f0
+       .word   set_fd_d_f2
+       .word   set_fd_d_f4
+       .word   set_fd_d_f6
+       .word   set_fd_d_f8
+       .word   set_fd_d_f10
+       .word   set_fd_d_f12
+       .word   set_fd_d_f14
+       .word   set_fd_d_f16
+       .word   set_fd_d_f18
+       .word   set_fd_d_f20
+       .word   set_fd_d_f22
+       .word   set_fd_d_f24
+       .word   set_fd_d_f26
+       .word   set_fd_d_f28
+       .word   set_fd_d_f30
+       .text
+
+set_fd_d_f0:
+       mtc1    t3, $f0
+       mtc1    t0, $f1
+       j       ra
+set_fd_d_f2:
+       mtc1    t3, $f2
+       mtc1    t0, $f3
+       j       ra
+set_fd_d_f4:
+       mtc1    t3, $f4
+       mtc1    t0, $f5
+       j       ra
+set_fd_d_f6:
+       mtc1    t3, $f6
+       mtc1    t0, $f7
+       j       ra
+set_fd_d_f8:
+       mtc1    t3, $f8
+       mtc1    t0, $f9
+       j       ra
+set_fd_d_f10:
+       mtc1    t3, $f10
+       mtc1    t0, $f11
+       j       ra
+set_fd_d_f12:
+       mtc1    t3, $f12
+       mtc1    t0, $f13
+       j       ra
+set_fd_d_f14:
+       mtc1    t3, $f14
+       mtc1    t0, $f15
+       j       ra
+set_fd_d_f16:
+       mtc1    t3, $f16
+       mtc1    t0, $f17
+       j       ra
+set_fd_d_f18:
+       mtc1    t3, $f18
+       mtc1    t0, $f19
+       j       ra
+set_fd_d_f20:
+       mtc1    t3, $f20
+       mtc1    t0, $f21
+       j       ra
+set_fd_d_f22:
+       mtc1    t3, $f22
+       mtc1    t0, $f23
+       j       ra
+set_fd_d_f24:
+       mtc1    t3, $f24
+       mtc1    t0, $f25
+       j       ra
+set_fd_d_f26:
+       mtc1    t3, $f26
+       mtc1    t0, $f27
+       j       ra
+set_fd_d_f28:
+       mtc1    t3, $f28
+       mtc1    t0, $f29
+       j       ra
+set_fd_d_f30:
+       mtc1    t3, $f30
+       mtc1    t0, $f31
+       j       ra
+END(set_fd_d)
+
+/*----------------------------------------------------------------------------
+ * renorm_fs_s --
+ *
+ * Results:
+ *     t1      unbiased exponent
+ *     t2      normalized fraction
+ *
+ *----------------------------------------------------------------------------
+ */
+LEAF(renorm_fs_s)
+/*
+ * Find out how many leading zero bits are in t2 and put in t9.
+ */
+       move    v0, t2
+       move    t9, zero
+       srl     v1, v0, 16
+       bne     v1, zero, 1f
+       addu    t9, 16
+       sll     v0, 16
+1:
+       srl     v1, v0, 24
+       bne     v1, zero, 1f
+       addu    t9, 8
+       sll     v0, 8
+1:
+       srl     v1, v0, 28
+       bne     v1, zero, 1f
+       addu    t9, 4
+       sll     v0, 4
+1:
+       srl     v1, v0, 30
+       bne     v1, zero, 1f
+       addu    t9, 2
+       sll     v0, 2
+1:
+       srl     v1, v0, 31
+       bne     v1, zero, 1f
+       addu    t9, 1
+/*
+ * Now shift t2 the correct number of bits.
+ */
+1:
+       subu    t9, t9, SLEAD_ZEROS     # dont count normal leading zeros
+       li      t1, SEXP_MIN
+       subu    t1, t1, t9              # adjust exponent
+       sll     t2, t2, t9
+       j       ra
+END(renorm_fs_s)
+
+/*----------------------------------------------------------------------------
+ * renorm_fs_d --
+ *
+ * Results:
+ *     t1      unbiased exponent
+ *     t2,t3   normalized fraction
+ *
+ *----------------------------------------------------------------------------
+ */
+LEAF(renorm_fs_d)
+/*
+ * Find out how many leading zero bits are in t2,t3 and put in t9.
+ */
+       move    v0, t2
+       move    t9, zero
+       bne     t2, zero, 1f
+       move    v0, t3
+       addu    t9, 32
+1:
+       srl     v1, v0, 16
+       bne     v1, zero, 1f
+       addu    t9, 16
+       sll     v0, 16
+1:
+       srl     v1, v0, 24
+       bne     v1, zero, 1f
+       addu    t9, 8
+       sll     v0, 8
+1:
+       srl     v1, v0, 28
+       bne     v1, zero, 1f
+       addu    t9, 4
+       sll     v0, 4
+1:
+       srl     v1, v0, 30
+       bne     v1, zero, 1f
+       addu    t9, 2
+       sll     v0, 2
+1:
+       srl     v1, v0, 31
+       bne     v1, zero, 1f
+       addu    t9, 1
+/*
+ * Now shift t2,t3 the correct number of bits.
+ */
+1:
+       subu    t9, t9, DLEAD_ZEROS     # dont count normal leading zeros
+       li      t1, DEXP_MIN
+       subu    t1, t1, t9              # adjust exponent
+       li      v0, 32
+       blt     t9, v0, 1f
+       subu    t9, t9, v0              # shift fraction left >= 32 bits
+       sll     t2, t3, t9
+       move    t3, zero
+       j       ra
+1:
+       subu    v0, v0, t9              # shift fraction left < 32 bits
+       sll     t2, t2, t9
+       srl     v1, t3, v0
+       or      t2, t2, v1
+       sll     t3, t3, t9
+       j       ra
+END(renorm_fs_d)
+
+/*----------------------------------------------------------------------------
+ * renorm_ft_s --
+ *
+ * Results:
+ *     t5      unbiased exponent
+ *     t6      normalized fraction
+ *
+ *----------------------------------------------------------------------------
+ */
+LEAF(renorm_ft_s)
+/*
+ * Find out how many leading zero bits are in t6 and put in t9.
+ */
+       move    v0, t6
+       move    t9, zero
+       srl     v1, v0, 16
+       bne     v1, zero, 1f
+       addu    t9, 16
+       sll     v0, 16
+1:
+       srl     v1, v0, 24
+       bne     v1, zero, 1f
+       addu    t9, 8
+       sll     v0, 8
+1:
+       srl     v1, v0, 28
+       bne     v1, zero, 1f
+       addu    t9, 4
+       sll     v0, 4
+1:
+       srl     v1, v0, 30
+       bne     v1, zero, 1f
+       addu    t9, 2
+       sll     v0, 2
+1:
+       srl     v1, v0, 31
+       bne     v1, zero, 1f
+       addu    t9, 1
+/*
+ * Now shift t6 the correct number of bits.
+ */
+1:
+       subu    t9, t9, SLEAD_ZEROS     # dont count normal leading zeros
+       li      t5, SEXP_MIN
+       subu    t5, t5, t9              # adjust exponent
+       sll     t6, t6, t9
+       j       ra
+END(renorm_ft_s)
+
+/*----------------------------------------------------------------------------
+ * renorm_ft_d --
+ *
+ * Results:
+ *     t5      unbiased exponent
+ *     t6,t7   normalized fraction
+ *
+ *----------------------------------------------------------------------------
+ */
+LEAF(renorm_ft_d)
+/*
+ * Find out how many leading zero bits are in t6,t7 and put in t9.
+ */
+       move    v0, t6
+       move    t9, zero
+       bne     t6, zero, 1f
+       move    v0, t7
+       addu    t9, 32
+1:
+       srl     v1, v0, 16
+       bne     v1, zero, 1f
+       addu    t9, 16
+       sll     v0, 16
+1:
+       srl     v1, v0, 24
+       bne     v1, zero, 1f
+       addu    t9, 8
+       sll     v0, 8
+1:
+       srl     v1, v0, 28
+       bne     v1, zero, 1f
+       addu    t9, 4
+       sll     v0, 4
+1:
+       srl     v1, v0, 30
+       bne     v1, zero, 1f
+       addu    t9, 2
+       sll     v0, 2
+1:
+       srl     v1, v0, 31
+       bne     v1, zero, 1f
+       addu    t9, 1
+/*
+ * Now shift t6,t7 the correct number of bits.
+ */
+1:
+       subu    t9, t9, DLEAD_ZEROS     # dont count normal leading zeros
+       li      t5, DEXP_MIN
+       subu    t5, t5, t9              # adjust exponent
+       li      v0, 32
+       blt     t9, v0, 1f
+       subu    t9, t9, v0              # shift fraction left >= 32 bits
+       sll     t6, t7, t9
+       move    t7, zero
+       j       ra
+1:
+       subu    v0, v0, t9              # shift fraction left < 32 bits
+       sll     t6, t6, t9
+       srl     v1, t7, v0
+       or      t6, t6, v1
+       sll     t7, t7, t9
+       j       ra
+END(renorm_ft_d)
diff --git a/sys/arch/wgrisc/wgrisc/genassym.c b/sys/arch/wgrisc/wgrisc/genassym.c
new file mode 100644 (file)
index 0000000..24550e7
--- /dev/null
@@ -0,0 +1,74 @@
+/*     $OpenBSD: genassym.c,v 1.1.1.1 1997/02/06 16:02:45 pefo Exp $   */
+/*
+ * Copyright (c) 1992, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Ralph Campbell.
+ *
+ * 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: @(#)genassym.c    8.2 (Berkeley) 9/23/93
+ *      $Id: genassym.c,v 1.1.1.1 1997/02/06 16:02:45 pefo Exp $
+ */
+
+
+#include <sys/param.h>
+#include <sys/buf.h>
+#include <sys/map.h>
+#include <sys/proc.h>
+#include <sys/mbuf.h>
+#include <sys/user.h>
+
+#include <machine/reg.h>
+
+main()
+{
+       register struct proc *p = (struct proc *)0;
+       register struct user *up = (struct user *)0;
+       register struct vmmeter *vm = (struct vmmeter *)0;
+       register int size, s, n;
+
+       printf("#define\tP_FORW %d\n", &p->p_forw);
+       printf("#define\tP_BACK %d\n", &p->p_back);
+       printf("#define\tP_PRIORITY %d\n", &p->p_priority);
+       printf("#define\tP_ADDR %d\n", &p->p_addr);
+       printf("#define\tP_UPTE %d\n", p->p_md.md_upte);
+       printf("#define\tU_PCB_REGS %d\n", up->u_pcb.pcb_regs);
+       printf("#define\tU_PCB_FPREGS %d\n", &up->u_pcb.pcb_regs[F0]);
+       printf("#define\tU_PCB_CONTEXT %d\n", &up->u_pcb.pcb_context);
+       printf("#define\tU_PCB_ONFAULT %d\n", &up->u_pcb.pcb_onfault);
+       printf("#define\tU_PCB_SEGTAB %d\n", &up->u_pcb.pcb_segtab);
+       printf("#define\tVM_MIN_ADDRESS 0x%x\n", VM_MIN_ADDRESS);
+       printf("#define\tVM_MIN_KERNEL_ADDRESS 0x%x\n", VM_MIN_KERNEL_ADDRESS);
+       printf("#define\tV_SWTCH %d\n", &vm->v_swtch);
+       printf("#define\tSIGILL %d\n", SIGILL);
+       printf("#define\tSIGFPE %d\n", SIGFPE);
+       exit(0);
+}
diff --git a/sys/arch/wgrisc/wgrisc/locore.S b/sys/arch/wgrisc/wgrisc/locore.S
new file mode 100644 (file)
index 0000000..c97d83e
--- /dev/null
@@ -0,0 +1,4485 @@
+
+/*     $OpenBSD: locore.S,v 1.1.1.1 1997/02/06 16:02:45 pefo Exp $     */
+/*
+ * Copyright (c) 1992, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Digital Equipment Corporation and Ralph Campbell.
+ *
+ * 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.
+ *
+ * Copyright (C) 1989 Digital Equipment Corporation.
+ * Permission to use, copy, modify, and distribute this software and
+ * its documentation for any purpose and without fee is hereby granted,
+ * provided that the above copyright notice appears in all copies.
+ * Digital Equipment Corporation makes no representations about the
+ * suitability of this software for any purpose.  It is provided "as is"
+ * without express or implied warranty.
+ *
+ * from: Header: /sprite/src/kernel/mach/ds3100.md/RCS/loMem.s,
+ *     v 1.1 89/07/11 17:55:04 nelson Exp  SPRITE (DECWRL)
+ * from: Header: /sprite/src/kernel/mach/ds3100.md/RCS/machAsm.s,
+ *     v 9.2 90/01/29 18:00:39 shirriff Exp  SPRITE (DECWRL)
+ * from: Header: /sprite/src/kernel/vm/ds3100.md/vmPmaxAsm.s,
+ *     v 1.1 89/07/10 14:27:41 nelson Exp  SPRITE (DECWRL)
+ *
+ *     from: @(#)locore.s      8.5 (Berkeley) 1/4/94
+ *     $Id: locore.S,v 1.1.1.1 1997/02/06 16:02:45 pefo Exp $
+ */
+
+/*
+ *     Contains code that is the first executed at boot time plus
+ *     assembly language support routines.
+ */
+
+#include <sys/errno.h>
+#include <sys/syscall.h>
+
+#include <machine/param.h>
+#include <machine/psl.h>
+#include <machine/asm.h>
+#include <machine/cpu.h>
+#include <machine/regnum.h>
+#include <machine/pte.h>
+
+#include "assym.h"
+
+       .set    noreorder
+
+/*
+ * Amount to take off of the stack for the benefit of the debugger.
+ */
+#define START_FRAME    ((4 * 4) + 4 + 4)
+
+       .globl  start
+start:
+       mtc0    zero, COP_0_STATUS_REG  # Disable interrupts
+       mtc0    zero, COP_0_CAUSE_REG   # Clear soft interrupts
+
+#ifndef R4K
+       la      v0, 1f                          # it appears that we have to
+       or      v0, UNCACHED_MEMORY_ADDR        # run uncached.
+       j       v0
+       nop
+1:
+       mfc0    v0, COP_0_R3K_CONF      # reconfigure FP interrupt.
+       li      v1, 0xe3ffffff
+       and     v0, v0, v1
+       mtc0    v0, COP_0_R3K_CONF
+       nop; nop; nop; nop; nop; nop; nop; nop; nop; nop
+       la      v0, 1f
+       j       v0
+       nop
+1:
+#endif
+       
+/*
+ * Initialize stack and call machine startup.
+ */
+       la      sp, start - START_FRAME
+       la      gp, _gp
+       sw      zero, START_FRAME - 4(sp)       # Zero out old ra for debugger
+       jal     mips_init                       # mips_init(argc, argv, envp)
+       sw      zero, START_FRAME - 8(sp)       # Zero out old fp for debugger
+
+       li      t0, SR_COP_1_BIT                # Disable interrupts and
+       mtc0    t0, COP_0_STATUS_REG    #   enable the fp coprocessor
+       li      sp, KERNELSTACK - START_FRAME   # switch to standard stack
+       mfc0    t0, COP_0_PRID          # read processor ID register
+       nop
+       nop                                     # wait for new status to
+       nop                                     # to be effective
+       nop
+       cfc1    t1, FPC_ID                      # read FPU ID register
+       sw      t0, cpu_id                      # save PRID register
+       sw      t1, fpu_id                      # save FPU ID register
+       jal     main                            # main(regs)
+       move    a0, zero
+/*
+ * proc[1] == /etc/init now running here.
+ * Restore user registers and return.
+ */
+#ifdef R4K     /* ==================XXXXX============================== */
+       .set    noat
+       li      v0, SR_EXL
+       mtc0    v0, COP_0_STATUS_REG    # set exeption level bit.
+
+       lw      a0, UADDR+U_PCB_REGS+(SR * 4)
+       lw      t0, UADDR+U_PCB_REGS+(MULLO * 4)
+       lw      t1, UADDR+U_PCB_REGS+(MULHI * 4)
+       mtlo    t0
+       mthi    t1
+       lw      a0, UADDR+U_PCB_REGS+(PC * 4)
+       lw      AT, UADDR+U_PCB_REGS+(AST * 4)
+       lw      v0, UADDR+U_PCB_REGS+(V0 * 4)
+       dmtc0   a0, COP_0_EXC_PC        # set return address
+       li      a0, R4K_PSL_USERSET
+       mtc0    a0, COP_0_STATUS_REG    # switch to user mode (when eret...)
+       lw      v1, UADDR+U_PCB_REGS+(V1 * 4)
+       lw      a0, UADDR+U_PCB_REGS+(A0 * 4)
+       lw      a1, UADDR+U_PCB_REGS+(A1 * 4)
+       lw      a2, UADDR+U_PCB_REGS+(A2 * 4)
+       lw      a3, UADDR+U_PCB_REGS+(A3 * 4)
+       lw      t0, UADDR+U_PCB_REGS+(T0 * 4)
+       lw      t1, UADDR+U_PCB_REGS+(T1 * 4)
+       lw      t2, UADDR+U_PCB_REGS+(T2 * 4)
+       lw      t3, UADDR+U_PCB_REGS+(T3 * 4)
+       lw      t4, UADDR+U_PCB_REGS+(T4 * 4)
+       lw      t5, UADDR+U_PCB_REGS+(T5 * 4)
+       lw      t6, UADDR+U_PCB_REGS+(T6 * 4)
+       lw      t7, UADDR+U_PCB_REGS+(T7 * 4)
+       lw      s0, UADDR+U_PCB_REGS+(S0 * 4)
+       lw      s1, UADDR+U_PCB_REGS+(S1 * 4)
+       lw      s2, UADDR+U_PCB_REGS+(S2 * 4)
+       lw      s3, UADDR+U_PCB_REGS+(S3 * 4)
+       lw      s4, UADDR+U_PCB_REGS+(S4 * 4)
+       lw      s5, UADDR+U_PCB_REGS+(S5 * 4)
+       lw      s6, UADDR+U_PCB_REGS+(S6 * 4)
+       lw      s7, UADDR+U_PCB_REGS+(S7 * 4)
+       lw      t8, UADDR+U_PCB_REGS+(T8 * 4)
+       lw      gp, UADDR+U_PCB_REGS+(GP * 4)
+       lw      sp, UADDR+U_PCB_REGS+(SP * 4)
+       lw      s8, UADDR+U_PCB_REGS+(S8 * 4)
+       lw      ra, UADDR+U_PCB_REGS+(RA * 4)
+       lw      t9, UADDR+U_PCB_REGS+(T9 * 4)
+       eret
+       .set    at
+#else
+       .set    noat
+       li      v0, R3K_PSL_USERSET
+       mtc0    v0, COP_0_STATUS_REG            # switch to user mode
+       lw      a0, UADDR+U_PCB_REGS+(SR * 4)
+       lw      t0, UADDR+U_PCB_REGS+(MULLO * 4)
+       lw      t1, UADDR+U_PCB_REGS+(MULHI * 4)
+       mtlo    t0
+       mthi    t1
+       lw      k0, UADDR+U_PCB_REGS+(PC * 4)
+       lw      AT, UADDR+U_PCB_REGS+(AST * 4)
+       lw      v0, UADDR+U_PCB_REGS+(V0 * 4)
+       lw      v1, UADDR+U_PCB_REGS+(V1 * 4)
+       lw      a0, UADDR+U_PCB_REGS+(A0 * 4)
+       lw      a1, UADDR+U_PCB_REGS+(A1 * 4)
+       lw      a2, UADDR+U_PCB_REGS+(A2 * 4)
+       lw      a3, UADDR+U_PCB_REGS+(A3 * 4)
+       lw      t0, UADDR+U_PCB_REGS+(T0 * 4)
+       lw      t1, UADDR+U_PCB_REGS+(T1 * 4)
+       lw      t2, UADDR+U_PCB_REGS+(T2 * 4)
+       lw      t3, UADDR+U_PCB_REGS+(T3 * 4)
+       lw      t4, UADDR+U_PCB_REGS+(T4 * 4)
+       lw      t5, UADDR+U_PCB_REGS+(T5 * 4)
+       lw      t6, UADDR+U_PCB_REGS+(T6 * 4)
+       lw      t7, UADDR+U_PCB_REGS+(T7 * 4)
+       lw      s0, UADDR+U_PCB_REGS+(S0 * 4)
+       lw      s1, UADDR+U_PCB_REGS+(S1 * 4)
+       lw      s2, UADDR+U_PCB_REGS+(S2 * 4)
+       lw      s3, UADDR+U_PCB_REGS+(S3 * 4)
+       lw      s4, UADDR+U_PCB_REGS+(S4 * 4)
+       lw      s5, UADDR+U_PCB_REGS+(S5 * 4)
+       lw      s6, UADDR+U_PCB_REGS+(S6 * 4)
+       lw      s7, UADDR+U_PCB_REGS+(S7 * 4)
+       lw      t8, UADDR+U_PCB_REGS+(T8 * 4)
+       lw      t9, UADDR+U_PCB_REGS+(T9 * 4)
+       lw      gp, UADDR+U_PCB_REGS+(GP * 4)
+       lw      sp, UADDR+U_PCB_REGS+(SP * 4)
+       lw      s8, UADDR+U_PCB_REGS+(S8 * 4)
+       lw      ra, UADDR+U_PCB_REGS+(RA * 4)
+       j       k0
+       rfe
+       .set    at
+#endif         /* ==================XXXXX============================== */
+
+/*
+ * Primitives
+ */
+
+/*
+ * This table is indexed by u.u_pcb.pcb_onfault in trap().
+ * The reason for using this table rather than storing an address in
+ * u.u_pcb.pcb_onfault is simply to make the code faster.
+ */
+       .globl  onfault_table
+       .data
+       .align  3
+onfault_table:
+       .word   0               # invalid index number
+#define BADERR         1
+       .word   baderr
+#define COPYERR                2
+       .word   copyerr
+#define FSWBERR                3
+       .word   fswberr
+#define FSWINTRBERR    4
+       .word   fswintrberr
+#ifdef DEBUG
+#define MDBERR         5
+       .word   mdberr
+#endif
+       .text
+
+/*
+ * See if access to addr with a len type instruction causes a machine check.
+ * len is length of access (1=byte, 2=short, 4=long)
+ *
+ * badaddr(addr, len)
+ *     char *addr;
+ *     int len;
+ */
+LEAF(badaddr)
+       li      v0, BADERR
+       bne     a1, 1, 2f
+       sw      v0, UADDR+U_PCB_ONFAULT
+       b       5f
+       lbu     v0, (a0)
+2:
+       bne     a1, 2, 4f
+       nop
+       b       5f
+       lhu     v0, (a0)
+4:
+       lw      v0, (a0)
+5:
+       sw      zero, UADDR+U_PCB_ONFAULT
+       j       ra
+       move    v0, zero                # made it w/o errors
+baderr:
+       j       ra
+       li      v0, 1                   # trap sends us here
+END(badaddr)
+
+/*
+ * This code is copied the user's stack for returning from signal handlers
+ * (see sendsig() and sigreturn()). We have to compute the address
+ * of the sigcontext struct for the sigreturn call.
+ */
+       .globl  sigcode
+sigcode:
+       addu    a0, sp, 16              # address of sigcontext
+       li      v0, SYS_sigreturn       # sigreturn(scp)
+       syscall
+       break   0                       # just in case sigreturn fails
+       .globl  esigcode
+esigcode:
+
+/*
+ * Copy a null terminated string within the kernel address space.
+ * Maxlength may be null if count not wanted.
+ *     copystr(fromaddr, toaddr, maxlength, &lencopied)
+ *             caddr_t fromaddr;
+ *             caddr_t toaddr;
+ *             u_int maxlength;
+ *             u_int *lencopied;
+ */
+LEAF(copystr)
+       move    t2, a2                  # Save the number of bytes
+1:
+       lbu     t0, 0(a0)
+       subu    a2, a2, 1
+       beq     t0, zero, 2f
+       sb      t0, 0(a1)
+       addu    a0, a0, 1
+       bne     a2, zero, 1b
+       addu    a1, a1, 1
+2:
+       beq     a3, zero, 3f
+       subu    a2, t2, a2              # compute length copied
+       sw      a2, 0(a3)
+3:
+       j       ra
+       move    v0, zero
+END(copystr)
+
+/*
+ * fillw(pat, addr, count)
+ */
+LEAF(fillw)
+1:
+       addiu   a2, a2, -1
+       sh      a0, 0(a1)
+       bne     a2,zero, 1b
+       addiu   a1, a1, 2
+
+       jr      ra
+       nop
+END(fillw)
+
+/*
+ *     Block I/O routines mainly used by I/O drivers.
+ *
+ *     Args as:        a0 = port
+ *                     a1 = memory address
+ *                     a2 = count
+ */
+LEAF(insb)
+       beq     a2, zero, 2f
+       addu    a2, a1
+1:
+       lbu     v0, 0(a0)
+       addiu   a1, 1
+       bne     a1, a2, 1b
+       sb      v0, -1(a1)
+2:
+       jr      ra
+       nop
+END(insb)
+
+LEAF(insw)
+       beq     a2, zero, 2f
+       addu    a2, a2
+       addu    a2, a1
+1:
+       lhu     v0, 0(a0)
+       addiu   a1, 2
+       bne     a1, a2, 1b
+       sh      v0, -2(a1)
+2:
+       jr      ra
+       nop
+END(insw)
+
+LEAF(insl)
+       beq     a2, zero, 2f
+       sll     a2, 2
+       addu    a2, a1
+1:
+       lw      v0, 0(a0)
+       addiu   a1, 4
+       bne     a1, a2, 1b
+       sw      v0, -4(a1)
+2:
+       jr      ra
+       nop
+END(insl)
+
+LEAF(outsb)
+       beq     a2, zero, 2f
+       addu    a2, a1
+1:
+       lbu     v0, 0(a1)
+       addiu   a1, 1
+       bne     a1, a2, 1b
+       sb      v0, 0(a0)
+2:
+       jr      ra
+       nop
+END(outsb)
+
+LEAF(outsw)
+       beq     a2, zero, 2f
+       addu    a2, a2
+       li      v0, 1
+       and     v0, a1
+       bne     v0, zero, 3f            # arghh, unaligned.
+       addu    a2, a1
+1:
+       lhu     v0, 0(a1)
+       addiu   a1, 2
+       bne     a1, a2, 1b
+       sh      v0, 0(a0)
+2:
+       jr      ra
+       nop
+3:
+       LWHI    v0, 0(a1)
+       LWLO    v0, 3(a1)
+       addiu   a1, 2
+       bne     a1, a2, 3b
+       sh      v0, 0(a0)
+
+       jr      ra
+       nop
+END(outsw)
+
+LEAF(outsl)
+       beq     a2, zero, 2f
+       sll     a2, 2
+       li      v0, 3
+       and     v0, a1
+       bne     v0, zero, 3f            # arghh, unaligned.
+       addu    a2, a1
+1:
+       lw      v0, 0(a1)
+       addiu   a1, 4
+       bne     a1, a2, 1b
+       sw      v0, 0(a0)
+2:
+       jr      ra
+       nop
+3:
+       LWHI    v0, 0(a1)
+       LWLO    v0, 3(a1)
+       addiu   a1, 4
+       bne     a1, a2, 3b
+       sw      v0, 0(a0)
+
+       jr      ra
+       nop
+END(outsl)
+
+/*
+ * Copy a null terminated string from the user address space into
+ * the kernel address space.
+ *
+ *     copyinstr(fromaddr, toaddr, maxlength, &lencopied)
+ *             caddr_t fromaddr;
+ *             caddr_t toaddr;
+ *             u_int maxlength;
+ *             u_int *lencopied;
+ */
+NON_LEAF(copyinstr, STAND_FRAME_SIZE, ra)
+       subu    sp, sp, STAND_FRAME_SIZE
+       .mask   0x80000000, (STAND_RA_OFFSET - STAND_FRAME_SIZE)
+       sw      ra, STAND_RA_OFFSET(sp)
+       blt     a0, zero, copyerr       # make sure address is in user space
+       li      v0, COPYERR
+       jal     copystr
+       sw      v0, UADDR+U_PCB_ONFAULT
+       lw      ra, STAND_RA_OFFSET(sp)
+       sw      zero, UADDR+U_PCB_ONFAULT
+       addu    sp, sp, STAND_FRAME_SIZE
+       j       ra
+       move    v0, zero
+END(copyinstr)
+
+/*
+ * Copy a null terminated string from the kernel address space into
+ * the user address space.
+ *
+ *     copyoutstr(fromaddr, toaddr, maxlength, &lencopied)
+ *             caddr_t fromaddr;
+ *             caddr_t toaddr;
+ *             u_int maxlength;
+ *             u_int *lencopied;
+ */
+NON_LEAF(copyoutstr, STAND_FRAME_SIZE, ra)
+       subu    sp, sp, STAND_FRAME_SIZE
+       .mask   0x80000000, (STAND_RA_OFFSET - STAND_FRAME_SIZE)
+       sw      ra, STAND_RA_OFFSET(sp)
+       blt     a1, zero, copyerr       # make sure address is in user space
+       li      v0, COPYERR
+       jal     copystr
+       sw      v0, UADDR+U_PCB_ONFAULT
+       lw      ra, STAND_RA_OFFSET(sp)
+       sw      zero, UADDR+U_PCB_ONFAULT
+       addu    sp, sp, STAND_FRAME_SIZE
+       j       ra
+       move    v0, zero
+END(copyoutstr)
+
+/*
+ * Copy specified amount of data from user space into the kernel
+ *     copyin(from, to, len)
+ *             caddr_t *from;  (user source address)
+ *             caddr_t *to;    (kernel destination address)
+ *             unsigned len;
+ */
+NON_LEAF(copyin, STAND_FRAME_SIZE, ra)
+       subu    sp, sp, STAND_FRAME_SIZE
+       .mask   0x80000000, (STAND_RA_OFFSET - STAND_FRAME_SIZE)
+       sw      ra, STAND_RA_OFFSET(sp)
+       blt     a0, zero, copyerr       # make sure address is in user space
+       li      v0, COPYERR
+       jal     bcopy
+       sw      v0, UADDR+U_PCB_ONFAULT
+       lw      ra, STAND_RA_OFFSET(sp)
+       sw      zero, UADDR+U_PCB_ONFAULT
+       addu    sp, sp, STAND_FRAME_SIZE
+       j       ra
+       move    v0, zero
+END(copyin)
+
+/*
+ * Copy specified amount of data from kernel to the user space
+ *     copyout(from, to, len)
+ *             caddr_t *from;  (kernel source address)
+ *             caddr_t *to;    (user destination address)
+ *             unsigned len;
+ */
+NON_LEAF(copyout, STAND_FRAME_SIZE, ra)
+       subu    sp, sp, STAND_FRAME_SIZE
+       .mask   0x80000000, (STAND_RA_OFFSET - STAND_FRAME_SIZE)
+       sw      ra, STAND_RA_OFFSET(sp)
+       blt     a1, zero, copyerr       # make sure address is in user space
+       li      v0, COPYERR
+       jal     bcopy
+       sw      v0, UADDR+U_PCB_ONFAULT
+       lw      ra, STAND_RA_OFFSET(sp)
+       sw      zero, UADDR+U_PCB_ONFAULT
+       addu    sp, sp, STAND_FRAME_SIZE
+       j       ra
+       move    v0, zero
+END(copyout)
+
+LEAF(copyerr)
+       lw      ra, STAND_RA_OFFSET(sp)
+       sw      zero, UADDR+U_PCB_ONFAULT
+       addu    sp, sp, STAND_FRAME_SIZE
+       j       ra
+       li      v0, EFAULT              # return error
+END(copyerr)
+
+/*
+ * Copy the kernel stack to the new process and save the current context so
+ * the new process will return nonzero when it is resumed by cpu_switch().
+ *
+ *     copykstack(up)
+ *             struct user *up;
+ */
+LEAF(copykstack)
+       subu    v0, sp, UADDR           # compute offset into stack
+       addu    v0, v0, a0              # v0 = new stack address
+       move    v1, sp                  # v1 = old stack address
+       li      t1, KERNELSTACK
+1:
+       lw      t0, 0(v1)               # copy stack data
+       addu    v1, v1, 4
+       sw      t0, 0(v0)
+       bne     v1, t1, 1b
+       addu    v0, v0, 4
+       /* FALLTHROUGH */
+/*
+ * Save registers and state so we can do a longjmp later.
+ * Note: this only works if p != curproc since
+ * cpu_switch() will copy over pcb_context.
+ *
+ *     savectx(up)
+ *             struct user *up;
+ */
+ALEAF(savectx)
+       sw      s0, U_PCB_CONTEXT+0(a0)
+       sw      s1, U_PCB_CONTEXT+4(a0)
+       sw      s2, U_PCB_CONTEXT+8(a0)
+       sw      s3, U_PCB_CONTEXT+12(a0)
+       mfc0    v0, COP_0_STATUS_REG
+       sw      s4, U_PCB_CONTEXT+16(a0)
+       sw      s5, U_PCB_CONTEXT+20(a0)
+       sw      s6, U_PCB_CONTEXT+24(a0)
+       sw      s7, U_PCB_CONTEXT+28(a0)
+       sw      sp, U_PCB_CONTEXT+32(a0)
+       sw      s8, U_PCB_CONTEXT+36(a0)
+       sw      ra, U_PCB_CONTEXT+40(a0)
+       sw      v0, U_PCB_CONTEXT+44(a0)
+       j       ra
+       move    v0, zero
+END(copykstack)
+
+/*
+ * 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.
+ */
+/*
+ * setrunqueue(p)
+ *     proc *p;
+ *
+ * Call should be made at splclock(), and p->p_stat should be SRUN.
+ */
+NON_LEAF(setrunqueue, STAND_FRAME_SIZE, ra)
+       subu    sp, sp, STAND_FRAME_SIZE
+       .mask   0x80000000, (STAND_RA_OFFSET - STAND_FRAME_SIZE)
+       lw      t0, P_BACK(a0)          ## firewall: p->p_back must be 0
+       sw      ra, STAND_RA_OFFSET(sp) ##
+       beq     t0, zero, 1f            ##
+       lbu     t0, P_PRIORITY(a0)      # put on p->p_priority / 4 queue
+       PANIC("setrunqueue")            ##
+1:
+       li      t1, 1                   # compute corresponding bit
+       srl     t0, t0, 2               # compute index into 'whichqs'
+       sll     t1, t1, t0
+       lw      t2, whichqs             # set corresponding bit
+       nop
+       or      t2, t2, t1
+       sw      t2, whichqs
+       sll     t0, t0, 3               # compute index into 'qs'
+       la      t1, qs
+       addu    t0, t0, t1              # t0 = qp = &qs[pri >> 2]
+       lw      t1, P_BACK(t0)          # t1 = qp->ph_rlink
+       sw      t0, P_FORW(a0)          # p->p_forw = qp
+       sw      t1, P_BACK(a0)          # p->p_back = qp->ph_rlink
+       sw      a0, P_FORW(t1)          # p->p_back->p_forw = p;
+       sw      a0, P_BACK(t0)          # qp->ph_rlink = p
+       j       ra
+       addu    sp, sp, STAND_FRAME_SIZE
+END(setrunqueue)
+
+/*
+ * Remrq(p)
+ *
+ * Call should be made at splclock().
+ */
+NON_LEAF(remrunqueue, STAND_FRAME_SIZE, ra)
+       subu    sp, sp, STAND_FRAME_SIZE
+       .mask   0x80000000, (STAND_RA_OFFSET - STAND_FRAME_SIZE)
+       lbu     t0, P_PRIORITY(a0)      # get from p->p_priority / 4 queue
+       li      t1, 1                   # compute corresponding bit
+       srl     t0, t0, 2               # compute index into 'whichqs'
+       lw      t2, whichqs             # check corresponding bit
+       sll     t1, t1, t0
+       and     v0, t2, t1
+       sw      ra, STAND_RA_OFFSET(sp) ##
+       bne     v0, zero, 1f            ##
+       lw      v0, P_BACK(a0)          # v0 = p->p_back
+       PANIC("remrq")                  ## it wasnt recorded to be on its q
+1:
+       lw      v1, P_FORW(a0)          # v1 = p->p_forw
+       nop
+       sw      v1, P_FORW(v0)          # p->p_back->p_forw = p->p_forw;
+       sw      v0, P_BACK(v1)          # p->p_forw->p_back = p->r_rlink
+       sll     t0, t0, 3               # compute index into 'qs'
+       la      v0, qs
+       addu    t0, t0, v0              # t0 = qp = &qs[pri >> 2]
+       lw      v0, P_FORW(t0)          # check if queue empty
+       nop
+       bne     v0, t0, 2f              # No. qp->ph_link != qp
+       nop
+       xor     t2, t2, t1              # clear corresponding bit in 'whichqs'
+       sw      t2, whichqs
+2:
+       sw      zero, P_BACK(a0)        ## for firewall checking
+       j       ra
+       addu    sp, sp, STAND_FRAME_SIZE
+END(remrunqueue)
+
+/*
+ * switch_exit()
+ *
+ * At exit of a process, do a cpu_switch for the last time.
+ * The mapping of the pcb at p->p_addr has already been deleted,
+ * and the memory for the pcb+stack has been freed.
+ * All interrupts should be blocked at this point.
+ */
+LEAF(switch_exit)
+       la      v1, nullproc                    # save state into garbage proc
+       lw      t0, P_UPTE+0(v1)                # t0 = first u. pte
+       lw      t1, P_UPTE+4(v1)                # t1 = 2nd u. pte
+       li      v0, UADDR                       # v0 = first HI entry
+       mtc0    zero, COP_0_TLB_INDEX           # set the index register
+#ifdef R4K     /* ==================XXXXX============================== */
+       dmtc0   v0, COP_0_TLB_HI                # init high entry
+       dmtc0   t0, COP_0_TLB_LO0               # init low entry0
+       dmtc0   t1, COP_0_TLB_LO1               # init low entry1
+       nop
+       tlbwi                                   # Write the TLB entry.
+       nop
+       nop
+       sw      zero, curproc
+#else
+       mtc0    v0, COP_0_TLB_HI                # init high entry
+       mtc0    t0, COP_0_TLB_LO0               # init low entry
+       li      t0, 1 << R3K_TLB_INDEX_SHIFT
+       tlbwi                                   # Write the TLB entry.
+       addu    v0, v0, NBPG                    # 2nd HI entry
+       mtc0    t0, COP_0_TLB_INDEX             # set the index register
+       mtc0    v0, COP_0_TLB_HI                # init high entry
+       mtc0    t1, COP_0_TLB_LO0               # init low entry
+       sw      zero, curproc
+       tlbwi                                   # Write the TLB entry.
+#endif         /* ==================XXXXX============================== */
+       b       cpu_switch
+       li      sp, KERNELSTACK - START_FRAME   # switch to standard stack
+END(switch_exit)
+
+/*
+ * When no processes are on the runq, cpu_switch branches to idle
+ * to wait for something to come ready.
+ * Note: this is really a part of cpu_switch() but defined here for kernel
+ * profiling.
+ */
+LEAF(idle)
+       li      t0, (INT_MASK | SR_INT_ENAB)    # XXX INT_MASK should be a var..
+       mtc0    t0, COP_0_STATUS_REG            # enable all interrupts
+       sw      zero, curproc                   # set curproc NULL for stats
+1:
+       lw      t0, whichqs                     # look for non-empty queue
+       nop
+       beq     t0, zero, 1b
+       nop
+       b       sw1
+       mtc0    zero, COP_0_STATUS_REG  # Disable all interrupts
+END(idle)
+
+/*
+ * cpu_switch()
+ * Find the highest priority process and resume it.
+ */
+NON_LEAF(cpu_switch, STAND_FRAME_SIZE, ra)
+       sw      sp, UADDR+U_PCB_CONTEXT+32      # save old sp
+       subu    sp, sp, STAND_FRAME_SIZE
+       sw      ra, STAND_RA_OFFSET(sp)
+       .mask   0x80000000, (STAND_RA_OFFSET - STAND_FRAME_SIZE)
+       lw      t2, cnt+V_SWTCH                 # for statistics
+       lw      t1, whichqs                     # look for non-empty queue
+       sw      s0, UADDR+U_PCB_CONTEXT+0       # do a 'savectx()'
+       sw      s1, UADDR+U_PCB_CONTEXT+4
+       sw      s2, UADDR+U_PCB_CONTEXT+8
+       sw      s3, UADDR+U_PCB_CONTEXT+12
+       mfc0    t0, COP_0_STATUS_REG    # t0 = saved status register
+       sw      s4, UADDR+U_PCB_CONTEXT+16
+       sw      s5, UADDR+U_PCB_CONTEXT+20
+       sw      s6, UADDR+U_PCB_CONTEXT+24
+       sw      s7, UADDR+U_PCB_CONTEXT+28
+       sw      s8, UADDR+U_PCB_CONTEXT+36
+       sw      ra, UADDR+U_PCB_CONTEXT+40      # save return address
+       sw      t0, UADDR+U_PCB_CONTEXT+44      # save status register
+       addu    t2, t2, 1
+       sw      t2, cnt+V_SWTCH
+       beq     t1, zero, idle                  # if none, idle
+       mtc0    zero, COP_0_STATUS_REG  # Disable all interrupts
+sw1:
+       nop                                     # wait for intrs disabled
+       nop
+       nop
+       nop
+       lw      t0, whichqs                     # look for non-empty queue
+       li      t2, -1                          # t2 = lowest bit set
+       beq     t0, zero, idle                  # if none, idle
+       move    t3, t0                          # t3 = saved whichqs
+1:
+       addu    t2, t2, 1
+       and     t1, t0, 1                       # bit set?
+       beq     t1, zero, 1b
+       srl     t0, t0, 1                       # try next bit
+/*
+ * Remove process from queue.
+ */
+       sll     t0, t2, 3
+       la      t1, qs
+       addu    t0, t0, t1                      # t0 = qp = &qs[highbit]
+       lw      a0, P_FORW(t0)                  # a0 = p = highest pri process
+       nop
+       lw      v0, P_FORW(a0)                  # v0 = p->p_forw
+       bne     t0, a0, 2f                      # make sure something in queue
+       sw      v0, P_FORW(t0)                  # qp->ph_link = p->p_forw;
+       PANIC("cpu_switch")                     # nothing in queue
+2:
+       sw      t0, P_BACK(v0)                  # p->p_forw->p_back = qp
+       bne     v0, t0, 3f                      # queue still not empty
+       sw      zero, P_BACK(a0)                ## for firewall checking
+       li      v1, 1                           # compute bit in 'whichqs'
+       sll     v1, v1, t2
+       xor     t3, t3, v1                      # clear bit in 'whichqs'
+       sw      t3, whichqs
+3:
+/*
+ * Switch to new context.
+ * NOTE: This is hard coded to UPAGES == 2.
+ * Also, there should be no TLB faults at this point.
+ */
+       sw      zero, want_resched
+       jal     pmap_alloc_tlbpid               # v0 = TLB PID
+       move    s0, a0                          # BDSLOT: save p
+       sw      s0, curproc                     # set curproc
+       lw      t0, P_UPTE+0(s0)                # t0 = first u. pte
+       lw      t1, P_UPTE+4(s0)                # t1 = 2nd u. pte
+#ifdef R4K     /* ==================XXXXX============================== */
+       or      v0, v0, UADDR                   # v0 = first HI entry
+       mtc0    zero, COP_0_TLB_INDEX           # set the index register
+       dmtc0   v0, COP_0_TLB_HI                # init high entry
+       dmtc0   t0, COP_0_TLB_LO0               # init low entry0
+       dmtc0   t1, COP_0_TLB_LO1               # init low entry1
+       nop
+       tlbwi                                   # Write the TLB entry.
+       nop                                     # Delay for effect
+       nop                                     # Delay for effect
+       nop
+       nop
+#else
+       sll     v0, v0, R3K_PID_SHIFT
+       or      v0, v0, UADDR
+       mtc0    zero, COP_0_TLB_INDEX           # set the index register
+       mtc0    v0, COP_0_TLB_HI                # init high entry
+       mtc0    t0, COP_0_TLB_LO0               # init low entry
+       li      t0, 1 << R3K_TLB_INDEX_SHIFT
+       tlbwi                                   # Write the TLB entry.
+       addu    v0, v0, NBPG                    # 2nd HI entry
+       mtc0    t0, COP_0_TLB_INDEX             # set the index register
+       mtc0    v0, COP_0_TLB_HI                # init high entry
+       mtc0    t1, COP_0_TLB_LO0               # init low entry
+       nop
+       tlbwi                                   # Write the TLB entry.
+#endif         /* ==================XXXXX============================== */
+
+/*
+ * Now running on new u struct.
+ * Restore registers and return.
+ */
+       lw      v0, UADDR+U_PCB_CONTEXT+44      # restore kernel context
+       lw      ra, UADDR+U_PCB_CONTEXT+40
+       lw      s0, UADDR+U_PCB_CONTEXT+0
+       lw      s1, UADDR+U_PCB_CONTEXT+4
+       lw      s2, UADDR+U_PCB_CONTEXT+8
+       lw      s3, UADDR+U_PCB_CONTEXT+12
+       lw      s4, UADDR+U_PCB_CONTEXT+16
+       lw      s5, UADDR+U_PCB_CONTEXT+20
+       lw      s6, UADDR+U_PCB_CONTEXT+24
+       lw      s7, UADDR+U_PCB_CONTEXT+28
+       lw      sp, UADDR+U_PCB_CONTEXT+32
+       lw      s8, UADDR+U_PCB_CONTEXT+36
+       mtc0    v0, COP_0_STATUS_REG
+       j       ra
+       li      v0, 1                           # possible return to 'savectx()'
+END(cpu_switch)
+
+/*
+ * {fu,su},{ibyte,isword,iword}, fetch or store a byte, short or word to
+ * user text space.
+ * {fu,su},{byte,sword,word}, fetch or store a byte, short or word to
+ * user data space.
+ */
+LEAF(fuword)
+ALEAF(fuiword)
+       blt     a0, zero, fswberr       # make sure address is in user space
+       li      v0, FSWBERR
+       sw      v0, UADDR+U_PCB_ONFAULT
+       lw      v0, 0(a0)               # fetch word
+       j       ra
+       sw      zero, UADDR+U_PCB_ONFAULT
+END(fuword)
+
+LEAF(fusword)
+ALEAF(fuisword)
+       blt     a0, zero, fswberr       # make sure address is in user space
+       li      v0, FSWBERR
+       sw      v0, UADDR+U_PCB_ONFAULT
+       lhu     v0, 0(a0)               # fetch short
+       j       ra
+       sw      zero, UADDR+U_PCB_ONFAULT
+END(fusword)
+
+LEAF(fubyte)
+ALEAF(fuibyte)
+       blt     a0, zero, fswberr       # make sure address is in user space
+       li      v0, FSWBERR
+       sw      v0, UADDR+U_PCB_ONFAULT
+       lbu     v0, 0(a0)               # fetch byte
+       j       ra
+       sw      zero, UADDR+U_PCB_ONFAULT
+END(fubyte)
+
+LEAF(suword)
+       blt     a0, zero, fswberr       # make sure address is in user space
+       li      v0, FSWBERR
+       sw      v0, UADDR+U_PCB_ONFAULT
+       sw      a1, 0(a0)               # store word
+       sw      zero, UADDR+U_PCB_ONFAULT
+       j       ra
+       move    v0, zero
+END(suword)
+
+/*
+ * Have to flush instruction cache afterwards.
+ */
+LEAF(suiword)
+       blt     a0, zero, fswberr       # make sure address is in user space
+       li      v0, FSWBERR
+       sw      v0, UADDR+U_PCB_ONFAULT
+       sw      a1, 0(a0)               # store word
+       sw      zero, UADDR+U_PCB_ONFAULT
+#ifdef R4K
+       b       R4K_FlushICache         # FlushICache sets v0 = 0. (Ugly)
+#else
+       b       R3K_FlushICache         # FlushICache sets v0 = 0. (Ugly)
+#endif
+       li      a1, 4                   # size of word
+END(suiword)
+
+/*
+ * Will have to flush the instruction cache if byte merging is done in hardware.
+ */
+LEAF(susword)
+ALEAF(suisword)
+       blt     a0, zero, fswberr       # make sure address is in user space
+       li      v0, FSWBERR
+       sw      v0, UADDR+U_PCB_ONFAULT
+       sh      a1, 0(a0)               # store short
+       sw      zero, UADDR+U_PCB_ONFAULT
+       j       ra
+       move    v0, zero
+END(susword)
+
+LEAF(subyte)
+ALEAF(suibyte)
+       blt     a0, zero, fswberr       # make sure address is in user space
+       li      v0, FSWBERR
+       sw      v0, UADDR+U_PCB_ONFAULT
+       sb      a1, 0(a0)               # store byte
+       sw      zero, UADDR+U_PCB_ONFAULT
+       j       ra
+       move    v0, zero
+END(subyte)
+
+LEAF(fswberr)
+       j       ra
+       li      v0, -1
+END(fswberr)
+
+/*
+ * fuswintr and suswintr are just like fusword and susword except that if
+ * the page is not in memory or would cause a trap, then we return an error.
+ * The important thing is to prevent sleep() and switch().
+ */
+LEAF(fuswintr)
+       blt     a0, zero, fswintrberr   # make sure address is in user space
+       li      v0, FSWINTRBERR
+       sw      v0, UADDR+U_PCB_ONFAULT
+       lhu     v0, 0(a0)               # fetch short
+       j       ra
+       sw      zero, UADDR+U_PCB_ONFAULT
+END(fuswintr)
+
+LEAF(suswintr)
+       blt     a0, zero, fswintrberr   # make sure address is in user space
+       li      v0, FSWINTRBERR
+       sw      v0, UADDR+U_PCB_ONFAULT
+       sh      a1, 0(a0)               # store short
+       sw      zero, UADDR+U_PCB_ONFAULT
+       j       ra
+       move    v0, zero
+END(suswintr)
+
+LEAF(fswintrberr)
+       j       ra
+       li      v0, -1
+END(fswintrberr)
+
+/*
+ * Insert 'p' after 'q'.
+ *     _insque(p, q)
+ *             caddr_t p, q;
+ */
+LEAF(_insque)
+       lw      v0, 0(a1)               # v0 = q->next
+       sw      a1, 4(a0)               # p->prev = q
+       sw      v0, 0(a0)               # p->next = q->next
+       sw      a0, 4(v0)               # q->next->prev = p
+       j       ra
+       sw      a0, 0(a1)               # q->next = p
+END(_insque)
+
+/*
+ * Remove item 'p' from queue.
+ *     _remque(p)
+ *             caddr_t p;
+ */
+LEAF(_remque)
+       lw      v0, 0(a0)               # v0 = p->next
+       lw      v1, 4(a0)               # v1 = p->prev
+       nop
+       sw      v0, 0(v1)               # p->prev->next = p->next
+       j       ra
+       sw      v1, 4(v0)               # p->next->prev = p->prev
+END(_remque)
+
+/*
+ * This code is copied to the TLB exception vector address to
+ * handle TLB translation misses.
+ * NOTE: This code must be relocatable and max 32 instructions!!!
+ * Don't check for invalid pte's here. We load them as well and
+ * let the processor trap to load the correct value after service.
+ */
+#ifdef R4K     /* ==================XXXXX============================== */
+       .globl  R4K_TLBMiss
+R4K_TLBMiss:
+       .set    noat
+       dmfc0   k0, COP_0_BAD_VADDR     # get the virtual address
+       lw      k1, UADDR+U_PCB_SEGTAB          # get the current segment table
+       bltz    k0, 1f                          # kernel address space ->
+       srl     k0, k0, SEGSHIFT - 2            # compute segment table index
+       andi    k0, k0, 0x7fc                   # PMAP_SEGTABSIZ-1
+       addu    k1, k1, k0
+       dmfc0   k0, COP_0_BAD_VADDR     # get the virtual address
+       lw      k1, 0(k1)                       # get pointer to segment map
+       srl     k0, k0, PGSHIFT - 2             # compute segment map index
+       andi    k0, k0, ((NPTEPG/2) - 1) << 3
+       beq     k1, zero, 2f                    # invalid segment map
+       addu    k1, k1, k0                      # index into segment map
+       lw      k0, 0(k1)                       # get page PTE
+       lw      k1, 4(k1)
+       dsll    k0, k0, 34
+       dsrl    k0, k0, 34
+       dmtc0   k0, COP_0_TLB_LO0
+       dsll    k1, k1, 34
+       dsrl    k1, k1, 34
+       dmtc0   k1, COP_0_TLB_LO1
+       nop
+       tlbwr                                   # update TLB
+       nop
+       nop
+       nop
+       nop
+       nop
+       eret
+1:
+       j       R4K_TLBMissException
+       nop
+2:
+       j       SlowFault
+       nop
+
+       .globl  R4K_TLBMissEnd
+R4K_TLBMissEnd:
+       .set    at
+
+/*
+ * This code is copied to the general exception vector address to
+ * handle all execptions except RESET and TLBMiss.
+ * NOTE: This code must be relocatable!!!
+ */
+       .globl  R4K_Exception
+R4K_Exception:
+/*
+ * Find out what mode we came from and jump to the proper handler.
+ */
+       .set    noat
+       mfc0    k0, COP_0_STATUS_REG    # Get the status register
+       mfc0    k1, COP_0_CAUSE_REG     # Get the cause register value.
+       and     k0, k0, SR_KSU_USER     # test for user mode
+                                               # sneaky but the bits are
+                                               # with us........
+       sll     k0, k0, 3                       # shift user bit for cause index
+       and     k1, k1, CR_EXC_CODE     # Mask out the cause bits.
+       or      k1, k1, k0                      # change index to user table
+1:
+       la      k0, R4K_ExceptionTable          # get base of the jump table
+       addu    k0, k0, k1                      # Get the address of the
+                                               #  function entry.  Note that
+                                               #  the cause is already
+                                               #  shifted left by 2 bits so
+                                               #  we dont have to shift.
+       lw      k0, 0(k0)                       # Get the function address
+       nop
+       j       k0                              # Jump to the function.
+       nop
+       .set    at
+       .globl  R4K_ExceptionEnd
+R4K_ExceptionEnd:
+
+/*
+ * We couldn't find a TLB entry.
+ * Find out what mode we came from and call the appropriate handler.
+ */
+SlowFault:
+       .set    noat
+       mfc0    k0, COP_0_STATUS_REG
+       nop
+       and     k0, k0, SR_KSU_USER
+       bne     k0, zero, R4K_UserGenException
+       nop
+       .set    at
+/*
+ * Fall though ...
+ */
+
+/*----------------------------------------------------------------------------
+ *
+ * R4K_KernGenException --
+ *
+ *     Handle an exception from kernel mode.
+ *
+ * Results:
+ *     None.
+ *
+ * Side effects:
+ *     None.
+ *
+ *----------------------------------------------------------------------------
+ */
+
+/*
+ * The kernel exception stack contains 18 saved general registers,
+ * the status register and the multiply lo and high registers.
+ * In addition, we set this up for linkage conventions.
+ */
+#define KERN_REG_SIZE          (18 * 4)
+#define KERN_REG_OFFSET                (STAND_FRAME_SIZE)
+#define KERN_SR_OFFSET         (STAND_FRAME_SIZE + KERN_REG_SIZE)
+#define KERN_MULT_LO_OFFSET    (STAND_FRAME_SIZE + KERN_REG_SIZE + 4)
+#define KERN_MULT_HI_OFFSET    (STAND_FRAME_SIZE + KERN_REG_SIZE + 8)
+#define        KERN_EXC_FRAME_SIZE     (STAND_FRAME_SIZE + KERN_REG_SIZE + 12)
+
+NNON_LEAF(R4K_KernGenException, KERN_EXC_FRAME_SIZE, ra)
+       .set    noat
+#ifdef DEBUG
+       la      k0, mdbpcb                      # save registers for mdb
+       sw      s0, (S0 * 4)(k0)
+       sw      s1, (S1 * 4)(k0)
+       sw      s2, (S2 * 4)(k0)
+       sw      s3, (S3 * 4)(k0)
+       sw      s4, (S4 * 4)(k0)
+       sw      s5, (S5 * 4)(k0)
+       sw      s6, (S6 * 4)(k0)
+       sw      s7, (S7 * 4)(k0)
+       sw      s8, (S8 * 4)(k0)
+       sw      gp, (GP * 4)(k0)
+       sw      sp, (SP * 4)(k0)
+#endif
+       subu    sp, sp, KERN_EXC_FRAME_SIZE
+       .mask   0x80000000, (STAND_RA_OFFSET - KERN_EXC_FRAME_SIZE)
+/*
+ * Save the relevant kernel registers onto the stack.
+ * We don't need to save s0 - s8, sp and gp because
+ * the compiler does it for us.
+ */
+       sw      AT, KERN_REG_OFFSET + 0(sp)
+       sw      v0, KERN_REG_OFFSET + 4(sp)
+       sw      v1, KERN_REG_OFFSET + 8(sp)
+       sw      a0, KERN_REG_OFFSET + 12(sp)
+       mflo    v0
+       mfhi    v1
+       sw      a1, KERN_REG_OFFSET + 16(sp)
+       sw      a2, KERN_REG_OFFSET + 20(sp)
+       sw      a3, KERN_REG_OFFSET + 24(sp)
+       sw      t0, KERN_REG_OFFSET + 28(sp)
+       mfc0    a0, COP_0_STATUS_REG    # First arg is the status reg.
+       sw      t1, KERN_REG_OFFSET + 32(sp)
+       sw      t2, KERN_REG_OFFSET + 36(sp)
+       sw      t3, KERN_REG_OFFSET + 40(sp)
+       sw      t4, KERN_REG_OFFSET + 44(sp)
+       mfc0    a1, COP_0_CAUSE_REG     # Second arg is the cause reg.
+       sw      t5, KERN_REG_OFFSET + 48(sp)
+       sw      t6, KERN_REG_OFFSET + 52(sp)
+       sw      t7, KERN_REG_OFFSET + 56(sp)
+       sw      t8, KERN_REG_OFFSET + 60(sp)
+       mfc0    a2, COP_0_BAD_VADDR     # Third arg is the fault addr.
+       sw      t9, KERN_REG_OFFSET + 64(sp)
+       sw      ra, KERN_REG_OFFSET + 68(sp)
+       sw      v0, KERN_MULT_LO_OFFSET(sp)
+       sw      v1, KERN_MULT_HI_OFFSET(sp)
+       mfc0    a3, COP_0_EXC_PC                # Fourth arg is the pc.
+       sw      a0, KERN_SR_OFFSET(sp)
+
+       mtc0    zero,COP_0_STATUS_REG   # Set kernel no error level
+/*
+ * Call the exception handler.
+ */
+       jal     trap
+       sw      a3, STAND_RA_OFFSET(sp)         # for debugging
+/*
+ * Restore registers and return from the exception.
+ * v0 contains the return address.
+ */
+       mtc0    zero,COP_0_STATUS_REG   # Make shure int disabled
+       lw      a0, KERN_SR_OFFSET(sp)
+       lw      t0, KERN_MULT_LO_OFFSET(sp)
+       lw      t1, KERN_MULT_HI_OFFSET(sp)
+       mtc0    a0, COP_0_STATUS_REG    # Restore the SR, disable intrs
+       mtlo    t0
+       mthi    t1
+       dmtc0   v0, COP_0_EXC_PC                # set return address
+       lw      AT, KERN_REG_OFFSET + 0(sp)
+       lw      v0, KERN_REG_OFFSET + 4(sp)
+       lw      v1, KERN_REG_OFFSET + 8(sp)
+       lw      a0, KERN_REG_OFFSET + 12(sp)
+       lw      a1, KERN_REG_OFFSET + 16(sp)
+       lw      a2, KERN_REG_OFFSET + 20(sp)
+       lw      a3, KERN_REG_OFFSET + 24(sp)
+       lw      t0, KERN_REG_OFFSET + 28(sp)
+       lw      t1, KERN_REG_OFFSET + 32(sp)
+       lw      t2, KERN_REG_OFFSET + 36(sp)
+       lw      t3, KERN_REG_OFFSET + 40(sp)
+       lw      t4, KERN_REG_OFFSET + 44(sp)
+       lw      t5, KERN_REG_OFFSET + 48(sp)
+       lw      t6, KERN_REG_OFFSET + 52(sp)
+       lw      t7, KERN_REG_OFFSET + 56(sp)
+       lw      t8, KERN_REG_OFFSET + 60(sp)
+       lw      t9, KERN_REG_OFFSET + 64(sp)
+       lw      ra, KERN_REG_OFFSET + 68(sp)
+       addu    sp, sp, KERN_EXC_FRAME_SIZE
+       eret                                    #  exception.
+       .set    at
+END(R4K_KernGenException)
+
+/*----------------------------------------------------------------------------
+ *
+ * R4K_UserGenException --
+ *
+ *     Handle an exception from user mode.
+ *
+ * Results:
+ *     None.
+ *
+ * Side effects:
+ *     None.
+ *
+ *----------------------------------------------------------------------------
+ */
+NNON_LEAF(R4K_UserGenException, STAND_FRAME_SIZE, ra)
+       .set    noat
+       .mask   0x80000000, (STAND_RA_OFFSET - STAND_FRAME_SIZE)
+/*
+ * Save all of the registers except for the kernel temporaries in u.u_pcb.
+ */
+       sw      AT, UADDR+U_PCB_REGS+(AST * 4)
+       sw      v0, UADDR+U_PCB_REGS+(V0 * 4)
+       sw      v1, UADDR+U_PCB_REGS+(V1 * 4)
+       sw      a0, UADDR+U_PCB_REGS+(A0 * 4)
+       mflo    v0
+       sw      a1, UADDR+U_PCB_REGS+(A1 * 4)
+       sw      a2, UADDR+U_PCB_REGS+(A2 * 4)
+       sw      a3, UADDR+U_PCB_REGS+(A3 * 4)
+       sw      t0, UADDR+U_PCB_REGS+(T0 * 4)
+       mfhi    v1
+       sw      t1, UADDR+U_PCB_REGS+(T1 * 4)
+       sw      t2, UADDR+U_PCB_REGS+(T2 * 4)
+       sw      t3, UADDR+U_PCB_REGS+(T3 * 4)
+       sw      t4, UADDR+U_PCB_REGS+(T4 * 4)
+       mfc0    a0, COP_0_STATUS_REG    # First arg is the status reg.
+       sw      t5, UADDR+U_PCB_REGS+(T5 * 4)
+       sw      t6, UADDR+U_PCB_REGS+(T6 * 4)
+       sw      t7, UADDR+U_PCB_REGS+(T7 * 4)
+       sw      s0, UADDR+U_PCB_REGS+(S0 * 4)
+       mfc0    a1, COP_0_CAUSE_REG     # Second arg is the cause reg.
+       sw      s1, UADDR+U_PCB_REGS+(S1 * 4)
+       sw      s2, UADDR+U_PCB_REGS+(S2 * 4)
+       sw      s3, UADDR+U_PCB_REGS+(S3 * 4)
+       sw      s4, UADDR+U_PCB_REGS+(S4 * 4)
+       mfc0    a2, COP_0_BAD_VADDR     # Third arg is the fault addr
+       sw      s5, UADDR+U_PCB_REGS+(S5 * 4)
+       sw      s6, UADDR+U_PCB_REGS+(S6 * 4)
+       sw      s7, UADDR+U_PCB_REGS+(S7 * 4)
+       sw      t8, UADDR+U_PCB_REGS+(T8 * 4)
+       mfc0    a3, COP_0_EXC_PC                # Fourth arg is the pc.
+       sw      t9, UADDR+U_PCB_REGS+(T9 * 4)
+       sw      gp, UADDR+U_PCB_REGS+(GP * 4)
+       sw      sp, UADDR+U_PCB_REGS+(SP * 4)
+       sw      s8, UADDR+U_PCB_REGS+(S8 * 4)
+       li      sp, KERNELSTACK - STAND_FRAME_SIZE      # switch to kernel SP
+       sw      ra, UADDR+U_PCB_REGS+(RA * 4)
+       sw      v0, UADDR+U_PCB_REGS+(MULLO * 4)
+       sw      v1, UADDR+U_PCB_REGS+(MULHI * 4)
+       sw      a0, UADDR+U_PCB_REGS+(SR * 4)
+       la      gp, _gp                         # switch to kernel GP
+       sw      a3, UADDR+U_PCB_REGS+(PC * 4)
+       sw      a3, STAND_RA_OFFSET(sp)         # for debugging
+       .set    at
+# Turn off fpu and enter kernel mode
+       and     t0, a0, ~(SR_COP_1_BIT | SR_EXL | SR_KSU_MASK | SR_INT_ENAB)
+       .set    noat
+/*
+ * Call the exception handler.
+ */
+       jal     trap
+       mtc0    t0, COP_0_STATUS_REG
+/*
+ * Restore user registers and return.
+ * First disable interrupts and set exeption level.
+ */
+       mtc0    zero, COP_0_STATUS_REG  # disable int
+       nop
+       nop
+       nop
+       li      v0, SR_EXL
+       mtc0    v0, COP_0_STATUS_REG    # set exeption level
+
+       lw      a0, UADDR+U_PCB_REGS+(SR * 4)
+       lw      t0, UADDR+U_PCB_REGS+(MULLO * 4)
+       lw      t1, UADDR+U_PCB_REGS+(MULHI * 4)
+       mtc0    a0, COP_0_STATUS_REG    # still exeption level
+       mtlo    t0
+       mthi    t1
+       lw      a0, UADDR+U_PCB_REGS+(PC * 4)
+       lw      AT, UADDR+U_PCB_REGS+(AST * 4)
+       lw      v0, UADDR+U_PCB_REGS+(V0 * 4)
+       dmtc0   a0, COP_0_EXC_PC                # set return address
+       lw      v1, UADDR+U_PCB_REGS+(V1 * 4)
+       lw      a0, UADDR+U_PCB_REGS+(A0 * 4)
+       lw      a1, UADDR+U_PCB_REGS+(A1 * 4)
+       lw      a2, UADDR+U_PCB_REGS+(A2 * 4)
+       lw      a3, UADDR+U_PCB_REGS+(A3 * 4)
+       lw      t0, UADDR+U_PCB_REGS+(T0 * 4)
+       lw      t1, UADDR+U_PCB_REGS+(T1 * 4)
+       lw      t2, UADDR+U_PCB_REGS+(T2 * 4)
+       lw      t3, UADDR+U_PCB_REGS+(T3 * 4)
+       lw      t4, UADDR+U_PCB_REGS+(T4 * 4)
+       lw      t5, UADDR+U_PCB_REGS+(T5 * 4)
+       lw      t6, UADDR+U_PCB_REGS+(T6 * 4)
+       lw      t7, UADDR+U_PCB_REGS+(T7 * 4)
+       lw      s0, UADDR+U_PCB_REGS+(S0 * 4)
+       lw      s1, UADDR+U_PCB_REGS+(S1 * 4)
+       lw      s2, UADDR+U_PCB_REGS+(S2 * 4)
+       lw      s3, UADDR+U_PCB_REGS+(S3 * 4)
+       lw      s4, UADDR+U_PCB_REGS+(S4 * 4)
+       lw      s5, UADDR+U_PCB_REGS+(S5 * 4)
+       lw      s6, UADDR+U_PCB_REGS+(S6 * 4)
+       lw      s7, UADDR+U_PCB_REGS+(S7 * 4)
+       lw      t8, UADDR+U_PCB_REGS+(T8 * 4)
+       lw      t9, UADDR+U_PCB_REGS+(T9 * 4)
+       lw      gp, UADDR+U_PCB_REGS+(GP * 4)
+       lw      sp, UADDR+U_PCB_REGS+(SP * 4)
+       lw      s8, UADDR+U_PCB_REGS+(S8 * 4)
+       lw      ra, UADDR+U_PCB_REGS+(RA * 4)
+       eret
+       .set    at
+END(R4K_UserGenException)
+
+/*----------------------------------------------------------------------------
+ *
+ * R4K_KernIntr --
+ *
+ *     Handle an interrupt from kernel mode.
+ *     Interrupts use the standard kernel stack.
+ *     switch_exit sets up a kernel stack after exit so interrupts won't fail.
+ *
+ * Results:
+ *     None.
+ *
+ * Side effects:
+ *     None.
+ *
+ *----------------------------------------------------------------------------
+ */
+#define KINTR_REG_OFFSET       (STAND_FRAME_SIZE)
+#define KINTR_SR_OFFSET                (STAND_FRAME_SIZE + KERN_REG_SIZE)
+#define KINTR_MULT_LO_OFFSET   (STAND_FRAME_SIZE + KERN_REG_SIZE + 4)
+#define KINTR_MULT_HI_OFFSET   (STAND_FRAME_SIZE + KERN_REG_SIZE + 8)
+#define KINTR_MULT_GP_OFFSET   (STAND_FRAME_SIZE + KERN_REG_SIZE + 12)
+#define        KINTR_FRAME_SIZE        (STAND_FRAME_SIZE + KERN_REG_SIZE + 16)
+
+NNON_LEAF(R4K_KernIntr, KINTR_FRAME_SIZE, ra)
+       .set    noat
+       subu    sp, sp, KINTR_FRAME_SIZE        # allocate stack frame
+       .mask   0x80000000, (STAND_RA_OFFSET - KINTR_FRAME_SIZE)
+/*
+ * Save the relevant kernel registers onto the stack.
+ * We don't need to save s0 - s8, sp and gp because
+ * the compiler does it for us.
+ */
+       sw      AT, KINTR_REG_OFFSET + 0(sp)
+       sw      v0, KINTR_REG_OFFSET + 4(sp)
+       sw      v1, KINTR_REG_OFFSET + 8(sp)
+       sw      a0, KINTR_REG_OFFSET + 12(sp)
+       mflo    v0
+       mfhi    v1
+       sw      a1, KINTR_REG_OFFSET + 16(sp)
+       sw      a2, KINTR_REG_OFFSET + 20(sp)
+       sw      a3, KINTR_REG_OFFSET + 24(sp)
+       sw      t0, KINTR_REG_OFFSET + 28(sp)
+       mfc0    a0, COP_0_STATUS_REG    # First arg is the status reg.
+       sw      t1, KINTR_REG_OFFSET + 32(sp)
+       sw      t2, KINTR_REG_OFFSET + 36(sp)
+       sw      t3, KINTR_REG_OFFSET + 40(sp)
+       sw      t4, KINTR_REG_OFFSET + 44(sp)
+       mfc0    a1, COP_0_CAUSE_REG     # Second arg is the cause reg.
+       sw      t5, KINTR_REG_OFFSET + 48(sp)
+       sw      t6, KINTR_REG_OFFSET + 52(sp)
+       sw      t7, KINTR_REG_OFFSET + 56(sp)
+       sw      t8, KINTR_REG_OFFSET + 60(sp)
+       mfc0    a2, COP_0_EXC_PC                # Third arg is the pc.
+       sw      t9, KINTR_REG_OFFSET + 64(sp)
+       sw      ra, KINTR_REG_OFFSET + 68(sp)
+       sw      v0, KINTR_MULT_LO_OFFSET(sp)
+       sw      v1, KINTR_MULT_HI_OFFSET(sp)
+       sw      a0, KINTR_SR_OFFSET(sp)
+
+       mtc0    zero, COP_0_STATUS_REG  # Reset exl, trap possible.
+/*
+ * Call the interrupt handler.
+ */
+       jal     interrupt
+       sw      a2, STAND_RA_OFFSET(sp)         # for debugging
+/*
+ * Restore registers and return from the interrupt.
+ */
+       mtc0    zero, COP_0_STATUS_REG  # Disable interrupt
+       lw      a0, KINTR_SR_OFFSET(sp)
+       lw      t0, KINTR_MULT_LO_OFFSET(sp)
+       lw      t1, KINTR_MULT_HI_OFFSET(sp)
+       mtc0    a0, COP_0_STATUS_REG    # Restore the SR, disable intrs
+       mtlo    t0
+       mthi    t1
+       lw      a0, STAND_RA_OFFSET(sp)
+       lw      AT, KINTR_REG_OFFSET + 0(sp)
+       lw      v0, KINTR_REG_OFFSET + 4(sp)
+       dmtc0   a0, COP_0_EXC_PC                # set return address
+       lw      v1, KINTR_REG_OFFSET + 8(sp)
+       lw      a0, KINTR_REG_OFFSET + 12(sp)
+       lw      a1, KINTR_REG_OFFSET + 16(sp)
+       lw      a2, KINTR_REG_OFFSET + 20(sp)
+       lw      a3, KINTR_REG_OFFSET + 24(sp)
+       lw      t0, KINTR_REG_OFFSET + 28(sp)
+       lw      t1, KINTR_REG_OFFSET + 32(sp)
+       lw      t2, KINTR_REG_OFFSET + 36(sp)
+       lw      t3, KINTR_REG_OFFSET + 40(sp)
+       lw      t4, KINTR_REG_OFFSET + 44(sp)
+       lw      t5, KINTR_REG_OFFSET + 48(sp)
+       lw      t6, KINTR_REG_OFFSET + 52(sp)
+       lw      t7, KINTR_REG_OFFSET + 56(sp)
+       lw      t8, KINTR_REG_OFFSET + 60(sp)
+       lw      t9, KINTR_REG_OFFSET + 64(sp)
+       lw      ra, KINTR_REG_OFFSET + 68(sp)
+       addu    sp, sp, KINTR_FRAME_SIZE
+       eret                                    #  interrupt.
+       .set    at
+END(R4K_KernIntr)
+
+/*----------------------------------------------------------------------------
+ *
+ * R4K_UserIntr --
+ *
+ *     Handle an interrupt from user mode.
+ *     Note: we save minimal state in the u.u_pcb struct and use the standard
+ *     kernel stack since there has to be a u page if we came from user mode.
+ *     If there is a pending software interrupt, then save the remaining state
+ *     and call softintr(). This is all because if we call switch() inside
+ *     interrupt(), not all the user registers have been saved in u.u_pcb.
+ *
+ * Results:
+ *     None.
+ *
+ * Side effects:
+ *     None.
+ *
+ *----------------------------------------------------------------------------
+ */
+NNON_LEAF(R4K_UserIntr, STAND_FRAME_SIZE, ra)
+       .set    noat
+       .mask   0x80000000, (STAND_RA_OFFSET - STAND_FRAME_SIZE)
+/*
+ * Save the relevant user registers into the u.u_pcb struct.
+ * We don't need to save s0 - s8 because
+ * the compiler does it for us.
+ */
+       sw      AT, UADDR+U_PCB_REGS+(AST * 4)
+       sw      v0, UADDR+U_PCB_REGS+(V0 * 4)
+       sw      v1, UADDR+U_PCB_REGS+(V1 * 4)
+       sw      a0, UADDR+U_PCB_REGS+(A0 * 4)
+       mflo    v0
+       mfhi    v1
+       sw      a1, UADDR+U_PCB_REGS+(A1 * 4)
+       sw      a2, UADDR+U_PCB_REGS+(A2 * 4)
+       sw      a3, UADDR+U_PCB_REGS+(A3 * 4)
+       sw      t0, UADDR+U_PCB_REGS+(T0 * 4)
+       mfc0    a0, COP_0_STATUS_REG    # First arg is the status reg.
+       sw      t1, UADDR+U_PCB_REGS+(T1 * 4)
+       sw      t2, UADDR+U_PCB_REGS+(T2 * 4)
+       sw      t3, UADDR+U_PCB_REGS+(T3 * 4)
+       sw      t4, UADDR+U_PCB_REGS+(T4 * 4)
+       mfc0    a1, COP_0_CAUSE_REG     # Second arg is the cause reg.
+       sw      t5, UADDR+U_PCB_REGS+(T5 * 4)
+       sw      t6, UADDR+U_PCB_REGS+(T6 * 4)
+       sw      t7, UADDR+U_PCB_REGS+(T7 * 4)
+       sw      t8, UADDR+U_PCB_REGS+(T8 * 4)
+       mfc0    a2, COP_0_EXC_PC                # Third arg is the pc.
+       sw      t9, UADDR+U_PCB_REGS+(T9 * 4)
+       sw      gp, UADDR+U_PCB_REGS+(GP * 4)
+       sw      sp, UADDR+U_PCB_REGS+(SP * 4)
+       sw      ra, UADDR+U_PCB_REGS+(RA * 4)
+       li      sp, KERNELSTACK - STAND_FRAME_SIZE      # switch to kernel SP
+       sw      v0, UADDR+U_PCB_REGS+(MULLO * 4)
+       sw      v1, UADDR+U_PCB_REGS+(MULHI * 4)
+       sw      a0, UADDR+U_PCB_REGS+(SR * 4)
+       sw      a2, UADDR+U_PCB_REGS+(PC * 4)
+       la      gp, _gp                         # switch to kernel GP
+# Turn off fpu and enter kernel mode
+       .set    at
+       and     t0, a0, ~(SR_COP_1_BIT | SR_EXL | SR_INT_ENAB | SR_KSU_MASK)
+       .set    noat
+       mtc0    t0, COP_0_STATUS_REG
+/*
+ * Call the interrupt handler.
+ */
+       jal     interrupt
+       sw      a2, STAND_RA_OFFSET(sp)         # for debugging
+/*
+ * Restore registers and return from the interrupt.
+ */
+       mtc0    zero, COP_0_STATUS_REG
+       nop
+       nop
+       nop
+       li      v0, SR_EXL
+       mtc0    v0, COP_0_STATUS_REG    # set exeption level bit.
+
+       lw      a0, UADDR+U_PCB_REGS+(SR * 4)
+       lw      v0, astpending                  # any pending interrupts?
+       mtc0    a0, COP_0_STATUS_REG    # Restore the SR, disable intrs
+       bne     v0, zero, 1f                    # dont restore, call softintr
+       lw      t0, UADDR+U_PCB_REGS+(MULLO * 4)
+       lw      t1, UADDR+U_PCB_REGS+(MULHI * 4)
+       lw      a0, UADDR+U_PCB_REGS+(PC * 4)
+       lw      AT, UADDR+U_PCB_REGS+(AST * 4)
+       lw      v0, UADDR+U_PCB_REGS+(V0 * 4)
+       dmtc0   a0, COP_0_EXC_PC                # set return address
+       lw      v1, UADDR+U_PCB_REGS+(V1 * 4)
+       lw      a0, UADDR+U_PCB_REGS+(A0 * 4)
+       lw      a1, UADDR+U_PCB_REGS+(A1 * 4)
+       lw      a2, UADDR+U_PCB_REGS+(A2 * 4)
+       lw      a3, UADDR+U_PCB_REGS+(A3 * 4)
+       mtlo    t0
+       mthi    t1
+       lw      t0, UADDR+U_PCB_REGS+(T0 * 4)
+       lw      t1, UADDR+U_PCB_REGS+(T1 * 4)
+       lw      t2, UADDR+U_PCB_REGS+(T2 * 4)
+       lw      t3, UADDR+U_PCB_REGS+(T3 * 4)
+       lw      t4, UADDR+U_PCB_REGS+(T4 * 4)
+       lw      t5, UADDR+U_PCB_REGS+(T5 * 4)
+       lw      t6, UADDR+U_PCB_REGS+(T6 * 4)
+       lw      t7, UADDR+U_PCB_REGS+(T7 * 4)
+       lw      t8, UADDR+U_PCB_REGS+(T8 * 4)
+       lw      t9, UADDR+U_PCB_REGS+(T9 * 4)
+       lw      gp, UADDR+U_PCB_REGS+(GP * 4)
+       lw      sp, UADDR+U_PCB_REGS+(SP * 4)
+       lw      ra, UADDR+U_PCB_REGS+(RA * 4)
+       eret                                    #  interrupt.
+
+1:
+/*
+ * We have pending software interrupts; save remaining user state in u.u_pcb.
+ */
+       sw      s0, UADDR+U_PCB_REGS+(S0 * 4)
+       sw      s1, UADDR+U_PCB_REGS+(S1 * 4)
+       sw      s2, UADDR+U_PCB_REGS+(S2 * 4)
+       sw      s3, UADDR+U_PCB_REGS+(S3 * 4)
+       sw      s4, UADDR+U_PCB_REGS+(S4 * 4)
+       sw      s5, UADDR+U_PCB_REGS+(S5 * 4)
+       sw      s6, UADDR+U_PCB_REGS+(S6 * 4)
+       sw      s7, UADDR+U_PCB_REGS+(S7 * 4)
+       sw      s8, UADDR+U_PCB_REGS+(S8 * 4)
+       li      t0, HARD_INT_MASK | SR_INT_ENAB
+/*
+ * Call the software interrupt handler.
+ */
+       jal     softintr
+       mtc0    t0, COP_0_STATUS_REG    # enable interrupts (spl0)
+/*
+ * Restore user registers and return. NOTE: interrupts are enabled.
+ */
+       mtc0    zero, COP_0_STATUS_REG
+       nop
+       nop
+       nop
+       li      v0, SR_EXL
+       mtc0    v0, COP_0_STATUS_REG    # set exeption level bit.
+
+       lw      a0, UADDR+U_PCB_REGS+(SR * 4)
+       lw      t0, UADDR+U_PCB_REGS+(MULLO * 4)
+       lw      t1, UADDR+U_PCB_REGS+(MULHI * 4)
+       mtc0    a0, COP_0_STATUS_REG    # this should disable interrupts
+       mtlo    t0
+       mthi    t1
+       lw      a0, UADDR+U_PCB_REGS+(PC * 4)
+       lw      AT, UADDR+U_PCB_REGS+(AST * 4)
+       lw      v0, UADDR+U_PCB_REGS+(V0 * 4)
+       dmtc0   a0, COP_0_EXC_PC                # set return address
+       lw      v1, UADDR+U_PCB_REGS+(V1 * 4)
+       lw      a0, UADDR+U_PCB_REGS+(A0 * 4)
+       lw      a1, UADDR+U_PCB_REGS+(A1 * 4)
+       lw      a2, UADDR+U_PCB_REGS+(A2 * 4)
+       lw      a3, UADDR+U_PCB_REGS+(A3 * 4)
+       lw      t0, UADDR+U_PCB_REGS+(T0 * 4)
+       lw      t1, UADDR+U_PCB_REGS+(T1 * 4)
+       lw      t2, UADDR+U_PCB_REGS+(T2 * 4)
+       lw      t3, UADDR+U_PCB_REGS+(T3 * 4)
+       lw      t4, UADDR+U_PCB_REGS+(T4 * 4)
+       lw      t5, UADDR+U_PCB_REGS+(T5 * 4)
+       lw      t6, UADDR+U_PCB_REGS+(T6 * 4)
+       lw      t7, UADDR+U_PCB_REGS+(T7 * 4)
+       lw      s0, UADDR+U_PCB_REGS+(S0 * 4)
+       lw      s1, UADDR+U_PCB_REGS+(S1 * 4)
+       lw      s2, UADDR+U_PCB_REGS+(S2 * 4)
+       lw      s3, UADDR+U_PCB_REGS+(S3 * 4)
+       lw      s4, UADDR+U_PCB_REGS+(S4 * 4)
+       lw      s5, UADDR+U_PCB_REGS+(S5 * 4)
+       lw      s6, UADDR+U_PCB_REGS+(S6 * 4)
+       lw      s7, UADDR+U_PCB_REGS+(S7 * 4)
+       lw      t8, UADDR+U_PCB_REGS+(T8 * 4)
+       lw      t9, UADDR+U_PCB_REGS+(T9 * 4)
+       lw      gp, UADDR+U_PCB_REGS+(GP * 4)
+       lw      sp, UADDR+U_PCB_REGS+(SP * 4)
+       lw      s8, UADDR+U_PCB_REGS+(S8 * 4)
+       lw      ra, UADDR+U_PCB_REGS+(RA * 4)
+       eret
+       .set    at
+END(R4K_UserIntr)
+
+/*----------------------------------------------------------------------------
+ *
+ * R4K_TLBInvalidException --
+ *
+ *     Handle a TLB invalid exception from kernel mode in kernel space.
+ *     The BaddVAddr, Context, and EntryHi registers contain the failed
+ *     virtual address.
+ *
+ * Results:
+ *     None.
+ *
+ * Side effects:
+ *     None.
+ *
+ *----------------------------------------------------------------------------
+ */
+NLEAF(R4K_TLBInvalidException)
+       .set    noat
+       dmfc0   k0, COP_0_BAD_VADDR     # get the fault address
+       li      k1, VM_MIN_KERNEL_ADDRESS       # compute index
+       subu    k0, k0, k1
+       lw      k1, Sysmapsize                  # index within range?
+       srl     k0, k0, PGSHIFT
+       sltu    k1, k0, k1
+       beq     k1, zero, sys_stk_chk           # No. check for valid stack
+       lw      k1, Sysmap
+
+       sll     k0, k0, 2                       # compute offset from index
+       tlbp                                    # Probe the invalid entry
+       addu    k1, k1, k0
+       and     k0, k0, 4                       # check even/odd page
+       bne     k0, zero, KernTLBIOdd
+       nop
+
+       mfc0    k0, COP_0_TLB_INDEX
+       nop
+       bltz    k0, sys_stk_chk
+       sltiu   k0, k0, 8
+
+       bne     k0, zero, sys_stk_chk
+       lw      k0, 0(k1)                       # get PTE entry
+
+       dsll    k0, k0, 34                      # get rid of "wired" bit
+       dsrl    k0, k0, 34
+       dmtc0   k0, COP_0_TLB_LO0               # load PTE entry
+       and     k0, k0, PG_V                    # check for valid entry
+       beq     k0, zero, R4K_KernGenException  # PTE invalid
+       lw      k0, 4(k1)                       # get odd PTE entry
+       dsll    k0, k0, 34
+       dsrl    k0, k0, 34
+       dmtc0   k0, COP_0_TLB_LO1               # load PTE entry
+       nop
+       tlbwi                                   # write TLB
+       nop
+       nop
+       nop
+       nop
+       nop
+       eret
+
+KernTLBIOdd:
+       mfc0    k0, COP_0_TLB_INDEX
+       nop
+       bltz    k0, sys_stk_chk
+       sltiu   k0, k0, 8
+
+       bne     k0, zero, sys_stk_chk
+       lw      k0, 0(k1)                       # get PTE entry
+
+       dsll    k0, k0, 34                      # get rid of wired bit
+       dsrl    k0, k0, 34
+       dmtc0   k0, COP_0_TLB_LO1               # save PTE entry
+       and     k0, k0, PG_V                    # check for valid entry
+       beq     k0, zero, R4K_KernGenException  # PTE invalid
+       lw      k0, -4(k1)                      # get even PTE entry
+       dsll    k0, k0, 34
+       dsrl    k0, k0, 34
+       dmtc0   k0, COP_0_TLB_LO0               # save PTE entry
+       nop
+       tlbwi                                   # update TLB
+       nop
+       nop
+       nop
+       nop
+       nop
+       eret
+END(R4K_TLBInvalidException)
+
+/*----------------------------------------------------------------------------
+ *
+ * R4K_TLBMissException --
+ *
+ *     Handle a TLB miss exception from kernel mode in kernel space.
+ *     The BaddVAddr, Context, and EntryHi registers contain the failed
+ *     virtual address.
+ *
+ * Results:
+ *     None.
+ *
+ * Side effects:
+ *     None.
+ *
+ *----------------------------------------------------------------------------
+ */
+NLEAF(R4K_TLBMissException)
+       .set    noat
+       dmfc0   k0, COP_0_BAD_VADDR     # get the fault address
+       li      k1, VM_MIN_KERNEL_ADDRESS       # compute index
+       subu    k0, k0, k1
+       lw      k1, Sysmapsize                  # index within range?
+       srl     k0, k0, PGSHIFT
+       sltu    k1, k0, k1
+       beq     k1, zero, sys_stk_chk           # No. check for valid stack
+       lw      k1, Sysmap
+       srl     k0, k0, 1
+       sll     k0, k0, 3                       # compute offset from index
+       addu    k1, k1, k0
+       lw      k0, 0(k1)                       # get PTE entry
+       lw      k1, 4(k1)                       # get odd PTE entry
+       dsll    k0, k0, 34                      # get rid of "wired" bit
+       dsrl    k0, k0, 34
+       dmtc0   k0, COP_0_TLB_LO0               # load PTE entry
+       dsll    k1, k1, 34
+       dsrl    k1, k1, 34
+       dmtc0   k1, COP_0_TLB_LO1               # load PTE entry
+       nop
+       tlbwr                                   # write TLB
+       nop
+       nop
+       nop
+       nop
+       nop
+       eret
+
+sys_stk_chk:
+       subu    k0, sp, UADDR + 0x200           # check to see if we have a
+       sltiu   k0, UPAGES*NBPG - 0x200         #  valid kernel stack
+       bne     k0, zero, R4K_KernGenException  # Go panic
+       nop
+
+       la      a0, start - START_FRAME - 8     # set sp to a valid place
+       sw      sp, 24(a0)
+       move    sp, a0
+       la      a0, 1f
+       mfc0    a2, COP_0_STATUS_REG
+       mfc0    a3, COP_0_CAUSE_REG
+       dmfc0   a1, COP_0_EXC_PC
+       sw      a2, 16(sp)
+       sw      a3, 20(sp)
+       move    a2, ra
+       jal     printf
+       dmfc0   a3, COP_0_BAD_VADDR
+       .data
+1:
+       .asciiz "ktlbmiss: PC %x RA %x ADR %x\nSR %x CR %x SP %x\n"
+       .text
+
+       la      sp, start - START_FRAME         # set sp to a valid place
+       PANIC("kernel stack overflow")
+       .set    at
+END(R4K_TLBMissException)
+
+/*----------------------------------------------------------------------------
+ *
+ * wbflush --
+ *
+ *     Return when the write buffer is empty.
+ *
+ *     wbflush()
+ *
+ * Results:
+ *     None.
+ *
+ * Side effects:
+ *     None.
+ *
+ *----------------------------------------------------------------------------
+ */
+LEAF(wbflush)
+       nop
+       sync
+       j       ra
+       nop
+END(wbflush)
+
+/*--------------------------------------------------------------------------
+ *
+ * R4K_TLBWriteIndexed --
+ *
+ *     Write the given entry into the TLB at the given index.
+ *
+ *     R4K_TLBWriteIndexed(index, tlb)
+ *             unsigned index;
+ *             tlb *tlb;
+ *
+ * Results:
+ *     None.
+ *
+ * Side effects:
+ *     TLB entry set.
+ *
+ *--------------------------------------------------------------------------
+ */
+LEAF(R4K_TLBWriteIndexed)
+       mfc0    v1, COP_0_STATUS_REG    # Save the status register.
+       mtc0    zero, COP_0_STATUS_REG  # Disable interrupts
+       nop
+       lw      a2, 8(a1)
+       lw      a3, 12(a1)
+       dmfc0   t0, COP_0_TLB_HI                # Save the current PID.
+
+       dmtc0   a2, COP_0_TLB_LO0               # Set up entry low0.
+       dmtc0   a3, COP_0_TLB_LO1               # Set up entry low1.
+       lw      a2, 0(a1)
+       lw      a3, 4(a1)
+       mtc0    a0, COP_0_TLB_INDEX     # Set the index.
+       dmtc0   a2, COP_0_TLB_PG_MASK   # Set up entry mask.
+       dmtc0   a3, COP_0_TLB_HI                # Set up entry high.
+       nop
+       tlbwi                                   # Write the TLB
+       nop
+       nop
+       nop                                     # Delay for effect
+       nop
+
+       dmtc0   t0, COP_0_TLB_HI                # Restore the PID.
+       nop
+       dmtc0   zero, COP_0_TLB_PG_MASK # Default mask value.
+       j       ra
+       mtc0    v1, COP_0_STATUS_REG    # Restore the status register
+END(R4K_TLBWriteIndexed)
+
+/*--------------------------------------------------------------------------
+ *
+ * R4K_SetPID --
+ *
+ *     Write the given pid into the TLB pid reg.
+ *
+ *     R4K_SetPID(pid)
+ *             int pid;
+ *
+ * Results:
+ *     None.
+ *
+ * Side effects:
+ *     PID set in the entry hi register.
+ *
+ *--------------------------------------------------------------------------
+ */
+LEAF(R4K_SetPID)
+       dmtc0   a0, COP_0_TLB_HI                # Write the hi reg value
+       j       ra
+       nop
+END(R4K_SetPID)
+
+/*--------------------------------------------------------------------------
+ *
+ * R4K_SetWIRED --
+ *
+ *     Write the given value into the TLB wired reg.
+ *
+ *     R4K_SetPID(wired)
+ *             int wired;
+ *
+ * Results:
+ *     None.
+ *
+ * Side effects:
+ *     WIRED set in the wired register.
+ *
+ *--------------------------------------------------------------------------
+ */
+LEAF(R4K_SetWIRED)
+       mtc0    a0, COP_0_TLB_WIRED
+       j       ra
+       nop
+END(R4K_SetWIRED)
+
+/*--------------------------------------------------------------------------
+ *
+ * R4K_GetWIRED --
+ *
+ *     Get the value from the TLB wired reg.
+ *
+ *     R4K_GetWIRED(void)
+ *
+ * Results:
+ *     Value of wired reg.
+ *
+ * Side effects:
+ *     None.
+ *
+ *--------------------------------------------------------------------------
+ */
+LEAF(R4K_GetWIRED)
+       mfc0    v0, COP_0_TLB_WIRED
+       j       ra
+       nop
+END(R4K_GetWIRED)
+
+/*--------------------------------------------------------------------------
+ *
+ * R4K_TLBFlush --
+ *
+ *     Flush the "random" entries from the TLB.
+ *     Uses "wired" register to determine what register to start with.
+ *
+ *     R4K_TLBFlush()
+ *
+ * Results:
+ *     None.
+ *
+ * Side effects:
+ *     The TLB is flushed.
+ *
+ *--------------------------------------------------------------------------
+ */
+LEAF(R4K_TLBFlush)
+       mfc0    v1, COP_0_STATUS_REG    # Save the status register.
+       mtc0    zero, COP_0_STATUS_REG  # Disable interrupts
+       mfc0    t1, COP_0_TLB_WIRED
+       li      t2, VMNUM_TLB_ENTRIES
+       li      v0, CACHED_MEMORY_ADDR  # invalid address
+       dmfc0   t0, COP_0_TLB_HI        # Save the PID
+
+       dmtc0   v0, COP_0_TLB_HI        # Mark entry high as invalid
+       dmtc0   zero, COP_0_TLB_LO0     # Zero out low entry0.
+       dmtc0   zero, COP_0_TLB_LO1     # Zero out low entry1.
+       mtc0    zero, COP_0_TLB_PG_MASK # Zero out mask entry.
+/*
+ * Align the starting value (t1) and the upper bound (t2).
+ */
+1:
+       mtc0    t1, COP_0_TLB_INDEX     # Set the index register.
+       addu    t1, t1, 1               # Increment index.
+       tlbwi                           # Write the TLB entry.
+       nop
+       nop
+       bne     t1, t2, 1b
+       nop
+
+       dmtc0   t0, COP_0_TLB_HI        # Restore the PID
+       j       ra
+       mtc0    v1, COP_0_STATUS_REG    # Restore the status register
+END(R4K_TLBFlush)
+
+
+/*--------------------------------------------------------------------------
+ *
+ * R4K_TLBFlushAddr --
+ *
+ *     Flush any TLB entries for the given address and TLB PID.
+ *
+ *     R4K_TLBFlushAddr(TLBhi)
+ *             unsigned TLBhi;
+ *
+ * Results:
+ *     None.
+ *
+ * Side effects:
+ *     The process's page is flushed from the TLB.
+ *
+ *--------------------------------------------------------------------------
+ */
+LEAF(R4K_TLBFlushAddr)
+       mfc0    v1, COP_0_STATUS_REG    # Save the status register.
+       mtc0    zero, COP_0_STATUS_REG  # Disable interrupts
+       nop
+       li      v0, (PG_HVPN | PG_ASID)
+       and     a0, a0, v0              # Make shure valid hi value.
+       dmfc0   t0, COP_0_TLB_HI        # Get current PID
+       dmtc0   a0, COP_0_TLB_HI        # look for addr & PID
+       nop
+       nop
+       nop
+       tlbp                            # Probe for the entry.
+       nop
+       nop                             # Delay for effect
+       nop
+       mfc0    v0, COP_0_TLB_INDEX     # See what we got
+       li      t1, CACHED_MEMORY_ADDR  # Load invalid entry.
+       bltz    v0, 1f                  # index < 0 => !found
+       nop
+       dmtc0   t1, COP_0_TLB_HI        # Mark entry high as invalid
+
+       dmtc0   zero, COP_0_TLB_LO0     # Zero out low entry.
+       dmtc0   zero, COP_0_TLB_LO1     # Zero out low entry.
+       nop
+       tlbwi
+       nop
+       nop
+       nop
+       nop
+1:
+       dmtc0   t0, COP_0_TLB_HI        # restore PID
+       j       ra
+       mtc0    v1, COP_0_STATUS_REG    # Restore the status register
+END(R4K_TLBFlushAddr)
+
+/*--------------------------------------------------------------------------
+ *
+ * R4K_TLBUpdate --
+ *
+ *     Update the TLB if highreg is found; otherwise, enter the data.
+ *
+ *     R4K_TLBUpdate(virpageadr, lowregx)
+ *             unsigned virpageadr, lowregx;
+ *
+ * Results:
+ *     < 0 if loaded >= 0 if updated.
+ *
+ * Side effects:
+ *     None.
+ *
+ *--------------------------------------------------------------------------
+ */
+LEAF(R4K_TLBUpdate)
+       mfc0    v1, COP_0_STATUS_REG    # Save the status register.
+       mtc0    zero, COP_0_STATUS_REG  # Disable interrupts
+       and     t1, a0, 0x1000          # t1 = Even/Odd flag
+       li      v0, (PG_HVPN | PG_ASID)
+       and     a0, a0, v0
+       dmfc0   t0, COP_0_TLB_HI        # Save current PID
+       dmtc0   a0, COP_0_TLB_HI        # Init high reg
+       and     a2, a1, PG_G            # Copy global bit
+       nop
+       nop
+       tlbp                            # Probe for the entry.
+       dsll    a1, a1, 34
+       dsrl    a1, a1, 34
+       bne     t1, zero, 2f            # Decide even odd
+       mfc0    v0, COP_0_TLB_INDEX     # See what we got
+# EVEN
+       nop
+       bltz    v0, 1f                  # index < 0 => !found
+       nop
+
+       tlbr                            # update, read entry first
+       nop
+       nop
+       nop
+       dmtc0   a1, COP_0_TLB_LO0       # init low reg0.
+       nop
+       tlbwi                           # update slot found
+       b       4f
+       nop
+1:
+       mtc0    zero, COP_0_TLB_PG_MASK # init mask.
+       dmtc0   a0, COP_0_TLB_HI        # init high reg.
+       dmtc0   a1, COP_0_TLB_LO0       # init low reg0.
+       dmtc0   a2, COP_0_TLB_LO1       # init low reg1.
+       nop
+       tlbwr                           # enter into a random slot
+       b       4f
+       nop
+# ODD
+2:
+       nop
+       bltz    v0, 3f                  # index < 0 => !found
+       nop
+
+       tlbr                            # read the entry first
+       nop
+       nop
+       nop
+       dmtc0   a1, COP_0_TLB_LO1       # init low reg1.
+       nop
+       tlbwi                           # update slot found
+       b       4f
+       nop
+3:
+       mtc0    zero, COP_0_TLB_PG_MASK # init mask.
+       dmtc0   a0, COP_0_TLB_HI        # init high reg.
+       dmtc0   a2, COP_0_TLB_LO0       # init low reg0.
+       dmtc0   a1, COP_0_TLB_LO1       # init low reg1.
+       nop
+       tlbwr                           # enter into a random slot
+
+4:                                     # Make shure pipeline
+       nop                             # advances before we
+       nop                             # uses the tlb.
+       nop
+       nop
+       dmtc0   t0, COP_0_TLB_HI        # restore PID
+       j       ra
+       mtc0    v1, COP_0_STATUS_REG    # Restore the status register
+END(R4K_TLBUpdate)
+
+/*--------------------------------------------------------------------------
+ *
+ * R4K_TLBRead --
+ *
+ *     Read the TLB entry.
+ *
+ *     R4K_TLBRead(entry, tlb)
+ *             unsigned entry;
+ *             struct tlb *tlb;
+ *
+ * Results:
+ *     None.
+ *
+ * Side effects:
+ *     tlb will contain the TLB entry found.
+ *
+ *--------------------------------------------------------------------------
+ */
+LEAF(R4K_TLBRead)
+       mfc0    v1, COP_0_STATUS_REG    # Save the status register.
+       mtc0    zero, COP_0_STATUS_REG  # Disable interrupts
+       nop
+       nop
+       nop
+       dmfc0   t0, COP_0_TLB_HI        # Get current PID
+
+       mtc0    a0, COP_0_TLB_INDEX     # Set the index register
+       nop
+       tlbr                            # Read from the TLB
+       nop
+       nop
+       nop
+       mfc0    t2, COP_0_TLB_PG_MASK   # fetch the hi entry
+       dmfc0   t3, COP_0_TLB_HI        # fetch the hi entry
+       dmfc0   t4, COP_0_TLB_LO0       # See what we got
+       dmfc0   t5, COP_0_TLB_LO1       # See what we got
+       dmtc0   t0, COP_0_TLB_HI        # restore PID
+       nop
+       nop
+       nop                             # wait for PID active
+       mtc0    v1, COP_0_STATUS_REG    # Restore the status register
+       sw      t2, 0(a1)
+       sw      t3, 4(a1)
+       sw      t4, 8(a1)
+       j       ra
+       sw      t5, 12(a1)
+END(R4K_TLBRead)
+
+/*--------------------------------------------------------------------------
+ *
+ * R4K_TLBGetPID --
+ *
+ *     R4K_TLBGetPID()
+ *
+ * Results:
+ *     Returns the current TLB pid reg.
+ *
+ * Side effects:
+ *     None.
+ *
+ *--------------------------------------------------------------------------
+ */
+LEAF(R4K_TLBGetPID)
+       dmfc0   v0, COP_0_TLB_HI        # get PID
+       j       ra
+       and     v0, v0, VMTLB_PID       # mask off PID
+END(R4K_TLBGetPID)
+
+/*----------------------------------------------------------------------------
+ *
+ * R4K_ConfigCache --
+ *
+ *     Size the caches.
+ *     NOTE: should only be called from mips_init().
+ *
+ * Results:
+ *             None.
+ *
+ * Side effects:
+ *     The size of the data cache is stored into CpuPrimaryDataCacheSize.
+ *     The size of instruction cache is stored into CpuPrimaryInstCacheSize.
+ *     Alignment mask for cache aliasing test is stored in CpuCacheAliasMask.
+ *
+ *----------------------------------------------------------------------------
+ */
+LEAF(R4K_ConfigCache)
+       .set    noreorder
+       mfc0    v0, COP_0_CONFIG                # Get configuration register
+       mfc0    v1, COP_0_PRID
+       srl     t1, v0, 9                       # Get I cache size.
+       and     t1, 3
+       li      t2, 4096
+       sllv    t2, t2, t1
+       sw      t2, CpuPrimaryDataCacheSize
+       addiu   t2, -1
+       and     t2, ~(NBPG - 1)
+       sw      t2, CpuCacheAliasMask
+
+       and     t2, v0, 0x20
+       srl     t2, t2, 1
+       addu    t2, t2, 16
+       sw      t2, CpuPrimaryDataCacheLSize
+
+       srl     t1, v0, 6                       # Get I cache size.
+       and     t1, 3
+       li      t2, 4096
+       sllv    t2, t2, t1
+       sw      t2, CpuPrimaryInstCacheSize
+
+       and     t2, v0, 0x10
+       addu    t2, t2, 16
+       sw      t2, CpuPrimaryInstCacheLSize
+       and     v1, 0xff00
+       li      t1, (MIPS_R4600 << 8)
+       li      t2, 1
+       bnel    v1, t1, 1f
+       li      t2, 0
+1:
+       sw      t2, CpuTwoWayCache
+       j       ra
+       nop
+END(R4K_ConfigCache)
+
+/*----------------------------------------------------------------------------
+ *
+ * R4K_FlushCache --
+ *
+ *     Flush the caches. Assumes a line size of 16 bytes for speed.
+ *
+ * Results:
+ *     None.
+ *
+ * Side effects:
+ *     The contents of the caches is flushed.
+ *
+ *----------------------------------------------------------------------------
+ */
+LEAF(R4K_FlushCache)
+       .set    noreorder
+/*XXX 4600 Bug */
+       mfc0    v1, COP_0_STATUS_REG    # Save the status register.
+       mtc0    zero, COP_0_STATUS_REG  # Disable interrupts
+/*XXX*/
+       lw      v0, CpuTwoWayCache
+       lw      t1, CpuPrimaryInstCacheSize
+       lw      t2, CpuPrimaryDataCacheSize
+ #     lw      t3, CpuPrimaryInstCacheLSize
+ #     lw      t4, CpuPrimaryDataCacheLSize
+/*
+ * Flush the instruction cache.
+ */
+       li      t0, CACHED_MEMORY_ADDR
+       addu    t1, t0, t1              # End address
+       subu    t1, t1, 128
+1:
+       bne     v0, zero, 2f
+       cache   0, 0(t0)
+
+       cache   0, 16(t0)
+       cache   0, 48(t0)
+       cache   0, 80(t0)
+       b       3f
+       cache   0, 112(t0)
+
+2:
+       cache   0, 8192+0(t0)
+       cache   0, 8192+32(t0)
+       cache   0, 8192+64(t0)
+       cache   0, 8192+96(t0)
+
+3:
+       cache   0, 32(t0)
+       cache   0, 64(t0)
+       cache   0, 96(t0)
+       bne     t0, t1, 1b
+       addu    t0, t0, 128
+
+/*
+ * Flush the data cache.
+ */
+       li      t0, CACHED_MEMORY_ADDR
+       addu    t1, t0, t2              # End address
+       subu    t1, t1, 128
+1:
+       bne     v0, zero, 2f
+       cache   1, 0(t0)
+
+       cache   1, 16(t0)
+       cache   1, 48(t0)
+       cache   1, 80(t0)
+       b       3f
+       cache   1, 112(t0)
+
+2:
+       cache   1, 8192+0(t0)
+       cache   1, 8192+32(t0)
+       cache   1, 8192+64(t0)
+       cache   1, 8192+96(t0)
+
+3:
+       cache   1, 32(t0)
+       cache   1, 64(t0)
+       cache   1, 96(t0)
+       bne     t0, t1, 1b
+       addu    t0, t0, 128
+
+/*XXX 4600 Bug */
+       mtc0    v1, COP_0_STATUS_REG    # Restore the status register.
+/*XXX*/
+       j       ra
+       nop
+END(R4K_FlushCache)
+
+/*----------------------------------------------------------------------------
+ *
+ * R4K_FlushICache --
+ *
+ *     void R4K_FlushICache(addr, len)
+ *             vm_offset_t addr, len;
+ *
+ *     Flush instruction cache for range of addr to addr + len - 1.
+ *     The address can be any valid address so long as no TLB misses occur.
+ *     Assumes a cache line size of 16 bytes for speed.
+ *
+ * Results:
+ *     None.
+ *
+ * Side effects:
+ *     The contents of the cache is flushed.
+ *     Must not touch v0.
+ *
+ *----------------------------------------------------------------------------
+ */
+LEAF(R4K_FlushICache)
+/*XXX 4600 Bug */
+       mfc0    v1, COP_0_STATUS_REG    # Save the status register.
+       mtc0    zero, COP_0_STATUS_REG  # Disable interrupts
+/*XXX*/
+       lw      v0, CpuTwoWayCache
+       addu    a1, 127         # Align
+       srl     a1, a1, 7       # Number of unrolled loops
+1:
+       bne     v0, zero, 2f
+       addu    a1, -1
+
+       cache   0, 16(a0)
+       cache   0, 48(a0)
+       cache   0, 80(a0)
+       b       3f
+       cache   0, 112(a0)
+
+2:
+       cache   0, 8192+0(a0)
+       cache   0, 8192+32(a0)
+       cache   0, 8192+64(a0)
+       cache   0, 8192+96(a0)
+
+3:
+       cache   0, 0(a0)
+       cache   0, 32(a0)
+       cache   0, 64(a0)
+       cache   0, 96(a0)
+       bne     a1, zero, 1b
+       addu    a0, 128
+
+/*XXX 4600 Bug */
+       mtc0    v1, COP_0_STATUS_REG    # Restore the status register.
+/*XXX*/
+       j       ra
+       move    v0, zero                # suiword depends on this!!
+END(R4K_FlushICache)
+
+/*----------------------------------------------------------------------------
+ *
+ * R4K_FlushDCache --
+ *
+ *     void R4K_FlushDCache(addr, len)
+ *             vm_offset_t addr, len;
+ *
+ *     Flush data cache for index range of addr to addr + len - 1.
+ *     The address is reduced to a kseg0 index.
+ *     
+ * Results:
+ *     None.
+ *
+ * Side effects:
+ *     The contents of the cache is written back to primary memory.
+ *     The cache line is invalidated.
+ *
+ *----------------------------------------------------------------------------
+ */
+LEAF(R4K_FlushDCache)
+/*XXX 4600 Bug */
+       mfc0    v1, COP_0_STATUS_REG    # Save the status register.
+       mtc0    zero, COP_0_STATUS_REG  # Disable interrupts
+/*XXX*/
+       lw      v0, CpuTwoWayCache
+       lw      a2, CpuPrimaryDataCacheSize
+       addiu   a2, -1
+       and     a0, a0, a2
+       addu    a1, 127         # Align
+       li      a2, 0x80000000
+       addu    a0, a0, a2
+       addu    a1, a1, a0
+       and     a0, a0, -128
+       subu    a1, a1, a0
+       srl     a1, a1, 7       # Compute number of cache lines
+1:
+       bne     v0, zero, 2f
+       addu    a1, -1
+
+       cache   1, 16(a0)
+       cache   1, 48(a0)
+       cache   1, 80(a0)
+       b       3f
+       cache   1, 112(a0)
+
+2:
+       cache   1, 8192+0(a0)
+       cache   1, 8192+32(a0)
+       cache   1, 8192+64(a0)
+       cache   1, 8192+96(a0)
+
+3:
+       cache   1, 0(a0)
+       cache   1, 32(a0)
+       cache   1, 64(a0)
+       cache   1, 96(a0)
+       bne     a1, zero, 1b
+       addu    a0, 128
+
+/*XXX 4600 Bug */
+       mtc0    v1, COP_0_STATUS_REG    # Restore the status register.
+/*XXX*/
+       j       ra
+       nop
+END(R4K_FlushDCache)
+
+/*----------------------------------------------------------------------------
+ *
+ * R4K_HitFlushDCache --
+ *
+ *     void R4K_HitFlushDCache(addr, len)
+ *             vm_offset_t addr, len;
+ *
+ *     Flush data cache for range of addr to addr + len - 1.
+ *     The address can be any valid viritual address as long
+ *     as no TLB invalid traps occur. Only lines with matching
+ *     addr is flushed.
+ *     
+ * Results:
+ *     None.
+ *
+ * Side effects:
+ *     The contents of the cache is written back to primary memory.
+ *     The cache line is invalidated.
+ *
+ *----------------------------------------------------------------------------
+ */
+LEAF(R4K_HitFlushDCache)
+       lw      v0, CpuTwoWayCache
+       beq     a1, zero, 3f
+       addu    a1, 127         # Align
+       addu    a1, a1, a0
+       and     a0, a0, -128
+       subu    a1, a1, a0
+       srl     a1, a1, 7       # Compute number of cache lines
+1:
+       bne     v0, zero, 2f
+       addu    a1, -1
+
+       cache   0x15, 16(a0)
+       cache   0x15, 48(a0)
+       cache   0x15, 80(a0)
+       cache   0x15, 112(a0)
+
+2:
+       cache   0x15, 0(a0)
+       cache   0x15, 32(a0)
+       cache   0x15, 64(a0)
+       cache   0x15, 96(a0)
+       bne     a1, zero, 1b
+       addu    a0, 128
+
+3:
+       j       ra
+       nop
+END(R4K_HitFlushDCache)
+/*----------------------------------------------------------------------------
+ *
+ * R4K_InvalidateDCache --
+ *
+ *     void R4K_FlushDCache(addr, len)
+ *             vm_offset_t addr, len;
+ *
+ *     Flush data cache for range of addr to addr + len - 1.
+ *     The address can be any valid address as long as no TLB misses occur.
+ *     (Be sure to use cached K0SEG kernel addresses or mapped addresses)
+ * Results:
+ *     None.
+ *
+ * Side effects:
+ *     The cache line is invalidated.
+ *
+ *----------------------------------------------------------------------------
+ */
+LEAF(R4K_InvalidateDCache)
+       addu    a1, a1, a0                      # compute ending address
+1:
+       cache   0x11,8194(a0)
+       addu    a0, a0, 4
+       bne     a0, a1, 1b
+       cache   0x11,-4(a0)
+
+       j       ra
+       nop
+END(R4K_InvalidateDCache)
+
+#else          /* ==================XXXXX============================== */
+
+/*
+ *----------------------------------------------------------------------------
+ *
+ * R3K_UTLBmiss --
+ *
+ *     Vector code for a MIPS-I user-space TLB miss from user-space.
+ *
+ *
+ * This code is copied to the UTLB exception vector address to
+ * handle user level TLB translation misses.
+ * NOTE: This code must be relocatable!!!
+ */
+       .globl  R3K_UTLBMiss
+R3K_UTLBMiss:
+       .set    noat
+       mfc0    k0, COP_0_BAD_VADDR             # get the virtual address
+       lw      k1, UADDR+U_PCB_SEGTAB          # get the current segment table
+       bltz    k0, 1f                          # R3000 chip bug
+       srl     k0, k0, SEGSHIFT                # compute segment table index
+       sll     k0, k0, 2
+       addu    k1, k1, k0
+       mfc0    k0, COP_0_BAD_VADDR             # get the virtual address
+       lw      k1, 0(k1)                       # get pointer to segment map
+       srl     k0, k0, PGSHIFT - 2             # compute segment map index
+       andi    k0, k0, (NPTEPG - 1) << 2
+       beq     k1, zero, 2f                    # invalid segment map
+       addu    k1, k1, k0                      # index into segment map
+       lw      k0, 0(k1)                       # get page PTE
+       nop
+       beq     k0, zero, 2f                    # dont load invalid entries
+       mtc0    k0, COP_0_TLB_LO0
+       mfc0    k1, COP_0_EXC_PC                # get return address
+       tlbwr                                   # update TLB
+       j       k1
+       rfe
+1:
+       mfc0    k1, COP_0_EXC_PC                # get return address
+       nop
+       j       k1
+       rfe
+2:
+       j       R3K_SlowFault                   # handle the rest
+       nop
+       .set    at
+       .globl  R3K_UTLBMissEnd
+R3K_UTLBMissEnd:
+
+
+/*
+ *----------------------------------------------------------------------------
+ *
+ * R3K_execption --
+ *
+ *     Vector code for the general exception vector 0x80000080
+ *     on an r2000 or r3000.
+ *
+ * This code is copied to the general exception vector address to
+ * handle all execptions except RESET and UTLBMiss.
+ * NOTE: This code must be relocatable!!!
+ *
+ *----------------------------------------------------------------------------
+ */
+       .globl  R3K_Exception
+R3K_Exception:
+       .set    noat
+       mfc0    k0, COP_0_STATUS_REG            # Get the status register
+       mfc0    k1, COP_0_CAUSE_REG             # Get the cause register value.
+       and     k0, k0, SR_KU_PREV              # test for user mode
+       sll     k0, k0, 4                       # shift user bit for cause index
+       and     k1, k1, CR_EXC_CODE             # Mask out the cause bits.
+       or      k1, k1, k0                      # change index to user table
+1:
+       la      k0, R3K_ExceptionTable           # get base of the jump table
+       addu    k0, k0, k1                      # Get the address of the
+                                               #  function entry.  Note that
+                                               #  the cause is already
+                                               #  shifted left by 2 bits so
+                                               #  we dont have to shift.
+       lw      k0, 0(k0)                       # Get the function address
+       nop
+       j       k0                              # Jump to the function.
+       nop
+       .set    at
+       .globl  R3K_ExceptionEnd
+R3K_ExceptionEnd:
+
+/*----------------------------------------------------------------------------
+ *
+ * R3K_SlowFault --
+ *
+ * Alternate entry point into the R3K_UserGenExceptionor or
+ * or R3K_user_Kern_exception, when the ULTB miss handler couldn't
+ * find a TLB entry.
+ *
+ * Find out what mode we came from and call the appropriate handler.
+ */
+R3K_SlowFault:
+       .set    noat
+       mfc0    k0, COP_0_STATUS_REG
+       nop
+       and     k0, k0, SR_KU_PREV
+       bne     k0, zero, R3K_UserGenException
+       nop
+       .set    at
+/*
+ * Fall though ...
+ */
+
+/*----------------------------------------------------------------------------
+ *
+ * R3K_KernGenException --
+ *
+ *     Handle an exception from kernel mode.
+ *
+ * Results:
+ *     None.
+ *
+ * Side effects:
+ *     None.
+ *
+ *----------------------------------------------------------------------------
+ */
+
+/*
+ * The kernel exception stack contains 18 saved general registers,
+ * the status register and the multiply lo and high registers.
+ * In addition, we set this up for linkage conventions.
+ */
+#define KERN_REG_SIZE          (18 * 4)
+#define KERN_REG_OFFSET                (STAND_FRAME_SIZE)
+#define KERN_SR_OFFSET         (STAND_FRAME_SIZE + KERN_REG_SIZE)
+#define KERN_MULT_LO_OFFSET    (STAND_FRAME_SIZE + KERN_REG_SIZE + 4)
+#define KERN_MULT_HI_OFFSET    (STAND_FRAME_SIZE + KERN_REG_SIZE + 8)
+#define        KERN_EXC_FRAME_SIZE     (STAND_FRAME_SIZE + KERN_REG_SIZE + 12)
+
+NNON_LEAF(R3K_KernGenException, KERN_EXC_FRAME_SIZE, ra)
+       .set    noat
+#ifdef DEBUG
+       la      k0, mdbpcb                      # save registers for kadb
+       sw      s0, (S0 * 4)(k0)
+       sw      s1, (S1 * 4)(k0)
+       sw      s2, (S2 * 4)(k0)
+       sw      s3, (S3 * 4)(k0)
+       sw      s4, (S4 * 4)(k0)
+       sw      s5, (S5 * 4)(k0)
+       sw      s6, (S6 * 4)(k0)
+       sw      s7, (S7 * 4)(k0)
+       sw      s8, (S8 * 4)(k0)
+       sw      gp, (GP * 4)(k0)
+       sw      sp, (SP * 4)(k0)
+#endif
+       subu    sp, sp, KERN_EXC_FRAME_SIZE
+       .mask   0x80000000, (STAND_RA_OFFSET - KERN_EXC_FRAME_SIZE)
+/*
+ * Save the relevant kernel registers onto the stack.
+ * We don't need to save s0 - s8, sp and gp because
+ * the compiler does it for us.
+ */
+       sw      AT, KERN_REG_OFFSET + 0(sp)
+       sw      v0, KERN_REG_OFFSET + 4(sp)
+       sw      v1, KERN_REG_OFFSET + 8(sp)
+       sw      a0, KERN_REG_OFFSET + 12(sp)
+       mflo    v0
+       mfhi    v1
+       sw      a1, KERN_REG_OFFSET + 16(sp)
+       sw      a2, KERN_REG_OFFSET + 20(sp)
+       sw      a3, KERN_REG_OFFSET + 24(sp)
+       sw      t0, KERN_REG_OFFSET + 28(sp)
+       mfc0    a0, COP_0_STATUS_REG            # First arg is the status reg.
+       sw      t1, KERN_REG_OFFSET + 32(sp)
+       sw      t2, KERN_REG_OFFSET + 36(sp)
+       sw      t3, KERN_REG_OFFSET + 40(sp)
+       sw      t4, KERN_REG_OFFSET + 44(sp)
+       mfc0    a1, COP_0_CAUSE_REG             # Second arg is the cause reg.
+       sw      t5, KERN_REG_OFFSET + 48(sp)
+       sw      t6, KERN_REG_OFFSET + 52(sp)
+       sw      t7, KERN_REG_OFFSET + 56(sp)
+       sw      t8, KERN_REG_OFFSET + 60(sp)
+       mfc0    a2, COP_0_BAD_VADDR             # Third arg is the fault addr.
+       sw      t9, KERN_REG_OFFSET + 64(sp)
+       sw      ra, KERN_REG_OFFSET + 68(sp)
+       sw      v0, KERN_MULT_LO_OFFSET(sp)
+       sw      v1, KERN_MULT_HI_OFFSET(sp)
+       mfc0    a3, COP_0_EXC_PC                # Fourth arg is the pc.
+       sw      a0, KERN_SR_OFFSET(sp)
+/*
+ * Call the exception handler.
+ */
+       jal     trap
+       sw      a3, STAND_RA_OFFSET(sp)         # for debugging
+/*
+ * Restore registers and return from the exception.
+ * v0 contains the return address.
+ */
+       lw      a0, KERN_SR_OFFSET(sp)
+       lw      t0, KERN_MULT_LO_OFFSET(sp)
+       lw      t1, KERN_MULT_HI_OFFSET(sp)
+       mtc0    a0, COP_0_STATUS_REG            # Restore the SR, disable intrs
+       mtlo    t0
+       mthi    t1
+       move    k0, v0
+
+       lw      AT, KERN_REG_OFFSET + 0(sp)
+       lw      v0, KERN_REG_OFFSET + 4(sp)
+       lw      v1, KERN_REG_OFFSET + 8(sp)
+       lw      a0, KERN_REG_OFFSET + 12(sp)
+       lw      a1, KERN_REG_OFFSET + 16(sp)
+       lw      a2, KERN_REG_OFFSET + 20(sp)
+       lw      a3, KERN_REG_OFFSET + 24(sp)
+       lw      t0, KERN_REG_OFFSET + 28(sp)
+       lw      t1, KERN_REG_OFFSET + 32(sp)
+       lw      t2, KERN_REG_OFFSET + 36(sp)
+       lw      t3, KERN_REG_OFFSET + 40(sp)
+       lw      t4, KERN_REG_OFFSET + 44(sp)
+       lw      t5, KERN_REG_OFFSET + 48(sp)
+       lw      t6, KERN_REG_OFFSET + 52(sp)
+       lw      t7, KERN_REG_OFFSET + 56(sp)
+       lw      t8, KERN_REG_OFFSET + 60(sp)
+       lw      t9, KERN_REG_OFFSET + 64(sp)
+       lw      ra, KERN_REG_OFFSET + 68(sp)
+
+       addu    sp, sp, KERN_EXC_FRAME_SIZE
+       j       k0                              # Now return from the
+       rfe                                     #  exception.
+       .set    at
+END(R3K_KernGenException)
+
+/*----------------------------------------------------------------------------
+ *
+ * R3K_UserGenException --
+ *
+ *     Handle an exception from user mode.
+ *
+ * Results:
+ *     None.
+ *
+ * Side effects:
+ *     None.
+ *
+ *----------------------------------------------------------------------------
+ */
+NNON_LEAF(R3K_UserGenException, STAND_FRAME_SIZE, ra)
+       .set    noat
+       .mask   0x80000000, (STAND_RA_OFFSET - STAND_FRAME_SIZE)
+/*
+ * Save all of the registers except for the kernel temporaries in u.u_pcb.
+ */
+       sw      AT, UADDR+U_PCB_REGS+(AST * 4)
+       sw      v0, UADDR+U_PCB_REGS+(V0 * 4)
+       sw      v1, UADDR+U_PCB_REGS+(V1 * 4)
+       sw      a0, UADDR+U_PCB_REGS+(A0 * 4)
+       mflo    v0
+       sw      a1, UADDR+U_PCB_REGS+(A1 * 4)
+       sw      a2, UADDR+U_PCB_REGS+(A2 * 4)
+       sw      a3, UADDR+U_PCB_REGS+(A3 * 4)
+       sw      t0, UADDR+U_PCB_REGS+(T0 * 4)
+       mfhi    v1
+       sw      t1, UADDR+U_PCB_REGS+(T1 * 4)
+       sw      t2, UADDR+U_PCB_REGS+(T2 * 4)
+       sw      t3, UADDR+U_PCB_REGS+(T3 * 4)
+       sw      t4, UADDR+U_PCB_REGS+(T4 * 4)
+       mfc0    a0, COP_0_STATUS_REG            # First arg is the status reg.
+       sw      t5, UADDR+U_PCB_REGS+(T5 * 4)
+       sw      t6, UADDR+U_PCB_REGS+(T6 * 4)
+       sw      t7, UADDR+U_PCB_REGS+(T7 * 4)
+       sw      s0, UADDR+U_PCB_REGS+(S0 * 4)
+       mfc0    a1, COP_0_CAUSE_REG             # Second arg is the cause reg.
+       sw      s1, UADDR+U_PCB_REGS+(S1 * 4)
+       sw      s2, UADDR+U_PCB_REGS+(S2 * 4)
+       sw      s3, UADDR+U_PCB_REGS+(S3 * 4)
+       sw      s4, UADDR+U_PCB_REGS+(S4 * 4)
+       mfc0    a2, COP_0_BAD_VADDR             # Third arg is the fault addr
+       sw      s5, UADDR+U_PCB_REGS+(S5 * 4)
+       sw      s6, UADDR+U_PCB_REGS+(S6 * 4)
+       sw      s7, UADDR+U_PCB_REGS+(S7 * 4)
+       sw      t8, UADDR+U_PCB_REGS+(T8 * 4)
+       mfc0    a3, COP_0_EXC_PC                # Fourth arg is the pc.
+       sw      t9, UADDR+U_PCB_REGS+(T9 * 4)
+       sw      gp, UADDR+U_PCB_REGS+(GP * 4)
+       sw      sp, UADDR+U_PCB_REGS+(SP * 4)
+       sw      s8, UADDR+U_PCB_REGS+(S8 * 4)
+       li      sp, KERNELSTACK - STAND_FRAME_SIZE      # switch to kernel SP
+       sw      ra, UADDR+U_PCB_REGS+(RA * 4)
+       sw      v0, UADDR+U_PCB_REGS+(MULLO * 4)
+       sw      v1, UADDR+U_PCB_REGS+(MULHI * 4)
+       sw      a0, UADDR+U_PCB_REGS+(SR * 4)
+       la      gp, _gp                         # switch to kernel GP
+       sw      a3, UADDR+U_PCB_REGS+(PC * 4)
+       sw      a3, STAND_RA_OFFSET(sp)         # for debugging
+       .set    at
+       and     t0, a0, ~SR_COP_1_BIT   # Turn off the FPU.
+       .set    noat
+/*
+ * Call the exception handler.
+ */
+       jal     trap
+       mtc0    t0, COP_0_STATUS_REG
+/*
+ * Restore user registers and return. NOTE: interrupts are enabled.
+ */
+       lw      a0, UADDR+U_PCB_REGS+(SR * 4)
+       lw      t0, UADDR+U_PCB_REGS+(MULLO * 4)
+       lw      t1, UADDR+U_PCB_REGS+(MULHI * 4)
+       mtc0    a0, COP_0_STATUS_REG            # this should disable interrupts
+       mtlo    t0
+       mthi    t1
+       lw      k0, UADDR+U_PCB_REGS+(PC * 4)
+       lw      AT, UADDR+U_PCB_REGS+(AST * 4)
+       lw      v0, UADDR+U_PCB_REGS+(V0 * 4)
+       lw      v1, UADDR+U_PCB_REGS+(V1 * 4)
+       lw      a0, UADDR+U_PCB_REGS+(A0 * 4)
+       lw      a1, UADDR+U_PCB_REGS+(A1 * 4)
+       lw      a2, UADDR+U_PCB_REGS+(A2 * 4)
+       lw      a3, UADDR+U_PCB_REGS+(A3 * 4)
+       lw      t0, UADDR+U_PCB_REGS+(T0 * 4)
+       lw      t1, UADDR+U_PCB_REGS+(T1 * 4)
+       lw      t2, UADDR+U_PCB_REGS+(T2 * 4)
+       lw      t3, UADDR+U_PCB_REGS+(T3 * 4)
+       lw      t4, UADDR+U_PCB_REGS+(T4 * 4)
+       lw      t5, UADDR+U_PCB_REGS+(T5 * 4)
+       lw      t6, UADDR+U_PCB_REGS+(T6 * 4)
+       lw      t7, UADDR+U_PCB_REGS+(T7 * 4)
+       lw      s0, UADDR+U_PCB_REGS+(S0 * 4)
+       lw      s1, UADDR+U_PCB_REGS+(S1 * 4)
+       lw      s2, UADDR+U_PCB_REGS+(S2 * 4)
+       lw      s3, UADDR+U_PCB_REGS+(S3 * 4)
+       lw      s4, UADDR+U_PCB_REGS+(S4 * 4)
+       lw      s5, UADDR+U_PCB_REGS+(S5 * 4)
+       lw      s6, UADDR+U_PCB_REGS+(S6 * 4)
+       lw      s7, UADDR+U_PCB_REGS+(S7 * 4)
+       lw      t8, UADDR+U_PCB_REGS+(T8 * 4)
+       lw      t9, UADDR+U_PCB_REGS+(T9 * 4)
+       lw      gp, UADDR+U_PCB_REGS+(GP * 4)
+       lw      sp, UADDR+U_PCB_REGS+(SP * 4)
+       lw      s8, UADDR+U_PCB_REGS+(S8 * 4)
+       lw      ra, UADDR+U_PCB_REGS+(RA * 4)
+
+       j       k0
+       rfe
+       .set    at
+END(R3K_UserGenException)
+
+/*----------------------------------------------------------------------------
+ *
+ * R3K_KernIntr --
+ *
+ *     Handle an interrupt from kernel mode.
+ *     Interrupts use the standard kernel stack.
+ *     switch_exit sets up a kernel stack after exit so interrupts won't fail.
+ *
+ * Results:
+ *     None.
+ *
+ * Side effects:
+ *     None.
+ *
+ *----------------------------------------------------------------------------
+ */
+#define KINTR_REG_OFFSET       (STAND_FRAME_SIZE)
+#define KINTR_SR_OFFSET                (STAND_FRAME_SIZE + KERN_REG_SIZE)
+#define KINTR_MULT_LO_OFFSET   (STAND_FRAME_SIZE + KERN_REG_SIZE + 4)
+#define KINTR_MULT_HI_OFFSET   (STAND_FRAME_SIZE + KERN_REG_SIZE + 8)
+#define KINTR_GP_OFFSET                (STAND_FRAME_SIZE + KERN_REG_SIZE + 12)
+#define        KINTR_FRAME_SIZE        (STAND_FRAME_SIZE + KERN_REG_SIZE + 16)
+
+NNON_LEAF(R3K_KernIntr, KINTR_FRAME_SIZE, ra)
+       .set    noat
+       subu    sp, sp, KINTR_FRAME_SIZE        # allocate stack frame
+       .mask   0x80000000, (STAND_RA_OFFSET - KINTR_FRAME_SIZE)
+/*
+ * Save the relevant kernel registers onto the stack.
+ * We don't need to save s0 - s8 and sp because
+ * the compiler does it for us.
+ */
+       sw      AT, KINTR_REG_OFFSET + 0(sp)
+       sw      v0, KINTR_REG_OFFSET + 4(sp)
+       sw      v1, KINTR_REG_OFFSET + 8(sp)
+       sw      a0, KINTR_REG_OFFSET + 12(sp)
+       mflo    v0
+       mfhi    v1
+       sw      a1, KINTR_REG_OFFSET + 16(sp)
+       sw      a2, KINTR_REG_OFFSET + 20(sp)
+       sw      a3, KINTR_REG_OFFSET + 24(sp)
+       sw      t0, KINTR_REG_OFFSET + 28(sp)
+       mfc0    a0, COP_0_STATUS_REG            # First arg is the status reg.
+       sw      t1, KINTR_REG_OFFSET + 32(sp)
+       sw      t2, KINTR_REG_OFFSET + 36(sp)
+       sw      t3, KINTR_REG_OFFSET + 40(sp)
+       sw      t4, KINTR_REG_OFFSET + 44(sp)
+       mfc0    a1, COP_0_CAUSE_REG             # Second arg is the cause reg.
+       sw      t5, KINTR_REG_OFFSET + 48(sp)
+       sw      t6, KINTR_REG_OFFSET + 52(sp)
+       sw      t7, KINTR_REG_OFFSET + 56(sp)
+       sw      t8, KINTR_REG_OFFSET + 60(sp)
+       mfc0    a2, COP_0_EXC_PC                # Third arg is the pc.
+       sw      t9, KINTR_REG_OFFSET + 64(sp)
+       sw      ra, KINTR_REG_OFFSET + 68(sp)
+       sw      v0, KINTR_MULT_LO_OFFSET(sp)
+       sw      v1, KINTR_MULT_HI_OFFSET(sp)
+       sw      a0, KINTR_SR_OFFSET(sp)
+       sw      gp, KINTR_GP_OFFSET(sp)
+       la      gp, _gp                         # switch to kernel GP
+/*
+ * Call the interrupt handler.
+ */
+       jal     interrupt
+       sw      a2, STAND_RA_OFFSET(sp)         # for debugging
+/*
+ * Restore registers and return from the interrupt.
+ */
+       lw      a0, KINTR_SR_OFFSET(sp)
+       lw      t0, KINTR_MULT_LO_OFFSET(sp)
+       lw      t1, KINTR_MULT_HI_OFFSET(sp)
+       mtc0    a0, COP_0_STATUS_REG            # Restore the SR, disable intrs
+       mtlo    t0
+       mthi    t1
+       lw      k0, STAND_RA_OFFSET(sp)
+       lw      AT, KINTR_REG_OFFSET + 0(sp)
+       lw      v0, KINTR_REG_OFFSET + 4(sp)
+       lw      v1, KINTR_REG_OFFSET + 8(sp)
+       lw      a0, KINTR_REG_OFFSET + 12(sp)
+       lw      a1, KINTR_REG_OFFSET + 16(sp)
+       lw      a2, KINTR_REG_OFFSET + 20(sp)
+       lw      a3, KINTR_REG_OFFSET + 24(sp)
+       lw      t0, KINTR_REG_OFFSET + 28(sp)
+       lw      t1, KINTR_REG_OFFSET + 32(sp)
+       lw      t2, KINTR_REG_OFFSET + 36(sp)
+       lw      t3, KINTR_REG_OFFSET + 40(sp)
+       lw      t4, KINTR_REG_OFFSET + 44(sp)
+       lw      t5, KINTR_REG_OFFSET + 48(sp)
+       lw      t6, KINTR_REG_OFFSET + 52(sp)
+       lw      t7, KINTR_REG_OFFSET + 56(sp)
+       lw      t8, KINTR_REG_OFFSET + 60(sp)
+       lw      t9, KINTR_REG_OFFSET + 64(sp)
+       lw      ra, KINTR_REG_OFFSET + 68(sp)
+
+       addu    sp, sp, KINTR_FRAME_SIZE
+       j       k0                              # Now return from the
+       rfe                                     #  interrupt.
+       .set    at
+END(R3K_KernIntr)
+
+/*----------------------------------------------------------------------------
+ *
+ * R3K_UserIntr --
+ *
+ *     Handle an interrupt from user mode.
+ *     Note: we save minimal state in the u.u_pcb struct and use the standard
+ *     kernel stack since there has to be a u page if we came from user mode.
+ *     If there is a pending software interrupt, then save the remaining state
+ *     and call softintr(). This is all because if we call switch() inside
+ *     interrupt(), not all the user registers have been saved in u.u_pcb.
+ *
+ * Results:
+ *     None.
+ *
+ * Side effects:
+ *     None.
+ *
+ *----------------------------------------------------------------------------
+ */
+NNON_LEAF(R3K_UserIntr, STAND_FRAME_SIZE, ra)
+       .set    noat
+       .mask   0x80000000, (STAND_RA_OFFSET - STAND_FRAME_SIZE)
+/*
+ * Save the relevant user registers into the u.u_pcb struct.
+ * We don't need to save s0 - s8 because
+ * the compiler does it for us.
+ */
+       sw      AT, UADDR+U_PCB_REGS+(AST * 4)
+       sw      v0, UADDR+U_PCB_REGS+(V0 * 4)
+       sw      v1, UADDR+U_PCB_REGS+(V1 * 4)
+       sw      a0, UADDR+U_PCB_REGS+(A0 * 4)
+       mflo    v0
+       mfhi    v1
+       sw      a1, UADDR+U_PCB_REGS+(A1 * 4)
+       sw      a2, UADDR+U_PCB_REGS+(A2 * 4)
+       sw      a3, UADDR+U_PCB_REGS+(A3 * 4)
+       sw      t0, UADDR+U_PCB_REGS+(T0 * 4)
+       mfc0    a0, COP_0_STATUS_REG            # First arg is the status reg.
+       sw      t1, UADDR+U_PCB_REGS+(T1 * 4)
+       sw      t2, UADDR+U_PCB_REGS+(T2 * 4)
+       sw      t3, UADDR+U_PCB_REGS+(T3 * 4)
+       sw      t4, UADDR+U_PCB_REGS+(T4 * 4)
+       mfc0    a1, COP_0_CAUSE_REG             # Second arg is the cause reg.
+       sw      t5, UADDR+U_PCB_REGS+(T5 * 4)
+       sw      t6, UADDR+U_PCB_REGS+(T6 * 4)
+       sw      t7, UADDR+U_PCB_REGS+(T7 * 4)
+       sw      t8, UADDR+U_PCB_REGS+(T8 * 4)
+       mfc0    a2, COP_0_EXC_PC                # Third arg is the pc.
+       sw      t9, UADDR+U_PCB_REGS+(T9 * 4)
+       sw      gp, UADDR+U_PCB_REGS+(GP * 4)
+       sw      sp, UADDR+U_PCB_REGS+(SP * 4)
+       sw      ra, UADDR+U_PCB_REGS+(RA * 4)
+       li      sp, KERNELSTACK - STAND_FRAME_SIZE      # switch to kernel SP
+       sw      v0, UADDR+U_PCB_REGS+(MULLO * 4)
+       sw      v1, UADDR+U_PCB_REGS+(MULHI * 4)
+       sw      a0, UADDR+U_PCB_REGS+(SR * 4)
+       sw      a2, UADDR+U_PCB_REGS+(PC * 4)
+       la      gp, _gp                         # switch to kernel GP
+       .set    at
+       and     t0, a0, ~SR_COP_1_BIT           # Turn off the FPU.
+       .set    noat
+       mtc0    t0, COP_0_STATUS_REG
+/*
+ * Call the interrupt handler.
+ */
+       jal     interrupt
+       sw      a2, STAND_RA_OFFSET(sp)         # for debugging
+/*
+ * Restore registers and return from the interrupt.
+ */
+       lw      a0, UADDR+U_PCB_REGS+(SR * 4)
+       lw      v0, astpending                  # any pending interrupts?
+       mtc0    a0, COP_0_STATUS_REG            # Restore the SR, disable intrs
+       bne     v0, zero, 1f                    # dont restore, call softintr
+       lw      t0, UADDR+U_PCB_REGS+(MULLO * 4)
+       lw      t1, UADDR+U_PCB_REGS+(MULHI * 4)
+       lw      k0, UADDR+U_PCB_REGS+(PC * 4)
+       lw      AT, UADDR+U_PCB_REGS+(AST * 4)
+       lw      v0, UADDR+U_PCB_REGS+(V0 * 4)
+       lw      v1, UADDR+U_PCB_REGS+(V1 * 4)
+       lw      a0, UADDR+U_PCB_REGS+(A0 * 4)
+       lw      a1, UADDR+U_PCB_REGS+(A1 * 4)
+       lw      a2, UADDR+U_PCB_REGS+(A2 * 4)
+       lw      a3, UADDR+U_PCB_REGS+(A3 * 4)
+       mtlo    t0
+       mthi    t1
+       lw      t0, UADDR+U_PCB_REGS+(T0 * 4)
+       lw      t1, UADDR+U_PCB_REGS+(T1 * 4)
+       lw      t2, UADDR+U_PCB_REGS+(T2 * 4)
+       lw      t3, UADDR+U_PCB_REGS+(T3 * 4)
+       lw      t4, UADDR+U_PCB_REGS+(T4 * 4)
+       lw      t5, UADDR+U_PCB_REGS+(T5 * 4)
+       lw      t6, UADDR+U_PCB_REGS+(T6 * 4)
+       lw      t7, UADDR+U_PCB_REGS+(T7 * 4)
+       lw      t8, UADDR+U_PCB_REGS+(T8 * 4)
+       lw      t9, UADDR+U_PCB_REGS+(T9 * 4)
+       lw      gp, UADDR+U_PCB_REGS+(GP * 4)
+       lw      sp, UADDR+U_PCB_REGS+(SP * 4)
+       lw      ra, UADDR+U_PCB_REGS+(RA * 4)
+       j       k0                              # Now return from the
+       rfe                                     #  interrupt.
+
+1:
+/*
+ * We have pending software interrupts; save remaining user state in u.u_pcb.
+ */
+       sw      s0, UADDR+U_PCB_REGS+(S0 * 4)
+       sw      s1, UADDR+U_PCB_REGS+(S1 * 4)
+       sw      s2, UADDR+U_PCB_REGS+(S2 * 4)
+       sw      s3, UADDR+U_PCB_REGS+(S3 * 4)
+       sw      s4, UADDR+U_PCB_REGS+(S4 * 4)
+       sw      s5, UADDR+U_PCB_REGS+(S5 * 4)
+       sw      s6, UADDR+U_PCB_REGS+(S6 * 4)
+       sw      s7, UADDR+U_PCB_REGS+(S7 * 4)
+       sw      s8, UADDR+U_PCB_REGS+(S8 * 4)
+       li      t0, HARD_INT_MASK | SR_INT_ENAB
+/*
+ * Call the software interrupt handler.
+ */
+       jal     softintr
+       mtc0    t0, COP_0_STATUS_REG            # enable interrupts (spl0)
+/*
+ * Restore user registers and return. NOTE: interrupts are enabled.
+ */
+       lw      a0, UADDR+U_PCB_REGS+(SR * 4)
+       lw      t0, UADDR+U_PCB_REGS+(MULLO * 4)
+       lw      t1, UADDR+U_PCB_REGS+(MULHI * 4)
+       mtc0    a0, COP_0_STATUS_REG            # this should disable interrupts
+       mtlo    t0
+       mthi    t1
+       lw      k0, UADDR+U_PCB_REGS+(PC * 4)
+       lw      AT, UADDR+U_PCB_REGS+(AST * 4)
+       lw      v0, UADDR+U_PCB_REGS+(V0 * 4)
+       lw      v1, UADDR+U_PCB_REGS+(V1 * 4)
+       lw      a0, UADDR+U_PCB_REGS+(A0 * 4)
+       lw      a1, UADDR+U_PCB_REGS+(A1 * 4)
+       lw      a2, UADDR+U_PCB_REGS+(A2 * 4)
+       lw      a3, UADDR+U_PCB_REGS+(A3 * 4)
+       lw      t0, UADDR+U_PCB_REGS+(T0 * 4)
+       lw      t1, UADDR+U_PCB_REGS+(T1 * 4)
+       lw      t2, UADDR+U_PCB_REGS+(T2 * 4)
+       lw      t3, UADDR+U_PCB_REGS+(T3 * 4)
+       lw      t4, UADDR+U_PCB_REGS+(T4 * 4)
+       lw      t5, UADDR+U_PCB_REGS+(T5 * 4)
+       lw      t6, UADDR+U_PCB_REGS+(T6 * 4)
+       lw      t7, UADDR+U_PCB_REGS+(T7 * 4)
+       lw      s0, UADDR+U_PCB_REGS+(S0 * 4)
+       lw      s1, UADDR+U_PCB_REGS+(S1 * 4)
+       lw      s2, UADDR+U_PCB_REGS+(S2 * 4)
+       lw      s3, UADDR+U_PCB_REGS+(S3 * 4)
+       lw      s4, UADDR+U_PCB_REGS+(S4 * 4)
+       lw      s5, UADDR+U_PCB_REGS+(S5 * 4)
+       lw      s6, UADDR+U_PCB_REGS+(S6 * 4)
+       lw      s7, UADDR+U_PCB_REGS+(S7 * 4)
+       lw      t8, UADDR+U_PCB_REGS+(T8 * 4)
+       lw      t9, UADDR+U_PCB_REGS+(T9 * 4)
+       lw      gp, UADDR+U_PCB_REGS+(GP * 4)
+       lw      sp, UADDR+U_PCB_REGS+(SP * 4)
+       lw      s8, UADDR+U_PCB_REGS+(S8 * 4)
+       lw      ra, UADDR+U_PCB_REGS+(RA * 4)
+
+       j       k0
+       rfe
+       .set    at
+END(R3K_UserIntr)
+
+
+
+#if 0
+/*----------------------------------------------------------------------------
+ *
+ * R3K_TLBModException --
+ *
+ *     Handle a TLB modified exception.
+ *     The BaddVAddr, Context, and EntryHi registers contain the failed
+ *     virtual address.
+ *
+ * Results:
+ *     None.
+ *
+ * Side effects:
+ *     None.
+ *
+ *----------------------------------------------------------------------------
+ */
+NLEAF(R3K_TLBModException)
+       .set    noat
+       tlbp                                    # find the TLB entry
+       mfc0    k0, COP_0_TLB_LO0               # get the physical address
+       mfc0    k1, COP_0_TLB_INDEX             # check to be sure its valid
+       or      k0, k0, VM_TLB_MOD_BIT  # update TLB
+       blt     k1, zero, 4f                    # not found!!!
+       mtc0    k0, COP_0_TLB_LO0
+       li      k1, CACHED_MEMORY_ADDR
+       subu    k0, k0, k1
+       srl     k0, k0, VM_TLB_PHYS_PAGE_SHIFT
+       la      k1, pmap_attributes
+       addu    k0, k0, k1
+       lbu     k1, 0(k0)                       # fetch old value
+       nop
+       or      k1, k1, 1                       # set modified bit
+       sb      k1, 0(k0)                       # save new value
+       mfc0    k0, COP_0_EXC_PC                # get return address
+       nop
+       j       k0
+       rfe
+4:
+       break   0                               # panic
+       .set    at
+END(R3K_TLBModException)
+#endif
+
+/*----------------------------------------------------------------------------
+ *
+ * R3K_TLBMissException --
+ *
+ *     Handle a TLB miss exception from kernel mode.
+ *     The BaddVAddr, Context, and EntryHi registers contain the failed
+ *     virtual address.
+ *
+ * Results:
+ *     None.
+ *
+ * Side effects:
+ *     None.
+ *
+ *----------------------------------------------------------------------------
+ */
+NLEAF(R3K_TLBMissException)
+       .set    noat
+       mfc0    k0, COP_0_BAD_VADDR             # get the fault address
+       li      k1, VM_MIN_KERNEL_ADDRESS       # compute index
+       subu    k0, k0, k1
+       lw      k1, Sysmapsize                  # index within range?
+       srl     k0, k0, PGSHIFT
+       sltu    k1, k0, k1
+       beq     k1, zero, 1f                    # No. check for valid stack
+       nop
+       lw      k1, Sysmap
+       sll     k0, k0, 2                       # compute offset from index
+       addu    k1, k1, k0
+       lw      k0, 0(k1)                       # get PTE entry
+       mfc0    k1, COP_0_EXC_PC                # get return address
+       mtc0    k0, COP_0_TLB_LO0               # save PTE entry
+       and     k0, k0, PG_V                    # check for valid entry
+       beq     k0, zero, R3K_KernGenException  # PTE invalid
+       nop
+       tlbwr                                   # update TLB
+       j       k1
+       rfe
+
+1:
+       subu    k0, sp, UADDR + 0x200           # check to see if we have a
+       sltiu   k0, UPAGES*NBPG - 0x200         #  valid kernel stack
+       bne     k0, zero, R3K_KernGenException  # Go panic
+       nop
+
+       la      a0, start - START_FRAME - 8     # set sp to a valid place
+       sw      sp, 24(a0)
+       move    sp, a0
+       la      a0, 1f
+       mfc0    a2, COP_0_STATUS_REG
+       mfc0    a3, COP_0_CAUSE_REG
+       mfc0    a1, COP_0_EXC_PC
+       sw      a2, 16(sp)
+       sw      a3, 20(sp)
+       move    a2, ra
+       jal     printf
+       mfc0    a3, COP_0_BAD_VADDR
+       .data
+1:
+       .asciiz "ktlbmiss: PC %x RA %x ADR %x\nSR %x CR %x SP %x\n"
+       .text
+
+       la      sp, start - START_FRAME         # set sp to a valid place
+       PANIC("kernel stack overflow")
+       .set    at
+END(R3K_TLBMissException)
+
+/*----------------------------------------------------------------------------
+ *
+ * wbflush --
+ *
+ *     Return when the write buffer is empty.
+ *
+ *     wbflush()
+ *
+ * Results:
+ *     None.
+ *
+ * Side effects:
+ *     None.
+ *
+ *----------------------------------------------------------------------------
+ */
+LEAF(wbflush)
+       lbu     v0,0xa0000000
+       nop
+       j       ra
+       nop
+END(wbflush)
+
+
+/*--------------------------------------------------------------------------
+ *
+ * R3K_TLBWriteIndexed --
+ *
+ *     Write the given entry into the TLB at the given index.
+ *
+ *     R3K_TLBWriteIndexed(index, highEntry, lowEntry)
+ *             int index;
+ *             int highEntry;
+ *             int lowEntry;
+ *
+ * Results:
+ *     None.
+ *
+ * Side effects:
+ *     TLB entry set.
+ *
+ *--------------------------------------------------------------------------
+ */
+LEAF(R3K_TLBWriteIndexed)
+       mfc0    v1, COP_0_STATUS_REG            # Save the status register.
+       mtc0    zero, COP_0_STATUS_REG          # Disable interrupts
+       mfc0    t0, COP_0_TLB_HI                # Save the current PID.
+
+       sll     a0, a0, R3K_TLB_INDEX_SHIFT
+       mtc0    a0, COP_0_TLB_INDEX             # Set the index.
+       mtc0    a1, COP_0_TLB_HI                # Set up entry high.
+       mtc0    a2, COP_0_TLB_LO0               # Set up entry low.
+       nop
+       tlbwi                                   # Write the TLB
+
+       mtc0    t0, COP_0_TLB_HI                # Restore the PID.
+       j       ra
+       mtc0    v1, COP_0_STATUS_REG            # Restore the status register
+END(R3K_TLBWriteIndexed)
+
+/*--------------------------------------------------------------------------
+ *
+ * R3K_SetPID --
+ *
+ *     Write the given pid into the TLB pid reg.
+ *
+ *     R3K_SetPID(pid)
+ *             int pid;
+ *
+ * Results:
+ *     None.
+ *
+ * Side effects:
+ *     PID set in the entry hi register.
+ *
+ *--------------------------------------------------------------------------
+ */
+LEAF(R3K_SetPID)
+       sll     a0, a0, R3K_PID_SHIFT           # put PID in right spot
+       mtc0    a0, COP_0_TLB_HI                # Write the hi reg value
+       j       ra
+       nop
+END(R3K_SetPID)
+
+/*--------------------------------------------------------------------------
+ *
+ * R3K_TLBFlush --
+ *
+ *     Flush the "random" entries from the TLB.
+ *
+ *     R3K_TLBFlush()
+ *
+ * Results:
+ *     None.
+ *
+ * Side effects:
+ *     The TLB is flushed.
+ *
+ *--------------------------------------------------------------------------
+ */
+LEAF(R3K_TLBFlush)
+       mfc0    v1, COP_0_STATUS_REG            # Save the status register.
+       mtc0    zero, COP_0_STATUS_REG          # Disable interrupts
+       mfc0    t0, COP_0_TLB_HI                # Save the PID
+       li      t1, CACHED_MEMORY_ADDR          # invalid address
+       mtc0    t1, COP_0_TLB_HI                # Mark entry high as invalid
+       mtc0    zero, COP_0_TLB_LO0             # Zero out low entry.
+/*
+ * Align the starting value (t1) and the upper bound (t2).
+ */
+       li      t1, R3K_NUM_WIRED_ENTRIES << R3K_TLB_INDEX_SHIFT
+       li      t2, R3K_NUM_TLB_ENTRIES << R3K_TLB_INDEX_SHIFT
+1:
+       mtc0    t1, COP_0_TLB_INDEX             # Set the index register.
+       addu    t1, t1, 1 << R3K_TLB_INDEX_SHIFT # Increment index.
+       bne     t1, t2, 1b
+       tlbwi                                   # Write the TLB entry.
+
+       mtc0    t0, COP_0_TLB_HI                # Restore the PID
+       j       ra
+       mtc0    v1, COP_0_STATUS_REG            # Restore the status register
+END(R3K_TLBFlush)
+
+/*--------------------------------------------------------------------------
+ *
+ * R3K_TLBFlushAddr --
+ *
+ *     Flush any TLB entries for the given address and TLB PID.
+ *
+ *     R3K_TLBFlushAddr(highreg)
+ *             unsigned highreg;
+ *
+ * Results:
+ *     None.
+ *
+ * Side effects:
+ *     The process's page is flushed from the TLB.
+ *
+ *--------------------------------------------------------------------------
+ */
+LEAF(R3K_TLBFlushAddr)
+       mfc0    v1, COP_0_STATUS_REG            # Save the status register.
+       mtc0    zero, COP_0_STATUS_REG          # Disable interrupts
+       mfc0    t0, COP_0_TLB_HI                # Get current PID
+       nop
+
+       mtc0    a0, COP_0_TLB_HI                # look for addr & PID
+       nop
+       tlbp                                    # Probe for the entry.
+       mfc0    v0, COP_0_TLB_INDEX             # See what we got
+       li      t1, CACHED_MEMORY_ADDR          # Load invalid entry.
+       bltz    v0, 1f                          # index < 0 => !found
+       mtc0    t1, COP_0_TLB_HI                # Mark entry high as invalid
+       mtc0    zero, COP_0_TLB_LO0             # Zero out low entry.
+       nop
+       tlbwi
+1:
+       mtc0    t0, COP_0_TLB_HI                # restore PID
+       j       ra
+       mtc0    v1, COP_0_STATUS_REG            # Restore the status register
+END(R3K_TLBFlushAddr)
+
+/*--------------------------------------------------------------------------
+ *
+ * R3K_TLBUpdate --
+ *
+ *     Update the TLB if highreg is found; otherwise, enter the data.
+ *
+ *     R3K_TLBUpdate(highreg, lowreg)
+ *             unsigned highreg, lowreg;
+ *
+ * Results:
+ *     None.
+ *
+ * Side effects:
+ *     None.
+ *
+ *--------------------------------------------------------------------------
+ */
+LEAF(R3K_TLBUpdate)
+       mfc0    v1, COP_0_STATUS_REG            # Save the status register.
+       mtc0    zero, COP_0_STATUS_REG          # Disable interrupts
+       mfc0    t0, COP_0_TLB_HI                # Save current PID
+       nop                                     # 2 cycles before intr disabled
+       mtc0    a0, COP_0_TLB_HI                # init high reg.
+       nop
+       tlbp                                    # Probe for the entry.
+       mfc0    v0, COP_0_TLB_INDEX             # See what we got
+       mtc0    a1, COP_0_TLB_LO0               # init low reg.
+       bltz    v0, 1f                          # index < 0 => !found
+       sra     v0, v0, R3K_TLB_INDEX_SHIFT     # convert index to regular num
+       b       2f
+       tlbwi                                   # update slot found
+1:
+       mtc0    a0, COP_0_TLB_HI                # init high reg.
+       nop
+       tlbwr                                   # enter into a random slot
+2:
+       mtc0    t0, COP_0_TLB_HI                # restore PID
+       j       ra
+       mtc0    v1, COP_0_STATUS_REG            # Restore the status register
+END(R3K_TLBUpdate)
+
+/*--------------------------------------------------------------------------
+ *
+ * R3K_TLBFind --
+ *
+ *     Search the TLB for the given entry.
+ *
+ *     R3K_TLBFind(hi)
+ *             unsigned hi;
+ *
+ * Results:
+ *     Returns a value >= 0 if the entry was found (the index).
+ *     Returns a value < 0 if the entry was not found.
+ *
+ * Side effects:
+ *     tlbhi and tlblo will contain the TLB entry found.
+ *
+ *--------------------------------------------------------------------------
+ */
+       .comm   tlbhi, 4
+       .comm   tlblo, 4
+LEAF(R3K_TLBFind)
+       mfc0    v1, COP_0_STATUS_REG            # Save the status register.
+       mtc0    zero, COP_0_STATUS_REG          # Disable interrupts
+       mfc0    t0, COP_0_TLB_HI                # Get current PID
+       nop
+       mtc0    a0, COP_0_TLB_HI                # Set up entry high.
+       nop
+       tlbp                                    # Probe for the entry.
+       mfc0    v0, COP_0_TLB_INDEX             # See what we got
+       nop
+       bltz    v0, 1f                          # not found
+       nop
+       tlbr                                    # read TLB
+       mfc0    t1, COP_0_TLB_HI                # See what we got
+       mfc0    t2, COP_0_TLB_LO0               # See what we got
+       sw      t1, tlbhi
+       sw      t2, tlblo
+       srl     v0, v0, R3K_TLB_INDEX_SHIFT     # convert index to regular num
+1:
+       mtc0    t0, COP_0_TLB_HI                # Restore current PID
+       j       ra
+       mtc0    v1, COP_0_STATUS_REG            # Restore the status register
+END(R3K_TLBFind)
+
+/*--------------------------------------------------------------------------
+ *
+ * R3K_TLBRead --
+ *
+ *     Read the TLB entry.
+ *
+ *     R3K_TLBRead(entry)
+ *             unsigned entry;
+ *
+ * Results:
+ *     None.
+ *
+ * Side effects:
+ *     tlbhi and tlblo will contain the TLB entry found.
+ *
+ *--------------------------------------------------------------------------
+ */
+LEAF(R3K_TLBRead)
+       mfc0    v1, COP_0_STATUS_REG            # Save the status register.
+       mtc0    zero, COP_0_STATUS_REG          # Disable interrupts
+       mfc0    t0, COP_0_TLB_HI                # Get current PID
+
+       sll     a0, a0, R3K_TLB_INDEX_SHIFT
+       mtc0    a0, COP_0_TLB_INDEX             # Set the index register
+       nop
+       tlbr                                    # Read from the TLB
+       mfc0    t3, COP_0_TLB_HI                # fetch the hi entry
+       mfc0    t4, COP_0_TLB_LO0               # fetch the low entry
+       sw      t3, tlbhi
+       sw      t4, tlblo
+
+       mtc0    t0, COP_0_TLB_HI                # restore PID
+       j       ra
+       mtc0    v1, COP_0_STATUS_REG    # Restore the status register
+END(R3K_TLBRead)
+
+/*--------------------------------------------------------------------------
+ *
+ * R3K_TLBGetPID --
+ *
+ *     R3K_TLBGetPID()
+ *
+ * Results:
+ *     Returns the current TLB pid reg.
+ *
+ * Side effects:
+ *     None.
+ *
+ *--------------------------------------------------------------------------
+ */
+LEAF(R3K_TLBGetPID)
+       mfc0    v0, COP_0_TLB_HI        # get PID
+       nop
+       and     v0, v0, R3K_PID_MASK    # mask off PID
+       j       ra
+       srl     v0, v0, R3K_PID_SHIFT   # put PID in right spot
+END(R3K_TLBGetPID)
+
+/*----------------------------------------------------------------------------
+ *
+ * R3K_ConfigCache --
+ *
+ *     Size the caches.
+ *     NOTE: should only be called from mips_init().
+ *
+ * Results:
+ *             None.
+ *
+ * Side effects:
+ *     The size of the data cache is stored into CpuPrimaryDataCacheSize and
+ *     the size of instruction cache is stored into CpuPrimaryInstCacheSize.
+ *
+ *----------------------------------------------------------------------------
+ */
+NON_LEAF(R3K_ConfigCache, STAND_FRAME_SIZE, ra)
+       subu    sp, sp, STAND_FRAME_SIZE
+       sw      ra, STAND_RA_OFFSET(sp)         # Save return address.
+       .mask   0x80000000, (STAND_RA_OFFSET - STAND_FRAME_SIZE)
+       mtc0    zero, COP_0_STATUS_REG          # Disable interrupts.
+       la      v0, 1f
+       or      v0, UNCACHED_MEMORY_ADDR        # Run uncached.
+       j       v0
+       nop
+1:
+/*
+ * This works because jal doesn't change pc[31..28] and the
+ * linker still thinks SizeCache is in the cached region so it computes
+ * the correct address without complaining.
+ */
+       jal     R3K_SizeCache                   # Get the size of the d-cache.
+       nop
+       sw      v0, CpuPrimaryDataCacheSize
+       nop                                     # Make sure sw out of pipe
+       nop
+       nop
+       nop
+       li      v0, SR_SWAP_CACHES              # Swap caches
+       mtc0    v0, COP_0_STATUS_REG
+       nop                                     # Insure caches stable
+       nop
+       nop
+       nop
+       jal     R3K_SizeCache                   # Get the size of the i-cache.
+       nop
+       mtc0    zero, COP_0_STATUS_REG          # Swap back caches and enable.
+       nop
+       nop
+       nop
+       nop
+       sw      v0, CpuPrimaryInstCacheSize
+       la      t0, 1f
+       j       t0                              # Back to cached mode
+       nop
+1:
+       lw      ra, STAND_RA_OFFSET(sp)         # Restore return addr
+       addu    sp, sp, STAND_FRAME_SIZE        # Restore sp.
+       j       ra
+       nop
+END(R3K_ConfigCache)
+
+/*----------------------------------------------------------------------------
+ *
+ * R3K_SizeCache --
+ *
+ *     Get the size of the cache.
+ *
+ * Results:
+ *     The size of the cache.
+ *
+ * Side effects:
+ *     None.
+ *
+ *----------------------------------------------------------------------------
+ */
+LEAF(R3K_SizeCache)
+       mfc0    t0, COP_0_STATUS_REG            # Save the current status reg.
+       nop
+       or      v0, t0, SR_ISOL_CACHES          # Isolate the caches.
+       nop                                     # Make sure no stores in pipe
+       mtc0    v0, COP_0_STATUS_REG
+       nop                                     # Make sure isolated
+       nop
+       nop
+/*
+ * Clear cache size boundaries.
+ */
+       li      v0, MIN_CACHE_SIZE
+       li      v1, CACHED_MEMORY_ADDR
+       li      t2, MAX_CACHE_SIZE
+1:
+       addu    t1, v0, v1                      # Compute address to clear
+       sw      zero, 0(t1)                     # Clear cache memory
+       bne     v0, t2, 1b
+       sll     v0, v0, 1
+
+       li      v0, -1
+       sw      v0, 0(v1)                       # Store marker in cache
+       li      v0, MIN_CACHE_SIZE
+2:
+       addu    t1, v0, v1                      # Compute address
+       lw      t3, 0(t1)                       # Look for marker
+       nop
+       bne     t3, zero, 3f                    # Found marker.
+       nop
+       bne     v0, t2, 2b                      # keep looking
+       sll     v0, v0, 1                       # cache size * 2
+
+       move    v0, zero                        # must be no cache
+3:
+       mtc0    t0, COP_0_STATUS_REG
+       nop                                     # Make sure unisolated
+       nop
+       nop
+       nop
+       j       ra
+       nop
+END(R3K_SizeCache)
+
+/*----------------------------------------------------------------------------
+ *
+ * R3K_FlushCache --
+ *
+ *     Flush the caches.
+ *
+ * Results:
+ *     None.
+ *
+ * Side effects:
+ *     The contents of the caches is flushed.
+ *
+ *----------------------------------------------------------------------------
+ */
+LEAF(R3K_FlushCache)
+       lw      t1, CpuPrimaryInstCacheSize     # Must load before isolating
+       lw      t2, CpuPrimaryDataCacheSize     # Must load before isolating
+       mfc0    t3, COP_0_STATUS_REG            # Save the status register.
+       mtc0    zero, COP_0_STATUS_REG          # Disable interrupts.
+       la      v0, 1f
+       or      v0, UNCACHED_MEMORY_ADDR        # Run uncached.
+       j       v0
+       nop
+/*
+ * Flush the instruction cache.
+ */
+1:
+       li      v0, SR_ISOL_CACHES | SR_SWAP_CACHES
+       mtc0    v0, COP_0_STATUS_REG            # Isolate and swap caches.
+       li      t0, UNCACHED_MEMORY_ADDR
+       subu    t0, t0, t1
+       li      t1, UNCACHED_MEMORY_ADDR
+       la      v0, 1f                          # Run cached
+       j       v0
+       nop
+1:
+       addu    t0, t0, 4
+       bne     t0, t1, 1b
+       sb      zero, -4(t0)
+
+       la      v0, 1f
+       or      v0, UNCACHED_MEMORY_ADDR
+       j       v0                              # Run uncached
+       nop
+/*
+ * Flush the data cache.
+ */
+1:
+       li      v0, SR_ISOL_CACHES
+       mtc0    v0, COP_0_STATUS_REG            # Isolate and swap back caches
+       li      t0, UNCACHED_MEMORY_ADDR
+       subu    t0, t0, t2
+       la      v0, 1f
+       j       v0                              # Back to cached mode
+       nop
+1:
+       addu    t0, t0, 4
+       bne     t0, t1, 1b
+       sb      zero, -4(t0)
+
+       nop                                     # Insure isolated stores
+       nop                                     #   out of pipe.
+       nop
+       nop
+       mtc0    t3, COP_0_STATUS_REG            # Restore status reg.
+       nop                                     # Insure cache unisolated.
+       nop
+       nop
+       nop
+       j       ra
+       nop
+END(R3K_FlushCache)
+
+/*----------------------------------------------------------------------------
+ *
+ * R3K_FlushICache --
+ *
+ *     void R3K_FlushICache(addr, len)
+ *             vm_offset_t addr, len;
+ *
+ *     Flush instruction cache for range of addr to addr + len - 1.
+ *     The address can be any valid address so long as no TLB misses occur.
+ *
+ * Results:
+ *     Returns zero.
+ *
+ * Side effects:
+ *     The contents of the cache is flushed.
+ *
+ *----------------------------------------------------------------------------
+ */
+LEAF(R3K_FlushICache)
+       mfc0    t0, COP_0_STATUS_REG            # Save SR
+       mtc0    zero, COP_0_STATUS_REG          # Disable interrupts.
+
+       la      v1, 1f
+       or      v1, UNCACHED_MEMORY_ADDR        # Run uncached.
+       j       v1
+       nop
+
+1:
+       lbu     v1, 0xa0000000                  # make sure stores are complete
+# XXX is executing from uncached sufficient so the above can be skipped?
+       li      v1, SR_ISOL_CACHES | SR_SWAP_CACHES
+       mtc0    v1, COP_0_STATUS_REG
+       nop
+       addu    a1, a1, a0                      # compute ending address
+2:
+       addu    a0, a0, 4
+       bne     a0, a1, 2b
+       sb      zero, -4(a0)
+
+       mtc0    t0, COP_0_STATUS_REG            # enable interrupts
+       j       ra                              # return and run cached
+       li      v0, 0
+END(R3K_FlushICache)
+
+/*----------------------------------------------------------------------------
+ *
+ * R3K_FlushDCache --
+ *
+ *     void R3K_FlushDCache(addr, len)
+ *             vm_offset_t addr, len;
+ *
+ *     Flush data cache for range of addr to addr + len - 1.
+ *     The address can be any valid address so long as no TLB misses occur.
+ *     (Be sure to use cached K0SEG kernel addresses)
+ * Results:
+ *     None.
+ *
+ * Side effects:
+ *     The contents of the cache is flushed.
+ *
+ *----------------------------------------------------------------------------
+ */
+LEAF(R3K_FlushDCache)
+ALEAF(R3K_HitFlushDCache)
+       mfc0    t0, COP_0_STATUS_REG            # Save SR
+       mtc0    zero, COP_0_STATUS_REG          # Disable interrupts.
+       nop
+
+       lbu     v1, 0xa0000000                  # make sure stores are complete
+
+       li      v1, SR_ISOL_CACHES
+       mtc0    v1, COP_0_STATUS_REG
+       nop
+       addu    t1, a1, a0                      # compute ending address
+1:
+       sb      zero, 0(a0)
+       sb      zero, 4(a0)
+       sb      zero, 8(a0)
+       sb      zero, 12(a0)
+       sb      zero, 16(a0)
+       sb      zero, 20(a0)
+       sb      zero, 24(a0)
+       addu    a0, 32
+       bltu    a0, t1, 1b
+       sb      zero, -4(a0)
+
+       nop                                     # drain pipeline
+       nop
+       mtc0    t0, COP_0_STATUS_REG            # enable interrupts
+       nop
+       j       ra                              # return and run cached
+       nop
+END(R3K_FlushDCache)
+
+#endif         /* ==================XXXXX============================== */
+
+/*
+ * Set/clear software interrupt routines.
+ */
+
+LEAF(setsoftclock)
+       mfc0    v0, COP_0_CAUSE_REG     # read cause register
+       nop
+       or      v0, v0, SOFT_INT_MASK_0 # set soft clock interrupt
+       mtc0    v0, COP_0_CAUSE_REG     # save it
+       j       ra
+       nop
+END(setsoftclock)
+
+LEAF(clearsoftclock)
+       mfc0    v0, COP_0_CAUSE_REG     # read cause register
+       nop
+       and     v0, v0, ~SOFT_INT_MASK_0        # clear soft clock interrupt
+       mtc0    v0, COP_0_CAUSE_REG     # save it
+       j       ra
+       nop
+END(clearsoftclock)
+
+LEAF(setsoftnet)
+       mfc0    v0, COP_0_CAUSE_REG     # read cause register
+       nop
+       or      v0, v0, SOFT_INT_MASK_1 # set soft net interrupt
+       mtc0    v0, COP_0_CAUSE_REG     # save it
+       j       ra
+       nop
+END(setsoftnet)
+
+LEAF(clearsoftnet)
+       mfc0    v0, COP_0_CAUSE_REG     # read cause register
+       nop
+       and     v0, v0, ~SOFT_INT_MASK_1        # clear soft net interrupt
+       mtc0    v0, COP_0_CAUSE_REG     # save it
+       j       ra
+       nop
+END(clearsoftnet)
+
+/*
+ * Set/change interrupt priority routines.
+ */
+
+LEAF(CPU_EnableIntr)
+       mfc0    v0, COP_0_STATUS_REG    # read status register
+       nop
+       or      v0, v0, SR_INT_ENAB
+       mtc0    v0, COP_0_STATUS_REG    # enable all interrupts
+       j       ra
+       nop
+END(CPU_EnableIntr)
+
+LEAF(spl0)
+       mfc0    v0, COP_0_STATUS_REG    # read status register
+       nop
+       or      t0, v0, (INT_MASK | SR_INT_ENAB)
+       mtc0    t0, COP_0_STATUS_REG    # enable all interrupts
+       j       ra
+       and     v0, v0, (INT_MASK | SR_INT_ENAB)
+END(spl0)
+
+LEAF(splsoftclock)
+       mfc0    v0, COP_0_STATUS_REG    # read status register
+       li      t0, ~SOFT_INT_MASK_0    # disable soft clock
+       and     t0, t0, v0
+       mtc0    t0, COP_0_STATUS_REG    # save it
+       nop                                     # 3 ins to disable
+       j       ra
+       and     v0, v0, (INT_MASK | SR_INT_ENAB)
+END(splsoftclock)
+
+LEAF(splsoftnet)
+       mfc0    v0, COP_0_STATUS_REG    # read status register
+       li      t0, ~(SOFT_INT_MASK_1|SOFT_INT_MASK_0)
+       and     t0, t0, v0
+       mtc0    t0, COP_0_STATUS_REG    # save it
+       j       ra
+       and     v0, v0, (INT_MASK | SR_INT_ENAB)
+END(splsoftnet)
+
+LEAF(CPU__spl0)
+       mfc0    v0, COP_0_STATUS_REG    # read status register
+       li      t0, ~(INT_MASK_0|SOFT_INT_MASK_1|SOFT_INT_MASK_0)
+       and     t0, t0, v0
+       mtc0    t0, COP_0_STATUS_REG    # save it
+       nop                                     # 3 ins to disable
+       j       ra
+       and     v0, v0, (INT_MASK | SR_INT_ENAB)
+END(CPU__spl0)
+
+LEAF(CPU__spl1)
+       mfc0    v0, COP_0_STATUS_REG    # read status register
+       li      t0, ~(INT_MASK_1|SOFT_INT_MASK_0|SOFT_INT_MASK_1)
+       and     t0, t0, v0
+       mtc0    t0, COP_0_STATUS_REG    # save it
+       nop                                     # 3 ins to disable
+       j       ra
+       and     v0, v0, (INT_MASK | SR_INT_ENAB)
+END(CPU__spl1)
+
+LEAF(CPU__spl2)
+       mfc0    v0, COP_0_STATUS_REG    # read status register
+       li      t0, ~(INT_MASK_2|SOFT_INT_MASK_1|SOFT_INT_MASK_0)
+       and     t0, t0, v0
+       mtc0    t0, COP_0_STATUS_REG    # save it
+       nop                                     # 3 ins to disable
+       j       ra
+       and     v0, v0, (INT_MASK | SR_INT_ENAB)
+END(CPU__spl2)
+
+LEAF(CPU__spl3)
+       mfc0    v0, COP_0_STATUS_REG    # read status register
+       li      t0, ~(INT_MASK_3|SOFT_INT_MASK_1|SOFT_INT_MASK_0)
+       and     t0, t0, v0
+       mtc0    t0, COP_0_STATUS_REG    # save it
+       nop                                     # 3 ins to disable
+       j       ra
+       and     v0, v0, (INT_MASK | SR_INT_ENAB)
+END(CPU__spl3)
+
+LEAF(CPU__spl4)
+       mfc0    v0, COP_0_STATUS_REG    # read status register
+       li      t0, ~(INT_MASK_4|SOFT_INT_MASK_1|SOFT_INT_MASK_0)
+       and     t0, t0, v0
+       mtc0    t0, COP_0_STATUS_REG    # save it
+       nop                                     # 3 ins to disable
+       j       ra
+       and     v0, v0, (INT_MASK | SR_INT_ENAB)
+END(CPU__spl4)
+
+LEAF(CPU__spl5)
+       mfc0    v0, COP_0_STATUS_REG    # read status register
+       li      t0, ~(INT_MASK_5|SOFT_INT_MASK_1|SOFT_INT_MASK_0)
+       and     t0, t0, v0
+       mtc0    t0, COP_0_STATUS_REG    # save it
+       nop                                     # 3 ins to disable
+       j       ra
+       and     v0, v0, (INT_MASK | SR_INT_ENAB)
+END(CPU__spl5)
+
+/*
+ * We define an alternate entry point after mcount is called so it
+ * can be used in mcount without causeing a recursive loop.
+ */
+LEAF(splhigh)
+ALEAF(_splhigh)
+       mfc0    v0, COP_0_STATUS_REG    # read status register
+       li      t0, ~SR_INT_ENAB        # disable all interrupts
+       and     t0, t0, v0
+       mtc0    t0, COP_0_STATUS_REG    # save it
+       nop                                     # 3 ins to disable
+       j       ra
+       and     v0, v0, (INT_MASK | SR_INT_ENAB)
+END(splhigh)
+
+/*
+ * Restore saved interrupt mask.
+ */
+LEAF(splx)
+ALEAF(_splx)
+       mfc0    v0, COP_0_STATUS_REG
+       li      t0, ~(INT_MASK | SR_INT_ENAB)
+       and     t0, t0, v0
+       or      t0, t0, a0
+       mtc0    t0, COP_0_STATUS_REG
+       nop                                     # 3 ins to disable
+       j       ra
+       nop
+END(splx)
+
+/*----------------------------------------------------------------------------
+ *
+ * CPU_SwitchFPState --
+ *
+ *     Save the current state into 'from' and restore it from 'to'.
+ *
+ *     CPU_SwitchFPState(from, to)
+ *             struct proc *from;
+ *             struct user *to;
+ *
+ * Results:
+ *     None.
+ *
+ * Side effects:
+ *     None.
+ *
+ *----------------------------------------------------------------------------
+ */
+LEAF(CPU_SwitchFPState)
+       mfc0    t1, COP_0_STATUS_REG    # Save old SR
+       li      t0, SR_COP_1_BIT        # enable the coprocessor
+       mtc0    t0, COP_0_STATUS_REG
+
+       beq     a0, zero, 1f            # skip save if NULL pointer
+       nop
+/*
+ * First read out the status register to make sure that all FP operations
+ * have completed.
+ */
+       lw      a0, P_ADDR(a0)          # get pointer to pcb for proc
+       cfc1    t0, FPC_CSR             # stall til FP done
+       cfc1    t0, FPC_CSR             # now get status
+       li      t3, ~SR_COP_1_BIT
+       lw      t2, U_PCB_REGS+(PS * 4)(a0)     # get CPU status register
+       sw      t0, U_PCB_FPREGS+(32 * 4)(a0)   # save FP status
+       and     t2, t2, t3                      # clear COP_1 enable bit
+       sw      t2, U_PCB_REGS+(PS * 4)(a0)     # save new status register
+/*
+ * Save the floating point registers.
+ */
+       swc1    $f0, U_PCB_FPREGS+(0 * 4)(a0)
+       swc1    $f1, U_PCB_FPREGS+(1 * 4)(a0)
+       swc1    $f2, U_PCB_FPREGS+(2 * 4)(a0)
+       swc1    $f3, U_PCB_FPREGS+(3 * 4)(a0)
+       swc1    $f4, U_PCB_FPREGS+(4 * 4)(a0)
+       swc1    $f5, U_PCB_FPREGS+(5 * 4)(a0)
+       swc1    $f6, U_PCB_FPREGS+(6 * 4)(a0)
+       swc1    $f7, U_PCB_FPREGS+(7 * 4)(a0)
+       swc1    $f8, U_PCB_FPREGS+(8 * 4)(a0)
+       swc1    $f9, U_PCB_FPREGS+(9 * 4)(a0)
+       swc1    $f10, U_PCB_FPREGS+(10 * 4)(a0)
+       swc1    $f11, U_PCB_FPREGS+(11 * 4)(a0)
+       swc1    $f12, U_PCB_FPREGS+(12 * 4)(a0)
+       swc1    $f13, U_PCB_FPREGS+(13 * 4)(a0)
+       swc1    $f14, U_PCB_FPREGS+(14 * 4)(a0)
+       swc1    $f15, U_PCB_FPREGS+(15 * 4)(a0)
+       swc1    $f16, U_PCB_FPREGS+(16 * 4)(a0)
+       swc1    $f17, U_PCB_FPREGS+(17 * 4)(a0)
+       swc1    $f18, U_PCB_FPREGS+(18 * 4)(a0)
+       swc1    $f19, U_PCB_FPREGS+(19 * 4)(a0)
+       swc1    $f20, U_PCB_FPREGS+(20 * 4)(a0)
+       swc1    $f21, U_PCB_FPREGS+(21 * 4)(a0)
+       swc1    $f22, U_PCB_FPREGS+(22 * 4)(a0)
+       swc1    $f23, U_PCB_FPREGS+(23 * 4)(a0)
+       swc1    $f24, U_PCB_FPREGS+(24 * 4)(a0)
+       swc1    $f25, U_PCB_FPREGS+(25 * 4)(a0)
+       swc1    $f26, U_PCB_FPREGS+(26 * 4)(a0)
+       swc1    $f27, U_PCB_FPREGS+(27 * 4)(a0)
+       swc1    $f28, U_PCB_FPREGS+(28 * 4)(a0)
+       swc1    $f29, U_PCB_FPREGS+(29 * 4)(a0)
+       swc1    $f30, U_PCB_FPREGS+(30 * 4)(a0)
+       swc1    $f31, U_PCB_FPREGS+(31 * 4)(a0)
+
+1:
+/*
+ *  Restore the floating point registers.
+ */
+       lw      t0, U_PCB_FPREGS+(32 * 4)(a1)   # get status register
+       lwc1    $f0, U_PCB_FPREGS+(0 * 4)(a1)
+       lwc1    $f1, U_PCB_FPREGS+(1 * 4)(a1)
+       lwc1    $f2, U_PCB_FPREGS+(2 * 4)(a1)
+       lwc1    $f3, U_PCB_FPREGS+(3 * 4)(a1)
+       lwc1    $f4, U_PCB_FPREGS+(4 * 4)(a1)
+       lwc1    $f5, U_PCB_FPREGS+(5 * 4)(a1)
+       lwc1    $f6, U_PCB_FPREGS+(6 * 4)(a1)
+       lwc1    $f7, U_PCB_FPREGS+(7 * 4)(a1)
+       lwc1    $f8, U_PCB_FPREGS+(8 * 4)(a1)
+       lwc1    $f9, U_PCB_FPREGS+(9 * 4)(a1)
+       lwc1    $f10, U_PCB_FPREGS+(10 * 4)(a1)
+       lwc1    $f11, U_PCB_FPREGS+(11 * 4)(a1)
+       lwc1    $f12, U_PCB_FPREGS+(12 * 4)(a1)
+       lwc1    $f13, U_PCB_FPREGS+(13 * 4)(a1)
+       lwc1    $f14, U_PCB_FPREGS+(14 * 4)(a1)
+       lwc1    $f15, U_PCB_FPREGS+(15 * 4)(a1)
+       lwc1    $f16, U_PCB_FPREGS+(16 * 4)(a1)
+       lwc1    $f17, U_PCB_FPREGS+(17 * 4)(a1)
+       lwc1    $f18, U_PCB_FPREGS+(18 * 4)(a1)
+       lwc1    $f19, U_PCB_FPREGS+(19 * 4)(a1)
+       lwc1    $f20, U_PCB_FPREGS+(20 * 4)(a1)
+       lwc1    $f21, U_PCB_FPREGS+(21 * 4)(a1)
+       lwc1    $f22, U_PCB_FPREGS+(22 * 4)(a1)
+       lwc1    $f23, U_PCB_FPREGS+(23 * 4)(a1)
+       lwc1    $f24, U_PCB_FPREGS+(24 * 4)(a1)
+       lwc1    $f25, U_PCB_FPREGS+(25 * 4)(a1)
+       lwc1    $f26, U_PCB_FPREGS+(26 * 4)(a1)
+       lwc1    $f27, U_PCB_FPREGS+(27 * 4)(a1)
+       lwc1    $f28, U_PCB_FPREGS+(28 * 4)(a1)
+       lwc1    $f29, U_PCB_FPREGS+(29 * 4)(a1)
+       lwc1    $f30, U_PCB_FPREGS+(30 * 4)(a1)
+       lwc1    $f31, U_PCB_FPREGS+(31 * 4)(a1)
+
+       and     t0, t0, ~FPC_EXCEPTION_BITS
+       ctc1    t0, FPC_CSR
+       nop
+
+       mtc0    t1, COP_0_STATUS_REG    # Restore the status register.
+       j       ra
+       nop
+END(CPU_SwitchFPState)
+
+/*----------------------------------------------------------------------------
+ *
+ * CPU_SaveCurFPState --
+ *
+ *     Save the current floating point coprocessor state.
+ *
+ *     CPU_SaveCurFPState(p)
+ *             struct proc *p;
+ *
+ * Results:
+ *     None.
+ *
+ * Side effects:
+ *     cpuFPCurProcPtr is cleared.
+ *
+ *----------------------------------------------------------------------------
+ */
+LEAF(CPU_SaveCurFPState)
+       lw      a0, P_ADDR(a0)                  # get pointer to pcb for proc
+       mfc0    t1, COP_0_STATUS_REG    # Disable interrupts and
+       li      t0, SR_COP_1_BIT                #  enable the coprocessor
+       mtc0    t0, COP_0_STATUS_REG
+       sw      zero, cpuFPCurProcPtr           # indicate state has been saved
+/*
+ * First read out the status register to make sure that all FP operations
+ * have completed.
+ */
+       lw      t2, U_PCB_REGS+(PS * 4)(a0)     # get CPU status register
+       li      t3, ~SR_COP_1_BIT
+       and     t2, t2, t3                      # clear COP_1 enable bit
+       cfc1    t0, FPC_CSR             # stall til FP done
+       cfc1    t0, FPC_CSR             # now get status
+       sw      t2, U_PCB_REGS+(PS * 4)(a0)     # save new status register
+       sw      t0, U_PCB_FPREGS+(32 * 4)(a0)   # save FP status
+/*
+ * Save the floating point registers.
+ */
+       swc1    $f0, U_PCB_FPREGS+(0 * 4)(a0)
+       swc1    $f1, U_PCB_FPREGS+(1 * 4)(a0)
+       swc1    $f2, U_PCB_FPREGS+(2 * 4)(a0)
+       swc1    $f3, U_PCB_FPREGS+(3 * 4)(a0)
+       swc1    $f4, U_PCB_FPREGS+(4 * 4)(a0)
+       swc1    $f5, U_PCB_FPREGS+(5 * 4)(a0)
+       swc1    $f6, U_PCB_FPREGS+(6 * 4)(a0)
+       swc1    $f7, U_PCB_FPREGS+(7 * 4)(a0)
+       swc1    $f8, U_PCB_FPREGS+(8 * 4)(a0)
+       swc1    $f9, U_PCB_FPREGS+(9 * 4)(a0)
+       swc1    $f10, U_PCB_FPREGS+(10 * 4)(a0)
+       swc1    $f11, U_PCB_FPREGS+(11 * 4)(a0)
+       swc1    $f12, U_PCB_FPREGS+(12 * 4)(a0)
+       swc1    $f13, U_PCB_FPREGS+(13 * 4)(a0)
+       swc1    $f14, U_PCB_FPREGS+(14 * 4)(a0)
+       swc1    $f15, U_PCB_FPREGS+(15 * 4)(a0)
+       swc1    $f16, U_PCB_FPREGS+(16 * 4)(a0)
+       swc1    $f17, U_PCB_FPREGS+(17 * 4)(a0)
+       swc1    $f18, U_PCB_FPREGS+(18 * 4)(a0)
+       swc1    $f19, U_PCB_FPREGS+(19 * 4)(a0)
+       swc1    $f20, U_PCB_FPREGS+(20 * 4)(a0)
+       swc1    $f21, U_PCB_FPREGS+(21 * 4)(a0)
+       swc1    $f22, U_PCB_FPREGS+(22 * 4)(a0)
+       swc1    $f23, U_PCB_FPREGS+(23 * 4)(a0)
+       swc1    $f24, U_PCB_FPREGS+(24 * 4)(a0)
+       swc1    $f25, U_PCB_FPREGS+(25 * 4)(a0)
+       swc1    $f26, U_PCB_FPREGS+(26 * 4)(a0)
+       swc1    $f27, U_PCB_FPREGS+(27 * 4)(a0)
+       swc1    $f28, U_PCB_FPREGS+(28 * 4)(a0)
+       swc1    $f29, U_PCB_FPREGS+(29 * 4)(a0)
+       swc1    $f30, U_PCB_FPREGS+(30 * 4)(a0)
+       swc1    $f31, U_PCB_FPREGS+(31 * 4)(a0)
+
+       mtc0    t1, COP_0_STATUS_REG    # Restore the status register.
+       j       ra
+       nop
+END(CPU_SaveCurFPState)
+
+/*----------------------------------------------------------------------------
+ *
+ * CPU_FPTrap --
+ *
+ *     Handle a floating point Trap.
+ *
+ *     CPU_FPTrap(statusReg, causeReg, pc)
+ *             unsigned statusReg;
+ *             unsigned causeReg;
+ *             unsigned pc;
+ *
+ * Results:
+ *     None.
+ *
+ * Side effects:
+ *     None.
+ *
+ *----------------------------------------------------------------------------
+ */
+NON_LEAF(CPU_FPTrap, STAND_FRAME_SIZE, ra)
+       subu    sp, sp, STAND_FRAME_SIZE
+       mfc0    t0, COP_0_STATUS_REG
+       sw      ra, STAND_RA_OFFSET(sp)
+       .mask   0x80000000, (STAND_RA_OFFSET - STAND_FRAME_SIZE)
+
+       or      t1, t0, SR_COP_1_BIT
+       mtc0    t1, COP_0_STATUS_REG
+       nop
+       nop
+       nop
+       nop
+       cfc1    t1, FPC_CSR     # stall til FP done
+       cfc1    t1, FPC_CSR     # now get status
+       nop
+       sll     t2, t1, (31 - 17)       # unimplemented operation?
+       bgez    t2, 3f                  # no, normal trap
+       nop
+/*
+ * We got an unimplemented operation trap so
+ * fetch the instruction, compute the next PC and emulate the instruction.
+ */
+       bgez    a1, 1f                  # Check the branch delay bit.
+       nop
+/*
+ * The instruction is in the branch delay slot so the branch will have to
+ * be emulated to get the resulting PC.
+ */
+       sw      a2, STAND_FRAME_SIZE + 8(sp)
+       li      a0, UADDR+U_PCB_REGS            # first arg is ptr to CPU registers
+       move    a1, a2                          # second arg is instruction PC
+       move    a2, t1                          # third arg is floating point CSR
+       jal     CPU_EmulateBranch               # compute PC after branch
+       move    a3, zero                        # fourth arg is FALSE
+/*
+ * Now load the floating-point instruction in the branch delay slot
+ * to be emulated.
+ */
+       lw      a2, STAND_FRAME_SIZE + 8(sp)    # restore EXC pc
+       b       2f
+       lw      a0, 4(a2)                       # a0 = coproc instruction
+/*
+ * This is not in the branch delay slot so calculate the resulting
+ * PC (epc + 4) into v0 and continue to CPU_EmulateFP().
+ */
+1:
+       lw      a0, 0(a2)                       # a0 = coproc instruction
+       addu    v0, a2, 4                       # v0 = next pc
+2:
+       sw      v0, UADDR+U_PCB_REGS+(PC * 4)   # save new pc
+/*
+ * Check to see if the instruction to be emulated is a floating-point
+ * instruction.
+ */
+       srl     a3, a0, OPCODE_SHIFT
+       beq     a3, OPCODE_C1, 4f               # this should never fail
+       nop
+/*
+ * Send a floating point exception signal to the current process.
+ */
+3:
+       lw      a0, curproc                     # get current process
+       cfc1    a2, FPC_CSR             # code = FP execptions
+       ctc1    zero, FPC_CSR           # Clear exceptions
+       jal     trapsignal
+       li      a1, SIGFPE
+       b       FPReturn
+       nop
+
+/*
+ * Finally, we can call CPU_EmulateFP() where a0 is the instruction to emulate.
+ */
+4:
+       jal     CPU_EmulateFP
+       nop
+
+/*
+ * Turn off the floating point coprocessor and return.
+ */
+FPReturn:
+       mfc0    t0, COP_0_STATUS_REG
+       lw      ra, STAND_RA_OFFSET(sp)
+       and     t0, t0, ~SR_COP_1_BIT
+       mtc0    t0, COP_0_STATUS_REG
+       j       ra
+       addu    sp, sp, STAND_FRAME_SIZE
+END(CPU_FPTrap)
+
+#ifdef DEBUG
+/*
+ * Read a long and return it.
+ * Note: addresses can be unaligned!
+ *
+ * long
+L* mdbpeek(addr)
+L*     caddt_t addr;
+L* {
+L*     return (*(long *)addr);
+L* }
+ */
+LEAF(mdbpeek)
+       li      v0, MDBERR
+       sw      v0, UADDR+U_PCB_ONFAULT
+       and     v0, a0, 3               # unaligned address?
+       bne     v0, zero, 1f
+       nop
+       b       2f
+       lw      v0, (a0)                # aligned access
+1:
+       LWHI    v0, 0(a0)               # get next 4 bytes (unaligned)
+       LWLO    v0, 3(a0)
+2:
+       j       ra                      # made it w/o errors
+       sw      zero, UADDR+U_PCB_ONFAULT
+mdberr:
+       li      v0, 1                   # trap sends us here
+       sw      v0, mdbmkfault
+       j       ra
+       nop
+END(mdbpeek)
+
+/*
+ * Write a long to 'addr'.
+ * Note: addresses can be unaligned!
+ *
+L* void
+L* mdbpoke(addr, value)
+L*     caddt_t addr;
+L*     long value;
+L* {
+L*     *(long *)addr = value;
+L* }
+ */
+LEAF(mdbpoke)
+       li      v0, MDBERR
+       sw      v0, UADDR+U_PCB_ONFAULT
+       and     v0, a0, 3               # unaligned address?
+       bne     v0, zero, 1f
+       nop
+       b       2f
+       sw      a1, (a0)                # aligned access
+1:
+       SWHI    a1, 0(a0)               # store next 4 bytes (unaligned)
+       SWLO    a1, 3(a0)
+       and     a0, a0, ~3              # align address for cache flush
+2:
+       sw      zero, UADDR+U_PCB_ONFAULT
+#ifdef R4K
+       b       R4K_FlushICache         # flush instruction cache
+#else
+       b       R3K_FlushICache         # flush instruction cache
+#endif
+       li      a1, 8
+END(mdbpoke)
+
+/*
+ * Save registers and state so we can do a 'mdbreset' (like longjmp) later.
+ * Always returns zero.
+ *
+L* int mdb_savearea[11];
+L*
+L* int
+L* mdbsetexit()
+L* {
+L*     mdb_savearea[0] = 0;
+L*     return (0);
+L* }
+ */
+       .comm   mdb_savearea, (11 * 4)
+
+LEAF(mdbsetexit)
+       la      a0, mdb_savearea
+       sw      s0, 0(a0)
+       sw      s1, 4(a0)
+       sw      s2, 8(a0)
+       sw      s3, 12(a0)
+       sw      s4, 16(a0)
+       sw      s5, 20(a0)
+       sw      s6, 24(a0)
+       sw      s7, 28(a0)
+       sw      sp, 32(a0)
+       sw      s8, 36(a0)
+       sw      ra, 40(a0)
+       j       ra
+       move    v0, zero
+END(mdbsetexit)
+
+/*
+ * Restore registers and state (like longjmp) and return x.
+ *
+L* int
+L* mdbreset(x)
+L* {
+L*     return (x);
+L* }
+ */
+LEAF(mdbreset)
+       la      v0, mdb_savearea
+       lw      ra, 40(v0)
+       lw      s0, 0(v0)
+       lw      s1, 4(v0)
+       lw      s2, 8(v0)
+       lw      s3, 12(v0)
+       lw      s4, 16(v0)
+       lw      s5, 20(v0)
+       lw      s6, 24(v0)
+       lw      s7, 28(v0)
+       lw      sp, 32(v0)
+       lw      s8, 36(v0)
+       j       ra
+       move    v0, a0
+END(mdbreset)
+
+/*
+ * Trap into the debugger.
+ */
+LEAF(mdbpanic)
+       break   BREAK_SOVER_VAL
+       j       ra
+       nop
+END(mdbpanic)
+#endif /* DEBUG */
+
+#ifdef DEBUG
+LEAF(cpu_getregs)
+       sw      sp, 0(a0)
+       sw      ra, 4(a0)
+       j       ra
+       sw      s8, 8(a0)
+END(cpu_getregs)
+#endif /* DEBUG */
+
+/*
+ * Interrupt counters for vmstat.
+ */
+       .data
+       .globl intrcnt
+       .globl eintrcnt
+       .globl intrnames
+       .globl eintrnames
+intrnames:
+       .asciiz "softclock"
+       .asciiz "softnet"
+       .asciiz "local_dma"
+       .asciiz "local_dev"
+       .asciiz "isa_dev"
+       .asciiz "isa_nmi"
+       .asciiz "clock"
+       .asciiz "statclock"
+eintrnames:
+       .align  3
+intrcnt:
+       .word   0,0,0,0,0,0,0,0
+eintrcnt:
diff --git a/sys/arch/wgrisc/wgrisc/machdep.c b/sys/arch/wgrisc/wgrisc/machdep.c
new file mode 100644 (file)
index 0000000..8fd0d5a
--- /dev/null
@@ -0,0 +1,1060 @@
+/*     $OpenBSD: machdep.c,v 1.1.1.1 1997/02/06 16:02:46 pefo Exp $    */
+/*
+ * Copyright (c) 1988 University of Utah.
+ * Copyright (c) 1992, 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, The Mach Operating System project at
+ * Carnegie-Mellon University and Ralph Campbell.
+ *
+ * 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: @(#)machdep.c     8.3 (Berkeley) 1/12/94
+ *      $Id: machdep.c,v 1.1.1.1 1997/02/06 16:02:46 pefo Exp $
+ */
+
+/* from: Utah Hdr: machdep.c 1.63 91/04/24 */
+
+#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/user.h>
+#include <sys/exec.h>
+#include <sys/sysctl.h>
+#include <sys/mount.h>
+#include <sys/syscallargs.h>
+#ifdef SYSVSHM
+#include <sys/shm.h>
+#endif
+#ifdef SYSVSEM
+#include <sys/sem.h>
+#endif
+#ifdef SYSVMSG
+#include <sys/msg.h>
+#endif
+
+#include <vm/vm_kern.h>
+
+#include <machine/cpu.h>
+#include <machine/reg.h>
+#include <machine/pio.h>
+#include <machine/psl.h>
+#include <machine/pte.h>
+#include <machine/autoconf.h>
+#include <machine/memconf.h>
+
+#include <sys/exec_ecoff.h>
+
+#include <dev/cons.h>
+
+#include <wgrisc/wgrisc/wgrisctype.h>
+#include <wgrisc/riscbus/riscbus.h>
+
+extern struct consdev *cn_tab;
+
+/* the following is used externally (sysctl_hw) */
+char   machine[] = "wgrisc";   /* cpu "architecture" */
+char   cpu_model[30];
+
+vm_map_t buffer_map;
+
+/*
+ * 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 = 0;       /* set when safe to use msgbuf */
+int    physmem;                /* max supported memory, changes to actual */
+int    cpucfg;                 /* Value of processor config register */
+int    cputype;                /* Mother board type */
+int    ncpu = 1;               /* At least one cpu in the system */
+int    isa_io_base;            /* Base address of ISA io port space */
+int    isa_mem_base;           /* Base address of ISA memory space */
+
+struct mem_descriptor mem_layout[MAXMEMSEGS];
+
+extern int Mach_spl0(), Mach_spl1(), Mach_spl2(), Mach_spl3();
+extern int Mach_spl4(), Mach_spl5(), splhigh();
+int    (*Mach_splnet)() = splhigh;
+int    (*Mach_splbio)() = splhigh;
+int    (*Mach_splimp)() = splhigh;
+int    (*Mach_spltty)() = splhigh;
+int    (*Mach_splclock)() = splhigh;
+int    (*Mach_splstatclock)() = splhigh;
+
+static void tlb_init_pica();
+static void tlb_init_tyne();
+
+
+/*
+ * safepri is a safe priority for sleep to set for a spin-wait
+ * during autoconfiguration or after a panic.
+ */
+int    safepri = PSL_LOWIPL;
+
+struct user *proc0paddr;
+struct proc nullproc;          /* for use by swtch_exit() */
+
+/*
+ * Do all the stuff that locore normally does before calling main().
+ * Process arguments passed to us by the BOOT.
+ * Reset mapping and set up mapping to hardware and init "wired" reg.
+ * Return the first page address following the system.
+ */
+mips_init(argc, argv, code)
+       int argc;
+       char *argv[];
+       u_int code;
+{
+       register char *cp;
+       register int i;
+       register unsigned firstaddr;
+       register caddr_t sysend;
+       caddr_t start;
+       struct tlb tlb;
+       extern char _ftext[], edata[], end[];
+
+       /* clear the BSS segment in OpenBSD code */
+       sysend = (caddr_t)mips_round_page(end);
+       bzero(edata, sysend - edata);
+
+       /* Initialize the CPU type */
+       cputype = WGRISC9100;
+       mem_layout[0].mem_start = 0;
+       mem_layout[0].mem_size = mips_trunc_page(CACHED_TO_PHYS(_ftext));
+       mem_layout[1].mem_start = CACHED_TO_PHYS((int)sysend);
+       mem_layout[1].mem_size = 0x400000 - (int)(CACHED_TO_PHYS(sysend));
+       physmem = 4096 * 1024;
+
+
+       switch (cputype) {
+       case WGRISC9100:
+               strcpy(cpu_model, "Willowglen RISC PC 9100");
+               isa_io_base = RISC_ISA_IO_BASE;
+               isa_mem_base = RISC_ISA_MEM_BASE;
+
+               /*
+                * Set up interrupt handling and I/O addresses.
+                */
+#if 0 /* XXX FIXME */
+               Mach_splnet = Mach_spl1;
+               Mach_splbio = Mach_spl0;
+               Mach_splimp = Mach_spl1;
+               Mach_spltty = Mach_spl2;
+               Mach_splstatclock = Mach_spl3;
+#endif
+               break;
+
+       default:
+               boot(RB_HALT | RB_NOSYNC);
+       }
+       physmem = btoc(physmem);
+
+       /* look at argv[0] and compute bootdev for autoconfig setup */
+       makebootdev(argv[0]);
+
+       /*
+        * Look at arguments passed to us and compute boothowto.
+        * Default to SINGLE and ASKNAME if no args.
+        */
+       boothowto = RB_SINGLE | RB_ASKNAME;
+#ifdef KADB
+       boothowto |= RB_KDB;
+#endif
+       if (argc > 1) {
+               for (i = 1; i < argc; i++) {
+                       if(strncasecmp("osloadoptions=",argv[i],14) == 0) {
+                               for (cp = argv[i]+14; *cp; cp++) {
+                                       switch (*cp) {
+                                       case 'a': /* autoboot */
+                                               boothowto &= ~RB_SINGLE;
+                                               break;
+
+                                       case 'd': /* use compiled in default root */
+                                               boothowto |= RB_DFLTROOT;
+                                               break;
+
+                                       case 'm': /* mini root present in memory */
+                                               boothowto |= RB_MINIROOT;
+                                               break;
+
+                                       case 'n': /* ask for names */
+                                               boothowto |= RB_ASKNAME;
+                                               break;
+
+                                       case 'N': /* don't ask for names */
+                                               boothowto &= ~RB_ASKNAME;
+                                               break;
+                                       }
+
+                               }
+                       }
+               }
+       }
+
+#ifdef MFS
+       /*
+        * Check to see if a mini-root was loaded into memory. It resides
+        * at the start of the next page just after the end of BSS.
+        */
+       if (boothowto & RB_MINIROOT) {
+               boothowto |= RB_DFLTROOT;
+               sysend += mfs_initminiroot(sysend);
+       }
+#endif
+
+#ifdef R4K
+       R4K_SetWIRED(0);
+       R4K_TLBFlush();
+       R4K_SetWIRED(R4K_NUM_WIRED_ENTRIES);
+
+       switch (cputype) {
+       case ACER_PICA_61:
+               tlb_init_pica();
+               break;
+       }
+
+#else
+       R3K_TLBFlush();
+#endif
+       
+       /*
+        * Init mapping for u page(s) for proc[0], pm_tlbpid 1.
+        */
+       sysend = (caddr_t)((int)sysend + 3 & -4);
+       start = sysend;
+       curproc->p_addr = proc0paddr = (struct user *)sysend;
+       curproc->p_md.md_regs = proc0paddr->u_pcb.pcb_regs;
+       firstaddr = CACHED_TO_PHYS(sysend);
+       for (i = 0; i < UPAGES;) {
+#ifdef R4K
+               tlb.tlb_mask = PG_SIZE_4K;
+               tlb.tlb_hi = vad_to_vpn((UADDR + (i << PGSHIFT))) | 1;
+               tlb.tlb_lo0 = vad_to_pfn(firstaddr) | PG_V | PG_M | PG_CACHED;
+               tlb.tlb_lo1 = vad_to_pfn(firstaddr + NBPG) | PG_V | PG_M | PG_CACHED;
+               curproc->p_md.md_upte[i] = tlb.tlb_lo0;
+               curproc->p_md.md_upte[i+1] = tlb.tlb_lo1;
+               R4K_TLBWriteIndexed(i,&tlb);
+               firstaddr += NBPG * 2;
+               i += 2;
+               R4K_SetPID(1);
+#else
+               R3K_TLBWriteIndexed(i,
+                  (UADDR + (i << PGSHIFT)) | (1 << R3K_PID_SHIFT),
+                   (curproc->p_md.md_upte[i] = firstaddr | PG_V | PG_M));
+               firstaddr += NBPG;
+               i += 1;
+               R3K_SetPID(1);
+#endif
+       }
+       sysend += UPAGES * NBPG;
+       sysend = (caddr_t)((int)sysend+3 & -4);
+
+       /*
+        * init nullproc for swtch_exit().
+        * init mapping for u page(s), pm_tlbpid 0
+        * This could be used for an idle process.
+        */
+       nullproc.p_addr = (struct user *)sysend;
+       nullproc.p_md.md_regs = nullproc.p_addr->u_pcb.pcb_regs;
+       bcopy("nullproc", nullproc.p_comm, sizeof("nullproc"));
+       firstaddr = CACHED_TO_PHYS(sysend);
+       for (i = 0; i < UPAGES; i+=2) {
+               nullproc.p_md.md_upte[i] = vad_to_pfn(firstaddr) | PG_V | PG_M | PG_CACHED;
+               nullproc.p_md.md_upte[i+1] = vad_to_pfn(firstaddr + NBPG) | PG_V | PG_M | PG_CACHED;
+               firstaddr += NBPG * 2;
+       }
+       sysend += UPAGES * NBPG;
+
+       /* clear pages for u areas */
+       bzero(start, sysend - start);
+
+       /*
+        * Copy down exception vector code.
+        */
+       {
+#ifdef R4K
+               extern char R4K_TLBMiss[], R4K_TLBMissEnd[];
+               extern char R4K_Exception[], R4K_ExceptionEnd[];
+
+               if (R4K_TLBMissEnd - R4K_TLBMiss > 0x80)
+                       panic("startup: TLB code too large");
+               bcopy(R4K_TLBMiss, (char *)R4K_TLB_MISS_EXC_VEC,
+                       R4K_TLBMissEnd - R4K_TLBMiss);
+               bcopy(R4K_Exception, (char *)R4K_GEN_EXC_VEC,
+                       R4K_ExceptionEnd - R4K_Exception);
+
+               cpucfg = R4K_ConfigCache();
+               R4K_FlushCache();
+#else
+               extern char R3K_UTLBMiss[], R3K_UTLBMissEnd[];
+               extern char R3K_Exception[], R3K_ExceptionEnd[];
+               if (R3K_UTLBMissEnd - R3K_UTLBMiss > 0x80)
+                       panic("startup: TLB code too large");
+               bcopy(R3K_UTLBMiss, (char *)R3K_TLB_MISS_EXC_VEC,
+                       R3K_UTLBMissEnd - R3K_UTLBMiss);
+               bcopy(R3K_Exception, (char *)R3K_GEN_EXC_VEC,
+                       R3K_ExceptionEnd - R3K_Exception);
+
+               cpucfg = R3K_ConfigCache();
+               R3K_FlushCache();
+#endif
+       }
+
+       /*
+        * Initialize error message buffer.
+        */
+       msgbufp = (struct msgbuf *)(sysend);
+       sysend = (caddr_t)(sysend + (sizeof(struct msgbuf)));
+       msgbufmapped = 1;
+
+       /*
+        * Allocate space for system data structures.
+        * The first available kernel virtual address is in "sysend".
+        * As pages of kernel virtual memory are allocated, "sysend"
+        * is incremented.
+        *
+        * These data structures are allocated here instead of cpu_startup()
+        * because physical memory is directly addressable. We don't have
+        * to map these into virtual address space.
+        */
+       start = sysend;
+
+#define        valloc(name, type, num) \
+           (name) = (type *)sysend; sysend = (caddr_t)((name)+(num))
+#define        valloclim(name, type, num, lim) \
+           (name) = (type *)sysend; sysend = (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 allocate more buffer space than the BSD standard of
+        * using 10% of memory for the first 2 Meg, 5% of remaining.
+        * We just allocate a flat 10%. Ensure a minimum of 16 buffers.
+        * We allocate 1/2 as many swap buffer headers as file i/o buffers.
+        */
+       if (bufpages == 0)
+               bufpages = physmem / 10 / 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);
+
+       /*
+        * Clear allocated memory.
+        */
+       bzero(start, sysend - start);
+
+       /*
+        * Initialize the virtual memory system.
+        */
+       pmap_bootstrap((vm_offset_t)sysend);
+}
+
+#if keep_for_future_r4k_machines
+void
+tlb_init_pica()
+{
+       struct tlb tlb;
+
+       tlb.tlb_mask = PG_SIZE_256K;
+       tlb.tlb_hi = vad_to_vpn(R4030_V_LOCAL_IO_BASE);
+       tlb.tlb_lo0 = vad_to_pfn(R4030_P_LOCAL_IO_BASE) | PG_IOPAGE;
+       tlb.tlb_lo1 = vad_to_pfn(PICA_P_INT_SOURCE) | PG_IOPAGE;
+       R4K_TLBWriteIndexed(1, &tlb);
+}
+#endif
+
+/*
+ * Console initialization: called early on from main,
+ * before vm init or startup.  Do enough configuration
+ * to choose and initialize a console.
+ */
+void
+consinit()
+{
+       static int initted;
+
+       if (initted)
+               return;
+       initted = 1;
+       cninit();
+mdbpanic();
+}
+
+/*
+ * cpu_startup: allocate memory for variable-sized tables,
+ * initialize cpu, and do autoconfiguration.
+ */
+void
+cpu_startup()
+{
+       register unsigned i;
+       register caddr_t v;
+       int base, residual;
+       vm_offset_t minaddr, maxaddr;
+       vm_size_t size;
+#ifdef DEBUG
+       extern int pmapdebug;
+       int opmapdebug = pmapdebug;
+
+       pmapdebug = 0;          /* Shut up pmap debug during bootstrap */
+#endif
+
+       /*
+        * Good {morning,afternoon,evening,night}.
+        */
+       printf(version);
+       printf("real mem = %d\n", ctob(physmem));
+
+       /*
+        * Allocate virtual address space for file I/O buffers.
+        * Note they are different than the array of headers, 'buf',
+        * and 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;
+       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);
+               vm_map_pageable(buffer_map, curbuf, curbuf+curbufsize, FALSE);
+               vm_map_simplify(buffer_map, curbuf);
+       }
+       /*
+        * 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.
+        */
+       if (boothowto & RB_CONFIG) {
+#ifdef BOOT_CONFIG
+               user_config();
+#else
+               printf("kernel does not support -c; continuing..\n");
+#endif
+       }
+       configure();
+
+       spl0();         /* safe to turn interrupts on now */
+}
+
+/*
+ * 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 */
+}
+
+/*
+ * Set registers on exec.
+ * Clear all registers except sp, pc.
+ */
+void
+setregs(p, pack, stack, retval)
+       register struct proc *p;
+       struct exec_package *pack;
+       u_long stack;
+       register_t *retval;
+{
+       extern struct proc *cpuFPCurProcPtr;
+
+       bzero((caddr_t)p->p_md.md_regs, (FSR + 1) * sizeof(int));
+       p->p_md.md_regs[SP] = stack;
+       p->p_md.md_regs[PC] = pack->ep_entry & ~3;
+       p->p_md.md_regs[T9] = pack->ep_entry & ~3; /* abicall req */
+#ifdef R4K
+       p->p_md.md_regs[PS] = R4K_PSL_USERSET;
+#else
+       p->p_md.md_regs[PS] = R3K_PSL_USERSET;
+#endif
+       p->p_md.md_flags & ~MDP_FPUSED;
+       if (cpuFPCurProcPtr == p)
+               cpuFPCurProcPtr = (struct proc *)0;
+       p->p_md.md_ss_addr = 0;
+}
+
+/*
+ * 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 */
+       siginfo_t *sf_sip;              /* pointer to siginfo_t */
+       struct  sigcontext *sf_scp;     /* context ptr for handler */
+       sig_t   sf_handler;             /* handler addr for u_sigc */
+       struct  sigcontext sf_sc;       /* actual context */
+       siginfo_t sf_si;
+};
+
+#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, type, val)
+       sig_t catcher;
+       int sig, mask;
+       u_long code;
+       int type;
+       union sigval val;
+{
+       register struct proc *p = curproc;
+       register struct sigframe *fp;
+       register int *regs;
+       register struct sigacts *psp = p->p_sigacts;
+       int oonstack, fsize;
+       struct sigcontext ksc;
+       extern char sigcode[], esigcode[];
+
+       regs = p->p_md.md_regs;
+       oonstack = psp->ps_sigstk.ss_flags & SA_ONSTACK;
+       /*
+        * Allocate and validate space for the signal handler
+        * context. Note that if the stack is in data space, the
+        * call to grow() is a nop, and the copyout()
+        * will fail if the process has not already allocated
+        * the space with a `brk'.
+        */
+       fsize = sizeof(struct sigframe);
+       if (!(psp->ps_siginfo & sigmask(sig)))
+               fsize -= sizeof(siginfo_t);
+       if ((psp->ps_flags & SAS_ALTSTACK) &&
+           (psp->ps_sigstk.ss_flags & SA_ONSTACK) == 0 &&
+           (psp->ps_sigonstack & sigmask(sig))) {
+               fp = (struct sigframe *)(psp->ps_sigstk.ss_sp +
+                                        psp->ps_sigstk.ss_size - fsize);
+               psp->ps_sigstk.ss_flags |= SA_ONSTACK;
+       } else
+               fp = (struct sigframe *)(regs[SP] - fsize);
+       if ((unsigned)fp <= USRSTACK - ctob(p->p_vmspace->vm_ssize)) 
+               (void)grow(p, (unsigned)fp);
+#ifdef DEBUG
+       if ((sigdebug & SDB_FOLLOW) ||
+           (sigdebug & SDB_KSTACK) && p->p_pid == sigpid)
+               printf("sendsig(%d): sig %d ssp %x usp %x scp %x\n",
+                      p->p_pid, sig, &oonstack, fp, &fp->sf_sc);
+#endif
+       /*
+        * Build the signal context to be used by sigreturn.
+        */
+       ksc.sc_onstack = oonstack;
+       ksc.sc_mask = mask;
+       ksc.sc_pc = regs[PC];
+       ksc.mullo = regs[MULLO];
+       ksc.mulhi = regs[MULHI];
+       ksc.sc_regs[ZERO] = 0xACEDBADE;         /* magic number */
+       bcopy((caddr_t)&regs[1], (caddr_t)&ksc.sc_regs[1],
+               sizeof(ksc.sc_regs) - sizeof(int));
+       ksc.sc_fpused = p->p_md.md_flags & MDP_FPUSED;
+       if (ksc.sc_fpused) {
+               extern struct proc *cpuFPCurProcPtr;
+
+               /* if FPU has current state, save it first */
+               if (p == cpuFPCurProcPtr)
+                       CPU_SaveCurFPState(p);
+               bcopy((caddr_t)&p->p_md.md_regs[F0], (caddr_t)ksc.sc_fpregs,
+                       sizeof(ksc.sc_fpregs));
+       }
+
+       if (psp->ps_siginfo & sigmask(sig)) {
+               siginfo_t si;
+
+               initsiginfo(&si, sig, code, type, val);
+               if (copyout((caddr_t)&si, (caddr_t)&fp->sf_si, sizeof si))
+                       goto bail;
+       }
+
+       if (copyout((caddr_t)&ksc, (caddr_t)&fp->sf_sc, sizeof(ksc))) {
+bail:
+               /*
+                * 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;
+       }
+       /* 
+        * Build the argument list for the signal handler.
+        */
+       regs[A0] = sig;
+       regs[A1] = (psp->ps_siginfo & sigmask(sig)) ? (int)&fp->sf_si : NULL;
+       regs[A2] = (int)&fp->sf_sc;
+       regs[A3] = (int)catcher;
+
+       regs[PC] = (int)catcher;
+       regs[T9] = (int)catcher;
+       regs[SP] = (int)fp;
+       /*
+        * Signal trampoline code is at base of user stack.
+        */
+       regs[RA] = (int)PS_STRINGS - (esigcode - sigcode);
+#ifdef DEBUG
+       if ((sigdebug & SDB_FOLLOW) ||
+           (sigdebug & SDB_KSTACK) && p->p_pid == sigpid)
+               printf("sendsig(%d): sig %d returns\n",
+                      p->p_pid, sig);
+#endif
+}
+
+/*
+ * 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 */
+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 int *regs;
+       struct sigcontext ksc;
+       int error;
+
+       scp = SCARG(uap, sigcntxp);
+#ifdef DEBUG
+       if (sigdebug & SDB_FOLLOW)
+               printf("sigreturn: pid %d, scp %x\n", p->p_pid, scp);
+#endif
+       regs = p->p_md.md_regs;
+       /*
+        * Test and fetch the context structure.
+        * We grab it all at once for speed.
+        */
+       error = copyin((caddr_t)scp, (caddr_t)&ksc, sizeof(ksc));
+       if (error || ksc.sc_regs[ZERO] != 0xACEDBADE) {
+#ifdef DEBUG
+               if (!(sigdebug & SDB_FOLLOW))
+                       printf("sigreturn: pid %d, scp %x\n", p->p_pid, scp);
+               printf("  old sp %x ra %x pc %x\n",
+                       regs[SP], regs[RA], regs[PC]);
+               printf("  new sp %x ra %x pc %x err %d z %x\n",
+                       ksc.sc_regs[SP], ksc.sc_regs[RA], ksc.sc_regs[PC],
+                       error, ksc.sc_regs[ZERO]);
+#endif
+               return (EINVAL);
+       }
+       scp = &ksc;
+       /*
+        * Restore the user supplied information
+        */
+       if (scp->sc_onstack & 01)
+               p->p_sigacts->ps_sigstk.ss_flags |= SA_ONSTACK;
+       else
+               p->p_sigacts->ps_sigstk.ss_flags &= ~SA_ONSTACK;
+       p->p_sigmask = scp->sc_mask &~ sigcantmask;
+       regs[PC] = scp->sc_pc;
+       regs[MULLO] = scp->mullo;
+       regs[MULHI] = scp->mulhi;
+       bcopy((caddr_t)&scp->sc_regs[1], (caddr_t)&regs[1],
+               sizeof(scp->sc_regs) - sizeof(int));
+       if (scp->sc_fpused)
+               bcopy((caddr_t)scp->sc_fpregs, (caddr_t)&p->p_md.md_regs[F0],
+                       sizeof(scp->sc_fpregs));
+       return (EJUSTRETURN);
+}
+
+int    waittime = -1;
+
+void
+boot(howto)
+       register int howto;
+{
+
+       /* take a snap shot before clobbering any registers */
+       if (curproc)
+               savectx(curproc->p_addr, 0);
+
+#ifdef DEBUG
+       if (panicstr)
+               stacktrace();
+#endif
+
+       boothowto = howto;
+       if ((howto & RB_NOSYNC) == 0 && waittime < 0) {
+               extern struct proc proc0;
+               /* fill curproc with live object */
+               if (curproc == NULL)
+                       curproc = &proc0;
+               /*
+                * Synchronize the disks....
+                */
+               waittime = 0;
+               vfs_shutdown();
+
+               /*
+                * If we've been adjusting the clock, the todr
+                * will be out of synch; adjust it now.
+                */
+               resettodr();
+       }
+       (void) splhigh();               /* extreme priority */
+       if (howto & RB_HALT) {
+               printf("System halted.\n");
+               while(1); /* Forever */
+       }
+       else {
+               if (howto & RB_DUMP)
+                       dumpsys();
+               printf("System restart.\n");
+               delay(2000000);
+               __asm__(" li $2, 0xbfc00000; jr $2; nop\n");
+               while(1); /* Forever */
+       }
+       /*NOTREACHED*/
+}
+
+int    dumpmag = (int)0x8fca0101;      /* magic number for savecore */
+int    dumpsize = 0;           /* also for savecore */
+long   dumplo = 0;
+
+dumpconf()
+{
+       int nblks;
+
+       dumpsize = physmem;
+       if (dumpdev != NODEV && bdevsw[major(dumpdev)].d_psize) {
+               nblks = (*bdevsw[major(dumpdev)].d_psize)(dumpdev);
+               if (dumpsize > btoc(dbtob(nblks - dumplo)))
+                       dumpsize = btoc(dbtob(nblks - dumplo));
+               else if (dumplo == 0)
+                       dumplo = nblks - btodb(ctob(physmem));
+       }
+       /*
+        * Don't dump on the first CLBYTES (why CLBYTES?)
+        * in case the dump device includes a disk label.
+        */
+       if (dumplo < btodb(CLBYTES))
+               dumplo = btodb(CLBYTES);
+}
+
+/*
+ * 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()
+{
+       int error;
+
+       msgbufmapped = 0;
+       if (dumpdev == NODEV)
+               return;
+       /*
+        * For dumps during autoconfiguration,
+        * if dump device has already configured...
+        */
+       if (dumpsize == 0)
+               dumpconf();
+       if (dumplo < 0)
+               return;
+       printf("\ndumping to dev %x, offset %d\n", dumpdev, dumplo);
+       printf("dump ");
+       switch (error = (*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;
+
+       default:
+               printf("error %d\n", error);
+               break;
+
+       case 0:
+               printf("succeeded\n");
+       }
+}
+
+/*
+ * Return the best possible estimate of the time in the timeval
+ * to which tvp points.  Unfortunately, we can't read the hardware registers.
+ * 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 = splclock();
+       static struct timeval lasttime;
+
+       *tvp = time;
+#ifdef notdef
+       tvp->tv_usec += clkread();
+       while (tvp->tv_usec > 1000000) {
+               tvp->tv_sec++;
+               tvp->tv_usec -= 1000000;
+       }
+#endif
+       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);
+}
+
+initcpu()
+{
+
+}
+
+/*
+ * Convert an ASCII string into an integer.
+ */
+int
+atoi(s)
+       char *s;
+{
+       int c;
+       unsigned base = 10, d;
+       int neg = 0, val = 0;
+
+       if (s == 0 || (c = *s++) == 0)
+               goto out;
+
+       /* skip spaces if any */
+       while (c == ' ' || c == '\t')
+               c = *s++;
+
+       /* parse sign, allow more than one (compat) */
+       while (c == '-') {
+               neg = !neg;
+               c = *s++;
+       }
+
+       /* parse base specification, if any */
+       if (c == '0') {
+               c = *s++;
+               switch (c) {
+               case 'X':
+               case 'x':
+                       base = 16;
+                       c = *s++;
+                       break;
+               case 'B':
+               case 'b':
+                       base = 2;
+                       c = *s++;
+                       break;
+               default:
+                       base = 8;
+               }
+       }
+
+       /* parse number proper */
+       for (;;) {
+               if (c >= '0' && c <= '9')
+                       d = c - '0';
+               else if (c >= 'a' && c <= 'z')
+                       d = c - 'a' + 10;
+               else if (c >= 'A' && c <= 'Z')
+                       d = c - 'A' + 10;
+               else
+                       break;
+               val *= base;
+               val += d;
+               c = *s++;
+       }
+       if (neg)
+               val = -val;
+out:
+       return val;     
+}
diff --git a/sys/arch/wgrisc/wgrisc/mainbus.c b/sys/arch/wgrisc/wgrisc/mainbus.c
new file mode 100644 (file)
index 0000000..1c91d8e
--- /dev/null
@@ -0,0 +1,160 @@
+/*     $OpenBSD: mainbus.c,v 1.1.1.1 1997/02/06 16:02:46 pefo Exp $ */
+
+/*
+ * Copyright (c) 1996 Per Fogelstrom
+ * 
+ * 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 under OpenBSD by
+ *     Per Fogelstrom.
+ * 4. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/device.h>
+#include <sys/reboot.h>
+
+#include <wgrisc/wgrisc/wgrisctype.h>
+#include <machine/autoconf.h>
+
+struct mainbus_softc {
+       struct  device sc_dv;
+       struct  abus sc_bus;
+};
+
+/* Definition of the mainbus driver. */
+static int     mbmatch __P((struct device *, void *, void *));
+static void    mbattach __P((struct device *, struct device *, void *));
+static int     mbprint __P((void *, const char *));
+
+struct cfattach mainbus_ca = {
+       sizeof(struct device), mbmatch, mbattach
+};
+struct cfdriver mainbus_cd = {
+       NULL, "mainbus", DV_DULL, NULL, 0
+};
+
+void   mb_intr_establish __P((struct confargs *, int (*)(void *), void *));
+void   mb_intr_disestablish __P((struct confargs *));
+caddr_t        mb_cvtaddr __P((struct confargs *));
+int    mb_matchname __P((struct confargs *, char *));
+
+static int
+mbmatch(parent, cfdata, aux)
+       struct device *parent;
+       void *cfdata;
+       void *aux;
+{
+       struct cfdata *cf = cfdata;
+
+       if (cf->cf_unit > 0)
+               return(0);
+       return(1);
+}
+
+static void
+mbattach(parent, self, aux)
+       struct device *parent;
+       struct device *self;
+       void *aux;
+{
+       struct mainbus_softc *sc = (struct mainbus_softc *)self;
+       struct confargs nca;
+       extern int cputype, ncpus;
+
+       printf("\n");
+
+       sc->sc_bus.ab_dv = (struct device *)sc;
+       sc->sc_bus.ab_type = BUS_MAIN;
+       sc->sc_bus.ab_intr_establish = mb_intr_establish;
+       sc->sc_bus.ab_intr_disestablish = mb_intr_disestablish;
+       sc->sc_bus.ab_cvtaddr = mb_cvtaddr;
+       sc->sc_bus.ab_matchname = mb_matchname;
+
+       nca.ca_name = "cpu";
+       nca.ca_slot = 0;
+       nca.ca_offset = 0;
+       nca.ca_bus = &sc->sc_bus;
+       config_found(self, &nca, mbprint);
+
+       nca.ca_name = "riscbus";
+       nca.ca_slot = 0;
+       nca.ca_offset = 0;
+       nca.ca_bus = &sc->sc_bus;
+       config_found(self, &nca, mbprint);
+
+       nca.ca_name = "isabr";
+       nca.ca_slot = 0;
+       nca.ca_offset = 0;
+       nca.ca_bus = &sc->sc_bus;
+       config_found(self, &nca, mbprint);
+}
+
+static int
+mbprint(aux, pnp)
+       void *aux;
+       const char *pnp;
+{
+
+       if (pnp)
+               return (QUIET);
+       return (UNCONF);
+}
+
+void
+mb_intr_establish(ca, handler, val)
+       struct confargs *ca;
+       int (*handler) __P((void *));
+       void *val;
+{
+
+       panic("can never mb_intr_establish");
+}
+
+void
+mb_intr_disestablish(ca)
+       struct confargs *ca;
+{
+
+       panic("can never mb_intr_disestablish");
+}
+
+caddr_t
+mb_cvtaddr(ca)
+       struct confargs *ca;
+{
+
+       return (NULL);
+}
+
+int
+mb_matchname(ca, name)
+       struct confargs *ca;
+       char *name;
+{
+
+       return (strcmp(name, ca->ca_name) == 0);
+}
diff --git a/sys/arch/wgrisc/wgrisc/mem.c b/sys/arch/wgrisc/wgrisc/mem.c
new file mode 100644 (file)
index 0000000..7c529aa
--- /dev/null
@@ -0,0 +1,173 @@
+/*     $OpenBSD: mem.c,v 1.1.1.1 1997/02/06 16:02:46 pefo Exp $        */
+/*     $NetBSD: mem.c,v 1.6 1995/04/10 11:55:03 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 and Ralph Campbell.
+ *
+ * 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/msgbuf.h>
+#include <sys/systm.h>
+#include <sys/uio.h>
+#include <sys/malloc.h>
+
+#include <machine/cpu.h>
+
+#include <vm/vm.h>
+
+extern vm_offset_t avail_end;
+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;
+
+       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;
+                       c = iov->iov_len;
+                       if (v + c > ctob(physmem))
+                               return (EFAULT);
+                       v += CACHED_MEMORY_ADDR;
+                       error = uiomove((caddr_t)v, c, uio);
+                       continue;
+
+/* minor device 1 is kernel memory */
+               case 1:
+                       v = uio->uio_offset;
+                       c = min(iov->iov_len, MAXPHYS);
+                       if (v < CACHED_MEMORY_ADDR)
+                               return (EFAULT);
+                       if (v + c > PHYS_TO_CACHED(avail_end +
+                                                       sizeof (struct msgbuf)) &&
+                           (v < KSEG2_ADDR ||
+                           !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;
+                       }
+                       if (zeropage == NULL) {
+                               zeropage = (caddr_t)
+                                   malloc(CLBYTES, M_TEMP, M_WAITOK);
+                               bzero(zeropage, CLBYTES);
+                       }
+                       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;
+       }
+       return (error);
+}
+
+int
+mmmmap(dev, off, prot)
+       dev_t dev;
+       int off, prot;
+{
+
+       return (EOPNOTSUPP);
+}
diff --git a/sys/arch/wgrisc/wgrisc/minidebug.c b/sys/arch/wgrisc/wgrisc/minidebug.c
new file mode 100644 (file)
index 0000000..45b14a9
--- /dev/null
@@ -0,0 +1,975 @@
+/*     $OpenBSD: minidebug.c,v 1.1.1.1 1997/02/06 16:02:46 pefo 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
+ * Ralph Campbell.
+ *
+ * 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: @(#)kadb.c        8.1 (Berkeley) 6/10/93
+ *      $Id: minidebug.c,v 1.1.1.1 1997/02/06 16:02:46 pefo Exp $
+ */
+
+/*
+ * Define machine dependent primitives for mdb.
+ */
+
+#include <sys/types.h>
+#include <machine/pte.h>
+#include <vm/vm_prot.h>
+#undef SP
+#include <machine/cpu.h>
+#include <machine/reg.h>
+#include <machine/pcb.h>
+#include <machine/trap.h>
+#include <machine/mips_opcode.h>
+
+#ifndef TRUE
+#define TRUE 1
+#define FALSE 0
+#endif
+
+#ifdef R4K
+#define        FlushDCache(a,s)        R4K_FlushDCache(a,s)
+#define FlushICache(a,s)       R4K_FlushICache(a,s)
+#define FlushCache()           R4K_FlushCache()
+#define        TLBFlush()              R4K_TLBFlush()
+#else
+#define        FlushDCache(a,s)        R3K_FlushDCache(a,s)
+#define FlushICache(a,s)       R3K_FlushICache(a,s)
+#define FlushCache()           R3K_FlushCache()
+#define        TLBFlush()              R3K_TLBFlush()
+#endif
+
+void mips_dump_tlb(int, int);
+
+static char *op_name[64] = {
+/* 0 */        "spec", "bcond","j",    "jal",  "beq",  "bne",  "blez", "bgtz",
+/* 8 */        "addi", "addiu","slti", "sltiu","andi", "ori",  "xori", "lui",
+/*16 */        "cop0", "cop1", "cop2", "cop3", "beql", "bnel", "blezl","bgtzl",
+/*24 */        "daddi","daddiu","ldl", "ldr",  "op34", "op35", "op36", "op37",
+/*32 */        "lb",   "lh",   "lwl",  "lw",   "lbu",  "lhu",  "lwr",  "lwu",
+/*40 */        "sb",   "sh",   "swl",  "sw",   "sdl",  "sdr",  "swr",  "cache",
+/*48 */        "ll",   "lwc1", "lwc2", "lwc3", "lld",  "ldc1", "ldc2", "ld",
+/*56 */        "sc",   "swc1", "swc2", "swc3", "scd",  "sdc1", "sdc2", "sd"
+};
+
+static char *spec_name[64] = {
+/* 0 */        "sll",  "spec01","srl", "sra",  "sllv", "spec05","srlv","srav",
+/* 8 */        "jr",   "jalr", "spec12","spec13","syscall","break","spec16","sync",
+/*16 */        "mfhi", "mthi", "mflo", "mtlo", "dsllv","spec25","dsrlv","dsrav",
+/*24 */        "mult", "multu","div",  "divu", "dmult","dmultu","ddiv","ddivu",
+/*32 */        "add",  "addu", "sub",  "subu", "and",  "or",   "xor",  "nor",
+/*40 */        "spec50","spec51","slt","sltu", "dadd","daddu","dsub","dsubu",
+/*48 */        "tge","tgeu","tlt","tltu","teq","spec65","tne","spec67",
+/*56 */        "dsll","spec71","dsrl","dsra","dsll32","spec75","dsrl32","dsra32"
+};
+
+static char *bcond_name[32] = {
+/* 0 */        "bltz", "bgez", "bltzl", "bgezl", "?", "?", "?", "?",
+/* 8 */        "tgei", "tgeiu", "tlti", "tltiu", "teqi", "?", "tnei", "?",
+/*16 */        "bltzal", "bgezal", "bltzall", "bgezall", "?", "?", "?", "?",
+/*24 */        "?", "?", "?", "?", "?", "?", "?", "?",
+};
+
+static char *cop1_name[64] = {
+/* 0 */        "fadd", "fsub", "fmpy", "fdiv", "fsqrt","fabs", "fmov", "fneg",
+/* 8 */        "fop08","fop09","fop0a","fop0b","fop0c","fop0d","fop0e","fop0f",
+/*16 */        "fop10","fop11","fop12","fop13","fop14","fop15","fop16","fop17",
+/*24 */        "fop18","fop19","fop1a","fop1b","fop1c","fop1d","fop1e","fop1f",
+/*32 */        "fcvts","fcvtd","fcvte","fop23","fcvtw","fop25","fop26","fop27",
+/*40 */        "fop28","fop29","fop2a","fop2b","fop2c","fop2d","fop2e","fop2f",
+/*48 */        "fcmp.f","fcmp.un","fcmp.eq","fcmp.ueq","fcmp.olt","fcmp.ult",
+       "fcmp.ole","fcmp.ule",
+/*56 */        "fcmp.sf","fcmp.ngle","fcmp.seq","fcmp.ngl","fcmp.lt","fcmp.nge",
+       "fcmp.le","fcmp.ngt"
+};
+
+static char *fmt_name[16] = {
+       "s",    "d",    "e",    "fmt3",
+       "w",    "fmt5", "fmt6", "fmt7",
+       "fmt8", "fmt9", "fmta", "fmtb",
+       "fmtc", "fmtd", "fmte", "fmtf"
+};
+
+static char *reg_name[32] = {
+       "zero", "at",   "v0",   "v1",   "a0",   "a1",   "a2",   "a3",
+       "t0",   "t1",   "t2",   "t3",   "t4",   "t5",   "t6",   "t7",
+       "s0",   "s1",   "s2",   "s3",   "s4",   "s5",   "s6",   "s7",
+       "t8",   "t9",   "k0",   "k1",   "gp",   "sp",   "s8",   "ra"
+};
+
+static char *c0_opname[64] = {
+       "c0op00","tlbr",  "tlbwi", "c0op03","c0op04","c0op05","tlbwr", "c0op07",
+       "tlbp",  "c0op11","c0op12","c0op13","c0op14","c0op15","c0op16","c0op17",
+       "rfe",   "c0op21","c0op22","c0op23","c0op24","c0op25","c0op26","c0op27",
+       "eret","c0op31","c0op32","c0op33","c0op34","c0op35","c0op36","c0op37",
+       "c0op40","c0op41","c0op42","c0op43","c0op44","c0op45","c0op46","c0op47",
+       "c0op50","c0op51","c0op52","c0op53","c0op54","c0op55","c0op56","c0op57",
+       "c0op60","c0op61","c0op62","c0op63","c0op64","c0op65","c0op66","c0op67",
+       "c0op70","c0op71","c0op72","c0op73","c0op74","c0op75","c0op77","c0op77",
+};
+
+static char *c0_reg[32] = {
+       "index","random","tlblo0","tlblo1","context","tlbmask","wired","c0r7",
+       "badvaddr","count","tlbhi","c0r11","sr","cause","epc",  "prid",
+       "config","lladr","watchlo","watchhi","xcontext","c0r21","c0r22","c0r23",
+       "c0r24","c0r25","ecc","cacheerr","taglo","taghi","errepc","c0r31"
+};
+
+extern char *trap_type[];
+
+struct pcb mdbpcb;
+int mdbmkfault;
+
+#define MAXBRK 10
+struct brk {
+       int     inst;
+       int     addr;
+} brk_tab[MAXBRK];
+
+/*
+ * Mini debugger for kernel.
+ */
+int gethex(u_int *val, u_int dotval)
+{
+       u_int c;
+
+       *val = 0;
+       while((c = cngetc()) != '\e' && c != '\n' && c != '\r') {
+               if(c >= '0' && c <= '9') {
+                       *val = (*val << 4) + c - '0';
+                       cnputc(c);
+               }
+               else if(c >= 'a' && c <= 'f') {
+                       *val = (*val << 4) + c - 'a' + 10;
+                       cnputc(c);
+               }
+               else if(c == '\b') {
+                       *val = *val >> 4;
+                       printf("\b \b");
+               }
+               else if(c == ',') {
+                       cnputc(c);
+                       return(c);
+               }
+               else if(c == '.') {
+                       *val = dotval;;
+                       cnputc(c);
+               }
+       }
+       if(c == '\r')
+               c = '\n';
+       return(c);
+}
+
+void dump(u_int *addr, u_int size)
+{
+       int     cnt;
+
+       cnt = 0;
+
+       size = (size + 3) / 4;
+       while(size--) {
+               if((cnt++ & 3) == 0)
+                       printf("\n%08x: ",(int)addr);
+               printf("%08x ",*addr++);
+       }
+}
+
+void print_regs()
+{
+       printf("\n");
+       printf("T0-7 %08x %08x %08x %08x %08x %08x %08x %08x\n",
+               mdbpcb.pcb_regs[T0],mdbpcb.pcb_regs[T1],
+               mdbpcb.pcb_regs[T2],mdbpcb.pcb_regs[T3],
+               mdbpcb.pcb_regs[T4],mdbpcb.pcb_regs[T5],
+               mdbpcb.pcb_regs[T6],mdbpcb.pcb_regs[T7]);
+       printf("T8-9 %08x %08x     A0-4 %08x %08x %08x %08x\n",
+               mdbpcb.pcb_regs[T8],mdbpcb.pcb_regs[T9],
+               mdbpcb.pcb_regs[A0],mdbpcb.pcb_regs[A1],
+               mdbpcb.pcb_regs[A2],mdbpcb.pcb_regs[A3]);
+       printf("S0-7 %08x %08x %08x %08x %08x %08x %08x %08x\n",
+               mdbpcb.pcb_regs[S0],mdbpcb.pcb_regs[S1],
+               mdbpcb.pcb_regs[S2],mdbpcb.pcb_regs[S3],
+               mdbpcb.pcb_regs[S4],mdbpcb.pcb_regs[S5],
+               mdbpcb.pcb_regs[S6],mdbpcb.pcb_regs[S7]);
+       printf("  S8 %08x     V0-1 %08x %08x       GP %08x       SP %08x\n",
+               mdbpcb.pcb_regs[S8],mdbpcb.pcb_regs[V0],
+               mdbpcb.pcb_regs[V1],mdbpcb.pcb_regs[GP],
+               mdbpcb.pcb_regs[SP]);
+       printf("  AT %08x       PC %08x       RA %08x       SR %08x",
+               mdbpcb.pcb_regs[AST],mdbpcb.pcb_regs[PC],
+               mdbpcb.pcb_regs[RA],mdbpcb.pcb_regs[SR]);
+}
+
+set_break(va)
+{
+       int i;
+
+       va = va & ~3;
+       for(i = 0; i < MAXBRK; i++) {
+               if(brk_tab[i].addr == 0) {
+                       brk_tab[i].addr = va;
+                       brk_tab[i].inst = *(u_int *)va;
+                       return;
+               }
+       }
+       printf(" Break table full!!");
+}
+
+del_break(va)
+{
+       int i;
+
+       va = va & ~3;
+       for(i = 0; i < MAXBRK; i++) {
+               if(brk_tab[i].addr == va) {
+                       brk_tab[i].addr = 0;
+                       return;
+               }
+       }
+       printf(" Break to remove not found!!");
+}
+
+break_insert()
+{
+       int i;
+
+       for(i = 0; i < MAXBRK; i++) {
+               if(brk_tab[i].addr != 0) {
+                       brk_tab[i].inst = *(u_int *)brk_tab[i].addr;
+                       *(u_int *)brk_tab[i].addr = BREAK_BRKPT;
+                       FlushDCache(brk_tab[i].addr,4);
+                       FlushICache(brk_tab[i].addr,4);
+               }
+       }
+}
+
+break_restore()
+{
+       int i;
+
+       for(i = 0; i < MAXBRK; i++) {
+               if(brk_tab[i].addr != 0) {
+                       *(u_int *)brk_tab[i].addr = brk_tab[i].inst;
+                       FlushDCache(brk_tab[i].addr,4);
+                       FlushICache(brk_tab[i].addr,4);
+               }
+       }
+}
+
+break_find(va)
+{
+       int i;
+
+       for(i = 0; i < MAXBRK; i++) {
+               if(brk_tab[i].addr == va) {
+                       return(i);
+               }
+       }
+       return(-1);
+}
+
+prt_break()
+{
+       int i;
+
+       for(i = 0; i < MAXBRK; i++) {
+               if(brk_tab[i].addr != 0) {
+                       printf("\n    %08x\t", brk_tab[i].addr);
+                       mdbprintins(brk_tab[i].inst, brk_tab[i].addr);
+               }
+       }
+}
+mdb(causeReg, vadr, p, kernelmode)
+{
+       int c;
+       int newaddr;
+       int size;
+       int cause;
+static int ssandrun;   /* Single step and run flag (when cont at brk) */
+
+       splhigh();
+       cause = (causeReg & CR_EXC_CODE) >> CR_EXC_CODE_SHIFT;
+       newaddr = (int)(mdbpcb.pcb_regs[PC]);
+       switch(cause) {
+       case T_BREAK:
+               if(*(int *)newaddr == BREAK_SOVER) {
+                       break_restore();
+                       mdbpcb.pcb_regs[PC] += 4;
+                       printf("\nStop break (panic)\n# ");
+                       printf("    %08x\t",newaddr);
+                       mdbprintins(*(int *)newaddr, newaddr);
+                       printf("\n# ");
+                       break;
+               }
+               if(*(int *)newaddr == BREAK_BRKPT) {
+                       break_restore();
+                       printf("\rBRK %08x\t",newaddr);
+                       if(mdbprintins(*(int *)newaddr, newaddr)) {
+                               newaddr += 4;
+                               printf("\n    %08x\t",newaddr);
+                               mdbprintins(*(int *)newaddr, newaddr);
+                       }
+                       printf("\n# ");
+                       break;
+               }
+               if(mdbclrsstep(causeReg)) {
+                       if(ssandrun) { /* Step over bp before free run */
+                               ssandrun = 0;
+                               break_insert();
+                               return(TRUE);
+                       }
+                       printf("\r    %08x\t",newaddr);
+                       if(mdbprintins(*(int *)newaddr, newaddr)) {
+                               newaddr += 4;
+                               printf("\n    %08x\t",newaddr);
+                               mdbprintins(*(int *)newaddr, newaddr);
+                       }
+                       printf("\n# ");
+               }
+               break;
+
+       default:
+               printf("\n-- %s --\n# ",trap_type[cause]);
+       }
+       ssandrun = 0;
+       break_restore();
+
+       while(c = cngetc()) {
+               switch(c) {
+               case 'T':
+                       trapDump("Debugger");
+                       break;
+               case 'b':
+                       printf("break-");
+                       c = cngetc();
+                       switch(c) {
+                       case 's':
+                               printf("set at ");
+                               c = gethex(&newaddr, newaddr);
+                               if(c != '\e') {
+                                       set_break(newaddr);
+                               }
+                               break;
+
+                       case 'd':
+                               printf("delete at ");
+                               c = gethex(&newaddr, newaddr);
+                               if(c != '\e') {
+                                       del_break(newaddr);
+                               }
+                               break;
+
+                       case 'p':
+                               printf("print");
+                               prt_break();
+                               break;
+                       }
+                       break;
+
+               case 'r':
+                       print_regs();
+                       break;
+
+               case 'I':
+                       printf("Instruction at ");
+                       c = gethex(&newaddr, newaddr);
+                       while(c != '\e') {
+                               printf("\n    %08x\t",newaddr);
+                               mdbprintins(*(int *)newaddr, newaddr);
+                               newaddr += 4;
+                               c = cngetc();
+                       }
+                       break;
+
+               case 'c':
+                       printf("continue");
+                       if(break_find((int)(mdbpcb.pcb_regs[PC])) >= 0) {
+                               ssandrun = 1;
+                               mdbsetsstep();
+                       }
+                       else {
+                               break_insert();
+                       }
+                       return(TRUE);
+               case 'S':
+                       printf("Stack traceback:\n");
+                       stacktrace();
+                       return(TRUE);
+               case 's':
+                       set_break(mdbpcb.pcb_regs[PC] + 8);
+                       return(TRUE);
+               case ' ':
+                       mdbsetsstep();
+                       return(TRUE);
+
+               case 'd':
+                       printf("dump ");
+                       c = gethex(&newaddr, newaddr);
+                       if(c == ',') {
+                               c = gethex(&size,256);
+                       }
+                       else {
+                               size = 16;
+                       }
+                       if(c == '\n' && newaddr != 0) {
+                               dump((u_int *)newaddr, size);
+                               newaddr += size;
+                       }
+                       break;
+
+               case 'm':
+                       printf("mod ");
+                       c = gethex(&newaddr, newaddr);
+                       while(c == ',') {
+                               c = gethex(&size, 0);
+                               if(c != '\e')
+                                       *((u_int *)newaddr)++ = size;
+                       }
+                       break;
+
+               case 'i':
+                       printf("in-");
+                       c = cngetc();
+                       switch(c) {
+                       case 'b':
+                               printf("byte ");
+                               c = gethex(&newaddr, newaddr);
+                               if(c == '\n') {
+                                       printf("= %02x",
+                                               *(u_char *)newaddr);    
+                               }
+                               break;
+                       case 'h':
+                               printf("halfword ");
+                               c = gethex(&newaddr, newaddr);
+                               if(c == '\n') {
+                                       printf("= %04x",
+                                               *(u_short *)newaddr);   
+                               }
+                               break;
+                       case 'w':
+                               printf("word ");
+                               c = gethex(&newaddr, newaddr);
+                               if(c == '\n') {
+                                       printf("= %08x",
+                                               *(u_int *)newaddr);     
+                               }
+                               break;
+                       }
+                       break;
+
+               case 'o':
+                       printf("out-");
+                       c = cngetc();
+                       switch(c) {
+                       case 'b':
+                               printf("byte ");
+                               c = gethex(&newaddr, newaddr);
+                               if(c == ',') {
+                                       c = gethex(&size, 0);
+                                       if(c == '\n') {
+                                               *(u_char *)newaddr = size;      
+                                       }
+                               }
+                               break;
+                       case 'h':
+                               printf("halfword ");
+                               c = gethex(&newaddr, newaddr);
+                               if(c == ',') {
+                                       c = gethex(&size, 0);
+                                       if(c == '\n') {
+                                               *(u_short *)newaddr = size;     
+                                       }
+                               }
+                               break;
+                       case 'w':
+                               printf("word ");
+                               c = gethex(&newaddr, newaddr);
+                               if(c == ',') {
+                                       c = gethex(&size, 0);
+                                       if(c == '\n') {
+                                               *(u_int *)newaddr = size;       
+                                       }
+                               }
+                               break;
+                       }
+                       break;
+
+               case 't':
+                       printf("tlb-dump\n");
+                       mips_dump_tlb(0,23);
+                       (void)cngetc();
+                       mips_dump_tlb(24,47);
+                       break;
+
+               case 'f':
+                       printf("flush-");
+                       c = cngetc();
+                       switch(c) {
+                       case 't':
+                               printf("tlb");
+                               TLBFlush();
+                               break;
+
+                       case 'c':
+                               printf("cache");
+                               FlushCache();
+                               break;
+                       }
+                       break;
+                       
+               default:
+                       cnputc('\a');
+                       break;
+               }
+               printf("\n# ");
+       }
+}
+
+u_int mdb_ss_addr;
+u_int mdb_ss_instr;
+
+mdbsetsstep()
+{
+       register u_int va;
+       register int *locr0 = mdbpcb.pcb_regs;
+       int i;
+
+       /* compute next address after current location */
+       if(mdbpeek(locr0[PC]) != 0) {
+               va = CPU_EmulateBranch(locr0, locr0[PC], 0, mdbpeek(locr0[PC]));
+       }
+       else {
+               va = locr0[PC] + 4;
+       }
+       if (mdb_ss_addr) {
+               printf("mdbsetsstep: breakpoint already set at %x (va %x)\n",
+                       mdb_ss_addr, va);
+               return;
+       }
+       mdb_ss_addr = va;
+
+       if ((int)va < 0) {
+               /* kernel address */
+               mdb_ss_instr = mdbpeek(va);
+               mdbpoke((caddr_t)va, BREAK_SSTEP);
+               FlushDCache(va,4);
+               FlushICache(va,4);
+               return;
+       }
+}
+
+mdbclrsstep(cr)
+       int cr;
+{
+       register u_int pc, va;
+       u_int instr;
+
+       /* fix pc if break instruction is in the delay slot */
+       pc = mdbpcb.pcb_regs[PC];
+       if (cr < 0)
+               pc += 4;
+
+       /* check to be sure its the one we are expecting */
+       va = mdb_ss_addr;
+       if (!va || va != pc)
+               return(FALSE);
+
+       /* read break instruction */
+       instr = mdbpeek(va);
+       if (instr != BREAK_SSTEP)
+               return(FALSE);
+
+       if ((int)va < 0) {
+               /* kernel address */
+               mdbpoke((caddr_t)va, mdb_ss_instr);
+               FlushDCache(va,4);
+               FlushICache(va,4);
+               mdb_ss_addr = 0;
+               return(TRUE);
+       }
+
+       printf("can't clear break at %x\n", va);
+       mdb_ss_addr = 0;
+       return(FALSE);
+}
+
+void
+mdbreadc(lp)
+       char *lp;
+{
+       int c;
+
+       c = cngetc();
+       if (c == '\r')
+               c = '\n';
+       *lp = c;
+}
+
+void
+mdbwrite(lp, len)
+       char *lp;
+       int len;
+{
+       while (len-- > 0)
+               cnputc(*lp++);
+}
+
+/* ARGSUSED */
+mdbprintins(ins, mdbdot)
+{
+       InstFmt i;
+       int delay = 0;
+
+       i.word = ins;
+
+       switch (i.JType.op) {
+       case OP_SPECIAL:
+               if (i.word == 0) {
+                       printf("nop");
+                       break;
+               }
+               if (i.RType.func == OP_ADDU && i.RType.rt == 0) {
+                       printf("move\t%s,%s",
+                               reg_name[i.RType.rd],
+                               reg_name[i.RType.rs]);
+                       break;
+               }
+               printf("%s", spec_name[i.RType.func]);
+               switch (i.RType.func) {
+               case OP_SLL:
+               case OP_SRL:
+               case OP_SRA:
+               case OP_DSLL:
+               case OP_DSRL:
+               case OP_DSRA:
+               case OP_DSLL32:
+               case OP_DSRL32:
+               case OP_DSRA32:
+                       printf("\t%s,%s,%d",
+                               reg_name[i.RType.rd],
+                               reg_name[i.RType.rt],
+                               i.RType.shamt);
+                       break;
+
+               case OP_SLLV:
+               case OP_SRLV:
+               case OP_SRAV:
+               case OP_DSLLV:
+               case OP_DSRLV:
+               case OP_DSRAV:
+                       printf("\t%s,%s,%s",
+                               reg_name[i.RType.rd],
+                               reg_name[i.RType.rt],
+                               reg_name[i.RType.rs]);
+                       break;
+
+               case OP_MFHI:
+               case OP_MFLO:
+                       printf("\t%s", reg_name[i.RType.rd]);
+                       break;
+
+               case OP_JR:
+               case OP_JALR:
+                       delay = 1;
+                       /* FALLTHROUGH */
+               case OP_MTLO:
+               case OP_MTHI:
+                       printf("\t%s", reg_name[i.RType.rs]);
+                       break;
+
+               case OP_MULT:
+               case OP_MULTU:
+               case OP_DMULT:
+               case OP_DMULTU:
+               case OP_DIV:
+               case OP_DIVU:
+               case OP_DDIV:
+               case OP_DDIVU:
+                       printf("\t%s,%s",
+                               reg_name[i.RType.rs],
+                               reg_name[i.RType.rt]);
+                       break;
+
+               case OP_SYSCALL:
+               case OP_SYNC:
+                       break;
+
+               case OP_BREAK:
+                       printf("\t%d", (i.RType.rs << 5) | i.RType.rt);
+                       break;
+
+               default:
+                       printf("\t%s,%s,%s",
+                               reg_name[i.RType.rd],
+                               reg_name[i.RType.rs],
+                               reg_name[i.RType.rt]);
+               };
+               break;
+
+       case OP_BCOND:
+               printf("%s\t%s,", bcond_name[i.IType.rt],
+                       reg_name[i.IType.rs]);
+               goto pr_displ;
+
+       case OP_BLEZ:
+       case OP_BLEZL:
+       case OP_BGTZ:
+       case OP_BGTZL:
+               printf("%s\t%s,", op_name[i.IType.op],
+                       reg_name[i.IType.rs]);
+               goto pr_displ;
+
+       case OP_BEQ:
+       case OP_BEQL:
+               if (i.IType.rs == 0 && i.IType.rt == 0) {
+                       printf("b\t");
+                       goto pr_displ;
+               }
+               /* FALLTHROUGH */
+       case OP_BNE:
+       case OP_BNEL:
+               printf("%s\t%s,%s,", op_name[i.IType.op],
+                       reg_name[i.IType.rs],
+                       reg_name[i.IType.rt]);
+       pr_displ:
+               delay = 1;
+               printf("0x%08x", mdbdot + 4 + ((short)i.IType.imm << 2));
+               break;
+
+       case OP_COP0:
+               switch (i.RType.rs) {
+               case OP_BCx:
+               case OP_BCy:
+                       printf("bc0%c\t",
+                               "ft"[i.RType.rt & COPz_BC_TF_MASK]);
+                       goto pr_displ;
+
+               case OP_MT:
+                       printf("mtc0\t%s,%s",
+                               reg_name[i.RType.rt],
+                               c0_reg[i.RType.rd]);
+                       break;
+
+               case OP_DMT:
+                       printf("dmtc0\t%s,%s",
+                               reg_name[i.RType.rt],
+                               c0_reg[i.RType.rd]);
+                       break;
+
+               case OP_MF:
+                       printf("mfc0\t%s,%s",
+                               reg_name[i.RType.rt],
+                               c0_reg[i.RType.rd]);
+                       break;
+
+               case OP_DMF:
+                       printf("dmfc0\t%s,%s",
+                               reg_name[i.RType.rt],
+                               c0_reg[i.RType.rd]);
+                       break;
+
+               default:
+                       printf("%s", c0_opname[i.FRType.func]);
+               };
+               break;
+
+       case OP_COP1:
+               switch (i.RType.rs) {
+               case OP_BCx:
+               case OP_BCy:
+                       printf("bc1%c\t",
+                               "ft"[i.RType.rt & COPz_BC_TF_MASK]);
+                       goto pr_displ;
+
+               case OP_MT:
+                       printf("mtc1\t%s,f%d",
+                               reg_name[i.RType.rt],
+                               i.RType.rd);
+                       break;
+
+               case OP_MF:
+                       printf("mfc1\t%s,f%d",
+                               reg_name[i.RType.rt],
+                               i.RType.rd);
+                       break;
+
+               case OP_CT:
+                       printf("ctc1\t%s,f%d",
+                               reg_name[i.RType.rt],
+                               i.RType.rd);
+                       break;
+
+               case OP_CF:
+                       printf("cfc1\t%s,f%d",
+                               reg_name[i.RType.rt],
+                               i.RType.rd);
+                       break;
+
+               default:
+                       printf("%s.%s\tf%d,f%d,f%d",
+                               cop1_name[i.FRType.func],
+                               fmt_name[i.FRType.fmt],
+                               i.FRType.fd, i.FRType.fs, i.FRType.ft);
+               };
+               break;
+
+       case OP_J:
+       case OP_JAL:
+               printf("%s\t", op_name[i.JType.op]);
+               printf("0x%8x",(mdbdot & 0xF0000000) | (i.JType.target << 2));
+               delay = 1;
+               break;
+
+       case OP_LWC1:
+       case OP_SWC1:
+               printf("%s\tf%d,", op_name[i.IType.op],
+                       i.IType.rt);
+               goto loadstore;
+
+       case OP_LB:
+       case OP_LH:
+       case OP_LW:
+       case OP_LD:
+       case OP_LBU:
+       case OP_LHU:
+       case OP_LWU:
+       case OP_SB:
+       case OP_SH:
+       case OP_SW:
+       case OP_SD:
+               printf("%s\t%s,", op_name[i.IType.op],
+                       reg_name[i.IType.rt]);
+       loadstore:
+               printf("%d(%s)", (short)i.IType.imm,
+                       reg_name[i.IType.rs]);
+               break;
+
+       case OP_ORI:
+       case OP_XORI:
+               if (i.IType.rs == 0) {
+                       printf("li\t%s,0x%x",
+                               reg_name[i.IType.rt],
+                               i.IType.imm);
+                       break;
+               }
+               /* FALLTHROUGH */
+       case OP_ANDI:
+               printf("%s\t%s,%s,0x%x", op_name[i.IType.op],
+                       reg_name[i.IType.rt],
+                       reg_name[i.IType.rs],
+                       i.IType.imm);
+               break;
+
+       case OP_LUI:
+               printf("%s\t%s,0x%x", op_name[i.IType.op],
+                       reg_name[i.IType.rt],
+                       i.IType.imm);
+               break;
+
+       case OP_ADDI:
+       case OP_DADDI:
+       case OP_ADDIU:
+       case OP_DADDIU:
+               if (i.IType.rs == 0) {
+                       printf("li\t%s,%d",
+                               reg_name[i.IType.rt],
+                               (short)i.IType.imm);
+                       break;
+               }
+               /* FALLTHROUGH */
+       default:
+               printf("%s\t%s,%s,%d", op_name[i.IType.op],
+                       reg_name[i.IType.rt],
+                       reg_name[i.IType.rs],
+                       (short)i.IType.imm);
+       }
+       return(delay);
+}
+
+#define MIPS_JR_RA     0x03e00008      /* instruction code for jr ra */
+
+/*
+ * Very simple memory allocator for mdb.
+ */
+char *
+mdbmalloc(size)
+       int size;
+{
+       static char buffer[4096];
+       static char *bufp = buffer;
+       char *p;
+
+       /* round size up to sizeof(int) */
+       size = (size + sizeof(int) - 1) & ~(sizeof(int) - 1);
+       p = bufp;
+       bufp = p + size;
+       return (p);
+}
+
+/*
+ *     Dump TLB contents.
+ */
+void mips_dump_tlb(int first,int last)
+{
+       int tlbno;
+       struct tlb tlb;
+
+       tlbno = first;
+
+#ifdef R4K
+       while(tlbno <= last) {
+               R4K_TLBRead(tlbno, &tlb);
+               if(tlb.tlb_lo0 & PG_V || tlb.tlb_lo1 & PG_V) {
+                       printf("TLB %2d vad 0x%08x ", tlbno, tlb.tlb_hi);
+               }
+               else {
+                       printf("TLB*%2d vad 0x%08x ", tlbno, tlb.tlb_hi);
+               }
+               printf("0=0x%08x ", pfn_to_vad(tlb.tlb_lo0));
+               printf("%c", tlb.tlb_lo0 & PG_M ? 'M' : ' ');
+               printf("%c", tlb.tlb_lo0 & PG_G ? 'G' : ' ');
+               printf(" atr %x ", (tlb.tlb_lo0 >> 3) & 7);
+               printf("1=0x%08x ", pfn_to_vad(tlb.tlb_lo1));
+               printf("%c", tlb.tlb_lo1 & PG_M ? 'M' : ' ');
+               printf("%c", tlb.tlb_lo1 & PG_G ? 'G' : ' ');
+               printf(" atr %x ", (tlb.tlb_lo1 >> 3) & 7);
+               printf(" sz=%x\n", tlb.tlb_mask);
+
+               tlbno++;
+       }
+#else
+       printf("dumptlb not implemented for r3k yet, sorry.\n");
+#endif
+}
diff --git a/sys/arch/wgrisc/wgrisc/pmap.c b/sys/arch/wgrisc/wgrisc/pmap.c
new file mode 100644 (file)
index 0000000..1c64cfa
--- /dev/null
@@ -0,0 +1,1823 @@
+/*     $OpenBSD: pmap.c,v 1.1.1.1 1997/02/06 16:02:46 pefo Exp $       */
+/* 
+ * Copyright (c) 1992, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * the Systems Programming Group of the University of Utah Computer
+ * Science Department and Ralph Campbell.
+ *
+ * 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: @(#)pmap.c        8.4 (Berkeley) 1/26/94
+ *      $Id: pmap.c,v 1.1.1.1 1997/02/06 16:02:46 pefo Exp $
+ */
+
+/*
+ *     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 <sys/buf.h>
+#ifdef SYSVSHM
+#include <sys/shm.h>
+#endif
+
+#include <vm/vm_kern.h>
+#include <vm/vm_page.h>
+#include <vm/vm_pageout.h>
+
+#include <machine/cpu.h>
+#include <machine/pte.h>
+#include <machine/memconf.h>
+
+extern vm_page_t vm_page_alloc1 __P((void));
+extern void vm_page_free1 __P((vm_page_t));
+
+/*
+ * For each vm_page_t, there is a list of all currently valid virtual
+ * mappings of that page.  An entry is a pv_entry_t, the list is pv_table.
+ * XXX really should do this as a part of the higher level code.
+ */
+typedef 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 */
+       int             pv_flags;       /* Some flags for the mapping */
+} *pv_entry_t;
+#define        PV_UNCACHED     0x0001          /* Page is mapped unchached */
+
+pv_entry_t     pv_table;       /* array of entries, one per page */
+int    pmap_remove_pv();
+
+#ifdef MACHINE_NONCONTIG
+static vm_offset_t     avail_next;
+static vm_offset_t     avail_remaining;
+
+struct physseg {
+       vm_offset_t     start;
+       vm_offset_t     end;
+       int             first_page;
+} physsegs[MAXMEMSEGS+1];
+
+#define        pa_index(pa)    pmap_page_index(pa)
+
+#else
+#define pa_index(pa)           atop((pa) - first_phys_addr)
+#endif /* MACHINE_NONCONTIG */
+
+#define pa_to_pvh(pa)  (&pv_table[pa_index(pa)])
+
+#ifdef DEBUG
+struct {
+       int kernel;     /* entering kernel mapping */
+       int user;       /* entering user mapping */
+       int ptpneeded;  /* needed to allocate a PT page */
+       int pwchange;   /* no mapping change, just wiring or protection */
+       int wchange;    /* no mapping change, just wiring */
+       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 */
+       int cachehit;   /* new entry forced valid entry out */
+} enter_stats;
+struct {
+       int calls;
+       int removes;
+       int flushes;
+       int pidflushes; /* HW pid stolen */
+       int pvfirst;
+       int pvsearch;
+} remove_stats;
+
+#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_PVENTRY    0x0040
+#define PDB_BITS       0x0080
+#define PDB_COLLECT    0x0100
+#define PDB_PROTECT    0x0200
+#define PDB_TLBPID     0x0400
+#define PDB_PARANOIA   0x2000
+#define PDB_WIRING     0x4000
+#define PDB_PVDUMP     0x8000
+
+extern int _ftext[];
+extern int _end[];
+int pmapdebug = 0x0;
+
+#endif /* DEBUG */
+
+struct pmap    kernel_pmap_store;
+
+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) */
+#ifdef ATTR
+char           *pmap_attributes;       /* reference and modify bits */
+#endif
+struct segtab  *free_segtab;           /* free list kept locally */
+u_int          tlbpid_gen = 1;         /* TLB PID generation count */
+int            tlbpid_cnt = 2;         /* next available TLB PID */
+pt_entry_t     *Sysmap;                /* kernel pte table */
+u_int          Sysmapsize;             /* number of pte's in Sysmap */
+
+/*
+ *     Bootstrap the system enough to run with virtual memory.
+ *     firstaddr is the first unused kseg0 address (not page aligned).
+ */
+void
+pmap_bootstrap(firstaddr)
+       vm_offset_t firstaddr;
+{
+       register int i, n, nextpage;
+       register pt_entry_t *spte;
+       struct physseg *pseg;
+       vm_offset_t start = firstaddr;
+       extern int physmem;
+
+#define        valloc(name, type, num) \
+           (name) = (type *)firstaddr; firstaddr = (vm_offset_t)((name)+(num))
+       /*
+        * Allocate a PTE table for the kernel.
+        * The '1024' comes from PAGER_MAP_SIZE in vm_pager_init().
+        * This should be kept in sync.
+        * We also reserve space for kmem_alloc_pageable() for vm_fork().
+        */
+       Sysmapsize = (VM_KMEM_SIZE + VM_MBUF_SIZE + VM_PHYS_SIZE +
+               nbuf * MAXBSIZE + 16 * NCARGS) / NBPG + 1024 + 256;
+       Sysmapsize += maxproc * UPAGES * 2;
+#ifdef SYSVSHM
+       Sysmapsize += shminfo.shmall;
+#endif
+       valloc(Sysmap, pt_entry_t, Sysmapsize);
+#ifdef ATTR
+       valloc(pmap_attributes, char, physmem);
+#endif
+       /*
+        * Allocate memory for pv_table.
+        * This will allocate more entries than we really need.
+        * We could do this in pmap_init when we know the actual
+        * phys_start and phys_end but its better to use kseg0 addresses
+        * rather than kernel virtual addresses mapped through the TLB.
+        */
+#ifdef MACHINE_NONCONTIG
+       i = 0;
+       for( n = 0; n < MAXMEMSEGS; n++) {
+               i += mips_btop(mem_layout[n].mem_size);
+       }
+#else
+       i = physmem - mips_btop(CACHED_TO_PHYS(firstaddr));
+#endif /*MACHINE_NONCONTIG*/
+       valloc(pv_table, struct pv_entry, i);
+
+       /*
+        * Clear allocated memory.
+        */
+       firstaddr = mips_round_page(firstaddr);
+       bzero((caddr_t)start, firstaddr - start);
+
+       avail_start = CACHED_TO_PHYS(firstaddr);
+       avail_end = mips_ptob(physmem);
+
+#ifdef MACHINE_NONCONTIG
+       avail_remaining = 0;
+       nextpage = 0;
+
+       /*
+        * Now set up memory areas. Be careful to remove areas used
+         * for the OS and for exception vector stuff.
+         */
+       pseg = &physsegs[0];
+
+       for( i = 0; i < MAXMEMSEGS; i++) {
+               /* Adjust for the kernel exeption vectors and sys data area */
+               if(mem_layout[i].mem_start < 0x20000) { 
+                       if((mem_layout[i].mem_start + mem_layout[i].mem_size) < 0x8000)
+                               continue;       /* To small skip it */
+                       mem_layout[i].mem_size -= 0x20000 - mem_layout[i].mem_start;
+                       mem_layout[i].mem_start = 0x20000;  /* Adjust to be above vec's */
+               }
+               /* Adjust for the kernel expansion area (bufs etc) */
+               if((mem_layout[i].mem_start + mem_layout[i].mem_size > CACHED_TO_PHYS(_ftext)) && 
+                  (mem_layout[i].mem_start < CACHED_TO_PHYS(avail_start))) { 
+                       mem_layout[i].mem_size -= CACHED_TO_PHYS(avail_start) - mem_layout[i].mem_start;
+                       mem_layout[i].mem_start = CACHED_TO_PHYS(avail_start);
+               }
+
+               if(mem_layout[i].mem_size == 0)
+                       continue;
+
+               pseg->start = mem_layout[i].mem_start;
+               pseg->end = pseg->start + mem_layout[i].mem_size;
+               pseg->first_page = nextpage;
+               nextpage += (pseg->end - pseg->start) / NBPG;
+               avail_remaining += (pseg->end - pseg->start) / NBPG;
+               pseg++;
+       }
+
+       avail_next = physsegs[0].start;
+
+#endif /* MACHINE_NONCONTIG */
+
+       virtual_avail = VM_MIN_KERNEL_ADDRESS;
+       virtual_end = VM_MIN_KERNEL_ADDRESS + Sysmapsize * NBPG;
+       /* XXX need to decide how to set cnt.v_page_size */
+
+       simple_lock_init(&pmap_kernel()->pm_lock);
+       pmap_kernel()->pm_count = 1;
+
+       /*
+        * The R4?00 stores only one copy of the Global bit in the
+        * translation lookaside buffer for each 2 page entry. 
+        * Thus invalid entrys must have the Global bit set so
+        * when Entry LO and Entry HI G bits are anded together
+        * they will produce a global bit to store in the tlb.
+        */
+       for(i = 0, spte = Sysmap; i < Sysmapsize; i++, spte++)
+               spte->pt_entry = PG_G;
+}
+
+/*
+ * 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;
+{
+       vm_offset_t val;
+       extern boolean_t vm_page_startup_initialized;
+
+       if (vm_page_startup_initialized)
+               panic("pmap_bootstrap_alloc: called after startup initialized");
+
+       val = PHYS_TO_CACHED(avail_start);
+       size = round_page(size);
+       avail_start += size;
+
+       blkclr((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
+#ifdef MACHINE_NONCONTIG
+pmap_init()
+#else
+pmap_init(phys_start, phys_end)
+       vm_offset_t phys_start, phys_end;
+#endif
+{
+
+#ifdef DEBUG
+       if (pmapdebug & (PDB_FOLLOW|PDB_INIT))
+#ifdef MACHINE_NONCONTIG
+               printf("pmap_init(%lx, %lx)\n", avail_start, avail_end);
+#else
+               printf("pmap_init(%lx, %lx)\n", phys_start, phys_end);
+#endif
+#endif /*DEBUG*/
+}
+
+#ifdef MACHINE_NONCONTIG
+inline int
+pmap_page_index(pa)
+    vm_offset_t pa;
+{
+       struct physseg *ps = &physsegs[0];
+       while (ps->start) {
+               if(pa >= ps->start && pa < ps->end) {
+                       return(atop(pa - ps->start) + ps->first_page);
+               }
+               ps++;
+       }
+       return -1;
+}
+
+unsigned int
+pmap_free_pages()
+{
+        return avail_remaining;
+}
+
+void
+pmap_virtual_space(startp, endp)
+       vm_offset_t  *startp;
+       vm_offset_t  *endp;
+{
+       *startp = virtual_avail;
+       *endp = virtual_end;
+}
+
+int
+pmap_next_page(p_addr)
+       vm_offset_t *p_addr;
+{
+       static int cur_seg = 0;
+
+       if (physsegs[cur_seg].start == 0)
+               return FALSE;
+       if (avail_next == physsegs[cur_seg].end) {
+               avail_next = physsegs[++cur_seg].start;
+       }
+
+       if (avail_next == 0)
+               return FALSE;
+       *p_addr = avail_next;
+       avail_next += NBPG;
+       avail_remaining--;
+       return TRUE;
+}
+#endif /*MACHINE_NONCONTIG*/
+
+/*
+ *     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;
+{
+       register int i;
+       int s;
+       extern struct vmspace vmspace0;
+       extern struct user *proc0paddr;
+
+#ifdef DEBUG
+       if (pmapdebug & (PDB_FOLLOW|PDB_CREATE))
+               printf("pmap_pinit(%x)\n", pmap);
+#endif
+       simple_lock_init(&pmap->pm_lock);
+       pmap->pm_count = 1;
+       if (free_segtab) {
+               s = splimp();
+               pmap->pm_segtab = free_segtab;
+               free_segtab = *(struct segtab **)free_segtab;
+               pmap->pm_segtab->seg_tab[0] = NULL;
+               splx(s);
+       } else {
+               register struct segtab *stp;
+               vm_page_t mem;
+               void pmap_zero_page();
+
+               do {
+                       mem = vm_page_alloc1();
+                       if (mem == NULL) {
+                               VM_WAIT;        /* XXX What else can we do */
+                       }                       /* XXX Deadlock situations? */
+               } while (mem == NULL);
+
+               pmap_zero_page(VM_PAGE_TO_PHYS(mem));
+               pmap->pm_segtab = stp = (struct segtab *)
+                       PHYS_TO_CACHED(VM_PAGE_TO_PHYS(mem));
+               i = NBPG / sizeof(struct segtab);
+               s = splimp();
+               while (--i != 0) {
+                       stp++;
+                       *(struct segtab **)stp = free_segtab;
+                       free_segtab = stp;
+               }
+               splx(s);
+       }
+#ifdef DIAGNOSTIC
+       for (i = 0; i < PMAP_SEGTABSIZE; i++)
+               if (pmap->pm_segtab->seg_tab[i] != 0)
+                       panic("pmap_pinit: pm_segtab != 0");
+#endif
+       if (pmap == &vmspace0.vm_pmap) {
+               /*
+                * The initial process has already been allocated a TLBPID
+                * in mach_init().
+                */
+               pmap->pm_tlbpid = 1;
+               pmap->pm_tlbgen = tlbpid_gen;
+               proc0paddr->u_pcb.pcb_segtab = (void *)pmap->pm_segtab;
+       } else {
+               pmap->pm_tlbpid = 0;
+               pmap->pm_tlbgen = 0;
+       }
+}
+
+/*
+ *     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;
+
+#ifdef DEBUG
+       if (pmapdebug & (PDB_FOLLOW|PDB_CREATE))
+               printf("pmap_destroy(%x)\n", pmap);
+#endif
+       if (pmap == NULL)
+               return;
+
+       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 pmap_t pmap;
+{
+
+#ifdef DEBUG
+       if (pmapdebug & (PDB_FOLLOW|PDB_CREATE))
+               printf("pmap_release(%x)\n", pmap);
+#endif
+
+       if (pmap->pm_segtab) {
+               register pt_entry_t *pte;
+               register int i;
+               int s;
+#ifdef DIAGNOSTIC
+               register int j;
+#endif
+
+               for (i = 0; i < PMAP_SEGTABSIZE; i++) {
+                       /* get pointer to segment map */
+                       pte = pmap->pm_segtab->seg_tab[i];
+                       if (!pte)
+                               continue;
+#ifdef DIAGNOSTIC
+                       for (j = 0; j < NPTEPG; j++) {
+                               if ((pte+j)->pt_entry)
+                                       panic("pmap_release: segmap not empty");
+                       }
+#endif
+#ifdef R4K
+                       R4K_HitFlushDCache(pte, PAGE_SIZE);
+#endif
+                       vm_page_free1(
+                               PHYS_TO_VM_PAGE(CACHED_TO_PHYS(pte)));
+                       pmap->pm_segtab->seg_tab[i] = NULL;
+               }
+               s = splimp();
+               *(struct segtab **)pmap->pm_segtab = free_segtab;
+               free_segtab = pmap->pm_segtab;
+               splx(s);
+               pmap->pm_segtab = NULL;
+       }
+}
+
+/*
+ *     Add a reference to the specified pmap.
+ */
+void
+pmap_reference(pmap)
+       pmap_t pmap;
+{
+
+#ifdef DEBUG
+       if (pmapdebug & PDB_FOLLOW)
+               printf("pmap_reference(%x)\n", pmap);
+#endif
+       if (pmap != NULL) {
+               simple_lock(&pmap->pm_lock);
+               pmap->pm_count++;
+               simple_unlock(&pmap->pm_lock);
+       }
+}
+
+/*
+ *     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;
+       vm_offset_t sva, eva;
+{
+       register vm_offset_t nssva;
+       register pt_entry_t *pte;
+       unsigned entry;
+       int flush;
+
+#ifdef DEBUG
+       if (pmapdebug & (PDB_FOLLOW|PDB_REMOVE|PDB_PROTECT))
+               printf("pmap_remove(%x, %x, %x)\n", pmap, sva, eva);
+       remove_stats.calls++;
+#endif
+       if (pmap == NULL)
+               return;
+
+       if (!pmap->pm_segtab) {
+               register pt_entry_t *pte;
+
+               /* remove entries from kernel pmap */
+#ifdef DIAGNOSTIC
+               if (sva < VM_MIN_KERNEL_ADDRESS || eva > virtual_end)
+                       panic("pmap_remove: kva not in range");
+#endif
+               pte = kvtopte(sva);
+               for (; sva < eva; sva += NBPG, pte++) {
+                       entry = pte->pt_entry;
+                       if (!(entry & PG_V))
+                               continue;
+                       if (entry & PG_WIRED)
+                               pmap->pm_stats.wired_count--;
+                       pmap->pm_stats.resident_count--;
+                       if(pmap_remove_pv(pmap, sva, pfn_to_vad(entry))) {
+#ifdef R4K
+                               R4K_FlushDCache(sva, PAGE_SIZE);
+#endif
+                       }
+#ifdef ATTR
+                       pmap_attributes[atop(pfn_to_vad(entry))] = 0;
+#endif
+                       /*
+                        * Flush the TLB for the given address.
+                        */
+                       pte->pt_entry = PG_NV | PG_G; /* See above about G bit */
+#ifdef R4K
+                       R4K_TLBFlushAddr(sva);
+#else
+                       R3K_TLBFlushAddr(sva);
+#endif
+#ifdef DEBUG
+                       remove_stats.flushes++;
+
+#endif
+               }
+               return;
+       }
+
+#ifdef DIAGNOSTIC
+       if (eva > VM_MAXUSER_ADDRESS)
+               panic("pmap_remove: uva not in range");
+#endif
+       while (sva < eva) {
+               nssva = mips_trunc_seg(sva) + NBSEG;
+               if (nssva == 0 || nssva > eva)
+                       nssva = eva;
+               /*
+                * If VA belongs to an unallocated segment,
+                * skip to the next segment boundary.
+                */
+               if (!(pte = pmap_segmap(pmap, sva))) {
+                       sva = nssva;
+                       continue;
+               }
+               /*
+                * Invalidate every valid mapping within this segment.
+                */
+               pte += uvtopte(sva);
+               for (; sva < nssva; sva += NBPG, pte++) {
+                       entry = pte->pt_entry;
+                       if (!(entry & PG_V))
+                               continue;
+                       if (entry & PG_WIRED)
+                               pmap->pm_stats.wired_count--;
+                       pmap->pm_stats.resident_count--;
+                       if(pmap_remove_pv(pmap, sva, pfn_to_vad(entry))) {
+#ifdef R4K
+                               R4K_FlushDCache(sva, PAGE_SIZE);
+#endif
+                       }
+#ifdef ATTR
+                       pmap_attributes[atop(pfn_to_vad(entry))] = 0;
+#endif
+                       pte->pt_entry = PG_NV;
+                       /*
+                        * Flush the TLB for the given address.
+                        */
+                       if (pmap->pm_tlbgen == tlbpid_gen) {
+#ifdef R4K
+                               R4K_TLBFlushAddr(sva | (pmap->pm_tlbpid <<
+                                       R4K_PID_SHIFT));
+#else
+                               R3K_TLBFlushAddr(sva | (pmap->pm_tlbpid <<
+                                       R3K_PID_SHIFT));
+#endif
+#ifdef DEBUG
+                               remove_stats.flushes++;
+#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 pv_entry_t pv;
+       register vm_offset_t va;
+       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 (!IS_VM_PHYSADDR(pa))
+               return;
+
+       switch (prot) {
+       case VM_PROT_READ|VM_PROT_WRITE:
+       case VM_PROT_ALL:
+               break;
+
+       /* copy_on_write */
+       case VM_PROT_READ:
+       case VM_PROT_READ|VM_PROT_EXECUTE:
+               pv = pa_to_pvh(pa);
+               s = splimp();
+               /*
+                * Loop over all current mappings setting/clearing as appropos.
+                */
+               if (pv->pv_pmap != NULL) {
+                       for (; pv; pv = pv->pv_next) {
+                               extern vm_offset_t pager_sva, pager_eva;
+
+                               va = pv->pv_va;
+
+                               /*
+                                * XXX don't write protect pager mappings
+                                */
+                               if (va >= pager_sva && va < pager_eva)
+                                       continue;
+                               pmap_protect(pv->pv_pmap, va, va + PAGE_SIZE,
+                                       prot);
+                       }
+               }
+               splx(s);
+               break;
+
+       /* remove_all */
+       default:
+               pv = pa_to_pvh(pa);
+               s = splimp();
+               while (pv->pv_pmap != NULL) {
+                       pmap_remove(pv->pv_pmap, pv->pv_va,
+                                   pv->pv_va + PAGE_SIZE);
+               }
+               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;
+       vm_offset_t sva, eva;
+       vm_prot_t prot;
+{
+       register vm_offset_t nssva;
+       register pt_entry_t *pte;
+       register unsigned entry;
+       u_int p;
+
+#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;
+
+       if ((prot & VM_PROT_READ) == VM_PROT_NONE) {
+               pmap_remove(pmap, sva, eva);
+               return;
+       }
+
+       p = (prot & VM_PROT_WRITE) ? PG_M : PG_RO;
+
+       if (!pmap->pm_segtab) {
+               /*
+                * Change entries in kernel pmap.
+                * This will trap if the page is writeable (in order to set
+                * the dirty bit) even if the dirty bit is already set. The
+                * optimization isn't worth the effort since this code isn't
+                * executed much. The common case is to make a user page
+                * read-only.
+                */
+#ifdef DIAGNOSTIC
+               if (sva < VM_MIN_KERNEL_ADDRESS || eva > virtual_end)
+                       panic("pmap_protect: kva not in range");
+#endif
+               pte = kvtopte(sva);
+               for (; sva < eva; sva += NBPG, pte++) {
+                       entry = pte->pt_entry;
+                       if (!(entry & PG_V))
+                               continue;
+                       entry = (entry & ~(PG_M | PG_RO)) | p;
+                       pte->pt_entry = entry;
+                       /*
+                        * Update the TLB if the given address is in the cache.
+                        */
+#ifdef R4K
+                       R4K_TLBUpdate(sva, entry);
+#else
+                       R3K_TLBUpdate(sva, entry);
+#endif
+               }
+               return;
+       }
+
+#ifdef DIAGNOSTIC
+       if (eva > VM_MAXUSER_ADDRESS)
+               panic("pmap_protect: uva not in range");
+#endif
+       while (sva < eva) {
+               nssva = mips_trunc_seg(sva) + NBSEG;
+               if (nssva == 0 || nssva > eva)
+                       nssva = eva;
+               /*
+                * If VA belongs to an unallocated segment,
+                * skip to the next segment boundary.
+                */
+               if (!(pte = pmap_segmap(pmap, sva))) {
+                       sva = nssva;
+                       continue;
+               }
+               /*
+                * Change protection on every valid mapping within this segment.
+                */
+               pte += (sva >> PGSHIFT) & (NPTEPG - 1);
+               for (; sva < nssva; sva += NBPG, pte++) {
+                       entry = pte->pt_entry;
+                       if (!(entry & PG_V))
+                               continue;
+                       entry = (entry & ~(PG_M | PG_RO)) | p;
+                       pte->pt_entry = entry;
+                       /*
+                        * Update the TLB if the given address is in the cache.
+                        */
+                       if (pmap->pm_tlbgen == tlbpid_gen)
+#ifdef R4K
+                               R4K_TLBUpdate(sva | (pmap->pm_tlbpid <<
+                                       R4K_PID_SHIFT), entry);
+#else
+                               R3K_TLBUpdate(sva | (pmap->pm_tlbpid <<
+                                       R3K_PID_SHIFT), entry);
+#endif
+               }
+       }
+}
+
+/*
+ *     Return RO protection of page.
+ */
+int
+pmap_is_page_ro(pmap, va, entry)
+       pmap_t      pmap;
+       vm_offset_t va;
+       int         entry;
+{
+       return(entry & PG_RO);
+}
+
+/*
+ *     pmap_page_cache:
+ *
+ *     Change all mappings of a page to cached/uncached.
+ */
+void
+pmap_page_cache(pa,mode)
+       vm_offset_t pa;
+{
+       register pv_entry_t pv;
+       register pt_entry_t *pte;
+       register vm_offset_t va;
+       register unsigned entry;
+       register unsigned newmode;
+       int s;
+
+#ifdef DEBUG
+       if (pmapdebug & (PDB_FOLLOW|PDB_ENTER))
+               printf("pmap_page_uncache(%x)\n", pa);
+#endif
+       if (!IS_VM_PHYSADDR(pa))
+               return;
+
+       newmode = mode & PV_UNCACHED ? PG_UNCACHED : PG_CACHED;
+       pv = pa_to_pvh(pa);
+       s = splimp();
+       while (pv) {
+               pv->pv_flags = (pv->pv_flags & ~PV_UNCACHED) | mode;
+               if (!pv->pv_pmap->pm_segtab) {
+               /*
+                * Change entries in kernel pmap.
+                */
+                       pte = kvtopte(pv->pv_va);
+                       entry = pte->pt_entry;
+                       if (entry & PG_V) {
+                               entry = (entry & ~PG_CACHEMODE) | newmode;
+                               pte->pt_entry = entry;
+#ifdef R4K
+                               R4K_TLBUpdate(pv->pv_va, entry);
+#else
+                               R3K_TLBUpdate(pv->pv_va, entry);
+#endif
+                       }
+               }
+               else {
+                       if (pte = pmap_segmap(pv->pv_pmap, pv->pv_va)) {
+                               pte += (pv->pv_va >> PGSHIFT) & (NPTEPG - 1);
+                               entry = pte->pt_entry;
+                               if (entry & PG_V) {
+                                       entry = (entry & ~PG_CACHEMODE) | newmode;
+                                       pte->pt_entry = entry;
+                                       if (pv->pv_pmap->pm_tlbgen == tlbpid_gen)
+#ifdef R4K
+                                               R4K_TLBUpdate(pv->pv_va | (pv->pv_pmap->pm_tlbpid <<
+                                                       R4K_PID_SHIFT), entry);
+#else
+                                               R3K_TLBUpdate(pv->pv_va | (pv->pv_pmap->pm_tlbpid <<
+                                                       R3K_PID_SHIFT), entry);
+#endif
+                               }
+                       }
+               }
+               pv = pv->pv_next;
+       }
+
+       splx(s);
+}
+
+/*
+ *     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 u_int npte;
+       register int i, j;
+       vm_page_t mem;
+
+#ifdef DEBUG
+       if (pmapdebug & (PDB_FOLLOW|PDB_ENTER))
+               printf("pmap_enter(%x, %x, %x, %x, %x)\n",
+                      pmap, va, pa, prot, wired);
+#endif
+#ifdef DIAGNOSTIC
+       if (!pmap)
+               panic("pmap_enter: pmap");
+       if (!pmap->pm_segtab) {
+               enter_stats.kernel++;
+               if (va < VM_MIN_KERNEL_ADDRESS || va >= virtual_end)
+                       panic("pmap_enter: kva");
+       } else {
+               enter_stats.user++;
+               if (va >= VM_MAXUSER_ADDRESS)
+                       panic("pmap_enter: uva");
+       }
+       if (pa & 0x80000000)
+               panic("pmap_enter: pa");
+       if (!(prot & VM_PROT_READ))
+               panic("pmap_enter: prot");
+#endif
+
+       if (IS_VM_PHYSADDR(pa)) {
+               register pv_entry_t pv, npv;
+               int s;
+
+               if (!(prot & VM_PROT_WRITE))
+                       npte = PG_ROPAGE;
+               else {
+                       register vm_page_t mem;
+
+                       mem = PHYS_TO_VM_PAGE(pa);
+                       if ((int)va < 0) {
+                               /*
+                                * Don't bother to trap on kernel writes,
+                                * just record page as dirty.
+                                */
+                               npte = PG_RWPAGE;
+#if 0 /*XXX*/
+                               mem->flags &= ~PG_CLEAN;
+#endif
+                       } else
+#ifdef ATTR
+                               if ((pmap_attributes[atop(pa)] &
+                                   PMAP_ATTR_MOD) || !(mem->flags & PG_CLEAN))
+#else
+                               if (!(mem->flags & PG_CLEAN))
+#endif
+                                       npte = PG_RWPAGE;
+                               else
+                                       npte = PG_CWPAGE;
+               }
+
+#ifdef DEBUG
+               enter_stats.managed++;
+#endif
+               /*
+                * Enter the pmap and virtual address into the
+                * physical to virtual map table.
+                */
+               pv = pa_to_pvh(pa);
+               s = splimp();
+#ifdef DEBUG
+               if (pmapdebug & PDB_ENTER)
+                       printf("pmap_enter: pv %x: was %x/%x/%x\n",
+                              pv, pv->pv_va, pv->pv_pmap, pv->pv_next);
+#endif
+               if (pv->pv_pmap == NULL) {
+                       /*
+                        * No entries yet, use header as the first entry
+                        */
+#ifdef DEBUG
+                       if (pmapdebug & PDB_PVENTRY)
+                               printf("pmap_enter: first pv: pmap %x va %x\n",
+                                       pmap, va);
+                       enter_stats.firstpv++;
+#endif
+                       pv->pv_va = va;
+                       pv->pv_flags = 0;
+                       pv->pv_pmap = pmap;
+                       pv->pv_next = NULL;
+               } else {
+#ifdef R4K
+                       if (!(pv->pv_flags & PV_UNCACHED)) {
+                       /*
+                        * There is at least one other VA mapping this page.
+                        * Check if they are cache index compatible. If not
+                        * remove all mappings, flush the cache and set page
+                        * to be mapped uncached. Caching will be restored
+                        * when pages are mapped compatible again. NOT!
+                        */
+                               for (npv = pv; npv; npv = npv->pv_next) {
+                                       /*
+                                        * Check cache aliasing incompatibility
+                                        */
+                                       if((npv->pv_va & CpuCacheAliasMask) != (va & CpuCacheAliasMask)) {
+                                               printf("pmap_enter: creating uncached mapping 0x%x, 0x%x.\n",npv->pv_va, va);
+                                               pmap_page_cache(pa,PV_UNCACHED);
+                                               R4K_FlushDCache(pv->pv_va, PAGE_SIZE);
+                                               npte = (npte & ~PG_CACHEMODE) | PG_UNCACHED;
+                                               break;
+                                       }
+                               }
+                       }
+                       else {
+                               npte = (npte & ~PG_CACHEMODE) | PG_UNCACHED;
+                       }
+#endif
+                       /*
+                        * There is at least one other VA mapping this page.
+                        * Place this entry after the header.
+                        *
+                        * Note: the entry may already be in the table if
+                        * we are only changing the protection bits.
+                        */
+                       for (npv = pv; npv; npv = npv->pv_next) {
+                               if (pmap == npv->pv_pmap && va == npv->pv_va) {
+#ifdef DIAGNOSTIC
+                                       unsigned entry;
+
+                                       if (!pmap->pm_segtab)
+                                               entry = kvtopte(va)->pt_entry;
+                                       else {
+                                               pte = pmap_segmap(pmap, va);
+                                               if (pte) {
+                                                       pte += (va >> PGSHIFT) &
+                                                           (NPTEPG - 1);
+                                                       entry = pte->pt_entry;
+                                               } else
+                                                       entry = 0;
+                                       }
+                                       if (!(entry & PG_V) ||
+                                           pfn_to_vad(entry) != pa)
+                                               printf(
+                       "pmap_enter: found va %x pa %x in pv_table but != %x\n",
+                                                       va, pa, entry);
+#endif
+                                       goto fnd;
+                               }
+                       }
+#ifdef DEBUG
+                       if (pmapdebug & PDB_PVENTRY)
+                               printf("pmap_enter: new pv: pmap %x va %x\n",
+                                       pmap, va);
+#endif
+                       /* can this cause us to recurse forever? */
+                       npv = (pv_entry_t)
+                               malloc(sizeof *npv, M_VMPVENT, M_NOWAIT);
+                       npv->pv_va = va;
+                       npv->pv_pmap = pmap;
+                       npv->pv_next = pv->pv_next;
+                       npv->pv_flags = pv->pv_flags;
+                       pv->pv_next = npv;
+#ifdef DEBUG
+                       if (!npv->pv_next)
+                               enter_stats.secondpv++;
+#endif
+               fnd:
+                       ;
+               }
+               splx(s);
+       } else {
+               /*
+                * Assumption: if it is not part of our managed memory
+                * then it must be device memory which may be volitile.
+                */
+#ifdef DEBUG
+               enter_stats.unmanaged++;
+#endif
+               npte = (prot & VM_PROT_WRITE) ? (PG_IOPAGE & ~PG_G) : (PG_IOPAGE& ~(PG_G | PG_M));
+       }
+
+       /*
+        * The only time we need to flush the cache is if we
+        * execute from a physical address and then change the data.
+        * This is the best place to do this.
+        * pmap_protect() and pmap_remove() are mostly used to switch
+        * between R/W and R/O pages.
+        * NOTE: we only support cache flush for read only text.
+        */
+       if (prot == (VM_PROT_READ | VM_PROT_EXECUTE))
+#ifdef R4K
+               R4K_FlushICache(PHYS_TO_CACHED(pa), PAGE_SIZE);
+#else
+               R3K_FlushICache(PHYS_TO_CACHED(pa), PAGE_SIZE);
+#endif
+
+       if (!pmap->pm_segtab) {
+               /* enter entries into kernel pmap */
+               pte = kvtopte(va);
+               npte |= vad_to_pfn(pa) | PG_ROPAGE | PG_G;
+               if (wired) {
+                       pmap->pm_stats.wired_count++;
+                       npte |= PG_WIRED;
+               }
+               if (!(pte->pt_entry & PG_V)) {
+                       pmap->pm_stats.resident_count++;
+               } else {
+#ifdef DIAGNOSTIC
+                       if (pte->pt_entry & PG_WIRED)
+                               panic("pmap_enter: kernel wired");
+#endif
+               }
+               /*
+                * Update the same virtual address entry.
+                */
+#ifdef R4K
+               j = R4K_TLBUpdate(va, npte);
+#else
+               j = R3K_TLBUpdate(va, npte);
+#endif
+               pte->pt_entry = npte;
+               return;
+       }
+
+       if (!(pte = pmap_segmap(pmap, va))) {
+               do {
+                       mem = vm_page_alloc1();
+                       if (mem == NULL) {
+                               VM_WAIT;        /* XXX What else can we do */
+                       }                       /* XXX Deadlock situations? */
+               } while (mem == NULL);
+
+               pmap_zero_page(VM_PAGE_TO_PHYS(mem));
+               pmap_segmap(pmap, va) = pte = (pt_entry_t *)
+                       PHYS_TO_CACHED(VM_PAGE_TO_PHYS(mem));
+#ifdef DIAGNOSTIC
+               for (i = 0; i < NPTEPG; i++) {
+                       if ((pte+i)->pt_entry)
+                               panic("pmap_enter: new segmap not empty");
+               }
+#endif
+       }
+       pte += (va >> PGSHIFT) & (NPTEPG - 1);
+
+       /*
+        * Now validate mapping with desired protection/wiring.
+        */
+       npte |= vad_to_pfn(pa);
+       if (wired) {
+               pmap->pm_stats.wired_count++;
+               npte |= PG_WIRED;
+       }
+#ifdef DEBUG
+       if (pmapdebug & PDB_ENTER) {
+               printf("pmap_enter: new pte %x", npte);
+               if (pmap->pm_tlbgen == tlbpid_gen)
+                       printf(" tlbpid %d", pmap->pm_tlbpid);
+               printf("\n");
+       }
+#endif
+       if (!(pte->pt_entry & PG_V)) {
+               pmap->pm_stats.resident_count++;
+       }
+       pte->pt_entry = npte;
+       if (pmap->pm_tlbgen == tlbpid_gen)
+#ifdef R4K
+               j = R4K_TLBUpdate(va | (pmap->pm_tlbpid << R4K_PID_SHIFT), npte);
+#else
+               j = R3K_TLBUpdate(va | (pmap->pm_tlbpid << R3K_PID_SHIFT), npte);
+#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;
+       u_int p;
+       register int i;
+
+#ifdef DEBUG
+       if (pmapdebug & (PDB_FOLLOW|PDB_WIRING))
+               printf("pmap_change_wiring(%x, %x, %x)\n", pmap, va, wired);
+#endif
+       if (pmap == NULL)
+               return;
+
+       p = wired ? PG_WIRED : 0;
+
+       /*
+        * Don't need to flush the TLB since PG_WIRED is only in software.
+        */
+       if (!pmap->pm_segtab) {
+               /* change entries in kernel pmap */
+#ifdef DIAGNOSTIC
+               if (va < VM_MIN_KERNEL_ADDRESS || va >= virtual_end)
+                       panic("pmap_change_wiring");
+#endif
+               pte = kvtopte(va);
+       } else {
+               if (!(pte = pmap_segmap(pmap, va)))
+                       return;
+               pte += (va >> PGSHIFT) & (NPTEPG - 1);
+       }
+
+       if (!(pte->pt_entry & PG_WIRED) && p)
+               pmap->pm_stats.wired_count++;
+       else if ((pte->pt_entry & PG_WIRED) && !p)
+               pmap->pm_stats.wired_count--;
+
+       if (pte->pt_entry & PG_V)
+               pte->pt_entry = (pte->pt_entry & ~PG_WIRED) | p;
+}
+
+/*
+ *     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
+
+       if (!pmap->pm_segtab) {
+#ifdef DIAGNOSTIC
+               if (va < VM_MIN_KERNEL_ADDRESS || va >= virtual_end)
+                       panic("pmap_extract");
+#endif
+               pa = pfn_to_vad(kvtopte(va)->pt_entry);
+       } else {
+               register pt_entry_t *pte;
+
+               if (!(pte = pmap_segmap(pmap, va)))
+                       pa = 0;
+               else {
+                       pte += (va >> PGSHIFT) & (NPTEPG - 1);
+                       pa = pfn_to_vad(pte->pt_entry);
+               }
+       }
+       if (pa)
+               pa |= va & PGOFSET;
+
+#ifdef DEBUG
+       if (pmapdebug & PDB_FOLLOW)
+               printf("pmap_extract: pa %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
+}
+
+/*
+ *     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;
+{
+
+#ifdef DEBUG
+       if (pmapdebug & PDB_FOLLOW)
+               printf("pmap_collect(%x)\n", pmap);
+#endif
+}
+
+/*
+ *     pmap_zero_page zeros the specified (machine independent) page.
+ */
+void
+pmap_zero_page(phys)
+       vm_offset_t phys;
+{
+       register int *p, *end;
+
+#ifdef DEBUG
+       if (pmapdebug & PDB_FOLLOW)
+               printf("pmap_zero_page(%x)\n", phys);
+#endif
+/*XXX FIXME Not very sophisticated */
+#ifdef R4K
+       R4K_FlushCache();
+#endif
+       p = (int *)PHYS_TO_CACHED(phys);
+       end = p + PAGE_SIZE / sizeof(int);
+       do {
+               p[0] = 0;
+               p[1] = 0;
+               p[2] = 0;
+               p[3] = 0;
+               p += 4;
+       } while (p != end);
+/*XXX FIXME Not very sophisticated */
+#ifdef R4K
+       R4K_FlushCache();
+#endif
+}
+
+/*
+ *     pmap_copy_page copies the specified (machine independent)
+ *     page.
+ */
+void
+pmap_copy_page(src, dst)
+       vm_offset_t src, dst;
+{
+       register int *s, *d, *end;
+       register int tmp0, tmp1, tmp2, tmp3;
+
+#ifdef DEBUG
+       if (pmapdebug & PDB_FOLLOW)
+               printf("pmap_copy_page(%x, %x)\n", src, dst);
+#endif
+/*XXX FIXME Not very sophisticated */
+#ifdef R4K
+       R4K_FlushCache();
+#endif
+       s = (int *)PHYS_TO_CACHED(src);
+       d = (int *)PHYS_TO_CACHED(dst);
+       end = s + PAGE_SIZE / sizeof(int);
+       do {
+               tmp0 = s[0];
+               tmp1 = s[1];
+               tmp2 = s[2];
+               tmp3 = s[3];
+               d[0] = tmp0;
+               d[1] = tmp1;
+               d[2] = tmp2;
+               d[3] = tmp3;
+               s += 4;
+               d += 4;
+       } while (s != end);
+/*XXX FIXME Not very sophisticated */
+#ifdef R4K
+       R4K_FlushCache();
+#endif
+}
+
+/*
+ *     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
+}
+
+/*
+ *     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
+#ifdef ATTR
+       pmap_attributes[atop(pa)] &= ~PMAP_ATTR_MOD;
+#endif
+}
+
+/*
+ *     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
+#ifdef ATTR
+       pmap_attributes[atop(pa)] &= ~PMAP_ATTR_REF;
+#endif
+}
+
+/*
+ *     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 ATTR
+       return (pmap_attributes[atop(pa)] & PMAP_ATTR_REF);
+#else
+       return (FALSE);
+#endif
+}
+
+/*
+ *     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 ATTR
+       return (pmap_attributes[atop(pa)] & PMAP_ATTR_MOD);
+#else
+       return (FALSE);
+#endif
+}
+
+vm_offset_t
+pmap_phys_address(ppn)
+       int ppn;
+{
+
+#ifdef DEBUG
+       if (pmapdebug & PDB_FOLLOW)
+               printf("pmap_phys_address(%x)\n", ppn);
+#endif
+       return (mips_ptob(ppn));
+}
+
+/*
+ * Miscellaneous support routines
+ */
+
+/*
+ * Allocate a hardware PID and return it.
+ * It takes almost as much or more time to search the TLB for a
+ * specific PID and flush those entries as it does to flush the entire TLB.
+ * Therefore, when we allocate a new PID, we just take the next number. When
+ * we run out of numbers, we flush the TLB, increment the generation count
+ * and start over. PID zero is reserved for kernel use.
+ * This is called only by switch().
+ */
+int
+pmap_alloc_tlbpid(p)
+       register struct proc *p;
+{
+       register pmap_t pmap;
+       register int id;
+
+       pmap = &p->p_vmspace->vm_pmap;
+       if (pmap->pm_tlbgen != tlbpid_gen) {
+               id = tlbpid_cnt;
+#ifdef R4K
+               if (id == R4K_NUM_PIDS) {
+                       R4K_TLBFlush();
+#else
+               if (id == R3K_NUM_PIDS) {
+                       R3K_TLBFlush();
+#endif
+                       /* reserve tlbpid_gen == 0 to alway mean invalid */
+                       if (++tlbpid_gen == 0)
+                               tlbpid_gen = 1;
+                       id = 1;
+               }
+               tlbpid_cnt = id + 1;
+               pmap->pm_tlbpid = id;
+               pmap->pm_tlbgen = tlbpid_gen;
+       } else
+               id = pmap->pm_tlbpid;
+
+#ifdef DEBUG
+       if (pmapdebug & (PDB_FOLLOW|PDB_TLBPID)) {
+               if (curproc)
+                       printf("pmap_alloc_tlbpid: curproc %d '%s' ",
+                               curproc->p_pid, curproc->p_comm);
+               else
+                       printf("pmap_alloc_tlbpid: curproc <none> ");
+               printf("segtab %x tlbpid %d pid %d '%s'\n",
+                       pmap->pm_segtab, id, p->p_pid, p->p_comm);
+       }
+#endif
+       return (id);
+}
+
+/*
+ * Remove a physical to virtual address translation.
+ * Returns TRUE if it was the last mapping and cached, else FALSE.
+ */
+int
+pmap_remove_pv(pmap, va, pa)
+       pmap_t pmap;
+       vm_offset_t va, pa;
+{
+       register pv_entry_t pv, npv;
+       int s, last;
+
+#ifdef DEBUG
+       if (pmapdebug & (PDB_FOLLOW|PDB_PVENTRY))
+               printf("pmap_remove_pv(%x, %x, %x)\n", pmap, va, pa);
+#endif
+       /*
+        * Remove page from the PV table (raise IPL since we
+        * may be called at interrupt time).
+        */
+       if (!IS_VM_PHYSADDR(pa))
+               return(TRUE);
+       pv = pa_to_pvh(pa);
+       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) {
+               last = (pv->pv_flags & PV_UNCACHED) ? FALSE : TRUE;
+               npv = pv->pv_next;
+               if (npv) {
+                       *pv = *npv;
+                       free((caddr_t)npv, M_VMPVENT);
+               } else
+                       pv->pv_pmap = NULL;
+#ifdef DEBUG
+               remove_stats.pvfirst++;
+#endif
+       } else {
+               last = FALSE;
+               for (npv = pv->pv_next; npv; pv = npv, npv = npv->pv_next) {
+#ifdef DEBUG
+                       remove_stats.pvsearch++;
+#endif
+                       if (pmap == npv->pv_pmap && va == npv->pv_va)
+                               goto fnd;
+               }
+#ifdef DIAGNOSTIC
+               printf("pmap_remove_pv(%x, %x, %x) not found\n", pmap, va, pa);
+               panic("pmap_remove_pv");
+#endif
+       fnd:
+               pv->pv_next = npv->pv_next;
+               free((caddr_t)npv, M_VMPVENT);
+       }
+       splx(s);
+       return(last);
+}
+
+/*
+ *     vm_page_alloc1:
+ *
+ *     Allocate and return a memory cell with no associated object.
+ */
+vm_page_t
+vm_page_alloc1()
+{
+       register vm_page_t      mem;
+       int             spl;
+
+       spl = splimp();                         /* XXX */
+       simple_lock(&vm_page_queue_free_lock);
+       if (vm_page_queue_free.tqh_first == NULL) {
+               simple_unlock(&vm_page_queue_free_lock);
+               splx(spl);
+               return (NULL);
+       }
+
+       mem = vm_page_queue_free.tqh_first;
+       TAILQ_REMOVE(&vm_page_queue_free, mem, pageq);
+
+       cnt.v_free_count--;
+       simple_unlock(&vm_page_queue_free_lock);
+       splx(spl);
+
+       mem->flags = PG_BUSY | PG_CLEAN | PG_FAKE;
+       mem->wire_count = 0;
+
+       /*
+        *      Decide if we should poke the pageout daemon.
+        *      We do this if the free count is less than the low
+        *      water mark, or if the free count is less than the high
+        *      water mark (but above the low water mark) and the inactive
+        *      count is less than its target.
+        *
+        *      We don't have the counts locked ... if they change a little,
+        *      it doesn't really matter.
+        */
+
+       if (cnt.v_free_count < cnt.v_free_min ||
+           (cnt.v_free_count < cnt.v_free_target &&
+            cnt.v_inactive_count < cnt.v_inactive_target))
+               thread_wakeup((void *)&vm_pages_needed);
+       return (mem);
+}
+
+/*
+ *     vm_page_free1:
+ *
+ *     Returns the given page to the free list,
+ *     disassociating it with any VM object.
+ *
+ *     Object and page must be locked prior to entry.
+ */
+void
+vm_page_free1(mem)
+       register vm_page_t      mem;
+{
+
+       if (mem->flags & PG_ACTIVE) {
+               TAILQ_REMOVE(&vm_page_queue_active, mem, pageq);
+               mem->flags &= ~PG_ACTIVE;
+               cnt.v_active_count--;
+       }
+
+       if (mem->flags & PG_INACTIVE) {
+               TAILQ_REMOVE(&vm_page_queue_inactive, mem, pageq);
+               mem->flags &= ~PG_INACTIVE;
+               cnt.v_inactive_count--;
+       }
+
+       if (!(mem->flags & PG_FICTITIOUS)) {
+               int     spl;
+
+               spl = splimp();
+               simple_lock(&vm_page_queue_free_lock);
+               TAILQ_INSERT_TAIL(&vm_page_queue_free, mem, pageq);
+
+               cnt.v_free_count++;
+               simple_unlock(&vm_page_queue_free_lock);
+               splx(spl);
+       }
+}
+
+/*
+ * Find first virtual address >= *vap that doesn't cause
+ * a cache alias conflict.
+ */
+void
+pmap_prefer(foff, vap)
+       register vm_offset_t foff;
+       register vm_offset_t *vap;
+{
+       register vm_offset_t    va = *vap;
+       register long           m, d;
+
+       m = 0x10000;            /* Max aliased cache size */
+
+       d = foff - va;
+       d &= (m-1);
+       *vap = va + d;
+}
+
diff --git a/sys/arch/wgrisc/wgrisc/process_machdep.c b/sys/arch/wgrisc/wgrisc/process_machdep.c
new file mode 100644 (file)
index 0000000..e73da3d
--- /dev/null
@@ -0,0 +1,114 @@
+/*     $OpenBSD: process_machdep.c,v 1.1.1.1 1997/02/06 16:02:46 pefo Exp $    */
+/*
+ * Copyright (c) 1994 Adam Glass   
+ * Copyright (c) 1993 The Regents of the University of California.
+ * Copyright (c) 1993 Jan-Simon Pendry
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Jan-Simon Pendry.
+ *
+ * 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:
+ *     Id: procfs_i386.c,v 4.1 1993/12/17 10:47:45 jsp Rel
+ *
+ *     $Id: process_machdep.c,v 1.1.1.1 1997/02/06 16:02:46 pefo Exp $
+ */
+
+/*
+ * This file may seem a bit stylized, but that so that it's easier to port.
+ * Functions to be implemented here are:
+ *
+ * process_read_regs(proc, regs)
+ *     Get the current user-visible register set from the process
+ *     and copy it into the regs structure (<machine/reg.h>).
+ *     The process is stopped at the time read_regs is called.
+ *
+ * process_write_regs(proc, regs)
+ *     Update the current register set from the passed in regs
+ *     structure.  Take care to avoid clobbering special CPU
+ *     registers or privileged bits in the PSL.
+ *     The process is stopped at the time write_regs is called.
+ *
+ * process_sstep(proc)
+ *     Arrange for the process to trap after executing a single instruction.
+ *
+ * process_set_pc(proc)
+ *     Set the process's program counter.
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/time.h>
+#include <sys/kernel.h>
+#include <sys/proc.h>
+#include <sys/user.h>
+#include <sys/vnode.h>
+#include <sys/ptrace.h>
+#include <machine/psl.h>
+#include <machine/reg.h>
+
+int
+process_read_regs(p, regs)
+       struct proc *p;
+       struct reg *regs;
+{
+       bcopy((caddr_t)p->p_md.md_regs, (caddr_t)regs, sizeof(struct reg));
+       return (0);
+}
+
+int
+process_write_regs(p, regs)
+       struct proc *p;
+       struct reg *regs;
+{
+       bcopy((caddr_t)regs, (caddr_t)p->p_md.md_regs, sizeof(struct reg));
+/*XXX Clear to user set bits!! */
+       return (0);
+}
+
+int
+process_sstep(p, sstep)
+       struct proc *p;
+{
+       if(sstep)
+               cpu_singlestep(p);
+       return (0);
+}
+
+int
+process_set_pc(p, addr)
+       struct proc *p;
+       caddr_t addr;
+{
+       p->p_md.md_regs[PC] = (int)addr;
+       return (0);
+}
+
diff --git a/sys/arch/wgrisc/wgrisc/swapgeneric.c b/sys/arch/wgrisc/wgrisc/swapgeneric.c
new file mode 100644 (file)
index 0000000..9ac8d37
--- /dev/null
@@ -0,0 +1,61 @@
+/*     $OpenBSD: swapgeneric.c,v 1.1.1.1 1997/02/06 16:02:46 pefo Exp $ */
+
+/*-
+ * Copyright (c) 1994
+ *      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.
+ *
+ *      @(#)swapgeneric.c       8.2 (Berkeley) 3/21/94
+ */
+
+/*
+ * fake swapgeneric.c -- should do this differently.
+ */
+
+#include <sys/param.h>
+#include <sys/conf.h>
+#include <machine/disklabel.h>
+
+int (*mountroot)() = NULL;     /* tells autoconf.c that we are "generic" */
+
+dev_t  rootdev = NODEV;
+dev_t  dumpdev = NODEV;
+
+struct swdevt swdevt[] = {
+       { makedev(3, 0*MAXPARTITIONS+1), 0, 0 },        /* sd0b */
+       { makedev(3, 1*MAXPARTITIONS+1), 0, 0 },        /* sd1b */
+       { makedev(3, 2*MAXPARTITIONS+1), 0, 0 },        /* sd2b */
+       { makedev(3, 3*MAXPARTITIONS+1), 0, 0 },        /* sd3b */
+       { makedev(3, 4*MAXPARTITIONS+1), 0, 0 },        /* sd4b */
+       { makedev(3, 5*MAXPARTITIONS+1), 0, 0 },        /* sd5b */
+       { makedev(3, 6*MAXPARTITIONS+1), 0, 0 },        /* sd6b */
+       { makedev(3, 7*MAXPARTITIONS+1), 0, 0 },        /* sd7b */
+       { NODEV, 0, 0 }
+};
diff --git a/sys/arch/wgrisc/wgrisc/sys_machdep.c b/sys/arch/wgrisc/wgrisc/sys_machdep.c
new file mode 100644 (file)
index 0000000..e8bfa98
--- /dev/null
@@ -0,0 +1,130 @@
+/*     $OpenBSD: sys_machdep.c,v 1.1.1.1 1997/02/06 16:02:46 pefo Exp $        */
+/*     $NetBSD: sys_machdep.c,v 1.6 1994/10/26 21:10:42 cgd Exp $      */
+
+/*
+ * Copyright (c) 1992, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Ralph Campbell.
+ *
+ * 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.1 (Berkeley) 6/10/93
+ */
+
+#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 <sys/syscallargs.h>
+
+#ifdef TRACE
+int    nvualarm;
+
+vtrace(p, uap, retval)
+       struct proc *p;
+       register struct vtrace_args /* {
+               syscallarg(int) request;
+               syscallarg(int) value;
+       } */ *uap;
+       register_t *retval;
+{
+       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, (caddr_t)p->p_pid, SCARG(uap, value));
+               break;
+
+       case VTR_STAMP:
+               trace(TR_STAMP, SCARG(uap, value), p->p_pid);
+               break;
+       }
+       return (0);
+}
+
+vdoualarm(arg)
+       int arg;
+{
+       register struct proc *p;
+
+       p = pfind(arg);
+       if (p)
+               psignal(p, 16);
+       nvualarm--;
+}
+#endif
+
+sys_sysarch(p, v, retval)
+       struct proc *p;
+       void *v;
+       register_t *retval;
+{
+       struct sys_sysarch_args /* {
+               syscallarg(int) op;
+               syscallarg(char *) parms;
+       } */ *uap = v;
+       int error = 0;
+
+       switch(SCARG(uap, op)) {
+       default:
+               error = EINVAL;
+               break;
+       }
+       return(error);
+}
diff --git a/sys/arch/wgrisc/wgrisc/trap.c b/sys/arch/wgrisc/wgrisc/trap.c
new file mode 100644 (file)
index 0000000..4e457d8
--- /dev/null
@@ -0,0 +1,1653 @@
+/*     $OpenBSD: trap.c,v 1.1.1.1 1997/02/06 16:02:46 pefo Exp $       */
+/*
+ * Copyright (c) 1988 University of Utah.
+ * Copyright (c) 1992, 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 and Ralph Campbell.
+ *
+ * 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.32 91/04/06
+ *
+ *     from: @(#)trap.c        8.5 (Berkeley) 1/11/94
+ *      $Id: trap.c,v 1.1.1.1 1997/02/06 16:02:46 pefo Exp $
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/proc.h>
+#include <sys/kernel.h>
+#include <sys/signalvar.h>
+#include <sys/syscall.h>
+#include <sys/user.h>
+#include <sys/buf.h>
+#include <sys/device.h>
+#ifdef KTRACE
+#include <sys/ktrace.h>
+#endif
+#include <net/netisr.h>
+
+#include <machine/trap.h>
+#include <machine/psl.h>
+#include <machine/reg.h>
+#include <machine/cpu.h>
+#include <machine/pio.h>
+#include <machine/autoconf.h>
+#include <machine/pte.h>
+#include <machine/pmap.h>
+#include <machine/mips_opcode.h>
+
+#include <vm/vm.h>
+#include <vm/vm_kern.h>
+#include <vm/vm_page.h>
+
+#include <wgrisc/wgrisc/wgrisctype.h>
+
+#include <sys/cdefs.h>
+#include <sys/syslog.h>
+
+struct proc *cpuFPCurProcPtr;          /* pointer to last proc to use FP */
+
+unsigned CPU_EmulateBranch();
+
+#ifdef R4K
+extern void R4K_KernGenException();
+extern void R4K_UserGenException();
+extern void R4K_KernIntr();
+extern void R4K_UserIntr();
+extern void R4K_TLBModException();
+extern void R4K_TLBInvalidException();
+
+void (*R4K_ExceptionTable[])() = {
+/*
+ * The kernel exception handlers.
+ */
+       R4K_KernIntr,                   /* external interrupt */
+       R4K_KernGenException,           /* TLB modification */
+       R4K_TLBInvalidException,        /* TLB miss (load or instr. fetch) */
+       R4K_TLBInvalidException,        /* TLB miss (store) */
+       R4K_KernGenException,           /* address error (load or I-fetch) */
+       R4K_KernGenException,           /* address error (store) */
+       R4K_KernGenException,           /* bus error (I-fetch) */
+       R4K_KernGenException,           /* bus error (load or store) */
+       R4K_KernGenException,           /* system call */
+       R4K_KernGenException,           /* breakpoint */
+       R4K_KernGenException,           /* reserved instruction */
+       R4K_KernGenException,           /* coprocessor unusable */
+       R4K_KernGenException,           /* arithmetic overflow */
+       R4K_KernGenException,           /* trap exception */
+       R4K_KernGenException,           /* viritual coherence exception inst */
+       R4K_KernGenException,           /* floating point exception */
+       R4K_KernGenException,           /* reserved */
+       R4K_KernGenException,           /* reserved */
+       R4K_KernGenException,           /* reserved */
+       R4K_KernGenException,           /* reserved */
+       R4K_KernGenException,           /* reserved */
+       R4K_KernGenException,           /* reserved */
+       R4K_KernGenException,           /* reserved */
+       R4K_KernGenException,           /* watch exception */
+       R4K_KernGenException,           /* reserved */
+       R4K_KernGenException,           /* reserved */
+       R4K_KernGenException,           /* reserved */
+       R4K_KernGenException,           /* reserved */
+       R4K_KernGenException,           /* reserved */
+       R4K_KernGenException,           /* reserved */
+       R4K_KernGenException,           /* reserved */
+       R4K_KernGenException,           /* viritual coherence exception data */
+/*
+ * The user exception handlers.
+ */
+       R4K_UserIntr,                   /*  0 */
+       R4K_UserGenException,           /*  1 */
+       R4K_UserGenException,           /*  2 */
+       R4K_UserGenException,           /*  3 */
+       R4K_UserGenException,           /*  4 */
+       R4K_UserGenException,           /*  5 */
+       R4K_UserGenException,           /*  6 */
+       R4K_UserGenException,           /*  7 */
+       R4K_UserGenException,           /*  8 */
+       R4K_UserGenException,           /*  9 */
+       R4K_UserGenException,           /* 10 */
+       R4K_UserGenException,           /* 11 */
+       R4K_UserGenException,           /* 12 */
+       R4K_UserGenException,           /* 13 */
+       R4K_UserGenException,           /* 14 */
+       R4K_UserGenException,           /* 15 */
+       R4K_UserGenException,           /* 16 */
+       R4K_UserGenException,           /* 17 */
+       R4K_UserGenException,           /* 18 */
+       R4K_UserGenException,           /* 19 */
+       R4K_UserGenException,           /* 20 */
+       R4K_UserGenException,           /* 21 */
+       R4K_UserGenException,           /* 22 */
+       R4K_UserGenException,           /* 23 */
+       R4K_UserGenException,           /* 24 */
+       R4K_UserGenException,           /* 25 */
+       R4K_UserGenException,           /* 26 */
+       R4K_UserGenException,           /* 27 */
+       R4K_UserGenException,           /* 28 */
+       R4K_UserGenException,           /* 29 */
+       R4K_UserGenException,           /* 20 */
+       R4K_UserGenException,           /* 31 */
+};
+#else
+extern void R3K_KernGenException();
+extern void R3K_UserGenException();
+extern void R3K_KernIntr();
+extern void R3K_UserIntr();
+extern void R3K_TLBModException();
+extern void R3K_TLBMissException();
+
+void (*R3K_ExceptionTable[])() = {
+/*
+ * The kernel exception handlers.
+ */
+       R3K_KernIntr,                   /* external interrupt */
+       R3K_KernGenException,           /* TLB modification */
+       R3K_TLBMissException,           /* TLB miss (load or instr. fetch) */
+       R3K_TLBMissException,           /* TLB miss (store) */
+       R3K_KernGenException,           /* address error (load or I-fetch) */
+       R3K_KernGenException,           /* address error (store) */
+       R3K_KernGenException,           /* bus error (I-fetch) */
+       R3K_KernGenException,           /* bus error (load or store) */
+       R3K_KernGenException,           /* system call */
+       R3K_KernGenException,           /* breakpoint */
+       R3K_KernGenException,           /* reserved instruction */
+       R3K_KernGenException,           /* coprocessor unusable */
+       R3K_KernGenException,           /* arithmetic overflow */
+       R3K_KernGenException,           /* Reserved */
+       R3K_KernGenException,           /* Reserved */
+       R3K_KernGenException,           /* Reserved */
+       R3K_KernGenException,           /* Reserved */
+       R3K_KernGenException,           /* Reserved */
+       R3K_KernGenException,           /* Reserved */
+       R3K_KernGenException,           /* Reserved */
+       R3K_KernGenException,           /* Reserved */
+       R3K_KernGenException,           /* Reserved */
+       R3K_KernGenException,           /* Reserved */
+       R3K_KernGenException,           /* Reserved */
+       R3K_KernGenException,           /* Reserved */
+       R3K_KernGenException,           /* Reserved */
+       R3K_KernGenException,           /* Reserved */
+       R3K_KernGenException,           /* Reserved */
+       R3K_KernGenException,           /* Reserved */
+       R3K_KernGenException,           /* Reserved */
+       R3K_KernGenException,           /* Reserved */
+       R3K_KernGenException,           /* Reserved */
+/*
+ * The user exception handlers.
+ */
+       R3K_UserIntr,                   /*  0 */
+       R3K_UserGenException,           /*  1 */
+       R3K_UserGenException,           /*  2 */
+       R3K_UserGenException,           /*  3 */
+       R3K_UserGenException,           /*  4 */
+       R3K_UserGenException,           /*  5 */
+       R3K_UserGenException,           /*  6 */
+       R3K_UserGenException,           /*  7 */
+       R3K_UserGenException,           /*  8 */
+       R3K_UserGenException,           /*  9 */
+       R3K_UserGenException,           /* 10 */
+       R3K_UserGenException,           /* 11 */
+       R3K_UserGenException,           /* 12 */
+       R3K_UserGenException,           /* 13 */
+       R3K_UserGenException,           /* 14 */
+       R3K_UserGenException,           /* 15 */
+       R3K_UserGenException,           /* Reserved */
+       R3K_UserGenException,           /* Reserved */
+       R3K_UserGenException,           /* Reserved */
+       R3K_UserGenException,           /* Reserved */
+       R3K_UserGenException,           /* Reserved */
+       R3K_UserGenException,           /* Reserved */
+       R3K_UserGenException,           /* Reserved */
+       R3K_UserGenException,           /* Reserved */
+       R3K_UserGenException,           /* Reserved */
+       R3K_UserGenException,           /* Reserved */
+       R3K_UserGenException,           /* Reserved */
+       R3K_UserGenException,           /* Reserved */
+       R3K_UserGenException,           /* Reserved */
+       R3K_UserGenException,           /* Reserved */
+       R3K_UserGenException,           /* Reserved */
+       R3K_UserGenException,           /* Reserved */
+};
+#endif
+
+char   *trap_type[] = {
+       "external interrupt",
+       "TLB modification",
+       "TLB miss (load or instr. fetch)",
+       "TLB miss (store)",
+       "address error (load or I-fetch)",
+       "address error (store)",
+       "bus error (I-fetch)",
+       "bus error (load or store)",
+       "system call",
+       "breakpoint",
+       "reserved instruction",
+       "coprocessor unusable",
+       "arithmetic overflow",
+       "trap",
+       "viritual coherency instruction",
+       "floating point",
+       "reserved 16",
+       "reserved 17",
+       "reserved 18",
+       "reserved 19",
+       "reserved 20",
+       "reserved 21",
+       "reserved 22",
+       "watch",
+       "reserved 24",
+       "reserved 25",
+       "reserved 26",
+       "reserved 27",
+       "reserved 28",
+       "reserved 29",
+       "reserved 30",
+       "viritual coherency data",
+};
+
+#define        NHWI    8
+struct {
+       int     int_mask;
+       int     (*int_hand)();
+} cpu_int_tab[NHWI];
+
+#ifdef DEBUG
+#define TRAPSIZE       10
+struct trapdebug {             /* trap history buffer for debugging */
+       u_int   status;
+       u_int   cause;
+       u_int   vadr;
+       u_int   pc;
+       u_int   ra;
+       u_int   sp;
+       u_int   code;
+} trapdebug[TRAPSIZE], *trp = trapdebug;
+#endif /* DEBUG */
+
+#ifdef DEBUG   /* stack trace code, also useful for DDB one day */
+extern void stacktrace();
+extern void logstacktrace();
+
+/* extern functions printed by name in stack backtraces */
+extern void idle(), cpu_switch(), splx(), wbflush();
+extern void R4K_TLBMiss();
+extern void R3K_TLBMiss();
+#endif /* DEBUG */
+
+static void mips_errintr();
+extern const struct callback *callv;
+extern volatile struct chiptime *Mach_clock_addr;
+extern u_long intrcnt[];
+extern u_int cputype;
+
+/*
+ * Handle an exception.
+ * Called from RxK_KernGenException() or RxK_UserGenException()
+ * when a processor trap occurs.
+ * In the case of a kernel trap, we return the pc where to resume if
+ * ((struct pcb *)UADDR)->pcb_onfault is set, otherwise, return old pc.
+ */
+unsigned
+trap(statusReg, causeReg, vadr, pc, args)
+       unsigned statusReg;     /* status register at time of the exception */
+       unsigned causeReg;      /* cause register at time of exception */
+       unsigned vadr;          /* address (if any) the fault occured on */
+       unsigned pc;            /* program counter where to continue */
+{
+       register int type, i, usermode;
+       unsigned ucode = 0;
+       register struct proc *p = curproc;
+       u_quad_t sticks;
+       vm_prot_t ftype;
+       extern unsigned onfault_table[];
+       int typ = 0;
+
+#ifdef R4K
+       usermode = R4K_USERMODE(statusReg);
+#else
+       usermode = R3K_USERMODE(statusReg);
+#endif
+#ifdef DEBUG
+       trp->status = statusReg;
+       trp->cause = causeReg;
+       trp->vadr = vadr;
+       trp->pc = pc;
+       trp->ra = !usermode ? ((int *)&args)[19] :
+               p->p_md.md_regs[RA];
+       trp->sp = (int)&args;
+       trp->code = 0;
+       if (++trp == &trapdebug[TRAPSIZE])
+               trp = trapdebug;
+#endif
+
+       cnt.v_trap++;
+       type = (causeReg & CR_EXC_CODE) >> CR_EXC_CODE_SHIFT;
+       if (usermode) {
+               type |= T_USER;
+               sticks = p->p_sticks;
+       }
+
+       /*
+        * Enable hardware interrupts if they were on before.
+        * We only respond to software interrupts when returning to user mode.
+        */
+       if (statusReg & SR_INT_ENAB)
+               splx((statusReg & HARD_INT_MASK) | SR_INT_ENAB);
+
+       switch (type) {
+       case T_TLB_MOD:
+               /* check for kernel address */
+               if ((int)vadr < 0) {
+                       register pt_entry_t *pte;
+                       register unsigned entry;
+                       register vm_offset_t pa;
+
+                       pte = kvtopte(vadr);
+                       entry = pte->pt_entry;
+#ifdef DIAGNOSTIC
+                       if (!(entry & PG_V) || (entry & PG_M))
+                               panic("trap: ktlbmod: invalid pte");
+#endif
+                       if (pmap_is_page_ro(pmap_kernel(), mips_trunc_page(vadr), entry)) {
+                               /* write to read only page in the kernel */
+                               ftype = VM_PROT_WRITE;
+                               goto kernel_fault;
+                       }
+                       entry |= PG_M;
+                       pte->pt_entry = entry;
+                       vadr &= ~PGOFSET;
+#ifdef R4K
+                       R4K_TLBUpdate(vadr, entry);
+#else
+                       R3K_TLBUpdate(vadr, entry);
+#endif
+                       pa = pfn_to_vad(entry);
+#ifdef ATTR
+                       pmap_attributes[atop(pa)] |= PMAP_ATTR_MOD;
+#else
+                       if (!IS_VM_PHYSADDR(pa))
+                               panic("trap: ktlbmod: unmanaged page");
+                       PHYS_TO_VM_PAGE(pa)->flags &= ~PG_CLEAN;
+#endif
+                       return (pc);
+               }
+               /* FALLTHROUGH */
+
+       case T_TLB_MOD+T_USER:
+           {
+               register pt_entry_t *pte;
+               register unsigned entry;
+               register vm_offset_t pa;
+               pmap_t pmap = &p->p_vmspace->vm_pmap;
+
+               if (!(pte = pmap_segmap(pmap, vadr)))
+                       panic("trap: utlbmod: invalid segmap");
+               pte += (vadr >> PGSHIFT) & (NPTEPG - 1);
+               entry = pte->pt_entry;
+#ifdef DIAGNOSTIC
+               if (!(entry & PG_V) || (entry & PG_M)) {
+                       panic("trap: utlbmod: invalid pte");
+               }
+#endif
+               if (pmap_is_page_ro(pmap, mips_trunc_page(vadr), entry)) {
+                       /* write to read only page */
+                       ftype = VM_PROT_WRITE;
+                       goto dofault;
+               }
+               entry |= PG_M;
+               pte->pt_entry = entry;
+#ifdef R4K
+               vadr = (vadr & ~PGOFSET) | (pmap->pm_tlbpid << R4K_PID_SHIFT);
+               R4K_TLBUpdate(vadr, entry);
+#else
+               vadr = (vadr & ~PGOFSET) | (pmap->pm_tlbpid << R3K_PID_SHIFT);
+               R3K_TLBUpdate(vadr, entry);
+#endif
+               pa = pfn_to_vad(entry);
+#ifdef ATTR
+               pmap_attributes[atop(pa)] |= PMAP_ATTR_MOD;
+#else
+               if (!IS_VM_PHYSADDR(pa)) {
+                       panic("trap: utlbmod: unmanaged page");
+               }
+               PHYS_TO_VM_PAGE(pa)->flags &= ~PG_CLEAN;
+#endif
+               if (!usermode)
+                       return (pc);
+               goto out;
+           }
+
+       case T_TLB_LD_MISS:
+       case T_TLB_ST_MISS:
+               ftype = (type == T_TLB_ST_MISS) ? VM_PROT_WRITE : VM_PROT_READ;
+               /* check for kernel address */
+               if ((int)vadr < 0) {
+                       register vm_offset_t va;
+                       int rv;
+
+               kernel_fault:
+                       va = trunc_page((vm_offset_t)vadr);
+                       rv = vm_fault(kernel_map, va, ftype, FALSE);
+                       if (rv == KERN_SUCCESS)
+                               return (pc);
+                       if (i = ((struct pcb *)UADDR)->pcb_onfault) {
+                               ((struct pcb *)UADDR)->pcb_onfault = 0;
+                               return (onfault_table[i]);
+                       }
+                       goto err;
+               }
+               /*
+                * It is an error for the kernel to access user space except
+                * through the copyin/copyout routines.
+                */
+               if ((i = ((struct pcb *)UADDR)->pcb_onfault) == 0)
+                       goto err;
+               /* check for fuswintr() or suswintr() getting a page fault */
+               if (i == 4)
+                       return (onfault_table[i]);
+               goto dofault;
+
+       case T_TLB_LD_MISS+T_USER:
+               ftype = VM_PROT_READ;
+               goto dofault;
+
+       case T_TLB_ST_MISS+T_USER:
+               ftype = VM_PROT_WRITE;
+       dofault:
+           {
+               register vm_offset_t va;
+               register struct vmspace *vm;
+               register vm_map_t map;
+               int rv;
+
+               vm = p->p_vmspace;
+               map = &vm->vm_map;
+               va = trunc_page((vm_offset_t)vadr);
+               rv = vm_fault(map, va, ftype, FALSE);
+#ifdef VMFAULT_TRACE
+               printf("vm_fault(%x (pmap %x), %x (%x), %x, %d) -> %x at pc %x\n",
+                      map, &vm->vm_pmap, va, vadr, ftype, FALSE, rv, pc);
+#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) {
+                       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 (!usermode)
+                               return (pc);
+                       goto out;
+               }
+               if (!usermode) {
+                       if (i = ((struct pcb *)UADDR)->pcb_onfault) {
+                               ((struct pcb *)UADDR)->pcb_onfault = 0;
+                               return (onfault_table[i]);
+                       }
+                       goto err;
+               }
+               ucode = ftype;
+               i = SIGSEGV;
+               typ = SEGV_MAPERR;
+               break;
+           }
+
+       case T_ADDR_ERR_LD+T_USER:      /* misaligned or kseg access */
+       case T_ADDR_ERR_ST+T_USER:      /* misaligned or kseg access */
+               ucode = 0;              /* XXX should be VM_PROT_something */
+               i = SIGBUS;
+               typ = BUS_ADRALN;
+               break;
+       case T_BUS_ERR_IFETCH+T_USER:   /* BERR asserted to cpu */
+       case T_BUS_ERR_LD_ST+T_USER:    /* BERR asserted to cpu */
+               ucode = 0;              /* XXX should be VM_PROT_something */
+               i = SIGBUS;
+               typ = BUS_OBJERR;
+               break;
+
+       case T_SYSCALL+T_USER:
+           {
+               register int *locr0 = p->p_md.md_regs;
+               register struct sysent *callp;
+               unsigned int code;
+               int numsys;
+               struct args {
+                       int i[8];
+               } args;
+               int rval[2];
+
+               cnt.v_syscall++;
+               /* compute next PC after syscall instruction */
+               if ((int)causeReg < 0)
+                       locr0[PC] = CPU_EmulateBranch(locr0, pc, 0, 0);
+               else
+                       locr0[PC] += 4;
+               callp = p->p_emul->e_sysent;
+               numsys = p->p_emul->e_nsysent;
+               code = locr0[V0];
+               switch (code) {
+               case SYS_syscall:
+                       /*
+                        * Code is first argument, followed by actual args.
+                        */
+                       code = locr0[A0];
+                       if (code >= numsys)
+                               callp += p->p_emul->e_nosys; /* (illegal) */
+                       else
+                               callp += code;
+                       i = callp->sy_argsize / sizeof(int);
+                       args.i[0] = locr0[A1];
+                       args.i[1] = locr0[A2];
+                       args.i[2] = locr0[A3];
+                       if (i > 3) {
+                               i = copyin((caddr_t)(locr0[SP] +
+                                               4 * sizeof(int)),
+                                       (caddr_t)&args.i[3],
+                                       (u_int)(i - 3) * sizeof(int));
+                               if (i) {
+                                       locr0[V0] = i;
+                                       locr0[A3] = 1;
+#ifdef SYSCALL_DEBUG
+                                       scdebug_call(p, code, args.i);
+#endif
+#ifdef KTRACE
+                                       if (KTRPOINT(p, KTR_SYSCALL))
+                                               ktrsyscall(p->p_tracep, code,
+                                                       callp->sy_argsize,
+                                                       args.i);
+#endif
+                                       goto done;
+                               }
+                       }
+                       break;
+
+               case SYS___syscall:
+                       /*
+                        * Like syscall, but code is a quad, so as to maintain
+                        * quad alignment for the rest of the arguments.
+                        */
+                       code = locr0[A0 + _QUAD_LOWWORD];
+                       if (code >= numsys)
+                               callp += p->p_emul->e_nosys; /* (illegal) */
+                       else
+                               callp += code; 
+                       i = callp->sy_argsize / sizeof(int);
+                       args.i[0] = locr0[A2];
+                       args.i[1] = locr0[A3];
+                       if (i > 2) {
+                               i = copyin((caddr_t)(locr0[SP] +
+                                               4 * sizeof(int)),
+                                       (caddr_t)&args.i[2],
+                                       (u_int)(i - 2) * sizeof(int));
+                               if (i) {
+                                       locr0[V0] = i;
+                                       locr0[A3] = 1;
+#ifdef SYSCALL_DEBUG
+                                       scdebug_call(p, code, args.i);
+#endif
+#ifdef KTRACE
+                                       if (KTRPOINT(p, KTR_SYSCALL))
+                                               ktrsyscall(p->p_tracep, code,
+                                                       callp->sy_argsize,
+                                                       args.i);
+#endif
+                                       goto done;
+                               }
+                       }
+                       break;
+
+               default:
+                       if (code >= numsys)
+                               callp += p->p_emul->e_nosys; /* (illegal) */
+                       else
+                               callp += code;
+                       i = callp->sy_narg;
+                       args.i[0] = locr0[A0];
+                       args.i[1] = locr0[A1];
+                       args.i[2] = locr0[A2];
+                       args.i[3] = locr0[A3];
+                       if (i > 4) {
+                               i = copyin((caddr_t)(locr0[SP] +
+                                               4 * sizeof(int)),
+                                       (caddr_t)&args.i[4],
+                                       (u_int)(i - 4) * sizeof(int));
+                               if (i) {
+                                       locr0[V0] = i;
+                                       locr0[A3] = 1;
+#ifdef SYSCALL_DEBUG
+                                       scdebug_call(p, code, args.i);
+#endif
+#ifdef KTRACE
+                                       if (KTRPOINT(p, KTR_SYSCALL))
+                                               ktrsyscall(p->p_tracep, code,
+                                                       callp->sy_argsize,
+                                                       args.i);
+#endif
+                                       goto done;
+                               }
+                       }
+               }
+#ifdef SYSCALL_DEBUG
+               scdebug_call(p, code, args.i);
+#endif
+#ifdef KTRACE
+               if (KTRPOINT(p, KTR_SYSCALL))
+                       ktrsyscall(p->p_tracep, code, callp->sy_argsize, args.i);
+#endif
+               rval[0] = 0;
+               rval[1] = locr0[V1];
+#ifdef DEBUG
+               if (trp == trapdebug)
+                       trapdebug[TRAPSIZE - 1].code = code;
+               else
+                       trp[-1].code = code;
+#endif
+               i = (*callp->sy_call)(p, &args, rval);
+               /*
+                * Reinitialize proc pointer `p' as it may be different
+                * if this is a child returning from fork syscall.
+                */
+               p = curproc;
+               locr0 = p->p_md.md_regs;
+#ifdef DEBUG
+               { int s;
+               s = splhigh();
+               trp->status = statusReg;
+               trp->cause = causeReg;
+               trp->vadr = locr0[SP];
+               trp->pc = locr0[PC];
+               trp->ra = locr0[RA];
+               trp->code = -code;
+               if (++trp == &trapdebug[TRAPSIZE])
+                       trp = trapdebug;
+               splx(s);
+               }
+#endif
+               switch (i) {
+               case 0:
+                       locr0[V0] = rval[0];
+                       locr0[V1] = rval[1];
+                       locr0[A3] = 0;
+                       break;
+
+               case ERESTART:
+                       locr0[PC] = pc;
+                       break;
+
+               case EJUSTRETURN:
+                       break;  /* nothing to do */
+
+               default:
+                       locr0[V0] = i;
+                       locr0[A3] = 1;
+               }
+               if(code == SYS_ptrace)
+#ifdef R4K
+                       R4K_FlushCache();
+#else
+                       R3K_FlushCache();
+#endif
+       done:
+#ifdef SYSCALL_DEBUG
+               scdebug_ret(p, code, i, rval);
+#endif
+#ifdef KTRACE
+               if (KTRPOINT(p, KTR_SYSRET))
+                       ktrsysret(p->p_tracep, code, i, rval[0]);
+#endif
+               goto out;
+           }
+
+       case T_BREAK+T_USER:
+           {
+               register unsigned va, instr;
+               struct uio uio;
+               struct iovec iov;
+
+               /* compute address of break instruction */
+               va = pc;
+               if ((int)causeReg < 0)
+                       va += 4;
+
+               /* read break instruction */
+               instr = fuiword((caddr_t)va);
+#if 0
+               printf("trap: %s (%d) breakpoint %x at %x: (adr %x ins %x)\n",
+                       p->p_comm, p->p_pid, instr, pc,
+                       p->p_md.md_ss_addr, p->p_md.md_ss_instr); /* XXX */
+#endif
+               if (p->p_md.md_ss_addr != va || instr != BREAK_SSTEP) {
+                       i = SIGTRAP;
+                       typ = TRAP_TRACE;
+                       break;
+               }
+
+               /*
+                * Restore original instruction and clear BP
+                */
+               iov.iov_base = (caddr_t)&p->p_md.md_ss_instr;
+               iov.iov_len = sizeof(int); 
+               uio.uio_iov = &iov;
+               uio.uio_iovcnt = 1; 
+               uio.uio_offset = (off_t)va;
+               uio.uio_resid = sizeof(int);
+               uio.uio_segflg = UIO_SYSSPACE;
+               uio.uio_rw = UIO_WRITE;
+               uio.uio_procp = curproc;
+               i = procfs_domem(p, p, NULL, &uio);
+#ifdef R4K
+               R4K_FlushCache();
+#else
+               R3K_FlushCache();
+#endif
+
+               if (i < 0)
+                       printf("Warning: can't restore instruction at %x: %x\n",
+                               p->p_md.md_ss_addr, p->p_md.md_ss_instr);
+
+               p->p_md.md_ss_addr = 0;
+               i = SIGTRAP;
+               typ = TRAP_TRACE;
+               break;
+           }
+
+       case T_RES_INST+T_USER:
+               i = SIGILL;
+               typ = ILL_ILLOPC;
+               break;
+
+       case T_COP_UNUSABLE+T_USER:
+               if ((causeReg & CR_COP_ERR) != 0x10000000) {
+                       i = SIGILL;     /* only FPU instructions allowed */
+                       typ = ILL_ILLOPC;
+                       break;
+               }
+               CPU_SwitchFPState(cpuFPCurProcPtr, p->p_md.md_regs);
+               cpuFPCurProcPtr = p;
+               p->p_md.md_regs[PS] |= SR_COP_1_BIT;
+               p->p_md.md_flags |= MDP_FPUSED;
+               goto out;
+
+       case T_FPE:
+#ifdef DEBUG
+               trapDump("fpintr");
+#else
+               printf("FPU Trap: PC %x CR %x SR %x\n",
+                       pc, causeReg, statusReg);
+               goto err;
+#endif
+
+       case T_FPE+T_USER:
+               CPU_FPTrap(statusReg, causeReg, pc);
+               goto out;
+
+       case T_OVFLOW+T_USER:
+               i = SIGFPE;
+               typ = FPE_FLTOVF;
+               break;
+
+       case T_ADDR_ERR_LD:     /* misaligned access */
+       case T_ADDR_ERR_ST:     /* misaligned access */
+       case T_BUS_ERR_LD_ST:   /* BERR asserted to cpu */
+               if (i = ((struct pcb *)UADDR)->pcb_onfault) {
+                       ((struct pcb *)UADDR)->pcb_onfault = 0;
+                       return (onfault_table[i]);
+               }
+               /* FALLTHROUGH */
+
+       default:
+       err:
+#ifdef DEBUG
+           {
+               extern struct pcb mdbpcb;
+
+               if (usermode)
+                       mdbpcb = p->p_addr->u_pcb;
+               else {
+                       mdbpcb.pcb_regs[ZERO] = 0;
+                       mdbpcb.pcb_regs[AST] = ((int *)&args)[2];
+                       mdbpcb.pcb_regs[V0] = ((int *)&args)[3];
+                       mdbpcb.pcb_regs[V1] = ((int *)&args)[4];
+                       mdbpcb.pcb_regs[A0] = ((int *)&args)[5];
+                       mdbpcb.pcb_regs[A1] = ((int *)&args)[6];
+                       mdbpcb.pcb_regs[A2] = ((int *)&args)[7];
+                       mdbpcb.pcb_regs[A3] = ((int *)&args)[8];
+                       mdbpcb.pcb_regs[T0] = ((int *)&args)[9];
+                       mdbpcb.pcb_regs[T1] = ((int *)&args)[10];
+                       mdbpcb.pcb_regs[T2] = ((int *)&args)[11];
+                       mdbpcb.pcb_regs[T3] = ((int *)&args)[12];
+                       mdbpcb.pcb_regs[T4] = ((int *)&args)[13];
+                       mdbpcb.pcb_regs[T5] = ((int *)&args)[14];
+                       mdbpcb.pcb_regs[T6] = ((int *)&args)[15];
+                       mdbpcb.pcb_regs[T7] = ((int *)&args)[16];
+                       mdbpcb.pcb_regs[T8] = ((int *)&args)[17];
+                       mdbpcb.pcb_regs[T9] = ((int *)&args)[18];
+                       mdbpcb.pcb_regs[RA] = ((int *)&args)[19];
+                       mdbpcb.pcb_regs[MULLO] = ((int *)&args)[21];
+                       mdbpcb.pcb_regs[MULHI] = ((int *)&args)[22];
+                       mdbpcb.pcb_regs[PC] = pc;
+                       mdbpcb.pcb_regs[SR] = statusReg;
+                       bzero((caddr_t)&mdbpcb.pcb_regs[F0], 33 * sizeof(int));
+               }
+               if (mdb(causeReg, vadr, p, !usermode))
+                       return (mdbpcb.pcb_regs[PC]);
+           }
+#else
+#ifdef DEBUG
+               stacktrace();
+               trapDump("trap");
+#endif
+#endif
+               panic("trap");
+       }
+       p->p_md.md_regs[PC] = pc;
+       p->p_md.md_regs[CAUSE] = causeReg;
+       p->p_md.md_regs[BADVADDR] = vadr;
+       trapsignal(p, i, ucode, typ, (caddr_t)vadr);
+out:
+       /*
+        * Note: we should only get here if returning to user mode.
+        */
+       /* take pending signals */
+       while ((i = CURSIG(p)) != 0)
+               postsig(i);
+       p->p_priority = p->p_usrpri;
+       astpending = 0;
+       if (want_resched) {
+               int s;
+
+               /*
+                * 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 switched, 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 ((i = CURSIG(p)) != 0)
+                       postsig(i);
+       }
+
+       /*
+        * If profiling, charge system time to the trapped pc.
+        */
+       if (p->p_flag & P_PROFIL) {
+               extern int psratio;
+
+               addupc_task(p, pc, (int)(p->p_sticks - sticks) * psratio);
+       }
+
+       curpriority = p->p_priority;
+       return (pc);
+}
+
+/*
+ * Handle an interrupt.
+ * Called from RxK_KernIntr() or RxK_UserIntr()
+ * Note: curproc might be NULL.
+ */
+interrupt(statusReg, causeReg, pc, what, args)
+       unsigned statusReg;     /* status register at time of the exception */
+       unsigned causeReg;      /* cause register at time of exception */
+       unsigned pc;            /* program counter where to continue */
+{
+       register unsigned mask, causemask;
+       register int i;
+       struct clockframe cf;
+
+#ifdef DEBUG
+       trp->status = statusReg;
+       trp->cause = causeReg;
+       trp->vadr = 0;
+       trp->pc = pc;
+       trp->ra = 0;
+       trp->sp = (int)&args;
+       trp->code = 0;
+       if (++trp == &trapdebug[TRAPSIZE])
+               trp = trapdebug;
+#endif
+
+       cnt.v_intr++;
+       mask = causeReg & statusReg;    /* pending interrupts & enable mask */
+       cf.pc = pc;
+       cf.sr = statusReg;
+       cf.cr = causeReg;
+
+#ifndef R4K
+       if(mask & INT_MASK_0) {
+               if(R3K_USERMODE(statusReg))
+                       CPU_FPTrap(statusReg, causeReg, pc);
+               else
+                       printf("FPU Int @ 0x%x\n", pc);
+       }
+#endif
+
+       /*
+        *  Check off all enabled interrupts. Called interrupt routine
+        *  returns mask of interrupts to reenable.
+        */
+       causemask = 0;
+       for(i = 0; i < NHWI; i++) {
+               if(cpu_int_tab[i].int_mask & mask) {
+                       causemask |= cpu_int_tab[i].int_mask;
+                       causeReg &= (*cpu_int_tab[i].int_hand)(mask, &cf);
+               }
+       }
+       causeReg |= causemask;
+       /*
+        *  Reenable all non served hardware levels.
+        */
+       splx((statusReg & ~causeReg & HARD_INT_MASK) | SR_INT_ENAB);
+
+
+       if (mask & SOFT_INT_MASK_0) {
+               clearsoftclock();
+               cnt.v_soft++;
+               softclock();
+       }
+       /*
+        *  Process network interrupt if we trapped or will very soon
+        */
+       if ((mask & SOFT_INT_MASK_1) ||
+           netisr && (statusReg & SOFT_INT_MASK_1)) {
+               clearsoftnet();
+               cnt.v_soft++;
+               intrcnt[1]++;
+#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
+#include "ppp.h"
+#if NPPP > 0
+               if(netisr & (1 << NETISR_PPP)) {
+                       netisr &= ~(1 << NETISR_PPP);
+                       pppintr();
+               }
+#endif
+       }
+       if (mask & SOFT_INT_MASK_0) {
+               clearsoftclock();
+               intrcnt[0]++;
+               cnt.v_soft++;
+               softclock();
+       }
+}
+
+/*
+ *     Set up handler for external interrupt events.
+ *     Events are checked in priority order.
+ */
+void
+set_intr(mask, int_hand, prio)
+       int     mask;
+       int     (*int_hand)();
+       int     prio;
+{
+       if(prio > NHWI)
+               panic("set_intr: to high priority");
+
+       if(cpu_int_tab[prio].int_mask != 0)
+               panic("set_intr: int already set");
+
+       cpu_int_tab[prio].int_hand = int_hand;
+       cpu_int_tab[prio].int_mask = mask;
+}
+
+/*
+ * This is called from RxK_UserIntr() if astpending is set.
+ * This is very similar to the tail of trap().
+ */
+softintr(statusReg, pc)
+       unsigned statusReg;     /* status register at time of the exception */
+       unsigned pc;            /* program counter where to continue */
+{
+       register struct proc *p = curproc;
+       int sig;
+
+       cnt.v_soft++;
+       /* take pending signals */
+       while ((sig = CURSIG(p)) != 0)
+               postsig(sig);
+       p->p_priority = p->p_usrpri;
+       astpending = 0;
+       if (p->p_flag & P_OWEUPC) {
+               p->p_flag &= ~P_OWEUPC;
+               ADDUPROF(p);
+       }
+       if (want_resched) {
+               int s;
+
+               /*
+                * 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 switched, 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);
+       }
+       curpriority = p->p_priority;
+}
+
+#ifdef DEBUG
+trapDump(msg)
+       char *msg;
+{
+       register int i;
+       int s;
+
+       s = splhigh();
+       printf("trapDump(%s)\n", msg);
+       for (i = 0; i < TRAPSIZE; i++) {
+               if (trp == trapdebug)
+                       trp = &trapdebug[TRAPSIZE - 1];
+               else
+                       trp--;
+               if (trp->cause == 0)
+                       break;
+               printf("%s: ADR %x PC %x CR %x SR %x\n",
+                       trap_type[(trp->cause & CR_EXC_CODE) >>
+                               CR_EXC_CODE_SHIFT],
+                       trp->vadr, trp->pc, trp->cause, trp->status);
+               printf("   RA %x SP %x code %d\n", trp->ra, trp->sp, trp->code);
+       }
+       splx(s);
+}
+#endif
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * MemErrorInterrupts --
+ *
+ *     Handler an interrupt for the control register.
+ *
+ * Results:
+ *     None.
+ *
+ * Side effects:
+ *     None.
+ *
+ *----------------------------------------------------------------------
+ */
+static void
+mips_errintr()
+{
+#if 0
+       volatile u_short *sysCSRPtr =
+               (u_short *)PHYS_TO_UNCACHED(KN01_SYS_CSR);
+       u_short csr;
+
+       csr = *sysCSRPtr;
+
+       if (csr & KN01_CSR_MERR) {
+               printf("Memory error at 0x%x\n",
+                       *(unsigned *)PHYS_TO_UNCACHED(KN01_SYS_ERRADR));
+               panic("Mem error interrupt");
+       }
+       *sysCSRPtr = (csr & ~KN01_CSR_MBZ) | 0xff;
+#endif
+}
+
+
+/*
+ * Return the resulting PC as if the branch was executed.
+ */
+unsigned
+CPU_EmulateBranch(regsPtr, instPC, fpcCSR, allowNonBranch)
+       unsigned *regsPtr;
+       unsigned instPC;
+       unsigned fpcCSR;
+       int allowNonBranch;
+{
+       InstFmt inst;
+       unsigned retAddr;
+       int condition;
+
+#define GetBranchDest(InstPtr, inst) \
+       ((unsigned)InstPtr + 4 + ((short)inst.IType.imm << 2))
+
+
+       if(allowNonBranch == 0) {
+               inst = *(InstFmt *)instPC;
+       }
+       else {
+               inst = *(InstFmt *)&allowNonBranch;
+       }
+#if 0
+       printf("regsPtr=%x PC=%x Inst=%x fpcCsr=%x\n", regsPtr, instPC,
+               inst.word, fpcCSR); /* XXX */
+#endif
+       switch ((int)inst.JType.op) {
+       case OP_SPECIAL:
+               switch ((int)inst.RType.func) {
+               case OP_JR:
+               case OP_JALR:
+                       retAddr = regsPtr[inst.RType.rs];
+                       break;
+
+               default:
+                       if (!allowNonBranch)
+                               panic("CPU_EmulateBranch: Non-branch");
+                       retAddr = instPC + 4;
+                       break;
+               }
+               break;
+
+       case OP_BCOND:
+               switch ((int)inst.IType.rt) {
+               case OP_BLTZ:
+               case OP_BLTZL:
+               case OP_BLTZAL:
+               case OP_BLTZALL:
+                       if ((int)(regsPtr[inst.RType.rs]) < 0)
+                               retAddr = GetBranchDest(instPC, inst);
+                       else
+                               retAddr = instPC + 8;
+                       break;
+
+               case OP_BGEZ:
+               case OP_BGEZL:
+               case OP_BGEZAL:
+               case OP_BGEZALL:
+                       if ((int)(regsPtr[inst.RType.rs]) >= 0)
+                               retAddr = GetBranchDest(instPC, inst);
+                       else
+                               retAddr = instPC + 8;
+                       break;
+
+               default:
+                       panic("CPU_EmulateBranch: Bad branch cond");
+               }
+               break;
+
+       case OP_J:
+       case OP_JAL:
+               retAddr = (inst.JType.target << 2) | 
+                       ((unsigned)instPC & 0xF0000000);
+               break;
+
+       case OP_BEQ:
+       case OP_BEQL:
+               if (regsPtr[inst.RType.rs] == regsPtr[inst.RType.rt])
+                       retAddr = GetBranchDest(instPC, inst);
+               else
+                       retAddr = instPC + 8;
+               break;
+
+       case OP_BNE:
+       case OP_BNEL:
+               if (regsPtr[inst.RType.rs] != regsPtr[inst.RType.rt])
+                       retAddr = GetBranchDest(instPC, inst);
+               else
+                       retAddr = instPC + 8;
+               break;
+
+       case OP_BLEZ:
+       case OP_BLEZL:
+               if ((int)(regsPtr[inst.RType.rs]) <= 0)
+                       retAddr = GetBranchDest(instPC, inst);
+               else
+                       retAddr = instPC + 8;
+               break;
+
+       case OP_BGTZ:
+       case OP_BGTZL:
+               if ((int)(regsPtr[inst.RType.rs]) > 0)
+                       retAddr = GetBranchDest(instPC, inst);
+               else
+                       retAddr = instPC + 8;
+               break;
+
+       case OP_COP1:
+               switch (inst.RType.rs) {
+               case OP_BCx:
+               case OP_BCy:
+                       if ((inst.RType.rt & COPz_BC_TF_MASK) == COPz_BC_TRUE)
+                               condition = fpcCSR & FPC_COND_BIT;
+                       else
+                               condition = !(fpcCSR & FPC_COND_BIT);
+                       if (condition)
+                               retAddr = GetBranchDest(instPC, inst);
+                       else
+                               retAddr = instPC + 8;
+                       break;
+
+               default:
+                       if (!allowNonBranch)
+                               panic("CPU_EmulateBranch: Bad coproc branch instruction");
+                       retAddr = instPC + 4;
+               }
+               break;
+
+       default:
+               if (!allowNonBranch)
+                       panic("CPU_EmulateBranch: Non-branch instruction");
+               retAddr = instPC + 4;
+       }
+#if 0
+       printf("Target addr=%x\n", retAddr); /* XXX */
+#endif
+       return (retAddr);
+}
+
+/*
+ * This routine is called by procxmt() to single step one instruction.
+ * We do this by storing a break instruction after the current instruction,
+ * resuming execution, and then restoring the old instruction.
+ */
+cpu_singlestep(p)
+       register struct proc *p;
+{
+       register unsigned va;
+       register int *locr0 = p->p_md.md_regs;
+       int i;
+       int bpinstr = BREAK_SSTEP;
+       int curinstr;
+       struct uio uio;
+       struct iovec iov;
+
+       /*
+        * Fetch what's at the current location.
+        */
+       iov.iov_base = (caddr_t)&curinstr;
+       iov.iov_len = sizeof(int); 
+       uio.uio_iov = &iov;
+       uio.uio_iovcnt = 1; 
+       uio.uio_offset = (off_t)locr0[PC];
+       uio.uio_resid = sizeof(int);
+       uio.uio_segflg = UIO_SYSSPACE;
+       uio.uio_rw = UIO_READ;
+       uio.uio_procp = curproc;
+       procfs_domem(curproc, p, NULL, &uio);
+
+       /* compute next address after current location */
+       if(curinstr != 0) {
+               va = CPU_EmulateBranch(locr0, locr0[PC], locr0[FSR], curinstr);
+       }
+       else {
+               va = locr0[PC] + 4;
+       }
+       if (p->p_md.md_ss_addr) {
+               printf("SS %s (%d): breakpoint already set at %x (va %x)\n",
+                       p->p_comm, p->p_pid, p->p_md.md_ss_addr, va); /* XXX */
+               return (EFAULT);
+       }
+       p->p_md.md_ss_addr = va;
+       /*
+        * Fetch what's at the current location.
+        */
+       iov.iov_base = (caddr_t)&p->p_md.md_ss_instr;
+       iov.iov_len = sizeof(int); 
+       uio.uio_iov = &iov;
+       uio.uio_iovcnt = 1; 
+       uio.uio_offset = (off_t)va;
+       uio.uio_resid = sizeof(int);
+       uio.uio_segflg = UIO_SYSSPACE;
+       uio.uio_rw = UIO_READ;
+       uio.uio_procp = curproc;
+       procfs_domem(curproc, p, NULL, &uio);
+
+       /*
+        * Store breakpoint instruction at the "next" location now.
+        */
+       iov.iov_base = (caddr_t)&bpinstr;
+       iov.iov_len = sizeof(int); 
+       uio.uio_iov = &iov;
+       uio.uio_iovcnt = 1; 
+       uio.uio_offset = (off_t)va;
+       uio.uio_resid = sizeof(int);
+       uio.uio_segflg = UIO_SYSSPACE;
+       uio.uio_rw = UIO_WRITE;
+       uio.uio_procp = curproc;
+       i = procfs_domem(curproc, p, NULL, &uio);
+#ifdef R4K
+       R4K_FlushCache();
+#else
+       R3K_FlushCache();
+#endif
+
+       if (i < 0)
+               return (EFAULT);
+#if 0
+       printf("SS %s (%d): breakpoint set at %x: %x (pc %x) br %x\n",
+               p->p_comm, p->p_pid, p->p_md.md_ss_addr,
+               p->p_md.md_ss_instr, locr0[PC], curinstr); /* XXX */
+#endif
+       return (0);
+}
+
+#ifdef DEBUG
+kdbpeek(addr)
+{
+       if (addr & 3) {
+               printf("kdbpeek: unaligned address %x\n", addr);
+               return (-1);
+       }
+       return (*(int *)addr);
+}
+#endif
+
+#ifdef DEBUG
+#define MIPS_JR_RA     0x03e00008      /* instruction code for jr ra */
+
+/* forward */
+char *fn_name(unsigned addr);
+void stacktrace_subr __P((int, int, int, int, int (*)(const char*, ...)));
+
+/*
+ * Print a stack backtrace.
+ */
+void
+stacktrace(a0, a1, a2, a3)
+       int a0, a1, a2, a3;
+{
+       stacktrace_subr(a0, a1, a2, a3, printf);
+}
+
+void
+logstacktrace(a0, a1, a2, a3)
+       int a0, a1, a2, a3;
+{
+       stacktrace_subr(a0, a1, a2, a3, addlog);
+}
+
+void
+stacktrace_subr(a0, a1, a2, a3, printfn)
+       int a0, a1, a2, a3;
+       int (*printfn) __P((const char*, ...));
+{
+       unsigned pc, sp, fp, ra, va, subr;
+       unsigned instr, mask;
+       InstFmt i;
+       int more, stksize;
+       int regs[3];
+       extern setsoftclock();
+       extern char start[], edata[];
+       unsigned int frames =  0;
+
+       cpu_getregs(regs);
+
+       /* get initial values from the exception frame */
+       sp = regs[0];
+       pc = regs[1];
+       ra = 0;
+       fp = regs[2];
+
+/* Jump here when done with a frame, to start a new one */
+loop:
+       ra = 0;
+
+/* Jump here after a nonstandard (interrupt handler) frame */
+specialframe:
+       stksize = 0;
+       subr = 0;
+       if      (frames++ > 100) {
+               (*printfn)("\nstackframe count exceeded\n");
+               /* return breaks stackframe-size heuristics with gcc -O2 */
+               goto finish;    /*XXX*/
+       }
+
+       /* check for bad SP: could foul up next frame */
+       if (sp & 3 || sp < 0x80000000) {
+               (*printfn)("SP 0x%x: not in kernel\n", sp);
+               ra = 0;
+               subr = 0;
+               goto done;
+       }
+
+       /* check for bad PC */
+       if (pc & 3 || pc < 0x80000000 || pc >= (unsigned)edata) {
+               (*printfn)("PC 0x%x: not in kernel\n", pc);
+               ra = 0;
+               goto done;
+       }
+
+       /*
+        * Find the beginning of the current subroutine by scanning backwards
+        * from the current PC for the end of the previous subroutine.
+        */
+       if (!subr) {
+               va = pc - sizeof(int);
+               while ((instr = kdbpeek(va)) != MIPS_JR_RA)
+               va -= sizeof(int);
+               va += 2 * sizeof(int);  /* skip back over branch & delay slot */
+               /* skip over nulls which might separate .o files */
+               while ((instr = kdbpeek(va)) == 0)
+                       va += sizeof(int);
+               subr = va;
+       }
+
+       /*
+        * Jump here for locore entry pointsn for which the preceding
+        * function doesn't end in "j ra"
+        */
+stackscan:
+       /* scan forwards to find stack size and any saved registers */
+       stksize = 0;
+       more = 3;
+       mask = 0;
+       for (va = subr; more; va += sizeof(int),
+                             more = (more == 3) ? 3 : more - 1) {
+               /* stop if hit our current position */
+               if (va >= pc)
+                       break;
+               instr = kdbpeek(va);
+               i.word = instr;
+               switch (i.JType.op) {
+               case OP_SPECIAL:
+                       switch (i.RType.func) {
+                       case OP_JR:
+                       case OP_JALR:
+                               more = 2; /* stop after next instruction */
+                               break;
+
+                       case OP_SYSCALL:
+                       case OP_BREAK:
+                               more = 1; /* stop now */
+                       };
+                       break;
+
+               case OP_BCOND:
+               case OP_J:
+               case OP_JAL:
+               case OP_BEQ:
+               case OP_BNE:
+               case OP_BLEZ:
+               case OP_BGTZ:
+                       more = 2; /* stop after next instruction */
+                       break;
+
+               case OP_COP0:
+               case OP_COP1:
+               case OP_COP2:
+               case OP_COP3:
+                       switch (i.RType.rs) {
+                       case OP_BCx:
+                       case OP_BCy:
+                               more = 2; /* stop after next instruction */
+                       };
+                       break;
+
+               case OP_SW:
+                       /* look for saved registers on the stack */
+                       if (i.IType.rs != 29)
+                               break;
+                       /* only restore the first one */
+                       if (mask & (1 << i.IType.rt))
+                               break;
+                       mask |= (1 << i.IType.rt);
+                       switch (i.IType.rt) {
+                       case 4: /* a0 */
+                               a0 = kdbpeek(sp + (short)i.IType.imm);
+                               break;
+
+                       case 5: /* a1 */
+                               a1 = kdbpeek(sp + (short)i.IType.imm);
+                               break;
+
+                       case 6: /* a2 */
+                               a2 = kdbpeek(sp + (short)i.IType.imm);
+                               break;
+
+                       case 7: /* a3 */
+                               a3 = kdbpeek(sp + (short)i.IType.imm);
+                               break;
+
+                       case 30: /* fp */
+                               fp = kdbpeek(sp + (short)i.IType.imm);
+                               break;
+
+                       case 31: /* ra */
+                               ra = kdbpeek(sp + (short)i.IType.imm);
+                       }
+                       break;
+
+               case OP_ADDI:
+               case OP_ADDIU:
+                       /* look for stack pointer adjustment */
+                       if (i.IType.rs != 29 || i.IType.rt != 29)
+                               break;
+                       stksize = - ((short)i.IType.imm);
+               }
+       }
+
+done:
+       (*printfn)("%s+%x (%x,%x,%x,%x) ra %x sz %d\n",
+               fn_name(subr), pc - subr, a0, a1, a2, a3, ra, stksize);
+
+       if (ra) {
+               if (pc == ra && stksize == 0)
+                       (*printfn)("stacktrace: loop!\n");
+               else {
+                       pc = ra;
+                       sp += stksize;
+                       ra = 0;
+                       goto loop;
+               }
+       } else {
+finish:
+               if (curproc)
+                       (*printfn)("User-level: pid %d\n", curproc->p_pid);
+               else
+                       (*printfn)("User-level: curproc NULL\n");
+       }
+}
+
+/*
+ * Functions ``special'' enough to print by name
+ */
+#ifdef __STDC__
+#define Name(_fn)  { (void*)_fn, # _fn }
+#else
+#define Name(_fn) { _fn, "_fn"}
+#endif
+static struct { void *addr; char *name;} names[] = {
+       Name(interrupt),
+       Name(trap),
+#ifdef R4K
+       Name(R4K_KernGenException),
+       Name(R4K_UserGenException),
+       Name(R4K_KernIntr),
+       Name(R4K_UserIntr),
+#else
+       Name(R3K_KernGenException),
+       Name(R3K_UserGenException),
+       Name(R3K_KernIntr),
+       Name(R3K_UserIntr),
+#endif
+       Name(splx),
+       Name(idle),
+       Name(cpu_switch),
+       {0, 0}
+};
+
+/*
+ * Map a function address to a string name, if known; or a hex string.
+ */
+char *
+fn_name(unsigned addr)
+{
+       static char buf[17];
+       int i = 0;
+
+       for (i = 0; names[i].name; i++)
+               if (names[i].addr == (void*)addr)
+                       return (names[i].name);
+       sprintf(buf, "%x", addr);
+       return (buf);
+}
+
+#endif /* DEBUG */
diff --git a/sys/arch/wgrisc/wgrisc/vm_machdep.c b/sys/arch/wgrisc/wgrisc/vm_machdep.c
new file mode 100644 (file)
index 0000000..80729f6
--- /dev/null
@@ -0,0 +1,494 @@
+/*     $OpenBSD: vm_machdep.c,v 1.1.1.1 1997/02/06 16:02:46 pefo Exp $ */
+/*
+ * Copyright (c) 1988 University of Utah.
+ * Copyright (c) 1992, 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 and Ralph Campbell.
+ *
+ * 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
+ *
+ *     from: @(#)vm_machdep.c  8.3 (Berkeley) 1/4/94
+ *      $Id: vm_machdep.c,v 1.1.1.1 1997/02/06 16:02:46 pefo Exp $
+ */
+
+
+
+#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 <vm/vm.h>
+#include <vm/vm_kern.h>
+#include <vm/vm_page.h>
+#if 0
+#include <vm/vm_object.h>
+#endif
+
+#include <machine/pte.h>
+#include <machine/cpu.h>
+
+vm_offset_t kmem_alloc_wait_align();
+
+/*
+ * 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.
+ */
+cpu_fork(p1, p2)
+       register struct proc *p1, *p2;
+{
+       register struct user *up = p2->p_addr;
+       register pt_entry_t *pte;
+       register int i;
+       extern struct proc *cpuFPCurProcPtr;
+
+       p2->p_md.md_regs = up->u_pcb.pcb_regs;
+       p2->p_md.md_flags = p1->p_md.md_flags & MDP_FPUSED;
+
+       /*
+        * Cache the PTEs for the user area in the machine dependent
+        * part of the proc struct so cpu_switch() can quickly map in
+        * the user struct and kernel stack. Note: if the virtual address
+        * translation changes (e.g. swapout) we have to update this.
+        */
+       pte = kvtopte(up);
+       for (i = 0; i < UPAGES; i++) {
+               p2->p_md.md_upte[i] = pte->pt_entry & ~(PG_G | PG_RO | PG_WIRED);
+               pte++;
+       }
+
+       /*
+        * Copy floating point state from the FP chip if this process
+        * has state stored there.
+        */
+       if (p1 == cpuFPCurProcPtr)
+               CPU_SaveCurFPState(p1);
+
+       /*
+        * Copy pcb and stack from proc p1 to p2. 
+        * We do this as cheaply as possible, copying only the active
+        * part of the stack.  The stack and pcb need to agree;
+        */
+       p2->p_addr->u_pcb = p1->p_addr->u_pcb;
+       /* cache segtab for ULTBMiss() */
+       p2->p_addr->u_pcb.pcb_segtab = (void *)p2->p_vmspace->vm_pmap.pm_segtab;
+
+       /*
+        * Arrange for a non-local goto when the new process
+        * is started, to resume here, returning nonzero from setjmp.
+        */
+#ifdef DIAGNOSTIC
+       if (p1 != curproc)
+               panic("cpu_fork: curproc");
+#endif
+       if (copykstack(up)) {
+               /*
+                * Return 1 in child.
+                */
+               return (1);
+       }
+       return (0);
+}
+
+/*
+ * Finish a swapin operation.
+ * We neded to update the cached PTEs for the user area in the
+ * machine dependent part of the proc structure.
+ */
+void
+cpu_swapin(p)
+       register struct proc *p;
+{
+       register struct user *up = p->p_addr;
+       register pt_entry_t *pte;
+       register int i;
+
+       /*
+        * Cache the PTEs for the user area in the machine dependent
+        * part of the proc struct so cpu_switch() can quickly map in
+        * the user struct and kernel stack.
+        */
+       pte = kvtopte(up);
+       for (i = 0; i < UPAGES; i++) {
+               p->p_md.md_upte[i] = pte->pt_entry & ~(PG_G | PG_RO | PG_WIRED);
+               pte++;
+       }
+}
+
+/*
+ * 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;
+{
+       extern struct proc *cpuFPCurProcPtr;
+
+       if (cpuFPCurProcPtr == p)
+               cpuFPCurProcPtr = (struct proc *)0;
+
+       vmspace_free(p->p_vmspace);
+
+       (void) splhigh();
+       kmem_free(kernel_map, (vm_offset_t)p->p_addr, ctob(UPAGES));
+       switch_exit();
+       /* NOTREACHED */
+}
+
+/*
+ * Dump the machine specific header information at the start of a core dump.
+ */
+cpu_coredump(p, vp, cred, core)
+       struct proc *p;
+       struct vnode *vp;
+       struct ucred *cred;
+       struct core *core;
+{
+       extern struct proc *cpuFPCurProcPtr;
+
+       /*
+        * Copy floating point state from the FP chip if this process
+        * has state stored there.
+        */
+       if (p == cpuFPCurProcPtr)
+               CPU_SaveCurFPState(p);
+
+       return (vn_rdwr(UIO_WRITE, vp, (caddr_t)p->p_addr, ctob(UPAGES),
+           (off_t)0, UIO_SYSSPACE, IO_NODELOCKED|IO_UNIT, cred, (int *)NULL,
+           p));
+}
+
+/*
+ * 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.
+ */
+void
+pagemove(from, to, size)
+       register caddr_t from, to;
+       size_t size;
+{
+       register pt_entry_t *fpte, *tpte;
+
+       if (size % CLBYTES)
+               panic("pagemove");
+       fpte = kvtopte(from);
+       tpte = kvtopte(to);
+#ifdef R4K
+       if(((int)from & CpuCacheAliasMask) != ((int)to & CpuCacheAliasMask)) {
+               R4K_HitFlushDCache(from, size);
+       }
+#endif
+       while (size > 0) {
+#ifdef R4K
+               R4K_TLBFlushAddr(from);
+               R4K_TLBUpdate(to, *fpte);
+#else
+               R3K_TLBFlushAddr(from);
+               R3K_TLBUpdate(to, *fpte);
+#endif
+               *tpte++ = *fpte;
+               fpte->pt_entry = PG_NV | PG_G;
+               fpte++;
+               size -= NBPG;
+               from += NBPG;
+               to += NBPG;
+       }
+}
+
+extern vm_map_t phys_map;
+
+/*
+ * Map an IO request into kernel virtual address space.  Requests fall into
+ * one of five catagories:
+ *
+ *     B_PHYS|B_UAREA: User u-area swap.
+ *                     Address is relative to start of u-area (p_addr).
+ *     B_PHYS|B_PAGET: User page table swap.
+ *                     Address is a kernel VA in usrpt (Usrptmap).
+ *     B_PHYS|B_DIRTY: Dirty page push.
+ *                     Address is a VA in proc2's address space.
+ *     B_PHYS|B_PGIN:  Kernel pagein of user pages.
+ *                     Address is VA in user's address space.
+ *     B_PHYS:         User "raw" IO request.
+ *                     Address is VA in user's address space.
+ *
+ * All requests are (re)mapped into kernel VA space via the phys_map
+ */
+void
+vmapbuf(bp, len)
+       struct buf *bp;
+       vm_size_t len;
+{
+       register caddr_t addr;
+       register vm_size_t sz;
+       struct proc *p;
+       int off;
+       vm_offset_t kva;
+       register vm_offset_t pa;
+
+       if ((bp->b_flags & B_PHYS) == 0)
+               panic("vmapbuf");
+       addr = bp->b_saveaddr = bp->b_un.b_addr;
+       off = (int)addr & PGOFSET;
+       p = bp->b_proc;
+       sz = round_page(off + len);
+       kva = kmem_alloc_wait_align(phys_map, sz, (vm_size_t)addr & CpuCacheAliasMask);
+       bp->b_un.b_addr = (caddr_t) (kva + off);
+       sz = atop(sz);
+       while (sz--) {
+               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.
+ * We also invalidate the TLB entries and restore the original b_addr.
+ */
+void
+vunmapbuf(bp, len)
+       struct buf *bp;
+       vm_size_t len;
+{
+       register caddr_t addr = bp->b_un.b_addr;
+       register vm_size_t sz;
+       vm_offset_t kva;
+
+       if ((bp->b_flags & B_PHYS) == 0)
+               panic("vunmapbuf");
+       sz = round_page(len + ((int)addr & PGOFSET));
+       kva = (vm_offset_t)((int)addr & ~PGOFSET);
+       kmem_free_wakeup(phys_map, kva, sz);
+       bp->b_un.b_addr = bp->b_saveaddr;
+       bp->b_saveaddr = NULL;
+}
+
+
+/*
+ *     SAVE_HINT:
+ *
+ *     Saves the specified entry as the hint for
+ *     future lookups.  Performs necessary interlocks.
+ */
+#define        SAVE_HINT(map,value) \
+               simple_lock(&(map)->hint_lock); \
+               (map)->hint = (value); \
+               simple_unlock(&(map)->hint_lock);
+
+
+/*
+ *     kmem_alloc_upage:
+ *
+ *     Allocate pageable memory to the kernel's address map.
+ *     map must be "kernel_map" below.
+ *     (Currently only used when allocating U pages).
+ */
+vm_offset_t
+kmem_alloc_upage(map, size)
+       vm_map_t                map;
+       register vm_size_t      size;
+{
+       vm_offset_t             addr;
+       register int            result;
+
+
+       size = round_page(size);
+
+       addr = vm_map_min(map);
+       result = vm_map_find_U(map, NULL, (vm_offset_t) 0,
+                               &addr, size, TRUE);
+       if (result != KERN_SUCCESS) {
+               return(0);
+       }
+
+       return(addr);
+}
+
+/*
+ *     vm_map_find finds an unallocated region in the target address
+ *     map with the given length aligned on U viritual address.
+ *     The search is defined to be first-fit from the specified address;
+ *     the region found is returned in the same parameter.
+ *
+ */
+int
+vm_map_find_U(map, object, offset, addr, length, find_space)
+       vm_map_t        map;
+       vm_object_t     object;
+       vm_offset_t     offset;
+       vm_offset_t     *addr;          /* IN/OUT */
+       vm_size_t       length;
+       boolean_t       find_space;
+{
+       register vm_offset_t    start;
+       int                     result;
+
+       start = *addr;
+       vm_map_lock(map);
+       if (find_space) {
+               if (vm_map_findspace_align(map, start, length, addr, 0)) {
+                       vm_map_unlock(map);
+                       return (KERN_NO_SPACE);
+               }
+               start = *addr;
+       }
+       result = vm_map_insert(map, object, offset, start, start + length);
+       vm_map_unlock(map);
+       return (result);
+}
+
+/*
+ * Find sufficient space for `length' bytes in the given map, starting at
+ * `start'.  The map must be locked.  Returns 0 on success, 1 on no space.
+ */
+int
+vm_map_findspace_align(map, start, length, addr, align)
+       register vm_map_t map;
+       register vm_offset_t start;
+       vm_size_t length;
+       vm_offset_t *addr;
+       vm_size_t align;
+{
+       register vm_map_entry_t entry, next;
+       register vm_offset_t end;
+
+       if (start < map->min_offset)
+               start = map->min_offset;
+       if (start > map->max_offset)
+               return (1);
+
+       /*
+        * Look for the first possible address; if there's already
+        * something at this address, we have to start after it.
+        */
+       if (start == map->min_offset) {
+               if ((entry = map->first_free) != &map->header)
+                       start = entry->end;
+       } else {
+               vm_map_entry_t tmp;
+               if (vm_map_lookup_entry(map, start, &tmp))
+                       start = tmp->end;
+               entry = tmp;
+       }
+
+       /*
+        * Look through the rest of the map, trying to fit a new region in
+        * the gap between existing regions, or after the very last region.
+        */
+       for (;; start = (entry = next)->end) {
+               /*
+                * Find the end of the proposed new region.  Be sure we didn't
+                * go beyond the end of the map, or wrap around the address;
+                * if so, we lose.  Otherwise, if this is the last entry, or
+                * if the proposed new region fits before the next entry, we
+                * win.
+                */
+               start = ((start + NBPG -1) & ~(NBPG - 1)); /* Paranoia */
+               if((start & CpuCacheAliasMask) <= align) {
+                       start += align - (start & CpuCacheAliasMask);
+               }
+               else {
+                       start = ((start + CpuCacheAliasMask) & ~CpuCacheAliasMask);
+                       start += align;
+               }
+                       
+               end = start + length;
+               if (end > map->max_offset || end < start)
+                       return (1);
+               next = entry->next;
+               if (next == &map->header || next->start >= end)
+                       break;
+       }
+       SAVE_HINT(map, entry);
+       *addr = start;
+       return (0);
+}
+
+/*
+ *     kmem_alloc_wait_align
+ *
+ *     Allocates pageable memory from a sub-map of the kernel.  If the submap
+ *     has no room, the caller sleeps waiting for more memory in the submap.
+ *
+ */
+vm_offset_t
+kmem_alloc_wait_align(map, size, align)
+       vm_map_t        map;
+       vm_size_t       size;
+       vm_size_t       align;
+{
+       vm_offset_t     addr;
+
+       size = round_page(size);
+
+       for (;;) {
+               /*
+                * To make this work for more than one map,
+                * use the map's lock to lock out sleepers/wakers.
+                */
+               vm_map_lock(map);
+               if (vm_map_findspace_align(map, 0, size, &addr, align) == 0)
+                       break;
+               /* no space now; see if we can ever get space */
+               if (vm_map_max(map) - vm_map_min(map) < size) {
+                       vm_map_unlock(map);
+                       return (0);
+               }
+               assert_wait(map, TRUE);
+               vm_map_unlock(map);
+               thread_block();
+       }
+       vm_map_insert(map, NULL, (vm_offset_t)0, addr, addr + size);
+       vm_map_unlock(map);
+       return (addr);
+}
diff --git a/sys/arch/wgrisc/wgrisc/wgrisctype.h b/sys/arch/wgrisc/wgrisc/wgrisctype.h
new file mode 100644 (file)
index 0000000..7781964
--- /dev/null
@@ -0,0 +1,38 @@
+/*     $OpenBSD: wgrisctype.h,v 1.1.1.1 1997/02/06 16:02:47 pefo Exp $ */
+
+/*
+ * Copyright (c) 1996 Per Fogelstrom
+ * 
+ * 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 under OpenBSD by
+ *     Per Fogelstrom.
+ * 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.
+ *
+ */
+
+/*
+ * Mother board type byte of "systype" environment variable.
+ */
+#define        WGRISC9100      0x1     /* WGRISC 9100 R3081 board */