summaryrefslogtreecommitdiff
path: root/sys/arch/pc532
diff options
context:
space:
mode:
authorTheo de Raadt <deraadt@cvs.openbsd.org>1995-10-18 08:53:40 +0000
committerTheo de Raadt <deraadt@cvs.openbsd.org>1995-10-18 08:53:40 +0000
commitd6583bb2a13f329cf0332ef2570eb8bb8fc0e39c (patch)
treeece253b876159b39c620e62b6c9b1174642e070e /sys/arch/pc532
initial import of NetBSD tree
Diffstat (limited to 'sys/arch/pc532')
-rw-r--r--sys/arch/pc532/Makefile32
-rw-r--r--sys/arch/pc532/To.Do40
-rw-r--r--sys/arch/pc532/compile/.keep_me3
-rw-r--r--sys/arch/pc532/conf/DEFAULT90
-rw-r--r--sys/arch/pc532/conf/INSTALL65
-rw-r--r--sys/arch/pc532/conf/KLONDIKE84
-rw-r--r--sys/arch/pc532/conf/Makefile.pc532159
-rw-r--r--sys/arch/pc532/conf/STEELHEAD85
-rw-r--r--sys/arch/pc532/conf/files.pc53280
-rw-r--r--sys/arch/pc532/dev/aic.c137
-rw-r--r--sys/arch/pc532/dev/device.h65
-rw-r--r--sys/arch/pc532/dev/dp.c1046
-rw-r--r--sys/arch/pc532/dev/dpreg.h128
-rw-r--r--sys/arch/pc532/dev/lpt.c876
-rw-r--r--sys/arch/pc532/dev/lptreg.h75
-rw-r--r--sys/arch/pc532/dev/ncr.c297
-rw-r--r--sys/arch/pc532/dev/ncr5380.c1907
-rw-r--r--sys/arch/pc532/dev/ncr5380reg.h258
-rw-r--r--sys/arch/pc532/dev/ncr_5380.h145
-rw-r--r--sys/arch/pc532/dev/ncr_defs.h57
-rw-r--r--sys/arch/pc532/dev/ncrreg.h62
-rw-r--r--sys/arch/pc532/dev/oldncr.c953
-rw-r--r--sys/arch/pc532/dev/rd.c173
-rw-r--r--sys/arch/pc532/dev/scn.c1119
-rw-r--r--sys/arch/pc532/dev/scnreg.h209
-rw-r--r--sys/arch/pc532/include/ansi.h74
-rw-r--r--sys/arch/pc532/include/asm.h116
-rw-r--r--sys/arch/pc532/include/cdefs.h35
-rw-r--r--sys/arch/pc532/include/cpu.h119
-rw-r--r--sys/arch/pc532/include/db_machdep.h131
-rw-r--r--sys/arch/pc532/include/disklabel.h46
-rw-r--r--sys/arch/pc532/include/endian.h127
-rw-r--r--sys/arch/pc532/include/exec.h50
-rw-r--r--sys/arch/pc532/include/float.h80
-rw-r--r--sys/arch/pc532/include/frame.h110
-rw-r--r--sys/arch/pc532/include/icu.h134
-rw-r--r--sys/arch/pc532/include/ieeefp.h19
-rw-r--r--sys/arch/pc532/include/jmpbuf.h53
-rw-r--r--sys/arch/pc532/include/limits.h84
-rw-r--r--sys/arch/pc532/include/mtpr.h3
-rw-r--r--sys/arch/pc532/include/param.h169
-rw-r--r--sys/arch/pc532/include/pcb.h98
-rw-r--r--sys/arch/pc532/include/pmap.h241
-rw-r--r--sys/arch/pc532/include/proc.h48
-rw-r--r--sys/arch/pc532/include/profile.h70
-rw-r--r--sys/arch/pc532/include/psl.h240
-rw-r--r--sys/arch/pc532/include/ptrace.h40
-rw-r--r--sys/arch/pc532/include/reg.h96
-rw-r--r--sys/arch/pc532/include/setjmp.h7
-rw-r--r--sys/arch/pc532/include/signal.h68
-rw-r--r--sys/arch/pc532/include/stdarg.h61
-rw-r--r--sys/arch/pc532/include/trap.h91
-rw-r--r--sys/arch/pc532/include/types.h74
-rw-r--r--sys/arch/pc532/include/varargs.h68
-rw-r--r--sys/arch/pc532/include/vmparam.h230
-rw-r--r--sys/arch/pc532/pc532/autoconf.c229
-rw-r--r--sys/arch/pc532/pc532/bcopy.s85
-rw-r--r--sys/arch/pc532/pc532/bzero.s99
-rw-r--r--sys/arch/pc532/pc532/clock.c253
-rw-r--r--sys/arch/pc532/pc532/conf.c223
-rw-r--r--sys/arch/pc532/pc532/db_disasm.c1899
-rw-r--r--sys/arch/pc532/pc532/db_interface.c436
-rw-r--r--sys/arch/pc532/pc532/db_trace.c681
-rw-r--r--sys/arch/pc532/pc532/disksubr.c241
-rw-r--r--sys/arch/pc532/pc532/genassym.c124
-rw-r--r--sys/arch/pc532/pc532/icuinit.c86
-rw-r--r--sys/arch/pc532/pc532/in_cksum.c173
-rw-r--r--sys/arch/pc532/pc532/intr.c229
-rw-r--r--sys/arch/pc532/pc532/locore.s1191
-rw-r--r--sys/arch/pc532/pc532/machdep.c1121
-rw-r--r--sys/arch/pc532/pc532/mem.c283
-rw-r--r--sys/arch/pc532/pc532/ns_cksum.c206
-rw-r--r--sys/arch/pc532/pc532/ntoh.s47
-rw-r--r--sys/arch/pc532/pc532/oc_cksum.s67
-rw-r--r--sys/arch/pc532/pc532/pmap.c1945
-rw-r--r--sys/arch/pc532/pc532/process_machdep.c179
-rw-r--r--sys/arch/pc532/pc532/random.s75
-rw-r--r--sys/arch/pc532/pc532/swapgeneric.c199
-rw-r--r--sys/arch/pc532/pc532/sys_machdep.c110
-rw-r--r--sys/arch/pc532/pc532/trap.c570
-rw-r--r--sys/arch/pc532/pc532/umprintf.c105
-rw-r--r--sys/arch/pc532/pc532/vm_machdep.c346
-rw-r--r--sys/arch/pc532/stand/Makefile98
-rw-r--r--sys/arch/pc532/stand/README26
-rw-r--r--sys/arch/pc532/stand/boot.c279
-rw-r--r--sys/arch/pc532/stand/conf.c59
-rw-r--r--sys/arch/pc532/stand/cons.c93
-rw-r--r--sys/arch/pc532/stand/devopen.c203
-rw-r--r--sys/arch/pc532/stand/filesystem.c40
-rw-r--r--sys/arch/pc532/stand/inflate.c1433
-rw-r--r--sys/arch/pc532/stand/machdep.c98
-rw-r--r--sys/arch/pc532/stand/prf.c79
-rw-r--r--sys/arch/pc532/stand/rd.c29
-rw-r--r--sys/arch/pc532/stand/samachdep.h42
-rw-r--r--sys/arch/pc532/stand/scn.c103
-rw-r--r--sys/arch/pc532/stand/scsi_hi.c303
-rw-r--r--sys/arch/pc532/stand/scsi_low.c426
-rw-r--r--sys/arch/pc532/stand/sd.c196
-rw-r--r--sys/arch/pc532/stand/so.h67
-rw-r--r--sys/arch/pc532/stand/srt0.s91
-rw-r--r--sys/arch/pc532/stand/test.c191
-rw-r--r--sys/arch/pc532/stand/tgets.c89
102 files changed, 26074 insertions, 0 deletions
diff --git a/sys/arch/pc532/Makefile b/sys/arch/pc532/Makefile
new file mode 100644
index 00000000000..56051070bd5
--- /dev/null
+++ b/sys/arch/pc532/Makefile
@@ -0,0 +1,32 @@
+# $NetBSD: Makefile,v 1.2 1994/10/26 08:23:50 cgd Exp $
+
+# @(#)Makefile 7.3 (Berkeley) 6/9/91
+
+COMM= ../net/*.[ch] ../netimp/*.[ch] ../netinet/*.[ch] ../netns/*.[ch] \
+ ../netiso/*.[ch] ../netccitt/*.[ch] \
+ ../kern/*.c ../ufs/*.[ch] ../nfs/*.[ch] ../vm/*.[ch] ../sys/*.h
+
+# Makefile for pc532 tags file
+
+SUBDIR= stand
+
+TPC532= ../pc532/tags
+SPC532= ../pc532/pc532/*.[ch] ../pc532/include/*.h \
+ ../pc532/dev/*.[ch] ../pc532/scsi/*.[ch]
+APC532= ../pc532/pc532/*.s
+
+# Directories in which to place pc532 tags links
+DPC532= dev include scsi
+
+tags:
+ -ctags -dtf ${TPC532} ${COMM} ${SPC532}
+ egrep "^ENTRY(.*)|^ALTENTRY(.*)" ${APC532} | \
+ sed "s;\([^:]*\):\([^(]*\)(\([^, )]*\)\(.*\);\3 \1 /^\2(\3\4$$/;" \
+ >> ${TPC532}
+ sort -o ${TPC532} ${TPC532}
+
+links:
+ -for i in ${DPC532}; do \
+ cd ../$$i && rm -f tags; ln -s ../tags tags; done
+
+.include <bsd.prog.mk>
diff --git a/sys/arch/pc532/To.Do b/sys/arch/pc532/To.Do
new file mode 100644
index 00000000000..88173f4628d
--- /dev/null
+++ b/sys/arch/pc532/To.Do
@@ -0,0 +1,40 @@
+$NetBSD: To.Do,v 1.4 1995/06/09 06:03:45 phil Exp $
+
+This is the "To Do" list for NetBSD/pc532
+ (Order is not in order of importance.)
+
+- improve scn driver (integrate mods from Phil Bunde)
+
+- get kernel debugger working
+
+- get the dp scsi driver working
+
+- write an aic scsi driver
+
+- improve copyin/out and friends
+
+- get gdb working (partially done)
+
+- ptrace syscall (?)
+
+- improve bim (detect a non-writeable disklabel, ...)
+
+- man4 man pages
+
+- man8 man pages
+
+- mods to better support ufs boot loader
+
+- integrate printer driver from matthias (partially done)
+
+- verify all devices including vn, tun, ...
+
+- integrate other machine independent "devices"
+
+- write a bim.8
+
+- find or write a "usable" comm package to replace kermit for
+ initial downloading.
+
+- find out why profiling does not accumulate any time
+
diff --git a/sys/arch/pc532/compile/.keep_me b/sys/arch/pc532/compile/.keep_me
new file mode 100644
index 00000000000..a3950d5c483
--- /dev/null
+++ b/sys/arch/pc532/compile/.keep_me
@@ -0,0 +1,3 @@
+$NetBSD: .keep_me,v 1.2 1994/10/26 08:23:53 cgd Exp $
+
+This normally empty directory needs to be kept in the distribution.
diff --git a/sys/arch/pc532/conf/DEFAULT b/sys/arch/pc532/conf/DEFAULT
new file mode 100644
index 00000000000..f25774619f9
--- /dev/null
+++ b/sys/arch/pc532/conf/DEFAULT
@@ -0,0 +1,90 @@
+#
+# DEFAULT: default install kernel
+# Only has scn0-5 are configured.
+# Instead of scn6/7 the lpt0/1 devices get into the kernel.
+#
+
+machine pc532
+
+maxusers 8 # estimated number of users
+options TIMEZONE=0, DST=0 # time zone to read RTC in
+options SWAPPAGER # paging
+options VNODEPAGER,DEVPAGER # vnode and device node caching
+
+#options DDB # kernel debugger; recommended
+#options DIAGNOSTIC # internal consistency checking
+options KTRACE # system call tracing, a la ktrace(1)
+
+#options ACCOUNTING # process accounting
+options FIFO # fifos; recommended
+#options SYSVSHM # System V shared memory; broken
+#options SHMMAXPGS=1024
+#options LKM # loadable kernel modules
+
+# compatibility options
+#options COMPAT_09 # NetBSD 0.9,
+#options COMPAT_10 # NetBSD 1.0,
+options COMPAT_43 # and 4.3BSD
+#options TCP_COMPAT_42 # TCP bug compatibility with 4.2BSD
+
+# file system options
+#options QUOTA # file system quotas
+options FFS # Berkeley fast file system
+#options LFS # log-structered file system
+options MFS # memory file system; uses RAM and swap
+options MSDOSFS # MS-DOS file system
+options CD9660 # ISO 9660 CD-ROM file system, with RR
+options NULLFS # loopback file system
+#options UMAPFS # NULLFS + uid and gid remapping
+options UNION # union file system
+#options PORTAL # /portal
+options FDESC # /dev/fd
+options KERNFS # /kern
+options PROCFS # /proc
+#options NFSSERVER # Network File System server
+options NFSCLIENT # Network File System client
+
+# networking options
+#options GATEWAY # packet forwarding
+options INET # IP + ICMP + TCP + UDP
+#options NS # XNS
+#options ISO,TPIP # OSI
+#options EON # OSI tunneling over IP
+#options CCITT,LLC,HDLC # X.25
+
+# pc532 specific options
+#options COMDEF_SPEED=B19200 # default baud on the scn chips
+options PLIP # PLIP driver in dev/lpt.c
+options DEV_RTC # RTC driver in pc532/mem.c
+options NO_INLINE_SPLX # don't inline splx calls
+
+config netbsd swap generic
+options GENERIC
+
+membus0 at root
+
+ncr0 at membus?
+
+scsibus0 at scsi?
+
+sd* at scsibus? target ? lun ? # SCSI disks
+st* at scsibus? target ? lun ? # SCSI tapes
+cd* at scsibus? target ? lun ? # SCSI CD-ROMs
+
+scn0 at membus?
+scn1 at membus?
+scn2 at membus?
+scn3 at membus?
+scn4 at membus?
+scn5 at membus?
+
+lpt0 at membus? addr 0xffc80030 irq 7
+lpt1 at membus? addr 0xffc80034 irq 6
+
+pseudo-device pty 16 # pseudo-terminals
+pseudo-device loop 1 # loopback network
+pseudo-device vnd 2 # vnode devices
+pseudo-device bpfilter 4 # packet filter
+pseudo-device sl 1 # compressed SLIP
+pseudo-device ppp 1 # Point-to-Point Protocol
+pseudo-device tun 1 # network tunneling
diff --git a/sys/arch/pc532/conf/INSTALL b/sys/arch/pc532/conf/INSTALL
new file mode 100644
index 00000000000..2ae8556d6c4
--- /dev/null
+++ b/sys/arch/pc532/conf/INSTALL
@@ -0,0 +1,65 @@
+# $NetBSD: INSTALL,v 1.3 1995/09/29 04:16:48 phil Exp $
+#
+# INSTALL -- install kernel
+#
+#
+
+# architecture type and name of kernel; REQUIRED
+machine "pc532"
+
+# time zone RTC is expected to be set in; REQUIRED
+options TIMEZONE=0, DST=0 # time zone to read RTC in
+options GENERIC
+
+# estimated number of users
+maxusers 2
+
+# paging of processes, and caching vnodes and devices; REQUIRED
+options SWAPPAGER
+options VNODEPAGER
+options DEVPAGER
+
+# networking options
+#options INET
+
+# generic SCSI system
+options SCSI
+
+# filesystems
+#options FIFO
+options MSDOSFS
+options FFS
+#options NFSCLIENT
+options CD9660
+
+# pc532 special options
+# options PLIP
+options NO_INLINE_SPLX
+
+config "netbsd" swap generic
+
+membus0 at root
+
+rd0 at membus?
+options RD_SIZE=0x200000
+
+ncr0 at membus?
+scsibus0 at scsi?
+
+sd* at scsibus? target ? lun ?
+st* at scsibus? target ? lun ?
+cd* at scsibus? target ? lun ?
+
+scn0 at membus?
+scn1 at membus?
+scn2 at membus?
+scn3 at membus?
+#scn4 at membus?
+#scn5 at membus?
+
+#lpt0 at membus? addr 0xffc80030 irq 7
+#lpt1 at membus? addr 0xffc80034 irq 6
+
+#pseudo-device loop 1 # loopback network
+#pseudo-device sl 1 # compressed SLIP
+#pseudo-device ppp 1 # Point-to-Point Protocol
diff --git a/sys/arch/pc532/conf/KLONDIKE b/sys/arch/pc532/conf/KLONDIKE
new file mode 100644
index 00000000000..4bbf1a1998d
--- /dev/null
+++ b/sys/arch/pc532/conf/KLONDIKE
@@ -0,0 +1,84 @@
+# $NetBSD: KLONDIKE,v 1.2 1995/09/26 20:16:01 phil Exp $
+#
+# KLONDIKE: Matthias Pfaller's pc532
+#
+
+machine pc532
+
+maxusers 8 # estimated number of users
+options TIMEZONE=0, DST=0 # time zone to read RTC in
+options SWAPPAGER # paging
+options VNODEPAGER,DEVPAGER # vnode and device node caching
+
+#options DDB # kernel debugger; recommended
+#options DIAGNOSTIC # internal consistency checking
+options KTRACE # system call tracing, a la ktrace(1)
+
+#options ACCOUNTING # process accounting
+options FIFO # fifos; recommended
+#options SYSVSHM # System V shared memory; broken
+#options SHMMAXPGS=1024
+#options LKM # loadable kernel modules
+
+# compatibility options
+options COMPAT_43 # 4.3 system calls
+
+# file system options
+#options QUOTA # file system quotas
+options FFS # Berkeley fast file system
+#options LFS # log-structered file system
+options MFS # memory file system; uses RAM and swap
+options MSDOSFS # MS-DOS file system
+options CD9660 # ISO 9660 CD-ROM file system, with RR
+options NULLFS # loopback file system
+#options UMAPFS # NULLFS + uid and gid remapping
+options UNION # union file system
+#options PORTAL # /portal
+#options FDESC # /dev/fd
+options KERNFS # /kern
+options PROCFS # /proc
+options NFSSERVER # Network File System server
+options NFSCLIENT # Network File System client
+
+# networking options
+#options GATEWAY # packet forwarding
+options INET # IP + ICMP + TCP + UDP
+#options NS # XNS
+#options ISO,TPIP # OSI
+#options EON # OSI tunneling over IP
+#options CCITT,LLC,HDLC # X.25
+
+# pc532 specific options
+options COMDEF_SPEED=B19200 # default baud on the scn chips
+options PLIP # PLIP driver in dev/lpt.c
+options DEV_RTC # RTC driver in pc532/mem.c
+
+config netbsd root on sd0a swap on sd0b and sd1b
+
+membus0 at root
+#clock0 at membus?
+#timer0 at membus?
+
+ncr0 at membus?
+
+scsibus0 at scsi?
+
+sd* at scsibus? target ? lun ? # SCSI disks
+st* at scsibus? target ? lun ? # SCSI tapes
+cd* at scsibus? target ? lun ? # SCSI CD-ROMs
+
+scn0 at membus?
+scn1 at membus?
+scn2 at membus?
+scn3 at membus?
+
+lpt0 at membus? addr 0xffc80030 irq 7
+lpt1 at membus? addr 0xffc80034 irq 6
+
+pseudo-device pty 16 # pseudo-terminals
+pseudo-device loop 1 # loopback network
+pseudo-device vnd 2 # vnode devices
+#pseudo-device bpfilter 4 # packet filter
+#pseudo-device sl 1 # compressed SLIP
+#pseudo-device ppp 1 # Point-to-Point Protocol
+#pseudo-device tun 1 # ip tunneling
diff --git a/sys/arch/pc532/conf/Makefile.pc532 b/sys/arch/pc532/conf/Makefile.pc532
new file mode 100644
index 00000000000..a1fd431b9bd
--- /dev/null
+++ b/sys/arch/pc532/conf/Makefile.pc532
@@ -0,0 +1,159 @@
+# $NetBSD: Makefile.pc532,v 1.14 1995/09/19 23:51:40 thorpej Exp $
+
+# Copyright 1990 W. Jolitz
+# @(#)Makefile.i386 7.1 5/10/91
+#
+# Makefile for NetBSD/532
+#
+# Edited by Philip A. Nelson
+#
+# This makefile is constructed from a machine description:
+# config machineid
+# Most changes should be made in the machine description
+# /sys/arch/pc532/conf/``machineid''
+# after which you should do
+# config machineid
+# Generic makefile changes should be made in
+# /sys/arch/pc532/conf/Makefile.pc532
+# after which config should be rerun for all machines.
+#
+# N.B.: NO DEPENDENCIES ON FOLLOWING FLAGS ARE INVISIBLE 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
+#
+
+TOUCH= touch -f -c
+AS= as
+LD= ld
+CC= cc
+CPP= cpp
+AWK= awk
+
+S= ../../../..
+PC532= ../..
+
+.s.o:; (${CPP} ${COPTS} ${PC532}/pc532/$*.s | ${AS} ${ASFLAGS} -o $*.o)
+
+INCLUDES= -I. -I$S -I$S/sys -I${PC532}
+COPTS= ${INCLUDES} ${IDENT} -D_KERNEL
+ASFLAGS=
+CFLAGS= -O -Werror -fno-builtin -msb ${COPTS}
+
+### find out what to use for libkern
+.include "$S/lib/libkern/Makefile.inc"
+.ifndef PROF
+LIBKERN= ${KERNLIB}
+.else
+LIBKERN= ${KERNLIB_PROF}
+.endif
+
+### find out what to use for libcompat
+.include "$S/compat/common/Makefile.inc"
+.ifndef PROF
+LIBCOMPAT= ${COMPATLIB}
+.else
+LIBCOMPAT= ${COMPATLIB_PROF}
+.endif
+
+NORMAL_S= (${CPP} ${COPTS} ${PROF} $< | ${AS} ${ASFLAGS} -o $*.o)
+NORMAL_C= ${CC} -c ${CFLAGS} ${PROF} $<
+NORMAL_C_C= ${CC} -c ${CFLAGS} ${PROF} ${PARAM} $<
+DRIVER_C= ${CC} -c ${CFLAGS} ${PROF} $<
+DRIVER_C_C= ${CC} -c ${CFLAGS} ${PROF} ${PARAM} $<
+SYSTEM_OBJS=locore.o ${OBJS} param.o ioconf.o conf.o vnode_if.o ${LIBKERN} \
+ ${LIBCOMPAT}
+SYSTEM_DEP=Makefile ${SYSTEM_OBJS}
+SYSTEM_LD_HEAD= @echo loading $@; rm -f $@
+SYSTEM_LD= @${LD} -z -T FE002000 -o $@ -X vers.o ${SYSTEM_OBJS}
+SYSTEM_LD_TAIL= size $@ ; nm -n $@ > SYMMS ; chmod 755 $@
+
+%OBJS
+
+%CFILES
+
+%LOAD
+
+clean::
+ rm -f eddep *netbsd tags *.o locore.i [a-uw-z]*.s \
+ errs linterrs makelinks genassym
+
+#lint: /tmp param.c
+# @lint -hbxn -I. -DGENERIC -Dvolatile= ${COPTS} ${PARAM} \
+# ${I386}/i386/Locore.c ${CFILES} ioconf.c param.c | \
+# grep -v 'struct/union .* never defined' | \
+# grep -v 'possible pointer alignment problem'
+
+locore.o: assym.h ${PC532}/pc532/locore.s \
+ ${PC532}/pc532/bcopy.s ${PC532}/pc532/bzero.s
+
+# the following is necessary because autoconf.o depends on #if GENERIC
+autoconf.o: Makefile
+
+# depend on network configuration
+af.o uipc_proto.o locore.o: Makefile
+
+# depend on maxusers
+assym.s machdep.o: Makefile
+
+# depends on KDB (cons.o also depends on GENERIC)
+trap.o cons.o: Makefile
+
+assym.s: $S/sys/param.h machine/pte.h $S/sys/buf.h \
+ $S/sys/vmmeter.h \
+ $S/sys/proc.h $S/sys/msgbuf.h machine/vmparam.h
+
+assym.h: genassym
+ ./genassym >assym.h
+
+genassym: ${PC532}/pc532/genassym.c
+ ${CC} -static ${INCLUDES} -D_KERNEL ${IDENT} ${PARAM} \
+ ${PC532}/pc532/genassym.c -o genassym
+
+depend: assym.h param.c vnode_if.h
+ sh /usr/bin/mkdep ${COPTS} ${CFILES} ioconf.c
+ sh /usr/bin/mkdep -a -p ${INCLUDES} ${IDENT} ${PARAM} ${PC532}/pc532/genassym.c
+
+links:
+ egrep '#if' ${CFILES} | sed -f $S/conf/defines | \
+ sed -e 's/:.*//' -e 's/\.c/.o/' | sort -u > dontlink
+ echo ${CFILES} | tr -s ' ' '\12' | sed 's/\.c/.o/' | \
+ sort -u | comm -23 - dontlink | \
+ sed 's,../.*/\(.*.o\),rm -f \1;ln -s ../GENERIC/\1 \1,' > makelinks
+ sh makelinks && rm -f dontlink
+
+tags:
+ @echo "see $S/kern/Makefile for tags"
+
+ioconf.o: ioconf.c $S/sys/param.h $S/sys/buf.h \
+ ${PC532}/dev/device.h machine/icu.h
+ ${CC} -c ${CFLAGS} ioconf.c
+
+conf.o: $S/sys/param.h $S/sys/systm.h $S/sys/buf.h $S/sys/ioctl.h \
+ $S/sys/tty.h $S/sys/conf.h ${PC532}/pc532/conf.c
+ ${CC} -traditional -c ${CFLAGS} ${PC532}/pc532/conf.c
+
+param.c: $S/conf/param.c
+ -rm -f param.c
+ cp $S/conf/param.c .
+
+param.o: param.c Makefile
+ ${CC} -c ${CFLAGS} ${PARAM} param.c
+
+vers.o: ${SYSTEM_DEP} ${SYSTEM_SWAP_DEP}
+ sh $S/conf/newvers.sh
+ ${CC} ${CFLAGS} -c vers.c
+
+# for config.new
+newvers:
+ sh $S/conf/newvers.sh
+ ${CC} ${CFLAGS} -c vers.c
+
+# This allows you to specify which "awk" you will run, i.e.:
+# make AWK=nawk ...
+vnode_if.c vnode_if.h : $S/kern/vnode_if.sh $S/kern/vnode_if.src
+ AWK=${AWK} sh $S/kern/vnode_if.sh $S/kern/vnode_if.src
+
+%RULES
+
diff --git a/sys/arch/pc532/conf/STEELHEAD b/sys/arch/pc532/conf/STEELHEAD
new file mode 100644
index 00000000000..076615e0393
--- /dev/null
+++ b/sys/arch/pc532/conf/STEELHEAD
@@ -0,0 +1,85 @@
+# $NetBSD: STEELHEAD,v 1.9 1995/09/26 20:16:02 phil Exp $
+#
+# STEELHEAD: Phil Nelson's pc532
+#
+machine "pc532"
+
+maxusers 10 # estimated number of users
+options TIMEZONE=0, DST=0 # time zone to read RTC in
+options SWAPPAGER # paging
+options VNODEPAGER,DEVPAGER # vnode and device node caching
+#options DDB # kernel debugger; not working
+#options DIAGNOSTIC # internal consistency checking
+
+#options ACCOUNTING # process accounting
+options KTRACE # system call tracing, a la ktrace(1)
+options FIFO # fifos; recommended
+#options SYSVSHM # System V shared memory; broken
+#options "SHMMAXPGS=1024"
+#options LKM # loadable kernel modules
+
+# compatibility options
+options "COMPAT_43" # 4.3 system calls
+options "TCP_COMPAT_42" # 4.2 networking ABI
+options "COMPAT_09" # NetBSD-0.9
+options "COMPAT_10" # NetBSD-1.0
+
+# file system options
+#options QUOTA # file system quotas
+options FFS # Berkeley fast file system
+#options FASTLINKS # fast symbolic links in FFS
+#options MFS # memory file system; uses RAM and swap
+options NFSSERVER # Network File System server
+options NFSCLIENT # Network File System client
+#options ISOFS # ISO 9660 CD-ROM file system, with RR
+#options MSDOSFS # MS-DOS FAT file system
+options FDESC # /dev/fd
+options KERNFS # kernel file system; recommended
+
+# networking options
+#options GATEWAY # packet forwarding
+options INET # IP
+#options NS # XNS
+#options CCITT # X.25
+#options ISO # OSI
+#options TPIP # ?
+#options EON # ?
+
+# pc532 specific options
+options "COMDEF_SPEED=B19200" # default baud on the scn chips
+#options "RAMD_SIZE=1536000" # Size of the "boot strap ram disk"
+#options "RAMD_ADR=0x400000" # Adr of the "boot strap ram disk"
+options "CONFIG_NEW" # Use config.new stuff
+options "DEV_RTC" # /dev/rtc access to hardware clock
+options "CON_BRK_PANIC" # 3 breaks on tty0 -> panic? y/n
+
+config "netbsd" root on sd0 swap on sd0 and sd1 and vnd0a
+
+membus0 at root
+
+#rd0 at membus?
+
+ncr0 at membus?
+
+scsibus0 at scsi?
+
+sd* at scsibus? target ? lun ? # SCSI disks
+st* at scsibus? target ? lun ? # SCSI tapes
+#cd* at scsibus? target ? lun ? # SCSI ???
+
+scn0 at membus?
+scn1 at membus?
+scn2 at membus?
+scn3 at membus?
+scn4 at membus?
+scn5 at membus?
+scn6 at membus?
+scn7 at membus?
+
+pseudo-device pty 16 # pseudo-terminals
+pseudo-device loop 1 # loopback network
+pseudo-device bpfilter 4 # packet filter
+pseudo-device sl 1 # compressed SLIP
+pseudo-device ppp 1 # Point-to-Point Protocol
+pseudo-device vnd 4 # Vnode devices
+#pseudo-device ether #
diff --git a/sys/arch/pc532/conf/files.pc532 b/sys/arch/pc532/conf/files.pc532
new file mode 100644
index 00000000000..06d6a76db93
--- /dev/null
+++ b/sys/arch/pc532/conf/files.pc532
@@ -0,0 +1,80 @@
+# $NetBSD: files.pc532,v 1.15.2.1 1995/10/17 00:18:56 phil Exp $
+#
+# new style config file for pc532 architecture
+#
+
+# maxpartitions must be first item in files.${ARCH}.newconf
+maxpartitions 8
+
+maxusers 2 16 64
+
+device membus at root {[addr = -1], [irq = -1]}
+
+major {vnd = 5}
+
+device rd at membus: disk
+file arch/pc532/dev/rd.c rd needs-count
+major {rd = 3}
+
+#device timer at membus
+#device clock at membus
+file arch/pc532/pc532/clock.c # clock timer
+
+device scn at membus: tty
+file arch/pc532/dev/scn.c scn needs-flag
+
+device lpt at membus: ether, ifnet
+file arch/pc532/dev/lpt.c lpt needs-count
+
+define scsi {}
+
+device ncr at membus: scsi
+file arch/pc532/dev/ncr.c ncr needs-count
+device oldncr at membus: scsi
+file arch/pc532/dev/oldncr.c oldncr needs-count
+device dp at membus: scsi
+file arch/pc532/dev/dp.c dp needs-count
+device aic at membus: scsi
+file arch/pc532/dev/aic.c aic needs-count
+
+device scsibus at scsi {target = -1, lun = -1}
+
+device cd at scsibus: disk
+file scsi/cd.c cd needs-flag
+major {cd = 4}
+device sd at scsibus: disk
+file scsi/sd.c sd needs-flag
+major {sd = 0}
+device st at scsibus: tape
+file scsi/st.c st needs-flag
+major {st = 2}
+device ch at scsibus: disk
+file scsi/ch.c ch needs-flag
+device uk at scsibus: disk
+file scsi/uk.c uk needs-flag
+device su at scsibus: disk
+file scsi/su.c su needs-flag
+
+file dev/cons.c
+file dev/cninit.c
+file scsi/scsiconf.c scsi
+file scsi/scsi_base.c scsi
+file scsi/scsi_ioctl.c scsi
+file arch/pc532/pc532/autoconf.c
+file arch/pc532/pc532/db_disasm.c ddb
+file arch/pc532/pc532/db_interface.c ddb
+file arch/pc532/pc532/db_trace.c ddb
+file arch/pc532/pc532/disksubr.c disk
+file arch/pc532/pc532/icuinit.c
+file arch/pc532/pc532/in_cksum.c inet
+file arch/pc532/pc532/intr.c
+file arch/pc532/pc532/machdep.c
+file arch/pc532/pc532/mem.c
+file arch/pc532/pc532/ns_cksum.c ns
+#file arch/pc532/pc532/ntoh.s
+file arch/pc532/pc532/pmap.c
+file arch/pc532/pc532/process_machdep.c
+file arch/pc532/pc532/random.s
+file arch/pc532/pc532/sys_machdep.c
+file arch/pc532/pc532/trap.c
+file arch/pc532/pc532/vm_machdep.c
diff --git a/sys/arch/pc532/dev/aic.c b/sys/arch/pc532/dev/aic.c
new file mode 100644
index 00000000000..f0c3e022f38
--- /dev/null
+++ b/sys/arch/pc532/dev/aic.c
@@ -0,0 +1,137 @@
+/* $NetBSD: aic.c,v 1.4 1995/08/12 20:31:10 mycroft Exp $ */
+
+/* Written by Phil Nelson for the pc532. Used source with the following
+ * copyrights as a model.
+ *
+ * aic.c: A Adaptec 6250 driver for the pc532.
+ */
+/*
+ * (Mostly) Written by Julian Elischer (julian@tfs.com)
+ * for TRW Financial Systems for use under the MACH(2.5) operating system.
+ *
+ * TRW Financial Systems, in accordance with their agreement with Carnegie
+ * Mellon University, makes this software available to CMU to distribute
+ * or use in any manner that they see fit as long as this message is kept with
+ * the software. For this reason TFS also grants any other persons or
+ * organisations permission to use or modify this software.
+ *
+ * TFS supplies this software to be publicly redistributed
+ * on the understanding that TFS is not responsible for the correct
+ * functioning of this software in any circumstances.
+ */
+
+/*
+ * a FEW lines in this driver come from a MACH adaptec-disk driver
+ * so the copyright below is included:
+ *
+ * Copyright 1990 by Open Software Foundation,
+ * Grenoble, FRANCE
+ *
+ * All Rights Reserved
+ *
+ * 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 and
+ * that both the copyright notice and this permission notice appear in
+ * supporting documentation, and that the name of OSF or Open Software
+ * Foundation not be used in advertising or publicity pertaining to
+ * distribution of the software without specific, written prior
+ * permission.
+ *
+ * OSF DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS,
+ * IN NO EVENT SHALL OSF BE LIABLE FOR ANY SPECIAL, INDIRECT, OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT,
+ * NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
+ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ */
+
+#include "sys/types.h"
+#include "sys/param.h"
+#include "sys/systm.h"
+#include "sys/errno.h"
+#include "sys/ioctl.h"
+#include "sys/buf.h"
+#include "machine/stdarg.h"
+#include "sys/proc.h"
+#include "sys/user.h"
+#include "sys/dkbad.h"
+#include "sys/disklabel.h"
+#include "scsi/scsi_all.h"
+#include "scsi/scsiconf.h"
+
+#include "device.h"
+
+/* Some constants (may need to be changed!) */
+#define AIC_NSEG 16
+
+int aicprobe(struct pc532_device *);
+int aicattach(struct pc532_device *);
+int aic_scsi_cmd(struct scsi_xfer *);
+void aicminphys(struct buf *);
+long int aic_adapter_info(int);
+
+struct scsidevs *
+scsi_probe(int masunit, struct scsi_switch *sw, int physid, int type, int want);
+
+struct pc532_driver aicdriver = {
+ aicprobe, aicattach, "aic",
+};
+
+struct scsi_switch dp_switch = {
+ "aic",
+ aic_scsi_cmd,
+ aicminphys,
+ 0,
+ 0,
+ aic_adapter_info,
+ 0, 0, 0
+};
+
+int aicprobe(struct pc532_device *dvp)
+{
+ return (0); /* All pc532s should have one, but it is not working now. */
+}
+
+
+int aicattach(struct pc532_device *dvp)
+{
+ int r;
+
+ r = scsi_attach(0, 7, &dp_switch,
+ &dvp->pd_drive, &dvp->pd_unit, dvp->pd_flags);
+
+ return(r);
+}
+
+void aicminphys(struct buf *bp)
+{
+
+ if(bp->b_bcount > ((AIC_NSEG - 1) * NBPG))
+ bp->b_bcount = ((AIC_NSEG - 1) * NBPG);
+ minphys(bp);
+}
+
+long int aic_adapter_info(int unit)
+{
+ return (1); /* only 1 outstanding request. */
+}
+
+
+/* Do a scsi command. */
+
+struct scsi_xfer *cur_xs;
+
+int aic_scsi_cmd(struct scsi_xfer *xs)
+{
+printf ("aic_scsi_cmd: ... \n");
+ cur_xs = xs;
+
+ return (HAD_ERROR);
+}
+
+void aic_intr (struct intrframe frame)
+{
+}
diff --git a/sys/arch/pc532/dev/device.h b/sys/arch/pc532/dev/device.h
new file mode 100644
index 00000000000..ed5aba7f4a0
--- /dev/null
+++ b/sys/arch/pc532/dev/device.h
@@ -0,0 +1,65 @@
+/* $NetBSD: device.h,v 1.2 1994/10/26 08:24:09 cgd Exp $ */
+
+/*-
+ * Copyright (c) 1991 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)isa_device.h 7.1 (Berkeley) 5/9/91
+ */
+
+/*
+ * Per device structure.
+ */
+struct pc532_device {
+ struct pc532_driver *pd_driver;
+ char *pd_name; /* device name */
+ int pd_unit; /* unit number */
+ int pd_drive; /* drive number */
+ int pd_flags; /* flags needed */
+ int pd_alive; /* device is present */
+};
+
+/*
+ * Per-driver structure.
+ *
+ * Each device driver defines entries for a set of routines
+ * as well as an array of types which are acceptable to it.
+ * These are used at boot time by the configuration program.
+ */
+struct pc532_driver {
+ int (*probe)(); /* test whether device is present */
+ int (*attach)(); /* setup driver for a device */
+ char *name; /* device name */
+};
+
+extern struct pc532_device pc532_devtab_bio[], pc532_devtab_tty[],
+ pc532_devtab_net[];
+
diff --git a/sys/arch/pc532/dev/dp.c b/sys/arch/pc532/dev/dp.c
new file mode 100644
index 00000000000..17bc9979ef0
--- /dev/null
+++ b/sys/arch/pc532/dev/dp.c
@@ -0,0 +1,1046 @@
+/* $NetBSD: dp.c,v 1.8 1995/08/12 20:31:11 mycroft Exp $ */
+
+/* Written by Phil Nelson for the pc532. Used source with the following
+ * copyrights as a model.
+ *
+ * dp.c: A NCR DP8490 driver for the pc532.
+ */
+
+/*
+ * (Mostly) Written by Julian Elischer (julian@tfs.com)
+ * for TRW Financial Systems for use under the MACH(2.5) operating system.
+ *
+ * TRW Financial Systems, in accordance with their agreement with Carnegie
+ * Mellon University, makes this software available to CMU to distribute
+ * or use in any manner that they see fit as long as this message is kept with
+ * the software. For this reason TFS also grants any other persons or
+ * organisations permission to use or modify this software.
+ *
+ * TFS supplies this software to be publicly redistributed
+ * on the understanding that TFS is not responsible for the correct
+ * functioning of this software in any circumstances.
+ *
+ */
+
+/*
+ * a FEW lines in this driver come from a MACH adaptec-disk driver
+ * so the copyright below is included:
+ *
+ * Copyright 1990 by Open Software Foundation,
+ * Grenoble, FRANCE
+ *
+ * All Rights Reserved
+ *
+ * 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 and
+ * that both the copyright notice and this permission notice appear in
+ * supporting documentation, and that the name of OSF or Open Software
+ * Foundation not be used in advertising or publicity pertaining to
+ * distribution of the software without specific, written prior
+ * permission.
+ *
+ * OSF DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS,
+ * IN NO EVENT SHALL OSF BE LIABLE FOR ANY SPECIAL, INDIRECT, OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT,
+ * NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
+ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/errno.h>
+#include <sys/ioctl.h>
+#include <sys/buf.h>
+#include <machine/stdarg.h>
+#include <sys/proc.h>
+#include <sys/user.h>
+#include <sys/dkbad.h>
+#include <sys/disklabel.h>
+#include <scsi/scsi_all.h>
+#include <scsi/scsiconf.h>
+
+#include <machine/frame.h>
+#include <machine/icu.h>
+
+#include "device.h"
+#include "dpreg.h"
+
+#define DP_DEBUG 0
+
+/* Some constants (may need to be changed!) */
+#define DP_NSEG 16
+
+int dpprobe(struct pc532_device *);
+int dpattach(struct pc532_device *);
+int dp_scsi_cmd(struct scsi_xfer *);
+void dpminphys(struct buf *);
+long int dp_adapter_info(int);
+void dp_intr(void);
+void dp_intr_work(void);
+
+struct scsidevs *
+scsi_probe(int masunit, struct scsi_switch *sw, int physid, int type, int want);
+
+struct pc532_driver dpdriver = {
+ dpprobe, dpattach, "dp",
+};
+
+struct scsi_switch dp_switch = {
+ "dp",
+ dp_scsi_cmd,
+ dpminphys,
+ 0,
+ 0,
+ dp_adapter_info,
+ 0, 0, 0
+};
+
+/* Sense command. */
+static u_char sense_cmd[] = { 3, 0, 0, 0, 0, 0};
+
+/* Do we need to initialize. */
+int dp_needs_init = 1;
+
+/* Do we need a reset . */
+int dp_needs_reset = 1;
+
+/* SCSI phase we are currently in . . . */
+int dp_scsi_phase;
+
+/* SCSI Driver state */
+int dp_dvr_state = DP_DVR_READY;
+
+/* For polled error reporting. */
+int dp_intr_retval;
+
+/* For counting the retries. */
+int dp_try_count;
+
+/* Give the interrupt routine access to the current scsi_xfer info block. */
+struct scsi_xfer *cur_xs = NULL;
+
+/* names of phases for debug printouts */
+const char *dp_phase_names[] = {
+ "DATA OUT",
+ "DATA IN",
+ "CMD",
+ "STATUS",
+ "PHASE 4",
+ "PHASE 5",
+ "MSG OUT",
+ "MSG IN",
+};
+
+/* Initial probe for a device. If it is using the dp controller,
+ just say yes so that attach can be the one to find the real drive. */
+
+int dpprobe(struct pc532_device *dvp)
+{
+ /* If we call this, we need to add SPL_DP to the bio mask! */
+ PL_bio |= SPL_DP;
+ PL_zero |= PL_bio;
+
+ if (dp_needs_init)
+ dp_initialize();
+
+ if (dp_needs_reset)
+ dp_reset();
+
+ /* All pc532s should have one, so we don't check ! :) */
+ return (1);
+}
+
+
+int dpattach(struct pc532_device *dvp)
+{
+ int r;
+
+ r = scsi_attach(0, 7, &dp_switch,
+ &dvp->pd_drive, &dvp->pd_unit, dvp->pd_flags);
+
+ return(r);
+}
+
+void dpminphys(struct buf *bp)
+{
+
+ if(bp->b_bcount > ((DP_NSEG - 1) * NBPG))
+ bp->b_bcount = ((DP_NSEG - 1) * NBPG);
+ minphys(bp);
+}
+
+long int dp_adapter_info(int unit)
+{
+ return (1); /* only 1 outstanding request. */
+}
+
+#if DP_DEBUG
+void
+dp_print_stat1(u_char stat1)
+{
+ printf("stat1=");
+ if ( stat1 & 0x80 ) printf(" /RST");
+ if ( stat1 & 0x40 ) printf(" /BSY");
+ if ( stat1 & 0x20 ) printf(" /REQ");
+ if ( stat1 & 0x10 ) printf(" /MSG");
+ if ( stat1 & 0x08 ) printf(" /CD");
+ if ( stat1 & 0x04 ) printf(" /IO");
+ if ( stat1 & 0x02 ) printf(" /SEL");
+ if ( stat1 & 0x01 ) printf(" /DBP");
+ printf("\n");
+}
+
+void
+dp_print_stat2(u_char stat2)
+{
+ printf("stat2=");
+ if ( stat2 & 0x80 ) printf(" EDMA");
+ if ( stat2 & 0x40 ) printf(" DRQ");
+ if ( stat2 & 0x20 ) printf(" SPER");
+ if ( stat2 & 0x10 ) printf(" INT");
+ if ( stat2 & 0x08 ) printf(" PHSM");
+ if ( stat2 & 0x04 ) printf(" BSY");
+ if ( stat2 & 0x02 ) printf(" /ATN");
+ if ( stat2 & 0x01 ) printf(" /ACK");
+ printf("\n");
+}
+#endif
+
+#if DP_DEBUG
+void
+dp_print_regs()
+{
+ u_char stat1 = RD_ADR(u_char, DP_STAT1);
+ u_char stat2 = RD_ADR(u_char, DP_STAT2);
+ dp_print_stat1(stat1);
+ dp_print_stat2(stat2);
+}
+#endif
+
+/* Do a scsi command. */
+
+int dp_scsi_cmd(struct scsi_xfer *xs)
+{
+ struct iovec *iovp;
+ int flags;
+ int retval; /* Return values from functions. */
+ int x; /* for splbio() & splhigh() */
+ int dvr_state;
+ int ti_val; /* For timeouts. */
+
+#if DP_DEBUG
+ printf("\n");
+#endif
+ x = splhigh();
+ if (dp_dvr_state == DP_DVR_READY)
+ dp_dvr_state = DP_DVR_STARTED;
+ dvr_state = dp_dvr_state;
+ splx(x);
+
+ if (dvr_state != DP_DVR_STARTED)
+ return (TRY_AGAIN_LATER);
+
+ cur_xs = xs;
+
+ /* Some initial checks. */
+ flags = xs->flags;
+ if (!(flags & INUSE)) {
+#if DP_DEBUG
+ printf("dp xs not in use!\n");
+#endif
+ xs->flags |= INUSE;
+ }
+ if (flags & ITSDONE) {
+#if DP_DEBUG
+ printf("dp xs already done!\n");
+#endif
+ xs->flags &= ~ITSDONE;
+ }
+ if (dp_needs_reset || (xs->flags & SCSI_RESET))
+ dp_reset();
+#if DP_DEBUG
+ printf ("scsi_cmd: flags=0x%x, targ=%d, lu=%d, cmdlen=%d, cmd=%x\n",
+ xs->flags, xs->targ, xs->lu, xs->cmdlen, xs->cmd->opcode);
+#endif
+#if 1
+ /* we don't always get NOMASK passed in, so this hack fakes it. */
+ {
+ if ( !initproc )
+ xs->flags |= SCSI_NOMASK;
+ }
+#endif
+ if (!(xs->flags & SCSI_NOMASK)) {
+ x = splbio();
+ retval = dp_start_cmd(xs);
+ splx(x);
+ return retval;
+ }
+ /* No interrupts available! */
+ retval = dp_start_cmd(xs);
+ if (retval != SUCCESSFULLY_QUEUED)
+ return retval;
+#if DP_DEBUG > 1
+ printf("polling for interrupts\n");
+#endif
+ ti_val = WAIT_MUL * xs->timeout;
+ while (dp_dvr_state != DP_DVR_READY) {
+ if (RD_ADR(u_char, DP_STAT2) & DP_S_IRQ) {
+ dp_intr_work();
+ ti_val = WAIT_MUL * xs->timeout;
+ retval = dp_intr_retval;
+ }
+ if (--ti_val == 0) {
+ /* Software Timeout! */
+ xs->error = XS_SWTIMEOUT;
+ dp_dvr_state = DP_DVR_READY;
+ retval = HAD_ERROR;
+ }
+ }
+ if (xs->error == XS_SWTIMEOUT) {
+ /* Software Timeout! */
+ printf ("scsi timeout!\n");
+#if DP_DEBUG
+ dp_print_regs();
+ printf("TCMD = 0x%x\n", RD_ADR(u_char, DP_TCMD));
+#endif
+ dp_reset();
+ }
+#if 1
+ /* another hack: read cannot handle anything but SUCCESSFULLY_QUEUED */
+ if (xs->cmd->opcode == 0x28)
+ return SUCCESSFULLY_QUEUED;
+#endif
+ return retval;
+}
+
+/*===========================================================================*
+ * dp_intr *
+ *===========================================================================*/
+
+/* This is where a lot of the work happens! This is called in non-interrupt
+ mode when an interrupt would have happened. It is also the real interrupt
+ routine. It uses dp_dvr_state to determine the next actions along with
+ cur_xs->flags. */
+
+void dp_intr(void)
+{
+ int x = splhigh();
+#if DP_DEBUG
+ printf("\n REAL dp_intr\n");
+#endif
+ dp_intr_work();
+ splx(x);
+}
+
+void dp_intr_work(void)
+{
+ u_char isr;
+ u_char new_phase;
+ u_char stat1;
+ u_char stat2;
+ static u_char status;
+ static u_char message;
+ int ret;
+
+ scsi_select_ctlr (DP8490);
+ WR_ADR(u_char, DP_EMR_ISR, DP_EF_ISR_NEXT);
+ isr = RD_ADR (u_char, DP_EMR_ISR);
+ dp_clear_isr();
+
+ stat1 = RD_ADR(u_char, DP_STAT1);
+ new_phase = (stat1 >> 2) & 7;
+
+#if DP_DEBUG
+ printf ("dp_intr: dvr_state %d isr=0x%x new_phase = %d %s\n",
+ dp_dvr_state, isr, new_phase, dp_phase_names[new_phase]);
+#if DP_DEBUG > 1
+ dp_print_regs();
+#endif
+#endif
+#if 0
+ /* de-assert the bus */
+ WR_ADR(u_char, DP_ICMD, DP_EMODE);
+ /* disable dma */
+ RD_ADR(u_char, DP_MODE) &= ~DP_M_DMA;
+#endif
+ if (isr & DP_ISR_BSYERR) {
+#if DP_DEBUG
+ printf("dp_intr: Busy error\n");
+#endif
+ }
+ if (isr & DP_ISR_EDMA) {
+#if DP_DEBUG > 1
+ printf("dp_intr: EDMA detected\n");
+#endif
+ RD_ADR(u_char, DP_MODE) &= ~DP_M_DMA;
+ WR_ADR(u_char, DP_ICMD, DP_EMODE);
+ }
+ if (!(isr & DP_ISR_APHS)) {
+#if DP_DEBUG > 1
+ printf("dp_intr: Not an APHS!\n");
+ printf("dp_intr: dvr_state %d isr=0x%x (exit)\n",
+ dp_dvr_state, isr);
+#endif
+ return;
+ }
+
+ switch (dp_dvr_state) {
+ case DP_DVR_ARB: /* Next comes the command phase! */
+ if (new_phase != DP_PHASE_CMD) {
+#if DP_DEBUG
+ printf ("Phase mismatch cmd!\n");
+#endif
+ goto phase_mismatch;
+ }
+ dp_dvr_state = DP_DVR_CMD;
+ ret = dp_pdma_out(cur_xs->cmd, cur_xs->cmdlen, DP_PHASE_CMD);
+ dp_clear_isr();
+ break;
+
+ case DP_DVR_CMD: /* Next comes the data i/o phase if needed. */
+ /*
+ * This state can potentially accept data in, data out,
+ * or status for new_phase. data in or data out could
+ * be skipped (new_phase is status) if an error was detected
+ * in the command.
+ */
+ if (cur_xs->flags & SCSI_DATA_UIO) {
+ /* UIO work. */
+ panic ("scsi uio");
+ }
+ if (new_phase == DP_PHASE_DATAI) {
+#if 1
+ /* just a quick hack until we
+ can trust flags to be correct
+ */
+ if (!cur_xs->data) {
+#else
+ if (!(cur_xs->flags & SCSI_DATA_IN)) {
+#endif
+#if DP_DEBUG
+ printf("Phase mismatch in.\n");
+#endif
+ goto phase_mismatch;
+ }
+ /* expect STAT phase next */
+ dp_dvr_state = DP_DVR_DATA;
+ ret = dp_pdma_in(cur_xs->data, cur_xs->datalen,
+ DP_PHASE_DATAI);
+ dp_clear_isr();
+ break;
+ }
+ else if (new_phase == DP_PHASE_DATAO) {
+#if 1
+ /* just a quick hack until we
+ can trust flags to be correct
+ */
+ if (!cur_xs->data) {
+#else
+ if (!(cur_xs->flags & SCSI_DATA_OUT)) {
+#endif
+#if DP_DEBUG
+ printf("Phase mismatch out.\n");
+#endif
+ goto phase_mismatch;
+ }
+ /* expect STAT phase next */
+ dp_dvr_state = DP_DVR_DATA;
+ ret = dp_pdma_out(cur_xs->data, cur_xs->datalen,
+ DP_PHASE_DATAO);
+ dp_clear_isr();
+ break;
+ }
+ /* Fall through to next phase. */
+ case DP_DVR_DATA: /* Next comes the stat phase */
+ if (new_phase != DP_PHASE_STATUS) {
+#if DP_DEBUG
+ printf("Phase mismatch stat.\n");
+#endif
+ goto phase_mismatch;
+ }
+ dp_dvr_state = DP_DVR_STAT;
+ dp_pdma_in(&status, 1, DP_PHASE_STATUS);
+ dp_clear_isr();
+#if DP_DEBUG > 1
+ printf("status = 0x%x\n", status);
+#endif
+ break;
+
+ case DP_DVR_STAT:
+ if (new_phase != DP_PHASE_MSGI) {
+#if DP_DEBUG
+ printf ("msgi phase mismatch\n");
+#endif
+ goto phase_mismatch;
+ }
+ dp_dvr_state = DP_DVR_MSGI;
+ dp_pdma_in(&message, 1, DP_PHASE_MSGI);
+ dp_clear_isr();
+#if DP_DEBUG > 1
+ printf("message = 0x%x\n", message);
+#endif
+#if 0
+ if (status != SCSI_OK && dp_try_count < cur_xs->retries) {
+ printf("dp_intr: retry: dp_try_count = %d\n",
+ dp_try_count);
+ dp_restart_cmd();
+ }
+#endif
+ break;
+
+ default:
+phase_mismatch:
+ /* TEMP error generation!!! */
+ dp_reset();
+ dp_dvr_state = DP_DVR_READY;
+ cur_xs->error = XS_DRIVER_STUFFUP;
+ dp_intr_retval = HAD_ERROR;
+ /* If this true interrupt code, call the done routine. */
+ if (cur_xs->when_done) {
+ (*(cur_xs->when_done))(cur_xs->done_arg, cur_xs->done_arg2);
+ }
+ }
+
+ if (dp_dvr_state == DP_DVR_MSGI) {
+#if DP_DEBUG > 1
+ printf ("dvr_stat: dp_try_count = %d\n", dp_try_count);
+#endif
+ WR_ADR (u_char, DP_MODE, 0); /* Turn off monbsy, dma, ... */
+ if (status == SCSI_OK) {
+ cur_xs->error = XS_NOERROR;
+ dp_intr_retval = COMPLETE;
+ } else if (status & SCSI_BUSY) {
+ cur_xs->error = XS_BUSY;
+ dp_intr_retval = HAD_ERROR;
+ } else if (status & SCSI_CHECK) {
+ /* Do a sense command. */
+ cur_xs->error = XS_SENSE;
+ dp_intr_retval = HAD_ERROR;
+ dp_get_sense (cur_xs);
+ }
+ cur_xs->flags |= ITSDONE;
+ dp_dvr_state = DP_DVR_READY;
+#if DP_DEBUG > 1
+ printf("calling wakeup on 0x%x\n", cur_xs);
+#endif
+ wakeup((caddr_t) cur_xs);
+ /* If this true interrupt code, call the done routine. */
+ if (cur_xs->when_done) {
+#if DP_DEBUG > 1
+ printf("dp_intr: calling when_done 0x%x\n", cur_xs->when_done);
+#endif
+ (*(cur_xs->when_done))(cur_xs->done_arg, cur_xs->done_arg2);
+ }
+ }
+#if DP_DEBUG > 1
+ printf ("exit dp_intr.\n");
+#endif
+}
+
+
+/*===========================================================================*
+ * dp_initialize *
+ *===========================================================================*/
+
+dp_initialize()
+{
+#if DP_DEBUG
+ printf("dp_initialize()\n");
+#endif
+ scsi_select_ctlr (DP8490);
+ WR_ADR (u_char, DP_ICMD, DP_EMODE); /* Set Enhanced mode */
+ WR_ADR (u_char, DP_MODE, 0); /* Disable everything. */
+ WR_ADR (u_char, DP_EMR_ISR, DP_EF_RESETIP);
+ WR_ADR (u_char, DP_EMR_ISR, DP_EF_NOP);
+ WR_ADR (u_char, DP_SER, 0x80); /* scsi adr 7. */
+ dp_scsi_phase = DP_PHASE_NONE;
+ dp_needs_init = 0;
+}
+
+/*===========================================================================*
+ * dp_reset *
+ *===========================================================================*/
+
+/*
+ * Reset dp SCSI bus.
+ */
+
+dp_reset()
+{
+ volatile int i;
+ int x = splbio();
+
+ scsi_select_ctlr (DP8490);
+ WR_ADR (u_char, DP_MODE, 0); /* get into harmless state */
+ WR_ADR (u_char, DP_OUTDATA, 0);
+ WR_ADR (u_char, DP_ICMD, DP_A_RST|DP_EMODE); /* assert RST on SCSI bus */
+ for (i = 55; i; --i); /* wait 25 usec */
+ WR_ADR (u_char, DP_ICMD, DP_EMODE); /* deassert RST, get off bus */
+ WR_ADR (u_char, DP_EMR_ISR, DP_EF_ISR_NEXT | DP_EMR_APHS);
+ WR_ADR (u_char, DP_EMR_ISR, DP_INT_MASK); /* set interrupt mask */
+ splx(x);
+ for (i = 800000; i; --i); /* wait 360 msec */
+ dp_needs_reset = 0;
+}
+
+/*===========================================================================*
+ * dp_wait_bus_free *
+ *===========================================================================*/
+/* Wait for the SCSI bus to become free. Currently polled because I am
+ * assuming a single initiator configuration -- so this code would not be
+ * running if the bus were busy.
+ */
+int
+dp_wait_bus_free()
+{
+ int i;
+ u_char stat1;
+ volatile int j;
+
+ /* get into a harmless state */
+ WR_ADR (u_char, DP_TCMD, 0);
+ WR_ADR (u_char, DP_MODE, 0); /* return to initiator mode */
+ WR_ADR (u_char, DP_ICMD, DP_EMODE); /* clear SEL, disable data out */
+ i = WAIT_MUL * 2000;
+ while (i--) {
+ /* Must be clear for 2 usec, so read twice */
+ stat1 = RD_ADR (u_char, DP_STAT1);
+ if (stat1 & (DP_S_BSY | DP_S_SEL)) continue;
+ for (j = 5; j; j--);
+ stat1 = RD_ADR (u_char, DP_STAT1);
+ if (stat1 & (DP_S_BSY | DP_S_SEL)) continue;
+ return OK;
+ }
+#if DP_DEBUG
+ printf("wait bus free failed\n");
+ dp_print_stat1(stat1);
+#endif
+ dp_needs_reset = 1;
+ return NOT_OK;
+}
+
+/*===========================================================================*
+ * dp_select *
+ *===========================================================================*/
+/* Select SCSI device, set up for command transfer.
+ */
+int
+dp_select(adr)
+long adr;
+{
+ int i, stat1;
+
+#if DP_DEBUG > 1
+ printf("dp_select(0x%x)\n", adr);
+#endif
+ WR_ADR (u_char, DP_TCMD, 0); /* get to harmless state */
+ WR_ADR (u_char, DP_MODE, 0); /* get to harmless state */
+ WR_ADR (u_char, DP_OUTDATA, adr); /* SCSI bus address */
+ WR_ADR (u_char, DP_ICMD, DP_A_SEL | DP_ENABLE_DB | DP_EMODE);
+ for (i = 0;; ++i) { /* wait for target to assert SEL */
+ stat1 = RD_ADR (u_char, DP_STAT1);
+ if (stat1 & DP_S_BSY) break; /* select successful */
+ if (i > WAIT_MUL * 2000) { /* timeout */
+ u_char isr;
+ WR_ADR(u_char, DP_EMR_ISR, DP_EF_ISR_NEXT);
+ isr = RD_ADR (u_char, DP_EMR_ISR);
+#if DP_DEBUG
+ printf ("SCSI: SELECT timeout adr %d\n", adr);
+ dp_print_regs();
+ printf("ICMD = 0x%x isr = 0x%x\n", RD_ADR(u_char, DP_ICMD), isr);
+#endif
+ dp_reset();
+ return NOT_OK;
+ }
+ }
+ WR_ADR (u_char, DP_ICMD, DP_EMODE); /* clear SEL, disable data out */
+ WR_ADR (u_char, DP_OUTDATA, 0);
+ dp_clear_isr();
+ WR_ADR (u_char, DP_TCMD, 4); /* bogus phase, guarantee mismatch */
+ WR_ADR (u_char, DP_MODE, DP_M_BSY | DP_M_DMA);
+ return OK;
+}
+
+/*===========================================================================*
+ * scsi_select_ctlr
+ *===========================================================================*/
+/* Select a SCSI device.
+ */
+scsi_select_ctlr (ctlr)
+int ctlr;
+{
+ /* May need other stuff here to syncronize between dp & aic. */
+
+ RD_ADR (u_char, ICU_IO) &= ~ICU_SCSI_BIT; /* i/o, not port */
+ RD_ADR (u_char, ICU_DIR) &= ~ICU_SCSI_BIT; /* output */
+ if (ctlr == DP8490)
+ RD_ADR (u_char, ICU_DATA) &= ~ICU_SCSI_BIT; /* select = 0 for 8490 */
+ else
+ RD_ADR (u_char, ICU_DATA) |= ICU_SCSI_BIT; /* select = 1 for AIC6250 */
+}
+
+/*===========================================================================*
+ * dp_start_cmd *
+ *===========================================================================*/
+
+int dp_start_cmd(struct scsi_xfer *xs)
+{
+#if 0
+ WR_ADR (u_char, DP_OUTDATA, 1 << xs->targ); /* SCSI bus address */
+ WR_ADR (u_char, DP_EMR_ISR, DP_EF_ARB);
+ dp_dvr_state = DP_DVR_ARB;
+#else
+
+ /* This is not the "right" way to start it. We should just have the
+ chip do the select for us and interrupt at the end. */
+
+ if (!dp_wait_bus_free()) {
+#if DP_DEBUG
+ printf("dp_start_cmd: DP DRIVER BUSY\n");
+#endif
+ xs->error = XS_BUSY;
+ return TRY_AGAIN_LATER;
+ }
+
+ if (!dp_select(1 << xs->targ)) {
+#if DP_DEBUG
+ printf("dp_start_cmd: DP DRIVER STUFFUP\n");
+#endif
+ xs->error = XS_DRIVER_STUFFUP;
+ return HAD_ERROR;
+ }
+#endif
+
+ /* After selection, we now wait for the APHS interrupt! */
+ dp_dvr_state = DP_DVR_ARB; /* Just finished the select/arbitration */
+ dp_try_count = 1;
+
+ if (!(xs->flags & SCSI_NOMASK)) {
+ /* Set up the timeout! */
+#if DP_DEBUG > 1
+ printf ("dp_start_cmd: dp timeouts not done\n");
+#endif
+ }
+ return SUCCESSFULLY_QUEUED;
+}
+
+/*===========================================================================*
+ * dp_restart_cmd *
+ *===========================================================================*/
+
+int dp_restart_cmd()
+{
+#if 0
+ WR_ADR (u_char, DP_OUTDATA, xs->targ); /* SCSI bus address */
+ WR_ADR (u_char, DP_EMR_ISR, DP_EF_ARB);
+ dp_dvr_state = DP_DVR_ARB;
+#endif
+
+ /* This is not the "right" way to start it. We should just have the
+ chip do the select for us and interrupt at the end. */
+
+ DELAY(50);
+#if DP_DEBUG
+ printf ("restart .. stat1=0x%x stat2=0x%x\n", RD_ADR(u_char, DP_STAT1),
+ RD_ADR(u_char, DP_STAT2));
+#endif
+ if (!dp_wait_bus_free()) {
+ cur_xs->error = XS_BUSY;
+ return;
+ }
+
+#if DP_DEBUG
+ printf ("restart .1 stat1=0x%x stat2=0x%x\n", RD_ADR(u_char, DP_STAT1),
+ RD_ADR(u_char, DP_STAT2));
+ printf ("cur_xs->targ=%d\n",cur_xs->targ);
+#endif
+ if (!dp_select (1 << cur_xs->targ)) {
+ cur_xs->error = XS_DRIVER_STUFFUP;
+ return;
+ }
+
+#if DP_DEBUG
+ printf ("restart .2 stat1=0x%x stat2=0x%x\n", RD_ADR(u_char, DP_STAT1),
+ RD_ADR(u_char, DP_STAT2));
+#endif
+ /* After selection, we now wait for the APHS interrupt! */
+ dp_dvr_state = DP_DVR_ARB; /* Just finished the select/arbitration */
+ dp_try_count++;
+
+ if (!(cur_xs->flags & SCSI_NOMASK)) {
+ /* Set up the timeout! */
+#if DP_DEBUG
+ printf ("dp_restart_cmd: dp timeouts not done\n");
+#endif
+ }
+}
+
+/*===========================================================================*
+ * dp_pdma_out *
+ *===========================================================================*/
+
+/* Note: in NetBSD, the scsi dma addresses are set by the mapping hardware
+ to inhibit cache. There is therefore, no need to worry about cache hits
+ during access to dma addresses. */
+
+int dp_pdma_out(char *buf, int count, int phase)
+{
+ int cnt;
+ int ret = OK;
+ u_int stat2;
+
+#if DP_DEBUG
+ printf("dp_pdma_out: write %d bytes\n", count);
+#endif
+#if DP_DEBUG > 1
+ if (RD_ADR(u_char, DP_STAT2) & DP_S_IRQ)
+ printf("WARNING: stat2:IRQ set on call to dp_pdma_out\n");
+#endif
+
+ /* Set it up. */
+ WR_ADR(u_char, DP_TCMD, phase);
+ RD_ADR(u_char, DP_MODE) |= DP_M_DMA;
+ WR_ADR(u_char, DP_ICMD, DP_ENABLE_DB | DP_EMODE);
+ WR_ADR(u_char, DP_START_SEND, 0);
+
+ /* Do the pdma: first longs, then bytes. */
+ while (count > sizeof(long)) {
+ WR_ADR(long, DP_DMA, *(((long *)buf)++));
+ count -= sizeof(long);
+ }
+ while (count-- > 1) {
+ WR_ADR(u_char, DP_DMA, *(buf++));
+ }
+
+ /* wait for DRQ to be asserted for the last byte, or an
+ * interrupt request to be signaled
+ */
+ while (1) {
+ stat2 = RD_ADR(u_char, DP_STAT2);
+ if (stat2 & (DP_S_IRQ | DP_S_DRQ)) break;
+ }
+
+ if (stat2 & DP_S_DRQ) {
+ WR_ADR(u_char, DP_DMA_EOP, *buf);
+ }
+ else {
+ /* dma error! */
+#if DP_DEBUG
+ printf ("dma write error!\n");
+ dp_print_stat1(RD_ADR(u_char, DP_STAT1));
+ dp_print_stat2(stat2);
+#endif
+ cur_xs->error = XS_DRIVER_STUFFUP;
+ /* Clear dma mode, just in case, and disable the bus. */
+ RD_ADR (u_char, DP_MODE) &= ~DP_M_DMA;
+ WR_ADR (u_char, DP_ICMD, DP_EMODE);
+ ret = NOT_OK;
+ }
+#if 0
+ /* Clear dma mode, just in case, and disable the bus. */
+ RD_ADR (u_char, DP_MODE) &= ~DP_M_DMA;
+ WR_ADR (u_char, DP_ICMD, DP_EMODE);
+#endif
+
+ return ret;
+}
+
+/*===========================================================================*
+ * dp_pdma_in *
+ *===========================================================================*/
+
+/* Note: in NetBSD, the scsi dma addresses are set by the mapping hardware
+ to inhibit cache. There is therefore, no need to worry about cache hits
+ during access to dma addresses. */
+
+int dp_pdma_in(char *buf, int count, int phase)
+{
+ int ret = OK;
+ int i_count = count;
+ u_int stat2;
+ u_char *dma_adr = (u_char *) DP_DMA; /* Address for last few bytes. */
+
+#if DP_DEBUG > 1
+ printf("dp_pdma_in: read %d bytes\n", count);
+#endif
+ /* Set it up. */
+ WR_ADR(u_char, DP_TCMD, phase);
+ RD_ADR(u_char, DP_MODE) |= DP_M_DMA;
+ WR_ADR(u_char, DP_EMR_ISR, DP_EF_START_RCV | DP_EMR_APHS);
+
+ /* Do the pdma */
+ while (count >= sizeof(long)) {
+ *(((long *)buf)++) = RD_ADR(long, DP_DMA);
+ count -= sizeof(long);
+ }
+
+ while (count-- > 0) {
+ *(buf++) = RD_ADR(u_char, (dma_adr++));
+ }
+
+ /* Clear dma mode, just in case, and disable the bus. */
+ RD_ADR(u_char, DP_MODE) &= ~DP_M_DMA;
+ WR_ADR(u_char, DP_ICMD, DP_EMODE);
+ return ret;
+}
+
+dp_wait_for_edma()
+{
+ int i;
+
+ for (i = 0; i < 1000000; ++i) {
+ u_char tcmd = RD_ADR(u_char, DP_TCMD);
+ if (tcmd & DP_TCMD_EDMA) {
+#if DP_DEBUG > 1
+ printf("dp_wait_for_phase: EDMA detected\n");
+#endif
+ RD_ADR(u_char, DP_MODE) &= ~DP_M_DMA;
+ WR_ADR(u_char, DP_ICMD, DP_EMODE);
+ return;
+ }
+ }
+ printf("wait for edma timeout\n");
+#if DP_DEBUG
+ dp_print_regs();
+#endif
+ panic("dp: wait for edma");
+}
+
+dp_wait_for_phase(u_char phase)
+{
+ int i;
+ u_char isr;
+
+#if DP_DEBUG > 1
+ printf("wait for phase %d...", phase);
+#endif
+ /* set the TCR register */
+ WR_ADR(u_char, DP_TCMD, phase);
+ /* wait for phase match */
+ for (i = 0; i < 1000000; ++i) {
+ u_char stat2 = RD_ADR(u_char, DP_STAT2);
+ if (stat2 & DP_S_PHASE) {
+#if DP_DEBUG > 1
+ printf("done\n");
+#endif
+ /* completely clear the isr */
+ WR_ADR(u_char, DP_EMR_ISR, DP_EF_ISR_NEXT);
+ isr = RD_ADR (u_char, DP_EMR_ISR);
+ dp_clear_isr();
+ return;
+ }
+ }
+ printf("wait for phase %d timeout\n", phase);
+#if DP_DEBUG
+ dp_print_regs();
+#endif
+ panic("dp: wait for phase");
+}
+
+/*===========================================================================*
+ * dp_get_sense *
+ *===========================================================================*/
+
+dp_get_sense (struct scsi_xfer *xs)
+{
+ u_char status;
+ u_char message;
+ u_char isr;
+ int ret;
+
+ bzero((u_char *) &xs->sense, sizeof(xs->sense));
+
+ /* completely clear the isr on entry */
+ WR_ADR(u_char, DP_EMR_ISR, DP_EF_ISR_NEXT);
+ isr = RD_ADR (u_char, DP_EMR_ISR);
+ dp_clear_isr();
+
+ RD_ADR(u_char, DP_MODE) &= ~DP_M_DMA;
+ WR_ADR(u_char, DP_ICMD, DP_EMODE);
+
+#if DP_DEBUG > 2
+ printf ("sense 1: wait bus free\n");
+#endif
+ if (!dp_wait_bus_free()) {
+#if DP_DEBUG > 2
+ printf("sense 1: wait-bus-free failed\n");
+#endif
+ xs->error = XS_BUSY;
+ return;
+ }
+
+#if DP_DEBUG > 2
+ printf ("sense 2: select device\n");
+#endif
+ if (!dp_select (1 << xs->targ)) {
+#if DP_DEBUG
+ printf("sense 2: select failed\n");
+#endif
+ xs->error = XS_DRIVER_STUFFUP;
+ return;
+ }
+ /* completely clear the isr */
+ WR_ADR(u_char, DP_EMR_ISR, DP_EF_ISR_NEXT);
+ isr = RD_ADR (u_char, DP_EMR_ISR);
+ dp_clear_isr();
+
+ /* send the command */
+ sense_cmd[1] = xs->lu << 5;
+#if 0
+ sense_cmd[4] = sizeof(struct scsi_sense_data);
+#else
+ sense_cmd[4] = 0x04;
+#endif
+ dp_wait_for_phase(DP_PHASE_CMD);
+ ret = dp_pdma_out(sense_cmd, sizeof(sense_cmd), DP_PHASE_CMD);
+ if (ret != OK) {
+#if DP_DEBUG
+ printf("dp_pdma_out: ret=%d\n", ret);
+#endif
+ return;
+ }
+
+ /* read sense data */
+ dp_wait_for_edma();
+ dp_wait_for_phase(DP_PHASE_DATAI);
+ ret = dp_pdma_in((u_char *) &xs->sense, sense_cmd[4], DP_PHASE_DATAI);
+ if (ret != OK) {
+#if DP_DEBUG
+ printf ("dp_pdma_in: ret=%d\n", ret);
+#endif
+ }
+
+ /* read status */
+ dp_wait_for_phase(DP_PHASE_STATUS);
+ ret = dp_pdma_in(&status, 1, DP_PHASE_STATUS);
+ if (ret != OK) {
+#if DP_DEBUG
+ printf ("dp_pdma_in: ret=%d\n", ret);
+#endif
+ }
+
+ /* read message */
+ dp_wait_for_phase(DP_PHASE_MSGI);
+ ret = dp_pdma_in(&message, 1, DP_PHASE_MSGI);
+ if (ret != OK) {
+#if DP_DEBUG
+ printf ("dp_pdma_in: ret=%d\n", ret);
+#endif
+ }
+
+#if DP_DEBUG
+ printf("sense status = 0x%x\n", status);
+ printf(" sense (0x%x) valid = %d code = 0x%x class = 0x%x\n",
+ *(u_char *) &xs->sense,
+ xs->sense.valid, xs->sense.error_code, xs->sense.error_class);
+#endif
+
+ if (status & SCSI_BUSY) {
+ xs->error = XS_BUSY;
+ }
+ WR_ADR (u_char, DP_MODE, 0); /* Turn off monbsy, dma, ... */
+}
diff --git a/sys/arch/pc532/dev/dpreg.h b/sys/arch/pc532/dev/dpreg.h
new file mode 100644
index 00000000000..df1af1257bd
--- /dev/null
+++ b/sys/arch/pc532/dev/dpreg.h
@@ -0,0 +1,128 @@
+/* $NetBSD: dpreg.h,v 1.6 1994/10/26 08:24:11 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.
+ *
+ * dp.h: defines for the dp driver.
+ */
+
+/* Most of this comes from the Minix dp driver by Bruce Culbertson. */
+
+/* NCR 8490 SCSI controller registers
+ */
+#define DP_CTL 0xffd00000 /* base for control registers */
+#define DP_DMA 0xffe00000 /* base for data registers */
+#define DP_DMA_EOP 0xffeff000 /* SCSI DMA with EOP asserted */
+#define DP_CURDATA (DP_CTL+0)
+#define DP_OUTDATA (DP_CTL+0)
+#define DP_ICMD (DP_CTL+1)
+#define DP_MODE (DP_CTL+2)
+#define DP_TCMD (DP_CTL+3)
+#define DP_STAT1 (DP_CTL+4)
+#define DP_SER (DP_CTL+4)
+#define DP_STAT2 (DP_CTL+5)
+#define DP_START_SEND (DP_CTL+5)
+#define DP_INDATA (DP_CTL+6)
+#define DP_EMR_ISR (DP_CTL+7)
+
+/* Bits in NCR 8490 registers
+ */
+#define DP_A_RST 0x80
+#define DP_A_SEL 0x04
+#define DP_S_SEL 0x02
+#define DP_S_REQ 0x20
+#define DP_S_BSY 0x40
+#define DP_S_BSYERR 0x04
+#define DP_S_PHASE 0x08
+#define DP_S_IRQ 0x10
+#define DP_S_DRQ 0x40
+#define DP_TCMD_EDMA 0x80 /* true end of dma in tcmd */
+#define DP_M_DMA 0x02
+#define DP_M_BSY 0x04
+#define DP_M_EDMA 0x08
+#define DP_ENABLE_DB 0x01
+#define DP_EMODE 0x40 /* enhanced mode */
+#define DP_EF_NOP 0x00 /* enhanced functions */
+#define DP_EF_ARB 0x01
+#define DP_EF_RESETIP 0x02
+#define DP_EF_START_RCV 0x04
+#define DP_EF_ISR_NEXT 0x06
+#define DP_EMR_APHS 0x80
+#define DP_ISR_BSYERR 0x04
+#define DP_ISR_APHS 0x08
+#define DP_ISR_DPHS 0x10
+#define DP_ISR_EDMA 0x20
+#define DP_INT_MASK (~(DP_ISR_APHS | DP_ISR_BSYERR | DP_ISR_EDMA))
+
+#define DP_PHASE_DATAO 0 /* Data out */
+#define DP_PHASE_DATAI 1 /* Data in */
+#define DP_PHASE_CMD 2 /* CMD out */
+#define DP_PHASE_STATUS 3 /* Status in */
+#define DP_PHASE_MSGO 6 /* Message out */
+#define DP_PHASE_MSGI 7 /* Message in */
+
+#define DP_PHASE_NONE 4 /* will mismatch all phases (??) */
+
+/* Driver state. Helps interrupt code decide what to do next. */
+#define DP_DVR_READY 0
+#define DP_DVR_STARTED 1
+#define DP_DVR_ARB 2
+#define DP_DVR_CMD 3
+#define DP_DVR_DATA 4
+#define DP_DVR_STAT 5
+#define DP_DVR_MSGI 6
+#define DP_DVR_SENSE 7
+
+#define dp_clear_isr() /* clear 8490 interrupts */ \
+ WR_ADR (u_char, DP_EMR_ISR, DP_EF_RESETIP); \
+ WR_ADR (u_char, DP_EMR_ISR, DP_EF_NOP | DP_EMR_APHS);
+
+/* Status of interrupt routine.
+ */
+#define ISR_NOTDONE 0
+#define ISR_OK 1
+#define ISR_BSYERR 2
+#define ISR_RSTERR 3
+#define ISR_BADPHASE 4
+#define ISR_TIMEOUT 5
+#define ISR_DMACNTERR 6
+
+#define ICU_ADR 0xfffffe00
+#define ICU_IO (ICU_ADR+20)
+#define ICU_DIR (ICU_ADR+21)
+#define ICU_DATA (ICU_ADR+19)
+#define ICU_SCSI_BIT 0x80
+
+/* Miscellaneous
+ */
+#define WAIT_MUL 1000 /* Estimate! .. for polling. */
+
+#define OK 1
+#define NOT_OK 0
diff --git a/sys/arch/pc532/dev/lpt.c b/sys/arch/pc532/dev/lpt.c
new file mode 100644
index 00000000000..9811279385f
--- /dev/null
+++ b/sys/arch/pc532/dev/lpt.c
@@ -0,0 +1,876 @@
+/* $NetBSD: lpt.c,v 1.6 1995/09/26 20:16:06 phil Exp $ */
+
+/*
+ * Copyright (c) 1994 Matthias Pfaller.
+ * Copyright (c) 1994 Poul-Henning Kamp
+ * 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 Matthias's parallel printer port.
+ * This driver is based on the i386 lpt driver and
+ * some IP code from Poul-Henning Kamp.
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/proc.h>
+#include <sys/user.h>
+#include <sys/buf.h>
+#include <sys/kernel.h>
+#include <sys/ioctl.h>
+#include <sys/uio.h>
+#include <sys/device.h>
+#include <sys/syslog.h>
+#include <sys/malloc.h>
+#include <machine/cpu.h>
+
+#include "lpt.h"
+#include "lptreg.h"
+
+#if defined(INET) && defined(PLIP)
+#include <sys/mbuf.h>
+#include <sys/socket.h>
+#include <net/if.h>
+#include <net/if_types.h>
+#include <net/netisr.h>
+#include <net/route.h>
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/in_var.h>
+#include <netinet/ip.h>
+#include <netinet/if_ether.h>
+#endif
+
+#define LPT_INVERT (LPC_NBUSY|LPC_NERROR|LPC_NACK|LPC_ONLINE)
+#define LPT_MASK (LPC_NBUSY|LPC_NERROR|LPC_NACK|LPC_NOPAPER|LPC_ONLINE)
+
+#define TIMEOUT hz*16 /* wait up to 16 seconds for a ready */
+#define STEP hz/4
+
+#define LPTPRI (PZERO+8)
+#define LPT_BSIZE 1024
+
+#if defined(INET) && defined(PLIP)
+#ifndef PLIPMTU /* MTU for the plip# interfaces */
+#if defined(COMPAT_PLIP10)
+#define PLIPMTU 1600
+#else
+#define PLIPMTU (ETHERMTU - ifp->if_hdrlen)
+#endif
+#endif
+
+#ifndef PLIPMXSPIN1 /* DELAY factor for the plip# interfaces */
+#define PLIPMXSPIN1 2000 /* Spinning for remote intr to happen */
+#endif
+
+#ifndef PLIPMXSPIN2 /* DELAY factor for the plip# interfaces */
+#define PLIPMXSPIN2 6000 /* Spinning for remote handshake to happen */
+#endif
+
+#ifndef PLIPMXERRS /* Max errors before !RUNNING */
+#define PLIPMXERRS 20
+#endif
+#ifndef PLIPMXRETRY
+#define PLIPMXRETRY 20 /* Max number of retransmits */
+#endif
+#ifndef PLIPRETRY
+#define PLIPRETRY hz/50 /* Time between retransmits */
+#endif
+#endif
+
+struct lpt_softc {
+ struct device sc_dev;
+ size_t sc_count;
+ u_char *sc_inbuf;
+ u_char *sc_cp;
+ volatile struct i8255 *sc_i8255;
+ int sc_irq;
+ u_char sc_state;
+#define LPT_OPEN 0x01 /* device is open */
+#define LPT_INIT 0x02 /* waiting to initialize for open */
+
+ u_char sc_status;
+ u_char sc_flags;
+#define LPT_AUTOLF 0x20 /* automatic LF on CR */
+#define LPT_NOPRIME 0x40 /* don't prime on open */
+
+#if defined(INET) && defined(PLIP)
+ struct arpcom sc_arpcom;
+ u_char *sc_ifbuf;
+ int sc_ifierrs; /* consecutive input errors */
+ int sc_ifoerrs; /* consecutive output errors */
+ int sc_ifsoftint; /* i/o software interrupt */
+ volatile int sc_pending; /* interrputs pending */
+#define PLIP_IPENDING 1
+#define PLIP_OPENDING 2
+
+#if defined(COMPAT_PLIP10)
+ u_char sc_adrcksum;
+#endif
+#endif
+};
+
+#define LPTUNIT(s) (minor(s) & 0x1f)
+#define LPTFLAGS(s) (minor(s) & 0xe0)
+
+static int lptmatch(struct device *, void *, void *aux);
+static void lptattach(struct device *, struct device *, void *);
+static void lptintr(struct lpt_softc *);
+static int notready(u_char, struct lpt_softc *);
+static void lptout(void *arg);
+static int pushbytes(struct lpt_softc *);
+
+#if defined(INET) && defined(PLIP)
+/* Functions for the plip# interface */
+static void plipattach(struct lpt_softc *,int);
+static int plipioctl(struct ifnet *, u_long, caddr_t);
+static void plipsoftint(struct lpt_softc *);
+static void plipinput(struct lpt_softc *);
+static void plipstart(struct ifnet *);
+static void plipoutput(struct lpt_softc *);
+#endif
+
+struct cfdriver lptcd = {
+ NULL,
+ "lpt",
+ lptmatch,
+ lptattach,
+ DV_TTY,
+ sizeof(struct lpt_softc),
+ NULL,
+ 0
+};
+
+lptmatch(struct device *parent, void *cf, void *aux)
+{
+ volatile struct i8255 *i8255 =
+ (volatile struct i8255 *)((struct cfdata *)cf)->cf_loc[0];
+ int unit = ((struct cfdata *)cf)->cf_unit;
+
+ if (unit >= LPT_MAX)
+ return(0);
+
+ if ((int) i8255 == -1)
+ i8255 = LPT_ADR(unit);
+
+ i8255->port_control = LPT_PROBE_MODE;
+
+ i8255->port_control = LPT_PROBE_CLR;
+ if ((i8255->port_c & LPT_PROBE_MASK) != 0)
+ return 0;
+
+ i8255->port_control = LPT_PROBE_SET;
+ if ((i8255->port_c & LPT_PROBE_MASK) == 0)
+ return 0;
+
+ i8255->port_control = LPT_PROBE_CLR;
+ if ((i8255->port_c & LPT_PROBE_MASK) != 0)
+ return 0;
+
+ i8255->port_control = LPT_MODE;
+ i8255->port_a = LPA_ACTIVE | LPA_NPRIME;
+
+ return 1;
+}
+
+void
+lptattach(struct device *parent, struct device *self, void *aux)
+{
+ struct lpt_softc *sc = (struct lpt_softc *) self;
+ volatile struct i8255 *i8255 =
+ (volatile struct i8255 *)self->dv_cfdata->cf_loc[0];
+
+ if ((sc->sc_irq = self->dv_cfdata->cf_loc[1]) == -1)
+ sc->sc_irq = LPT_IRQ(self->dv_unit);
+
+ if ((int)i8255 == -1)
+ i8255 = LPT_ADR(self->dv_unit);
+ i8255->port_control = LPT_MODE;
+ i8255->port_a = LPA_ACTIVE | LPA_NPRIME;
+ i8255->port_control = LPT_IRQDISABLE;
+
+ sc->sc_state = 0;
+ sc->sc_i8255 = i8255;
+
+#if defined(INET) && defined(PLIP)
+ plipattach(sc, self->dv_unit);
+#endif
+ intr_establish(sc->sc_irq, lptintr, sc, sc->sc_dev.dv_xname,
+ IPL_NONE, FALLING_EDGE);
+ printf(" addr 0x%x, irq %d\n", (int) i8255, sc->sc_irq);
+}
+
+/*
+ * Reset the printer, then wait until it's selected and not busy.
+ */
+int
+lptopen(dev_t dev, int flag)
+{
+ struct lpt_softc *sc = (struct lpt_softc *) lptcd.cd_devs[LPTUNIT(dev)];
+ volatile struct i8255 *i8255 = sc->sc_i8255;
+ u_char flags = LPTFLAGS(dev);
+ int error;
+ int spin;
+
+ if (LPTUNIT(dev) >= NLPT || !sc)
+ return ENXIO;
+
+ if (sc->sc_state)
+ return EBUSY;
+
+#if defined(INET) && defined(PLIP)
+ if (sc->sc_arpcom.ac_if.if_flags & IFF_UP)
+ return EBUSY;
+#endif
+
+ sc->sc_state = LPT_INIT;
+ sc->sc_flags = flags;
+
+ if ((flags & LPT_NOPRIME) == 0) {
+ /* assert INIT for 100 usec to start up printer */
+ i8255->port_a &= ~LPA_NPRIME;
+ DELAY(100);
+ }
+
+ if (flags & LPT_AUTOLF)
+ i8255->port_a |= LPA_ALF | LPA_SELECT | LPA_NPRIME;
+ else
+ i8255->port_a = (i8255->port_a & ~LPA_ALF)
+ | LPA_SELECT | LPA_NPRIME;
+
+ /* wait till ready (printer running diagnostics) */
+ for (spin = 0; notready(i8255->port_c, sc); spin += STEP) {
+ if (spin >= TIMEOUT) {
+ sc->sc_state = 0;
+ return EBUSY;
+ }
+
+ /* wait 1/4 second, give up if we get a signal */
+ if (error = tsleep((caddr_t)sc, LPTPRI | PCATCH, "lptopen",
+ STEP) != EWOULDBLOCK) {
+ sc->sc_state = 0;
+ return error;
+ }
+ }
+
+ sc->sc_inbuf = malloc(LPT_BSIZE, M_DEVBUF, M_WAITOK);
+ sc->sc_status =
+ sc->sc_count = 0;
+ sc->sc_state = LPT_OPEN;
+
+ return 0;
+}
+
+int
+notready(u_char status, struct lpt_softc *sc)
+{
+ status ^= LPT_INVERT;
+
+ if (status != sc->sc_status) {
+ if (status & LPC_NOPAPER)
+ log(LOG_NOTICE, "%s: out of paper\n", sc->sc_dev.dv_xname);
+ if (status & LPC_ONLINE)
+ log(LOG_NOTICE, "%s: offline\n", sc->sc_dev.dv_xname);
+ if (status & LPC_NERROR)
+ log(LOG_NOTICE, "%s: output error\n", sc->sc_dev.dv_xname);
+ if (status & LPC_NACK)
+ log(LOG_NOTICE, "%s: NACK low\n", sc->sc_dev.dv_xname);
+ if (status & LPC_NBUSY)
+ log(LOG_NOTICE, "%s: NBUSY low\n", sc->sc_dev.dv_xname);
+ sc->sc_status = status;
+ }
+ return status & LPT_MASK;
+}
+
+void
+lptout(void *arg)
+{
+ struct lpt_softc *sc = (struct lpt_softc *) arg;
+ if (sc->sc_count > 0)
+ sc->sc_i8255->port_control = LPT_IRQENABLE;
+}
+
+/*
+ * Close the device, and free the local line buffer.
+ */
+lptclose(dev_t dev, int flag)
+{
+ struct lpt_softc *sc = (struct lpt_softc *) lptcd.cd_devs[LPTUNIT(dev)];
+
+ if (sc->sc_count)
+ (void) pushbytes(sc);
+
+ sc->sc_i8255->port_control = LPT_IRQDISABLE;
+ sc->sc_state = 0;
+ free(sc->sc_inbuf, M_DEVBUF);
+
+ return 0;
+}
+
+int
+pushbytes(struct lpt_softc *sc)
+{
+ volatile struct i8255 *i8255 = sc->sc_i8255;
+ int error;
+
+ while (sc->sc_count > 0) {
+ i8255->port_control = LPT_IRQENABLE;
+ if (error = tsleep((caddr_t)sc, LPTPRI | PCATCH,
+ "lptwrite", 0))
+ return error;
+ }
+ return 0;
+}
+
+/*
+ * Copy a line from user space to a local buffer, then call pushbytes to
+ * get the chars moved to the output queue.
+ */
+lptwrite(dev_t dev, struct uio *uio)
+{
+ struct lpt_softc *sc = (struct lpt_softc *) lptcd.cd_devs[LPTUNIT(dev)];
+ size_t n;
+ int error = 0;
+
+ if (sc->sc_count) return EBUSY;
+ while (n = min(LPT_BSIZE, uio->uio_resid)) {
+ uiomove(sc->sc_cp = sc->sc_inbuf, n, uio);
+ sc->sc_count = n;
+ error = pushbytes(sc);
+ if (error) {
+ /*
+ * Return accurate residual if interrupted or timed
+ * out.
+ */
+ uio->uio_resid += sc->sc_count;
+ sc->sc_count = 0;
+ return error;
+ }
+ }
+ return 0;
+}
+
+/*
+ * Handle printer interrupts which occur when the printer is ready to accept
+ * another char.
+ */
+void
+lptintr(struct lpt_softc *sc)
+{
+ volatile struct i8255 *i8255 = sc->sc_i8255;
+
+#if defined(INET) && defined(PLIP)
+ if(sc->sc_arpcom.ac_if.if_flags & IFF_UP) {
+ i8255->port_a &= ~LPA_ACKENABLE;
+ sc->sc_pending |= PLIP_IPENDING;
+ softintr(sc->sc_ifsoftint);
+ return;
+ }
+#endif
+
+ if ((sc->sc_state & LPT_OPEN) == 0) {
+ i8255->port_control = LPT_IRQDISABLE;
+ return;
+ }
+
+ if (sc->sc_count) {
+ /* is printer online and ready for output? */
+ if (notready(i8255->port_c, sc)) {
+ i8255->port_control = LPT_IRQDISABLE;
+ timeout(lptout, sc, STEP);
+ return;
+ }
+ /* send char */
+ i8255->port_a &= ~LPA_ACTIVE;
+ i8255->port_b = *sc->sc_cp++;
+ i8255->port_a |= LPA_ACTIVE;
+ sc->sc_count--;
+ }
+
+ if (sc->sc_count == 0) {
+ /* none, wake up the top half to get more */
+ i8255->port_control = LPT_IRQDISABLE;
+ wakeup((caddr_t)sc);
+ }
+}
+
+int
+lptioctl(dev_t dev, int cmd, caddr_t data, int flag)
+{
+ int error = 0;
+
+ switch (cmd) {
+ default:
+ error = EINVAL;
+ }
+
+ return error;
+}
+
+#if defined(INET) && defined(PLIP)
+
+static void
+plipattach(struct lpt_softc *sc, int unit)
+{
+ struct ifnet *ifp = &sc->sc_arpcom.ac_if;
+
+ sc->sc_ifbuf = NULL;
+ ifp->if_unit = unit;
+ ifp->if_name = "plip";
+ ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_NOTRAILERS;
+ ifp->if_output = ether_output;
+ ifp->if_start = plipstart;
+ ifp->if_ioctl = plipioctl;
+ ifp->if_watchdog = 0;
+
+ ifp->if_type = IFT_ETHER;
+ ifp->if_addrlen = 6;
+ ifp->if_hdrlen = 14;
+ ifp->if_mtu = PLIPMTU;
+ sc->sc_ifsoftint = intr_establish(SOFTINT, plipsoftint, sc,
+ sc->sc_dev.dv_xname, IPL_NET, 0);
+
+ if_attach(ifp);
+}
+
+/*
+ * Process an ioctl request.
+ */
+static int
+plipioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
+{
+ struct proc *p = curproc;
+ struct lpt_softc *sc = (struct lpt_softc *) lptcd.cd_devs[ifp->if_unit];
+ volatile struct i8255 *i8255 = sc->sc_i8255;
+ struct ifaddr *ifa = (struct ifaddr *)data;
+ struct ifreq *ifr = (struct ifreq *)data;
+ int s;
+ int error = 0;
+
+ switch (cmd) {
+
+ case SIOCSIFFLAGS:
+ if (((ifp->if_flags & IFF_UP) == 0) &&
+ (ifp->if_flags & IFF_RUNNING)) {
+ ifp->if_flags &= ~IFF_RUNNING;
+ sc->sc_i8255->port_control = LPT_MODE;
+ i8255->port_a = LPA_ACTIVE | LPA_NPRIME;
+ if (sc->sc_ifbuf)
+ free(sc->sc_ifbuf, M_DEVBUF);
+ sc->sc_ifbuf = NULL;
+ }
+ if (((ifp->if_flags & IFF_UP)) &&
+ ((ifp->if_flags & IFF_RUNNING) == 0)) {
+ if (sc->sc_state) {
+ error = EBUSY;
+ break;
+ }
+ if (!sc->sc_ifbuf)
+ sc->sc_ifbuf =
+ malloc(ifp->if_mtu + ifp->if_hdrlen,
+ M_DEVBUF, M_WAITOK);
+ ifp->if_flags |= IFF_RUNNING;
+ sc->sc_i8255->port_control = LPT_IRQDISABLE;
+ sc->sc_i8255->port_b = 0;
+ sc->sc_i8255->port_a |= LPA_ACKENABLE;
+ }
+ break;
+
+ case SIOCSIFADDR:
+ if (ifa->ifa_addr->sa_family == AF_INET) {
+ if (!sc->sc_ifbuf)
+ sc->sc_ifbuf =
+ malloc(PLIPMTU + ifp->if_hdrlen,
+ M_DEVBUF, M_WAITOK);
+ sc->sc_arpcom.ac_enaddr[0] = 0xfc;
+ sc->sc_arpcom.ac_enaddr[1] = 0xfc;
+ bcopy((caddr_t)&IA_SIN(ifa)->sin_addr,
+ (caddr_t)&sc->sc_arpcom.ac_enaddr[2], 4);
+ sc->sc_arpcom.ac_ipaddr = IA_SIN(ifa)->sin_addr;
+#if defined(COMPAT_PLIP10)
+ if (ifp->if_flags & IFF_LINK0) {
+ int i;
+ sc->sc_arpcom.ac_enaddr[0] = 0xfd;
+ sc->sc_arpcom.ac_enaddr[1] = 0xfd;
+ for (i = sc->sc_adrcksum = 0; i < 5; i++)
+ sc->sc_adrcksum += sc->sc_arpcom.ac_enaddr[i];
+ sc->sc_adrcksum *= 2;
+ }
+#endif
+ ifp->if_flags |= IFF_RUNNING | IFF_UP;
+#if 0
+ for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) {
+ struct sockaddr_dl *sdl;
+ if ((sdl = (struct sockaddr_dl *)ifa->ifa_addr) &&
+ sdl->sdl_family == AF_LINK) {
+ sdl->sdl_type = IFT_ETHER;
+ sdl->sdl_alen = ifp->if_addrlen;
+ bcopy((caddr_t)((struct arpcom *)ifp)->ac_enaddr,
+ LLADDR(sdl), ifp->if_addrlen);
+ break;
+ }
+ }
+#endif
+ sc->sc_i8255->port_control = LPT_IRQDISABLE;
+ sc->sc_i8255->port_b = 0;
+ sc->sc_i8255->port_a |= LPA_ACKENABLE;
+ arp_ifinit(&sc->sc_arpcom, ifa);
+ } else
+ error = EAFNOSUPPORT;
+ break;
+
+ case SIOCAIFADDR:
+ case SIOCDIFADDR:
+ case SIOCSIFDSTADDR:
+ if (ifa->ifa_addr->sa_family != AF_INET)
+ error = EAFNOSUPPORT;
+ break;
+
+ case SIOCSIFMTU:
+ if ((error = suser(p->p_ucred, &p->p_acflag)))
+ return(error);
+ if (ifp->if_mtu != ifr->ifr_metric) {
+ ifp->if_mtu = ifr->ifr_metric;
+ if (sc->sc_ifbuf) {
+ s = splimp();
+ free(sc->sc_ifbuf, M_DEVBUF);
+ sc->sc_ifbuf =
+ malloc(ifp->if_mtu + ifp->if_hdrlen,
+ M_DEVBUF, M_WAITOK);
+ splx(s);
+ }
+ }
+ break;
+
+ case SIOCGIFMTU:
+ ifr->ifr_metric = ifp->if_mtu;
+ break;
+
+ default:
+ error = EINVAL;
+ }
+ return (error);
+}
+
+static void
+plipsoftint(struct lpt_softc *sc)
+{
+ int pending = sc->sc_pending;
+
+ while (sc->sc_pending & PLIP_IPENDING) {
+ pending |= sc->sc_pending;
+ sc->sc_pending = 0;
+ plipinput(sc);
+ }
+
+ if (pending & PLIP_OPENDING)
+ plipoutput(sc);
+}
+
+static int
+plipreceive(volatile struct i8255 *i8255, u_char *buf, int len)
+{
+ int i;
+ u_char cksum = 0, c;
+
+ while (len--) {
+ i = PLIPMXSPIN2;
+ while ((i8255->port_c & LPC_NBUSY) != 0)
+ if (i-- < 0) return -1;
+ c = i8255->port_c >> 4;
+ i8255->port_b = 0x11;
+ while ((i8255->port_c & LPC_NBUSY) == 0)
+ if (i-- < 0) return -1;
+ c |= i8255->port_c & 0xf0;
+ i8255->port_b = 0x01;
+ cksum += (*buf++ = c);
+ }
+ return(cksum);
+}
+
+static void
+plipinput(struct lpt_softc *sc)
+{
+ extern struct mbuf *m_devget(char *, int, int, struct ifnet *, void (*)());
+ struct ifnet *ifp = &sc->sc_arpcom.ac_if;
+ volatile struct i8255 *i8255 = sc->sc_i8255;
+ struct mbuf *m;
+ struct ether_header *eh;
+ u_char *p = sc->sc_ifbuf, minibuf[4];
+ int c, i = 0, s, len, cksum;
+
+ if (!(i8255->port_c & LPC_NACK)) {
+ i8255->port_a |= LPA_ACKENABLE;
+ ifp->if_collisions++;
+ return;
+ }
+ i8255->port_b = 0x01;
+ i8255->port_a &= ~(LPA_ACKENABLE | LPA_ACTIVE);
+
+#if defined(COMPAT_PLIP10)
+ if (ifp->if_flags & IFF_LINK0) {
+ if (plipreceive(i8255, minibuf, 3) < 0) goto err;
+ len = (minibuf[1] << 8) | minibuf[2];
+ if (len > (ifp->if_mtu + ifp->if_hdrlen)) goto err;
+
+ switch (minibuf[0]) {
+ case 0xfc:
+ p[0] = p[ 6] = ifp->ac_enaddr[0];
+ p[1] = p[ 7] = ifp->ac_enaddr[1];
+ p[2] = p[ 8] = ifp->ac_enaddr[2];
+ p[3] = p[ 9] = ifp->ac_enaddr[3];
+ p[4] = p[10] = ifp->ac_enaddr[4];
+ p += 5;
+ if ((cksum = plipreceive(i8255, p, 1)) < 0) goto err;
+ p += 6;
+ if ((c = plipreceive(i8255, p, len - 11)) < 0) goto err;
+ cksum += c + sc->sc_adrcksum;
+ c = p[1]; p[1] = p[2]; p[2] = c;
+ cksum &= 0xff;
+ break;
+ case 0xfd:
+ if ((cksum = plipreceive(i8255, p, len)) < 0) goto err;
+ break;
+ default:
+ goto err;
+ }
+ } else
+#endif
+ {
+ if (plipreceive(i8255, minibuf, 2) < 0) goto err;
+ len = (minibuf[1] << 8) | minibuf[0];
+ if (len > (ifp->if_mtu + ifp->if_hdrlen)) {
+ log(LOG_NOTICE, "plip%d: packet > MTU\n", ifp->if_unit);
+ goto err;
+ }
+ if ((cksum = plipreceive(i8255, p, len)) < 0) goto err;
+ }
+
+ if (plipreceive(i8255, minibuf, 1) < 0) goto err;
+ if (cksum != minibuf[0]) {
+ log(LOG_NOTICE, "plip%d: checksum error\n", ifp->if_unit);
+ goto err;
+ }
+ i8255->port_b = 0x00;
+
+ s = splimp();
+ if (m = m_devget(sc->sc_ifbuf, len, 0, ifp, NULL)) {
+ /* We assume that the header fit entirely in one mbuf. */
+ eh = mtod(m, struct ether_header *);
+ m->m_pkthdr.len -= sizeof(*eh);
+ m->m_len -= sizeof(*eh);
+ m->m_data += sizeof(*eh);
+ ether_input(ifp, eh, m);
+ }
+ splx(s);
+ sc->sc_ifierrs = 0;
+ ifp->if_ipackets++;
+ i8255->port_a |= LPA_ACKENABLE | LPA_ACTIVE;
+ return;
+
+err:
+ i8255->port_b = 0x00;
+
+ if (sc->sc_ifierrs < PLIPMXERRS) {
+ i8255->port_a |= LPA_ACKENABLE | LPA_ACTIVE;
+ } else {
+ /* We are not able to send receive anything for now,
+ * so stop wasting our time and leave the interrupt
+ * disabled.
+ */
+ if (sc->sc_ifierrs == PLIPMXERRS)
+ log(LOG_NOTICE, "plip%d: rx hard error\n", ifp->if_unit);
+ i8255->port_a |= LPA_ACTIVE;
+ }
+ ifp->if_ierrors++;
+ sc->sc_ifierrs++;
+ return;
+}
+
+static int
+pliptransmit(volatile struct i8255 *i8255, u_char *buf, int len)
+{
+ int i;
+ u_char cksum = 0, c;
+
+ while (len--) {
+ i = PLIPMXSPIN2;
+ cksum += (c = *buf++);
+ while ((i8255->port_c & LPC_NBUSY) == 0)
+ if (i-- < 0) return -1;
+ i8255->port_b = c & 0x0f;
+ i8255->port_b = c & 0x0f | 0x10;
+ c >>= 4;
+ while ((i8255->port_c & LPC_NBUSY) != 0)
+ if (i-- < 0) return -1;
+ i8255->port_b = c | 0x10;
+ i8255->port_b = c;
+ }
+ return(cksum);
+}
+
+/*
+ * Setup output on interface.
+ */
+static void
+plipstart(struct ifnet *ifp)
+{
+ struct lpt_softc *sc = (struct lpt_softc *) lptcd.cd_devs[ifp->if_unit];
+ sc->sc_pending |= PLIP_OPENDING;
+ softintr(sc->sc_ifsoftint);
+}
+
+static void
+plipoutput(struct lpt_softc *sc)
+{
+ struct ifnet *ifp = &sc->sc_arpcom.ac_if;
+ volatile struct i8255 *i8255 = sc->sc_i8255;
+ struct mbuf *m0, *m;
+ u_char minibuf[4], cksum;
+ int len, i, s;
+
+ if (ifp->if_flags & IFF_OACTIVE)
+ return;
+ ifp->if_flags |= IFF_OACTIVE;
+
+ if (sc->sc_ifoerrs)
+ untimeout((void (*)(void *))plipoutput, sc);
+
+ for (;;) {
+ s = splnet();
+ IF_DEQUEUE(&ifp->if_snd, m0);
+ splx(s);
+ if (!m0)
+ break;
+
+ for (len = 0, m = m0; m; m = m->m_next)
+ len += m->m_len;
+#if defined(COMPAT_PLIP10)
+ if (ifp->if_flags & IFF_LINK0) {
+ minibuf[0] = 3;
+ minibuf[1] = 0xfd;
+ minibuf[2] = len >> 8;
+ minibuf[3] = len;
+ } else
+#endif
+ {
+ minibuf[0] = 2;
+ minibuf[1] = len;
+ minibuf[2] = len >> 8;
+ }
+
+ /* Trigger remote interrupt */
+ i = PLIPMXSPIN1;
+ do {
+ if (sc->sc_pending & PLIP_IPENDING) {
+ i8255->port_b = 0x00;
+ sc->sc_pending = 0;
+ plipinput(sc);
+ i = PLIPMXSPIN1;
+ } else if (i-- < 0)
+ goto retry;
+ /* Retrigger remote interrupt */
+ i8255->port_b = 0x08;
+ } while ((i8255->port_c & LPC_NERROR) == 0);
+ i8255->port_a &= ~(LPA_ACKENABLE | LPA_ACTIVE);
+
+ if (pliptransmit(i8255, minibuf + 1, minibuf[0]) < 0) goto retry;
+ for (cksum = 0, m = m0; m; m = m->m_next) {
+ i = pliptransmit(i8255, mtod(m, u_char *), m->m_len);
+ if (i < 0) goto retry;
+ cksum += i;
+ }
+ if (pliptransmit(i8255, &cksum, 1) < 0) goto retry;
+ i = PLIPMXSPIN2;
+ while ((i8255->port_c & LPC_NBUSY) == 0)
+ if (i-- < 0) goto retry;
+ i8255->port_b = 0x00;
+
+ ifp->if_opackets++;
+ ifp->if_obytes += len + 4;
+ sc->sc_ifoerrs = 0;
+ s = splimp();
+ m_freem(m0);
+ splx(s);
+ i8255->port_a |= LPA_ACKENABLE;
+ }
+ i8255->port_a |= LPA_ACTIVE;
+ ifp->if_flags &= ~IFF_OACTIVE;
+ return;
+
+retry:
+ if (i8255->port_c & LPC_NACK)
+ ifp->if_collisions++;
+ else
+ ifp->if_oerrors++;
+
+ ifp->if_flags &= ~IFF_OACTIVE;
+ i8255->port_b = 0x00;
+
+ if ((ifp->if_flags & (IFF_RUNNING | IFF_UP)) == (IFF_RUNNING | IFF_UP)
+ && sc->sc_ifoerrs < PLIPMXRETRY) {
+ s = splnet();
+ IF_PREPEND(&ifp->if_snd, m0);
+ splx(s);
+ i8255->port_a |= LPA_ACKENABLE | LPA_ACTIVE;
+ timeout((void (*)(void *))plipoutput, sc, PLIPRETRY);
+ } else {
+ if (sc->sc_ifoerrs == PLIPMXRETRY) {
+ log(LOG_NOTICE, "plip%d: tx hard error\n", ifp->if_unit);
+ }
+ s = splimp();
+ m_freem(m0);
+ splx(s);
+ i8255->port_a |= LPA_ACTIVE;
+ }
+ sc->sc_ifoerrs++;
+}
+
+#endif
diff --git a/sys/arch/pc532/dev/lptreg.h b/sys/arch/pc532/dev/lptreg.h
new file mode 100644
index 00000000000..6298f1fe291
--- /dev/null
+++ b/sys/arch/pc532/dev/lptreg.h
@@ -0,0 +1,75 @@
+/* $NetBSD: lptreg.h,v 1.3 1995/05/16 07:30:35 phil Exp $ */
+
+/*
+ * Copyright (c) 1994 Matthias Pfaller.
+ * 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 Matthias Pfaller.
+ * 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.
+ *
+ * lptreg.h: definitions for the lpt driver.
+ *
+ */
+
+struct i8255 {
+ unsigned char port_a; /* Port A data (r/w) */
+ unsigned char port_b; /* Port B data (r/w) */
+ unsigned char port_c; /* Port C data (r/w) */
+ unsigned char port_control; /* Port control (-/w) */
+};
+
+/* port_a */
+#define LPA_ALF 0x01
+#define LPA_SELECT 0x02
+#define LPA_NPRIME 0x04
+#define LPA_ACKENABLE 0x08 /* Enable Ack interrupts */
+#define LPA_ACTIVE 0x10 /* Device active led */
+
+/* port_c */
+#define LPC_IRQ 0x01
+#define LPC_NSTROBE 0x02
+#define LPC_NBUSY 0x08 /* Negative logic! */
+#define LPC_NERROR 0x10
+#define LPC_ONLINE 0x20
+#define LPC_NOPAPER 0x40
+#define LPC_NACK 0x80
+
+/* port_control */
+#define LPT_PROBE_MODE 0x8c
+#define LPT_MODE 0x8d /* Port A: Output, Mode 0 */
+ /* Port B: Output, Mode 1 */
+ /* Port C: Input */
+#define LPT_IRQENABLE 0x05 /* Enable LPT interrupts */
+#define LPT_IRQDISABLE 0x04 /* Disable LPT interrupts */
+
+#define LPT_PROBE_MASK 0x08
+#define LPT_PROBE_SET 0x07
+#define LPT_PROBE_CLR 0x06
+
+ /* Default mapped address */
+#define LPT_ADR(unit) (((volatile struct i8255 *)0xFFC80030) + unit)
+ /* Default interrupts */
+#define LPT_IRQ(unit) (unit?IR_TTY3 - 1:IR_TTY3)
+#define LPT_MAX 2 /* Maximum number of lpt interfaces*/
diff --git a/sys/arch/pc532/dev/ncr.c b/sys/arch/pc532/dev/ncr.c
new file mode 100644
index 00000000000..0501972eabe
--- /dev/null
+++ b/sys/arch/pc532/dev/ncr.c
@@ -0,0 +1,297 @@
+/* $NetBSD: ncr.c,v 1.20 1995/09/26 20:16:08 phil Exp $ */
+
+/*
+ * Copyright (c) 1994 Matthias Pfaller.
+ * 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 Matthias Pfaller.
+ * 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.
+ *
+ * $Id: ncr.c,v 1.1 1995/10/18 08:51:17 deraadt Exp $
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/device.h>
+#include <sys/buf.h>
+#include <scsi/scsi_all.h>
+#include <scsi/scsi_message.h>
+#include <scsi/scsiconf.h>
+#include <machine/stdarg.h>
+
+/*
+ * Include the driver definitions
+ */
+#include "ncr5380reg.h"
+#include "ncrreg.h"
+
+/*
+ * Set the various driver options
+ */
+#define NREQ 18 /* Size of issue queue */
+#define AUTO_SENSE 1 /* Automatically issue a request-sense */
+
+#define DRNAME ncr /* used in various prints */
+#undef DBG_SEL /* Show the selection process */
+#undef DBG_REQ /* Show enqueued/ready requests */
+#undef DBG_NOWRITE /* Do not allow writes to the targets */
+#undef DBG_PIO /* Show the polled-I/O process */
+#undef DBG_INF /* Show information transfer process */
+#undef DBG_NOSTATIC /* No static functions, all in DDB trace*/
+#define DBG_PID /* Keep track of driver */
+#undef REAL_DMA /* Use DMA if sensible */
+#undef REAL_DMA_POLL 0 /* 1: Poll for end of DMA-transfer */
+#define USE_PDMA /* Use special pdma-transfer function */
+
+/*
+ * Softc of currently active controller (a bit of fake; we only have one)
+ */
+static struct ncr_softc *cur_softc;
+
+/*
+ * Function decls:
+ */
+static int transfer_pdma __P((u_char *, u_char *, u_long *));
+static void ncr_intr __P((void *));
+static void ncr_soft_intr __P((void *));
+#define scsi_dmaok(x) 0
+#define pdma_ready() 0
+#define fair_to_keep_dma() 1
+#define claimed_dma() 1
+#define reconsider_dma()
+#define ENABLE_NCR5380(sc) do { \
+ scsi_select_ctlr(DP8490); \
+ cur_softc = sc; \
+ } while (0)
+
+void
+delay(timeo)
+ int timeo;
+{
+ int len;
+ for (len=0; len < timeo * 2; len++);
+}
+
+static int
+machine_match(pdp, cdp, auxp, cfd)
+ struct device *pdp;
+ struct cfdata *cdp;
+ void *auxp;
+ struct cfdriver *cfd;
+{
+ if(cdp->cf_unit != 0) /* Only one unit */
+ return(0);
+ return(1);
+}
+
+static void
+scsi_mach_init(sc)
+ struct ncr_softc *sc;
+{
+ register int i;
+ intr_disable(IR_SCSI1);
+ i = intr_establish(SOFTINT, ncr_soft_intr, sc, sc->sc_dev.dv_xname,
+ IPL_BIO, 0);
+ intr_establish(IR_SCSI1, ncr_intr, (void *)i, sc->sc_dev.dv_xname,
+ IPL_BIO, RISING_EDGE);
+ printf(" addr 0x%x, irq %d", NCR5380, IR_SCSI1);
+}
+
+/*
+ * 5380 interrupt.
+ */
+static void
+ncr_intr(softint)
+ void *softint;
+{
+ int ctrlr;
+
+ ctrlr = scsi_select_ctlr(DP8490);
+ if (NCR5380->ncr_dmstat & SC_IRQ_SET) {
+ intr_disable(IR_SCSI1);
+ softintr((int)softint);
+ }
+ scsi_select_ctlr(ctrlr);
+}
+
+static void
+ncr_soft_intr(sc)
+ void *sc;
+{
+ int ctrlr = scsi_select_ctlr(DP8490);
+ ncr_ctrl_intr(sc);
+ scsi_select_ctlr(ctrlr);
+}
+
+/*
+ * PDMA stuff
+ */
+#define movsd(from, to, n) do { \
+ register int r0 __asm ("r0") = n; \
+ register u_char *r1 __asm("r1") = from; \
+ register u_char *r2 __asm("r2") = to; \
+ __asm volatile ("movsd" \
+ : "=r" (r1), "=r" (r2) \
+ : "0" (r1), "1" (r2), "r" (r0) \
+ : "r0", "memory" \
+ ); \
+ from = r1; to = r2; \
+ } while (0)
+
+#define movsb(from, to, n) do { \
+ register int r0 __asm ("r0") = n; \
+ register u_char *r1 __asm("r1") = from; \
+ register u_char *r2 __asm("r2") = to; \
+ __asm volatile ("movsb" \
+ : "=r" (r1), "=r" (r2) \
+ : "0" (r1), "1" (r2), "r" (r0) \
+ : "r0", "memory" \
+ ); \
+ from = r1; to = r2; \
+ } while (0)
+
+#define TIMEOUT 1000000
+#define READY(dataout) do { \
+ for (i = TIMEOUT; i > 0; i --) { \
+ /*if (!(NCR5380->ncr_dmstat & SC_PHS_MTCH)) {*/ \
+ if (NCR5380->ncr_dmstat & SC_IRQ_SET) { \
+ if (dataout) NCR5380->ncr_icom &= ~SC_ADTB; \
+ NCR5380->ncr_mode &= ~SC_M_DMA; \
+ *count = len; \
+ if ((idstat = NCR5380->ncr_idstat) & SC_S_REQ) \
+ *phase = (idstat >> 2) & 7; \
+ else \
+ *phase = NR_PHASE; \
+ return(1); \
+ } \
+ if (NCR5380->ncr_dmstat & SC_DMA_REQ) break; \
+ delay(1); \
+ } \
+ if (i <= 0) panic("ncr0: pdma timeout"); \
+ } while (0)
+
+#define byte_data ((volatile u_char *)pdma)
+#define word_data ((volatile u_short *)pdma)
+#define long_data ((volatile u_long *)pdma)
+
+#define W1(n) *byte_data = *(data + n)
+#define W2(n) *word_data = *((u_short *)data + n)
+#define W4(n) *long_data = *((u_long *)data + n)
+#define R1(n) *(data + n) = *byte_data
+#define R4(n) *((u_long *)data + n) = *long_data
+
+static int
+transfer_pdma(phase, data, count)
+ u_char *phase;
+ u_char *data;
+ u_long *count;
+{
+ register volatile u_char *pdma = PDMA_ADDRESS;
+ register int len = *count, i, idstat;
+
+ if (len < 256) {
+ __asm volatile ("lmr ivar0,%0" : : "g" (data));
+ transfer_pio(phase, data, count, 0);
+ return(1);
+ }
+ NCR5380->ncr_tcom = *phase;
+ scsi_clr_ipend();
+ if (PH_IN(*phase)) {
+ NCR5380->ncr_icom = 0;
+ NCR5380->ncr_mode = IMODE_BASE | SC_M_DMA;
+ NCR5380->ncr_ircv = 0;
+ while (len >= 256) {
+ if (!((u_long) data & 0xfff))
+ __asm volatile ("lmr ivar0,%0" : : "g" (data));
+ READY(0);
+ di();
+ movsd((u_char *)pdma, data, 64);
+ len -= 256;
+ ei();
+ }
+ if (len) {
+ di();
+ while (len) {
+ READY(0);
+ R1(0);
+ data++;
+ len--;
+ }
+ ei();
+ }
+ } else {
+ NCR5380->ncr_mode = IMODE_BASE | SC_M_DMA;
+ NCR5380->ncr_icom = SC_ADTB;
+ NCR5380->ncr_dmstat = SC_S_SEND;
+ while (len >= 256) {
+ /* The second ready is to
+ * compensate for DMA-prefetch.
+ * Since we adjust len only at
+ * the end of the block, there
+ * is no need to correct the
+ * residue.
+ */
+ READY(1);
+ di();
+ W1(0); READY(1); W1(1); W2(1);
+ data += 4;
+ movsd(data, (u_char *)pdma, 63);
+ ei();
+ len -= 256;
+ }
+ if (len) {
+ READY(1);
+ di();
+ while (len) {
+ W1(0);
+ READY(1);
+ data++;
+ len--;
+ }
+ ei();
+ }
+ i = TIMEOUT;
+ while (((NCR5380->ncr_dmstat & (SC_DMA_REQ|SC_PHS_MTCH))
+ == SC_PHS_MTCH) && --i);
+ if (!i)
+ printf("ncr0: timeout waiting for SC_DMA_REQ.\n");
+ *byte_data = 0;
+ }
+
+ncr_timeout_error:
+ NCR5380->ncr_mode &= ~SC_M_DMA;
+ if((idstat = NCR5380->ncr_idstat) & SC_S_REQ)
+ *phase = (idstat >> 2) & 7;
+ else
+ *phase = NR_PHASE;
+ *count = len;
+ return(1);
+}
+
+/*
+ * Last but not least... Include the general driver code
+ */
+#include "ncr5380.c"
diff --git a/sys/arch/pc532/dev/ncr5380.c b/sys/arch/pc532/dev/ncr5380.c
new file mode 100644
index 00000000000..cbc267873c7
--- /dev/null
+++ b/sys/arch/pc532/dev/ncr5380.c
@@ -0,0 +1,1907 @@
+/* $NetBSD: ncr5380.c,v 1.5 1995/10/10 08:08:01 phil Exp $ */
+
+/*
+ * Copyright (c) 1995 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.
+ */
+
+
+#ifdef DBG_NOSTATIC
+# define static
+#endif
+#ifdef DBG_SEL
+# define DBG_SELPRINT(a,b) printf(a,b)
+#else
+# define DBG_SELPRINT(a,b)
+#endif
+#ifdef DBG_PIO
+# define DBG_PIOPRINT(a,b,c) printf(a,b,c)
+#else
+# define DBG_PIOPRINT(a,b,c)
+#endif
+#ifdef DBG_INF
+# define DBG_INFPRINT(a,b,c) a(b,c)
+#else
+# define DBG_INFPRINT(a,b,c)
+#endif
+#ifdef DBG_PID
+ static char *last_hit = NULL, *olast_hit = NULL;
+# define PID(a) olast_hit = last_hit; last_hit = a;
+#else
+# define PID(a)
+#endif
+
+/*
+ * Bit mask of targets you want debugging to be shown
+ */
+u_char dbg_target_mask = 0x7f;
+
+/*
+ * Set bit for target when parity checking must be disabled.
+ * My (LWP) Maxtor 7245S seems to generate parity errors on about 50%
+ * of all transfers while the data is correct!?
+ */
+u_char ncr5380_no_parchk = 0xff;
+
+/*
+ * This is the default sense-command we send.
+ */
+static u_char sense_cmd[] = {
+ REQUEST_SENSE, 0, 0, 0, sizeof(struct scsi_sense_data), 0
+};
+
+/*
+ * True if the main co-routine is running
+ */
+static volatile int main_running = 0;
+
+/*
+ * Mask of targets selected
+ */
+static u_char busy;
+
+static void ncr5380_minphys(struct buf *bp);
+static int ncr5380_scsi_cmd(struct scsi_xfer *xs);
+static int ncr5380_show_scsi_cmd(struct scsi_xfer *xs);
+
+struct scsi_adapter ncr5380_switch = {
+ ncr5380_scsi_cmd, /* scsi_cmd() */
+ ncr5380_minphys, /* scsi_minphys() */
+ 0, /* open_target_lu() */
+ 0 /* close_target_lu() */
+};
+
+struct scsi_device ncr5380_dev = {
+ NULL, /* use default error handler */
+ NULL, /* do not have a start functio */
+ NULL, /* have no async handler */
+ NULL /* Use default done routine */
+};
+
+
+static SC_REQ req_queue[NREQ];
+static SC_REQ *free_head = NULL; /* Free request structures */
+
+
+/*
+ * Inline functions:
+ */
+
+/*
+ * Determine the size of a SCSI command.
+ */
+extern __inline__ int command_size(opcode)
+u_char opcode;
+{
+ switch ((opcode >> 4) & 0xf) {
+ case 0:
+ case 1:
+ return (6);
+ case 2:
+ case 3:
+ return (10);
+ }
+ return (12);
+}
+
+
+/*
+ * Wait for request-line to become active. When it doesn't return 0.
+ * Otherwise return != 0.
+ * The timeouts in the 'wait_req_*' functions are arbitrary and rather
+ * large. In 99% of the invocations nearly no timeout is needed but in
+ * some cases (especially when using my tapedrive, a Tandberg 3600) the
+ * device is busy internally and the first SCSI-phase will be delayed.
+ */
+extern __inline__ int wait_req_true(void)
+{
+ int timeout = 25000;
+
+ while (!(GET_5380_REG(NCR5380_IDSTAT) & SC_S_REQ) && --timeout)
+ delay(1);
+ return (GET_5380_REG(NCR5380_IDSTAT) & SC_S_REQ);
+}
+
+/*
+ * Wait for request-line to become inactive. When it doesn't return 0.
+ * Otherwise return != 0.
+ */
+extern __inline__ int wait_req_false(void)
+{
+ int timeout = 25000;
+
+ while ((GET_5380_REG(NCR5380_IDSTAT) & SC_S_REQ) && --timeout)
+ delay(1);
+ return (!(GET_5380_REG(NCR5380_IDSTAT) & SC_S_REQ));
+}
+
+extern __inline__ void ack_message()
+{
+ SET_5380_REG(NCR5380_ICOM, 0);
+}
+
+extern __inline__ void nack_message(SC_REQ *reqp)
+{
+ SET_5380_REG(NCR5380_ICOM, SC_A_ATN);
+ reqp->msgout = MSG_ABORT;
+}
+
+extern __inline__ void finish_req(SC_REQ *reqp)
+{
+ int sps;
+ struct scsi_xfer *xs = reqp->xs;
+
+#ifdef REAL_DMA
+ /*
+ * If we bounced, free the bounce buffer
+ */
+ if (reqp->dr_flag & DRIVER_BOUNCING)
+ free_bounceb(reqp->bounceb);
+#endif /* REAL_DMA */
+#ifdef DBG_REQ
+ if (dbg_target_mask & (1 << reqp->targ_id))
+ show_request(reqp, "DONE");
+#endif
+#ifdef DBG_ERR_RET
+ if (reqp->xs->error != 0)
+ show_request(reqp, "ERR_RET");
+#endif
+
+ /*
+ * Return request to free-q
+ */
+ sps = splbio();
+ reqp->next = free_head;
+ free_head = reqp;
+ splx(sps);
+
+ xs->flags |= ITSDONE;
+ scsi_done(xs);
+}
+
+/*
+ * Auto config stuff....
+ */
+int ncr_cprint __P((void *auxp, char *));
+void ncr_attach __P((struct device *, struct device *, void *));
+int ncr_match __P((struct device *, struct cfdata *, void *));
+
+/*
+ * Tricks to make driver-name configurable
+ */
+#define CFNAME(n) __CONCAT(n,cd)
+#define CFSTRING(n) __STRING(n)
+
+struct cfdriver CFNAME(DRNAME) = {
+ NULL, CFSTRING(DRNAME), (cfmatch_t)ncr_match, ncr_attach,
+ DV_DULL, sizeof(struct ncr_softc), NULL, 0 };
+
+int
+ncr_match(pdp, cdp, auxp)
+struct device *pdp;
+struct cfdata *cdp;
+void *auxp;
+{
+ return (machine_match(pdp, cdp, auxp, &CFNAME(DRNAME)));
+}
+
+void
+ncr_attach(pdp, dp, auxp)
+struct device *pdp, *dp;
+void *auxp;
+{
+ struct ncr_softc *sc;
+ int i;
+
+ sc = (struct ncr_softc *)dp;
+
+ sc->sc_link.adapter_softc = sc;
+ sc->sc_link.adapter_target = 7;
+ sc->sc_link.adapter = &ncr5380_switch;
+ sc->sc_link.device = &ncr5380_dev;
+ sc->sc_link.openings = NREQ - 1;
+
+ /*
+ * bitmasks
+ */
+ sc->sc_noselatn = 0;
+ sc->sc_selected = 0;
+
+ /*
+ * Initialize machine-type specific things...
+ */
+ scsi_mach_init(sc);
+ printf("\n");
+
+ /*
+ * Initialize request queue freelist.
+ */
+ for (i = 0; i < NREQ; i++) {
+ req_queue[i].next = free_head;
+ free_head = &req_queue[i];
+ }
+
+ /*
+ * Initialize the host adapter
+ */
+ scsi_idisable();
+ ENABLE_NCR5380(sc);
+ SET_5380_REG(NCR5380_ICOM, 0);
+ SET_5380_REG(NCR5380_MODE, IMODE_BASE);
+ SET_5380_REG(NCR5380_TCOM, 0);
+ SET_5380_REG(NCR5380_IDSTAT, 0);
+ scsi_ienable();
+
+ /*
+ * attach all scsi units on us
+ */
+ config_found(dp, &sc->sc_link, ncr_cprint);
+}
+
+/*
+ * print diag if name is NULL else just extra
+ */
+int
+ncr_cprint(auxp, name)
+void *auxp;
+char *name;
+{
+ if (name == NULL)
+ return (UNCONF);
+ return (QUIET);
+}
+/*
+ * End of auto config stuff....
+ */
+
+/*
+ * Carry out a request from the high level driver.
+ */
+static int
+ncr5380_scsi_cmd(struct scsi_xfer *xs)
+{
+ int sps;
+ SC_REQ *reqp;
+ int flags = xs->flags;
+
+ /*
+ * We do not queue RESET commands
+ */
+ if (flags & SCSI_RESET) {
+ scsi_reset(xs->sc_link->adapter_softc);
+ return (COMPLETE);
+ }
+
+ /*
+ * Get a request block
+ */
+ sps = splbio();
+ if ((reqp = free_head) == 0) {
+ splx(sps);
+ return (TRY_AGAIN_LATER);
+ }
+ free_head = reqp->next;
+ reqp->next = NULL;
+ splx(sps);
+
+ /*
+ * Initialize our private fields
+ */
+ reqp->dr_flag = (flags & SCSI_POLL) ? DRIVER_NOINT : 0;
+ reqp->phase = NR_PHASE;
+ reqp->msgout = MSG_NOOP;
+ reqp->status = SCSGOOD;
+ reqp->link = NULL;
+ reqp->xs = xs;
+ reqp->targ_id = xs->sc_link->target;
+ reqp->targ_lun = xs->sc_link->lun;
+ reqp->xdata_ptr = (u_char*)xs->data;
+ reqp->xdata_len = xs->datalen;
+ bcopy(xs->cmd, &reqp->xcmd, sizeof(struct scsi_generic));
+ reqp->xcmd.bytes[0] |= reqp->targ_lun << 5;
+
+ /*
+ * Sanity check on flags...
+ */
+ if (flags & ITSDONE) {
+ ncr_tprint(reqp, "scsi_cmd: command already done.....\n");
+ xs->flags &= ~ITSDONE;
+ }
+ if (!(flags & INUSE)) {
+ ncr_tprint(reqp, "scsi_cmd: command not in use.....\n");
+ xs->flags |= ~INUSE;
+ }
+
+#ifdef REAL_DMA
+ /*
+ * Check if DMA can be used on this request
+ */
+ if (scsi_dmaok(reqp))
+ reqp->dr_flag |= DRIVER_DMAOK;
+#endif /* REAL_DMA */
+
+ /*
+ * Insert the command into the issue queue. Note that 'REQUEST SENSE'
+ * commands are inserted at the head of the queue since any command
+ * will clear the existing contingent allegience condition and the sense
+ * data is only valid while the condition exists.
+ * When possible, link the command to a previous command to the same
+ * target. This is not very sensible when AUTO_SENSE is not defined!
+ * Interrupts are disabled while we are fiddling with the issue-queue.
+ */
+ sps = splbio();
+ if ((issue_q == NULL) || (reqp->xcmd.opcode == REQUEST_SENSE)) {
+ reqp->next = issue_q;
+ issue_q = reqp;
+ }
+ else {
+ SC_REQ *tmp, *link;
+
+ tmp = issue_q;
+ link = NULL;
+ do {
+ if (!link && (tmp->targ_id == reqp->targ_id) && !tmp->link)
+ link = tmp;
+ } while (tmp->next && (tmp = tmp->next));
+ tmp->next = reqp;
+#ifdef AUTO_SENSE
+ if (link) {
+ link->link = reqp;
+ link->xcmd.bytes[link->xs->cmdlen-1] |= 1;
+ }
+#endif
+ }
+ splx(sps);
+
+#ifdef DBG_REQ
+ if (dbg_target_mask & (1 << reqp->targ_id))
+ show_request(reqp, (reqp->xcmd.opcode == REQUEST_SENSE) ?
+ "HEAD":"TAIL");
+#endif
+
+ run_main(xs->sc_link->adapter_softc);
+
+ if (xs->flags & SCSI_POLL)
+ return (COMPLETE); /* We're booting */
+ return (SUCCESSFULLY_QUEUED);
+}
+
+#define MIN_PHYS 65536 /*BARF!!!!*/
+static void
+ncr5380_minphys(struct buf *bp)
+{
+ if (bp->b_bcount > MIN_PHYS)
+ bp->b_bcount = MIN_PHYS;
+ minphys(bp);
+}
+#undef MIN_PHYS
+
+static int
+ncr5380_show_scsi_cmd(struct scsi_xfer *xs)
+{
+ u_char *b = (u_char *) xs->cmd;
+ int i = 0;
+
+ if (!(xs->flags & SCSI_RESET)) {
+ printf("(%d:%d:%d,0x%x)-", xs->sc_link->scsibus,
+ xs->sc_link->target, xs->sc_link->lun, xs->sc_link->flags);
+ while (i < xs->cmdlen) {
+ if (i)
+ printf(",");
+ printf("%x",b[i++]);
+ }
+ printf("-\n");
+ }
+ else {
+ printf("(%d:%d:%d)-RESET-\n",
+ xs->sc_link->scsibus,xs->sc_link->target, xs->sc_link->lun);
+ }
+}
+
+/*
+ * The body of the driver.
+ */
+static void
+scsi_main(sc)
+struct ncr_softc *sc;
+{
+ SC_REQ *req, *prev;
+ int itype;
+ int sps;
+
+ /*
+ * While running in the driver SCSI-interrupts are disabled.
+ */
+ scsi_idisable();
+ ENABLE_NCR5380(sc);
+
+ PID("scsi_main1");
+ for (;;) {
+ sps = splbio();
+ if (!connected) {
+ /*
+ * Check if it is fair keep any exclusive access to DMA
+ * claimed. If not, stop queueing new jobs so the discon_q
+ * will be eventually drained and DMA can be given up.
+ */
+ if (!fair_to_keep_dma())
+ goto main_exit;
+
+ /*
+ * Search through the issue-queue for a command
+ * destined for a target that isn't busy.
+ */
+ prev = NULL;
+ for (req=issue_q; req != NULL; prev = req, req = req->next) {
+ if (!(busy & (1 << req->targ_id))) {
+ /*
+ * Found one, remove it from the issue queue
+ */
+ if (prev == NULL)
+ issue_q = req->next;
+ else prev->next = req->next;
+ req->next = NULL;
+ break;
+ }
+ }
+
+ /*
+ * When a request has just ended, we get here before an other
+ * device detects that the bus is free and that it can
+ * reconnect. The problem is that when this happens, we always
+ * baffle the device because our (initiator) id is higher. This
+ * can cause a sort of starvation on slow devices. So we check
+ * for a pending reselection here.
+ * Note that 'connected' will be non-null if the reselection
+ * succeeds.
+ */
+ if ((GET_5380_REG(NCR5380_IDSTAT) & (SC_S_SEL|SC_S_IO))
+ == (SC_S_SEL|SC_S_IO)){
+ if (req != NULL) {
+ req->next = issue_q;
+ issue_q = req;
+ }
+ splx(sps);
+
+ reselect(sc);
+ scsi_clr_ipend();
+ goto connected;
+ }
+
+ /*
+ * The host is not connected and there is no request
+ * pending, exit.
+ */
+ if (req == NULL) {
+ PID("scsi_main2");
+ goto main_exit;
+ }
+
+ /*
+ * Re-enable interrupts before handling the request.
+ */
+ splx(sps);
+
+#ifdef DBG_REQ
+ if (dbg_target_mask & (1 << req->targ_id))
+ show_request(req, "TARGET");
+#endif
+ /*
+ * We found a request. Try to connect to the target. If the
+ * initiator fails arbitration, the command is put back in the
+ * issue queue.
+ */
+ if (scsi_select(req, 0)) {
+ sps = splbio();
+ req->next = issue_q;
+ issue_q = req;
+ splx(sps);
+#ifdef DBG_REQ
+ if (dbg_target_mask & (1 << req->targ_id))
+ ncr_tprint(req, "Select failed\n");
+#endif
+ }
+ }
+ else splx(sps);
+connected:
+ if (connected) {
+ /*
+ * If the host is currently connected but a 'real-dma' transfer
+ * is in progress, the 'end-of-dma' interrupt restarts main.
+ * So quit.
+ */
+ sps = splbio();
+ if (connected && (connected->dr_flag & DRIVER_IN_DMA)) {
+ PID("scsi_main3");
+ goto main_exit;
+ }
+ splx(sps);
+
+ /*
+ * Let the target guide us through the bus-phases
+ */
+ while (information_transfer() == -1)
+ ;
+ }
+ }
+ /* NEVER TO REACH HERE */
+ panic("ncr5380-SCSI: not designed to come here");
+
+main_exit:
+ /*
+ * We enter here with interrupts disabled. We are about to exit main
+ * so interrupts should be re-enabled. Because interrupts are edge
+ * triggered, we could already have missed the interrupt. Therefore
+ * we check the IRQ-line here and re-enter when we really missed a
+ * valid interrupt.
+ */
+ PID("scsi_main4");
+ scsi_ienable();
+ SET_5380_REG(NCR5380_IDSTAT, SC_HOST_ID);
+ if (GET_5380_REG(NCR5380_DMSTAT) & SC_IRQ_SET) {
+ if ((itype = check_intr(sc)) != INTR_SPURIOUS) {
+ scsi_idisable();
+ splx(sps);
+
+ if (itype == INTR_RESEL)
+ reselect(sc);
+#ifdef REAL_DMA
+ else dma_ready();
+#else
+ else {
+ if (pdma_ready())
+ goto connected;
+ panic("Got DMA interrupt without DMA");
+ }
+#endif
+ scsi_clr_ipend();
+ goto connected;
+ }
+ }
+ reconsider_dma();
+
+ main_running = 0;
+ splx(sps);
+ PID("scsi_main5");
+}
+
+#ifdef REAL_DMA
+/*
+ * The SCSI-DMA interrupt.
+ * This interrupt can only be triggered when running in non-polled DMA
+ * mode. When DMA is not active, it will be silently ignored, it is usually
+ * to late because the EOP interrupt of the controller happens just a tiny
+ * bit earlier. It might become usefull when scatter/gather is implemented,
+ * because in that case only part of the DATAIN/DATAOUT transfer is taken
+ * out of a single buffer.
+ */
+static void
+ncr_dma_intr(sc)
+struct ncr_softc *sc;
+{
+ SC_REQ *reqp;
+ int dma_done;
+
+ PID("ncr_dma_intr");
+ if ((reqp = connected) && (reqp->dr_flag & DRIVER_IN_DMA)) {
+ scsi_idisable();
+ if (!(dma_done = dma_ready())) {
+ transfer_dma(reqp, reqp->phase, 0);
+ return;
+ }
+ run_main(sc);
+ }
+}
+#endif /* REAL_DMA */
+
+/*
+ * The SCSI-controller interrupt. This interrupt occurs on reselections and
+ * at the end of non-polled DMA-interrupts. It is assumed to be called from
+ * the machine-dependent hardware interrupt.
+ */
+static void
+ncr_ctrl_intr(sc)
+struct ncr_softc *sc;
+{
+ int itype;
+ int dma_done;
+
+ while (GET_5380_REG(NCR5380_DMSTAT) & SC_IRQ_SET) {
+ scsi_idisable();
+ if ((itype = check_intr(sc)) != INTR_SPURIOUS) {
+ if (itype == INTR_RESEL)
+ reselect(sc);
+ else {
+#ifdef REAL_DMA
+ if (!(dma_done = dma_ready())) {
+ transfer_dma(connected, connected->phase, 0);
+ return;
+ }
+#else
+ if (pdma_ready())
+ return;
+ panic("Got DMA interrupt without DMA\n");
+#endif
+ }
+ scsi_clr_ipend();
+ }
+ run_main(sc);
+ return;
+ }
+ PID("ncr_ctrl_intr1");
+}
+
+/*
+ * Initiate a connection path between the host and the target. The function
+ * first goes into arbitration for the SCSI-bus. When this succeeds, the target
+ * is selected and an 'IDENTIFY' message is send.
+ * Returns -1 when the arbitration failed. Otherwise 0 is returned. When
+ * the target does not respond (to either selection or 'MESSAGE OUT') the
+ * 'done' function is executed.
+ * The result code given by the driver can be influenced by setting 'code'
+ * to a non-zero value. This is the case when 'select' is called by abort.
+ */
+static int
+scsi_select(reqp, code)
+SC_REQ *reqp;
+{
+ u_long timeout;
+ u_char tmp[1];
+ u_char phase;
+ u_long cnt;
+ int sps;
+ u_int8_t atn_flag;
+ u_int8_t targ_bit;
+ struct ncr_softc *sc;
+
+ sc = reqp->xs->sc_link->adapter_softc;
+ DBG_SELPRINT ("Starting arbitration\n", 0);
+ PID("scsi_select1");
+
+ sps = splbio();
+
+ /*
+ * Prevent a race condition here. If a reslection interrupt occurred
+ * between the decision to pick a new request and the call to select,
+ * we abort the selection.
+ * Interrupts are lowered when the 5380 is setup to arbitrate for the
+ * bus.
+ */
+ if (connected || (GET_5380_REG(NCR5380_IDSTAT) & SC_S_BSY)) {
+ splx(sps);
+ PID("scsi_select2");
+ return (-1);
+ }
+
+ /*
+ * Set phase bits to 0, otherwise the 5380 won't drive the bus during
+ * selection.
+ */
+ SET_5380_REG(NCR5380_TCOM, 0);
+ SET_5380_REG(NCR5380_ICOM, 0);
+
+ /*
+ * Arbitrate for the bus.
+ */
+ SET_5380_REG(NCR5380_DATA, SC_HOST_ID);
+ SET_5380_REG(NCR5380_MODE, SC_ARBIT);
+
+ splx(sps);
+
+ cnt = 10000;
+ while (!(GET_5380_REG(NCR5380_ICOM) & SC_AIP) && --cnt)
+ delay(1);
+
+ if (!(GET_5380_REG(NCR5380_ICOM) & SC_AIP)) {
+ SET_5380_REG(NCR5380_MODE, IMODE_BASE);
+ delay(1);
+ PID("scsi_select3");
+
+ if (GET_5380_REG(NCR5380_IDSTAT) & SC_S_BSY) {
+ /*
+ * Damn, we have a connected target that we don't know
+ * of. Some targets seem to respond to a selection
+ * AFTER the selection-timeout. Try to get the target
+ * into the Message-out phase so we can send an ABORT
+ * message. We try to avoid resetting the SCSI-bus!
+ */
+ if (!reach_msg_out(sc, sizeof(struct scsi_generic))) {
+ u_long len = 1;
+ u_char phase = PH_MSGOUT;
+ u_char msg = MSG_ABORT;
+
+ transfer_pio(&phase, &msg, &len, 0);
+ }
+ else if (GET_5380_REG(NCR5380_IDSTAT) & SC_S_BSY)
+ scsi_reset(sc);
+ }
+ PID("scsi_select4");
+ return (-1);
+ }
+
+ /* The arbitration delay is 2.2 usecs */
+ delay(3);
+
+ /*
+ * Check the result of the arbitration. If we failed, return -1.
+ */
+ if (GET_5380_REG(NCR5380_ICOM) & SC_LA) {
+ /*
+ * The spec requires that we should read the data register to
+ * check for higher id's and check the SC_LA again.
+ */
+ tmp[0] = GET_5380_REG(NCR5380_DATA);
+ if (GET_5380_REG(NCR5380_ICOM) & SC_LA) {
+ SET_5380_REG(NCR5380_MODE, IMODE_BASE);
+ SET_5380_REG(NCR5380_ICOM, 0);
+ DBG_SELPRINT ("Arbitration lost,deassert SC_ARBIT\n",0);
+ PID("scsi_select5");
+ return (-1);
+ }
+ }
+ SET_5380_REG(NCR5380_ICOM, SC_A_SEL | SC_A_BSY);
+ if (GET_5380_REG(NCR5380_ICOM) & SC_LA) {
+ SET_5380_REG(NCR5380_MODE, IMODE_BASE);
+ SET_5380_REG(NCR5380_ICOM, 0);
+ DBG_SELPRINT ("Arbitration lost, deassert SC_A_SEL\n", 0);
+ PID("scsi_select6");
+ return (-1);
+ }
+ /* Bus settle delay + Bus clear delay = 1.2 usecs */
+ delay(2);
+ DBG_SELPRINT ("Arbitration complete\n", 0);
+
+ targ_bit = 1 << reqp->targ_id;
+
+ /*
+ * Now that we won the arbitration, start the selection.
+ */
+ SET_5380_REG(NCR5380_DATA, SC_HOST_ID | targ_bit);
+
+ if (sc->sc_noselatn & targ_bit)
+ atn_flag = 0;
+ else
+ atn_flag = SC_A_ATN;
+
+ /*
+ * Raise ATN while SEL is true before BSY goes false from arbitration,
+ * since this is the only way to guarantee that we'll get a MESSAGE OUT
+ * phase immediately after the selection.
+ */
+ SET_5380_REG(NCR5380_ICOM, SC_A_BSY | SC_A_SEL | atn_flag | SC_ADTB);
+ SET_5380_REG(NCR5380_MODE, IMODE_BASE);
+
+ /*
+ * Turn off reselection interrupts
+ */
+ SET_5380_REG(NCR5380_IDSTAT, 0);
+
+ /*
+ * Reset BSY. The delay following it, surpresses a glitch in the
+ * 5380 which causes us to see our own BSY signal instead of that of
+ * the target.
+ */
+ SET_5380_REG(NCR5380_ICOM, SC_A_SEL | atn_flag | SC_ADTB);
+ delay(1);
+
+ /*
+ * Wait for the target to react, the specs call for a timeout of
+ * 250 ms.
+ */
+ cnt = 25000 /* 250 */;
+ while (!(GET_5380_REG(NCR5380_IDSTAT) & SC_S_BSY) && --cnt)
+ delay(10);
+
+ if (!(GET_5380_REG(NCR5380_IDSTAT) & SC_S_BSY)) {
+ /*
+ * There is no reaction from the target, start the selection
+ * timeout procedure. We release the databus but keep SEL
+ * asserted. After that we wait a 'selection abort time' (200
+ * usecs) and 2 deskew delays (90 ns) and check BSY again.
+ * When BSY is asserted, we assume the selection succeeded,
+ * otherwise we release the bus.
+ */
+ SET_5380_REG(NCR5380_ICOM, SC_A_SEL | SC_A_ATN);
+ delay(201);
+ if (!(GET_5380_REG(NCR5380_IDSTAT) & SC_S_BSY)) {
+ SET_5380_REG(NCR5380_ICOM, 0);
+ reqp->xs->error = code ? code : XS_SELTIMEOUT;
+ DBG_SELPRINT ("Target %d not responding to sel\n",
+ reqp->targ_id);
+ finish_req(reqp);
+ PID("scsi_select7");
+ return (0);
+ }
+ }
+ SET_5380_REG(NCR5380_ICOM, atn_flag);
+
+ DBG_SELPRINT ("Target %d responding to select.\n", reqp->targ_id);
+
+ /*
+ * The SCSI-interrupts are disabled while a request is being handled.
+ */
+ scsi_idisable();
+
+ /*
+ * If we did not request ATN, then don't try to send IDENTIFY.
+ */
+ if (atn_flag == 0) {
+ reqp->phase = PH_CMD;
+ goto identify_failed;
+ }
+
+ /*
+ * Here we prepare to send an 'IDENTIFY' message.
+ * Allow disconnect only when interrups are allowed.
+ */
+ tmp[0] = MSG_IDENTIFY(reqp->targ_lun,
+ (reqp->dr_flag & DRIVER_NOINT) ? 0 : 0);
+ cnt = 1;
+ phase = PH_MSGOUT;
+
+ /*
+ * Since we followed the SCSI-spec and raised ATN while SEL was true
+ * but before BSY was false during the selection, a 'MESSAGE OUT'
+ * phase should follow. Unfortunately, this does not happen on
+ * all targets (Asante ethernet devices, for example), so we must
+ * check the actual mode if the message transfer fails--if the
+ * new phase is PH_CMD and has never been successfully selected
+ * w/ATN in the past, then we assume that it is an old device
+ * that doesn't support select w/ATN.
+ */
+ if (transfer_pio(&phase, tmp, &cnt, 0) || cnt) {
+
+ if ((phase == PH_CMD) && !(sc->sc_selected & targ_bit)) {
+ DBG_SELPRINT ("Target %d: not responding to ATN.\n",
+ reqp->targ_id);
+ sc->sc_noselatn |= targ_bit;
+ reqp->phase = PH_CMD;
+ goto identify_failed;
+ }
+
+ DBG_SELPRINT ("Target %d: failed to send identify\n",
+ reqp->targ_id);
+ /*
+ * Try to disconnect from the target. We cannot leave
+ * it just hanging here.
+ */
+ if (!reach_msg_out(sc, sizeof(struct scsi_generic))) {
+ u_long len = 1;
+ u_char phase = PH_MSGOUT;
+ u_char msg = MSG_ABORT;
+
+ transfer_pio(&phase, &msg, &len, 0);
+ }
+ else scsi_reset(sc);
+
+ SET_5380_REG(NCR5380_ICOM, 0);
+ reqp->xs->error = code ? code : XS_DRIVER_STUFFUP;
+ finish_req(reqp);
+ PID("scsi_select8");
+ return (0);
+ }
+ reqp->phase = PH_MSGOUT;
+
+identify_failed:
+ sc->sc_selected |= targ_bit;
+
+#ifdef notyet /* LWP: Do we need timeouts in the driver? */
+ /*
+ * Command is connected, start timer ticking.
+ */
+ ccb_p->xtimeout = ccb_p->timeout + Lbolt;
+#endif
+
+ connected = reqp;
+ busy |= targ_bit;
+ PID("scsi_select9");
+ return (0);
+}
+
+/*
+ * Return codes:
+ * -1: quit main, trigger on interrupt
+ * 0: keep on running main.
+ */
+static int
+information_transfer()
+{
+ SC_REQ *reqp = connected;
+ u_char tmp, phase;
+ u_long len;
+
+ PID("info_transf1");
+ /*
+ * Clear pending interrupts from 5380-chip.
+ */
+ scsi_clr_ipend();
+
+ /*
+ * We only have a valid SCSI-phase when REQ is asserted. Something
+ * is deadly wrong when BSY has dropped.
+ */
+ tmp = GET_5380_REG(NCR5380_IDSTAT);
+
+ if (!(tmp & SC_S_BSY)) {
+ busy &= ~(1 << reqp->targ_id);
+ connected = NULL;
+ reqp->xs->error = XS_BUSY;
+ finish_req(reqp);
+ PID("info_transf2");
+ return (0);
+ }
+
+ if (tmp & SC_S_REQ) {
+ phase = (tmp >> 2) & 7;
+ if (phase != reqp->phase) {
+ reqp->phase = phase;
+ DBG_INFPRINT(show_phase, reqp, phase);
+ }
+ }
+ else return (-1);
+
+ switch (phase) {
+ case PH_DATAOUT:
+
+#ifdef DBG_NOWRITE
+ ncr_tprint(reqp, "NOWRITE set -- write attempt aborted.");
+ reqp->msgout = MSG_ABORT;
+ SET_5380_REG(NCR5380_ICOM, SC_A_ATN);
+ return (-1);
+#endif /* DBG_NOWRITE */
+ /*
+ * If this is the first write using DMA, fill
+ * the bounce buffer.
+ */
+ if (reqp->xdata_ptr == reqp->xs->data) { /* XXX */
+ if (reqp->dr_flag & DRIVER_BOUNCING)
+ bcopy(reqp->xdata_ptr, reqp->bounceb, reqp->xdata_len);
+ }
+
+ case PH_DATAIN:
+#ifdef REAL_DMA
+ if (reqp->dr_flag & DRIVER_DMAOK) {
+ int poll = REAL_DMA_POLL|(reqp->dr_flag & DRIVER_NOINT);
+ transfer_dma(reqp, phase, poll);
+ if (!poll)
+ return (0);
+ }
+ else
+#endif
+ {
+ PID("info_transf3");
+ len = reqp->xdata_len;
+#ifdef USE_PDMA
+ if (transfer_pdma(&phase, reqp->xdata_ptr, &len) == 0)
+ return (0);
+#else
+ transfer_pio(&phase, reqp->xdata_ptr, &len, 0);
+#endif
+ reqp->xdata_ptr += reqp->xdata_len - len;
+ reqp->xdata_len = len;
+ }
+ return (-1);
+ case PH_MSGIN:
+ /*
+ * We only expect single byte messages here.
+ */
+ len = 1;
+ transfer_pio(&phase, &tmp, &len, 1);
+ reqp->message = tmp;
+ return (handle_message(reqp, tmp));
+ case PH_MSGOUT:
+ len = 1;
+ transfer_pio(&phase, &reqp->msgout, &len, 0);
+ if (reqp->msgout == MSG_ABORT) {
+ busy &= ~(1 << reqp->targ_id);
+ connected = NULL;
+ reqp->xs->error = XS_DRIVER_STUFFUP;
+ finish_req(reqp);
+ PID("info_transf4");
+ return (0);
+ }
+ reqp->msgout = MSG_NOOP;
+ return (-1);
+ case PH_CMD :
+ len = command_size(reqp->xcmd.opcode);
+ transfer_pio(&phase, (u_char *)&reqp->xcmd, &len, 0);
+ PID("info_transf5");
+ return (-1);
+ case PH_STATUS:
+ len = 1;
+ transfer_pio(&phase, &tmp, &len, 0);
+ reqp->status = tmp;
+ PID("info_transf6");
+ return (-1);
+ default :
+ ncr_tprint(reqp, "Unknown phase\n");
+ }
+ PID("info_transf7");
+ return (-1);
+}
+
+/*
+ * Handle the message 'msg' send to us by the target.
+ * Return values:
+ * 0 : The current command has completed.
+ * -1 : Get on to the next phase.
+ */
+static int
+handle_message(reqp, msg)
+SC_REQ *reqp;
+u_int msg;
+{
+ int sps;
+
+ PID("hmessage1");
+ switch (msg) {
+ /*
+ * Linking lets us reduce the time required to get
+ * the next command to the device, skipping the arbitration
+ * and selection time. In the current implementation,
+ * we merely have to start the next command pointed
+ * to by 'next_link'.
+ */
+ case MSG_LINK_CMD_COMPLETE:
+ case MSG_LINK_CMD_COMPLETEF:
+ if (reqp->link == NULL) {
+ ncr_tprint(reqp, "No link for linked command");
+ nack_message(reqp);
+ PID("hmessage2");
+ return (-1);
+ }
+ ack_message();
+ reqp->xs->error = 0;
+
+#ifdef AUTO_SENSE
+ if (check_autosense(reqp, 0) == -1)
+ return (-1);
+#endif /* AUTO_SENSE */
+
+#ifdef DBG_REQ
+ if (dbg_target_mask & (1 << reqp->targ_id))
+ show_request(reqp->link, "LINK");
+#endif
+ connected = reqp->link;
+ finish_req(reqp);
+ PID("hmessage3");
+ return (-1);
+ case MSG_ABORT:
+ case MSG_CMDCOMPLETE:
+ ack_message();
+ connected = NULL;
+ busy &= ~(1 << reqp->targ_id);
+ if (!(reqp->dr_flag & DRIVER_AUTOSEN)) {
+ reqp->xs->resid = reqp->xdata_len;
+ reqp->xs->error = 0;
+ }
+
+#ifdef AUTO_SENSE
+ if (check_autosense(reqp, 0) == -1) {
+ PID("hmessage4");
+ return (0);
+ }
+#endif /* AUTO_SENSE */
+
+ finish_req(reqp);
+ PID("hmessage5");
+ return (0);
+ case MSG_MESSAGE_REJECT:
+ ack_message();
+ PID("hmessage6");
+ return (-1);
+ case MSG_DISCONNECT:
+ ack_message();
+#ifdef DBG_REQ
+ if (dbg_target_mask & (1 << reqp->targ_id))
+ show_request(reqp, "DISCON");
+#endif
+ sps = splbio();
+ connected = NULL;
+ reqp->next = discon_q;
+ discon_q = reqp;
+ splx(sps);
+ PID("hmessage7");
+ return (0);
+ case MSG_SAVEDATAPOINTER:
+ case MSG_RESTOREPOINTERS:
+ /*
+ * We save pointers implicitely at disconnect.
+ * So we can ignore these messages.
+ */
+ ack_message();
+ PID("hmessage8");
+ return (-1);
+ case MSG_EXTENDED:
+ nack_message(reqp);
+ PID("hmessage9");
+ return (-1);
+ default:
+ ncr_tprint(reqp, "Unkown message %x\n", msg);
+ return (-1);
+ }
+ PID("hmessage10");
+ return (-1);
+}
+
+/*
+ * Handle reselection. If a valid reconnection occurs, connected
+ * points at the reconnected command. The command is removed from the
+ * disconnected queue.
+ */
+static void
+reselect(sc)
+struct ncr_softc *sc;
+{
+ u_char phase;
+ u_long len;
+ u_char msg;
+ u_char target_mask;
+ int abort = 0;
+ SC_REQ *tmp, *prev;
+
+ PID("reselect1");
+ target_mask = GET_5380_REG(NCR5380_DATA) & ~SC_HOST_ID;
+
+ /*
+ * At this point, we have detected that our SCSI-id is on the bus,
+ * SEL is true and BSY was false for at least one bus settle
+ * delay (400 ns.).
+ * We must assert BSY ourselves, until the target drops the SEL signal.
+ * The SCSI-spec specifies no maximum time for this, so we have to
+ * choose something long enough to suit all targets.
+ */
+ SET_5380_REG(NCR5380_ICOM, SC_A_BSY);
+ len = 1000;
+ while ((GET_5380_REG(NCR5380_IDSTAT) & SC_S_SEL) && (len > 0)) {
+ delay(1);
+ len--;
+ }
+ if (GET_5380_REG(NCR5380_IDSTAT) & SC_S_SEL) {
+ /* Damn SEL isn't dropping */
+ scsi_reset(sc);
+ return;
+ }
+
+ SET_5380_REG(NCR5380_ICOM, 0);
+
+ /*
+ * Get the expected identify message.
+ */
+ phase = PH_MSGIN;
+ len = 1;
+ transfer_pio(&phase, &msg, &len, 0);
+ if (len || !MSG_ISIDENTIFY(msg)) {
+ ncr_aprint(sc, "Expecting IDENTIFY, got 0x%x\n", msg);
+ abort = 1;
+ }
+ else {
+ /*
+ * Find the command reconnecting
+ */
+ for (tmp = discon_q, prev = NULL; tmp; prev = tmp, tmp = tmp->next){
+ if (target_mask == (1 << tmp->targ_id)) {
+ if (prev)
+ prev->next = tmp->next;
+ else discon_q = tmp->next;
+ tmp->next = NULL;
+ break;
+ }
+ }
+ if (tmp == NULL) {
+ ncr_aprint(sc, "No disconnected job for targetmask %x\n",
+ target_mask);
+ abort = 1;
+ }
+ }
+ if (abort) {
+ msg = MSG_ABORT;
+ len = 1;
+ phase = PH_MSGOUT;
+
+ SET_5380_REG(NCR5380_ICOM, SC_A_ATN);
+ transfer_pio(&phase, &msg, &len, 0);
+ }
+ else {
+ connected = tmp;
+#ifdef DBG_REQ
+ if (dbg_target_mask & (1 << tmp->targ_id))
+ show_request(tmp, "RECON");
+#endif
+ }
+ PID("reselect2");
+}
+
+/*
+ * Transfer data in a given phase using programmed I/O.
+ * Returns -1 when a different phase is entered without transferring the
+ * maximum number of bytes, 0 if all bytes transferred or exit is in the same
+ * phase.
+ */
+static int
+transfer_pio(phase, data, len, dont_drop_ack)
+u_char *phase;
+u_char *data;
+u_long *len;
+int dont_drop_ack;
+{
+ u_int cnt = *len;
+ u_char ph = *phase;
+ u_char tmp, new_icom;
+
+ DBG_PIOPRINT ("SCSI: transfer_pio start: phase: %d, len: %d\n", ph,cnt);
+ PID("tpio1");
+ SET_5380_REG(NCR5380_TCOM, ph);
+ do {
+ if (!wait_req_true()) {
+ DBG_PIOPRINT ("SCSI: transfer_pio: missing REQ\n", 0, 0);
+ break;
+ }
+ if (((GET_5380_REG(NCR5380_IDSTAT) >> 2) & 7) != ph) {
+ DBG_PIOPRINT ("SCSI: transfer_pio: phase mismatch\n", 0, 0);
+ break;
+ }
+ if (PH_IN(ph)) {
+ *data++ = GET_5380_REG(NCR5380_DATA);
+ SET_5380_REG(NCR5380_ICOM, SC_A_ACK);
+ if ((cnt == 1) && dont_drop_ack)
+ new_icom = SC_A_ACK;
+ else new_icom = 0;
+ }
+ else {
+ SET_5380_REG(NCR5380_DATA, *data++);
+
+ /*
+ * The SCSI-standard suggests that in the 'MESSAGE OUT' phase,
+ * the initiator should drop ATN on the last byte of the
+ * message phase after REQ has been asserted for the handshake
+ * but before the initiator raises ACK.
+ */
+ if (!( (ph == PH_MSGOUT) && (cnt > 1) )) {
+ SET_5380_REG(NCR5380_ICOM, SC_ADTB);
+ SET_5380_REG(NCR5380_ICOM, SC_ADTB | SC_A_ACK);
+ new_icom = 0;
+ }
+ else {
+ SET_5380_REG(NCR5380_ICOM, SC_ADTB | SC_A_ATN);
+ SET_5380_REG(NCR5380_ICOM, SC_ADTB|SC_A_ATN|SC_A_ACK);
+ new_icom = SC_A_ATN;
+ }
+ }
+ if (!wait_req_false()) {
+ DBG_PIOPRINT ("SCSI: transfer_pio - REQ not dropping\n", 0, 0);
+ break;
+ }
+ SET_5380_REG(NCR5380_ICOM, new_icom);
+
+ } while (--cnt);
+
+ if ((tmp = GET_5380_REG(NCR5380_IDSTAT)) & SC_S_REQ)
+ *phase = (tmp >> 2) & 7;
+ else *phase = NR_PHASE;
+ *len = cnt;
+ DBG_PIOPRINT ("SCSI: transfer_pio done: phase: %d, len: %d\n",
+ *phase, cnt);
+ PID("tpio2");
+ if (!cnt || (*phase == ph))
+ return (0);
+ return (-1);
+}
+
+#ifdef REAL_DMA
+/*
+ * Start a DMA-transfer on the device using the current pointers.
+ * If 'poll' is true, the function busy-waits until DMA has completed.
+ */
+static void
+transfer_dma(reqp, phase, poll)
+SC_REQ *reqp;
+u_int phase;
+int poll;
+{
+ int dma_done;
+ u_char mbase = 0;
+ int sps;
+
+again:
+ PID("tdma1");
+
+ /*
+ * We should be in phase, otherwise we are not allowed to
+ * drive the bus.
+ */
+ SET_5380_REG(NCR5380_TCOM, phase);
+
+ /*
+ * Defer interrupts until DMA is fully running.
+ */
+ sps = splbio();
+
+ /*
+ * Clear pending interrupts and parity errors.
+ */
+ scsi_clr_ipend();
+
+ if (!poll) {
+ /*
+ * Enable SCSI interrupts and set IN_DMA flag, set 'mbase'
+ * to the interrupts we want enabled.
+ */
+ scsi_ienable();
+ reqp->dr_flag |= DRIVER_IN_DMA;
+ mbase = SC_E_EOPI | SC_MON_BSY;
+ }
+ else scsi_idisable();
+ mbase |= IMODE_BASE | SC_M_DMA;
+ scsi_dma_setup(reqp, phase, mbase);
+
+ splx(sps);
+
+ if (poll) {
+ /*
+ * On polled-dma transfers, we wait here until the
+ * 'end-of-dma' condition occurs.
+ */
+ poll_edma(reqp);
+ if (!(dma_done = dma_ready()))
+ goto again;
+ }
+ PID("tdma2");
+}
+
+/*
+ * Check results of a DMA data-transfer.
+ */
+static int
+dma_ready()
+{
+ SC_REQ *reqp = connected;
+ int dmstat, is_edma;
+ long bytes_left, bytes_done;
+
+ is_edma = get_dma_result(reqp, &bytes_left);
+ dmstat = GET_5380_REG(NCR5380_DMSTAT);
+
+ /*
+ * Check if the call is sensible and not caused by any spurious
+ * interrupt.
+ */
+ if (!is_edma && !(dmstat & (SC_END_DMA|SC_BSY_ERR))
+ && (dmstat & SC_PHS_MTCH) ) {
+ ncr_tprint(reqp, "dma_ready: spurious call"
+ "(dm:%x,last_hit: %s)\n",
+#ifdef DBG_PID
+ dmstat, last_hit);
+#else
+ dmstat, "unknown");
+#endif
+ return (0);
+ }
+
+ /*
+ * Clear all (pending) interrupts.
+ */
+ scsi_clr_ipend();
+
+ /*
+ * Update various transfer-pointers/lengths
+ */
+ bytes_done = reqp->dm_cur->dm_count - bytes_left;
+
+ if ((reqp->dr_flag & DRIVER_BOUNCING) && (PH_IN(reqp->phase))) {
+ /*
+ * Copy the bytes read until now from the bounce buffer
+ * to the 'real' destination. Flush the data-cache
+ * before copying.
+ */
+ PCIA();
+ bcopy(reqp->bouncerp, reqp->xdata_ptr, bytes_done);
+ reqp->bouncerp += bytes_done;
+ }
+
+ reqp->xdata_ptr = &reqp->xdata_ptr[bytes_done]; /* XXX */
+ reqp->xdata_len -= bytes_done; /* XXX */
+ if ((reqp->dm_cur->dm_count -= bytes_done) == 0)
+ reqp->dm_cur++;
+ else reqp->dm_cur->dm_addr += bytes_done;
+
+ if (PH_IN(reqp->phase) && (dmstat & SC_PAR_ERR)) {
+ if (!(ncr5380_no_parchk & (1 << reqp->targ_id)))
+ /* XXX: Should be parity error ???? */
+ reqp->xs->error = XS_DRIVER_STUFFUP;
+ }
+
+ /*
+ * DMA mode should always be reset even when we will continue with the
+ * next chain.
+ */
+ SET_5380_REG(NCR5380_MODE, GET_5380_REG(NCR5380_MODE) & ~SC_M_DMA);
+
+
+ if ((dmstat & SC_BSY_ERR) || !(dmstat & SC_PHS_MTCH)
+ || (reqp->dm_cur > reqp->dm_last) || (reqp->xs->error)) {
+
+ /*
+ * Tell interrupt functions DMA mode has ended.
+ */
+ reqp->dr_flag &= ~DRIVER_IN_DMA;
+
+ /*
+ * Clear mode and icom
+ */
+ SET_5380_REG(NCR5380_MODE, IMODE_BASE);
+ SET_5380_REG(NCR5380_ICOM, 0);
+
+ if (dmstat & SC_BSY_ERR) {
+ if (!reqp->xs->error)
+ reqp->xs->error = XS_BUSY;
+ finish_req(reqp);
+ PID("dma_ready1");
+ return (1);
+ }
+
+ if (reqp->xs->error != 0) {
+ncr_tprint(reqp, "dma-ready: code = %d\n", reqp->xs->error); /* LWP */
+ reqp->msgout = MSG_ABORT;
+ SET_5380_REG(NCR5380_ICOM, SC_A_ATN);
+ }
+ PID("dma_ready2");
+ return (1);
+ }
+ return (0);
+}
+#endif /* REAL_DMA */
+
+static int
+check_autosense(reqp, linked)
+SC_REQ *reqp;
+int linked;
+{
+ int sps;
+
+ /*
+ * If we not executing an auto-sense and the status code
+ * is request-sense, we automatically issue a request
+ * sense command.
+ */
+ PID("cautos1");
+ if (!(reqp->dr_flag & DRIVER_AUTOSEN)) {
+ if (reqp->status == SCSCHKC) {
+ bcopy(sense_cmd, &reqp->xcmd, sizeof(sense_cmd));
+ reqp->xdata_ptr = (u_char *)&reqp->xs->sense;
+ reqp->xdata_len = sizeof(reqp->xs->sense);
+ reqp->dr_flag |= DRIVER_AUTOSEN;
+ reqp->dr_flag &= ~DRIVER_DMAOK;
+ if (!linked) {
+ sps = splbio();
+ reqp->next = issue_q;
+ issue_q = reqp;
+ splx(sps);
+ }
+ else reqp->xcmd.bytes[4] |= 1;
+
+#ifdef DBG_REQ
+ bzero(reqp->xdata_ptr, reqp->xdata_len);
+ if (dbg_target_mask & (1 << reqp->targ_id))
+ show_request(reqp, "AUTO-SENSE");
+#endif
+ PID("cautos2");
+ return (-1);
+ }
+ }
+ else {
+ /*
+ * An auto-sense has finished
+ */
+ if ((reqp->status & SCSMASK) != SCSGOOD)
+ reqp->xs->error = XS_DRIVER_STUFFUP; /* SC_E_AUTOSEN; */
+ else reqp->xs->error = XS_SENSE;
+ reqp->status = SCSCHKC;
+ }
+ PID("cautos3");
+ return (0);
+}
+
+static int
+reach_msg_out(sc, len)
+struct ncr_softc *sc;
+u_long len;
+{
+ u_char phase;
+ u_char data;
+
+ ncr_aprint(sc, "Trying to reach Message-out phase\n");
+ if ((phase = GET_5380_REG(NCR5380_IDSTAT)) & SC_S_REQ)
+ phase = (phase >> 2) & 7;
+ else return (-1);
+ ncr_aprint(sc, "Trying to reach Message-out phase, now: %d\n", phase);
+ if (phase == PH_MSGOUT)
+ return (0);
+
+ SET_5380_REG(NCR5380_TCOM, phase);
+
+ do {
+ if (!wait_req_true())
+ break;
+ if (((GET_5380_REG(NCR5380_IDSTAT) >> 2) & 7) != phase)
+ break;
+ if (PH_IN(phase)) {
+ data = GET_5380_REG(NCR5380_DATA);
+ SET_5380_REG(NCR5380_ICOM, SC_A_ACK | SC_A_ATN);
+ }
+ else {
+ SET_5380_REG(NCR5380_DATA, 0);
+ SET_5380_REG(NCR5380_ICOM, SC_ADTB|SC_A_ACK|SC_A_ATN);
+ }
+ if (!wait_req_false())
+ break;
+ SET_5380_REG(NCR5380_ICOM, SC_A_ATN);
+ } while (--len);
+
+ if ((phase = GET_5380_REG(NCR5380_IDSTAT)) & SC_S_REQ) {
+ phase = (phase >> 2) & 7;
+ if (phase == PH_MSGOUT) {
+ ncr_aprint(sc, "Message-out phase reached.\n");
+ return (0);
+ }
+ }
+ return (-1);
+}
+
+static void
+scsi_reset(sc)
+struct ncr_softc *sc;
+{
+ SC_REQ *tmp, *next;
+ int sps;
+
+ ncr_aprint(sc, "Resetting SCSI-bus\n");
+
+ PID("scsi_reset1");
+ sps = splbio();
+ SET_5380_REG(NCR5380_ICOM, SC_A_RST);
+ delay(1);
+ SET_5380_REG(NCR5380_ICOM, 0);
+
+ /*
+ * None of the jobs in the discon_q will ever be reconnected,
+ * notify this to the higher level code.
+ */
+ for (tmp = discon_q; tmp ;) {
+ next = tmp->next;
+ tmp->next = NULL;
+ tmp->xs->error = XS_TIMEOUT;
+ busy &= ~(1 << tmp->targ_id);
+ finish_req(tmp);
+ tmp = next;
+ }
+ discon_q = NULL;
+
+ /*
+ * The current job will never finish either.
+ * The problem is that we can't finish the job because an instance
+ * of main is running on it. Our best guess is that the job is currently
+ * doing REAL-DMA. In that case 'dma_ready()' should correctly finish
+ * the job because it detects BSY-loss.
+ */
+ if (tmp = connected) {
+ if (tmp->dr_flag & DRIVER_IN_DMA) {
+ tmp->xs->error = XS_DRIVER_STUFFUP;
+#ifdef REAL_DMA
+ dma_ready();
+#endif
+ }
+ }
+ splx(sps);
+ PID("scsi_reset2");
+}
+
+/*
+ * Check validity of the IRQ set by the 5380. If the interrupt is valid,
+ * the appropriate action is carried out (reselection or DMA ready) and
+ * INTR_RESEL or INTR_DMA is returned. Otherwise a console notice is written
+ * and INTR_SPURIOUS is returned.
+ */
+static int
+check_intr(sc)
+struct ncr_softc *sc;
+{
+ SC_REQ *reqp;
+
+ if ((GET_5380_REG(NCR5380_IDSTAT) & (SC_S_SEL|SC_S_IO))
+ ==(SC_S_SEL|SC_S_IO))
+ return (INTR_RESEL);
+ else {
+ if ((reqp = connected) && (reqp->dr_flag & DRIVER_IN_DMA)){
+ reqp->dr_flag &= ~DRIVER_IN_DMA;
+ return (INTR_DMA);
+ }
+ }
+ scsi_clr_ipend();
+ printf("-->");
+ scsi_show();
+ ncr_aprint(sc, "Spurious interrupt.\n");
+ return (INTR_SPURIOUS);
+}
+
+#ifdef REAL_DMA
+/*
+ * Check if DMA can be used for this request. This function also builds
+ * the dma-chain.
+ */
+static int
+scsi_dmaok(reqp)
+SC_REQ *reqp;
+{
+ u_long phy_buf;
+ u_long phy_len;
+ void *req_addr;
+ u_long req_len;
+ struct dma_chain *dm;
+
+ /*
+ * Initialize locals and requests' DMA-chain.
+ */
+ req_len = reqp->xdata_len;
+ req_addr = (void*)reqp->xdata_ptr;
+ dm = reqp->dm_cur = reqp->dm_last = reqp->dm_chain;
+ dm->dm_count = dm->dm_addr = 0;
+ reqp->dr_flag &= ~DRIVER_BOUNCING;
+
+ /*
+ * Do not accept zero length DMA.
+ */
+ if (req_len == 0)
+ return (0);
+
+ /*
+ * LWP: I think that this restriction is not strictly nessecary.
+ */
+ if ((req_len & 0x1) || ((u_int)req_addr & 0x3))
+ return (0);
+
+ /*
+ * Build the DMA-chain.
+ */
+ dm->dm_addr = phy_buf = kvtop(req_addr);
+ while (req_len) {
+ if (req_len < (phy_len = NBPG - ((u_long)req_addr & PGOFSET)))
+ phy_len = req_len;
+
+ req_addr += phy_len;
+ req_len -= phy_len;
+ dm->dm_count += phy_len;
+
+ if (req_len) {
+ u_long tmp = kvtop(req_addr);
+
+ if ((phy_buf + phy_len) != tmp) {
+ if (wrong_dma_range(reqp, dm)) {
+ if (reqp->dr_flag & DRIVER_BOUNCING)
+ goto bounceit;
+ return (0);
+ }
+
+ if (++dm >= &reqp->dm_chain[MAXDMAIO]) {
+ ncr_tprint(reqp,"dmaok: DMA chain too long!\n");
+ return (0);
+ }
+ dm->dm_count = 0;
+ dm->dm_addr = tmp;
+ }
+ phy_buf = tmp;
+ }
+ }
+ if (wrong_dma_range(reqp, dm)) {
+ if (reqp->dr_flag & DRIVER_BOUNCING)
+ goto bounceit;
+ return (0);
+ }
+ reqp->dm_last = dm;
+ return (1);
+
+bounceit:
+ if ((reqp->bounceb = alloc_bounceb(reqp->xdata_len)) == NULL) {
+ /*
+ * If we can't get a bounce buffer, forget DMA
+ */
+ reqp->dr_flag &= ~DRIVER_BOUNCING;
+ return(0);
+ }
+ /*
+ * Initialize a single DMA-range containing the bounced request
+ */
+ dm = reqp->dm_cur = reqp->dm_last = reqp->dm_chain;
+ dm->dm_addr = kvtop(reqp->bounceb);
+ dm->dm_count = reqp->xdata_len;
+ reqp->bouncerp = reqp->bounceb;
+
+ return (1);
+}
+#endif /* REAL_DMA */
+
+static void
+run_main(sc)
+struct ncr_softc *sc;
+{
+ int sps = splbio();
+
+ if (!main_running) {
+ /*
+ * If shared resources are required, claim them
+ * before entering 'scsi_main'. If we can't get them
+ * now, assume 'run_main' will be called when the resource
+ * becomes available.
+ */
+ if (!claimed_dma()) {
+ splx(sps);
+ return;
+ }
+ main_running = 1;
+ splx(sps);
+ scsi_main(sc);
+ }
+ else splx(sps);
+}
+
+/*
+ * Prefix message with full target info.
+ */
+static void
+ncr_tprint(SC_REQ *reqp, char *fmt, ...)
+{
+ va_list ap;
+
+ va_start(ap, fmt);
+ sc_print_addr(reqp->xs->sc_link);
+ printf("%r", fmt, ap);
+ va_end(ap);
+}
+
+/*
+ * Prefix message with adapter info.
+ */
+static void
+ncr_aprint(struct ncr_softc *sc, char *fmt, ...)
+{
+ va_list ap;
+
+ va_start(ap, fmt);
+ printf("%s : %r", sc->sc_dev.dv_xname, fmt, ap);
+ va_end(ap);
+}
+/****************************************************************************
+ * Start Debugging Functions *
+ ****************************************************************************/
+static void
+show_data_sense(xs)
+struct scsi_xfer *xs;
+{
+ u_char *p1, *p2;
+ int i;
+ int sz;
+
+ p1 = (u_char *) xs->cmd;
+ p2 = (u_char *)&xs->sense;
+ if(*p2 == 0)
+ return; /* No(n)sense */
+ printf("cmd[%d,%d]: ", xs->cmdlen, sz = command_size(*p1));
+ for (i = 0; i < sz; i++)
+ printf("%x ", p1[i]);
+ printf("\nsense: ");
+ for (i = 0; i < sizeof(xs->sense); i++)
+ printf("%x ", p2[i]);
+ printf("\n");
+}
+
+static void
+show_request(reqp, qtxt)
+SC_REQ *reqp;
+char *qtxt;
+{
+ printf("REQ-%s: %d %x[%d] cmd[0]=%x S=%x M=%x R=%x resid=%d %s\n",
+ qtxt, reqp->targ_id, reqp->xdata_ptr, reqp->xdata_len,
+ reqp->xcmd.opcode, reqp->status, reqp->message,
+ reqp->xs->error, reqp->xs->resid, reqp->link ? "L":"");
+ if (reqp->status == SCSCHKC)
+ show_data_sense(reqp->xs);
+}
+
+static char *sig_names[] = {
+ "PAR", "SEL", "I/O", "C/D", "MSG", "REQ", "BSY", "RST",
+ "ACK", "ATN", "LBSY", "PMATCH", "IRQ", "EPAR", "DREQ", "EDMA"
+};
+
+static void
+show_signals(dmstat, idstat)
+u_char dmstat, idstat;
+{
+ u_short tmp, mask;
+ int i, j, need_pipe;
+
+ tmp = idstat | ((dmstat & 3) << 8);
+ printf("Bus signals (%02x/%02x): ", idstat, dmstat & 3);
+ for (mask = 1, j = need_pipe = 0; mask <= tmp; mask <<= 1, j++) {
+ if (tmp & mask)
+ printf("%s%s", need_pipe++ ? "|" : "", sig_names[j]);
+ }
+ printf("\nDma status (%02x): ", dmstat);
+ for (mask = 4, j = 10, need_pipe = 0; mask <= dmstat; mask <<= 1, j++) {
+ if (dmstat & mask)
+ printf("%s%s", need_pipe++ ? "|" : "", sig_names[j]);
+ }
+ printf("\n");
+}
+
+scsi_show()
+{
+ SC_REQ *tmp;
+ int sps = splhigh();
+ u_char idstat, dmstat;
+
+#ifndef DBG_PID
+ #define last_hit ""
+ #define olast_hit ""
+#endif
+
+ for (tmp = issue_q; tmp; tmp = tmp->next)
+ show_request(tmp, "ISSUED");
+ for (tmp = discon_q; tmp; tmp = tmp->next)
+ show_request(tmp, "DISCONNECTED");
+ if (connected)
+ show_request(connected, "CONNECTED");
+ idstat = GET_5380_REG(NCR5380_IDSTAT);
+ dmstat = GET_5380_REG(NCR5380_DMSTAT);
+ show_signals(dmstat, idstat);
+ if (connected)
+ printf("phase = %d, ", connected->phase);
+ printf("busy:%x, last_hit:%s, olast_hit:%s spl:%04x\n", busy,
+ last_hit, olast_hit, sps);
+
+ splx(sps);
+}
diff --git a/sys/arch/pc532/dev/ncr5380reg.h b/sys/arch/pc532/dev/ncr5380reg.h
new file mode 100644
index 00000000000..783013af418
--- /dev/null
+++ b/sys/arch/pc532/dev/ncr5380reg.h
@@ -0,0 +1,258 @@
+/* $NetBSD: ncr5380reg.h,v 1.3 1995/09/26 20:16:13 phil Exp $ */
+
+/*
+ * Copyright (c) 1995 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 _NCR5380REG_H
+#define _NCR5380REG_H
+/*
+ * NCR5380 common interface definitions.
+ */
+
+/*
+ * Register numbers: (first argument to GET/SET_5380_REG )
+ */
+#define NCR5380_DATA 0 /* Data register */
+#define NCR5380_ICOM 1 /* Initiator command register */
+#define NCR5380_MODE 2 /* Mode register */
+#define NCR5380_TCOM 3 /* Target command register */
+#define NCR5380_IDSTAT 4 /* Bus status register */
+#define NCR5380_DMSTAT 5 /* DMA status register */
+#define NCR5380_TRCV 6 /* Target receive register */
+#define NCR5380_IRCV 7 /* Initiator receive register */
+
+/*
+ * Definitions for Initiator command register.
+ */
+#define SC_A_RST 0x80 /* RW - Assert RST */
+#define SC_TEST 0x40 /* W - Test mode */
+#define SC_AIP 0x40 /* R - Arbitration in progress */
+#define SC_LA 0x20 /* R - Lost arbitration */
+#define SC_A_ACK 0x10 /* RW - Assert ACK */
+#define SC_A_BSY 0x08 /* RW - Assert BSY */
+#define SC_A_SEL 0x04 /* RW - Assert SEL */
+#define SC_A_ATN 0x02 /* RW - Assert ATN */
+#define SC_ADTB 0x01 /* RW - Assert Data To Bus */
+
+/*
+ * Definitions for mode register
+ */
+#define SC_B_DMA 0x80 /* RW - Block mode DMA (not on TT!) */
+#define SC_T_MODE 0x40 /* RW - Target mode */
+#define SC_E_PAR 0x20 /* RW - Enable parity check */
+#define SC_E_PARI 0x10 /* RW - Enable parity interrupt */
+#define SC_E_EOPI 0x08 /* RW - Enable End Of Process Interrupt */
+#define SC_MON_BSY 0x04 /* RW - Monitor BSY */
+#define SC_M_DMA 0x02 /* RW - Set DMA mode */
+#define SC_ARBIT 0x01 /* RW - Arbitrate */
+
+/*
+ * Definitions for tcom register
+ */
+#define SC_LBS 0x80 /* RW - Last Byte Send (not on TT!) */
+#define SC_A_REQ 0x08 /* RW - Assert REQ */
+#define SC_A_MSG 0x04 /* RW - Assert MSG */
+#define SC_A_CD 0x02 /* RW - Assert C/D */
+#define SC_A_IO 0x01 /* RW - Assert I/O */
+
+/*
+ * Definitions for idstat register
+ */
+#define SC_S_RST 0x80 /* R - RST is set */
+#define SC_S_BSY 0x40 /* R - BSY is set */
+#define SC_S_REQ 0x20 /* R - REQ is set */
+#define SC_S_MSG 0x10 /* R - MSG is set */
+#define SC_S_CD 0x08 /* R - C/D is set */
+#define SC_S_IO 0x04 /* R - I/O is set */
+#define SC_S_SEL 0x02 /* R - SEL is set */
+#define SC_S_PAR 0x01 /* R - Parity bit */
+
+/*
+ * Definitions for dmastat register
+ */
+#define SC_END_DMA 0x80 /* R - End of DMA */
+#define SC_DMA_REQ 0x40 /* R - DMA request */
+#define SC_PAR_ERR 0x20 /* R - Parity error */
+#define SC_IRQ_SET 0x10 /* R - IRQ is active */
+#define SC_PHS_MTCH 0x08 /* R - Phase Match */
+#define SC_BSY_ERR 0x04 /* R - Busy error */
+#define SC_ATN_STAT 0x02 /* R - State of ATN line */
+#define SC_ACK_STAT 0x01 /* R - State of ACK line */
+#define SC_S_SEND 0x00 /* W - Start DMA output */
+
+#define SC_CLINT { /* Clear interrupts */ \
+ int i = GET_5380_REG(NCR5380_IRCV); \
+ }
+
+
+/*
+ * Definition of SCSI-bus phases. The values are determined by signals
+ * on the SCSI-bus. DO NOT CHANGE!
+ * The values must be used to index the pointers in SCSI-PARMS.
+ */
+#define NR_PHASE 8
+#define PH_DATAOUT 0
+#define PH_DATAIN 1
+#define PH_CMD 2
+#define PH_STATUS 3
+#define PH_RES1 4
+#define PH_RES2 5
+#define PH_MSGOUT 6
+#define PH_MSGIN 7
+
+#define PH_OUT(phase) (!(phase & 1)) /* TRUE if output phase */
+#define PH_IN(phase) (phase & 1) /* TRUE if input phase */
+
+/*
+ * Id of Host-adapter
+ */
+#define SC_HOST_ID 0x80
+
+/*
+ * Base setting for 5380 mode register
+ */
+#define IMODE_BASE SC_E_PAR
+
+/*
+ * SCSI completion status codes, should move to sys/scsi/????
+ */
+#define SCSMASK 0x1e /* status code mask */
+#define SCSGOOD 0x00 /* good status */
+#define SCSCHKC 0x02 /* check condition */
+#define SCSBUSY 0x08 /* busy status */
+#define SCSCMET 0x04 /* condition met / good */
+
+/*
+ * Return values of check_intr()
+ */
+#define INTR_SPURIOUS 0
+#define INTR_RESEL 2
+#define INTR_DMA 3
+
+struct ncr_softc {
+ struct device sc_dev;
+ struct scsi_link sc_link;
+
+ /*
+ * Some (pre-SCSI2) devices don't support select with ATN.
+ * If the device responds to select with ATN by going into
+ * command phase (ignoring ATN), then we flag it in the
+ * following bitmask.
+ * We also keep track of which devices have been selected
+ * before. This allows us to not even try raising ATN if
+ * the target doesn't respond to it the first time.
+ */
+ u_int8_t sc_noselatn;
+ u_int8_t sc_selected;
+};
+
+/*
+ * Max. number of dma-chains per request
+ */
+#define MAXDMAIO (MAXPHYS/NBPG + 1)
+
+/*
+ * Some requests are not contiguous in physical memory. We need to break them
+ * up into contiguous parts for DMA.
+ */
+struct dma_chain {
+ u_int dm_count;
+ u_long dm_addr;
+};
+
+/*
+ * Define our issue, free and disconnect queue's.
+ */
+typedef struct req_q {
+ struct req_q *next; /* next in free, issue or discon queue */
+ struct req_q *link; /* next linked command to execute */
+ struct scsi_xfer *xs; /* request from high-level driver */
+ u_short dr_flag; /* driver state */
+ u_char phase; /* current SCSI phase */
+ u_char msgout; /* message to send when requested */
+ u_char targ_id; /* target for command */
+ u_char targ_lun; /* lun for command */
+ u_char status; /* returned status byte */
+ u_char message; /* returned message byte */
+ u_char *bounceb; /* allocated bounce buffer */
+ u_char *bouncerp; /* bounce read-pointer */
+ struct dma_chain dm_chain[MAXDMAIO];
+ struct dma_chain *dm_cur; /* current dma-request */
+ struct dma_chain *dm_last; /* last dma-request */
+ long xdata_len; /* length of transfer */
+ u_char *xdata_ptr; /* virtual address of transfer */
+ struct scsi_generic xcmd; /* command to execute */
+} SC_REQ;
+
+/*
+ * Values for dr_flag:
+ */
+#define DRIVER_IN_DMA 0x01 /* Non-polled DMA activated */
+#define DRIVER_AUTOSEN 0x02 /* Doing automatic sense */
+#define DRIVER_NOINT 0x04 /* We are booting: no interrupts */
+#define DRIVER_DMAOK 0x08 /* DMA can be used on this request */
+#define DRIVER_BOUNCING 0x10 /* Using the bounce buffer */
+
+/* XXX: Should go to ncr5380var.h */
+static SC_REQ *issue_q = NULL; /* Commands waiting to be issued*/
+static SC_REQ *discon_q = NULL; /* Commands disconnected */
+static SC_REQ *connected = NULL; /* Command currently connected */
+
+/*
+ * Function decls:
+ */
+static int transfer_pio __P((u_char *, u_char *, u_long *, int));
+static int wait_req_true __P((void));
+static int wait_req_false __P((void));
+static int scsi_select __P((SC_REQ *, int));
+static int handle_message __P((SC_REQ *, u_int));
+static void ack_message __P((void));
+static void nack_message __P((SC_REQ *));
+static int information_transfer __P((void));
+static void reselect __P((struct ncr_softc *));
+static int dma_ready __P((void));
+static void transfer_dma __P((SC_REQ *, u_int, int));
+static int check_autosense __P((SC_REQ *, int));
+static int reach_msg_out __P((struct ncr_softc *, u_long));
+static int check_intr __P((struct ncr_softc *));
+static void scsi_reset __P((struct ncr_softc *));
+static int scsi_dmaok __P((SC_REQ *));
+static void run_main __P((struct ncr_softc *));
+static void scsi_main __P((struct ncr_softc *));
+static void ncr_ctrl_intr __P((struct ncr_softc *));
+static void ncr_dma_intr __P((struct ncr_softc *));
+static void ncr_tprint __P((SC_REQ *, char *, ...));
+static void ncr_aprint __P((struct ncr_softc *, char *, ...));
+
+static void show_request __P((SC_REQ *, char *));
+static void show_phase __P((SC_REQ *, int));
+static void show_signals __P((u_char, u_char));
+
+#endif /* _NCR5380REG_H */
diff --git a/sys/arch/pc532/dev/ncr_5380.h b/sys/arch/pc532/dev/ncr_5380.h
new file mode 100644
index 00000000000..4d209f5671f
--- /dev/null
+++ b/sys/arch/pc532/dev/ncr_5380.h
@@ -0,0 +1,145 @@
+/* $NetBSD: ncr_5380.h,v 1.4 1995/08/25 07:30:37 phil 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.
+ */
+/*
+ * File: scsi_5380.h
+ * Author: Alessandro Forin, Carnegie Mellon University
+ * Date: 5/91
+ *
+ * Defines for the NCR 5380 (SCSI chip), aka Am5380
+ *
+ * Modified for the pc532 by Phil Nelson. 1/94
+ */
+
+/*
+ * Register map
+ */
+
+typedef struct {
+ volatile unsigned char sci_data; /* r: Current data */
+#define sci_odata sci_data /* w: Out data */
+
+ volatile unsigned char sci_icmd; /* rw: Initiator command */
+
+ volatile unsigned char sci_mode; /* rw: Mode */
+
+ volatile unsigned char sci_tcmd; /* rw: Target command */
+
+ volatile unsigned char sci_bus_csr; /* r: Bus Status */
+#define sci_sel_enb sci_bus_csr /* w: Select enable */
+
+ volatile unsigned char sci_csr; /* r: Status */
+#define sci_dma_send sci_csr /* w: Start dma send data */
+
+ volatile unsigned char sci_idata; /* r: Input data */
+#define sci_trecv sci_idata /* w: Start dma receive, target */
+
+ volatile unsigned char sci_iack; /* r: Interrupt Acknowledge */
+#define sci_irecv sci_iack /* w: Start dma receive, initiator */
+} sci_regmap_t;
+
+
+/*
+ * Initiator command register
+ */
+
+#define SCI_ICMD_DATA 0x01 /* rw: Assert data bus */
+#define SCI_ICMD_ATN 0x02 /* rw: Assert ATN signal */
+#define SCI_ICMD_SEL 0x04 /* rw: Assert SEL signal */
+#define SCI_ICMD_BSY 0x08 /* rw: Assert BSY signal */
+#define SCI_ICMD_ACK 0x10 /* rw: Assert ACK signal */
+#define SCI_ICMD_LST 0x20 /* r: Lost arbitration */
+#define SCI_ICMD_DIFF SCI_ICMD_LST /* w: Differential cable */
+#define SCI_ICMD_AIP 0x40 /* r: Arbitration in progress */
+#define SCI_ICMD_TEST SCI_ICMD_AIP /* w: Test mode */
+#define SCI_ICMD_RST 0x80 /* rw: Assert RST signal */
+
+
+/*
+ * Mode register
+ */
+
+#define SCI_MODE_ARB 0x01 /* rw: Start arbitration */
+#define SCI_MODE_DMA 0x02 /* rw: Enable DMA xfers */
+#define SCI_MODE_MONBSY 0x04 /* rw: Monitor BSY signal */
+#define SCI_MODE_DMA_IE 0x08 /* rw: Enable DMA complete interrupt */
+#define SCI_MODE_PERR_IE 0x10 /* rw: Interrupt on parity errors */
+#define SCI_MODE_PAR_CHK 0x20 /* rw: Check parity */
+#define SCI_MODE_TARGET 0x40 /* rw: Target mode (Initiator if 0) */
+#define SCI_MODE_BLOCKDMA 0x80 /* rw: Block-mode DMA handshake (MBZ) */
+
+
+/*
+ * Target command register
+ */
+
+#define SCI_TCMD_IO 0x01 /* rw: Assert I/O signal */
+#define SCI_TCMD_CD 0x02 /* rw: Assert C/D signal */
+#define SCI_TCMD_MSG 0x04 /* rw: Assert MSG signal */
+#define SCI_TCMD_PHASE_MASK 0x07 /* r: Mask for current bus phase */
+#define SCI_TCMD_REQ 0x08 /* rw: Assert REQ signal */
+#define SCI_TCMD_LAST_SENT 0x80 /* ro: Last byte was xferred
+ * (not on 5380/1) */
+
+#define SCI_PHASE(x) SCSI_PHASE(x)
+
+/*
+ * Current (SCSI) Bus status
+ */
+
+#define SCI_BUS_DBP 0x01 /* r: Data Bus parity */
+#define SCI_BUS_SEL 0x02 /* r: SEL signal */
+#define SCI_BUS_IO 0x04 /* r: I/O signal */
+#define SCI_BUS_CD 0x08 /* r: C/D signal */
+#define SCI_BUS_MSG 0x10 /* r: MSG signal */
+#define SCI_BUS_REQ 0x20 /* r: REQ signal */
+#define SCI_BUS_BSY 0x40 /* r: BSY signal */
+#define SCI_BUS_RST 0x80 /* r: RST signal */
+
+#define SCI_CUR_PHASE(x) SCSI_PHASE((x)>>2)
+
+/*
+ * Bus and Status register
+ */
+
+#define SCI_CSR_ACK 0x01 /* r: ACK signal */
+#define SCI_CSR_ATN 0x02 /* r: ATN signal */
+#define SCI_CSR_DISC 0x04 /* r: Disconnected (BSY==0) */
+#define SCI_CSR_PHASE_MATCH 0x08 /* r: Bus and SCI_TCMD match */
+#define SCI_CSR_INT 0x10 /* r: Interrupt request */
+#define SCI_CSR_PERR 0x20 /* r: Parity error */
+#define SCI_CSR_DREQ 0x40 /* r: DMA request */
+#define SCI_CSR_DONE 0x80 /* r: DMA count is zero */
+
+
+/* icu scsi chip switching */
+
+#define ICU_ADR 0xfffffe00
+#define ICU_IO (ICU_ADR+20)
+#define ICU_DIR (ICU_ADR+21)
+#define ICU_DATA (ICU_ADR+19)
+#define ICU_SCSI_BIT 0x80
diff --git a/sys/arch/pc532/dev/ncr_defs.h b/sys/arch/pc532/dev/ncr_defs.h
new file mode 100644
index 00000000000..952661c3b54
--- /dev/null
+++ b/sys/arch/pc532/dev/ncr_defs.h
@@ -0,0 +1,57 @@
+/* $NetBSD: ncr_defs.h,v 1.4 1995/08/25 07:30:39 phil Exp $ */
+
+/*-
+ * Copyright (C) 1993 Allen K. Briggs, Chris P. Caputo,
+ * Michael L. Finch, Bradley A. Grantham, and
+ * Lawrence A. Kesteloot
+ * 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 Alice Group.
+ * 4. The names of the Alice Group or any of its members may not be used
+ * to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE ALICE GROUP ``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 ALICE GROUP 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 _SCSI_DEFS_H
+#define _SCSI_DEFS_H
+
+#define SCSI_PHASE_DATA_OUT 0x0
+#define SCSI_PHASE_DATA_IN 0x1
+#define SCSI_PHASE_CMD 0x2
+#define SCSI_PHASE_STATUS 0x3
+#define SCSI_PHASE_UNSPEC1 0x4
+#define SCSI_PHASE_UNSPEC2 0x5
+#define SCSI_PHASE_MESSAGE_OUT 0x6
+#define SCSI_PHASE_MESSAGE_IN 0x7
+
+#define SCSI_PHASE(x) ((x)&0x7)
+
+/* These should be fixed up. */
+
+#define SCSI_RET_SUCCESS 0
+#define SCSI_RET_RETRY 1
+#define SCSI_RET_DEVICE_DOWN 2
+#define SCSI_RET_COMMAND_FAIL 3
+
+#endif
diff --git a/sys/arch/pc532/dev/ncrreg.h b/sys/arch/pc532/dev/ncrreg.h
new file mode 100644
index 00000000000..41c371ba231
--- /dev/null
+++ b/sys/arch/pc532/dev/ncrreg.h
@@ -0,0 +1,62 @@
+/* $NetBSD: ncrreg.h,v 1.2 1995/08/25 07:30:40 phil Exp $ */
+
+/*
+ * Copyright (c) 1994 Matthias Pfaller.
+ * 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 Matthias Pfaller.
+ * 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.
+ *
+ * $Id: ncrreg.h,v 1.1 1995/10/18 08:51:18 deraadt Exp $
+ */
+
+#ifndef _NCRREG_H
+#define _NCRREG_H
+
+#define PDMA_ADDRESS ((volatile u_char *) 0xffe00000)
+#define NCR5380 ((volatile struct ncr5380 *) 0xffd00000)
+
+struct ncr5380 {
+ volatile u_char regs[8]; /* use only the odd bytes */
+};
+
+#define ncr_data regs[0] /* Data register */
+#define ncr_icom regs[1] /* Initiator command register */
+#define ncr_mode regs[2] /* Mode register */
+#define ncr_tcom regs[3] /* Target command register */
+#define ncr_idstat regs[4] /* Bus status register */
+#define ncr_dmstat regs[5] /* DMA status register */
+#define ncr_trcv regs[6] /* Target receive register */
+#define ncr_ircv regs[7] /* Initiator receive register */
+
+#define GET_5380_REG(rnum) NCR5380->regs[rnum]
+#define SET_5380_REG(rnum,val) (NCR5380->regs[rnum] = val)
+#define scsi_ienable() intr_enable(IR_SCSI1)
+#define scsi_idisable() intr_disable(IR_SCSI1)
+#define scsi_clr_ipend() do { \
+ int i = GET_5380_REG(NCR5380_IRCV); \
+ } while (0)
+
+#endif /* _NCRREG_H */
diff --git a/sys/arch/pc532/dev/oldncr.c b/sys/arch/pc532/dev/oldncr.c
new file mode 100644
index 00000000000..24b95d104a4
--- /dev/null
+++ b/sys/arch/pc532/dev/oldncr.c
@@ -0,0 +1,953 @@
+/* $NetBSD: oldncr.c,v 1.2 1995/08/27 04:07:54 phil Exp $ */
+
+/*
+ * Copyright (C) 1993 Allen K. Briggs, Chris P. Caputo,
+ * Michael L. Finch, Bradley A. Grantham, and
+ * Lawrence A. Kesteloot
+ * 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 Alice Group.
+ * 4. The names of the Alice Group or any of its members may not be used
+ * to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE ALICE GROUP ``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 ALICE GROUP 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.
+ */
+
+/* Modified for use with the pc532 by Phil Nelson, June 94. */
+
+#define PSEUDO_DMA 1
+
+static int ncr_debug=1;
+
+#include <sys/types.h>
+#include <sys/malloc.h>
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/errno.h>
+#include <sys/buf.h>
+#include <sys/kernel.h>
+#include <sys/proc.h>
+#include <sys/user.h>
+#include <sys/device.h>
+#include <scsi/scsi_all.h>
+#include <scsi/scsi_debug.h>
+#include <scsi/scsiconf.h>
+
+#include <machine/icu.h>
+
+#include "ncr_defs.h"
+#include "ncr_5380.h"
+
+#define NCR5380 DP8490
+
+#define SCI_PHASE_DISC 0 /* sort of ... */
+#define SCI_CLR_INTR(regs) {register int temp = regs->sci_iack;}
+#define SCI_ACK(ptr,phase) (ptr)->sci_tcmd = (phase)
+#define SCSI_TIMEOUT_VAL 10000000
+#define WAIT_FOR_NOT_REQ(ptr) { \
+ int scsi_timeout = SCSI_TIMEOUT_VAL; \
+ while ( ((ptr)->sci_bus_csr & SCI_BUS_REQ) && \
+ ((ptr)->sci_bus_csr & SCI_BUS_REQ) && \
+ ((ptr)->sci_bus_csr & SCI_BUS_REQ) && \
+ (--scsi_timeout) ); \
+ if (!scsi_timeout) { \
+ printf("scsi timeout--WAIT_FOR_NOT_REQ---ncr.c, \
+ line %d.\n", __LINE__); \
+ goto scsi_timeout_error; \
+ } \
+ }
+
+#define WAIT_FOR_REQ(ptr) { \
+ int scsi_timeout = SCSI_TIMEOUT_VAL; \
+ while ( (((ptr)->sci_bus_csr & SCI_BUS_REQ) == 0) && \
+ (((ptr)->sci_bus_csr & SCI_BUS_REQ) == 0) && \
+ (((ptr)->sci_bus_csr & SCI_BUS_REQ) == 0) && \
+ (--scsi_timeout) ); \
+ if (!scsi_timeout) { \
+ printf("scsi timeout--WAIT_FOR_REQ---ncr.c, \
+ line %d.\n", __LINE__); \
+ goto scsi_timeout_error; \
+ } \
+ }
+#define WAIT_FOR_BSY(ptr) { \
+ int scsi_timeout = SCSI_TIMEOUT_VAL; \
+ while ((((ptr)->sci_bus_csr & SCI_BUS_BSY) == 0) && \
+ (((ptr)->sci_bus_csr & SCI_BUS_BSY) == 0) && \
+ (((ptr)->sci_bus_csr & SCI_BUS_BSY) == 0) && \
+ (--scsi_timeout) ); \
+ if (!scsi_timeout) { \
+ printf("scsi timeout--WAIT_FOR_BSY---ncr.c, \
+ line %d.\n", __LINE__); \
+ goto scsi_timeout_error; \
+ } \
+ }
+
+#ifdef DDB
+int Debugger();
+#else
+#define Debugger() panic("Should call Debugger here (mac/dev/ncr.c).")
+#endif
+
+typedef unsigned long int physaddr;
+typedef sci_regmap_t sci_padded_regmap_t;
+
+#define NNCR5380 1
+
+struct ncr5380_softc {
+ struct device sc_dev;
+ struct scsi_link sc_link;
+};
+
+/* From the mapping of the pc532 address space. See pc532/machdep.c */
+static volatile sci_padded_regmap_t *ncr = (sci_regmap_t *) 0xffd00000;
+static volatile long *sci_4byte_addr= (long *) 0xffe00000;
+static volatile u_char *sci_1byte_addr=(u_char *) 0xffe00000;
+
+static void ncr5380_minphys(struct buf *bp);
+static int ncr5380_scsi_cmd(struct scsi_xfer *xs);
+
+static int ncr5380_show_scsi_cmd(struct scsi_xfer *xs);
+static int ncr5380_reset_target(int adapter, int target);
+static int ncr5380_poll(int adapter, int timeout);
+static int ncr5380_send_cmd(struct scsi_xfer *xs);
+
+extern void ncr5380_intr(int adapter);
+extern void spinwait(int);
+
+static int scsi_gen(int adapter, int id, int lun,
+ struct scsi_generic *cmd, int cmdlen,
+ void *databuf, int datalen);
+static int scsi_group0(int adapter, int id, int lun,
+ int opcode, int addr, int len,
+ int flags, caddr_t databuf, int datalen);
+
+static char scsi_name[] = "ncr";
+
+struct scsi_adapter ncr5380_switch = {
+ ncr5380_scsi_cmd, /* scsi_cmd() */
+ ncr5380_minphys, /* scsi_minphys() */
+ 0, /* open_target_lu() */
+ 0 /* close_target_lu() */
+};
+
+/* This is copied from julian's bt driver */
+/* "so we have a default dev struct for our link struct." */
+struct scsi_device ncr_dev = {
+ NULL, /* Use default error handler. */
+ NULL, /* have a queue, served by this (?) */
+ NULL, /* have no async handler. */
+ NULL /* Use default "done" routine. */
+};
+
+extern int matchbyname();
+static int ncrprobe();
+static void ncrattach();
+
+struct cfdriver oldncrcd =
+ { NULL, "ncr", ncrprobe, ncrattach,
+ DV_DULL, sizeof(struct ncr5380_softc), NULL, 0 };
+
+static int
+ncrprobe(parent, self, aux)
+ struct device *parent, *self;
+ void *aux;
+{
+/* int unit = cf->cf_unit; */
+ struct ncr5380_softc *ncr5380 = (void *)self;
+
+#if 0
+DELETE THIS ????
+ if (unit >= NNCR5380) {
+ printf("ncr5380attach: unit %d more than %d configured.\n",
+ unit+1, NNCR5380);
+ return 0;
+ }
+ ncr5380 = malloc(sizeof(struct ncr5380_data), M_TEMP, M_NOWAIT);
+ if (!ncr5380) {
+ printf("ncr5380attach: Can't malloc.\n");
+ return 0;
+ }
+
+ bzero(ncr5380, sizeof(*ncr5380));
+ ncr5380data[unit] = ncr5380;
+#endif
+
+ /* If we call this, we need to add SPL_DP to the bio mask! */
+ /* PL_bio |= SPL_DP; Not yet ... no interrupts */
+
+ return 1;
+}
+
+static void
+ncrattach(parent, self, aux)
+ struct device *parent, *self;
+ void *aux;
+{
+ register volatile sci_padded_regmap_t *regs = ncr;
+ struct ncr5380_softc *ncr5380 = (void *)self;
+ int r;
+
+ ncr5380->sc_link.adapter_softc = ncr5380;
+/* ncr5380->sc_link.scsibus = 0; */
+ ncr5380->sc_link.adapter_target = 7;
+ ncr5380->sc_link.adapter = &ncr5380_switch;
+ ncr5380->sc_link.device = &ncr_dev;
+ ncr5380->sc_link.openings = 1;
+
+ printf("\n");
+
+ config_found(self, &(ncr5380->sc_link), NULL);
+}
+
+#define MIN_PHYS 65536 /*BARF!!!!*/
+static void
+ncr5380_minphys(struct buf *bp)
+{
+ if (bp->b_bcount > MIN_PHYS) {
+ printf("Uh-oh... ncr5380_minphys setting bp->b_bcount = %x.\n", MIN_PHYS);
+ bp->b_bcount = MIN_PHYS;
+ }
+ minphys(bp);
+}
+#undef MIN_PHYS
+
+static int
+ncr5380_scsi_cmd(struct scsi_xfer *xs)
+{
+ int flags, s, r;
+
+ flags = xs->flags;
+ if (xs->bp) flags |= (SCSI_NOSLEEP);
+ if ( flags & ITSDONE ) {
+ printf("Already done?");
+ xs->flags &= ~ITSDONE;
+ }
+ if ( ! ( flags & INUSE ) ) {
+ printf("Not in use?");
+ xs->flags |= INUSE;
+ }
+
+ if ( flags & SCSI_RESET ) {
+ printf("flags & SCSIRESET.\n");
+ s = splbio();
+ ncr5380_reset_target(xs->sc_link->scsibus,
+ xs->sc_link->target);
+ splx(s);
+ return(COMPLETE);
+ }
+
+ xs->resid = 0; /* Default value? */
+ r = ncr5380_send_cmd(xs);
+ xs->flags |= ITSDONE;
+ scsi_done(xs);
+ switch(r) {
+ case COMPLETE: case SUCCESSFULLY_QUEUED:
+ r = SUCCESSFULLY_QUEUED;
+ if (xs->flags&SCSI_POLL)
+ r = COMPLETE;
+ break;
+ default:
+ break;
+ }
+ return r;
+}
+
+static int
+ncr5380_show_scsi_cmd(struct scsi_xfer *xs)
+{
+ u_char *b = (u_char *) xs->cmd;
+ int i = 0;
+
+ if ( ! ( xs->flags & SCSI_RESET ) ) {
+ printf("ncr5380(%d:%d:%d)-",
+ xs->sc_link->scsibus, xs->sc_link->target, xs->sc_link->lun);
+ while (i < xs->cmdlen) {
+ if (i) printf(",");
+ printf("%x",b[i++]);
+ }
+ printf("-\n");
+ } else {
+ printf("ncr5380(%d:%d:%d)-RESET-\n",
+ xs->sc_link->scsibus, xs->sc_link->target, xs->sc_link->lun);
+ }
+}
+
+/*
+ * Actual chip control.
+ */
+
+void
+delay(int timeo)
+{
+ int len;
+ for (len=0;len<timeo*2;len++);
+}
+
+#if 0
+extern void
+spinwait(int ms)
+{
+ while (ms--)
+ delay(500);
+}
+#endif
+
+extern void
+ncr5380_intr(int adapter)
+{
+ register volatile sci_padded_regmap_t *regs = ncr;
+
+ SCI_CLR_INTR(regs);
+ regs->sci_mode = 0x00;
+}
+
+extern int
+scsi_irq_intr(void)
+{
+ register volatile sci_padded_regmap_t *regs = ncr;
+
+/* if (regs->sci_csr != SCI_CSR_PHASE_MATCH)
+ printf("scsi_irq_intr called (not just phase match -- "
+ "csr = 0x%x, bus_csr = 0x%x).\n",
+ regs->sci_csr, regs->sci_bus_csr);
+ ncr5380_intr(0); */
+ return 1;
+}
+
+extern int
+scsi_drq_intr(void)
+{
+/* printf("scsi_drq_intr called.\n"); */
+/* ncr5380_intr(0); */
+ return 1;
+}
+
+static int
+ncr5380_reset_target(int adapter, int target)
+{
+ register volatile sci_padded_regmap_t *regs = ncr;
+ int dummy;
+
+ scsi_select_ctlr (DP8490);
+ regs->sci_icmd = SCI_ICMD_TEST;
+ regs->sci_icmd = SCI_ICMD_TEST | SCI_ICMD_RST;
+ delay(2500);
+ regs->sci_icmd = 0;
+
+ regs->sci_mode = 0;
+ regs->sci_tcmd = SCI_PHASE_DISC;
+ regs->sci_sel_enb = 0;
+
+ SCI_CLR_INTR(regs);
+ SCI_CLR_INTR(regs);
+}
+
+
+static int
+ncr5380_send_cmd(struct scsi_xfer *xs)
+{
+ int s, i, sense;
+
+#if 0
+ ncr5380_show_scsi_cmd(xs);
+#endif
+ s = splbio();
+ sense = scsi_gen( xs->sc_link->scsibus, xs->sc_link->target,
+ xs->sc_link->lun, xs->cmd, xs->cmdlen,
+ xs->data, xs->datalen );
+ splx(s);
+ switch (sense) {
+ case 0x00:
+ xs->error = XS_NOERROR;
+ return (COMPLETE);
+ case 0x02: /* Check condition */
+ for (i = 10; i; i--) {
+ s = splbio();
+ sense = scsi_group0(xs->sc_link->scsibus,
+ xs->sc_link->target,
+ xs->sc_link->lun,
+ 0x3, 0x0,
+ sizeof(struct scsi_sense_data),
+ 0, (caddr_t) &(xs->sense),
+ sizeof(struct scsi_sense_data));
+ splx(s);
+ if (sense == 0) break;
+ if (sense == 8
+ && (xs->flags & SCSI_NOSLEEP) == 0)
+ tsleep((caddr_t)&lbolt, PRIBIO, "ncrbusy", 0);
+ }
+ if (!i)
+ printf("ncr(%d:%d): Sense failed (dev busy)\n",
+ xs->sc_link->target, xs->sc_link->lun);
+ xs->error = XS_SENSE;
+ return COMPLETE;
+ case 0x08: /* Busy */
+ xs->error = XS_BUSY;
+ return COMPLETE;
+ default:
+ xs->error = XS_DRIVER_STUFFUP;
+ return COMPLETE;
+ }
+}
+
+static int
+select_target(register volatile sci_padded_regmap_t *regs,
+ u_char myid, u_char tid, int with_atn)
+{
+ register u_char bid, icmd;
+ int ret = SCSI_RET_RETRY;
+
+ if ((regs->sci_bus_csr & (SCI_BUS_BSY|SCI_BUS_SEL)) &&
+ (regs->sci_bus_csr & (SCI_BUS_BSY|SCI_BUS_SEL)) &&
+ (regs->sci_bus_csr & (SCI_BUS_BSY|SCI_BUS_SEL)))
+ return ret;
+
+ /* for our purposes.. */
+ myid = 1 << myid;
+ tid = 1 << tid;
+
+ regs->sci_sel_enb = 0; /*myid; we don't want any interrupts. */
+ regs->sci_tcmd = 0; /* get into a harmless state */
+ regs->sci_mode = 0; /* get into a harmless state */
+
+ regs->sci_odata = myid;
+ regs->sci_mode = SCI_MODE_ARB;
+/* regs->sci_mode |= SCI_MODE_ARB; */
+ /* AIP might not set if BSY went true after we checked */
+ for (bid = 0; bid < 20; bid++) /* 20usec circa */
+ if (regs->sci_icmd & SCI_ICMD_AIP)
+ break;
+ if ((regs->sci_icmd & SCI_ICMD_AIP) == 0) {
+ goto lost;
+ }
+
+ spinwait(2); /* 2.2us arb delay */
+
+ if (regs->sci_icmd & SCI_ICMD_LST) {
+ goto lost;
+ }
+
+ regs->sci_mode &= ~SCI_MODE_PAR_CHK;
+ bid = regs->sci_data;
+
+ if ((bid & ~myid) > myid) {
+ goto lost;
+ }
+ if (regs->sci_icmd & SCI_ICMD_LST) {
+ goto lost;
+ }
+
+ /* Won arbitration, enter selection phase now */
+ icmd = regs->sci_icmd & ~(SCI_ICMD_DIFF|SCI_ICMD_TEST);
+ icmd |= (with_atn ? (SCI_ICMD_SEL|SCI_ICMD_ATN) : SCI_ICMD_SEL);
+ icmd |= SCI_ICMD_BSY;
+ regs->sci_icmd = icmd;
+
+ if (regs->sci_icmd & SCI_ICMD_LST) {
+ goto nosel;
+ }
+
+ /* XXX a target that violates specs might still drive the bus XXX */
+ /* XXX should put our id out, and after the delay check nothi XXX */
+ /* XXX ng else is out there. XXX */
+
+ delay(0);
+
+ regs->sci_tcmd = 0;
+ regs->sci_odata = myid | tid;
+ regs->sci_sel_enb = 0;
+
+/* regs->sci_mode &= ~SCI_MODE_ARB; 2 deskew delays, too */
+ regs->sci_mode = 0; /* 2 deskew delays, too */
+
+ icmd |= SCI_ICMD_DATA;
+ icmd &= ~(SCI_ICMD_BSY);
+
+ regs->sci_icmd = icmd;
+
+ /* bus settle delay, 400ns */
+ delay(2); /* too much (was 2) ? */
+
+/* regs->sci_mode |= SCI_MODE_PAR_CHK; */
+
+ {
+ register int timeo = 2500;/* 250 msecs in 100 usecs chunks */
+ while ((regs->sci_bus_csr & SCI_BUS_BSY) == 0) {
+ if (--timeo > 0) {
+ delay(100);
+ } else {
+ goto nodev;
+ }
+ }
+ }
+
+ icmd &= ~(SCI_ICMD_DATA|SCI_ICMD_SEL);
+ regs->sci_icmd = icmd;
+/* regs->sci_sel_enb = myid;*/ /* looks like we should NOT have it */
+ return SCSI_RET_SUCCESS;
+nodev:
+ ret = SCSI_RET_DEVICE_DOWN;
+ regs->sci_sel_enb = myid;
+nosel:
+ icmd &= ~(SCI_ICMD_DATA|SCI_ICMD_SEL|SCI_ICMD_ATN);
+ regs->sci_icmd = icmd;
+lost:
+ regs->sci_mode = 0;
+
+ return ret;
+}
+
+sci_data_out(regs, phase, count, data)
+ register sci_padded_regmap_t *regs;
+ unsigned char *data;
+{
+ register unsigned char icmd;
+ register int cnt=0;
+
+ /* ..checks.. */
+
+ icmd = regs->sci_icmd & ~(SCI_ICMD_DIFF|SCI_ICMD_TEST);
+loop:
+ if (SCI_CUR_PHASE(regs->sci_bus_csr) != phase)
+ return cnt;
+
+ WAIT_FOR_REQ(regs);
+ icmd |= SCI_ICMD_DATA;
+ regs->sci_icmd = icmd;
+ regs->sci_odata = *data++;
+ icmd |= SCI_ICMD_ACK;
+ regs->sci_icmd = icmd;
+
+ icmd &= ~(SCI_ICMD_DATA|SCI_ICMD_ACK);
+ WAIT_FOR_NOT_REQ(regs);
+ regs->sci_icmd = icmd;
+ ++cnt;
+ if (--count > 0)
+ goto loop;
+scsi_timeout_error:
+ return cnt;
+}
+
+sci_data_in(regs, phase, count, data)
+ register sci_padded_regmap_t *regs;
+ unsigned char *data;
+{
+ register unsigned char icmd;
+ register int cnt=0;
+
+ /* ..checks.. */
+
+ icmd = regs->sci_icmd & ~(SCI_ICMD_DIFF|SCI_ICMD_TEST);
+
+loop:
+ if (SCI_CUR_PHASE(regs->sci_bus_csr) != phase)
+ return cnt;
+
+ WAIT_FOR_REQ(regs);
+ *data++ = regs->sci_data;
+ icmd |= SCI_ICMD_ACK;
+ regs->sci_icmd = icmd;
+
+ icmd &= ~SCI_ICMD_ACK;
+ WAIT_FOR_NOT_REQ(regs);
+ regs->sci_icmd = icmd;
+ ++cnt;
+ if (--count > 0)
+ goto loop;
+
+scsi_timeout_error:
+ return cnt;
+}
+
+static int
+command_transfer(register volatile sci_padded_regmap_t *regs,
+ int maxlen, u_char *data, u_char *status, u_char *msg)
+{
+ int xfer=0, phase;
+
+/* printf("command_transfer called for 0x%x.\n", *data); */
+
+ regs->sci_icmd = 0;
+
+ while (1) {
+
+ WAIT_FOR_REQ(regs);
+
+ phase = SCI_CUR_PHASE(regs->sci_bus_csr);
+
+ switch (phase) {
+ case SCSI_PHASE_CMD:
+ SCI_ACK(regs,SCSI_PHASE_CMD);
+ xfer += sci_data_out(regs, SCSI_PHASE_CMD,
+ maxlen, data);
+ return xfer;
+ case SCSI_PHASE_DATA_IN:
+ printf("Data in phase in command_transfer?\n");
+ return 0;
+ case SCSI_PHASE_DATA_OUT:
+ printf("Data out phase in command_transfer?\n");
+ return 0;
+ case SCSI_PHASE_STATUS:
+ SCI_ACK(regs,SCSI_PHASE_STATUS);
+ printf("status in command_transfer.\n");
+ sci_data_in(regs, SCSI_PHASE_STATUS,
+ 1, status);
+ break;
+ case SCSI_PHASE_MESSAGE_IN:
+ SCI_ACK(regs,SCSI_PHASE_MESSAGE_IN);
+ printf("msgin in command_transfer.\n");
+ sci_data_in(regs, SCSI_PHASE_MESSAGE_IN,
+ 1, msg);
+ break;
+ case SCSI_PHASE_MESSAGE_OUT:
+ SCI_ACK(regs,SCSI_PHASE_MESSAGE_OUT);
+ sci_data_out(regs, SCSI_PHASE_MESSAGE_OUT,
+ 1, msg);
+ break;
+ default:
+ printf("Unexpected phase 0x%x in "
+ "command_transfer().\n", phase);
+scsi_timeout_error:
+ return xfer;
+ break;
+ }
+ }
+}
+
+static int
+data_transfer(register volatile sci_padded_regmap_t *regs,
+ int maxlen, u_char *data, u_char *status, u_char *msg)
+{
+ int retlen = 0, xfer, phase;
+
+ regs->sci_icmd = 0;
+
+ *status = 0;
+
+ while (1) {
+
+ WAIT_FOR_REQ(regs);
+
+ phase = SCI_CUR_PHASE(regs->sci_bus_csr);
+
+ switch (phase) {
+ case SCSI_PHASE_CMD:
+ printf("Command phase in data_transfer().\n");
+ return retlen;
+ case SCSI_PHASE_DATA_IN:
+ SCI_ACK(regs,SCSI_PHASE_DATA_IN);
+#if PSEUDO_DMA
+ xfer = sci_pdma_in(regs, SCSI_PHASE_DATA_IN,
+ maxlen, data);
+#else
+ xfer = sci_data_in(regs, SCSI_PHASE_DATA_IN,
+ maxlen, data);
+#endif
+ retlen += xfer;
+ maxlen -= xfer;
+ break;
+ case SCSI_PHASE_DATA_OUT:
+ SCI_ACK(regs,SCSI_PHASE_DATA_OUT);
+#if PSEUDO_DMA
+ xfer = sci_pdma_out(regs, SCSI_PHASE_DATA_OUT,
+ maxlen, data);
+#else
+ xfer = sci_data_out(regs, SCSI_PHASE_DATA_OUT,
+ maxlen, data);
+#endif
+ retlen += xfer;
+ maxlen -= xfer;
+ break;
+ case SCSI_PHASE_STATUS:
+ SCI_ACK(regs,SCSI_PHASE_STATUS);
+ sci_data_in(regs, SCSI_PHASE_STATUS,
+ 1, status);
+ break;
+ case SCSI_PHASE_MESSAGE_IN:
+ SCI_ACK(regs,SCSI_PHASE_MESSAGE_IN);
+ sci_data_in(regs, SCSI_PHASE_MESSAGE_IN,
+ 1, msg);
+ if (*msg == 0) {
+ return retlen;
+ } else {
+ printf( "message 0x%x in "
+ "data_transfer.\n", *msg);
+ }
+ break;
+ case SCSI_PHASE_MESSAGE_OUT:
+ SCI_ACK(regs,SCSI_PHASE_MESSAGE_OUT);
+ sci_data_out(regs, SCSI_PHASE_MESSAGE_OUT,
+ 1, msg);
+ break;
+ default:
+ printf( "Unexpected phase 0x%x in "
+ "data_transfer().\n", phase);
+scsi_timeout_error:
+ return retlen;
+ break;
+ }
+ }
+}
+
+static int
+scsi_request(register volatile sci_padded_regmap_t *regs,
+ int target, int lun, u_char *cmd, int cmdlen,
+ char *databuf, int datalen, int *sent, int *ret)
+{
+/* Returns 0 on success, -1 on internal error, or the status byte */
+ int cmd_bytes_sent, r;
+ u_char stat, msg, c;
+
+ *sent = 0;
+ scsi_select_ctlr (DP8490);
+
+ if ( ( r = select_target(regs, 7, target, 1) ) != SCSI_RET_SUCCESS) {
+ *ret = r;
+ SCI_CLR_INTR(regs);
+ switch (r) {
+ case SCSI_RET_RETRY:
+ return 0x08;
+ default:
+ printf("select_target(target %d, lun %d) failed(%d).\n",
+ target, lun, r);
+ case SCSI_RET_DEVICE_DOWN:
+ return -1;
+ }
+ }
+
+ c = 0x80 | lun;
+
+ if ((cmd_bytes_sent = command_transfer(regs, cmdlen,
+ (u_char *) cmd, &stat, &c))
+ != cmdlen) {
+ SCI_CLR_INTR(regs);
+ *ret = SCSI_RET_COMMAND_FAIL;
+ printf("Data underrun sending CCB (%d bytes of %d, sent).\n",
+ cmd_bytes_sent, cmdlen);
+ return -1;
+ }
+
+ *sent=data_transfer(regs, datalen, (u_char *)databuf,
+ &stat, &msg);
+
+ *ret = 0;
+
+ return stat;
+}
+
+static int
+scsi_gen(int adapter, int id, int lun, struct scsi_generic *cmd,
+ int cmdlen, void *databuf, int datalen)
+{
+ register volatile sci_padded_regmap_t *regs = ncr;
+ int i,j,sent,ret;
+
+ cmd->bytes[0] |= ((u_char) lun << 5);
+
+ i = scsi_request(regs, id, lun, (u_char *) cmd, cmdlen,
+ databuf, datalen, &sent, &ret);
+
+ return i;
+}
+
+static int
+scsi_group0(int adapter, int id, int lun, int opcode, int addr, int len,
+ int flags, caddr_t databuf, int datalen)
+{
+ register volatile sci_padded_regmap_t *regs = ncr;
+ unsigned char cmd[6];
+ int i,j,sent,ret;
+
+ cmd[0] = opcode; /* Operation code */
+ cmd[1] = (lun << 5) | ((addr >> 16) & 0x1F); /* Lun & MSB of addr */
+ cmd[2] = (addr >> 8) & 0xFF; /* addr */
+ cmd[3] = addr & 0xFF; /* LSB of addr */
+ cmd[4] = len; /* Allocation length */
+ cmd[5] = flags; /* Link/Flag */
+
+ i = scsi_request(regs, id, lun, cmd, 6, databuf, datalen, &sent, &ret);
+
+ return i;
+}
+
+/* pseudo-dma action */
+
+#if PSEUDO_DMA
+
+#define TIMEOUT 1000000
+#define READY(poll) \
+ i = TIMEOUT; \
+ while ((regs->sci_csr & (SCI_CSR_DREQ|SCI_CSR_PHASE_MATCH)) \
+ !=(SCI_CSR_DREQ|SCI_CSR_PHASE_MATCH)) \
+ if ( !(regs->sci_csr & SCI_CSR_PHASE_MATCH) \
+ || !(regs->sci_bus_csr & SCI_BUS_BSY) \
+ || (i-- < 0) ) { \
+ printf("ncr.c: timeout counter = %d, len = %d count=%d (count-len %d).\n", \
+ i, len,count,count-len); \
+ printf("ncr_debug = %d, 1=out, 2=in",ncr_debug); \
+ /*dump_regs();*/ \
+ if (poll && !(regs->sci_csr & SCI_CSR_PHASE_MATCH)) { \
+ regs->sci_icmd &= ~SCI_ICMD_DATA; \
+ len--; \
+ } else { \
+ regs->sci_mode &= ~SCI_MODE_DMA; \
+ } \
+ return count-len; \
+ }
+
+#define W1 *byte_data = *data++
+#define W4 *long_data = *((long*)data)++
+
+sci_pdma_out(regs, phase, count, data)
+ register volatile sci_padded_regmap_t *regs;
+ int phase;
+ int count;
+ u_char *data;
+{
+ register volatile long *long_data = sci_4byte_addr;
+ register volatile u_char *byte_data = sci_1byte_addr;
+ register int len = count, i;
+
+ncr_debug=1;
+
+ if (count < 128)
+ return sci_data_out(regs, phase, count, data);
+
+ WAIT_FOR_BSY(regs);
+ regs->sci_mode |= SCI_MODE_DMA;
+ regs->sci_icmd |= SCI_ICMD_DATA;
+ regs->sci_dma_send = 0;
+
+ while ( len >= 64 ) {
+ READY(1); W1; READY(1); W1; READY(1); W1; READY(1); W1;
+ READY(1);
+ W4;W4;W4; W4;W4;W4;W4; W4;W4;W4;W4; W4;W4;W4;W4;
+ len -= 64;
+ }
+ while (len) {
+ READY(1);
+ W1;
+ len--;
+ }
+ i = TIMEOUT;
+ while ( ((regs->sci_csr & (SCI_CSR_DREQ|SCI_CSR_PHASE_MATCH))
+ == SCI_CSR_PHASE_MATCH) && --i);
+ if (!i)
+ printf("ncr.c:%d: timeout waiting for SCI_CSR_DREQ.\n", __LINE__);
+ *byte_data = 0;
+scsi_timeout_error:
+ regs->sci_mode &= ~SCI_MODE_DMA;
+ return count-len;
+}
+
+#undef W1
+#undef W4
+
+#define R4 *((long *)data)++ = *long_data
+#define R1 *data++ = *byte_data
+
+sci_pdma_in(regs, phase, count, data)
+ register volatile sci_padded_regmap_t *regs;
+ int phase;
+ int count;
+ u_char *data;
+{
+ register volatile long *long_data = sci_4byte_addr;
+ register volatile u_char *byte_data = sci_1byte_addr;
+ register int len = count, i;
+
+ncr_debug=2;
+ if (count < 128)
+ return sci_data_in(regs, phase, count, data);
+
+/* printf("Called sci_pdma_in(0x%x, 0x%x, %d, 0x%x.\n", regs, phase, count, data); */
+
+ WAIT_FOR_BSY(regs);
+ regs->sci_mode |= SCI_MODE_DMA;
+ regs->sci_icmd |= SCI_ICMD_DATA;
+ regs->sci_irecv = 0;
+
+ while (len >= 1024) {
+ READY(0);
+ R4;R4;R4;R4; R4;R4;R4;R4; R4;R4;R4;R4; R4;R4;R4;R4;
+ R4;R4;R4;R4; R4;R4;R4;R4; R4;R4;R4;R4; R4;R4;R4;R4; /* 128 */
+ READY(0);
+ R4;R4;R4;R4; R4;R4;R4;R4; R4;R4;R4;R4; R4;R4;R4;R4;
+ R4;R4;R4;R4; R4;R4;R4;R4; R4;R4;R4;R4; R4;R4;R4;R4; /* 256 */
+ READY(0);
+ R4;R4;R4;R4; R4;R4;R4;R4; R4;R4;R4;R4; R4;R4;R4;R4;
+ R4;R4;R4;R4; R4;R4;R4;R4; R4;R4;R4;R4; R4;R4;R4;R4; /* 384 */
+ READY(0);
+ R4;R4;R4;R4; R4;R4;R4;R4; R4;R4;R4;R4; R4;R4;R4;R4;
+ R4;R4;R4;R4; R4;R4;R4;R4; R4;R4;R4;R4; R4;R4;R4;R4; /* 512 */
+ READY(0);
+ R4;R4;R4;R4; R4;R4;R4;R4; R4;R4;R4;R4; R4;R4;R4;R4;
+ R4;R4;R4;R4; R4;R4;R4;R4; R4;R4;R4;R4; R4;R4;R4;R4; /* 640 */
+ READY(0);
+ R4;R4;R4;R4; R4;R4;R4;R4; R4;R4;R4;R4; R4;R4;R4;R4;
+ R4;R4;R4;R4; R4;R4;R4;R4; R4;R4;R4;R4; R4;R4;R4;R4; /* 768 */
+ READY(0);
+ R4;R4;R4;R4; R4;R4;R4;R4; R4;R4;R4;R4; R4;R4;R4;R4;
+ R4;R4;R4;R4; R4;R4;R4;R4; R4;R4;R4;R4; R4;R4;R4;R4; /* 896 */
+ READY(0);
+ R4;R4;R4;R4; R4;R4;R4;R4; R4;R4;R4;R4; R4;R4;R4;R4;
+ R4;R4;R4;R4; R4;R4;R4;R4; R4;R4;R4;R4; R4;R4;R4;R4; /*1024 */
+ len -= 1024;
+ }
+ while (len >= 128) {
+ READY(0);
+ R4;R4;R4;R4; R4;R4;R4;R4; R4;R4;R4;R4; R4;R4;R4;R4;
+ R4;R4;R4;R4; R4;R4;R4;R4; R4;R4;R4;R4; R4;R4;R4;R4; /* 128 */
+ len -= 128;
+ }
+ while (len) {
+ READY(0);
+ R1;
+ len--;
+ }
+scsi_timeout_error:
+ regs->sci_mode &= ~SCI_MODE_DMA;
+ return count - len;
+}
+#undef R4
+#undef R1
+#endif
+
+/* Some stuff from dp.c ... */
+
+
+#if 0
+/* Select a SCSI device.
+ */
+int scsi_select_ctlr (int ctlr)
+{
+ /* May need other stuff here to syncronize between dp & aic. */
+
+ RD_ADR (u_char, ICU_IO) &= ~ICU_SCSI_BIT; /* i/o, not port */
+ RD_ADR (u_char, ICU_DIR) &= ~ICU_SCSI_BIT; /* output */
+ if (ctlr == NCR5380)
+ RD_ADR (u_char, ICU_DATA) &= ~ICU_SCSI_BIT; /* select = 0 for 8490 */
+ else
+ RD_ADR (u_char, ICU_DATA) |= ICU_SCSI_BIT; /* select = 1 for AIC6250 */
+}
+#endif
diff --git a/sys/arch/pc532/dev/rd.c b/sys/arch/pc532/dev/rd.c
new file mode 100644
index 00000000000..1b54557f7d9
--- /dev/null
+++ b/sys/arch/pc532/dev/rd.c
@@ -0,0 +1,173 @@
+/*
+ * Copyright (c) 1995 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 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.
+ *
+ * $Id: rd.c,v 1.1 1995/10/18 08:51:18 deraadt Exp $
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/buf.h>
+#include <sys/device.h>
+#include <sys/conf.h>
+
+static int rdmatch(struct device *parent, void *cf, void *aux);
+static void rdattach(struct device *parent, struct device *self, void *aux);
+
+struct cfdriver rdcd = {
+ NULL,
+ "rd",
+ rdmatch,
+ rdattach,
+ DV_DISK,
+ sizeof(struct device),
+ NULL,
+ 0
+};
+
+#if !defined(RD_SIZE)
+# define RD_SIZE 0x200000
+#endif
+
+u_char ram_disk[RD_SIZE] = "Ramdiskorigin";
+
+static int
+rdmatch(parent, cf, aux)
+ struct device *parent;
+ void *cf, *aux;
+{
+ return(((struct cfdata *)cf)->cf_unit == 0);
+}
+
+static void
+rdattach(parent, self, aux)
+ struct device *parent, *self;
+ void *aux;
+{
+ printf(" addr 0x%x, size 0x%x\n", ram_disk, RD_SIZE);
+}
+
+
+/* operational routines */
+
+int
+rdopen(dev, flags, devtype, p)
+ dev_t dev;
+ int flags, devtype;
+ struct proc *p;
+{
+ if (minor(dev) == 0)
+ return(0);
+ else
+ return(ENXIO);
+}
+
+int
+rdclose(dev, flags, devtype, p)
+ dev_t dev;
+ int flags, devtype;
+ struct proc *p;
+{
+ return(0);
+}
+
+int
+rdioctl(dev, cmd, addr, flag, p)
+ dev_t dev;
+ u_long cmd;
+ int flag;
+ caddr_t addr;
+ struct proc *p;
+{
+ return(ENOTTY);
+}
+
+int
+rdsize(dev)
+ dev_t dev;
+{
+ if (minor(dev) == 0)
+ return(RD_SIZE / DEV_BSIZE);
+ else
+ return(0);
+}
+
+int
+rddump(dev, blkno, va, size)
+ dev_t dev;
+ daddr_t blkno;
+ caddr_t va;
+ size_t size;
+{
+ return(ENXIO);
+}
+
+void
+rdstrategy(bp)
+ struct buf *bp;
+{
+ int loc, size;
+ char *adr;
+
+ if (minor(bp->b_dev) == 0)
+ loc = bp->b_blkno * DEV_BSIZE;
+ else {
+ bp->b_error = EINVAL;
+ bp->b_flags |= B_ERROR;
+ return;
+ }
+ size = bp->b_bcount;
+ adr = (char *) bp->b_un.b_addr;
+ if (loc + size > sizeof(ram_disk)) {
+ bp->b_error = EINVAL;
+ bp->b_flags |= B_ERROR;
+ return;
+ }
+ if (bp->b_flags & B_READ)
+ bcopy(&ram_disk[loc], adr, size);
+ else
+ bcopy(adr, &ram_disk[loc], size);
+ biodone(bp);
+}
+
+int
+rdread(dev, uio)
+ dev_t dev;
+ struct uio *uio;
+{
+ return(physio(rdstrategy, NULL, dev, B_READ, minphys, uio));
+}
+
+int
+rdwrite(dev, uio)
+ dev_t dev;
+ struct uio *uio;
+{
+ return(physio(rdstrategy, NULL, dev, B_WRITE, minphys, uio));
+}
diff --git a/sys/arch/pc532/dev/scn.c b/sys/arch/pc532/dev/scn.c
new file mode 100644
index 00000000000..1b391b8c022
--- /dev/null
+++ b/sys/arch/pc532/dev/scn.c
@@ -0,0 +1,1119 @@
+/* $NetBSD: scn.c,v 1.22 1995/09/26 20:16:17 phil Exp $ */
+
+/*
+ * Copyright (c) 1991 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)com.c 7.5 (Berkeley) 5/16/91
+ */
+
+#include "scn.h"
+
+#if NSCN > 0
+
+/* #define KERN_MORE */
+
+/* The pc532 has 4 duarts! */
+#define NLINES 8
+
+/*
+ * scn2681 driver for the pc532. Phil Nelson Feb 8, 1993
+ *
+ */
+#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 <dev/cons.h>
+
+#include <machine/icu.h>
+
+#include "scnreg.h"
+
+#include "sl.h"
+
+struct scn_softc {
+ struct device scn_dev;
+ struct tty *scn_tty;
+ struct rs232_s scn_line;
+ char scn_swflags;
+#define SCN_SW_SOFTCAR 0x01
+#define SCN_SW_CLOCAL 0x02
+#define SCN_SW_CRTSCTS 0x04
+};
+
+int scnprobe __P((struct device *, void *, void *));
+void scnattach __P((struct device *, struct device *, void *));
+int scnintr __P((int));
+int scnparam __P((struct tty *, struct termios *));
+void scnstart __P((struct tty *));
+int scnopen __P((dev_t, int, int, struct proc *));
+int scnclose __P((dev_t, int, int, struct proc *));
+
+struct cfdriver scncd =
+ { NULL, "scn", scnprobe, scnattach,
+ DV_TTY, sizeof(struct scn_softc), NULL, 0 };
+
+/* int scnsoftCAR;
+int scn_active; To Be Deleted ... */
+int scnconsole = SCN_CONSOLE;
+int scnconsinit = 0;
+int scndefaultrate = TTYDEF_SPEED;
+int scnmajor;
+
+struct duart_info uart[(NLINES+1)/2];
+/* struct rs232_s line[NLINES];
+ struct tty *scn_tty[NLINES]; To be deleted. */
+
+struct speedtab scnspeedtab[] = {
+ 0, 0x40, /* code for line-hangup */
+ 50, 0x00,
+ 75, 0x10,
+ 110, 0x21,
+ 134, 0x22,
+ 150, 0x13,
+ 200, 0x03,
+ 300, 0x24,
+ 600, 0x25,
+ 1050, 0x07,
+ 1200, 0x26,
+ 1800, 0x1a,
+ 2000, 0x17,
+ 2400, 0x28,
+ 4800, 0x29,
+ 7200, 0x0a,
+ 9600, 0x2b,
+ 19200, 0x1c,
+ 38400, 0x0c,
+ 57600, 0x60, /* An illegal speed....? */
+ -1, -1
+};
+
+#define getspeedcode(sp,val) \
+ { int i=0; \
+ while (scnspeedtab[i].sp_speed != -1 && \
+ scnspeedtab[i].sp_speed != sp) \
+ i++; \
+ val = scnspeedtab[i].sp_code; \
+ }
+
+/* Unit is 0-7. Other parts of the minor number are things like
+ hardware cts/rts handshaking. (XXX how?) */
+
+#define UNIT(x) (minor(x) & 0x7)
+
+/* Which uart is the device on? */
+#define UART(x) (UNIT(x) >> 1)
+
+extern struct tty *constty;
+
+#ifdef KGDB
+#include "machine/remote-sl.h"
+
+extern int kgdb_dev;
+extern int kgdb_rate;
+extern int kgdb_debug_init;
+#endif
+
+
+/* Debug routine to print out the rs line structures. */
+void print_rs (struct rs232_s *rs)
+{
+ printf ("\nline frame overrun parity break\n");
+ printf ("tty%1d state=%2x f=%2d o=%2d p=%2d b=%2d in=%x, out=%x grp=%d\n",
+ rs->unit, rs->framing_errors, rs->overrun_errors,
+ rs->parity_errors, rs->break_interrupts,
+ rs->uart->i_speed[rs->a_or_b], rs->uart->o_speed[rs->a_or_b],
+ rs->uart->speed_grp);
+}
+
+
+/*==========================================================================*
+ * scn_config *
+ *==========================================================================*/
+static
+int scn_config(unit, in_speed, out_speed, parity, stop_bits, data_bits )
+int unit; /* which rs line */
+int in_speed; /* input speed: 110, 300, 1200, etc */
+int out_speed; /* output speed: 110, 300, 1200, etc */
+int parity; /* some parity */
+int stop_bits; /* 2 (110 baud) or 1 (other speeds) */
+int data_bits; /* 5, 6, 7, or 8 */
+{
+/* Set various line control parameters for RS232 I/O. */
+
+ register struct rs232_s *rs;
+ char mr1_val, mr2_val;
+ int sp_grp, sp_both;
+ char set_speed; /* Non zero if we need to set the speed. */
+ char a_or_b; /* Used for ease of access. */
+ int in_code;
+ int out_code;
+ int x;
+
+ /* Get the speed codes. */
+ getspeedcode(in_speed,in_code);
+ getspeedcode(out_speed,out_code);
+
+ /* Check for speed errors. */
+ if (in_code == -1 || out_code == -1)
+ return (EINVAL);
+
+ /* Set up rs pointer. */
+ if (unit >= scncd.cd_ndevs)
+ return ENXIO;
+ rs = &((struct scn_softc *)scncd.cd_devs[unit])->scn_line;
+ a_or_b = rs->a_or_b;
+
+ /* Check out the Speeds. There are two groups of speeds. If the new
+ speeds are not in the same group, or the other line is not the same
+ speed of the other group, do not change the speeds. Also, if the
+ in speed and the out speed are in different groups, use the in speed. */
+
+ set_speed = FALSE;
+ if ( (in_code != rs->uart->i_code[a_or_b])
+ || (out_code != rs->uart->o_code[a_or_b])) {
+
+ /* We need to set the speeds .*/
+ set_speed = TRUE;
+
+ if ( ((in_code & LC_SP_GRP) != (out_code & LC_SP_GRP))
+ && (((in_code | out_code) & LC_SP_BOTH) != 1) ) {
+ /* Input speed and output speed are different groups. */
+ return (EINVAL);
+ }
+
+ sp_grp = ((in_code | out_code) & LC_SP_GRP)>>4;
+ sp_both = in_code & out_code & LC_SP_BOTH;
+
+ /* Check for compatibility and set the uart values */
+ if (sp_both)
+ sp_grp = rs->uart->speed_grp;
+ else
+ if ((sp_grp != rs->uart->speed_grp)
+ && !(rs->uart->i_code[1-a_or_b] & rs->uart->o_code[1-a_or_b]
+ & LC_SP_BOTH)) {
+ /* Can't change group, don`t change the speed rates. */
+ return (EINVAL);
+ }
+ rs->uart->i_code[a_or_b] = in_code;
+ rs->uart->o_code[a_or_b] = out_code;
+ rs->uart->i_speed[a_or_b] = in_speed;
+ rs->uart->o_speed[a_or_b] = out_speed;
+ }
+
+ /* Lock out interrupts while setting the parameters. (Just for safety.)
+ */
+ x=spltty();
+ WR_ADR (u_char, rs->cmd_port, CMD_MR1);
+ mr1_val = RD_ADR (u_char, rs->mr_port);
+ mr2_val = RD_ADR (u_char, rs->mr_port);
+ if ((((mr1_val & 0xe0) | parity | data_bits) != mr1_val) ||
+ (((mr2_val & 0xf0) | stop_bits) != mr2_val)) {
+ WR_ADR (u_char, rs->cmd_port, CMD_MR1);
+ WR_ADR (u_char, rs->mr_port, (mr1_val & 0xe0) | parity | data_bits);
+ WR_ADR (u_char, rs->mr_port, (mr2_val & 0xf0) | stop_bits);
+ }
+ if (set_speed) {
+ if (rs->uart->speed_grp != sp_grp) {
+ /* Change the group! */
+ rs->uart->speed_grp = sp_grp;
+ WR_ADR (u_char, rs->acr_port, (sp_grp << 7) | rs->uart->acr_int_bits);
+ }
+ WR_ADR (u_char, rs->speed_port, ((in_code & 0x0f) << 4)
+ | (out_code & 0x0f));
+ }
+ DELAY(96000/out_speed);
+
+ splx(x);
+ return (0);
+}
+
+
+scnprobe(parent, cf, aux)
+ struct device *parent;
+ void *cf;
+ void *aux;
+{
+ int unit = ((struct cfdata *)cf)->cf_unit;
+
+ if (unit >= NLINES) {
+ return(0); /* dev is "not working." */
+ } else {
+ return(1); /* dev is "working." */
+ }
+}
+
+void
+scnattach(parent, self, aux)
+ struct device *parent, *self;
+ void *aux;
+{
+ static char scnints[4] = { IR_TTY0, IR_TTY1, IR_TTY2, IR_TTY3 };
+ struct scn_softc *sc = (void *) self;
+ struct tty *tp;
+ u_char unit = sc->scn_dev.dv_unit;
+ u_char duart = unit >> 1;
+ register struct rs232_s *rs = &sc->scn_line;
+ int x;
+ int speed;
+ long line_base;
+ long uart_base;
+ long scn_first_adr;
+
+ if (unit == 0) DELAY(5); /* Let the output go out.... */
+
+ sc->scn_swflags |= SCN_SW_SOFTCAR;
+
+ /* Record unit number, uart, channel a_or_b. */
+ rs->unit = unit;
+ rs->uart = &uart[unit >> 1];
+ rs->a_or_b = unit % 2;
+
+ /* Establish interrupt vector */
+ if (rs->a_or_b == 0) {
+ /* Arg 0 is special, so we must pass "unit + 1" */
+ intr_establish(scnints[unit >> 1], (void (*)(void *))scnintr,
+ (void *)(unit + 1), sc->scn_dev.dv_xname, IPL_TTY, FALLING_EDGE);
+ }
+
+ /* Precalculate port numbers for speed. Magic numbers in the code (once). */
+ scn_first_adr = SCN_FIRST_MAP_ADR; /* to get around a gcc bug. */
+ line_base = scn_first_adr + LINE_SZ * unit;
+ uart_base = scn_first_adr + UART_SZ * duart;
+ rs->xmit_port = DATA_ADR;
+ rs->recv_port = DATA_ADR;
+ rs->mr_port = MR_ADR;
+ rs->stat_port = STAT_ADR;
+ rs->speed_port = SPEED_ADR;
+ rs->cmd_port = CMD_ADR;
+ rs->acr_port = ACR_ADR;
+ rs->ip_port = IP_ADR;
+ rs->opset_port = SET_OP_ADR;
+ rs->opclr_port = CLR_OP_ADR;
+
+ /* Initialize error counts */
+ rs->framing_errors = 0;
+ rs->overrun_errors = 0;
+ rs->parity_errors = 0;
+ rs->break_interrupts = 0;
+
+ /* Set up the hardware to a base state, in particular
+ * o reset transmitter and receiver
+ * o set speeds and configurations
+ * o receiver interrupts only (RxRDY and BREAK)
+ */
+
+ x = spltty();
+ istop(rs); /* CTS off... */
+
+ WR_ADR (u_char, rs->cmd_port, CMD_DIS_RX | CMD_DIS_TX);
+ WR_ADR (u_char, rs->cmd_port, CMD_RESET_RX);
+ WR_ADR (u_char, rs->cmd_port, CMD_RESET_TX);
+ WR_ADR (u_char, rs->cmd_port, CMD_RESET_ERR);
+ WR_ADR (u_char, rs->cmd_port, CMD_RESET_BRK);
+ WR_ADR (u_char, rs->cmd_port, CMD_MR1);
+ WR_ADR (u_char, rs->mr_port, 0); /* No receiver control of RTS. */
+ WR_ADR (u_char, rs->mr_port, 0);
+#if 1
+ if (unit != 0) {
+ WR_ADR (u_char, rs->mr_port, 0x80); /* Enable receiver control of RTS */
+ WR_ADR (u_char, rs->mr_port, 0x10); /* Enable CTS transmitter control */
+ }
+#endif
+
+ /* Initialize the uart structure if this is channel A. */
+ if (rs->a_or_b == 0) {
+ /* uart ports */
+ rs->uart->isr_port = ISR_ADR;
+ rs->uart->imr_port = IMR_ADR;
+ rs->uart->ipcr_port = IPCR_ADR;
+ rs->uart->opcr_port = OPCR_ADR;
+
+ /* Disable all interrupts. */
+ WR_ADR (u_char, rs->uart->imr_port, 0);
+ rs->uart->imr_int_bits = 0;
+
+ /* Output port config */
+ WR_ADR (u_char, rs->uart->opcr_port, 0);
+
+ /* Speeds... */
+ rs->uart->speed_grp = 1;
+ rs->uart->acr_int_bits = 0;
+ /* Set initial speed to an illegal code that can be changed to
+ any other baud. */
+ rs->uart->i_code[0] = rs->uart->o_code[0] =
+ rs->uart->i_code[1] = rs->uart->o_code[1] = 0x2f;
+ rs->uart->i_speed[0] = rs->uart->o_speed[0] =
+ rs->uart->i_speed[1] = rs->uart->o_speed[1] = 0x0;
+ }
+
+#if 0
+ rs->uart->acr_int_bits |= ACR_CTS << rs->a_or_b; /* Set CTS int */
+#endif
+ WR_ADR (u_char, rs->acr_port,
+ (rs->uart->speed_grp << 7) | rs->uart->acr_int_bits);
+ scn_config(unit, scndefaultrate, scndefaultrate,
+ LC_NONE, LC_STOP1, LC_BITS8);
+
+ /* Turn on the Rx and Tx. */
+ WR_ADR (u_char, rs->cmd_port, CMD_ENA_RX | CMD_ENA_TX);
+
+ /* Set up the interrupts. */
+ rs->uart->imr_int_bits
+ |= (/*IMR_RX_INT | IMR_TX_INT |*/ unit?IMR_BRK_INT:0) << (4*rs->a_or_b) | IMR_IP_INT;
+ WR_ADR (u_char, rs->uart->imr_port, rs->uart->imr_int_bits);
+
+ splx(x);
+
+#ifdef KGDB
+ if (kgdb_dev == makedev(scnmajor, unit+1)) {
+ if (scnconsole == unit)
+ kgdb_dev = -1; /* can't debug over console port */
+ else {
+ (void) scninit(unit, kgdb_rate);
+ if (kgdb_debug_init) {
+ /*
+ * Print prefix of device name,
+ * let kgdb_connect print the rest.
+ */
+ printf("scn%d: ", unit);
+ kgdb_connect(1);
+ } else
+ printf("scn%d: kgdb enabled\n", unit);
+ }
+ }
+#endif
+
+ /* print the device number... */
+ printf (" addr 0x%x\n", line_base);
+}
+
+/* ARGSUSED */
+scnopen(dev_t dev, int flag, int mode, struct proc *p)
+{
+ struct scn_softc *sc;
+ register struct tty *tp;
+ register int unit = UNIT(dev);
+ register struct rs232_s *rs;
+ int error = 0;
+ int x;
+
+ /* Set up rs pointer. */
+ if (unit >= scncd.cd_ndevs)
+ return ENXIO;
+ sc = scncd.cd_devs[unit];
+ if (!sc)
+ return ENXIO;
+ rs = &sc->scn_line;
+
+ x = spltty();
+
+ if(!sc->scn_tty) {
+ tp = sc->scn_tty = ttymalloc();
+ } else
+ tp = sc->scn_tty;
+
+ tp->t_oproc = scnstart;
+ tp->t_param = scnparam;
+ tp->t_dev = dev;
+ if ((tp->t_state & TS_ISOPEN) == 0) {
+ tp->t_state |= TS_WOPEN;
+ ttychars(tp);
+ tp->t_iflag = TTYDEF_IFLAG;
+ tp->t_oflag = TTYDEF_OFLAG;
+ tp->t_cflag = TTYDEF_CFLAG;
+ if (sc->scn_swflags & SCN_SW_CLOCAL)
+ tp->t_cflag |= CLOCAL;
+ if (sc->scn_swflags & SCN_SW_CRTSCTS)
+ tp->t_cflag |= CRTSCTS;
+ tp->t_lflag = TTYDEF_LFLAG;
+ tp->t_ispeed = tp->t_ospeed = scndefaultrate;
+ scnparam(tp, &tp->t_termios);
+ ttsetwater(tp);
+
+ /* Turn on DTR and RTS. */
+ istart(rs);
+ rx_ints_on (rs);
+
+ /* Carrier? XXX fix more like i386 */
+ if ((sc->scn_swflags & SCN_SW_SOFTCAR) || get_dcd(rs))
+ tp->t_state |= TS_CARR_ON;
+ } else if (tp->t_state&TS_XCLUDE && p->p_ucred->cr_uid != 0) {
+ splx(x);
+ return (EBUSY);
+ }
+
+ /* wait for carrier if necessary */
+ if ((flag & O_NONBLOCK) == 0)
+ while ((tp->t_cflag & CLOCAL) == 0 &&
+ (tp->t_state & TS_CARR_ON) == 0) {
+ tp->t_state |= TS_WOPEN;
+ error = ttysleep(tp, (caddr_t)&tp->t_rawq,
+ TTIPRI | PCATCH, ttopen, 0);
+ if (error) {
+ /* XXX should turn off chip if we're the
+ only waiter */
+ splx(x);
+ return error;
+ }
+ }
+ splx(x);
+
+ return (*linesw[tp->t_line].l_open)(dev, tp);
+}
+
+/*ARGSUSED*/
+scnclose(dev, flag, mode, p)
+ dev_t dev;
+ int flag, mode;
+ struct proc *p;
+{
+ register int unit = UNIT(dev);
+ struct scn_softc *sc = scncd.cd_devs[unit];
+ register struct tty *tp = sc->scn_tty;
+ register struct rs232_s *rs = &sc->scn_line;
+
+ (*linesw[tp->t_line].l_close)(tp, flag);
+#ifdef KGDB
+ /* do not disable interrupts if debugging */
+ if (kgdb_dev != makedev(scnmajor, unit))
+#endif
+ if ((tp->t_state&TS_ISOPEN) == 0)
+ rx_ints_off (rs);
+ if (tp->t_cflag&HUPCL || tp->t_state&TS_WOPEN ||
+ (tp->t_state&TS_ISOPEN) == 0) {
+ WR_ADR (u_char, rs->opclr_port, DTR_BIT << rs->a_or_b);
+ DELAY (10);
+ WR_ADR (u_char, rs->opset_port, DTR_BIT << rs->a_or_b);
+ }
+ ttyclose(tp);
+#if 0
+ if ((tp->t_state&TS_ISOPEN) == 0) {
+ ttyfree(tp);
+ sc->scn_tty = (struct tty *)NULL;
+ }
+#endif
+ return(0);
+}
+
+scnread(dev, uio, flag)
+ dev_t dev;
+ struct uio *uio;
+{
+ register struct scn_softc *sc = scncd.cd_devs[UNIT(dev)];
+ register struct tty *tp = sc->scn_tty;
+
+ return ((*linesw[tp->t_line].l_read)(tp, uio, flag));
+}
+
+scnwrite(dev, uio, flag)
+ dev_t dev;
+ struct uio *uio;
+{
+ register struct scn_softc *sc = scncd.cd_devs[UNIT(dev)];
+ register struct tty *tp = sc->scn_tty;
+
+ return ((*linesw[tp->t_line].l_write)(tp, uio, flag));
+}
+
+struct tty *
+scntty(dev)
+ dev_t dev;
+{
+ register struct scn_softc *sc = scncd.cd_devs[UNIT(dev)];
+ register struct tty *tp = sc->scn_tty;
+
+ return (tp);
+}
+
+void cts_int (struct rs232_s *rs, struct tty *tp)
+{
+}
+
+#if 0
+scnintr(int uart_no)
+{
+ int line0 = uart_no << 1;
+ int line1 = (uart_no << 1)+1;
+
+ register struct scn_softc *sc0 = scncd.cd_devs[line0];
+ register struct scn_softc *sc1 = scncd.cd_devs[line1];
+
+ register struct tty *tp0 = sc0->scn_tty;
+ register struct tty *tp1 = sc1->scn_tty;
+
+ register struct rs232_s *rs0 = &sc0->scn_line;
+ register struct rs232_s *rs1 = &sc1->scn_line;
+
+ register struct duart_info *uart = rs0->uart;
+
+ char rs_work = TRUE;
+
+ u_char rs_stat;
+ u_char rs_ipcr;
+ u_char ch;
+
+
+ rs_stat = RD_ADR(u_char, uart->isr_port);
+ printf ("scnintr, rs_stat = 0x%x\n", rs_stat);
+
+ if (rs_stat & IMR_BRK_INT) {
+ /* A break interrupt! */
+ rs0->lstatus = RD_ADR(u_char, rs0->stat_port);
+ printf ("lstatus = 0x%x\n", rs0->lstatus);
+ if (rs0->lstatus & SR_BREAK) {
+ ++rs0->break_interrupts;
+ RD_ADR(u_char, rs0->recv_port); /* Toss zero character. */
+ rs_stat &= ~IMR_RX_INT;
+ }
+ WR_ADR (u_char, rs0->cmd_port, CMD_RESET_BRK);
+ rs0->lstatus = RD_ADR(u_char, rs0->stat_port);
+ printf ("lstatus = 0x%x\n", rs0->lstatus);
+ }
+ if (rs_stat & IMR_RX_INT) {
+ ch = RD_ADR(u_char, rs0->recv_port);
+ printf ("input ch = \"%c\"\n", ch);
+ }
+}
+/* Change this for real interrupts! */
+_scnintr(int uart_no)
+
+#else
+
+/* Change this for real interrupts! */
+scnintr(int line1)
+#endif
+{
+ register struct scn_softc *sc0 = scncd.cd_devs[line1 - 1];
+ register struct scn_softc *sc1 = scncd.cd_devs[line1];
+
+ register struct tty *tp0 = sc0->scn_tty;
+ register struct tty *tp1 = sc1->scn_tty;
+
+ register struct rs232_s *rs0 = &sc0->scn_line;
+ register struct rs232_s *rs1 = &sc1->scn_line;
+
+ register struct duart_info *uart = rs0->uart;
+
+ char rs_work = TRUE;
+
+ u_char rs_stat;
+ u_char rs_ipcr;
+ u_char ch;
+
+#ifdef CON_BRK_PANIC
+ u_char nr_brk = 0;
+#endif
+
+ while (rs_work) {
+ /* Loop to pick up ALL pending interrupts for device.
+ */
+ rs_work = FALSE;
+ rs_stat = RD_ADR(u_char, uart->isr_port);
+/* if (rs_stat & ~(IMR_TX_INT | IMR_TXB_INT)) printf ("scn intr rs_stat = 0x%x\n", rs_stat); */
+ if ((rs_stat & IMR_TX_INT) && (tp0 != NULL)
+ && (tp0->t_state & TS_BUSY)) {
+ /* output char done. */
+ tp0->t_state &= ~(TS_BUSY|TS_FLUSH);
+ tx_ints_off(rs0);
+ if (tp0->t_line)
+ (*linesw[tp0->t_line].l_start)(tp0);
+ else
+ scnstart(tp0);
+ rs_work = TRUE;
+ }
+ if (rs_stat & IMR_BRK_INT && (tp0 != NULL)) {
+ /* A break interrupt! */
+ rs0->lstatus = RD_ADR(u_char, rs0->stat_port);
+ if (rs0->lstatus & SR_BREAK) {
+ ++rs0->break_interrupts;
+ RD_ADR(u_char, rs0->recv_port); /* Toss zero character. */
+ rs_stat &= ~IMR_RX_INT;
+ }
+ WR_ADR (u_char, rs0->cmd_port, CMD_RESET_BRK);
+ rs_work = TRUE;
+#ifdef CON_BRK_PANIC
+ if (line1 == 1 && (rs0->lstatus & SR_BREAK)) {
+ if (++nr_brk >= 3) {
+ char c;
+ printf("\r\nDo you want a dump (y/n)? ");
+ do
+ c = cngetc();
+ while (c != 'y' && c != 'n');
+ printf("%c\r\n", c);
+ if (c == 'y') {
+ panic("Panic Button");
+ }
+ }
+ }
+#endif
+ }
+ if (rs_stat & IMR_RX_INT && (tp0 != NULL)) {
+ ch = RD_ADR(u_char, rs0->recv_port);
+ if (tp0->t_state & TS_ISOPEN)
+ (*linesw[tp0->t_line].l_rint)(ch, tp0);
+ rs_work = TRUE;
+#ifdef CON_BRK_PANIC
+ if (line1 == 1) nr_brk = 0;
+#endif
+ }
+ if ((rs_stat & IMR_TXB_INT) && (tp1 != NULL)
+ && (tp1->t_state & TS_BUSY)) {
+ /* output char done. */
+ tp1->t_state &= ~(TS_BUSY|TS_FLUSH);
+ tx_ints_off(rs1);
+ if (tp1->t_line)
+ (*linesw[tp1->t_line].l_start)(tp1);
+ else
+ scnstart(tp1);
+ rs_work = TRUE;
+ }
+ if (rs_stat & IMR_BRKB_INT && (tp1 != NULL)) {
+ /* A break interrupt! */
+ rs1->lstatus = RD_ADR(u_char, rs1->stat_port);
+ if (rs1->lstatus & SR_BREAK) {
+ ++rs1->break_interrupts;
+ RD_ADR(u_char, rs1->recv_port); /* Toss zero character. */
+ rs_stat &= ~IMR_RXB_INT;
+ }
+ WR_ADR (u_char, rs1->cmd_port, CMD_RESET_BRK);
+ rs_work = TRUE;
+ }
+ if (rs_stat & IMR_RXB_INT && (tp1 != NULL)) {
+ ch = RD_ADR(u_char, rs1->recv_port);
+ if (tp1->t_state & TS_ISOPEN)
+ (*linesw[tp1->t_line].l_rint)(ch, tp1);
+ rs_work = TRUE;
+ }
+ if (rs_stat & IMR_IP_INT) {
+ rs_work = TRUE;
+ rs_ipcr = RD_ADR (u_char, uart->ipcr_port);
+#if 0
+ /* RTS/CTS stuff! */
+ if (rs_ipcr & IPCR_CTS)
+ cts_int(rs0, tp0);
+ if (rs_ipcr & (IPCR_CTS << 1))
+ cts_int(rs1, tp1);
+#endif
+#if 0
+ if (rs_ipcr & ACR_DCD)
+ dcd_int(rs0, tp0);
+ if (rs_ipcr & (ACR_DCD << 1))
+ dcd_int(rs1, tp1);
+#endif
+ }
+ }
+}
+
+
+scnioctl(dev, cmd, data, flag, p)
+ dev_t dev;
+ int cmd;
+ caddr_t data;
+ int flag;
+ struct proc *p;
+{
+ register int unit = UNIT(dev);
+ register struct scn_softc *sc = scncd.cd_devs[unit];
+ register struct tty *tp = sc->scn_tty;
+ register struct rs232_s *rs = &sc->scn_line;
+ register scn;
+ register int error;
+
+ 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:
+ WR_ADR(u_char, rs->cmd_port, CMD_START_BRK);
+ break;
+
+ case TIOCCBRK:
+ WR_ADR (u_char, rs->cmd_port, CMD_STOP_BRK);
+ break;
+
+ case TIOCSDTR:
+ WR_ADR(u_char, rs->opset_port,
+ (DTR_BIT | RTS_BIT) << rs->a_or_b);
+ break;
+
+ case TIOCCDTR:
+ WR_ADR(u_char, rs->opclr_port,
+ (DTR_BIT | RTS_BIT) << rs->a_or_b);
+ break;
+
+ case TIOCMSET:
+/* (void) scnmctl(dev, *(int *)data, DMSET); */
+ rs->scn_bits = *(long *)data;
+ break;
+
+ case TIOCMBIS:
+/* (void) scnmctl(dev, *(int *)data, DMBIS); */
+ rs->scn_bits |= *(int *)data;
+ break;
+
+ case TIOCMBIC:
+/* (void) scnmctl(dev, *(int *)data, DMBIC); */
+ rs->scn_bits &= ~(*(int *)data);
+ break;
+
+ case TIOCMGET:
+/* *(int *)data = scnmctl(dev, 0, DMGET); */
+ *(int *)data = rs->scn_bits;
+ break;
+
+/* 386 case TIOCGFLAGS: {
+ int bits = 0;
+
+ if (sc->sc_swflags & COM_SW_SOFTCAR)
+ bits |= TIOCFLAG_SOFTCAR;
+ if (sc->sc_swflags & COM_SW_CLOCAL)
+ bits |= TIOCFLAG_CLOCAL;
+ if (sc->sc_swflags & COM_SW_CRTSCTS)
+ bits |= TIOCFLAG_CRTSCTS;
+ if (sc->sc_swflags & COM_SW_MDMBUF)
+ bits |= TIOCFLAG_MDMBUF;
+
+ *(int *)data = bits;
+ break;
+ }
+ case TIOCSFLAGS: {
+ int userbits, driverbits = 0;
+
+ error = suser(p->p_ucred, &p->p_acflag);
+ if (error != 0)
+ return(EPERM);
+
+ userbits = *(int *)data;
+ if ((userbits & TIOCFLAG_SOFTCAR) ||
+ (sc->sc_hwflags & COM_HW_CONSOLE))
+ driverbits |= COM_SW_SOFTCAR;
+ if (userbits & TIOCFLAG_CLOCAL)
+ driverbits |= COM_SW_CLOCAL;
+ if (userbits & TIOCFLAG_CRTSCTS)
+ driverbits |= COM_SW_CRTSCTS;
+ if (userbits & TIOCFLAG_MDMBUF)
+ driverbits |= COM_SW_MDMBUF;
+
+ sc->sc_swflags = driverbits;
+ break;
+ }
+*/
+ default:
+ return (ENOTTY);
+ }
+ return (0);
+}
+
+scnparam(tp, t)
+ register struct tty *tp;
+ register struct termios *t;
+{
+ int cflag = t->c_cflag;
+ int unit = UNIT(tp->t_dev);
+ register struct scn_softc *sc = scncd.cd_devs[unit];
+ int parity = LC_NONE,
+ stop_bits = LC_STOP1,
+ data_bits = LC_BITS8;
+ int error;
+ struct rs232_s *rs = &sc->scn_line;
+
+ /* Is this a hang up? */
+ if (t->c_ospeed == B0) {
+ WR_ADR (u_char, rs->opclr_port, DTR_BIT << rs->a_or_b);
+ DELAY (10);
+ WR_ADR (u_char, rs->opset_port, DTR_BIT << rs->a_or_b);
+ return(0);
+ }
+
+ /* Parity? */
+ if (cflag&PARENB) {
+ if ((cflag&PARODD) == 0)
+ parity = LC_EVEN;
+ else
+ parity = LC_ODD;
+ }
+
+ /* Stop bits. */
+ if (cflag&CSTOPB)
+ stop_bits = LC_STOP1;
+
+ /* Data bits. */
+ switch (cflag&CSIZE) {
+ case CS5:
+ data_bits = LC_BITS5; break;
+ case CS6:
+ data_bits = LC_BITS6; break;
+ case CS7:
+ data_bits = LC_BITS7; break;
+ case CS8:
+ data_bits = LC_BITS8; break;
+ }
+
+ error = scn_config (unit, t->c_ispeed, t->c_ospeed, parity, stop_bits,
+ data_bits);
+
+ /* If successful, copy to tty */
+ if (!error) {
+ tp->t_ispeed = t->c_ispeed;
+ tp->t_ospeed = t->c_ospeed;
+ tp->t_cflag = cflag;
+ }
+
+ return (error);
+}
+
+void
+scnstart(tp)
+ register struct tty *tp;
+{
+ int s, c;
+ int unit = UNIT(tp->t_dev);
+ register struct scn_softc *sc = scncd.cd_devs[unit];
+ struct rs232_s *rs = &sc->scn_line;
+
+ s = spltty();
+ if (tp->t_state & (TS_BUSY|TS_TTSTOP))
+ goto out;
+ if (tp->t_outq.c_cc <= tp->t_lowat) {
+ if (tp->t_state&TS_ASLEEP) {
+ tp->t_state &= ~TS_ASLEEP;
+ wakeup((caddr_t)&tp->t_outq);
+ }
+ selwakeup(&tp->t_wsel);
+ }
+ if (tp->t_outq.c_cc == 0)
+ goto out;
+ tp->t_state |= TS_BUSY;
+ if (tx_rdy(rs)) {
+ c = getc(&tp->t_outq);
+ WR_ADR(u_char, rs->xmit_port, c);
+ tx_ints_on(rs);
+ }
+out:
+ splx(s);
+}
+
+/*
+ * Stop output on a line.
+ */
+/*ARGSUSED*/
+scnstop(tp, flag)
+ register struct tty *tp;
+{
+ register int s;
+
+ s = spltty();
+ if (tp->t_state & TS_BUSY) {
+ if ((tp->t_state&TS_TTSTOP)==0)
+ tp->t_state |= TS_FLUSH;
+ }
+ splx(s);
+}
+
+/*
+ * Following are all routines needed for SCN to act as console
+ */
+
+scncnprobe(cp)
+ struct consdev *cp;
+{
+ /* locate the major number */
+ for (scnmajor = 0; scnmajor < nchrdev; scnmajor++)
+ if (cdevsw[scnmajor].d_open == scnopen)
+ break;
+
+ /* make sure hardware exists? XXX */
+
+ /* initialize required fields */
+ cp->cn_dev = makedev(scnmajor, SCN_CONSOLE);
+ cp->cn_pri = CN_NORMAL;
+ return 1;
+}
+
+scncninit(cp)
+ struct consdev *cp;
+{
+#if 0
+ int unit = UNIT(cp->cn_dev);
+
+ scninit(unit, scndefaultrate);
+ scnconsole = unit;
+ scnconsinit = 1;
+#endif
+}
+
+scninit(unit, rate)
+ int unit, rate;
+{
+#if 0
+ register int scn;
+ int s;
+ short stat;
+
+#ifdef lint
+ stat = unit; if (stat) return;
+#endif
+ scn = scn_addr[unit];
+ s = splhigh();
+ outb(com+com_cfcr, CFCR_DLAB);
+ rate = ttspeedtab(comdefaultrate, comspeedtab);
+ outb(com+com_data, rate & 0xFF);
+ outb(com+com_ier, rate >> 8);
+ outb(com+com_cfcr, CFCR_8BITS);
+ outb(com+com_ier, IER_ERXRDY | IER_ETXRDY);
+ outb(com+com_fifo, FIFO_ENABLE|FIFO_RCV_RST|FIFO_XMT_RST|FIFO_TRIGGER_14);
+ stat = inb(com+com_iir);
+ splx(s);
+#endif
+}
+
+#if 0
+int
+scnselect(dev, rw, p)
+ dev_t dev;
+ int rw;
+ struct proc *p;
+{
+ register struct tty *tp = scn_tty[UNIT(dev)];
+ int nread;
+ int s = spltty();
+ struct proc *selp;
+
+ switch (rw) {
+
+ case FREAD:
+ nread = ttnread(tp);
+ if (nread > 0 ||
+ ((tp->t_cflag&CLOCAL) == 0 && (tp->t_state&TS_CARR_ON) == 0))
+ goto win;
+ selrecord(p, &tp->t_rsel);
+ break;
+
+ case FWRITE:
+ if (tp->t_outq.c_cc <= tp->t_lowat)
+ goto win;
+ selrecord(p, &tp->t_wsel);
+ break;
+ }
+ splx(s);
+ return (0);
+ win:
+ splx(s);
+ return (1);
+}
+#endif
+
+
+/* So the kernel can write in unmapped mode! */
+int _mapped = 0;
+
+/*
+ * Console kernel input character routine.
+ */
+
+char
+scncngetc(dev_t dev)
+{
+ char c;
+ int x = spltty();
+ WR_ADR (u_char, SCN_FIRST_MAP_ADR + 14, (RTS_BIT | DTR_BIT));
+ while (0 == (RD_ADR (u_char, SCN_CON_MAP_STAT) & SR_RX_RDY));
+ c = RD_ADR(u_char, SCN_CON_MAP_DATA);
+ splx(x);
+ return c;
+}
+
+/* pc532 does not turn off console polling. */
+char
+scncnpollc(dev_t dev, int on)
+{
+}
+
+
+/*
+ * Console kernel output character routine.
+ */
+
+/* A simple kernel level "more" for debugging output. */
+#ifdef KERN_MORE
+int ___lines = 0;
+#endif
+
+scncnputc (dev_t dev, char c)
+{
+ int x = spltty();
+
+ if (c == '\n') scncnputc(dev,'\r');
+ if (_mapped) {
+ while (0 == (RD_ADR (u_char, SCN_CON_MAP_STAT) & SR_TX_RDY));
+ WR_ADR (u_char, SCN_CON_MAP_DATA, c);
+ while (0 == (RD_ADR (u_char, SCN_CON_MAP_STAT) & SR_TX_RDY));
+ RD_ADR(u_char, SCN_CON_MAP_ISR);
+ } else {
+ while (0 == (RD_ADR (u_char, SCN_CON_STAT) & SR_TX_RDY));
+ WR_ADR (u_char, SCN_CON_DATA, c);
+ while (0 == (RD_ADR (u_char, SCN_CON_STAT) & SR_TX_RDY));
+ RD_ADR(u_char, SCN_CON_ISR);
+ }
+#ifdef KERN_MORE
+ if (c == '\n' && ___lines >= 0)
+ {
+ if (++___lines == 22) {
+ ___lines = 0;
+ scncnputc(dev,'m');scncnputc(dev,'o');scncnputc(dev,'r');
+ scncnputc(dev,'e');scncnputc(dev,':');scncnputc(dev,' ');
+ scncngetc(dev);
+ scncnputc(dev,'\n');
+ }
+ }
+#endif
+ splx(x);
+}
+
+#endif
diff --git a/sys/arch/pc532/dev/scnreg.h b/sys/arch/pc532/dev/scnreg.h
new file mode 100644
index 00000000000..569ce9c5db7
--- /dev/null
+++ b/sys/arch/pc532/dev/scnreg.h
@@ -0,0 +1,209 @@
+/* $NetBSD: scnreg.h,v 1.5 1994/10/26 08:24:19 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.
+ *
+ * scnreg.h: definitions for the scn serial driver.
+ */
+
+/* Constants. */
+#ifdef COMDEF_SPEED
+#undef TTYDEF_SPEED
+#define TTYDEF_SPEED COMDEF_SPEED /* default baud rate */
+#endif
+
+#define SCN_FIRST_ADR 0x28000000 /* address of first RS232 port */
+#define SCN_FIRST_MAP_ADR 0xFFC80000 /* mapped address of first port */
+
+#define SCN_SIZE 0x8 /* address space for port */
+
+#define SCN_CONSOLE 0 /* minor number of console */
+
+#define SCN_CON_MAP_STAT 0xFFC80001 /* raw addresses for console */
+#define SCN_CON_MAP_DATA 0xFFC80003 /* Mapped .... */
+#define SCN_CON_MAP_ISR 0xFFC80005
+
+#define SCN_CON_STAT 0x28000001 /* raw addresses for console */
+#define SCN_CON_DATA 0x28000003 /* Unmapped .... */
+#define SCN_CON_ISR 0x28000005
+
+
+/* SCN2691 registers, values. */
+#define LINE_SZ 0x08
+#define UART_SZ 0x10
+#define MR_ADR (line_base+0)
+#define STAT_ADR (line_base+1)
+#define SPEED_ADR (line_base+1)
+#define CMD_ADR (line_base+2)
+#define DATA_ADR (line_base+3)
+#define IPCR_ADR (uart_base+4)
+#define ACR_ADR (uart_base+4)
+#define ISR_ADR (uart_base+5)
+#define IMR_ADR (uart_base+5)
+#define IP_ADR (uart_base+13)
+#define OPCR_ADR (uart_base+13)
+#define SET_OP_ADR (uart_base+14)
+#define CLR_OP_ADR (uart_base+15)
+
+/* Data Values */
+#define LC_ODD 0x04
+#define LC_EVEN 0x00
+#define LC_NONE 0x10
+#define LC_STOP1 0x07
+#define LC_STOP2 0x0f
+#define LC_BITS5 0x00
+#define LC_BITS6 0x01
+#define LC_BITS7 0x02
+#define LC_BITS8 0x03
+#define LC_CHARS 0x03
+#define LC_CHARS_SHIFT 0x08
+#define LC_SP_GRP 0x10
+#define LC_SP_BOTH 0x20
+
+#define RTS_BIT 0x1
+#define CTS_BIT 0x1
+#define DTR_BIT 0x4
+#define DCD_BIT 0x4
+
+/* CR (command) register values. */
+#define CMD_ENA_RX 0x01
+#define CMD_DIS_RX 0x02
+#define CMD_ENA_TX 0x04
+#define CMD_DIS_TX 0x08
+#define CMD_MR1 0x10
+#define CMD_RESET_RX 0x20
+#define CMD_RESET_TX 0x30
+#define CMD_RESET_ERR 0x40
+#define CMD_RESET_BRK 0x50
+#define CMD_START_BRK 0x60
+#define CMD_STOP_BRK 0x70
+
+/* SR register */
+#define SR_RX_RDY 0x01
+#define SR_TX_RDY 0x04
+#define SR_BREAK 0x80
+#define SR_FRAME 0x40
+#define SR_PARITY 0x20
+#define SR_OVERRUN 0x10
+
+/* Output port configuration. */
+#define OPCR_CONFIG 0x00
+
+/* Input port interrupt config. */
+#define ACR_CTS 0x01
+#define ACR_DCD 0x04
+#define IPCR_CTS 0x10
+#define IPCR_DCD 0x40
+
+/* Interrupt configurations. */
+#define IMR_IP_INT 0x80
+#define IMR_BRK_INT 0x04
+#define IMR_RX_INT 0x02
+#define IMR_TX_INT 0x01
+#define IMR_BRKB_INT 0x40
+#define IMR_RXB_INT 0x20
+#define IMR_TXB_INT 0x10
+
+/* If we need a delay.... */
+#define DELAY(x) {int i; for (i=0; i<x*10000; i++); }
+
+#define istart(rs) \
+ (WR_ADR(u_char, rs->opset_port, (RTS_BIT | DTR_BIT) << (rs)->a_or_b))
+
+#define istop(rs) \
+ (WR_ADR(u_char, rs->opclr_port, RTS_BIT << (rs)->a_or_b))
+
+#define get_dcd(rs) \
+ (RD_ADR(u_char, rs->ip_port) & (DCD_BIT << (1-rs->a_or_b)))
+
+#define tx_rdy(rs) \
+ (RD_ADR(u_char, rs->stat_port) & SR_TX_RDY)
+
+/* Interrupts on and off. */
+#define tx_ints_off(rs) \
+ { rs->uart->imr_int_bits &= ~((IMR_TX_INT) << (4*rs->a_or_b)); \
+ WR_ADR (u_char, rs->uart->imr_port, rs->uart->imr_int_bits); }
+
+#define tx_ints_on(rs) \
+ { rs->uart->imr_int_bits |= (IMR_TX_INT) << (4*rs->a_or_b); \
+ WR_ADR (u_char, rs->uart->imr_port, rs->uart->imr_int_bits); }
+
+#define rx_ints_off(rs) \
+ { rs->uart->imr_int_bits &= ~((IMR_RX_INT) << (4*rs->a_or_b)); \
+ WR_ADR (u_char, rs->uart->imr_port, rs->uart->imr_int_bits); }
+
+#define rx_ints_on(rs) \
+ { rs->uart->imr_int_bits |= (IMR_RX_INT) << (4*rs->a_or_b); \
+ WR_ADR (u_char, rs->uart->imr_port, rs->uart->imr_int_bits); }
+
+/* Structure definitions. */
+typedef unsigned long port_t;
+
+/* The DUART description table */
+struct duart_info {
+ char i_speed[2], o_speed[2]; /* Channel A and B speeds. */
+ char i_code[2], o_code[2]; /* Channel A and B speeds. */
+ char speed_grp; /* ACR bit 7 */
+ char acr_int_bits; /* ACR bits 0-6 */
+ char imr_int_bits; /* IMR bits current set. */
+
+ port_t isr_port;
+ port_t imr_port;
+ port_t ipcr_port;
+ port_t opcr_port;
+};
+
+/* RS232 device structure, one per device. */
+struct rs232_s {
+ int unit; /* unit number of this line (base 0) */
+ struct duart_info *uart; /* pointer to uart struct */
+ char a_or_b; /* 0 => A, 1 => B */
+
+ long scn_bits; /* Temp! for TIOCM ... */
+
+ port_t xmit_port; /* i/o ports */
+ port_t recv_port;
+ port_t mr_port;
+ port_t stat_port; /* sra or srb */
+ port_t speed_port; /* csra or csrb */
+ port_t cmd_port; /* cra or crb */
+ port_t acr_port;
+ port_t ip_port;
+ port_t opset_port;
+ port_t opclr_port;
+
+ unsigned char lstatus; /* last line status */
+ unsigned framing_errors; /* error counts (no reporting yet) */
+ unsigned overrun_errors;
+ unsigned parity_errors;
+ unsigned break_interrupts;
+
+};
+
diff --git a/sys/arch/pc532/include/ansi.h b/sys/arch/pc532/include/ansi.h
new file mode 100644
index 00000000000..4251db0c798
--- /dev/null
+++ b/sys/arch/pc532/include/ansi.h
@@ -0,0 +1,74 @@
+/* $NetBSD: ansi.h,v 1.6 1994/10/26 08:24:21 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/pc532/include/asm.h b/sys/arch/pc532/include/asm.h
new file mode 100644
index 00000000000..fbb3a42206a
--- /dev/null
+++ b/sys/arch/pc532/include/asm.h
@@ -0,0 +1,116 @@
+/* $NetBSD: asm.h,v 1.5 1994/10/26 08:24:22 cgd Exp $ */
+
+/*
+ * Mach Operating System
+ * Copyright (c) 1992 Carnegie Mellon University
+ * Copyright (c) 1992 Helsinki University of Technology
+ * 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 AND HELSINKI UNIVERSITY OF TECHNOLOGY ALLOW FREE USE
+ * OF THIS SOFTWARE IN ITS "AS IS" CONDITION. CARNEGIE MELLON AND
+ * HELSINKI UNIVERSITY OF TECHNOLOGY DISCLAIM 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 Mellon
+ * the rights to redistribute these changes.
+ */
+
+/*
+ * File: asm.h
+ * Author: Johannes Helander, Tero Kivinen, Tatu Ylonen
+ * Modified by Phil Nelson for NetBSD.
+ * Modified by Matthias Pfaller for PIC.
+ * Helsinki University of Technology 1992.
+ */
+
+#ifndef _MACHINE_ASM_H_
+#define _MACHINE_ASM_H_
+
+#ifdef __STDC__
+#define CAT(a, b) a ## b
+#define EX(x) _ ## x
+#define LEX(x) _ ## x ## :
+#else
+#define CAT(a, b) a/**/b
+#define EX(x) _/**/x
+#define LEX(x) _/**/x/**/:
+#endif
+
+#define FRAME enter [],0
+#define EMARF exit []
+
+#if 1 /* DEBUG */
+#define DFRAME FRAME
+#define DEMARF EMARF
+#else
+#define DFRAME
+#define DEMARF
+#endif
+
+#define S_ARG0 4(sp)
+#define S_ARG1 8(sp)
+#define S_ARG2 12(sp)
+#define S_ARG3 16(sp)
+
+#define B_ARG0 8(fp)
+#define B_ARG1 12(fp)
+#define B_ARG2 16(fp)
+#define B_ARG3 20(fp)
+
+#define ALIGN 0
+
+#ifdef PIC
+#define PIC_PROLOGUE \
+ sprd sb,tos; \
+ addr __GLOBAL_OFFSET_TABLE_(pc),r1; \
+ lprd sb,r1
+#define PIC_EPILOGUE \
+ lprd sb,tos
+#define PIC_GOT(x) 0(x(sb))
+
+#define PIC_S_ARG0 8(sp)
+#define PIC_S_ARG1 12(sp)
+#define PIC_S_ARG2 16(sp)
+#define PIC_S_ARG3 20(sp)
+#else
+#define PIC_PROLOGUE
+#define PIC_EPILOGUE
+#define PIC_GOT(x) x(pc)
+
+#define PIC_S_ARG0 4(sp)
+#define PIC_S_ARG1 8(sp)
+#define PIC_S_ARG2 12(sp)
+#define PIC_S_ARG3 16(sp)
+#endif
+
+#ifdef PROF
+#define MC1 .data; 1:; .long 0; .text
+#define MC2 addr 1b(pc),r0; bsr mcount
+#else
+#define MC1
+#define MC2
+#endif
+
+#define DECL(x) MC1; .globl x; .type x,@function; .align ALIGN; CAT(x,:); MC2
+
+#define ENTRY(x) DECL(EX(x))
+#define Entry(x) DECL(EX(x))
+#define ASENTRY(x) DECL(x)
+#define ASMSTR .asciz
+
+#define SVC svc
+
+#endif
diff --git a/sys/arch/pc532/include/cdefs.h b/sys/arch/pc532/include/cdefs.h
new file mode 100644
index 00000000000..eb5deb6adbd
--- /dev/null
+++ b/sys/arch/pc532/include/cdefs.h
@@ -0,0 +1,35 @@
+/* $NetBSD: cdefs.h,v 1.2 1995/03/23 20:10:38 jtc Exp $ */
+
+/*
+ * Written by J.T. Conklin <jtc@wimsey.com> 01/17/95.
+ * Public domain.
+ */
+
+#ifndef _MACHINE_CDEFS_H_
+#define _MACHINE_CDEFS_H_
+
+#ifdef __STDC__
+#define _C_LABEL(x) _STRING(_ ## x)
+#else
+#define _C_LABEL(x) _STRING(_/**/x)
+#endif
+
+#ifdef __GNUC__
+#ifdef __STDC__
+#define __indr_reference(sym,alias) \
+ __asm__(".stabs \"_" #alias "\",11,0,0,0"); \
+ __asm__(".stabs \"_" #sym "\",1,0,0,0")
+#define __warn_references(sym,msg) \
+ __asm__(".stabs \"" msg "\",30,0,0,0"); \
+ __asm__(".stabs \"_" #sym "\",1,0,0,0")
+#else
+#define __indr_reference(sym,alias) \
+ __asm__(".stabs \"_/**/alias\",11,0,0,0"); \
+ __asm__(".stabs \"_/**/sym\",1,0,0,0")
+#define __warn_references(sym,msg) \
+ __asm__(".stabs msg,30,0,0,0"); \
+ __asm__(".stabs \"_/**/sym\",1,0,0,0")
+#endif
+#endif
+
+#endif /* !_MACHINE_CDEFS_H_ */
diff --git a/sys/arch/pc532/include/cpu.h b/sys/arch/pc532/include/cpu.h
new file mode 100644
index 00000000000..454bca5c00e
--- /dev/null
+++ b/sys/arch/pc532/include/cpu.h
@@ -0,0 +1,119 @@
+/* $NetBSD: cpu.h,v 1.12 1995/06/28 02:55:56 cgd Exp $ */
+
+/*-
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * William Jolitz.
+ *
+ * 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.
+ *
+ * @(#)cpu.h 5.4 (Berkeley) 5/9/91
+ */
+
+#ifndef _MACHINE_CPU_H_
+#define _MACHINE_CPU_H_
+/*
+ * Definitions unique to ns532 cpu support.
+ *
+ * modified from 386 code for the pc532 by Phil Nelson (12/92)
+ */
+
+#include "machine/psl.h"
+#include "machine/frame.h"
+
+/*
+ * definitions of cpu-dependent requirements
+ * referenced in generic code
+ */
+#define cpu_swapin(p) /* nothing */
+#define cpu_set_init_frame(p,fp) (p)->p_md.md_regs = fp
+#define cpu_swapout(p) panic("cpu_swapout: can't get here");
+
+/* XXX needed? PAN
+ * function vs. inline configuration;
+ * these are defined to get generic functions
+ * rather than inline or machine-dependent implementations
+ */
+#define NEED_MINMAX /* need {,i,l,ul}{min,max} functions */
+#define NEED_FFS /* need ffs function */
+#define NEED_BCMP /* need bcmp function */
+#define NEED_STRLEN /* need strlen function */
+
+/*
+ * Arguments to hardclock, softclock and gatherstats
+ * encapsulate the previous machine state in an opaque
+ * clockframe; for now, use generic intrframe.
+ */
+
+#define clockframe intrframe
+
+#define CLKF_USERMODE(framep) ((framep)->if_psr & PSR_USR)
+#define CLKF_BASEPRI(framep) ((framep)->if_pl == imask[IPL_ZERO])
+#define CLKF_PC(framep) ((framep)->if_pc)
+#define CLKF_INTR(frame) (0) /* XXX should have an interrupt stack */
+
+#ifdef _KERNEL
+#include <machine/icu.h>
+#endif
+
+/*
+ * Preempt the current process if in interrupt from user mode,
+ * or after the current trap/syscall if in system mode.
+ */
+int want_resched; /* resched() was called */
+#define need_resched() (want_resched = 1, setsoftast())
+
+/*
+ * Give a profiling tick to the current process from the softclock
+ * interrupt. On the pc532, request an ast to send us through trap(),
+ * marking the proc as needing a profiling tick.
+ */
+#define profile_tick(p, framep) ((p)->p_flag |= P_OWEUPC, setsoftast())
+#define need_proftick(p) ((p)->p_flag |= P_OWEUPC, setsoftast())
+
+/*
+ * Notify the current process (p) that it has a signal pending,
+ * process as soon as possible.
+ */
+#define signotify(p) setsoftast()
+
+/*
+ * 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
diff --git a/sys/arch/pc532/include/db_machdep.h b/sys/arch/pc532/include/db_machdep.h
new file mode 100644
index 00000000000..a20ea5465d0
--- /dev/null
+++ b/sys/arch/pc532/include/db_machdep.h
@@ -0,0 +1,131 @@
+/* $NetBSD: db_machdep.h,v 1.3 1994/10/26 08:24:24 cgd Exp $ */
+
+/*
+ * Mach Operating System
+ * Copyright (c) 1992 Carnegie Mellon University
+ * Copyright (c) 1992 Helsinki University of Technology
+ * 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 AND HELSINKI UNIVERSITY OF TECHNOLOGY ALLOW FREE USE
+ * OF THIS SOFTWARE IN ITS "AS IS" CONDITION. CARNEGIE MELLON AND
+ * HELSINKI UNIVERSITY OF TECHNOLOGY DISCLAIM 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 Mellon
+ * the rights to redistribute these changes.
+ */
+/*
+ * HISTORY
+ * 11-May-92 Tero Kivinen (kivinen) at Helsinki University of Technology
+ * Created.
+ *
+ */
+/*
+ * File: ns532/db_machdep.h
+ * Author: Tero Kivinen, Helsinki University of Technology 1992.
+ *
+ * Machine-dependent defines for kernel debugger.
+ *
+ * modified by Phil Nelson for inclusion in 532bsd.
+ *
+ */
+
+#ifndef _MACHINE_DB_MACHDEP_H_
+#define _MACHINE_DB_MACHDEP_H_
+
+/* #include <mach/ns532/vm_types.h> */
+/* #include <mach/ns532/vm_param.h> */
+#include <vm/vm_prot.h>
+#include <vm/vm_param.h>
+#include <vm/vm_inherit.h>
+#include <vm/lock.h>
+
+/* #include <ns532/thread.h> /* for thread_status */
+#include <machine/frame.h> /* For struct trapframe */
+
+#include <machine/psl.h>
+#include <machine/trap.h>
+
+typedef vm_offset_t db_addr_t; /* address - unsigned */
+typedef int db_expr_t; /* expression - signed */
+
+typedef struct ns532_saved_state db_regs_t;
+db_regs_t ddb_regs; /* register state */
+#define DDB_REGS (&ddb_regs)
+
+#define PC_REGS(regs) ((db_addr_t)(regs)->pc)
+
+#define BKPT_INST 0xf2 /* breakpoint instruction */
+#define BKPT_SIZE (1) /* size of breakpoint inst */
+#define BKPT_SET(inst) (BKPT_INST)
+
+/* #define FIXUP_PC_AFTER_BREAK ddb_regs.pc -= 1; */
+
+#define db_clear_single_step(regs) ((regs)->psr &= ~PSR_T)
+#define db_set_single_step(regs) ((regs)->psr |= PSR_T)
+
+#define IS_BREAKPOINT_TRAP(type, code) ((type) == T_BPT)
+#define IS_WATCHPOINT_TRAP(type, code) ((type) == T_WATCHPOINT)
+
+#define I_BSR 0x02
+#define I_JSR 0x7f /* and low 3 bits of next byte are 0x6 */
+#define I_RET 0x12
+#define I_RETT 0x42
+#define I_RETI 0x52
+
+#define inst_trap_return(ins) (((ins)&0xff) == I_RETT || \
+ ((ins)&0xff) == I_RETI)
+#define inst_return(ins) (((ins)&0xff) == I_RET)
+#define inst_call(ins) (((ins)&0xff) == I_BSR || \
+ (((ins)&0xff) == I_JSR && \
+ ((ins)&0x0700) == 0x0600))
+
+#define inst_load(ins) 0
+#define inst_store(ins) 0
+
+extern int db_active_ipl;
+
+/* access capability and access macros */
+
+#define DB_ACCESS_LEVEL 2 /* access any space */
+#define DB_CHECK_ACCESS(addr,size,task) \
+ db_check_access(addr,size,task)
+#define DB_PHYS_EQ(task1,addr1,task2,addr2) \
+ db_phys_eq(task1,addr1,task2,addr2)
+#define DB_VALID_KERN_ADDR(addr) \
+ ((addr) >= VM_MIN_KERNEL_ADDRESS && \
+ (addr) < VM_MAX_KERNEL_ADDRESS)
+#define DB_VALID_ADDRESS(addr,user) \
+ ((!(user) && DB_VALID_KERN_ADDR(addr)) || \
+ ((user) && (addr) < VM_MIN_KERNEL_ADDRESS))
+
+boolean_t db_check_access(/* vm_offset_t, int, task_t */);
+boolean_t db_phys_eq(/* task_t, vm_offset_t, task_t, vm_offset_t */);
+
+/* macros for printing OS server dependent task name */
+
+#define DB_TASK_NAME(task) db_task_name(task)
+#define DB_TASK_NAME_TITLE "COMMAND "
+#define DB_TASK_NAME_LEN 23
+#define DB_NULL_TASK_NAME "? "
+
+void db_task_name(/* task_t */);
+
+/* macro for checking if a thread has used floating point */
+
+#define db_thread_fp_used(thread) ((thread)->pcb->fps && (thread)->pcb->fps->valid)
+
+#endif
diff --git a/sys/arch/pc532/include/disklabel.h b/sys/arch/pc532/include/disklabel.h
new file mode 100644
index 00000000000..0142c9807e4
--- /dev/null
+++ b/sys/arch/pc532/include/disklabel.h
@@ -0,0 +1,46 @@
+/* $NetBSD: disklabel.h,v 1.1 1994/10/14 18:27:14 cgd Exp $ */
+
+/*
+ * Copyright (c) 1994 Christopher G. Demetriou
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Christopher G. Demetriou.
+ * 4. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _MACHINE_DISKLABEL_H_
+#define _MACHINE_DISKLABEL_H_
+
+#define LABELSECTOR 0 /* sector containing label */
+#define LABELOFFSET 64 /* offset of label in sector */
+#define MAXPARTITIONS 8 /* number of partitions */
+#define RAW_PART 2 /* raw partition: xx?c */
+
+/* Just a dummy */
+struct cpu_disklabel {
+ int cd_dummy; /* must have one element. */
+};
+
+#endif /* _MACHINE_DISKLABEL_H_ */
diff --git a/sys/arch/pc532/include/endian.h b/sys/arch/pc532/include/endian.h
new file mode 100644
index 00000000000..a9d8cb4d942
--- /dev/null
+++ b/sys/arch/pc532/include/endian.h
@@ -0,0 +1,127 @@
+/* $NetBSD: endian.h,v 1.8 1995/06/18 07:13:46 phil Exp $ */
+
+/*
+ * Copyright (c) 1987, 1991 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 7.8 (Berkeley) 4/3/91
+ */
+
+#ifndef _PC532_ENDIAN_H_
+#define _PC532_ENDIAN_H_
+
+/*
+ * 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, ns32000 */
+#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
+
+#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
+
+
+#ifdef __GNUC__
+
+#define __byte_swap_long_variable(x) \
+({ register unsigned long __x = (x); \
+ __asm ("rotw 8,%1; rotd 16,%1; rotw 8,%1" \
+ : "=r" (__x) \
+ : "0" (__x)); \
+ __x; })
+
+#define __byte_swap_word_variable(x) \
+({ register unsigned short __x = (x); \
+ __asm ("rotw 8,%1" \
+ : "=r" (__x) \
+ : "0" (__x)); \
+ __x; })
+
+
+#ifdef __OPTIMIZE__
+
+#define __byte_swap_long_constant(x) \
+ ((((x) & 0xff000000) >> 24) | \
+ (((x) & 0x00ff0000) >> 8) | \
+ (((x) & 0x0000ff00) << 8) | \
+ (((x) & 0x000000ff) << 24))
+#define __byte_swap_word_constant(x) \
+ ((((x) & 0xff00) >> 8) | \
+ (((x) & 0x00ff) << 8))
+#define __byte_swap_long(x) \
+ (__builtin_constant_p((x)) ? \
+ __byte_swap_long_constant(x) : __byte_swap_long_variable(x))
+#define __byte_swap_word(x) \
+ (__builtin_constant_p((x)) ? \
+ __byte_swap_word_constant(x) : __byte_swap_word_variable(x))
+
+#else /* __OPTIMIZE__ */
+
+#define __byte_swap_long(x) __byte_swap_long_variable(x)
+#define __byte_swap_word(x) __byte_swap_word_variable(x)
+
+#endif /* __OPTIMIZE__ */
+
+#define ntohl(x) __byte_swap_long(x)
+#define ntohs(x) __byte_swap_word(x)
+#define htonl(x) __byte_swap_long(x)
+#define htons(x) __byte_swap_word(x)
+
+#endif /* __GNUC__ */
+
+
+/*
+ * Macros for network/external number representation conversion.
+ */
+#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 /* _POSIX_SOURCE */
+
+#endif /* _PC532_ENDIAN_H_ */
diff --git a/sys/arch/pc532/include/exec.h b/sys/arch/pc532/include/exec.h
new file mode 100644
index 00000000000..ecbac2d452f
--- /dev/null
+++ b/sys/arch/pc532/include/exec.h
@@ -0,0 +1,50 @@
+/* $NetBSD: exec.h,v 1.7 1994/10/26 08:24:26 cgd Exp $ */
+
+/*
+ * Copyright (c) 1993 Paul Kranenburg
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _PC532_EXEC_H_
+#define _PC532_EXEC_H_
+
+#define __LDPGSZ 4096
+
+/* Relocation format. */
+struct relocation_info_pc532 {
+ int r_address; /* offset in text or data segment */
+ unsigned int r_symbolnum : 22, /* ordinal number of add symbol */
+ r_copy : 1, /* run time copy */
+ r_relative : 1, /* load address relative */
+ r_pcrel : 1, /* 1 if value should be pc-relative */
+ r_length : 2, /* log base 2 of value's width */
+ r_extern : 1, /* 1 if need to add symbol to value */
+ r_jmptable : 1, /* relocate to jump table */
+ r_disp : 2, /* ns32k data type */
+ r_baserel : 1; /* linkage table relative */
+};
+#define relocation_info relocation_info_pc532
+
+#endif /* _PC532_EXEC_H_ */
diff --git a/sys/arch/pc532/include/float.h b/sys/arch/pc532/include/float.h
new file mode 100644
index 00000000000..740e82785d6
--- /dev/null
+++ b/sys/arch/pc532/include/float.h
@@ -0,0 +1,80 @@
+/* $NetBSD: float.h,v 1.7 1995/06/20 20:45:48 jtc Exp $ */
+
+/*
+ * Copyright (c) 1989 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 7.1 (Berkeley) 5/8/90
+ */
+
+#ifndef _PC532_FLOAT_H_
+#define _PC532_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.2250738585072014E-308
+#define DBL_MIN_10_EXP (-307)
+#define DBL_MAX_EXP 1024
+#define DBL_MAX 1.7976931348623157E+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 /* _PC532_FLOAT_H_ */
diff --git a/sys/arch/pc532/include/frame.h b/sys/arch/pc532/include/frame.h
new file mode 100644
index 00000000000..674f8eb7d5d
--- /dev/null
+++ b/sys/arch/pc532/include/frame.h
@@ -0,0 +1,110 @@
+/* $NetBSD: frame.h,v 1.4 1994/10/26 08:24:28 cgd Exp $ */
+
+/*-
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * William Jolitz.
+ *
+ * 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.
+ *
+ * @(#)frame.h 5.2 (Berkeley) 1/18/91
+ */
+
+#ifndef _MACHINE_FRAME_H_
+#define _MACHINE_FRAME_H_
+
+#include <sys/signal.h>
+#include <machine/reg.h>
+
+/*
+ * System stack frames.
+ */
+
+/*
+ * Exception/Trap Stack Frame
+ */
+
+struct trapframe {
+ long tf_msr; /* For abt. 0 for others. */
+ long tf_tear; /* For abt. 0 for others. */
+ long tf_trapno;
+ long tf_reg[8]; /* R7 - R0 from enter */
+ long tf_usp;
+ long tf_sb;
+ long tf_fp; /* From enter */
+ /* below portion defined in 532 hardware */
+ long tf_pc;
+ u_short tf_mod; /* Not used in direct excption mode. */
+ u_short tf_psr;
+};
+
+/* Interrupt stack frame */
+
+struct intrframe {
+ long if_vec;
+ long if_pl; /* the "processor level" for clock. */
+ long if_reg[8]; /* R7 - R0 from enter */
+ long if_usp;
+ long if_sb;
+ long if_fp; /* From enter */
+ /* below portion defined in 532 hardware */
+ long if_pc;
+ u_short if_mod; /* Not used in direct excption mode. */
+ u_short if_psr;
+};
+
+/*
+ * System Call Stack Frame
+ */
+
+struct syscframe {
+ long sf_reg[8]; /* R7 - R0 from enter */
+ long sf_usp;
+ long sf_sb;
+ long sf_fp; /* From enter */
+ /* below portion defined in 532 hardware */
+ long sf_pc;
+ u_short sf_mod; /* Not used in direct excption mode. */
+ u_short sf_psr;
+};
+
+/*
+ * Signal frame
+ */
+struct sigframe {
+ int sf_signum;
+ int sf_code;
+ struct sigcontext *sf_scp;
+ sig_t sf_handler;
+ struct sigcontext sf_sc;
+} ;
+
+#endif
diff --git a/sys/arch/pc532/include/icu.h b/sys/arch/pc532/include/icu.h
new file mode 100644
index 00000000000..e669036e5d1
--- /dev/null
+++ b/sys/arch/pc532/include/icu.h
@@ -0,0 +1,134 @@
+/* $NetBSD: icu.h,v 1.5 1995/08/25 07:52:18 phil 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.
+ *
+ * icu.h
+ */
+
+/* icu.h: defines for use with the ns32532 icu. */
+
+#ifndef _MACHINE_ICU_H_
+#define _MACHINE_ICU_H_
+
+/* We don't use vector interrupts, but make it right anyway */
+#define VEC_ICU 0x10
+
+/* The address of the ICU! */
+#define ICU_ADR 0xfffffe00
+
+/* ICU clock speed. */
+#define ICU_CLK_HZ 3686400/4 /* raw ICU clock speed */
+
+/* ICU registers
+ */
+#define HVCT 0
+#define SVCT 1
+#define ELTG 2
+#define TPL 4
+#define IPND 6
+#define ISRV 8
+#define IMSK 10
+#define CSRC 12
+#define FPRT 14
+#define MCTL 16
+#define OCASN 17
+#define CIPTR 18
+#define PDAT 19
+#define IPS 20
+#define PDIR 21
+#define CCTL 22
+#define CICTL 23
+#define LCSV 24
+#define HCSV 26
+#define LCCV 28
+#define HCCV 30
+
+/* Byte and Word access to ICU registers
+ */
+#define ICUB(n) *((unsigned char *)(ICU_ADR + n))
+#define ICUW(n) *((unsigned short *)(ICU_ADR + n))
+
+#ifndef LOCORE
+/* Interrupt trigger modes
+ */
+enum {HIGH_LEVEL, LOW_LEVEL, RISING_EDGE, FALLING_EDGE} int_modes;
+#endif /* !LOCORE */
+
+/* Hardware interrupt request lines.
+ */
+#define IR_CLK 2 /* highest priority */
+#define IR_SCSI0 5 /* Adaptec 6250 */
+#define IR_SCSI1 4 /* NCR DP8490 */
+#define IR_TTY0 13
+#define IR_TTY0RDY 12
+#define IR_TTY1 11
+#define IR_TTY1RDY 10
+#define IR_TTY2 9
+#define IR_TTY2RDY 8
+#define IR_TTY3 7
+#define IR_TTY3RDY 6
+
+/* edge polarity
+ * 0 0 falling edge
+ * 0 1 rising edge
+ * 1 0 low level
+ * 1 1 high level
+ *
+ */
+#define IEDGE 0
+#define IPOLARITY 0
+
+#define ints_off bicpsrw PSR_I
+#define ints_on bispsrw PSR_I
+
+/* SCSI controllers */
+#define AIC6250 0
+#define DP8490 1
+#define ICU_SCSI_BIT 0x80
+
+#ifndef LOCORE
+/*
+ * Select a SCSI controller.
+ */
+static __inline int
+scsi_select_ctlr(int ctlr)
+{
+ int old;
+
+ old = (ICUB(PDAT) & ICU_SCSI_BIT) == 0;
+ if (ctlr == DP8490)
+ ICUB(PDAT) &= ~ICU_SCSI_BIT; /* select = 0 for 8490 */
+ else
+ ICUB(PDAT) |= ICU_SCSI_BIT; /* select = 1 for AIC6250 */
+ return(old);
+}
+#endif /* !LOCORE */
+#endif /* _MACHINE_ICU_H_ */
diff --git a/sys/arch/pc532/include/ieeefp.h b/sys/arch/pc532/include/ieeefp.h
new file mode 100644
index 00000000000..58a853dfa72
--- /dev/null
+++ b/sys/arch/pc532/include/ieeefp.h
@@ -0,0 +1,19 @@
+/*
+ * Written by J.T. Conklin, Apr 28, 1995
+ * Public domain.
+ */
+
+#ifndef _PC532_IEEEFP_H_
+#define _PC532_IEEEFP_H_
+
+/* defined just to keep prototypes in machine independant header happy. */
+typedef int fp_except;
+
+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 /* _PC532_IEEEFP_H_ */
diff --git a/sys/arch/pc532/include/jmpbuf.h b/sys/arch/pc532/include/jmpbuf.h
new file mode 100644
index 00000000000..4b477c7a3b5
--- /dev/null
+++ b/sys/arch/pc532/include/jmpbuf.h
@@ -0,0 +1,53 @@
+/* $NetBSD: jmpbuf.h,v 1.3 1994/10/26 08:24:30 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.
+ *
+ *
+ * machine/setjmp.h : for support of the library routines.
+ */
+
+#ifndef _MACHINE_JMPBUF_H_
+#define _MACHINE_JMPBUF_H_
+
+/* These are byte offsets into the jmp buffer. */
+
+#define JMP_BUF_R3 0
+#define JMP_BUF_R4 4
+#define JMP_BUF_R5 8
+#define JMP_BUF_R6 12
+#define JMP_BUF_R7 16
+#define JMP_BUF_PC 20
+#define JMP_BUF_SP 24
+#define JMP_BUF_FP 28
+#define JMP_BUF_SB 32
+#define JMP_BUF_SIGMASK 36
+
+#endif
diff --git a/sys/arch/pc532/include/limits.h b/sys/arch/pc532/include/limits.h
new file mode 100644
index 00000000000..4c53bb0489f
--- /dev/null
+++ b/sys/arch/pc532/include/limits.h
@@ -0,0 +1,84 @@
+/* $NetBSD: limits.h,v 1.7 1994/10/26 08:24:31 cgd Exp $ */
+
+/*
+ * Copyright (c) 1988 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 7.2 (Berkeley) 6/28/90
+ */
+
+#define CHAR_BIT 8 /* number of bits in a char */
+#define MB_LEN_MAX 1 /* no multibyte characters */
+
+#define SCHAR_MIN (-0x7f-1) /* min value for a signed char */
+#define SCHAR_MAX 0x7f /* max value for a signed char */
+
+#define UCHAR_MAX 0xff /* max value for an unsigned char */
+#define CHAR_MAX 0x7f /* max value for a char */
+#define CHAR_MIN (-0x7f-1) /* min value for a char */
+
+#define USHRT_MAX 0xffff /* max value for an unsigned short */
+#define SHRT_MAX 0x7fff /* max value for a short */
+#define SHRT_MIN (-0x7fff-1) /* min value for a short */
+
+#define UINT_MAX 0xffffffff /* max value for an unsigned int */
+#define INT_MAX 0x7fffffff /* max value for an int */
+#define INT_MIN (-0x7fffffff-1) /* min value for an int */
+
+#define ULONG_MAX 0xffffffffUL /* max value for an unsigned long */
+#define LONG_MAX 0x7fffffff /* max value for a long */
+#define LONG_MIN (-0x7fffffff-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 */
+
+#define UQUAD_MAX 0xffffffffffffffffULL /* max unsigned quad */
+#define QUAD_MAX 0x7fffffffffffffffLL /* max signed quad */
+#define QUAD_MIN (-0x7fffffffffffffffLL-1) /* min signed quad */
+
+#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_MIN 2.2250738585072014E-308
+#define DBL_MAX 1.7976931348623157E+308
+
+#define FLT_DIG 6
+#define FLT_MAX 3.40282347E+38F
+#define FLT_MIN 1.17549435E-38F
+#endif
diff --git a/sys/arch/pc532/include/mtpr.h b/sys/arch/pc532/include/mtpr.h
new file mode 100644
index 00000000000..c487c474e9f
--- /dev/null
+++ b/sys/arch/pc532/include/mtpr.h
@@ -0,0 +1,3 @@
+/* $NetBSD: mtpr.h,v 1.3 1994/10/26 08:24:32 cgd Exp $ */
+
+/* EMPTY */
diff --git a/sys/arch/pc532/include/param.h b/sys/arch/pc532/include/param.h
new file mode 100644
index 00000000000..2be9a2d4889
--- /dev/null
+++ b/sys/arch/pc532/include/param.h
@@ -0,0 +1,169 @@
+/* $NetBSD: param.h,v 1.12 1995/06/26 06:56:05 cgd Exp $ */
+
+/*-
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * William Jolitz.
+ *
+ * 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.
+ *
+ * @(#)param.h 5.8 (Berkeley) 6/28/91
+ */
+
+/*
+ * Machine dependent constants for NS 32532.
+ *
+ * Derived from the i386 param.h by Phil Nelson.
+ *
+ */
+
+#ifndef _MACHINE_PARAM_H_
+#define _MACHINE_PARAM_H_
+
+#ifdef _KERNEL
+#include <machine/cpu.h>
+#endif
+
+#define MACHINE "pc532"
+#define MACHINE_ARCH "ns32k"
+#define MID_MACHINE MID_NS32532
+
+/*
+ * Round p (pointer or byte index) up to a correctly-aligned value
+ * for all data types (int, long, ...). The result is u_int and
+ * must be cast to any desired pointer type.
+ */
+#define ALIGNBYTES (sizeof(int) - 1)
+#define ALIGN(p) (((u_int)(p) + ALIGNBYTES) &~ ALIGNBYTES)
+
+#define NBPG 4096 /* bytes/page */
+#define PGOFSET (NBPG-1) /* byte offset into page */
+#define PGSHIFT 12 /* LOG2(NBPG) */
+#define NPTEPG (NBPG/(sizeof (struct pte)))
+
+#define NBPDR (1024*NBPG) /* bytes/page dir */
+#define PDROFSET (NBPDR-1) /* byte offset into page dir */
+#define PDRSHIFT 22 /* LOG2(NBPDR) */
+
+#define KERNBASE 0xFE000000 /* start of kernel virtual */
+#define BTOPKERNBASE ((u_long)KERNBASE >> PGSHIFT)
+
+#define DEV_BSIZE 512
+#define DEV_BSHIFT 9 /* log2(DEV_BSIZE) */
+#define BLKDEV_IOSIZE 4096 /* Was 2048 (pan) */
+#define MAXPHYS (64 * 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 USPACE (UPAGES * NBPG)
+
+/*
+ * 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.
+ */
+#ifndef MSIZE
+#define MSIZE 128 /* size of an mbuf */
+#endif /* MSIZE */
+
+#ifndef MCLSHIFT
+#define MCLSHIFT 11 /* convert bytes to m_buf clusters */
+#endif /* MCLSHIFT */
+#define MCLBYTES (1 << MCLSHIFT) /* size of a m_buf cluster */
+#define MCLOFSET (MCLBYTES - 1) /* offset within a m_buf cluster */
+
+#ifndef NMBCLUSTERS
+#define NMBCLUSTERS 512 /* map size, max cluster allocation */
+#endif
+
+/*
+ * Size of kernel malloc arena in CLBYTES-sized logical pages
+ */
+#ifndef NKMEMCLUSTERS
+#define NKMEMCLUSTERS (2048*1024/CLBYTES)
+#endif
+
+/*
+ * Some macros for units conversion
+ */
+
+/* pages ("clicks") to disk blocks */
+#define ctod(x) ((x) << (PGSHIFT - DEV_BSHIFT))
+#define dtoc(x) ((x) >> (PGSHIFT - DEV_BSHIFT))
+
+/* clicks 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 will be if we
+ * add an entry to cdevsw/bdevsw for that purpose.
+ * For now though just use DEV_BSIZE.
+ */
+#define bdbtofsb(bn) ((bn) / (BLKDEV_IOSIZE/DEV_BSIZE))
+
+
+/*
+ * Mach derived conversion macros
+ */
+#define ns532_round_pdr(x) ((((unsigned)(x)) + NBPDR - 1) & ~(NBPDR-1))
+#define ns532_trunc_pdr(x) ((unsigned)(x) & ~(NBPDR-1))
+#define ns532_round_page(x) ((((unsigned)(x)) + NBPG - 1) & ~(NBPG-1))
+#define ns532_trunc_page(x) ((unsigned)(x) & ~(NBPG-1))
+#define ns532_btod(x) ((unsigned)(x) >> PDRSHIFT)
+#define ns532_dtob(x) ((unsigned)(x) << PDRSHIFT)
+#define ns532_btop(x) ((unsigned)(x) >> PGSHIFT)
+#define ns532_ptob(x) ((unsigned)(x) << PGSHIFT)
+
+#ifndef _KERNEL
+#define DELAY(n) { volatile int N = (n); while (--N > 0); }
+#endif
+
+/* Macros to read and write from absolute addresses. */
+
+#define WR_ADR(type,adr,val) (*((volatile type *)(adr))=(val))
+#define RD_ADR(type,adr) (*((volatile type *)(adr)))
+
+#endif
diff --git a/sys/arch/pc532/include/pcb.h b/sys/arch/pc532/include/pcb.h
new file mode 100644
index 00000000000..e9ed77517f0
--- /dev/null
+++ b/sys/arch/pc532/include/pcb.h
@@ -0,0 +1,98 @@
+/* $NetBSD: pcb.h,v 1.6 1995/03/28 18:18:24 jtc Exp $ */
+
+/*-
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * William Jolitz.
+ *
+ * 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.
+ *
+ * @(#)pcb.h 5.10 (Berkeley) 5/12/91
+ */
+
+#ifndef _MACHINE_PCB_H_
+#define _MACHINE_PCB_H_
+
+/*
+ * PC 532 process control block
+ *
+ * Phil Nelson, 12/8/92
+ *
+ */
+
+/* The registers as pushed from a trap/interrupt with the
+ exception of USP and SB, and they are placed by software. */
+struct on_stack {
+ long pcb_reg[8]; /* R7 - R0 from enter */
+ long pcb_usp; /* User stack pointer, by software. */
+ long pcb_sb; /* Static Base pointer, by software. */
+ long pcb_fp; /* From enter */
+ long pcb_pc; /* From the trap/interrupt */
+ u_short pcb_mod; /* in direct exception mode. */
+ u_short pcb_psr;
+};
+
+struct pcb {
+ /* Put in a pointer to the trap/interrupt frame. */
+ struct on_stack *pcb_onstack;
+
+ /* Floating point stuff */
+ long pcb_fsr; /* fpu status reg */
+ double pcb_freg[8]; /* F0 - F7 */
+
+ /* Saved during a "swtch" */
+
+ long pcb_ksp; /* Kernel stack -- sp0. */
+ long pcb_kfp; /* Kernel fp. */
+ long pcb_ptb; /* ptb0 */
+ long pcb_pl; /* "processor level" */
+
+/*
+ * Software pcb (extension)
+ */
+ u_short pcb_flags; /* Used? PAN */
+ caddr_t pcb_onfault; /* copyin/out fault recovery */
+};
+
+/*
+ * The pcb is augmented with machine-dependent additional data for
+ * core dumps. For the pc532, there is nothing to add.
+ */
+struct md_coredump {
+ long md_pad[8];
+};
+
+
+#ifdef _KERNEL
+struct pcb *curpcb; /* our current running pcb */
+#endif
+
+#endif
diff --git a/sys/arch/pc532/include/pmap.h b/sys/arch/pc532/include/pmap.h
new file mode 100644
index 00000000000..5e198f27d3e
--- /dev/null
+++ b/sys/arch/pc532/include/pmap.h
@@ -0,0 +1,241 @@
+/* $NetBSD: pmap.h,v 1.7 1995/05/11 16:53:07 jtc Exp $ */
+
+/*
+ * Copyright (c) 1991 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 William Jolitz of UUNET Technologies 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.
+ *
+ * @(#)pmap.h 7.4 (Berkeley) 5/12/91
+ */
+
+/*
+ * Derived from hp300 version by Mike Hibler, this version by William
+ * Jolitz uses a recursive map [a pde points to the page directory] to
+ * map the page tables using the pagetables themselves. This is done to
+ * reduce the impact on kernel virtual memory for lots of sparse address
+ * space, and to reduce the cost of memory to each process.
+ *
+ * from hp300: @(#)pmap.h 7.2 (Berkeley) 12/16/90
+ */
+
+#ifndef _MACHINE_PMAP_H_
+#define _MACHINE_PMAP_H_
+
+/*
+ * 532 page table entry and page table directory
+ * Phil Nelson, 12/92
+ *
+ * modified from the 386 stuff by W.Jolitz, 8/89
+ */
+
+struct pde /* First level PTE */
+{
+unsigned long
+ pd_v:1, /* valid bit */
+ pd_prot:2, /* access control */
+ pd_mbz1:4, /* reserved, must be zero */
+ pd_u:1, /* hardware maintained 'used' bit */
+ pd_mbz2:1, /* reserved, must be zero */
+ :3, /* reserved for software */
+ pd_pfnum:20; /* physical page frame number of pte's*/
+};
+
+#define PD_MASK 0xffc00000 /* page directory address bits */
+#define PT_MASK 0x003ff000 /* page table address bits */
+#define PD_SHIFT 22 /* page directory address shift */
+#define PG_SHIFT 12 /* page table address shift */
+
+struct pte
+{
+unsigned int
+ pg_v:1, /* valid bit */
+ pg_prot:2, /* access control */
+ pg_mbz1:3, /* reserved, must be zero */
+ pg_nc:1, /* 'uncacheable page' bit */
+ pg_u:1, /* hardware maintained 'used' bit */
+ pg_m:1, /* hardware maintained modified bit */
+ pg_w:1, /* software, wired down page */
+ :2, /* software (unused) */
+ pg_pfnum:20; /* physical page frame number */
+};
+
+#define PG_V 0x00000001
+#define PG_RO 0x00000000
+#define PG_RW 0x00000002
+#define PG_u 0x00000004
+#define PG_PROT 0x00000006 /* all protection bits . */
+#define PG_W 0x00000200 /* Wired bit (user def) */
+#define PG_N 0x00000040 /* Non-cacheable */
+#define PG_M 0x00000100
+#define PG_U 0x00000080
+#define PG_FRAME 0xfffff000
+
+
+#define PG_NOACC 0
+#define PG_KR 0x00000000
+#define PG_KW 0x00000002
+#define PG_URKR 0x00000004
+#define PG_URKW 0x00000004
+#define PG_UW 0x00000006
+
+/* Garbage for current bastardized pager that assumes a hp300 */
+#define PG_NV 0
+#define PG_CI 0
+
+/*
+ * Page Protection Exception bits
+ */
+
+#define PGEX_TEX 0x03 /* Which exception. */
+#define PGEX_DDT 0x04 /* Data direction: 0 => read */
+#define PGEX_UST 0x08 /* user/super 0 => supervisor */
+#define PGEX_STT 0xf0 /* CPU status. */
+
+#define PGEX_P PGEX_TEX /* Protection violation vs. not present */
+#define PGEX_W PGEX_DDT /* during a Write cycle */
+#define PGEX_U PGEX_UST /* access from User mode (UPL) */
+
+typedef struct pde pd_entry_t; /* page directory entry */
+typedef struct pte pt_entry_t; /* Mach page table entry */
+
+/*
+ * One page directory, shared between
+ * kernel and user modes.
+ */
+#define NS532_PAGE_SIZE NBPG
+#define NS532_PDR_SIZE NBPDR
+
+#define NS532_KPDES 8 /* KPT page directory size */
+#define NS532_UPDES NBPDR/sizeof(struct pde)-8 /* UPT page directory size */
+
+#define UPTDI 0x3f6 /* ptd entry for u./kernel&user stack */
+#define PTDPTDI 0x3f7 /* ptd entry that points to ptd! */
+#define KPTDI_FIRST 0x3f8 /* start of kernel virtual pde's */
+#define KPTDI_LAST 0x3ff /* last of kernel virtual pde's */
+
+/*
+ * Address of current and alternate address space page table maps
+ * and directories.
+ */
+#ifdef _KERNEL
+extern struct pte PTmap[], APTmap[], Upte;
+extern struct pde PTD[], APTD[], PTDpde, APTDpde, Upde;
+extern pt_entry_t *Sysmap;
+
+extern int IdlePTD; /* physical address of "Idle" state directory */
+#endif
+
+/*
+ * virtual address to page table entry and
+ * to physical address. Likewise for alternate address space.
+ * Note: these work recursively, thus vtopte of a pte will give
+ * the corresponding pde that in turn maps it.
+ */
+#define vtopte(va) (PTmap + ns532_btop(va))
+#define kvtopte(va) vtopte(va)
+#define ptetov(pt) (ns532_ptob(pt - PTmap))
+#define vtophys(va) (ns532_ptob(vtopte(va)->pg_pfnum) | ((int)(va) & PGOFSET))
+#define ispt(va) ((va) >= UPT_MIN_ADDRESS && (va) <= KPT_MAX_ADDRESS)
+
+#define avtopte(va) (APTmap + ns532_btop(va))
+#define ptetoav(pt) (NS532_ptob(pt - APTmap))
+#define avtophys(va) (ns532_ptob(avtopte(va)->pg_pfnum) | ((int)(va) & PGOFSET))
+
+/*
+ * macros to generate page directory/table indicies
+ */
+
+#define pdei(va) (((va)&PD_MASK)>>PD_SHIFT)
+#define ptei(va) (((va)&PT_MASK)>>PG_SHIFT)
+
+/*
+ * Pmap stuff
+ */
+
+struct pmap {
+ pd_entry_t *pm_pdir; /* KVA of page directory */
+ boolean_t pm_pdchanged; /* pdir changed */
+ short pm_dref; /* page directory ref count */
+ short pm_count; /* pmap reference count */
+ simple_lock_data_t pm_lock; /* lock on pmap */
+ struct pmap_statistics pm_stats; /* pmap statistics */
+ long pm_ptpages; /* more stats: PT pages */
+};
+
+typedef struct pmap *pmap_t;
+
+/*
+ * Macros for speed
+ */
+#define PMAP_ACTIVATE(pmapp, pcbp) \
+ if ((pmapp) != NULL /*&& (pmapp)->pm_pdchanged */) { \
+ (pcbp)->pcb_ptb = \
+ pmap_extract(pmap_kernel(),(vm_offset_t)(pmapp)->pm_pdir); \
+ if ((pmapp) == &curproc->p_vmspace->vm_pmap) \
+ _load_ptb0((pcbp)->pcb_ptb); \
+ (pmapp)->pm_pdchanged = FALSE; \
+ }
+
+#define PMAP_DEACTIVATE(pmapp, pcbp)
+
+/*
+ * For each vm_page_t, there is a list of all currently valid virtual
+ * mappings of that page. An entry is a pv_entry_t, the list is pv_table.
+ */
+typedef struct pv_entry {
+ struct pv_entry *pv_next; /* next pv_entry */
+ pmap_t pv_pmap; /* pmap where mapping lies */
+ vm_offset_t pv_va; /* virtual address for mapping */
+ int pv_flags; /* flags */
+} *pv_entry_t;
+
+#define PV_ENTRY_NULL ((pv_entry_t) 0)
+
+#define PV_CI 0x01 /* all entries must be cache inhibited */
+#define PV_PTPAGE 0x02 /* entry maps a page table page */
+
+#ifdef _KERNEL
+
+pv_entry_t pv_table; /* array of entries, one per page */
+struct pmap kernel_pmap_store;
+
+#define pa_index(pa) atop(pa - vm_first_phys)
+#define pa_to_pvh(pa) (&pv_table[pa_index(pa)])
+
+#define pmap_kernel() (&kernel_pmap_store)
+#define pmap_resident_count(pmap) ((pmap)->pm_stats.resident_count)
+
+#endif /* _KERNEL */
+
+#endif
diff --git a/sys/arch/pc532/include/proc.h b/sys/arch/pc532/include/proc.h
new file mode 100644
index 00000000000..c4a53bfb776
--- /dev/null
+++ b/sys/arch/pc532/include/proc.h
@@ -0,0 +1,48 @@
+/* $NetBSD: proc.h,v 1.4 1994/10/26 08:24:37 cgd Exp $ */
+
+/*
+ * Copyright (c) 1991 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)proc.h 7.1 (Berkeley) 5/15/91
+ */
+
+#ifndef _MACHINE_PROC_H_
+#define _MACHINE_PROC_H_
+
+/*
+ * Machine-dependent part of the proc structure for the pc532.
+ */
+struct mdproc {
+ int *md_regs; /* pointer to regs on the stack */
+};
+
+#endif
diff --git a/sys/arch/pc532/include/profile.h b/sys/arch/pc532/include/profile.h
new file mode 100644
index 00000000000..5f8490ad786
--- /dev/null
+++ b/sys/arch/pc532/include/profile.h
@@ -0,0 +1,70 @@
+/* $NetBSD: profile.h,v 1.4 1995/03/28 18:18:30 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.
+ *
+ * @(#)profile.h 8.1 (Berkeley) 6/11/93
+ */
+
+/* pc532 version, 5/15/94.
+ */
+
+#define _MCOUNT_DECL static inline void _mcount
+
+#define MCOUNT \
+extern void mcount() asm("mcount"); \
+void \
+mcount() \
+{ \
+ int selfpc, frompcindex; \
+ /* \
+ * find the return address for mcount, \
+ * and the return address for mcount's caller. \
+ * \
+ * selfpc = pc pushed by mcount call \
+ */ \
+ asm("movd 4(fp),%0" : "=r" (selfpc)); \
+ /* \
+ * frompcindex = pc pushed by call into self. \
+ */ \
+ asm("movd 4(0(fp)),%0" : "=r" (frompcindex)); \
+ _mcount(frompcindex, selfpc); \
+}
+
+#ifdef _KERNEL
+/*
+ * Note that we assume splhigh() and splx() cannot call mcount()
+ * recursively.
+ */
+#define MCOUNT_ENTER s = splhigh()
+#define MCOUNT_EXIT splx(s)
+#endif /* _KERNEL */
diff --git a/sys/arch/pc532/include/psl.h b/sys/arch/pc532/include/psl.h
new file mode 100644
index 00000000000..e9bbaca6d68
--- /dev/null
+++ b/sys/arch/pc532/include/psl.h
@@ -0,0 +1,240 @@
+/* $NetBSD: psl.h,v 1.13 1995/09/26 20:16:21 phil Exp $ */
+
+/*-
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * William Jolitz.
+ *
+ * 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.
+ *
+ * @(#)psl.h 5.2 (Berkeley) 1/18/91
+ */
+
+#ifndef _MACHINE_PSL_H_
+#define _MACHINE_PSL_H_
+
+/*
+ * 32532 processor status longword.
+ */
+#define PSL_C 0x00000001 /* carry bit */
+#define PSL_T 0x00000002 /* trace enable bit */
+#define PSL_L 0x00000004 /* less bit */
+#define PSL_V 0x00000010 /* overflow bit */
+#define PSL_F 0x00000020 /* flag bit */
+#define PSL_Z 0x00000040 /* zero bit */
+#define PSL_N 0x00000080 /* negative bit */
+
+#define PSL_USER 0x00000100 /* User mode bit */
+#define PSL_US 0x00000200 /* User stack mode bit */
+#define PSL_P 0x00000400 /* Prevent TRC trap */
+#define PSL_I 0x00000800 /* interrupt enable bit */
+
+#define PSL_USERSET (PSL_USER | PSL_US | PSL_I)
+#define PSL_USERSTATIC (PSL_USER | PSL_US | PSL_I)
+
+/* The PSR versions ... */
+#define PSR_USR PSL_USER
+
+#ifdef _KERNEL
+#include <machine/icu.h>
+/*
+ * Interrupt levels
+ */
+#define IPL_NONE -1
+#define IPL_ZERO 0 /* level 0 */
+#define IPL_BIO 1 /* block I/O */
+#define IPL_NET 2 /* network */
+#define IPL_TTY 3 /* terminal */
+#define IPL_CLOCK 4 /* clock */
+#define IPL_IMP 5 /* memory allocation */
+#define NIPL 6 /* number of interrupt priority levels */
+#define IPL_NAMES {"zero", "bio", "net", "tty", "clock", "imp"}
+
+/*
+ * Preassigned software interrupts
+ */
+#define SOFTINT 16
+#define SIR_CLOCK (SOFTINT+0)
+#define SIR_CLOCKMASK (1 << SIR_CLOCK)
+#define SIR_NET (SOFTINT+1)
+#define SIR_NETMASK ((1 << SIR_NET) | SIR_CLOCKMASK)
+#define SIR_ALLMASK 0xffff0000
+
+#ifndef LOCORE
+/*
+ * Structure of the software interrupt table
+ */
+struct iv {
+ void (*iv_vec)();
+ void *iv_arg;
+ int iv_cnt;
+ char *iv_use;
+};
+
+extern unsigned int imask[], Cur_pl, idisabled, sirpending, astpending;
+extern void intr_init();
+extern void check_sir();
+extern int intr_establish(int, void (*)(), void *, char *, int, int);
+extern struct iv ivt[];
+
+/*
+ * Disable/Enable CPU-Interrupts
+ */
+#define di() /* Removing the nop will give you *BIG* trouble */ \
+ __asm __volatile("bicpsrw 0x800 ; nop" : : : "cc")
+#define ei() __asm __volatile("bispsrw 0x800" : : : "cc")
+
+/*
+ * Globaly disable/enable specific interrupts
+ * (overriding spl0)
+ */
+#define intr_disable(ir) do { \
+ di(); \
+ ICUW(IMSK) = Cur_pl | (idisabled |= (1 << ir)); \
+ ei(); \
+ } while(0)
+
+#define intr_enable(ir) do { \
+ di(); \
+ ICUW(IMSK) = Cur_pl | (idisabled &= ~(1 << ir)); \
+ ei(); \
+ } while(0)
+
+/*
+ * Add a mask to Cur_pl, and return the old value of Cur_pl.
+ */
+#if !defined(NO_INLINE_SPLX) || defined(DEFINE_SPLX)
+# ifndef NO_INLINE_SPLX
+static __inline
+# endif
+int
+splraise(register int ncpl)
+{
+ register int ocpl;
+ di();
+ ocpl = Cur_pl;
+ ncpl |= ocpl;
+ ICUW(IMSK) = ncpl | idisabled;
+ Cur_pl = ncpl;
+ ei();
+ return(ocpl);
+}
+
+/*
+ * Restore a value to Cur_pl (unmasking interrupts).
+ *
+ * NOTE: We go to the trouble of returning the old value of cpl for
+ * the benefit of some splsoftclock() callers. This extra work is
+ * usually optimized away by the compiler.
+ */
+# ifndef DEFINE_SPLX
+static
+# endif
+# ifndef NO_INLINE_SPLX
+__inline
+# endif
+int
+splx(register int ncpl)
+{
+ register int ocpl;
+ di();
+ ocpl = Cur_pl;
+ ICUW(IMSK) = ncpl | idisabled;
+ Cur_pl = ncpl;
+ if (sirpending && ncpl == imask[IPL_ZERO]) {
+ Cur_pl |= SIR_ALLMASK;
+ check_sir();
+ Cur_pl = ncpl;
+ }
+ ei();
+ return (ocpl);
+}
+
+/*
+ * This special version of splx returns with interrupts disabled.
+ */
+# ifdef DEFINE_SPLX
+int
+splx_di(register int ncpl)
+{
+ register int ocpl;
+ di();
+ ocpl = Cur_pl;
+ ICUW(IMSK) = ncpl | idisabled;
+ Cur_pl = ncpl;
+ if (sirpending && ncpl == imask[IPL_ZERO]) {
+ Cur_pl |= SIR_ALLMASK;
+ check_sir();
+ Cur_pl = ncpl;
+ }
+ return (ocpl);
+}
+# endif
+#endif
+
+/*
+ * Hardware interrupt masks
+ */
+#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() splx(SIR_CLOCKMASK|imask[IPL_ZERO])
+#define splsoftnet() splraise(SIR_NETMASK)
+
+/*
+ * Miscellaneous
+ */
+#define splhigh() splraise(-1)
+#define spl0() splx(imask[IPL_ZERO])
+#define splnone() spl0()
+
+/*
+ * Software interrupt registration
+ */
+#define softintr(n) (sirpending |= (1 << (n)))
+#define setsoftast() (astpending = 1)
+#define setsoftclock() softintr(SIR_CLOCK)
+#define setsoftnet() softintr(SIR_NET)
+
+#endif /* !LOCORE */
+#endif /* _KERNEL */
+
+#endif /* _MACHINE_PSL_H_ */
diff --git a/sys/arch/pc532/include/ptrace.h b/sys/arch/pc532/include/ptrace.h
new file mode 100644
index 00000000000..395182d4bc4
--- /dev/null
+++ b/sys/arch/pc532/include/ptrace.h
@@ -0,0 +1,40 @@
+/* $NetBSD: ptrace.h,v 1.6 1995/07/28 08:00:17 phil Exp $ */
+
+/*
+ * Copyright (c) 1993 Christopher G. Demetriou
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. 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 withough specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * pc532-dependent ptrace definitions
+ */
+#define PT_STEP (PT_FIRSTMACH + 0)
+#define PT_GETREGS (PT_FIRSTMACH + 1)
+#define PT_SETREGS (PT_FIRSTMACH + 2)
+#define PT_GETFPREGS (PT_FIRSTMACH + 3)
+#define PT_SETFPREGS (PT_FIRSTMACH + 4)
diff --git a/sys/arch/pc532/include/reg.h b/sys/arch/pc532/include/reg.h
new file mode 100644
index 00000000000..49c87ea3967
--- /dev/null
+++ b/sys/arch/pc532/include/reg.h
@@ -0,0 +1,96 @@
+/* $NetBSD: reg.h,v 1.10 1995/08/29 22:40:59 phil Exp $ */
+
+/*-
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * William Jolitz.
+ *
+ * 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.
+ *
+ * @(#)reg.h 5.5 (Berkeley) 1/18/91
+ */
+
+/* Modified for the pc532... 2/1/93 by Phil Nelson
+ */
+
+#ifndef _MACHINE_REG_H_
+#define _MACHINE_REG_H_
+
+/*
+ * Location of the users' stored
+ * registers within appropriate frame of 'trap' and 'syscall', relative to
+ * base of stack frame.
+ * Normal usage is u.u_ar0[XX] in kernel.
+ */
+
+/* When referenced during a trap/exception and a syscall,
+ registers are at these offsets from p-p_regs*/
+
+#define REG_R0 (7)
+#define REG_R1 (6)
+#define REG_R2 (5)
+#define REG_R3 (4)
+#define REG_R4 (3)
+#define REG_R5 (2)
+#define REG_R6 (1)
+#define REG_R7 (0)
+
+#define REG_SP (8)
+#define REG_SB (9)
+#define REG_FP (10)
+#define REG_PC (11)
+#define REG_PSR (12)
+
+/* The reg struct .. in the order of above. */
+
+struct reg {
+ int r_r7;
+ int r_r6;
+ int r_r5;
+ int r_r4;
+ int r_r3;
+ int r_r2;
+ int r_r1;
+ int r_r0;
+
+ int r_sp;
+ int r_sb;
+ int r_fp;
+ int r_pc;
+ short r_mod;
+ short r_psr;
+};
+
+struct fpreg {
+ int r_fsr;
+ double r_freg[8];
+};
+#endif /* _MACHINE_REG_H_ */
diff --git a/sys/arch/pc532/include/setjmp.h b/sys/arch/pc532/include/setjmp.h
new file mode 100644
index 00000000000..5a080a0ab7c
--- /dev/null
+++ b/sys/arch/pc532/include/setjmp.h
@@ -0,0 +1,7 @@
+/* $NetBSD: setjmp.h,v 1.1 1994/12/20 10:37:01 cgd Exp $ */
+
+/*
+ * machine/setjmp.h: machine dependent setjmp-related information.
+ */
+
+#define _JBLEN 10 /* size, in longs, of a jmp_buf */
diff --git a/sys/arch/pc532/include/signal.h b/sys/arch/pc532/include/signal.h
new file mode 100644
index 00000000000..810bfd6c45a
--- /dev/null
+++ b/sys/arch/pc532/include/signal.h
@@ -0,0 +1,68 @@
+/* $NetBSD: signal.h,v 1.5 1995/01/10 19:01:36 jtc Exp $ */
+
+/*
+ * Copyright (c) 1982, 1986, 1989, 1991 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.
+ *
+ * @(#)signal.h 7.16 (Berkeley) 3/17/91
+ */
+
+#ifndef _MACHINE_SIGNAL_H_
+#define _MACHINE_SIGNAL_H_
+
+typedef int sig_atomic_t;
+
+#ifndef _ANSI_SOURCE
+/*
+ * Get the "code" values
+ */
+#include <machine/trap.h>
+
+/*
+ * 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_sp; /* sp to restore */
+ int sc_fp; /* fp to restore */
+ int sc_sb; /* sb to restore */
+ int sc_pc; /* pc to restore */
+ int sc_ps; /* psl to restore */
+ int sc_reg[8]; /* The registers */
+};
+
+#endif /* !_ANSI_SOURCE */
+#endif /* !_MACHINE_SIGNAL_H_ */
diff --git a/sys/arch/pc532/include/stdarg.h b/sys/arch/pc532/include/stdarg.h
new file mode 100644
index 00000000000..32a97df670c
--- /dev/null
+++ b/sys/arch/pc532/include/stdarg.h
@@ -0,0 +1,61 @@
+/* $NetBSD: stdarg.h,v 1.9 1995/03/28 18:18:36 jtc Exp $ */
+
+/*-
+ * Copyright (c) 1991, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)stdarg.h 8.1 (Berkeley) 6/10/93
+ */
+
+#ifndef _PC532_STDARG_H_
+#define _PC532_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 += __va_promote(type), ap - __va_promote(type)))[0]
+#endif
+
+#define va_end(ap) ((void) 0)
+
+#endif /* !_PC532_STDARG_H_ */
diff --git a/sys/arch/pc532/include/trap.h b/sys/arch/pc532/include/trap.h
new file mode 100644
index 00000000000..034423fa8ea
--- /dev/null
+++ b/sys/arch/pc532/include/trap.h
@@ -0,0 +1,91 @@
+/* $NetBSD: trap.h,v 1.3 1994/10/26 08:24:44 cgd Exp $ */
+
+/*
+ * Mach Operating System
+ * Copyright (c) 1992 Carnegie Mellon University
+ * Copyright (c) 1992 Helsinki University of Technology
+ * 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 AND HELSINKI UNIVERSITY OF TECHNOLOGY ALLOW FREE USE
+ * OF THIS SOFTWARE IN ITS "AS IS" CONDITION. CARNEGIE MELLON AND
+ * HELSINKI UNIVERSITY OF TECHNOLOGY DISCLAIM 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 Mellon
+ * the rights to redistribute these changes.
+ */
+/*
+ * File: ns532/trap.h
+ * Author: Tatu Ylonen, Helsinki University of Technology 1992.
+ * Modified for NetBSD by Phil Nelson
+ * Hardware trap vectors for ns532.
+ */
+
+#ifndef _MACHINE_TRAP_H_
+#define _MACHINE_TRAP_H_
+
+#define T_NVI 0 /* non-vectored interrupt */
+#define T_NMI 1 /* non-maskable interrupt */
+#define T_ABT 2 /* abort */
+#define T_SLAVE 3 /* coprocessor trap */
+#define T_ILL 4 /* illegal operation in user mode */
+#define T_SVC 5 /* supervisor call */
+#define T_DVZ 6 /* divide by zero */
+#define T_FLG 7 /* flag instruction */
+#define T_BPT 8 /* breakpoint instruction */
+#define T_TRC 9 /* trace trap */
+#define T_UND 10 /* undefined instruction */
+#define T_RBE 11 /* restartable bus error */
+#define T_NBE 12 /* non-restartable bus error */
+#define T_OVF 13 /* integer overflow trap */
+#define T_DBG 14 /* debug trap */
+#define T_RESERVED 15 /* reserved */
+
+/* Not a real trap. */
+#define T_WATCHPOINT 17 /* watchpoint */
+
+/* To allow for preemption */
+#define T_INTERRUPT 18 /* trap code from interrupt! */
+
+/* To include system/user mode in the trap information. */
+#define T_USER 32
+
+#define PARRDU_PHYS 0x28000040 /* Read parity error */
+#define PARCLU_PHYS 0x28000050 /* Clear parity error */
+
+#define PARRDU_VM 0xFFC80040 /* Read parity error */
+#define PARCLU_VM 0xFFC80050 /* Clear parity error */
+
+/* memory management status register bits and meanings. */
+#define MSR_STT 0xf0 /* CPU status. */
+#define STT_SEQ_INS 0x80 /* Sequential instruction fetch */
+#define STT_NSQ_INS 0x90 /* Non-sequential instruction fetch */
+#define STT_DATA 0xa0 /* Data transfer */
+#define STT_RMW 0xb0 /* Read/modify/write */
+#define STT_REA 0xc0 /* Read for effective address */
+
+#define MSR_UST 0x08 /* User/supervisor */
+#define UST_USER 0x08 /* User mode is 1. Super = 0 */
+
+#define MSR_DDT 0x04 /* Data Direction */
+#define DDT_WRITE 0x04 /* Write is 1. Read is 0 */
+
+#define MSR_TEX 0x03 /* Exception kind. */
+#define TEX_PTE1 0x01 /* First level PTE invalid */
+#define TEX_PTE2 0x02 /* Second level PTE invalid */
+#define TEX_PROT 0x03 /* Protection violation */
+
+#endif
diff --git a/sys/arch/pc532/include/types.h b/sys/arch/pc532/include/types.h
new file mode 100644
index 00000000000..c048c9ae906
--- /dev/null
+++ b/sys/arch/pc532/include/types.h
@@ -0,0 +1,74 @@
+/* $NetBSD: types.h,v 1.11 1995/08/25 07:52:20 phil Exp $ */
+
+/*-
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)types.h 7.5 (Berkeley) 3/9/91
+ */
+
+#ifndef _MACHINE_TYPES_H_
+#define _MACHINE_TYPES_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[6];
+} 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;
+typedef long long int64_t;
+typedef unsigned long long u_int64_t;
+
+typedef int32_t register_t;
+
+#define __SWAP_BROKEN
+
+#endif /* _MACHTYPES_H_ */
diff --git a/sys/arch/pc532/include/varargs.h b/sys/arch/pc532/include/varargs.h
new file mode 100644
index 00000000000..5aedb16124f
--- /dev/null
+++ b/sys/arch/pc532/include/varargs.h
@@ -0,0 +1,68 @@
+/* $NetBSD: varargs.h,v 1.8 1995/03/28 18:18:40 jtc Exp $ */
+
+/*-
+ * Copyright (c) 1990, 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 _PC532_VARARGS_H_
+#define _PC532_VARARGS_H_
+
+#include <machine/ansi.h>
+
+typedef _BSD_VA_LIST_ va_list;
+
+#define va_dcl int va_alist;
+
+#define __va_promote(type) \
+ (((sizeof(type) + sizeof(int) - 1) / sizeof(int)) * sizeof(int))
+
+#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 += __va_promote(type), ap - __va_promote(type)))[0]
+#endif
+
+#define va_end(ap) ((void) 0)
+
+#endif /* !_PC532_VARARGS_H_ */
diff --git a/sys/arch/pc532/include/vmparam.h b/sys/arch/pc532/include/vmparam.h
new file mode 100644
index 00000000000..cee95ebf38a
--- /dev/null
+++ b/sys/arch/pc532/include/vmparam.h
@@ -0,0 +1,230 @@
+/* $NetBSD: vmparam.h,v 1.6 1995/02/14 18:52:29 phil Exp $ */
+
+/*-
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * William Jolitz.
+ *
+ * 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.
+ *
+ * @(#)vmparam.h 5.9 (Berkeley) 5/12/91
+ */
+
+#ifndef _MACHINE_VMPARAM_H_
+#define _MACHINE_VMPARAM_H_
+
+/*
+ * Machine dependent constants for 532.
+ */
+
+/*
+ * Virtual address space arrangement. On 532, both user and kernel
+ * share the address space, not unlike the vax.
+ * USRTEXT is the start of the user text/data space, while USRSTACK
+ * is the top (end) of the user stack. Immediately above the user stack
+ * resides the user structure, which is UPAGES long and contains the
+ * kernel stack.
+ *
+ * Immediately after the user structure is the page table map, and then
+ * kernal address space.
+ */
+#define USRTEXT 0x1000 /* For NetBSD... */
+#define USRSTACK 0xFDBFE000
+#define BTOPUSRSTACK (0xFDC00-(UPAGES)) /* btop(USRSTACK) */
+#define LOWPAGES 0
+#define HIGHPAGES UPAGES
+
+/*
+ * Virtual memory related constants, all in bytes
+ */
+#define MAXTSIZ (16*1024*1024) /* max text size */
+#ifndef DFLDSIZ
+#define DFLDSIZ (24*1024*1024) /* initial data size limit */
+#endif
+#ifndef MAXDSIZ
+#define MAXDSIZ (128*1024*1024) /* max data size */
+#endif
+#ifndef DFLSSIZ
+#define DFLSSIZ (1*1024*1024) /* initial stack size limit */
+#endif
+#ifndef MAXSSIZ
+#define MAXSSIZ (8*1024*1024) /* 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.
+ */
+#define DMMIN 32 /* smallest swap allocation */
+#define DMMAX 4096 /* largest potential swap allocation */
+#define DMTEXT 1024 /* swap allocation for text */
+
+/*
+ * Sizes of the system and user portions of the system page table.
+ */
+#define SYSPTSIZE (2*NPTEPG)
+#define USRPTSIZE (2*NPTEPG)
+
+/*
+ * Size of User Raw I/O map
+ */
+#define USRIOSIZE 64
+
+/*
+ * 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.
+ * { wfj 6/16/89: Retail AT memory expansion $800/megabyte, loan of $17
+ * on disk costing $7/mb or $0.18 (in memory still 100:1 in cost!) }
+ */
+#define SAFERSS 8 /* 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 KLMAX*CLSIZE must be <= DMMIN in dmap.h.
+ */
+
+#define KLMAX (4/CLSIZE)
+#define KLSEQL (2/CLSIZE) /* in klust if vadvise(VA_SEQL) */
+#define KLIN (4/CLSIZE) /* default data/stack in klust */
+#define KLTXT (4/CLSIZE) /* default text in klust */
+#define KLOUT (4/CLSIZE)
+
+/*
+ * KLSDIST is the advance or retard of the fifo reclaim for sequential
+ * processes data space.
+ */
+#define KLSDIST 3 /* klusters advance/retard for seq. fifo */
+
+#if 0
+/*
+ * 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
+ * minfree is 64k bytes, but at most 1/2 of desfree
+ */
+#define LOTSFREE (512 * 1024)
+#define LOTSFREEFRACT 4
+#define DESFREE (200 * 1024)
+#define DESFREEFRACT 8
+#define MINFREE (64 * 1024)
+#define MINFREEFRACT 2
+#endif
+
+/*
+ * 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
+
+#define mapin(pte, v, pfnum, prot) \
+ {(*(int *)(pte) = ((pfnum)<<PGSHIFT) | (prot)) ; }
+
+/*
+ * Mach derived constants
+ */
+
+/* user/kernel map constants */
+#define VM_MIN_ADDRESS ((vm_offset_t)0)
+#define VM_MAXUSER_ADDRESS ((vm_offset_t)0xFDBFE000)
+#define UPT_MIN_ADDRESS ((vm_offset_t)0xFDC00000)
+#define UPT_MAX_ADDRESS ((vm_offset_t)0xFDFF7000)
+#define VM_MAX_ADDRESS UPT_MAX_ADDRESS
+#define VM_MIN_KERNEL_ADDRESS ((vm_offset_t)0xFDFF7000)
+#define UPDT VM_MIN_KERNEL_ADDRESS
+#define KPT_MIN_ADDRESS ((vm_offset_t)0xFDFF8000)
+#define KPT_MAX_ADDRESS ((vm_offset_t)0xFDFFF000)
+#define VM_MAX_KERNEL_ADDRESS ((vm_offset_t)0xFF7FF000)
+
+/* virtual sizes (bytes) for various kernel submaps */
+#define VM_MBUF_SIZE (NMBCLUSTERS*MCLBYTES)
+#define VM_KMEM_SIZE (NKMEMCLUSTERS*CLBYTES)
+#define VM_PHYS_SIZE (USRIOSIZE*CLBYTES)
+
+/* # of kernel PT pages (initial only, can grow dynamically) */
+#define VM_KERNEL_PT_PAGES ((vm_size_t)2) /* XXX: SYSPTSIZE */
+
+/* pcb base */
+#define pcbb(p) ((u_int)(p)->p_addr)
+
+#endif
diff --git a/sys/arch/pc532/pc532/autoconf.c b/sys/arch/pc532/pc532/autoconf.c
new file mode 100644
index 00000000000..7be020147c3
--- /dev/null
+++ b/sys/arch/pc532/pc532/autoconf.c
@@ -0,0 +1,229 @@
+/* $NetBSD: autoconf.c,v 1.15 1995/09/26 20:16:23 phil Exp $ */
+
+/*-
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * William Jolitz.
+ *
+ * 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.
+ *
+ * @(#)autoconf.c 7.1 (Berkeley) 5/9/91
+ */
+
+/*
+ * Setup the system to run on the current machine.
+ *
+ * Configure() is called at boot time and initializes the vba
+ * device tables and the memory controller monitoring. Available
+ * devices are determined (from possibilities mentioned in ioconf.c),
+ * and the drivers are initialized.
+ */
+
+#include <sys/param.h>
+#include <sys/disklabel.h>
+#include <sys/conf.h>
+#include <sys/systm.h>
+#include <sys/reboot.h>
+#include <sys/buf.h>
+#include <sys/malloc.h>
+#include <sys/device.h>
+
+/*
+ * The following several variables are related to
+ * the configuration process, and are used in initializing
+ * the machine.
+ */
+
+int dkn; /* number of iostat dk numbers assigned so far */
+extern int cold; /* cold start flag initialized in locore.s */
+
+/*
+ * Determine i/o configuration for a machine.
+ */
+configure()
+{
+ extern int safepri;
+ int i;
+ static char *ipl_names[] = IPL_NAMES;
+
+ /* Start the clocks. */
+ startrtclock();
+
+ /* Find out what the hardware configuration looks like! */
+ if (config_rootfound("membus", "membus") == 0)
+ panic ("No mem bus found!");
+
+ for (i = 0; i < NIPL; i++)
+ printf("%s%s=%x", i?", ":"", ipl_names[i], imask[i]);
+ printf("\n");
+
+ safepri = imask[IPL_ZERO];
+ spl0();
+
+#if GENERIC
+ if ((boothowto & RB_ASKNAME) == 0)
+ setroot();
+ setconf();
+#else
+ setroot();
+#endif
+
+ /*
+ * Configure swap area and related system
+ * parameter based on device(s) used.
+ */
+ swapconf();
+ dumpconf();
+ cold = 0;
+}
+
+/*
+ * Configure swap space and related parameters.
+ */
+swapconf()
+{
+ register struct swdevt *swp;
+ register int nblks;
+ extern int Maxmem;
+
+
+ for (swp = swdevt; swp->sw_dev > 0; swp++)
+ {
+ unsigned d = major(swp->sw_dev);
+
+ if (d >= nblkdev) break;
+ if (bdevsw[d].d_psize) {
+ nblks = (*bdevsw[d].d_psize)(swp->sw_dev);
+ if (nblks > 0 &&
+ (swp->sw_nblks == 0 || swp->sw_nblks > nblks))
+ swp->sw_nblks = nblks;
+ else
+ swp->sw_nblks = 0;
+ }
+ swp->sw_nblks = ctod(dtoc(swp->sw_nblks));
+
+ }
+}
+
+#define DOSWAP /* change swdevt and dumpdev */
+u_long bootdev = 0; /* should be dev_t, but not until 32 bits */
+
+static char devname[][2] = {
+ 's','d', /* 0 = sd */
+ 's','w', /* 1 = sw */
+ 's','t', /* 2 = st */
+ 'r','d', /* 3 = rd */
+ 'c','d', /* 4 = cd */
+};
+
+/*
+ * Attempt to find the device from which we were booted.
+ * If we can do so, and not instructed not to do so,
+ * change rootdev to correspond to the load device.
+ */
+setroot()
+{
+ int majdev, mindev, unit, part, adaptor;
+ dev_t temp, orootdev;
+ struct swdevt *swp;
+
+ if (boothowto & RB_DFLTROOT ||
+ (bootdev & B_MAGICMASK) != (u_long)B_DEVMAGIC)
+ return;
+ majdev = (bootdev >> B_TYPESHIFT) & B_TYPEMASK;
+ if (majdev > sizeof(devname) / sizeof(devname[0]))
+ return;
+ adaptor = (bootdev >> B_ADAPTORSHIFT) & B_ADAPTORMASK;
+ part = (bootdev >> B_PARTITIONSHIFT) & B_PARTITIONMASK;
+ unit = (bootdev >> B_UNITSHIFT) & B_UNITMASK;
+ mindev = (unit * MAXPARTITIONS) + part;
+ orootdev = rootdev;
+ rootdev = makedev(majdev, mindev);
+ /*
+ * If the original rootdev is the same as the one
+ * just calculated, don't need to adjust the swap configuration.
+ */
+ if (rootdev == orootdev)
+ return;
+ printf("changing root device to %c%c%d%c\n",
+ devname[majdev][0], devname[majdev][1],
+ unit, part + 'a');
+
+#ifdef DOSWAP
+ for (swp = swdevt; swp->sw_dev != NODEV; swp++) {
+ if (majdev == major(swp->sw_dev) &&
+ (mindev / MAXPARTITIONS)
+ == (minor(swp->sw_dev) / MAXPARTITIONS)) {
+ temp = swdevt[0].sw_dev;
+ swdevt[0].sw_dev = swp->sw_dev;
+ swp->sw_dev = temp;
+ break;
+ }
+ }
+ if (swp->sw_dev == NODEV)
+ return;
+
+ /*
+ * If dumpdev was the same as the old primary swap device, move
+ * it to the new primary swap device.
+ */
+ if (temp == dumpdev)
+ dumpdev = swdevt[0].sw_dev;
+#endif
+}
+
+/* mem bus stuff */
+
+static int membusprobe();
+static void membusattach();
+
+struct cfdriver membuscd =
+ { NULL, "membus", membusprobe, membusattach,
+ DV_DULL, sizeof(struct device), NULL, 0 };
+
+static int
+membusprobe(parent, cf, aux)
+ struct device *parent;
+ struct cfdata *cf;
+ void *aux;
+{
+ return (strcmp(cf->cf_driver->cd_name, "membus") == 0);
+}
+
+static void
+membusattach(parent, self, args)
+ struct device *parent, *self;
+ void *args;
+{
+ printf ("\n");
+ while (config_found(self, NULL, NULL))
+ ;
+}
diff --git a/sys/arch/pc532/pc532/bcopy.s b/sys/arch/pc532/pc532/bcopy.s
new file mode 100644
index 00000000000..134743ae74e
--- /dev/null
+++ b/sys/arch/pc532/pc532/bcopy.s
@@ -0,0 +1,85 @@
+/* $NetBSD: bcopy.s,v 1.5 1995/08/29 22:37:41 phil Exp $ */
+
+/*
+ * Mach Operating System
+ * Copyright (c) 1992 Carnegie Mellon University
+ * Copyright (c) 1992 Helsinki University of Technology
+ * 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 AND HELSINKI UNIVERSITY OF TECHNOLOGY ALLOW FREE USE
+ * OF THIS SOFTWARE IN ITS "AS IS" CONDITION. CARNEGIE MELLON AND
+ * HELSINKI UNIVERSITY OF TECHNOLOGY DISCLAIM 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 Mellon
+ * the rights to redistribute these changes.
+ */
+/*
+ * File: ns532/bcopy.s
+ * Author: Tatu Ylonen, Jukka Virtanen
+ * Helsinki University of Technology 1992.
+ */
+
+#include <machine/asm.h>
+
+ .text
+
+/* ovbcopy (from, to, bcount) -- does overlapping stuff */
+
+ENTRY(bcopy)
+ENTRY(ovbcopy)
+ DFRAME
+ movd B_ARG0,r1 /* from */
+ movd B_ARG1,r2 /* to */
+ cmpd r2, r1
+ bls common /* safe to do standard thing */
+ movd B_ARG2,r0 /* bcount */
+ addd r1, r0 /* add to start of from */
+ cmpd r2, r0
+ bhs common /* safe to do standard thing */
+
+/* Must do a reverse copy (and assume that the start is on a
+ word boundry . . . so we move the "remaining" bytes first) */
+
+ movd B_ARG2, r0 /* bcount */
+ addqd -1, r0
+ addd r0, r1
+ addd r0, r2
+ addqd 1, r0
+ andd 3, r0
+ movsb b /* move bytes backwards */
+ addqd -3, r1 /* change to double pointer */
+ addqd -3, r2 /* ditto */
+ movd B_ARG2, r0
+ lshd -2,r0
+ movsd b /* move words backwards */
+ DEMARF
+ ret 0
+
+/* bcopy(from, to, bcount) -- non overlapping */
+
+/* ENTRY(bcopy) -- same as ovbcopy until furthur notice.... */
+ DFRAME
+ movd B_ARG0,r1 /* from */
+ movd B_ARG1,r2 /* to */
+common: movd B_ARG2,r0 /* bcount */
+ lshd -2,r0
+ movsd /* move words */
+ movd B_ARG2,r0
+ andd 3,r0
+ movsb /* move bytes */
+ DEMARF
+ ret 0
diff --git a/sys/arch/pc532/pc532/bzero.s b/sys/arch/pc532/pc532/bzero.s
new file mode 100644
index 00000000000..22a1e87efdd
--- /dev/null
+++ b/sys/arch/pc532/pc532/bzero.s
@@ -0,0 +1,99 @@
+/* $NetBSD: bzero.s,v 1.2 1994/10/26 08:24:51 cgd Exp $ */
+
+/*
+ * Mach Operating System
+ * Copyright (c) 1992 Carnegie Mellon University
+ * Copyright (c) 1992 Helsinki University of Technology
+ * 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 AND HELSINKI UNIVERSITY OF TECHNOLOGY ALLOW FREE USE
+ * OF THIS SOFTWARE IN ITS "AS IS" CONDITION. CARNEGIE MELLON AND
+ * HELSINKI UNIVERSITY OF TECHNOLOGY DISCLAIM 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 Mellon
+ * the rights to redistribute these changes.
+ */
+/*
+ * File: ns532/bzero.s
+ * Author: Tero Kivinen, Helsinki University of Technology 1992.
+ *
+ * $Id: bzero.s,v 1.1 1995/10/18 08:51:21 deraadt Exp $
+ */
+
+#include <machine/asm.h>
+
+/*
+ * bzero(char * addr, unsigned int length)
+ */
+
+ .text
+Entry(blkclr)
+ENTRY(bzero)
+ DFRAME
+ movd B_ARG0,r1 /* addr */
+ movd B_ARG1,r2 /* length */
+ movd r1,r0 /* align addr */
+ andd 3,r0
+ cmpqd 0,r0
+ beq wstart /* already aligned */
+ negd r0,r0
+ addqd 4,r0
+ cmpd r0,r2
+ bhi bytes /* not enough data to align */
+b1loop: movqb 0,0(r1) /* zero bytes */
+ addqd 1,r1
+ addqd -1,r2
+ acbd -1,r0,b1loop
+wstart: movd r2,r0 /* length */
+ lshd -6,r0
+ cmpqd 0,r0
+ beq phase2
+w1loop: movqd 0,0(r1) /* zero words */
+ movqd 0,4(r1)
+ movqd 0,8(r1)
+ movqd 0,12(r1)
+ movqd 0,16(r1)
+ movqd 0,20(r1)
+ movqd 0,24(r1)
+ movqd 0,28(r1)
+ movqd 0,32(r1)
+ movqd 0,36(r1)
+ movqd 0,40(r1)
+ movqd 0,44(r1)
+ movqd 0,48(r1)
+ movqd 0,52(r1)
+ movqd 0,56(r1)
+ movqd 0,60(r1)
+ addd 64,r1
+ acbd -1,r0,w1loop
+phase2: movd r2,r0 /* length */
+ andd 63,r0
+ lshd -2,r0
+ cmpqd 0,r0
+ beq bytes
+w2loop: movqd 0,0(r1)
+ addqd 4,r1
+ acbd -1,r0,w2loop
+bytes: movd r2,r0 /* length */
+ andd 3,r0
+ cmpqd 0,r0
+ beq done
+bloop: movqb 0,0(r1) /* zero bytes */
+ addqd 1,r1
+ acbb -1,r0,bloop
+done: DEMARF
+ ret 0
diff --git a/sys/arch/pc532/pc532/clock.c b/sys/arch/pc532/pc532/clock.c
new file mode 100644
index 00000000000..81bcc8f8353
--- /dev/null
+++ b/sys/arch/pc532/pc532/clock.c
@@ -0,0 +1,253 @@
+/* $NetBSD: clock.c,v 1.11 1995/05/16 07:30:46 phil Exp $ */
+
+/*-
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * William Jolitz and Don Ahn.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)clock.c 7.2 (Berkeley) 5/12/91
+ *
+ */
+
+/*
+ * Primitive clock interrupt routines.
+ *
+ * Improved by Phil Budne ... 10/17/94.
+ * Pulled over code from i386/isa/clock.c (Matthias Pfaller 12/03/94).
+ */
+
+#include <sys/param.h>
+#include <sys/time.h>
+#include <sys/kernel.h>
+#include <sys/systm.h>
+
+#include <machine/icu.h>
+
+void spinwait __P((int));
+
+void
+startrtclock()
+{
+ int timer = (ICU_CLK_HZ) / hz;
+
+ /* Write the timer values to the ICU. */
+ WR_ADR (unsigned short, ICU_ADR + HCSV, timer);
+ WR_ADR (unsigned short, ICU_ADR + HCCV, timer);
+
+ /* Establish interrupt vector */
+ intr_establish(IR_CLK, hardclock, NULL, "clock", IPL_CLOCK,
+ FALLING_EDGE);
+}
+
+void
+cpu_initclocks()
+{
+ /* enable clock interrupt */
+ WR_ADR (unsigned char, ICU_ADR +CICTL, 0x30);
+}
+
+void
+spinwait(int millisecs)
+{
+ DELAY(5000 * millisecs);
+}
+
+DELAY(n)
+{
+ volatile int N = (n);
+ while (--N > 0)
+ ;
+}
+
+void
+setstatclockrate(int dummy)
+{
+ printf ("setstatclockrate\n");
+}
+
+
+static int month[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
+
+static int
+yeartoday(year)
+ int year;
+{
+
+ return((year % 4) ? 365 : 366);
+}
+
+int
+hexdectodec(n)
+ char n;
+{
+
+ return(((n >> 4) & 0x0F) * 10 + (n & 0x0F));
+}
+
+char
+dectohexdec(n)
+ int n;
+{
+
+ return((char)(((n / 10) << 4) & 0xF0) | ((n % 10) & 0x0F));
+}
+
+static int timeset;
+struct rtc_st {
+ unsigned char rtc_csec;
+ unsigned char rtc_sec;
+ unsigned char rtc_min;
+ unsigned char rtc_hr;
+ unsigned char rtc_dow;
+ unsigned char rtc_dom;
+ unsigned char rtc_mon;
+ unsigned char rtc_yr;
+};
+
+/*
+ * Initialize the time of day register, based on the time base which is, e.g.
+ * from a filesystem.
+ */
+void
+inittodr(base)
+ time_t base;
+{
+ /*
+ * We ignore the suggested time for now and go for the RTC
+ * clock time stored in the CMOS RAM.
+ */
+ struct rtc_st rtclk;
+ time_t n;
+ int csec, sec, min, hr, dom, mon, yr;
+ int i, days = 0;
+ int s;
+ extern int have_rtc;
+
+ timeset = 1;
+ if (!have_rtc) {
+ time.tv_sec = base;
+ return;
+ }
+
+ rw_rtc((unsigned char *)&rtclk, 0);
+
+ csec = hexdectodec(rtclk.rtc_csec);
+ sec = hexdectodec(rtclk.rtc_sec);
+ min = hexdectodec(rtclk.rtc_min);
+ hr = hexdectodec(rtclk.rtc_hr);
+ dom = hexdectodec(rtclk.rtc_dom);
+ mon = hexdectodec(rtclk.rtc_mon);
+ yr = hexdectodec(rtclk.rtc_yr);
+ yr = (yr < 70) ? yr + 100 : yr;
+
+ /*
+ * Check to see if it was really the rtc
+ * by checking for bad date info.
+ */
+ if (sec > 59 || min > 59 || hr > 23 || dom > 31 || mon > 12) {
+ printf("inittodr: No clock found\n");
+ time.tv_sec = base;
+ return;
+ }
+
+ n = sec + 60 * min + 3600 * hr;
+ n += (dom - 1) * 3600 * 24;
+
+ if (yeartoday(yr) == 366)
+ month[1] = 29;
+ for (i = mon - 2; i >= 0; i--)
+ days += month[i];
+ month[1] = 28;
+ for (i = 70; i < yr; i++)
+ days += yeartoday(i);
+ n += days * 3600 * 24;
+
+ n += tz.tz_minuteswest * 60;
+ if (tz.tz_dsttime)
+ n -= 3600;
+ s = splclock();
+ time.tv_sec = n;
+ time.tv_usec = csec * 10000;
+ splx(s);
+}
+
+/*
+ * Reset the clock.
+ */
+void
+resettodr()
+{
+ struct rtc_st rtclk;
+ time_t n;
+ int diff, i, j;
+ int s;
+
+ /*
+ * We might have been called by boot() due to a crash early
+ * on. Don't reset the clock chip in this case.
+ */
+ if (!timeset)
+ return;
+
+ diff = tz.tz_minuteswest * 60;
+ if (tz.tz_dsttime)
+ diff -= 3600;
+
+ s = splclock();
+ n = (time.tv_sec - diff) % (3600 * 24); /* hrs+mins+secs */
+ rtclk.rtc_csec = dectohexdec(time.tv_usec / 10000);
+ rtclk.rtc_sec = dectohexdec(n%60);
+ n /= 60;
+ rtclk.rtc_min = dectohexdec(n%60);
+ rtclk.rtc_hr = dectohexdec(n/60);
+
+ n = (time.tv_sec - diff) / (3600 * 24); /* days */
+ splx(s);
+ rtclk.rtc_dow = (n + 4) % 7; /* 1/1/70 is Thursday */
+
+ for (j = 1970, i = yeartoday(j); n >= i; j++, i = yeartoday(j))
+ n -= i;
+
+ rtclk.rtc_yr = dectohexdec(j - 1900);
+
+ if (i == 366)
+ month[1] = 29;
+ for (i = 0; n >= month[i]; i++)
+ n -= month[i];
+ month[1] = 28;
+ rtclk.rtc_mon = dectohexdec(++i);
+
+ rtclk.rtc_dom = dectohexdec(++n);
+
+ rw_rtc((unsigned char *)&rtclk, 1);
+}
diff --git a/sys/arch/pc532/pc532/conf.c b/sys/arch/pc532/pc532/conf.c
new file mode 100644
index 00000000000..6898e20f64b
--- /dev/null
+++ b/sys/arch/pc532/pc532/conf.c
@@ -0,0 +1,223 @@
+/* $NetBSD: conf.c,v 1.26 1995/09/26 20:16:25 phil Exp $ */
+
+/*-
+ * Copyright (c) 1991 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)conf.c 7.9 (Berkeley) 5/28/91
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/buf.h>
+#include <sys/ioctl.h>
+#include <sys/tty.h>
+#include <sys/conf.h>
+#include <sys/vnode.h>
+
+int ttselect __P((dev_t, int, struct proc *));
+
+#include "sd.h"
+bdev_decl(sd);
+bdev_decl(sw);
+#include "st.h"
+bdev_decl(st);
+#include "rd.h"
+bdev_decl(rd);
+#include "cd.h"
+bdev_decl(cd);
+#include "vnd.h"
+bdev_decl(vnd);
+#include "ccd.h"
+bdev_decl(ccd);
+
+struct bdevsw bdevsw[] =
+{
+ bdev_disk_init(NSD,sd), /* 0: SCSI disk */
+ bdev_swap_init(1,sw), /* 1: swap pseudo-device */
+ bdev_tape_init(NST,st), /* 2: SCSI tape */
+ bdev_disk_init(NRD,rd), /* 3: ram disk */
+ bdev_disk_init(NCD,cd), /* 4: SCSI CD-ROM */
+ bdev_disk_init(NVND,vnd), /* 5: vnode disk driver */
+ bdev_disk_init(NCCD,ccd), /* 6: concatenated disk driver */
+};
+int nblkdev = sizeof(bdevsw) / sizeof(bdevsw[0]);
+
+/* 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, 0}
+
+cdev_decl(cn);
+cdev_decl(ctty);
+#define mmread mmrw
+#define mmwrite mmrw
+cdev_decl(mm);
+cdev_decl(sd);
+cdev_decl(sw);
+#include "pty.h"
+#define ptstty ptytty
+#define ptsioctl ptyioctl
+cdev_decl(pts);
+#define ptctty ptytty
+#define ptcioctl ptyioctl
+cdev_decl(ptc);
+cdev_decl(log);
+#include "scn.h"
+cdev_decl(scn);
+cdev_decl(rd);
+cdev_decl(st);
+cdev_decl(fd);
+cdev_decl(cd);
+cdev_decl(vnd);
+cdev_decl(ccd);
+#include "bpfilter.h"
+cdev_decl(bpf);
+#include "tun.h"
+cdev_decl(tun);
+#include "lpt.h"
+cdev_decl(lpt);
+
+struct cdevsw cdevsw[] =
+{
+ cdev_cn_init(1,cn), /* 0: virtual console */
+ cdev_ctty_init(1,ctty), /* 1: controlling terminal */
+ cdev_mm_init(1,mm), /* 2: /dev/{null,mem,kmem,...} */
+ cdev_disk_init(NSD,sd), /* 3: SCSI disk */
+ cdev_swap_init(1,sw), /* 4: /dev/drum (swap device) */
+ cdev_tty_init(NPTY,pts), /* 5: pseudo-tty slave */
+ cdev_ptc_init(NPTY,ptc), /* 6: pseudo-tty master */
+ cdev_log_init(1,log), /* 7: /dev/klog */
+ cdev_tty_init(NSCN,scn), /* 8: serial ports */
+ cdev_disk_init(NRD,rd), /* 9: RAM disk */
+ cdev_tape_init(NST,st), /* 10: SCSI tape */
+ cdev_fd_init(1,fd), /* 11: file descriptor pseudo-device */
+ cdev_disk_init(NCD,cd), /* 12: SCSI CD-ROM */
+ cdev_disk_init(NVND,vnd), /* 13: vnode disk driver */
+ cdev_bpftun_init(NBPFILTER,bpf),/* 14: Berkeley packet filter */
+ cdev_bpftun_init(NTUN,tun), /* 15: network tunnel */
+ cdev_notdef(), /* 16 */
+ cdev_lpt_init(NLPT, lpt), /* 17: Centronics */
+ cdev_disk_init(NCCD,ccd), /* 18: concatenated disk driver */
+};
+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);
+
+/*
+ * Returns true if dev is /dev/mem or /dev/kmem.
+ */
+iskmemdev(dev)
+ dev_t dev;
+{
+
+ return (major(dev) == mem_no && minor(dev) < 2);
+}
+
+/*
+ * Returns true if dev is /dev/zero.
+ */
+iszerodev(dev)
+ dev_t dev;
+{
+
+ return (major(dev) == mem_no && minor(dev) == 12);
+}
+
+static int chrtoblktbl[] = {
+ /* XXXX This needs to be dynamic for LKMs. */
+ /*VCHR*/ /*VBLK*/
+ /* 0 */ NODEV,
+ /* 1 */ NODEV,
+ /* 2 */ NODEV,
+ /* 3 */ 0,
+ /* 4 */ NODEV,
+ /* 5 */ NODEV,
+ /* 6 */ NODEV,
+ /* 7 */ NODEV,
+ /* 8 */ NODEV,
+ /* 9 */ 3,
+ /* 10 */ 2,
+ /* 11 */ NODEV,
+ /* 12 */ 4,
+ /* 13 */ 5,
+ /* 14 */ NODEV,
+ /* 15 */ NODEV,
+ /* 16 */ NODEV,
+ /* 17 */ NODEV,
+ /* 18 */ 6
+};
+
+/*
+ * Convert a character device number to a block device number.
+ */
+chrtoblk(dev)
+ dev_t dev;
+{
+ int blkmaj;
+
+ if (major(dev) >= nchrdev)
+ return (NODEV);
+ blkmaj = chrtoblktbl[major(dev)];
+ if (blkmaj == NODEV)
+ return (NODEV);
+ return (makedev(blkmaj, minor(dev)));
+}
+
+/*
+ * This entire table could be autoconfig()ed but that would mean that
+ * the kernel's idea of the console would be out of sync with that of
+ * the standalone boot. I think it best that they both use the same
+ * known algorithm unless we see a pressing need otherwise.
+ */
+#include <dev/cons.h>
+
+cons_decl(scn);
+
+struct consdev constab[] = {
+#if NSCN > 0
+ cons_init(scn),
+#endif
+ { 0 },
+};
diff --git a/sys/arch/pc532/pc532/db_disasm.c b/sys/arch/pc532/pc532/db_disasm.c
new file mode 100644
index 00000000000..71336343565
--- /dev/null
+++ b/sys/arch/pc532/pc532/db_disasm.c
@@ -0,0 +1,1899 @@
+/* $NetBSD: db_disasm.c,v 1.2 1994/10/26 08:24:55 cgd Exp $ */
+
+/*
+ * Mach Operating System
+ * Copyright (c) 1992 Carnegie Mellon University
+ * Copyright (c) 1992 Helsinki University of Technology
+ * Copyright (c) 1992 Bob Krause, Bruce Culbertson
+ * 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 AND HELSINKI UNIVERSITY OF TECHNOLOGY AND BOB
+ * KRAUSE AND BRUCE CULBERTSON ALLOW FREE USE OF THIS SOFTWARE IN ITS
+ * "AS IS" CONDITION. CARNEGIE MELLON AND HELSINKI UNIVERSITY OF
+ * TECHNOLOGY AND BOB KRAUSE AND BRUCE CULBERTSON DISCLAIM 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 Mellon
+ * the rights to redistribute these changes.
+ */
+/*
+ * From Bruce Culbertson's and Bob Krause's ROM monitor for the pc532
+ * adapted to pc532 Mach by Tero Kivinen and Tatu Ylonen at Helsinki
+ * University of Technology.
+ */
+
+/*
+ * Adapted for 532bsd (386bsd port) by Phil Nelson.
+ *
+ * Not yet complete!
+ *
+ */
+
+#define STATIC static
+
+/* #include <mach/boolean.h> */
+#include <machine/db_machdep.h>
+#include <ddb/db_access.h>
+#include <ddb/db_sym.h>
+#include <ddb/db_variables.h>
+#include <machine/pmap.h>
+#include <vm/vm_map.h>
+/* #include <kern/thread.h> */
+
+struct operand {
+ int o_mode; /* address mode */
+ int o_reg0; /* first register */
+ int o_reg1; /* second register */
+ long o_disp0; /* first displacment value */
+ long o_disp1; /* second displacement value */
+ int o_iscale; /* scaled indexing factor */
+ int o_ireg; /* scaled indexing register */
+};
+
+struct insn {
+ int i_format; /* instruction format */
+ int i_op; /* operation code */
+ char i_monic[8]; /* mneumonic string */
+ unsigned char i_iol; /* integer operand length */
+ struct operand i_opr[4]; /* operands */
+};
+
+/* Addressing modes (not the same format as in a machine instruction) */
+#define AMODE_NONE 0 /* operand not used by instruction */
+#define AMODE_REG 1 /* register */
+#define AMODE_RREL 2 /* register relative */
+#define AMODE_MREL 3 /* memory relative */
+#define AMODE_IMM 4 /* immediate */
+#define AMODE_ABS 5 /* absolute */
+#define AMODE_EXT 6 /* external */
+#define AMODE_TOS 7 /* top of stack */
+#define AMODE_MSPC 8 /* memory space */
+#define AMODE_REGLIST 9 /* a register list */
+#define AMODE_QUICK 10 /* quick integer (-8 .. +7) */
+#define AMODE_INVALID 11 /* invalid address mode found */
+#define AMODE_AREG 12 /* CPU dedicated register */
+#define AMODE_BLISTB 13 /* byte length bit list */
+#define AMODE_BLISTW 14 /* word length bit list */
+#define AMODE_BLISTD 15 /* double-word length bit list */
+#define AMODE_SOPT 16 /* options in string instructions */
+#define AMODE_CFG 17 /* configuration bits */
+#define AMODE_MREG 18 /* memory management register */
+#define AMODE_CINV 19 /* cache invalidate options */
+
+/* Instruction types */
+#define ITYPE_FMT0 0
+#define ITYPE_FMT1 1
+#define ITYPE_FMT2 2
+#define ITYPE_FMT3 3
+#define ITYPE_FMT4 4
+#define ITYPE_FMT5 5
+#define ITYPE_FMT6 6
+#define ITYPE_FMT7 7
+#define ITYPE_FMT8 8
+#define ITYPE_FMT9 9
+#define ITYPE_NOP 10
+#define ITYPE_FMT11 11
+#define ITYPE_FMT12 12
+#define ITYPE_UNDEF 13
+#define ITYPE_FMT14 14
+#define ITYPE_FMT15 15
+
+/* Table to determine the 'condition' field of an instruction */
+STATIC
+char cond_table[16][3] = {
+ "eq", /* equal */
+ "ne", /* not equal */
+ "cs", /* carry set */
+ "cc", /* carry clear */
+ "hi", /* higher */
+ "ls", /* lower or same */
+ "gt", /* greater than */
+ "le", /* less than or equal */
+ "fs", /* flag set */
+ "fc", /* flag clear */
+ "lo", /* lower */
+ "hs", /* higher or same */
+ "lt", /* less than */
+ "ge", /* greater than or equal */
+ "r", /* unconditional branch */
+ "??" /* never branch (nop) */
+};
+
+#define IOL(x) (((x)&0x3) + 1)
+#define IOL_BYTE 1 /* Byte (8-bits) */
+#define IOL_WORD 2 /* Word (16-bits) */
+#define IOL_NONE 3 /* Does not apply */
+#define IOL_DOUBLE 4 /* Double Word (32-bits) */
+
+STATIC
+char iol_table[5][2] = {
+ "?", /* Should never appear */
+ "b", /* byte */
+ "w", /* word */
+ "?", /* undefined */
+ "d" /* double word */
+};
+
+STATIC
+char fol_table[2][2] = {
+ "l", /* long floating-point */
+ "f" /* standard floating-point */
+};
+
+STATIC
+char scale_table[5][2] = {
+ "?", /* no scaled indexing */
+ "b", /* byte */
+ "w", /* word */
+ "d", /* double-word */
+ "q" /* quad-word */
+};
+
+STATIC
+char cfg_table[4][2] = {
+ "i", /* vectored interrupt enable */
+ "f", /* floating point enable */
+ "m", /* memory management enable */
+ "c" /* custom slave enable */
+};
+
+STATIC
+char sopt_table[8][4] = {
+ "", /* no options */
+ "b", /* backward */
+ "w", /* while match */
+ "b,w", /* backward, while match */
+ "?", /* undefined */
+ "b,?", /* undefined */
+ "u", /* until match */
+ "b,u" /* backward, until match */
+};
+
+#define AREG_US 0x0 /* user stack */
+#define AREG_FP 0x8 /* frame pointer */
+#define AREG_SP 0x9 /* stack pointer */
+#define AREG_SB 0xa /* static base */
+#define AREG_PSR 0xd /* processor status register */
+#define AREG_INTBASE 0xe /* interrupt base */
+#define AREG_MOD 0xf /* module */
+
+/* Floating-point operand length field masks */
+#define FOL_SINGLE 0x1 /* Single Precision (32-bits) */
+#define FOL_DOUBLE 0x0 /* Double Precision (64-bits) */
+
+#define FMT0_COND(x) (((x)&0xf0)>>4) /* Condition code for fmt 0 */
+#define FMT1_OP(x) (((x)&0xf0)>>4) /* Op code for fmt 1 */
+#define FMT2_OP(x) (((x)&0x70)>>4) /* Op code for fmt 2 */
+#define FMT2_COND(x, y) (((x)>>7) + (((y)&0x80)<<1)) /* Condition code for fmt 2 */
+#define FMT3_OP(x) ((x)&0x7) /* bits 2-4 of fmt 3 op code */
+#define FMT4_OP(x) (((x)&0x3c)>>2) /* Op code for fmt 4 */
+#define FMT5_OP(x) (((x)&0x3c)>>2) /* op code for fmt 5 */
+#define FMT6_OP(x) (((x)&0x3c)>>2) /* op code for fmt 6 */
+#define FMT7_OP(x) (((x)&0x3c)>>2) /* op code for fmt 7 */
+#define FMT8_OP(x, y) ((((x)&0xc0)>>6) + ((y)&0x4))
+#define FMT8_REG(x) (((x)&0x38)>>3) /* register operand for fmt 8 */
+#define FMT8_SU 1 /* register value -> movsu */
+#define FMT8_US 3 /* register value -> movus */
+#define FMT9_OP(x) (((x)&0x38)>>3) /* op code for fmt 9 */
+#define FMT9_F(x) (((x)&0x4)>>2) /* float type for fmt 9 */
+#define FMT11_OP(x) (((x)&0x3c)>>2) /* op code for fmt 11 */
+#define FMT12_OP(x) (((x)&0x3c)>>2) /* op code for fmt 12 */
+#define FMT11_F(x) ((x)&01) /* float type for fmt 11 */
+#define FMT12_F(x) ((x)&01) /* float type for fmt 12 */
+#define FMT14_OP(x) (((x)&0x3c)>>2) /* op code for fmt 14 */
+
+#define GEN_R0 0 /* register 0 */
+#define GEN_R1 1 /* register 1 */
+#define GEN_R2 2 /* register 2 */
+#define GEN_R3 3 /* register 3 */
+#define GEN_R4 4 /* register 4 */
+#define GEN_R5 5 /* register 5 */
+#define GEN_R6 6 /* register 6 */
+#define GEN_R7 7 /* register 7 */
+#define GEN_RR0 8 /* register 0 relative */
+#define GEN_RR1 9 /* register 1 relative */
+#define GEN_RR2 10 /* register 2 relative */
+#define GEN_RR3 11 /* register 3 relative */
+#define GEN_RR4 12 /* register 4 relative */
+#define GEN_RR5 13 /* register 5 relative */
+#define GEN_RR6 14 /* register 6 relative */
+#define GEN_RR7 15 /* register 7 relative */
+#define GEN_FRMR 16 /* frame memory relative */
+#define GEN_SPMR 17 /* stack memory relative */
+#define GEN_SBMR 18 /* static memory relative */
+#define GEN_RES 19 /* reserved for future use */
+#define GEN_IMM 20 /* immediate */
+#define GEN_ABS 21 /* absolute */
+#define GEN_EXT 22 /* external */
+#define GEN_TOS 23 /* top of stack */
+#define GEN_FRM 24 /* frame memory */
+#define GEN_SPM 25 /* stack memory */
+#define GEN_SBM 26 /* static memory */
+#define GEN_PCM 27 /* program memory */
+#define GEN_SIB 28 /* scaled index, bytes */
+#define GEN_SIW 29 /* scaled index, words */
+#define GEN_SID 30 /* scaled index, double words */
+#define GEN_SIQ 31 /* scaled index, quad words */
+
+STATIC
+unsigned char fmttab[128] = {
+/* This is really an array of 256 nibbles. The index is the first
+ * byte of an instruction opcode. The value in the array is the
+ * instruction format corresponding to that first byte.
+ *
+ * group 1st byte insn format insn type
+ */
+(4+ /* 00000000 format 4 add .b */
+(4*16)), /* 00000001 format 4 add .w */
+(1+ /* 00000010 format 1 bsr */
+(4*16)), /* 00000011 format 4 add .l */
+(4+ /* 00000100 format 4 cmp .b */
+(4*16)), /* 00000101 format 4 cmp .w */
+(13+ /* 00000110 format 19 undefined */
+(4*16)), /* 00000111 format 4 cmp .l */
+(4+ /* 00001000 format 4 bic .b */
+(4*16)), /* 00001001 format 4 bic .w */
+(0+ /* 00001010 format 0 beq */
+(4*16)), /* 00001011 format 4 bic .w */
+(2+ /* 00001100 format 2 addq .b */
+(2*16)), /* 00001101 format 2 addq .w */
+(5+ /* 00001110 format 5 */
+(2*16)), /* 00001111 format 2 addq .l */
+(4+ /* 00010000 format 4 addc .b */
+(4*16)), /* 00010001 format 4 addc .w */
+(1+ /* 00010010 format 1 ret */
+(4*16)), /* 00010011 format 4 addc .l */
+(4+ /* 00010100 format 4 mov .b */
+(4*16)), /* 00010101 format 4 mov .w */
+(15+ /* 00010110 format 15 */
+(4*16)), /* 00010111 format 4 mov .l */
+(4+ /* 00011000 format 4 or .b */
+(4*16)), /* 00011001 format 4 or .w */
+(0+ /* 00011010 format 0 bne */
+(4*16)), /* 00011011 format 4 or .l */
+(2+ /* 00011100 format 2 cmpq .b */
+(2*16)), /* 00011101 format 2 cmpq .w */
+(14+ /* 00011110 format 14 */
+(2*16)), /* 00011111 format 2 cmpq .l */
+(4+ /* 00100000 format 4 sub .b */
+(4*16)), /* 00100001 format 4 sub .w */
+(1+ /* 00100010 format 1 cxp */
+(4*16)), /* 00100011 format 4 sub .l */
+(4+ /* 00100100 format 4 addr .b */
+(4*16)), /* 00100101 format 4 addr .w */
+(13+ /* 00100110 format 19 undefined */
+(4*16)), /* 00100111 format 4 addr .l */
+(4+ /* 00101000 format 4 and .b */
+(4*16)), /* 00101001 format 4 and .w */
+(0+ /* 00101010 format 0 bcs */
+(4*16)), /* 00101011 format 4 and .l */
+(2+ /* 00101100 format 2 spr .b */
+(2*16)), /* 00101101 format 2 spr .w */
+(8+ /* 00101110 format 8 */
+(2*16)), /* 00101111 format 2 spr .l */
+(4+ /* 00110000 format 4 subc .b */
+(4*16)), /* 00110001 format 4 subc .w */
+(1+ /* 00110010 format 1 rxp */
+(4*16)), /* 00110011 format 4 subc .l */
+(4+ /* 00110100 format 4 tbit .b */
+(4*16)), /* 00110101 format 4 tbit .w */
+(15+ /* 00110110 format 15 */
+(4*16)), /* 00110111 format 4 tbit .l */
+(4+ /* 00111000 format 4 xor .b */
+(4*16)), /* 00111001 format 4 xor .w */
+(0+ /* 00111010 format 0 bcc */
+(4*16)), /* 00111011 format 4 xor .l */
+(2+ /* 00111100 format 2 scond .b */
+(2*16)), /* 00111101 format 2 scond .w */
+(9+ /* 00111110 format 9 */
+(2*16)), /* 00111111 format 2 scond .l */
+(4+ /* 01000000 format 4 add .b */
+(4*16)), /* 01000001 format 4 add .w */
+(1+ /* 01000010 format 1 rett */
+(4*16)), /* 01000011 format 4 add .l */
+(4+ /* 01000100 format 4 cmp .b */
+(4*16)), /* 01000101 format 4 cmp .w */
+(13+ /* 01000110 format 19 undefined */
+(4*16)), /* 01000111 format 4 cmp .l */
+(4+ /* 01001000 format 4 bic .b */
+(4*16)), /* 01001001 format 4 bic .w */
+(0+ /* 01001010 format 0 bhi */
+(4*16)), /* 01001011 format 4 bic .l */
+(2+ /* 01001100 format 2 acb .b */
+(2*16)), /* 01001101 format 2 acb .w */
+(6+ /* 01001110 format 6 */
+(2*16)), /* 01001111 format 2 acb .l */
+(4+ /* 01010000 format 4 addc .b */
+(4*16)), /* 01010001 format 4 addc .w */
+(1+ /* 01010010 format 1 reti */
+(4*16)), /* 01010011 format 4 addc .l */
+(4+ /* 01010100 format 4 mov .b */
+(4*16)), /* 01010101 format 4 mov .w */
+(15+ /* 01010110 format 15 */
+(4*16)), /* 01010111 format 4 mov .l */
+(4+ /* 01011000 format 4 or .b */
+(4*16)), /* 01011001 format 4 or .w */
+(0+ /* 01011010 format 0 bis */
+(4*16)), /* 01011011 format 4 or .l */
+(2+ /* 01011100 format 2 movq .b */
+(2*16)), /* 01011101 format 2 movq .w */
+(13+ /* 01011110 format 16 undefined */
+(2*16)), /* 01011111 format 2 movq .l */
+(4+ /* 01100000 format 4 sub .b */
+(4*16)), /* 01100001 format 4 sub .w */
+(1+ /* 01100010 format 1 save */
+(4*16)), /* 01100011 format 4 sub .l */
+(4+ /* 01100100 format 4 addr .b */
+(4*16)), /* 01100101 format 4 addr .w */
+(13+ /* 01100110 format 19 undefined */
+(4*16)), /* 01100111 format 4 addr .l */
+(4+ /* 01101000 format 4 and .b */
+(4*16)), /* 01101001 format 4 and .w */
+(0+ /* 01101010 format 0 bgt */
+(4*16)), /* 01101011 format 4 and .l */
+(2+ /* 01101100 format 2 lpr .b */
+(2*16)), /* 01101101 format 2 lpr .w */
+(8+ /* 01101110 format 8 */
+(2*16)), /* 01101111 format 2 lpr .l */
+(4+ /* 01110000 format 4 subc .b */
+(4*16)), /* 01110001 format 4 subc .w */
+(1+ /* 01110010 format 1 restore */
+(4*16)), /* 01110011 format 4 subc .l */
+(4+ /* 01110100 format 4 tbit .b */
+(4*16)), /* 01110101 format 4 tbit .w */
+(15+ /* 01110110 format 15 */
+(4*16)), /* 01110111 format 4 tbit .l */
+(4+ /* 01111000 format 4 xor .b */
+(4*16)), /* 01111001 format 4 xor .w */
+(0+ /* 01111010 format 0 ble */
+(4*16)), /* 01111011 format 4 xor .l */
+(3+ /* 01111100 format 3 */
+(3*16)), /* 01111101 format 3 */
+(13+ /* 01111110 format 10 undefined */
+(3*16)), /* 01111111 format 3 */
+(4+ /* 10000000 format 4 add .b */
+(4*16)), /* 10000001 format 4 add .w */
+(1+ /* 10000010 format 1 enter */
+(4*16)), /* 10000011 format 4 add .l */
+(4+ /* 10000100 format 4 cmp .b */
+(4*16)), /* 10000101 format 4 cmp .w */
+(13+ /* 10000110 format 19 undefined */
+(4*16)), /* 10000111 format 4 cmp .l */
+(4+ /* 10001000 format 4 bic .b */
+(4*16)), /* 10001001 format 4 bic .w */
+(0+ /* 10001010 format 0 bfs */
+(4*16)), /* 10001011 format 4 bic .l */
+(2+ /* 10001100 format 2 addq .b */
+(2*16)), /* 10001101 format 2 addq .w */
+(13+ /* 10001110 format 18 undefined */
+(2*16)), /* 10001111 format 2 addq .l */
+(4+ /* 10010000 format 4 addc .b */
+(4*16)), /* 10010001 format 4 addc .w */
+(1+ /* 10010010 format 1 exit */
+(4*16)), /* 10010011 format 4 addc .l */
+(4+ /* 10010100 format 4 mov .b */
+(4*16)), /* 10010101 format 4 mov .w */
+(15+ /* 10010110 format 15 */
+(4*16)), /* 10010111 format 4 mov .l */
+(4+ /* 10011000 format 4 or .b */
+(4*16)), /* 10011001 format 4 or .w */
+(0+ /* 10011010 format 0 bfc */
+(4*16)), /* 10011011 format 4 or .l */
+(2+ /* 10011100 format 2 cmpq .b */
+(2*16)), /* 10011101 format 2 cmpq .w */
+(13+ /* 10011110 format 13 undefined */
+(2*16)), /* 10011111 format 2 cmpq .l */
+(4+ /* 10100000 format 4 sub .b */
+(4*16)), /* 10100001 format 4 sub .w */
+(10+ /* 10100010 format 1 nop */
+(4*16)), /* 10100011 format 4 sub .l */
+(4+ /* 10100100 format 4 addr .b */
+(4*16)), /* 10100101 format 4 addr .w */
+(13+ /* 10100110 format 19 undefined */
+(4*16)), /* 10100111 format 4 addr .l */
+(4+ /* 10101000 format 4 and .b */
+(4*16)), /* 10101001 format 4 and .w */
+(0+ /* 10101010 format 0 blo */
+(4*16)), /* 10101011 format 4 and .l */
+(2+ /* 10101100 format 2 spr .b */
+(2*16)), /* 10101101 format 2 spr .w */
+(8+ /* 10101110 format 8 */
+(2*16)), /* 10101111 format 2 spr .l */
+(4+ /* 10110000 format 4 subc .b */
+(4*16)), /* 10110001 format 4 subc .w */
+(1+ /* 10110010 format 1 wait */
+(4*16)), /* 10110011 format 4 subc .l */
+(4+ /* 10110100 format 4 tbit .b */
+(4*16)), /* 10110101 format 4 tbit .w */
+(15+ /* 10110110 format 15 */
+(4*16)), /* 10110111 format 4 tbit .l */
+(4+ /* 10111000 format 4 xor .b */
+(4*16)), /* 10111001 format 4 xor .w */
+(0+ /* 10111010 format 0 bhs */
+(4*16)), /* 10111011 format 4 xor .l */
+(2+ /* 10111100 format 2 scond .b */
+(2*16)), /* 10111101 format 2 scond .w */
+(11+ /* 10111110 format 11 */
+(2*16)), /* 10111111 format 2 scond .l */
+(4+ /* 11000000 format 4 add .b */
+(4*16)), /* 11000001 format 4 add .w */
+(1+ /* 11000010 format 1 dia */
+(4*16)), /* 11000011 format 4 add .l */
+(4+ /* 11000100 format 4 cmp .b */
+(4*16)), /* 11000101 format 4 cmp .w */
+(13+ /* 11000110 format 19 undefined */
+(4*16)), /* 11000111 format 4 cmp .l */
+(4+ /* 11001000 format 4 bic .b */
+(4*16)), /* 11001001 format 4 bic .w */
+(0+ /* 11001010 format 0 blt */
+(4*16)), /* 11001011 format 4 bic .l */
+(2+ /* 11001100 format 2 acb .b */
+(2*16)), /* 11001101 format 2 acb .w */
+(7+ /* 11001110 format 7 */
+(2*16)), /* 11001111 format 2 acb .l */
+(4+ /* 11010000 format 4 addc .b */
+(4*16)), /* 11010001 format 4 addc .w */
+(1+ /* 11010010 format 1 flag */
+(4*16)), /* 11010011 format 4 addc .l */
+(4+ /* 11010100 format 4 mov .b */
+(4*16)), /* 11010101 format 4 mov .w */
+(15+ /* 11010110 format 15 */
+(4*16)), /* 11010111 format 4 mov .l */
+(4+ /* 11011000 format 4 or .b */
+(4*16)), /* 11011001 format 4 or .w */
+(0+ /* 11011010 format 0 bqt */
+(4*16)), /* 11011011 format 4 or .l */
+(2+ /* 11011100 format 2 movq .b */
+(2*16)), /* 11011101 format 2 movq .w */
+(13+ /* 11011110 format 17 undefined */
+(2*16)), /* 11011111 format 2 movq .l */
+(4+ /* 11100000 format 4 sub .b */
+(4*16)), /* 11100001 format 4 sub .w */
+(1+ /* 11100010 format 1 svc */
+(4*16)), /* 11100011 format 4 sub .l */
+(4+ /* 11100100 format 4 addr .b */
+(4*16)), /* 11100101 format 4 addr .w */
+(13+ /* 11100110 format 19 undefined */
+(4*16)), /* 11100111 format 4 addr .l */
+(4+ /* 11101000 format 4 and .b */
+(4*16)), /* 11101001 format 4 and .w */
+(0+ /* 11101010 format 0 b */
+(4*16)), /* 11101011 format 4 and .l */
+(2+ /* 11101100 format 2 lpr .b */
+(2*16)), /* 11101101 format 2 lpr .w */
+(8+ /* 11101110 format 8 */
+(2*16)), /* 11101111 format 2 lpr .l */
+(4+ /* 11110000 format 4 subc .b */
+(4*16)), /* 11110001 format 4 subc .w */
+(1+ /* 11110010 format 1 bpt */
+(4*16)), /* 11110011 format 4 subc .l */
+(4+ /* 11110100 format 4 tbit .b */
+(4*16)), /* 11110101 format 4 tbit .w */
+(15+ /* 11110110 format 15 */
+(4*16)), /* 11110111 format 4 tbit .l */
+(4+ /* 11111000 format 4 xor .b */
+(4*16)), /* 11111001 format 4 xor .w */
+(10+ /* 11111010 format 0 nop */
+(4*16)), /* 11111011 format 4 xor .l */
+(13+ /* 11111100 format 3 undefined */
+(13*16)), /* 11111101 format 3 undefined */
+((12+ /* 11111110 format 12 new 532 */
+13*16)) }; /* 11111111 format 3 undefined */
+
+STATIC
+char fmt1_table[16][8] = {
+ "bsr", /* branch to subroutine */
+ "ret", /* return from subroutine */
+ "cxp", /* call external procedure */
+ "rxp", /* return from external procedure */
+ "rett", /* return from trap */
+ "reti", /* return from interrupt */
+ "save", /* save general purpose registers */
+ "restore", /* restore general purpose registers */
+ "enter", /* enter new procedure context */
+ "exit", /* exit procedure context */
+ "nop", /* no operation */
+ "wait", /* wait fro interrupt */
+ "dia", /* diagnose */
+ "flag", /* flag trap */
+ "svc", /* supervisor call trap */
+ "bpt" /* breakpoint trap */
+};
+
+#define FMT1_BSR 0x0 /* branch to subroutine */
+#define FMT1_RET 0x1 /* return from subroutine */
+#define FMT1_CXP 0x2 /* call external procedure */
+#define FMT1_RXP 0x3 /* return from external procedure */
+#define FMT1_RETT 0x4 /* return from trap */
+#define FMT1_RETI 0x5 /* return from interrupt */
+#define FMT1_SAVE 0x6 /* save general purpose registers */
+#define FMT1_RESTORE 0x7 /* restore general purpose registers */
+#define FMT1_ENTER 0x8 /* enter new procedure context */
+#define FMT1_EXIT 0x9 /* exit procedure context */
+#define FMT1_NOP 0xa /* no operation */
+#define FMT1_WAIT 0xb /* wait fro interrupt */
+#define FMT1_DIA 0xc /* diagnose */
+#define FMT1_FLAG 0xd /* flag trap */
+#define FMT1_SVC 0xe /* supervisor call trap */
+#define FMT1_BPT 0xf /* breakpoint trap */
+
+STATIC
+char fmt2_table[7][5] = {
+ "addq", /* add quick */
+ "cmpq", /* compare quick */
+ "spr", /* save processor register */
+ "s", /* save condition as boolean */
+ "acb", /* add, compare and branch */
+ "movq", /* move quick */
+ "lpr" /* load processor register */
+};
+
+#define FMT2_ADDQ 0x0 /* add quick */
+#define FMT2_CMPQ 0x1 /* compare quick */
+#define FMT2_SPR 0x2 /* store processr oregister */
+#define FMT2_SCOND 0x3 /* save condition as boolean */
+#define FMT2_ACB 0x4 /* add, compare and branch */
+#define FMT2_MOVQ 0x5 /* move quick */
+#define FMT2_LPR 0x6 /* load processor register */
+
+STATIC
+char fmt3_table[8][7] = {
+ "cxpd", /* call external procedure with descriptor */
+ "bicpsr", /* bit clear in PSR */
+ "jump", /* jump */
+ "bispsr", /* bit set in PSR */
+ "??3??", /* UNDEFINED */
+ "adjsp", /* adjust stack pointer */
+ "jsr", /* jump to subroutine */
+ "case" /* case branch */
+};
+
+#define FMT3_CXPD 0x0 /* call external procedure with descriptor */
+#define FMT3_BICPSR 0x1 /* bit clear in PSR */
+#define FMT3_JUMP 0x2 /* jump */
+#define FMT3_BISPSR 0x3 /* bit set in PSR */
+#define FMT3_UNDEF 0x4 /* UNDEFINED */
+#define FMT3_ADJSP 0x5 /* adjust stack pointer */
+#define FMT3_JSR 0x6 /* jump to subroutine */
+#define FMT3_CASE 0x7 /* case branch */
+
+STATIC
+char fmt4_table[16][5] = {
+ "add", /* add */
+ "cmp", /* compare */
+ "bic", /* bit clear */
+ "?4?", /* UNDEFINED */
+ "addc", /* add with carry */
+ "mov", /* move */
+ "or", /* or */
+ "?4?", /* UNDEFINED */
+ "sub", /* subtract */
+ "addr", /* compute effective address */
+ "and", /* and */
+ "?4?", /* UNDEFINED */
+ "subc", /* subtract with carry */
+ "tbit", /* test bit */
+ "xor", /* exclusive or */
+ "?4?" /* UNDEFINED */
+};
+
+#define FMT4_ADD 0x0 /* add */
+#define FMT4_CMP 0x1 /* compare */
+#define FMT4_BIC 0x2 /* bit clear */
+#define FMT4_ADDC 0x4 /* add with carry */
+#define FMT4_MOV 0x5 /* move */
+#define FMT4_OR 0x6 /* or */
+#define FMT4_SUB 0x8 /* subtract */
+#define FMT4_ADDR 0x9 /* compute effective address */
+#define FMT4_AND 0xa /* and */
+#define FMT4_SUBC 0xc /* subtract with carry */
+#define FMT4_TBIT 0xd /* test bit */
+#define FMT4_XOR 0xe /* exclusive or */
+
+STATIC
+char fmt5_table[4][7] = {
+ "movs", /* move string */
+ "cmps", /* compare string */
+ "setcfg", /* set configuration register */
+ "skps" /* skip string */
+};
+
+#define FMT5_MOVS 0x0 /* move string */
+#define FMT5_CMPS 0x1 /* compare string */
+#define FMT5_SETCFG 0x2 /* set configuration register */
+#define FMT5_SKPS 0x3 /* skip string */
+
+STATIC
+char fmt6_table[16][6] = {
+ "rot", /* rotate */
+ "ash", /* arithmetic shift */
+ "cbit", /* clear bit */
+ "cbiti", /* clear bit interlocked */
+ "??6??", /* undefined */
+ "lsh", /* logical shift */
+ "sbit", /* set bit */
+ "sbiti", /* set bit interlocked */
+ "neg", /* negate */
+ "not", /* not */
+ "??6??", /* undefined */
+ "subp", /* subtract packed decimal */
+ "abs", /* absolute value */
+ "com", /* complement */
+ "ibit", /* invert bit */
+ "addp" /* add packed decimal */
+};
+
+#define FMT6_ROT 0x0 /* rotate */
+#define FMT6_ASH 0x1 /* arithmetic shift */
+#define FMT6_CBIT 0x2 /* clear bit */
+#define FMT6_CBITI 0x3 /* clear bit interlocked */
+#define FMT6_UNDEF1 0x4 /* undefined */
+#define FMT6_LSH 0x5 /* logical shift */
+#define FMT6_SBIT 0x6 /* s#define FMT6_NOT 0x9 /* not */
+#define FMT6_UNDEF2 0xa /* undefined */
+#define FMT6_SUBP 0xb /* subtract packed decimal */
+#define FMT6_ABS 0xc /* absolute value */
+#define FMT6_COM 0xd /* complement */
+#define FMT6_IBIT 0xe /* invert bit */
+#define FMT6_ADDP 0xf /* add packed decimal */
+
+STATIC
+char fmt7_table[16][7] = {
+ "movm", /* move multiple */
+ "cmpm", /* compare multiple */
+ "inss", /* insert field short */
+ "exts", /* extract field short */
+ "movxb", /* move with sign-extention byte to word */
+ "movzb", /* move with zero-extention byte to word */
+ "movz", /* move with zero extention i to double */
+ "movx", /* move with sign-extention i to double */
+ "mul", /* multiply */
+ "mei", /* multiply extended integer */
+ "?7?", /* undefined */
+ "dei", /* divide extended integer */
+ "quo", /* quotient */
+ "rem", /* remainder */
+ "mod", /* modulus */
+ "div" /* divide */
+};
+
+#define FMT7_MOVM 0x0 /* move multiple */
+#define FMT7_CMPM 0x1 /* compare multiple */
+#define FMT7_INSS 0x2 /* insert field short */
+#define FMT7_EXTS 0x3 /* extract field short */
+#define FMT7_MOVXBW 0x4 /* move with sign-extention byte to word */
+#define FMT7_MOVZBW 0x5 /* move with zero-extention byte to word */
+#define FMT7_MOVZD 0x6 /* move with zero extention i to double */
+#define FMT7_MOVXD 0x7 /* move with sign-extention i to double */
+#define FMT7_MUL 0x8 /* multiply */
+#define FMT7_MEI 0x9 /* multiply extended integer */
+#define FMT7_UNDEF 0xa /* undefined */
+#define FMT7_DEI 0xb /* divide extended integer */
+#define FMT7_QUO 0xc /* quotient */
+#define FMT7_REM 0xd /* remainder */
+#define FMT7_MOD 0xe /* modulus */
+#define FMT7_DIV 0xf /* divide */
+
+STATIC
+char fmt8_table[8][6] = {
+ "ext", /* extract field */
+ "cvtp", /* convert to bit pointer */
+ "ins", /* insert field */
+ "check", /* bounds check */
+ "index", /* calculate index */
+ "ffs", /* find first set bit */
+ "mov", /* move supervisor to/from user space */
+ "??8??" /* undefined */
+};
+
+#define FMT8_EXT 0x0 /* extract field */
+#define FMT8_CVTP 0x1 /* convert to bit pointer */
+#define FMT8_INS 0x2 /* insert field */
+#define FMT8_CHECK 0x3 /* bounds check */
+#define FMT8_INDEX 0x4 /* calculate index */
+#define FMT8_FFS 0x5 /* find first set bit */
+#define FMT8_MOV 0x6 /* move supervisor to/from user space */
+#define FMT8_UNDEF 0x7 /* undefined */
+
+STATIC
+char fmt9_table[8][6] = {
+ "mov", /* move converting integer to floating point */
+ "lfsr", /* load floating-point status register */
+ "movlf", /* move long floating to floating */
+ "movfl", /* move floating to long floating */
+ "round", /* round floating to integer */
+ "trunc", /* truncate floating to integer */
+ "sfsr", /* store floating-point status register */
+ "floor" /* floor floating to integer */
+};
+
+#define FMT9_MOV 0x0 /* move converting integer to floating point */
+#define FMT9_LFSR 0x1 /* load floating-point status register */
+#define FMT9_MOVLF 0x2 /* move long floating to floating */
+#define FMT9_MOVFL 0x3 /* move floating to long floating */
+#define FMT9_ROUND 0x4 /* round floating to integer */
+#define FMT9_TRUNC 0x5 /* truncate floating to integer */
+#define FMT9_SFSR 0x6 /* store floating-point status register */
+#define FMT9_FLOOR 0x7 /* floor floating to integer */
+
+#define NOP 0xff; /* catch all nop instruction */
+
+STATIC
+char fmt11_table[16][4] = {
+ "add", /* add floating */
+ "mov", /* move floating */
+ "cmp", /* compare floating */
+ "?f?", /* undefined */
+ "sub", /* subtract floating */
+ "neg", /* negate floating */
+ "?f?", /* undefined */
+ "?f?", /* undefined */
+ "div", /* divide floating */
+ "?f?", /* undefined */
+ "?f?", /* undefined */
+ "?f?", /* undefined */
+ "mul", /* multiply floating */
+ "abs", /* absolute value floating */
+ "?f?", /* undefined */
+ "?f?" /* undefined */
+};
+
+STATIC
+char fmt12_table[16][6] = {
+ "?f?", /* 0 undefined */
+ "?f?", /* 1 undefined */
+ "poly", /* 2 */
+ "dot", /* 3 */
+ "scalb", /* 4 */
+ "logb", /* 5 */
+ "?f?", /* 6 undefined */
+ "?f?", /* 7 undefined */
+ "?f?", /* 8 undefined */
+ "?f?", /* 9 undefined */
+ "?f?", /* 10 undefined */
+ "?f?", /* 11 undefined */
+ "?f?", /* 12 undefined */
+ "?f?", /* 13 undefined */
+ "?f?", /* 14 undefined */
+ "?f?", /* 15 undefined */
+};
+
+#define FMT11_ADD 0x0 /* add floating */
+#define FMT11_MOV 0x1 /* move floating */
+#define FMT11_CMP 0x2 /* compare floating */
+#define FMT11_UNDEF1 0x3 /* undefined */
+#define FMT11_SUB 0x4 /* subtract floating */
+#define FMT11_NEG 0x5 /* negate floating */
+#define FMT11_UNDEF2 0x6 /* undefined */
+#define FMT11_UNDEF3 0x7 /* undefined */
+#define FMT11_DIV 0x8 /* divide floating */
+#define FMT11_UNDEF4 0x9 /* undefined */
+#define FMT11_UNDEF5 0xa /* undefined */
+#define FMT11_UNDEF6 0xb /* undefined */
+#define FMT11_MUL 0xc /* multiply floating */
+#define FMT11_ABS 0xd /* absolute value floating */
+#define FMT11_UNDEF7 0xe /* undefined */
+#define FMT11_UNDEF8 0xf /* undefined */
+
+#define FMT12_POLY 2
+#define FMT12_DOT 3
+#define FMT12_SCALB 4
+#define FMT12_LOGB 5
+
+STATIC
+char fmt14_table[][6] = {
+ "rdval", /* validate address for reading */
+ "wrval", /* validate address for writing */
+ "lmr", /* load memory managemnet register */
+ "smr", /* store memory management register */
+ "???",
+ "???",
+ "???",
+ "???",
+ "???",
+ "cinv",
+};
+
+#define FMT14_RDVAL 0x0 /* validate address for reading */
+#define FMT14_WRVAL 0x1 /* validate address for writing */
+#define FMT14_LMR 0x2 /* load memory managemnet register */
+#define FMT14_SMR 0x3 /* store memory management register */
+#define FMT14_CINV 0x9 /* cache invalidate */
+
+/*
+ * These are indices into regTable. Keep in sync!
+ */
+#define REG_R0 0 /* General Register 0 */
+#define REG_F0 8 /* Floating Point 0 */
+#define REG_PC 32 /* Program counter */
+#define REG_USP (REG_PC+1)
+#define REG_ISP (REG_PC+2)
+#define REG_FP (REG_PC+3)
+#define REG_SB (REG_PC+4)
+#define REG_INTBASE (REG_PC+5)
+#define REG_MOD (REG_PC+6)
+#define REG_PSR (REG_PC+7)
+#define REG_UPSR (REG_PC+8)
+#define REG_DCR (REG_PC+9)
+#define REG_DSR (REG_PC+10)
+#define REG_CAR (REG_PC+11)
+#define REG_BPC (REG_PC+12)
+#define REG_CFG (REG_PC+13)
+
+#define REG_PTB0 46
+#define REG_PTB1 (REG_PTB0+1)
+#define REG_IVAR0 (REG_PTB0+2)
+#define REG_IVAR1 (REG_PTB0+3)
+#define REG_TEAR (REG_PTB0+4)
+#define REG_MCR (REG_PTB0+5)
+#define REG_MSR (REG_PTB0+6)
+
+#define REG_FSR 53
+#define REG_SP (REG_FSR+1)
+#define REG_NIL (REG_FSR+2)
+
+struct regTable {
+ char *name;
+};
+
+STATIC
+struct regTable regTable[] = {
+ {"r0"}, /* General Register 0 */
+ {"r1"}, /* General Register 1 */
+ {"r2"}, /* General Register 2 */
+ {"r3"}, /* General Register 3 */
+ {"r4"}, /* General Register 4 */
+ {"r5"}, /* General Register 5 */
+ {"r6"}, /* General Register 6 */
+ {"r7"}, /* General Register 7 */
+ {"f0"}, /* Floating Point 0 */
+ {"f1"}, /* Floating Point 1 */
+ {"f2"}, /* Floating Point 2 */
+ {"f3"}, /* Floating Point 3 */
+ {"f4"}, /* Floating Point 4 */
+ {"f5"}, /* Floating Point 5 */
+ {"f6"}, /* Floating Point 6 */
+ {"f7"}, /* Floating Point 7 */
+ {"l1l"}, /* Floating Point L1 */
+ {"l1h"}, /* Floating Point L1 */
+ {"l3l"}, /* Floating Point L3 */
+ {"l3h"}, /* Floating Point L3 */
+ {"l5l"}, /* Floating Point L5 */
+ {"l5h"}, /* Floating Point L5 */
+ {"l7l"}, /* Floating Point L7 */
+ {"l7h"}, /* Floating Point L7 */
+ {"l0"},
+ {"l1"},
+ {"l2"},
+ {"l3"},
+ {"l4"},
+ {"l5"},
+ {"l6"},
+ {"l7"},
+ {"pc"}, /* Program counter */
+ {"usp"}, /* 532 */
+ {"isp"}, /* 532 */
+ {"fp"}, /* Frame Pointer */
+ {"sb"}, /* Static Base */
+ {"intbase"}, /* Interrupt Base */
+ {"mod"}, /* Module Register */
+ {"psr"}, /* Processor Status */
+ {"upsr"}, /* Processor Status */
+ {"dcr"}, /* 532 */
+ {"dsr"}, /* 532 */
+ {"car"}, /* 532 */
+ {"bpc"}, /* 532 */
+ {"cfg"}, /* 532 */
+ {"ptb0"}, /* Page Table Base 0 */
+ {"ptb1"}, /* Page Table Base 1 */
+ {"ivar0"}, /* 532 */
+ {"ivar1"}, /* 532 */
+ {"tear"}, /* 532 */
+ {"mcr"}, /* 532 */
+ {"msr"}, /* Memory Management Status */
+ {"fsr"}, /* Floating Point Status */
+ {"sp"}, /* x(x(sp)) adr mode */
+ {"???"}, /* unknown reg */
+};
+
+#define REGTABLESZ ((sizeof regTable) / (sizeof (struct regTable)))
+
+#define GetShort(x, y) ((((x) & 0x80) >> 7) + (((y) & 0x7) << 1))
+#define GetGen0(x) (((x) & 0xf8) >> 3)
+#define GetGen1(x,y) ((((x) & 0xc0) >> 6) + (((y) & 0x7) << 2))
+#define GetGenSI(x) (int)((((x) & 0x1c) == 0x1c) ? (((x) & 0x3) + 1) : 0)
+#define ScaledFields(input, reg, gen) \
+ ((reg) = ((input) & 0x7), \
+ (gen) = (((input) & 0xf8) >> 3))
+
+STATIC unsigned char cpuRegTable [] = {
+ REG_UPSR, REG_DCR, REG_BPC, REG_DSR,
+ REG_CAR, REG_NIL, REG_NIL, REG_NIL,
+ REG_FP, REG_SP, REG_SB, REG_USP,
+ REG_CFG, REG_PSR, REG_INTBASE, REG_MOD,
+};
+
+STATIC unsigned char mmuRegTable [] = {
+ REG_NIL, REG_NIL, REG_NIL, REG_NIL,
+ REG_NIL, REG_NIL, REG_NIL, REG_NIL,
+ REG_NIL, REG_MCR, REG_MSR, REG_TEAR,
+ REG_PTB0, REG_PTB1,REG_IVAR0, REG_IVAR1,
+};
+
+void db_reverseBits();
+
+#define get_byte(l,t) ((unsigned char) db_get_task_value(l, 1, FALSE, t))
+
+void db_formatOperand(operand, loc, task)
+ struct operand *operand;
+ db_addr_t loc;
+ task_t task;
+{
+ int need_comma, i, mask, textlen;
+
+ switch (operand->o_mode) {
+
+ case AMODE_REG:
+ case AMODE_AREG:
+ case AMODE_MREG:
+ db_printf("%s", regTable[operand->o_reg0].name);
+ break;
+
+ case AMODE_MREL:
+ db_task_printsym((db_addr_t) operand->o_disp1,
+ DB_STGY_ANY, task);
+ db_printf("(");
+ db_task_printsym((db_addr_t) operand->o_disp0,
+ DB_STGY_ANY, task);
+ db_printf("(%s))",regTable[operand->o_reg0].name);
+ break;
+
+ case AMODE_QUICK:
+ case AMODE_IMM:
+ db_task_printsym((db_addr_t) operand->o_disp0,
+ DB_STGY_ANY, task);
+ break;
+
+ case AMODE_ABS:
+ db_printf("@");
+ db_task_printsym((db_addr_t) operand->o_disp0,
+ DB_STGY_ANY, task);
+ break;
+
+ case AMODE_EXT:
+ db_printf("ext(%ld)", operand->o_disp0);
+ if (operand->o_disp1)
+ db_printf("+%ld", operand->o_disp1);
+ break;
+
+ case AMODE_TOS:
+ db_printf("tos");
+ break;
+
+ case AMODE_RREL:
+ case AMODE_MSPC:
+ db_task_printsym((db_addr_t) operand->o_disp0,
+ DB_STGY_XTRN, task);
+ db_printf("(%s)",regTable[operand->o_reg0].name);
+ break;
+
+ case AMODE_REGLIST:
+ db_printf("[");
+ need_comma = 0;
+ for (i = 0; i < 8; i++) {
+ mask = (1<<i);
+ if (operand->o_reg0&mask) {
+ if (need_comma)
+ db_printf(",");
+ db_printf("r%d", i);
+ need_comma = 1;
+ }
+ }
+ db_printf("]");
+ break;
+
+ case AMODE_BLISTB:
+ i = 7;
+ goto bitlist;
+
+ case AMODE_BLISTW:
+ i = 15;
+ goto bitlist;
+
+ case AMODE_BLISTD:
+ i = 31;
+
+bitlist:
+ db_printf("B'");
+ for (; i >= 0; i--, textlen++) {
+ mask = (1<<i);
+ if (operand->o_disp0&mask)
+ db_printf("1");
+ else
+ db_printf("0");
+ }
+ break;
+
+ case AMODE_SOPT:
+ i = operand->o_disp0>>1;
+ db_printf("%s", sopt_table[i]);
+ break;
+
+ case AMODE_CFG:
+ db_printf("[");
+ need_comma = 0;
+ for (i = 0;i < 3;i++) {
+ mask = 1<<i;
+ if (operand->o_disp0&mask) {
+ if (need_comma)
+ db_printf(",");
+ db_printf("%s",cfg_table[i]);
+ need_comma = 1;
+ }
+ }
+ db_printf("]");
+ break;
+
+ case AMODE_CINV:
+ { /* print cache invalidate flags */
+ char *p;
+ int i, need_comma = 0;
+
+ for (i = 4, p = "AID"; i; i >>= 1, ++p)
+ if (i & operand->o_disp0) {
+ if (need_comma)
+ db_printf(",");
+ db_printf("%c",*p);
+ need_comma = 1;
+ }
+ }
+ break;
+
+ case AMODE_INVALID:
+ db_printf("?");
+ break;
+ }
+ if (operand->o_iscale) {
+ db_printf("[r%d:", operand->o_ireg);
+ db_printf("%s]",scale_table[operand->o_iscale]);
+ }
+}
+
+void db_formatAsm(insn, loc, task, altfmt)
+ struct insn *insn;
+ db_addr_t loc;
+ task_t task;
+ boolean_t altfmt;
+{
+ int i, j;
+
+ db_printf("%s\t", &insn->i_monic[0]);
+
+ for (i = 0; i < 4 && insn->i_opr[i].o_mode != AMODE_NONE; i++) {
+ if (i != 0) {
+ db_printf(",");
+ }
+ db_formatOperand(&insn->i_opr[i], loc, task);
+ }
+ j = 0;
+ for (i = 0; i < 4 && insn->i_opr[i].o_mode != AMODE_NONE; i++) {
+ if (insn->i_opr[i].o_mode == AMODE_MSPC ||
+ insn->i_opr[i].o_mode == AMODE_RREL) {
+ register struct db_variable *regp;
+ db_expr_t value;
+
+ if (strcmp(db_regs->name, "pc") == 0) {
+ value = loc;
+ } else {
+ if (!altfmt) {
+ continue;
+ }
+ for (regp = db_regs; regp < db_eregs; regp++) {
+ if (strcmp(regp->name,
+ regTable[insn->
+ i_opr[i].o_reg0].
+ name) == 0) {
+ break;
+ }
+ }
+ db_read_write_variable(regp, &value,
+ DB_VAR_GET, 0);
+ }
+ if (j != 0) {
+ db_printf(",");
+ } else {
+ db_printf("\t<");
+ }
+ db_task_printsym((db_addr_t)
+ insn->i_opr[i].o_disp0 + value,
+ DB_STGY_XTRN, task);
+ j++;
+ }
+ }
+ if (j != 0) {
+ db_printf(">");
+ }
+}
+
+void db_initInsn (insn)
+ struct insn *insn;
+{
+ insn->i_opr[0].o_mode = AMODE_NONE;
+ insn->i_opr[0].o_iscale = 0;
+ insn->i_opr[1].o_mode = AMODE_NONE;
+ insn->i_opr[1].o_iscale = 0;
+ insn->i_opr[2].o_mode = AMODE_NONE;
+ insn->i_opr[2].o_iscale = 0;
+ insn->i_opr[3].o_mode = AMODE_NONE;
+ insn->i_opr[3].o_iscale = 0;
+}
+
+int db_disp(loc, result, task)
+ db_addr_t loc;
+ long *result;
+ task_t task;
+{
+ unsigned int b;
+
+ b = get_byte(loc, task);
+ if (!(b & 0x80)) { /* one byte */
+ *result = ((b & 0x40) ? 0xffffffc0L : 0) | (b & 0x3f);
+ return(1);
+ } else if (!(b & 0x40)) { /* two byte */
+ *result =
+ ((b & 0x20) ? 0xffffe000L : 0) | ((b & 0x1f) << 8);
+ b = get_byte(loc + 1, task);
+ *result |= b;
+ return 2;
+ } else { /* four byte */
+ *result =
+ ((b & 0x20) ? 0xe0000000L : 0) | /* bug fix 8/28 */
+ ((b & 0x1f) << 24); /* bug fix 7/21 */
+ b = get_byte(loc + 1, task);
+ *result |= (b << 16);
+ b = get_byte(loc + 2, task);
+ *result |= (b << 8);
+ b = get_byte(loc + 3, task);
+ *result |= b;
+ return(4);
+ }
+}
+
+int db_decode_operand(loc, byte, operand, iol, task)
+ db_addr_t loc;
+ unsigned char byte;
+ struct operand *operand;
+ unsigned char iol;
+ task_t task;
+{
+ register int i, consumed = 0;
+ unsigned long value;
+
+ switch (byte) {
+
+ case GEN_R0:
+ case GEN_R1:
+ case GEN_R2:
+ case GEN_R3:
+ case GEN_R4:
+ case GEN_R5:
+ case GEN_R6:
+ case GEN_R7:
+ operand->o_mode = AMODE_REG;
+ operand->o_reg0 = REG_R0 + byte;
+ break;
+
+ case GEN_RR0:
+ case GEN_RR1:
+ case GEN_RR2:
+ case GEN_RR3:
+ case GEN_RR4:
+ case GEN_RR5:
+ case GEN_RR6:
+ case GEN_RR7:
+ operand->o_mode = AMODE_RREL;
+ operand->o_reg0 = REG_R0 + (byte&0x7);
+ goto one_disp;
+
+ case GEN_FRMR:
+ operand->o_reg0 = REG_FP;
+ operand->o_mode = AMODE_MREL;
+ goto two_disp;
+
+ case GEN_SPMR:
+ operand->o_reg0 = REG_SP;
+ operand->o_mode = AMODE_MREL;
+ goto two_disp;
+
+ case GEN_SBMR:
+ operand->o_reg0 = REG_SB;
+ operand->o_mode = AMODE_MREL;
+ goto two_disp;
+
+ case GEN_IMM:
+ operand->o_mode = AMODE_IMM;
+ /* fix to sign extend */
+ value = (get_byte(loc, task) & 0x80)? 0xffffffff: 0;
+ for (i = 0; i < iol; i++) {
+ value = (value << 8) + get_byte(loc + i, task);
+ }
+ operand->o_disp0 = value;
+ consumed = iol;
+ break;
+
+ case GEN_ABS:
+ operand->o_mode = AMODE_ABS;
+ goto one_disp;
+
+ case GEN_EXT:
+ operand->o_mode = AMODE_EXT;
+ goto two_disp;
+
+ case GEN_TOS:
+ operand->o_mode = AMODE_TOS;
+ break;
+
+ case GEN_FRM:
+ operand->o_mode = AMODE_MSPC;
+ operand->o_reg0 = REG_FP;
+ goto one_disp;
+
+ case GEN_SPM:
+ operand->o_mode = AMODE_MSPC;
+ operand->o_reg0 = REG_SP;
+ goto one_disp;
+
+ case GEN_SBM:
+ operand->o_mode = AMODE_MSPC;
+ operand->o_reg0 = REG_SB;
+ goto one_disp;
+
+ case GEN_PCM:
+ operand->o_mode = AMODE_MSPC;
+ operand->o_reg0 = REG_PC;
+ goto one_disp;
+
+ default:
+ operand->o_mode = AMODE_INVALID;
+ break;
+
+two_disp:
+ consumed = db_disp(loc, &operand->o_disp0, task);
+ consumed += db_disp(loc + consumed, &operand->o_disp1, task);
+ break;
+
+one_disp:
+ consumed = db_disp(loc, &operand->o_disp0, task);
+ break;
+ }
+ return(consumed);
+}
+
+int db_gen(insn, loc, mask, byte0, byte1, task)
+ struct insn *insn;
+ db_addr_t loc;
+ int mask; /* 1 to get gen1, 2 to get gen2 */
+ unsigned char byte0, byte1;
+ task_t task;
+{
+ int opr = 0, opr2, consumed = 0;
+ unsigned char gen0, gen1;
+
+ gen0 = GetGen0(byte1); /* mask and shift gen fields */
+ gen1 = GetGen1(byte0, byte1); /* gen0 is really 1, gen1 is 2 */
+
+ while (insn->i_opr[opr].o_mode != AMODE_NONE)
+ opr++;
+
+ if (mask & 0x1) {
+ if (insn->i_opr[opr].o_iscale = GetGenSI(gen0)) {
+ ScaledFields(get_byte(loc, task),
+ insn->i_opr[opr].o_ireg, gen0);
+ consumed++;
+ }
+ opr2 = opr + 1;
+ } else {
+ opr2 = opr;
+ }
+
+ if (mask & 0x2 &&
+ (insn->i_opr[opr2].o_iscale = GetGenSI(gen1))) {
+ ScaledFields(get_byte(loc + consumed, task),
+ insn->i_opr[opr2].o_ireg, gen1);
+ consumed++;
+ }
+
+ if (mask & 0x1) {
+ consumed += db_decode_operand(loc + consumed, gen0,
+ &insn->i_opr[opr], insn->i_iol,
+ task);
+ }
+ if (mask & 0x2) {
+ consumed += db_decode_operand(loc + consumed, gen1,
+ &insn->i_opr[opr2], insn->i_iol,
+ task);
+ }
+ return(consumed);
+}
+
+int db_dasm_ns32k(insn, loc, task)
+ struct insn *insn;
+ db_addr_t loc; /* start addr of this insn */
+ task_t task;
+{
+ unsigned char byte0, byte1, byte2;
+ int i, j;
+ int consumed;
+
+ insn->i_iol = IOL_NONE; /* Don't assume any operand length */
+ byte0 = get_byte(loc, task); /* look at first byte in insn */
+ consumed = 1;
+ i = byte0 / 2; /* get index into fmttab */
+ if (byte0 % 2)
+ j = ((fmttab[i] & 0xf0) >> 4);
+ else
+ j = (fmttab[i]) & 0x0f;
+
+ insn->i_format = j; /* set insn type */
+
+ switch (j) {
+ case ITYPE_FMT0:
+ insn->i_op = FMT0_COND(byte0); /* condition code field */
+ insn->i_monic[0] = 'b';
+ insn->i_monic[1] = cond_table[insn->i_op][0];
+ insn->i_monic[2] = cond_table[insn->i_op][1];
+ insn->i_monic[3] = '\0';
+ insn->i_opr[0].o_mode = AMODE_IMM; /* MSPC implied */
+ insn->i_opr[0].o_reg0 = REG_PC;
+ consumed += db_disp(loc + consumed, &insn->i_opr[0].o_disp0,
+ task);
+ insn->i_opr[0].o_disp0 += loc;
+ break;
+
+ case ITYPE_FMT1:
+ insn->i_op = FMT1_OP(byte0);
+ strcpy(insn->i_monic, fmt1_table[insn->i_op]);
+ switch (insn->i_op) {
+ case FMT1_CXP:
+ case FMT1_RXP:
+ case FMT1_RET:
+ case FMT1_RETT:
+ insn->i_opr[0].o_mode = AMODE_IMM;
+ consumed += db_disp(loc + consumed,
+ &insn->i_opr[0].o_disp0, task);
+ break;
+
+ case FMT1_BSR:
+ insn->i_opr[0].o_mode = AMODE_IMM; /* MSPC implied */
+ insn->i_opr[0].o_reg0 = REG_PC;
+ consumed += db_disp(loc + consumed,
+ &insn->i_opr[0].o_disp0, task);
+ insn->i_opr[0].o_disp0 += loc;
+ break;
+
+ case FMT1_SAVE:
+ case FMT1_RESTORE:
+ case FMT1_ENTER:
+ case FMT1_EXIT:
+ insn->i_opr[0].o_mode = AMODE_REGLIST;
+ insn->i_opr[0].o_reg0 = get_byte(loc + consumed, task);
+ consumed++;
+ if (insn->i_op == FMT1_EXIT ||
+ insn->i_op == FMT1_RESTORE) /* WBC bug fix */
+ db_reverseBits (&(insn->i_opr[0].o_reg0));
+ if (insn->i_op == FMT1_ENTER) {
+ /* MSPC implied */
+ insn->i_opr[1].o_mode = AMODE_IMM;
+ insn->i_opr[1].o_reg0 = REG_PC;
+ consumed += db_disp(loc + consumed,
+ &insn->i_opr[1].o_disp0,
+ task);
+ }
+ break;
+ }
+ break;
+
+ case ITYPE_FMT2:
+ byte1 = get_byte(loc + consumed, task);
+ consumed++;
+ insn->i_op = FMT2_OP(byte0);
+ insn->i_iol = IOL(byte0);
+ i = GetShort(byte0, byte1);
+ strcpy(insn->i_monic, fmt2_table[insn->i_op]);
+ switch (insn->i_op) {
+
+ case FMT2_SCOND:
+ strcat(insn->i_monic, cond_table[i]);
+ break;
+
+ case FMT2_ADDQ:
+ case FMT2_CMPQ:
+ case FMT2_ACB:
+ case FMT2_MOVQ:
+ if (i&0x08) { /* negative quick value */
+ insn->i_opr[0].o_disp0 = i;
+ insn->i_opr[0].o_disp0 |= 0xfffffff0;
+ } else {
+ insn->i_opr[0].o_disp0 = i;
+ }
+ insn->i_opr[0].o_mode = AMODE_QUICK;
+ break;
+
+ case FMT2_LPR:
+ case FMT2_SPR:
+ insn->i_opr[0].o_reg0 = cpuRegTable [i];
+ insn->i_opr[0].o_mode = AMODE_AREG;
+ break;
+ }
+ consumed += db_gen(insn, loc + consumed, 0x1, 0, byte1, task);
+ strcat(insn->i_monic, iol_table[insn->i_iol]);
+ if (insn->i_op == FMT2_ACB) {
+ consumed += db_disp(loc + consumed,
+ &insn->i_opr[2].o_disp0, task);
+ insn->i_opr[2].o_disp0 += loc;
+ insn->i_opr[2].o_mode = AMODE_IMM;
+ }
+ break;
+
+ case ITYPE_FMT3:
+ insn->i_format = ITYPE_FMT3;
+ byte1 = get_byte(loc + consumed, task);
+ consumed++;
+ insn->i_op = FMT3_OP(byte1);
+ insn->i_iol = IOL(byte0);
+ strcpy(insn->i_monic, fmt3_table[insn->i_op]);
+ consumed += db_gen(insn, loc + consumed, 0x1, 0, byte1, task);
+ switch (insn->i_op) {
+
+ case FMT3_CXPD:
+ case FMT3_JUMP:
+ case FMT3_JSR:
+ if (insn->i_iol != IOL_DOUBLE)
+ insn->i_format = ITYPE_UNDEF;
+ break;
+
+ case FMT3_BICPSR:
+ case FMT3_BISPSR:
+ if (insn->i_iol == IOL_DOUBLE) {
+ insn->i_format = ITYPE_UNDEF;
+ break;
+ }
+ if (insn->i_opr[0].o_mode == AMODE_IMM) {
+ if (insn->i_iol == IOL_BYTE)
+ insn->i_opr[0].o_mode = AMODE_BLISTB;
+ else
+ insn->i_opr[0].o_mode = AMODE_BLISTW;
+ }
+ /* fall through */
+
+ case FMT3_CASE:
+ case FMT3_ADJSP:
+ strcat(insn->i_monic, iol_table[insn->i_iol]);
+ break;
+
+ case FMT3_UNDEF:
+ insn->i_format = ITYPE_UNDEF;
+ break;
+
+ }
+ break;
+
+ case ITYPE_FMT4:
+ byte1 = get_byte(loc + consumed, task);
+ consumed++;
+ insn->i_op = FMT4_OP(byte0);
+ insn->i_iol = IOL(byte0);
+ strcpy(insn->i_monic, fmt4_table[insn->i_op]);
+ consumed += db_gen(insn, loc + consumed, 0x3, byte0,
+ byte1, task);
+ if (insn->i_op == FMT4_ADDR) {
+ if (insn->i_iol != IOL_DOUBLE)
+ insn->i_format = ITYPE_UNDEF;
+ }
+ else
+ strcat(insn->i_monic, iol_table[insn->i_iol]);
+ break;
+
+ case ITYPE_FMT5:
+ byte1 = get_byte(loc + consumed, task);
+ consumed++;
+ insn->i_op = FMT5_OP(byte1);
+ if (insn->i_op > FMT5_SKPS) {
+ insn->i_format = ITYPE_UNDEF;
+ break;
+ }
+ strcpy(insn->i_monic, fmt5_table[insn->i_op]);
+ byte2 = get_byte(loc + consumed, task);
+ consumed++;
+ insn->i_opr[0].o_disp0 = GetShort(byte1, byte2);
+ insn->i_iol = IOL(byte1);
+ switch (insn->i_op) {
+
+ case FMT5_MOVS:
+ case FMT5_CMPS:
+ case FMT5_SKPS:
+ if (insn->i_opr[0].o_disp0&0x1)
+ strcat(insn->i_monic, "t");
+ else
+ strcat(insn->i_monic,
+ iol_table[insn->i_iol]);
+ insn->i_opr[0].o_mode = AMODE_SOPT;
+ break;
+
+ case FMT5_SETCFG:
+ insn->i_opr[0].o_mode = AMODE_CFG;
+ break;
+ }
+ break;
+
+ case ITYPE_FMT6:
+ byte1 = get_byte(loc + consumed, task);
+ consumed++;
+ byte2 = get_byte(loc + consumed, task);
+ consumed++;
+ insn->i_op = FMT6_OP(byte1);
+ insn->i_iol = IOL(byte1);
+ strcpy(insn->i_monic, fmt6_table[insn->i_op]);
+ strcat(insn->i_monic, iol_table[insn->i_iol]);
+ if (insn->i_op == FMT6_ROT ||
+ insn->i_op == FMT6_ASH ||
+ insn->i_op == FMT6_LSH)
+ {
+ insn->i_iol = 1; /* shift and rotate special case */
+ }
+ if (insn->i_op == FMT6_UNDEF1 ||
+ insn->i_op == FMT6_UNDEF2) {
+ insn->i_format = ITYPE_UNDEF;
+ break;
+ }
+ consumed += db_gen(insn, loc + consumed, 0x3, byte1, byte2,
+ task);
+ break;
+
+ case ITYPE_FMT7:
+ byte1 = get_byte(loc + consumed, task);
+ consumed++;
+ byte2 = get_byte(loc + consumed, task);
+ consumed++;
+ insn->i_op = FMT7_OP(byte1);
+ strcpy(insn->i_monic, fmt7_table[insn->i_op]);
+ insn->i_iol = IOL(byte1);
+ strcat(insn->i_monic, iol_table[insn->i_iol]);
+ consumed += db_gen(insn, loc + consumed, 0x3, byte1, byte2,
+ task);
+ switch (insn->i_op) {
+
+ case FMT7_MOVM:
+ case FMT7_CMPM:
+ consumed += db_disp(loc + consumed,
+ &insn->i_opr[2].o_disp0, task);
+ /* WBC bug fix */
+ insn->i_opr[2].o_mode = AMODE_IMM;
+ break;
+
+ case FMT7_INSS:
+ case FMT7_EXTS:
+ byte2 = get_byte(loc + consumed, task);
+ consumed++;
+ insn->i_opr[2].o_disp0 = ((byte2&0xe0)>>5);
+ insn->i_opr[2].o_mode = AMODE_IMM;
+ insn->i_opr[3].o_disp0 = ((byte2&0x1f) + 1);
+ insn->i_opr[3].o_mode = AMODE_IMM;
+ break;
+
+ case FMT7_MOVZD:
+ case FMT7_MOVXD:
+ strcat(insn->i_monic, "d");
+ break;
+
+ case FMT7_UNDEF:
+ insn->i_format = ITYPE_UNDEF;
+ break;
+ }
+ break;
+
+ case ITYPE_FMT8:
+ byte1 = get_byte(loc + consumed, task);
+ consumed++;
+ byte2 = get_byte(loc + consumed, task);
+ consumed++;
+ insn->i_op = FMT8_OP(byte0, byte1);
+ strcpy(insn->i_monic, fmt8_table[insn->i_op]);
+ insn->i_iol = IOL(byte1);
+ switch (insn->i_op) {
+
+ case FMT8_MOV:
+ if (FMT8_REG(byte1) == FMT8_SU)
+ strcat(insn->i_monic, "su");
+ else if (FMT8_REG(byte1) == FMT8_US)
+ strcat(insn->i_monic, "us");
+ else
+ strcat(insn->i_monic, "??");
+ /* fall through */
+
+ case FMT8_EXT:
+ case FMT8_INS:
+ case FMT8_CHECK:
+ case FMT8_INDEX:
+ case FMT8_FFS:
+ strcat(insn->i_monic, iol_table[insn->i_iol]);
+ /* fall through */
+
+ case FMT8_CVTP:
+ if (insn->i_op != FMT8_FFS && insn->i_op != FMT8_MOV) {
+ insn->i_opr[0].o_reg0 =
+ REG_R0 + FMT8_REG(byte1);
+ insn->i_opr[0].o_mode = AMODE_REG;
+ }
+ consumed += db_gen(insn, loc + consumed, 0x3, byte1,
+ byte2, task);
+ if (insn->i_op == FMT8_EXT ||
+ insn->i_op == FMT8_INS) {
+ consumed += db_disp(loc + consumed,
+ &insn->i_opr[3].o_disp0,
+ task);
+ insn->i_opr[3].o_mode = AMODE_IMM;
+ }
+ break;
+
+ default:
+ insn->i_format = ITYPE_UNDEF;
+ break;
+ }
+ break;
+
+ case ITYPE_FMT9:
+ byte1 = get_byte(loc + consumed, task);
+ consumed++;
+ byte2 = get_byte(loc + consumed, task);
+ consumed++;
+ insn->i_op = FMT9_OP(byte1);
+ strcpy(insn->i_monic, fmt9_table[insn->i_op]);
+ insn->i_iol = IOL(byte1);
+ i = FMT9_F(byte1);
+ switch (insn->i_op) {
+
+ case FMT9_MOV:
+ strcat(insn->i_monic, iol_table[insn->i_iol]);
+ strcat(insn->i_monic, fol_table[i]);
+ consumed += db_gen(insn, loc + consumed, 0x3, byte1,
+ byte2, task);
+ if (insn->i_opr[1].o_mode == AMODE_REG)
+ insn->i_opr[1].o_reg0 =
+ REG_F0 + (insn->i_opr[1].o_reg0 - REG_R0);
+ break;
+
+ case FMT9_LFSR:
+ consumed += db_gen(insn, loc + consumed, 0x1,
+ byte1, byte2, task);
+ break;
+
+ case FMT9_SFSR:
+ consumed += db_gen(insn, loc + consumed, 0x2,
+ byte1, byte2, task);
+ break;
+
+ case FMT9_MOVLF:
+ case FMT9_MOVFL:
+ consumed += db_gen(insn, loc + consumed, 0x3, byte1,
+ byte2, task);
+ if (insn->i_opr[0].o_mode == AMODE_REG)
+ insn->i_opr[0].o_reg0 =
+ REG_F0 + (insn->i_opr[0].o_reg0 - REG_R0);
+ if (insn->i_opr[1].o_mode == AMODE_REG)
+ insn->i_opr[1].o_reg0 =
+ REG_F0 + (insn->i_opr[1].o_reg0 - REG_R0);
+ break;
+
+ case FMT9_ROUND:
+ case FMT9_TRUNC:
+ case FMT9_FLOOR:
+ strcat(insn->i_monic, fol_table[i]);
+ strcat(insn->i_monic, iol_table[insn->i_iol]);
+ consumed += db_gen(insn, loc + consumed, 0x3, byte1,
+ byte2, task);
+ if (insn->i_opr[0].o_mode == AMODE_REG)
+ insn->i_opr[0].o_reg0 =
+ REG_F0 + (insn->i_opr[0].o_reg0 - REG_R0);
+ break;
+ }
+ break;
+
+ case ITYPE_NOP:
+ insn->i_op = NOP;
+ strcpy(insn->i_monic, "nop");
+ break;
+
+ case ITYPE_FMT11:
+ byte1 = get_byte(loc + consumed, task);
+ consumed++;
+ byte2 = get_byte(loc + consumed, task);
+ consumed++;
+ insn->i_op = FMT11_OP(byte1);
+ switch (insn->i_op) {
+
+ case FMT11_ADD:
+ case FMT11_MOV:
+ case FMT11_CMP:
+ case FMT11_SUB:
+ case FMT11_NEG:
+ case FMT11_DIV:
+ case FMT11_MUL:
+ case FMT11_ABS:
+ strcpy(insn->i_monic, fmt11_table[insn->i_op]);
+ strcat(insn->i_monic, fol_table[FMT11_F(byte1)]);
+ consumed += db_gen(insn, loc + consumed, 0x3, byte1,
+ byte2, task);
+ if (insn->i_opr[0].o_mode == AMODE_REG)
+ insn->i_opr[0].o_reg0 =
+ REG_F0 + (insn->i_opr[0].o_reg0 - REG_R0);
+ if (insn->i_opr[1].o_mode == AMODE_REG)
+ insn->i_opr[1].o_reg0 =
+ REG_F0 + (insn->i_opr[1].o_reg0 - REG_R0);
+ break;
+
+ default:
+ insn->i_format = ITYPE_UNDEF;
+ break;
+
+ }
+ break;
+
+ case ITYPE_FMT12:
+ byte1 = get_byte(loc + consumed, task);
+ consumed++;
+ byte2 = get_byte(loc + consumed, task);
+ consumed++;
+ insn->i_op = FMT12_OP(byte1);
+ switch (insn->i_op) {
+
+ case FMT12_POLY:
+ case FMT12_DOT:
+ case FMT12_SCALB:
+ case FMT12_LOGB:
+ strcpy(insn->i_monic, fmt12_table[insn->i_op]);
+ strcat(insn->i_monic, fol_table[FMT12_F(byte1)]);
+ consumed += db_gen(insn, loc + consumed, 0x3, byte1,
+ byte2, task);
+ if (insn->i_opr[0].o_mode == AMODE_REG)
+ insn->i_opr[0].o_reg0 =
+ REG_F0 + (insn->i_opr[0].o_reg0 - REG_R0);
+ if (insn->i_opr[1].o_mode == AMODE_REG)
+ insn->i_opr[1].o_reg0 =
+ REG_F0 + (insn->i_opr[1].o_reg0 - REG_R0);
+ break;
+
+ default:
+ insn->i_format = ITYPE_UNDEF;
+ break;
+
+ }
+ break;
+
+ case ITYPE_UNDEF:
+ strcpy(insn->i_monic, "???");
+ break;
+
+ case ITYPE_FMT14:
+ byte1 = get_byte(loc + consumed, task);
+ consumed++;
+ byte2 = get_byte(loc + consumed, task);
+ consumed++;
+ insn->i_op = FMT14_OP(byte1);
+ insn->i_iol = 4;
+ strcpy(insn->i_monic, fmt14_table[insn->i_op]);
+ switch (insn->i_op) {
+
+ case FMT14_CINV:
+ insn->i_opr[0].o_disp0 = GetShort(byte1, byte2);
+ insn->i_opr[0].o_mode = AMODE_CINV;
+ consumed += db_gen(insn, loc + consumed, 0x1,
+ byte1/* was 0*/, byte2, task);
+ break;
+
+ case FMT14_LMR:
+ case FMT14_SMR:
+ insn->i_opr[0].o_reg0 =
+ mmuRegTable[GetShort(byte1, byte2)];
+ insn->i_opr[0].o_mode = AMODE_REG;
+ /* fall through */
+
+ case FMT14_RDVAL:
+ case FMT14_WRVAL:
+ consumed += db_gen(insn, loc + consumed, 0x1,
+ byte1/* was 0*/, byte2, task);
+ break;
+ }
+ break;
+
+ default:
+ insn->i_format = ITYPE_UNDEF;
+ strcpy(insn->i_monic, "???");
+ break;
+ }
+ return(consumed);
+}
+
+/*
+ * Reverse the order of the bits in the LS byte of *ip.
+ */
+void db_reverseBits (ip)
+ int *ip;
+{
+ int i, src, dst;
+
+ src = *ip;
+ dst = 0;
+ for (i = 0; i < 8; ++i) {
+ dst = (dst << 1) | (src & 1);
+ src >>= 1;
+ }
+ *ip = dst;
+}
+
+/*
+ * Disassemble instruction at 'loc'. 'altfmt' specifies an
+ * (optional) alternate format. Return address of start of
+ * next instruction.
+ */
+db_addr_t
+db_disasm(loc, altfmt, task)
+ db_addr_t loc;
+ boolean_t altfmt;
+ task_t task;
+{
+ int ate;
+ struct insn insn;
+
+ db_initInsn(&insn);
+ ate = db_dasm_ns32k(&insn, loc, task);
+ if (altfmt) {
+ int i;
+
+ for(i = 0; i < ate; i++) {
+ db_printf("%02x",
+ db_get_task_value(loc + i, 1, FALSE,
+ task) & 0xff);
+ }
+ if (i < 4)
+ db_printf("\t");
+ db_printf("\t");
+ }
+ db_formatAsm(&insn, loc, task, altfmt);
+ db_printf("\n");
+ return loc + ate;
+}
diff --git a/sys/arch/pc532/pc532/db_interface.c b/sys/arch/pc532/pc532/db_interface.c
new file mode 100644
index 00000000000..f22be4739fa
--- /dev/null
+++ b/sys/arch/pc532/pc532/db_interface.c
@@ -0,0 +1,436 @@
+/* $NetBSD: db_interface.c,v 1.3 1995/04/10 13:15:43 mycroft Exp $ */
+
+/*
+ * Mach Operating System
+ * Copyright (c) 1992 Carnegie Mellon University
+ * Copyright (c) 1992 Helsinki University of Technology
+ * 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 AND HELSINKI UNIVERSITY OF TECHNOLOGY ALLOW FREE USE
+ * OF THIS SOFTWARE IN ITS "AS IS" CONDITION. CARNEGIE MELLON AND
+ * HELSINKI UNIVERSITY OF TECHNOLOGY DISCLAIM 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 Mellon
+ * the rights to redistribute these changes.
+ */
+/*
+ * File: ns532/db_interface.c
+ * Author: Tero Kivinen, Helsinki University of Technology 1992.
+ *
+ * Interface to new kernel debugger.
+ */
+
+#include <sys/reboot.h>
+#include <vm/pmap.h>
+
+#include <ns532/thread.h>
+#include <ns532/db_machdep.h>
+#include <ns532/trap.h>
+#include <ns532/setjmp.h>
+#include <ns532/machparam.h>
+#include <mach/vm_param.h>
+#include <vm/vm_map.h>
+#include <kern/thread.h>
+#include <kern/task.h>
+#include <ddb/db_task_thread.h>
+
+int db_active = 0;
+
+/*
+ * Received keyboard interrupt sequence.
+ */
+void
+kdb_kbd_trap(regs)
+ struct ns532_saved_state *regs;
+{
+ if (db_active == 0) {
+ printf("\n\nkernel: keyboard interrupt\n");
+ kdb_trap(-1, 0, regs);
+ }
+}
+
+extern char * trap_type[];
+extern int TRAP_TYPES;
+
+/*
+ * Print trap reason.
+ */
+void
+kdbprinttrap(type, code)
+ int type, code;
+{
+ printf("kernel: ");
+ if (type > TRAP_TYPES)
+ printf("type %d", type);
+ else
+ printf("%s", trap_type[type]);
+ printf(" trap, code=%x\n", code);
+}
+
+/*
+ * kdb_trap - field a TRACE or BPT trap
+ */
+
+extern jmp_buf_t *db_recover;
+
+int db_active_ipl;
+
+kdb_trap(type, code, regs)
+ int type, code;
+ register struct ns532_saved_state *regs;
+{
+ int s;
+
+ s = splsched();
+ db_active_ipl = s;
+
+ switch (type) {
+ case T_BPT: /* breakpoint */
+ case T_WATCHPOINT: /* watchpoint */
+ case T_TRC: /* trace step */
+ case T_DBG: /* hardware debug trap */
+ case -1: /* keyboard interrupt */
+ break;
+
+ default:
+ if (db_recover) {
+ db_printf("Caught ");
+ if (type > TRAP_TYPES)
+ db_printf("type %d", type);
+ else
+ db_printf("%s", trap_type[type]);
+ db_printf(" trap, code = %x, pc = %x\n",
+ code, regs->pc);
+ db_error("");
+ /*NOTREACHED*/
+ }
+ kdbprinttrap(type, code);
+ }
+
+ /* Should switch to kdb's own stack here. */
+
+ ddb_regs = *regs;
+
+ db_active++;
+ cnpollc(TRUE);
+ db_task_trap(type, code, (DDB_REGS->psr & PSR_U) == 0);
+ cnpollc(FALSE);
+ db_active--;
+
+ if ((type = T_BPT) &&
+ (db_get_task_value(PC_REGS(DDB_REGS), BKPT_SIZE, FALSE, TASK_NULL)
+ == BKPT_INST))
+ PC_REGS(DDB_REGS) += BKPT_SIZE;
+
+ *regs = ddb_regs;
+ (void) splx(s);
+ return (1);
+}
+
+int
+db_user_to_kernel_address(task, addr, kaddr, flag)
+ task_t task;
+ vm_offset_t addr;
+ unsigned *kaddr;
+ int flag;
+{
+ register pt_entry_t *ptp;
+
+ ptp = pmap_pte(task->map->pmap, addr);
+ if (ptp == PT_ENTRY_NULL || (*ptp & NS532_PTE_VALID) == 0) {
+ if (flag) {
+ db_printf("\nno memory is assigned to address %08x\n",
+ addr);
+ db_error(0);
+ /* NOTREACHED */
+ }
+ return(-1);
+ }
+ *kaddr = (unsigned)ptetokv(*ptp) + (addr & (NS532_PGBYTES-1));
+ return(0);
+}
+
+/*
+ * Read bytes from kernel address space for debugger.
+ */
+
+void
+db_read_bytes(addr, size, data, task)
+ vm_offset_t addr;
+ register int size;
+ register char *data;
+ task_t task;
+{
+ register char *src;
+ register int n;
+ unsigned kern_addr;
+
+ src = (char *)addr;
+ if (addr >= VM_MIN_KERNEL_ADDRESS || task == TASK_NULL) {
+ if (task == TASK_NULL)
+ task = db_current_task();
+ while (--size >= 0) {
+ if (addr++ < VM_MIN_KERNEL_ADDRESS &&
+ task == TASK_NULL) {
+ db_printf("\nbad address %x\n", addr);
+ db_error(0);
+ /* NOTREACHED */
+ }
+ *data++ = *src++;
+ }
+ return;
+ }
+ while (size > 0) {
+ if (db_user_to_kernel_address(task, addr, &kern_addr, 1) < 0)
+ return;
+ src = (char *)kern_addr;
+ n = ns532_trunc_page(addr + NS532_PGBYTES) - addr;
+ if (n > size)
+ n = size;
+ size -= n;
+ addr += n;
+ while (--n >= 0)
+ *data++ = *src++;
+ }
+}
+
+/*
+ * Write bytes to kernel address space for debugger.
+ */
+void
+db_write_bytes(addr, size, data, task)
+ vm_offset_t addr;
+ register int size;
+ register char *data;
+ task_t task;
+{
+ register char *dst;
+
+ register pt_entry_t *ptep0 = 0;
+ pt_entry_t oldmap0 = 0;
+ vm_offset_t addr1;
+ register pt_entry_t *ptep1 = 0;
+ pt_entry_t oldmap1 = 0;
+ extern char etext;
+ void db_write_bytes_user_space();
+
+ if ((addr < VM_MIN_KERNEL_ADDRESS) ^
+ ((addr + size) <= VM_MIN_KERNEL_ADDRESS)) {
+ db_error("\ncannot write data into mixed space\n");
+ /* NOTREACHED */
+ }
+ if (addr < VM_MIN_KERNEL_ADDRESS) {
+ if (task) {
+ db_write_bytes_user_space(addr, size, data, task);
+ return;
+ } else if (db_current_task() == TASK_NULL) {
+ db_printf("\nbad address %x\n", addr);
+ db_error(0);
+ /* NOTREACHED */
+ }
+ }
+
+ if (addr >= VM_MIN_KERNEL_ADDRESS &&
+ addr <= (vm_offset_t)&etext)
+ {
+ ptep0 = pmap_pte(pmap_kernel(), addr);
+ oldmap0 = *ptep0;
+ *ptep0 |= NS532_PTE_WRITE;
+
+ addr1 = ns532_trunc_page(addr + size - 1);
+ if (ns532_trunc_page(addr) != addr1) {
+ /* data crosses a page boundary */
+
+ ptep1 = pmap_pte(pmap_kernel(), addr1);
+ oldmap1 = *ptep1;
+ *ptep1 |= NS532_PTE_WRITE;
+ }
+ _flush_tlb();
+ }
+
+ dst = (char *)addr;
+
+ while (--size >= 0) {
+ *dst++ = *data++;
+ _flush_instruction_cache_addr(dst);
+ }
+
+ if (ptep0) {
+ *ptep0 = oldmap0;
+ if (ptep1) {
+ *ptep1 = oldmap1;
+ }
+ _flush_tlb();
+ }
+}
+
+void
+db_write_bytes_user_space(addr, size, data, task)
+ vm_offset_t addr;
+ register int size;
+ register char *data;
+ task_t task;
+{
+ register char *dst;
+ register n;
+ unsigned kern_addr;
+
+ while (size > 0) {
+ if (db_user_to_kernel_address(task, addr, &kern_addr, 1) < 0)
+ return;
+ dst = (char *)kern_addr;
+ n = ns532_trunc_page(addr+NS532_PGBYTES) - addr;
+ if (n > size)
+ n = size;
+ size -= n;
+ addr += n;
+ while (--n >= 0)
+ *dst++ = *data++;
+ }
+}
+
+boolean_t
+db_check_access(addr, size, task)
+ vm_offset_t addr;
+ register int size;
+ task_t task;
+{
+ register n;
+ unsigned kern_addr;
+
+ if (addr >= VM_MIN_KERNEL_ADDRESS) {
+ if (kernel_task == TASK_NULL)
+ return(TRUE);
+ task = kernel_task;
+ } else if (task == TASK_NULL) {
+ if (current_thread() == THREAD_NULL)
+ return(FALSE);
+ task = current_thread()->task;
+ }
+ while (size > 0) {
+ if (db_user_to_kernel_address(task, addr, &kern_addr, 0) < 0)
+ return(FALSE);
+ n = ns532_trunc_page(addr+NS532_PGBYTES) - addr;
+ if (n > size)
+ n = size;
+ size -= n;
+ addr += n;
+ }
+ return(TRUE);
+}
+
+boolean_t
+db_phys_eq(task1, addr1, task2, addr2)
+ task_t task1;
+ vm_offset_t addr1;
+ task_t task2;
+ vm_offset_t addr2;
+{
+ unsigned kern_addr1, kern_addr2;
+
+ if (addr1 >= VM_MIN_KERNEL_ADDRESS || addr2 >= VM_MIN_KERNEL_ADDRESS)
+ return(FALSE);
+ if ((addr1 & (NS532_PGBYTES-1)) != (addr2 & (NS532_PGBYTES-1)))
+ return(FALSE);
+ if (task1 == TASK_NULL) {
+ if (current_thread() == THREAD_NULL)
+ return(FALSE);
+ task1 = current_thread()->task;
+ }
+ if (db_user_to_kernel_address(task1, addr1, &kern_addr1, 0) < 0
+ || db_user_to_kernel_address(task2, addr2, &kern_addr2) < 0)
+ return(FALSE);
+ return(kern_addr1 == kern_addr2);
+}
+
+#define DB_USER_STACK_ADDR (VM_MIN_KERNEL_ADDRESS)
+#define DB_NAME_SEARCH_LIMIT (DB_USER_STACK_ADDR-(NS532_PGBYTES*3))
+
+static int
+db_search_null(task, svaddr, evaddr, skaddr, flag)
+ task_t task;
+ unsigned *svaddr;
+ unsigned evaddr;
+ unsigned *skaddr;
+ int flag;
+{
+ register unsigned vaddr;
+ register unsigned *kaddr;
+
+ kaddr = (unsigned *)*skaddr;
+ for (vaddr = *svaddr; vaddr > evaddr; vaddr -= sizeof(unsigned)) {
+ if (vaddr % NS532_PGBYTES == 0) {
+ vaddr -= sizeof(unsigned);
+ if (db_user_to_kernel_address(task, vaddr,
+ skaddr, 0) < 0)
+ return(-1);
+ kaddr = (unsigned *)*skaddr;
+ } else {
+ vaddr -= sizeof(unsigned);
+ kaddr--;
+ }
+ if ((*kaddr == 0) ^ (flag == 0)) {
+ *svaddr = vaddr;
+ *skaddr = (unsigned)kaddr;
+ return(0);
+ }
+ }
+ return(-1);
+}
+
+void
+db_task_name(task)
+ task_t task;
+{
+ register char *p;
+ register n;
+ unsigned vaddr, kaddr;
+
+ vaddr = DB_USER_STACK_ADDR;
+ kaddr = 0;
+
+ /*
+ * skip nulls at the end
+ */
+ if (db_search_null(task, &vaddr,
+ DB_NAME_SEARCH_LIMIT, &kaddr, 0) < 0) {
+ db_printf(DB_NULL_TASK_NAME);
+ return;
+ }
+ /*
+ * search start of args
+ */
+ if (db_search_null(task, &vaddr,
+ DB_NAME_SEARCH_LIMIT, &kaddr, 1) < 0) {
+ db_printf(DB_NULL_TASK_NAME);
+ return;
+ }
+
+ n = DB_TASK_NAME_LEN-1;
+ p = (char *)kaddr + sizeof(unsigned);
+ for (vaddr += sizeof(int); vaddr < DB_USER_STACK_ADDR && n > 0;
+ vaddr++, p++, n--) {
+ if (vaddr % NS532_PGBYTES == 0) {
+ (void)db_user_to_kernel_address(task,
+ vaddr, &kaddr, 0);
+ p = (char*)kaddr;
+ }
+ db_printf("%c", (*p < ' ' || *p > '~')? ' ': *p);
+ }
+ while (n-- >= 0) /* compare with >= 0 for one more space */
+ db_printf(" ");
+}
diff --git a/sys/arch/pc532/pc532/db_trace.c b/sys/arch/pc532/pc532/db_trace.c
new file mode 100644
index 00000000000..3d32b0df2d1
--- /dev/null
+++ b/sys/arch/pc532/pc532/db_trace.c
@@ -0,0 +1,681 @@
+/* $NetBSD: db_trace.c,v 1.2 1994/10/26 08:24:58 cgd Exp $ */
+
+/*
+ * Mach Operating System
+ * Copyright (c) 1992 Carnegie Mellon University
+ * Copyright (c) 1992 Helsinki University of Technology
+ * 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 AND HELSINKI UNIVERSITY OF TECHNOLOGY ALLOW FREE USE
+ * OF THIS SOFTWARE IN ITS "AS IS" CONDITION. CARNEGIE MELLON AND
+ * HELSINKI UNIVERSITY OF TECHNOLOGY DISCLAIM 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 Mellon
+ * the rights to redistribute these changes.
+ */
+/*
+ * File: ns532/db_trace.c
+ * Author: Tero Kivinen, Tatu Ylonen
+ * Helsinki University of Technology 1992.
+ *
+ * Stack trace and special register support for debugger.
+ */
+
+
+#include <mach/boolean.h>
+#include <machine/db_machdep.h>
+#include <machine/pic.h>
+
+#include <ddb/db_access.h>
+#include <ddb/db_sym.h>
+#include <ddb/db_variables.h>
+
+#include <kern/thread.h>
+
+int db_spec_regs();
+int db_ns532_reg_value();
+int db_ns532_kreg_value();
+
+/*
+ * Machine register set.
+ */
+struct db_variable db_regs[] = {
+ { "r0", (int *)&ddb_regs.r0, db_ns532_reg_value },
+ { "r1", (int *)&ddb_regs.r1, db_ns532_reg_value },
+ { "r2", (int *)&ddb_regs.r2, db_ns532_reg_value },
+ { "r3", (int *)&ddb_regs.r3, db_ns532_reg_value },
+ { "r4", (int *)&ddb_regs.r4, db_ns532_reg_value },
+ { "r5", (int *)&ddb_regs.r5, db_ns532_reg_value },
+ { "r6", (int *)&ddb_regs.r6, db_ns532_reg_value },
+ { "r7", (int *)&ddb_regs.r7, db_ns532_reg_value },
+ { "sp", (int *)&ddb_regs.usp, db_ns532_reg_value },
+ { "fp", (int *)&ddb_regs.fp, db_ns532_reg_value },
+ { "sb", (int *)&ddb_regs.sb, db_ns532_reg_value },
+ { "pc", (int *)&ddb_regs.pc, db_ns532_reg_value },
+ { "psr",(int *)&ddb_regs.psr, db_ns532_reg_value },
+ { "tear",(int *)&ddb_regs.tear,db_ns532_reg_value },
+ { "msr",(int *)&ddb_regs.msr, db_ns532_reg_value },
+ { "ipl",(int *)&db_active_ipl,db_ns532_reg_value },
+#ifdef FLOATS_SAVED
+ { "f0", (int *)&ddb_regs.l0a, db_ns532_reg_value },
+ { "f1", (int *)&ddb_regs.l0b, db_ns532_reg_value },
+ { "f2", (int *)&ddb_regs.l1a, db_ns532_reg_value },
+ { "f3", (int *)&ddb_regs.l1b, db_ns532_reg_value },
+ { "f4", (int *)&ddb_regs.l2a, db_ns532_reg_value },
+ { "f5", (int *)&ddb_regs.l2b, db_ns532_reg_value },
+ { "f6", (int *)&ddb_regs.l3a, db_ns532_reg_value },
+ { "f7", (int *)&ddb_regs.l3b, db_ns532_reg_value },
+ { "fsr",(int *)&ddb_regs.fsr, db_ns532_reg_value },
+#endif FLOATS_SAVED
+ { "ksp", (int *) 0, db_spec_regs },
+ { "intbase", (int *) 0, db_spec_regs },
+ { "ptb", (int *) 0, db_spec_regs },
+ { "ivar", (int *) 0, db_spec_regs },
+ { "rtear", (int *) 0, db_spec_regs }, /* current reg value */
+ { "mcr", (int *) 0, db_spec_regs },
+ { "rmsr", (int *) 0, db_spec_regs }, /* current reg value */
+ { "dcr", (int *) 0, db_spec_regs },
+ { "dsr", (int *) 0, db_spec_regs },
+ { "car", (int *) 0, db_spec_regs },
+ { "bpc", (int *) 0, db_spec_regs },
+ { "cfg", (int *) 0, db_spec_regs }
+};
+struct db_variable *db_eregs = db_regs + sizeof(db_regs)/sizeof(db_regs[0]);
+
+struct db_regs_bits_s {
+ char *name;
+ char *bitfld;
+};
+
+struct db_regs_bits_s db_regs_bits[] = {
+ "psr", "0,0,0,0: ,0,0,0,0: ,0,0,0,0: ,0,0,0,0: ,0,0,0,0: ,i,p,s,u,n,z,f,v,0,l,t,c",
+ "fsr", "0,0,0,0: ,0,0,0,0: ,0,0,0,0: ,0,0,0,rmb,s5,s4,s3,s2,s1,s0,@roundm,if,ien,uf,uen,@trapt",
+ "mcr", "0,0,0,0: ,0,0,0,0: ,0,0,0,0: ,0,0,0,0: ,0,0,0,0: ,0,0,0,0: ,0,0,0,0: ,ao,ds,ts,tu",
+ "msr", "0,0,0,0: ,0,0,0,0: ,0,0,0,0: ,0,0,0,0: ,0,0,0,0 :,0,0,0,0: ,@sst,ust,ddt,@tex",
+ "rmsr", "0,0,0,0: ,0,0,0,0: ,0,0,0,0: ,0,0,0,0: ,0,0,0,0 :,0,0,0,0: ,@sst,ust,ddt,@tex",
+ "dcr", "0,0,0,0: ,0,0,0,0: ,den,sd,ud,pce,tr,bcp,si,0: ,0,0,0,0: ,0,0,0,bf,cae,crd,cwr,vnp,cbe3,cbe2,cbe1,cbe0",
+ "dsr", "rd,bpc,bex,bca,0,0,0,0: ,0,0,0,0: ,0,0,0,0: ,0,0,0,0: ,0,0,0,0: ,0,0,0,0: ,0,0,0,0",
+ "cfg", "0,0,0,0: ,0,0,0,0: ,0,0,0,0: ,0,0,0,0: ,0,0,pf,lic,ic,ldc,dc,de,1,1,1,1,c,m,f,i"
+ };
+
+struct db_regs_bits_s *db_eregs_bits = db_regs_bits +
+ sizeof(db_regs_bits)/sizeof(db_regs_bits[0]);
+
+struct db_regs_fields_s {
+ char *name;
+ int bits;
+ char *values;
+};
+
+struct db_regs_fields_s db_regs_fields[] = {
+ "trapt", 3, "None,Underflow,Overflow,Div by 0,Ill inst,Invalid oper,Inexact res,Reserved",
+ "roundm", 2, "Nearest,Zero,Pos inf,Neg inf",
+ "tex", 2, "None,1st PTE inv,2nd PTE inv,Prot",
+ "sst", 4, "0000,0001,0010,0011,0100,0101,0110,0111,Seq.ins.fetch,Non.seq.ins.fetch,Data transfer,Read-modify-write,Read eff.addr,1101,1110,1111"
+};
+
+struct db_regs_fields_s *db_eregs_fields = db_regs_fields +
+ sizeof(db_regs_fields)/sizeof(db_regs_fields[0]);
+
+/*
+ * Stack trace.
+ */
+#define INKERNEL(va) (((vm_offset_t)(va)) >= VM_MIN_KERNEL_ADDRESS)
+
+struct ns532_frame {
+ struct ns532_frame *f_frame;
+ int f_retaddr;
+ int f_arg0;
+};
+
+#define TRAP 1
+#define INTERRUPT 2
+#define SYSCALL 3
+
+struct ns532_kregs {
+ char *name;
+ int offset;
+} ns532_kregs[] = {
+ { "r3", (int)(&((struct ns532_kernel_state *)0)->k_r3) },
+ { "r4", (int)(&((struct ns532_kernel_state *)0)->k_r4) },
+ { "r5", (int)(&((struct ns532_kernel_state *)0)->k_r5) },
+ { "r6", (int)(&((struct ns532_kernel_state *)0)->k_r6) },
+ { "r7", (int)(&((struct ns532_kernel_state *)0)->k_r7) },
+ { "sp", (int)(&((struct ns532_kernel_state *)0)->k_sp) },
+ { "fp", (int)(&((struct ns532_kernel_state *)0)->k_fp) },
+ { "pc", (int)(&((struct ns532_kernel_state *)0)->k_pc) },
+ { 0 },
+};
+
+int *
+db_lookup_ns532_kreg(name, kregp)
+ char *name;
+ int *kregp;
+{
+ register struct ns532_kregs *kp;
+
+ for (kp = ns532_kregs; kp->name; kp++) {
+ if (strcmp(name, kp->name) == 0)
+ return((int *)((int)kregp + kp->offset));
+ }
+ return(0);
+}
+
+int
+db_ns532_reg_value(vp, valuep, flag, ap)
+ struct db_variable *vp;
+ db_expr_t *valuep;
+ int flag;
+ db_var_aux_param_t ap;
+{
+ int *dp = 0;
+ db_expr_t null_reg = 0;
+ register thread_t thread = ap->thread;
+
+ if (db_option(ap->modif, 'u')) {
+ if (thread == THREAD_NULL) {
+ if ((thread = current_thread()) == THREAD_NULL)
+ db_error("no user registers\n");
+ }
+ if (thread == current_thread()) {
+ if ((ddb_regs.psr & PSR_U) == 0)
+ dp = vp->valuep;
+ }
+ } else {
+ if (thread == THREAD_NULL || thread == current_thread()) {
+ dp = vp->valuep;
+ } else if ((thread->state & TH_SWAPPED) == 0 &&
+ thread->kernel_stack) {
+ dp = db_lookup_ns532_kreg(vp->name,
+ (int *)(STACK_IKS(thread->kernel_stack)));
+ if (dp == 0)
+ dp = &null_reg;
+ } else if ((thread->state & TH_SWAPPED) &&
+ thread->swap_func != thread_exception_return) {
+ /* only pc is valid */
+ if (vp->valuep == (int *) &ddb_regs.pc) {
+ dp = (int *)(&thread->swap_func);
+ } else {
+ dp = &null_reg;
+ }
+ }
+ }
+ if (dp == 0) {
+ if (thread->pcb == 0)
+ db_error("no pcb\n");
+ dp = (int *)((int)(&thread->pcb->iss) +
+ ((int)vp->valuep - (int)&ddb_regs));
+ }
+ if (flag == DB_VAR_SET)
+ *dp = *valuep;
+ else
+ *valuep = *dp;
+ return(0);
+}
+
+db_addr_t db_trap_symbol_value = 0;
+db_addr_t db_intr_symbol_value = 0;
+boolean_t db_trace_symbols_found = FALSE;
+
+void
+db_find_trace_symbols()
+{
+ db_expr_t value;
+ if (db_value_of_name("_trap", &value))
+ db_trap_symbol_value = (db_addr_t) value;
+ if (db_value_of_name("_interrupt", &value))
+ db_intr_symbol_value = (db_addr_t) value;
+ db_trace_symbols_found = TRUE;
+}
+
+/*
+ * Figure out how many arguments were passed into the frame at "fp".
+ */
+int db_numargs_default = 5;
+
+int
+db_numargs(fp, task)
+ struct ns532_frame *fp;
+ task_t task;
+{
+ int a;
+ char *nextaddr;
+
+ nextaddr = (char *) db_get_task_value((int) &fp->f_frame, 4,
+ FALSE, task);
+ a = nextaddr-(char *)fp-8;
+ a /= 4;
+ if (a < 0 || a > 16)
+ a = db_numargs_default;
+ return a;
+}
+
+extern int (*ivect[])();
+
+/*
+ * Figure out the next frame up in the call stack.
+ * For trap(), we print the address of the faulting instruction and
+ * proceed with the calling frame. We return the ip that faulted.
+ * If the trap was caused by jumping through a bogus pointer, then
+ * the next line in the backtrace will list some random function as
+ * being called. It should get the argument list correct, though.
+ * It might be possible to dig out from the next frame up the name
+ * of the function that faulted, but that could get hairy.
+ */
+void
+db_nextframe(fp, ip, frame_type, thread)
+ struct ns532_frame **fp; /* in/out */
+ db_addr_t *ip; /* out */
+ int frame_type; /* in */
+ thread_t thread; /* in */
+{
+ extern char * trap_type[];
+ extern int TRAP_TYPES;
+
+ struct ns532_saved_state *saved_regs;
+ int vector;
+ task_t task = (thread != THREAD_NULL)? thread->task: TASK_NULL;
+
+ switch(frame_type) {
+ case TRAP:
+ /*
+ * We know that trap() has 1 argument and we know that
+ * it is an (int *).
+ */
+ saved_regs = (struct ns532_saved_state *)
+ db_get_value((int) &((*fp)->f_arg0), 4, FALSE);
+ if (saved_regs->trapno >= 0 &&
+ saved_regs->trapno < TRAP_TYPES) {
+ db_printf(">>>>>> %s trap at ",
+ trap_type[saved_regs->trapno]);
+ } else {
+ db_printf(">>>>>> trap (number %d) at ",
+ saved_regs->trapno & 0xffff);
+ }
+ db_task_printsym(saved_regs->pc, DB_STGY_PROC, task);
+ db_printf(" <<<<<<\n");
+ *fp = (struct ns532_frame *)saved_regs->fp;
+ *ip = (db_addr_t)saved_regs->pc;
+ break;
+ case INTERRUPT:
+ /*
+ * We know that interrupt() has 3 argument.
+ */
+
+ vector = db_get_value((int) &((*fp)->f_arg0), 4, FALSE);
+ saved_regs = (struct ns532_saved_state *)
+ db_get_value((int) &((*fp)->f_arg0) + 8, 4, FALSE);
+ db_printf(">>>>>> ");
+ if (vector >=0 && vector < NINTR) {
+ db_task_printsym((int) ivect[vector],
+ DB_STGY_PROC, task);
+ db_printf(" interrupt at ");
+ } else {
+ db_printf("interrupt vector %d at ", vector);
+ }
+ db_task_printsym(saved_regs->pc, DB_STGY_PROC, task);
+ db_printf(" <<<<<<\n");
+ *fp = (struct ns532_frame *)saved_regs->fp;
+ *ip = (db_addr_t)saved_regs->pc;
+ break;
+ default:
+ *ip = (db_addr_t)
+ db_get_task_value((int) &(*fp)->f_retaddr, 4, FALSE, task);
+ *fp = (struct ns532_frame *)
+ db_get_task_value((int) &(*fp)->f_frame, 4, FALSE, task);
+ break;
+ }
+}
+
+void
+db_stack_trace_cmd(addr, have_addr, count, modif)
+ db_expr_t addr;
+ boolean_t have_addr;
+ db_expr_t count;
+ char *modif;
+{
+ struct ns532_frame *frame, *lastframe;
+ int *argp;
+ db_addr_t callpc;
+ int frame_type;
+ boolean_t kernel_only = TRUE;
+ boolean_t trace_thread = FALSE;
+ char *filename;
+ int linenum;
+ task_t task;
+ thread_t th;
+ int user_frame = 0;
+ extern unsigned db_maxoff;
+
+
+ if (!db_trace_symbols_found)
+ db_find_trace_symbols();
+
+ {
+ register char *cp = modif;
+ register char c;
+
+ while ((c = *cp++) != 0) {
+ if (c == 't')
+ trace_thread = TRUE;
+ if (c == 'u')
+ kernel_only = FALSE;
+ }
+ }
+
+ if (count == -1)
+ count = 65535;
+
+ if (!have_addr && !trace_thread) {
+ frame = (struct ns532_frame *)ddb_regs.fp;
+ callpc = (db_addr_t)ddb_regs.pc;
+ th = current_thread();
+ task = (th != THREAD_NULL) ? th->task : TASK_NULL;
+ } else if (trace_thread) {
+ if (have_addr) {
+ th = (thread_t) addr;
+ if (!db_check_thread_address_valid(th))
+ return;
+ } else {
+ th = db_default_thread;
+ if (th = THREAD_NULL)
+ current_thread();
+ if (th == THREAD_NULL) {
+ db_printf("no active thread\n");
+ return;
+ }
+ }
+ task = th->task;
+ if (th == current_thread()) {
+ frame = (struct ns532_frame *)ddb_regs.fp;
+ callpc = (db_addr_t)ddb_regs.pc;
+ } else {
+ if (th->pcb == 0) {
+ db_printf("thread has no pcb\n");
+ return;
+ }
+ if ((th->state & TH_SWAPPED) ||
+ th->kernel_stack == 0) {
+ register struct ns532_saved_state *iss =
+ &th->pcb->iss;
+
+ db_printf("Continuation ");
+ db_task_printsym(th->swap_func, DB_STGY_PROC,
+ task);
+ db_printf("\n");
+
+ frame = (struct ns532_frame *) (iss->fp);
+ callpc = (db_addr_t) (iss->pc);
+ } else {
+ register struct ns532_kernel_state *iks;
+ iks = STACK_IKS(th->kernel_stack);
+ frame = (struct ns532_frame *) (iks->k_fp);
+ callpc = (db_addr_t) (iks->k_pc);
+ }
+ }
+ } else {
+ frame = (struct ns532_frame *)addr;
+ th = (db_default_thread)? db_default_thread: current_thread();
+ task = (th != THREAD_NULL)? th->task: TASK_NULL;
+ callpc = (db_addr_t)db_get_task_value((int)&frame->f_retaddr,
+ 4, FALSE, task);
+ }
+
+ if (!INKERNEL(callpc) && !INKERNEL(frame)) {
+ db_printf(">>>>>> user space <<<<<<\n");
+ user_frame++;
+ }
+
+ while (count-- && frame != 0) {
+ register int narg;
+ char * name;
+ db_expr_t offset;
+
+ if (INKERNEL(callpc) && user_frame == 0) {
+ db_addr_t call_func = 0;
+
+ db_symbol_values(db_search_task_symbol(callpc,
+ DB_STGY_XTRN,
+ &offset,
+ TASK_NULL),
+ &name, &call_func);
+ if (call_func == db_trap_symbol_value) {
+ frame_type = TRAP;
+ narg = 1;
+ } else if (call_func == db_intr_symbol_value) {
+ frame_type = INTERRUPT;
+ narg = 3;
+#ifdef SYSCALL_FRAME_IMPLEMENTED
+ } else if (call_func == db_syscall_symbol_value) {
+ frame_type = SYSCALL;
+ goto next_frame;
+#endif
+ } else {
+ frame_type = 0;
+ narg = db_numargs(frame, task);
+ }
+ } else if ((INKERNEL(callpc) == 0) != (INKERNEL(frame) == 0)) {
+ frame_type = 0;
+ narg = -1;
+ } else {
+ frame_type = 0;
+ narg = db_numargs(frame, task);
+ }
+
+ db_find_task_sym_and_offset(callpc, &name, &offset, task);
+ if (name == 0 || offset > db_maxoff) {
+ db_printf("0x%x(", callpc);
+ offset = 0;
+ } else
+ db_printf("%s(", name);
+
+ argp = &frame->f_arg0;
+ while (narg > 0) {
+ db_printf("%x",
+ db_get_task_value((int)argp,4,FALSE,task));
+ argp++;
+ if (--narg != 0)
+ db_printf(",");
+ }
+ if (narg < 0)
+ db_printf("...");
+ db_printf(")");
+ if (offset) {
+ db_printf("+%x", offset);
+ }
+ if (db_line_at_pc(0, &filename, &linenum, callpc)) {
+ db_printf(" [%s", filename);
+ if (linenum > 0)
+ db_printf(":%d", linenum);
+ printf("]");
+ }
+
+ db_printf("\n");
+ next_frame:
+ lastframe = frame;
+ db_nextframe(&frame, &callpc, frame_type, th);
+
+ if (frame == 0) {
+ /* end of chain */
+ break;
+ }
+ if (!INKERNEL(lastframe) ||
+ (!INKERNEL(callpc) && !INKERNEL(frame)))
+ user_frame++;
+ if (user_frame == 1) {
+ db_printf(">>>>>> user space <<<<<<\n");
+ if (kernel_only)
+ break;
+ }
+ if (frame <= lastframe) {
+ if (INKERNEL(lastframe) && !INKERNEL(frame))
+ continue;
+ db_printf("Bad frame pointer: 0x%x\n", frame);
+ break;
+ }
+ }
+}
+
+/**********************************************
+
+ Get/Set value of special registers.
+
+ *********************************************/
+
+int db_spec_regs(vp, valp, what)
+ struct db_variable *vp;
+ db_expr_t *valp;
+ int what;
+{
+ if (strcmp(vp->name, "intbase") == 0)
+ if (what == DB_VAR_GET)
+ *valp = _get_intbase();
+ else
+ _set_intbase(*valp);
+ else if (strcmp(vp->name, "ptb") == 0)
+ if (what == DB_VAR_GET)
+ *valp = _get_ptb();
+ else
+ _set_ptb(*valp);
+ else if (strcmp(vp->name, "ivar") == 0)
+ if (what == DB_VAR_GET)
+ *valp = 0;
+ else
+ _invalidate_page(*valp);
+ else if (strcmp(vp->name, "rtear") == 0)
+ if (what == DB_VAR_GET)
+ *valp = _get_tear();
+ else
+ _set_tear(*valp);
+ else if (strcmp(vp->name, "mcr") == 0)
+ if (what == DB_VAR_GET)
+ *valp = _get_mcr();
+ else
+ _set_mcr(*valp);
+ else if (strcmp(vp->name, "rmsr") == 0)
+ if (what == DB_VAR_GET)
+ *valp = _get_msr();
+ else
+ _set_msr(*valp);
+ else if (strcmp(vp->name, "dcr") == 0)
+ if (what == DB_VAR_GET)
+ *valp = _get_dcr();
+ else
+ _set_dcr(*valp);
+ else if (strcmp(vp->name, "dsr") == 0)
+ if (what == DB_VAR_GET)
+ *valp = _get_dsr();
+ else
+ _set_dsr(*valp);
+ else if (strcmp(vp->name, "car") == 0)
+ if (what == DB_VAR_GET)
+ *valp = _get_car();
+ else
+ _set_car(*valp);
+ else if (strcmp(vp->name, "bpc") == 0)
+ if (what == DB_VAR_GET)
+ *valp = _get_bpc();
+ else
+ _set_bpc(*valp);
+ else if (strcmp(vp->name, "cfg") == 0)
+ if (what == DB_VAR_GET)
+ *valp = _get_cfg();
+ else
+ _set_cfg(*valp);
+ else if (strcmp(vp->name, "ksp") == 0)
+ if (what == DB_VAR_GET)
+ *valp = _get_ksp();
+ else
+ _set_ksp(*valp);
+ else
+ db_printf("Internal error, unknown register in db_spec_regs");
+}
+
+/***************************************************
+
+ Print special bit mask registers in bitmask format
+
+ **************************************************/
+
+int db_print_spec_reg(vp, valuep)
+ struct db_variable *vp;
+ db_expr_t valuep;
+{
+ struct db_regs_bits_s *dbrb;
+ int i;
+ char *p, buf[256];
+
+ for (dbrb = db_regs_bits; dbrb < db_eregs_bits; dbrb++)
+ if (strcmp(dbrb->name, vp->name) == 0)
+ break;
+ if (dbrb == db_eregs_bits)
+ return 1;
+ db_printf("\t<");
+ p = dbrb->bitfld;
+ for (i = 31 ; i >= 0 && *p ; i--) { /* All bits */
+ if (*p >= '0' && *p <= '9') { /* is number */
+ for (; *p != ',' && *p; p++) /* Skip number */
+ ;
+ if (*p == ',')
+ p++;
+ } else { /* Is text */
+ char *q;
+ strcpy(buf, p);
+ for(q = buf; *q != ',' && *q; q++, p++) /* Find end */
+ ;
+ if (*p == ',')
+ p++;
+ *q='\0';
+ if (buf[0] == '@') { /* Is bitfield */
+ struct db_regs_fields_s *df;
+ q=buf+1; /* Find field */
+ for (df = db_regs_fields;
+ df < db_eregs_fields; df++)
+ if (strcmp(df->name, q) == 0)
+ break;
+ if (df == db_eregs_fields)
+ db_printf("Internal error in print_spec_regs [%s]\n", buf);
+ else {
+ unsigned int ff;
+ db_printf("%s=", q); /* Print field */
+ ff = (~(0xffffffff << df->bits)) &
+ (valuep>>(i-(df->bits-1)));
+ i += df->bits; /* Find value */
+ for (q = df->values;
+ ff > 0 && *q; ff--, q++)
+ for (;*q != ',' && *q; q++)
+ ;
+ if (*q != '\0') {
+ strcpy(buf, q);
+ for(q = buf; *q != ',' && *q;
+ q++)
+ ;
+ *q='\0';
+ db_printf("%s "); /* Print value */
+ } else
+ db_printf(" ");
+ }
+ } else { /* Normal bit */
+ if ((1<<i) & valuep) {
+ db_printf("%s ", buf);
+ }
+ }
+ }
+ }
+ db_printf(">");
+ return 0;
+}
diff --git a/sys/arch/pc532/pc532/disksubr.c b/sys/arch/pc532/pc532/disksubr.c
new file mode 100644
index 00000000000..397a7fc9dd3
--- /dev/null
+++ b/sys/arch/pc532/pc532/disksubr.c
@@ -0,0 +1,241 @@
+/* $NetBSD: disksubr.c,v 1.7 1995/08/25 07:49:05 phil Exp $ */
+
+/*
+ * Copyright (c) 1982, 1986, 1988 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)ufs_disksubr.c 7.16 (Berkeley) 5/4/91
+ */
+
+#include "param.h"
+#include "systm.h"
+#include "buf.h"
+#include "disklabel.h"
+#include "syslog.h"
+
+#define b_cylin b_resid
+
+/*
+ * Attempt to read a disk label from a device
+ * using the indicated stategy routine.
+ * The label must be partly set up before this:
+ * secpercyl and anything required in the strategy routine
+ * (e.g., sector size) must be filled in before calling us.
+ * Returns null on success and an error string on failure.
+ */
+char *
+readdisklabel(dev, strat, lp, osdep)
+ dev_t dev;
+ void (*strat)();
+ register struct disklabel *lp;
+ struct cpu_disklabel *osdep;
+{
+ register struct buf *bp;
+ struct disklabel *dlp;
+ char *msg = NULL;
+
+ if (lp->d_secperunit == 0)
+ lp->d_secperunit = 0x1fffffff;
+ lp->d_npartitions = 1;
+ if (lp->d_partitions[0].p_size == 0)
+ lp->d_partitions[0].p_size = 0x1fffffff;
+ lp->d_partitions[0].p_offset = 0;
+
+ bp = geteblk((int)lp->d_secsize);
+ bp->b_dev = dev;
+ bp->b_blkno = LABELSECTOR;
+ bp->b_bcount = lp->d_secsize;
+ bp->b_flags = B_BUSY | B_READ;
+ bp->b_cylin = LABELSECTOR / lp->d_secpercyl;
+ (*strat)(bp);
+ if (biowait(bp)) {
+ msg = "I/O error";
+ } else for (dlp = (struct disklabel *)bp->b_un.b_addr;
+ dlp <= (struct disklabel *)(bp->b_un.b_addr+DEV_BSIZE-sizeof(*dlp));
+ dlp = (struct disklabel *)((char *)dlp + sizeof(long))) {
+ if (dlp->d_magic != DISKMAGIC || dlp->d_magic2 != DISKMAGIC) {
+ if (msg == NULL)
+ msg = "no disk label";
+ } else if (dlp->d_npartitions > MAXPARTITIONS ||
+ dkcksum(dlp) != 0)
+ msg = "disk label corrupted";
+ else {
+ *lp = *dlp;
+ msg = NULL;
+ break;
+ }
+ }
+ bp->b_flags = B_INVAL | B_AGE;
+ brelse(bp);
+ return (msg);
+}
+
+/*
+ * Check new disk label for sensibility
+ * before setting it.
+ */
+setdisklabel(olp, nlp, openmask, osdep)
+ register struct disklabel *olp, *nlp;
+ u_long openmask;
+ struct cpu_disklabel *osdep;
+{
+ register i;
+ register struct partition *opp, *npp;
+
+ if (nlp->d_magic != DISKMAGIC || nlp->d_magic2 != DISKMAGIC ||
+ dkcksum(nlp) != 0)
+ return (EINVAL);
+ while ((i = ffs((long)openmask)) != 0) {
+ i--;
+ openmask &= ~(1 << i);
+ if (nlp->d_npartitions <= i)
+ return (EBUSY);
+ opp = &olp->d_partitions[i];
+ npp = &nlp->d_partitions[i];
+ if (npp->p_offset != opp->p_offset || npp->p_size < opp->p_size)
+ return (EBUSY);
+ /*
+ * Copy internally-set partition information
+ * if new label doesn't include it. XXX
+ */
+ if (npp->p_fstype == FS_UNUSED && opp->p_fstype != FS_UNUSED) {
+ npp->p_fstype = opp->p_fstype;
+ npp->p_fsize = opp->p_fsize;
+ npp->p_frag = opp->p_frag;
+ npp->p_cpg = opp->p_cpg;
+ }
+ }
+ nlp->d_checksum = 0;
+ nlp->d_checksum = dkcksum(nlp);
+ *olp = *nlp;
+ return (0);
+}
+
+/* encoding of disk minor numbers, should be elsewhere... */
+#define dkunit(dev) (minor(dev) >> 3)
+#define dkpart(dev) (minor(dev) & 07)
+#define dkminor(unit, part) (((unit) << 3) | (part))
+
+/*
+ * Write disk label back to device after modification.
+ */
+writedisklabel(dev, strat, lp, osdep)
+ dev_t dev;
+ void (*strat)();
+ register struct disklabel *lp;
+ struct cpu_disklabel *osdep;
+{
+ struct buf *bp;
+ struct disklabel *dlp;
+ int labelpart;
+ int error = 0;
+
+ labelpart = dkpart(dev);
+ if (lp->d_partitions[labelpart].p_offset != 0) {
+ if (lp->d_partitions[0].p_offset != 0)
+ return (EXDEV); /* not quite right */
+ labelpart = 0;
+ }
+ bp = geteblk((int)lp->d_secsize);
+ bp->b_dev = makedev(major(dev), dkminor(dkunit(dev), labelpart));
+ bp->b_blkno = LABELSECTOR;
+ bp->b_bcount = lp->d_secsize;
+ bp->b_flags = B_READ;
+ (*strat)(bp);
+ if (error = biowait(bp))
+ goto done;
+ for (dlp = (struct disklabel *)bp->b_un.b_addr;
+ dlp <= (struct disklabel *)
+ (bp->b_un.b_addr + lp->d_secsize - sizeof(*dlp));
+ dlp = (struct disklabel *)((char *)dlp + sizeof(long))) {
+ if (dlp->d_magic == DISKMAGIC && dlp->d_magic2 == DISKMAGIC &&
+ dkcksum(dlp) == 0) {
+ *dlp = *lp;
+ bp->b_flags = B_WRITE;
+ (*strat)(bp);
+ error = biowait(bp);
+ goto done;
+ }
+ }
+ error = ESRCH;
+done:
+ brelse(bp);
+ return (error);
+}
+
+
+/*
+ * Determine the size of the transfer, and make sure it is
+ * within the boundaries of the partition. Adjust transfer
+ * if needed, and signal errors or early completion.
+ */
+int
+bounds_check_with_label(struct buf *bp, struct disklabel *lp, int wlabel)
+{
+ struct partition *p = lp->d_partitions + dkpart(bp->b_dev);
+ int maxsz = p->p_size,
+ sz = (bp->b_bcount + DEV_BSIZE - 1) >> DEV_BSHIFT;
+
+ /* Check to see if it is the label sector and it is write only. */
+ if (bp->b_blkno + p->p_offset <= LABELSECTOR &&
+ (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_cylin = (bp->b_blkno + p->p_offset) / lp->d_secpercyl;
+ return(1);
+
+bad:
+ bp->b_flags |= B_ERROR;
+ return(-1);
+}
+
+/* XXX unknown */
+int
+dk_establish()
+{}
diff --git a/sys/arch/pc532/pc532/genassym.c b/sys/arch/pc532/pc532/genassym.c
new file mode 100644
index 00000000000..487cd8c72b3
--- /dev/null
+++ b/sys/arch/pc532/pc532/genassym.c
@@ -0,0 +1,124 @@
+/* $NetBSD: genassym.c,v 1.8 1995/06/09 05:59:58 phil Exp $ */
+
+/*-
+ * Copyright (c) 1982, 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * William Jolitz.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)genassym.c 5.11 (Berkeley) 5/10/91
+ */
+
+#include <sys/param.h>
+#include <sys/proc.h>
+#include <sys/resourcevar.h>
+#include <sys/device.h>
+#include <vm/vm.h>
+#include <sys/user.h>
+
+#include <machine/cpu.h>
+#include <machine/trap.h>
+
+#include <stdio.h>
+
+main()
+{
+ struct proc *p = (struct proc *)0;
+ struct user *up = (struct user *)0;
+ struct rusage *rup = (struct rusage *)0;
+ struct uprof *uprof = (struct uprof *)0;
+ struct pcb *pcb = (struct pcb *)0;
+ struct on_stack *regs = (struct on_stack *)0;
+ struct iv *iv = (struct iv *)0;
+ struct vmmeter *vm = 0;
+ register unsigned i;
+
+ printf("#define\tKERNBASE 0x%x\n", KERNBASE);
+ printf("#define\tUDOT_SZ %d\n", sizeof(struct user));
+ printf("#define\tP_FORW %d\n", &p->p_forw);
+ printf("#define\tP_BACK %d\n", &p->p_back);
+ printf("#define\tP_VMSPACE %d\n", &p->p_vmspace);
+ printf("#define\tP_ADDR %d\n", &p->p_addr);
+ printf("#define\tP_PRIORITY %d\n", &p->p_priority);
+ printf("#define\tP_STAT %d\n", &p->p_stat);
+ printf("#define\tP_WCHAN %d\n", &p->p_wchan);
+ printf("#define\tP_FLAG %d\n", &p->p_flag);
+ printf("#define\tP_PID %d\n", &p->p_pid);
+
+ printf("#define\tSSLEEP %d\n", SSLEEP);
+ printf("#define\tSRUN %d\n", SRUN);
+ printf("#define\tUPAGES %d\n", UPAGES);
+ printf("#define\tHIGHPAGES %d\n", HIGHPAGES);
+ printf("#define\tCLSIZE %d\n", CLSIZE);
+ printf("#define\tNBPG %d\n", NBPG);
+ printf("#define\tNPTEPG %d\n", NPTEPG);
+ printf("#define\tPGSHIFT %d\n", PGSHIFT);
+ printf("#define\tSYSPTSIZE %d\n", SYSPTSIZE);
+ printf("#define\tUSRPTSIZE %d\n", USRPTSIZE);
+
+ printf("#define\tKERN_STK_START 0x%x\n",
+ USRSTACK + UPAGES*NBPG);
+ printf("#define\tKSTK_SIZE %d\n", UPAGES*NBPG);
+ printf("#define\tON_STK_SIZE %d\n", sizeof(struct on_stack));
+ printf("#define\tREGS_USP %d\n", &regs->pcb_usp);
+ printf("#define\tREGS_FP %d\n", &regs->pcb_fp);
+ printf("#define\tREGS_SB %d\n", &regs->pcb_sb);
+ printf("#define\tREGS_PSR %d\n", &regs->pcb_psr);
+
+ printf("#define\tPCB_ONSTACK %d\n", &pcb->pcb_onstack);
+ printf("#define\tPCB_FSR %d\n", &pcb->pcb_fsr);
+ for (i=0; i<8; i++)
+ printf("#define\tPCB_F%d %d\n", i, &pcb->pcb_freg[i]);
+ printf("#define\tPCB_KSP %d\n", &pcb->pcb_ksp);
+ printf("#define\tPCB_KFP %d\n", &pcb->pcb_kfp);
+ printf("#define\tPCB_PTB %d\n", &pcb->pcb_ptb);
+ printf("#define\tPCB_PL %d\n", &pcb->pcb_pl);
+ printf("#define\tPCB_FLAGS %d\n", &pcb->pcb_flags);
+ printf("#define\tPCB_ONFAULT %d\n", &pcb->pcb_onfault);
+
+ printf("#define\tV_TRAP %d\n", &vm->v_trap);
+ printf("#define\tV_INTR %d\n", &vm->v_intr);
+
+ printf("#define\tIV_VEC %d\n", &iv->iv_vec);
+ printf("#define\tIV_ARG %d\n", &iv->iv_arg);
+ printf("#define\tIV_CNT %d\n", &iv->iv_cnt);
+ printf("#define\tIV_USE %d\n", &iv->iv_use);
+
+ printf("#define\tUSRSTACK 0x%x\n", USRSTACK);
+#ifdef SYSVSHM
+ printf("#define\tSHMMAXPGS %d\n", SHMMAXPGS);
+#endif
+ printf("#define\tENOENT %d\n", ENOENT);
+ printf("#define\tEFAULT %d\n", EFAULT);
+ printf("#define\tENAMETOOLONG %d\n", ENAMETOOLONG);
+ exit(0);
+}
diff --git a/sys/arch/pc532/pc532/icuinit.c b/sys/arch/pc532/pc532/icuinit.c
new file mode 100644
index 00000000000..79ed7d7b718
--- /dev/null
+++ b/sys/arch/pc532/pc532/icuinit.c
@@ -0,0 +1,86 @@
+/* $NetBSD: icuinit.c,v 1.3 1994/10/26 08:25:03 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.
+ */
+
+/* icuinit.c - C support for 532 icu stuff. */
+
+#include <sys/param.h>
+#include <machine/cpu.h>
+#include <machine/icu.h>
+
+/* Table for initializing ICU. Written in order to ICU.
+ * Monitor has already set
+ * CCTL=0x15 MCTL=0 LCSV=13 IPS=0 PDIR=0xfe PDAT=0xfe
+ */
+struct icu_init_type {
+ unsigned char offset;
+ unsigned char val;
+} icu_tab [] = {
+ {IMSK, 0xff}, /* mask off ints for now */
+ {IMSK+1, 0xff}, /* " */
+ {CIPTR, IR_CLK << 4}, /* clock int vector (CIPTR) */
+ {CICTL, 0x00}, /* clock interrupt enable (CICTL) */
+ {IPS, 0x7e}, /* 0=i/o, 1=int_req */
+ {PDIR, 0x7e}, /* 1=in, 0=out */
+ {OCASN, 0}, /* clock output (n/a) */
+ {PDAT, 0xfe}, /* keep ROM at high mem */
+ {ISRV, 0}, /* int in service (set by hw) */
+ {ISRV+1, 0}, /* int in service */
+ {CSRC, 0}, /* cascade source */
+ {CSRC+1, 0}, /* cascade source */
+ {SVCT, VEC_ICU}, /* isr vector */
+ {FPRT, 0}, /* priority */
+ {TPL, IPOLARITY & 0xff}, /* polarity */
+ {TPL+1, IPOLARITY >> 8}, /* " */
+ {ELTG, IEDGE & 0xff}, /* edge trigger (0 = edge) */
+ {ELTG+1, IEDGE >> 8}, /* " */
+ {MCTL, 0x02}, /* fixed priority */
+ {CCTL, 0x1c}, /* prescale, no cat, run clocks */
+};
+#define ICUTAB_SZ (sizeof (icu_tab) / sizeof (struct icu_init_type))
+
+
+/*===========================================================================*
+ * icu_init
+ *===========================================================================*/
+
+/* Initialize interrupt control unit. Starts clock interrupts.
+ */
+
+icu_init()
+{
+ struct icu_init_type *p;
+
+ for (p = icu_tab; p < icu_tab + ICUTAB_SZ; ++p)
+ WR_ADR (unsigned char, ICU_ADR + p->offset, p->val);
+}
+
diff --git a/sys/arch/pc532/pc532/in_cksum.c b/sys/arch/pc532/pc532/in_cksum.c
new file mode 100644
index 00000000000..e45b6ef8d6c
--- /dev/null
+++ b/sys/arch/pc532/pc532/in_cksum.c
@@ -0,0 +1,173 @@
+/* $NetBSD: in_cksum.c,v 1.4 1995/08/29 22:37:44 phil Exp $ */
+
+/*-
+ * Copyright (c) 1994, 1995 Charles M. Hannum. All rights reserved.
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * from tahoe: in_cksum.c 1.2 86/01/05
+ * @(#)in_cksum.c 1.3 (Berkeley) 1/19/91
+ */
+
+#include <sys/param.h>
+#include <sys/mbuf.h>
+
+/*
+ * Checksum routine for Internet Protocol family headers.
+ *
+ * This routine is very heavily used in the network
+ * code and should be modified for each CPU to be as fast as possible.
+ *
+ * This implementation is the ns32k version.
+ */
+
+#define REDUCE {sum = (sum & 0xffff) + (sum >> 16);}
+#define ADDCARRY {if (sum > 0xffff) sum -= 0xffff;}
+#define SWAP {sum <<= 8;}
+#define ADVANCE(x) {w += x; mlen -= x;}
+
+/*
+ * Thanks to gcc we don't have to guess
+ * which registers contain sum & w.
+ */
+#define Asm __asm __volatile
+#define ADD(n) Asm("addd " #n "(%2),%0" : "=r" (sum) : "0" (sum), "r" (w))
+#define ADC(n) Asm("addcd " #n "(%2),%0" : "=r" (sum) : "0" (sum), "r" (w))
+#define MOP Asm("addcd 0,%0" : "=r" (sum) : "0" (sum))
+#define UNSWAP Asm("rotd 8,%0" : "=r" (sum) : "0" (sum))
+#define ADDBYTE {sum += *w; SWAP; byte_swapped ^= 1;}
+#define ADDWORD {sum += *(u_short *)w;}
+
+int
+in_cksum(m, len)
+ register struct mbuf *m;
+ register int len;
+{
+ register u_char *w;
+ register unsigned sum = 0;
+ register int mlen = 0;
+ int byte_swapped = 0;
+
+ for (; m && len; m = m->m_next) {
+ mlen = m->m_len;
+ if (mlen == 0)
+ continue;
+ w = mtod(m, u_char *);
+ if (len < mlen)
+ mlen = len;
+ len -= mlen;
+ if (mlen < 16)
+ goto short_mbuf;
+ /*
+ * Force to long boundary so we do longword aligned
+ * memory operations
+ */
+ if ((3 & (long)w) != 0) {
+ REDUCE;
+ if ((1 & (long)w) != 0) {
+ ADDBYTE;
+ ADVANCE(1);
+ }
+ if ((2 & (long)w) != 0) {
+ ADDWORD;
+ ADVANCE(2);
+ }
+ }
+ /*
+ * Align 4 bytes past a 16-byte cache line boundary.
+ */
+ if ((4 & (long)w) == 0) {
+ ADD(0);
+ MOP;
+ ADVANCE(4);
+ }
+ if ((8 & (long)w) != 0) {
+ ADD(0); ADC(4);
+ MOP;
+ ADVANCE(8);
+ }
+ /*
+ * Do as much of the checksum as possible 32 bits at at time.
+ * In fact, this loop is unrolled to make overhead from
+ * branches &c small.
+ */
+ while (mlen >= 32) {
+ /*
+ * Add with carry 16 words and fold in the last carry
+ * by adding a 0 with carry.
+ *
+ * Use the burst fill delay for pointer update.
+ */
+ ADD(0); ADC(4); ADC(8); ADC(12);
+ MOP;
+ w += 32;
+ ADD(-16); ADC(-12); ADC(-8); ADC(-4);
+ MOP;
+ mlen -= 32;
+ }
+ if (mlen >= 16) {
+ ADD(12); ADC(0); ADC(4); ADC(8);
+ MOP;
+ ADVANCE(16);
+ }
+ short_mbuf:
+ if (mlen >= 8) {
+ ADD(0); ADC(4);
+ MOP;
+ ADVANCE(8);
+ }
+ if (mlen >= 4) {
+ ADD(0);
+ MOP;
+ ADVANCE(4);
+ }
+ if (mlen > 0) {
+ REDUCE;
+ if (mlen >= 2) {
+ ADDWORD;
+ ADVANCE(2);
+ }
+ if (mlen >= 1) {
+ ADDBYTE;
+ }
+ }
+ }
+
+ if (len)
+ printf("cksum: out of data\n");
+ if (byte_swapped) {
+ UNSWAP;
+ }
+ REDUCE;
+ ADDCARRY;
+ return (sum ^ 0xffff);
+}
+
diff --git a/sys/arch/pc532/pc532/intr.c b/sys/arch/pc532/pc532/intr.c
new file mode 100644
index 00000000000..4bf7111802d
--- /dev/null
+++ b/sys/arch/pc532/pc532/intr.c
@@ -0,0 +1,229 @@
+/* $NetBSD: intr.c,v 1.5 1995/09/26 20:16:26 phil Exp $ */
+
+/*
+ * Copyright (c) 1994 Matthias Pfaller.
+ * 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 Matthias Pfaller.
+ * 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.
+ *
+ * $Id: intr.c,v 1.1 1995/10/18 08:51:21 deraadt Exp $
+ */
+
+#define DEFINE_SPLX
+#include <sys/param.h>
+#include <sys/vmmeter.h>
+#include <sys/systm.h>
+#include <net/netisr.h>
+#include <machine/psl.h>
+
+#define INTS 32
+struct iv ivt[INTS];
+static int next_sir = 16;
+unsigned int imask[NIPL] = {0xffffffff};
+unsigned int Cur_pl = 0xffffffff, idisabled, sirpending, astpending;
+
+static void softnet();
+static void badhard(struct intrframe *);
+static void badsoft(void *);
+
+/*
+ * Initialize the interrupt system.
+ */
+void
+intr_init()
+{
+ int i;
+ for (i = 0; i < 16; i++)
+ ivt[i].iv_vec = badhard;
+
+ for (i = 16; i < 32; i++) {
+ ivt[i].iv_vec = badsoft;
+ ivt[i].iv_arg = (void *)i;
+ }
+
+ intr_establish(SOFTINT, softclock, NULL, "softclock", IPL_CLOCK, 0);
+ intr_establish(SOFTINT, softnet, NULL, "softnet", IPL_NET, 0);
+
+ for (i = 1; i < NIPL; i++)
+ imask[i] |= SIR_ALLMASK;
+}
+
+/*
+ * Handle pending software interrupts.
+ * This function has to be entered with interrupts disabled and
+ * it will return with interrupts disabled.
+ */
+void
+check_sir()
+{
+ register unsigned int cirpending, mask;
+ register struct iv *iv;
+
+ while (cirpending = sirpending) {
+ sirpending = 0;
+ ei();
+ for (iv = ivt + 16, mask = 0x10000;
+ cirpending & -mask; mask <<= 1, iv++) {
+ if ((cirpending & mask) != 0) {
+ cnt.v_soft++;
+ iv->iv_cnt++;
+ iv->iv_vec(iv->iv_arg);
+ }
+ }
+ di();
+ }
+ return;
+}
+
+/*
+ * Establish an interrupt. If intr is set to SOFTINT, a software interrupt
+ * is allocated.
+ */
+int
+intr_establish(int intr, void (*vector)(), void *arg, char *use,
+ int level, int mode)
+{
+ if (intr == SOFTINT) {
+ if (next_sir >= INTS)
+ panic("No software interrupts left");
+ di();
+ intr = next_sir++;
+ } else {
+ if (ivt[intr].iv_vec != badhard) {
+ printf("Interrupt %d already allocated\n", intr);
+ return(-1);
+ }
+ di();
+ switch (mode) {
+ case RISING_EDGE:
+ ICUW(TPL) |= (1 << intr);
+ ICUW(ELTG) &= ~(1 << intr);
+ break;
+ case FALLING_EDGE:
+ ICUW(TPL) &= ~(1 << intr);
+ ICUW(ELTG) &= ~(1 << intr);
+ break;
+ case HIGH_LEVEL:
+ ICUW(TPL) |= (1 << intr);
+ ICUW(ELTG) |= (1 << intr);
+ break;
+ case LOW_LEVEL:
+ ICUW(TPL) &= ~(1 << intr);
+ ICUW(ELTG) |= (1 << intr);
+ break;
+ default:
+ panic("Unknown interrupt mode");
+ }
+ }
+ ivt[intr].iv_vec = vector;
+ ivt[intr].iv_arg = arg;
+ ivt[intr].iv_cnt = 0;
+ ivt[intr].iv_use = use;
+ ei();
+ if (level > IPL_ZERO)
+ imask[level] |= 1 << intr;
+#include "sl.h"
+#include "ppp.h"
+#if NSL > 0 || NPPP > 0
+ /* In the presence of SLIP or PPP, splimp > spltty. */
+ imask[IPL_IMP] |= imask[IPL_TTY];
+#endif
+ /*
+ * There are network and disk drivers that use free() at interrupt
+ * time, so imp > (net | bio).
+ */
+ imask[IPL_IMP] |= imask[IPL_NET] | imask[IPL_BIO];
+ imask[IPL_ZERO] &= ~(1 << intr);
+ return(intr);
+}
+
+/*
+ * Network software interrupt routine
+ */
+static void
+softnet()
+{
+ register int isr;
+
+ di(); isr = netisr; netisr = 0; ei();
+ if (isr == 0) return;
+#ifdef INET
+#include "ether.h"
+#if NETHER > 0
+ if (isr & (1 << NETISR_ARP)) arpintr();
+#endif
+ if (isr & (1 << NETISR_IP)) ipintr();
+#endif
+#ifdef IMP
+ if (isr & (1 << NETISR_IMP)) impintr();
+#endif
+#ifdef NS
+ if (isr & (1 << NETISR_NS)) nsintr();
+#endif
+#ifdef ISO
+ if (isr & (1 << NETISR_ISO)) clnlintr();
+#endif
+#ifdef CCITT
+ if (isr & (1 << NETISR_CCITT)) ccittintr();
+#endif
+#include "ppp.h"
+#if NPPP > 0
+ if (isr & (1 << NETISR_PPP)) pppintr();
+#endif
+}
+
+/*
+ * Default hardware interrupt handler
+ */
+static void
+badhard(struct intrframe *frame)
+{
+ static int bad_count = 0;
+ di();
+ bad_count++;
+ if (bad_count < 5)
+ printf("Unknown hardware interrupt: vec=%d pc=0x%08x psr=0x%04x cpl=0x%08x\n",
+ frame->if_vec, frame->if_pc, frame->if_psr, frame->if_pl);
+
+ if (bad_count == 5)
+ printf("Too many unknown hardware interrupts, quitting reporting them.\n");
+ ei();
+}
+
+/*
+ * Default software interrupt handler
+ */
+static void
+badsoft(void *n)
+{
+ static int bad_count = 0;
+ bad_count++;
+ if (bad_count < 5)
+ printf("Unknown software interrupt: vec=%d\n", (int)n);
+
+ if (bad_count == 5)
+ printf("Too many unknown software interrupts, quitting reporting them.\n");
+}
diff --git a/sys/arch/pc532/pc532/locore.s b/sys/arch/pc532/pc532/locore.s
new file mode 100644
index 00000000000..f468675555d
--- /dev/null
+++ b/sys/arch/pc532/pc532/locore.s
@@ -0,0 +1,1191 @@
+/* $NetBSD: locore.s,v 1.29.2.1 1995/10/17 00:19:05 phil 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.
+ *
+ * locore.s
+ *
+ * locore.s,v 1.2 1993/09/13 07:26:47 phil Exp
+ */
+
+/*
+ * locore.s - - assembler routines needed for BSD stuff. (ns32532/pc532)
+ *
+ * Phil Nelson, Dec 6, 1992
+ *
+ */
+
+/* This is locore.s! */
+#define LOCORE
+
+/* Get the defines... */
+#include <machine/asm.h>
+#include <machine/icu.h>
+#include "assym.h"
+
+/* define some labels */
+#define PSR_U 0x100
+#define PSR_S 0x200
+#define PSR_P 0x400
+#define PSR_I 0x800
+
+#define CFG_IVEC 0x1
+#define CFG_FPU 0x2
+#define CFG_MEM 0x4
+#define CFG_DE 0x100
+#define CFG_DATA 0x200
+#define CFG_DLCK 0x400
+#define CFG_INS 0x800
+#define CFG_ILCK 0x1000
+
+/* Initial Kernel stack page and the Idle processes' stack. */
+#define KERN_INT_SP 0xFFC00FFC
+
+/* Global Data */
+
+.data
+.globl _cold, __save_sp, __save_fp, __old_intbase
+_cold: .long 1
+__save_sp: .long 0
+__save_fp: .long 0
+__old_intbase: .long 0
+__have_fpu: .long 0
+
+.text
+.globl start
+start:
+ br here_we_go
+
+ .align 4 /* So the trap table is double aligned. */
+int_base_tab: /* Here is the fixed jump table for traps! */
+ .long __int
+ .long __trap_nmi
+ .long __trap_abt
+ .long __trap_slave
+ .long __trap_ill
+ .long __trap_svc
+ .long __trap_dvz
+ .long __trap_flg
+ .long __trap_bpt
+ .long __trap_trc
+ .long __trap_und
+ .long __trap_rbe
+ .long __trap_nbe
+ .long __trap_ovf
+ .long __trap_dbg
+ .long __trap_reserved
+
+here_we_go: /* This is the actual start of the locore code! */
+
+ bicpsrw PSR_I /* make sure interrupts are off. */
+ bicpsrw PSR_S /* make sure we are using sp0. */
+ lprd sb, 0 /* gcc expects this. */
+ sprd sp, __save_sp(pc) /* save monitor's sp. */
+ sprd fp, __save_fp(pc) /* save monitor's fp. */
+ sprd intbase, __old_intbase(pc) /* save monitor's intbase. */
+
+.globl _bootdev
+.globl _boothowto
+ /* Save the registers loaded by the boot program ... if the kernel
+ was loaded by the boot program. */
+ cmpd 0xc1e86394, r3
+ bne zero_bss
+ movd r7, _boothowto(pc)
+ movd r6, _bootdev(pc)
+
+zero_bss:
+ /* Zero the bss segment. */
+ addr _end(pc),r0 # setup to zero the bss segment.
+ addr _edata(pc),r1
+ subd r1,r0 # compute _end - _edata
+ movd r0,tos # push length
+ addr _edata(pc),tos # push address
+ bsr _bzero # zero the bss segment
+
+ bsr __low_level_init /* Do the low level setup. */
+
+ lprd sp, KERN_INT_SP # use the idle/interrupt stack.
+ lprd fp, KERN_INT_SP # use the idle/interrupt stack.
+
+ /* Load cfg register is bF6 (IC,DC,DE,M,F) or bF4 */
+ sprd cfg, r0
+ tbitb 1, r0 /* Test the F bit! */
+ bfc cfg_no_fpu
+ movqd 1, __have_fpu(pc)
+ lprd cfg, 0xbf6
+ br jmphi
+
+cfg_no_fpu:
+ lprd cfg, 0xbf4
+
+/* Now jump to high addresses after starting mapping! */
+
+jmphi:
+ addr here(pc), r0
+ ord KERNBASE, r0
+ jump 0(r0)
+
+here:
+ lprd intbase, int_base_tab /* set up the intbase. */
+
+ /* stack and frame pointer are pointing at high memory. */
+
+ bsr _init532 /* Set thing up to call main()! */
+
+ /* Get the proc0 kernel stack and pcb set up. */
+ movd KERN_STK_START, r1 /* Standard sp start! */
+ lprd sp, r1 /* Load it! */
+ lprd fp, USRSTACK /* fp for the user. */
+ lprd usp, USRSTACK /* starting stack for the user. */
+
+ /* Build the "trap" frame to return to address 0 in user space! */
+ movw PSR_I|PSR_S|PSR_U, tos /* psr - user/user stack/interrupts */
+ movw 0, tos /* mod - 0! */
+ movd 0, tos /* pc - 0 after module table */
+ enter [],8 /* Extra space is for USP */
+ movqd 0, tos /* Zero the registers in the pcb. */
+ movqd 0, tos
+ movqd 0, tos
+ movqd 0, tos
+ movqd 0, tos
+ movqd 0, tos
+ movqd 0, tos
+ movqd 0, tos
+ movqd 0, REGS_SB(sp)
+
+ /* Now things should be ready to start _main! */
+
+ addr 0(sp), tos
+ bsr _main /* Start the kernel! */
+ movd tos, r0 /* Pop addr */
+
+ /* We should only get here in proc 1. */
+ movd _curproc(pc), r1
+ cmpqd 0, r1
+ beq main_panic
+ movd P_PID(r1),r0
+ cmpqd 1, r0
+ bne main_panic
+ lprd usp, REGS_USP(sp)
+ lprd sb, REGS_SB(sp)
+
+ exit [r0,r1,r2,r3,r4,r5,r6,r7]
+ rett 0
+
+main_panic:
+ addr main_panic_str(pc), tos
+ bsr _panic
+
+main_panic_str:
+ .asciz "After main -- no curproc or not proc 1."
+
+/* Signal support */
+.align 2
+.globl _sigcode
+.globl _esigcode
+_sigcode:
+ jsr 0(12(sp))
+ movd 103, r0
+ svc
+.align 2
+_esigcode:
+
+/* To get the ptb0 register set correctly. */
+
+ENTRY(_load_ptb0)
+ movd S_ARG0, r0
+ andd ~KERNBASE, r0
+ lmr ptb0, r0
+ ret 0
+
+ENTRY(_load_ptb1)
+ movd S_ARG0, r0
+ andd ~KERNBASE, r0
+ lmr ptb1, r0
+ ret 0
+
+ENTRY (_get_ptb0)
+ smr ptb0, r0
+ ret 0
+
+ENTRY (tlbflush)
+ smr ptb0, r0
+ lmr ptb0, r0
+ ret 0
+
+ENTRY (_get_sp_adr) /* for use in testing.... */
+ addr 4(sp), r0
+ ret 0
+
+ENTRY (_get_ret_adr)
+ movd 0(sp), r0
+ ret 0
+
+ENTRY (_get_fp_ret)
+ movd 4(fp), r0
+ ret 0
+
+ENTRY (_get_2fp_ret)
+ movd 4(0(fp)), r0
+ ret 0
+
+ENTRY (_get_fp)
+ addr 0(fp), r0
+ ret 0
+
+/* reboot the machine :) if possible */
+
+ENTRY(low_level_reboot)
+
+ movd -1,tos
+ bsr _splx
+ cmpqd 0,tos
+ ints_off /* Stop things! */
+ addr xxxlow(pc), r0 /* jump to low memory */
+ andd ~KERNBASE, r0
+ movd r0, tos
+ ret 0
+xxxlow:
+ lmr mcr, 0 /* Turn off mapping. */
+ lprd sp, __save_sp(pc) /* get monitor's sp. */
+ jump 0x10000032 /* Jump to the ROM! */
+
+
+/* To get back to the rom monitor .... */
+ENTRY(bpt_to_monitor)
+
+/* Switch to monitor's stack. */
+ ints_off
+ bicpsrw PSR_S /* make sure we are using sp0. */
+ sprd psr, tos /* Push the current psl. */
+ save [r1,r2,r3,r4]
+ sprd sp, r1 /* save kernel's sp */
+ sprd fp, r2 /* save kernel's fp */
+ sprd intbase, r3 /* Save current intbase. */
+ smr ptb0, r4 /* Save current ptd! */
+
+/* Change to low addresses */
+ lmr ptb0, _IdlePTD(pc) /* Load the idle ptd */
+ addr low(pc), r0
+ andd ~KERNBASE, r0
+ movd r0, tos
+ ret 0
+
+low:
+/* Turn off mapping. */
+ smr mcr, r0
+ lmr mcr, 0
+ lprd sp, __save_sp(pc) /* restore monitors sp */
+ lprd fp, __save_fp(pc) /* restore monitors fp */
+ lprd intbase, __old_intbase(pc) /* restore monitors intbase */
+ bpt
+
+/* Reload kernel stack AND return. */
+ lprd intbase, r3 /* restore kernel's intbase */
+ lprd fp, r2 /* restore kernel's fp */
+ lprd sp, r1 /* restore kernel's sp */
+ lmr mcr, r0
+ addr highagain(pc), r0
+ ord KERNBASE, r0
+ jump 0(r0)
+highagain:
+ lmr ptb0, r4 /* Get the last ptd! */
+ restore [r1,r2,r3,r4]
+ lprd psr, tos /* restore psl */
+ ints_on
+ ret 0
+
+
+/*===========================================================================*
+ * ram_size *
+ *===========================================================================*
+
+ char *
+ ram_size (start)
+ char *start;
+
+ Determines RAM size.
+
+ First attempt: write-and-read-back (WRB) each page from start
+ until WRB fails or get a parity error. This didn't work because
+ address decoding wraps around.
+
+ New algorithm:
+
+ ret = round-up-page (start);
+ loop:
+ if (!WRB or parity or wrap) return ret;
+ ret += pagesz; (* check end of RAM at powers of two *)
+ goto loop;
+
+ Several things make this tricky. First, the value read from
+ an address will be the same value written to the address if
+ the cache is on -- regardless of whether RAM is located at
+ the address. Hence the cache must be disabled. Second,
+ reading an unpopulated RAM address is likely to produce a
+ parity error. Third, a value written to an unpopulated address
+ can be held by capacitance on the bus and can be correctly
+ read back if there is no intervening bus cycle. Hence,
+ read and write two patterns.
+
+*/
+
+cfg_dc = 0x200
+pagesz = 0x1000
+pattern0 = 0xa5a5a5a5
+pattern1 = 0x5a5a5a5a
+nmi_vec = 0x44
+parity_clr = 0x28000050
+
+/*
+ r0 current page, return value
+ r1 old config register
+ r2 temp config register
+ r3 pattern0
+ r4 pattern1
+ r5 old nmi vector
+ r6 save word at @0
+ r7 save word at @4
+*/
+.globl _ram_size
+_ram_size:
+ enter [r1,r2,r3,r4,r5,r6,r7],0
+ # initialize things
+ movd @0,r6 #save 8 bytes of first page
+ movd @4,r7
+ movd 0,@0 #zero 8 bytes of first page
+ movd 0,@4
+ sprw cfg,r1 #turn off data cache
+ movw r1,r2 #r1 = old config
+ andw ~cfg_dc,r2 # was: com cfg_dc,r2
+ lprw cfg,r2
+ movd @nmi_vec,r5 #save old NMI vector
+ addr tmp_nmi(pc),@nmi_vec #tmp NMI vector
+ movd 8(fp),r0 #r0 = start
+ addr pagesz-1(r0),r0 #round up to page
+ andd ~(pagesz-1),r0 # was: com (pagesz-1),r0
+ movd pattern0,r3
+ movd pattern1,r4
+rz_loop:
+ movd r3,0(r0) #write 8 bytes
+ movd r4,4(r0)
+ lprw cfg,r2 #flush write buffer
+ cmpd r3,0(r0) #read back and compare
+ bne rz_exit
+ cmpd r4,4(r0)
+ bne rz_exit
+ cmpqd 0,@0 #check for address wrap
+ bne rz_exit
+ cmpqd 0,@4 #check for address wrap
+ bne rz_exit
+ addr pagesz(r0),r0 #next page
+ br rz_loop
+rz_exit:
+ movd r6,@0 #restore 8 bytes of first page
+ movd r7,@4
+ lprd cfg,r1 #turn data cache back on
+ movd r5,@nmi_vec #restore NMI vector
+ movd parity_clr,r2
+ movb 0(r2),r2 #clear parity status
+ exit [r1,r2,r3,r4,r5,r6,r7]
+ ret 0
+
+tmp_nmi: #come here if parity error
+ addr rz_exit(pc),0(sp) #modify return addr to exit
+ rett 0
+
+/* Low level kernel support routines. */
+
+/* External symbols that are needed. */
+/* .globl EX(cnt) */
+.globl EX(curproc)
+.globl EX(curpcb)
+.globl EX(qs)
+.globl EX(whichqs)
+.globl EX(want_resched)
+.globl EX(Cur_pl)
+
+/*
+ User/Kernel copy routines ... {fu,su}{word,byte} and copyin/coyinstr
+
+ These are "Fetch User" or "Save user" word or byte. They return -1 if
+ a page fault occurs on access.
+*/
+
+ENTRY(fuword)
+ENTRY(fuiword)
+ enter [r2],0
+ movd _curpcb(pc), r2
+ addr fusufault(pc), PCB_ONFAULT(r2)
+ movd 0(B_ARG0), r0
+ br fusu_ret
+
+ENTRY(fubyte)
+ENTRY(fuibyte)
+ enter [r2],0
+ movd _curpcb(pc), r2
+ addr fusufault(pc), PCB_ONFAULT(r2)
+ movzbd 0(B_ARG0), r0
+ br fusu_ret
+
+ENTRY(suword)
+ENTRY(suiword)
+ enter [r2],0
+ movqd 4, tos
+ movd B_ARG0, tos
+ bsr _check_user_write
+ adjspd -8
+ cmpqd 0, r0
+ bne fusufault
+ movd _curpcb(pc), r2
+ addr fusufault(pc), PCB_ONFAULT(r2)
+ movqd 0, r0
+ movd B_ARG1,0(B_ARG0)
+ br fusu_ret
+
+ENTRY(subyte)
+ENTRY(suibyte)
+ enter [r2],0
+ movqd 1, tos
+ movd B_ARG0, tos
+ bsr _check_user_write
+ adjspd -8
+ cmpqd 0, r0
+ bne fusufault
+ movd _curpcb(pc), r2
+ addr fusufault(pc), PCB_ONFAULT(r2)
+ movqd 0, r0
+ movb B_ARG1, 0(B_ARG0)
+ br fusu_ret
+
+fusufault:
+ movqd -1, r0
+fusu_ret:
+ movqd 0, PCB_ONFAULT(r2)
+ exit [r2]
+ ret 0
+
+/* Two more fu/su routines .... for now ... just return -1. */
+ENTRY(fuswintr)
+ENTRY(suswintr)
+ movqd -1, r0
+ ret 0
+
+/* C prototype: copyin ( int *usrc, int *kdst, u_int i)
+ C prototype: copyout ( int *ksrc, int *udst, u_int i)
+
+ i is the number of Bytes! to copy!
+
+ Similar code....
+ */
+
+ENTRY(copyout)
+ enter [r2,r3],0
+# Check for copying priviledges! i.e. copy on write!
+ movd B_ARG2, tos /* Length */
+ movd B_ARG1, tos /* adr */
+ bsr _check_user_write
+ adjspd -8
+ cmpqd 0, r0
+ bne cifault
+ br docopy
+
+ENTRY(copyin)
+ enter [r2,r3],0
+docopy:
+ movd _curpcb(pc), r3
+ addr cifault(pc), PCB_ONFAULT(r3)
+ movd B_ARG2, r0 /* Length! */
+ movd B_ARG0, r1 /* Src adr */
+ movd B_ARG1, r2 /* Dst adr */
+ movsb /* Move it! */
+ movqd 0, r0
+ movqd 0, PCB_ONFAULT(r3)
+ exit [r2,r3]
+ ret 0
+
+cifault:
+ movd EFAULT, r0
+ movd _curpcb(pc), r3
+ movqd 0, PCB_ONFAULT(r3)
+ exit [r2,r3]
+ ret 0
+
+
+/*****************************************************************************/
+
+/*
+ * The following primitives manipulate the run queues.
+ * _whichqs tells which of the 32 queues _qs
+ * have processes in them. Setrq 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_pri, divided by 4
+ * actually to shrink the 0-127 range of priorities into the 32 available
+ * queues.
+ */
+ .globl _whichqs,_qs,_cnt,_panic
+
+/*
+ * setrunqueue(struct proc *p);
+ * Insert a process on the appropriate queue. Should be called at splclock().
+ */
+ENTRY(setrunqueue)
+ movd S_ARG0, r0
+ movd r2, tos
+
+ cmpqd 0, P_BACK(r0) /* should not be on q already */
+ bne 1f
+ cmpqd 0, P_WCHAN(r0)
+ bne 1f
+ cmpb SRUN, P_STAT(r0)
+ bne 1f
+
+ movzbd P_PRIORITY(r0),r1
+ lshd -2,r1
+ sbitd r1,_whichqs(pc) /* set queue full bit */
+ addr _qs(pc)[r1:q], r1 /* locate q hdr */
+ movd P_BACK(r1),r2 /* locate q tail */
+ movd r1, P_FORW(r0) /* set p->p_forw */
+ movd r0, P_BACK(r1) /* update q's p_back */
+ movd r0, P_FORW(r2) /* update tail's p_forw */
+ movd r2, P_BACK(r0) /* set p->p_back */
+ movd tos, r2
+ ret 0
+
+1: addr 2f(pc),tos /* Was on the list! */
+ bsr _panic
+2: .asciz "setrunqueue problem!"
+
+/*
+ * remrq(struct proc *p);
+ * Remove a process from its queue. Should be called at splclock().
+ */
+ENTRY(remrq)
+ movd S_ARG0, r1
+ movd r2, tos
+ movzbd P_PRIORITY(r1), r0
+
+ lshd -2, r0
+ tbitd r0, _whichqs(pc)
+ bfc 1f
+
+ movd P_BACK(r1), r2 /* Address of prev. item */
+ movqd 0, P_BACK(r1) /* Clear reverse link */
+ movd P_FORW(r1), r1 /* Addr of next item. */
+ movd r1, P_FORW(r2) /* Unlink item. */
+ movd r2, P_BACK(r1)
+ cmpd r1, r2 /* r1 = r2 => empty queue */
+ bne 2f
+
+ cbitd r0, _whichqs(pc) /* mark q as empty */
+
+2: movd tos, r2
+ ret 0
+
+1: addr 2f(pc),tos /* No queue entry! */
+ bsr _panic
+2: .asciz "remrq problem!"
+
+/* Switch to another process from kernel code... */
+
+ENTRY(cpu_switch)
+ ints_off /* to make sure cpu_switch runs to completion. */
+ enter [r0,r1,r2,r3,r4,r5,r6,r7],0
+/* addqd 1, _cnt+V_SWTCH(pc) */
+
+ movd _curproc(pc), r0
+ cmpqd 0, r0
+ beq sw1
+
+ /* Save "kernel context" - - user context is saved at trap/svc.
+ Kernel registers are saved at entry to swtch. */
+
+ movd P_ADDR(r0), r0
+ sprd sp, PCB_KSP(r0)
+ sprd fp, PCB_KFP(r0)
+ smr ptb0, PCB_PTB(r0)
+
+ /* Save the Cur_pl. */
+ movd _Cur_pl(pc), PCB_PL(r0)
+
+ movqd 0, _curproc(pc) /* no current proc! */
+
+sw1: /* Get something from a Queue! */
+ ints_off /* Just in case we came from Idle. */
+ movqd 0, r0
+ ffsd _whichqs(pc), r0
+ bfs Idle
+
+ /* Get the process and unlink it from the queue. */
+ addr _qs(pc)[r0:q], r1 /* address of qs entry! */
+ movd 0(r1), r2 /* get process pointer! */
+ movd P_FORW(r2), r3 /* get address of next entry. */
+
+ /* Test code */
+ cmpqd 0, r3
+ bne notzero
+ bsr _dump_qs
+notzero:
+
+ /* unlink the entry. */
+ movd r3, 0(r1) /* New head pointer. */
+ movd r1, P_BACK(r3) /* New reverse pointer. */
+ cmpd r1, r3 /* Empty? */
+ bne restart
+
+ /* queue is empty, turn off whichqs. */
+ cbitd r0, _whichqs(pc)
+
+restart: /* r2 has pointer to new proc.. */
+
+ /* Reload the new kernel context ... r2 points to proc entry. */
+ movqd 0, P_BACK(r2) /* NULL p_forw */
+ movqd 0, _want_resched(pc) /* We did a resched! */
+ movd P_ADDR(r2), r3 /* get new pcb pointer */
+
+
+ /* Do we need to reload floating point here? */
+
+ lmr ptb0, PCB_PTB(r3)
+ lprd sp, PCB_KSP(r3)
+ lprd fp, PCB_KFP(r3)
+ movw PCB_FLAGS(r3), r4 /* Get the flags. */
+
+ movd r2, _curproc(pc)
+ movd r3, _curpcb(pc)
+
+ /* Restore the previous processor level. */
+ movd PCB_PL(r3), tos
+ bsr _splx
+ cmpqd 0,tos
+ /* Return to the caller of swtch! */
+ exit [r0,r1,r2,r3,r4,r5,r6,r7]
+ ret 0
+
+/*
+ * The idle process!
+ */
+Idle:
+ lprd sp, KERN_INT_SP /* Set up the "interrupt" stack. */
+ movqd 0, r0
+ ffsd _whichqs(pc), r0
+ bfc sw1
+ movd _imask(pc),tos
+ bsr _splx
+ cmpqd 0,tos
+ wait /* Wait for interrupt. */
+ br sw1
+
+/* As part of the fork operation, we need to prepare a user are for
+ execution, to be resumed by swtch()...
+
+ C proto is low_level_fork (struct user *up)
+
+ up is a pointer the the "user" struct in the child.
+ We copy the kernel stack and update the pcb of the child to
+ return from low_level_fork twice.
+
+ The first return should return a 0. The "second" return should
+ be because of a swtch() and should return a 1.
+
+*/
+
+ENTRY(low_level_fork)
+ enter [r0,r1,r2,r3,r4,r5,r6,r7],0
+
+ /* Save "kernel context" - - user context is saved at trap/svc.
+ Kernel registers are saved at entry to swtch. */
+
+ movd B_ARG0, r2 /* Gets the paddr field of child. */
+ sprd sp, PCB_KSP(r2)
+ sprd fp, PCB_KFP(r2)
+ /* Don't save ptb0 because child has a different ptb0! */
+ movd _Cur_pl(pc), PCB_PL(r2)
+
+ /* Copy the kernel stack from this process to new stack. */
+ addr 0(sp), r1 /* Source address */
+ movd r1, r3 /* Calculate the destination address */
+ subd USRSTACK, r3 /* Get the offset */
+ addd r3, r2 /* r2 had B_ARG0 in it. now the dest addr */
+ movd r2, r5 /* Save the destination address */
+ movd KSTK_SIZE, r0 /* Calculate the length of the kernel stack. */
+ subd r3, r0
+
+ movd r0, r4 /* Check for a double alligned stack. */
+ andd 3, r4
+ cmpqd 0, r4
+ beq kcopy
+ addr m_ll_fork(pc),tos /* panic if not double alligned. */
+ bsr _panic
+
+kcopy:
+ lshd -2,r0 /* Divide by 4 to get # of doubles. */
+ movsd /* Copy the stack! */
+
+ /* Set parent to return 0. */
+ movqd 0,28(sp)
+
+ /* Set child to return 1. */
+ movqd 1,28(r5)
+
+ exit [r0,r1,r2,r3,r4,r5,r6,r7]
+ ret 0
+
+m_ll_fork: .asciz "_low_level_fork: kstack not double alligned."
+
+/*
+ * savectx(struct pcb *pcb, int altreturn);
+ * Update pcb, saving current processor state and arranging for alternate
+ * return in cpu_switch() if altreturn is true.
+ */
+ENTRY(savectx)
+ enter [r0,r1,r2,r3,r4,r5,r6,r7],0
+ movd B_ARG0, r2
+ sprd sp,PCB_KSP(r2)
+ sprd fp,PCB_KFP(r2)
+ movd _Cur_pl(pc),PCB_PL(r2)
+ exit [r0,r1,r2,r3,r4,r5,r6,r7]
+ ret 0
+
+ENTRY(_trap_nmi)
+ enter [r0,r1,r2,r3,r4,r5,r6,r7],8
+ sprd usp, REGS_USP(sp)
+ sprd sb, REGS_SB(sp)
+ movqd 1, tos
+ br all_trap
+
+ENTRY(_trap_abt)
+ enter [r0,r1,r2,r3,r4,r5,r6,r7],8
+ sprd usp, REGS_USP(sp)
+ sprd sb, REGS_SB(sp)
+ movqd 2, tos
+ smr tear, tos
+ smr msr, tos
+ br abt_trap
+
+ENTRY(_trap_slave)
+ enter [r0,r1,r2,r3,r4,r5,r6,r7],8
+ sprd usp, REGS_USP(sp)
+ sprd sb, REGS_SB(sp)
+ movqd 3, tos
+ br all_trap
+
+ENTRY(_trap_ill)
+ enter [r0,r1,r2,r3,r4,r5,r6,r7],8
+ sprd usp, REGS_USP(sp)
+ sprd sb, REGS_SB(sp)
+ movqd 4, tos
+ br all_trap
+
+ENTRY(_trap_svc)
+ enter [r0,r1,r2,r3,r4,r5,r6,r7],8
+ sprd usp, REGS_USP(sp)
+ sprd sb, REGS_SB(sp)
+ lprd sb, 0 /* for the kernel */
+
+ /* Have an fpu? */
+ cmpqd 0, __have_fpu(pc)
+ beq svc_no_fpu
+
+ /* Save the FPU registers. */
+ movd _curpcb(pc), r3
+ sfsr PCB_FSR(r3)
+ movl f0,PCB_F0(r3)
+ movl f1,PCB_F1(r3)
+ movl f2,PCB_F2(r3)
+ movl f3,PCB_F3(r3)
+ movl f4,PCB_F4(r3)
+ movl f5,PCB_F5(r3)
+ movl f6,PCB_F6(r3)
+ movl f7,PCB_F7(r3)
+
+ /* Call the system. */
+ bsr _syscall
+
+ /* Restore the FPU registers. */
+ movd _curpcb(pc), r3
+ lfsr PCB_FSR(r3)
+ movl PCB_F0(r3),f0
+ movl PCB_F1(r3),f1
+ movl PCB_F2(r3),f2
+ movl PCB_F3(r3),f3
+ movl PCB_F4(r3),f4
+ movl PCB_F5(r3),f5
+ movl PCB_F6(r3),f6
+ movl PCB_F7(r3),f7
+
+ /* Restore the usp and sb. */
+ lprd usp, REGS_USP(sp)
+ lprd sb, REGS_SB(sp)
+
+ exit [r0,r1,r2,r3,r4,r5,r6,r7]
+ rett 0
+
+svc_no_fpu:
+ /* Call the system. */
+ bsr _syscall
+
+ /* Restore the usp and sb. */
+ lprd usp, REGS_USP(sp)
+ lprd sb, REGS_SB(sp)
+
+ exit [r0,r1,r2,r3,r4,r5,r6,r7]
+ rett 0
+
+ENTRY(_trap_dvz)
+ enter [r0,r1,r2,r3,r4,r5,r6,r7],8
+ sprd usp, REGS_USP(sp)
+ sprd sb, REGS_SB(sp)
+ movqd 6, tos
+ br all_trap
+
+ENTRY(_trap_flg)
+ cinv ia, r0
+ addqd 1, tos /* Increment return address */
+ rett 0
+
+ENTRY(_trap_bpt)
+ enter [r0,r1,r2,r3,r4,r5,r6,r7],8
+ sprd usp, REGS_USP(sp)
+ sprd sb, REGS_SB(sp)
+ movd 8, tos
+ br all_trap
+
+ENTRY(_trap_trc)
+ enter [r0,r1,r2,r3,r4,r5,r6,r7],8
+ sprd usp, REGS_USP(sp)
+ sprd sb, REGS_SB(sp)
+ movd 9, tos
+ br all_trap
+
+ENTRY(_trap_und)
+ enter [r0,r1,r2,r3,r4,r5,r6,r7],8
+ sprd usp, REGS_USP(sp)
+ sprd sb, REGS_SB(sp)
+ movd 10, tos
+ br all_trap
+
+ENTRY(_trap_rbe)
+ enter [r0,r1,r2,r3,r4,r5,r6,r7],8
+ sprd usp, REGS_USP(sp)
+ sprd sb, REGS_SB(sp)
+ movd 11, tos
+ br all_trap
+
+ENTRY(_trap_nbe)
+ enter [r0,r1,r2,r3,r4,r5,r6,r7],8
+ sprd usp, REGS_USP(sp)
+ sprd sb, REGS_SB(sp)
+ movd 12, tos
+ br all_trap
+
+ENTRY(_trap_ovf)
+ enter [r0,r1,r2,r3,r4,r5,r6,r7],8
+ sprd usp, REGS_USP(sp)
+ sprd sb, REGS_SB(sp)
+ movd 13, tos
+ br all_trap
+
+ENTRY(_trap_dbg)
+ enter [r0,r1,r2,r3,r4,r5,r6,r7],8
+ sprd usp, REGS_USP(sp)
+ sprd sb, REGS_SB(sp)
+ movd 14, tos
+ br all_trap
+
+ENTRY(_trap_reserved)
+ enter [r0,r1,r2,r3,r4,r5,r6,r7],8
+ sprd usp, REGS_USP(sp)
+ sprd sb, REGS_SB(sp)
+ movd 15, tos
+all_trap:
+ movqd 0,tos /* Add 2 zeros for msr,tear in frame. */
+ movqd 0,tos
+
+abt_trap:
+ lprd sb, 0 /* for the kernel */
+
+ /* Was this a real process? */
+ cmpqd 0, _curproc(pc)
+ beq trap_no_fpu
+
+ /* Have an fpu? */
+ cmpqd 0, __have_fpu(pc)
+ beq trap_no_fpu
+
+ /* Save the FPU registers. */
+ movd _curpcb(pc), r3 /* R3 is saved by gcc. */
+ sfsr PCB_FSR(r3)
+ movl f0,PCB_F0(r3)
+ movl f1,PCB_F1(r3)
+ movl f2,PCB_F2(r3)
+ movl f3,PCB_F3(r3)
+ movl f4,PCB_F4(r3)
+ movl f5,PCB_F5(r3)
+ movl f6,PCB_F6(r3)
+ movl f7,PCB_F7(r3)
+
+ bsr _trap
+ adjspd -12 /* Pop off software part of trap frame. */
+
+ /* Restore the FPU registers. */
+ lfsr PCB_FSR(r3)
+ movl PCB_F0(r3),f0
+ movl PCB_F1(r3),f1
+ movl PCB_F2(r3),f2
+ movl PCB_F3(r3),f3
+ movl PCB_F4(r3),f4
+ movl PCB_F5(r3),f5
+ movl PCB_F6(r3),f6
+ movl PCB_F7(r3),f7
+
+ /* Reload the usp and sb just in case anything has changed. */
+ lprd usp, REGS_USP(sp)
+ lprd sb, REGS_SB(sp)
+
+ exit [r0,r1,r2,r3,r4,r5,r6,r7]
+ rett 0
+
+trap_no_fpu:
+ bsr _trap
+ adjspd -12 /* Pop off software part of trap frame. */
+
+ /* Reload the usp and sb just in case anything has changed. */
+ lprd usp, REGS_USP(sp)
+ lprd sb, REGS_SB(sp)
+
+ exit [r0,r1,r2,r3,r4,r5,r6,r7]
+ rett 0
+
+/* Interrupt service routines.... */
+ENTRY(_int)
+ enter [r0,r1,r2,r3,r4,r5,r6,r7],8
+ sprd usp,REGS_USP(sp)
+ sprd sb,REGS_SB(sp)
+ lprd sb,0 /* for the kernel */
+ movd _Cur_pl(pc), tos
+ movb @ICU_ADR+HVCT,r0 /* fetch vector */
+ andd 0x0f,r0
+ movd r0,tos
+ movqd 1,r1
+ lshd r0,r1
+ orw r1,_Cur_pl(pc) /* or bit to Cur_pl */
+ orw r1,@ICU_ADR+IMSK /* and to IMSK */
+ /* bits set by idisabled in IMSK */
+ /* have to be preserved */
+ ints_off /* flush pending writes */
+ ints_on /* and now turn ints on */
+ addqd 1,_intrcnt(pc)[r0:d]
+ lshd 4,r0
+ addqd 1,_cnt+V_INTR(pc)
+ addqd 1,_ivt+IV_CNT(r0) /* increment counters */
+ movd _ivt+IV_ARG(r0),r1 /* get argument */
+ cmpqd 0,r1
+ bne 1f
+ addr 0(sp),r1 /* NULL -> push frame address */
+1: movd r1,tos
+ movd _ivt+IV_VEC(r0),r0 /* call the handler */
+ jsr 0(r0)
+
+ adjspd -8 /* Remove arg and vec from stack */
+ bsr _splx_di /* Restore Cur_pl */
+ cmpqd 0,tos
+
+ tbitw 8, REGS_PSR(sp) /* In system mode? */
+ bfs do_user_intr /* branch if yes! */
+
+ lprd usp, REGS_USP(sp)
+ lprd sb, REGS_SB(sp)
+ exit [r0,r1,r2,r3,r4,r5,r6,r7]
+ rett 0
+
+do_user_intr:
+ /* Do "user" mode interrupt processing, including preemption. */
+ ints_off
+ movd _curproc(pc), r2
+ cmpqd 0,r2
+ beq intr_panic
+
+ /* Have an fpu? */
+ cmpqd 0, __have_fpu(pc)
+ beq intr_no_fpu
+
+ /* Save the FPU registers. */
+ movd _curpcb(pc), r3 /* R3 is saved by gcc. */
+ sfsr PCB_FSR(r3)
+ movl f0,PCB_F0(r3)
+ movl f1,PCB_F1(r3)
+ movl f2,PCB_F2(r3)
+ movl f3,PCB_F3(r3)
+ movl f4,PCB_F4(r3)
+ movl f5,PCB_F5(r3)
+ movl f6,PCB_F6(r3)
+ movl f7,PCB_F7(r3)
+
+intr_no_fpu:
+ /* turn on interrupts! */
+ ints_on
+
+ cmpqd 0, _want_resched(pc)
+ beq do_usr_ret
+ movd 18, tos
+ movqd 0,tos
+ movqd 0,tos
+ bsr _trap
+ adjspd -12 /* Pop off software part of trap frame. */
+
+do_usr_ret:
+
+ /* Have an fpu? */
+ cmpqd 0, __have_fpu(pc)
+ beq intr_ret_no_fpu
+
+ /* Restore the FPU registers. r3 should be as set before. */
+ lfsr PCB_FSR(r3)
+ movl PCB_F0(r3),f0
+ movl PCB_F1(r3),f1
+ movl PCB_F2(r3),f2
+ movl PCB_F3(r3),f3
+ movl PCB_F4(r3),f4
+ movl PCB_F5(r3),f5
+ movl PCB_F6(r3),f6
+ movl PCB_F7(r3),f7
+
+intr_ret_no_fpu:
+ lprd usp, REGS_USP(sp)
+ lprd sb, REGS_SB(sp)
+ exit [r0,r1,r2,r3,r4,r5,r6,r7]
+ rett 0
+
+intr_panic:
+ addr intr_panic_msg(pc),tos /* panic if not double alligned. */
+ bsr _panic
+
+intr_panic_msg:
+ .asciz "user mode interrupt with no current process!"
+
+/* Include all other .s files. */
+#include "bcopy.s"
+#include "bzero.s"
+
+
+/* pmap support??? ..... */
+
+/*
+ * Note: This version greatly munged to avoid various assembler errors
+ * that may be fixed in newer versions of gas. Perhaps newer versions
+ * will have more pleasant appearance.
+ */
+
+ .set IDXSHIFT,10
+ .set SYSTEM,0xFE000000 # virtual address of system start
+ /*note: gas copys sign bit (e.g. arithmetic >>), can't do SYSTEM>>22! */
+ .set SYSPDROFF,0x3F8 # Page dir index of System Base
+
+/*
+ * PTmap is recursive pagemap at top of virtual address space.
+ * Within PTmap, the page directory can be found (third indirection).
+ */
+#define PDRPDROFF 0x03F7 /* page dir index of page dir */
+ .globl _PTmap, _PTD, _PTDpde, _Sysmap
+ .set _PTmap,0xFDC00000
+ .set _PTD,0xFDFF7000
+ .set _Sysmap,0xFDFF8000
+ .set _PTDpde,0xFDFF7000+4*PDRPDROFF
+
+/*
+ * APTmap, APTD is the alternate recursive pagemap.
+ * It's used when modifying another process's page tables.
+ */
+#define APDRPDROFF 0x03FE /* page dir index of page dir */
+ .globl _APTmap, _APTD, _APTDpde
+ .set _APTmap,0xFF800000
+ .set _APTD,0xFFBFE000
+ .set _APTDpde,0xFDFF7000+4*APDRPDROFF
+
+/*
+ * Access to each processes kernel stack is via a region of
+ * per-process address space (at the beginning), immediatly above
+ * the user process stack.
+ */
+#if 0
+ .set _kstack, USRSTACK
+ .globl _kstack
+#endif
+ .set PPDROFF,0x3F6
+/* # .set PPTEOFF,0x400-UPAGES # 0x3FE */
+ .set PPTEOFF,0x3FE
+
+.data
+.globl _PDRPDROFF
+_PDRPDROFF:
+ .long PDRPDROFF
+
+/* vmstat -i uses the following labels and __int even increments the
+ * counters. This information is also availiable from ivt[n].iv_use
+ * and ivt[n].iv_cnt in much better form.
+ */
+ .globl _intrnames, _eintrnames, _intrcnt, _eintrcnt
+_intrnames:
+ .asciz "int 0"
+ .asciz "int 1"
+ .asciz "int 2"
+ .asciz "int 3"
+ .asciz "int 4"
+ .asciz "int 5"
+ .asciz "int 6"
+ .asciz "int 7"
+ .asciz "int 8"
+ .asciz "int 9"
+ .asciz "int 10"
+ .asciz "int 11"
+ .asciz "int 12"
+ .asciz "int 13"
+ .asciz "int 14"
+ .asciz "int 15"
+_eintrnames:
+_intrcnt:
+ .long 0
+ .long 0
+ .long 0
+ .long 0
+ .long 0
+ .long 0
+ .long 0
+ .long 0
+ .long 0
+ .long 0
+ .long 0
+ .long 0
+ .long 0
+ .long 0
+ .long 0
+ .long 0
+_eintrcnt:
diff --git a/sys/arch/pc532/pc532/machdep.c b/sys/arch/pc532/pc532/machdep.c
new file mode 100644
index 00000000000..a1b98265e35
--- /dev/null
+++ b/sys/arch/pc532/pc532/machdep.c
@@ -0,0 +1,1121 @@
+/* $NetBSD: machdep.c,v 1.40.2.1 1995/10/17 00:19:08 phil Exp $ */
+
+/*-
+ * Copyright (c) 1982, 1987, 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * William Jolitz.
+ *
+ * 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 7.4 (Berkeley) 6/3/91
+ */
+
+/*
+ * Modified for the pc532 by Phil Nelson. 2/3/93
+ */
+
+static char rcsid[] = "/b/source/CVS/src/sys/arch/pc532/pc532/machdep.c,v 1.2 1993/09/13 07:26:49 phil Exp";
+
+#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/user.h>
+#include <sys/exec.h>
+#include <sys/buf.h>
+#include <sys/reboot.h>
+#include <sys/conf.h>
+#include <sys/file.h>
+#include <sys/callout.h>
+#include <sys/malloc.h>
+#include <sys/mbuf.h>
+#include <sys/msgbuf.h>
+#include <sys/vnode.h>
+#include <sys/device.h>
+#include <sys/sysctl.h>
+#include <sys/mount.h>
+#include <sys/syscallargs.h>
+
+#include <dev/cons.h>
+
+#include <net/netisr.h>
+
+#include <vm/vm.h>
+#include <vm/vm_kern.h>
+#include <vm/vm_page.h>
+
+#include <machine/psl.h>
+#include <machine/reg.h>
+#include <machine/cpu.h>
+#include <machine/pmap.h>
+#include <machine/icu.h>
+
+extern vm_offset_t avail_end;
+extern struct user *proc0paddr;
+
+vm_map_t buffer_map;
+
+/* A local function... */
+void reboot_cpu();
+void dumpsys __P((void));
+
+
+/* the following is used externally (sysctl_hw) */
+char machine[] = "pc532";
+char cpu_model[] = "ns32532";
+
+/*
+ * 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 */
+
+
+/* Real low level initialization. This is called in unmapped mode and
+ sets up the inital page directory and page tables for the kernel.
+ This routine is the first to be called by locore.s to get the
+ kernel running at the correct place in memory.
+ */
+
+extern char end[], _edata[];
+extern vm_offset_t avail_start;
+extern vm_offset_t avail_end;
+
+int physmem = 0;
+int maxmem = 0;
+
+vm_offset_t KPTphys;
+
+int IdlePTD;
+int start_page;
+int _istack;
+
+int low_mem_map;
+
+/* Support for VERY low debugging ... in case we get NO output.
+ (e.g. in case pmap does not work and can't do regular mapped
+ output. */
+#if VERYLOWDEBUG
+#include <pc532/umprintf.c>
+#endif
+
+void
+_low_level_init ()
+{
+ int ix, ix1, ix2;
+ int p0, p1, p2;
+ extern int _mapped;
+
+#if VERYLOWDEBUG
+ umprintf ("starting low level init\n");
+#endif
+
+ mem_size = ram_size(end);
+ physmem = btoc(mem_size);
+ start_page = (((int)&end + NS532_PAGE_SIZE) & ~(NS532_PAGE_SIZE-1))
+ & 0xffffff;
+ avail_start = start_page;
+ avail_end = mem_size - NS532_PAGE_SIZE;
+
+#if VERYLOWDEBUG
+ umprintf ("mem_size = 0x%x\nphysmem=%x\nstart_page=0x%x\navail_end=0x%x\n",
+ mem_size, physmem, start_page, avail_end);
+#endif
+
+
+ /* Initialize the mmu with a simple memory map. */
+
+ /* A new interrupt stack, i.e. not the rom monitor's. */
+ _istack = avail_start;
+ avail_start += NS532_PAGE_SIZE;
+
+ /* The page directory that starts the entire mapping. */
+ p0 = (int) avail_start;
+ IdlePTD = p0;
+ KPTphys = p0;
+ avail_start += NS532_PAGE_SIZE;
+
+ /* First clear out the page table directory. */
+ bzero((char *)p0, NS532_PAGE_SIZE);
+
+ /* Now for the memory mapped I/O, the ICU and the eprom. */
+ p1 = (int) avail_start;
+ avail_start += NS532_PAGE_SIZE;
+ bzero ((char *)p1, NS532_PAGE_SIZE);
+
+ /* Addresses here start at FFC00000... */
+
+ /* Map the interrupt stack to FFC00000 - FFC00FFF */
+ WR_ADR(int, p1, _istack+3);
+
+ /* All futhur entries are cache inhibited. => 0x4? in low bits. */
+
+ /* The Duarts and Parity. Addresses FFC80000 */
+ WR_ADR(int, p1+4*0x80, 0x28000043);
+
+ /* SCSI Polled (Reduced space.) Addresses FFD00000 - FFDFFFFF */
+ for (ix = 0x100; ix < 0x200; ix++)
+ WR_ADR(int, p1 + ix*4, 0x30000043 + ((ix - 0x100)<<12));
+
+ /* SCSI "DMA" (Reduced space.) Addresses FFE00000 - FFEEFFFF */
+ for (ix = 0x200; ix < 0x2ff; ix++)
+ WR_ADR(int, p1 + ix*4, 0x38000043 + ((ix - 0x200)<<12));
+
+ /* SCSI "DMA" With A22 (EOP) Addresses FFEFF000 - FFEFFFFF */
+ WR_ADR(int, p1 + 0x2ff*4, 0x38400043);
+
+ /* The e-prom Addresses FFF00000 - FFF3FFFF */
+ for (ix = 0x300; ix < 0x340; ix++)
+ WR_ADR(int, p1 + ix*4, 0x10000043 + ((ix - 0x300)<<12));
+
+ /* Finally the ICU! Addresses FFFFF000 - FFFFFFFF */
+ WR_ADR(int, p1+4*0x3ff, 0xFFFFF043);
+
+ /* Add the memory mapped I/O entry in the directory. */
+ WR_ADR(int, p0+4*1023, p1 + 0x43);
+
+ /* Map the kernel pages starting at FE00000 and at 0.
+ It also maps any pages past the end of the kernel,
+ up to the value of avail_start at this point.
+ These pages currently are:
+ 1 - interrupt stack
+ 2 - Top level page table
+ 3 - 2nd level page table for I/O
+ 4 - 2nd level page table for the kernel & low memory
+ 5-7 will be allocated as 2nd level page tables by pmap_bootstrap.
+ */
+
+ low_mem_map = p2 = (int) avail_start;
+ avail_start += NS532_PAGE_SIZE;
+ bzero ((char *)p2, NS532_PAGE_SIZE);
+ WR_ADR(int,p0+4*pdei(KERNBASE), p2 + 3);
+ WR_ADR(int,p0, p2+3);
+
+ for (ix = 0; ix < (avail_start)/NS532_PAGE_SIZE; ix++) {
+ WR_ADR(int, p2 + ix*4, NS532_PAGE_SIZE * ix + 3);
+ }
+
+ /* Load the ptb0 register and start mapping. */
+
+ _mapped = 1;
+ _load_ptb0 (p0);
+ asm(" lmr mcr, 3"); /* Start the machine mapping, 1 vm space. */
+
+}
+
+extern void icu_init();
+
+/* init532 is the first procedure called in mapped mode by locore.s
+ */
+
+init532()
+{
+ int free_pages;
+ void (**int_tab)();
+ extern int _save_sp;
+
+/*#include "ddb.h" */
+#if NDDB > 0
+ kdb_init();
+ if (boothowto & RB_KDB)
+ Debugger();
+#endif
+
+ /* Initialize the pmap stuff.... */
+ pmap_bootstrap (avail_start, 0);
+ /* now running on new page tables, configured, and u/iom is accessible */
+
+ /* Set up the proc0paddr struct. */
+ proc0paddr->u_pcb.pcb_flags = 0;
+ proc0paddr->u_pcb.pcb_pl = 0xffffffff;
+ proc0paddr->u_pcb.pcb_ptb = IdlePTD;
+ proc0paddr->u_pcb.pcb_onstack =
+ (struct on_stack *) proc0paddr + UPAGES*NBPG
+ - sizeof (struct on_stack);
+
+ /* Set up the ICU. */
+ icu_init();
+ intr_init();
+}
+
+
+/*
+ * Machine-dependent startup code
+ */
+int boothowto = 0, Maxmem = 0;
+long dumplo;
+int physmem, maxmem;
+
+extern int bootdev;
+extern cyloffset;
+
+/* pmap_enter prototype */
+void pmap_enter __P((register pmap_t, vm_offset_t, register vm_offset_t,
+ vm_prot_t, boolean_t));
+
+void
+cpu_startup(void)
+{
+ register int unixsize;
+ register unsigned i;
+ register struct pte *pte;
+ int mapaddr, j;
+ register caddr_t v;
+ int maxbufs, base, residual;
+ extern long Usrptsize;
+ vm_offset_t minaddr, maxaddr;
+ vm_size_t size;
+ int firstaddr;
+
+ /*
+ * Initialize error message buffer (at end of core).
+ */
+
+ /* avail_end was pre-decremented in pmap_bootstrap to compensate */
+ for (i = 0; i < btoc(sizeof (struct msgbuf)); i++)
+ pmap_enter(pmap_kernel(), (vm_offset_t) msgbufp,
+ avail_end + i * NBPG, VM_PROT_ALL, TRUE);
+ msgbufmapped = 1;
+
+#ifdef KDB
+ kdb_init(); /* startup kernel debugger */
+#endif
+ /*
+ * Good {morning,afternoon,evening,night}.
+ */
+ printf(version);
+ printf("\nreal mem = 0x%x\n", ctob(physmem));
+
+ /*
+ * Allocate space for system data structures.
+ * The first available kernel virtual address is in "v".
+ * As pages of kernel virtual memory are allocated, "v" is incremented.
+ * As pages of memory are allocated and cleared,
+ * "firstaddr" is incremented.
+ * An index into the kernel page table corresponding to the
+ * virtual memory address maintained in "v" is kept in "mapaddr".
+ */
+
+ /*
+ * Make two passes. The first pass calculates how much memory is
+ * needed and allocates it. The second pass assigns virtual
+ * addresses to the various data structures.
+ */
+ firstaddr = 0;
+again:
+ v = (caddr_t)firstaddr;
+
+#define valloc(name, type, num) \
+ (name) = (type *)v; v = (caddr_t)((name)+(num))
+#define valloclim(name, type, num, lim) \
+ (name) = (type *)v; v = (caddr_t)((lim) = ((name)+(num)))
+ valloc(callout, struct callout, ncallout);
+ valloc(swapmap, struct map, nswapmap = maxproc * 2);
+#ifdef SYSVSHM
+ valloc(shmsegs, struct shmid_ds, shminfo.shmmni);
+#endif
+ /*
+ * Determine how many buffers to allocate.
+ * Use 10% of memory for the first 2 Meg, 5% of the remaining
+ * memory. Insure a minimum of 16 buffers.
+ * We allocate 1/2 as many swap buffer headers as file i/o buffers.
+ */
+ if (bufpages == 0)
+ if (physmem < (2 * 1024 * 1024))
+ bufpages = physmem / 10 / CLSIZE;
+ else
+ bufpages = ((2 * 1024 * 1024 + physmem) / 20) / CLSIZE;
+
+ bufpages = min(NKMEMCLUSTERS*2/5, bufpages); /* XXX ? - cgd */
+
+ if (nbuf == 0) {
+ nbuf = bufpages / 2;
+ if (nbuf < 16) {
+ nbuf = 16;
+ /* XXX (cgd) -- broken vfs_bio currently demands this */
+ bufpages = 32;
+ }
+ }
+
+ if (nswbuf == 0) {
+ nswbuf = (nbuf / 2) &~ 1; /* force even */
+ if (nswbuf > 256)
+ nswbuf = 256; /* sanity */
+ }
+ valloc(swbuf, struct buf, nswbuf);
+ valloc(buf, struct buf, nbuf);
+
+ /*
+ * End of first pass, size has been calculated so allocate memory
+ */
+ if (firstaddr == 0) {
+ size = (vm_size_t)(v - firstaddr);
+ firstaddr = (int)kmem_alloc(kernel_map, round_page(size));
+ if (firstaddr == 0)
+ panic("startup: no room for tables");
+ goto again;
+ }
+
+ /*
+ * End of second pass, addresses have been assigned
+ */
+ if ((vm_size_t)(v - firstaddr) != size)
+ panic("startup: table size inconsistency");
+
+ /*
+ * Now allocate buffers proper. They are different than the above
+ * in that they usually occupy more virtual memory than physical.
+ */
+ size = MAXBSIZE * nbuf;
+ buffer_map = kmem_suballoc(kernel_map, (vm_offset_t *)&buffers,
+ &maxaddr, size, TRUE);
+ minaddr = (vm_offset_t)buffers;
+ if (vm_map_find(buffer_map, vm_object_allocate(size), (vm_offset_t)0,
+ &minaddr, size, FALSE) != KERN_SUCCESS)
+ panic("startup: cannot allocate buffers");
+ base = bufpages / nbuf;
+ residual = bufpages % nbuf;
+ if (base >= MAXBSIZE) {
+ /* don't want to alloc more physical mem than needed */
+ base = MAXBSIZE;
+ residual = 0;
+ }
+ 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];
+
+ printf("avail mem = 0x%x\n", ptoa(cnt.v_free_count));
+ printf("using %d buffers containing %d bytes of memory\n",
+ nbuf, bufpages * CLBYTES);
+
+ /*
+ * Set up buffers, so they can be used to read disk labels.
+ */
+ bufinit();
+
+ /*
+ * Configure the system.
+ */
+ configure();
+}
+
+#ifdef PGINPROF
+/*
+ * Return the difference (in microseconds)
+ * between the current time and a previous
+ * time as represented by the arguments.
+ * If there is a pending clock interrupt
+ * which has not been serviced due to high
+ * ipl, return error code.
+ */
+/*ARGSUSED*/
+vmtime(otime, olbolt, oicr)
+ register int otime, olbolt, oicr;
+{
+
+ return (((time.tv_sec-otime)*60 + lbolt-olbolt)*16667);
+}
+#endif
+
+/*
+ * Send an interrupt to process.
+ *
+ * Stack is set up to allow sigcode stored
+ * in u. to call routine, followed by kcall
+ * to sigreturn routine below. After sigreturn
+ * resets the signal mask, the stack, and the
+ * frame pointer, it returns to the user
+ * specified pc, psl.
+ */
+
+void
+sendsig(catcher, sig, mask, code)
+ sig_t catcher;
+ int sig, mask;
+ u_long code;
+{
+ register struct proc *p = curproc;
+ register int *regs;
+ register struct sigframe *fp;
+ struct sigacts *ps = p->p_sigacts;
+ int oonstack;
+ extern char sigcode[], esigcode[];
+
+ regs = p->p_md.md_regs;
+ oonstack = ps->ps_sigstk.ss_flags & SS_ONSTACK;
+
+ /*
+ * Allocate space for the signal handler context.
+ */
+ if ((ps->ps_flags & SAS_ALTSTACK) && !oonstack &&
+ (ps->ps_sigonstack & sigmask(sig))) {
+ fp = (struct sigframe *)(ps->ps_sigstk.ss_base +
+ ps->ps_sigstk.ss_size - sizeof(struct sigframe));
+ ps->ps_sigstk.ss_flags |= SS_ONSTACK;
+ } else {
+ fp = (struct sigframe *)(regs[REG_SP]
+ - sizeof(struct sigframe));
+ }
+
+ if ((unsigned)fp <= (unsigned)p->p_vmspace->vm_maxsaddr + MAXSSIZ - ctob(p->p_vmspace->vm_ssize))
+ (void)grow(p, (unsigned)fp);
+
+ if (useracc((caddr_t)fp, sizeof (struct sigframe), B_WRITE) == 0) {
+ /*
+ * 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.
+ */
+ fp->sf_signum = sig;
+ fp->sf_code = code;
+ fp->sf_scp = &fp->sf_sc;
+ fp->sf_handler = catcher;
+
+ /* save registers */
+ bcopy (regs, fp->sf_scp->sc_reg, 8*sizeof(int));
+
+ /*
+ * Build the signal context to be used by sigreturn.
+ */
+ fp->sf_sc.sc_onstack = oonstack;
+ fp->sf_sc.sc_mask = mask;
+ fp->sf_sc.sc_sp = regs[REG_SP];
+ fp->sf_sc.sc_fp = regs[REG_FP];
+ fp->sf_sc.sc_pc = regs[REG_PC];
+ fp->sf_sc.sc_ps = regs[REG_PSR];
+ fp->sf_sc.sc_sb = regs[REG_SB];
+ regs[REG_SP] = (int)fp;
+ regs[REG_PC] = (int)(((char *)PS_STRINGS) - (esigcode - sigcode));
+}
+
+/*
+ * 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.
+ */
+int
+sys_sigreturn(p, v, retval)
+ struct proc *p;
+ void *v;
+ register_t *retval;
+{
+ struct sys_sigreturn_args /* {
+ syscallarg(struct sigcontext *) sigcntxp;
+ } */ *uap = v;
+ register struct sigcontext *scp;
+ register struct sigframe *fp;
+ register int *regs = p->p_md.md_regs;
+ fp = (struct sigframe *) regs[REG_SP] ;
+
+ if (useracc((caddr_t)fp, sizeof (*fp), 0) == 0)
+ return(EINVAL);
+
+ /* restore registers */
+ bcopy (fp->sf_scp->sc_reg, regs, 8*sizeof(int));
+
+ scp = fp->sf_scp;
+ if (useracc((caddr_t)scp, sizeof (*scp), 0) == 0)
+ return(EINVAL);
+#ifdef notyet
+ if ((scp->sc_ps & PSL_MBZ) != 0 || (scp->sc_ps & PSL_MBO) != PSL_MBO) {
+ return(EINVAL);
+ }
+#endif
+ if (scp->sc_onstack & 01)
+ p->p_sigacts->ps_sigstk.ss_flags |= SS_ONSTACK;
+ else
+ p->p_sigacts->ps_sigstk.ss_flags &= ~SS_ONSTACK;
+ p->p_sigmask = scp->sc_mask &~
+ (sigmask(SIGKILL)|sigmask(SIGCONT)|sigmask(SIGSTOP));
+ regs[REG_FP] = scp->sc_fp;
+ regs[REG_SP] = scp->sc_sp;
+ regs[REG_PC] = scp->sc_pc;
+ regs[REG_PSR] = scp->sc_ps;
+ regs[REG_SB] = scp->sc_sb;
+ return(EJUSTRETURN);
+}
+
+int waittime = -1;
+struct pcb dumppcb;
+
+void
+boot(howto)
+ int howto;
+{
+ register int devtype; /* r10 == major of root dev */
+ extern const char *panicstr;
+ extern int cold;
+ int nomsg = 1;
+
+ if(cold) {
+ printf("cold boot: hit reset please");
+ for(;;);
+ }
+ boothowto = howto;
+ if ((howto&RB_NOSYNC) == 0 && waittime < 0) {
+ waittime = 0;
+ vfs_shutdown();
+ /*
+ * If we've been adjusting the clock, the todr
+ * will be out of synch; adjust it now. (non panic!)
+ */
+ if (panicstr == 0)
+ resettodr();
+
+ DELAY(10000); /* wait for printf to finish */
+ }
+ splhigh();
+ devtype = major(rootdev);
+
+ if (howto&RB_HALT) {
+ printf ("\nThe operating system has halted.\n\n");
+ cpu_reset();
+ for(;;) ;
+ /*NOTREACHED*/
+ } else {
+ if (howto & RB_DUMP) {
+ savectx(&dumppcb, 0);
+ dumppcb.pcb_ptb = _get_ptb0();
+ dumpsys();
+ }
+ }
+
+ printf("rebooting ...");
+ reboot_cpu();
+ for(;;) ;
+ /*NOTREACHED*/
+}
+
+void
+microtime(tvp)
+ register struct timeval *tvp;
+{
+ int s = splhigh();
+
+ *tvp = time;
+ tvp->tv_usec += tick;
+ while (tvp->tv_usec > 1000000) {
+ tvp->tv_sec++;
+ tvp->tv_usec -= 1000000;
+ }
+ splx(s);
+}
+
+/*
+ * Strange exec values! (Do we want to support a minix a.out header?)
+ */
+int
+cpu_exec_aout_makecmds()
+{
+ return ENOEXEC;
+};
+
+/*
+ * Clear registers on exec
+ */
+void
+setregs(p, entry, stack, retval)
+ struct proc *p;
+ struct exec_package *entry;
+ u_long stack;
+ register_t *retval;
+{
+ struct on_stack *r = (struct on_stack *)p->p_md.md_regs;
+ int i;
+
+/* printf ("Setregs: entry = %x, stack = %x, (usp = %x)\n", entry, stack,
+ r->pcb_usp); */
+
+ /* Start fp at stack also! */
+ r->pcb_usp = stack;
+ r->pcb_fp = stack;
+ r->pcb_pc = entry->ep_entry;
+ r->pcb_psr = PSL_USERSET;
+ r->pcb_reg[0] = (int)PS_STRINGS;
+ for (i=1; i<8; i++) r->pcb_reg[i] = 0;
+
+ p->p_addr->u_pcb.pcb_flags = 0;
+}
+
+
+extern struct pte *CMAP1, *CMAP2;
+extern caddr_t CADDR1, CADDR2;
+/*
+ * zero out physical memory
+ * specified in relocation units (NBPG bytes)
+ */
+clearseg(n)
+{
+ /* map page n in to virtual address CADDR2 */
+ *(int *)CMAP2 = PG_V | PG_KW | ctob(n);
+ tlbflush();
+ bzero(CADDR2,NBPG);
+ *(int *) CADDR2 = 0;
+}
+
+/*
+ * copy a page of physical memory
+ * specified in relocation units (NBPG bytes)
+ */
+copyseg(frm, n)
+{
+ /* map page n in to virtual address CADDR2 */
+ *(int *)CMAP2 = PG_V | PG_KW | ctob(n);
+ tlbflush();
+ bcopy((void *)frm, (void *)CADDR2, NBPG);
+}
+
+/*
+ * copy a page of physical memory
+ * specified in relocation units (NBPG bytes)
+ */
+physcopyseg(frm, to)
+{
+ /* map page frm in to virtual address CADDR1 */
+ *(int *)CMAP1 = PG_V | PG_KW | ctob(frm);
+ /* map page to in to virtual address CADDR2 */
+ *(int *)CMAP2 = PG_V | PG_KW | ctob(to);
+ tlbflush();
+ bcopy(CADDR1, CADDR2, NBPG);
+}
+
+/*
+ * insert an element into a queue
+ */
+#undef insque
+_insque(element, head)
+ register struct prochd *element, *head;
+{
+ element->ph_link = head->ph_link;
+ head->ph_link = (struct proc *)element;
+ element->ph_rlink = (struct proc *)head;
+ ((struct prochd *)(element->ph_link))->ph_rlink=(struct proc *)element;
+}
+
+/*
+ * remove an element from a queue
+ */
+#undef remque
+_remque(element)
+ register struct prochd *element;
+{
+ ((struct prochd *)(element->ph_link))->ph_rlink = element->ph_rlink;
+ ((struct prochd *)(element->ph_rlink))->ph_link = element->ph_link;
+ element->ph_rlink = (struct proc *)0;
+}
+
+vmunaccess() {printf ("vmunaccess!\n");}
+
+/*
+ * Below written in C to allow access to debugging code
+ */
+copyinstr(fromaddr, toaddr, maxlength, lencopied) size_t *lencopied, maxlength;
+ void *toaddr, *fromaddr; {
+ int c,tally;
+
+ tally = 0;
+ while (maxlength--) {
+ c = fubyte(fromaddr++);
+ if (c == -1) {
+ if(lencopied) *lencopied = tally;
+ return(EFAULT);
+ }
+ tally++;
+ *(char *)toaddr++ = (char) c;
+ if (c == 0){
+ if(lencopied) *lencopied = (u_int)tally;
+ return(0);
+ }
+ }
+ if(lencopied) *lencopied = (u_int)tally;
+ return(ENAMETOOLONG);
+}
+
+copyoutstr(fromaddr, toaddr, maxlength, lencopied) size_t *lencopied, maxlength;
+ void *fromaddr, *toaddr; {
+ int c;
+ int tally;
+
+ tally = 0;
+ while (maxlength--) {
+ c = subyte(toaddr++, *(char *)fromaddr);
+ if (c == -1) return(EFAULT);
+ tally++;
+ if (*(char *)fromaddr++ == 0){
+ if(lencopied) *lencopied = tally;
+ return(0);
+ }
+ }
+ if(lencopied) *lencopied = tally;
+ return(ENAMETOOLONG);
+}
+
+copystr(fromaddr, toaddr, maxlength, lencopied) size_t *lencopied, maxlength;
+ void *fromaddr, *toaddr; {
+ u_int tally;
+
+ tally = 0;
+ while (maxlength--) {
+ *(u_char *)toaddr = *(u_char *)fromaddr++;
+ tally++;
+ if (*(u_char *)toaddr++ == 0) {
+ if(lencopied) *lencopied = tally;
+ return(0);
+ }
+ }
+ if(lencopied) *lencopied = tally;
+ return(ENAMETOOLONG);
+}
+
+/*
+ * These variables are needed by /sbin/savecore
+ */
+u_long dumpmag = 0x8fca0101; /* magic number */
+int dumpsize = 0; /* pages */
+long dumplo = 0; /* blocks */
+
+/*
+ * This is called by configure to set dumplo and dumpsize.
+ * Dumps always skip the first CLBYTES of disk space
+ * in case there might be a disk label stored there.
+ * If there is extra space, put dump at the end to
+ * reduce the chance that swapping trashes it.
+ */
+void
+dumpconf()
+{
+ int nblks; /* size of dump area */
+ int maj;
+
+ if (dumpdev == NODEV)
+ return;
+ maj = major(dumpdev);
+ if (maj < 0 || maj >= nblkdev)
+ panic("dumpconf: bad dumpdev=0x%x", dumpdev);
+ if (bdevsw[maj].d_psize == NULL)
+ return;
+ nblks = (*bdevsw[maj].d_psize)(dumpdev);
+ if (nblks <= ctod(1))
+ return;
+
+ dumpsize = physmem;
+
+ /* Always skip the first CLBYTES, in case there is a label there. */
+ if (dumplo < ctod(1))
+ dumplo = ctod(1);
+
+ /* Put dump at end of partition, and make it fit. */
+ if (dumpsize > dtoc(nblks - dumplo))
+ dumpsize = dtoc(nblks - dumplo);
+ if (dumplo < nblks - ctod(dumpsize))
+ dumplo = nblks - ctod(dumpsize);
+}
+
+/*
+ * Doadump comes here after turning off memory management and
+ * getting on the dump stack, either when called above, or by
+ * the auto-restart code.
+ */
+#define BYTES_PER_DUMP NBPG /* must be a multiple of pagesize XXX small */
+static vm_offset_t dumpspace;
+
+vm_offset_t
+reserve_dumppages(p)
+ vm_offset_t p;
+{
+
+ dumpspace = p;
+ return (p + BYTES_PER_DUMP);
+}
+
+void
+dumpsys()
+{
+ unsigned bytes, i, n;
+ int maddr, psize;
+ daddr_t blkno;
+ int (*dump) __P((dev_t, daddr_t, caddr_t, size_t));
+ int error = 0;
+ int c;
+
+ msgbufmapped = 0; /* don't record dump msgs in msgbuf */
+ 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);
+
+ psize = (*bdevsw[major(dumpdev)].d_psize)(dumpdev);
+ printf("dump ");
+ if (psize == -1) {
+ printf("area unavailable\n");
+ return;
+ }
+
+#if 0 /* XXX this doesn't work. grr. */
+ /* toss any characters present prior to dump */
+ while (sget() != NULL); /*syscons and pccons differ */
+#endif
+
+ bytes = mem_size;
+ maddr = 0;
+ blkno = dumplo;
+ dump = bdevsw[major(dumpdev)].d_dump;
+ for (i = 0; i < bytes; i += n) {
+ /* Print out how many MBs we to go. */
+ n = bytes - i;
+ if (n && (n % (1024*1024)) == 0)
+ printf("%d ", n / (1024 * 1024));
+
+ /* Limit size for next transfer. */
+ if (n > BYTES_PER_DUMP)
+ n = BYTES_PER_DUMP;
+
+ (void) pmap_map(dumpspace, maddr, maddr + n, VM_PROT_READ);
+ error = (*dump)(dumpdev, blkno, (caddr_t)dumpspace, n);
+ if (error)
+ break;
+ maddr += n;
+ blkno += btodb(n); /* XXX? */
+
+#if 0 /* XXX this doesn't work. grr. */
+ /* operator aborting dump? */
+ if (sget() != NULL) {
+ error = EINTR;
+ break;
+ }
+#endif
+ }
+
+ switch (error) {
+
+ case ENXIO:
+ printf("device bad\n");
+ break;
+
+ case EFAULT:
+ printf("device not ready\n");
+ break;
+
+ case EINVAL:
+ printf("area improper\n");
+ break;
+
+ case EIO:
+ printf("i/o error\n");
+ break;
+
+ case EINTR:
+ printf("aborted from console\n");
+ break;
+
+ case 0:
+ printf("succeeded\n");
+ break;
+
+ default:
+ printf("error %d\n", error);
+ break;
+ }
+ printf("\n\n");
+ delay(5000000); /* 5 seconds */
+}
+
+/* Stub function for reboot_cpu. */
+
+void reboot_cpu()
+{
+ extern void low_level_reboot();
+
+ /* Point Low MEMORY to Kernel Memory! */
+ *((int *)PTD) = low_mem_map+3; /* PTD[pdei(KERNBASE)]; */
+ low_level_reboot();
+
+}
+
+int
+sys_sysarch(p, v, retval)
+ struct proc *p;
+ void *v;
+ register_t *retval;
+{
+ struct sysarch_args /* {
+ syscallarg(int) op;
+ syscallarg(char *) parms;
+ } */ *uap = v;
+
+ return ENOSYS;
+}
+
+/*
+ * consinit:
+ * initialize the system console.
+ * XXX - shouldn't deal with this cons_initted thing, but then,
+ * it shouldn't be called from init386 either.
+ */
+static int cons_initted;
+
+void
+consinit()
+{
+ if (!cons_initted) {
+ cninit();
+ cons_initted = 1;
+ }
+}
+
+/* DEBUG routine */
+
+void dump_qs()
+{ int ix;
+ struct proc *ptr;
+
+ for (ix=0; ix<NQS; ix++)
+ if (qs[ix].ph_link != qs[ix].ph_rlink)
+ {
+ ptr = qs[ix].ph_link;
+ do {
+ printf ("qs[%d]: 0x%x 0x%x\n", ix, ptr->p_forw, ptr->p_back);
+ ptr = ptr->p_forw;
+ } while (ptr != (struct proc *)0 && ptr != qs[ix].ph_link);
+ }
+ panic("nil P_BACK");
+}
+
+/*
+ * 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 */
+}
diff --git a/sys/arch/pc532/pc532/mem.c b/sys/arch/pc532/pc532/mem.c
new file mode 100644
index 00000000000..4d565be9770
--- /dev/null
+++ b/sys/arch/pc532/pc532/mem.c
@@ -0,0 +1,283 @@
+/* $NetBSD: mem.c,v 1.13 1995/09/26 20:16:30 phil Exp $ */
+
+/*
+ * Copyright (c) 1988 University of Utah.
+ * Copyright (c) 1982, 1986, 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * the Systems Programming Group of the University of Utah Computer
+ * Science Department.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)mem.c 8.3 (Berkeley) 1/12/94
+ */
+
+/*
+ * Memory special file
+ */
+
+#include <sys/param.h>
+#include <sys/conf.h>
+#include <sys/buf.h>
+#include <sys/systm.h>
+#include <sys/uio.h>
+#include <sys/malloc.h>
+
+#include <machine/cpu.h>
+
+#include <vm/vm.h>
+
+extern char *vmmap; /* poor name! */
+caddr_t zeropage;
+
+#ifndef NO_RTC
+int have_rtc = 1; /* For access to rtc. */
+#else
+int have_rtc = 0; /* For no rtc. */
+#endif
+#define ROM_ORIGIN 0xFFF00000 /* Mapped origin! */
+
+/* Do the actual reading and writing of the rtc. We have to read
+ and write the entire contents at a time. rw = 0 => read,
+ rw = 1 => write. */
+
+void rw_rtc (unsigned char *buffer, int rw)
+{
+ static unsigned char magic[8] =
+ {0xc5, 0x3a, 0xa3, 0x5c, 0xc5, 0x3a, 0xa3, 0x5c};
+ volatile unsigned char * const rom_p = (unsigned char *)ROM_ORIGIN;
+ unsigned char *bp;
+ unsigned char dummy; /* To defeat optimization */
+
+ /* Read or write to the real time chip. Address line A0 functions as
+ * data input, A2 is used as the /write signal. Accesses to the RTC
+ * are always done to one of the addresses (unmapped):
+ *
+ * 0x10000000 - write a '0' bit
+ * 0x10000001 - write a '1' bit
+ * 0x10000004 - read a bit
+ *
+ * Data is output from the RTC using D0. To read or write time
+ * information, the chip has to be activated first, to distinguish
+ * clock accesses from normal ROM reads. This is done by writing,
+ * bit by bit, a magic pattern to the chip. Before that, a dummy read
+ * assures that the chip's pattern comparison register pointer is
+ * reset. The RTC register file is always read or written wholly,
+ * even if we are only interested in a part of it.
+ */
+
+ /* Activate the real time chip */
+ dummy = rom_p[4]; /* Synchronize the comparison reg. */
+
+ for (bp=magic; bp<magic+8; bp++) {
+ int i;
+ for (i=0; i<8; i++)
+ dummy = rom_p[ (*bp>>i) & 0x01 ];
+ }
+
+ if (rw == 0) {
+ /* Read the time from the RTC. Do this even this is
+ a write, since the user might have only given
+ partial data and the RTC must always be written
+ completely.
+ */
+
+ for (bp=buffer; bp<buffer+8; bp++) {
+ int i;
+ for (i=0; i<8; i++) {
+ *bp >>= 1;
+ *bp |= ((rom_p[4] & 0x01) ? 0x80 : 0x00);
+ }
+ }
+ } else {
+ /* Write to the RTC */
+ for (bp=buffer; bp<buffer+8; bp++) {
+ int i;
+ for (i=0; i<8; i++)
+ dummy = rom_p[ (*bp>>i) & 0x01 ];
+ }
+ }
+}
+
+/*ARGSUSED*/
+int
+mmopen(dev, flag, mode)
+ dev_t dev;
+ int flag, mode;
+{
+
+ return (0);
+}
+
+/*ARGSUSED*/
+int
+mmclose(dev, flag, mode)
+ dev_t dev;
+ int flag, mode;
+{
+
+ return (0);
+}
+
+/*ARGSUSED*/
+int
+mmrw(dev, uio, flags)
+ dev_t dev;
+ struct uio *uio;
+ int flags;
+{
+ register vm_offset_t o, v;
+ register int c;
+ register struct iovec *iov;
+ int error = 0;
+ static int physlock;
+ /* /dev/rtc support. */
+ unsigned char buffer[8];
+
+ if (minor(dev) == 0) {
+ /* lock against other uses of shared vmmap */
+ while (physlock > 0) {
+ physlock++;
+ error = tsleep((caddr_t)&physlock, PZERO | PCATCH,
+ "mmrw", 0);
+ if (error)
+ return (error);
+ }
+ physlock = 1;
+ }
+ while (uio->uio_resid > 0 && error == 0) {
+ iov = uio->uio_iov;
+ if (iov->iov_len == 0) {
+ uio->uio_iov++;
+ uio->uio_iovcnt--;
+ if (uio->uio_iovcnt < 0)
+ panic("mmrw");
+ continue;
+ }
+ switch (minor(dev)) {
+
+/* minor device 0 is physical memory */
+ case 0:
+ v = uio->uio_offset;
+ pmap_enter(pmap_kernel(), (vm_offset_t)vmmap,
+ trunc_page(v), uio->uio_rw == UIO_READ ?
+ VM_PROT_READ : VM_PROT_WRITE, TRUE);
+ o = uio->uio_offset & PGOFSET;
+ c = min(uio->uio_resid, (int)(NBPG - o));
+ error = uiomove((caddr_t)vmmap + o, c, uio);
+ pmap_remove(pmap_kernel(), (vm_offset_t)vmmap,
+ (vm_offset_t)vmmap + NBPG);
+ continue;
+
+/* minor device 1 is kernel memory */
+ case 1:
+ v = uio->uio_offset;
+ c = min(iov->iov_len, MAXPHYS);
+ if (!kernacc((caddr_t)v, c,
+ uio->uio_rw == UIO_READ ? B_READ : B_WRITE))
+ return (EFAULT);
+ error = uiomove((caddr_t)v, c, uio);
+ continue;
+
+/* minor device 2 is EOF/RATHOLE */
+ case 2:
+ if (uio->uio_rw == UIO_WRITE)
+ uio->uio_resid = 0;
+ return (0);
+
+#ifdef DEV_RTC
+/* minor device 3 is the realtime clock. */
+ case 3:
+ if (!have_rtc)
+ return (ENXIO);
+
+ /* Calc offsets and lengths. */
+ v = uio->uio_offset;
+ if (v > 8)
+ return (0); /* EOF */
+ c = iov->iov_len;
+ if (v+c > 8)
+ c = 8-v;
+
+ rw_rtc(buffer, 0); /* Read the rtc. */
+
+ error = uiomove((caddr_t)&buffer[v], c, uio);
+
+ if (uio->uio_rw == UIO_READ || error)
+ return (error);
+
+ rw_rtc(buffer, 1); /* Write the rtc. */
+
+ return (error);
+#endif
+
+/* 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;
+ }
+ if (minor(dev) == 0) {
+unlock:
+ if (physlock > 1)
+ wakeup((caddr_t)&physlock);
+ physlock = 0;
+ }
+ return (error);
+}
+
+int
+mmmmap(dev, off, prot)
+ dev_t dev;
+ int off, prot;
+{
+
+ return (EOPNOTSUPP);
+}
diff --git a/sys/arch/pc532/pc532/ns_cksum.c b/sys/arch/pc532/pc532/ns_cksum.c
new file mode 100644
index 00000000000..34660d2ecd2
--- /dev/null
+++ b/sys/arch/pc532/pc532/ns_cksum.c
@@ -0,0 +1,206 @@
+/* $NetBSD: ns_cksum.c,v 1.2 1994/10/26 08:25:11 cgd Exp $ */
+
+/*
+ * Copyright (c) 1982, 1988 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)ns_cksum.c 7.7 (Berkeley) 4/29/91
+ */
+
+#include "sys/param.h"
+#include "sys/mbuf.h"
+
+/*
+ * Checksum routine for Network Systems Protocol Packets (Big-Endian).
+ *
+ * This routine is very heavily used in the network
+ * code and should be modified for each CPU to be as fast as possible.
+ */
+
+#define ADDCARRY(x) { if ((x) > 65535) (x) -= 65535; }
+#define FOLD(x) {l_util.l = (x); (x) = l_util.s[0] + l_util.s[1]; ADDCARRY(x);}
+
+u_short
+ns_cksum(m, len)
+ register struct mbuf *m;
+ register int len;
+{
+ register u_short *w;
+ register int sum = 0;
+ register int mlen = 0;
+ register int sum2;
+
+ union {
+ u_short s[2];
+ long l;
+ } l_util;
+
+ for (;m && len; m = m->m_next) {
+ if (m->m_len == 0)
+ continue;
+ /*
+ * Each trip around loop adds in
+ * word from one mbuf segment.
+ */
+ w = mtod(m, u_short *);
+ if (mlen == -1) {
+ /*
+ * There is a byte left from the last segment;
+ * ones-complement add it into the checksum.
+ */
+#if BYTE_ORDER == BIG_ENDIAN
+ sum += *(u_char *)w;
+#else
+ sum += *(u_char *)w << 8;
+#endif
+ sum += sum;
+ w = (u_short *)(1 + (char *)w);
+ mlen = m->m_len - 1;
+ len--;
+ FOLD(sum);
+ } else
+ mlen = m->m_len;
+ if (len < mlen)
+ mlen = len;
+ len -= mlen;
+ /*
+ * We can do a 16 bit ones complement sum using
+ * 32 bit arithmetic registers for adding,
+ * with carries from the low added
+ * into the high (by normal carry-chaining)
+ * so long as we fold back before 16 carries have occured.
+ */
+ if (1 & (int) w)
+ goto uuuuglyy;
+#ifndef TINY
+/* -DTINY reduces the size from 1250 to 550, but slows it down by 22% */
+ while ((mlen -= 32) >= 0) {
+ sum += w[0]; sum += sum; sum += w[1]; sum += sum;
+ sum += w[2]; sum += sum; sum += w[3]; sum += sum;
+ sum += w[4]; sum += sum; sum += w[5]; sum += sum;
+ sum += w[6]; sum += sum; sum += w[7]; sum += sum;
+ FOLD(sum);
+ sum += w[8]; sum += sum; sum += w[9]; sum += sum;
+ sum += w[10]; sum += sum; sum += w[11]; sum += sum;
+ sum += w[12]; sum += sum; sum += w[13]; sum += sum;
+ sum += w[14]; sum += sum; sum += w[15]; sum += sum;
+ FOLD(sum);
+ w += 16;
+ }
+ mlen += 32;
+#endif
+ while ((mlen -= 8) >= 0) {
+ sum += w[0]; sum += sum; sum += w[1]; sum += sum;
+ sum += w[2]; sum += sum; sum += w[3]; sum += sum;
+ FOLD(sum);
+ w += 4;
+ }
+ mlen += 8;
+ while ((mlen -= 2) >= 0) {
+ sum += *w++; sum += sum;
+ }
+ goto commoncase;
+uuuuglyy:
+#if BYTE_ORDER == BIG_ENDIAN
+#define ww(n) (((u_char *)w)[n + n + 1])
+#define vv(n) (((u_char *)w)[n + n])
+#else
+#if BYTE_ORDER == LITTLE_ENDIAN
+#define vv(n) (((u_char *)w)[n + n + 1])
+#define ww(n) (((u_char *)w)[n + n])
+#endif
+#endif
+ sum2 = 0;
+#ifndef TINY
+ while ((mlen -= 32) >= 0) {
+ sum += ww(0); sum += sum; sum += ww(1); sum += sum;
+ sum += ww(2); sum += sum; sum += ww(3); sum += sum;
+ sum += ww(4); sum += sum; sum += ww(5); sum += sum;
+ sum += ww(6); sum += sum; sum += ww(7); sum += sum;
+ FOLD(sum);
+ sum += ww(8); sum += sum; sum += ww(9); sum += sum;
+ sum += ww(10); sum += sum; sum += ww(11); sum += sum;
+ sum += ww(12); sum += sum; sum += ww(13); sum += sum;
+ sum += ww(14); sum += sum; sum += ww(15); sum += sum;
+ FOLD(sum);
+ sum2 += vv(0); sum2 += sum2; sum2 += vv(1); sum2 += sum2;
+ sum2 += vv(2); sum2 += sum2; sum2 += vv(3); sum2 += sum2;
+ sum2 += vv(4); sum2 += sum2; sum2 += vv(5); sum2 += sum2;
+ sum2 += vv(6); sum2 += sum2; sum2 += vv(7); sum2 += sum2;
+ FOLD(sum2);
+ sum2 += vv(8); sum2 += sum2; sum2 += vv(9); sum2 += sum2;
+ sum2 += vv(10); sum2 += sum2; sum2 += vv(11); sum2 += sum2;
+ sum2 += vv(12); sum2 += sum2; sum2 += vv(13); sum2 += sum2;
+ sum2 += vv(14); sum2 += sum2; sum2 += vv(15); sum2 += sum2;
+ FOLD(sum2);
+ w += 16;
+ }
+ mlen += 32;
+#endif
+ while ((mlen -= 8) >= 0) {
+ sum += ww(0); sum += sum; sum += ww(1); sum += sum;
+ sum += ww(2); sum += sum; sum += ww(3); sum += sum;
+ FOLD(sum);
+ sum2 += vv(0); sum2 += sum2; sum2 += vv(1); sum2 += sum2;
+ sum2 += vv(2); sum2 += sum2; sum2 += vv(3); sum2 += sum2;
+ FOLD(sum2);
+ w += 4;
+ }
+ mlen += 8;
+ while ((mlen -= 2) >= 0) {
+ sum += ww(0); sum += sum;
+ sum2 += vv(0); sum2 += sum2;
+ w++;
+ }
+ sum += (sum2 << 8);
+commoncase:
+ if (mlen == -1) {
+#if BYTE_ORDER == BIG_ENDIAN
+ sum += *(u_char *)w << 8;
+#else
+ sum += *(u_char *)w;
+#endif
+ }
+ FOLD(sum);
+ }
+ if (mlen == -1) {
+ /* We had an odd number of bytes to sum; assume a garbage
+ byte of zero and clean up */
+ sum += sum;
+ FOLD(sum);
+ }
+ /*
+ * sum has already been kept to low sixteen bits.
+ * just examine result and exit.
+ */
+ if(sum==0xffff) sum = 0;
+ return (sum);
+}
diff --git a/sys/arch/pc532/pc532/ntoh.s b/sys/arch/pc532/pc532/ntoh.s
new file mode 100644
index 00000000000..8801e9a1bbf
--- /dev/null
+++ b/sys/arch/pc532/pc532/ntoh.s
@@ -0,0 +1,47 @@
+/* $NetBSD: ntoh.s,v 1.2 1994/10/26 08:25:12 cgd Exp $ */
+
+/*
+ * Mach Operating System
+ * Copyright (c) 1992 Carnegie Mellon University
+ * Copyright (c) 1992 Helsinki University of Technology
+ * 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 AND HELSINKI UNIVERSITY OF TECHNOLOGY ALLOW FREE USE
+ * OF THIS SOFTWARE IN ITS "AS IS" CONDITION. CARNEGIE MELLON AND
+ * HELSINKI UNIVERSITY OF TECHNOLOGY DISCLAIM 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 Mellon
+ * the rights to redistribute these changes.
+ */
+
+#include <machine/asm.h>
+
+ .text
+ENTRY(ntohl)
+ENTRY(htonl)
+ movd S_ARG0,r0
+ rotw 8,r0
+ rotd 16,r0
+ rotw 8,r0
+ ret 0
+
+
+ENTRY(ntohs)
+ENTRY(htons)
+ movzwd S_ARG0,r0
+ rotw 8,r0
+ ret 0
diff --git a/sys/arch/pc532/pc532/oc_cksum.s b/sys/arch/pc532/pc532/oc_cksum.s
new file mode 100644
index 00000000000..cb42cdb26f3
--- /dev/null
+++ b/sys/arch/pc532/pc532/oc_cksum.s
@@ -0,0 +1,67 @@
+/* $NetBSD: oc_cksum.s,v 1.2 1994/10/26 08:25:13 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.
+ *
+ *
+ * oc_cksum: ones complement 16 bit checksum for NS32532
+ *
+ * oc_cksum (buffer, count, strtval)
+ *
+ * Do a 16 bit one's complement sum of 'count' bytes from 'buffer'.
+ * 'strtval' is the starting value of the sum (usually zero).
+ */
+
+
+#include <machine/asm.h>
+
+ /* This could use some tuning for better speed. */
+
+ .globl _oc_cksum
+_oc_cksum:
+ movd S_ARG0,r2 /* buffer */
+ movd S_ARG1,r1 /* count */
+ movd S_ARG2,r0 /* strtval */
+
+loop:
+ cmpqd 1, r1
+ ble oneleft
+ addw 0(r2), r0
+ addqd 2,r2
+ addqd -2,r1
+ br loop
+
+oneleft:
+ bls done
+ movqd 0, r1
+ movb 0(r2), r1
+ addw r1, r0
+done:
+ ret 0
diff --git a/sys/arch/pc532/pc532/pmap.c b/sys/arch/pc532/pc532/pmap.c
new file mode 100644
index 00000000000..bf6089666fa
--- /dev/null
+++ b/sys/arch/pc532/pc532/pmap.c
@@ -0,0 +1,1945 @@
+/* $NetBSD: pmap.c,v 1.10 1995/08/25 07:49:13 phil Exp $ */
+
+/*
+ * Copyright (c) 1991 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 William Jolitz of UUNET Technologies 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.
+ *
+ * @(#)pmap.c 7.7 (Berkeley) 5/12/91
+ */
+
+/*
+ * Derived from hp300 version by Mike Hibler, this version by William
+ * Jolitz uses a recursive map [a pde points to the page directory] to
+ * map the page tables using the pagetables themselves. This is done to
+ * reduce the impact on kernel virtual memory for lots of sparse address
+ * space, and to reduce the cost of memory to each process.
+ *
+ * Derived from: hp300/@(#)pmap.c 7.1 (Berkeley) 12/5/90
+ */
+
+/*
+ * Reno i386 version, from Mike Hibler's hp300 version.
+ */
+
+/*
+ * Most recently made to be a pc532 pmap! (Phil Nelson, 1/14/93)
+ */
+
+/*
+ * 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/proc.h>
+#include <sys/malloc.h>
+#include <sys/user.h>
+
+#include <vm/vm.h>
+#include <vm/vm_param.h>
+#include <vm/vm_kern.h>
+#include <vm/vm_page.h>
+
+/* Prototypes of routines used here. */
+
+vm_offset_t pmap_extract(pmap_t, vm_offset_t);
+void pmap_activate(register pmap_t, struct pcb *);
+extern vm_offset_t reserve_dumppages __P((vm_offset_t));
+
+/*
+ * Allocate various and sundry SYSMAPs used in the days of old VM
+ * and not yet converted. XXX.
+ */
+
+#define BSDVM_COMPAT 1
+
+#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 */
+} enter_stats;
+struct {
+ int calls;
+ int removes;
+ int pvfirst;
+ int pvsearch;
+ int ptinvalid;
+ int uflushes;
+ int sflushes;
+} remove_stats;
+
+int debugmap = 0;
+int pmapdebug = 0; /* 0xffff */
+#define PDB_FOLLOW 0x0001
+#define PDB_INIT 0x0002
+#define PDB_ENTER 0x0004
+#define PDB_REMOVE 0x0008
+#define PDB_CREATE 0x0010
+#define PDB_PTPAGE 0x0020
+#define PDB_CACHE 0x0040
+#define PDB_BITS 0x0080
+#define PDB_COLLECT 0x0100
+#define PDB_PROTECT 0x0200
+#define PDB_PDRTAB 0x0400
+#define PDB_PARANOIA 0x2000
+#define PDB_WIRING 0x4000
+#define PDB_PVDUMP 0x8000
+
+int pmapvacflush = 0;
+#define PVF_ENTER 0x01
+#define PVF_REMOVE 0x02
+#define PVF_PROTECT 0x04
+#define PVF_TOTAL 0x80
+#endif
+
+/*
+ * Get PDEs and PTEs for user/kernel address space
+ */
+#define pmap_pde(m, v) (&((m)->pm_pdir[((vm_offset_t)(v) >> PD_SHIFT)&1023]))
+
+#define pmap_pte_pa(pte) (*(int *)(pte) & PG_FRAME)
+
+#define pmap_pde_v(pte) ((pte)->pd_v)
+#define pmap_pte_w(pte) ((pte)->pg_w)
+/* #define pmap_pte_ci(pte) ((pte)->pg_ci) */
+#define pmap_pte_m(pte) ((pte)->pg_m)
+#define pmap_pte_u(pte) ((pte)->pg_u)
+#define pmap_pte_v(pte) ((pte)->pg_v)
+#define pmap_pte_set_w(pte, v) ((pte)->pg_w = (v))
+#define pmap_pte_set_prot(pte, v) ((pte)->pg_prot = (v))
+
+
+/* for debug output */
+#define pg printf
+
+/*
+ * Given a map and a machine independent protection code,
+ * convert to a ns532 protection code.
+ */
+#define pte_prot(m, p) (protection_codes[p])
+int protection_codes[8];
+
+struct user *proc0paddr;
+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) */
+vm_offset_t vm_first_phys; /* PA of first managed page */
+vm_offset_t vm_last_phys; /* PA just past last managed page */
+int ns532pagesperpage; /* PAGE_SIZE / NS532_PAGE_SIZE */
+boolean_t pmap_initialized = FALSE; /* Has pmap_init completed? */
+short *pmap_attributes; /* reference and modify bits */
+
+boolean_t pmap_testbit();
+void pmap_clear_modify();
+
+#if BSDVM_COMPAT
+#include "msgbuf.h"
+
+/*
+ * All those kernel PT submaps that BSD is so fond of
+ */
+struct pte *CMAP1, *CMAP2, *xxx_mmap;
+caddr_t CADDR1, CADDR2, vmmap;
+struct pte *msgbufmap;
+struct msgbuf *msgbufp;
+#endif
+
+vm_offset_t KPTphys;
+extern int PDRPDROFF;
+
+/*
+ * Bootstrap memory allocator. This function allows for early dynamic
+ * memory allocation until the virtual memory system has been bootstrapped.
+ * After that point, either kmem_alloc or malloc should be used. This
+ * function works by stealing pages from the (to be) managed page pool,
+ * stealing virtual address space, then mapping the pages and zeroing them.
+ *
+ * It should be used from pmap_bootstrap till vm_page_startup, afterwards
+ * it cannot be used, and will generate a panic if tried. Note that this
+ * memory will never be freed, and in essence it is wired down.
+ */
+void *
+pmap_bootstrap_alloc(size)
+ int size;
+{
+ extern boolean_t vm_page_startup_initialized;
+ vm_offset_t val;
+
+ if (vm_page_startup_initialized)
+ panic("pmap_bootstrap_alloc: called after startup initialized")\
+;
+ size = round_page(size);
+ val = virtual_avail;
+
+ virtual_avail = pmap_map(virtual_avail, avail_start,
+ avail_start + size, VM_PROT_READ|VM_PROT_WRITE);
+ avail_start += size;
+
+ blkclr ((caddr_t) val, size);
+ return ((void *) val);
+}
+
+
+
+/* static */
+void
+v_probe(pmap_t pmap, vm_offset_t va)
+{
+ int *ptr;
+ struct pde *pde_entry;
+ struct pte *pte_entry;
+
+ /* get a pointer to the top level page table entry */
+ pde_entry = pmap_pde(pmap, va);
+ if (!pmap_pde_v(pde_entry)) {
+ printf("va 0x%x, no top-level entry\n", va);
+ return;
+ }
+ ptr = (int *) pde_entry;
+ pte_entry = ((struct pte *) ((*ptr & PG_FRAME) | KERNBASE)) + ptei(va);
+ ptr = (int *) pte_entry;
+ if (!pmap_pte_v(pte_entry)) {
+ printf("pte_entry 0x%x *pte_entry 0x%x\n", ptr, *ptr);
+ printf("va 0x%x, no 2nd-level entry\n", va);
+ return;
+ }
+ /* print the page table entry */
+ printf("v_probe: va 0x%x pa 0x%x entry 0x%x\n",
+ va, (*ptr & PG_FRAME) | (va & ~PG_FRAME), *ptr);
+}
+
+static
+void
+map_page(pmap_t pmap, vm_offset_t va, vm_offset_t pa)
+{
+ int *ptr;
+ struct pde *pde_entry;
+ struct pte *pte_entry;
+
+ /* get a pointer to the top level page table entry */
+ pde_entry = pmap_pde(pmap, va);
+ if (!pmap_pde_v(pde_entry)) {
+ printf("map_page(0x%x, 0x%x, 0x%x) failed\n", pmap, va, pa);
+ panic("missing 2nd level page table");
+ }
+ /* get a pointer to the 2nd level table entry */
+ ptr = (int *) pde_entry;
+ pte_entry = ((struct pte *) (*ptr & PG_FRAME)) + ptei(va);
+ if (pmap_pte_v(pte_entry)) {
+ printf("map_page(0x%x, 0x%x, 0x%x) failed\n", pmap, va, pa);
+ panic("2nd level page table entry already valid");
+ }
+ /* make the page table entry */
+ ptr = (int *) pte_entry;
+ *ptr = pa | PG_V | PG_KW;
+ /* just to be safe */
+ tlbflush();
+}
+
+/*
+ * Map in physical page 'pa' to virtual address 'va', and install
+ * as a 2nd level page table at index 'index' for the given
+ * pmap.
+ */
+static
+void
+map_page_table(pmap_t pmap, int index, vm_offset_t va, vm_offset_t pa)
+{
+ int *ptr = (int *) &pmap->pm_pdir[index];
+ if (*ptr) {
+ printf("2nd level table present for index %x\n", index);
+ panic("remapping 2nd level table");
+ }
+ /* map in the 2nd level table */
+ map_page(pmap_kernel(), va, pa);
+ /* init the 2nd level table to all invalid */
+ bzero(pa, NBPG);
+ /* install the 2nd level table */
+ *ptr = pa | PG_V | PG_KW;
+ /* just to be safe */
+ tlbflush();
+}
+
+/*
+ * Bootstrap the system enough to run with virtual memory.
+ * Map the kernel's code and data, and allocate the system page table.
+ *
+ * On the Ns532 this is called after mapping has already been enabled
+ * and just syncs the pmap module with what has already been done.
+ * [We can't call it easily with mapping off since the kernel is not
+ * mapped with PA == VA, hence we would have to relocate every address
+ * from the linked base (virtual) address 0xFE000000 to the actual
+ * (physical) address starting relative to 0]
+ */
+struct pte *pmap_pte();
+
+void
+pmap_bootstrap(firstaddr, loadaddr)
+ vm_offset_t firstaddr;
+ vm_offset_t loadaddr;
+{
+ int x, *ptr;
+#if BSDVM_COMPAT
+ vm_offset_t va;
+ struct pte *pte;
+#endif
+ extern vm_offset_t maxmem, physmem;
+
+ ns532pagesperpage = 1; /* PAGE_SIZE / NS532_PAGE_SIZE; */
+
+ /*
+ * Initialize protection array.
+ */
+ ns532_protection_init();
+
+ /* setup avail_start, avail_end, virtual_avail, virtual_end */
+ avail_start = firstaddr;
+ avail_end = mem_size;
+
+ /* XXX: allow for msgbuf */
+ avail_end -= ns532_round_page(sizeof(struct msgbuf));
+
+ virtual_avail = avail_start + KERNBASE;
+ virtual_end = VM_MAX_KERNEL_ADDRESS;
+
+ /*
+ * Create Kernel page directory table and page maps.
+ */
+ pmap_kernel()->pm_pdir = (pd_entry_t *) (KPTphys + KERNBASE);
+ /* recursively map in ptb0 */
+ ptr = ((int *) pmap_kernel()->pm_pdir) + PDRPDROFF;
+ if (*ptr) {
+ printf("ptb0 0x%x offset 0x%x should be 0 but is 0x%x\n",
+ pmap_kernel()->pm_pdir, PDRPDROFF, *ptr);
+ bpt_to_monitor();
+ }
+ /* don't add KERNBASE as this has to be a physical address */
+ *ptr = KPTphys | PG_V | PG_KW;
+ /* fill in the rest of the top-level kernel VA entries */
+ for (x = ns532_btod(VM_MIN_KERNEL_ADDRESS);
+ x < ns532_btod(VM_MAX_KERNEL_ADDRESS); x++) {
+ ptr = (int *) &pmap_kernel()->pm_pdir[x];
+ /* only fill in the entries not yet made in _low_level_init() */
+ if (!*ptr) {
+ /* map in the page table */
+ map_page_table(pmap_kernel(), x,
+ virtual_avail, avail_start);
+ avail_start += NBPG;
+ virtual_avail += NBPG;
+ }
+ }
+ /* map in the kernel stack for process 0 */
+ /* install avail_start as a 2nd level table for index 0x3f6 */
+ map_page_table(pmap_kernel(), 0x3f6, virtual_avail, avail_start);
+ avail_start += NBPG;
+ virtual_avail += NBPG;
+ /* reserve UPAGES pages */
+ proc0paddr = (struct user *) virtual_avail;
+ curpcb = (struct pcb *) proc0paddr;
+ va = ns532_dtob(0x3f6) | ns532_ptob(0x3fe); /* USRSTACK ? */
+ for (x = 0; x < UPAGES; ++x) {
+ map_page(pmap_kernel(), va, avail_start);
+ map_page(pmap_kernel(), virtual_avail, avail_start);
+ bzero(va, NBPG);
+ va += NBPG;
+ avail_start += NBPG;
+ virtual_avail += NBPG;
+ }
+
+ simple_lock_init(&pmap_kernel()->pm_lock);
+ pmap_kernel()->pm_count = 1;
+
+#ifdef DEBUG
+ printf("avail_start = 0x%x\n", avail_start);
+ printf("avail_end = 0x%x\n", avail_end);
+ printf("virtual_avail = 0x%x\n", virtual_avail);
+ printf("virtual_end = 0x%x\n", virtual_end);
+#endif
+
+#if BSDVM_COMPAT
+ /*
+ * Allocate all the submaps we need
+ */
+#define SYSMAP(c, p, v, n) \
+ v = (c)va; va += ((n)*NS532_PAGE_SIZE); p = pte; pte += (n);
+
+ va = virtual_avail;
+ pte = pmap_pte(pmap_kernel(), va);
+
+ SYSMAP(caddr_t ,CMAP1 ,CADDR1 ,1 )
+ SYSMAP(caddr_t ,CMAP2 ,CADDR2 ,1 )
+ SYSMAP(caddr_t ,xxx_mmap ,vmmap ,1 )
+ SYSMAP(struct msgbuf * ,msgbufmap ,msgbufp ,1 )
+ virtual_avail = va;
+#endif
+ virtual_avail = reserve_dumppages(va);
+#ifdef DEBUG
+ printf("virtual_avail = 0x%x\n", virtual_avail);
+#endif
+ tlbflush();
+ /* XXX why do we do this??? - MM */
+ *(int *)PTD = 0;
+ tlbflush();
+}
+
+/*
+ * Initialize the pmap module.
+ * Called by vm_init, to initialize any structures that the pmap
+ * system needs to map virtual memory.
+ */
+void
+pmap_init(phys_start, phys_end)
+ vm_offset_t phys_start, phys_end;
+{
+ int result;
+ vm_offset_t addr, addr2;
+ vm_size_t npg, s;
+ int rv;
+
+#ifdef DEBUG
+ if (pmapdebug & (PDB_FOLLOW|PDB_INIT))
+ printf("pmap_init(0x%x, 0x%x)\n", phys_start, phys_end);
+#endif
+
+ if (PAGE_SIZE != NBPG)
+ panic("pmap_init: CLSIZE != 1");
+ /*
+ * Now that kernel map has been allocated, we can mark as
+ * unavailable regions which we have mapped in locore.
+ */
+
+#if 0
+ /* the following reserves the (virtual) i/o space */
+ addr = 0xffc00000;
+ result = vm_map_find(kernel_map, NULL, (vm_offset_t) 0,
+ &addr, NBPG, FALSE);
+ if (result != KERN_SUCCESS) {
+ printf("vm_map_find for virtual i/o space failed %d\n", result);
+ }
+
+ /* reserve the used page tables following the kernel */
+ /* bumped this to 10 pages just to be paranoid */
+ addr = (vm_offset_t) KERNBASE + KPTphys;
+ vm_object_reference(kernel_object);
+ result = vm_map_find(kernel_map, kernel_object, addr,
+ &addr, 10*NBPG, FALSE);
+ if (result != KERN_SUCCESS) {
+ printf("vm_map_find for kernel page maps failed %d\n", result);
+ }
+#endif
+ /*
+ * Allocate memory for random pmap data structures. Includes the
+ * pv_head_table and pmap_attributes.
+ */
+ npg = atop(phys_end - phys_start);
+ s = (vm_size_t) (sizeof(struct pv_entry) * npg + 2*npg);
+ s = round_page(s);
+ addr = (vm_offset_t) kmem_alloc(kernel_map, s);
+ pv_table = (pv_entry_t) addr;
+ addr += sizeof(struct pv_entry) * npg;
+ pmap_attributes = (short *) addr;
+
+#ifdef DEBUG
+ if (pmapdebug & PDB_INIT)
+ printf("pmap_init: %x bytes (%x pgs): tbl %x attr %x\n",
+ s, npg, pv_table, pmap_attributes);
+#endif
+
+ /*
+ * Now it is safe to enable pv_table recording.
+ */
+ vm_first_phys = phys_start;
+ vm_last_phys = phys_end;
+ pmap_initialized = TRUE;
+}
+
+/*
+ * Used to map a range of physical addresses into kernel
+ * virtual address space.
+ *
+ * For now, VM is already on, we only need to map the
+ * specified memory.
+ */
+vm_offset_t
+pmap_map(virt, start, end, prot)
+ vm_offset_t virt;
+ vm_offset_t start;
+ vm_offset_t end;
+ int prot;
+{
+#ifdef DEBUG
+ if (pmapdebug & PDB_FOLLOW)
+ printf("pmap_map(%x, %x, %x, %x)\n", virt, start, end, prot);
+#endif
+ while (start < end) {
+ pmap_enter(pmap_kernel(), virt, start, prot, FALSE);
+ virt += PAGE_SIZE;
+ start += PAGE_SIZE;
+ }
+ return(virt);
+}
+
+/*
+ * 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.
+ *
+ * [ just allocate a ptd and mark it uninitialize -- should we track
+ * with a table which process has which ptd? -wfj ]
+ */
+
+pmap_t
+pmap_create(size)
+ vm_size_t size;
+{
+ register pmap_t pmap;
+
+#ifdef DEBUG
+ if (pmapdebug & (PDB_FOLLOW|PDB_CREATE))
+ printf("pmap_create(%x)\n", size);
+#endif
+ /*
+ * Software use map does not need a pmap
+ */
+ if (size)
+ return(NULL);
+
+ /* XXX: is it ok to wait here? */
+ pmap = (pmap_t) malloc(sizeof *pmap, M_VMPMAP, M_WAITOK);
+#ifdef notifwewait
+ if (pmap == NULL)
+ panic("pmap_create: cannot allocate a pmap");
+#endif
+ bzero(pmap, sizeof(*pmap));
+ pmap_pinit(pmap);
+ return (pmap);
+}
+
+/*
+ * Initialize a preallocated and zeroed pmap structure,
+ * such as one in a vmspace structure.
+ */
+void
+pmap_pinit(pmap)
+ register struct pmap *pmap;
+{
+#ifdef DEBUG
+ if (pmapdebug & (PDB_FOLLOW|PDB_CREATE))
+ pg("pmap_pinit(%x)\n", pmap);
+#endif
+
+ /*
+ * No need to allocate page table space yet but we do need a
+ * valid page directory table.
+ */
+ pmap->pm_pdir = (pd_entry_t *) kmem_alloc(kernel_map, NBPG);
+
+ /* wire in kernel global address entries */
+ bcopy(PTD+KPTDI_FIRST, pmap->pm_pdir+KPTDI_FIRST,
+ (KPTDI_LAST-KPTDI_FIRST+1)*4);
+
+ /* install self-referential address mapping entry */
+ *(int *)(pmap->pm_pdir+PTDPTDI) =
+ (int)pmap_extract(pmap_kernel(), (vm_offset_t) pmap->pm_pdir)
+ | PG_V | PG_KW;
+
+ pmap->pm_count = 1;
+ simple_lock_init(&pmap->pm_lock);
+}
+
+/*
+ * Retire the given physical map from service.
+ * Should only be called if the map contains
+ * no valid mappings.
+ */
+void
+pmap_destroy(pmap)
+ register pmap_t pmap;
+{
+ int count;
+
+#ifdef DEBUG
+ if (pmapdebug & PDB_FOLLOW)
+ 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 struct pmap *pmap;
+{
+#ifdef DEBUG
+ if (pmapdebug & PDB_FOLLOW)
+ pg("pmap_release(%x)\n", pmap);
+#endif
+#ifdef notdef /* DIAGNOSTIC */
+ /* count would be 0 from pmap_destroy... */
+ simple_lock(&pmap->pm_lock);
+ if (pmap->pm_count != 1)
+ panic("pmap_release count");
+#endif
+ kmem_free(kernel_map, (vm_offset_t)pmap->pm_pdir, NBPG);
+}
+
+/*
+ * 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)
+ struct pmap *pmap;
+ register vm_offset_t sva;
+ register vm_offset_t eva;
+{
+ register pt_entry_t *ptp,*ptq;
+ vm_offset_t va;
+ vm_offset_t pa;
+ pt_entry_t *pte;
+ pv_entry_t pv, npv;
+ int ix;
+ int s, bits;
+
+#ifdef DEBUG
+ pt_entry_t opte;
+
+ if (pmapdebug & (PDB_FOLLOW|PDB_REMOVE|PDB_PROTECT))
+ pg("pmap_remove(%x, %x, %x)\n", pmap, sva, eva);
+#endif
+
+ if (pmap == NULL)
+ return;
+
+ /* are we current address space or kernel? */
+ if (pmap->pm_pdir[PTDPTDI].pd_pfnum == PTDpde.pd_pfnum
+ || pmap == pmap_kernel())
+ ptp=PTmap;
+
+ /* otherwise, we are alternate address space */
+ else {
+ if (pmap->pm_pdir[PTDPTDI].pd_pfnum
+ != APTDpde.pd_pfnum) {
+ APTDpde = pmap->pm_pdir[PTDPTDI];
+ tlbflush();
+ }
+ ptp=APTmap;
+ }
+#ifdef DEBUG
+ remove_stats.calls++;
+#endif
+
+ /* this is essential since we must check the PDE(sva) for precense */
+ while (sva <= eva && !pmap_pde_v(pmap_pde(pmap, sva)))
+ sva = (sva & PD_MASK) + (1<<PD_SHIFT);
+ sva = ns532_btop(sva);
+ eva = ns532_btop(eva);
+
+ for (; sva < eva; sva++) {
+ /*
+ * Weed out invalid mappings.
+ * Note: we assume that the page directory table is
+ * always allocated, and in kernel virtual.
+ */
+ ptq=ptp+sva;
+ while((sva & 0x3ff) && !pmap_pte_pa(ptq))
+ {
+ if(++sva >= eva)
+ return;
+ ptq++;
+ }
+
+
+ if(!(sva & 0x3ff)) /* Only check once in a while */
+ {
+ if (!pmap_pde_v(pmap_pde(pmap, ns532_ptob(sva))))
+ {
+ /* We can race ahead here, straight to next pde.. */
+ sva = (sva & 0xffc00) + (1<<10) -1 ;
+ continue;
+ }
+ }
+ if(!pmap_pte_pa(ptp+sva))
+ continue;
+
+ pte = ptp + sva;
+ pa = pmap_pte_pa(pte);
+ va = ns532_ptob(sva);
+#ifdef DEBUG
+ opte = *pte;
+ remove_stats.removes++;
+#endif
+ /*
+ * Update statistics
+ */
+ if (pmap_pte_w(pte))
+ pmap->pm_stats.wired_count--;
+ pmap->pm_stats.resident_count--;
+
+ /*
+ * Invalidate the PTEs.
+ * XXX: should cluster them up and invalidate as many
+ * as possible at once.
+ */
+#ifdef DEBUG
+ if (pmapdebug & PDB_REMOVE)
+ printf("remove: inv %x ptes at pte %x pa %x va %x\n",
+ ns532pagesperpage, pte, pa, va);
+#endif
+ bits = ix = 0;
+ do {
+ bits |= *(int *)pte & (PG_U|PG_M);
+ *(int *)pte++ = 0;
+ /*TBIS(va + ix * NS532_PAGE_SIZE);*/
+ } while (++ix != ns532pagesperpage);
+ if (curproc && pmap == &curproc->p_vmspace->vm_pmap)
+ pmap_activate(pmap, (struct pcb *)curproc->p_addr);
+#if 0
+/* commented out in 386 version as well */
+ /* are we current address space or kernel? */
+ if (pmap->pm_pdir[PTDPTDI].pd_pfnum == PTDpde.pd_pfnum
+ || pmap == pmap_kernel()) {
+ _load_ptb0(curpcb->pcb_ptb);
+ }
+#endif
+ tlbflush();
+
+#ifdef needednotdone
+reduce wiring count on page table pages as references drop
+#endif
+
+ /*
+ * Remove from the PV table (raise IPL since we
+ * may be called at interrupt time).
+ */
+ if (pa < vm_first_phys || pa >= vm_last_phys)
+ continue;
+ 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) {
+ 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 {
+ for (npv = pv->pv_next; npv; npv = npv->pv_next) {
+#ifdef DEBUG
+ remove_stats.pvsearch++;
+#endif
+ if (pmap == npv->pv_pmap && va == npv->pv_va)
+ break;
+ pv = npv;
+ }
+#ifdef DEBUG
+ if (npv == NULL) {
+ printf("vm_first_phys %x pa %x vm_last_phys %x\n",
+ vm_first_phys, pa, vm_last_phys);
+ panic("pmap_remove: PA not in pv_tab");
+ }
+#endif
+ pv->pv_next = npv->pv_next;
+ free((caddr_t)npv, M_VMPVENT);
+ pv = pa_to_pvh(pa);
+ }
+
+#ifdef notdef
+[tally number of pagetable pages, if sharing of ptpages adjust here]
+#endif
+ /*
+ * Update saved attributes for managed page
+ */
+ pmap_attributes[pa_index(pa)] |= bits;
+ splx(s);
+ }
+#ifdef notdef
+[cache and tlb flushing, if needed]
+#endif
+}
+
+/*
+ * Routine: pmap_remove_all
+ * Function:
+ * Removes this physical page from
+ * all physical maps in which it resides.
+ * Reflects back modify bits to the pager.
+ */
+void
+pmap_remove_all(pa)
+ vm_offset_t pa;
+{
+ register pv_entry_t pv;
+ int s;
+
+#ifdef DEBUG
+ if (pmapdebug & (PDB_FOLLOW|PDB_REMOVE|PDB_PROTECT))
+ printf("pmap_remove_all(%x)", pa);
+ /*pmap_pvdump(pa);*/
+#endif
+ /*
+ * Not one of ours
+ */
+ if (pa < vm_first_phys || pa >= vm_last_phys)
+ return;
+
+ pv = pa_to_pvh(pa);
+ s = splimp();
+ /*
+ * Do it the easy way for now
+ */
+ while (pv->pv_pmap != NULL) {
+#ifdef DEBUG
+ if (!pmap_pde_v(pmap_pde(pv->pv_pmap, pv->pv_va)) ||
+ pmap_pte_pa(pmap_pte(pv->pv_pmap, pv->pv_va)) != pa)
+ panic("pmap_remove_all: bad mapping");
+#endif
+ pmap_remove(pv->pv_pmap, pv->pv_va, pv->pv_va + PAGE_SIZE);
+ }
+ splx(s);
+}
+
+/*
+ * Routine: pmap_copy_on_write
+ * Function:
+ * Remove write privileges from all
+ * physical maps for this physical page.
+ */
+void
+pmap_copy_on_write(pa)
+ vm_offset_t pa;
+{
+#ifdef DEBUG
+ if (pmapdebug & (PDB_FOLLOW|PDB_PROTECT))
+ printf("pmap_copy_on_write(%x)", pa);
+#endif
+ pmap_changebit(pa, /* was PG_RO, TRUE */ PG_RW, FALSE);
+}
+
+/*
+ * 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 pt_entry_t *pte;
+ register vm_offset_t va;
+ register int ix;
+ int ns532prot;
+ boolean_t firstpage = TRUE;
+ register pt_entry_t *ptp;
+
+#ifdef DEBUG
+ if (pmapdebug & (PDB_FOLLOW|PDB_PROTECT))
+ printf("pmap_protect(%x, %x, %x, %x)", pmap, sva, eva, prot);
+#endif
+ if (pmap == NULL)
+ return;
+
+ if ((prot & VM_PROT_READ) == VM_PROT_NONE) {
+ pmap_remove(pmap, sva, eva);
+ return;
+ }
+ if (prot & VM_PROT_WRITE)
+ return;
+
+ /* are we current address space or kernel? */
+ if (pmap->pm_pdir[PTDPTDI].pd_pfnum == PTDpde.pd_pfnum
+ || pmap == pmap_kernel())
+ ptp=PTmap;
+
+ /* otherwise, we are alternate address space */
+ else {
+ if (pmap->pm_pdir[PTDPTDI].pd_pfnum
+ != APTDpde.pd_pfnum) {
+ APTDpde = pmap->pm_pdir[PTDPTDI];
+ tlbflush();
+ }
+ ptp=APTmap;
+ }
+ for (va = sva; va < eva; va += PAGE_SIZE) {
+ /*
+ * Page table page is not allocated.
+ * Skip it, we don't want to force allocation
+ * of unnecessary PTE pages just to set the protection.
+ */
+ if (!pmap_pde_v(pmap_pde(pmap, va))) {
+ /* XXX: avoid address wrap around */
+ if (va >= ns532_trunc_pdr((vm_offset_t)-1))
+ break;
+ va = ns532_round_pdr(va + PAGE_SIZE) - PAGE_SIZE;
+ continue;
+ }
+
+ pte = ptp + ns532_btop(va);
+
+ /*
+ * Page not valid. Again, skip it.
+ * Should we do this? Or set protection anyway?
+ */
+ if (!pmap_pte_v(pte))
+ continue;
+
+ ix = 0;
+ ns532prot = pte_prot(pmap, prot);
+ if(va < UPT_MAX_ADDRESS)
+ ns532prot |= 2 /*PG_u*/;
+ do {
+ /* clear VAC here if PG_RO? */
+ pmap_pte_set_prot(pte++, ns532prot);
+ /*TBIS(va + ix * NS532_PAGE_SIZE);*/
+ } while (++ix != ns532pagesperpage);
+ }
+ if (curproc && pmap == &curproc->p_vmspace->vm_pmap)
+ pmap_activate(pmap, (struct pcb *)curproc->p_addr);
+}
+
+/*
+ * Insert the given physical page (p) at
+ * the specified virtual address (v) in the
+ * target physical map with the protection requested.
+ *
+ * If specified, the page will be wired down, meaning
+ * that the related pte can not be reclaimed.
+ *
+ * NB: This is the only routine which MAY NOT lazy-evaluate
+ * or lose information. That is, this routine must actually
+ * insert this page into the given map NOW.
+ */
+void
+pmap_enter(pmap, va, pa, prot, wired)
+ register pmap_t pmap;
+ vm_offset_t va;
+ register vm_offset_t pa;
+ vm_prot_t prot;
+ boolean_t wired;
+{
+ register pt_entry_t *pte;
+ register int npte, ix;
+ vm_offset_t opa;
+ boolean_t cacheable = TRUE;
+ boolean_t checkpv = TRUE;
+
+#ifdef DEBUG
+ if (pmapdebug & (PDB_FOLLOW|PDB_ENTER))
+ printf("pmap_enter(%x, %x, %x, %x, %x)\n",
+ pmap, va, pa, prot, wired);
+#endif
+ if (pmap == NULL)
+ return;
+
+ if(va >= VM_MAX_KERNEL_ADDRESS)
+ panic("pmap_enter: toobig");
+ /* also, should not muck with PTD va! */
+
+#ifdef DEBUG
+ if (pmap == pmap_kernel())
+ enter_stats.kernel++;
+ else
+ enter_stats.user++;
+#endif
+
+ /*
+ * Page Directory table entry not valid, we need a new PT page
+ */
+ pte = pmap_pte(pmap, va);
+ if (!pte)
+ panic("ptdi %x", pmap->pm_pdir[PTDPTDI]);
+
+#ifdef DEBUG
+ if (pmapdebug & PDB_ENTER)
+ printf("enter: pte %x, *pte %x ", pte, *(int *)pte);
+#endif
+
+
+ if (pmap_pte_v(pte)) {
+ register vm_offset_t opa;
+
+ opa = pmap_pte_pa(pte);
+
+ /*
+ * Mapping has not changed, must be protection or wiring change.
+ */
+ if (opa == pa) {
+#ifdef DEBUG
+ enter_stats.pwchange++;
+#endif
+ /*
+ * Wiring change, just update stats.
+ * We don't worry about wiring PT pages as they remain
+ * resident as long as there are valid mappings in them.
+ * Hence, if a user page is wired, the PT page will be also.
+ */
+ if (wired && !pmap_pte_w(pte) || !wired && pmap_pte_w(pte)) {
+#ifdef DEBUG
+ if (pmapdebug & PDB_ENTER)
+ pg("enter: wiring change -> %x ", wired);
+#endif
+ if (wired)
+ pmap->pm_stats.wired_count++;
+ else
+ pmap->pm_stats.wired_count--;
+#ifdef DEBUG
+ enter_stats.wchange++;
+#endif
+ }
+ goto validate;
+ }
+
+ /*
+ * Mapping has changed, invalidate old range and fall through to
+ * handle validating new mapping.
+ */
+#ifdef DEBUG
+ if (pmapdebug & PDB_ENTER)
+ printf("enter: removing old mapping %x pa %x ", va, opa);
+#endif
+ pmap_remove(pmap, va, va + NBPG);
+#ifdef DEBUG
+ enter_stats.mchange++;
+#endif
+ }
+
+ /*
+ * Enter on the PV list if part of our managed memory
+ * Note that we raise IPL while manipulating pv_table
+ * since pmap_enter can be called at interrupt time.
+ */
+/* if (pmap_valid_page(pa)) in the i386 version ... */
+ if (pa >= vm_first_phys && pa < vm_last_phys) {
+ register pv_entry_t pv, npv;
+ int s;
+
+#ifdef DEBUG
+ enter_stats.managed++;
+#endif
+ pv = pa_to_pvh(pa);
+ s = splimp();
+#ifdef DEBUG
+ if (pmapdebug & PDB_ENTER)
+ printf("enter: pv at %x: %x/%x/%x\n",
+ pv, pv->pv_va, pv->pv_pmap, pv->pv_next);
+#endif
+ /*
+ * No entries yet, use header as the first entry
+ */
+ if (pv->pv_pmap == NULL) {
+#ifdef DEBUG
+ enter_stats.firstpv++;
+#endif
+ pv->pv_va = va;
+ pv->pv_pmap = pmap;
+ pv->pv_next = NULL;
+ pv->pv_flags = 0;
+ }
+ /*
+ * There is at least one other VA mapping this page.
+ * Place this entry after the header.
+ */
+ else {
+ /*printf("second time: ");*/
+#ifdef DEBUG
+ for (npv = pv; npv; npv = npv->pv_next)
+ if (pmap == npv->pv_pmap && va == npv->pv_va)
+ panic("pmap_enter: already in pv_tab");
+#endif
+ npv = (pv_entry_t)
+ malloc(sizeof *npv, M_VMPVENT, M_NOWAIT);
+ if (npv == NULL)
+ panic("pmap_enter: malloc returned NULL");
+ npv->pv_va = va;
+ npv->pv_pmap = pmap;
+ npv->pv_next = pv->pv_next;
+ pv->pv_next = npv;
+#ifdef DEBUG
+ if (!npv->pv_next)
+ enter_stats.secondpv++;
+#endif
+ }
+ splx(s);
+ }
+ /*
+ * Assumption: if it is not part of our managed memory
+ * then it must be device memory which may be volitile.
+ */
+ if (pmap_initialized) {
+ checkpv = cacheable = FALSE;
+#ifdef DEBUG
+ enter_stats.unmanaged++;
+#endif
+ }
+
+ /*
+ * Increment counters
+ */
+ pmap->pm_stats.resident_count++;
+ if (wired)
+ pmap->pm_stats.wired_count++;
+
+validate:
+ /*
+ * Now validate mapping with desired protection/wiring.
+ * Assume uniform modified and referenced status for all
+ * Ns532 pages in a MACH page.
+ */
+ npte = (pa & PG_FRAME) | pte_prot(pmap, prot) | PG_V;
+ npte |= (*(int *)pte & (PG_M|PG_U));
+ if (wired)
+ npte |= PG_W;
+ if (va < VM_MAXUSER_ADDRESS) /* i.e. below USRSTACK */
+ npte |= PG_u;
+ else if (va < UPT_MAX_ADDRESS)
+ /* pagetables need to be user RW, for some reason, and the
+ * user area must be writable too. Anything above
+ * VM_MAXUSER_ADDRESS is protected from user access by
+ * the user data and code segment descriptors, so this is OK.
+ *
+ * andrew@werple.apana.org.au
+ */
+ npte |= PG_u | PG_RW;
+
+#ifdef DEBUG
+ if (pmapdebug & PDB_ENTER)
+ printf("enter: new pte value %x\n", npte);
+#endif
+ ix = 0;
+ do {
+ *(int *)pte++ = npte;
+ /*TBIS(va);*/
+ npte += NS532_PAGE_SIZE;
+ va += NS532_PAGE_SIZE;
+ } while (++ix != ns532pagesperpage);
+ pte--;
+#ifdef DEBUGx
+cache, tlb flushes
+#endif
+#if 0
+ pads(pmap);
+ _load_ptb0(((struct pcb *)curproc->p_addr)->pcb_ptb);
+#endif
+ tlbflush();
+}
+
+/*
+ * pmap_page_protect:
+ *
+ * Lower the permission for all mappings to a given page.
+ */
+void
+pmap_page_protect(phys, prot)
+ vm_offset_t phys;
+ vm_prot_t prot;
+{
+ switch (prot) {
+ case VM_PROT_READ:
+ case VM_PROT_READ|VM_PROT_EXECUTE:
+ pmap_copy_on_write(phys);
+ break;
+ case VM_PROT_ALL:
+ break;
+ default:
+ pmap_remove_all(phys);
+ break;
+ }
+}
+
+/*
+ * 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;
+ register int ix;
+
+#ifdef DEBUG
+ if (pmapdebug & PDB_FOLLOW)
+ printf("pmap_change_wiring(%x, %x, %x)\n", pmap, va, wired);
+#endif
+ if (pmap == NULL)
+ return;
+
+ pte = pmap_pte(pmap, va);
+#ifdef DEBUG
+ /*
+ * Page table page is not allocated.
+ * Should this ever happen? Ignore it for now,
+ * we don't want to force allocation of unnecessary PTE pages.
+ */
+ if (!pmap_pde_v(pmap_pde(pmap, va))) {
+ if (pmapdebug & PDB_PARANOIA)
+ pg("pmap_change_wiring: invalid PDE for %x\n", va);
+ return;
+ }
+ /*
+ * Page not valid. Should this ever happen?
+ * Just continue and change wiring anyway.
+ */
+ if (!pmap_pte_v(pte)) {
+ if (pmapdebug & PDB_PARANOIA)
+ pg("pmap_change_wiring: invalid PTE for %x\n", va);
+ }
+#endif
+ if (wired && !pmap_pte_w(pte) || !wired && pmap_pte_w(pte)) {
+ if (wired)
+ pmap->pm_stats.wired_count++;
+ else
+ pmap->pm_stats.wired_count--;
+ }
+ /*
+ * Wiring is not a hardware characteristic so there is no need
+ * to invalidate TLB.
+ */
+ ix = 0;
+ do {
+ pmap_pte_set_w(pte++, wired);
+ } while (++ix != ns532pagesperpage);
+}
+
+/*
+ * Routine: pmap_pte
+ * Function:
+ * Extract the page table entry associated
+ * with the given map/virtual_address pair.
+ * [ what about induced faults -wfj]
+ */
+
+struct pte *pmap_pte(pmap, va)
+ register pmap_t pmap;
+ vm_offset_t va;
+{
+#ifdef DEBUGx
+ if (pmapdebug & PDB_FOLLOW)
+ printf("pmap_pte(%x, %x) ->\n", pmap, va);
+#endif
+ if (pmap && pmap_pde_v(pmap_pde(pmap, va))) {
+
+ /* are we current address space or kernel? */
+ if (pmap->pm_pdir[PTDPTDI].pd_pfnum == PTDpde.pd_pfnum
+ || pmap == pmap_kernel())
+ return ((struct pte *) vtopte(va));
+
+ /* otherwise, we are alternate address space */
+ else {
+ if (pmap->pm_pdir[PTDPTDI].pd_pfnum
+ != APTDpde.pd_pfnum) {
+ APTDpde = pmap->pm_pdir[PTDPTDI];
+ tlbflush();
+ }
+ return((struct pte *) avtopte(va));
+ }
+ }
+ return(0);
+}
+
+/*
+ * 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 DEBUGx
+ if (pmapdebug & PDB_FOLLOW)
+ pg("pmap_extract(%x, %x) -> ", pmap, va);
+#endif
+ pa = 0;
+ if (pmap && pmap_pde_v(pmap_pde(pmap, va))) {
+ pa = *(int *) pmap_pte(pmap, va);
+ }
+ if (pa)
+ pa = (pa & PG_FRAME) | (va & ~PG_FRAME);
+#ifdef DEBUGx
+ if (pmapdebug & PDB_FOLLOW)
+ printf("%x\n", pa);
+#endif
+ return(pa);
+}
+
+/*
+ * Copy the range specified by src_addr/len
+ * from the source map to the range dst_addr/len
+ * in the destination map.
+ *
+ * This routine is only advisory and need not do anything.
+ */
+void pmap_copy(dst_pmap, src_pmap, dst_addr, len, src_addr)
+ pmap_t dst_pmap;
+ pmap_t src_pmap;
+ vm_offset_t dst_addr;
+ vm_size_t len;
+ vm_offset_t src_addr;
+{
+/* printf ("pmap_copy: dst=0x%x src=0x%x d_addr=0x%x len=0x%x s_addr=0x%x\n",
+ dst_pmap, src_pmap, dst_addr, len, 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()");
+#endif
+ tlbflush();
+}
+
+/*
+ * 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.
+ * [ needs to be written -wfj ]
+ */
+void
+pmap_collect(pmap)
+ pmap_t pmap;
+{
+ register vm_offset_t pa;
+ register pv_entry_t pv;
+ register int *pte;
+ vm_offset_t kpa;
+ int s;
+
+#ifdef DEBUG
+ int *pde;
+ int opmapdebug;
+#endif
+ if (pmap != pmap_kernel())
+ return;
+}
+
+/* [ macro again?, should I force kstack into user map here? -wfj ] */
+void
+pmap_activate(pmap, pcbp)
+ register pmap_t pmap;
+ struct pcb *pcbp;
+{
+#ifdef DEBUG
+ if (pmapdebug & (PDB_FOLLOW|PDB_PDRTAB))
+ pg("pmap_activate(%x, %x)\n", pmap, pcbp);
+#endif
+ PMAP_ACTIVATE(pmap, pcbp);
+#ifdef DEBUG
+ {
+ int x;
+ printf("pde ");
+ for(x=0x3f6; x < 0x3fA; x++)
+ printf("%x ", pmap->pm_pdir[x]);
+ pads(pmap);
+ pg(" pcb_ptb %x\n", pcbp->pcb_ptb);
+ }
+#endif
+}
+
+/*
+ * pmap_zero_page zeros the specified (machine independent)
+ * page by mapping the page into virtual memory and using
+ * bzero to clear its contents, one machine dependent page
+ * at a time.
+ */
+void
+pmap_zero_page(phys)
+ register vm_offset_t phys;
+{
+ register int ix;
+
+#ifdef DEBUG
+ if (pmapdebug & PDB_FOLLOW)
+ printf("pmap_zero_page(%x)\n", phys);
+#endif
+ phys >>= PG_SHIFT;
+ ix = 0;
+ do {
+ clearseg(phys++);
+ } while (++ix != ns532pagesperpage);
+}
+
+/*
+ * pmap_copy_page copies the specified (machine independent)
+ * page by mapping the page into virtual memory and using
+ * bcopy to copy the page, one machine dependent page at a
+ * time.
+ */
+void
+pmap_copy_page(src, dst)
+ register vm_offset_t src, dst;
+{
+ register int ix;
+
+#ifdef DEBUG
+ if (pmapdebug & PDB_FOLLOW)
+ printf("pmap_copy_page(%x, %x)", src, dst);
+#endif
+ src >>= PG_SHIFT;
+ dst >>= PG_SHIFT;
+ ix = 0;
+ do {
+ physcopyseg(src++, dst++);
+ } while (++ix != ns532pagesperpage);
+}
+
+
+/*
+ * Routine: pmap_pageable
+ * Function:
+ * Make the specified pages (by pmap, offset)
+ * pageable (or not) as requested.
+ *
+ * A page which is not pageable may not take
+ * a fault; therefore, its page table entry
+ * must remain valid for the duration.
+ *
+ * This routine is merely advisory; pmap_enter
+ * will specify that these pages are to be wired
+ * down (or not) as appropriate.
+ */
+void
+pmap_pageable(pmap, sva, eva, pageable)
+ pmap_t pmap;
+ vm_offset_t sva, eva;
+ boolean_t pageable;
+{
+#ifdef DEBUG
+ if (pmapdebug & PDB_FOLLOW)
+ printf("pmap_pageable(%x, %x, %x, %x)\n",
+ pmap, sva, eva, pageable);
+#endif
+ /*
+ * If we are making a PT page pageable then all valid
+ * mappings must be gone from that page. Hence it should
+ * be all zeros and there is no need to clean it.
+ * Assumptions:
+ * - we are called with only one page at a time
+ * - PT pages have only one pv_table entry
+ */
+ if (pmap == pmap_kernel() && pageable && sva + PAGE_SIZE == eva) {
+ register pv_entry_t pv;
+ register vm_offset_t pa;
+
+#ifdef DEBUG
+ if ((pmapdebug & (PDB_FOLLOW|PDB_PTPAGE)) == PDB_PTPAGE)
+ printf("pmap_pageable(%x, %x, %x, %x)\n",
+ pmap, sva, eva, pageable);
+#endif
+ /*if (!pmap_pde_v(pmap_pde(pmap, sva)))
+ return;*/
+ if(pmap_pte(pmap, sva) == 0)
+ return;
+ pa = pmap_pte_pa(pmap_pte(pmap, sva));
+ if (pa < vm_first_phys || pa >= vm_last_phys)
+ return;
+ pv = pa_to_pvh(pa);
+ /*if (!ispt(pv->pv_va))
+ return;*/
+#ifdef DEBUG
+ if (pv->pv_va != sva || pv->pv_next) {
+ pg("pmap_pageable: bad PT page va %x next %x\n",
+ pv->pv_va, pv->pv_next);
+ return;
+ }
+#endif
+ /*
+ * Mark it unmodified to avoid pageout
+ */
+ pmap_clear_modify(pa);
+#ifdef needsomethinglikethis
+ if (pmapdebug & PDB_PTPAGE)
+ pg("pmap_pageable: PT page %x(%x) unmodified\n",
+ sva, *(int *)pmap_pte(pmap, sva));
+ if (pmapdebug & PDB_WIRING)
+ pmap_check_wiring("pageable", sva);
+#endif
+ }
+}
+
+/*
+ * Clear the modify bits on the specified physical page.
+ */
+
+void
+pmap_clear_modify(pa)
+ vm_offset_t pa;
+{
+#ifdef DEBUG
+ if (pmapdebug & PDB_FOLLOW)
+ printf("pmap_clear_modify(%x)", pa);
+#endif
+ pmap_changebit(pa, PG_M, FALSE);
+}
+
+/*
+ * pmap_clear_reference:
+ *
+ * Clear the reference bit on the specified physical page.
+ */
+
+void pmap_clear_reference(pa)
+ vm_offset_t pa;
+{
+#ifdef DEBUG
+ if (pmapdebug & PDB_FOLLOW)
+ printf("pmap_clear_reference(%x)", pa);
+#endif
+ pmap_changebit(pa, PG_U, FALSE);
+}
+
+/*
+ * pmap_is_referenced:
+ *
+ * Return whether or not the specified physical page is referenced
+ * by any physical maps.
+ */
+
+boolean_t
+pmap_is_referenced(pa)
+ vm_offset_t pa;
+{
+#ifdef DEBUG
+ if (pmapdebug & PDB_FOLLOW) {
+ boolean_t rv = pmap_testbit(pa, PG_U);
+ printf("pmap_is_referenced(%x) -> %c", pa, "FT"[rv]);
+ return(rv);
+ }
+#endif
+ return(pmap_testbit(pa, PG_U));
+}
+
+/*
+ * pmap_is_modified:
+ *
+ * Return whether or not the specified physical page is modified
+ * by any physical maps.
+ */
+
+boolean_t
+pmap_is_modified(pa)
+ vm_offset_t pa;
+{
+#ifdef DEBUG
+ if (pmapdebug & PDB_FOLLOW) {
+ boolean_t rv = pmap_testbit(pa, PG_M);
+ printf("pmap_is_modified(%x) -> %c\n", pa, "FT"[rv]);
+ return(rv);
+ }
+#endif
+ return(pmap_testbit(pa, PG_M));
+}
+
+vm_offset_t
+pmap_phys_address(ppn)
+ int ppn;
+{
+ return(ns532_ptob(ppn));
+}
+
+/*
+ * Miscellaneous support routines follow
+ */
+
+ns532_protection_init()
+{
+ register int *kp, prot;
+
+ kp = protection_codes;
+ for (prot = 0; prot < 8; prot++) {
+ switch (prot) {
+ case VM_PROT_NONE | VM_PROT_NONE | VM_PROT_NONE:
+ *kp++ = 0;
+ break;
+ case VM_PROT_READ | VM_PROT_NONE | VM_PROT_NONE:
+ case VM_PROT_READ | VM_PROT_NONE | VM_PROT_EXECUTE:
+ case VM_PROT_NONE | VM_PROT_NONE | VM_PROT_EXECUTE:
+ *kp++ = PG_RO;
+ break;
+ case VM_PROT_NONE | VM_PROT_WRITE | VM_PROT_NONE:
+ case VM_PROT_NONE | VM_PROT_WRITE | VM_PROT_EXECUTE:
+ case VM_PROT_READ | VM_PROT_WRITE | VM_PROT_NONE:
+ case VM_PROT_READ | VM_PROT_WRITE | VM_PROT_EXECUTE:
+ *kp++ = PG_RW;
+ break;
+ }
+ }
+}
+
+boolean_t
+pmap_testbit(pa, bit)
+ register vm_offset_t pa;
+ int bit;
+{
+ register pv_entry_t pv;
+ register int *pte, ix;
+ int s;
+
+ if (pa < vm_first_phys || pa >= vm_last_phys)
+ return(FALSE);
+
+ pv = pa_to_pvh(pa);
+ s = splimp();
+ /*
+ * Check saved info first
+ */
+ if (pmap_attributes[pa_index(pa)] & bit) {
+ splx(s);
+ return(TRUE);
+ }
+ /*
+ * Not found, check current mappings returning
+ * immediately if found.
+ */
+ if (pv->pv_pmap != NULL) {
+ for (; pv; pv = pv->pv_next) {
+ pte = (int *) pmap_pte(pv->pv_pmap, pv->pv_va);
+ ix = 0;
+ do {
+ if (*pte++ & bit) {
+ splx(s);
+ return(TRUE);
+ }
+ } while (++ix != ns532pagesperpage);
+ }
+ }
+ splx(s);
+ return(FALSE);
+}
+
+pmap_changebit(pa, bit, setem)
+ register vm_offset_t pa;
+ int bit;
+ boolean_t setem;
+{
+ register pv_entry_t pv;
+ register int *pte, npte, ix;
+ vm_offset_t va;
+ int s;
+ boolean_t firstpage = TRUE;
+
+#ifdef DEBUG
+ if (pmapdebug & PDB_BITS)
+ printf("pmap_changebit(%x, %x, %s)",
+ pa, bit, setem ? "set" : "clear");
+#endif
+ if (pa < vm_first_phys || pa >= vm_last_phys)
+ return;
+
+ pv = pa_to_pvh(pa);
+ s = splimp();
+ /*
+ * Clear saved attributes (modify, reference)
+ */
+ if (!setem)
+ pmap_attributes[pa_index(pa)] &= ~bit;
+
+ /*
+ * Loop over all current mappings setting/clearing as appropos
+ * If setting RO do we need to clear the VAC?
+ */
+
+ if (pv->pv_pmap != NULL) {
+#ifdef DEBUG
+ int toflush = 0;
+#endif
+ for (; pv; pv = pv->pv_next) {
+#ifdef DEBUG
+ toflush |= (pv->pv_pmap == pmap_kernel()) ? 2 : 1;
+#endif
+ va = pv->pv_va;
+
+ /*
+ * XXX don't write protect pager mappings
+ */
+ if (bit == PG_RO) {
+ extern vm_offset_t pager_sva, pager_eva;
+
+ if (va >= pager_sva && va < pager_eva)
+ continue;
+ }
+
+ pte = (int *) pmap_pte(pv->pv_pmap, va);
+ ix = 0;
+ do {
+ if (setem)
+ npte = *pte | bit;
+ else
+ npte = *pte & ~bit;
+ if (*pte != npte) {
+ *pte = npte;
+ /*TBIS(va);*/
+ }
+ va += NS532_PAGE_SIZE;
+ pte++;
+ } while (++ix != ns532pagesperpage);
+
+ if (curproc && pv->pv_pmap == &curproc->p_vmspace->vm_pmap)
+ pmap_activate(pv->pv_pmap, (struct pcb *)curproc->p_addr);
+ }
+#ifdef somethinglikethis
+ if (setem && bit == PG_RO && (pmapvacflush & PVF_PROTECT)) {
+ if ((pmapvacflush & PVF_TOTAL) || toflush == 3)
+ DCIA();
+ else if (toflush == 2)
+ DCIS();
+ else
+ DCIU();
+ }
+#endif
+ }
+ splx(s);
+}
+
+#ifdef DEBUG
+pmap_pvdump(pa)
+ vm_offset_t pa;
+{
+ register pv_entry_t pv;
+
+ printf("pa %x", pa);
+ for (pv = pa_to_pvh(pa); pv; pv = pv->pv_next) {
+ printf(" -> pmap %x, va %x, flags %x",
+ pv->pv_pmap, pv->pv_va, pv->pv_flags);
+ pads(pv->pv_pmap);
+ }
+ printf(" ");
+}
+
+#ifdef notyet
+pmap_check_wiring(str, va)
+ char *str;
+ vm_offset_t va;
+{
+ vm_map_entry_t entry;
+ register int count, *pte;
+
+ va = trunc_page(va);
+ if (!pmap_pde_v(pmap_pde(pmap_kernel(), va)) ||
+ !pmap_pte_v(pmap_pte(pmap_kernel(), va)))
+ return;
+
+ if (!vm_map_lookup_entry(pt_map, va, &entry)) {
+ pg("wired_check: entry for %x not found\n", va);
+ return;
+ }
+ count = 0;
+ for (pte = (int *)va; pte < (int *)(va+PAGE_SIZE); pte++)
+ if (*pte)
+ count++;
+ if (entry->wired_count != count)
+ pg("*%s*: %x: w%d/a%d\n",
+ str, va, entry->wired_count, count);
+}
+#endif
+
+/* print address space of pmap*/
+pads(pm)
+ pmap_t pm;
+{
+ unsigned va, i, j;
+ struct pte *ptep;
+ int num=0;
+
+/* if(pm == pmap_kernel()) return; */
+ for (i = 0; i < 1024; i++)
+ if(pm->pm_pdir[i].pd_v)
+ for (j = 0; j < 1024 ; j++) {
+ va = (i<<22)+(j<<12);
+ if (pm == pmap_kernel() && va < 0xfe000000)
+ continue;
+ if (pm != pmap_kernel() && va > UPT_MAX_ADDRESS)
+ continue;
+ ptep = pmap_pte(pm, va);
+ if(pmap_pte_v(ptep)) {
+ if (num % 4 == 0) printf (" ");
+ printf("%8x:%8x", va, *(int *)ptep);
+ if (++num %4 == 0)
+ printf ("\n");
+ else
+ printf (" ");
+ }
+ } ;
+ if (num % 4 != 0) printf ("\n");
+}
+
+pmap_print (pmap_t pm, unsigned int start, unsigned int stop)
+{
+ unsigned va, i, j;
+ struct pte *ptep;
+ int num;
+
+ printf ("pmap_print: pm_pdir = 0x%x\n", pm->pm_pdir);
+ printf (" map between 0x%x and 0x%x\n", start, stop);
+ for (i = 0; i < 1024; i++)
+ if (pm->pm_pdir != 0) {
+ if(pm->pm_pdir[i].pd_v && (start>>22) <= i
+ && (stop>>22) >= i) {
+ printf ("1st Level Entry 0x%x, 2nd PA = 0x%x000\n",
+ i, pm->pm_pdir[i].pd_pfnum);
+ num = 0;
+ for (j = 0; j < 1024 ; j++) {
+ va = (i<<22)+(j<<12);
+ ptep = pmap_pte(pm, va);
+ if(ptep->pg_v && start <= va && stop >= va) {
+ if (num % 5 == 0) printf (" ");
+ printf("%8x:%05x", va, ptep->pg_pfnum);
+ if (++num %5 == 0)
+ printf ("\n");
+ else
+ printf (" ");
+ }
+ } ;
+ if (num % 5 != 0) printf ("\n");
+ };
+ };
+ if (num % 5 != 0) printf ("\n");
+}
+#endif
diff --git a/sys/arch/pc532/pc532/process_machdep.c b/sys/arch/pc532/pc532/process_machdep.c
new file mode 100644
index 00000000000..fecbcd2d193
--- /dev/null
+++ b/sys/arch/pc532/pc532/process_machdep.c
@@ -0,0 +1,179 @@
+/* $NetBSD: process_machdep.c,v 1.8 1995/09/26 20:16:32 phil Exp $ */
+
+/*
+ * 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.
+ */
+
+/* Modified by Phil Nelson for the pc532 port. 1/12/94 */
+
+/*
+ * 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>
+#include <machine/frame.h>
+
+static inline struct reg *
+process_regs(p)
+ struct proc *p;
+{
+ void *ptr;
+
+ if ((p->p_flag & P_INMEM) == 0)
+ return (NULL);
+
+ ptr = (char *)p->p_addr + ((char *)p->p_md.md_regs - (char *)USRSTACK);
+ return (ptr);
+}
+
+int
+process_read_regs(p, regs)
+ struct proc *p;
+ struct reg *regs;
+{
+ struct reg *pregs;
+
+ pregs = process_regs(p);
+ if (pregs == NULL)
+ return (EIO);
+
+ *regs = *pregs;
+ return (0);
+}
+
+int
+process_write_regs(p, regs)
+ struct proc *p;
+ struct reg *regs;
+{
+ struct reg *pregs;
+
+ pregs = process_regs(p);
+ if (pregs == NULL)
+ return (EIO);
+
+ if (((regs->r_psr ^ pregs->r_psr) & PSL_USERSTATIC) != 0)
+ return (EPERM);
+
+ *pregs = *regs;
+ return (0);
+}
+
+int
+process_read_fpregs(p, regs)
+ struct proc *p;
+ struct fpreg *regs;
+{
+ if ((p->p_flag & P_INMEM) == 0)
+ return (EIO);
+
+ bcopy(&p->p_addr->u_pcb.pcb_fsr, regs, sizeof(*regs));
+ return (0);
+}
+
+int
+process_write_fpregs(p, regs)
+ struct proc *p;
+ struct fpreg *regs;
+{
+ if ((p->p_flag & P_INMEM) == 0)
+ return (EIO);
+
+ bcopy(regs, &p->p_addr->u_pcb.pcb_fsr, sizeof(*regs));
+ return (0);
+}
+
+int
+process_sstep(p, sstep)
+ struct proc *p;
+ int sstep;
+{
+ struct reg *pregs;
+
+ pregs = process_regs(p);
+ if (pregs == NULL)
+ return (EIO);
+
+ if (sstep)
+ pregs->r_psr |= PSL_T;
+ else
+ pregs->r_psr &= ~PSL_T;
+
+ return (0);
+}
+
+int
+process_set_pc(p, addr)
+ struct proc *p;
+ caddr_t addr;
+{
+ struct reg *pregs;
+
+ pregs = process_regs(p);
+ if (pregs == NULL)
+ return (EIO);
+
+ pregs->r_pc = (int)addr;
+
+ return (0);
+}
diff --git a/sys/arch/pc532/pc532/random.s b/sys/arch/pc532/pc532/random.s
new file mode 100644
index 00000000000..174d296cd04
--- /dev/null
+++ b/sys/arch/pc532/pc532/random.s
@@ -0,0 +1,75 @@
+/* $NetBSD: random.s,v 1.2 1994/10/26 08:25:17 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: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the University of California,
+ * Lawrence Berkeley Laboratory and its contributors.'' 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 ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Here is a very good random number generator. This implementation is
+ * based on ``Two Fast Implementations of the "Minimal Standard" Random
+ * Number Generator'', David G. Carta, Communications of the ACM, Jan 1990,
+ * Vol 33 No 1. Do NOT modify this code unless you have a very thorough
+ * understanding of the algorithm. It's trickier than you think. If
+ * you do change it, make sure that its 10,000'th invocation returns
+ * 1043618065.
+ *
+ * Here is easier-to-decipher pseudocode:
+ *
+ * p = (16807*seed)<30:0> # e.g., the low 31 bits of the product
+ * q = (16807*seed)<62:31> # e.g., the high 31 bits starting at bit 32
+ * if (p + q < 2^31)
+ * seed = p + q
+ * else
+ * seed = ((p + q) & (2^31 - 1)) + 1
+ * return (seed);
+ *
+ * The result is in (0,2^31), e.g., it's always positive.
+ *
+ * written by Phil Nelson for ns32k.
+ */
+
+#include <machine/asm.h>
+
+ .data
+randseed:
+ .long 1
+
+ .text
+ENTRY(random)
+ enter [r2],0
+ movzwd randseed(pc), r2 /* 1st 16 bit multiply */
+ muld 16807, r2 /* result is positive */
+ movd r2, r1
+ bicd 0xffff0000, r2 /* save bottom 16 bits */
+ ashd -16, r1 /* move top 16 to bottom */
+ movzwd randseed+2(pc), r0 /* 2n 16 bit multiply */
+ muld 16807, r0
+ addd r0, r1 /* add to top 16 bits of first */
+ movd r1, r0 /* save a copy in r0 */
+ bicd 0xffff8000, r1 /* move "bottom" 15 to r2 */
+ ashd 16, r1
+ addd r2, r1 /* this is now p! */
+ ashd -15, r0 /* this is now q! */
+ addd r1, r0 /* q+r */
+ bfc nocarry
+ subd 0x7fffffff, r0
+
+nocarry:
+ movd r0, randseed(pc)
+ exit [r2]
+ ret 0
diff --git a/sys/arch/pc532/pc532/swapgeneric.c b/sys/arch/pc532/pc532/swapgeneric.c
new file mode 100644
index 00000000000..33685357263
--- /dev/null
+++ b/sys/arch/pc532/pc532/swapgeneric.c
@@ -0,0 +1,199 @@
+/* $NetBSD: swapgeneric.c,v 1.1 1995/08/25 07:49:14 phil Exp $ */
+
+/*-
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * William Jolitz.
+ *
+ * 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 5.5 (Berkeley) 5/9/91
+ */
+
+#include <sys/param.h>
+#include <sys/conf.h>
+#include <sys/buf.h>
+#include <sys/systm.h>
+#include <sys/reboot.h>
+#include <sys/device.h>
+#include <sys/disklabel.h>
+
+#include "sd.h"
+#include "cd.h"
+#ifdef RAMD_SIZE
+#define NRD 1
+#else
+#define NRD 0
+#endif
+
+/*
+ * Generic configuration; all in one
+ */
+dev_t rootdev = NODEV;
+dev_t argdev = NODEV;
+dev_t dumpdev = NODEV;
+int nswap;
+struct swdevt swdevt[] = {
+ { NODEV, 1, 0 },
+ { NODEV, 0, 0 },
+};
+long dumplo;
+int dmmin, dmmax, dmtext;
+
+#if NSD > 0
+extern struct cfdriver sdcd;
+#endif
+#if NCD > 0
+extern struct cfdriver cdcd;
+#endif
+#if NRD > 0
+extern struct cfdriver rdcd;
+#endif
+
+struct genericconf {
+ struct cfdriver *gc_driver;
+ char *gc_name;
+ dev_t gc_major;
+} genericconf[] = {
+#if NSD > 0
+ { &sdcd, "sd", 0 },
+#endif
+#if NCD > 0
+ { &cdcd, "cd", 4 },
+#endif
+#if NRD > 0
+ { &rdcd, "rd", 3 },
+#endif
+ { 0 }
+};
+
+extern int ffs_mountroot();
+int (*mountroot)() = ffs_mountroot;
+
+setconf()
+{
+ register struct genericconf *gc;
+ int unit, swaponroot = 0;
+
+ if (rootdev != NODEV)
+ goto doswap;
+
+ if (genericconf[0].gc_driver == 0)
+ goto verybad;
+
+ if (boothowto & RB_ASKNAME) {
+ char name[128];
+retry:
+ printf("root device? ");
+ gets(name);
+ for (gc = genericconf; gc->gc_driver; gc++)
+ if (gc->gc_name[0] == name[0] &&
+ gc->gc_name[1] == name[1])
+ goto gotit;
+ goto bad;
+gotit:
+ if (name[3] == '*') {
+ name[3] = name[4];
+ swaponroot++;
+ }
+ if (name[2] >= '0' && name[2] <= '7' && name[3] == 0) {
+ unit = name[2] - '0';
+ goto found;
+ }
+ printf("bad/missing unit number\n");
+bad:
+ printf("use:\n");
+ for (gc = genericconf; gc->gc_driver; gc++)
+ printf("\t%s%%d\n", gc->gc_name);
+ goto retry;
+ }
+ unit = 0;
+ for (gc = genericconf; gc->gc_driver; gc++) {
+ if (gc->gc_driver->cd_ndevs > unit &&
+ gc->gc_driver->cd_devs[unit]) {
+ printf("root on %s0\n", gc->gc_name);
+ goto found;
+ }
+ }
+verybad:
+ printf("no suitable root -- hit any key to reboot\n");
+ printf("\n>");
+ cngetc();
+ cpu_reset();
+ for (;;) ;
+
+found:
+ rootdev = makedev(gc->gc_major, unit * MAXPARTITIONS);
+doswap:
+ swdevt[0].sw_dev = argdev = dumpdev =
+ makedev(major(rootdev), minor(rootdev) + 1);
+ /* swap size and dumplo set during autoconfigure */
+ if (swaponroot)
+ rootdev = dumpdev;
+}
+
+gets(cp)
+ char *cp;
+{
+ register char *lp;
+ register c;
+
+ lp = cp;
+ for (;;) {
+ printf("%c", c = cngetc()&0177);
+ switch (c) {
+ case '\n':
+ case '\r':
+ *lp++ = '\0';
+ printf("\r\n");
+ return;
+ case '\b':
+ case '\177':
+ if (lp > cp) {
+ printf(" \b");
+ lp--;
+ }
+ continue;
+ case '#':
+ lp--;
+ if (lp < cp)
+ lp = cp;
+ continue;
+ case '@':
+ case 'u'&037:
+ lp = cp;
+ printf("%c", '\n');
+ continue;
+ default:
+ *lp++ = c;
+ }
+ }
+}
diff --git a/sys/arch/pc532/pc532/sys_machdep.c b/sys/arch/pc532/pc532/sys_machdep.c
new file mode 100644
index 00000000000..0ae1c03dd9b
--- /dev/null
+++ b/sys/arch/pc532/pc532/sys_machdep.c
@@ -0,0 +1,110 @@
+/* $NetBSD: sys_machdep.c,v 1.5 1995/09/26 20:16:34 phil Exp $ */
+
+/*-
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * William Jolitz.
+ *
+ * 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 5.5 (Berkeley) 1/19/91
+ */
+
+#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, v, retval)
+ struct proc *p;
+ void *v;
+ register_t *retval;
+{
+ register struct vtrace_args /* {
+ syscallarg(int) request;
+ syscallarg(int) value;
+ } */ *uap = v;
+ int vdoualarm();
+
+ switch (SCARG(uap, request)) {
+
+ case VTR_DISABLE: /* disable a trace point */
+ case VTR_ENABLE: /* enable a trace point */
+ if (SCARG(uap, value) < 0 || SCARG(uap, value) >= TR_NFLAGS)
+ return (EINVAL);
+ *retval = traceflags[SCARG(uap, value)];
+ traceflags[SCARG(uap, value)] = SCARG(uap, request);
+ break;
+
+ case VTR_VALUE: /* return a trace point setting */
+ if (SCARG(uap, value) < 0 || SCARG(uap, value) >= TR_NFLAGS)
+ return (EINVAL);
+ *retval = traceflags[SCARG(uap, value)];
+ break;
+
+ case VTR_UALARM: /* set a real-time ualarm, less than 1 min */
+ if (SCARG(uap, value) <= 0 || SCARG(uap, value) > 60 * hz ||
+ nvualarm > 5)
+ return (EINVAL);
+ nvualarm++;
+ timeout(vdoualarm, (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
diff --git a/sys/arch/pc532/pc532/trap.c b/sys/arch/pc532/pc532/trap.c
new file mode 100644
index 00000000000..d72213d7d48
--- /dev/null
+++ b/sys/arch/pc532/pc532/trap.c
@@ -0,0 +1,570 @@
+/* $NetBSD: trap.c,v 1.13 1995/06/09 06:00:10 phil Exp $ */
+
+/*-
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * the University of Utah, and William Jolitz.
+ *
+ * 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.
+ *
+ * @(#)trap.c 7.4 (Berkeley) 5/13/91
+ */
+
+/*
+ * 532 Trap and System call handling
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/proc.h>
+#include <sys/user.h>
+#include <sys/acct.h>
+#include <sys/kernel.h>
+#ifdef KTRACE
+#include <sys/ktrace.h>
+#endif
+#include <sys/syscall.h>
+
+#include <vm/vm_param.h>
+#include <vm/pmap.h>
+#include <vm/vm_map.h>
+
+#include <machine/cpu.h>
+#include <machine/trap.h>
+#include <machine/psl.h>
+
+
+
+unsigned rcr2();
+extern short cpl;
+
+/*
+ * trap(frame):
+ * Exception, fault, and trap interface to BSD kernel. This
+ * common code is called from assembly language IDT gate entry
+ * routines that prepare a suitable stack frame, and restore this
+ * frame after the exception has been processed. Note that the
+ * effect is as if the arguments were passed call by reference.
+ */
+/*ARGSUSED*/
+trap(frame)
+ struct trapframe frame;
+{
+ register int i;
+ register struct proc *p = curproc;
+ struct timeval sticks;
+ int ucode, type, tear, msr;
+
+ cnt.v_trap++;
+
+ type = frame.tf_trapno;
+ tear = frame.tf_tear;
+ msr = frame.tf_msr;
+
+ if (curpcb->pcb_onfault && frame.tf_trapno != T_ABT) {
+copyfault:
+ frame.tf_pc = (int)curpcb->pcb_onfault;
+ return;
+ }
+
+#ifdef DDB
+ if (curpcb && curpcb->pcb_onfault) {
+ if (frame.tf_trapno == T_BPTFLT
+ || frame.tf_trapno == T_TRCTRAP)
+ if (kdb_trap (type, 0, &frame))
+ return;
+ }
+#endif
+
+ if (curpcb == 0 || curproc == 0) goto we_re_toast;
+
+ if ((frame.tf_psr & PSL_USER) == PSL_USER) {
+ type |= T_USER;
+#ifdef notdef
+ sticks = p->p_stime;
+#endif
+ p->p_md.md_regs = (int *)&(frame.tf_reg);
+ }
+
+ ucode = 0;
+
+ switch (type) {
+
+ default:
+ we_re_toast:
+#ifdef KDB
+ if (kdb_trap(&psl))
+ return;
+#endif
+#ifdef DDB
+ if (kdb_trap (type, 0, &frame))
+ return;
+#endif
+
+ printf("bad trap: type=%d, pc=0x%x, tear=0x%x, msr=0x%x\n",
+ type, frame.tf_pc, frame.tf_tear, frame.tf_msr);
+ panic("trap");
+ /*NOTREACHED*/
+
+ case T_ABT: /* System level pagefault! */
+ if (((msr & MSR_STT) == STT_SEQ_INS)
+ || ((msr & MSR_STT) == STT_NSQ_INS))
+ {
+ printf ("System pagefault: pc=0x%x, tear=0x%x, msr=0x%x\n",
+ frame.tf_pc, frame.tf_tear, frame.tf_msr);
+ goto we_re_toast;
+ }
+
+ /* fall into */
+ case T_ABT | T_USER: /* User level pagefault! */
+/* if (type == (T_ABT | T_USER))
+ printf ("pagefault: pc=0x%x, tear=0x%x, msr=0x%x\n",
+ frame.tf_pc, frame.tf_tear, frame.tf_msr); */
+ {
+ register vm_offset_t va;
+ register struct vmspace *vm = p->p_vmspace;
+ register vm_map_t map;
+ int rv;
+ vm_prot_t ftype;
+ extern vm_map_t kernel_map;
+ unsigned nss,v;
+
+ va = trunc_page((vm_offset_t)tear);
+ /*
+ * Avoid even looking at pde_v(va) for high va's. va's
+ * above VM_MAX_KERNEL_ADDRESS don't correspond to normal
+ * PDE's (half of them correspond to APDEpde and half to
+ * an unmapped kernel PDE). va's betweeen 0xFEC00000 and
+ * VM_MAX_KERNEL_ADDRESS correspond to unmapped kernel PDE's
+ * (XXX - why are only 3 initialized when 6 are required to
+ * reach VM_MAX_KERNEL_ADDRESS?). Faulting in an unmapped
+ * kernel page table would give inconsistent PTD's.
+ *
+ * XXX - faulting in unmapped page tables wastes a page if
+ * va turns out to be invalid.
+ *
+ * XXX - should "kernel address space" cover the kernel page
+ * tables? Might have same problem with PDEpde as with
+ * APDEpde (or there may be no problem with APDEpde).
+ */
+ if (va > 0xFEBFF000) {
+ v = KERN_FAILURE; /* becomes SIGBUS */
+ goto nogo;
+ }
+ /*
+ * It is only a kernel address space fault iff:
+ * 1. (type & T_USER) == 0 and
+ * 2. pcb_onfault not set or
+ * 3. pcb_onfault set but supervisor space fault
+ * The last can occur during an exec() copyin where the
+ * argument space is lazy-allocated.
+ */
+ if (type == T_ABT && va >= KERNBASE)
+ map = kernel_map;
+ else
+ map = &vm->vm_map;
+ if ((msr & MSR_DDT) == DDT_WRITE
+ || (msr & MSR_STT) == STT_RMW)
+ ftype = VM_PROT_READ | VM_PROT_WRITE;
+ else
+ ftype = VM_PROT_READ;
+
+#ifdef DEBUG
+ if (map == kernel_map && va == 0) {
+ printf("trap: bad kernel access at %x\n", va);
+ goto we_re_toast;
+ }
+#endif
+
+ nss = 0;
+ if ((caddr_t)va >= vm->vm_maxsaddr
+ && (caddr_t)va < (caddr_t)VM_MAXUSER_ADDRESS
+ && map != kernel_map) {
+ nss = clrnd(btoc((unsigned)vm->vm_maxsaddr
+ + MAXSSIZ - (unsigned)va));
+ if (nss > btoc(p->p_rlimit[RLIMIT_STACK].rlim_cur)) {
+/*pg("trap rlimit %d, maxsaddr %x va %x ", nss, vm->vm_maxsaddr, va);*/
+ rv = KERN_FAILURE;
+ goto nogo;
+ }
+ }
+
+ /* check if page table is mapped, if not, fault it first */
+#define pde_v(v) (PTD[((v)>>PD_SHIFT)&1023].pd_v)
+ if (!pde_v(va)) {
+ v = trunc_page(vtopte(va));
+ rv = vm_fault(map, v, ftype, FALSE);
+ if (rv != KERN_SUCCESS) goto nogo;
+ /* check if page table fault, increment wiring */
+ vm_map_pageable(map, v, round_page(v+1), FALSE);
+ } else v=0;
+ rv = vm_fault(map, va, ftype, FALSE);
+
+ if (rv == KERN_SUCCESS) {
+ /*
+ * XXX: continuation of rude stack hack
+ */
+ if (nss > vm->vm_ssize)
+ vm->vm_ssize = nss;
+ va = trunc_page(vtopte(va));
+ /* for page table, increment wiring
+ as long as not a page table fault as well */
+ if (!v && map != kernel_map)
+ vm_map_pageable(map, va, round_page(va+1), FALSE);
+ if (type == T_ABT)
+ return;
+ goto out;
+ }
+nogo:
+ if (type == T_ABT) {
+ if (curpcb->pcb_onfault)
+ goto copyfault;
+ printf("vm_fault(0x%x, 0x%x, 0x%x, 0) -> 0x%x\n",
+ map, va, ftype, rv);
+ printf(" type 0x%x, tear 0x%x msr 0x%x\n",
+ type, tear, msr);
+ goto we_re_toast;
+ }
+ i = (rv == KERN_PROTECTION_FAILURE) ? SIGBUS : SIGSEGV;
+ break;
+ }
+
+ case T_UND | T_USER: /* undefined instruction */
+ case T_ILL | T_USER: /* Illegal instruction! */
+ ucode = type &~ T_USER;
+ i = SIGILL;
+ break;
+
+ case T_NVI | T_USER: /* Non-vectored interrupt */
+ case T_NMI | T_USER: /* non-maskable interrupt */
+ case T_FLG | T_USER: /* flag instruction */
+ goto we_re_toast;
+
+ case T_NBE | T_USER: /* non-restartable bus error */
+ ucode = type &~ T_USER;
+ i = SIGBUS;
+ break;
+
+ case T_RBE | T_USER: /* restartable bus error */
+ return;
+
+ case T_SLAVE | T_USER: /* coprocessor trap */
+ ucode = type &~ T_USER;
+/* ucode = FPE_INTDIV_TRAP; */
+ i = SIGFPE;
+ break;
+
+ case T_DVZ | T_USER: /* divide by zero */
+ ucode = type &~ T_USER;
+/* ucode = FPE_INTDIV_TRAP; */
+ i = SIGFPE;
+ break;
+
+ case T_OVF | T_USER: /* integer overflow trap */
+ ucode = type &~ T_USER;
+/* ucode = FPE_INTOVF_TRAP; */
+ i = SIGFPE;
+ break;
+
+
+ case T_TRC | T_USER: /* trace trap */
+ case T_BPT | T_USER: /* breakpoint instruction */
+ case T_DBG | T_USER: /* debug trap */
+ frame.tf_psr &= ~PSL_P;
+ i = SIGTRAP;
+ break;
+
+ case T_INTERRUPT | T_USER: /* Allow Process Switch */
+/* if ((p->p_flag & SOWEUPC) && p->p_stats->p_prof.pr_scale) {
+ addupc(frame.tf_eip, &p->p_stats->p_prof, 1);
+ p->p_flag &= ~SOWEUPC;
+ } */
+ goto out;
+
+ } /* End of switch */
+
+ trapsignal(p, i, ucode);
+ if ((type & T_USER) == 0)
+ return;
+out:
+ while (i = CURSIG(p))
+ postsig(i);
+ p->p_priority = p->p_usrpri;
+ if (want_resched) {
+ /*
+ * Since we are curproc, clock will normally just change
+ * our priority without moving us from one queue to another
+ * (since the running process is not on a queue.)
+ * If that happened after we setrunqueue ourselves but
+ * before we switch()'ed, we might not be on the queue
+ * indicated by our priority.
+ */
+ (void) splstatclock();
+ setrunqueue(p);
+ p->p_stats->p_ru.ru_nivcsw++;
+ mi_switch();
+ (void) splnone();
+ while (i = CURSIG(p))
+ postsig(i);
+ }
+ if (p->p_stats->p_prof.pr_scale) {
+ int ticks;
+
+#ifdef YO_WHAT
+ struct timeval *tv = &p->p_stime;
+
+ ticks = ((tv->tv_sec - syst.tv_sec) * 1000 +
+ (tv->tv_usec - syst.tv_usec) / 1000) / (tick / 1000);
+ if (ticks) {
+#ifdef PROFTIMER
+ extern int profscale;
+ addupc(frame.tf_eip, &p->p_stats->p_prof,
+ ticks * profscale);
+#else
+/* addupc(frame.tf_pc, &p->p_stats->p_prof, ticks); */
+#endif
+ }
+#endif
+ }
+ curpriority = p->p_priority;
+}
+
+
+/*
+ * syscall(frame):
+ * System call request from POSIX system call gate interface to kernel.
+ * Like trap(), argument is call by reference.
+ */
+/*ARGSUSED*/
+syscall(frame)
+ volatile struct syscframe frame;
+{
+
+ register caddr_t params;
+ register int i;
+ register struct sysent *callp;
+ register struct proc *p;
+ struct timeval sticks;
+ int error, opc, nsys;
+ int args[8], rval[2];
+ int code;
+
+ cnt.v_syscall++;
+
+ /* is this a user? */
+ if ((frame.sf_psr & PSL_USER) != PSL_USER)
+ panic("syscall - process not in user mode.");
+
+ p = curproc;
+#ifdef notdef
+ sticks = p->p_stime;
+#endif
+ code = frame.sf_reg[REG_R0];
+ p->p_md.md_regs = (int *) & (frame.sf_reg);
+ params = (caddr_t)frame.sf_usp + sizeof (int) ;
+
+ callp = p->p_emul->e_sysent;
+ nsys = p->p_emul->e_nsysent;
+
+ /* Set new return address and save old one. */
+ opc = frame.sf_pc++;
+
+ switch (code) {
+ case SYS_syscall:
+ code = fuword(params);
+ params += sizeof(int);
+ break;
+
+ case SYS___syscall:
+ code = fuword(params + _QUAD_LOWWORD * sizeof(int));
+ params += sizeof(quad_t);
+ break;
+
+ default:
+ /* do nothing by default */
+ break;
+ }
+
+ /* Guard against bad sys call numbers! */
+ if (code < 0 || code >= nsys)
+ callp += p->p_emul->e_nosys; /* indir (illegal) */
+ else
+ callp += code;
+
+ if ((i = callp->sy_argsize) &&
+ (error = copyin(params, (caddr_t)args, (u_int)i))) {
+ frame.sf_reg[REG_R0] = error;
+ frame.sf_psr |= PSL_C;
+#ifdef SYSCALL_DEBUG
+ scdebug_call(p, code, callp->sy_narg, i, args);
+#endif
+#ifdef KTRACE
+ if (KTRPOINT(p, KTR_SYSCALL))
+ ktrsyscall(p->p_tracep, code, i, &args);
+#endif
+ goto done;
+ }
+#ifdef SYSCALL_DEBUG
+ scdebug_call(p, code, callp->sy_narg, i, args);
+#endif
+#ifdef KTRACE
+ if (KTRPOINT(p, KTR_SYSCALL))
+ ktrsyscall(p->p_tracep, code, i, &args);
+#endif
+ rval[0] = 0;
+ rval[1] = 0;
+ error = (*callp->sy_call)(p, args, rval);
+ if (error == ERESTART)
+ frame.sf_pc = opc;
+ else if (error != EJUSTRETURN) {
+ if (error) {
+ frame.sf_reg[REG_R0] = error;
+ frame.sf_psr |= PSL_C;
+ } else {
+ frame.sf_reg[REG_R0] = rval[0];
+ frame.sf_reg[REG_R1] = rval[1];
+ frame.sf_psr &= ~PSL_C;
+ }
+ }
+ /* else if (error == EJUSTRETURN) */
+ /* nothing to do */
+done:
+ /*
+ * Reinitialize proc pointer `p' as it may be different
+ * if this is a child returning from fork syscall.
+ */
+ p = curproc;
+ while (i = CURSIG(p))
+ postsig(i);
+ p->p_priority = p->p_usrpri;
+ if (want_resched) {
+ /*
+ * Since we are curproc, clock will normally just change
+ * our priority without moving us from one queue to another
+ * (since the running process is not on a queue.)
+ * If that happened after we setrunqeue ourselves but before
+ * we switch()'ed, we might not be on the queue indicated by
+ * our priority.
+ */
+ (void) splstatclock();
+ setrunqueue(p);
+ p->p_stats->p_ru.ru_nivcsw++;
+ mi_switch();
+ (void) splnone();
+ while (i = CURSIG(p))
+ postsig(i);
+ }
+ if (p->p_stats->p_prof.pr_scale) {
+ int ticks;
+#ifdef YO_WHAT
+ struct timeval *tv = &p->p_stime;
+
+ ticks = ((tv->tv_sec - syst.tv_sec) * 1000 +
+ (tv->tv_usec - syst.tv_usec) / 1000) / (tick / 1000);
+ if (ticks) {
+#ifdef PROFTIMER
+ extern int profscale;
+ addupc(frame.sf_pc, &p->p_stats->p_prof,
+ ticks * profscale);
+#else
+/* addupc(frame.sf_pc, &p->p_stats->p_prof, ticks); */
+#endif
+ }
+#endif
+ }
+ curpriority = p->p_priority;
+#ifdef SYSCALL_DEBUG
+ scdebug_ret(p, code, error, rval[0]);
+#endif
+#ifdef KTRACE
+ if (KTRPOINT(p, KTR_SYSRET))
+ ktrsysret(p->p_tracep, code, error, rval[0]);
+#endif
+
+}
+
+/* For the child, do the stuff after mi_swtch() in syscall so
+ low_level_fork does not have to rethread the kernel stack. */
+void
+ll_fork_sig()
+{
+ register struct proc *p = curproc;
+ int i;
+
+ (void) splnone();
+ while (i = CURSIG(p))
+ postsig(i);
+}
+
+
+/* #define dbg_user */
+/* Other stuff.... */
+int
+check_user_write ( u_long addr, u_long size)
+{
+ int rv;
+ vm_offset_t va;
+
+#ifdef dbg_user
+printf ("ck_ur_wr: addr=0x%x, size=0x%x", addr, size);
+#endif
+ /* check for all possible places! */
+ va = trunc_page((vm_offset_t) addr);
+ if (va > VM_MAXUSER_ADDRESS) return (1);
+
+ while ((u_long)va < (addr + size)) {
+ /* check for copy on write access. */
+#ifdef dbg_user
+printf (" (0x%x:%d)", va, vtopte(va)->pg_prot);
+#endif
+ if (!(vtopte(va)->pg_v) || vtopte(va)->pg_prot != 3 ) {
+#ifdef dbg_user
+printf (" fault");
+#endif
+ rv = vm_fault(&curproc->p_vmspace->vm_map, va,
+ VM_PROT_READ | VM_PROT_WRITE, FALSE);
+ if (rv != KERN_SUCCESS)
+#ifdef dbg_user
+{ printf (" bad\n");
+#endif
+ return(1);
+#ifdef dbg_user
+}
+#endif
+ }
+ va += NBPG;
+ }
+#ifdef dbg_user
+printf ("\n");
+#endif
+
+ return (0);
+}
diff --git a/sys/arch/pc532/pc532/umprintf.c b/sys/arch/pc532/pc532/umprintf.c
new file mode 100644
index 00000000000..21d4d2cb108
--- /dev/null
+++ b/sys/arch/pc532/pc532/umprintf.c
@@ -0,0 +1,105 @@
+/* $NetBSD: umprintf.c,v 1.3 1994/10/26 08:25:20 cgd Exp $ */
+
+/*-
+ * Copyright (c) 1986, 1988, 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.
+ *
+ * hacked out from ..
+ * @(#)subr_prf.c 7.30 (Berkeley) 6/29/91
+ */
+
+#include <stdarg.h>
+static char *ksprintn __P((u_long num, int base, int *len));
+
+void
+umprintf(char *fmt,...)
+{
+ va_list ap;
+ char *p;
+ int tmp;
+ int base;
+ unsigned long ul;
+ char ch;
+
+ va_start (ap,fmt);
+
+ for (;;) {
+ while ((ch = *fmt++) != '%') {
+ if (ch == '\0')
+ return;
+ scncnputc(0, ch);
+ }
+ ch = *fmt++;
+ switch (ch) {
+ case 'd':
+ ul = va_arg(ap, u_long);
+ base = 10;
+ goto number;
+ case 'x':
+ ul = va_arg(ap, u_long);
+ base = 16;
+number: p = ksprintn(ul, base, &tmp);
+ while (ch = *p--)
+ scncnputc(0,ch);
+ break;
+ default:
+ scncnputc(0,ch);
+ }
+ }
+}
+
+/*
+ * Put a number (base <= 16) in a buffer in reverse order; return an
+ * optional length and a pointer to the NULL terminated (preceded?)
+ * buffer.
+ */
+static char *
+ksprintn(ul, base, lenp)
+ register u_long ul;
+ register int base, *lenp;
+{ /* A long in base 8, plus NULL. */
+ static char buf[sizeof(long) * NBBY / 3 + 2];
+ register char *p;
+ int d;
+
+ p = buf;
+ *p='\0';
+ do {
+ d = ul % base;
+ if (d < 10)
+ *++p = '0' + d;
+ else
+ *++p = 'a' + d - 10;
+ } while (ul /= base);
+ if (lenp)
+ *lenp = p - buf;
+ return (p);
+}
diff --git a/sys/arch/pc532/pc532/vm_machdep.c b/sys/arch/pc532/pc532/vm_machdep.c
new file mode 100644
index 00000000000..b4a9fc90248
--- /dev/null
+++ b/sys/arch/pc532/pc532/vm_machdep.c
@@ -0,0 +1,346 @@
+/* $NetBSD: vm_machdep.c,v 1.11 1995/08/29 22:37:54 phil Exp $ */
+
+/*-
+ * Copyright (c) 1982, 1986 The Regents of the University of California.
+ * Copyright (c) 1989, 1990 William Jolitz
+ * 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 William Jolitz.
+ *
+ * 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.
+ *
+ * @(#)vm_machdep.c 7.3 (Berkeley) 5/13/91
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/proc.h>
+#include <sys/malloc.h>
+#include <sys/vnode.h>
+#include <sys/buf.h>
+#include <sys/user.h>
+#include <sys/core.h>
+#include <sys/exec.h>
+
+#include <vm/vm.h>
+#include <vm/vm_kern.h>
+
+#include <machine/cpu.h>
+
+/*
+ * 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;
+{
+ struct user *up = p2->p_addr;
+ int foo, offset, addr, i;
+
+ /*
+ * Copy pcb from proc p1 to p2.
+ * _low_level_init will copy the kernel stack as cheeply as
+ * possible.
+ */
+ p2->p_addr->u_pcb = p1->p_addr->u_pcb;
+ p2->p_addr->u_pcb.pcb_onstack =
+ (struct on_stack *) p2->p_addr + USPACE
+ - sizeof (struct on_stack);
+
+ /*
+ * Wire top of address space of child to it's kstack.
+ * First, fault in a page of pte's to map it.
+ */
+ addr = trunc_page((u_int)vtopte(USRSTACK));
+ vm_map_pageable(&p2->p_vmspace->vm_map, addr, addr+USPACE, FALSE);
+ for (i=0; i < UPAGES; i++)
+ pmap_enter(&p2->p_vmspace->vm_pmap, USRSTACK+i*NBPG,
+ pmap_extract(pmap_kernel(), ((int)p2->p_addr)+i*NBPG),
+ VM_PROT_READ, TRUE);
+
+ pmap_activate(&p2->p_vmspace->vm_pmap, &up->u_pcb);
+
+ /*
+ * Low_level_fork returns twice! First with a 0 in the
+ * parent space and Second with a 1 in the child.
+ */
+
+ return (low_level_fork(up));
+}
+
+
+#ifdef notyet
+
+/*
+ * cpu_exit is called as the last action during exit.
+ *
+ * We change to an inactive address space and a "safe" stack,
+ * passing thru an argument to the new stack. Now, safely isolated
+ * from the resources we're shedding, we release the address space
+ * and any remaining machine-dependent resources, including the
+ * memory for the user structure and kernel stack.
+ *
+ * Next, we assign a dummy context to be written over by swtch,
+ * calling it to send this process off to oblivion.
+ * [The nullpcb allows us to minimize cost in swtch() by not having
+ * a special case].
+ */
+struct proc *swtch_to_inactive();
+
+void
+cpu_exit(p)
+ register struct proc *p;
+{
+ static struct pcb nullpcb; /* pcb to overwrite on last swtch */
+
+ /* free cporcessor (if we have it) */
+ if( p == npxproc) npxproc =0;
+
+ /* move to inactive space and stack, passing arg accross */
+ p = swtch_to_inactive(p);
+
+ /* drop per-process resources */
+ vmspace_free(p->p_vmspace);
+ kmem_free(kernel_map, (vm_offset_t)p->p_addr, ctob(UPAGES));
+
+ p->p_addr = (struct user *) &nullpcb;
+ splstatclock();
+ cpu_switch();
+ /* NOTREACHED */
+}
+#else
+void
+cpu_exit(p)
+ register struct proc *p;
+{
+
+ splstatclock();
+ cpu_switch();
+ /* Not reached. */
+ panic ("cpu_exit! swtch returned!");
+}
+
+void
+cpu_wait(p)
+ struct proc *p;
+{
+
+ /* drop per-process resources */
+ vmspace_free(p->p_vmspace);
+ kmem_free(kernel_map, (vm_offset_t)p->p_addr, ctob(UPAGES));
+}
+#endif
+
+
+/*
+ * Dump the machine specific segment at the start of a core dump.
+ */
+int
+cpu_coredump(p, vp, cred, chdr)
+ struct proc *p;
+ struct vnode *vp;
+ struct ucred *cred;
+ struct core *chdr;
+{
+ int error;
+ struct {
+ struct reg regs;
+ struct fpreg fpregs;
+ } cpustate;
+ struct coreseg cseg;
+
+ CORE_SETMAGIC(*chdr, COREMAGIC, MID_NS32532, 0);
+ chdr->c_hdrsize = ALIGN(sizeof(*chdr));
+ chdr->c_seghdrsize = ALIGN(sizeof(cseg));
+ chdr->c_cpusize = sizeof(cpustate);
+ cpustate.regs = *((struct reg *)p->p_md.md_regs);
+ cpustate.fpregs = *((struct fpreg *)&p->p_addr->u_pcb.pcb_fsr);
+
+ CORE_SETMAGIC(cseg, CORESEGMAGIC, MID_NS32532, CORE_CPU);
+ cseg.c_addr = 0;
+ cseg.c_size = chdr->c_cpusize;
+
+ error = vn_rdwr(UIO_WRITE, vp, (caddr_t)&cseg, chdr->c_seghdrsize,
+ (off_t)chdr->c_hdrsize, UIO_SYSSPACE,
+ IO_NODELOCKED|IO_UNIT, cred, (int *)NULL, p);
+ if (error)
+ return error;
+
+ error = vn_rdwr(UIO_WRITE, vp, (caddr_t)&cpustate, sizeof(cpustate),
+ (off_t)(chdr->c_hdrsize + chdr->c_seghdrsize), UIO_SYSSPACE,
+ IO_NODELOCKED|IO_UNIT, cred, (int *)NULL, p);
+
+ if (!error)
+ chdr->c_nseg++;
+
+ return error;
+}
+
+
+/*
+ * Set a red zone in the kernel stack after the u. area.
+ */
+setredzone(pte, vaddr)
+ u_short *pte;
+ caddr_t vaddr;
+{
+/* eventually do this by setting up an expand-down stack segment
+ for ss0: selector, allowing stack access down to top of u.
+ this means though that protection violations need to be handled
+ thru a double fault exception that must do an integral task
+ switch to a known good context, within which a dump can be
+ taken. a sensible scheme might be to save the initial context
+ used by sched (that has physical memory mapped 1:1 at bottom)
+ and take the dump while still in mapped mode */
+}
+
+/*
+ * Move pages from one kernel virtual address to another.
+ * Both addresses are assumed to reside in the Sysmap,
+ * and size must be a multiple of CLSIZE.
+ */
+pagemove(from, to, size)
+ register caddr_t from, to;
+ int size;
+{
+ register struct pte *fpte, *tpte;
+
+ if (size % CLBYTES)
+ panic("pagemove");
+ fpte = kvtopte(from);
+ tpte = kvtopte(to);
+ while (size > 0) {
+ *tpte++ = *fpte;
+ *(int *)fpte++ = 0;
+ from += NBPG;
+ to += NBPG;
+ size -= NBPG;
+ }
+ tlbflush();
+}
+
+/*
+ * Convert kernel VA to physical address
+ */
+kvtop(addr)
+ register caddr_t addr;
+{
+ vm_offset_t va;
+ va = pmap_extract(pmap_kernel(), (vm_offset_t)addr);
+ if (va == 0)
+ panic("kvtop: zero page frame");
+ return((int)va);
+}
+
+extern vm_map_t phys_map;
+
+/*
+ * Map an IO request into kernel virtual address space. 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 useriomap
+ * (a name with only slightly more meaning than "kernelmap")
+ */
+vmapbuf(bp)
+ register struct buf *bp;
+{
+ register int npf;
+ register caddr_t addr;
+ register long flags = bp->b_flags;
+ struct proc *p;
+ int off;
+ vm_offset_t kva;
+ register vm_offset_t pa;
+
+ if ((flags & B_PHYS) == 0)
+ panic("vmapbuf");
+ addr = bp->b_saveaddr = bp->b_un.b_addr;
+ off = (int)addr & PGOFSET;
+ p = bp->b_proc;
+ npf = btoc(round_page(bp->b_bcount + off));
+ kva = kmem_alloc_wait(phys_map, ctob(npf));
+ bp->b_un.b_addr = (caddr_t) (kva + off);
+ while (npf--) {
+ pa = pmap_extract(&p->p_vmspace->vm_pmap, (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.
+ */
+vunmapbuf(bp)
+ register struct buf *bp;
+{
+ register int npf;
+ register caddr_t addr = bp->b_un.b_addr;
+ vm_offset_t kva;
+
+ if ((bp->b_flags & B_PHYS) == 0)
+ panic("vunmapbuf");
+ npf = btoc(round_page(bp->b_bcount + ((int)addr & PGOFSET)));
+ kva = (vm_offset_t)((int)addr & ~PGOFSET);
+ kmem_free_wakeup(phys_map, kva, ctob(npf));
+ bp->b_un.b_addr = bp->b_saveaddr;
+ bp->b_saveaddr = NULL;
+}
+
+/*
+ * (Force reset the processor by invalidating the entire address space!)
+ * Well, lets just hang!
+ */
+cpu_reset()
+{
+ splhigh();
+ while (1);
+}
diff --git a/sys/arch/pc532/stand/Makefile b/sys/arch/pc532/stand/Makefile
new file mode 100644
index 00000000000..0dd6ee9ecf3
--- /dev/null
+++ b/sys/arch/pc532/stand/Makefile
@@ -0,0 +1,98 @@
+# $NetBSD: Makefile,v 1.7.2.1 1995/10/17 00:19:13 phil Exp $
+
+# @(#)Makefile 8.1 (Berkeley) 6/10/93
+
+#DESTDIR=
+STANDDIR=${DESTDIR}/stand
+# load at 0x400000 - 18 * 1024 - 0x10000
+# that way the boot code will be at the correct
+# address if the floppy image is started from memory
+# NOTE: alloc() function takes memory after _end
+RELOC= 3EB800
+
+CONS= -DSCNCONSOLE
+DEFS= -DSTANDALONE ${CONS}
+CFLAGS= -O ${INCPATH} ${DEFS} -fwritable-strings
+
+SRCS= cons.c devopen.c scn.c scsi_low.c scsi_hi.c \
+ conf.c prf.c tgets.c machdep.c sd.c rd.c filesystem.c
+
+S= ${.CURDIR}/../../..
+SAREL=
+KERNREL=
+
+.PATH: ${S}/arch/${MACHINE_ARCH}/${MACHINE_ARCH}
+.PATH: ${S}/stand ${S}/lib/libsa
+
+INCPATH=-I${.CURDIR} -I${.CURDIR}/../.. -I${S} -I${S}/lib/libsa
+
+### find out what to use for libs
+.include "../../../lib/libkern/Makefile.inc"
+LIBKERN= ${KERNLIB}
+
+NO_NET=
+.include "../../../lib/libsa/Makefile.inc"
+LIBSA= ${SALIB}
+
+#LIBS= ${LIBSA} ${.OBJDIR}/libdrive.a \
+# ${LIBKERN} ${LIBSA} ${LIBKERN}
+LIBS= ${LIBSA} ${.OBJDIR}/libdrive.a \
+ ${LIBKERN} ${LIBSA}
+
+BOOTS= boot zboot.o
+ALL= ${BOOTS}
+
+all: ${ALL}
+
+${BOOTS}: ${LIBS}
+
+OBJS= ${SRCS:N*.h:R:S/$/.o/g}
+${.OBJDIR}/libdrive.a: ${OBJS}
+ ar crv $@ $?
+ ranlib $@
+
+# depend on DEFS
+
+devopen.o machdep.o srt0.o: Makefile
+cons.o: Makefile
+
+# startups
+
+srt0.o: ${.CURDIR}/srt0.s
+ cpp ${INCPATH} ${DEFS} ${.CURDIR}/srt0.s | as -o srt0.o
+
+# new boot
+boot: boot.o srt0.o ${LIBS}
+ ld -z -T ${RELOC} -e begin srt0.o boot.o ${LIBS} -o $@
+ @size boot
+
+zboot.o: inflate.o
+ ld -r srt0.o inflate.o $(LIBS) -o zboot.o
+
+# new boot user mode test
+TESTBOOT= boot.o test.o $(SC) ${LIBS}
+# objects from regular libc;
+SC= cerror.o syscall.o malloc.o sbrk.o getpagesize.o
+testboot: $(TESTBOOT)
+ ld -o testboot /usr/lib/crt0.o $(TESTBOOT) ${LIBS} -o $@
+
+$(SC): /usr/lib/libc.a
+ ar x /usr/lib/libc.a $(SC)
+
+# utilities
+
+install: ${ALL}
+ cp ${ALL} ${DESTDIR}/usr/mdec
+
+.include <bsd.dep.mk>
+.include <bsd.obj.mk>
+.include <bsd.subdir.mk>
+
+FRC:
+
+# clean ...
+
+clean::
+ rm -f ${ALL} ${.OBJDIR}/libdrive.a ${OBJS} boot.o srt0.o inflate.o
+
+cleandir: clean
diff --git a/sys/arch/pc532/stand/README b/sys/arch/pc532/stand/README
new file mode 100644
index 00000000000..a835dde57e6
--- /dev/null
+++ b/sys/arch/pc532/stand/README
@@ -0,0 +1,26 @@
+$NetBSD: README,v 1.2 1994/10/26 08:25:43 cgd Exp $
+
+pc532 stand/boot
+Phil Budne <phil@ultimate.com> 5/19/1994
+
+Based on hp300 stand/pboot.c, uses libso
+ (lacks the fun "spinner" that the i386 boot program displays)
+
+May be debugged under usermode (using "testboot" image)
+
+Passes howto, bootdev, & symbols to booted program;
+ r3/ magic value 0xc1e86394 (3253232532)
+ r4/ end of symbols
+ r5/ physical load address (typ 0x2000)
+ r6/ bootdev
+ r7/ howto (flags: RB_{ASKNAME,KDB,SINGLE,HALT})
+
+All files have Berzerkley style copyrights, except libso files from
+Jordan Hubbard's "libso" (which in turn come from Bruce Culbertson's
+ROM monitor); scsi_hi.c scsi_lo.c so.h
+
+TODO:
+
+check if kernel will overlap boot program!
+pick up initial how and boot dev
+
diff --git a/sys/arch/pc532/stand/boot.c b/sys/arch/pc532/stand/boot.c
new file mode 100644
index 00000000000..6301d6f1cd6
--- /dev/null
+++ b/sys/arch/pc532/stand/boot.c
@@ -0,0 +1,279 @@
+/* $NetBSD: boot.c,v 1.4.2.1 1995/10/17 00:19:15 phil Exp $ */
+
+/*-
+ * Copyright (c) 1982, 1986, 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)boot.c 8.1 (Berkeley) 6/10/93
+ */
+
+#ifndef lint
+static char rcsid[] = "$NetBSD: boot.c,v 1.4.2.1 1995/10/17 00:19:15 phil Exp $";
+#endif /* not lint */
+
+#include <sys/param.h>
+#include <sys/reboot.h>
+#include <a.out.h>
+#include "stand.h"
+#include "samachdep.h"
+
+/*
+ * Boot program... bits in `howto' determine whether boot stops to
+ * ask for system name. Boot device is derived from ROM provided
+ * information.
+ */
+
+extern unsigned opendev;
+extern int noconsole;
+extern int testing;
+
+char *ssym, *esym;
+
+char *name;
+char *names[] = {
+ "/netbsd", "/onetbsd", "/netbsd.old",
+};
+#define NUMNAMES (sizeof(names)/sizeof(char *))
+#define LOADADDR ((char *)0x2000)
+
+static int bdev, bctlr, bunit, bpart;
+
+main()
+{
+ int currname = 0;
+ int io;
+
+ cninit();
+ scsiinit();
+
+ printf("\n>> NetBSD BOOT pc532 [$Revision: 1.1 $]\n");
+
+ bdev = B_TYPE(bootdev);
+ bctlr = B_CONTROLLER(bootdev);
+ bunit = B_UNIT(bootdev);
+ bpart = B_PARTITION(bootdev);
+
+ for (;;) {
+ name = names[currname++];
+ if (currname == NUMNAMES)
+ currname = 0;
+
+ if (!noconsole) {
+ howto = 0;
+ getbootdev(&howto);
+ }
+ else
+ printf(": %s\n", name);
+
+ io = open(name, 0);
+
+ if (io >= 0) {
+ copyunix(howto, opendev, io);
+ close(io);
+ }
+ else
+ printf("boot: %s\n", strerror(errno));
+ }
+}
+
+/*ARGSUSED*/
+copyunix(howto, devtype, io)
+ register int howto; /* boot flags */
+ register u_int devtype; /* boot device */
+ register int io;
+{
+ struct exec x;
+ int i;
+ register char *load; /* load addr for unix */
+ register char *addr;
+ char *file;
+ int dev, ctlr, unit, part;
+
+ /* XXX use devtype? */
+ dev = B_TYPE(opendev);
+ ctlr = B_CONTROLLER(opendev);
+ unit = B_UNIT(opendev);
+ part = B_PARTITION(opendev);
+ /* get the file name part of name */
+ devparse(name, &i, &i, &i, &i, &i, &file);
+
+ i = read(io, (char *)&x, sizeof(x));
+ if (i != sizeof(x) || N_BADMAG(x)) {
+ printf("Bad format\n");
+ return;
+ }
+ addr = LOADADDR; /* Always load at LOADADDR */
+ load = (char *)(x.a_entry & 0x00ffff00); /* XXX make less magical? */
+ printf("Booting %s%d%c:%s @ 0x%x\n",
+ devsw[dev].dv_name, unit + (8*ctlr), 'a' + part, file, load);
+
+ if (testing) {
+ load = addr = alloc(2*1024*1024); /* XXX stat the file? */
+ if (!addr) {
+ printf("alloc failed\n");
+ exit(1);
+ }
+ }
+
+ /* Text */
+ printf("%d", x.a_text);
+ if (N_GETMAGIC(x) == ZMAGIC && lseek(io, 0, SEEK_SET) == -1)
+ goto shread;
+ if (read(io, addr, x.a_text) != x.a_text)
+ goto shread;
+ addr += x.a_text;
+ if (N_GETMAGIC(x) == NMAGIC)
+ while ((int)addr & CLOFSET)
+ *addr++ = 0;
+ /* Data */
+ printf("+%d", x.a_data);
+ if (read(io, addr, x.a_data) != x.a_data)
+ goto shread;
+ addr += x.a_data;
+
+ /* Bss */
+ printf("+%d", x.a_bss);
+ bzero( addr, x.a_bss );
+ addr += x.a_bss;
+
+ /* Symbols */
+ ssym = load + (addr - LOADADDR);
+ bcopy(&x.a_syms, addr, sizeof(x.a_syms));
+ addr += sizeof(x.a_syms);
+ printf(" [%d+", x.a_syms);
+ if (x.a_syms && read(io, addr, x.a_syms) != x.a_syms)
+ goto shread;
+ addr += x.a_syms;
+
+ /* read size of string table */
+ i = 0;
+ if (x.a_syms && read(io, &i, sizeof(int)) != sizeof(int))
+ goto shread;
+
+ /* read strings */
+ printf("%d]", i);
+ bcopy(&i, addr, sizeof(int));
+ if (i) {
+ i -= sizeof(int);
+ addr += sizeof(int);
+ if (read(io, addr, i) != i)
+ goto shread;
+ addr += i;
+ }
+
+ if (load != LOADADDR) {
+ bcopy(LOADADDR, load, addr - LOADADDR);
+ addr = load + (addr - LOADADDR);
+ }
+#define round_to_size(x,t) \
+ (((int)(x) + sizeof(t) - 1) & ~(sizeof(t) - 1))
+ esym = (char *)round_to_size(addr - load,int);
+#undef round_to_size
+
+ /* and note the end address of all this */
+ printf(" total=0x%x", addr);
+
+ x.a_entry &= 0xffffff;
+ printf(" start 0x%x\n", x.a_entry);
+
+#ifdef DEBUG
+ printf("ssym=0x%x esym=0x%x\n", ssym, esym);
+ printf("\n\nReturn to boot...\n");
+ getchar();
+#endif
+
+ if (!testing) {
+#ifdef __GNUC__
+ /* do NOT change order!!
+ * the following are passed as args, and are in registers
+ * clobbered by the last two movd's!!!
+ */
+ asm(" movd %0,r5" : : "g" (load));
+ asm(" movd %0,r6" : : "g" (devtype));
+ asm(" movd %0,r7" : : "g" (howto));
+
+ /* magic value for locore.s to look for (3253232532) */
+ asm(" movd %0,r3" : : "i" (0xc1e86394));
+ asm(" movd %0,r4" : : "g" (esym));
+#endif /* __GNUC__ */
+ (*((int (*)()) x.a_entry))();
+ }
+ return;
+shread:
+ printf("Short read\n");
+ return;
+}
+
+char line[100];
+
+getbootdev(howto)
+ int *howto;
+{
+ char c, *ptr = line;
+
+ printf("Boot: [[[%s%d%c:]%s][-abdrs]] :- ",
+ devsw[bdev].dv_name, bunit + (8 * bctlr), 'a'+bpart, name);
+
+ if (tgets(line)) {
+ while (c = *ptr) {
+ while (c == ' ')
+ c = *++ptr;
+ if (!c)
+ return;
+ if (c == '-')
+ while ((c = *++ptr) && c != ' ')
+ switch (c) {
+ case 'a':
+ *howto |= RB_ASKNAME;
+ continue;
+ case 'b':
+ *howto |= RB_HALT;
+ continue;
+ case 'd':
+ *howto |= RB_KDB;
+ continue;
+ case 'r':
+ *howto |= RB_DFLTROOT;
+ continue;
+ case 's':
+ *howto |= RB_SINGLE;
+ continue;
+ }
+ else {
+ name = ptr;
+ while ((c = *++ptr) && c != ' ');
+ if (c)
+ *ptr++ = 0;
+ }
+ }
+ } else
+ printf("\n");
+}
diff --git a/sys/arch/pc532/stand/conf.c b/sys/arch/pc532/stand/conf.c
new file mode 100644
index 00000000000..6f4a50da0a8
--- /dev/null
+++ b/sys/arch/pc532/stand/conf.c
@@ -0,0 +1,59 @@
+/* $NetBSD: conf.c,v 1.3 1995/08/29 21:55:42 phil Exp $ */
+
+/*
+ * Copyright (c) 1982, 1986, 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)conf.c 8.1 (Berkeley) 6/10/93
+ */
+
+#include <sys/param.h>
+#include "stand.h"
+
+int rdstrategy __P((void *devdata, int rw,
+ daddr_t blk, u_int size, char *buf, u_int *rsize));
+int rdopen __P((struct open_file *f, ...));
+
+int sdstrategy __P((void *devdata, int rw,
+ daddr_t blk, u_int size, char *buf, u_int *rsize));
+int sdopen __P((struct open_file *f, ...));
+
+#define sdioctl noioctl
+#define rdioctl noioctl
+
+struct devsw devsw[] = {
+ { "sd", sdstrategy, sdopen, nullsys, sdioctl }, /*0*/
+ { NULL, NULL, NULL, NULL, NULL },
+ { NULL, NULL, NULL, NULL, NULL },
+ { "rd", rdstrategy, rdopen, nullsys, rdioctl }, /*3*/
+};
+
+int ndevs = (sizeof(devsw)/sizeof(devsw[0]));
diff --git a/sys/arch/pc532/stand/cons.c b/sys/arch/pc532/stand/cons.c
new file mode 100644
index 00000000000..307a58539c5
--- /dev/null
+++ b/sys/arch/pc532/stand/cons.c
@@ -0,0 +1,93 @@
+/* $NetBSD: cons.c,v 1.3 1995/08/29 21:55:43 phil Exp $ */
+
+/*
+ * Copyright (c) 1988 University of Utah.
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * the Systems Programming Group of the University of Utah Computer
+ * Science Department.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * from: Utah Hdr: cons.c 1.7 92/02/28
+ *
+ * @(#)cons.c 8.1 (Berkeley) 6/10/93
+ */
+
+#include <sys/param.h>
+#include <dev/cons.h>
+#include "samachdep.h"
+
+#ifdef SCNCONSOLE
+int scnprobe(), scninit(), scngetchar(), scnputchar();
+#endif
+
+struct consdev constab[] = {
+#ifdef SCNCONSOLE
+ { scnprobe, scninit, scngetchar, scnputchar },
+#endif
+ { 0 },
+};
+
+struct consdev *cn_tab;
+int noconsole;
+
+cninit()
+{
+ register struct consdev *cp;
+
+ cn_tab = NULL;
+ noconsole = 1;
+ for (cp = constab; cp->cn_probe; cp++) {
+ (*cp->cn_probe)(cp);
+ if (cp->cn_pri > CN_DEAD &&
+ (cn_tab == NULL || cp->cn_pri > cn_tab->cn_pri))
+ cn_tab = cp;
+ }
+ if (cn_tab) {
+ (*cn_tab->cn_init)(cn_tab);
+ noconsole = 0;
+ }
+}
+
+cngetc()
+{
+ if (cn_tab)
+ return((*cn_tab->cn_getc)(cn_tab->cn_dev));
+ return(0);
+}
+
+cnputc(c)
+ int c;
+{
+ if (cn_tab)
+ (*cn_tab->cn_putc)(cn_tab->cn_dev, c);
+}
diff --git a/sys/arch/pc532/stand/devopen.c b/sys/arch/pc532/stand/devopen.c
new file mode 100644
index 00000000000..4ddac7c398a
--- /dev/null
+++ b/sys/arch/pc532/stand/devopen.c
@@ -0,0 +1,203 @@
+/* $NetBSD: devopen.c,v 1.4 1995/08/29 21:55:44 phil Exp $ */
+
+/*-
+ * Copyright (c) 1993 John Brezak
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR `AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/param.h>
+#include <sys/reboot.h>
+
+#include "stand.h"
+#include "samachdep.h"
+
+u_int opendev;
+
+#define ispart(c) ((c) >= 'a' && (c) <= 'h')
+
+atoi(char *cp)
+{
+ int val = 0;
+ while(isdigit(*cp))
+ val = val * 10 + (*cp++ - '0');
+ return(val);
+}
+
+usage()
+{
+ printf("\
+Usage: device(adaptor, controller, drive, partition)file\n\
+ <device><unit><partitonletter>:file\n\
+");
+}
+
+devlookup(char *d, int len)
+{
+ struct devsw *dp = devsw;
+ int i;
+
+ for (i = 0; i < ndevs; i++, dp++)
+ if (dp->dv_name && strncmp(dp->dv_name, d, len) == 0)
+ return(i);
+
+ printf("No such device - Configured devices are:\n");
+ for (dp = devsw, i = 0; i < ndevs; i++, dp++)
+ if (dp->dv_name)
+ printf(" %s", dp->dv_name);
+ printf("\n");
+ errno = ENODEV;
+ return(-1);
+}
+
+/*
+ * Parse a device spec in one of two forms.
+ *
+ * dev(adapt, ctlr, unit, part)file
+ * [A-Za-z]*[0-9]*[A-Za-z]:file
+ * dev unit part
+ */
+devparse(char *fname, int *dev, int *adapt, int *ctlr, int *unit, int *part, char **file)
+{
+ int *argp, i;
+ char *s, *args[4];
+
+ /* get device name and make lower case */
+ for (s = fname; *s && *s != '/' && *s != ':' && *s != '('; s++)
+ if (isupper(*s)) *s = tolower(*s);
+
+ /* first form */
+ if (*s == '(') {
+ /* lookup device and get index */
+ if ((*dev = devlookup(fname, s - fname)) < 0)
+ goto baddev;
+
+ /* tokenize device ident */
+ args[0] = ++s;
+ for (i = 1; *s && *s != ')'; s++) {
+ if (i > 3)
+ goto baddev;
+ if (*s == ',')
+ args[i++] = ++s;
+ }
+ switch(i) {
+ case 4:
+ *adapt = atoi(args[0]);
+ *ctlr = atoi(args[1]);
+ *unit = atoi(args[2]);
+ *part = atoi(args[3]);
+ break;
+ case 3:
+ *ctlr = atoi(args[0]);
+ *unit = atoi(args[1]);
+ *part = atoi(args[2]);
+ break;
+ case 2:
+ *unit = atoi(args[0]);
+ *part = atoi(args[1]);
+ break;
+ case 1:
+ *part = atoi(args[0]);
+ break;
+ case 0:
+ break;
+ }
+ *file = ++s;
+ }
+
+ /* second form */
+ else if (*s == ':') {
+ /* isolate device */
+ for (s = fname; *s != ':' && !isdigit(*s); s++);
+
+ /* lookup device and get index */
+ if ((*dev = devlookup(fname, s - fname)) < 0)
+ goto baddev;
+
+ /* isolate unit */
+ if ((*unit = atoi(s)) > ((1 << (sizeof(char) * 8)) - 1))
+ goto bad;
+ for (; isdigit(*s); s++);
+
+ /* translate partition */
+ if (!ispart(*s))
+ goto bad;
+
+ *part = *s++ - 'a';
+ if (*s != ':')
+ goto bad;
+ *file = ++s;
+ }
+
+ /* no device present */
+ else
+ *file = fname;
+
+ /* return the remaining unparsed part as the file to boot */
+ return(0);
+
+ bad:
+ usage();
+
+ baddev:
+ return(-1);
+}
+
+
+devopen(f, fname, file)
+ struct open_file *f;
+ const char *fname;
+ char **file;
+{
+ int n, error;
+ int dev, ctlr, unit, part;
+ int adapt = 0; /* XXX not used on HP */
+ struct devsw *dp = &devsw[0];
+
+ dev = B_TYPE(bootdev);
+ ctlr = B_CONTROLLER(bootdev);
+ unit = B_UNIT(bootdev);
+ part = B_PARTITION(bootdev);
+
+ if (error = devparse(fname, &dev, &adapt, &ctlr, &unit, &part, file))
+ return(error);
+
+ dp = &devsw[dev];
+
+ if (!dp->dv_open)
+ return(ENODEV);
+
+ opendev = MAKEBOOTDEV(dev, adapt, ctlr, unit, part);
+
+ f->f_dev = dp;
+
+ if ((error = (*dp->dv_open)(f, ctlr, unit, part)) == 0)
+ return(0);
+
+ printf("%s(%d,%d,%d,%d): %s\n", devsw[dev].dv_name,
+ adapt, ctlr, unit, part, strerror(error));
+
+ return(error);
+}
diff --git a/sys/arch/pc532/stand/filesystem.c b/sys/arch/pc532/stand/filesystem.c
new file mode 100644
index 00000000000..3d0ff77b8d1
--- /dev/null
+++ b/sys/arch/pc532/stand/filesystem.c
@@ -0,0 +1,40 @@
+/* $NetBSD: filesystem.c,v 1.2 1994/10/26 08:25:48 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.
+ */
+
+#include <stand.h>
+#include <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/pc532/stand/inflate.c b/sys/arch/pc532/stand/inflate.c
new file mode 100644
index 00000000000..3ebe08c086a
--- /dev/null
+++ b/sys/arch/pc532/stand/inflate.c
@@ -0,0 +1,1433 @@
+/*
+ * Copyright (c) 1995 Matthias Pfaller.
+ *
+ * Most of this code is from the unzip512 distribution and was put
+ * in the public domain by Mark Adler 1994.
+ *
+ * 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 Matthias Pfaller.
+ * 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.
+ *
+ * $Id: inflate.c,v 1.1 1995/10/18 08:51:23 deraadt Exp $
+ */
+
+#include <sys/param.h>
+#include <sys/reboot.h>
+#include <a.out.h>
+#include "stand.h"
+#include "samachdep.h"
+
+#ifndef EOF
+#define EOF -1
+#endif
+typedef unsigned char uch; /* code assumes unsigned bytes; these type- */
+typedef unsigned short ush; /* defs replace byte/UWORD/ULONG (which are */
+typedef unsigned long ulg; /* predefined on some systems) & match zip */
+
+extern int qflag;
+extern uch slide[];
+extern ulg crc_32_tab[];
+
+#define NEXTBYTE nextbyte()
+#define FLUSH(n) flush(n)
+#define WSIZE 0x8000
+#define memzero(dest, len) bzero(dest, len)
+
+/* Function prototypes */
+#ifndef OF
+# ifdef __STDC__
+# define OF(a) a
+# else /* !__STDC__ */
+# define OF(a) ()
+# endif /* ?__STDC__ */
+#endif
+
+/* From: funzip.c -- put in the public domain by Mark Adler */
+
+#define VERSION "3.83 of 28 August 1994"
+
+/*
+
+ All funzip does is take a zip file from stdin and decompress the
+ first entry to stdout. The entry has to be either deflated or
+ stored. If the entry is encrypted, then the decryption password
+ must be supplied on the command line as the first argument.
+
+ funzip needs to be linked with inflate.o and crypt.o compiled from
+ the unzip source. If decryption is desired, the full version of
+ crypt.c (and crypt.h) from zcrypt21.zip or later must be used.
+
+ */
+
+/* compression methods */
+#define STORED 0
+#define DEFLATED 8
+
+/* PKZIP header definitions */
+#define ZIPMAG 0x4b50 /* two-byte zip lead-in */
+#define LOCREM 0x0403 /* remaining two bytes in zip signature */
+#define LOCSIG 0x04034b50L /* full signature */
+#define LOCFLG 4 /* offset of bit flag */
+#define CRPFLG 1 /* bit for encrypted entry */
+#define EXTFLG 8 /* bit for extended local header */
+#define LOCHOW 6 /* offset of compression method */
+#define LOCTIM 8 /* file mod time (for decryption) */
+#define LOCCRC 12 /* offset of crc */
+#define LOCSIZ 16 /* offset of compressed size */
+#define LOCLEN 20 /* offset of uncompressed length */
+#define LOCFIL 24 /* offset of file name field length */
+#define LOCEXT 26 /* offset of extra field length */
+#define LOCHDR 28 /* size of local header, including LOCREM */
+#define EXTHDR 16 /* size of extended local header, inc sig */
+
+/* GZIP header definitions */
+#define GZPMAG 0x8b1f /* two-byte gzip lead-in */
+#define GZPHOW 0 /* offset of method number */
+#define GZPFLG 1 /* offset of gzip flags */
+#define GZPMUL 2 /* bit for multiple-part gzip file */
+#define GZPISX 4 /* bit for extra field present */
+#define GZPISF 8 /* bit for filename present */
+#define GZPISC 16 /* bit for comment present */
+#define GZPISE 32 /* bit for encryption */
+#define GZPTIM 2 /* offset of Unix file modification time */
+#define GZPEXF 6 /* offset of extra flags */
+#define GZPCOS 7 /* offset of operating system compressed on */
+#define GZPHDR 8 /* length of minimal gzip header */
+
+/* Macros for getting two-byte and four-byte header values */
+#define SH(p) ((ush)(uch)((p)[0]) | ((ush)(uch)((p)[1]) << 8))
+#define LG(p) ((ulg)(SH(p)) | ((ulg)(SH((p)+2)) << 16))
+
+/* Function prototypes */
+ulg updcrc OF((uch *, ulg));
+int inflate OF((void));
+void err OF((int, char *));
+
+/* Globals */
+uch *outptr; /* points to next byte in output buffer */
+ulg outcnt; /* bytes in output buffer */
+ulg outsiz; /* total bytes written to out */
+int encrypted; /* flag to turn on decryption */
+int qflag = 1; /* turn off messages in inflate.c */
+uch slide[WSIZE];
+uch *addr, *load, *esym;
+extern uch *r3, *r6, *r7;
+int bsize;
+
+/* Masks for inflate.c */
+ush mask_bits[] = {
+ 0x0000,
+ 0x0001, 0x0003, 0x0007, 0x000f, 0x001f, 0x003f, 0x007f, 0x00ff,
+ 0x01ff, 0x03ff, 0x07ff, 0x0fff, 0x1fff, 0x3fff, 0x7fff, 0xffff
+};
+
+extern uch input_data[];
+uch *datap = input_data;
+struct exec x;
+
+int nextbyte()
+{
+ extern int input_len;
+
+ if (!(input_len & 0x1fff))
+ twiddle();
+ if (input_len-- > 0)
+ return(*datap++);
+ else
+ return(EOF);
+}
+
+int nextblock(p, n)
+char *p;
+int n;
+{
+ extern int input_len;
+
+ twiddle();
+ if (input_len < n)
+ return(0);
+ memcpy(p, datap, n);
+ input_len -= n;
+ datap += n;
+ return(n);
+}
+
+ulg updcrc(s, n)
+uch *s; /* pointer to bytes to pump through */
+ulg n; /* number of bytes in s[] */
+/* Run a set of bytes through the crc shift register. If s is a NULL
+ pointer, then initialize the crc shift register contents instead.
+ Return the current crc in either case. */
+{
+ register ulg c; /* temporary variable */
+
+ static ulg crc = 0xffffffffL; /* shift register contents */
+
+ if (s == (uch *)NULL)
+ c = 0xffffffffL;
+ else
+ {
+ c = crc;
+ while (n--)
+ c = crc_32_tab[((int)c ^ (*s++)) & 0xff] ^ (c >> 8);
+ }
+ crc = c;
+ return c ^ 0xffffffffL; /* (instead of ~c for 64-bit machines) */
+}
+
+void nextstate()
+{
+ static int state = 0;
+
+ switch (state) {
+ case 0:
+ if (N_BADMAG(x))
+ panic("Bad exec format\n");
+ load = addr = (uch *)(x.a_entry & 0x00ffff00);
+ printf("Uncompressing @ 0x%x\n", addr);
+ bsize = x.a_text;
+ if (N_GETMAGIC(x) == ZMAGIC) {
+ bcopy(&x, addr, sizeof(x));
+ addr += sizeof(x);
+ bsize -= sizeof(x);
+ }
+ printf("%d", x.a_text);
+ state = 1;
+ break;
+
+ case 1:
+ if (N_GETMAGIC(x) == NMAGIC)
+ while ((int)addr & CLOFSET)
+ *addr++ = 0;
+ bsize = x.a_data;
+ printf("+%d", x.a_data);
+ state = 2;
+ break;
+
+ case 2:
+ printf("+%d", x.a_bss);
+ bzero(addr, x.a_bss );
+ addr += x.a_bss;
+ bcopy(&x.a_syms, addr, sizeof(x.a_syms));
+ addr += sizeof(x.a_syms);
+ printf(" [%d+", x.a_syms);
+ if (x.a_syms) {
+ bsize = x.a_syms + sizeof(int);
+ state = 3;
+ break;
+ }
+ printf("0]");
+
+ case 4:
+ printf(" total 0x%x", addr);
+ x.a_entry &= 0xffffff;
+ printf(" start 0x%x\n", x.a_entry);
+#define round_to_size(x,t) \
+ (((int)(x) + sizeof(t) - 1) & ~(sizeof(t) - 1))
+ esym = (char *)round_to_size(addr - load, int);
+#undef round_to_size
+ state = -1;
+ break;
+
+ case 3:
+ printf("%d]", ((int *)addr)[-1]);
+ bsize = ((int *)addr)[-1] - sizeof(int);
+ state = 4;
+ break;
+
+ case -1:
+ printf("Already at EOF\n");
+ break;
+ }
+}
+
+int flush(w) /* used by inflate.c (FLUSH macro) */
+ulg w; /* number of bytes to flush */
+{
+ uch *p = slide;
+
+ updcrc(slide, w);
+ outsiz += w;
+
+ while (bsize <= w) {
+ bcopy(p, addr, bsize);
+ p += bsize;
+ addr += bsize;
+ w -= bsize;
+ nextstate();
+ }
+ if (w) {
+ bcopy(p, addr, w);
+ addr += w;
+ bsize -= w;
+ }
+ return(0);
+}
+
+main()
+{
+ ush n;
+ uch h[LOCHDR]; /* first local header (GZPHDR < LOCHDR) */
+ int g = 0; /* true if gzip format */
+ char *s = "";
+
+ cninit();
+
+ addr = (uch *)&x;
+ bsize = sizeof(x);
+
+ /* read local header, check validity, and skip name and extra fields */
+ n = nextbyte(); n |= nextbyte() << 8;
+ if (n == ZIPMAG)
+ {
+ if (nextblock((char *)h, LOCHDR) != LOCHDR || SH(h) != LOCREM)
+ panic("invalid zip file");
+ if (SH(h + LOCHOW) != STORED && SH(h + LOCHOW) != DEFLATED)
+ panic("first entry not deflated or stored--can't funzip");
+ for (n = SH(h + LOCFIL); n--; ) g = nextbyte();
+ for (n = SH(h + LOCEXT); n--; ) g = nextbyte();
+ g = 0;
+ encrypted = h[LOCFLG] & CRPFLG;
+ }
+ else if (n == GZPMAG)
+ {
+ if (nextblock((char *)h, GZPHDR) != GZPHDR)
+ panic("invalid gzip file");
+ if (h[GZPHOW] != DEFLATED)
+ panic("gzip file not deflated");
+ if (h[GZPFLG] & GZPMUL)
+ panic("cannot handle multi-part gzip files");
+ if (h[GZPFLG] & GZPISX)
+ {
+ n = nextbyte(); n |= nextbyte() << 8;
+ while (n--) g = nextbyte();
+ }
+ if (h[GZPFLG] & GZPISF)
+ while ((g = nextbyte()) != 0 && g != EOF) ;
+ if (h[GZPFLG] & GZPISC)
+ while ((g = nextbyte()) != 0 && g != EOF) ;
+ g = 1;
+ encrypted = h[GZPFLG] & GZPISE;
+ }
+ else
+ panic("input not a zip or gzip file");
+
+ /* if entry encrypted, decrypt and validate encryption header */
+ if (encrypted)
+ panic("cannot decrypt entry (need to recompile with full crypt.c)");
+
+ /* prepare output buffer and crc */
+ outptr = slide;
+ outcnt = 0L;
+ outsiz = 0L;
+ updcrc(NULL, 0L);
+
+ /* decompress */
+ if (g || h[LOCHOW])
+ { /* deflated entry */
+ int r;
+
+ if ((r = inflate()) != 0)
+ if (r == 3)
+ panic("out of memory");
+ else
+ panic("invalid compressed data--format violated");
+ inflate_free();
+ }
+ else
+ { /* stored entry */
+ register ulg n;
+
+ n = LG(h + LOCLEN);
+ if (n != LG(h + LOCSIZ)) {
+ printf("len %ld, siz %ld\n", n, LG(h + LOCSIZ));
+ panic("invalid compressed data--length mismatch");
+ }
+ while (n--) {
+ ush c = nextbyte();
+ *outptr++ = (uch)c;
+ if (++outcnt == WSIZE) /* do FlushOutput() */
+ {
+ flush(outcnt);
+ outptr = slide;
+ outcnt = 0L;
+ }
+ }
+ if (outcnt) /* flush one last time; no need to reset outptr/outcnt */
+ flush(outcnt);
+ }
+
+ /* if extended header, get it */
+ if (g)
+ {
+ if (nextblock((char *)h + LOCCRC, 8) != 8)
+ panic("gzip file ended prematurely");
+ }
+ else
+ if ((h[LOCFLG] & EXTFLG) &&
+ nextblock((char *)h + LOCCRC - 4, EXTHDR) != EXTHDR)
+ panic("zip file ended prematurely");
+
+ /* validate decompression */
+ if (LG(h + LOCCRC) != updcrc(slide, 0L))
+ panic("invalid compressed data--crc error");
+ if (LG(h + (g ? LOCSIZ : LOCLEN)) != outsiz)
+ panic("invalid compressed data--length error");
+
+ /* check if there are more entries */
+ if (!g && nextblock((char *)h, 4) == 4 && LG(h) == LOCSIG)
+ printf("funzip warning: zip file has more than one entry--rest ignored\n");
+
+ asm(" movd %0,r3" : : "g" (r3)); /* magic */
+ asm(" movd %0,r4" : : "g" (esym));
+ asm(" movd %0,r5" : : "g" (load));
+ asm(" movd %0,r6" : : "g" (r6)); /* devtype */
+ asm(" movd %0,r7" : : "g" (r7)); /* howto */
+
+ (*((int (*)()) x.a_entry))();
+}
+
+/* Table of CRC-32's of all single-byte values (made by makecrc.c) */
+ulg crc_32_tab[] = {
+ 0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L,
+ 0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L,
+ 0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L,
+ 0x90bf1d91L, 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL,
+ 0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, 0x136c9856L,
+ 0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L,
+ 0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L,
+ 0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL,
+ 0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L,
+ 0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, 0x26d930acL, 0x51de003aL,
+ 0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L,
+ 0xb8bda50fL, 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L,
+ 0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, 0x76dc4190L,
+ 0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL,
+ 0x9fbfe4a5L, 0xe8b8d433L, 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL,
+ 0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L,
+ 0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL,
+ 0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, 0x65b0d9c6L, 0x12b7e950L,
+ 0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L,
+ 0xfbd44c65L, 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L,
+ 0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, 0x4369e96aL,
+ 0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L,
+ 0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL, 0x270241aaL, 0xbe0b1010L,
+ 0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL,
+ 0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L,
+ 0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, 0xedb88320L, 0x9abfb3b6L,
+ 0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L,
+ 0x73dc1683L, 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L,
+ 0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, 0xf00f9344L,
+ 0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL,
+ 0x196c3671L, 0x6e6b06e7L, 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL,
+ 0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L,
+ 0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L,
+ 0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, 0xd80d2bdaL, 0xaf0a1b4cL,
+ 0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL,
+ 0x4669be79L, 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L,
+ 0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, 0xc5ba3bbeL,
+ 0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L,
+ 0x2cd99e8bL, 0x5bdeae1dL, 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL,
+ 0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L,
+ 0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL,
+ 0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, 0x86d3d2d4L, 0xf1d4e242L,
+ 0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L,
+ 0x18b74777L, 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL,
+ 0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, 0xa00ae278L,
+ 0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L,
+ 0x4969474dL, 0x3e6e77dbL, 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L,
+ 0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L,
+ 0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L,
+ 0xcdd70693L, 0x54de5729L, 0x23d967bfL, 0xb3667a2eL, 0xc4614ab8L,
+ 0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL,
+ 0x2d02ef8dL
+};
+
+/* From: inflate.c -- put in the public domain by Mark Adler
+ version c14o, 23 August 1994 */
+
+/*
+ Inflate deflated (PKZIP's method 8 compressed) data. The compression
+ method searches for as much of the current string of bytes (up to a
+ length of 258) in the previous 32K bytes. If it doesn't find any
+ matches (of at least length 3), it codes the next byte. Otherwise, it
+ codes the length of the matched string and its distance backwards from
+ the current position. There is a single Huffman code that codes both
+ single bytes (called "literals") and match lengths. A second Huffman
+ code codes the distance information, which follows a length code. Each
+ length or distance code actually represents a base value and a number
+ of "extra" (sometimes zero) bits to get to add to the base value. At
+ the end of each deflated block is a special end-of-block (EOB) literal/
+ length code. The decoding process is basically: get a literal/length
+ code; if EOB then done; if a literal, emit the decoded byte; if a
+ length then get the distance and emit the referred-to bytes from the
+ sliding window of previously emitted data.
+
+ There are (currently) three kinds of inflate blocks: stored, fixed, and
+ dynamic. The compressor outputs a chunk of data at a time and decides
+ which method to use on a chunk-by-chunk basis. A chunk might typically
+ be 32K to 64K, uncompressed. If the chunk is uncompressible, then the
+ "stored" method is used. In this case, the bytes are simply stored as
+ is, eight bits per byte, with none of the above coding. The bytes are
+ preceded by a count, since there is no longer an EOB code.
+
+ If the data is compressible, then either the fixed or dynamic methods
+ are used. In the dynamic method, the compressed data is preceded by
+ an encoding of the literal/length and distance Huffman codes that are
+ to be used to decode this block. The representation is itself Huffman
+ coded, and so is preceded by a description of that code. These code
+ descriptions take up a little space, and so for small blocks, there is
+ a predefined set of codes, called the fixed codes. The fixed method is
+ used if the block ends up smaller that way (usually for quite small
+ chunks); otherwise the dynamic method is used. In the latter case, the
+ codes are customized to the probabilities in the current block and so
+ can code it much better than the pre-determined fixed codes can.
+
+ The Huffman codes themselves are decoded using a mutli-level table
+ lookup, in order to maximize the speed of decoding plus the speed of
+ building the decoding tables. See the comments below that precede the
+ lbits and dbits tuning parameters.
+ */
+
+
+/*
+ Notes beyond the 1.93a appnote.txt:
+
+ 1. Distance pointers never point before the beginning of the output
+ stream.
+ 2. Distance pointers can point back across blocks, up to 32k away.
+ 3. There is an implied maximum of 7 bits for the bit length table and
+ 15 bits for the actual data.
+ 4. If only one code exists, then it is encoded using one bit. (Zero
+ would be more efficient, but perhaps a little confusing.) If two
+ codes exist, they are coded using one bit each (0 and 1).
+ 5. There is no way of sending zero distance codes--a dummy must be
+ sent if there are none. (History: a pre 2.0 version of PKZIP would
+ store blocks with no distance codes, but this was discovered to be
+ too harsh a criterion.) Valid only for 1.93a. 2.04c does allow
+ zero distance codes, which is sent as one code of zero bits in
+ length.
+ 6. There are up to 286 literal/length codes. Code 256 represents the
+ end-of-block. Note however that the static length tree defines
+ 288 codes just to fill out the Huffman codes. Codes 286 and 287
+ cannot be used though, since there is no length base or extra bits
+ defined for them. Similarily, there are up to 30 distance codes.
+ However, static trees define 32 codes (all 5 bits) to fill out the
+ Huffman codes, but the last two had better not show up in the data.
+ 7. Unzip can check dynamic Huffman blocks for complete code sets.
+ The exception is that a single code would not be complete (see #4).
+ 8. The five bits following the block type is really the number of
+ literal codes sent minus 257.
+ 9. Length codes 8,16,16 are interpreted as 13 length codes of 8 bits
+ (1+6+6). Therefore, to output three times the length, you output
+ three codes (1+1+1), whereas to output four times the same length,
+ you only need two codes (1+3). Hmm.
+ 10. In the tree reconstruction algorithm, Code = Code + Increment
+ only if BitLength(i) is not zero. (Pretty obvious.)
+ 11. Correction: 4 Bits: # of Bit Length codes - 4 (4 - 19)
+ 12. Note: length code 284 can represent 227-258, but length code 285
+ really is 258. The last length deserves its own, short code
+ since it gets used a lot in very redundant files. The length
+ 258 is special since 258 - 3 (the min match length) is 255.
+ 13. The literal/length and distance code bit lengths are read as a
+ single stream of lengths. It is possible (and advantageous) for
+ a repeat code (16, 17, or 18) to go across the boundary between
+ the two sets of lengths.
+ */
+
+
+#define PKZIP_BUG_WORKAROUND /* PKZIP 1.93a problem--live with it */
+
+/*
+ inflate.h must supply the uch slide[WSIZE] array and the NEXTBYTE,
+ FLUSH() and memzero macros. If the window size is not 32K, it
+ should also define WSIZE. If INFMOD is defined, it can include
+ compiled functions to support the NEXTBYTE and/or FLUSH() macros.
+ There are defaults for NEXTBYTE and FLUSH() below for use as
+ examples of what those functions need to do. Normally, you would
+ also want FLUSH() to compute a crc on the data. inflate.h also
+ needs to provide these typedefs:
+
+ typedef unsigned char uch;
+ typedef unsigned short ush;
+ typedef unsigned long ulg;
+
+ This module uses the external functions malloc() and free() (and
+ probably memset() or bzero() in the memzero() macro). Their
+ prototypes are normally found in <string.h> and <stdlib.h>.
+ */
+
+/* Warning: the fwrite above might not work on 16-bit compilers, since
+ 0x8000 might be interpreted as -32,768 by the library function. */
+
+/* Huffman code lookup table entry--this entry is four bytes for machines
+ that have 16-bit pointers (e.g. PC's in the small or medium model).
+ Valid extra bits are 0..13. e == 15 is EOB (end of block), e == 16
+ means that v is a literal, 16 < e < 32 means that v is a pointer to
+ the next table, which codes e - 16 bits, and lastly e == 99 indicates
+ an unused code. If a code with e == 99 is looked up, this implies an
+ error in the data. */
+struct huft {
+ uch e; /* number of extra bits or operation */
+ uch b; /* number of bits in this code or subcode */
+ union {
+ ush n; /* literal, length base, or distance base */
+ struct huft *t; /* pointer to next level of table */
+ } v;
+};
+
+int huft_build OF((unsigned *, unsigned, unsigned, ush *, ush *,
+ struct huft **, int *));
+int huft_free OF((struct huft *));
+int inflate_codes OF((struct huft *, struct huft *, int, int));
+int inflate_stored OF((void));
+int inflate_fixed OF((void));
+int inflate_dynamic OF((void));
+int inflate_block OF((int *));
+int inflate OF((void));
+int inflate_free OF((void));
+
+
+/* The inflate algorithm uses a sliding 32K byte window on the uncompressed
+ stream to find repeated byte strings. This is implemented here as a
+ circular buffer. The index is updated simply by incrementing and then
+ and'ing with 0x7fff (32K-1). */
+/* It is left to other modules to supply the 32K area. It is assumed
+ to be usable as if it were declared "uch slide[32768];" or as just
+ "uch *slide;" and then malloc'ed in the latter case. The definition
+ must be in unzip.h, included above. */
+unsigned wp; /* current position in slide */
+
+
+/* Tables for deflate from PKZIP's appnote.txt. */
+static unsigned border[] = { /* Order of the bit length code lengths */
+ 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15};
+static ush cplens[] = { /* Copy lengths for literal codes 257..285 */
+ 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31,
+ 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0};
+ /* note: see note #13 above about the 258 in this list. */
+static ush cplext[] = { /* Extra bits for literal codes 257..285 */
+ 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2,
+ 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0, 99, 99}; /* 99==invalid */
+static ush cpdist[] = { /* Copy offsets for distance codes 0..29 */
+ 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193,
+ 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145,
+ 8193, 12289, 16385, 24577};
+static ush cpdext[] = { /* Extra bits for distance codes */
+ 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6,
+ 7, 7, 8, 8, 9, 9, 10, 10, 11, 11,
+ 12, 12, 13, 13};
+
+/* And'ing with mask[n] masks the lower n bits */
+ush mask[] = {
+ 0x0000,
+ 0x0001, 0x0003, 0x0007, 0x000f, 0x001f, 0x003f, 0x007f, 0x00ff,
+ 0x01ff, 0x03ff, 0x07ff, 0x0fff, 0x1fff, 0x3fff, 0x7fff, 0xffff
+};
+
+
+/* Macros for inflate() bit peeking and grabbing.
+ The usage is:
+
+ NEEDBITS(j)
+ x = b & mask[j];
+ DUMPBITS(j)
+
+ where NEEDBITS makes sure that b has at least j bits in it, and
+ DUMPBITS removes the bits from b. The macros use the variable k
+ for the number of bits in b. Normally, b and k are register
+ variables for speed, and are initialized at the begining of a
+ routine that uses these macros from a global bit buffer and count.
+
+ In order to not ask for more bits than there are in the compressed
+ stream, the Huffman tables are constructed to only ask for just
+ enough bits to make up the end-of-block code (value 256). Then no
+ bytes need to be "returned" to the buffer at the end of the last
+ block. See the huft_build() routine.
+ */
+
+ulg bb; /* bit buffer */
+unsigned bk; /* bits in bit buffer */
+
+#ifndef CHECK_EOF
+# define NEEDBITS(n) {while(k<(n)){b|=((ulg)NEXTBYTE)<<k;k+=8;}}
+#else
+# define NEEDBITS(n) {while(k<(n)){int c=NEXTBYTE;if(c==EOF)return 1;\
+ b|=((ulg)c)<<k;k+=8;}}
+#endif /* Piet Plomp: change "return 1" to "break" */
+
+#define DUMPBITS(n) {b>>=(n);k-=(n);}
+
+
+/*
+ Huffman code decoding is performed using a multi-level table lookup.
+ The fastest way to decode is to simply build a lookup table whose
+ size is determined by the longest code. However, the time it takes
+ to build this table can also be a factor if the data being decoded
+ is not very long. The most common codes are necessarily the
+ shortest codes, so those codes dominate the decoding time, and hence
+ the speed. The idea is you can have a shorter table that decodes the
+ shorter, more probable codes, and then point to subsidiary tables for
+ the longer codes. The time it costs to decode the longer codes is
+ then traded against the time it takes to make longer tables.
+
+ This results of this trade are in the variables lbits and dbits
+ below. lbits is the number of bits the first level table for literal/
+ length codes can decode in one step, and dbits is the same thing for
+ the distance codes. Subsequent tables are also less than or equal to
+ those sizes. These values may be adjusted either when all of the
+ codes are shorter than that, in which case the longest code length in
+ bits is used, or when the shortest code is *longer* than the requested
+ table size, in which case the length of the shortest code in bits is
+ used.
+
+ There are two different values for the two tables, since they code a
+ different number of possibilities each. The literal/length table
+ codes 286 possible values, or in a flat code, a little over eight
+ bits. The distance table codes 30 possible values, or a little less
+ than five bits, flat. The optimum values for speed end up being
+ about one bit more than those, so lbits is 8+1 and dbits is 5+1.
+ The optimum values may differ though from machine to machine, and
+ possibly even between compilers. Your mileage may vary.
+ */
+
+
+int lbits = 9; /* bits in base literal/length lookup table */
+int dbits = 6; /* bits in base distance lookup table */
+
+
+/* If BMAX needs to be larger than 16, then h and x[] should be ulg. */
+#define BMAX 16 /* maximum bit length of any code (16 for explode) */
+#define N_MAX 288 /* maximum number of codes in any set */
+
+
+unsigned hufts; /* track memory usage */
+
+void *malloc(n)
+int n;
+{
+ void *p;
+ p = alloc(n + sizeof(n));
+ if (!p)
+ return(NULL);
+ *((int *)p) = n;
+ p += sizeof(n);
+ return(p);
+}
+
+int huft_build(b, n, s, d, e, t, m)
+unsigned *b; /* code lengths in bits (all assumed <= BMAX) */
+unsigned n; /* number of codes (assumed <= N_MAX) */
+unsigned s; /* number of simple-valued codes (0..s-1) */
+ush *d; /* list of base values for non-simple codes */
+ush *e; /* list of extra bits for non-simple codes */
+struct huft **t; /* result: starting table */
+int *m; /* maximum lookup bits, returns actual */
+/* Given a list of code lengths and a maximum table size, make a set of
+ tables to decode that set of codes. Return zero on success, one if
+ the given code set is incomplete (the tables are still built in this
+ case), two if the input is invalid (all zero length codes or an
+ oversubscribed set of lengths), and three if not enough memory.
+ The code with value 256 is special, and the tables are constructed
+ so that no bits beyond that code are fetched when that code is
+ decoded. */
+{
+ unsigned a; /* counter for codes of length k */
+ unsigned c[BMAX+1]; /* bit length count table */
+ unsigned el; /* length of EOB code (value 256) */
+ unsigned f; /* i repeats in table every f entries */
+ int g; /* maximum code length */
+ int h; /* table level */
+ register unsigned i; /* counter, current code */
+ register unsigned j; /* counter */
+ register int k; /* number of bits in current code */
+ int lx[BMAX+1]; /* memory for l[-1..BMAX-1] */
+ int *l = lx+1; /* stack of bits per table */
+ register unsigned *p; /* pointer into c[], b[], or v[] */
+ register struct huft *q; /* points to current table */
+ struct huft r; /* table entry for structure assignment */
+ struct huft *u[BMAX]; /* table stack */
+ static unsigned v[N_MAX]; /* values in order of bit length */
+ register int w; /* bits before this table == (l * h) */
+ unsigned x[BMAX+1]; /* bit offsets, then code stack */
+ unsigned *xp; /* pointer into x */
+ int y; /* number of dummy codes added */
+ unsigned z; /* number of entries in current table */
+
+
+ /* Generate counts for each bit length */
+ el = n > 256 ? b[256] : BMAX; /* set length of EOB code, if any */
+ memzero((char *)c, sizeof(c));
+ p = b; i = n;
+ do {
+ c[*p]++; p++; /* assume all entries <= BMAX */
+ } while (--i);
+ if (c[0] == n) /* null input--all zero length codes */
+ {
+ *t = (struct huft *)NULL;
+ *m = 0;
+ return 0;
+ }
+
+
+ /* Find minimum and maximum length, bound *m by those */
+ for (j = 1; j <= BMAX; j++)
+ if (c[j])
+ break;
+ k = j; /* minimum code length */
+ if ((unsigned)*m < j)
+ *m = j;
+ for (i = BMAX; i; i--)
+ if (c[i])
+ break;
+ g = i; /* maximum code length */
+ if ((unsigned)*m > i)
+ *m = i;
+
+
+ /* Adjust last length count to fill out codes, if needed */
+ for (y = 1 << j; j < i; j++, y <<= 1)
+ if ((y -= c[j]) < 0)
+ return 2; /* bad input: more codes than bits */
+ if ((y -= c[i]) < 0)
+ return 2;
+ c[i] += y;
+
+
+ /* Generate starting offsets into the value table for each length */
+ x[1] = j = 0;
+ p = c + 1; xp = x + 2;
+ while (--i) { /* note that i == g from above */
+ *xp++ = (j += *p++);
+ }
+
+
+ /* Make a table of values in order of bit lengths */
+ p = b; i = 0;
+ do {
+ if ((j = *p++) != 0)
+ v[x[j]++] = i;
+ } while (++i < n);
+
+
+ /* Generate the Huffman codes and for each, make the table entries */
+ x[0] = i = 0; /* first Huffman code is zero */
+ p = v; /* grab values in bit order */
+ h = -1; /* no tables yet--level -1 */
+ w = l[-1] = 0; /* no bits decoded yet */
+ u[0] = (struct huft *)NULL; /* just to keep compilers happy */
+ q = (struct huft *)NULL; /* ditto */
+ z = 0; /* ditto */
+
+ /* go through the bit lengths (k already is bits in shortest code) */
+ for (; k <= g; k++)
+ {
+ a = c[k];
+ while (a--)
+ {
+ /* here i is the Huffman code of length k bits for value *p */
+ /* make tables up to required level */
+ while (k > w + l[h])
+ {
+ w += l[h++]; /* add bits already decoded */
+
+ /* compute minimum size table less than or equal to *m bits */
+ z = (z = g - w) > (unsigned)*m ? *m : z; /* upper limit */
+ if ((f = 1 << (j = k - w)) > a + 1) /* try a k-w bit table */
+ { /* too few codes for k-w bit table */
+ f -= a + 1; /* deduct codes from patterns left */
+ xp = c + k;
+ while (++j < z) /* try smaller tables up to z bits */
+ {
+ if ((f <<= 1) <= *++xp)
+ break; /* enough codes to use up j bits */
+ f -= *xp; /* else deduct codes from patterns */
+ }
+ }
+ if ((unsigned)w + j > el && (unsigned)w < el)
+ j = el - w; /* make EOB code end at table */
+ z = 1 << j; /* table entries for j-bit table */
+ l[h] = j; /* set table size in stack */
+
+ /* allocate and link in new table */
+ if ((q = (struct huft *)malloc((z + 1)*sizeof(struct huft))) ==
+ (struct huft *)NULL)
+ {
+ if (h)
+ huft_free(u[0]);
+ return 3; /* not enough memory */
+ }
+ hufts += z + 1; /* track memory usage */
+ *t = q + 1; /* link to list for huft_free() */
+ *(t = &(q->v.t)) = (struct huft *)NULL;
+ u[h] = ++q; /* table starts after link */
+
+ /* connect to last table, if there is one */
+ if (h)
+ {
+ x[h] = i; /* save pattern for backing up */
+ r.b = (uch)l[h-1]; /* bits to dump before this table */
+ r.e = (uch)(16 + j); /* bits in this table */
+ r.v.t = q; /* pointer to this table */
+ j = (i & ((1 << w) - 1)) >> (w - l[h-1]);
+ u[h-1][j] = r; /* connect to last table */
+ }
+ }
+
+ /* set up table entry in r */
+ r.b = (uch)(k - w);
+ if (p >= v + n)
+ r.e = 99; /* out of values--invalid code */
+ else if (*p < s)
+ {
+ r.e = (uch)(*p < 256 ? 16 : 15); /* 256 is end-of-block code */
+ r.v.n = *p++; /* simple code is just the value */
+ }
+ else
+ {
+ r.e = (uch)e[*p - s]; /* non-simple--look up in lists */
+ r.v.n = d[*p++ - s];
+ }
+
+ /* fill code-like entries with r */
+ f = 1 << (k - w);
+ for (j = i >> w; j < z; j += f)
+ q[j] = r;
+
+ /* backwards increment the k-bit code i */
+ for (j = 1 << (k - 1); i & j; j >>= 1)
+ i ^= j;
+ i ^= j;
+
+ /* backup over finished tables */
+ while ((i & ((1 << w) - 1)) != x[h])
+ w -= l[--h]; /* don't need to update q */
+ }
+ }
+
+
+ /* return actual size of base table */
+ *m = l[0];
+
+
+ /* Return true (1) if we were given an incomplete table */
+ return y != 0 && g != 1;
+}
+
+
+
+int huft_free(t)
+struct huft *t; /* table to free */
+/* Free the malloc'ed tables built by huft_build(), which makes a linked
+ list of the tables it made, with the links in a dummy first entry of
+ each table. */
+{
+ register struct huft *p, *q;
+
+
+ /* Go through linked list, freeing from the malloced (t[-1]) address. */
+ p = t;
+ while (p != (struct huft *)NULL)
+ {
+ q = (--p)->v.t;
+ free(((void *)p) - sizeof(int), ((int *)p)[-1]);
+ p = q;
+ }
+ return 0;
+}
+
+
+
+#ifdef ASM_INFLATECODES
+# define inflate_codes(tl,td,bl,bd) flate_codes(tl,td,bl,bd,(uch *)slide)
+ int flate_codes OF((struct huft *, struct huft *, int, int, uch *));
+
+#else
+
+int inflate_codes(tl, td, bl, bd)
+struct huft *tl, *td; /* literal/length and distance decoder tables */
+int bl, bd; /* number of bits decoded by tl[] and td[] */
+/* inflate (decompress) the codes in a deflated (compressed) block.
+ Return an error code or zero if it all goes ok. */
+{
+ register unsigned e; /* table entry flag/number of extra bits */
+ unsigned n, d; /* length and index for copy */
+ unsigned w; /* current window position */
+ struct huft *t; /* pointer to table entry */
+ unsigned ml, md; /* masks for bl and bd bits */
+ register ulg b; /* bit buffer */
+ register unsigned k; /* number of bits in bit buffer */
+
+
+ /* make local copies of globals */
+ b = bb; /* initialize bit buffer */
+ k = bk;
+ w = wp; /* initialize window position */
+
+
+ /* inflate the coded data */
+ ml = mask[bl]; /* precompute masks for speed */
+ md = mask[bd];
+ while (1) /* do until end of block */
+ {
+ NEEDBITS((unsigned)bl)
+ if ((e = (t = tl + ((unsigned)b & ml))->e) > 16)
+ do {
+ if (e == 99)
+ return 1;
+ DUMPBITS(t->b)
+ e -= 16;
+ NEEDBITS(e)
+ } while ((e = (t = t->v.t + ((unsigned)b & mask[e]))->e) > 16);
+ DUMPBITS(t->b)
+ if (e == 16) /* then it's a literal */
+ {
+ slide[w++] = (uch)t->v.n;
+ if (w == WSIZE)
+ {
+ FLUSH(w);
+ w = 0;
+ }
+ }
+ else /* it's an EOB or a length */
+ {
+ /* exit if end of block */
+ if (e == 15)
+ break;
+
+ /* get length of block to copy */
+ NEEDBITS(e)
+ n = t->v.n + ((unsigned)b & mask[e]);
+ DUMPBITS(e);
+
+ /* decode distance of block to copy */
+ NEEDBITS((unsigned)bd)
+ if ((e = (t = td + ((unsigned)b & md))->e) > 16)
+ do {
+ if (e == 99)
+ return 1;
+ DUMPBITS(t->b)
+ e -= 16;
+ NEEDBITS(e)
+ } while ((e = (t = t->v.t + ((unsigned)b & mask[e]))->e) > 16);
+ DUMPBITS(t->b)
+ NEEDBITS(e)
+ d = w - t->v.n - ((unsigned)b & mask[e]);
+ DUMPBITS(e)
+
+ /* do the copy */
+ do {
+ n -= (e = (e = WSIZE - ((d &= WSIZE-1) > w ? d : w)) > n ? n : e);
+#ifndef NOMEMCPY
+ if (w - d >= e) /* (this test assumes unsigned comparison) */
+ {
+ memcpy(slide + w, slide + d, e);
+ w += e;
+ d += e;
+ }
+ else /* do it slow to avoid memcpy() overlap */
+#endif /* !NOMEMCPY */
+ do {
+ slide[w++] = slide[d++];
+ } while (--e);
+ if (w == WSIZE)
+ {
+ FLUSH(w);
+ w = 0;
+ }
+ } while (n);
+ }
+ }
+
+
+ /* restore the globals from the locals */
+ wp = w; /* restore global window pointer */
+ bb = b; /* restore global bit buffer */
+ bk = k;
+
+
+ /* done */
+ return 0;
+}
+
+#endif /* ASM_INFLATECODES */
+
+
+
+int inflate_stored()
+/* "decompress" an inflated type 0 (stored) block. */
+{
+ unsigned n; /* number of bytes in block */
+ unsigned w; /* current window position */
+ register ulg b; /* bit buffer */
+ register unsigned k; /* number of bits in bit buffer */
+
+
+ /* make local copies of globals */
+ b = bb; /* initialize bit buffer */
+ k = bk;
+ w = wp; /* initialize window position */
+
+
+ /* go to byte boundary */
+ n = k & 7;
+ DUMPBITS(n);
+
+
+ /* get the length and its complement */
+ NEEDBITS(16)
+ n = ((unsigned)b & 0xffff);
+ DUMPBITS(16)
+ NEEDBITS(16)
+ if (n != (unsigned)((~b) & 0xffff))
+ return 1; /* error in compressed data */
+ DUMPBITS(16)
+
+
+ /* read and output the compressed data */
+ while (n--)
+ {
+ NEEDBITS(8)
+ slide[w++] = (uch)b;
+ if (w == WSIZE)
+ {
+ FLUSH(w);
+ w = 0;
+ }
+ DUMPBITS(8)
+ }
+
+
+ /* restore the globals from the locals */
+ wp = w; /* restore global window pointer */
+ bb = b; /* restore global bit buffer */
+ bk = k;
+ return 0;
+}
+
+
+/* Globals for literal tables (built once) */
+struct huft *fixed_tl = (struct huft *)NULL;
+struct huft *fixed_td;
+int fixed_bl, fixed_bd;
+
+int inflate_fixed()
+/* decompress an inflated type 1 (fixed Huffman codes) block. We should
+ either replace this with a custom decoder, or at least precompute the
+ Huffman tables. */
+{
+ /* if first time, set up tables for fixed blocks */
+ if (fixed_tl == (struct huft *)NULL)
+ {
+ int i; /* temporary variable */
+ static unsigned l[288]; /* length list for huft_build */
+
+ /* literal table */
+ for (i = 0; i < 144; i++)
+ l[i] = 8;
+ for (; i < 256; i++)
+ l[i] = 9;
+ for (; i < 280; i++)
+ l[i] = 7;
+ for (; i < 288; i++) /* make a complete, but wrong code set */
+ l[i] = 8;
+ fixed_bl = 7;
+ if ((i = huft_build(l, 288, 257, cplens, cplext,
+ &fixed_tl, &fixed_bl)) != 0)
+ {
+ fixed_tl = (struct huft *)NULL;
+ return i;
+ }
+
+ /* distance table */
+ for (i = 0; i < 30; i++) /* make an incomplete code set */
+ l[i] = 5;
+ fixed_bd = 5;
+ if ((i = huft_build(l, 30, 0, cpdist, cpdext, &fixed_td, &fixed_bd)) > 1)
+ {
+ huft_free(fixed_tl);
+ fixed_tl = (struct huft *)NULL;
+ return i;
+ }
+ }
+
+
+ /* decompress until an end-of-block code */
+ return inflate_codes(fixed_tl, fixed_td, fixed_bl, fixed_bd) != 0;
+}
+
+
+
+int inflate_dynamic()
+/* decompress an inflated type 2 (dynamic Huffman codes) block. */
+{
+ int i; /* temporary variables */
+ unsigned j;
+ unsigned l; /* last length */
+ unsigned m; /* mask for bit lengths table */
+ unsigned n; /* number of lengths to get */
+ struct huft *tl; /* literal/length code table */
+ struct huft *td; /* distance code table */
+ int bl; /* lookup bits for tl */
+ int bd; /* lookup bits for td */
+ unsigned nb; /* number of bit length codes */
+ unsigned nl; /* number of literal/length codes */
+ unsigned nd; /* number of distance codes */
+#ifdef PKZIP_BUG_WORKAROUND
+ static unsigned ll[288+32]; /* literal/length and distance code lengths */
+#else
+ static unsigned ll[286+30]; /* literal/length and distance code lengths */
+#endif
+ register ulg b; /* bit buffer */
+ register unsigned k; /* number of bits in bit buffer */
+
+
+ /* make local bit buffer */
+ b = bb;
+ k = bk;
+
+
+ /* read in table lengths */
+ NEEDBITS(5)
+ nl = 257 + ((unsigned)b & 0x1f); /* number of literal/length codes */
+ DUMPBITS(5)
+ NEEDBITS(5)
+ nd = 1 + ((unsigned)b & 0x1f); /* number of distance codes */
+ DUMPBITS(5)
+ NEEDBITS(4)
+ nb = 4 + ((unsigned)b & 0xf); /* number of bit length codes */
+ DUMPBITS(4)
+#ifdef PKZIP_BUG_WORKAROUND
+ if (nl > 288 || nd > 32)
+#else
+ if (nl > 286 || nd > 30)
+#endif
+ return 1; /* bad lengths */
+
+
+ /* read in bit-length-code lengths */
+ for (j = 0; j < nb; j++)
+ {
+ NEEDBITS(3)
+ ll[border[j]] = (unsigned)b & 7;
+ DUMPBITS(3)
+ }
+ for (; j < 19; j++)
+ ll[border[j]] = 0;
+
+
+ /* build decoding table for trees--single level, 7 bit lookup */
+ bl = 7;
+ if ((i = huft_build(ll, 19, 19, NULL, NULL, &tl, &bl)) != 0)
+ {
+ if (i == 1)
+ huft_free(tl);
+ return i; /* incomplete code set */
+ }
+
+
+ /* read in literal and distance code lengths */
+ n = nl + nd;
+ m = mask[bl];
+ i = l = 0;
+ while ((unsigned)i < n)
+ {
+ NEEDBITS((unsigned)bl)
+ j = (td = tl + ((unsigned)b & m))->b;
+ DUMPBITS(j)
+ j = td->v.n;
+ if (j < 16) /* length of code in bits (0..15) */
+ ll[i++] = l = j; /* save last length in l */
+ else if (j == 16) /* repeat last length 3 to 6 times */
+ {
+ NEEDBITS(2)
+ j = 3 + ((unsigned)b & 3);
+ DUMPBITS(2)
+ if ((unsigned)i + j > n)
+ return 1;
+ while (j--)
+ ll[i++] = l;
+ }
+ else if (j == 17) /* 3 to 10 zero length codes */
+ {
+ NEEDBITS(3)
+ j = 3 + ((unsigned)b & 7);
+ DUMPBITS(3)
+ if ((unsigned)i + j > n)
+ return 1;
+ while (j--)
+ ll[i++] = 0;
+ l = 0;
+ }
+ else /* j == 18: 11 to 138 zero length codes */
+ {
+ NEEDBITS(7)
+ j = 11 + ((unsigned)b & 0x7f);
+ DUMPBITS(7)
+ if ((unsigned)i + j > n)
+ return 1;
+ while (j--)
+ ll[i++] = 0;
+ l = 0;
+ }
+ }
+
+
+ /* free decoding table for trees */
+ huft_free(tl);
+
+
+ /* restore the global bit buffer */
+ bb = b;
+ bk = k;
+
+
+ /* build the decoding tables for literal/length and distance codes */
+ bl = lbits;
+ if ((i = huft_build(ll, nl, 257, cplens, cplext, &tl, &bl)) != 0)
+ {
+ return i; /* incomplete code set */
+ }
+ bd = dbits;
+ if ((i = huft_build(ll + nl, nd, 0, cpdist, cpdext, &td, &bd)) != 0)
+ {
+ if (i == 1 && !qflag) {
+#ifdef PKZIP_BUG_WORKAROUND
+ i = 0;
+ }
+#else
+ huft_free(td);
+ }
+ huft_free(tl);
+ return i; /* incomplete code set */
+#endif
+ }
+
+
+ /* decompress until an end-of-block code */
+ if (inflate_codes(tl, td, bl, bd))
+ return 1;
+
+
+ /* free the decoding tables, return */
+ huft_free(tl);
+ huft_free(td);
+ return 0;
+}
+
+
+
+int inflate_block(e)
+int *e; /* last block flag */
+/* decompress an inflated block */
+{
+ unsigned t; /* block type */
+ register ulg b; /* bit buffer */
+ register unsigned k; /* number of bits in bit buffer */
+
+
+ /* make local bit buffer */
+ b = bb;
+ k = bk;
+
+
+ /* read in last block bit */
+ NEEDBITS(1)
+ *e = (int)b & 1;
+ DUMPBITS(1)
+
+
+ /* read in block type */
+ NEEDBITS(2)
+ t = (unsigned)b & 3;
+ DUMPBITS(2)
+
+
+ /* restore the global bit buffer */
+ bb = b;
+ bk = k;
+
+
+ /* inflate that block type */
+ if (t == 2)
+ return inflate_dynamic();
+ if (t == 0)
+ return inflate_stored();
+ if (t == 1)
+ return inflate_fixed();
+
+
+ /* bad block type */
+ return 2;
+}
+
+
+
+int inflate()
+/* decompress an inflated entry */
+{
+ int e; /* last block flag */
+ int r; /* result code */
+ unsigned h; /* maximum struct huft's malloc'ed */
+
+
+ /* initialize window, bit buffer */
+ wp = 0;
+ bk = 0;
+ bb = 0;
+
+
+ /* decompress until the last block */
+ h = 0;
+ do {
+ hufts = 0;
+ if ((r = inflate_block(&e)) != 0)
+ return r;
+ if (hufts > h)
+ h = hufts;
+ } while (!e);
+
+
+ /* flush out slide */
+ FLUSH(wp);
+
+
+ /* return success */
+ return 0;
+}
+
+
+
+int inflate_free()
+{
+ if (fixed_tl != (struct huft *)NULL)
+ {
+ huft_free(fixed_td);
+ huft_free(fixed_tl);
+ fixed_td = fixed_tl = (struct huft *)NULL;
+ }
+ return 0;
+}
diff --git a/sys/arch/pc532/stand/machdep.c b/sys/arch/pc532/stand/machdep.c
new file mode 100644
index 00000000000..ec044477f0b
--- /dev/null
+++ b/sys/arch/pc532/stand/machdep.c
@@ -0,0 +1,98 @@
+/* $NetBSD: machdep.c,v 1.2 1994/10/26 08:25:49 cgd Exp $ */
+
+/*
+ * Copyright (c) 1994 Philip L. Budne.
+ * 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 L. Budne.
+ * 4. The name of Philip L. Budne 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.
+ */
+
+/*
+ * pc532 standalone machdep code
+ * Phil Budne, May 10, 1994
+ *
+ */
+
+#include <sys/types.h>
+#include "samachdep.h"
+
+int testing = 0;
+
+void
+bzero( char *addr, int len )
+{
+ while (len-- > 0)
+ *addr++ = '\0';
+}
+
+/* XXX TEMP; would like to use code more like hp300 scsi.c */
+
+void
+scsiinit(void)
+{
+}
+
+int
+scsialive(int ctlr)
+{
+ return 1; /* controller always alive! */
+}
+
+/* call functions in scsi_hi.c */
+#include "so.h"
+
+int
+scsi_tt_read(ctlr, slave, buf, len, blk, nblk)
+ int ctlr, slave;
+ u_char *buf;
+ u_int len;
+ daddr_t blk;
+ u_int nblk;
+{
+#if 0
+printf("scsi_tt_read ctlr %d, slave %d, len %d, blk %d, nblk %d\n",
+ ctlr, slave, len, blk, nblk );
+#endif
+ if (sc_rdwt(DISK_READ, blk, buf, nblk, 1<<slave, 0) == 0)
+ return 0;
+ return -2;
+}
+
+int
+scsi_tt_write(ctlr, slave, buf, len, blk, nblk)
+ int ctlr, slave;
+ u_char *buf;
+ u_int len;
+ daddr_t blk;
+ u_int nblk;
+{
+#if 0
+ if (sc_rdwt(DISK_WRITE, blk, buf, nblk, 1<<slave, 0) == 0)
+ return 0;
+#endif
+ return -2;
+}
diff --git a/sys/arch/pc532/stand/prf.c b/sys/arch/pc532/stand/prf.c
new file mode 100644
index 00000000000..e9db7e63e57
--- /dev/null
+++ b/sys/arch/pc532/stand/prf.c
@@ -0,0 +1,79 @@
+/* $NetBSD: prf.c,v 1.2 1994/10/26 08:25:50 cgd Exp $ */
+
+/*
+ * Copyright (c) 1982, 1986, 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)prf.c 8.1 (Berkeley) 6/10/93
+ */
+
+getchar()
+{
+ register int c;
+
+ while((c = cngetc()) == 0)
+ ;
+ if (c == '\r')
+ c = '\n';
+ else if (c == ('c'&037)) {
+ panic("^C");
+ /* NOTREACHED */
+ }
+ if (c != '\b' && c != '\177')
+ putchar(c);
+ return(c);
+}
+
+tgetchar()
+{
+ register int c;
+
+ if ((c = cngetc()) == 0)
+ return(0);
+
+ if (c == '\r')
+ c = '\n';
+ else if (c == ('c'&037)) {
+ panic("^C");
+ /* NOTREACHED */
+ }
+ if (c != '\b' && c != '\177')
+ putchar(c);
+ return(c);
+}
+
+putchar(c)
+ register int c;
+{
+ cnputc(c);
+ if (c == '\n')
+ cnputc('\r');
+}
diff --git a/sys/arch/pc532/stand/rd.c b/sys/arch/pc532/stand/rd.c
new file mode 100644
index 00000000000..4f3c3620a68
--- /dev/null
+++ b/sys/arch/pc532/stand/rd.c
@@ -0,0 +1,29 @@
+#include <sys/param.h>
+#include "stand.h"
+#include "samachdep.h"
+
+#ifndef RD_START
+#define RD_START 0x288000
+#endif
+
+rdopen(f, ctlr, unit, part)
+ struct open_file *f;
+ int ctlr, unit, part;
+{
+ f->f_devdata = (void *) RD_START;
+ return(0);
+}
+
+int
+rdstrategy(ss, func, dblk, size, buf, rsize)
+ void *ss;
+ int func;
+ daddr_t dblk; /* block number */
+ u_int size; /* request size in bytes */
+ void *buf;
+ u_int *rsize; /* out: bytes transferred */
+{
+ memcpy(buf, ss + (dblk << DEV_BSHIFT), size);
+ *rsize = size;
+ return(0);
+}
diff --git a/sys/arch/pc532/stand/samachdep.h b/sys/arch/pc532/stand/samachdep.h
new file mode 100644
index 00000000000..a48383f54d5
--- /dev/null
+++ b/sys/arch/pc532/stand/samachdep.h
@@ -0,0 +1,42 @@
+/* $NetBSD: samachdep.h,v 1.2 1994/10/26 08:25:51 cgd Exp $ */
+
+/*
+ * Copyright (c) 1982, 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)samachdep.h 8.1 (Berkeley) 6/10/93
+ */
+
+#define NSCSI 1
+#define NSD 8
+
+extern int howto;
+extern unsigned int bootdev;
diff --git a/sys/arch/pc532/stand/scn.c b/sys/arch/pc532/stand/scn.c
new file mode 100644
index 00000000000..b8637d16c38
--- /dev/null
+++ b/sys/arch/pc532/stand/scn.c
@@ -0,0 +1,103 @@
+/* $NetBSD: scn.c,v 1.3 1995/08/29 21:55:49 phil Exp $ */
+
+/*-
+ * Copyright (c) 1994 Philip L. Budne.
+ * 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 L. Budne.
+ * 4. The name of Philip L. Budne may not be used to endorse or promote
+ * products derived from this software without specific prior written
+ * permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY PHILIP BUDNE ``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 BUDNE 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.
+ */
+
+/*
+ * scn.c -- scn2681/2692/68881 standalone console driver
+ * Phil Budne, May 10, 1994
+ *
+ */
+
+#ifdef SCNCONSOLE
+#include <sys/types.h>
+#include <dev/cons.h>
+
+#define DUART 0x28000000
+
+/* registers */
+#define SCN_STAT 1
+#define SCN_DATA 3
+
+/* status bits */
+#define STAT_RXRDY 0x01
+#define STAT_TXRDY 0x04
+
+#ifndef SCNCNUNIT
+#define SCNCNUNIT 0
+#endif
+
+unsigned char * volatile scncnaddr = (unsigned char *) DUART + 8 * SCNCNUNIT;
+
+scnprobe(cp)
+ struct consdev *cp;
+{
+ /* the only game in town */
+ cp->cn_pri = CN_NORMAL; /* XXX remote? */
+}
+
+scninit(cp)
+ struct consdev *cp;
+{
+ /* leave things they way the PROM set them */
+}
+
+scngetchar(cp)
+ struct consdev *cp;
+{
+ register unsigned char * volatile scn = scncnaddr;
+
+ if ((scn[SCN_STAT] & STAT_RXRDY) == 0)
+ return(0);
+ return scn[SCN_DATA];
+}
+
+scnputchar(cp, c)
+ struct consdev *cp;
+ register int c;
+{
+ register unsigned char * volatile scn = scncnaddr;
+ register int timo;
+ short stat;
+
+ /* wait a reasonable time for the transmitter to come ready */
+ timo = 50000;
+ while (((stat = scn[SCN_STAT]) & STAT_TXRDY) == 0 && --timo)
+ ;
+ scn[SCN_DATA] = c;
+#if 0
+ /* wait for this transmission to complete */
+ timo = 1000000;
+ while (((stat = scn[SCN_STAT]) & STAT_TXRDY) == 0 && --timo)
+ ;
+#endif
+}
+#endif
diff --git a/sys/arch/pc532/stand/scsi_hi.c b/sys/arch/pc532/stand/scsi_hi.c
new file mode 100644
index 00000000000..866273596d5
--- /dev/null
+++ b/sys/arch/pc532/stand/scsi_hi.c
@@ -0,0 +1,303 @@
+/* $NetBSD: scsi_hi.c,v 1.3 1994/10/26 08:25:53 cgd Exp $ */
+
+/****************************************************************************
+ * NS32K Monitor SCSI high-level driver
+ * Bruce Culbertson
+ * 8 March 1990
+ * (This source is public domain source)
+ *
+ * There are three monitor SCSI commands. "Read" and "write" I think are
+ * fairly self explanatory once you read the help messages. They, in fact,
+ * execute the "extended read", "extended write", and "request sense"
+ * commands from the SCSI standard.
+ *
+ * "Raw" lets you execute any SCSI command but you need a SCSI reference to
+ * know what the commands are and what their formats are. The SCSI
+ * standard specifies that there are six buffers which, for example, hold a
+ * SCSI command or are the source or destination for data. You provide
+ * "raw" with an array of pointers to the six buffers. Using "edit", you
+ * can enter a SCSI command somewhere in memory and you can create the
+ * array of pointers. The array must actually be eight entries long; two
+ * entries are not used. By typing "raw <array address>", the SCSI command
+ * is executed.
+ *
+ * By the way, "read", "write", and "raw" talk only to the DP8490 SCSI
+ * controller. I have not had time to read the Adaptec data sheet and
+ * write a driver for it.
+ ****************************************************************************/
+#include "so.h"
+
+#define OK 0
+#define NOT_OK OK+1
+#define PRIVATE
+#define PUBLIC
+#define U8 unsigned char
+
+long scsiAdr = DEFAULT_SCSI_ADR, /* default SCSI address */
+ scsiLun = DEFAULT_SCSI_LUN;
+
+struct cmd_desc { /* SCSI command description */
+ const U8 *cmd; /* command string */
+ const U8 *odata; /* data to output, if any */
+ const struct cmd_desc *chain; /* next command */
+};
+
+struct drive { /* SCSI drive description */
+ U8 adr, lun; /* SCSI address and LUN */
+ U8 flags; /* drive characteristics */
+ U8 stat; /* drive state */
+ const struct cmd_desc *init; /* list of initialize commands */
+};
+/* for drive.flags */
+#define EXTENDED_RDWR 1 /* device does extended read, write */
+#define EXTENDED_SENSE 2 /* device does extended sense */
+/* for drive.stat */
+#define INITIALIZED 1 /* device is initialized */
+
+#ifdef OMTI
+/* These SCSI commands initialize a OMTI 5200 SCSI controller with a 360K
+ * floppy at LUN=1 and an ST-225 at LUN=0.
+ */
+const U8 floppy_parms_cmd[] = {0xc2, 0x20, 0, 0, 0, 0};
+const U8 floppy_parms_data[] = {0, 3, 0x27, 0xa, 0, 0, 0, 0x80, 1, 0};
+const U8 floppy_format_cmd[] = {0xc0, 0x20, 0, 0, 9, 0x8b};
+const U8 floppy_recal_cmd[] = {1, 0x20, 0, 0, 0, 0};
+const U8 wini_parms_cmd[] = {0xc2, 0, 0, 0, 0, 0};
+const U8 wini_parms_data[] = {0, 0, 0, 3, 2, 0x63, 0, 1, 0x10, 0};
+const U8 wini_recal_cmd[] = {1, 0, 0, 0, 0, 0};
+const struct cmd_desc floppy_init2 =
+ {floppy_recal_cmd, 0, 0};
+const struct cmd_desc floppy_init1 =
+ {floppy_format_cmd, 0, &floppy_init2};
+const struct cmd_desc floppy_init0 =
+ {floppy_parms_cmd, floppy_parms_data, &floppy_init1};
+const struct cmd_desc wini_init1 =
+ {wini_recal_cmd, 0, 0};
+const struct cmd_desc wini_init0 =
+ {wini_parms_cmd, wini_parms_data, &wini_init1};
+#endif
+
+PRIVATE struct drive drive_tbl[] = {
+#ifdef OMTI
+ {1, 0, 0, 0, &wini_init0},
+ {1, 1, 0, 0, &floppy_init0},
+#endif
+ {0, 0, EXTENDED_RDWR | EXTENDED_SENSE, 1, 0},
+};
+#define DRV_TBL_SZ (sizeof (drive_tbl) / sizeof (struct drive))
+
+/* Round up to multiple of four since SCSI transfers are always multiples
+ * of four bytes.
+ */
+#define CMD_LEN 12 /* longest SCSI command */
+#define SENSE_LEN 24 /* extended sense length */
+#define MSG_LEN 4
+#define STAT_LEN 4
+
+#define MAX_SCSI_RETRIES 6
+#define CMD_IX 2
+#define CMD_SENSE 0x03
+#define CMD_READ 0x08
+#define CMD_WRITE 0x0a
+#define CMD_XREAD 0x28
+#define CMD_XWRITE 0x2a
+PRIVATE U8 cmd_buf[CMD_LEN];
+
+#define SENSE_KEY 2
+#define NO_SENSE 0
+#define RECOVERY_ERR 1
+#define UNIT_ATTN 6
+#define ADD_SENSE_CODE 12
+#define SENSE_RST 0x29
+PRIVATE U8 sense_buf[SENSE_LEN];
+
+#define CHECK_CONDITION 2
+#define STAT_IX 3
+#define STAT_MASK 0x1f
+PRIVATE U8 stat_buf[STAT_LEN];
+#define IMSG_IX 7
+PRIVATE U8 msg_buf[MSG_LEN];
+
+#define ODATA_IX 0
+#define IDATA_IX 1
+PRIVATE struct scsi_args scsi_args;
+
+/*===========================================================================*
+ * sc_rdwt *
+ *===========================================================================*/
+/* Carry out a read or write request for the SCSI disk. */
+PRIVATE int
+sc_rdwt(op, block, ram_adr, len, sc_adr, lun)
+long block, ram_adr, len, sc_adr, lun;
+{
+ int retries, ret;
+ U8 *p;
+ struct drive *dp;
+
+ /* get drive characteristics */
+ for (dp = drive_tbl; dp < drive_tbl + DRV_TBL_SZ - 1; ++dp)
+ if (dp->adr == sc_adr && dp->lun == lun) break;
+ if (dp == drive_tbl + DRV_TBL_SZ - 1) {
+ dp->adr = sc_adr; /* have default, set adr, lun */
+ dp->lun = lun;
+ }
+ for (retries = 0; retries < MAX_SCSI_RETRIES; ++retries) {
+ if (dp->init && !(dp->stat & INITIALIZED))
+ if (OK != sc_initialize (dp)) {
+ printf("SCSI cannot initialize device\n");
+ return NOT_OK;
+ }
+ p = cmd_buf; /* build SCSI command */
+ if (dp->flags & EXTENDED_RDWR) { /* use extended commands */
+ *p++ = (op == DISK_READ)? CMD_XREAD: CMD_XWRITE;
+ *p++ = lun << 5;
+ *p++ = (block >> 24) & 0xff;
+ *p++ = (block >> 16) & 0xff;
+ *p++ = (block >> 8) & 0xff;
+ *p++ = (block >> 0) & 0xff;
+ *p++ = 0;
+ *p++ = (len >> 8) & 0xff;
+ *p++ = (len >> 0) & 0xff;
+ *p = 0;
+ } else { /* use short (SASI) commands */
+ *p++ = (op == DISK_READ)? CMD_READ: CMD_WRITE;
+ *p++ = (lun << 5) | ((block >> 16) & 0x1f);
+ *p++ = (block >> 8) & 0xff;
+ *p++ = (block >> 0) & 0xff;
+ *p++ = len;
+ *p = 0;
+ }
+ if (op == DISK_READ)
+ ret = exec_scsi_hi (cmd_buf, (U8 *)ram_adr, (U8 *)0, dp);
+ else
+ ret = exec_scsi_hi (cmd_buf, (U8 *)0, (U8 *)ram_adr, dp);
+ if (OK == ret) return OK;
+ dp->stat &= ~INITIALIZED;
+ }
+ printf("SCSI %s, block %d failed even after retries\n",
+ op == DISK_READ? "READ": "WRITE", block);
+ return NOT_OK;
+}
+
+/*===========================================================================*
+ * sc_initialize *
+ *===========================================================================*/
+/* Execute the list of initialization commands for the given drive.
+ */
+int
+sc_initialize (dp)
+struct drive *dp;
+{
+ const struct cmd_desc *cp;
+
+ for (cp = dp->init; cp != 0; cp = cp->chain)
+ if (OK != exec_scsi_hi (cp->cmd, 0, cp->odata, dp)) {
+ dp->stat &= ~INITIALIZED;
+ return NOT_OK;
+ }
+ dp->stat |= INITIALIZED;
+ return OK;
+}
+
+/*===========================================================================*
+ * exec_scsi_hi *
+ *===========================================================================*/
+/* Execute a "high-level" SCSI command. This means execute a low level
+ * command and, if it fails, execute a request sense to find out why.
+ */
+PRIVATE int
+exec_scsi_hi(cmd, data_in, data_out, dp)
+U8 *cmd, *data_out, *data_in;
+struct drive *dp;
+{
+ scsi_args.ptr[CMD_IX] = (long)cmd;
+ scsi_args.ptr[STAT_IX] = (long)stat_buf;
+ scsi_args.ptr[IMSG_IX] = (long)msg_buf;
+ scsi_args.ptr[IDATA_IX] = (long)data_in;
+ scsi_args.ptr[ODATA_IX] = (long)data_out;
+ if (OK != exec_scsi_low (&scsi_args, dp->adr))
+ return NOT_OK;
+ *stat_buf &= STAT_MASK; /* strip off lun */
+ if (*stat_buf == 0)
+ /* Success -- this should be the usual case */
+ return OK;
+ if (*stat_buf != CHECK_CONDITION) {
+ /* do not know how to handle this so return error */
+ printf("SCSI device returned unknown status: %d\n", *stat_buf);
+ return NOT_OK;
+ }
+ /* Something funny happened, need to execute request-sense command
+ * to learn more.
+ */
+ if (OK == get_sense(dp))
+ /* Something funny happened, but the device recovered from it and
+ * the command succeeded.
+ */
+ return OK;
+ return NOT_OK;
+}
+
+/*===========================================================================*
+ * get_sense *
+ *===========================================================================*/
+/* Execute a "request sense" SCSI command and check results. When a SCSI
+ * command returns CHECK_CONDITION, a request-sense command must be executed.
+ * A request-sense command provides information about the original command.
+ * The original command might have succeeded, in which case it does not
+ * need to be retried and OK is returned. Examples: read error corrected
+ * with error correction code, or error corrected by retries performed by
+ * the SCSI device. The original command also could have failed, in
+ * which case NOT_OK is returned.
+ */
+#define XLOGICAL_ADR \
+ (sense_buf[3]<<24 | sense_buf[4]<<16 | sense_buf[5]<<8 | sense_buf[6])
+#define LOGICAL_ADR \
+ (sense_buf[1]<<16 | sense_buf[2]<<8 | sense_buf[3])
+
+PRIVATE int
+get_sense (dp)
+struct drive *dp;
+{
+ U8 *p;
+
+ p = cmd_buf; /* build SCSI command */
+ *p++ = CMD_SENSE;
+ *p++ = dp->lun << 5;
+ *p++ = 0;
+ *p++ = 0;
+ *p++ = (dp->flags & EXTENDED_SENSE)? SENSE_LEN: 0;
+ *p = 0;
+ scsi_args.ptr[IDATA_IX] = (long)sense_buf;
+ scsi_args.ptr[ODATA_IX] = 0;
+ scsi_args.ptr[CMD_IX] = (long)cmd_buf;
+ scsi_args.ptr[STAT_IX] = (long)stat_buf;
+ scsi_args.ptr[IMSG_IX] = (long)msg_buf;
+ if (OK != exec_scsi_low (&scsi_args, dp->adr)) {
+ printf("SCSI SENSE command failed\n");
+ return NOT_OK;
+ }
+ if ((*stat_buf & STAT_MASK) != 0) {
+ printf("SCSI SENSE returned wrong status %d\n", *stat_buf);
+ return NOT_OK;
+ }
+ if (0 == (dp->flags & EXTENDED_SENSE)) {
+ printf("SCSI request sense, code 0x%x, log_adr 0x%x\n",
+ sense_buf[0], LOGICAL_ADR);
+ return NOT_OK;
+ }
+ switch (sense_buf[SENSE_KEY] & 0xf) {
+ case NO_SENSE:
+ case UNIT_ATTN: /* reset */
+ return NOT_OK; /* must retry command */
+ case RECOVERY_ERR:
+ /* eventually, we probably do not want to hear about these. */
+ printf("SCSI ok with recovery, code 0x%x, logical address 0x%x\n",
+ sense_buf[ADD_SENSE_CODE], XLOGICAL_ADR);
+ return OK; /* orig command was ok with recovery */
+ default:
+ printf("SCSI failure: key 0x%x code 0x%x log adr 0x%x sense buf 0x%x\n",
+ sense_buf[SENSE_KEY], sense_buf[ADD_SENSE_CODE],
+ XLOGICAL_ADR, sense_buf);
+ return NOT_OK; /* orig command failed */
+ }
+}
diff --git a/sys/arch/pc532/stand/scsi_low.c b/sys/arch/pc532/stand/scsi_low.c
new file mode 100644
index 00000000000..6fd2bc643f8
--- /dev/null
+++ b/sys/arch/pc532/stand/scsi_low.c
@@ -0,0 +1,426 @@
+/* $NetBSD: scsi_low.c,v 1.4 1994/12/09 21:04:42 phil Exp $ */
+
+/****************************************************************************
+ * NS32K Monitor SCSI low-level driver
+ * Bruce Culbertson
+ * 8 March 1990
+ * (This source is public domain source.)
+ *
+ * Originally written by Bruce Culbertson for a ns32016 port of Minix.
+ * Adapted from that for the pc532 (ns32632) monitor.
+ * Adapted from that for NetBSD/pc532 by Philip L. Bunde.
+ *
+ * Do not use DMA -- makes 32016 and pc532 versions compatible.
+ * Do not use interrupts -- makes it harder for the user code to bomb
+ * this code.
+ ****************************************************************************/
+
+#include "so.h"
+
+#define OK 0
+#define NOT_OK OK+1
+#define PRIVATE
+#define PUBLIC
+#define WR_ADR(adr,val) (*((volatile unsigned char *)(adr))=(val))
+#define RD_ADR(adr) (*((volatile unsigned char *)(adr)))
+#define AIC6250 0
+#define DP8490 1
+#define MAX_CACHE 0x10000
+
+/* SCSI bus phases
+ */
+#define PH_ODATA 0
+#define PH_IDATA 1
+#define PH_CMD 2
+#define PH_STAT 3
+#define PH_IMSG 7
+#define PH_NONE 8
+#define PH_IN(phase) ((phase) & 1)
+
+/* NCR5380 SCSI controller registers
+ */
+#define SC_CTL 0x30000000 /* base for control registers */
+#define SC_DMA 0x38000000 /* base for data registers */
+#define SC_CURDATA SC_CTL+0
+#define SC_OUTDATA SC_CTL+0
+#define SC_ICMD SC_CTL+1
+#define SC_MODE SC_CTL+2
+#define SC_TCMD SC_CTL+3
+#define SC_STAT1 SC_CTL+4
+#define SC_STAT2 SC_CTL+5
+#define SC_START_SEND SC_CTL+5
+#define SC_INDATA SC_CTL+6
+#define SC_RESETIP SC_CTL+7
+#define SC_START_RCV SC_CTL+7
+
+/* Bits in NCR5380 registers
+ */
+#define SC_A_RST 0x80
+#define SC_A_SEL 0x04
+#define SC_S_SEL 0x02
+#define SC_S_REQ 0x20
+#define SC_S_BSY 0x40
+#define SC_S_BSYERR 0x04
+#define SC_S_PHASE 0x08
+#define SC_S_IRQ 0x10
+#define SC_S_DRQ 0x40
+#define SC_M_DMA 0x02
+#define SC_M_BSY 0x04
+#define SC_ENABLE_DB 0x01
+
+/* Status of interrupt routine, returned in m1_i1 field of message.
+ */
+#define ISR_NOTDONE 0
+#define ISR_OK 1
+#define ISR_BSYERR 2
+#define ISR_RSTERR 3
+#define ISR_BADPHASE 4
+#define ISR_TIMEOUT 5
+
+#define ICU_ADR 0xfffffe00
+#define ICU_IO (ICU_ADR+20)
+#define ICU_DIR (ICU_ADR+21)
+#define ICU_DATA (ICU_ADR+19)
+#define ICU_SCSI_BIT 0x80
+
+/* Miscellaneous
+ */
+#define MAX_WAIT 2000000
+#define SC_LOG_LEN 32
+
+PRIVATE struct scsi_args *sc_ptrs;
+PRIVATE char sc_cur_phase,
+ sc_reset_done = 1,
+ sc_have_msg,
+ sc_accept_int,
+ sc_dma_dir;
+
+long sc_dma_port = SC_DMA,
+ sc_dma_adr;
+
+#ifdef DEBUG
+struct sc_log {
+ unsigned char stat1, stat2;
+} sc_log [SC_LOG_LEN],
+ *sc_log_head = sc_log;
+int sc_spurious_int;
+#endif
+unsigned char
+ sc_watchdog_error; /* watch dog error */
+
+/* error messages */
+char *scsi_errors[] = {
+ 0, /* ISR_NOTDONE */
+ 0, /* ISR_OK */
+ "busy error", /* ISR_BSYERR */
+ "reset error", /* ISR_RSTERR */
+ "NULL pointer for current phase", /* ISR_BADPHASE */
+ "timeout", /* ISR_TIMEOUT */
+};
+
+/*===========================================================================*
+ * exec_scsi_low *
+ *===========================================================================*/
+/* Execute a generic SCSI command. Passed pointers to eight buffers:
+ * data-out, data-in, command, status, dummy, dummy, message-out, message-in.
+ */
+PUBLIC
+int
+exec_scsi_low (args, scsi_adr)
+struct scsi_args *args;
+long scsi_adr;
+{
+ int ret;
+
+ sc_ptrs = args; /* make pointers globally accessible */
+ scCtlrSelect (DP8490);
+ if (!sc_reset_done) sc_reset();
+ /* TCMD has some undocumented behavior in initiator mode. I think the
+ * data bus cannot be enabled if i/o is asserted.
+ */
+ WR_ADR (SC_TCMD, 0);
+ if (OK != sc_wait_bus_free ()) { /* bus-free phase */
+ printf("SCSI: bus not free\n");
+ return NOT_OK;
+ }
+ sc_cur_phase = PH_NONE;
+ sc_have_msg = 0;
+ if (OK != sc_select (scsi_adr)) /* select phase */
+ return NOT_OK;
+ sc_watchdog_error = 0;
+ ret = sc_receive (); /* isr does the rest */
+ if (ret == ISR_OK) return OK;
+ else {
+ sc_reset();
+ printf("SCSI: %s\n", scsi_errors[ret]);
+ return NOT_OK;
+ }
+}
+
+/*===========================================================================*
+ * sc_reset *
+ *===========================================================================*/
+/*
+ * Reset SCSI bus.
+ */
+PRIVATE
+sc_reset()
+{
+ volatile int i;
+
+ WR_ADR (SC_MODE, 0); /* get into harmless state */
+ WR_ADR (SC_OUTDATA, 0);
+ WR_ADR (SC_ICMD, SC_A_RST); /* assert RST on SCSI bus */
+ i = 200; /* wait 25 usec */
+ while (i--);
+ WR_ADR (SC_ICMD, 0); /* deassert RST, get off bus */
+ sc_reset_done = 1;
+}
+
+/*===========================================================================*
+ * sc_wait_bus_free *
+ *===========================================================================*/
+PRIVATE int
+sc_wait_bus_free()
+{
+ int i = MAX_WAIT;
+ volatile int j;
+
+ while (i--) {
+ /* Must be clear for 2 usec, so read twice */
+ if (RD_ADR (SC_STAT1) & (SC_S_BSY | SC_S_SEL)) continue;
+ for (j = 0; j < 25; ++j);
+ if (RD_ADR (SC_STAT1) & (SC_S_BSY | SC_S_SEL)) continue;
+ return OK;
+ }
+ sc_reset_done = 0;
+ return NOT_OK;
+}
+
+/*===========================================================================*
+ * sc_select *
+ *===========================================================================*/
+/* This duplicates much of the work that the interrupt routine would do on a
+ * phase mismatch and, in fact, the original plan was to just do the select,
+ * let a phase mismatch occur, and let the interrupt routine do the rest.
+ * That didn't work because the 5380 did not reliably generate the phase
+ * mismatch interrupt after selection.
+ */
+PRIVATE int
+sc_select(adr)
+long adr;
+{
+ int i, stat1;
+ long new_ptr;
+
+ WR_ADR (SC_OUTDATA, adr); /* SCSI bus address */
+ WR_ADR (SC_ICMD, SC_A_SEL | SC_ENABLE_DB);
+ for (i = 0;; ++i) { /* wait for target to assert SEL */
+ stat1 = RD_ADR (SC_STAT1);
+ if (stat1 & SC_S_BSY) break; /* select successful */
+ if (i > MAX_WAIT) { /* timeout */
+ printf("SCSI: SELECT timeout\n");
+ sc_reset();
+ return NOT_OK;
+ }
+ }
+ WR_ADR (SC_ICMD, 0); /* clear SEL, disable data out */
+ WR_ADR (SC_OUTDATA, 0);
+ for (i = 0;; ++i) { /* wait for target to assert REQ */
+ if (stat1 & SC_S_REQ) break; /* target requesting transfer */
+ if (i > MAX_WAIT) { /* timeout */
+ printf("SCSI: REQ timeout\n");
+ sc_reset();
+ return NOT_OK;
+ }
+ stat1 = RD_ADR (SC_STAT1);
+ }
+ sc_cur_phase = (stat1 >> 2) & 7; /* get new phase from controller */
+ if (sc_cur_phase != PH_CMD) {
+ printf("SCSI: bad phase = %d\n", sc_cur_phase);
+ sc_reset();
+ return NOT_OK;
+ }
+ new_ptr = sc_ptrs->ptr[PH_CMD];
+ if (new_ptr == 0) {
+ printf("SCSI: NULL command pointer\n");
+ sc_reset();
+ return NOT_OK;
+ }
+ sc_accept_int = 1;
+ sc_dma_setup (DISK_WRITE, new_ptr);
+ WR_ADR (SC_TCMD, PH_CMD);
+ WR_ADR (SC_ICMD, SC_ENABLE_DB);
+ WR_ADR (SC_MODE, SC_M_BSY | SC_M_DMA);
+ WR_ADR (SC_START_SEND, 0);
+ return OK;
+}
+
+/*===========================================================================*
+ * scsi_interrupt *
+ *===========================================================================*/
+/* SCSI interrupt handler.
+ */
+PUBLIC
+int
+scsi_interrupt()
+{
+ unsigned char stat2, dummy;
+ long new_ptr;
+ int ret = ISR_NOTDONE;
+
+ stat2 = RD_ADR (SC_STAT2); /* get status before clearing request */
+
+# ifdef DEBUG /* debugging log of interrupts */
+ sc_log_head->stat1 = RD_ADR (SC_STAT1);
+ sc_log_head->stat2 = stat2;
+ if (++sc_log_head >= sc_log + SC_LOG_LEN) sc_log_head = sc_log;
+ sc_log_head->stat1 = sc_log_head->stat2 = 0xff;
+# endif
+
+ for (;;) {
+ dummy = RD_ADR (SC_RESETIP); /* clear interrupt request */
+ if (!sc_accept_int || /* return if spurious interrupt */
+ (!sc_watchdog_error &&
+ (stat2 & SC_S_BSYERR) == 0 && (stat2 & SC_S_PHASE) == 1))
+ {
+# ifdef DEBUG
+ ++sc_spurious_int;
+# endif
+ return ret;
+ }
+ RD_ADR (SC_MODE) &= ~SC_M_DMA; /* clear DMA mode */
+ WR_ADR (SC_ICMD, 0); /* disable data bus */
+ if (sc_cur_phase != PH_NONE) { /* if did DMA, save the new pointer */
+ new_ptr = sc_dma_adr; /* fetch new pointer from DMA cntlr */
+ if (sc_cur_phase == PH_IMSG && /* have message? */
+ new_ptr != sc_ptrs->ptr[PH_IMSG]) sc_have_msg = 1;
+ sc_ptrs->ptr[sc_cur_phase] = /* save pointer */
+ new_ptr;
+ }
+ if (sc_watchdog_error) ret = ISR_TIMEOUT;
+ else if (stat2 & SC_S_BSYERR) { /* target deasserted BSY? */
+ if (sc_have_msg) ret = ISR_OK;
+ else ret = ISR_BSYERR;
+ } else if (!(stat2 & SC_S_PHASE)) { /* if phase mismatch, setup new phase */
+ sc_cur_phase = /* get new phase from controller */
+ (RD_ADR (SC_STAT1) >> 2) & 7;
+ new_ptr = sc_ptrs->ptr[sc_cur_phase];
+ if (new_ptr == 0) ret = ISR_BADPHASE;
+ else {
+ WR_ADR (SC_TCMD, sc_cur_phase); /* write new phase into TCMD */
+ if (PH_IN (sc_cur_phase)) { /* set DMA controller */
+ sc_dma_setup (DISK_READ, new_ptr);
+ RD_ADR (SC_MODE) |= SC_M_DMA;
+ WR_ADR (SC_START_RCV, 0); /* tell SCSI to start DMA */
+ } else {
+ sc_dma_setup (DISK_WRITE, new_ptr);
+ RD_ADR (SC_MODE) |= SC_M_DMA;
+ WR_ADR (SC_ICMD, SC_ENABLE_DB);
+ WR_ADR (SC_START_SEND, 0);
+ }
+ }
+ } else ret = ISR_RSTERR;
+ if (ret != ISR_NOTDONE) { /* if done, send message to task */
+ sc_watchdog_error = 0;
+ sc_accept_int = 0;
+ WR_ADR (SC_MODE, 0); /* clear monbsy, dma */
+ break; /* reti re-enables ints */
+ }
+ if (0 == ((stat2 = /* check for another interrupt */
+ RD_ADR (SC_STAT2)) & SC_S_IRQ))
+ {
+ break;
+ }
+ }
+ return ret;
+}
+
+/*===========================================================================*
+ * sc_dma_setup *
+ *===========================================================================*/
+/* Fake DMA setup. Just store pointers and direction in global variables.
+ *
+ * The pseudo-DMA is subtler than it looks because of the cache.
+ *
+ * 1) When accessing I/O devices through a cache, some mechanism is
+ * necessary to ensure you access the device rather than the cache.
+ * On the 32532, the IODEC signal is supposed to be asserted for I/O
+ * addresses to accomplish this. However, a bug makes this much
+ * slower than necessary and severely hurts pseudo-DMA performance.
+ * Hence, IODEC is not asserted for the SCSI DMA port.
+ *
+ * 2) Because of (1), we must devise our own method of forcing the
+ * SCSI DMA port to be read. 0x8000000 addresses have been decoded
+ * to all access this port. By always using new addresses to access
+ * the DMA port (wrapping only after reading MAX_CACHE bytes), we
+ * force cache misses and, hence, device reads. Since the cache
+ * is write-through, we do not need to worry about writes.
+ *
+ * 3) It is possible to miss the last few bytes of a transfer if
+ * bus transfer size is not considered. The loop in sc_receive()
+ * transfers data until the interrupt signal is asserted. If
+ * bytes are transferred, the attempt to move the first byte of a
+ * double word causes the whole word to be read into the cache.
+ * Then the byte is transferred. If reading the double word
+ * completed the SCSI transfer, then the loop exits since
+ * interrupt is asserted. However, the last few bytes have only
+ * been moved into the cache -- they have not been moved to the
+ * DMA destination.
+ *
+ * 4) It is also possible to miss the first few bytes of a transfer.
+ * If the address used to access pseudo-dma port is not double word
+ * aligned, the whole double word is read into the cache, and then
+ * data is moved from the middle of the word (i.e. something other
+ * than the first bytes read from the SCSI controller) by the
+ * pseudo-dma loop in sc_receive().
+ */
+sc_dma_setup (dir, adr)
+int dir;
+long adr;
+{
+ if (sc_dma_port > SC_DMA + MAX_CACHE) sc_dma_port = SC_DMA;
+ sc_dma_dir = dir;
+ sc_dma_adr = adr;
+}
+
+/*===========================================================================*
+ * sc_receive *
+ *===========================================================================*/
+/* Replacement for Minix receive(), which waits for a message. This code
+ * spins, waiting for data to transfer or interrupt requests to handle.
+ * See sc_dma_setup for details.
+ */
+int
+sc_receive()
+{
+ int stat2, isr_ret;
+
+ for (;;) {
+ stat2 = RD_ADR (SC_STAT2);
+ if (stat2 & SC_S_IRQ) {
+ if (ISR_NOTDONE != (isr_ret = scsi_interrupt())) break;
+ } else if (stat2 & SC_S_DRQ) { /* test really not necessary on pc532 */
+ if (sc_dma_dir == DISK_READ)
+ *((long *)sc_dma_adr)++ = *((volatile long *)sc_dma_port)++;
+ else *((volatile long *)sc_dma_port)++ = *((long *)sc_dma_adr)++;
+ }
+ }
+ return isr_ret;
+}
+
+/*===========================================================================*
+ * scCtlrSelect
+ *===========================================================================*/
+/* Select a SCSI device.
+ */
+scCtlrSelect (ctlr)
+int ctlr;
+{
+ RD_ADR (ICU_IO) &= ~ICU_SCSI_BIT; /* i/o, not port */
+ RD_ADR (ICU_DIR) &= ~ICU_SCSI_BIT; /* output */
+ if (ctlr == DP8490)
+ RD_ADR (ICU_DATA) &= ~ICU_SCSI_BIT; /* select = 0 for 8490 */
+ else
+ RD_ADR (ICU_DATA) |= ICU_SCSI_BIT; /* select = 1 for AIC6250 */
+}
diff --git a/sys/arch/pc532/stand/sd.c b/sys/arch/pc532/stand/sd.c
new file mode 100644
index 00000000000..ff6ea431607
--- /dev/null
+++ b/sys/arch/pc532/stand/sd.c
@@ -0,0 +1,196 @@
+/* $NetBSD: sd.c,v 1.4 1995/08/29 21:55:50 phil Exp $ */
+
+/*
+ * Copyright (c) 1988 University of Utah.
+ * Copyright (c) 1990, 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 the Systems
+ * Programming Group of the University of Utah Computer Science Department.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * from: Utah $Hdr: sd.c 1.9 92/12/21$
+ *
+ * @(#)sd.c 8.1 (Berkeley) 6/10/93
+ */
+
+/*
+ * SCSI CCS disk driver
+ */
+
+#include <sys/param.h>
+#include <sys/disklabel.h>
+#include "stand.h"
+#include "samachdep.h"
+
+struct sd_softc {
+ int sc_ctlr;
+ int sc_unit;
+ int sc_part;
+ char sc_retry;
+ char sc_alive;
+ struct disklabel sc_label;
+} sd_softc[NSCSI][NSD];
+
+#ifdef SD_DEBUG
+int debug = SD_DEBUG;
+#endif
+
+#define SDRETRY 2
+
+sdinit(ctlr, unit)
+ int ctlr, unit;
+{
+ register struct sd_softc *ss = &sd_softc[ctlr][unit];
+
+ /* HP version does test_unit_ready
+ * followed by read_capacity to get blocksize
+ */
+ ss->sc_alive = 1;
+ return (1);
+}
+
+sdreset(ctlr, unit)
+ int ctlr, unit;
+{
+}
+
+char io_buf[MAXBSIZE];
+
+sdgetinfo(ss)
+ register struct sd_softc *ss;
+{
+ register struct disklabel *lp;
+ char *msg, *getdisklabel();
+ int sdstrategy(), i, err;
+
+ lp = &sd_softc[ss->sc_ctlr][ss->sc_unit].sc_label;
+ bzero((caddr_t)lp, sizeof *lp);
+ lp->d_secsize = DEV_BSIZE;
+ lp->d_secpercyl = 1;
+ lp->d_npartitions = MAXPARTITIONS;
+ lp->d_partitions[ss->sc_part].p_offset = 0;
+ lp->d_partitions[ss->sc_part].p_size = 0x7fffffff;
+
+ if (err = sdstrategy(ss, F_READ,
+ LABELSECTOR, DEV_BSIZE, io_buf, &i) < 0) {
+ printf("sdgetinfo: sdstrategy error %d\n", err);
+ return 0;
+ }
+
+ msg = getdisklabel(io_buf, lp);
+ if (msg) {
+ printf("sd(%d,%d,%d): %s\n",
+ ss->sc_ctlr, ss->sc_unit, ss->sc_part, msg);
+ return 0;
+ }
+ return(1);
+}
+
+sdopen(f, ctlr, unit, part)
+ struct open_file *f;
+ int ctlr, unit, part;
+{
+ register struct sd_softc *ss;
+ register struct disklabel *lp;
+
+#ifdef SD_DEBUG
+ if (debug)
+ printf("sdopen: ctlr=%d unit=%d part=%d\n",
+ ctlr, unit, part);
+#endif
+
+ if (ctlr >= NSCSI || !scsialive(ctlr))
+ return (EADAPT);
+ if (unit >= NSD)
+ return (ECTLR);
+ ss = &sd_softc[ctlr][unit]; /* XXX alloc()? keep pointers? */
+ ss->sc_part = part;
+ ss->sc_unit = unit;
+ ss->sc_ctlr = ctlr;
+ if (!ss->sc_alive) {
+ if (!sdinit(ctlr, unit))
+ return (ENXIO);
+ if (!sdgetinfo(ss))
+ return (ERDLAB);
+ }
+ lp = &sd_softc[ctlr][unit].sc_label;
+ if (part >= lp->d_npartitions || lp->d_partitions[part].p_size == 0)
+ return (EPART);
+
+ f->f_devdata = (void *)ss;
+ return (0);
+}
+
+int
+sdstrategy(ss, func, dblk, size, buf, rsize)
+ register struct sd_softc *ss;
+ int func;
+ daddr_t dblk; /* block number */
+ u_int size; /* request size in bytes */
+ char *buf;
+ u_int *rsize; /* out: bytes transferred */
+{
+ register int ctlr = ss->sc_ctlr;
+ register int unit = ss->sc_unit;
+ register int part = ss->sc_part;
+ register struct partition *pp = &ss->sc_label.d_partitions[part];
+ u_int nblk = size >> DEV_BSHIFT;
+ u_int blk = dblk + pp->p_offset;
+ char stat;
+
+ if (size == 0)
+ return(0);
+
+ ss->sc_retry = 0;
+
+#ifdef SD_DEBUG
+ if (debug)
+ printf("sdstrategy(%d,%d): size=%d blk=%d nblk=%d\n",
+ ctlr, unit, size, blk, nblk);
+#endif
+
+retry:
+ if (func == F_READ)
+ stat = scsi_tt_read(ctlr, unit, buf, size, blk, nblk);
+ else
+ stat = scsi_tt_write(ctlr, unit, buf, size, blk, nblk);
+ if (stat) {
+ printf("sd(%d,%d,%d): block=%x, error=0x%x\n",
+ ctlr, unit, ss->sc_part, blk, stat);
+ if (++ss->sc_retry > SDRETRY)
+ return(EIO);
+ goto retry;
+ }
+ *rsize = size;
+
+ return(0);
+}
diff --git a/sys/arch/pc532/stand/so.h b/sys/arch/pc532/stand/so.h
new file mode 100644
index 00000000000..63c85ef9d5a
--- /dev/null
+++ b/sys/arch/pc532/stand/so.h
@@ -0,0 +1,67 @@
+/* $NetBSD: so.h,v 1.2 1994/10/26 08:25:57 cgd Exp $ */
+
+#ifndef _SO_H_INCLUDE
+#define _SO_H_INCLUDE
+
+/* Definitions for standalone I/O lib */
+
+#define DUART0 0x28000000
+#define DUART1 0x28000020
+#define DUART2 0x28000040
+#define DUART3 0x28000060
+#define PARRDU 0x28000080
+#define PARCLU 0x280000A0
+#define SCSI_POLLED 0x30000000
+#define SCSI_DMA 0x38000000
+#define ICU_ADDR 0xFFFFFE00
+
+/* Which UART to use by default */
+#define DEFAULT_UART 0
+
+/* Which SCSI device to use by default */
+#define DEFAULT_SCSI_ADR 1
+#define DEFAULT_SCSI_LUN 0
+
+/* Low level scsi operation codes */
+#define DISK_READ 3
+#define DISK_WRITE 4
+
+/* The size of a disk block */
+#define DBLKSIZE 512
+
+/* Some disk address that will never be used */
+#define INSANE_BADDR 0x800000
+
+struct scsi_args {
+ long ptr [8];
+};
+
+#ifndef NULL
+#define NULL 0L
+#endif
+
+/*
+ * The next macro defines where the "break" area in memory ends for
+ * malloc() and friends. The area between edata and this address will
+ * then be reserved and should not be used for anything else (or you will
+ * no doubt have big problems). Depending on where your program's end-of-data
+ * is, you may wish to locate this in such a way as to usurp a minimum
+ * amount of memory.
+ */
+#define BREAK_END_ADDR ((char *)0x400000) /* to 4MB */
+
+/* Selectivly enable inline functions */
+#ifndef NO_INLINE
+#define Inline inline
+#else
+#define Inline
+#endif
+
+extern void fatal(), warn();
+extern long ulimit(int, long);
+extern int brk(char *);
+extern char *sbrk(int);
+
+extern int sc_rdwt();
+
+#endif /* _SO_H_INCLUDE */
diff --git a/sys/arch/pc532/stand/srt0.s b/sys/arch/pc532/stand/srt0.s
new file mode 100644
index 00000000000..fe7eaa8c127
--- /dev/null
+++ b/sys/arch/pc532/stand/srt0.s
@@ -0,0 +1,91 @@
+/* $NetBSD: srt0.s,v 1.3 1995/08/29 21:55:51 phil Exp $ */
+
+/*-
+ * Copyright (c) 1994 Philip L. Budne.
+ * 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 L. Budne.
+ * 4. The name of Philip L. Budne 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.
+ */
+
+/*
+ * srt0.s -- standalone C startup
+ * Phil Budne, May 10, 1994
+ *
+ * from: pc532 kernel locore.s
+ * Phil Nelson, Dec 6, 1992
+ *
+ */
+
+#define PSR_S 0x200
+#define PSR_I 0x800
+
+.data
+.globl _howto, _bootdev, _r3, _r6, _r7
+__save_sp: .long 0
+__save_fp: .long 0
+_bootdev: .long 0
+_howto: .long 0
+_r3: .long 0
+_r6: .long 0
+_r7: .long 0
+
+.text
+.globl begin
+begin:
+ bicpsrw PSR_I /* make sure interrupts are off. */
+ bicpsrw PSR_S /* make sure we are using sp0. */
+
+ /* In case we are zboot: */
+ movd r3,_r3(pc) /* magic */
+ movd r6,_r6(pc) /* devtype */
+ movd r7,_r7(pc) /* howto */
+
+ lprd sb, 0 /* gcc expects this. */
+ sprd sp, __save_sp(pc) /* save monitor's sp. */
+ sprd fp, __save_fp(pc) /* save monitor's fp. */
+/* sprd intbase, __old_intbase(pc) /* save monitor's intbase. */
+ movqd 0, _howto(pc)
+
+restart:
+ /* Zero the bss segment. */
+ addr _end(pc),r0 # setup to zero the bss segment.
+ addr _edata(pc),r1
+ subd r1,r0 # compute _end - _edata
+ movd r0,tos # push length
+ addr _edata(pc),tos # push address
+
+ movqd 0,_bootdev(pc) # XXX trash bootdev
+ bsr _bzero # zero the bss segment
+ bsr _main
+ /* fall */
+
+.globl __rtt
+__rtt: lprd sp, __save_sp(pc) /* restore monitor's sp. */
+ lprd fp, __save_fp(pc) /* restore monitor's fp. */
+/* XXX just return to monitor??? */
+ movqd 3, _howto /* RB_SINGLE|RB_ASKNAME */
+ br restart
diff --git a/sys/arch/pc532/stand/test.c b/sys/arch/pc532/stand/test.c
new file mode 100644
index 00000000000..9d41480cb19
--- /dev/null
+++ b/sys/arch/pc532/stand/test.c
@@ -0,0 +1,191 @@
+/* $NetBSD: test.c,v 1.2 1994/10/26 08:25:59 cgd Exp $ */
+
+/*-
+ * Copyright (c) 1994 Philip L. Budne.
+ * 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 L. Budne.
+ * 4. The name of Philip L. Budne may not be used to endorse or promote
+ * products derived from this software without specific prior written
+ * permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY PHILIP BUDNE ``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 BUDNE 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.
+ */
+
+/*-
+ * Allow test of "boot" (and presumably other "stand" utils)
+ * under user mode.
+ *
+ * Phil Budne <phil@ultimate.com> May 10, 1994
+ */
+
+/* my /sys/sys/syscall.h is out of sync w.r.t. lseek?? */
+#include "/usr/include/sys/syscall.h"
+#include <sys/types.h>
+
+extern int errno;
+
+int testing = 1;
+int bootdev;
+int howto;
+
+_open( char *fname, int mode )
+{
+ return syscall( SYS_open, fname, mode );
+}
+
+_read( int fd, char *buf, int len )
+{
+ return syscall( SYS_read, fd, buf, len );
+}
+
+_write( int fd, char *buf, int len )
+{
+ return syscall( SYS_write, fd, buf, len );
+}
+
+/*
+ * I'd like to strangle the jerk who thought it
+ * was a cool idea to change lseek, rather than creating
+ * a new "qseek" to handle long long offsets
+ */
+_lseek( int fd, off_t pos, int whence )
+{
+ return syscall( SYS_lseek, fd, 0, pos, whence );
+}
+
+int fd = -1;
+
+opendisk(int unit)
+{
+ char fname[32];
+ static int _unit = -1;
+
+ if (unit == _unit)
+ return;
+
+ if (fd >= 0) {
+ close(fd);
+ fd = -1;
+ }
+ _unit = unit;
+
+#if 0
+ sprintf( fname, "/dev/r%s%dc", "sd", unit );
+#else
+ strcpy( fname, "/dev/rsd0c" );
+#endif
+ fd = _open( fname, 0 );
+ if (fd < 0) {
+ printf("open %s failed\n", fname );
+ return;
+ }
+ printf("opened %s (fd %d)\n", fname, fd );
+}
+
+void
+bzero( char *addr, int len )
+{
+ while (len-- > 0)
+ *addr++ = '\0';
+}
+
+/* XXX TEMP; would like to use code more like hp300 scsi.c */
+
+void
+scsiinit(void)
+{
+}
+
+int
+scsialive(int ctlr)
+{
+ return 1; /* controller always alive! */
+}
+
+#define BPS 512
+scsi_tt_read(ctlr, slave, buf, len, blk, nblk)
+ char *buf;
+{
+ int pos;
+#if 0
+printf("scsi_tt_read(ctlr %d, slave %d, buf 0x%x, len %d, blk %d, nblk %d)\n",
+ ctlr, slave, buf, len, blk, nblk);
+#endif
+
+ opendisk(slave);
+
+ pos = _lseek( fd, blk * BPS, 0 );
+ if (pos != blk * BPS) {
+ printf("lseek pos %d error %d\n", pos, errno );
+ return errno;
+ }
+ if (_read( fd, buf, nblk * BPS ) != nblk * BPS) {
+ printf("read errno %d\n", errno );
+ return errno;
+ }
+ return 0;
+}
+
+scsi_tt_write()
+{
+ return -1;
+}
+
+#include <sys/types.h>
+#include <dev/cons.h>
+
+scnprobe(cp)
+ struct consdev *cp;
+{
+ /* the only game in town */
+ cp->cn_pri = CN_NORMAL; /* XXX remote? */
+}
+
+scninit(cp)
+ struct consdev *cp;
+{
+}
+
+scnputchar(c)
+ int c;
+{
+ char c2;
+ c2 = c;
+ _write(0, &c2, 1);
+}
+
+scngetchar()
+{
+ char c;
+ _read(0, &c, 1);
+ return c;
+}
+
+_rtt() {
+ syscall( SYS_exit, 1 );
+}
+
+alloc(int size)
+{
+ return malloc(size);
+}
diff --git a/sys/arch/pc532/stand/tgets.c b/sys/arch/pc532/stand/tgets.c
new file mode 100644
index 00000000000..232affa930a
--- /dev/null
+++ b/sys/arch/pc532/stand/tgets.c
@@ -0,0 +1,89 @@
+/* $NetBSD: tgets.c,v 1.2 1994/10/26 08:26:00 cgd Exp $ */
+
+/*-
+ * Copyright (c) 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)gets.c 8.1 (Berkeley) 6/11/93
+ */
+
+tgets(buf)
+ char *buf;
+{
+ register int c;
+ int i;
+ register char *lp = buf;
+
+ for (i = 2400000; i > 0; i--) {
+ c = tgetchar() & 0177;
+ if (c) {
+ for (;;) {
+ switch (c) {
+ case '\n':
+ case '\r':
+ *lp = '\0';
+ return;
+ case '\b':
+ case '\177':
+ if (lp > buf) {
+ lp--;
+ putchar('\b');
+ putchar(' ');
+ putchar('\b');
+ }
+ break;
+ case '#':
+ if (lp > buf)
+ --lp;
+ break;
+ case 'r'&037: {
+ register char *p;
+
+ putchar('\n');
+ for (p = buf; p < lp; ++p)
+ putchar(*p);
+ break;
+ }
+ case '@':
+ case 'u'&037:
+ case 'w'&037:
+ lp = buf;
+ putchar('\n');
+ break;
+ default:
+ *lp++ = c;
+ }
+ c = getchar() & 0177;
+ }
+ }
+ }
+ return(0);
+}