summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sys/arch/wgrisc/Makefile28
-rw-r--r--sys/arch/wgrisc/compile/.cvsignore1
-rw-r--r--sys/arch/wgrisc/compile/.keep_me1
-rw-r--r--sys/arch/wgrisc/conf/DISKLESS77
-rw-r--r--sys/arch/wgrisc/conf/GENERIC124
-rw-r--r--sys/arch/wgrisc/conf/Makefile.wgrisc183
-rw-r--r--sys/arch/wgrisc/conf/files.wgrisc106
-rw-r--r--sys/arch/wgrisc/conf/ld.script74
-rw-r--r--sys/arch/wgrisc/dev/ace.c1653
-rw-r--r--sys/arch/wgrisc/dev/asc.c2096
-rw-r--r--sys/arch/wgrisc/dev/ascreg.h326
-rw-r--r--sys/arch/wgrisc/dev/com_risc.c195
-rw-r--r--sys/arch/wgrisc/dev/dma.h147
-rw-r--r--sys/arch/wgrisc/dev/if_sn.c1288
-rw-r--r--sys/arch/wgrisc/dev/if_sn.h347
-rw-r--r--sys/arch/wgrisc/dev/scsi.h559
-rw-r--r--sys/arch/wgrisc/include/ansi.h75
-rw-r--r--sys/arch/wgrisc/include/asm.h198
-rw-r--r--sys/arch/wgrisc/include/autoconf.h79
-rw-r--r--sys/arch/wgrisc/include/bus.h155
-rw-r--r--sys/arch/wgrisc/include/cdefs.h39
-rw-r--r--sys/arch/wgrisc/include/cpu.h417
-rw-r--r--sys/arch/wgrisc/include/disklabel.h88
-rw-r--r--sys/arch/wgrisc/include/dlfcn.h42
-rw-r--r--sys/arch/wgrisc/include/ecoff.h94
-rw-r--r--sys/arch/wgrisc/include/elf_abi.h57
-rw-r--r--sys/arch/wgrisc/include/endian.h95
-rw-r--r--sys/arch/wgrisc/include/exec.h62
-rw-r--r--sys/arch/wgrisc/include/float.h81
-rw-r--r--sys/arch/wgrisc/include/ieeefp.h25
-rw-r--r--sys/arch/wgrisc/include/intr.h164
-rw-r--r--sys/arch/wgrisc/include/kbdreg.h82
-rw-r--r--sys/arch/wgrisc/include/kcore.h45
-rw-r--r--sys/arch/wgrisc/include/kdbparam.h75
-rw-r--r--sys/arch/wgrisc/include/limits.h101
-rw-r--r--sys/arch/wgrisc/include/link.h68
-rw-r--r--sys/arch/wgrisc/include/memconf.h50
-rw-r--r--sys/arch/wgrisc/include/mips_opcode.h260
-rw-r--r--sys/arch/wgrisc/include/param.h165
-rw-r--r--sys/arch/wgrisc/include/pcb.h61
-rw-r--r--sys/arch/wgrisc/include/pio.h46
-rw-r--r--sys/arch/wgrisc/include/pmap.h109
-rw-r--r--sys/arch/wgrisc/include/proc.h54
-rw-r--r--sys/arch/wgrisc/include/profile.h81
-rw-r--r--sys/arch/wgrisc/include/psl.h61
-rw-r--r--sys/arch/wgrisc/include/pte.h176
-rw-r--r--sys/arch/wgrisc/include/ptrace.h45
-rw-r--r--sys/arch/wgrisc/include/reg.h62
-rw-r--r--sys/arch/wgrisc/include/regdef.h74
-rw-r--r--sys/arch/wgrisc/include/regnum.h136
-rw-r--r--sys/arch/wgrisc/include/reloc.h38
-rw-r--r--sys/arch/wgrisc/include/setjmp.h8
-rw-r--r--sys/arch/wgrisc/include/signal.h68
-rw-r--r--sys/arch/wgrisc/include/stdarg.h65
-rw-r--r--sys/arch/wgrisc/include/trap.h68
-rw-r--r--sys/arch/wgrisc/include/types.h82
-rw-r--r--sys/arch/wgrisc/include/varargs.h69
-rw-r--r--sys/arch/wgrisc/include/vmparam.h229
-rw-r--r--sys/arch/wgrisc/isa/isa_machdep.h84
-rw-r--r--sys/arch/wgrisc/isa/isabus.c350
-rw-r--r--sys/arch/wgrisc/riscbus/riscbus.c318
-rw-r--r--sys/arch/wgrisc/riscbus/riscbus.h118
-rw-r--r--sys/arch/wgrisc/stand/Makefile96
-rw-r--r--sys/arch/wgrisc/stand/boot.c114
-rw-r--r--sys/arch/wgrisc/stand/conf.c70
-rw-r--r--sys/arch/wgrisc/stand/filesystem.c44
-rw-r--r--sys/arch/wgrisc/stand/libsa/Makefile14
-rw-r--r--sys/arch/wgrisc/stand/libsa/devopen.c128
-rw-r--r--sys/arch/wgrisc/stand/libsa/getenv.c45
-rw-r--r--sys/arch/wgrisc/stand/libsa/getputchar.c69
-rw-r--r--sys/arch/wgrisc/stand/rz.c174
-rw-r--r--sys/arch/wgrisc/stand/start.S129
-rw-r--r--sys/arch/wgrisc/wgrisc/autoconf.c464
-rw-r--r--sys/arch/wgrisc/wgrisc/clock.c327
-rw-r--r--sys/arch/wgrisc/wgrisc/clock_dp.c227
-rw-r--r--sys/arch/wgrisc/wgrisc/clockvar.h82
-rw-r--r--sys/arch/wgrisc/wgrisc/conf.c365
-rw-r--r--sys/arch/wgrisc/wgrisc/cpu.c192
-rw-r--r--sys/arch/wgrisc/wgrisc/cpu_exec.c104
-rw-r--r--sys/arch/wgrisc/wgrisc/disksubr.c355
-rw-r--r--sys/arch/wgrisc/wgrisc/fp.S3611
-rw-r--r--sys/arch/wgrisc/wgrisc/genassym.c74
-rw-r--r--sys/arch/wgrisc/wgrisc/locore.S4485
-rw-r--r--sys/arch/wgrisc/wgrisc/machdep.c1060
-rw-r--r--sys/arch/wgrisc/wgrisc/mainbus.c160
-rw-r--r--sys/arch/wgrisc/wgrisc/mem.c173
-rw-r--r--sys/arch/wgrisc/wgrisc/minidebug.c975
-rw-r--r--sys/arch/wgrisc/wgrisc/pmap.c1823
-rw-r--r--sys/arch/wgrisc/wgrisc/process_machdep.c114
-rw-r--r--sys/arch/wgrisc/wgrisc/swapgeneric.c61
-rw-r--r--sys/arch/wgrisc/wgrisc/sys_machdep.c130
-rw-r--r--sys/arch/wgrisc/wgrisc/trap.c1653
-rw-r--r--sys/arch/wgrisc/wgrisc/vm_machdep.c494
-rw-r--r--sys/arch/wgrisc/wgrisc/wgrisctype.h38
94 files changed, 29974 insertions, 0 deletions
diff --git a/sys/arch/wgrisc/Makefile b/sys/arch/wgrisc/Makefile
new file mode 100644
index 00000000000..79473e5afc1
--- /dev/null
+++ b/sys/arch/wgrisc/Makefile
@@ -0,0 +1,28 @@
+# from: @(#)Makefile 8.1 (Berkeley) 6/16/93
+# $Id: Makefile,v 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
index 00000000000..db5b0e04a3a
--- /dev/null
+++ b/sys/arch/wgrisc/compile/.cvsignore
@@ -0,0 +1 @@
+GENERIC
diff --git a/sys/arch/wgrisc/compile/.keep_me b/sys/arch/wgrisc/compile/.keep_me
new file mode 100644
index 00000000000..75270197a54
--- /dev/null
+++ b/sys/arch/wgrisc/compile/.keep_me
@@ -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
index 00000000000..744607c9c24
--- /dev/null
+++ b/sys/arch/wgrisc/conf/DISKLESS
@@ -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
index 00000000000..ca3772e008b
--- /dev/null
+++ b/sys/arch/wgrisc/conf/GENERIC
@@ -0,0 +1,124 @@
+# $OpenBSD: GENERIC,v 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
index 00000000000..ba4cb657c57
--- /dev/null
+++ b/sys/arch/wgrisc/conf/Makefile.wgrisc
@@ -0,0 +1,183 @@
+# $OpenBSD: Makefile.wgrisc,v 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
index 00000000000..ad6fed82a90
--- /dev/null
+++ b/sys/arch/wgrisc/conf/files.wgrisc
@@ -0,0 +1,106 @@
+# $OpenBSD: files.wgrisc,v 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
index 00000000000..3c59f13f80b
--- /dev/null
+++ b/sys/arch/wgrisc/conf/ld.script
@@ -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
index 00000000000..d577033f2c7
--- /dev/null
+++ b/sys/arch/wgrisc/dev/ace.c
@@ -0,0 +1,1653 @@
+/* $OpenBSD: ace.c,v 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
index 00000000000..13785ab9c0f
--- /dev/null
+++ b/sys/arch/wgrisc/dev/asc.c
@@ -0,0 +1,2096 @@
+/* $OpenBSD: asc.c,v 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
index 00000000000..3a5a213ba36
--- /dev/null
+++ b/sys/arch/wgrisc/dev/ascreg.h
@@ -0,0 +1,326 @@
+/* $OpenBSD: ascreg.h,v 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 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
index 00000000000..557179e6642
--- /dev/null
+++ b/sys/arch/wgrisc/dev/com_risc.c
@@ -0,0 +1,195 @@
+/* $OpenBSD: com_risc.c,v 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
index 00000000000..dd5fb4c51b2
--- /dev/null
+++ b/sys/arch/wgrisc/dev/dma.h
@@ -0,0 +1,147 @@
+/* $OpenBSD: dma.h,v 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
index 00000000000..b31ed2e0911
--- /dev/null
+++ b/sys/arch/wgrisc/dev/if_sn.c
@@ -0,0 +1,1288 @@
+/* $OpenBSD: if_sn.c,v 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
index 00000000000..4139a1c7850
--- /dev/null
+++ b/sys/arch/wgrisc/dev/if_sn.h
@@ -0,0 +1,347 @@
+/* $OpenBSD: if_sn.h,v 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
index 00000000000..79f6886db9f
--- /dev/null
+++ b/sys/arch/wgrisc/dev/scsi.h
@@ -0,0 +1,559 @@
+/* $OpenBSD: scsi.h,v 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 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 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
index 00000000000..cc607a5d559
--- /dev/null
+++ b/sys/arch/wgrisc/include/ansi.h
@@ -0,0 +1,75 @@
+/* $OpenBSD: ansi.h,v 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
index 00000000000..06df98758c2
--- /dev/null
+++ b/sys/arch/wgrisc/include/asm.h
@@ -0,0 +1,198 @@
+/* $OpenBSD: asm.h,v 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
index 00000000000..5bd56ec9341
--- /dev/null
+++ b/sys/arch/wgrisc/include/autoconf.h
@@ -0,0 +1,79 @@
+/* $OpenBSD: autoconf.h,v 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
index 00000000000..eb63712fc4f
--- /dev/null
+++ b/sys/arch/wgrisc/include/bus.h
@@ -0,0 +1,155 @@
+/* $OpenBSD: bus.h,v 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
index 00000000000..45491b2df35
--- /dev/null
+++ b/sys/arch/wgrisc/include/cdefs.h
@@ -0,0 +1,39 @@
+/* $OpenBSD: cdefs.h,v 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
index 00000000000..1ffa44898f9
--- /dev/null
+++ b/sys/arch/wgrisc/include/cpu.h
@@ -0,0 +1,417 @@
+/* $OpenBSD: cpu.h,v 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
index 00000000000..41df7318418
--- /dev/null
+++ b/sys/arch/wgrisc/include/disklabel.h
@@ -0,0 +1,88 @@
+/* $OpenBSD: disklabel.h,v 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
index 00000000000..d21e46eb68c
--- /dev/null
+++ b/sys/arch/wgrisc/include/dlfcn.h
@@ -0,0 +1,42 @@
+/* $OpenBSD: dlfcn.h,v 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
index 00000000000..0a7e76b27c2
--- /dev/null
+++ b/sys/arch/wgrisc/include/ecoff.h
@@ -0,0 +1,94 @@
+/* $OpenBSD: ecoff.h,v 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
index 00000000000..be988c70925
--- /dev/null
+++ b/sys/arch/wgrisc/include/elf_abi.h
@@ -0,0 +1,57 @@
+/* $OpenBSD: elf_abi.h,v 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
index 00000000000..b08ec1b92eb
--- /dev/null
+++ b/sys/arch/wgrisc/include/endian.h
@@ -0,0 +1,95 @@
+/* $OpenBSD: endian.h,v 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
index 00000000000..05ba554d5dc
--- /dev/null
+++ b/sys/arch/wgrisc/include/exec.h
@@ -0,0 +1,62 @@
+/* $OpenBSD: exec.h,v 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
index 00000000000..19c9ee76e9b
--- /dev/null
+++ b/sys/arch/wgrisc/include/float.h
@@ -0,0 +1,81 @@
+/* $OpenBSD: float.h,v 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
index 00000000000..6032cbcc0a2
--- /dev/null
+++ b/sys/arch/wgrisc/include/ieeefp.h
@@ -0,0 +1,25 @@
+/* $OpenBSD: ieeefp.h,v 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
index 00000000000..67e7ad75ff1
--- /dev/null
+++ b/sys/arch/wgrisc/include/intr.h
@@ -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
index 00000000000..1cc11515b73
--- /dev/null
+++ b/sys/arch/wgrisc/include/kbdreg.h
@@ -0,0 +1,82 @@
+/* $OpenBSD: kbdreg.h,v 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
index 00000000000..00903c7e50a
--- /dev/null
+++ b/sys/arch/wgrisc/include/kcore.h
@@ -0,0 +1,45 @@
+/* $OpenBSD: kcore.h,v 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
index 00000000000..b5e5c27002e
--- /dev/null
+++ b/sys/arch/wgrisc/include/kdbparam.h
@@ -0,0 +1,75 @@
+/* $OpenBSD: kdbparam.h,v 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
index 00000000000..67584eab9ea
--- /dev/null
+++ b/sys/arch/wgrisc/include/limits.h
@@ -0,0 +1,101 @@
+/* $OpenBSD: limits.h,v 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
index 00000000000..411e4e93e56
--- /dev/null
+++ b/sys/arch/wgrisc/include/link.h
@@ -0,0 +1,68 @@
+/* $OpenBSD: link.h,v 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
index 00000000000..ea66b629e96
--- /dev/null
+++ b/sys/arch/wgrisc/include/memconf.h
@@ -0,0 +1,50 @@
+/* $OpenBSD: memconf.h,v 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
index 00000000000..b314794d90b
--- /dev/null
+++ b/sys/arch/wgrisc/include/mips_opcode.h
@@ -0,0 +1,260 @@
+/* $OpenBSD: mips_opcode.h,v 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
index 00000000000..052db4a28eb
--- /dev/null
+++ b/sys/arch/wgrisc/include/param.h
@@ -0,0 +1,165 @@
+/* $OpenBSD: param.h,v 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
index 00000000000..f7f2ce46869
--- /dev/null
+++ b/sys/arch/wgrisc/include/pcb.h
@@ -0,0 +1,61 @@
+/* $OpenBSD: pcb.h,v 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
index 00000000000..a950695eb3e
--- /dev/null
+++ b/sys/arch/wgrisc/include/pio.h
@@ -0,0 +1,46 @@
+/* $OpenBSD: pio.h,v 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
index 00000000000..3044047e584
--- /dev/null
+++ b/sys/arch/wgrisc/include/pmap.h
@@ -0,0 +1,109 @@
+/* $OpenBSD: pmap.h,v 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
index 00000000000..6b6b1cecd05
--- /dev/null
+++ b/sys/arch/wgrisc/include/proc.h
@@ -0,0 +1,54 @@
+/* $OpenBSD: proc.h,v 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
index 00000000000..9d4b5d3efb8
--- /dev/null
+++ b/sys/arch/wgrisc/include/profile.h
@@ -0,0 +1,81 @@
+/* $OpenBSD: profile.h,v 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
index 00000000000..1158aaae34f
--- /dev/null
+++ b/sys/arch/wgrisc/include/psl.h
@@ -0,0 +1,61 @@
+/* $OpenBSD: psl.h,v 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
index 00000000000..97463fe7ff7
--- /dev/null
+++ b/sys/arch/wgrisc/include/pte.h
@@ -0,0 +1,176 @@
+/* $OpenBSD: pte.h,v 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
index 00000000000..cc39ce21efc
--- /dev/null
+++ b/sys/arch/wgrisc/include/ptrace.h
@@ -0,0 +1,45 @@
+/* $OpenBSD: ptrace.h,v 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
index 00000000000..b76697e21d6
--- /dev/null
+++ b/sys/arch/wgrisc/include/reg.h
@@ -0,0 +1,62 @@
+/* $OpenBSD: reg.h,v 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
index 00000000000..e78cfda0e6b
--- /dev/null
+++ b/sys/arch/wgrisc/include/regdef.h
@@ -0,0 +1,74 @@
+/* $OpenBSD: regdef.h,v 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
index 00000000000..a952baa78e2
--- /dev/null
+++ b/sys/arch/wgrisc/include/regnum.h
@@ -0,0 +1,136 @@
+/* $OpenBSD: regnum.h,v 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
index 00000000000..e9652853c1c
--- /dev/null
+++ b/sys/arch/wgrisc/include/reloc.h
@@ -0,0 +1,38 @@
+/* $OpenBSD: reloc.h,v 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
index 00000000000..9e9a2b275f5
--- /dev/null
+++ b/sys/arch/wgrisc/include/setjmp.h
@@ -0,0 +1,8 @@
+/* $OpenBSD: setjmp.h,v 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
index 00000000000..f69bea8f1c7
--- /dev/null
+++ b/sys/arch/wgrisc/include/signal.h
@@ -0,0 +1,68 @@
+/* $OpenBSD: signal.h,v 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
index 00000000000..d7547edec64
--- /dev/null
+++ b/sys/arch/wgrisc/include/stdarg.h
@@ -0,0 +1,65 @@
+/* $OpenBSD: stdarg.h,v 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
index 00000000000..bb9fd65c3fb
--- /dev/null
+++ b/sys/arch/wgrisc/include/trap.h
@@ -0,0 +1,68 @@
+/* $OpenBSD: trap.h,v 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
index 00000000000..af2da55a4d1
--- /dev/null
+++ b/sys/arch/wgrisc/include/types.h
@@ -0,0 +1,82 @@
+/* $OpenBSD: types.h,v 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
index 00000000000..8656c4b1607
--- /dev/null
+++ b/sys/arch/wgrisc/include/varargs.h
@@ -0,0 +1,69 @@
+/* $OpenBSD: varargs.h,v 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
index 00000000000..fc302f59943
--- /dev/null
+++ b/sys/arch/wgrisc/include/vmparam.h
@@ -0,0 +1,229 @@
+/* $OpenBSD: vmparam.h,v 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
index 00000000000..47d73c6318c
--- /dev/null
+++ b/sys/arch/wgrisc/isa/isa_machdep.h
@@ -0,0 +1,84 @@
+/* $OpenBSD: isa_machdep.h,v 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
index 00000000000..2c2c6e4ecde
--- /dev/null
+++ b/sys/arch/wgrisc/isa/isabus.c
@@ -0,0 +1,350 @@
+/* $OpenBSD: isabus.c,v 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
index 00000000000..93b54032f7c
--- /dev/null
+++ b/sys/arch/wgrisc/riscbus/riscbus.c
@@ -0,0 +1,318 @@
+/* $OpenBSD: riscbus.c,v 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
index 00000000000..3fb52adc839
--- /dev/null
+++ b/sys/arch/wgrisc/riscbus/riscbus.h
@@ -0,0 +1,118 @@
+/* $OpenBSD: riscbus.h,v 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
index 00000000000..a7dd6383200
--- /dev/null
+++ b/sys/arch/wgrisc/stand/Makefile
@@ -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
index 00000000000..170f6f923de
--- /dev/null
+++ b/sys/arch/wgrisc/stand/boot.c
@@ -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
index 00000000000..cecbc70b64c
--- /dev/null
+++ b/sys/arch/wgrisc/stand/conf.c
@@ -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
index 00000000000..514e6e809bf
--- /dev/null
+++ b/sys/arch/wgrisc/stand/filesystem.c
@@ -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
index 00000000000..d147171311d
--- /dev/null
+++ b/sys/arch/wgrisc/stand/libsa/Makefile
@@ -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
index 00000000000..79b35f8f595
--- /dev/null
+++ b/sys/arch/wgrisc/stand/libsa/devopen.c
@@ -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
index 00000000000..7e063cd4ad5
--- /dev/null
+++ b/sys/arch/wgrisc/stand/libsa/getenv.c
@@ -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
index 00000000000..dbfae22d4d6
--- /dev/null
+++ b/sys/arch/wgrisc/stand/libsa/getputchar.c
@@ -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
index 00000000000..1094aef4705
--- /dev/null
+++ b/sys/arch/wgrisc/stand/rz.c
@@ -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
index 00000000000..09114a91b7e
--- /dev/null
+++ b/sys/arch/wgrisc/stand/start.S
@@ -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
index 00000000000..6b6102ac7e3
--- /dev/null
+++ b/sys/arch/wgrisc/wgrisc/autoconf.c
@@ -0,0 +1,464 @@
+/* $OpenBSD: autoconf.c,v 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 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
index 00000000000..2b6156a2638
--- /dev/null
+++ b/sys/arch/wgrisc/wgrisc/clock.c
@@ -0,0 +1,327 @@
+/* $OpenBSD: clock.c,v 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 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
index 00000000000..78cbb096e4a
--- /dev/null
+++ b/sys/arch/wgrisc/wgrisc/clock_dp.c
@@ -0,0 +1,227 @@
+/* $OpenBSD: clock_dp.c,v 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
index 00000000000..bf174f291e1
--- /dev/null
+++ b/sys/arch/wgrisc/wgrisc/clockvar.h
@@ -0,0 +1,82 @@
+/* $OpenBSD: clockvar.h,v 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
index 00000000000..df8a4e6fc6f
--- /dev/null
+++ b/sys/arch/wgrisc/wgrisc/conf.c
@@ -0,0 +1,365 @@
+/* $OpenBSD: conf.c,v 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 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
index 00000000000..7f87fd99a0d
--- /dev/null
+++ b/sys/arch/wgrisc/wgrisc/cpu.c
@@ -0,0 +1,192 @@
+/* $OpenBSD: cpu.c,v 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
index 00000000000..4e3e657011a
--- /dev/null
+++ b/sys/arch/wgrisc/wgrisc/cpu_exec.c
@@ -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
index 00000000000..64d08bd1275
--- /dev/null
+++ b/sys/arch/wgrisc/wgrisc/disksubr.c
@@ -0,0 +1,355 @@
+/* $OpenBSD: disksubr.c,v 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
index 00000000000..0ba3cfa8d1e
--- /dev/null
+++ b/sys/arch/wgrisc/wgrisc/fp.S
@@ -0,0 +1,3611 @@
+/* $OpenBSD: fp.S,v 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 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
index 00000000000..f8407c88d8b
--- /dev/null
+++ b/sys/arch/wgrisc/wgrisc/genassym.c
@@ -0,0 +1,74 @@
+/* $OpenBSD: genassym.c,v 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 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
index 00000000000..c4e33c9ebea
--- /dev/null
+++ b/sys/arch/wgrisc/wgrisc/locore.S
@@ -0,0 +1,4485 @@
+
+/* $OpenBSD: locore.S,v 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 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
index 00000000000..427b4d950a4
--- /dev/null
+++ b/sys/arch/wgrisc/wgrisc/machdep.c
@@ -0,0 +1,1060 @@
+/* $OpenBSD: machdep.c,v 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 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
index 00000000000..12c7545a2cf
--- /dev/null
+++ b/sys/arch/wgrisc/wgrisc/mainbus.c
@@ -0,0 +1,160 @@
+/* $OpenBSD: mainbus.c,v 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
index 00000000000..b898f9546ac
--- /dev/null
+++ b/sys/arch/wgrisc/wgrisc/mem.c
@@ -0,0 +1,173 @@
+/* $OpenBSD: mem.c,v 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
index 00000000000..3b13aa67782
--- /dev/null
+++ b/sys/arch/wgrisc/wgrisc/minidebug.c
@@ -0,0 +1,975 @@
+/* $OpenBSD: minidebug.c,v 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 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
index 00000000000..0abc9c6bdaf
--- /dev/null
+++ b/sys/arch/wgrisc/wgrisc/pmap.c
@@ -0,0 +1,1823 @@
+/* $OpenBSD: pmap.c,v 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 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
index 00000000000..116348abefe
--- /dev/null
+++ b/sys/arch/wgrisc/wgrisc/process_machdep.c
@@ -0,0 +1,114 @@
+/* $OpenBSD: process_machdep.c,v 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 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
index 00000000000..00391d6c7d2
--- /dev/null
+++ b/sys/arch/wgrisc/wgrisc/swapgeneric.c
@@ -0,0 +1,61 @@
+/* $OpenBSD: swapgeneric.c,v 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
index 00000000000..9e52c5c6cd5
--- /dev/null
+++ b/sys/arch/wgrisc/wgrisc/sys_machdep.c
@@ -0,0 +1,130 @@
+/* $OpenBSD: sys_machdep.c,v 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
index 00000000000..ce22ad2e05b
--- /dev/null
+++ b/sys/arch/wgrisc/wgrisc/trap.c
@@ -0,0 +1,1653 @@
+/* $OpenBSD: trap.c,v 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 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
index 00000000000..f27b9b49c3a
--- /dev/null
+++ b/sys/arch/wgrisc/wgrisc/vm_machdep.c
@@ -0,0 +1,494 @@
+/* $OpenBSD: vm_machdep.c,v 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 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
index 00000000000..2e8f475a2dd
--- /dev/null
+++ b/sys/arch/wgrisc/wgrisc/wgrisctype.h
@@ -0,0 +1,38 @@
+/* $OpenBSD: wgrisctype.h,v 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 */