Initial import of arm32 port
authorderaadt <deraadt@openbsd.org>
Wed, 24 Apr 1996 11:08:22 +0000 (11:08 +0000)
committerderaadt <deraadt@openbsd.org>
Wed, 24 Apr 1996 11:08:22 +0000 (11:08 +0000)
209 files changed:
sys/arch/arm32/Makefile [new file with mode: 0644]
sys/arch/arm32/arm32/ast.c [new file with mode: 0644]
sys/arch/arm32/arm32/autoconf.c [new file with mode: 0644]
sys/arch/arm32/arm32/bcopy.S [new file with mode: 0644]
sys/arch/arm32/arm32/bcopy_page.S [new file with mode: 0644]
sys/arch/arm32/arm32/bcopyinout.S [new file with mode: 0644]
sys/arch/arm32/arm32/blockio.S [new file with mode: 0644]
sys/arch/arm32/arm32/clock.c [new file with mode: 0644]
sys/arch/arm32/arm32/conf.c [new file with mode: 0644]
sys/arch/arm32/arm32/coproc15.S [new file with mode: 0644]
sys/arch/arm32/arm32/copystr.S [new file with mode: 0644]
sys/arch/arm32/arm32/cpuswitch.S [new file with mode: 0644]
sys/arch/arm32/arm32/db_disasm.c [new file with mode: 0644]
sys/arch/arm32/arm32/db_interface.c [new file with mode: 0644]
sys/arch/arm32/arm32/db_machdep.c [new file with mode: 0644]
sys/arch/arm32/arm32/db_trace.c [new file with mode: 0644]
sys/arch/arm32/arm32/debug.c [new file with mode: 0644]
sys/arch/arm32/arm32/disassem.c [new file with mode: 0644]
sys/arch/arm32/arm32/disksubr.c [new file with mode: 0644]
sys/arch/arm32/arm32/exception.S [new file with mode: 0644]
sys/arch/arm32/arm32/fault.c [new file with mode: 0644]
sys/arch/arm32/arm32/fiq.S [new file with mode: 0644]
sys/arch/arm32/arm32/fusu.c [new file with mode: 0644]
sys/arch/arm32/arm32/genassym.c [new file with mode: 0644]
sys/arch/arm32/arm32/irq.S [new file with mode: 0644]
sys/arch/arm32/arm32/irqhandler.c [new file with mode: 0644]
sys/arch/arm32/arm32/kgdb_glue.c [new file with mode: 0644]
sys/arch/arm32/arm32/kgdb_step.c [new file with mode: 0644]
sys/arch/arm32/arm32/locore.S [new file with mode: 0644]
sys/arch/arm32/arm32/machdep.c [new file with mode: 0644]
sys/arch/arm32/arm32/makemodes.c [new file with mode: 0644]
sys/arch/arm32/arm32/mcount.S [new file with mode: 0644]
sys/arch/arm32/arm32/mem.c [new file with mode: 0644]
sys/arch/arm32/arm32/memset.S [new file with mode: 0644]
sys/arch/arm32/arm32/pmap.c [new file with mode: 0644]
sys/arch/arm32/arm32/postmortem.c [new file with mode: 0644]
sys/arch/arm32/arm32/process_machdep.c [new file with mode: 0644]
sys/arch/arm32/arm32/scratch.S [new file with mode: 0644]
sys/arch/arm32/arm32/setcpsr.S [new file with mode: 0644]
sys/arch/arm32/arm32/setstack.S [new file with mode: 0644]
sys/arch/arm32/arm32/spl.S [new file with mode: 0644]
sys/arch/arm32/arm32/strstr.c [new file with mode: 0644]
sys/arch/arm32/arm32/strtoul.c [new file with mode: 0644]
sys/arch/arm32/arm32/stubs.c [new file with mode: 0644]
sys/arch/arm32/arm32/swapgeneric.c [new file with mode: 0644]
sys/arch/arm32/arm32/sys_machdep.c [new file with mode: 0644]
sys/arch/arm32/arm32/syscall.c [new file with mode: 0644]
sys/arch/arm32/arm32/undefined.c [new file with mode: 0644]
sys/arch/arm32/arm32/vm_machdep.c [new file with mode: 0644]
sys/arch/arm32/boot/Makefile [new file with mode: 0644]
sys/arch/arm32/boot/Makefile.inc [new file with mode: 0644]
sys/arch/arm32/boot/README [new file with mode: 0644]
sys/arch/arm32/boot/_bsdboot.S [new file with mode: 0644]
sys/arch/arm32/boot/_main.S [new file with mode: 0644]
sys/arch/arm32/boot/areahand.S [new file with mode: 0644]
sys/arch/arm32/boot/arm6.h [new file with mode: 0644]
sys/arch/arm32/boot/bsdbooter.c [new file with mode: 0644]
sys/arch/arm32/boot/enteros.S [new file with mode: 0644]
sys/arch/arm32/boot/exit.S [new file with mode: 0644]
sys/arch/arm32/boot/exitos.S [new file with mode: 0644]
sys/arch/arm32/boot/memcpy.S [new file with mode: 0644]
sys/arch/arm32/boot/memset.S [new file with mode: 0644]
sys/arch/arm32/boot/regs.h [new file with mode: 0644]
sys/arch/arm32/boot/rmaouthdr [new file with mode: 0644]
sys/arch/arm32/boot/setcpsr.S [new file with mode: 0644]
sys/arch/arm32/boot/start.S [new file with mode: 0644]
sys/arch/arm32/boot/strstr.c [new file with mode: 0644]
sys/arch/arm32/boot/svc32.S [new file with mode: 0644]
sys/arch/arm32/boot/swis.h [new file with mode: 0644]
sys/arch/arm32/boot/swiv.S [new file with mode: 0644]
sys/arch/arm32/boot/swiv.h [new file with mode: 0644]
sys/arch/arm32/boot/vsprintf.c [new file with mode: 0644]
sys/arch/arm32/compile/.keep_me [new file with mode: 0644]
sys/arch/arm32/conf/BETA [new file with mode: 0644]
sys/arch/arm32/conf/CLAIRE [new file with mode: 0644]
sys/arch/arm32/conf/GENERIC [new file with mode: 0644]
sys/arch/arm32/conf/Makefile.arm32 [new file with mode: 0644]
sys/arch/arm32/conf/PHARM [new file with mode: 0644]
sys/arch/arm32/conf/REMY [new file with mode: 0644]
sys/arch/arm32/conf/VOYAGER [new file with mode: 0644]
sys/arch/arm32/conf/files.arm32 [new file with mode: 0644]
sys/arch/arm32/conf/monitors/AKF60 [new file with mode: 0644]
sys/arch/arm32/conf/monitors/AKF85 [new file with mode: 0644]
sys/arch/arm32/conf/monitors/Taxan875+LR [new file with mode: 0644]
sys/arch/arm32/conf/std.arm32 [new file with mode: 0644]
sys/arch/arm32/dev/console/console.c [new file with mode: 0644]
sys/arch/arm32/dev/console/debugconsole.c [new file with mode: 0644]
sys/arch/arm32/dev/console/dumb.c [new file with mode: 0644]
sys/arch/arm32/dev/console/fonts/font_bold.h [new file with mode: 0644]
sys/arch/arm32/dev/console/fonts/font_italic.h [new file with mode: 0644]
sys/arch/arm32/dev/console/fonts/font_normal.h [new file with mode: 0644]
sys/arch/arm32/dev/console/fonts/font_wide.h [new file with mode: 0644]
sys/arch/arm32/dev/console/vidc.c [new file with mode: 0644]
sys/arch/arm32/dev/console/vidc_mc.S [new file with mode: 0644]
sys/arch/arm32/dev/console/vidcconsole.c [new file with mode: 0644]
sys/arch/arm32/dev/console/vt220.c [new file with mode: 0644]
sys/arch/arm32/dev/console/vt220.h [new file with mode: 0644]
sys/arch/arm32/dev/rd_hooks.c [new file with mode: 0644]
sys/arch/arm32/doc/bootloader [new file with mode: 0644]
sys/arch/arm32/doc/history [new file with mode: 0644]
sys/arch/arm32/doc/majors+minors [new file with mode: 0644]
sys/arch/arm32/doc/note.users [new file with mode: 0644]
sys/arch/arm32/fpe-arm/armfpe.h [new file with mode: 0644]
sys/arch/arm32/fpe-arm/armfpe.s [new file with mode: 0644]
sys/arch/arm32/fpe-arm/armfpe_glue.S [new file with mode: 0644]
sys/arch/arm32/fpe-arm/armfpe_init.c [new file with mode: 0644]
sys/arch/arm32/fpe-sp/fpe.c [new file with mode: 0644]
sys/arch/arm32/fpe-sp/fpeadd.S [new file with mode: 0644]
sys/arch/arm32/fpe-sp/fpecmf.S [new file with mode: 0644]
sys/arch/arm32/fpe-sp/fpediv.S [new file with mode: 0644]
sys/arch/arm32/fpe-sp/fpefix.S [new file with mode: 0644]
sys/arch/arm32/fpe-sp/fpemul.S [new file with mode: 0644]
sys/arch/arm32/fpe-sp/fpesub.S [new file with mode: 0644]
sys/arch/arm32/fpe-sp/fpetoe.S [new file with mode: 0644]
sys/arch/arm32/include/ansi.h [new file with mode: 0644]
sys/arch/arm32/include/asm.h [new file with mode: 0644]
sys/arch/arm32/include/beep.h [new file with mode: 0644]
sys/arch/arm32/include/bootconfig.h [new file with mode: 0644]
sys/arch/arm32/include/cdefs.h [new file with mode: 0644]
sys/arch/arm32/include/cpu.h [new file with mode: 0644]
sys/arch/arm32/include/cpus.h [new file with mode: 0644]
sys/arch/arm32/include/db_machdep.h [new file with mode: 0644]
sys/arch/arm32/include/disklabel.h [new file with mode: 0644]
sys/arch/arm32/include/endian.h [new file with mode: 0644]
sys/arch/arm32/include/exec.h [new file with mode: 0644]
sys/arch/arm32/include/float.h [new file with mode: 0644]
sys/arch/arm32/include/fp.h [new file with mode: 0644]
sys/arch/arm32/include/frame.h [new file with mode: 0644]
sys/arch/arm32/include/iic.h [new file with mode: 0644]
sys/arch/arm32/include/io.h [new file with mode: 0644]
sys/arch/arm32/include/iomd.h [new file with mode: 0644]
sys/arch/arm32/include/irqhandler.h [new file with mode: 0644]
sys/arch/arm32/include/katelib.h [new file with mode: 0644]
sys/arch/arm32/include/kbd.h [new file with mode: 0644]
sys/arch/arm32/include/kgdb.h [new file with mode: 0644]
sys/arch/arm32/include/limits.h [new file with mode: 0644]
sys/arch/arm32/include/mouse.h [new file with mode: 0644]
sys/arch/arm32/include/param.h [new file with mode: 0644]
sys/arch/arm32/include/pcb.h [new file with mode: 0644]
sys/arch/arm32/include/pmap.h [new file with mode: 0644]
sys/arch/arm32/include/podule.h [new file with mode: 0644]
sys/arch/arm32/include/proc.h [new file with mode: 0644]
sys/arch/arm32/include/profile.h [new file with mode: 0644]
sys/arch/arm32/include/psl.h [new file with mode: 0644]
sys/arch/arm32/include/pte.h [new file with mode: 0644]
sys/arch/arm32/include/ptrace.h [new file with mode: 0644]
sys/arch/arm32/include/qmouse.h [new file with mode: 0644]
sys/arch/arm32/include/reg.h [new file with mode: 0644]
sys/arch/arm32/include/rtc.h [new file with mode: 0644]
sys/arch/arm32/include/setjmp.h [new file with mode: 0644]
sys/arch/arm32/include/signal.h [new file with mode: 0644]
sys/arch/arm32/include/stdarg.h [new file with mode: 0644]
sys/arch/arm32/include/types.h [new file with mode: 0644]
sys/arch/arm32/include/undefined.h [new file with mode: 0644]
sys/arch/arm32/include/varargs.h [new file with mode: 0644]
sys/arch/arm32/include/vconsole.h [new file with mode: 0644]
sys/arch/arm32/include/vidc.h [new file with mode: 0644]
sys/arch/arm32/include/vmparam.h [new file with mode: 0644]
sys/arch/arm32/kshell/dumphex.c [new file with mode: 0644]
sys/arch/arm32/kshell/shell_disassem.c [new file with mode: 0644]
sys/arch/arm32/kshell/shell_input.c [new file with mode: 0644]
sys/arch/arm32/kshell/shell_shell.c [new file with mode: 0644]
sys/arch/arm32/kshell/strchr.c [new file with mode: 0644]
sys/arch/arm32/mainbus/beep.c [new file with mode: 0644]
sys/arch/arm32/mainbus/com.c [new file with mode: 0644]
sys/arch/arm32/mainbus/comreg.h [new file with mode: 0644]
sys/arch/arm32/mainbus/cpu.c [new file with mode: 0644]
sys/arch/arm32/mainbus/fd.c [new file with mode: 0644]
sys/arch/arm32/mainbus/fdreg.h [new file with mode: 0644]
sys/arch/arm32/mainbus/iic.c [new file with mode: 0644]
sys/arch/arm32/mainbus/iic_asm.S [new file with mode: 0644]
sys/arch/arm32/mainbus/kbd.c [new file with mode: 0644]
sys/arch/arm32/mainbus/lpt.c [new file with mode: 0644]
sys/arch/arm32/mainbus/lptreg.h [new file with mode: 0644]
sys/arch/arm32/mainbus/mainbus.c [new file with mode: 0644]
sys/arch/arm32/mainbus/mainbus.h [new file with mode: 0644]
sys/arch/arm32/mainbus/pms.c [new file with mode: 0644]
sys/arch/arm32/mainbus/qmouse.c [new file with mode: 0644]
sys/arch/arm32/mainbus/rtc.c [new file with mode: 0644]
sys/arch/arm32/mainbus/vidcaudio.c [new file with mode: 0644]
sys/arch/arm32/mainbus/waveform.h [new file with mode: 0644]
sys/arch/arm32/mainbus/wd.c [new file with mode: 0644]
sys/arch/arm32/mainbus/wdreg.h [new file with mode: 0644]
sys/arch/arm32/podulebus/asc.c [new file with mode: 0644]
sys/arch/arm32/podulebus/ascreg.h [new file with mode: 0644]
sys/arch/arm32/podulebus/ascvar.h [new file with mode: 0644]
sys/arch/arm32/podulebus/if_ea.c [new file with mode: 0644]
sys/arch/arm32/podulebus/if_eareg.h [new file with mode: 0644]
sys/arch/arm32/podulebus/if_eb.c [new file with mode: 0644]
sys/arch/arm32/podulebus/if_ebreg.h [new file with mode: 0644]
sys/arch/arm32/podulebus/if_eh.c [new file with mode: 0644]
sys/arch/arm32/podulebus/if_ehreg.h [new file with mode: 0644]
sys/arch/arm32/podulebus/if_ie.c [new file with mode: 0644]
sys/arch/arm32/podulebus/if_iereg.h [new file with mode: 0644]
sys/arch/arm32/podulebus/ncr5380reg.h [new file with mode: 0644]
sys/arch/arm32/podulebus/ncr5380sbc.c [new file with mode: 0644]
sys/arch/arm32/podulebus/ncr5380var.h [new file with mode: 0644]
sys/arch/arm32/podulebus/oak.c [new file with mode: 0644]
sys/arch/arm32/podulebus/podulebus.c [new file with mode: 0644]
sys/arch/arm32/podulebus/podulebus.h [new file with mode: 0644]
sys/arch/arm32/podulebus/ptsc.c [new file with mode: 0644]
sys/arch/arm32/podulebus/ptscreg.h [new file with mode: 0644]
sys/arch/arm32/podulebus/ptscvar.h [new file with mode: 0644]
sys/arch/arm32/podulebus/sbic.c [new file with mode: 0644]
sys/arch/arm32/podulebus/sbicreg.h [new file with mode: 0644]
sys/arch/arm32/podulebus/sbicvar.h [new file with mode: 0644]
sys/arch/arm32/podulebus/sfas.c [new file with mode: 0644]
sys/arch/arm32/podulebus/sfasreg.h [new file with mode: 0644]
sys/arch/arm32/podulebus/sfasvar.h [new file with mode: 0644]

diff --git a/sys/arch/arm32/Makefile b/sys/arch/arm32/Makefile
new file mode 100644 (file)
index 0000000..4b3fb67
--- /dev/null
@@ -0,0 +1,32 @@
+#      $NetBSD: Makefile,v 1.1 1996/01/31 23:14:53 mark Exp $
+#      @(#)Makefile    7.3 (Berkeley) 6/9/91
+
+# Makefile for arm32 tags file and boot blocks
+
+NOPROG=        noprog
+NOMAN= noman
+
+SUBDIR=
+
+TARM32=        ../arm32/tags
+SARM32=        ../arm32/arm32/*.[ch] ../arm32/include/*.h ../arm32/dev/*.[ch] \
+       ../arm32/podulebus/*.[ch] ../arm32/mainbus/*.[ch]
+AARM32=        ../arm32/arm32/*.s
+
+# Directories in which to place arm32 tags links
+DARM32=        dev mainbus podulebus include
+
+tags:
+       -ctags -dtf ${TARM32} ${COMM} ${SARM32}
+       egrep "^ENTRY(.*)|^ALTENTRY(.*)" ${AARM32} | \
+           sed "s;\([^:]*\):\([^(]*\)(\([^, )]*\)\(.*\);\3 \1 /^\2(\3\4$$/;" \
+               >> ${TARM32}
+       sort -o ${TARM32} ${TARM32}
+
+links:
+       -for i in ${DARM32}; do \
+           cd $$i && rm -f tags; ln -s ../tags tags; done
+
+obj: _SUBDIRUSE
+
+.include <bsd.prog.mk>
diff --git a/sys/arch/arm32/arm32/ast.c b/sys/arch/arm32/arm32/ast.c
new file mode 100644 (file)
index 0000000..62c87bd
--- /dev/null
@@ -0,0 +1,168 @@
+/* $NetBSD: ast.c,v 1.2 1996/03/08 18:54:55 mark Exp $ */
+
+/*
+ * Copyright (c) 1994,1995 Mark Brinicombe
+ * 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 RiscBSD team.
+ * 4. The name of the company nor the name of the author may 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 OR CONTRIBUTERS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * RiscBSD kernel project
+ *
+ * ast.c
+ *
+ * Code to handle ast's and returns to user mode
+ *
+ * Created      : 11/10/94
+ */
+
+#include <sys/param.h>
+#include <sys/proc.h>
+#include <sys/user.h>
+#include <sys/acct.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/signal.h>
+#include <machine/cpu.h>
+#include <machine/frame.h>
+#include <machine/katelib.h>
+#include <machine/psl.h>
+
+int want_resched = 0;
+
+void
+userret(p, pc, oticks)
+       register struct proc *p;
+       int pc;
+       u_quad_t oticks;
+{
+       int sig, s;
+
+       if (p == NULL)
+               panic("userret: p=0 curproc=%08x", curproc);
+    
+#ifdef DIAGNOSTIC
+       if ((GetCPSR() & PSR_MODE) != PSR_SVC32_MODE) {
+               traceback();
+               panic("userret called in non SVC mode !");
+       }
+
+       if (current_spl_level != SPL_0)
+               printf("WARNING: (1) current spl level=%d\n", current_spl_level);
+#endif
+
+/* take pending signals */
+
+       while ((sig = (CURSIG(p))) != 0) {
+               postsig(sig);
+       }
+
+       p->p_priority = p->p_usrpri;
+
+/*
+ * Check for reschedule request
+ */
+
+       if (want_resched) {
+        /*
+         * Since we are curproc, a clock interrupt could
+         * change our priority without changing run queues
+         * (the running process is not kept on a run queue).
+         * If this happened after we setrunqueue ourselves but
+         * before we switch()'ed, we might not be on the queue
+         * indicated by our priority
+         */
+
+               s = splstatclock();
+               setrunqueue(p);
+               p->p_stats->p_ru.ru_nivcsw++;
+
+               mi_switch();
+
+               (void)splx(s);
+               while ((sig = (CURSIG(p))) != 0) {
+                       postsig(sig);
+               }
+       }
+
+/*
+ * Not sure if this profiling bit is working yet ... Not been tested
+ */
+
+       if (p->p_flag & P_PROFIL) {
+               extern int psratio;
+               addupc_task(p, pc, (int)(p->p_sticks - oticks) * psratio);
+       }
+
+       curpriority = p->p_priority;
+
+#ifdef DIAGNOSTIC
+       if (current_spl_level != SPL_0)
+               printf("WARNING: (2) current spl level=%d\n", current_spl_level);
+#endif
+}
+
+
+/*
+ * void ast(trapframe_t *frame)
+ *
+ * Handle asynchronous system traps.
+ * This is called from the irq handler to deliver signals
+ * and switch processes if required.
+ * userret() does all the signal delivery and process switching work
+ */
+
+void
+ast(frame)
+       trapframe_t *frame;
+{
+       register struct proc *p;
+
+       cnt.v_trap++;
+
+       if ((p = curproc) == 0)
+               p = &proc0;
+       if (&p->p_addr->u_pcb == 0)
+               panic("ast: nopcb!");
+
+       cnt.v_soft++;
+       if (p->p_flag & P_OWEUPC) {
+               p->p_flag &= ~P_OWEUPC;
+               ADDUPROF(p);
+       }
+#ifdef VALIDATE_TRAPFRAME
+       validate_trapframe(frame, 3);
+#endif
+
+       userret(p, frame->tf_pc, p->p_sticks);
+
+#ifdef VALIDATE_TRAPFRAME
+       validate_trapframe(frame, 3);
+#endif
+}
+
+/* End of ast.c */
diff --git a/sys/arch/arm32/arm32/autoconf.c b/sys/arch/arm32/arm32/autoconf.c
new file mode 100644 (file)
index 0000000..e70cb31
--- /dev/null
@@ -0,0 +1,281 @@
+/* $NetBSD: autoconf.c,v 1.2 1996/03/06 23:11:36 mark Exp $ */
+
+/*
+ * Copyright (c) 1994,1995 Mark Brinicombe.
+ * Copyright (c) 1994 Brini.
+ * 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 Brini.
+ * 4. The name of the company nor the name of the author may be used to
+ *    endorse or promote products derived from this software without specific
+ *    prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BRINI ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL BRINI 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.
+ *
+ * RiscBSD kernel project
+ *
+ * autoconf.c
+ *
+ * Autoconfiguration functions
+ *
+ * Created      : 08/10/94
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/reboot.h>
+#include <sys/disklabel.h>
+#include <sys/device.h>
+#include <sys/conf.h>
+#include <sys/kernel.h>
+#include <sys/malloc.h>
+
+#include <machine/irqhandler.h>
+#include <machine/bootconfig.h>
+
+#include "wdc.h"
+#include "fdc.h"
+#include "rd.h"
+#include "sd.h"
+#include "cd.h"
+#include "wcd.h"
+
+extern dev_t rootdev;
+extern dev_t swapdev;
+extern dev_t dumpdev;
+extern dev_t argdev;
+
+extern struct swdevt swdevt[];
+
+extern char *boot_args;
+extern int pmap_debug_level;
+
+char * strstr  __P((char */*s1*/, char */*s2*/));
+long   strtoul __P((const char *, char **, int));
+
+/* Table major numbers for the device names, NULL terminated */
+
+struct {
+    char *name;
+    dev_t dev;
+} rootdevices[] = {
+#if NWDC > 0
+       { "wd", 0x10 },
+#endif
+#if NFDC > 0
+       { "fd", 0x11 },
+#endif
+#if NRD > 0
+       { "rd", 0x12 },
+#endif
+#if NSD > 0
+       { "sd", 0x18 },
+#endif
+#if NCD > 0
+       { "cd", 0x1a },
+#endif
+#if NWCD > 0
+       { "wcd", 0x14 },
+#endif
+       { NULL, 0x00 },
+};
+
+/* Decode a device name to a major and minor number */
+
+dev_t
+get_device(name)
+       char *name;
+{
+       int loop;
+       int unit;
+       int part;
+    
+       if (strncmp(name, "/dev/", 5) == 0)
+               name += 5;
+
+       for (loop = 0; rootdevices[loop].name; ++loop) {
+               if (strncmp(name, rootdevices[loop].name,
+                   strlen(rootdevices[loop].name)) == 0) {
+                       name += strlen(rootdevices[loop].name);
+                       unit = name[0] - '0';
+                       part = name[1] - 'a';
+                       if (unit < 0 || unit > 9)
+                               return(NODEV);
+                       if (part < 0 || part > MAXPARTITIONS)
+                               return(NODEV);
+                       return(makedev(rootdevices[loop].dev,
+                           unit * MAXPARTITIONS + part));
+               }
+       } 
+       return(NODEV);  
+}
+
+
+/* Set the rootdev variable from the root specifier in the boot args */
+
+void
+set_root_device()
+{
+       char *ptr;
+            
+       if (boot_args) {
+               ptr = strstr(boot_args, "root=");
+               if (ptr) {
+                       ptr += 5;
+                       rootdev = get_device(ptr);
+              
+                       if (pmap_debug_level >= 0)
+                               printf("rootdev = %08x\n", rootdev);
+               }
+       }
+
+       if (rootdev == NODEV)
+               panic("No root device specified in boot config\n");
+}
+
+
+/* Set the swap devices from the swap specifiers in the boot ars */
+
+void
+set_swap_device()
+{
+       char *ptr;
+       int nswap = 0;
+            
+       if (boot_args) {
+               ptr = boot_args;
+               do {
+                       ptr = strstr(ptr, "swap=");
+                       if (ptr) {
+                               ptr += 5;
+                               swdevt[nswap].sw_dev = get_device(ptr);
+
+                               /*
+                                * Remember the first swap device
+                                */
+
+                               if (nswap == 0)
+                                       swapdev = get_device(ptr);
+                               ++nswap;
+                       }
+               } while (ptr);
+       }
+}
+
+
+/*
+ * Configure swap space and related parameters.
+ */
+
+void
+swapconf()
+{
+       register struct swdevt *swp;
+       register int nblks;
+       int swapsize = -1;
+       char *ptr;
+       int maj;
+       int s;          /* The spl stuff was here for debugging reaons */
+
+       /*
+        * Loop round all the defined swap device configuring them.
+        */
+
+       for (swp = swdevt; swp->sw_dev != NODEV; swp++) {
+               maj = major(swp->sw_dev);
+               if (maj > nblkdev)
+                       break;
+               if (bdevsw[maj].d_psize) {
+                       s = spltty();
+                       printf("swap dev %04x ", swp->sw_dev);
+                       (void)splx(s);
+                       if (swapsize == -1)
+                               nblks = (*bdevsw[maj].d_psize)(swp->sw_dev);
+                       else
+                               nblks = swapsize;
+                       s = spltty();
+                       if (nblks == -1)
+                               printf("-> device not configured for swap\n");
+                       else
+                               printf("-> %d bytes\n", nblks*DEV_BSIZE);
+                       (void)splx(s);
+                       if (nblks != -1 &&
+                           (swp->sw_nblks == 0 || swp->sw_nblks > nblks))
+                               swp->sw_nblks = nblks;
+                       swp->sw_nblks = ctod(dtoc(swp->sw_nblks));
+               }
+       }
+}
+
+
+/* Set up the root and swap device numbers, configure the swap space and dump space */
+
+void
+set_boot_devs()
+{
+       set_root_device();
+       set_swap_device();
+
+       if (swapdev == NODEV && minor(rootdev) < (MAXPARTITIONS - 2))
+               swapdev = makedev(major(rootdev), minor(rootdev) + 1);
+
+       dumpdev = swapdev;
+       argdev = swapdev;
+       swdevt[0].sw_dev = swapdev;
+
+       swapconf();
+       dumpconf();
+}
+
+
+/*
+ * void configure()
+ *
+ * Configure all the root devices
+ * The root devices are expected to configure their own children
+ */
+
+void
+configure()
+{
+
+/*
+ * Loop round all the root devices configuring them. Configure failure
+ * is not expected for the root devices
+ */
+
+       config_rootfound("mainbus", NULL);
+       config_rootfound("podulebus", NULL);
+
+/* Debugging information */
+
+       printf("ipl_bio=%08x ipl_net=%08x ipl_tty=%08x ipl_clock=%08x ipl_imp=%08x\n",
+           irqmasks[IPL_BIO], irqmasks[IPL_NET], irqmasks[IPL_TTY],
+           irqmasks[IPL_CLOCK], irqmasks[IPL_IMP]);
+
+/* Time to start taking interrupts so lets open the flood gates .... */
+         
+       (void)spl0();
+}
+
+/* End of autoconf.c */
diff --git a/sys/arch/arm32/arm32/bcopy.S b/sys/arch/arm32/arm32/bcopy.S
new file mode 100644 (file)
index 0000000..61bc76d
--- /dev/null
@@ -0,0 +1,113 @@
+/* $NetBSD: bcopy.S,v 1.1 1996/01/31 23:15:12 mark Exp $ */
+
+/*
+ * Copyright (c) 1995 Mark Brinicombe.
+ * Copyright (c) 1995 Brini.
+ * All rights reserved.
+ *
+ * This code is derived from software written for Brini by Mark Brinicombe
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided 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 Brini.
+ * 4. The name of the company nor the name of the author may be used to
+ *    endorse or promote products derived from this software without specific
+ *    prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BRINI ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL BRINI 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.
+ *
+ * RiscBSD kernel project
+ *
+ * memset.S
+ *
+ * optimized memset function
+ *
+ * Created      : 16/05/95
+ * Last updated : 16/05/95
+ *
+ *    $Id: bcopy.S,v 1.1.1.1 1996/04/24 11:08:23 deraadt Exp $
+ */
+
+sp     .req    r13
+lr     .req    r14
+pc     .req    r15
+
+.text
+       .global _bcopy
+       .global _ovbcopy
+
+_bcopy:
+_ovbcopy:
+       teq     r2, #0x00000000
+       moveq   r0, #0x00000000
+       moveq   pc, lr
+       cmp     r0, r1
+       blt     bcopy_back
+
+bcopy_loop:
+       ldrb    r3, [r0], #0x0001
+       strb    r3, [r1], #0x0001
+       subs    r2, r2, #0x00000001
+       bne     bcopy_loop
+
+       mov     pc, r14
+
+bcopy_back:
+       add     r0, r0, r2
+       add     r1, r1, r2
+
+bcopy_bloop:
+       ldrb    r3, [r0, #-0x0001]!
+       strb    r3, [r1, #-0x0001]!
+       subs    r2, r2, #0x00000001
+       bne     bcopy_bloop
+
+       mov     pc, r14
+
+
+       .global _memcpy
+
+_memcpy:
+       teq     r2, #0x00000000
+       moveq   r0, #0x00000000
+       moveq   pc, lr
+       cmp     r1, r0
+       blt     memcpy_back
+
+memcpy_loop:
+       ldrb    r3, [r1], #0x0001
+       strb    r3, [r0], #0x0001
+       subs    r2, r2, #0x00000001
+       bne     memcpy_loop
+
+       mov     pc, r14
+
+memcpy_back:
+       add     r0, r0, r2
+       add     r1, r1, r2
+
+memcpy_bloop:
+       ldrb    r3, [r1, #-0x0001]!
+       strb    r3, [r0, #-0x0001]!
+       subs    r2, r2, #0x00000001
+       bne     memcpy_bloop
+
+       mov     pc, r14
diff --git a/sys/arch/arm32/arm32/bcopy_page.S b/sys/arch/arm32/arm32/bcopy_page.S
new file mode 100644 (file)
index 0000000..b445275
--- /dev/null
@@ -0,0 +1,150 @@
+/* $NetBSD: bcopy_page.S,v 1.1 1996/01/31 23:15:17 mark Exp $ */
+
+/*
+ * Copyright (c) 1995 Scott Stevens
+ * 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 Scott Stevens.
+ * 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.
+ *
+ * RiscBSD kernel project
+ *
+ * bcopy_page.S
+ *
+ * page optimised bcopy and bzero routines
+ *
+ * Created      : 08/04/95
+ * Last updated : 12/05/95
+ *
+ *    $Id: bcopy_page.S,v 1.1.1.1 1996/04/24 11:08:23 deraadt Exp $
+ */
+
+#include <machine/param.h>
+
+/* TODO:
+ *
+ * Use r2 as the counter so that r3-r10 can be used instead of r4-r11
+ * This means r11 will not need to be pushed on the stack.
+ */
+
+/* bcopy_page(src, dest)
+ * r0 - src
+ * r1 - dest
+ * number of bytes (NBPG) is a multiple of 512
+ */
+
+       .global _bcopy_page
+_bcopy_page:
+       mov     r3, #(NBPG >> 9)
+
+       STMFD   r13!, {r4-r11, r14}
+
+loopcopy:
+       ldmia   r0!, {r4-r11}
+       stmia   r1!, {r4-r11}
+       ldmia   r0!, {r4-r11}
+       stmia   r1!, {r4-r11}
+       ldmia   r0!, {r4-r11}
+       stmia   r1!, {r4-r11}
+       ldmia   r0!, {r4-r11}
+       stmia   r1!, {r4-r11}
+
+       ldmia   r0!, {r4-r11}
+       stmia   r1!, {r4-r11}
+       ldmia   r0!, {r4-r11}
+       stmia   r1!, {r4-r11}
+       ldmia   r0!, {r4-r11}
+       stmia   r1!, {r4-r11}
+       ldmia   r0!, {r4-r11}
+       stmia   r1!, {r4-r11}
+
+       ldmia   r0!, {r4-r11}
+       stmia   r1!, {r4-r11}
+       ldmia   r0!, {r4-r11}
+       stmia   r1!, {r4-r11}
+       ldmia   r0!, {r4-r11}
+       stmia   r1!, {r4-r11}
+       ldmia   r0!, {r4-r11}
+       stmia   r1!, {r4-r11}
+
+       ldmia   r0!, {r4-r11}
+       stmia   r1!, {r4-r11}
+       ldmia   r0!, {r4-r11}
+       stmia   r1!, {r4-r11}
+       ldmia   r0!, {r4-r11}
+       stmia   r1!, {r4-r11}
+       ldmia   r0!, {r4-r11}
+       stmia   r1!, {r4-r11}
+
+       subs    r3, r3, #1
+       bgt     loopcopy
+
+       ldmfd   r13!, {r4-r11, r15}
+
+/* bzero_page(dest)
+ * r0 - dest
+ * number of bytes is a multiple of 512
+ */
+
+       .global _bzero_page
+_bzero_page:
+       mov     r3, #(NBPG >> 9)
+
+       stmfd   r13!, {r4-r11, r14}
+
+       mov     r4, #0
+       mov     r5, #0
+       mov     r6, #0
+       mov     r7, #0
+       mov     r8, #0
+       mov     r9, #0
+       mov     r10, #0
+       mov     r11, #0
+
+loopzero:
+       stmia   r0!, {r4-r11}
+       stmia   r0!, {r4-r11}
+       stmia   r0!, {r4-r11}
+       stmia   r0!, {r4-r11}
+
+       stmia   r0!, {r4-r11}
+       stmia   r0!, {r4-r11}
+       stmia   r0!, {r4-r11}
+       stmia   r0!, {r4-r11}
+
+       stmia   r0!, {r4-r11}
+       stmia   r0!, {r4-r11}
+       stmia   r0!, {r4-r11}
+       stmia   r0!, {r4-r11}
+
+       stmia   r0!, {r4-r11}
+       stmia   r0!, {r4-r11}
+       stmia   r0!, {r4-r11}
+       stmia   r0!, {r4-r11}
+
+       subs    r3, r3, #1
+       bgt     loopzero
+
+       ldmfd   r13!, {r4-r11, r15}
diff --git a/sys/arch/arm32/arm32/bcopyinout.S b/sys/arch/arm32/arm32/bcopyinout.S
new file mode 100644 (file)
index 0000000..c047e51
--- /dev/null
@@ -0,0 +1,132 @@
+/* $NetBSD: bcopyinout.S,v 1.3 1996/02/02 18:05:47 mycroft Exp $ */
+
+/*
+ * Copyright (c) 1995 Mark Brinicombe.
+ * Copyright (c) 1995 Brini.
+ * All rights reserved.
+ *
+ * This code is derived from software written for Brini by Mark Brinicombe
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided 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 Brini.
+ * 4. The name of the company nor the name of the author may be used to
+ *    endorse or promote products derived from this software without specific
+ *    prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BRINI ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL BRINI 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.
+ *
+ * RiscBSD kernel project
+ *
+ * bcopyinout.S
+ *
+ * optimized and fault protected copyinout function
+ *
+ * Created      : 16/05/95
+ * Last updated : 16/05/95
+ *
+ *    $Id: bcopyinout.S,v 1.1.1.1 1996/04/24 11:08:24 deraadt Exp $
+ */
+
+#include "assym.h"
+#include <sys/errno.h>
+
+sp     .req    r13
+lr     .req    r14
+pc     .req    r15
+
+.text
+Lcurpcb:
+       .word   _curpcb
+
+Lcurproc:
+       .word   _curproc
+
+bcopyinoutfault:
+       mov     r0, #0x00000000
+       str     r0, [r4, #PCB_ONFAULT]
+       mov     r0, #EFAULT
+       ldmfd   sp!, {r4}
+       mov     pc, lr
+
+bcopyinoutpcbfault:
+       stmfd   sp!, {lr}
+       mov     r3, r1
+       mov     r1, r4
+       add     r0, pc, #bcopyinouttext - . - 8
+       mov     r2, r3
+       ldr     r3, Lcurproc
+       ldr     r3, [r3]
+       bl      _printf
+       mov     r0, #EFAULT
+       ldmfd   sp!, {lr}
+       ldmfd   sp!, {r4}
+       mov     pc, lr
+
+bcopyinouttext:
+       .asciz  "Alert ! PCB = %08x during bcopyinout addr=%08x curproc=%08x\n"
+
+       .align  0
+
+       .global _bcopyinout
+
+_bcopyinout:
+       teq     r2, #0x00000000
+       moveq   r0, #0x000000000
+       moveq   pc,lr
+
+       stmfd   sp!, {r4}
+       ldr     r4, Lcurpcb
+       ldr     r4, [r4]
+       teq     r4, #0x00000000
+       beq     bcopyinoutpcbfault
+       add     r3, pc, #bcopyinoutfault - . - 8
+       str     r3, [r4, #PCB_ONFAULT]
+
+       cmp     r0, r1
+       blt     bcopy_back
+
+bcopy_loop:
+       ldrb    r3, [r0], #0x0001
+       strb    r3, [r1], #0x0001
+       subs    r2, r2, #0x00000001
+       bne     bcopy_loop
+
+       mov     r0, #0x00000000
+       str     r0, [r4, #PCB_ONFAULT]
+       ldmfd   sp!, {r4}
+       mov     pc, lr
+
+bcopy_back:
+       add     r0, r0, r2
+       add     r1, r1, r2
+
+bcopy_bloop:
+       ldrb    r3, [r0, #-0x0001]!
+       strb    r3, [r1, #-0x0001]!
+       subs    r2, r2, #0x00000001
+       bne     bcopy_bloop
+
+       mov     r0, #0x00000000
+       str     r0, [r4, #PCB_ONFAULT]
+       ldmfd   sp!, {r4}
+       mov     pc, r14
+
diff --git a/sys/arch/arm32/arm32/blockio.S b/sys/arch/arm32/arm32/blockio.S
new file mode 100644 (file)
index 0000000..dfa0405
--- /dev/null
@@ -0,0 +1,312 @@
+/* $NetBSD: blockio.S,v 1.1 1996/01/31 23:15:22 mark Exp $ */
+
+/*
+ * Copyright (c) 1994 Mark Brinicombe.
+ * Copyright (c) 1994 Brini.
+ * All rights reserved.
+ *
+ * This code is derived from software written for Brini by Mark Brinicombe
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided 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 Brini.
+ * 4. The name of the company nor the name of the author may be used to
+ *    endorse or promote products derived from this software without specific
+ *    prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BRINI ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL BRINI 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.
+ *
+ * RiscBSD kernel project
+ *
+ * blockio.S
+ *
+ * optimised block read/write from/to IO routines.
+ *
+ * Created      : 08/10/94
+ * Last updated : 12/05/95
+ *
+ *    $Id: blockio.S,v 1.1.1.1 1996/04/24 11:08:24 deraadt Exp $
+ */
+
+sp     .req    r13
+lr     .req    r14
+pc     .req    r15
+
+.text
+
+       .global _insw
+/*
+ * Reads short ints (16 bits) from an I/O address into a block of memory
+ *
+ * r0 = address to read from (IO)
+ * r1 = address to write to (memory)
+ * r2 = length
+ */
+
+_insw:
+/* Make sure that we have a positive length */
+       cmp     r2, #0x00000000
+       movle   pc, lr
+
+/* If the destination address and the size is word aligned, do it fast */
+
+       tst     r2, #0x00000001
+       tsteq   r1, #0x00000003
+       beq     fastinsw
+
+/* Non aligned insw */
+
+inswloop:
+       ldr     r3, [r0]
+       strb    r3, [r1], #0x0001
+       mov     r3, r3, lsr #8
+       strb    r3, [r1], #0x0001
+       subs    r2, r2, #0x00000001
+       bgt     inswloop
+
+       mov     pc, lr
+
+/* Word aligned insw */
+
+fastinsw:
+       stmfd   r13!, {r4}
+
+fastinswloop:
+       ldr     r3, [r0, #0x0002]       /* take advantage of nonaligned
+                                        * word accesses */
+       ldr     r4, [r0]
+       mov     r3, r3, lsr #16         /* Put the two shorts together */
+       orr     r3, r3, r4, lsl #16
+       str     r3, [r1], #0x0004       /* Store */
+       subs    r2, r2, #0x00000002     /* Next */
+       bgt     fastinswloop
+
+       ldmfd   r13!, {r4}
+
+       mov     pc, lr
+
+
+       .global _outsw
+
+/*
+ * Writes short ints (16 bits) from a block of memory to an I/O address
+ *
+ * r0 = address to write to (IO)
+ * r1 = address to read from (memory)
+ * r2 = length
+ */
+
+_outsw:
+/* Make sure that we have a positive length */
+       cmp     r2, #0x00000000
+       movle   pc, lr
+
+#ifdef notyet
+
+/*
+ * The optimised routines have not been tested yet and I don't feel
+ * like testing the new write code on 2.8 Gig of valuable data.
+ * Need to wait until I hang another HD on my machine
+ */
+
+/* If the destination address and the size is word aligned, do it fast */
+
+       tst     r2, #0x00000001
+       tsteq   r1, #0x00000003
+       beq     fastoutsw
+#endif
+
+/* Non aligned outsw */
+
+       stmfd   sp!, {r4}
+
+outswloop:
+       ldrb    r3, [r1], #0x0001
+       ldrb    r4, [r1], #0x0001
+       orr     r3, r3, r4, lsl #8
+       orr     r3, r3, r3, lsl #16
+       str     r3, [r0]
+       subs    r2, r2, #0x00000001
+       bgt     outswloop
+
+       ldmfd   sp!, {r4}
+
+       mov     pc, lr
+
+#ifdef notyet
+/* Word aligned outsw */
+
+fastoutsw:
+       stmfd   r13!, {r4}
+
+fastoutswloop:
+       ldr     r3, [r1], #0x0004
+
+       mov     r4, r3, lsl #16
+       orr     r4, r4, lsr #16
+       str     r4, [r0]
+
+       mov     r4, r3, lsr #16
+       orr     r4, r4, lsl #16
+       str     r4, [r0]
+
+       subs    r2, r2, #0x00000002
+       bgt     outswloop
+
+       ldmfd   sp!, {r4}
+
+       mov     pc, lr
+#endif
+
+       .global _insw16
+/*
+ * reads short ints (16 bits) from an I/O address into a block of memory
+ * with a length garenteed to be a multiple of 16 bytes
+ * with a word aligned destination address
+ *
+ * r0 = address to read from (IO)
+ * r1 = address to write to (memory)
+ * r2 = length
+ */
+
+_insw16:
+/* Make sure that we have a positive length */
+       cmp     r2, #0x00000000
+       movle   pc, lr
+
+/* If the destination address and the size is word aligned, do it fast */
+
+       tst     r2, #0x0000000f
+       tsteq   r1, #0x00000003
+
+       bne     _insw
+
+/* Word aligned insw */
+
+       stmfd   r13!, {r4-r7}
+
+insw16loop:
+       ldr     r3, [r0, #0x0002]       /* take advantage of nonaligned
+                                        * word accesses */
+       ldr     r7, [r0]
+       mov     r3, r3, lsr #16         /* Put the two shorts together */
+       orr     r3, r3, r7, lsl #16
+
+       ldr     r4, [r0, #0x0002]       /* take advantage of nonaligned
+                                        * word accesses */
+       ldr     r7, [r0]
+       mov     r4, r4, lsr #16         /* Put the two shorts together */
+       orr     r4, r4, r7, lsl #16
+
+       ldr     r5, [r0, #0x0002]       /* take advantage of nonaligned
+                                        * word accesses */
+       ldr     r7, [r0]
+       mov     r5, r5, lsr #16         /* Put the two shorts together */
+       orr     r5, r5, r7, lsl #16
+
+       ldr     r6, [r0, #0x0002]       /* take advantage of nonaligned
+                                        * word accesses */
+       ldr     r7, [r0]
+       mov     r6, r6, lsr #16         /* Put the two shorts together */
+       orr     r6, r6, r7, lsl #16
+
+       stmia   r1!, {r3-r6}
+       subs    r2, r2, #0x00000008     /* Next */
+       bgt     insw16loop
+
+       ldmfd   r13!, {r4-r7}
+
+       mov     pc, lr
+
+
+#ifdef notyet
+/*
+ * The optimised routines have not been tested yet and I don't feel
+ * like testing the new write code on 2.8 Gig of valuable data.
+ * Need to wait until I hang another HD on my machine
+ */
+       .global _outsw16
+/*
+ * Writes short ints (16 bits) from a block of memory to an I/O address
+ *
+ * r0 = address to write to (IO)
+ * r1 = address to read from (memory)
+ * r2 = length
+ */
+
+_outsw16:
+/* Make sure that we have a positive length */
+       cmp     r2, #0x00000000
+       movle   pc, lr
+
+/* If the destination address and the size is word aligned, do it fast */
+
+       tst     r2, #0x0000000f
+       tsteq   r1, #0x00000003
+
+       bne     _outsw
+
+/* Word aligned outsw */
+
+       stmfd   r13!, {r4-r8}
+
+outsw16loop:
+       ldmia   r1!, {r4-r8}
+
+       mov     r3, r4, lsl #16
+       orr     r3, r3, lsr #16
+       str     r3, [r0]
+
+       mov     r3, r4, lsr #16
+       orr     r3, r4, lsl #16
+       str     r3, [r0]
+
+       mov     r3, r5, lsl #16
+       orr     r3, r3, lsr #16
+       str     r3, [r0]
+
+       mov     r3, r5, lsr #16
+       orr     r3, r4, lsl #16
+       str     r3, [r0]
+
+       mov     r3, r6, lsl #16
+       orr     r3, r3, lsr #16
+       str     r3, [r0]
+
+       mov     r3, r6, lsr #16
+       orr     r3, r4, lsl #16
+       str     r3, [r0]
+
+       mov     r3, r7, lsl #16
+       orr     r3, r3, lsr #16
+       str     r3, [r0]
+
+       mov     r3, r7, lsr #16
+       orr     r3, r4, lsl #16
+       str     r3, [r0]
+
+       subs    r2, r2, #0x00000008
+       bgt     outsw16loop
+
+       ldmfd   sp!, {r4-r8}
+
+       mov     pc, lr
+#endif
diff --git a/sys/arch/arm32/arm32/clock.c b/sys/arch/arm32/arm32/clock.c
new file mode 100644 (file)
index 0000000..203830a
--- /dev/null
@@ -0,0 +1,394 @@
+/* $NetBSD: clock.c,v 1.4 1996/04/19 19:39:17 mark Exp $ */
+
+/*
+ * Copyright (c) 1994-1996 Mark Brinicombe.
+ * Copyright (c) 1994 Brini.
+ * All rights reserved.
+ *
+ * This code is derived from software written for Brini by Mark Brinicombe
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided 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 Brini.
+ * 4. The name of the company nor the name of the author may be used to
+ *    endorse or promote products derived from this software without specific
+ *    prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BRINI ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL BRINI 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.
+ *
+ * RiscBSD kernel project
+ *
+ * clock.c
+ *
+ * Timer related machine specific code
+ *
+ * Created      : 29/09/94
+ */
+
+/* Include header files */
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/time.h>
+
+#include <machine/katelib.h>
+#include <machine/iomd.h>
+#include <machine/irqhandler.h>
+#include <machine/cpu.h>
+#include <machine/rtc.h>
+
+#define TIMER0_COUNT 20000             /* 100Hz */
+#define TIMER_FREQUENCY 20000000       /* 2MHz clock */
+#define TICKS_PER_MICROSECOND (TIMER_FREQUENCY / 10000000)
+
+static irqhandler_t clockirq;
+static irqhandler_t statclockirq;
+
+
+/*
+ * int clockhandler(struct clockframe *frame)
+ *
+ * Function called by timer 0 interrupts. This just calls
+ * hardclock(). Eventually the irqhandler can call hardclock() directly
+ * but for now we use this function so that we can debug IRQ's
+ */
+int
+clockhandler(frame)
+       struct clockframe *frame;
+{
+       hardclock(frame);
+       return(1);
+}
+
+
+/*
+ * int statclockhandler(struct clockframe *frame)
+ *
+ * Function called by timer 1 interrupts. This just calls
+ * statclock(). Eventually the irqhandler can call statclock() directly
+ * but for now we use this function so that we can debug IRQ's
+ */
+int
+statclockhandler(frame)
+       struct clockframe *frame;
+{
+       statclock(frame);
+       return(1);
+}
+
+
+/*
+ * void setstatclockrate(int hz)
+ *
+ * Set the stat clock rate. The stat clock uses timer1
+ */
+
+void
+setstatclockrate(hz)
+       int hz;
+{
+       int count;
+    
+       count = TIMER_FREQUENCY / hz;
+    
+       printf("Setting statclock to %dHz (%d ticks)\n", hz, count);
+    
+       WriteByte(IOMD_T1LOW,  (count >> 0) & 0xff);
+       WriteByte(IOMD_T1HIGH, (count >> 8) & 0xff);
+
+/* reload the counter */
+
+       WriteByte(IOMD_T1GO, 0);
+}
+
+
+/*
+ * void cpu_initclocks(void)
+ *
+ * Initialise the clocks.
+ * This sets up the two timers in the IOMD and installs the IRQ handlers
+ *
+ * NOTE: Currently only timer 0 is setup and the IRQ handler is not installed
+ */
+void
+cpu_initclocks()
+{
+/*
+ * Load timer 0 with count down value
+ * This timer generates 100Hz interrupts for the system clock
+ */
+
+       printf("clock: hz=%d stathz = %d profhz = %d\n", hz, stathz, profhz);
+
+       WriteByte(IOMD_T0LOW,  (TIMER0_COUNT >> 0) & 0xff);
+       WriteByte(IOMD_T0HIGH, (TIMER0_COUNT >> 8) & 0xff);
+
+/* reload the counter */
+
+       WriteByte(IOMD_T0GO, 0);
+
+       clockirq.ih_func = clockhandler;
+       clockirq.ih_arg = 0;
+       clockirq.ih_level = IPL_CLOCK;
+       clockirq.ih_name = "TMR0 hard clk";
+       if (irq_claim(IRQ_TIMER0, &clockirq) == -1)
+               panic("Cannot installer timer 0 IRQ handler\n");
+
+       if (stathz) {
+               setstatclockrate(stathz);
+        
+               statclockirq.ih_func = statclockhandler;
+               statclockirq.ih_arg = 0;
+               statclockirq.ih_level = IPL_CLOCK;
+               if (irq_claim(IRQ_TIMER1, &clockirq) == -1)
+                       panic("Cannot installer timer 1 IRQ handler\n");
+       }
+}
+
+
+/*
+ * void microtime(struct timeval *tvp)
+ *
+ * Fill in the specified timeval struct with the current time
+ * accurate to the microsecond.
+ */
+
+void
+microtime(tvp)
+       struct timeval *tvp;
+{
+       int s;
+       int tm;
+       int deltatm;
+       static int oldtm;
+       static struct timeval oldtv;
+
+       s = splhigh();
+
+/*
+ * Latch the current value of the timer and then read it. This garentees
+ * an atmoic reading of the time.
+ */
+       WriteByte(IOMD_T0LATCH, 0);
+       tm = ReadByte(IOMD_T0LOW) + (ReadByte(IOMD_T0HIGH) << 8);
+       deltatm = tm - oldtm;
+       if (deltatm < 0) deltatm += TIMER0_COUNT;
+       if (deltatm < 0) {
+               printf("opps deltatm < 0 tm=%d oldtm=%d deltatm=%d\n",
+                   tm, oldtm, deltatm);
+       }
+       oldtm = tm;
+
+/* Fill in the timeval struct */
+
+       *tvp = time;    
+       tvp->tv_usec += (deltatm / TICKS_PER_MICROSECOND);
+
+/* Make sure the micro seconds don't overflow. */
+
+       while (tvp->tv_usec > 1000000) {
+               tvp->tv_usec -= 1000000;
+               ++tvp->tv_sec;
+       }
+
+/* Make sure the time has advanced. */
+
+       if (tvp->tv_sec == oldtv.tv_sec &&
+           tvp->tv_usec <= oldtv.tv_usec) {
+               tvp->tv_usec = oldtv.tv_usec + 1;
+               if (tvp->tv_usec > 1000000) {
+                       tvp->tv_usec -= 1000000;
+                       ++tvp->tv_sec;
+               }
+       }
+           
+
+       oldtv = *tvp;
+       (void)splx(s);          
+}
+
+
+void
+need_proftick(p)
+       struct proc *p;
+{
+}
+
+
+static inline int
+yeartoday(year)
+       int year;
+{
+       return((year % 4) ? 365 : 366);
+}
+
+                 
+static int month[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
+static int timeset = 0;
+
+#define SECPERDAY      (24*60*60)
+#define SECPERNYEAR    (365*SECPERDAY)
+#define SECPER4YEARS   (4*SECPERNYEAR+SECPERDAY)
+#define EPOCHYEAR      1970
+
+/*
+ * Write back the time of day to the rtc
+ */
+
+void
+resettodr()
+{
+       int s;
+       time_t year, mon, day, hour, min, sec;
+       rtc_t rtc;
+
+       if (!timeset)
+               return;
+
+       sec = time.tv_sec;
+       year = (sec / SECPER4YEARS) * 4;
+       sec %= SECPER4YEARS;
+
+       /* year now hold the number of years rounded down 4 */
+
+       while (sec > (yeartoday(EPOCHYEAR+year) * SECPERDAY)) {
+               sec -= yeartoday(EPOCHYEAR+year)*SECPERDAY;
+               year++;
+       }
+
+       /* year is now a correct offset from the EPOCHYEAR */
+
+       year+=EPOCHYEAR;
+       mon=0;
+       if (yeartoday(year) == 366)
+               month[1]=29;
+       else
+               month[1]=28;
+       while ((sec/SECPERDAY) > month[mon]) {
+               sec -= month[mon]*SECPERDAY;
+               mon++;
+       }
+
+       day = sec / SECPERDAY;
+       sec %= SECPERDAY;
+       hour = sec / 3600;
+       sec %= 3600;
+       min = sec / 60;
+       sec %= 60;
+       rtc.rtc_cen = year / 100;
+       rtc.rtc_year = year % 100;
+       rtc.rtc_mon = mon+1;
+       rtc.rtc_day = day+1;
+       rtc.rtc_hour = hour;
+       rtc.rtc_min = min;
+       rtc.rtc_sec = sec;
+       rtc.rtc_centi =
+       rtc.rtc_micro = 0;
+
+/*
+       printf("resettod: %d/%d/%d%d %d:%d:%d\n", rtc.rtc_day,
+           rtc.rtc_mon, rtc.rtc_cen, rtc.rtc_year, rtc.rtc_hour,
+           rtc.rtc_min, rtc.rtc_sec);
+*/
+
+       s = splclock();
+       rtc_write(&rtc);
+       (void)splx(s);
+}
+
+/*
+ * Initialise the time of day register, based on the time base which is, e.g.
+ * from a filesystem.
+ */
+
+void
+inittodr(base)
+       time_t base;
+{
+       time_t n;
+       int i, days = 0;
+       int s;
+       int year;
+       rtc_t rtc;
+
+/*
+ * We ignore the suggested time for now and go for the RTC
+ * clock time stored in the CMOS RAM.
+ */
+
+       s = splclock();
+       if (rtc_read(&rtc) == 0) {
+               (void)splx(s);
+               return;
+       }
+
+       (void)splx(s);
+
+       n = rtc.rtc_sec + 60 * rtc.rtc_min + 3600 * rtc.rtc_hour;
+       n += (rtc.rtc_day - 1) * 3600 * 24;
+       year = (rtc.rtc_year + rtc.rtc_cen * 100) - 1900;
+
+       if (yeartoday(year) == 366)
+               month[1] = 29;
+       for (i = rtc.rtc_mon - 2; i >= 0; i--)
+               days += month[i];
+       month[1] = 28;
+
+       for (i = 70; i < year; i++)
+               days += yeartoday(i);
+
+       n += days * 3600 * 24;
+
+       n += tz.tz_minuteswest * 60;
+       if (tz.tz_dsttime)
+               n -= 3600;
+
+       time.tv_sec = n;
+       time.tv_usec = 0;
+
+/* timeset is used to ensure the time is valid before a resettodr() */
+
+       timeset = 1;
+
+/* If the base was 0 then keep quiet */
+
+       if (base) {
+               printf("inittodr: %02d:%02d:%02d.%02d%02d %02d/%02d/%02d%02d\n",
+                   rtc.rtc_hour, rtc.rtc_min, rtc.rtc_sec, rtc.rtc_centi,
+                   rtc.rtc_micro, rtc.rtc_day, rtc.rtc_mon, rtc.rtc_cen,
+                   rtc.rtc_year);
+
+               if (n > base + 60) {
+                       days = (n - base) / SECPERDAY;
+                       printf("Clock has gained %d day%c %ld hours %ld minutes %ld secs\n",
+                           days, ((days == 1) ? 0 : 's'), ((n - base)  / 3600) % 24,
+                           ((n - base) / 60) % 60, (n - base) % 60);
+               }
+       }
+}  
+
+/* End of clock.c */
diff --git a/sys/arch/arm32/arm32/conf.c b/sys/arch/arm32/arm32/conf.c
new file mode 100644 (file)
index 0000000..8262efd
--- /dev/null
@@ -0,0 +1,437 @@
+/* $NetBSD: conf.c,v 1.6 1996/04/19 19:40:29 mark Exp $ */
+
+/*
+ * Copyright (c) 1994 Mark Brinicombe.
+ * Copyright (c) 1994 Brini.
+ * All rights reserved.
+ *
+ * This code is derived from software written for Brini by Mark Brinicombe
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided 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 Brini.
+ * 4. The name of the company nor the name of the author may be used to
+ *    endorse or promote products derived from this software without specific
+ *    prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BRINI ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL BRINI 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.
+ *
+ * RiscBSD kernel project
+ *
+ * conf.c
+ *
+ * Character and Block Device configuration
+ * Console configuration
+ *
+ * Defines the structures cdevsw and constab
+ *
+ * Created      : 17/09/94
+ */
+#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 *));
+
+#ifndef LKM
+#define lkmenodev       enodev
+#else
+int     lkmenodev();
+#endif
+
+#include "wdc.h"
+bdev_decl(wd);
+bdev_decl(sw);
+#include "fdc.h"
+bdev_decl(fd);
+#include "rd.h"
+bdev_decl(rd);
+#include "sd.h"
+bdev_decl(sd);
+#include "st.h"
+bdev_decl(st);
+#include "cd.h"
+bdev_decl(cd);
+#include "vnd.h"
+bdev_decl(vnd);
+#include "ccd.h"
+bdev_decl(ccd);
+/* Temporary hack for ATAPI CDROM */
+#include "wcd.h"
+bdev_decl(wcd);
+
+/* Block devices */
+
+struct bdevsw bdevsw[] = {
+       bdev_lkm_dummy(),               /*  0: */
+       bdev_swap_init(1, sw),          /*  1: swap pseudo-device */
+       bdev_lkm_dummy(),               /*  2: */
+       bdev_lkm_dummy(),               /*  3: */
+       bdev_lkm_dummy(),               /*  4: */
+       bdev_lkm_dummy(),               /*  5: */
+       bdev_lkm_dummy(),               /*  6: */
+       bdev_lkm_dummy(),               /*  7: */
+       bdev_lkm_dummy(),               /*  8: */
+       bdev_lkm_dummy(),               /*  9: */
+       bdev_lkm_dummy(),               /* 10: */
+       bdev_lkm_dummy(),               /* 11: */
+       bdev_lkm_dummy(),               /* 12: */
+       bdev_lkm_dummy(),               /* 13: */
+       bdev_lkm_dummy(),               /* 14: */
+       bdev_lkm_dummy(),               /* 15: */
+       bdev_disk_init(NWDC, wd),       /* 16: Internal IDE disk */
+       bdev_disk_init(NFDC, fd),       /* 17: floppy diskette */
+       bdev_disk_init(NRD, rd),        /* 18: ramdisk */
+       bdev_disk_init(NVND,vnd),       /* 19: vnode disk driver */
+       bdev_disk_init(NWCD, wcd),      /* 20: */
+       bdev_disk_init(NCCD,ccd),       /* 21: concatenated disk driver */
+       bdev_lkm_dummy(),               /* 22: */
+       bdev_lkm_dummy(),               /* 23: */
+       bdev_disk_init(NSD,sd),         /* 24: SCSI disk */
+       bdev_tape_init(NST,st),         /* 25: SCSI tape */
+       bdev_disk_init(NCD,cd),         /* 26: SCSI cdrom */
+       bdev_lkm_dummy(),               /* 27: */
+       bdev_lkm_dummy(),               /* 28: */
+       bdev_lkm_dummy(),               /* 29: */
+       bdev_lkm_dummy(),               /* 30: */
+       bdev_lkm_dummy(),               /* 31: */
+       bdev_lkm_dummy(),               /* 32: */
+       bdev_lkm_dummy(),               /* 33: */
+       bdev_lkm_dummy(),               /* 34: */
+       bdev_lkm_dummy(),               /* 35: */
+       bdev_lkm_dummy(),               /* 36: */
+       bdev_lkm_dummy(),               /* 37: */
+       bdev_lkm_dummy(),               /* 38: */
+       bdev_lkm_dummy(),               /* 39: */
+       bdev_lkm_dummy(),               /* 40: */
+       bdev_lkm_dummy(),               /* 41: */
+       bdev_lkm_dummy(),               /* 42: */
+       bdev_lkm_dummy(),               /* 43: */
+  };
+
+int nblkdev = sizeof(bdevsw) / sizeof(bdevsw[0]);
+
+
+/* Character device declarations */
+
+/* open, close, read, write, ioctl, tty, mmap */
+#define cdev_physcon_init(c,n) { \
+       dev_init(c,n,open), dev_init(c,n,close), dev_init(c,n,read), \
+       dev_init(c,n,write), dev_init(c,n,ioctl), dev_init(c,n,stop), \
+       dev_init(c,n,tty), ttselect, dev_init(c,n,mmap), 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 }
+
+/* open, close, write, ioctl */
+#define cdev_beep_init(c,n) { \
+       dev_init(c,n,open), dev_init(c,n,close), (dev_type_read((*))) enodev, \
+       (dev_type_write((*))) enodev, dev_init(c,n,ioctl), \
+       (dev_type_stop((*))) enodev, \
+       0, seltrue, (dev_type_mmap((*))) enodev, 0 }
+
+/* open, close, write, ioctl */
+#define cdev_kbd_init(c,n) { \
+       dev_init(c,n,open), dev_init(c,n,close), dev_init(c,n,read), \
+       (dev_type_write((*))) enodev, dev_init(c,n,ioctl), \
+       (dev_type_stop((*))) enodev, \
+       0, dev_init(c,n,select), (dev_type_mmap((*))) enodev, 0 }
+
+/* open, close, write, ioctl */
+#define cdev_cpu_init(c,n) { \
+       dev_init(c,n,open), dev_init(c,n,close), (dev_type_read((*))) enodev, \
+       (dev_type_write((*))) enodev, dev_init(c,n,ioctl), \
+       (dev_type_stop((*))) enodev, \
+       0, seltrue, (dev_type_mmap((*))) enodev, 0 }
+
+/* open, close, write, ioctl */
+#define cdev_vidcvid_init(c,n) { \
+       dev_init(c,n,open), dev_init(c,n,close), (dev_type_read((*))) enodev, \
+       (dev_type_write((*))) enodev, dev_init(c,n,ioctl), \
+       (dev_type_stop((*))) enodev, \
+       0, seltrue, dev_init(c,n,mmap), 0 }
+
+/* open, close, write, ioctl */
+#define cdev_uk_init(c,n) { \
+       dev_init(c,n,open), dev_init(c,n,close), dev_init(c,n,read), \
+       dev_init(c,n,write), dev_init(c,n,ioctl), \
+       (dev_type_stop((*))) enodev, \
+       0, seltrue, (dev_type_mmap((*))) enodev, 0 }
+
+/* open, close, read, ioctl */
+#define cdev_ss_init(c,n) { \
+       dev_init(c,n,open), dev_init(c,n,close), dev_init(c,n,read), \
+       (dev_type_write((*))) enodev, dev_init(c,n,ioctl), \
+       (dev_type_stop((*))) enodev, 0, seltrue, \
+       (dev_type_mmap((*))) enodev }
+
+/* open, close, write, ioctl */
+#define cdev_iic_init(c,n) { \
+       dev_init(c,n,open), dev_init(c,n,close), dev_init(c,n,read), \
+       dev_init(c,n,write), dev_init(c,n,ioctl), (dev_type_stop((*))) enodev, \
+       0, seltrue, (dev_type_mmap((*))) enodev, 0 }
+
+/* open, close, write, ioctl */
+#define cdev_rtc_init(c,n) { \
+       dev_init(c,n,open), dev_init(c,n,close), dev_init(c,n,read), \
+       dev_init(c,n,write), dev_init(c,n,ioctl), (dev_type_stop((*))) enodev, \
+       0, seltrue, (dev_type_mmap((*))) enodev, 0 }
+
+cdev_decl(cn);
+cdev_decl(ctty);
+#include "vt.h"                                 
+cdev_decl(physcon);
+cdev_decl(vidcvideo);
+#define mmread  mmrw
+#define mmwrite mmrw
+cdev_decl(mm);
+cdev_decl(wd);
+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 "com.h"
+cdev_decl(com);
+#include "lpt.h"
+cdev_decl(lpt);
+cdev_decl(fd);
+dev_decl(filedesc,open);
+cdev_decl(rd);
+#include "bpfilter.h"
+cdev_decl(bpf);
+cdev_decl(sd);
+cdev_decl(st);
+cdev_decl(cd);
+#include "ch.h"
+cdev_decl(ch);
+#include "uk.h"
+cdev_decl(uk);
+#include "ss.h"
+cdev_decl(ss);
+#ifdef LKM
+#define        NLKM    1
+#else
+#define        NLKM    0
+#endif
+cdev_decl(lkm);
+#include "tun.h"
+cdev_decl(tun);
+cdev_decl(vnd);
+cdev_decl(ccd);
+#include "quadmouse.h"
+cdev_decl(quadmouse);
+#include "pms.h"
+cdev_decl(pms);
+#include "beep.h"
+cdev_decl(beep);
+#include "kbd.h"
+cdev_decl(kbd);
+#include "audio.h"
+cdev_decl(audio);
+#include "cpu.h"
+cdev_decl(cpu);
+#include "iic.h"
+cdev_decl(iic);
+#include "rtc.h"
+cdev_decl(rtc);
+/* Temporary hack for ATAPI CDROM */
+cdev_decl(wcd);
+
+/* Character devices */
+
+struct cdevsw cdevsw[] = {
+       cdev_mm_init(1, mm),            /*  0: /dev/{null,mem,kmem,...} */
+       cdev_swap_init(1, sw),          /*  1: /dev/drum (swap pseudo-device) */
+       cdev_cn_init(1, cn),            /*  2: virtual console */
+       cdev_ctty_init(1,ctty),         /*  3: controlling terminal */
+       cdev_physcon_init(NVT, physcon),  /*  4: RPC console */
+        cdev_log_init(1,log),           /*  5: /dev/klog */
+       cdev_ptc_init(NPTY,ptc),        /*  6: pseudo-tty master */
+       cdev_tty_init(NPTY,pts),        /*  7: pseudo-tty slave */
+       cdev_lpt_init(NLPT,lpt),        /*  8: parallel printer */
+       cdev_mouse_init(NQUADMOUSE,quadmouse),       /* 9: quadmouse driver */
+       cdev_beep_init(NBEEP,beep),     /* 10: simple beep device */
+       cdev_kbd_init(NKBD,kbd),        /* 11: kbd device */
+       cdev_tty_init(NCOM,com),        /* 12: serial port */
+       cdev_lkm_dummy(),               /* 13: */
+       cdev_lkm_dummy(),               /* 14: */
+       cdev_lkm_dummy(),               /* 15: */
+       cdev_disk_init(NWDC, wd),       /* 16: ST506/ESDI/IDE disk */
+       cdev_disk_init(NFDC, fd),       /* 17: floppy diskette */
+       cdev_disk_init(NRD, rd),        /* 18: ram disk driver */
+       cdev_disk_init(NVND,vnd),       /* 19: vnode disk driver */
+       cdev_disk_init(NWCD, wcd),      /* 20: */
+       cdev_disk_init(NCCD,ccd),       /* 21: concatenated disk driver */
+       cdev_lkm_dummy(),               /* 22: */
+       cdev_lkm_dummy(),               /* 23: */
+       cdev_disk_init(NSD,sd),         /* 24: SCSI disk */
+       cdev_tape_init(NST,st),         /* 25: SCSI tape */
+       cdev_disk_init(NCD,cd),         /* 26: SCSI CD-ROM */
+       cdev_ch_init(NCH,ch),           /* 27: SCSI autochanger */
+       cdev_ch_init(NUK,uk),           /* 28: SCSI unknown */
+       cdev_ss_init(NSS,ss),           /* 29: SCSI scanner */
+       cdev_lkm_dummy(),               /* 30: */
+       cdev_lkm_dummy(),               /* 31: */
+       cdev_bpftun_init(NBPFILTER,bpf),/* 32: Berkeley packet filter */
+        cdev_bpftun_init(NTUN,tun),     /* 33: network tunnel */
+        cdev_fd_init(1,filedesc),       /* 34: file descriptor pseudo-device */
+       cdev_lkm_init(NLKM,lkm),        /* 35: loadable module driver */
+       cdev_audio_init(NAUDIO,audio),  /* 36: generic audio I/O */
+       cdev_vidcvid_init(1,vidcvideo), /* 37: vidcvideo device */
+       cdev_cpu_init(NCPU,cpu),        /* 38: cpu device */
+       cdev_lkm_dummy(),               /* 39: */
+       cdev_mouse_init(NPMS,pms),      /* 40: PS2 mouse driver */
+       cdev_lkm_dummy(),               /* 41: */
+       cdev_iic_init(NIIC, iic),       /* 42: IIC bus driver */
+       cdev_rtc_init(NRTC, rtc),       /* 43: RTC driver */
+};
+
+int nchrdev = sizeof(cdevsw) / sizeof(cdevsw[0]);
+
+int mem_no = 0;        /* major device number of memory special file */
+
+
+/*
+ * Returns true if dev is /dev/mem or /dev/kmem.
+ */
+int
+iskmemdev(dev)
+       dev_t dev;
+{
+       return (major(dev) == mem_no && minor(dev) < 2);
+}
+
+/*
+ * Returns true if dev is /dev/zero.
+ */
+int
+iszerodev(dev)
+       dev_t dev;
+{
+       return (major(dev) == mem_no && minor(dev) == 3);
+}
+
+
+static int chrtoblktbl[] = {
+/* XXXX This needs to be dynamic for LKMs. */
+    /*VCHR*/        /*VBLK*/
+    /*  0 */        NODEV,
+    /*  1 */        1,
+    /*  2 */        NODEV,
+    /*  3 */        NODEV,
+    /*  4 */        NODEV,
+    /*  5 */        NODEV,
+    /*  6 */        NODEV,
+    /*  7 */        NODEV,
+    /*  8 */        NODEV,
+    /*  9 */        NODEV,
+    /* 10 */        NODEV,
+    /* 11 */        NODEV,
+    /* 12 */        NODEV,
+    /* 13 */        NODEV,
+    /* 14 */        NODEV,
+    /* 15 */        NODEV,
+    /* 16 */        16,
+    /* 17 */        17,
+    /* 18 */        18,
+    /* 19 */        19,
+    /* 20 */        20,
+    /* 21 */        21,
+    /* 22 */        NODEV,
+    /* 23 */        NODEV,
+    /* 24 */        24,
+    /* 25 */        25,
+    /* 26 */        26,
+    /* 27 */        NODEV,
+    /* 28 */        NODEV,
+    /* 29 */        NODEV,
+    /* 30 */        NODEV,
+    /* 31 */        NODEV,
+    /* 32 */        NODEV,
+    /* 33 */        NODEV,
+    /* 34 */        NODEV,
+    /* 35 */        NODEV,
+    /* 36 */        NODEV,
+    /* 37 */        NODEV,
+    /* 38 */        NODEV,
+    /* 39 */        NODEV,
+    /* 40 */        NODEV,
+    /* 41 */        NODEV,
+    /* 42 */        NODEV,
+    /* 43 */        NODEV,
+};
+
+/*
+ * Convert a character device number to a block device number.
+ */
+dev_t
+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(rpcconsole);
+cons_decl(com);   
+       
+struct consdev constab[] = {
+#if (NVT + NRPC > 0)
+       cons_init(rpcconsole),
+#endif
+
+/*#if (NCOM > 0)
+       cons_init(com),
+#endif*/
+       { 0 },
+};
+                           
+/* End of conf.c */
diff --git a/sys/arch/arm32/arm32/coproc15.S b/sys/arch/arm32/arm32/coproc15.S
new file mode 100644 (file)
index 0000000..ceb3a0d
--- /dev/null
@@ -0,0 +1,150 @@
+/* $NetBSD: coproc15.S,v 1.1 1996/01/31 23:15:33 mark Exp $ */
+
+/*
+ * Copyright (c) 1994 Mark Brinicombe.
+ * Copyright (c) 1994 Brini.
+ * All rights reserved.
+ *
+ * This code is derived from software written for Brini by Mark Brinicombe
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided 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 Brini.
+ * 4. The name of the company nor the name of the author may be used to
+ *    endorse or promote products derived from this software without specific
+ *    prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BRINI ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL BRINI 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.
+ *
+ * RiscBSD kernel project
+ *
+ * coproc15.S 
+ *
+ * Manipulation of the CPU internal coprocessor #15 registers
+ *
+ * Created      : 29/11/94
+ * Last updated : 28/08/95
+ *
+ * Based on arm/readcoproc15.S & arm/writecoproc15.S
+ *
+ *    $Id: coproc15.S,v 1.1.1.1 1996/04/24 11:08:24 deraadt Exp $
+ */
+
+lr     .req    r14
+pc     .req    r15
+
+.text
+/*
+ * Functions to read the internal coprocessor registers
+ *
+ * Currently the only registers that can be read are
+ *  r0 - CPU ID
+ *  r5 - Fault status
+ *  r6 - Fault address
+ *
+ * Eventually these should be inlined.
+ */
+
+       .global _cpu_id
+
+_cpu_id:
+       mrc     15, 0, r0, c0, c0, 0
+       mov     pc, lr
+
+       .global _cpu_faultstatus
+
+_cpu_faultstatus:
+       mrc     15, 0, r0, c5, c0, 0
+       mov     pc, lr
+
+       .global _cpu_faultaddress
+
+_cpu_faultaddress:
+       mrc     15, 0, r0, c6, c0, 0
+       mov     pc, lr
+
+
+/*
+ * Functions to write the internal coprocessor registers
+ *
+ *
+ * Currently the only registers that can be write are
+ *  r1 - CPU Control
+ *  r2 - TTB
+ *  r3 - Domain Access Control
+ *  r5 - Flush TLB
+ *  r6 - Purge TLB
+ *  r7 - Flush IDC
+ *
+ * Eventually these should be inlined.
+ */
+       .global _cpu_control
+
+_cpu_control:
+       mcr     15, 0, r0, c1, c0, 0
+       mov     pc, lr
+
+       .global _setttb
+
+_setttb:
+/* We need to flush the cache as it uses virtual addresses that are about to change */
+       mcr     15, 0, r0, c7, c0, 0
+
+/* Write the TTB */
+       mcr     15, 0, r0, c2, c0, 0
+
+/* If we have updated the TTB we must flush the TLB */
+       mcr     15, 0, r0, c5, c0, 0
+
+/* For good measure we will flush the IDC as well - do we need this */
+       mcr     15, 0, r0, c7, c0, 0
+
+/* Make sure that pipeline is emptied */
+
+       mov     r0, r0
+       mov     r0, r0
+
+       mov     pc, lr
+
+       .global _cpu_domains
+
+_cpu_domains:
+       mcr     15, 0, r0, c3, c0, 0
+       mov     pc, lr
+
+       .global _tlbflush
+
+_tlbflush:
+       mcr     15, 0, r0, c5, c0, 0
+       mov     pc, lr
+
+       .global _tlbpurge
+
+_tlbpurge:
+       mcr     15, 0, r0, c6, c0, 0
+       mov     pc, lr
+
+       .global _idcflush
+
+_idcflush:
+       mcr     15, 0, r0, c7, c0, 0
+       mov     pc, lr
diff --git a/sys/arch/arm32/arm32/copystr.S b/sys/arch/arm32/arm32/copystr.S
new file mode 100644 (file)
index 0000000..0c22370
--- /dev/null
@@ -0,0 +1,132 @@
+/* $NetBSD: copystr.S,v 1.4 1996/03/27 22:19:32 mark Exp $ */
+
+/*
+ * Copyright (c) 1995 Mark Brinicombe.
+ * Copyright (c) 1995 Brini.
+ * All rights reserved.
+ *
+ * This code is derived from software written for Brini by Mark Brinicombe
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided 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 Brini.
+ * 4. The name of the company nor the name of the author may be used to
+ *    endorse or promote products derived from this software without specific
+ *    prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BRINI ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL BRINI 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.
+ *
+ * RiscBSD kernel project
+ *
+ * copystr.S
+ *
+ * optimised and fault protected copystr function
+ *
+ * Created      : 16/05/95
+ */
+
+#include "assym.h"
+#include <sys/errno.h>
+
+sp     .req    r13
+lr     .req    r14
+pc     .req    r15
+
+       .text
+Lcurpcb:
+       .word   _curpcb
+
+Lcurproc:
+       .word   _curproc
+
+copystrfault:
+       mov     r0, #0x00000000
+       str     r0, [r4, #PCB_ONFAULT]
+       mov     r0, #EFAULT
+       ldmfd   sp!, {r4-r6}
+       mov     pc, lr
+
+copystrpcbfault:
+       stmfd   sp!, {lr}
+       mov     r3, r1
+       mov     r1, r4
+       add     r0, pc, #copystrtext - . - 8
+       mov     r2, r3
+       ldr     r3, Lcurproc
+       ldr     r3, [r3]
+       bl      _printf
+
+       bl      _traceback
+
+       mov     r0, #EFAULT
+       ldmfd   sp!, {lr}
+       ldmfd   sp!, {r4-r6}
+       mov     pc, lr
+
+copystrtext:
+       .asciz  "Alert ! PCB = %08x during copystr addr=%08x curproc=%08x\n"
+
+       .align  0
+
+/*
+ * r0 - from
+ * r1 - to
+ * r2 - maxlens
+ * r3 - lencopied
+ */
+
+       .global _copystrinout
+
+_copystrinout:
+       stmfd   sp!, {r4-r6}
+       teq     r2, #0x00000000
+       moveq   r5, #0x00000000
+       moveq   r6, #0x00000000
+       beq     copystrexit
+
+       ldr     r4, Lcurpcb
+       ldr     r4, [r4]
+       teq     r4, #0x00000000
+       beq     copystrpcbfault
+       add     r5, pc, #copystrfault - . - 8
+       str     r5, [r4, #PCB_ONFAULT]
+       mov     r6, #0x00000000
+
+copystr_loop:
+       ldrb    r5, [r0], #0x0001
+       strb    r5, [r1], #0x0001
+       add     r6, r6, #0x00000001
+       teq     r5, #0x00000000
+       teqne   r6, r2
+       bne     copystr_loop
+
+copystrexit:
+       teq     r3, #0x00000000
+       strne   r6, [r3]
+
+       teq     r5, #0x00000000
+       moveq   r0, #0x00000000
+       movne   r0, #ENAMETOOLONG
+
+       mov     r6, #0x00000000
+       str     r6, [r4, #PCB_ONFAULT]
+       ldmfd   sp!, {r4-r6}
+       mov     pc, lr
diff --git a/sys/arch/arm32/arm32/cpuswitch.S b/sys/arch/arm32/arm32/cpuswitch.S
new file mode 100644 (file)
index 0000000..e40d6c5
--- /dev/null
@@ -0,0 +1,786 @@
+/* $NetBSD: cpuswitch.S,v 1.6 1996/03/27 21:24:39 mark Exp $ */
+
+/*
+ * Copyright (c) 1994-1996 Mark Brinicombe.
+ * Copyright (c) 1994 Brini.
+ * All rights reserved.
+ *
+ * This code is derived from software written for Brini by Mark Brinicombe
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided 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 Brini.
+ * 4. The name of the company nor the name of the author may be used to
+ *    endorse or promote products derived from this software without specific
+ *    prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BRINI ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL BRINI 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.
+ *
+ * RiscBSD kernel project
+ *
+ * cpu.S
+ *
+ * cpu switching functions
+ *
+ * Created      : 15/10/94
+ */
+
+#include "assym.h"
+#include <machine/param.h>
+#include <machine/cpu.h>
+
+sp     .req    r13
+lr     .req    r14
+pc     .req    r15
+
+/*
+ * PULLFRAME - macro to pull a trap frame from the stack in the current mode
+ * Since the current mode is used, the SVC R14 field is ignored.
+ */
+
+#define PULLFRAME \
+        ldr     r0, [sp], #0x0004;      /* Get the SPSR from stack */ \
+        msr     spsr_all, r0; \
+       add     sp, sp, #(4*15);        /* Adjust the stack pointer */ \
+        ldmdb   sp, {r0-r14}^;         /* Restore the registers (user mode) */ \
+        mov     r0, r0;                 /* NOP for previous instruction */ \
+       add     sp, sp, #0x00000004;    /* Skip SVC R14 */ \
+       ldr     lr, [sp], #0x0004;      /* Pull the return address */
+
+/*
+ * setrunqueue() and remrq()
+ *
+ * Functions to add and remove a process for the run queue.
+ */
+
+       .text
+
+Lwhichqs:
+       .word   _whichqs
+
+Lqs:
+       .word   _qs
+
+/*
+ * On entry
+ *     r0 = process
+ */
+
+       .global _setrunqueue
+_setrunqueue:
+/*
+ * Local register usage
+ *     r0 = process
+ *     r1 = queue
+ *     r2 = &qs[queue]
+ *     r3 = temp
+ *     r4 = whichqs
+ */
+       stmfd   sp!, {r4}
+
+#ifdef DIAGNOSTIC
+       ldr     r1, [r0, #(P_BACK)]
+       teq     r1, #0x00000000
+       bne     Lsetrunqueue_erg
+
+       ldr     r1, [r0, #(P_WCHAN)]
+       teq     r1, #0x00000000
+       bne     Lsetrunqueue_erg
+#endif
+
+/* Get the priority of the queue */
+
+       ldrb    r1, [r0, #(P_PRIORITY)]
+       mov     r1, r1, lsr #2
+
+/* Indicate that there is a process on this queue */
+
+       ldr     r4, Lwhichqs
+       ldr     r2, [r4]
+       mov     r3, #0x00000001
+       mov     r3, r3, lsl r1
+       orr     r2, r2, r3
+       str     r2, [r4]
+
+/* Get the address of the queue */
+
+       ldr     r2, Lqs
+       add     r1, r2, r1, lsl # 3
+
+/* Hook the process in */
+       str     r1, [r0, #(P_FORW)]
+       ldr     r2, [r1, #(P_BACK)]
+
+       str     r0, [r1, #(P_BACK)]
+#ifdef DIAGNOSTIC
+       teq     r2, #0x00000000
+       beq     Lsetrunqueue_erg
+#endif
+       str     r0, [r2, #(P_FORW)]
+       str     r2, [r0, #(P_BACK)]
+
+       ldmfd   sp!, {r4}
+
+       mov     pc, lr
+
+#ifdef DIAGNOSTIC
+Lsetrunqueue_erg:
+       mov     r2, r1
+       mov     r1, r0
+       add     r0, pc, #Ltext1 - . - 8
+       bl      _printf
+
+       ldr     r2, Lqs
+       ldr     r1, [r2]
+       add     r0, pc, #Ltext2 - . - 8
+       b       _panic  
+
+Ltext1:
+       .asciz  "setrunqueue : %08x %08x\n"
+Ltext2:
+       .asciz  "setrunqueue : [qs]=%08x qs=%08x\n"
+       .align  0
+#endif
+
+/*
+ * On entry
+ *     r0 = process
+ */
+
+       .global _remrq
+_remrq:
+
+/*
+ * Local register usage
+ *     r0 = oldproc
+ *     r1 = queue
+ *     r2 = &qs[queue]
+ *     r3 = scratch
+ *     r4 = whichqs
+ */
+       stmfd   sp!, {r4}
+
+/* Get the priority of the queue */
+
+       ldrb    r1, [r0, #(P_PRIORITY)]
+       mov     r1, r1, lsr #2
+
+/* Unhook the process */
+
+       ldr     r2, [r0, #(P_FORW)]
+       ldr     r3, [r0, #(P_BACK)]
+
+       str     r3, [r2, #(P_BACK)]
+       str     r2, [r3, #(P_FORW)]
+
+/* If the queue is now empty clear the queue not empty flag */
+
+       teq     r2, r3
+
+/* This could be reworked to avoid the use of r4 */
+
+       ldreq   r4, Lwhichqs
+       ldreq   r2, [r4]
+       moveq   r3, #0x00000001
+       moveq   r3, r3, lsl r1
+       biceq   r2, r2, r3
+       streq   r2, [r4]
+
+/* Remove the back pointer for the process */
+
+       mov     r1, #0x00000000
+       str     r1, [r0, #(P_BACK)]
+
+       ldmfd   sp!, {r4}
+
+       mov     pc, lr
+
+
+/*
+ * cpuswitch()
+ *
+ * preforms a process context switch.
+ * This function has several entry points
+ */
+
+
+Lcurproc:
+       .word   _curproc
+
+       .global _curpcb
+
+_curpcb:
+       .word   0x00000000
+
+Lcurpcb:
+       .word   _curpcb
+
+Lwant_resched:
+       .word   _want_resched
+
+
+/*
+ * Idle loop, exercised while waiting for a process to wake up.
+ */
+
+       .global _idle
+_idle:
+idle:
+
+/* Enable interrupts */
+
+       IRQenable
+
+#ifdef CPU_ARM7500
+/* ARM7500 has a suspend mode so use it ! [danny, does this work ? - mark] */
+
+       mov     r7, #(IOMD_BASE)
+       orr     r7, r7, #(IOMD_SUSPEND - IOMD_BASE)
+       mov     r3, #0x00000001
+       strb    r3, [r7]
+#endif
+
+/* Disable interrupts while we check for an active queue */
+
+       IRQdisable
+       ldr     r7, Lwhichqs
+       ldr     r3, [r7]
+       teq     r3, #0x00000000
+       bne     sw1
+
+/* All processes are still asleep so idle a while longer */
+
+       b       idle
+
+
+/*
+ * Find a new process to run, save the current context and
+ * load the new context
+ */
+
+       .global _cpu_switch
+_cpu_switch:
+/*
+ * Local register usage. Some of these registers are out of date.
+ * r1 = oldproc
+ * r2 = spl level
+ * r3 = whichqs
+ * r4 = queue
+ * r5 = &qs[queue]
+ * r6 = newproc
+ * r7 = scratch
+ */
+       stmfd   sp!, {r4-r7, lr}
+
+/*
+ * Get the current process and indicate that there is no longer a valid
+ * process (curproc = 0)
+ */
+
+       ldr     r7, Lcurproc
+       ldr     r1, [r7]
+       mov     r0, #0x00000000
+       str     r0, [r7]
+
+/* Zero the pcb */
+
+       ldr     r7, Lcurpcb
+       str     r0, [r7]
+
+/* Lower the spl level to spl0 and get the current spl level. */
+
+       mov     r7, r1
+
+#ifdef spl0
+       mov     r0, #(SPL_0)
+       bl      _splx
+#else
+       bl      _spl0
+#endif
+
+/* Push the old spl level onto the stack */
+
+       str     r0, [sp, #-0x0004]!
+
+       mov     r1, r7
+
+/* First phase : find a new process */
+
+/* rem: r1 = old proc */
+
+switch_search:
+       IRQdisable
+
+/* Do we have any active queues  */
+
+       ldr     r7, Lwhichqs
+       ldr     r3, [r7]
+
+/* If not we must idle until we do. */
+
+       teq     r3, #0x00000000
+       beq     idle
+
+sw1:
+/* rem: r1 = old proc */
+/* rem: r3 = whichqs */
+/* rem: interrupts are disabled */
+
+/*
+ * Paranoid debug time ....
+ * Is this overkill ? If we are not in SVC mode then things are
+ * very sick and will probably have already died.
+ */
+
+#ifdef DIAGNOSTIC
+       mrs     r4, cpsr_all
+       and     r4, r4, #(PSR_MODE)
+       teq     r4, #(PSR_SVC32_MODE)
+       beq     switchmodeok
+
+       add     r0, pc, #switchpanic - . - 8
+       mrs     r1, cpsr_all
+       bl      _panic
+
+switchpanic:
+       .asciz  "Yikes! In cpu_switch() but not in SVC mode (%08x)\n"
+       .align  0
+
+switchmodeok:
+#endif
+
+/*
+ * We have found an active queue. Currently we do not know which queue
+ * is active just that one of them is.
+ * We must check each queue to find the active one.
+ * r3 contains a bit for each of the 32 queues. A one indicates that
+ * that the queue has something in it.
+ */
+
+/* This ffs() type routine code be optimised */
+
+       mov     r4, #0x00000000
+
+findqueue:
+       mov     r0, #0x00000001
+       mov     r0, r0, lsl r4
+
+       tst     r3, r0
+       addeq   r4, r4, #0x00000001
+       beq     findqueue
+
+/*
+ * Ok we have found the active queue. The above code can never fail as
+ * we only get to it if r3 != 0
+ * r4 contains the number of the first queue found with a process in it.
+ */
+
+/* rem: r0 = bit mask of chosen queue (1 << r4) */
+/* rem: r1 = old proc */
+/* rem: r3 = whichqs */
+/* rem: r4 = queue number */
+/* rem: interrupts are disabled */
+
+/* Get the address of the queue (&qs[queue]) */
+
+       ldr     r5, Lqs
+       add     r5, r5, r4, lsl #3
+
+/*
+ * Get the process from the queue and place the next process in the queue
+ * at the head. This basically unlinks the process at the head of the queue.
+ */
+       ldr     r6, [r5, #(P_FORW)]
+
+/* rem: r6 = new process */
+
+       ldr     r7, [r6, #(P_FORW)]
+       str     r7, [r5, #(P_FORW)]     
+
+/*
+ * Test to see if the queue is now empty. If the head of the queue points
+ * to the queue itself then there are no more processes in the queue.
+ * We can therefore clear the queue not empty flag held in r3.
+ */
+
+       teq     r5, r7
+       biceq   r3, r3, r0
+
+/* rem: r0 = bit mask of chosen queue (1 << r4) - NOT NEEDED AN MORE */
+
+/* Fix the back pointer for the process now at the head of the queue. */
+
+       ldr     r0, [r6, #(P_BACK)]
+       str     r0, [r7, #(P_BACK)]
+
+/* Update the RAM copy of the queue not empty flags word. */
+
+       ldr     r7, Lwhichqs
+       str     r3, [r7]
+
+/* rem: r1 = old proc */
+/* rem: r3 = whichqs - NOT NEEDED ANY MORE */
+/* rem: r4 = queue number - NOT NEEDED ANY MORE */
+/* rem: r6 = new process */
+/* rem: interrupts are disabled */
+
+/* Clear the want_resched flag */
+
+       mov     r0, #0x00000000
+       ldr     r7, Lwant_resched
+       str     r0, [r7]
+
+/*
+ * Clear the back pointer of the process we have removed from the head
+ * of the queue. The new process is isolated now.
+ */
+
+       mov     r0, #0x00000000
+       str     r0, [r6, #(P_BACK)]
+
+/* We have a new curproc now so make a note it */
+
+       ldr     r7, Lcurproc
+       str     r6, [r7]
+
+/* Hook in a new pcb */
+
+       ldr     r7, Lcurpcb
+       ldr     r0, [r6, #(P_ADDR)]
+       str     r0, [r7]
+
+/* At this point we can allow IRQ's again. */
+
+/*
+       IRQenable
+       IRQdisable
+*/
+
+/* rem: r1 = old proc */
+/* rem: r6 = new process */
+/* rem: interrupts are disabled */
+
+/*
+ * If the new process is the same as the process that called cpu_switch
+ * Then we do not need to save and restore any contexts. This means
+ * we can make a quick exit.
+ * The test is simple if curproc on entry (now in r1) is the same as the
+ * proc removed from the queue we can jump to the exit.
+ */
+
+       teq     r1, r6
+       beq     switch_return
+
+/*
+ * If the curproc on entry to cpu_switch was zero then the process that
+ * called it was exiting. This means that we do not need to save the current
+ * context. Instead we can jump straight to restoring the context for
+ * the new process.
+ */
+
+       teq     r1, #0x00000000
+       beq     switch_exited
+
+/* rem: r1 = old proc */
+/* rem: r6 = new process */
+/* rem: interrupts are disabled */
+
+/* Stage two : Save old context */
+
+/* Remember the old process in r0 */
+
+       mov     r0, r1
+
+/* Get the user structure for the old process. */
+
+       ldr     r1, [r1, #(P_ADDR)]
+
+/* Save all the registers in the old process's pcb */
+
+       add     r7, r1, #(PCB_R8)
+       stmia   r7, {r8-r13}
+
+/*
+ * This can be optimised... We know we want to go from SVC32 mode to UND32
+ * mode
+ */
+
+        mrs    r3, cpsr_all
+       bic     r2, r3, #(PSR_MODE)
+       orr     r2, r2, #(PSR_UND32_MODE | I32_bit | F32_bit)
+        msr    cpsr_all, r2
+
+       str     sp, [r1, #(PCB_UND_SP)]
+
+        msr    cpsr_all, r3            /* Restore the old mode */
+
+/* rem: r0 = old proc */
+/* rem: r0 = old pcb */
+/* rem: r6 = new process */
+/* rem: interrupts are disabled */
+
+/* What else needs to be saved  Only FPA stuff when that is supported */
+
+/* Third phase : restore saved context */
+
+switch_exited:
+
+/* At this point we need to kill IRQ's again. */
+
+       mrs     r0, cpsr_all
+       orr     r0, r0, #(I32_bit | F32_bit)
+       msr     cpsr_all , r0
+
+/*     IRQdisable*/
+
+/* Get the user structure for the new process in r1 */
+
+       ldr     r1, [r6, #(P_ADDR)]
+
+/* Get the pagedir physical address for the process. */
+
+       ldr     r0, [r1, #(PCB_PAGEDIR)]
+
+/* Switch the memory to the new process */
+
+/* For good measure we will flush the IDC as well */
+        mcr     15, 0, r0, c7, c0, 0
+
+/* Write the TTB */
+        mcr     15, 0, r0, c2, c0, 0
+
+/* If we have updated the TTB we must flush the TLB */
+        mcr     15, 0, r0, c5, c0, 0
+
+/* For good measure we will flush the IDC as well */
+        mcr     15, 0, r0, c7, c0, 0
+
+/* Make sure that pipeline is emptied */
+        mov     r0, r0
+        mov     r0, r0
+
+/*
+ * This can be optimised... We know we want to go from SVC32 mode to UND32
+ * mode
+ */
+
+        mrs    r3, cpsr_all
+       bic     r2, r3, #(PSR_MODE)
+       orr     r2, r2, #(PSR_UND32_MODE)
+        msr    cpsr_all, r2
+
+       ldr     sp, [r1, #(PCB_UND_SP)]
+
+        msr    cpsr_all, r3            /* Restore the old mode */
+
+/* Restore all the save registers */
+
+       add     r7, r1, #PCB_R8
+       ldmia   r7, {r8-r13}
+
+/* Remember the pcb currently in use */
+
+       ldr     r7, Lcurpcb
+       str     r1, [r7]
+
+/* We can enable interrupts again */
+
+/*
+       IRQenable
+*/
+
+#ifdef ARMFPE
+       add     r0, r1, #(USER_SIZE) & 0x00ff
+       add     r0, r0, #(USER_SIZE) & 0xff00 
+       bl      _arm_fpe_core_changecontext
+#endif
+
+switch_return:
+
+/* We have a new curproc now so make a note it */
+
+/*
+       ldr     r7, Lcurproc
+       str     r6, [r7]
+*/
+
+/* Get the spl level from the stack and update the current spl level */
+
+       ldr     r0, [sp], #0x0004
+       bl      _splx
+
+/*     IRQenable*/
+
+/* cpu_switch returns the proc it switched to. */
+
+       mov     r0, r6
+
+/*
+ * Pull the registers that got pushed when either savectx or cpu_switch
+ * was called and return.
+ */
+       ldmfd   sp!, {r4-r7, pc}
+
+Lproc0:
+       .word   _proc0
+
+Lkernel_map:
+       .word   _kernel_map
+
+
+       .global _switch_exit
+
+_switch_exit:
+
+/*
+ * r0 = proc
+ * r1 = proc0
+ */
+
+       ldr     r1, Lproc0
+
+/* In case we fault */
+
+       mov     r2, #0x00000000
+       ldr     r3, Lcurproc
+       str     r2, [r3]
+
+/*     ldr     r3, Lcurpcb
+       str     r2, [r3]*/
+
+/* Switch to proc0 context */
+
+       IRQdisable
+
+       ldr     r2, [r1, #(P_ADDR)]
+       ldr     r3, [r2, #(PCB_PAGEDIR)]
+
+/* For good measure we will flush the IDC as well */
+        mcr     15, 0, r0, c7, c0, 0
+
+/* Write the TTB */
+        mcr     15, 0, r3, c2, c0, 0
+
+/* If we have updated the TTB we must flush the TLB */
+        mcr     15, 0, r0, c5, c0, 0
+
+/* For good measure we will flush the IDC as well */
+        mcr     15, 0, r0, c7, c0, 0
+
+/* Make sure that pipeline is emptied */
+        mov     r0, r0
+        mov     r0, r0
+
+/* Restore all the save registers */
+
+       add     r7, r2, #PCB_R8
+       ldmia   r7, {r8-r13}
+
+/* This is not really needed ! */
+/* Yes it is for the su and fu routines */
+
+/*     ldr     sp, [r2, #(PCB_SP)]*/
+       ldr     r3, Lcurpcb
+       str     r2, [r3]
+
+/*     IRQenable*/
+
+       str     r0, [sp, #-0x0004]!
+
+/* Thoroughly nuke the old process's resources. */
+
+/* This has to be done here, before we lose the pmap */
+
+       mov     r1, #0x00000000
+       add     r2, r1, #NBPG
+       ldr     r0, [r0, #(P_VMSPACE)]
+       add     r0, r0, #(VM_PMAP)
+       bl      _pmap_remove
+       ldr     r0, [sp]
+
+/*
+ * Have to wait until we have switched to proc0 as the pmap gets released
+ * in vmspace_free()
+ */
+
+       ldr     r0, [r0, #(P_VMSPACE)]
+       bl      _vmspace_free
+
+/* This has to be done here */
+
+       mov     r2, #(UPAGES << PGSHIFT)
+       ldr     r0, [sp], #0x0004
+       ldr     r1, [r0, #(P_ADDR)]
+       ldr     r0, Lkernel_map
+       ldr     r0, [r0]
+       bl      _kmem_free
+
+/* Paranoia */
+
+       mov     r0, #0x00000000
+       ldr     r1, Lcurproc
+       str     r0, [r1]
+
+        ldr     r1, Lproc0
+       b       switch_search
+
+
+Lcurrent_spl_level:
+       .word   _current_spl_level
+       .global _savectx
+_savectx:
+/*
+ * r0 = pcb
+ */
+
+/* Push registers.*/
+
+       stmfd   sp!, {r4-r7, lr}
+
+/* Store all the registers in the process's pcb */
+
+       add     r2, r0, #(PCB_R8)
+       stmia   r2, {r8-r13}
+
+/* Pull the regs of the stack */
+
+       ldmfd   sp!, {r4-r7, pc}
+
+
+       .global _proc_trampoline
+_proc_trampoline:
+       add     lr, pc, #(trampoline_return - . - 8)
+       mov     r0, r5
+       mov     r1, sp
+       mov     pc, r4
+
+trampoline_return:
+/* Kill irq's */
+
+        mrs     r0, cpsr_all
+        orr     r0, r0, #(I32_bit)
+        msr     cpsr_all, r0
+
+       PULLFRAME
+
+       movs    pc, lr                  /* Exit */
+       
diff --git a/sys/arch/arm32/arm32/db_disasm.c b/sys/arch/arm32/arm32/db_disasm.c
new file mode 100644 (file)
index 0000000..7e7d8b9
--- /dev/null
@@ -0,0 +1,558 @@
+/* $NetBSD: db_disasm.c,v 1.2 1996/03/06 22:46:37 mark Exp $ */
+
+/*
+ * Copyright (c) 1996 Mark Brinicombe.
+ * Copyright (c) 1996 Brini.
+ *
+ * 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 Brini.
+ * 4. The name of the company nor the name of the author may be used to
+ *    endorse or promote products derived from this software without specific
+ *    prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BRINI ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL BRINI 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.
+ *
+ * RiscBSD kernel project
+ *
+ * db_disasm.c
+ *
+ * Kernel disassembler
+ *
+ * Created      : 10/02/96
+ *
+ * Structured after the sparc/sparc/db_disasm.c by David S. Miller &
+ * Paul Kranenburg
+ *
+ * This code is not complete. Not all instructions are disassembled.
+ * Current LDF, STF, CDT and MSRF are not supported.
+ */
+
+#include <sys/param.h>
+#include <machine/db_machdep.h>
+#include <ddb/db_sym.h>
+
+/*
+ * General instruction format
+ *
+ *     insn[cc][mod]   [operands]
+ *
+ * Those fields with an uppercase format code indicate that the field follows
+ * directly after the instruction before the separator i.e. they modify the instruction
+ * rather than just being an operand to the instruction. The only exception is the
+ * writeback flag which follows a operand.
+ *
+ *
+ * 2 - print Operand 2 of a data processing instrcution
+ * d - destination register (bits 12-15)
+ * n - n register (bits 16-19)
+ * s - s register (bits 8-11)
+ * o - indirect register rn (bits 16-19) (used by swap)
+ * m - m register (bits 0-4)
+ * a - address operand of ldr/str instruction
+ * l - register list for ldm/stm instruction
+ * f - 1st fp operand (register) (bits 12-14)
+ * g - 2nd fp operand (register) (bits 16-18)
+ * h - 3rd fp operand (register/immediate) (bits 0-4)
+ * b - branch address
+ * X - block transfer type
+ * c - comment field bits(0-23)
+ * p - saved or current status register
+ * B - byte transfer flag
+ * S - set status flag
+ * T - user mode transfer
+ * P - fp precision
+ * R - fp rounding
+ * w - writeback flag
+ * # - co-processor number
+ * y - co-processor data processing registers
+ * z - co-processor data transfer registers
+ */
+
+struct arm32_insn {
+       u_int mask;
+       u_int pattern;
+       char* name;
+       char* format;
+};
+
+struct arm32_insn arm32_i[] = {
+    { 0x0f000000, 0x0f000000, "swi",   "c" },
+    { 0x0f000000, 0x0a000000, "b",     "b" },
+    { 0x0f000000, 0x0b000000, "bl",    "b" },
+    { 0x0fe000f0, 0x00000090, "mul",   "Sdms" },
+    { 0x0fe000f0, 0x00200090, "mla",   "Sdmsn" },
+    { 0x0e100000, 0x04000000, "str",   "BTdaW" },
+    { 0x0e100000, 0x04100000, "ldr",   "BTdaW" },
+    { 0x0c100010, 0x04000000, "str",   "BTdaW" },
+    { 0x0c100010, 0x04100000, "ldr",   "BTdaW" },
+    { 0x0e100000, 0x08000000, "stm",   "XnWl" },
+    { 0x0e100000, 0x08100000, "ldm",   "XnWl" },
+    { 0x0fb00ff0, 0x01000090, "swap",  "Bdmo" },
+    { 0x0fbf0fff, 0x010f0000, "mrs",   "dp" },
+    { 0x0dbffff0, 0x0129f000, "msr",   "pm" },
+    { 0x0dbffff0, 0x0128f000, "msrf",  "pm" },
+    { 0x0de00000, 0x00000000, "and",   "Sdn2" },
+    { 0x0de00000, 0x00200000, "eor",   "Sdn2" },
+    { 0x0de00000, 0x00400000, "sub",   "Sdn2" },
+    { 0x0de00000, 0x00600000, "rsb",   "Sdn2" },
+    { 0x0de00000, 0x00800000, "add",   "Sdn2" },
+    { 0x0de00000, 0x00a00000, "adc",   "Sdn2" },
+    { 0x0de00000, 0x00c00000, "sbc",   "Sdn2" },
+    { 0x0de00000, 0x00e00000, "rsc",   "Sdn2" },
+    { 0x0de00000, 0x01000000, "tst",   "Sn2" },
+    { 0x0de00000, 0x01200000, "teq",   "Sn2" },
+    { 0x0de00000, 0x01400000, "cmp",   "Sn2" },
+    { 0x0de00000, 0x01600000, "cmn",   "Sn2" },
+    { 0x0de00000, 0x01800000, "orr",   "Sdn2" },
+    { 0x0de00000, 0x01a00000, "mov",   "Sd2" },
+    { 0x0de00000, 0x01c00000, "bic",   "Sdn2" },
+    { 0x0de00000, 0x01e00000, "mvn",   "Sd2" },
+    { 0x0ff08f10, 0x0e000100, "adf",   "PRfgh" },
+    { 0x0ff08f10, 0x0e100100, "muf",   "PRfgh" },
+    { 0x0ff08f10, 0x0e200100, "suf",   "PRfgh" },
+    { 0x0ff08f10, 0x0e300100, "rsf",   "PRfgh" },
+    { 0x0ff08f10, 0x0e400100, "dvf",   "PRfgh" },
+    { 0x0ff08f10, 0x0e500100, "rdf",   "PRfgh" },
+    { 0x0ff08f10, 0x0e600100, "pow",   "PRfgh" },
+    { 0x0ff08f10, 0x0e700100, "rpw",   "PRfgh" },
+    { 0x0ff08f10, 0x0e800100, "rmf",   "PRfgh" },
+    { 0x0ff08f10, 0x0e900100, "fml",   "PRfgh" },
+    { 0x0ff08f10, 0x0ea00100, "fdv",   "PRfgh" },
+    { 0x0ff08f10, 0x0eb00100, "frd",   "PRfgh" },
+    { 0x0ff08f10, 0x0ec00100, "pol",   "PRfgh" },
+    { 0x0f008f10, 0x0e000100, "fpbop", "PRfgh" },
+    { 0x0ff08f10, 0x0e008100, "mvf",   "PRfh" },
+    { 0x0ff08f10, 0x0e108100, "mnf",   "PRfh" },
+    { 0x0ff08f10, 0x0e208100, "abs",   "PRfh" },
+    { 0x0ff08f10, 0x0e308100, "rnd",   "PRfh" },
+    { 0x0ff08f10, 0x0e408100, "sqt",   "PRfh" },
+    { 0x0ff08f10, 0x0e508100, "log",   "PRfh" },
+    { 0x0ff08f10, 0x0e608100, "lgn",   "PRfh" },
+    { 0x0ff08f10, 0x0e708100, "exp",   "PRfh" },
+    { 0x0ff08f10, 0x0e808100, "sin",   "PRfh" },
+    { 0x0ff08f10, 0x0e908100, "cos",   "PRfh" },
+    { 0x0ff08f10, 0x0ea08100, "tan",   "PRfh" },
+    { 0x0ff08f10, 0x0eb08100, "asn",   "PRfh" },
+    { 0x0ff08f10, 0x0ec08100, "acs",   "PRfh" },
+    { 0x0ff08f10, 0x0ed08100, "atn",   "PRfh" },
+    { 0x0f008f10, 0x0e008100, "fpuop", "PRfh" },
+    { 0x0e100f00, 0x0c000100, "stf",   "P" },
+    { 0x0e100f00, 0x0c100100, "ldf",   "P" },
+    { 0x0f100010, 0x0e000010, "mcr",   "#z" },
+    { 0x0f100010, 0x0e100010, "mrc",   "#z" },
+    { 0x0f000010, 0x0e000000, "cdp",   "#y" },
+    { 0x0e000000, 0x0c000000, "cdt",   "#" },
+    { 0x00000000, 0x00000000, NULL,    NULL }
+};
+
+char *arm32_insn_conditions[] = {
+    "eq",
+    "ne",
+    "cs",
+    "cc",
+    "mi",
+    "pl",
+    "vs",
+    "vc",
+    "hi",
+    "ls",
+    "ge",
+    "lt",
+    "gt",
+    "le",
+    "",
+    "nv"
+};
+
+char *insn_block_transfers[] = {
+    "da",
+    "ia",
+    "db",
+    "ib"
+};
+
+char *insn_stack_block_transfers[] = {
+    "fa",
+    "ea",
+    "fd",
+    "fa"
+};
+
+char *op_shifts[] = {
+    "lsl",
+    "lsr",
+    "asr",
+    "ror"
+};
+
+char *insn_fpa_rounding[] = {
+    "",
+    "p",
+    "m",
+    "z"
+};
+
+char *insn_fpa_precision[] = {
+    "s",
+    "d",
+    "e",
+    "p"
+};
+
+char *insn_fpaconstants[] = {
+    "0.0",
+    "1.0",
+    "2.0",
+    "3.0",
+    "4.0",
+    "5.0",
+    "0.5",
+    "10.0"
+};
+
+#define insn_condition(x)      arm32_insn_conditions[(x >> 28) & 0x0f]
+#define insn_blktrans(x)       insn_block_transfers[(x >> 23) & 3]
+#define insn_stkblktrans(x)    insn_stack_block_transfers[(x >> 23) & 3]
+#define op2_shift(x)           op_shifts[(x >> 5) & 3]
+#define insn_fparnd(x)         insn_fpa_rounding[(x >> 5) & 0x03]
+#define insn_fpaprec(x)                insn_fpa_precision[(((x >> 18) & 2)|(x >> 7)) & 3]
+#define insn_fpaimm(x)         insn_fpaconstants[x & 0x07]
+
+void db_register_shift __P((u_int insn));
+void db_print_reglist  __P((u_int insn));
+void db_insn_ldrstr    __P((u_int insn, u_int loc));
+
+
+vm_offset_t
+db_disasm(loc, altfmt)
+       vm_offset_t loc;
+       boolean_t altfmt;
+{
+       struct arm32_insn*      i_ptr = (struct arm32_insn *)&arm32_i;
+
+       u_int insn;
+       int matchp;
+       int branch;
+       char* f_ptr, *cp;
+       int fmt;
+
+       fmt = 0;
+       matchp = 0;
+       insn = db_get_value(loc, 4, 0);
+
+/*     db_printf("loc=%08x insn=%08x : ", loc, insn);*/
+/*     db_printf("loc=%08x : ", loc);*/
+
+       while (i_ptr->name) {
+               if ((insn & i_ptr->mask) ==  i_ptr->pattern) {
+                       matchp = 1;
+                       break;
+               }
+               i_ptr++;
+       }
+
+       if (!matchp) {
+               db_printf("undefined\n");
+               return(loc + 4);
+       }
+
+       db_printf("%s%s", i_ptr->name, insn_condition(insn));
+
+       f_ptr = i_ptr->format;
+
+       while (*f_ptr) {
+               switch (*f_ptr) {
+               case '2':
+                       if (insn & 0x02000000) {
+                               db_printf("#0x%08x", (insn & 0xff) << (((insn >> 7) & 0x1e)));
+                       } else {
+                               db_register_shift(insn);
+                       }
+                       break;
+               case 'd':
+                       db_printf("r%d", ((insn >> 12) & 0x0f));
+                       break;
+               case 'n':
+                       db_printf("r%d", ((insn >> 16) & 0x0f));
+                       break;
+               case 's':
+                       db_printf("r%d", ((insn >> 8) & 0x0f));
+                       break;
+               case 'o':
+                       db_printf("[r%d]", ((insn >> 16) & 0x0f));
+                       break;
+               case 'm':
+                       db_printf("r%d", ((insn >> 0) & 0x0f));
+                       break;
+               case 'a':
+                       db_insn_ldrstr(insn, loc);
+                       break;
+               case 'l':
+                       db_print_reglist(insn);
+                       break;
+               case 'f':
+                       db_printf("f%d", (insn >> 12) & 7);
+                       break;
+               case 'g':
+                       db_printf("f%d", (insn >> 16) & 7);
+                       break;
+               case 'h':
+                       if (insn & (1 << 3))
+                               db_printf("#%s", insn_fpaimm(insn));
+                       else
+                               db_printf("f%d", insn & 7);
+                       break;
+               case 'b':
+                       branch = ((insn << 2) & 0x03ffffff);
+                       if (branch & 0x02000000)
+                               branch |= 0xfc000000;
+                       db_printsym((db_addr_t)(loc + 8 + branch),
+                           DB_STGY_ANY);
+                       break;
+               case 'X':
+                       db_printf("%s", insn_blktrans(insn));
+                       break;
+               case 'c':
+                       db_printf("0x%08x", (insn & 0x00ffffff));
+                       break;
+               case 'p':
+                       if (insn & 0x00400000)
+                               db_printf("spsr");
+                       else
+                               db_printf("cpsr");
+               case 'B':
+                       if (insn & 0x00400000)
+                               db_printf("b");
+                       break;
+               case 'S':
+                       if (insn & 0x00100000)
+                               db_printf("s");
+                       break;
+               case 'T':
+                       if ((insn & 0x01200000) == 0x00200000)
+                               db_printf("t");
+                       break;
+               case 'P':
+                       db_printf("%s", insn_fpaprec(insn));
+                       break;
+               case 'R':
+                       db_printf("%s", insn_fparnd(insn));
+                       break;
+               case 'W':
+                       if (insn & (1 << 21))
+                               db_printf("!");
+                       break;
+               case '#':
+                       db_printf("CP #%d", (insn >> 8) & 0x0f);
+                       break;
+               case 'y':
+                       db_printf("%d, ", (insn >> 20) & 0x0f);
+
+                       db_printf("cr%d, cr%d, cr%d", (insn >> 12) & 0x0f, (insn >> 16) & 0x0f,
+                           insn & 0x0f);
+
+                       db_printf(", %d", (insn >> 5) & 0x07);
+                       break;
+               case 'z':
+                       db_printf("%d, ", (insn >> 21) & 0x07);
+                       db_printf("r%d, cr%d, cr%d", (insn >> 12) & 0x0f, (insn >> 16) & 0x0f,
+                           insn & 0x0f);
+
+                       if (((insn >> 5) & 0x07) != 0)
+                               db_printf(", %d", (insn >> 5) & 0x07);
+                       break;
+               default:
+                       db_printf("[%02x:c](unknown)", *f_ptr, *f_ptr);
+                       break;
+               }
+               ++fmt;
+               if (*(f_ptr+1) > 'A' && *(f_ptr+1) < 'Z')
+                       ++f_ptr;
+               else if (*(++f_ptr)) {
+                       if (fmt == 1)
+                               db_printf("\t");
+                       else
+                               db_printf(", ");
+               }
+       };
+
+       db_printf("\n");
+
+       return(loc + 4);
+}
+
+
+void
+db_register_shift(insn)
+       u_int insn;
+{
+       db_printf("r%d", (insn & 0x0f));
+       if ((insn & 0x00000ff0) == 0)
+               ;
+       else if ((insn & 0x00000ff0) == 0x00000060)
+               db_printf(", RRX");
+       else {
+               if (insn & 0x10)
+                       db_printf(", %s r%d", op2_shift(insn),
+                           (insn >> 8) & 0x0f);
+               else
+                       db_printf(", %s #%d", op2_shift(insn),
+                           (insn >> 7) & 0x1f);
+       }
+}
+
+
+void
+db_print_reglist(insn)
+       u_int insn;
+{
+       int loop;
+       int start;
+       int comma;
+
+       db_printf("{");
+       start = -1;
+       comma = 0;
+
+       for (loop = 0; loop < 17; ++loop) {
+               if (start != -1) {
+                       if (!(insn & (1 << loop)) || loop == 16) {
+                               if (comma)
+                                       db_printf(", ");
+                               else
+                                       comma = 1;
+                               if (start == loop - 1)
+                                       db_printf("r%d", start);
+                               else
+                                       db_printf("r%d-r%d", start, loop - 1);
+                               start = -1;
+                       }
+               } else {
+                       if (insn & (1 << loop))
+                               start = loop;
+               }
+        }
+       db_printf("}");
+
+       if (insn & (1 << 22))
+               db_printf("^");
+}
+
+void
+db_insn_ldrstr(insn, loc)
+       u_int insn;
+       u_int loc;
+{
+       if (((insn >> 16) & 0x0f) == 15 && (insn & (1 << 21)) == 0
+           && (insn & (1 << 24)) != 0 && (insn & (1 << 25) == 0)) {
+               if (insn & 0x00800000)
+                       loc += (insn & 0xffff);
+               else
+                       loc -= (insn & 0xffff);
+               db_printsym((db_addr_t)(loc - 8), DB_STGY_ANY);
+       } else {
+               printf("[r%d", (insn >> 16) & 0x0f);
+               printf("%s, ", (insn & (1 << 24)) ? "" : "]");
+
+               if (!(insn & 0x00800000))
+                       printf("-");
+               if (insn & (1 << 25))
+                       db_register_shift(insn);
+               else
+                       printf("#0x%04x", insn & 0xfff);
+               if (insn & (1 << 24))
+                       printf("]");
+       }
+}
+
+
+
+#if 0
+
+u_int instruction_msrf(u_int addr, u_int word)
+  {
+    printf("MSR%s\t", opcode_condition(word));
+
+    printf("%s_flg, ", (word & 0x00400000) ? "SPSR" : "CPSR");
+
+    if (word & 0x02000000)
+      printf("#0x%08x", (word & 0xff) << (32 - ((word >> 7) & 0x1e)));
+    else
+      printf("r%d", word &0x0f);
+    return(addr);
+  }
+
+
+u_int instruction_cdt(u_int addr, u_int word)
+  {
+    printf("%s%s%s\t", (word & (1 << 20)) ? "LDC" : "STC",
+      opcode_condition(word), (word & (1 << 22)) ? "L" : "");
+
+    printf("CP #%d, cr%d, ", (word >> 8) & 0x0f, (word >> 12) & 0x0f);
+
+    printf("[r%d", (word >> 16) & 0x0f);
+
+    printf("%s, ", (word & (1 << 24)) ? "" : "]");
+
+    if (!(word & (1 << 23)))
+      printf("-");
+
+    printf("#0x%02x", word & 0xff);
+
+    if (word & (1 << 24))
+      printf("]");
+
+    if (word & (1 << 21))
+      printf("!");
+
+    return(addr);
+  }
+
+
+u_int instruction_ldfstf(u_int addr, u_int word)
+  {
+    printf("%s%s%s\t", (word & (1 << 20)) ? "LDF" : "STF",
+      opcode_condition(word), (word & (1 << 22)) ? "L" : "");
+
+    printf("f%d, [r%d", (word >> 12) & 0x07, (word >> 16) & 0x0f);
+
+    printf("%s, ", (word & (1 << 24)) ? "" : "]");
+
+    if (!(word & (1 << 23)))
+      printf("-");
+
+    printf("#0x%03x", (word & 0xff) << 2);
+
+    if (word & (1 << 24))
+      printf("]");
+
+    if (word & (1 << 21))
+      printf("!");
+
+    return(addr);
+  }
+
+#endif
+
+/* End of db_disasm.c */
diff --git a/sys/arch/arm32/arm32/db_interface.c b/sys/arch/arm32/arm32/db_interface.c
new file mode 100644 (file)
index 0000000..47c8b4e
--- /dev/null
@@ -0,0 +1,288 @@
+/* $NetBSD: db_interface.c,v 1.5 1996/03/18 21:33:05 mark Exp $ */
+
+/* 
+ * Copyright (c) 1996 Scott K. Stevens
+ *
+ * Mach Operating System
+ * Copyright (c) 1991,1990 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.
+ *
+ *     From: db_interface.c,v 2.4 1991/02/05 17:11:13 mrt (CMU)
+ */
+
+/*
+ * Interface to new debugger.
+ */
+
+#include <sys/param.h>
+#include <sys/proc.h>
+#include <sys/reboot.h>
+#include <sys/systm.h> /* just for boothowto */
+#include <sys/exec.h>
+
+#include <vm/vm.h>
+
+#include <machine/db_machdep.h>
+#include <machine/katelib.h>
+#include <machine/pte.h>
+#include <ddb/db_command.h>
+#include <ddb/db_variables.h>
+
+static int nil;
+
+int db_access_svc_sp __P((struct db_variable *, db_expr_t *, int));
+
+struct db_variable db_regs[] = {
+       { "spsr", (int *)&DDB_TF->tf_spsr, FCN_NULL, },
+       { "r0", (int *)&DDB_TF->tf_r0, FCN_NULL, },
+       { "r1", (int *)&DDB_TF->tf_r1, FCN_NULL, },
+       { "r2", (int *)&DDB_TF->tf_r2, FCN_NULL, },
+       { "r3", (int *)&DDB_TF->tf_r3, FCN_NULL, },
+       { "r4", (int *)&DDB_TF->tf_r4, FCN_NULL, },
+       { "r5", (int *)&DDB_TF->tf_r5, FCN_NULL, },
+       { "r6", (int *)&DDB_TF->tf_r6, FCN_NULL, },
+       { "r7", (int *)&DDB_TF->tf_r7, FCN_NULL, },
+       { "r8", (int *)&DDB_TF->tf_r8, FCN_NULL, },
+       { "r9", (int *)&DDB_TF->tf_r9, FCN_NULL, },
+       { "r10", (int *)&DDB_TF->tf_r10, FCN_NULL, },
+       { "r11", (int *)&DDB_TF->tf_r11, FCN_NULL, },
+       { "r12", (int *)&DDB_TF->tf_r12, FCN_NULL, },
+       { "usr_sp", (int *)&DDB_TF->tf_usr_sp, FCN_NULL, },
+       { "svc_sp", (int *)&nil, db_access_svc_sp, },
+       { "usr_lr", (int *)&DDB_TF->tf_usr_lr, FCN_NULL, },
+       { "svc_lr", (int *)&DDB_TF->tf_svc_lr, FCN_NULL, },
+       { "pc", (int *)&DDB_TF->tf_pc, FCN_NULL, },
+};
+
+struct db_variable *db_eregs = db_regs + sizeof(db_regs)/sizeof(db_regs[0]);
+
+extern label_t *db_recover;
+
+int    db_active = 0;
+
+int db_access_svc_sp(vp, valp, rw)
+       struct db_variable *vp;
+       db_expr_t *valp;
+       int rw;
+{
+       if(rw == DB_VAR_GET)
+               *valp = get_stackptr(PSR_SVC32_MODE);
+       return(0);
+}
+
+#if 0
+extern char *trap_type[];
+#endif
+
+/*
+ * Received keyboard interrupt sequence.
+ */
+kdb_kbd_trap(tf)
+       struct trapframe *tf;
+{
+       if (db_active == 0 && (boothowto & RB_KDB)) {
+               printf("\n\nkernel: keyboard interrupt\n");
+               kdb_trap(-1, tf);
+       }
+}
+
+/*
+ *  kdb_trap - field a TRACE or BPT trap
+ */
+kdb_trap(type, tf)
+       int     type;
+       register struct trapframe *tf;
+{
+
+#if 0
+       fb_unblank();
+#endif
+
+       switch (type) {
+       case T_BREAKPOINT:      /* breakpoint */
+       case -1:                /* keyboard interrupt */
+               break;
+       default:
+               db_printf("kernel: trap");
+               if (db_recover != 0) {
+                       db_error("Faulted in DDB; continuing...\n");
+                       /*NOTREACHED*/
+               }
+       }
+
+       /* Should switch to kdb`s own stack here. */
+
+       ddb_regs.ddb_tf = *tf;
+       ddb_regs.ddb_tf.tf_pc -= 4;
+
+       db_active++;
+       cnpollc(TRUE);
+       db_trap(type, 0/*code*/);
+       cnpollc(FALSE);
+       db_active--;
+
+       *tf = ddb_regs.ddb_tf;
+
+       return (1);
+}
+
+/*
+ * Read bytes from kernel address space for debugger.
+ */
+void
+db_read_bytes(addr, size, data)
+       vm_offset_t     addr;
+       register int    size;
+       register char   *data;
+{
+       register char   *src;
+
+       src = (char *)addr;
+       while (--size >= 0)
+               *data++ = *src++;
+}
+
+#define        splpmap() splimp()
+
+static void
+db_write_text(dst, ch)
+       unsigned char *dst;
+       int ch;
+{        
+       pt_entry_t *ptep, pte, pteo;
+       int s;
+       vm_offset_t va;
+
+       s = splpmap();
+       va = (unsigned long)dst & (~PGOFSET);
+       ptep = vtopte(va);
+
+       if ((*ptep & L2_MASK) == L2_INVAL) { 
+               db_printf(" address 0x%x not a valid page\n", dst);
+               splx(s);
+               return;
+       }
+
+       pteo = ReadWord(ptep);
+       pte = pteo | PT_AP(AP_KRW);
+       WriteWord(ptep, pte);
+       tlbflush();
+
+       *dst = (unsigned char)ch;
+
+       WriteWord(ptep, pteo);
+       tlbflush();
+       splx(s);
+}
+
+/*
+ * Write bytes to kernel address space for debugger.
+ */
+void
+db_write_bytes(addr, size, data)
+       vm_offset_t     addr;
+       register int    size;
+       register char   *data;
+{
+       extern char     etext[];
+       register char   *dst;
+
+       dst = (char *)addr;
+       while (--size >= 0) {
+               if ((dst >= (char *)VM_MIN_KERNEL_ADDRESS) && (dst < etext))
+                       db_write_text(dst, *data);
+               else
+                       *dst = *data;
+               dst++, data++;
+       }
+}
+
+void
+Debugger()
+{
+       asm(".word      0xe7ffffff");
+}
+
+void db_show_vmstat_cmd __P((db_expr_t addr, int have_addr, db_expr_t count, char *modif));
+void db_show_fs_cmd __P((db_expr_t addr, int have_addr, db_expr_t count, char *modif));
+void db_show_vnode_cmd __P((db_expr_t addr, int have_addr, db_expr_t count, char *modif));
+
+struct db_command arm32_db_command_table[] = {
+       { "vmstat",     db_show_vmstat_cmd,     0, NULL },
+       { "fs",         db_show_fs_cmd,         0, NULL },
+       { "vnode",      db_show_vnode_cmd,      0, NULL },
+       { NULL,         NULL,                   0, NULL }
+};
+
+int
+db_trapper(addr, inst, frame)
+       u_int           addr;
+       u_int           inst;
+       trapframe_t     *frame;
+{
+/*     db_printf("db_trapper\n");*/
+       kdb_trap(1, frame);
+       return(0);
+}
+
+extern u_int esym;
+extern u_int end;
+
+void
+db_machine_init()
+{
+       struct exec *kernexec = (struct exec *)KERNEL_BASE;
+       u_int *ptr;
+       int len;
+
+/*
+ * The boot loader currently loads the kernel with the a.out header still attached.
+ */
+
+       if (kernexec->a_syms == 0) {
+               printf("[No symbol table]\n");
+       } else {
+               esym = (int)&end + kernexec->a_syms + sizeof(int);
+               len = *((u_int *)esym);
+               esym += (len + (sizeof(u_int) - 1)) & ~(sizeof(u_int) - 1);
+       }
+
+       install_coproc_handler(0, db_trapper);
+       db_machine_commands_install(arm32_db_command_table);
+}
+
+
+u_int
+branch_taken(insn, pc, reg, db_regs)
+       u_int insn;
+       u_int pc;
+       u_int reg;
+       db_regs_t *db_regs;
+{
+       int branch;
+
+       branch = ((insn << 2) & 0x03ffffff);
+       if (branch & 0x02000000)
+               branch |= 0xfc000000;
+       return(pc + 8 + branch);
+}
diff --git a/sys/arch/arm32/arm32/db_machdep.c b/sys/arch/arm32/arm32/db_machdep.c
new file mode 100644 (file)
index 0000000..ef01317
--- /dev/null
@@ -0,0 +1,163 @@
+/* $NetBSD: db_machdep.c,v 1.1 1996/03/06 23:08:36 mark Exp $ */
+
+/* 
+ * Copyright (c) 1996 Mark Brinicombe
+ *
+ * Mach Operating System
+ * Copyright (c) 1991,1990 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.
+ */
+
+#include <sys/param.h>
+#include <sys/proc.h>
+#include <sys/mount.h>
+#include <sys/vnode.h>
+#include <machine/db_machdep.h>
+
+#include <ddb/db_access.h>
+#include <ddb/db_sym.h>
+
+void
+db_show_fs_cmd(addr, have_addr, count, modif)
+       db_expr_t       addr;
+       int             have_addr;
+       db_expr_t       count;
+       char            *modif;
+{
+       struct vfsops **vfsp;
+       int s;
+       
+       s = splhigh();
+
+       db_printf("Registered filesystems (%d)\n", nvfssw);
+         
+       for (vfsp = &vfssw[0]; vfsp < &vfssw[nvfssw]; vfsp++) {
+               if (*vfsp == NULL)
+                       continue;
+               db_printf("  %s\n", (*vfsp)->vfs_name);
+       }
+       (void)splx(s);
+}
+
+
+/*
+ * Print out a description of a vnode.
+ * Some parts borrowed from kern/vfs_subr.c
+ */
+static char *typename[] =
+   { "VNON", "VREG", "VDIR", "VBLK", "VCHR", "VLNK", "VSOCK", "VFIFO", "VBAD" };
+
+void
+db_show_vnode_cmd(addr, have_addr, count, modif)
+       db_expr_t       addr;
+       int             have_addr;
+       db_expr_t       count;
+       char            *modif;
+{
+       char buf[64];
+       struct vnode *vp;
+
+       if (!have_addr) {
+               db_printf("vnode address must be specified\n");
+               return;
+       }
+
+       vp = (struct vnode *)addr;
+
+/* Decode the one argument */
+
+       db_printf("vp : %08x\n", (u_int)vp);
+       db_printf("vp->v_type = %d\n", vp->v_type);
+       db_printf("vp->v_flag = %ld\n", vp->v_flag);
+       db_printf("vp->v_numoutput = %ld\n", vp->v_numoutput);
+
+       db_printf("type %s, usecount %d, writecount %d, refcount %d,",
+               typename[vp->v_type], vp->v_usecount, vp->v_writecount,
+               vp->v_holdcnt);
+       buf[0] = '\0';
+       if (vp->v_flag & VROOT)
+               strcat(buf, "|VROOT");
+       if (vp->v_flag & VTEXT)
+               strcat(buf, "|VTEXT");
+       if (vp->v_flag & VSYSTEM)
+               strcat(buf, "|VSYSTEM");
+       if (vp->v_flag & VXLOCK)
+               strcat(buf, "|VXLOCK");
+       if (vp->v_flag & VXWANT)
+               strcat(buf, "|VXWANT");
+       if (vp->v_flag & VBWAIT)
+               strcat(buf, "|VBWAIT");
+       if (vp->v_flag & VALIASED)
+               strcat(buf, "|VALIASED");
+       if (buf[0] != '\0')
+               db_printf(" flags (%s)", &buf[1]);
+               db_printf("\n");
+       if (vp->v_data != NULL) {
+               db_printf("data=%08x\n", vp->v_data);
+       }
+}
+
+
+void
+db_show_vmstat_cmd(addr, have_addr, count, modif)
+       db_expr_t       addr;
+       int             have_addr;
+       db_expr_t       count;
+       char            *modif;
+{
+       struct vmmeter sum;
+    
+       sum = cnt;
+       db_printf("%9u cpu context switches\n", sum.v_swtch);
+       db_printf("%9u device interrupts\n", sum.v_intr);
+       db_printf("%9u software interrupts\n", sum.v_soft);
+       db_printf("%9u traps\n", sum.v_trap);
+       db_printf("%9u system calls\n", sum.v_syscall);
+       db_printf("%9u total faults taken\n", sum.v_faults);
+       db_printf("%9u swap ins\n", sum.v_swpin);
+       db_printf("%9u swap outs\n", sum.v_swpout);
+       db_printf("%9u pages swapped in\n", sum.v_pswpin / CLSIZE);
+       db_printf("%9u pages swapped out\n", sum.v_pswpout / CLSIZE);
+       db_printf("%9u page ins\n", sum.v_pageins);
+       db_printf("%9u page outs\n", sum.v_pageouts);
+       db_printf("%9u pages paged in\n", sum.v_pgpgin);
+       db_printf("%9u pages paged out\n", sum.v_pgpgout);
+       db_printf("%9u pages reactivated\n", sum.v_reactivated);
+       db_printf("%9u intransit blocking page faults\n", sum.v_intrans);
+       db_printf("%9u zero fill pages created\n", sum.v_nzfod / CLSIZE);
+       db_printf("%9u zero fill page faults\n", sum.v_zfod / CLSIZE);
+       db_printf("%9u pages examined by the clock daemon\n", sum.v_scan);
+       db_printf("%9u revolutions of the clock hand\n", sum.v_rev);
+       db_printf("%9u VM object cache lookups\n", sum.v_lookups);
+       db_printf("%9u VM object hits\n", sum.v_hits);
+       db_printf("%9u total VM faults taken\n", sum.v_vm_faults);
+       db_printf("%9u copy-on-write faults\n", sum.v_cow_faults);
+       db_printf("%9u pages freed by daemon\n", sum.v_dfree);
+       db_printf("%9u pages freed by exiting processes\n", sum.v_pfree);
+       db_printf("%9u pages free\n", sum.v_free_count);
+       db_printf("%9u pages wired down\n", sum.v_wire_count);
+       db_printf("%9u pages active\n", sum.v_active_count);
+       db_printf("%9u pages inactive\n", sum.v_inactive_count);
+       db_printf("%9u bytes per page\n", sum.v_page_size);
+}
diff --git a/sys/arch/arm32/arm32/db_trace.c b/sys/arch/arm32/arm32/db_trace.c
new file mode 100644 (file)
index 0000000..c44b432
--- /dev/null
@@ -0,0 +1,101 @@
+/* $NetBSD: db_trace.c,v 1.2 1996/03/06 22:49:51 mark Exp $ */
+
+/* 
+ * Copyright (c) 1996 Scott K. Stevens
+ *
+ * Mach Operating System
+ * Copyright (c) 1991,1990 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.
+ */
+
+#include <sys/param.h>
+#include <sys/proc.h>
+#include <machine/db_machdep.h>
+
+#include <ddb/db_access.h>
+#include <ddb/db_sym.h>
+#define INKERNEL(va)   (((vm_offset_t)(va)) >= USRSTACK)
+
+void
+db_stack_trace_cmd(addr, have_addr, count, modif)
+       db_expr_t       addr;
+       int             have_addr;
+       db_expr_t       count;
+       char            *modif;
+{
+       struct frame    *frame;
+       boolean_t       kernel_only = TRUE;
+
+       {
+               register char c, *cp = modif;
+               while ((c = *cp++) != 0)
+                       if (c == 'u')
+                               kernel_only = FALSE;
+       }
+
+       if (count == -1)
+               count = 65535;
+
+/*
+ * The frame pointer points to the top word of the stack frame so we
+ * need to adjust it by sizeof(struct frame) - sizeof(u_int))
+ * to get the address of the start of the frame structure.
+ */
+
+       if (!have_addr)
+               frame = (struct frame *)(DDB_TF->tf_r11 - (sizeof(struct frame) - sizeof(u_int)));
+       else
+               frame = (struct frame *)(addr - (sizeof(struct frame) - sizeof(u_int)));
+
+       while (count--) {
+               int             i;
+               db_expr_t       offset;
+               db_sym_t        sym;
+               char            *name;
+               db_addr_t       pc;
+
+/*             db_printf("fp=%08x: fp=%08x sp=%08x lr=%08x pc=%08x\n", (u_int)frame, frame->fr_fp, frame->fr_sp, frame->fr_lr, frame->fr_pc);*/
+
+               pc = frame->fr_pc;
+               if (!INKERNEL(pc))
+                       break;
+
+               db_find_sym_and_offset(pc, &name, &offset);
+               if (name == NULL)
+                       name = "?";
+
+               db_printf("%s(", name);
+
+               /*
+                * Switch to next frame up
+                */
+               frame = (struct frame *)(frame->fr_fp - (sizeof(struct frame) - sizeof(u_int)));
+
+               db_printsym(pc, DB_STGY_PROC);
+               db_printf(")");
+               db_printf("\n");
+               if (frame == NULL)
+                       break;
+       }
+}
diff --git a/sys/arch/arm32/arm32/debug.c b/sys/arch/arm32/arm32/debug.c
new file mode 100644 (file)
index 0000000..9654a89
--- /dev/null
@@ -0,0 +1,251 @@
+/* $NetBSD: debug.c,v 1.2 1996/03/08 20:14:48 mark Exp $ */
+
+/*
+ * Copyright (c) 1994 Melvin Tang-Richardson (Nut)
+ * Copyright (c) 1994 Mark Brinicombe
+ * 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 RiscBSD.
+ * 4. The name of the company nor the name of the author may be used to
+ *    endorse or promote products derived from this software without specific
+ *    prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY RISCBSD ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * 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.
+ *
+ * RiscBSD kernel project
+ *
+ * debug.c
+ *
+ * Debugging functions
+ *
+ * Created      : 11/10/94
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/callout.h>
+#include <sys/proc.h>
+#include <sys/user.h>
+#include <sys/mount.h>
+#include <sys/vnode.h>
+
+#include <vm/vm.h>
+#include <vm/vm_kern.h>
+
+int
+debug_count_processes_on_q(queue)
+       int queue;
+{
+       struct proc *lastproc, *queue_head;
+       int counter;
+       int s;
+
+       counter = 0;
+       s = splhigh();
+       queue_head=(struct proc *)&qs[queue];
+       for (lastproc=qs[queue].ph_link;lastproc!=queue_head;lastproc=lastproc->p_forw) {
+               if (lastproc != queue_head)
+                       printf("Process queue=%8x proc=%08x p_addr=%8x, comm=%s\n",
+                           queue, (u_int) lastproc, (u_int) lastproc->p_addr,
+                           lastproc->p_comm);
+               counter++;
+       }
+       (void)splx(s);
+       return(counter);
+}
+
+void
+debug_show_q_details()
+{
+       int counter=0;
+       int s;
+       
+       s = splhigh();
+       for (counter=0; counter<32; counter++ )
+               debug_count_processes_on_q(counter);
+
+       if (whichqs == 0)
+               printf("queues empty\n");
+       (void)splx(s);
+}
+
+void
+debug_show_all_procs(argc, argv)
+       int argc;
+       char *argv[];
+{
+       int np;
+       struct proc *ap, *p, *pp;
+       int s;
+       
+       s = splhigh();
+
+       np = nprocs;
+       p = ap = (struct proc *)allproc.lh_first;
+       if (argc > 1)
+               printf("  pid   proc     addr      map      pcb     pmap     comm       wchan\n");
+       else
+               printf("  pid   proc     addr     uid  ppid  pgrp    flag  stat comm          cputime  \n");
+       while (--np >= 0) {
+               pp = p->p_pptr;
+               if (pp == 0)
+                       pp = p;
+               if (p->p_stat) {
+                       if (argc > 1)
+                               printf("%5d %08x %08x %08x %08x %08x %12s  ",
+                                   p->p_pid, (u_int) ap, (u_int)p->p_addr,
+                                   (u_int) p->p_vmspace,
+                                   (u_int) &p->p_addr->u_pcb, (p->p_vmspace ? (u_int)&p->p_vmspace->vm_pmap : 0),
+                                   ((p->p_comm == 0) ? "..." : p->p_comm));
+                       else
+                               printf("%5d %08x %08x %5d %5d %5d  %08x  %d  %12s %5u.%02d  ",
+                                   p->p_pid, (u_int) ap, (u_int) p->p_addr,
+                                   p->p_cred->p_ruid,
+                                   pp->p_pid, p->p_pgrp->pg_id, p->p_flag,
+                                   p->p_stat, p->p_comm,
+                                   (u_int)p->p_rtime.tv_sec,
+                                   (u_int)p->p_rtime.tv_usec / 10000);
+                       if (p->p_wchan && argc > 1) {
+                               if (p->p_wmesg)
+                                       printf("%12s ", p->p_wmesg);
+                               printf("%x", (u_int)p->p_wchan);
+                       }
+                       printf("\n");
+               }
+               ap = p->p_list.le_next;
+               if (ap == 0 && np > 0)
+                       ap = (struct proc*)zombproc.lh_first;
+               p = ap;
+       }
+       (void)splx(s);
+}
+
+
+void
+debug_show_callout(argc, argv)
+       int argc;
+       char *argv[];
+{
+       register struct callout *p1;
+       register int    cum;
+       register int    s;
+       register int    t;
+
+       s = splhigh();
+       printf("      cum     ticks   func     arg\n");
+       for (cum = 0, p1 = calltodo.c_next; p1; p1 = p1->c_next) {
+               t = p1->c_time;
+               if (t > 0)
+                       cum += t;
+               printf("%9d %9d %08x %08x\n", cum, t, (u_int) p1->c_func,
+                   (u_int) p1->c_arg);
+       }
+       (void)splx(s);
+}
+
+void
+debug_show_fs(argc, argv)
+       int argc;
+       char *argv[];
+{
+       struct vfsops **vfsp;
+       int s;
+       
+       s = splhigh();
+
+       printf("Registered filesystems (%d)\n", nvfssw);
+         
+       for (vfsp = &vfssw[0]; vfsp < &vfssw[nvfssw]; vfsp++) {
+               if (*vfsp == NULL)
+                       continue;
+               printf("  %s\n", (*vfsp)->vfs_name);
+       }
+       (void)splx(s);
+}
+
+
+void
+debug_show_vm_map(map, text)
+       vm_map_t map;
+       char *text;
+{
+       vm_map_entry_t mapentry;
+       int s;
+       
+       s = splhigh();
+    
+       printf("vm_map dump : %s\n", text);
+
+       mapentry = &map->header;
+
+       do {
+               printf("vm_map_entry: start = %08x end = %08x\n",
+                   (u_int) mapentry->start, (u_int) mapentry->end);
+               mapentry = mapentry->next;
+       } while (mapentry != &map->header);
+       (void)splx(s);
+}
+
+
+void
+debug_show_pmap(pmap)
+       pmap_t pmap;
+{
+       u_int loop;
+       u_int loop1;
+       u_int start;
+       pt_entry_t *pt;
+       pd_entry_t *pd;
+       int s;
+       
+       s = splhigh();
+
+       pd = (pd_entry_t *)pmap;
+
+       printf("pdir=%08x\n", (u_int) pd);    
+       for (loop = 0; loop < 4096; ++loop) {
+               if (pd[loop] == 0)
+                       continue;
+               printf("%08x : %08x\n", loop * 1024*1024, pd[loop]);
+               if ((pd[loop] & 0xff) == 0x11) {
+                       pt = (pt_entry_t *)(PROCESS_PAGE_TBLS_BASE
+                           + loop * 1024);
+                       loop1 = 0;
+                       while (loop1 < 256) {
+                               if (pt[loop1]) {
+                                       start = loop1;
+                                       ++loop1;
+                                       while (loop1 < 256 && pt[loop1])
+                                               ++loop1;
+                                       printf("  %08x -> %08x\n",
+                                         loop * 1024*1024 + start * 4096,
+                                         loop * 1024*1024 + loop1 * 4096 - 1);
+                               }
+                               ++loop1;
+                       }
+               }
+       }
+       (void)splx(s);
+}
+
+/* End of debug.c */
diff --git a/sys/arch/arm32/arm32/disassem.c b/sys/arch/arm32/arm32/disassem.c
new file mode 100644 (file)
index 0000000..4ebddbd
--- /dev/null
@@ -0,0 +1,650 @@
+/* $NetBSD: disassem.c,v 1.3 1996/03/16 00:13:09 thorpej Exp $ */
+
+/*
+ * Copyright (c) 1994 Mark Brinicombe.
+ * Copyright (c) 1994 Brini.
+ * All rights reserved.
+ *
+ * This code is derived from software written for Brini by Mark Brinicombe
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided 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 Brini.
+ * 4. The name of the company nor the name of the author may be used to
+ *    endorse or promote products derived from this software without specific
+ *    prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BRINI ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL BRINI 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.
+ *
+ * RiscBSD kernel project
+ *
+ * disassem.c
+ *
+ * Debug / Monitor disassembler
+ *
+ * Created      : 09/10/94
+ */
+
+/* Include standard header files */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+
+/* Local header files */
+
+#include <machine/katelib.h>
+
+typedef u_int (*instruction_decoder) (u_int addr, u_int word);
+
+typedef struct _opcodes {
+       u_int mask;
+       u_int pattern;
+       u_int colour;
+       instruction_decoder decoder;
+} opcodes_struct;
+
+u_int instruction_swi(u_int addr, u_int word);
+u_int instruction_branch(u_int addr, u_int word);
+u_int instruction_mul(u_int addr, u_int word);
+u_int instruction_mla(u_int addr, u_int word);
+u_int instruction_ldrstr(u_int addr, u_int word);
+u_int instruction_ldmstm(u_int addr, u_int word);
+u_int instruction_dataproc(u_int addr, u_int word);
+u_int instruction_swap(u_int addr, u_int word);
+u_int instruction_mrs(u_int addr, u_int word);
+u_int instruction_msr(u_int addr, u_int word);
+u_int instruction_msrf(u_int addr, u_int word);
+u_int instruction_mrcmcr(u_int addr, u_int word);
+u_int instruction_cdp(u_int addr, u_int word);
+u_int instruction_cdt(u_int addr, u_int word);
+u_int instruction_fpabinop(u_int addr, u_int word);
+u_int instruction_fpaunop(u_int addr, u_int word);
+u_int instruction_ldfstf(u_int addr, u_int word);
+
+/* Declare global variables */
+
+opcodes_struct opcodes[] = {
+    { 0x0f000000, 0x0f000000, 7, instruction_swi },
+    { 0x0e000000, 0x0a000000, 7, instruction_branch },
+    { 0x0fe000f0, 0x00000090, 7, instruction_mul },
+    { 0x0fe000f0, 0x00200090, 7, instruction_mla },
+    { 0x0e000000, 0x04000000, 7, instruction_ldrstr },
+    { 0x0c000010, 0x04000000, 7, instruction_ldrstr },
+    { 0x0e000000, 0x08000000, 6, instruction_ldmstm },
+    { 0x0FB00FF0, 0x01000090, 7, instruction_swap },
+    { 0x0FBF0FFF, 0x010F0000, 1, instruction_mrs },
+    { 0x0DBFFFF0, 0x0129F000, 1, instruction_msr },
+    { 0x0DBFFFF0, 0x0128F000, 1, instruction_msrf },
+    { 0x0C000000, 0x00000000, 7, instruction_dataproc },
+    { 0x0F008F10, 0x0E000100, 3, instruction_fpabinop },
+    { 0x0F008F10, 0x0E008100, 3, instruction_fpaunop },
+    { 0x0E000F00, 0x0C000100, 3, instruction_ldfstf },
+    { 0x0F000010, 0x0E000010, 2, instruction_mrcmcr },
+    { 0x0F000010, 0x0E000000, 2, instruction_cdp },
+    { 0x0E000000, 0x0C000000, 2, instruction_cdt },
+    { 0x00000000, 0x00000000, 0, NULL }
+};
+
+char *opcode_conditions[] = {
+    "EQ",
+    "NE",
+    "CS",
+    "CC",
+    "MI",
+    "PL",
+    "VS",
+    "VC",
+    "HI",
+    "LS",
+    "GE",
+    "LT",
+    "GT",
+    "LE",
+    "",
+    "NV"
+};
+
+char *opcode_data_procs[] = {
+    "AND",
+    "EOR",
+    "SUB",
+    "RSB",
+    "ADD",
+    "ADC",
+    "SBC",
+    "RSC",
+    "TST",
+    "TEQ",
+    "CMP",
+    "CMN",
+    "ORR",
+    "MOV",
+    "BIC",
+    "MVN"
+};
+
+char *opcode_shifts[] = {
+    "LSL",
+    "LSR",
+    "ASR",
+    "ROR"
+};
+
+char *opcode_block_transfers[] = {
+    "DA",
+    "IA",
+    "DB",
+    "IB"
+};
+
+char *opcode_stack_block_transfers[] = {
+    "FA",
+    "EA",
+    "FD",
+    "FA"
+};
+
+char *opcode_fpabinops[] = {
+    "ADF",
+    "MUF",
+    "SUF",
+    "RSF",
+    "DVF",
+    "RDF",
+    "POW",
+    "RPW",
+    "RMF",
+    "FML",
+    "FDV",
+    "FRD",
+    "POL",
+    "???",
+    "???",
+    "???",
+    "???"
+};
+
+char *opcode_fpaunops[] = {
+    "MVF",
+    "MNF",
+    "ABS",
+    "RND",
+    "SQT",
+    "LOG",
+    "LGN",
+    "EXP",
+    "SIN",
+    "COS",
+    "TAN",
+    "ASN",
+    "ACS",
+    "ATN",
+    "???",
+    "???",
+    "???"
+};
+
+char *opcode_fpaconstants[] = {
+    "0.0",
+    "1.0",
+    "2.0",
+    "3.0",
+    "4.0",
+    "5.0",
+    "0.5",
+    "10.0"
+};
+
+char *opcode_fpa_rounding[] = {
+    "",
+    "P",
+    "M",
+    "Z"
+};
+
+char *opcode_fpa_precision[] = {
+    "S",
+    "D",
+    "E",
+    "P"
+};
+
+#define opcode_condition(x) opcode_conditions[x >> 28]
+
+#define opcode_s(x) ((x & 0x00100000) ? "S" : "")
+
+#define opcode_b(x) ((x & 0x00400000) ? "B" : "")
+
+#define opcode_t(x) ((x & 0x01200000) == 0x00200000 ? "T" : "")
+
+#define opcode_dataproc(x) opcode_data_procs[(x >> 21) & 0x0f]
+
+#define opcode_shift(x) opcode_shifts[(x >> 5) & 3]
+
+#define opcode_blktrans(x) opcode_block_transfers[(x >> 23) & 3]
+
+#define opcode_stkblktrans(x) opcode_stack_block_transfers[(x >> 23) & 3]
+
+#define opcode_fpabinop(x) opcode_fpabinops[(x >> 20) & 0x0f]
+
+#define opcode_fpaunop(x) opcode_fpaunops[(x >> 20) & 0x0f]
+
+#define opcode_fpaimm(x) opcode_fpaconstants[x & 0x07]
+
+#define opcode_fparnd(x) opcode_fpa_rounding[(x >> 5) & 0x03]
+
+#define opcode_fpaprec(x) opcode_fpa_precision[(((x >> 18) & 2)|(x >> 7)) & 3]
+
+/* Declare external variables */
+
+extern caddr_t shell_ident;
+
+/* Local function prototypes */
+
+u_int disassemble(u_char *addr);
+
+/* Now for the main code */
+
+void
+printascii(byte)
+       int byte;
+{
+       if (byte < 0x20)
+               printf("\x1b[31m%c\x1b[0m", byte + '@');
+       else if (byte == 0x7f)
+               printf("\x1b[31m?\x1b[0m");
+       else
+               printf("%c", byte);
+}
+
+
+u_int disassemble(u_char *addr)
+  {
+    int loop;
+    u_int word;
+    u_int result = 0;
+
+    printf("%08x : ", (u_int)addr);
+
+    word = *((u_int *)addr);
+
+    for (loop = 0; loop < 4; ++loop)
+      printascii(addr[loop]);
+
+    printf(" : %08x :    ", word);
+
+    loop = 0;
+
+    while (opcodes[loop].mask != 0)
+      {
+        if ((word & opcodes[loop].mask) == opcodes[loop].pattern)
+          {
+            printf("\x1b[3%dm", opcodes[loop].colour);
+            result = (*opcodes[loop].decoder)((u_int )addr, word);
+            printf("\x1b[0m");
+            break;
+          }
+        ++loop;
+      }
+
+    if (opcodes[loop].mask == 0)
+      printf("Undefined instruction");
+
+    printf("\n\r");
+    return(result);
+  }
+
+
+u_int instruction_swi(u_int addr, u_int word)
+  {
+    printf("SWI%s\t0x%08x", opcode_condition(word), (word & 0x00ffffff));
+    return(addr);
+  }
+
+
+u_int instruction_branch(u_int addr, u_int word)
+  {
+    u_int branch;
+
+    branch = ((word << 2) & 0x03ffffff);
+    if (branch & 0x02000000)
+      branch |= 0xfc000000;
+
+    branch += addr + 8;
+
+    if (word & 0x01000000)
+      printf("BL%s\t0x%08x", opcode_condition(word), branch);
+    else
+      printf("B%s\t0x%08x", opcode_condition(word), branch);
+
+    return(branch);
+  }
+
+
+u_int instruction_mul(u_int addr, u_int word)
+  {
+    printf("MUL%s%s\t", opcode_condition(word), opcode_s(word));
+
+    printf("r%d, r%d, r%d", (word >> 16) & 0x0f, word & 0x0f,
+      (word >> 8) & 0x0f);
+    return(addr);
+  }
+
+
+u_int instruction_mla(u_int addr, u_int word)
+  {
+    printf("MLA%s%s\t", opcode_condition(word), opcode_s(word));
+
+    printf("r%d, r%d, r%d, r%d", (word >> 16) & 0x0f, word & 0x0f,
+      (word >> 8) & 0x0f, (word >> 12) & 0x0f);
+    return(addr);
+  }
+
+
+void register_shift(u_int word)
+  {
+    printf("r%d", (word & 0x0f));
+    if ((word & 0x00000ff0) == 0)
+      ;
+    else if ((word & 0x00000ff0) == 0x00000060)
+      printf(", RRX");
+    else
+      {
+        if (word & 0x10)
+          {
+            printf(", %s r%d", opcode_shift(word), (word >> 8) & 0x0f);
+          }
+        else
+          {
+            printf(", %s #%d", opcode_shift(word), (word >> 7) & 0x1f);
+          }
+      }
+  }
+
+
+u_int instruction_ldrstr(u_int addr, u_int word)
+  {
+    printf("%s%s%s%s\t", (word & 0x00100000) ? "LDR" : "STR",
+      opcode_condition(word), opcode_b(word), opcode_t(word));
+
+    printf("r%d, ", (word >> 12) & 0x0f);
+
+    if (((word >> 16) & 0x0f) == 16)
+      {
+/*        u_int location;
+
+        location = addr + 8;
+
+        addr = */
+      }
+    else
+      {
+        printf("[r%d", (word >> 16) & 0x0f);
+
+        printf("%s, ", (word & (1 << 24)) ? "" : "]");
+
+        if (!(word & 0x00800000))
+          printf("-");
+
+        if (word & (1 << 25))
+          register_shift(word);
+        else
+          printf("#0x%04x", word & 0xfff);
+
+        if (word & (1 << 24))
+          printf("]");
+
+        if (word & (1 << 21))
+          printf("!");
+      }
+
+    return(addr);
+  }
+
+
+u_int instruction_ldmstm(u_int addr, u_int word)
+  {
+    int loop;
+    int start;
+
+    printf("%s%s%s\t", (word & 0x00100000) ? "LDM" : "STM",
+      opcode_condition(word), opcode_blktrans(word));
+
+    printf("r%d", (word >> 16) & 0x0f);
+
+    if (word & (1 << 21))
+      printf("!");
+
+    printf(", {");
+
+    start = -1;
+
+    for (loop = 0; loop < 17; ++loop)
+      {
+        if (start != -1)
+          {
+            if (!(word & (1 << loop)) || loop == 16)
+              {
+                if (start == loop - 1)
+                  printf("r%d, ", start);
+                else
+                  printf("r%d-r%d, ", start, loop - 1);
+                start = -1;
+              }
+          }
+        else
+          {
+            if (word & (1 << loop))
+              start = loop;
+          }
+
+      }
+    printf("\x7f\x7f}");
+
+    if (word & (1 << 22))
+      printf("^");
+    return(addr);
+  }
+
+
+u_int instruction_dataproc(u_int addr, u_int word)
+  {
+    if ((word & 0x01800000) == 0x01000000)
+      word = word & ~(1<<20);
+
+    printf("%s%s%s\t", opcode_dataproc(word), opcode_condition(word),
+      opcode_s(word));
+
+    if ((word & 0x01800000) != 0x01000000)
+      printf("r%d, ", (word >> 12) & 0x0f);
+
+    if ((word & 0x01a00000) != 0x01a00000)
+      printf("r%d, ", (word >> 16) & 0x0f);
+
+    if (word & 0x02000000)
+      {
+        printf("#&%08x", (word & 0xff) << (((word >> 7) & 0x1e)));
+      }
+    else
+      {
+        register_shift(word);
+      }
+    return(addr);
+  }
+
+
+u_int instruction_swap(u_int addr, u_int word)
+  {
+    printf("SWP%s%s\t", opcode_condition(word), opcode_b(word));
+
+    printf("r%d, r%d, [r%d]", (word >> 12) & 0x0f, (word & 0x0f),
+      (word >> 16) & 0x0f);
+    return(addr);
+  }
+
+
+u_int instruction_mrs(u_int addr, u_int word)
+  {
+    printf("MRS%s\tr%d, ", opcode_condition(word), (word >> 12) & 0x0f);
+
+    printf("%s", (word & 0x00400000) ? "SPSR" : "CPSR");
+    return(addr);
+  }
+
+
+u_int instruction_msr(u_int addr, u_int word)
+  {
+    printf("MSR%s\t", opcode_condition(word));
+
+    printf("%s, r%d", (word & 0x00400000) ? "SPSR" : "CPSR", word & 0x0f);
+
+    return(addr);
+  }
+
+
+u_int instruction_msrf(u_int addr, u_int word)
+  {
+    printf("MSR%s\t", opcode_condition(word));
+
+    printf("%s_flg, ", (word & 0x00400000) ? "SPSR" : "CPSR");
+
+    if (word & 0x02000000)
+      printf("#0x%08x", (word & 0xff) << (32 - ((word >> 7) & 0x1e)));
+    else
+      printf("r%d", word &0x0f);
+    return(addr);
+  }
+
+
+u_int instruction_mrcmcr(u_int addr, u_int word)
+  {
+    printf("%s%s\t", (word & (1 << 20)) ? "MRC" : "MCR",
+      opcode_condition(word));
+
+    printf("CP #%d, %d, ", (word >> 8) & 0x0f, (word >> 21) & 0x07);
+
+    printf("r%d, cr%d, cr%d", (word >> 12) & 0x0f, (word >> 16) & 0x0f,
+      word & 0x0f);
+
+    if (((word >> 5) & 0x07) != 0)
+      printf(", %d", (word >> 5) & 0x07);
+
+    return(addr);
+  }
+
+
+u_int instruction_cdp(u_int addr, u_int word)
+  {
+    printf("CDP%s\t", opcode_condition(word));
+
+    printf("CP #%d, %d, ", (word >> 8) & 0x0f, (word >> 20) & 0x0f);
+
+    printf("cr%d, cr%d, cr%d", (word >> 12) & 0x0f, (word >> 16) & 0x0f,
+      word & 0x0f);
+
+    printf(", %d", (word >> 5) & 0x07);
+
+    return(addr);
+  }
+
+
+u_int instruction_cdt(u_int addr, u_int word)
+  {
+    printf("%s%s%s\t", (word & (1 << 20)) ? "LDC" : "STC",
+      opcode_condition(word), (word & (1 << 22)) ? "L" : "");
+
+    printf("CP #%d, cr%d, ", (word >> 8) & 0x0f, (word >> 12) & 0x0f);
+
+    printf("[r%d", (word >> 16) & 0x0f);
+
+    printf("%s, ", (word & (1 << 24)) ? "" : "]");
+
+    if (!(word & (1 << 23)))
+      printf("-");
+
+    printf("#0x%02x", word & 0xff);
+
+    if (word & (1 << 24))
+      printf("]");
+
+    if (word & (1 << 21))
+      printf("!");
+
+    return(addr);
+  }
+
+
+u_int instruction_fpabinop(u_int addr, u_int word)
+  {
+    printf("%s%s%s%s\t", opcode_fpabinop(word), opcode_condition(word),
+      opcode_fpaprec(word), opcode_fparnd(word));
+
+    printf("f%d, f%d, ", (word >> 12) & 0x07, (word >> 16) & 0x07);
+
+    if (word & (1 << 3))
+      printf("#%s", opcode_fpaimm(word));
+    else
+      printf("f%d", word & 0x07);
+
+    return(addr);
+  }
+
+
+u_int instruction_fpaunop(u_int addr, u_int word)
+  {
+    printf("%s%s%s%s\t", opcode_fpaunop(word), opcode_condition(word),
+      opcode_fpaprec(word), opcode_fparnd(word));
+
+    printf("f%d, ", (word >> 12) & 0x07);
+
+    if (word & (1 << 3))
+      printf("#%s", opcode_fpaimm(word));
+    else
+      printf("f%d", word & 0x07);
+
+    return(addr);
+  }
+
+
+u_int instruction_ldfstf(u_int addr, u_int word)
+  {
+    printf("%s%s%s\t", (word & (1 << 20)) ? "LDF" : "STF",
+      opcode_condition(word), (word & (1 << 22)) ? "L" : "");
+
+    printf("f%d, [r%d", (word >> 12) & 0x07, (word >> 16) & 0x0f);
+
+    printf("%s, ", (word & (1 << 24)) ? "" : "]");
+
+    if (!(word & (1 << 23)))
+      printf("-");
+
+    printf("#0x%03x", (word & 0xff) << 2);
+
+    if (word & (1 << 24))
+      printf("]");
+
+    if (word & (1 << 21))
+      printf("!");
+
+    return(addr);
+  }
+
+/* End of disassem.c */
diff --git a/sys/arch/arm32/arm32/disksubr.c b/sys/arch/arm32/arm32/disksubr.c
new file mode 100644 (file)
index 0000000..d35dd1d
--- /dev/null
@@ -0,0 +1,572 @@
+/* $NetBSD: disksubr.c,v 1.2 1996/03/06 22:43:11 mark Exp $ */
+
+/*
+ * Copyright (c) 1982, 1986, 1988 Regents of the University of California.
+ * Copyright (c) 1995 Mark Brinicombe
+ * 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: @(#)ufs_disksubr.c        7.16 (Berkeley) 5/4/91
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/buf.h>
+#include <sys/dkbad.h>
+#include <sys/disklabel.h>
+#include <sys/syslog.h>
+#include <sys/device.h>
+#include <sys/disk.h>
+
+#define        b_cylin b_resid
+
+/* int filecore_checksum(char *bootblock)
+ *
+ * Calculates the filecore boot block checksum. This is used to validate
+ * a filecore boot block on the disc. If a boot block is validated then
+ * it is used to locate the partition table. If the boot block is not
+ * validated, it is assumed that the whole disc is RiscBSD.
+ */
+
+/*
+ * This can be coded better using add with carry but as it is used rarely
+ * there is not much point writing it in assembly.
+ */
+u_int
+filecore_checksum(bootblock)
+       u_char *bootblock;
+{
+       register u_int sum;
+       register u_int loop;
+
+/* A boot block of zero has a zero checksum - clever thinking Acorn, NOT ! */
+
+       sum = 0;
+
+       for (loop = 0; loop < 512; ++loop)
+               sum += bootblock[loop];
+
+/* If the whole block is zero then it is invalid */
+
+       if (sum == 0) return(0xffff);
+    
+       sum = 0;
+    
+       for (loop = 0; loop < 511; ++loop) {
+               sum += bootblock[loop];
+               if (sum > 255)
+                       sum -= 255;
+       }
+
+       return(sum);
+}
+
+
+/*
+ * Attempt to read a disk label from a device
+ * using the indicated stategy routine.
+ * The label must be partly set up before this:
+ * secpercyl, secsize and anything required for a block i/o read
+ * operation in the driver's strategy/start routines
+ * must be filled in before calling us.
+ *
+ * If dos partition table requested, attempt to load it and
+ * find disklabel inside a DOS partition. Also, if bad block
+ * table needed, attempt to extract it as well. Return buffer
+ * for use in signalling errors if requested.
+ *
+ * Returns null on success and an error string on failure.
+ */
+
+char *
+readdisklabel(dev, strat, lp, osdep)
+       dev_t dev;
+       void (*strat)();
+       struct disklabel *lp;
+       struct cpu_disklabel *osdep;
+{
+       struct riscbsd_partition *rp = osdep->partitions;
+       struct dkbad *bdp = &osdep->bad;
+       register struct buf *bp;
+       struct disklabel *dlp;
+       char *msg = NULL;
+       int cyl, riscbsdpartoff, i;
+
+/*     printf("Reading disclabel for %04x\n", dev);*/
+
+/* minimal requirements for archtypal disk label */
+
+       if (lp->d_secsize == 0)
+               lp->d_secsize = DEV_BSIZE;
+
+       if (lp->d_secperunit == 0)
+               lp->d_secperunit = 0x1fffffff;
+
+       lp->d_npartitions = MAXPARTITIONS;
+       for (i = 0; i < MAXPARTITIONS; i++) {
+               if (i == RAW_PART) continue;
+               lp->d_partitions[i].p_offset = 0;
+               lp->d_partitions[i].p_fstype = FS_UNUSED;
+               lp->d_partitions[i].p_size = 0;
+       }
+
+       if (lp->d_partitions[RAW_PART].p_size == 0) {
+               lp->d_partitions[RAW_PART].p_fstype = FS_UNUSED; 
+               lp->d_partitions[RAW_PART].p_offset = 0; 
+               lp->d_partitions[RAW_PART].p_size = 0x1fffffff;
+       }
+
+/* obtain buffer to probe drive with */
+    
+       bp = geteblk((int)lp->d_secsize);
+       
+/* request no partition relocation by driver on I/O operations */
+
+       bp->b_dev = dev;
+
+/* do riscbsd partitions in the process of getting disklabel? */
+
+       riscbsdpartoff = 0;
+       cyl = LABELSECTOR / lp->d_secpercyl;
+
+       if (rp) {
+               struct filecore_bootblock *bb;
+               int heads;
+               int sectors;
+
+/* read the filecore boot block */
+
+/*             printf("readdisclabel: Reading boot block\n");*/
+
+               bp->b_blkno = FILECORE_BOOT_SECTOR;
+               bp->b_bcount = lp->d_secsize;
+               bp->b_flags = B_BUSY | B_READ;
+               bp->b_cylin = bp->b_blkno / lp->d_secpercyl;
+               (*strat)(bp);
+
+/* if successful, validate boot block and locate parition table */
+
+               if (biowait(bp)) {
+                       msg = "filecore boot block I/O error";
+                       goto done;
+               }
+
+               bb = (struct filecore_bootblock *)bp->b_data;
+
+/* Validate boot block */
+        
+               if (bb->checksum != filecore_checksum((u_char *)bb)) {
+
+/* Invalid boot block so lets assume the entire disc is RiscBSD */
+
+/*                     printf("readdisklabel: Invalid filecore boot block (incorrect checksum)\n");*/
+                       goto readlabel;
+               }
+
+/* Get some information from the boot block */
+
+               cyl = bb->partition_cyl_low + (bb->partition_cyl_high << 8);
+
+               heads = bb->heads;
+               sectors = bb->secspertrack;
+                        
+/* Do we have a RiscBSD partition table ? */
+
+               if (bb->partition_type == PARTITION_FORMAT_RISCBSD) {
+/*                     printf("heads = %d nsectors = %d\n", heads, sectors);*/
+
+                       riscbsdpartoff = cyl * heads * sectors;
+               } else if (bb->partition_type == PARTITION_FORMAT_RISCIX) {
+                       struct riscix_partition_table *rpt;
+                       int loop;
+                       
+/* We have a RISCiX partition table :-( groan */
+
+/* Ok read the RISCiX partition table and see if there is a RiscBSD partition */
+
+                       bp->b_blkno = cyl * heads * sectors;
+                       printf("Found RiscIX partition table @ %08x\n", bp->b_blkno);
+                       bp->b_cylin = bp->b_blkno / lp->d_secpercyl;
+                       bp->b_bcount = lp->d_secsize;
+                       bp->b_flags = B_BUSY | B_READ;
+                       (*strat)(bp);
+
+/* if successful, locate disk label within block and validate */
+
+                       if (biowait(bp)) {
+                               msg = "disk label I/O error";
+                               goto done;
+                       }
+
+                       rpt = (struct riscix_partition_table *)bp->b_data;
+/*                     for (loop = 0; loop < NRISCIX_PARTITIONS; ++loop)
+                               printf("p%d: %16s %08x %08x %08x\n", loop,
+                                   rpt->partitions[loop].rp_name,
+                                   rpt->partitions[loop].rp_start,
+                                   rpt->partitions[loop].rp_length,
+                                   rpt->partitions[loop].rp_type);
+*/
+                       for (loop = 0; loop < NRISCIX_PARTITIONS; ++loop) {
+                               if (strcmp(rpt->partitions[loop].rp_name, "RiscBSD") == 0
+                                   || strcmp(rpt->partitions[loop].rp_name, "NetBSD") == 0) {
+                                       riscbsdpartoff = rpt->partitions[loop].rp_start;
+                                       break;
+                               }
+                       }
+                       if (loop == NRISCIX_PARTITIONS) {
+                               msg = "RiscBSD partition identifier string not found.";
+                               goto done;
+                       }
+               } else {
+                       msg = "Invalid partition format";
+                       goto done;
+               }
+       }
+
+/* next, dig out disk label */
+
+readlabel:
+/*     printf("Reading disklabel addr=%08x\n", riscbsdpartoff * DEV_BSIZE);*/
+  
+       bp->b_blkno = riscbsdpartoff + LABELSECTOR;
+       bp->b_cylin = bp->b_blkno / lp->d_secpercyl;
+       bp->b_bcount = lp->d_secsize;
+       bp->b_flags = B_BUSY | B_READ;
+       (*strat)(bp);
+
+/* if successful, locate disk label within block and validate */
+
+       if (biowait(bp)) {
+               msg = "disk label I/O error";
+               goto done;
+       }
+       for (dlp = (struct disklabel *)bp->b_data;
+           dlp <= (struct disklabel *)(bp->b_data + lp->d_secsize - 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;
+               }
+       }
+
+       if (msg)
+               goto done;
+
+       /* obtain bad sector table if requested and present */
+       if (bdp && (lp->d_flags & D_BADSECT)) {
+               struct dkbad *db;
+
+               i = 0;
+               do {
+                       /* read a bad sector table */
+                       bp->b_flags = B_BUSY | B_READ;
+                       bp->b_blkno = lp->d_secperunit - lp->d_nsectors + i;
+                       if (lp->d_secsize > DEV_BSIZE)
+                               bp->b_blkno *= lp->d_secsize / DEV_BSIZE;
+                       else
+                               bp->b_blkno /= DEV_BSIZE / lp->d_secsize;
+                       bp->b_bcount = lp->d_secsize;
+                       bp->b_cylin = lp->d_ncylinders - 1;
+                       (*strat)(bp);
+
+                       /* if successful, validate, otherwise try another */
+                       if (biowait(bp)) {
+                               msg = "bad sector table I/O error";
+                       } else {
+                               db = (struct dkbad *)(bp->b_data);
+#define DKBAD_MAGIC 0x4321
+                               if (db->bt_mbz == 0
+                                       && db->bt_flag == DKBAD_MAGIC) {
+                                       msg = NULL;
+                                       *bdp = *db;
+                                       break;
+                               } else
+                                       msg = "bad sector table corrupted";
+                       }
+               } while ((bp->b_flags & B_ERROR) && (i += 2) < 10 &&
+                       i < lp->d_nsectors);
+       }
+
+done:
+       bp->b_flags = B_INVAL | B_AGE | B_READ;
+       brelse(bp);
+       return (msg);
+}
+
+
+/*
+ * Check new disk label for sensibility
+ * before setting it.
+ */
+
+int
+setdisklabel(olp, nlp, openmask, osdep)
+       struct disklabel *olp;
+       struct disklabel *nlp;
+       u_long openmask;
+       struct cpu_disklabel *osdep;
+{
+       register i;
+       register struct partition *opp, *npp;
+
+/* sanity clause */
+
+       if (nlp->d_secpercyl == 0 || nlp->d_secsize == 0
+           || (nlp->d_secsize % DEV_BSIZE) != 0)
+               return(EINVAL);
+
+/* special case to allow disklabel to be invalidated */
+
+       if (nlp->d_magic == 0xffffffff) {
+               *olp = *nlp;
+               return (0);
+       }
+
+       if (nlp->d_magic != DISKMAGIC || nlp->d_magic2 != DISKMAGIC
+           || dkcksum(nlp) != 0)
+               return (EINVAL);
+
+/* XXX missing check if other dos partitions will be overwritten */
+
+       while (openmask != 0) {
+               i = ffs(openmask) - 1;
+               openmask &= ~(1 << i);
+               if (nlp->d_npartitions <= i)
+                       return (EBUSY);
+               opp = &olp->d_partitions[i];
+               npp = &nlp->d_partitions[i];
+               if (npp->p_offset != opp->p_offset || npp->p_size < opp->p_size)
+                       return (EBUSY);
+               /*
+                * Copy internally-set partition information
+                * if new label doesn't include it.             XXX
+                */
+               if (npp->p_fstype == FS_UNUSED && opp->p_fstype != FS_UNUSED) {
+                       npp->p_fstype = opp->p_fstype;
+                       npp->p_fsize = opp->p_fsize;
+                       npp->p_frag = opp->p_frag;
+                       npp->p_cpg = opp->p_cpg;
+               }
+       }
+
+       nlp->d_checksum = 0;
+       nlp->d_checksum = dkcksum(nlp);
+       *olp = *nlp;
+       return (0);
+}
+
+
+/*
+ * Write disk label back to device after modification.
+ */
+int
+writedisklabel(dev, strat, lp, osdep)
+       dev_t dev;
+       void (*strat)();
+       struct disklabel *lp;
+       struct cpu_disklabel *osdep;
+{
+       struct riscbsd_partition *rp = osdep->partitions;
+       register struct buf *bp;
+       struct disklabel *dlp;
+       int cyl, riscbsdpartoff;
+       int error = 0;
+
+/* get a buffer and initialize it */
+
+       bp = geteblk((int)lp->d_secsize);
+       bp->b_dev = dev;
+
+/* do riscbsd partitions in the process of getting disklabel? */
+
+       riscbsdpartoff = 0;
+       cyl = LABELSECTOR / lp->d_secpercyl;
+
+       if (rp) {
+               struct filecore_bootblock *bb;
+               int heads;
+               int sectors;
+
+/* read the filecore boot block */
+
+               printf("writedisklabel: Reading boot block\n");
+
+               bp->b_blkno = FILECORE_BOOT_SECTOR;
+               bp->b_bcount = lp->d_secsize;
+               bp->b_flags = B_BUSY | B_READ;
+               bp->b_cylin = bp->b_blkno / lp->d_secpercyl;
+               (*strat)(bp);
+
+/* if successful, validate boot block and locate parition table */
+
+               if (biowait(bp)) {
+                       printf("writedisklabel: filecore boot block I/O error\n");
+                       goto done;
+               }
+
+               bb = (struct filecore_bootblock *)bp->b_data;
+
+/* Validate boot block */
+        
+               if (bb->checksum != filecore_checksum((u_char *)bb)) {
+/* Invalid boot block so lets assume the entire disc is RiscBSD */
+
+                       printf("writedisklabel: Invalid filecore boot block (incorrect checksum)\n");
+                       goto writelabel;
+               }
+
+/* Do we have a RiscBSD partition ? */
+
+               if (bb->partition_type != PARTITION_FORMAT_RISCBSD) {
+                       printf("writedisklabel: Invalid partition format\n");
+                       goto done;
+               }
+
+               cyl = bb->partition_cyl_low + (bb->partition_cyl_high << 8);
+
+               heads = bb->heads;
+               sectors = bb->secspertrack;
+                        
+               /*printf("heads = %d nsectors = %d\n", heads, sectors);*/
+
+               riscbsdpartoff = cyl * heads * sectors;
+       }
+
+writelabel:
+
+/*     printf("writedisklabel: Reading disklabel addr=%08x\n", riscbsdpartoff * DEV_BSIZE);*/
+
+/* next, dig out disk label */
+
+       bp->b_blkno = riscbsdpartoff + LABELSECTOR;
+       bp->b_cylin = cyl;
+       bp->b_bcount = lp->d_secsize;
+       bp->b_flags = B_BUSY | B_READ;
+       (*strat)(bp);
+
+/* if successful, locate disk label within block and validate */
+
+       if ((error = biowait(bp)))
+               goto done;
+       for (dlp = (struct disklabel *)bp->b_data;
+           dlp <= (struct disklabel *)(bp->b_data + lp->d_secsize - sizeof(*dlp));
+           dlp = (struct disklabel *)((char *)dlp + sizeof(long))) {
+               if (dlp->d_magic == DISKMAGIC && dlp->d_magic2 == DISKMAGIC &&
+                   dkcksum(dlp) == 0) {
+                       *dlp = *lp;
+                       bp->b_flags = B_BUSY | B_WRITE;
+                       (*strat)(bp);
+                       error = biowait(bp);
+                       goto done;
+               }
+       }
+
+       error = ESRCH;
+
+done:
+       bp->b_flags |= B_INVAL;
+       brelse(bp);
+       return (error);
+}
+
+
+/*
+ * Determine the size of the transfer, and make sure it is
+ * within the boundaries of the partition. Adjust transfer
+ * if needed, and signal errors or early completion.
+ */
+int
+bounds_check_with_label(bp, lp, wlabel)
+       struct buf *bp;
+       struct disklabel *lp;
+       int wlabel;
+{
+       struct partition *p = lp->d_partitions + DISKPART(bp->b_dev);
+       int labelsector = lp->d_partitions[0].p_offset + LABELSECTOR;
+       int sz;
+
+       sz = howmany(bp->b_bcount, lp->d_secsize);
+
+       if (bp->b_blkno + sz > p->p_size) {
+               sz = p->p_size - bp->b_blkno;
+               if (sz == 0) {
+                       /* If exactly at end of disk, return EOF. */
+                       bp->b_resid = bp->b_bcount;
+                       goto done;
+               }
+               if (sz < 0) {
+                       /* If past end of disk, return EINVAL. */
+                       bp->b_error = EINVAL;
+                       goto bad;
+               }
+               /* Otherwise, truncate request. */
+               bp->b_bcount = sz << DEV_BSHIFT;
+       }
+
+       /* Overwriting disk label? */
+       if (bp->b_blkno + p->p_offset <= labelsector &&
+#if LABELSECTOR != 0
+           bp->b_blkno + p->p_offset + sz > labelsector &&
+#endif
+           (bp->b_flags & B_READ) == 0 && !wlabel) {
+               bp->b_error = EROFS;
+               goto bad;
+       }
+
+       /* calculate cylinder for disksort to order transfers with */
+       bp->b_cylin = (bp->b_blkno + p->p_offset) /
+           (lp->d_secsize / DEV_BSIZE) / lp->d_secpercyl;
+       return (1);
+
+bad:
+       bp->b_flags |= B_ERROR;
+done:
+       return (0);
+}
+
+
+int
+dk_establish(dk, dev)
+       struct dkdevice *dk;
+       struct device *dev;
+{
+       return(-1);
+}
+
+/* End of disksubr.c */
diff --git a/sys/arch/arm32/arm32/exception.S b/sys/arch/arm32/arm32/exception.S
new file mode 100644 (file)
index 0000000..8e4783f
--- /dev/null
@@ -0,0 +1,340 @@
+/* $NetBSD: exception.S,v 1.5 1996/03/13 21:00:26 mark Exp $ */
+
+/*
+ * Copyright (c) 1994-1996 Mark Brinicombe.
+ * Copyright (c) 1994 Brini.
+ * All rights reserved.
+ *
+ * This code is derived from software written for Brini by Mark Brinicombe
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided 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 Brini.
+ * 4. The name of the company nor the name of the author may be used to
+ *    endorse or promote products derived from this software without specific
+ *    prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BRINI ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL BRINI 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.
+ *
+ * RiscBSD kernel project
+ *
+ * exception.S
+ *
+ * Low level handlers for exception vectors
+ *
+ * Created      : 24/09/94
+ *
+ * Based on kate/display/abort.s
+ */
+
+#include <machine/cpu.h>
+#include "assym.h"
+
+/*
+ * PUSHFRAME - macro to push a trap frame on the stack in the current mode
+ * Since the current mode is used, the SVC R14 field is not defined.
+ */
+
+#define PUSHFRAME \
+       str     lr, [sp, #-4]!;         /* Push the return address */ \
+       sub     sp, sp, #0x00000004;    /* Skip SVC R14 */ \
+       stmdb   sp, {r0-r14}^;          /* Push the user mode registers */ \
+       sub     sp, sp, #(4*15);        /* Adjust the stack pointer */ \
+       mrs     r0, spsr_all;           /* Put the SPSR on the stack */ \
+       str     r0, [sp, #-4]!;
+
+/*
+ * PULLFRAME - macro to pull a trap frame from the stack in the current mode
+ * Since the current mode is used, the SVC R14 field is ignored.
+ */
+
+#define PULLFRAME \
+        ldr     r0, [sp], #0x0004;      /* Get the SPSR from stack */ \
+        msr     spsr_all, r0; \
+       add     sp, sp, #(4*15);        /* Adjust the stack pointer */ \
+        ldmdb   sp, {r0-r14}^;         /* Restore the registers (user mode) */ \
+        mov     r0, r0;                 /* NOP for previous instruction */ \
+       add     sp, sp, #0x00000004;    /* Skip SVC R14 */ \
+       ldr     lr, [sp], #0x0004;      /* Pull the return address */
+
+/*
+ * PUSHFRAMEINSVC - macro to push a trap frame on the stack in SVC32 mode
+ * This should only be used if the processor is not currently in SVC32
+ * mode. The processor mode is switched to SVC mode and the trap frame is
+ * stored. The SVC R14 field is used to store the previous value of
+ * R14 in SVC mode.  
+ */
+
+#define PUSHFRAMEINSVC \
+       stmdb   sp, {r0-r3};            /* Save 4 registers */ \
+       mov     r0, lr;                 /* Save xxx32 r14 */ \
+       mov     r1, sp;                 /* Save xxx32 sp */ \
+       mrs     r3, spsr_all;           /* Save xxx32 spsr */ \
+       mrs     r2, cpsr_all;           /* Get the CPSR */ \
+       bic     r2, r2, #(PSR_MODE);    /* Fix for SVC mode */ \
+       orr     r2, r2, #(PSR_SVC32_MODE); \
+       msr     cpsr_all, r2;           /* Punch into SVC mode */ \
+       str     r0, [sp, #-4]!;         /* Push return address */ \
+       str     lr, [sp, #-4]!;         /* Push SVC r14 */ \
+       msr     spsr_all, r3;           /* Restore correct spsr */ \
+       ldmdb   r1, {r0-r3};            /* Restore 4 regs from xxx mode */ \
+       stmdb   sp, {r0-r14}^;          /* Push the user mode registers */ \
+       sub     sp, sp, #(4*15);        /* Adjust the stack pointer */ \
+       mrs     r0, spsr_all;           /* Put the SPSR on the stack */ \
+       str     r0, [sp, #-4]!
+
+/*
+ * PULLFRAMEFROMSVCANDEXIT - macro to pull a trap frame from the stack
+ * in SVC32 mode and restore the saved processor mode and PC.
+ * This should be used when the SVC R14 register needs to be restored on
+ * exit.
+ */
+
+#define PULLFRAMEFROMSVCANDEXIT \
+        ldr     r0, [sp], #0x0004;     /* Get the SPSR from stack */ \
+        msr     spsr_all, r0;          /* restore SPSR */ \
+       add     sp, sp, #(4*15);        /* Adjust the stack pointer */ \
+        ldmdb   sp, {r0-r14}^;         /* Restore the registers (user mode) */ \
+        mov     r0, r0;                        /* NOP for previous instruction */ \
+       ldmia   sp!, {lr, pc}^          /* Restore lr and exit */
+
+sp     .req    r13
+lr     .req    r14
+pc     .req    r15
+
+       .text   
+       .align  0
+
+/* entry point for CPU data abort */
+
+       .global data_abort_entry
+
+data_abort_entry:
+        sub     lr, lr, #0x00000008     /* Adjust the lr */
+
+       PUSHFRAMEINSVC                  /* Push trap frame and switch */
+                                       /* to SVC32 mode */
+
+       mov     r0, sp                  /* pass the stack pointer as r0 */
+
+       add     lr, pc, #Ldata_abort_return - . - 8
+       ldr     r1, Ldata_abort_handler_address
+       ldr     pc, [r1]
+       
+Ldata_abort_return:
+#if 0  /* For now only handle ast's after interrupts */
+       ldr     r0, [sp]                /* Get the SPSR from stack */
+       and     r0, r0, #(PSR_MODE)     /* Test for USR32 mode before the ABT */
+       teq     r0, #(PSR_USR32_MODE)
+       ldreq   r0, Lastpending         /* Do we have an AST pending ? */
+       ldreq   r1, [r0]
+       teqeq   r1, #0x00000001
+       moveq   r1, #0x00000000         /* Clear it */
+       streq   r1, [r0]
+
+       moveq   r0, sp                  /* arg 0 = irq frame */
+       bleq    _ast                    /* call the AST handler */
+#endif
+
+/* Kill IRQ's */
+        mrs     r0, cpsr_all
+        orr     r0, r0, #(I32_bit)
+        msr     cpsr_all, r0
+
+       PULLFRAMEFROMSVCANDEXIT         /* Restore the trap frame and exit */
+
+Ldata_abort_handler_address:
+       .word   _data_abort_handler_address
+
+       .data
+       .global _data_abort_handler_address
+
+_data_abort_handler_address:
+       .word   abortdata
+
+       .text
+abortdata:
+        add     r0, pc, #abortdatamsg - . - 8
+       b       _panic
+
+abortdatamsg:
+        .asciz  "abortdata"
+        .align  0
+
+
+       .global prefetch_abort_entry
+
+prefetch_abort_entry:
+        sub     lr, lr, #0x00000004     /* Adjust the lr */
+
+       PUSHFRAMEINSVC
+
+       mov     r0, sp                  /* pass the stack pointer as r0 */
+
+       add     lr, pc, #Lprefetch_abort_return - . - 8
+       ldr     r1, Lprefetch_abort_handler_address
+       ldr     pc, [r1]
+       
+Lprefetch_abort_return:
+#if 0  /* For the moment ast's are only handled by irq handler */
+       ldr     r0, [sp]                /* Get the SPSR from stack */
+       and     r0, r0, #(PSR_MODE)     /* Test for USR32 mode before the IRQ */
+       teq     r0, #(PSR_USR32_MODE)
+       ldreq   r0, Lastpending         /* Do we have an AST pending ? */
+       ldreq   r1, [r0]
+       teqeq   r1, #0x00000001
+       moveq   r1, #0x00000000         /* Clear it */
+       streq   r1, [r0]
+
+       moveq   r0, sp                  /* arg 0 = irq frame */
+       bleq    _ast                    /* call the AST handler */
+#endif
+
+/* Kill IRQ's */
+        mrs     r0, cpsr_all
+        orr     r0, r0, #(I32_bit)
+        msr     cpsr_all, r0
+
+       PULLFRAMEFROMSVCANDEXIT
+
+Lprefetch_abort_handler_address:
+       .word   _prefetch_abort_handler_address
+
+       .data
+       .global _prefetch_abort_handler_address
+
+_prefetch_abort_handler_address:
+       .word   abortprefetch
+
+       .text
+abortprefetch:
+        add     r0, pc, #abortprefetchmsg - . - 8
+       b       _panic
+
+abortprefetchmsg:
+        .asciz  "abortprefetch"
+        .align  0
+
+
+/*
+ * swi_entry
+ *
+ * Main entry point for the SWI vector
+ */
+
+       .global swi_entry
+swi_entry:
+       PUSHFRAME
+
+       sub     r0, lr, #0x00000004     /* Get the address of the SWI */
+       ldr     r4, [r0]                /* Get the instruction */
+
+       bic     r1, r4, #0xff000000     /* Extract the comment field */
+
+       mov     r0, sp                  /* Pass the frame to any function */
+
+       bl      _syscall                /* It's a syscall ! */
+
+#if 0  /* Ast's only from the irqhandler .... */
+       ldr     r0, Lastpending         /* Do we have an AST pending ? */
+       ldr     r1, [r0]
+       teq     r1, #0x00000001
+       moveq   r1, #0x00000000         /* Clear it */
+       streq   r1, [r0]
+
+       moveq   r0, sp                  /* arg 0 = irq frame */
+       bleq    _ast                    /* call the AST handler */
+#endif
+
+/* Kill irq's */
+
+        mrs     r0, cpsr_all
+        orr     r0, r0, #(I32_bit)
+        msr     cpsr_all, r0
+
+       PULLFRAME
+
+       movs    pc, lr                  /* Exit */
+
+Lastpending:
+        .word   _astpending
+
+       .text
+       .align  0
+
+/*
+ * We indirect the undefined vector via the handler address
+ * in the data area.
+ * Entry to the undefined handler must look like direct
+ * entry from the vector.
+ */
+
+       .global undefined_entry
+undefined_entry:
+       stmfd   sp!, {r0, r1}
+       ldr     r0, Lundefined_handler_indirection
+       ldr     r1, [sp], #0x0004
+       str     r1, [r0, #0x0000]
+       ldr     r1, [sp], #0x0004
+       str     r1, [r0, #0x0004]
+       ldmia   r0, {r0, r1, pc}
+
+Lundefined_handler_indirection:
+       .word   Lundefined_handler_indirection_data
+
+/*
+ * assembly bounce code for calling the kernel
+ * undefined instruction handler. This uses
+ * a standard trap frame and is called in SVC mode.
+ */
+
+       .global _undefinedinstruction_bounce
+_undefinedinstruction_bounce:
+       PUSHFRAMEINSVC
+       mov     r0, sp
+       bl      _undefinedinstruction
+
+/* Kill irq's */
+        mrs     r0, cpsr_all
+        orr     r0, r0, #(I32_bit)
+        msr     cpsr_all, r0
+
+       PULLFRAMEFROMSVCANDEXIT
+
+
+       .data
+       .align  0
+
+/*
+ * Indirection data
+ * 2 words use for preserving r0 and r1
+ * 3rd word contains the undefined handler address.
+ */
+
+Lundefined_handler_indirection_data:
+       .word   0
+       .word   0
+
+       .global _undefined_handler_address
+_undefined_handler_address:
+       .word   _undefinedinstruction_bounce
+
+/* End of exception.S */
diff --git a/sys/arch/arm32/arm32/fault.c b/sys/arch/arm32/arm32/fault.c
new file mode 100644 (file)
index 0000000..c93f5c1
--- /dev/null
@@ -0,0 +1,1242 @@
+/* $NetBSD: fault.c,v 1.3 1996/03/13 21:41:41 mark Exp $ */
+
+/*
+ * Copyright (c) 1994-1996 Mark Brinicombe.
+ * Copyright (c) 1994 Brini.
+ * All rights reserved.
+ *
+ * This code is derived from software written for Brini by Mark Brinicombe
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided 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 Brini.
+ * 4. The name of the company nor the name of the author may be used to
+ *    endorse or promote products derived from this software without specific
+ *    prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BRINI ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL BRINI 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.
+ *
+ * RiscBSD kernel project
+ *
+ * fault.c
+ *
+ * Fault handlers
+ *
+ * Created      : 28/11/94
+ */
+
+/*
+ * Special compilation symbols
+ *
+ * DEBUG_FAULT_CORRECTION - Add debug code used to develop the register 
+ * correction following a data abort.
+ *
+ * CONTINUE_AFTER_SVC_PREFETCH - Do not panic following a prefetch abort
+ * in SVC mode. Used during developement.
+ */
+
+#define DEBUG_FAULT_CORRECTION
+/*#define CONTINUE_AFTER_SVC_PREFETCH*/
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/proc.h>
+#include <sys/user.h>
+#include <sys/kernel.h>
+
+#include <vm/vm_kern.h>
+
+#include <machine/katelib.h>
+#include <machine/cpu.h>
+#include <machine/pte.h>
+
+#include <machine/irqhandler.h>
+#include <machine/frame.h>
+
+extern int pmap_debug_level;
+extern int nopagefault;
+static int onfault_count = 0;
+int nopagefault = 0;           /* gross hack, has to go anyway */
+
+int pmap_modified_emulation __P((pmap_t, vm_offset_t));
+int pmap_handled_emulation __P((pmap_t, vm_offset_t));
+
+u_int disassemble __P((u_int));
+u_int ReadWordWithChecks __P((u_int, u_int *));
+
+/* Abort code */
+
+/* Define text descriptions of the different aborts */
+
+static char *aborts[16] = {
+       "Write buffer fault",
+       "Alignment fault",
+       "Write buffer fault",
+       "Alignment fault",
+       "Bus error (LF section)",
+       "Translation fault (section)",
+       "Bus error (page)",
+       "Translation fault (page)",
+       "Bus error (section)",
+       "Domain error (section)",
+       "Bus error (page)",
+       "Domain error (page)", 
+       "Bus error trans (L1)",
+       "Permission error (section)",
+       "Bus error trans (L2)",
+       "Permission error (page)"
+};
+
+/*
+ * void data_abort_handler(trapframe_t *frame)
+ *
+ * Abort handler called when read/write occurs at an address of
+ * a non existant or restricted (access permissions) memory page.
+ * We first need to identify the type of page fault.
+ */
+
+void
+data_abort_handler(frame)
+       trapframe_t *frame;
+{
+       struct proc *p;
+       struct pcb *pcb;
+       u_int fault_address;
+       u_int fault_status;
+       u_int fault_pc;
+       u_int fault_instruction;
+       u_int s;
+       int fault_code;
+       u_quad_t sticks;
+       int saved_lr;
+    
+/*
+ * OK you did not see this :-) This is worse than your worst nightmare
+ * This bug was found when implementing LDR/STR late abort fixes
+ * Don't know why I did not spot it before.
+ * I really need to rethink the trapframe structure ...
+ */
+
+       if ((frame->tf_spsr & PSR_MODE) == PSR_SVC32_MODE) {
+
+/* Ok an abort in SVC mode */
+
+/* CHEAT CHEAT CHEAT - SHUT YOUR EYES NOW ! */
+
+/* Copy the SVC r14 into the usr r14 - The usr r14 is garbage as the fault
+ * happened in svc mode but we need it in the usr slot so we can
+ * treat the registers as an array of ints during fixing.
+ * NOTE: This PC is in the position but writeback is not allowed on r15.
+ */
+               saved_lr = frame->tf_usr_lr;
+               frame->tf_usr_lr = frame->tf_svc_lr;
+        
+/* Note the trapframe does not have the SVC r13 so a fault from an
+ * instruction with writeback to r13 in SVC mode is not allowed.
+ * This should not happen as the kstack is always valid.
+ */
+       }
+     
+
+/*
+ * Enable IRQ's and FIQ's (disabled by CPU on abort) if trapframe shows
+ * they were enabled.
+ */
+
+#ifndef BLOCK_IRQS
+       if (!(frame->tf_spsr & I32_bit))
+               enable_interrupts(I32_bit);
+#endif
+
+/* Update vmmeter statistics */
+
+       cnt.v_trap++;
+
+/* Get fault address and status from the CPU */
+
+       fault_address = cpu_faultaddress();
+       fault_status = cpu_faultstatus();
+       fault_pc = frame->tf_pc;
+
+       fault_instruction = ReadWord(fault_pc);
+
+/* More debug stuff */
+
+       s = splhigh();
+       if (pmap_debug_level >= 0) {
+               printf("Data abort: '%s' status = %03x address = %08x PC = %08x\n",
+                   aborts[fault_status & 0xf], fault_status & 0xfff,
+                   fault_address, fault_pc);
+
+               printf("Instruction @V%08x = %08x\n",
+                   fault_pc, fault_instruction);
+       }
+
+/* Decode the fault instruction and fix the registers as needed */
+
+/* Was is a swap instruction ? */
+
+       if ((fault_instruction & 0x0fb00ff0) == 0x01000090) {
+               if (pmap_debug_level >= 0) {
+                       printf("SWP\n");
+                       disassemble(fault_pc);
+               }
+       } else if ((fault_instruction & 0x0c000000) == 0x04000000) {
+
+/* Was is a ldr/str instruction */
+
+#ifdef CPU_LATE_ABORT
+
+/* This is for late abort only */
+
+               int base;
+               int offset;
+               int *registers = &frame->tf_r0;
+#endif
+
+#ifdef DEBUG_FAULT_CORRECTION
+               if (pmap_debug_level >= 0) {
+/*                     printf("LDR/STR\n");*/
+                       disassemble(fault_pc);
+               }
+#endif
+               
+#ifdef CPU_LATE_ABORT
+
+/* This is for late abort only */
+
+       if ((fault_instruction & (1 << 24)) == 0
+           || (fault_instruction & (1 << 21)) != 0) {
+               base = (fault_instruction >> 16) & 0x0f;
+               if (base == 13 && (frame->tf_spsr & PSR_MODE) == PSR_SVC32_MODE) {
+                       disassemble(fault_pc);
+                       panic("Abort handler cannot fix this :-(\n");
+               }
+               if (base == 15) {
+                       disassemble(fault_pc);
+                       panic("Abort handler cannot fix this :-(\n");
+               }
+#ifdef DEBUG_FAULT_CORRECTION
+               if (pmap_debug_level >=0)
+                       printf("late abt fix: r%d=%08x ", base, registers[base]);
+#endif
+               if ((fault_instruction & (1 << 25)) == 0) {
+/* Immediate offset - easy */                  
+                       offset = fault_instruction & 0xfff;
+                       if ((fault_instruction & (1 << 23)))
+                               offset = -offset;
+                       registers[base] += offset;
+#ifdef DEBUG_FAULT_CORRECTION
+                       if (pmap_debug_level >=0)
+                               printf("imm=%08x ", offset);
+#endif
+               } else {
+                       int shift;
+
+                       offset = fault_instruction & 0x0f;
+                       if (offset == base) {
+                               disassemble(fault_pc);
+                               panic("Abort handler cannot fix this :-(\n");
+                       }
+                
+/* Register offset - hard we have to cope with shifts ! */
+                       offset = registers[offset];
+
+                       if ((fault_instruction & (1 << 4)) == 0)
+                               shift = (fault_instruction >> 7) & 0x1f;
+                       else {
+                               if ((fault_instruction & (1 << 7)) != 0) {
+                                       disassemble(fault_pc);
+                                       panic("Abort handler cannot fix this :-(\n");
+                               }
+                               shift = ((fault_instruction >> 8) & 0xf);
+                               if (base == shift) {
+                                       disassemble(fault_pc);
+                                       panic("Abort handler cannot fix this :-(\n");
+                               }
+#ifdef DEBUG_FAULT_CORRECTION
+                               if (pmap_debug_level >=0)
+                                       printf("shift reg=%d ", shift);
+#endif
+                               shift = registers[shift];
+                       }
+#ifdef DEBUG_FAULT_CORRECTION
+                       if (pmap_debug_level >=0)
+                               printf("shift=%08x ", shift);
+#endif
+                       switch (((fault_instruction >> 5) & 0x3)) {
+                       case 0 : /* Logical left */
+                               offset = (int)(((u_int)offset) << shift);
+                               break;
+                       case 1 : /* Logical Right */
+                               if (shift == 0) shift = 32;
+                               offset = (int)(((u_int)offset) >> shift);
+                               break;
+                       case 2 : /* Arithmetic Right */
+                               if (shift == 0) shift = 32;
+                               offset = (int)(((int)offset) >> shift);
+                               break;
+                       case 3 : /* Rotate right */
+                               disassemble(fault_pc);
+                               panic("Abort handler cannot fix this yet :-(\n");
+                               break;
+                       }
+
+#ifdef DEBUG_FAULT_CORRECTION
+                       if (pmap_debug_level >=0)
+                               printf("abt: fixed LDR/STR with register offset\n");
+#endif                  
+                       if ((fault_instruction & (1 << 23)))
+                               offset = -offset;
+#ifdef DEBUG_FAULT_CORRECTION
+                       if (pmap_debug_level >=0)
+                               printf("offset=%08x ", offset);
+#endif
+                       registers[base] += offset;
+               }
+#ifdef DEBUG_FAULT_CORRECTION
+               if (pmap_debug_level >=0)
+                       printf("r%d=%08x\n", base, registers[base]);
+#endif
+       }
+#endif
+       }
+       else if ((fault_instruction & 0x0e000000) == 0x08000000) {
+               int base;
+               int loop;
+               int count;
+               int *registers = &frame->tf_r0;
+        
+#ifdef DEBUG_FAULT_CORRECTION
+               if (pmap_debug_level >= 0) {
+                       printf("LDM/STM\n");
+                       disassemble(fault_pc);
+               }
+#endif
+               if (fault_instruction & (1 << 21)) {
+#ifdef DEBUG_FAULT_CORRECTION
+                       if (pmap_debug_level >= 0)
+                               printf("This instruction must be corrected\n");
+#endif
+                       base = (fault_instruction >> 16) & 0x0f;
+                       if (base == 15) {
+                               disassemble(fault_pc);
+                               panic("Abort handler cannot fix this :-(\n");
+                       }
+                       count = 0;
+                       for (loop = 0; loop < 16; ++loop) {
+                               if (fault_instruction & (1<<loop))
+                                       ++count;
+                       }
+#ifdef DEBUG_FAULT_CORRECTION
+                       if (pmap_debug_level >= 0) {
+                               printf("%d registers used\n", count);
+                               printf("Corrected r%d by %d bytes ", base, count * 4);
+                       }
+#endif
+                       if (fault_instruction & (1 << 23)) {
+#ifdef DEBUG_FAULT_CORRECTION
+                               if (pmap_debug_level >= 0)
+                                       printf("down\n");
+#endif
+                               registers[base] -= count * 4;
+                       } else {
+#ifdef DEBUG_FAULT_CORRECTION
+                               if (pmap_debug_level >= 0)
+                                       printf("up\n");
+#endif
+                               registers[base] += count * 4;
+                       }
+               }
+       } else if ((fault_instruction & 0x0e000000) == 0x0c000000) {
+               int base;
+               int offset;
+               int *registers = &frame->tf_r0;
+       
+/* REGISTER CORRECTION IS REQUIRED FOR THESE INSTRUCTIONS */
+
+#ifdef DEBUG_FAULT_CORRECTION
+               if (pmap_debug_level >= 0) {
+                       printf("LDC/STC\n");
+                       disassemble(fault_pc);
+               }
+#endif
+
+/* Only need to fix registers if write back is turned on */
+
+               if ((fault_instruction & (1 << 21)) != 0) {
+                       base = (fault_instruction >> 16) & 0x0f;
+                       if (base == 13 && (frame->tf_spsr & PSR_MODE) == PSR_SVC32_MODE) {
+                               disassemble(fault_pc);
+                               panic("Abort handler cannot fix this :-(\n");
+                       }
+                       if (base == 15) {
+                               disassemble(fault_pc);
+                               panic("Abort handler cannot fix this :-(\n");
+                       }
+
+                       offset = (fault_instruction & 0xff) << 2;
+                       if (pmap_debug_level >= 0)
+                               printf("r%d=%08x\n", base, registers[base]);
+                       if ((fault_instruction & (1 << 23)) != 0)
+                               offset = -offset;
+                       registers[base] += offset;
+                       if (pmap_debug_level >= 0)
+                               printf("r%d=%08x\n", base, registers[base]);
+               }
+       } else if ((fault_instruction & 0x0e000000) == 0x0c000000) {
+               disassemble(fault_pc);
+               panic("How did this happen ...\nWe have faulted on a non data transfer instruction");
+       }
+
+/*
+ * OK you did not see this :-) This is worse than your worst nightmare
+ * This bug was found when implementing LDR/STR late abort fixes
+ * Don't know why I did not spot it before.
+ * I really need to rethink the trapframe structure ...
+ */
+
+       if ((frame->tf_spsr & PSR_MODE) == PSR_SVC32_MODE) {
+
+/* Ok an abort in SVC mode */
+
+/* CHEAT CHEAT CHEAT - SHUT YOUR EYES NOW ! */
+
+/* Copy the SVC r14 into the usr r14 - The usr r14 is garbage as the fault
+ * happened in svc mode but we need it in the usr slot so we can
+ * treat the registers as an array of ints during fixing.
+ * NOTE: This PC is in the position but writeback is not allowed on r15.
+ */
+
+               frame->tf_svc_lr = frame->tf_usr_lr;
+               frame->tf_usr_lr = saved_lr;
+
+/* Note the trapframes does not have the SVC r13 so a fault from an
+ * instruction with writeback to r13 in SVC mode is not allowed.
+ * This should not happen as the kstack is always valid.
+ */
+       }
+
+       (void)splx(s);
+
+/* Extract the fault code from the fault status */
+
+       fault_code = fault_status & FAULT_TYPE_MASK;
+
+/* Get the current proc structure or proc0 if there is none */
+
+       if ((p = curproc) == 0)
+               p = &proc0;
+
+       if (pmap_debug_level >= 0)
+               printf("fault in process %08x\n", (u_int)p);
+
+/* can't use curpcb, as it might be NULL; and we have p in a register anyway */
+
+       pcb = &p->p_addr->u_pcb;
+       if (pcb == 0) {
+               vm_offset_t va;
+        
+               va = trunc_page((vm_offset_t)fault_address);
+               if (pmap_handled_emulation(kernel_pmap, va))
+                       return;
+               if (pmap_modified_emulation(kernel_pmap, va))
+                       return;
+               panic("no pcb ... we're toast !\n");
+       }
+
+       if (pcb != curpcb) {
+               printf("data_abort: Alert ! pcb(%08x) != curpcb(%08x)\n", (u_int)pcb,
+                   (u_int)curpcb);
+               printf("data_abort: Alert ! proc(%08x), curproc(%08x)\n", (u_int)p,
+                   (u_int)curproc);
+       }
+
+/* fusubail is used by [fs]uswintr to avoid page faulting */
+
+/*
+ * To get this correct I need to talk to the person coding the
+ * fubyte and subyte routines etc.
+ * There appear to be cases where a fault should be swallowed.
+ * The 386 does this by checking the error handler being used.
+ */
+/*
+ * Well it looks like I am doing this so I will talk to myself.
+ * Need to allow perm faults in case of modified bit emulation.
+ */
+
+       if (nopagefault != 0)
+               printf("fault occured with no_page_fault == %d\n", nopagefault);
+       if (pcb->pcb_onfault
+           && ((fault_code != FAULT_TRANS_S && fault_code != FAULT_TRANS_P)
+/*         || pcb->pcb_onfault == fusubailout*/)) {
+copyfault:
+               printf("Using pcb_onfault=%08x addr=%08x st=%08x\n",
+                   (u_int)pcb->pcb_onfault, fault_address, fault_status);
+               frame->tf_pc = (u_int)pcb->pcb_onfault;
+               if ((frame->tf_spsr & PSR_MODE) == PSR_USR32_MODE)
+                       printf("Yikes pcb_onfault=%08x during USR mode fault\n",
+                           (u_int)pcb->pcb_onfault);
+#ifdef VALIDATE_TRAPFRAME
+               validate_trapframe(frame, 1);
+#endif
+               ++onfault_count;
+               if (onfault_count > 10) {
+                       traceback();
+                       panic("Eaten by zombies\n");
+               }
+               return;
+       }
+
+/* Were we in user mode when the abort occurred ? */
+
+       if ((frame->tf_spsr & PSR_MODE) == PSR_USR32_MODE) {
+               sticks = p->p_sticks;
+        
+/* Modify the fault_code to reflect the USR/SVC state at time of fault */
+
+               fault_code |= FAULT_USER;
+               p->p_md.md_regs = frame;
+       }
+
+/* Now act of the fault type */
+
+       switch (fault_code) {
+       case FAULT_WRTBUF_0 | FAULT_USER: /* Write Buffer Fault */
+       case FAULT_WRTBUF_1 | FAULT_USER: /* Write Buffer Fault */
+       case FAULT_WRTBUF_0:              /* Write Buffer Fault */
+       case FAULT_WRTBUF_1:              /* Write Buffer Fault */
+/* If this happens forget it no point in continuing */
+
+               panic("Write Buffer Fault - Halting\n");
+               break;
+
+       case FAULT_ALIGN_0 | FAULT_USER: /* Alignment Fault */
+       case FAULT_ALIGN_1 | FAULT_USER: /* Alignment Fault */
+       case FAULT_ALIGN_0:              /* Alignment Fault */
+       case FAULT_ALIGN_1:              /* Alignment Fault */
+
+/*
+ * Really this should just kill the process. Alignment faults are turned
+ * off in the kernel in order to get better performance from shorts with
+ * GCC so an alignment fault means somebody has played with the control
+ * register in the CPU. Might as well panic as the kernel was not compiled
+ * for aligned accesses.
+ */
+               panic("Alignment fault - Halting\n");
+/*             trapsignal(p, SIGBUS, fault_status & FAULT_TYPE_MASK);*/
+               break;
+          
+       case FAULT_BUSERR_0 | FAULT_USER: /* Bus Error LF Section */
+       case FAULT_BUSERR_1 | FAULT_USER: /* Bus Error Page */
+       case FAULT_BUSERR_2 | FAULT_USER: /* Bus Error Section */
+       case FAULT_BUSERR_3 | FAULT_USER: /* Bus Error Page */
+       case FAULT_BUSERR_0:              /* Bus Error LF Section */
+       case FAULT_BUSERR_1:              /* Bus Error Page */
+       case FAULT_BUSERR_2:              /* Bus Error Section */
+       case FAULT_BUSERR_3:              /* Bus Error Page */
+
+/* What will accutally cause a bus error ? */
+/* Real bus errors are not a process problem but hardware */
+               panic("Bus Error - Halting\n");
+/*             trapsignal(p, SIGBUS, fault_status & FAULT_TYPE_MASK);*/
+               break;
+          
+       case FAULT_DOMAIN_S | FAULT_USER: /* Section Domain Error Fault */
+       case FAULT_DOMAIN_P | FAULT_USER: /* Page Domain Error Fault*/
+       case FAULT_DOMAIN_S:              /* Section Domain Error Fault */
+       case FAULT_DOMAIN_P:              /* Page Domain Error Fault*/
+
+/*
+ * Right well we dont use domains, everything is always a client and thus
+ * subject to access permissions.
+ * If we get a domain error then we have corrupts PTE's so we might
+ * as well die !
+ * I suppose eventually this should just kill the process who owns the
+ * PTE's but if this happens it implies a kernel problem.
+ */
+               panic("Domain Error - Halting\n");
+/*             trapsignal(p, SIGBUS, fault_status & FAULT_TYPE_MASK);*/
+               break;
+
+       case FAULT_PERM_P:               /* Page Permission Fault*/
+       case FAULT_PERM_P | FAULT_USER: /* Page Permission Fault*/
+/* Ok we have a permission fault in user or kernel mode */
+       {
+               register vm_offset_t va;
+               register struct vmspace *vm = p->p_vmspace;
+               register vm_map_t map;
+               int rv;
+               vm_prot_t ftype;
+
+/*
+ * Ok we have a permission fault in user mode. The only cause must be
+ * that a read only page has been written to. This may be genuine or it
+ * may be a bad access. In the future it may also be cause by the software
+ * emulation of the modified flag.
+ */
+               va = trunc_page((vm_offset_t)fault_address);
+
+               if (pmap_debug_level >= 0)
+                       printf("ok we have a page permission fault - addr=V%08x ",
+                           (u_int)va);
+
+/*
+ * It is only a kernel address space fault iff:
+ *     1. (fault_code & FAULT_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 ((fault_code & FAULT_USER) == 0
+                   && (va >= KERNEL_BASE || va <= VM_MIN_ADDRESS)) {
+ /* Was the fault due to the FPE ? */
+                       if ((frame->tf_spsr & PSR_MODE) == PSR_UND32_MODE) {
+                               printf("FPE Data abort: '%s' status = %03x address = %08x PC = %08x\n",
+                                   aborts[fault_status & 0xf], fault_status & 0xfff, fault_address,
+                                   fault_pc);
+                                   postmortem(frame);
+                               trapsignal(p, SIGBUS, FAULT_PERM_P);
+                               goto out;
+                       }
+
+                       printf("Data abort: '%s' status = %03x address = %08x PC = %08x\n",
+                           aborts[fault_status & 0xf], fault_status & 0xfff, fault_address,
+                           fault_pc);
+                       postmortem(frame);
+                       panic("permission fault in kernel by kernel\n");
+               } else
+                       map = &vm->vm_map;
+
+#ifdef DIAGNOSTIC
+               if (va == 0 && map == kernel_map) {
+                       printf("fault: bad kernel access at %x\n", (u_int)va);
+                       goto we_re_toast;
+               }
+#endif
+
+               if (pmap_debug_level >= 0)
+                       printf("vmmap=%08x ", (u_int)map);
+
+/*
+ * We need to know whether the page should be mapped as R or R/W.
+ * The MMU does not give us the info as to whether the fault was caused
+ * by a read or a write. This means we need to disassemble the instruction
+ * responcible and determine if it was a read or write instruction.
+ */
+
+               ftype = VM_PROT_READ;
+
+               if ((fault_instruction & 0x0c100000) == 0x04000000)
+                       ftype |= VM_PROT_WRITE; 
+               else if ((fault_instruction & 0x0a100000) == 0x08000000)
+                       ftype |= VM_PROT_WRITE; 
+               else if ((fault_instruction & 0x0fb00ff0) == 0x01000090)
+                       ftype |= VM_PROT_WRITE; 
+
+/*             if (!(ftype & VM_PROT_WRITE)) {
+                       panic("permission fault on a read !\n");
+               }*/
+
+               if (pmap_modified_emulation(map->pmap, va))
+                       goto out;
+               else {
+
+/* The page must be mapped to cause a permission fault. */
+
+                       rv = vm_fault(map, va, ftype, FALSE);
+                       if (pmap_debug_level >= 0)
+                               printf("fault result=%d\n", rv);
+                       if (rv == KERN_SUCCESS)
+                               goto out;
+                       printf("Data abort: '%s' status = %03x address = %08x PC = %08x\n",
+                           aborts[fault_status & 0xf], fault_status & 0xfff, fault_address,
+                           fault_pc);
+                       postmortem(frame);
+                       trapsignal(p, (rv == KERN_PROTECTION_FAILURE)
+                           ? SIGBUS : SIGSEGV, FAULT_PERM_P);
+                       break;
+               }
+       }            
+/*             panic("Page Permission Fault - Halting\n");*/
+               break;
+
+#if 0          
+        case FAULT_PERM_P: /* Page Permission Fault is non USR mode */
+
+/*
+ * Kernel permission faults should not happen. The kernel should never
+ * access memory it does not have permission for. Since the kernel has
+ * read access on all mapped pages it means the kernel has written to
+ * a read only kernel page. e.g. page 0
+ *
+ * Erg: Major cock up time. The kernel can take permission faults during
+ * the emulation of FP instructions. How comes I have not hit this problem ?
+ * ok out with the superglue ... This condition needs to be integrated with
+ * the FAULT_PERM_P | FAULT_USER case similarly to FAULT_TRANS_P
+ */
+
+               printf("Data abort: '%s' status = %03x address = %08x PC = %08x\n",
+                   aborts[fault_status & 0xf], fault_status & 0xfff, fault_address,
+                   fault_pc);
+               postmortem(frame);
+               panic("Page Permission Fault - (in SVC mode) Halting\n");
+               break;
+#endif
+
+       case FAULT_PERM_S | FAULT_USER: /* Section Permission Fault */
+/*
+ * Section permission fault should not happen yet.
+ * However I have had this panic once so it can occor
+ * Yes they do ... Writing to -1 in user space does it ...
+ */
+               printf("Data abort: '%s' status = %03x address = %08x PC = %08x\n",
+                   aborts[fault_status & 0xf], fault_status & 0xfff, fault_address,
+                   fault_pc);
+               disassemble(fault_pc);
+               postmortem(frame);
+               trapsignal(p, SIGBUS, FAULT_PERM_S);
+               break;
+
+/*             panic("Section Permission Fault - Halting\n");
+               trapsignal(p, SIGBUS, fault_status & FAULT_TYPE_MASK);
+               break;*/
+
+       case FAULT_BUSTRNL1 | FAULT_USER: /* Bus Error Trans L1 Fault */
+       case FAULT_BUSTRNL2 | FAULT_USER: /* Bus Error Trans L2 Fault */
+       case FAULT_BUSTRNL1:              /* Bus Error Trans L1 Fault */
+       case FAULT_BUSTRNL2:              /* Bus Error Trans L2 Fault */
+/*
+ * These faults imply that the PTE is corrupt. Likely to be a kernel
+ * fault so we had better stop.
+ */
+               panic("Bus Error Translation - Halting\n");
+               break;
+/*             trapsignal(p, SIGBUS, fault_status & FAULT_TYPE_MASK);
+               break;*/
+          
+       case FAULT_TRANS_P:              /* Page Translation Fault */
+       case FAULT_TRANS_P | FAULT_USER: /* Page Translation Fault */
+/* Ok page translation fault - The page does not exist */
+       {
+               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;
+               u_int nss;
+
+               va = trunc_page((vm_offset_t)fault_address);
+
+               if (pmap_debug_level >= 0)
+                       printf("ok we have a page fault - addr=V%08x ", (u_int)va);
+          
+/*
+ * It is only a kernel address space fault iff:
+ *     1. (fault_code & FAULT_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 (fault_code == FAULT_TRANS_P
+                   && (va >= KERNEL_BASE || va < VM_MIN_ADDRESS))
+                       map = kernel_map;
+               else
+                       map = &vm->vm_map;
+
+               if (pmap_debug_level >= 0)
+                       printf("vmmap=%08x ", (u_int)map);
+
+               if (pmap_handled_emulation(map->pmap, va))
+                       goto out;
+
+/*             debug_show_vm_map(map, "fault");*/
+
+/* We need to know whether the page should be mapped as R or R/W.
+ * The MMU does not give us the info as to whether the fault was caused
+ * by a read or a write. This means we need to disassemble the instruction
+ * responcible and determine if it was a read or write instruction.
+ * For the moment we will cheat and make it read only. If it was a write
+ * When the instruction is re-executed we will get a permission fault
+ * instead.
+ */
+               ftype = VM_PROT_READ;
+
+/* STR instruction ? */
+               if ((fault_instruction & 0x0c100000) == 0x04000000)
+                       ftype |= VM_PROT_WRITE; 
+/* STM instruction ? */
+               else if ((fault_instruction & 0x0a100000) == 0x08000000)
+                       ftype |= VM_PROT_WRITE; 
+/* SWP instruction ? */
+               else if ((fault_instruction & 0x0fb00ff0) == 0x01000090)
+                       ftype |= VM_PROT_WRITE; 
+
+               if (pmap_debug_level >= 0)
+                       printf("fault protection = %d\n", ftype);
+            
+#ifdef DIAGNOSTIC
+               if (va == 0 && map == kernel_map) {
+                       printf("trap: bad kernel access at %x\n", (u_int)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(USRSTACK-(u_int)va));
+                       if (nss > btoc(p->p_rlimit[RLIMIT_STACK].rlim_cur)) {
+                               rv = KERN_FAILURE;
+                               goto nogo;
+                       }
+               }
+
+/* check if page table is mapped, if not, fault it first */
+
+/*
+               if (*(((pt_entry_t **)(PROCESS_PAGE_TBLS_BASE + va >> (PD_SHIFT+2)))[]) == 0)
+                       panic("vm_fault: Page table is needed first\n")
+*/
+
+               rv = vm_fault(map, va, ftype, FALSE);
+/*printf("fault result=%d\n", rv);*/
+               if (rv == KERN_SUCCESS) {
+                       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 (map != kernel_map)
+                               vm_map_pageable(map, va, round_page(va+1), FALSE);
+                       if (fault_code == FAULT_TRANS_P)
+                               return;
+                       goto out;
+               }
+nogo:
+               if (fault_code == FAULT_TRANS_P) {
+                       printf("Failed page fault in kernel\n");
+                       if (pcb->pcb_onfault)
+                               goto copyfault;
+                       printf("vm_fault(%x, %x, %x, 0) -> %x\n",
+                           (u_int)map, (u_int)va, ftype, rv);
+                       goto we_re_toast;
+               }
+               printf("nogo, Data abort: '%s' status = %03x address = %08x PC = %08x\n",
+                   aborts[fault_status & 0xf], fault_status & 0xfff, fault_address,
+                   fault_pc);
+               disassemble(fault_pc);
+                               postmortem(frame);
+               trapsignal(p, (rv == KERN_PROTECTION_FAILURE)
+                   ? SIGBUS : SIGSEGV, FAULT_TRANS_P);
+               break;
+               }            
+/*             panic("Page Fault - Halting\n");*/
+               break;
+          
+       case FAULT_TRANS_S:              /* Section Translation Fault */
+       case FAULT_TRANS_S | FAULT_USER: /* Section Translation Fault */
+/* Section translation fault - the L1 page table does not exist */
+       {
+               register vm_offset_t va;
+               register struct vmspace *vm = p->p_vmspace;
+               register vm_map_t map;
+               int rv;
+               vm_prot_t ftype;
+               u_int nss, v;
+
+               va = trunc_page((vm_offset_t)fault_address);
+
+               if (pmap_debug_level >= 0)
+                       printf("ok we have a section fault page addr=V%08x\n",
+                           (u_int)va);
+          
+/*
+ * It is only a kernel address space fault iff:
+ *     1. (fault_code & FAULT_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 (fault_code == FAULT_TRANS_S && va >= KERNEL_BASE)
+                       map = kernel_map;
+               else
+                       map = &vm->vm_map;
+
+/*
+               debug_show_vm_map(map, "fault");
+               debug_show_vm_map(kernel_map, "kernel");
+*/
+
+/* We are mapping a page table so this must be kernel r/w */
+               ftype = VM_PROT_READ | VM_PROT_WRITE;
+#ifdef DIAGNOSTIC
+               if (map == kernel_map && va == 0) {
+                       printf("trap: bad kernel access at %x\n", (u_int)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) {
+/*                     printf("Address is in the stack\n");*/
+                       nss = clrnd(btoc(USRSTACK-(u_int)va));
+                       if (nss > btoc(p->p_rlimit[RLIMIT_STACK].rlim_cur)) {
+                               printf("Stack limit exceeded %08x %08x\n",
+                                   nss, btoc(p->p_rlimit[RLIMIT_STACK].rlim_cur));
+                               rv = KERN_FAILURE;
+                               goto nogo1;
+                       }
+               }
+
+/* check if page table is mapped, if not, fault it first */
+
+               v = trunc_page(vtopte(va));
+               if (pmap_debug_level >= 0)
+                       printf("v=%08x\n", v);
+               rv = vm_fault(map, v, ftype, FALSE);
+               if (rv != KERN_SUCCESS)
+                       goto nogo1;
+
+               if (pmap_debug_level >= 0)
+                       printf("vm_fault succeeded\n");
+
+/* update increment wiring as this is a page table fault */
+
+               vm_map_pageable(map, v, round_page(v+1), FALSE);
+
+               if (pmap_debug_level >= 0)
+                       printf("faulting in page %08x\n", (u_int)va);
+
+               ftype = VM_PROT_READ;
+
+               rv = vm_fault(map, va, ftype, FALSE);
+               if (rv == KERN_SUCCESS) {
+                       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 (fault_code == FAULT_TRANS_S)
+                               return;
+                       goto out;
+               }
+nogo1:
+               printf("nogo1, Data abort: '%s' status = %03x address = %08x PC = %08x\n",
+                   aborts[fault_status & 0xf], fault_status & 0xfff, fault_address,
+                   fault_pc);
+               disassemble(fault_pc);
+                       if (fault_code == FAULT_TRANS_S) {
+                       printf("Section fault in SVC mode\n");
+                       if (pcb->pcb_onfault)
+                               goto copyfault;
+                       printf("vm_fault(%x, %x, %x, 0) -> %x\n",
+                           (u_int)map, (u_int)va, ftype, rv);
+                       goto we_re_toast;
+               }
+               postmortem(frame);
+               trapsignal(p, (rv == KERN_PROTECTION_FAILURE)
+                   ? SIGBUS : SIGSEGV, FAULT_TRANS_S);
+               break;
+               }            
+/*             panic("Section Fault - Halting\n");
+               break;*/
+          
+       default :
+/* Are there any combinations I have missed ? */
+
+               printf("fault status = %08x fault code = %08x\n",
+                   fault_status, fault_code);
+
+we_re_toast:
+/* Were are dead, try and provide some debug infomation before dying */
+
+               postmortem(frame);
+
+               panic("Fault cannot be handled\n");
+               break;
+       }
+
+out:
+       if ((fault_code & FAULT_USER) == 0)
+               return;
+    
+#ifdef VALIDATE_TRAPFRAME
+       validate_trapframe(frame, 1);
+#endif
+       userret(p, frame->tf_pc, sticks);
+
+#ifdef VALIDATE_TRAPFRAME
+       validate_trapframe(frame, 1);
+#endif
+}
+
+
+/*
+ * void prefetch_abort_handler(trapframe_t *frame)
+ *
+ * Abort handler called when instruction execution occurs at
+ * a non existant or restricted (access permissions) memory page.
+ * If the address is invalid and we were in SVC mode then panic as
+ * the kernel should never prefetch abort.
+ * If the address is invalid and the page is mapped then the user process
+ * does no have read permission so send it a signal.
+ * Otherwise fault the page in and try again.
+ */
+
+void
+prefetch_abort_handler(frame)
+       trapframe_t *frame;
+{
+       register u_int fault_pc;
+       register struct proc *p;
+       register struct pcb *pcb;
+       u_int fault_instruction;
+       u_int s;
+       int fault_code;
+       u_quad_t sticks;
+
+/* Debug code */
+
+       if ((GetCPSR() & PSR_MODE) != PSR_SVC32_MODE) {
+               s = splhigh();
+               printf("fault being handled in non SVC32 mode\n");
+               postmortem(frame);
+               pmap_debug_level = 0;
+               (void)splx(s);
+               panic("Fault handler not in SVC mode\n");
+       }
+
+
+/*
+ * Enable IRQ's & FIQ's (disabled by the abort) This always comes
+ * from user mode so we know interrupts were not disabled.
+ * But we check anyway.
+ */
+
+#ifndef BLOCK_IRQS
+       if (!(frame->tf_spsr & I32_bit))
+               enable_interrupts(I32_bit);
+#endif
+
+/* Update vmmeter statistics */
+       cnt.v_trap++;
+
+/* Get the current proc structure or proc0 if there is none */
+
+       if ((p = curproc) == 0) {
+               p = &proc0;
+               printf("Prefetch about with curproc == 0\n");
+       }
+
+       if (pmap_debug_level >= 0)
+               printf("prefetch fault in process %08x\n", (u_int)p);
+
+/* can't use curpcb, as it might be NULL; and we have p in a register anyway */
+
+       pcb = &p->p_addr->u_pcb;
+       if (pcb == 0)
+               panic("no pcb ... we're toast !\n");
+
+       if (pcb != curpcb) {
+               printf("data_abort: Alert ! pcb(%08x) != curpcb(%08x)\n", (u_int)pcb,
+                   (u_int)curpcb);
+               printf("data_abort: Alert ! proc(%08x), curproc(%08x)\n", (u_int)p,
+                   (u_int)curproc);
+       }
+
+       if ((frame->tf_spsr & PSR_MODE) == PSR_USR32_MODE) {
+               sticks = p->p_sticks;
+        
+/* Modify the fault_code to reflect the USR/SVC state at time of fault */
+
+               fault_code |= FAULT_USER;
+               p->p_md.md_regs = frame;
+       } else {
+/* All the kernel code pages are loaded at boot and do not get paged */
+
+               s = splhigh();
+               printf("Prefetch address = %08x\n", frame->tf_pc);
+               postmortem(frame);
+
+#ifdef CONTINUE_AFTER_SVC_PREFETCH
+
+               printf("prefetch abort in SVC mode !\n");
+               printf("The system should now be considered very unstable :-)\n");
+               sigexit(curproc, SIGILL);
+/* Not reached */
+               (void)splx(s);
+#ifdef VALIDATE_TRAPFRAME
+               validate_trapframe(frame, 4);
+#endif
+               userret(p, frame->tf_pc, sticks);
+
+#ifdef VALIDATE_TRAPFRAME
+               validate_trapframe(frame, 4);
+#endif
+#else
+               panic("Prefetch abort in SVC mode\n");
+#endif
+       }
+
+/* Get fault address */
+
+       fault_pc = frame->tf_pc;
+
+       if (pmap_debug_level >= 0)
+               printf("Prefetch abort: PC = %08x\n", fault_pc);
+
+/* Ok validate the address, can only execute in USER space */
+
+       if (fault_pc < VM_MIN_ADDRESS || fault_pc >= VM_MAXUSER_ADDRESS) {
+               s = splhigh();
+               printf("prefetch: pc (%08x) not in user process space\n", fault_pc);
+               postmortem(frame);
+               trapsignal(p, SIGBUS, FAULT_PERM_P);
+               (void)splx(s);
+               userret(p, frame->tf_pc, sticks);
+               return;
+       }
+
+/* Ok read the fault address. This will fault the page in for us */
+
+       if (ReadWordWithChecks(fault_pc, &fault_instruction) != 0) {
+               s = splhigh();
+               printf("prefetch: faultin failed for address %08x!!\n", fault_pc);
+               postmortem(frame);
+               trapsignal(p, SIGSEGV, fault_pc);
+               (void)splx(s);
+       } else {
+
+/* More debug stuff */
+
+               if (pmap_debug_level >= 0) {
+                       s = splhigh();
+                       printf("Instruction @V%08x = %08x\n", fault_pc, fault_instruction);
+                       disassemble(fault_pc);
+                       printf("return addr=%08x\n", frame->tf_pc);
+
+                       (void)splx(s);
+               }
+       }
+
+#ifdef VALIDATE_TRAPFRAME
+       validate_trapframe(frame, 4);
+#endif
+
+       userret(p, frame->tf_pc, sticks);
+
+#ifdef VALIDATE_TRAPFRAME
+       validate_trapframe(frame, 2);
+#endif
+}
+
+
+void
+validate_trapframe(frame, where) 
+       trapframe_t *frame;
+       int where;
+{
+       char *ptr;
+       u_int mode;
+
+       if ((GetCPSR() & PSR_MODE) != PSR_SVC32_MODE)
+               printf("VTF Warning : validate_trapframe : Not in SVC32 mode\n");
+    
+       mode = frame->tf_spsr & PSR_MODE;
+        
+       switch (where) {
+       case 1:
+               ptr = "data abort handler";
+               break;
+       case 2:
+               ptr = "prefetch abort handler";
+               if (mode != PSR_USR32_MODE)
+                       printf("VTF Warning : %s : not USR32 mode\n", ptr);
+               break;
+       case 3:
+               ptr = "ast handler";
+               if (mode != PSR_USR32_MODE)
+                       printf("VTF Warning : %s : not USR32 mode\n", ptr);
+               break;
+       case 4:
+               ptr = "syscall handler";
+               if (mode != PSR_USR32_MODE)
+                       printf("VTF Warning : %s : not USR32 mode\n", ptr);
+               break;
+       case 5:
+               ptr = "undefined handler";
+               if (mode != PSR_USR32_MODE)
+                       printf("VTF Warning : %s : not USR32 mode\n", ptr);
+               break;
+       case 6:
+               ptr = "sigreturn handler";
+               if (mode != PSR_USR32_MODE)
+                       printf("VTF Warning : %s : not USR32 mode\n", ptr);
+               break;
+       default:
+               ptr = "unknown handler";
+               break;
+       }
+
+       if (frame->tf_usr_sp >= VM_MAXUSER_ADDRESS)
+               printf("VTF WARNING: %s : frame->tf_usr_sp >= VM_MAXUSER_ADDRESS [%08x]\n", ptr, frame->tf_usr_sp);
+       if (frame->tf_svc_lr >= 0xf1000000)
+               printf("VTF WARNING: %s : frame->tf_svc_lr >= 0xf1000000 [%08x]\n", ptr, frame->tf_svc_lr);
+       if (frame->tf_pc >= 0xf1000000)
+               printf("VTF WARNING: %s: frame->tf_pc >= 0xf1000000 [%08x]\n", ptr, frame->tf_pc);
+       if (frame->tf_pc < VM_MIN_ADDRESS)
+               printf("VTF WARNING: %s: frame->tf_pc >= VM_MIN_ADDRESS [%08x]\n", ptr, frame->tf_pc);
+       if (mode != PSR_USR32_MODE) {
+               if (frame->tf_svc_lr < 0xf0000000)
+                       printf("VTF WARNING: %s : frame->tf_svc_lr < 0xf0000000 [%08x]\n", ptr, frame->tf_svc_lr);
+               if (frame->tf_pc < 0xf0000000)
+                       printf("VTF WARNING: %s: frame->tf_pc < 0xf0000000 [%08x]\n", ptr, frame->tf_pc);
+       }
+}
+  
+/* End of fault.c */
diff --git a/sys/arch/arm32/arm32/fiq.S b/sys/arch/arm32/arm32/fiq.S
new file mode 100644 (file)
index 0000000..4495cc4
--- /dev/null
@@ -0,0 +1,78 @@
+/* $NetBSD: fiq.S,v 1.1 1996/01/31 23:15:55 mark Exp $ */
+
+/*
+ * Copyright (c) 1994 Mark Brinicombe.
+ * Copyright (c) 1994 Brini.
+ * All rights reserved.
+ *
+ * This code is derived from software written for Brini by Mark Brinicombe
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided 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 Brini.
+ * 4. The name of the company nor the name of the author may be used to
+ *    endorse or promote products derived from this software without specific
+ *    prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BRINI ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL BRINI 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.
+ *
+ * RiscBSD kernel project
+ *
+ * fiq.S
+ *
+ * Low level fiq handlers
+ *
+ * Created      : 27/09/94
+ * Last updated : 28/11/94
+ *
+ *    $Id: fiq.S,v 1.1.1.1 1996/04/24 11:08:26 deraadt Exp $
+ */
+
+#include <machine/cpu.h>
+
+sp     .req    r13
+lr     .req    r14
+pc     .req    r15
+
+.text
+
+       .global _floppy_read_fiq
+       .global _floppy_read_fiq_end
+
+_floppy_read_fiq:
+       subs    r11, r11, #0x00000001
+       addeq   r13, r13, #0x00018000
+       ldrb    r10, [r13]
+       strb    r10, [r12], #0x0001
+       subs    pc, lr, #0x00000004
+_floppy_read_fiq_end:
+
+       .global _floppy_write_fiq
+       .global _floppy_write_fiq_end
+
+_floppy_write_fiq:
+       subs    r11, r11, #0x00000001
+       addeq   r13, r13, #0x00018000
+       ldrb    r10, [r12], #0x0001
+       strb    r10, [r13]
+       subs    pc, lr, #0x00000004
+
+_floppy_write_fiq_end:
diff --git a/sys/arch/arm32/arm32/fusu.c b/sys/arch/arm32/arm32/fusu.c
new file mode 100644 (file)
index 0000000..824c6e3
--- /dev/null
@@ -0,0 +1,224 @@
+/* $NetBSD: fusu.c,v 1.2 1996/03/27 22:42:08 mark Exp $ */
+
+/*
+ * Copyright (C) 1993 Wolfgang Solfrank.
+ * Copyright (C) 1993 TooLs GmbH.
+ * 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 TooLs GmbH.
+ * 4. The name of TooLs GmbH may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * Emulate fubyte.
+ */
+
+int
+fubyte(addr)
+char *addr;
+{
+       unsigned char c;
+       
+       if (copyin(addr,&c,sizeof(c)))
+               return -1;
+       return c;
+}
+
+/*
+ * Emulate fuibyte.
+ * Note: This is the same as fubyte.
+ *      In case of separate I&D space this MUST be replaced.
+ */
+
+int
+fuibyte(addr)
+char *addr;
+{
+       unsigned char c;
+       
+       if (copyin(addr,&c,sizeof(c)))
+               return -1;
+       return c;
+}
+
+/*
+ * Emulate fuiword
+ * Note: This is the same as fuword.
+ *      In case of separate I&D space this MUST be replaced.
+ */
+
+int
+fuiword(addr)
+char *addr;
+{
+       unsigned long l;
+       
+       if (copyin(addr,&l,sizeof(l)))
+               return -1;
+       return l;
+}
+
+/*
+ * Emulate fuswintr
+ */
+
+int
+fuswintr(addr)
+char *addr;
+{
+       unsigned short s;
+       extern int nopagefault;
+       int ret;
+       
+       nopagefault++;
+       if (copyin(addr,&s,sizeof(s)))
+               ret = -1;
+       else
+               ret = s;
+       nopagefault--;
+       return ret;
+}
+
+/*
+ * Emulate fusword
+ */
+
+int
+fusword(addr)
+char *addr;
+{
+       unsigned short s;
+       
+       if (copyin(addr,&s,sizeof(s)))
+               return -1;
+       return s;
+}
+
+/*
+ * Emulate fuword
+ */
+
+int
+fuword(addr)
+char *addr;
+{
+       unsigned long l;
+       
+       if (copyin(addr,&l,sizeof(l)))
+               return -1;
+       return l;
+}
+
+/*
+ * Emulate subyte.
+ */
+
+int
+subyte(addr,c)
+char *addr;
+unsigned char c;
+{
+       if (copyout(&c,addr,sizeof(c)))
+               return -1;
+       return 0;
+}
+
+/*
+ * Emulate suibyte.
+ * Note: This is the same as subyte.
+ *      In case of separate I&D space this MUST be replaced.
+ */
+
+int
+suibyte(addr,c)
+char *addr;
+unsigned char c;
+{
+       if (copyout(&c,addr,sizeof(c)))
+               return -1;
+       return 0;
+}
+
+/*
+ * Emulate suiword
+ * Note: This is the same as suword.
+ *      In case of separate I&D space this MUST be replaced.
+ */
+
+int
+suiword(addr,l)
+char *addr;
+unsigned long l;
+{
+       if (copyout(&l,addr,sizeof(l)))
+               return -1;
+       return 0;
+}
+
+/*
+ * Emulate suswintr
+ */
+
+int
+suswintr(addr,s)
+char *addr;
+unsigned short s;
+{
+       extern int nopagefault;
+       int ret;
+       
+       nopagefault++;
+       ret = copyout(&s,addr,sizeof(s)) ? -1 : 0;
+       nopagefault--;
+       return ret;
+}
+
+/*
+ * Emulate susword
+ */
+
+int
+susword(addr,s)
+char *addr;
+unsigned short s;
+{
+       if (copyout(&s,addr,sizeof(s)))
+               return -1;
+       return 0;
+}
+
+/*
+ * Emulate suword
+ */
+
+int
+suword(addr,l)
+char *addr;
+unsigned long l;
+{
+       if (copyout(&l,addr,sizeof(l)))
+               return -1;
+       return 0;
+}
diff --git a/sys/arch/arm32/arm32/genassym.c b/sys/arch/arm32/arm32/genassym.c
new file mode 100644 (file)
index 0000000..9fe837d
--- /dev/null
@@ -0,0 +1,138 @@
+/* $NetBSD: genassym.c,v 1.4 1996/03/13 21:22:32 mark 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.
+ */
+
+#include <sys/param.h>
+#include <sys/proc.h>
+#include <sys/resourcevar.h>
+#include <sys/device.h>
+#include <sys/user.h>
+#include <sys/signal.h>
+
+#include <vm/vm.h>
+
+#include <machine/pmap.h>
+#include <machine/frame.h>
+#include <machine/vmparam.h>
+#include <machine/irqhandler.h>
+
+main()
+{
+       struct proc *p = 0;
+       struct vmmeter *vm = 0;
+       struct pcb *pcb = 0;
+       struct trapframe *tf = 0;
+       struct sigframe *sigf = 0;
+       struct uprof *uprof = 0;
+       irqhandler_t *ih = 0;
+       struct vconsole *vc = 0;
+       struct vidc_info *vi = 0;
+       struct vmspace *vms = 0;
+
+#define        def(N,V)        printf("#define\t%s %d\n", N, V)
+
+       def("UPAGES", UPAGES);
+       def("PGSHIFT", PGSHIFT);
+       def("PDSHIFT", PDSHIFT);
+
+       def("P_ADDR", &p->p_addr);
+       def("P_BACK", &p->p_back);
+       def("P_FORW", &p->p_forw);
+       def("P_PRIORITY", &p->p_priority);
+       def("P_STAT", &p->p_stat);
+       def("P_WCHAN", &p->p_wchan);
+       def("P_VMSPACE", &p->p_vmspace);
+       def("P_SPARE", &p->p_md.__spare);
+
+       def("PCB_PAGEDIR", &pcb->pcb_pagedir);
+       def("PCB_FLAGS", &pcb->pcb_flags);
+       def("PCB_R0", &pcb->pcb_r0);
+       def("PCB_R1", &pcb->pcb_r1);
+       def("PCB_R2", &pcb->pcb_r2);
+       def("PCB_R3", &pcb->pcb_r3);
+       def("PCB_R4", &pcb->pcb_r4);
+       def("PCB_R5", &pcb->pcb_r5);
+       def("PCB_R6", &pcb->pcb_r6);
+       def("PCB_R7", &pcb->pcb_r7);
+       def("PCB_R8", &pcb->pcb_r8);
+       def("PCB_R9", &pcb->pcb_r9);
+       def("PCB_R10", &pcb->pcb_r10);
+       def("PCB_R11", &pcb->pcb_r11);
+       def("PCB_R12", &pcb->pcb_r12);
+       def("PCB_SP", &pcb->pcb_sp);
+       def("PCB_LR", &pcb->pcb_lr);
+       def("PCB_PC", &pcb->pcb_pc);
+       def("PCB_UND_SP", &pcb->pcb_und_sp);
+       def("PCB_ONFAULT", &pcb->pcb_onfault);
+
+       def("USER_SIZE", sizeof(struct user));
+
+       def("V_TRAP", &vm->v_trap);
+       def("V_INTR", &vm->v_intr);
+       def("V_SOFT", &vm->v_soft);
+
+       def("VM_MAP", &vms->vm_map);
+       def("VM_PMAP", &vms->vm_pmap);
+
+       def("PR_BASE", &uprof->pr_base);
+       def("PR_SIZE", &uprof->pr_size);
+       def("PR_OFF", &uprof->pr_off);
+       def("PR_SCALE", &uprof->pr_scale);
+
+       def("IH_FUNC", &ih->ih_func);
+       def("IH_ARG", &ih->ih_arg);
+       def("IH_LEVEL", &ih->ih_level);
+       def("IH_NUM", &ih->ih_num);
+       def("IH_FLAGS", &ih->ih_flags);
+       def("IH_MASK", &ih->ih_irqmask);
+       def("IH_BIT", &ih->ih_irqbit);
+       def("IH_NEXT", &ih->ih_next);
+
+       def("SIGF_HANDLER", &sigf->sf_handler);
+       def("SIGF_SC", &sigf->sf_sc);
+
+       def("SIGTRAP", SIGTRAP);
+       def("SIGEMT", SIGEMT);
+
+       def("TF_R0", &tf->tf_r0);
+       def("TF_R10", &tf->tf_r10);
+       def("TF_PC", &tf->tf_pc);
+
+       def("PROCSIZE", sizeof(struct proc));
+       def("TRAPFRAMESIZE", sizeof(struct trapframe));
+       exit(0);
+}
diff --git a/sys/arch/arm32/arm32/irq.S b/sys/arch/arm32/arm32/irq.S
new file mode 100644 (file)
index 0000000..c1f9ed0
--- /dev/null
@@ -0,0 +1,508 @@
+/* $NetBSD: irq.S,v 1.4 1996/03/27 20:42:53 mark Exp $ */
+
+/*
+ * Copyright (c) 1994-1996 Mark Brinicombe.
+ * Copyright (c) 1994 Brini.
+ * All rights reserved.
+ *
+ * This code is derived from software written for Brini by Mark Brinicombe
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided 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 Brini.
+ * 4. The name of the company nor the name of the author may be used to
+ *    endorse or promote products derived from this software without specific
+ *    prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BRINI ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL BRINI 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.
+ *
+ * RiscBSD kernel project
+ *
+ * irq.S
+ *
+ * Low level irq and fiq handlers
+ *
+ * Created      : 27/09/94
+ */
+
+#include "assym.h"
+#include <machine/cpu.h>
+#include <machine/iomd.h>
+
+#define PUSHFRAME \
+       str     lr, [sp, #-4]!;         /* Push the return address */ \
+       sub     sp, sp, #0x00000004;    /* Skip SVC R14 */ \
+       stmdb   sp, {r0-r14}^;          /* Push the user mode registers */ \
+       sub     sp, sp, #(4*15);        /* Adjust the stack pointer */ \
+       mrs     r0, spsr_all;           /* Put the SPSR on the stack */ \
+       str     r0, [sp, #-4]!;
+
+#define PULLFRAME \
+        ldr     r0, [sp], #0x0004;      /* Get the SPSR from stack */ \
+        msr     spsr_all, r0; \
+       add     sp, sp, #(4*15);        /* Adjust the stack pointer */ \
+        ldmdb   sp, {r0-r14}^;         /* Restore the registers (user mode) */ \
+       mov     r0, r0;                 /* NOP for previous instruction */ \
+       add     sp, sp, #0x00000004;    /* Skip SVC R14 */ \
+       ldr     lr, [sp], #0x0004;      /* Pull the return address */
+
+#define PULLFRAMEANDEXIT \
+        ldr     r0, [sp], #0x0004;      /* Get the SPSR from stack */ \
+        msr     spsr_all, r0; \
+       add     sp, sp, #(4*15);        /* Adjust the stack pointer */ \
+        ldmdb   sp, {r0-r14}^;         /* Restore the registers (user mode) */ \
+       mov     r0, r0;                 /* NOP for previous instruction */ \
+       add     sp, sp, #0x00000004;    /* Skip SVC R14 */ \
+       ldmia   sp!, {pc}^              /* Pull the return address */
+
+sp     .req    r13
+lr     .req    r14
+pc     .req    r15
+
+.text
+
+/*
+ *
+ * irq_entry
+ *
+ * Main entry point for the IRQ vector
+ *
+ * This function reads the irq request bits in the IOMD registers
+ * IRQRQA, IRQRQB and DMARQ
+ * It then calls an installed handler for each bit that is set.
+ * The function stray_irqhandler is called if a handler is not defined
+ * for a particular interrupt.
+ * If a interrupt handler is found then it is called with r0 containing
+ * the argument defined in the handler structure. If the field ih_arg
+ * is zero then a pointer to the IRQ frame on the stack is passed instead.
+ */
+
+Ldisabled_mask:
+       .word   _disabled_mask
+
+Lcurrent_spl_level:    
+       .word   _current_spl_level
+
+       .global irq_entry
+
+/*
+ * Regsister usage
+ *
+ *  r6  - Address of current handler
+ *  r7  - Pointer to handler pointer list
+ *  r8  - Current IRQ requests.
+ *  r9  - Used to count through possible IRQ bits.
+ *  r10 - Base address of IOMD
+ */
+
+irq_entry:
+       sub     lr, lr, #0x00000004     /* Adjust the lr */
+
+       PUSHFRAME
+
+/* Raise the spl level and re-enable interrupts */
+
+#if 0
+       ldr     r1, Lcurrent_spl_level
+       ldr     r0, [r1]
+       add     r0, r0, #1
+       bl      _raisespl
+#endif
+#if 0
+        mrs     r0, cpsr_all           /* Enable IRQ's */
+       bic     r0, r0, #I32_bit
+       msr     cpsr_all, r0
+#endif
+
+/*
+ * If we did not raise the spl level high enough we will get another
+ * interrupt here.
+ */
+
+        mov     r11, #0x00000000
+       mov     r10, #(IOMD_BASE)       /* Point to the IOMD */
+       ldrb    r8, [r10, #(IOMD_IRQRQA - IOMD_BASE)]   /* Get IRQ request A */
+/*     strb    r8, [r10, #(IOMD_IRQRQA - IOMD_BASE)]*/
+       ldrb    r9, [r10, #(IOMD_IRQRQB - IOMD_BASE)]   /* Get IRQ request B */
+       orr     r8, r8, r9, lsl #8
+       ldrb    r9, [r10, #(IOMD_DMARQ - IOMD_BASE)]    /* Get DMA Request */
+       orr     r8, r8, r9, lsl #16
+
+/*#if 0*/
+       mov     r0, #0x7d               /* Clear IOMD IRQ bits */
+       strb    r0, [r10, #(IOMD_IRQRQA - IOMD_BASE)]
+/*#endif*/
+
+/*     ldr     r1, Ldisabled_mask
+       ldr     r0, [r1]
+       orr     r0, r0, r8
+       str     r0, [r1]
+
+       bl      _irq_setmasks*/
+
+#if 0
+        mrs     r0, cpsr_all           /* Enable IRQ's */
+       bic     r0, r0, #I32_bit
+       msr     cpsr_all, r0
+#endif
+       mov     r0, sp
+       mov     r1, r8
+       bl      _validate_irq_address
+
+       ldr     r7, [pc, #irqhandlers - . - 8]
+        mov    r9, #0x00000001
+
+       stmfd   sp!, {r8}
+
+irqloop:
+       tst     r8, r9                  /* Is a bit set ? */
+
+       beq     nextirq                 /* No ? try next bit */
+
+       ldr     r6, [r7]                /* Get address of first handler structure */
+
+       teq     r6, #0x00000000         /* Do we have a handler */
+       moveq   r0, r8                  /* IRQ requests as arg 0 */
+       beq     _stray_irqhandler       /* call special handler */
+
+        ldr    r0, Lcnt
+       ldr     r1, [r0, #(V_INTR)]
+       add     r1, r1, #0x00000001
+       str     r1, [r0, #(V_INTR)]
+
+irqchainloop:
+       add     lr, pc, #nextinchain - . - 8    /* return address */
+
+#ifdef IRQSTATS
+        ldr    r0, Lintrcnt
+       ldr     r1, [r6, #(IH_NUM)]
+
+       add     r0, r0, r1, lsl #2
+       ldr     r1, [r0]
+       add     r1, r1, #0x00000001
+       str     r1, [r0]
+#endif
+
+       ldr     r0, [r6, #(IH_ARG)]     /* Get argument pointer */
+       teq     r0, #0x00000000         /* If arg is zero pass stack frame */
+       addeq   r0, sp, #4                      /* ... stack frame */
+       ldr     pc, [r6, #(IH_FUNC)]    /* Call handler */
+
+nextinchain:
+/*     ldr     r1, Ldisabled_mask
+       ldr     r2, [r1]
+       bic     r2, r2, r9
+       str     r2, [r1]
+       bl      _irq_setmasks*/
+
+       teq     r0, #0x00000001         /* Was the irq serviced ? */
+       beq     nextirq
+
+       ldr     r6, [r6, #(IH_NEXT)]
+       teq     r6, #0x00000000
+/*     bne     irqchainloop*/
+
+nextirq:
+       add     r7, r7, #0x00000004     /* update pointer to handlers */
+       mov     r9, r9, lsl #1          /* move on to next bit */
+       teq     r9, #(1 << 24)          /* done the last bit ? */
+       bne     irqloop                 /* no - loop back. */
+
+       ldmfd   sp!, {r8}
+
+
+#if 0
+        mrs     r0, cpsr_all           /* Enable IRQ's */
+       orr     r0, r0, #I32_bit
+       msr     cpsr_all, r0
+#endif
+
+       bl      _dosoftints             /* Handle the soft interrupts */
+
+/* Disable interrupts and lower the spl level */
+
+#if 0
+        mrs     r0, cpsr_all           /* Enable IRQ's */
+       orr     r0, r0, #I32_bit
+       msr     cpsr_all, r0
+#endif
+#if 0
+       ldr     r1, Lcurrent_spl_level
+       ldr     r0, [r1]
+       sub     r0, r0, #1
+       bl      _lowerspl
+#endif
+
+       ldr     r0, [sp]                /* Get the SPSR from stack */
+
+       and     r0, r0, #(PSR_MODE)     /* Test for USR32 mode before the IRQ */
+       teq     r0, #(PSR_USR32_MODE)
+       ldreq   r0, Lastpending         /* Do we have an AST pending ? */
+       ldreq   r1, [r0]
+       teqeq   r1, #0x00000001
+       moveq   r1, #0x00000000         /* Clear it */
+       streq   r1, [r0]
+
+       moveq   r0, sp                  /* arg 0 = irq frame */
+       beq     _irqast                 /* exit via the AST handler */
+
+       PULLFRAME
+
+       movs    pc, lr                  /* Exit */
+
+
+       .global _irqast
+_irqast:
+/* Punch into SVC32 mode (R0 points to the irqframe) */
+/* We can trash all the registers we like :-) */
+
+/* Debug message */
+
+/*     stmfd   sp!, {r0-r3}
+       add     r0, pc, #Lirqtext0 - . - 8
+       bl      _printf
+       ldmfd   sp!, {r0-r3}*/
+
+        mrs     r2, cpsr_all
+       tst     r2, #(I32_bit)
+       bne     Lis
+
+        orr     r2, r2, #(I32_bit)
+        msr     cpsr_all, r2
+
+       stmfd   sp!, {r0-r3, lr}
+       add     r0, pc, #Lirqtext0 - . - 8
+       bl      _printf
+       ldmfd   sp!, {r0-r3, lr}
+Lis:
+       add     sp, sp, #72     /* Correct IRQ32 sp */
+
+/*
+ * We have now put IRQ mode back correct so we never need to return to
+ * IRQ mode we can just exit via SVC mode. We must copy the trap frame
+ * which still lies on the IRQ stack over to the SVC stack.
+ */
+
+/* Punch into SVC 32 mode (IRQ's still disabled) */
+
+       mrs     r2, cpsr_all
+       bic     r2, r2, #(PSR_MODE)
+       eor     r2, r2, #(PSR_SVC32_MODE)
+       orr     r2, r2, #(I32_bit)      /* Overkill */
+       msr     cpsr_all, r2
+
+       sub     sp, sp, #72     /* Correct SVC32 sp */
+       mov     r12, sp
+
+/* r0  points to the trap frame on the IRQ stack (SP corrected) */
+/* r12 points to the trap frame on the SVC stack */
+
+       ldmia   r0!, {r1-r9}    /* Pull 9 regs off the IRQ stack */
+       stmia   r12!, {r1-r9}   /* Store on the SVC stack */
+       ldmia   r0!, {r1-r9}    /* Pull 9 regs off the IRQ stack */
+       stmia   r12!, {r1-r9}   /* Store on the SVC stack */
+
+/* Ok the IRQ trapframe is now the SVC trapframe */
+
+/* IRQ's could be enabled here */
+
+/* Debug message */
+
+/*     stmfd   sp!, {r0-r3}
+       add     r0, pc, #Lirqtext1 - . - 8
+       bl      _printf
+       ldmfd   sp!, {r0-r3}
+*/
+/* r0 points to trap frame on entry to ast() */
+
+       mov     r0, sp
+       stmfd   sp!, {lr}       /* Is this needed ? */
+
+       bl      _ast
+
+       ldmfd   sp!, {lr}       /* Is this needed ? */
+
+/* Remember the address of the trap frame */
+
+/*     stmfd   sp!, {r0-r3}
+       add     r0, pc, #Lirqtext2 - . - 8
+       bl      _printf
+       ldmfd   sp!, {r0-r3}
+*/
+
+/* Pull the frame from the SVC stack and return */
+
+/*     mov     lr, #0*/
+
+/* Kill IRQ's incase ast as somehow re-enabled them ... */
+
+        mrs     r0, cpsr_all
+        orr     r0, r0, #(I32_bit)
+        msr     cpsr_all, r0
+
+       PULLFRAMEANDEXIT
+
+       mov     r4, #0x000000A0
+       mov     pc, #0x00000000
+
+Lirqtext0:
+       .asciz  "irqs enabled during ast\n"
+       .align  0
+
+Lirqtext1:
+       .asciz  "irqframe copied to SVC stack\n"
+       .align  0
+
+Lirqtext2:
+       .asciz  "irqframe restored from SVC stack\n"
+       .align  0
+
+Lspl_mask:
+       .word   _spl_mask
+
+Lcurrent_mask:
+       .word   _current_mask
+
+       .global _irq_setmasks
+
+_irq_setmasks:
+       ldr     r1, Lcurrent_mask
+       ldr     r1, [r1]
+       ldr     r2, Lspl_mask
+       ldr     r2, [r2]
+       and     r1, r1, r2
+       ldr     r2, Ldisabled_mask
+       ldr     r2, [r2]
+       bic     r1, r1, r2
+
+       mov     r0, #(IOMD_BASE)        /* Point to the IOMD */
+       strb    r1, [r0, #(IOMD_IRQMSKA - IOMD_BASE)]   /* Set IRQ mask A */
+       mov     r1, r1, lsr #8
+       strb    r1, [r0, #(IOMD_IRQMSKB - IOMD_BASE)]   /* Set IRQ mask B */
+       mov     r1, r1, lsr #8
+       strb    r1, [r0, #(IOMD_DMAMSK - IOMD_BASE)]    /* Set DMA mask */
+       mov     pc, r14
+
+
+Lcnt:
+       .word   _cnt
+
+Lintrcnt:
+       .word   _intrcnt
+
+
+irqhandlers:
+       .word   _irqhandlers            /* Pointer to array of irqhandlers */
+
+Lastpending:
+       .word   _astpending
+
+#ifdef IRQSTATS
+/* These symbols are used by vmstat */
+
+       .text
+       .global __intrnames
+__intrnames:
+       .word   _intrnames
+
+       .data
+
+        .globl  _intrnames, _eintrnames, _intrcnt, _eintrcnt
+_intrnames:
+       .asciz  "interrupt  0 "
+       .asciz  "softnet      " /* reserved0 */
+       .asciz  "interrupt  2 "
+       .asciz  "interrupt  3 "
+       .asciz  "interrupt  4 "
+       .asciz  "interrupt  5 "
+       .asciz  "interrupt  6 "
+       .asciz  "softclock    " /* reserved1 */
+       .asciz  "reserved 2   "
+       .asciz  "interrupt  9 "
+       .asciz  "interrupt 10 "
+       .asciz  "interrupt 11 "
+       .asciz  "interrupt 12 "
+       .asciz  "interrupt 13 "
+       .asciz  "interrupt 14 "
+       .asciz  "interrupt 15 "
+       .asciz  "dma channel 0"
+       .asciz  "dma channel 1"
+       .asciz  "dma channel 2"
+       .asciz  "dma channel 3"
+       .asciz  "interrupt 20 "
+       .asciz  "interrupt 21 "
+       .asciz  "reserved 3   "
+       .asciz  "reserved 4   "
+       .asciz  "exp card 0   "
+       .asciz  "exp card 1   "
+       .asciz  "exp card 2   "
+       .asciz  "exp card 3   "
+       .asciz  "exp card 4   "
+       .asciz  "exp card 5   "
+       .asciz  "exp card 6   "
+       .asciz  "exp card 7   "
+_eintrnames:
+
+       .bss
+       .align  0
+_intrcnt:
+       .space  32*4
+_eintrcnt:
+
+#else
+/* Dummy entries to keep vmstat happy */
+
+       .text
+        .globl  _intrnames, _eintrnames, _intrcnt, _eintrcnt
+_intrnames:
+       .long   0
+_eintrnames:
+
+_intrcnt:
+       .long   0
+_eintrcnt:
+#endif
+
+/* FIQ code */
+
+       .text
+       .align  0
+       .global _fiq_setregs            /* Sets up the FIQ handler */
+
+_fiq_setregs:
+        mrs    r2, cpsr_all
+       mov     r3, r2
+       bic     r2, r2, #(PSR_MODE)
+       orr     r2, r2, #(PSR_FIQ32_MODE)
+        msr    cpsr_all, r2
+
+       ldr     r8,  [r0, #0x000c]      /* Update FIQ registers*/
+       ldr     r9,  [r0, #0x0010]
+       ldr     r10, [r0, #0x0014]
+       ldr     r11, [r0, #0x0018]
+       ldr     r12, [r0, #0x001c]
+       ldr     r13, [r0, #0x0020]
+
+        msr    cpsr_all, r3            /* Back to old mode */
+
+       mov     pc, lr                  /* Exit */
+
+/* End of irq.S */
diff --git a/sys/arch/arm32/arm32/irqhandler.c b/sys/arch/arm32/arm32/irqhandler.c
new file mode 100644 (file)
index 0000000..fe3a764
--- /dev/null
@@ -0,0 +1,573 @@
+/* $NetBSD: irqhandler.c,v 1.4 1996/03/28 21:43:52 mark Exp $ */
+
+/*
+ * Copyright (c) 1994-1996 Mark Brinicombe.
+ * Copyright (c) 1994 Brini.
+ * All rights reserved.
+ *
+ * This code is derived from software written for Brini by Mark Brinicombe
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided 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 Brini.
+ * 4. The name of the company nor the name of the author may be used to
+ *    endorse or promote products derived from this software without specific
+ *    prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BRINI ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL BRINI 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.
+ *
+ * RiscBSD kernel project
+ *
+ * irqhandler.c
+ *
+ * IRQ/FIQ initialisation, claim, release and handler routines
+ *
+ * NOTE: Although the irqhandlers support chaining and the claim
+ * and release routines install handlers at the top of the chain
+ * The low level IRQ handler will only call the top handler in a
+ * chain.
+ *
+ * Created      : 30/09/94
+ */
+
+/* Note: Need to remove IRQ_FLAG_ACTIVE as it is not used */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <vm/vm.h>
+#include <sys/syslog.h>
+
+#include <machine/irqhandler.h>
+#include <machine/cpu.h>
+#include <machine/iomd.h>
+#include <machine/katelib.h>
+#include <machine/pte.h>
+
+irqhandler_t *irqhandlers[NIRQS];
+fiqhandler_t *fiqhandlers;
+
+u_int irqmasks[IRQ_LEVELS];
+u_int current_mask;
+u_int actual_mask;
+u_int disabled_mask;
+u_int spl_mask;
+u_int soft_interrupts;
+extern u_int intrcnt[];
+
+typedef struct {
+    vm_offset_t physical;
+    vm_offset_t virtual;
+} pv_addr_t;
+             
+extern pv_addr_t systempage;
+
+/* Prototypes */
+
+int podule_irqhandler __P((void));
+int irq_claim __P((int /*irq*/, irqhandler_t */*handler*/));
+void zero_page_readonly __P((void));
+void zero_page_readwrite __P((void));
+
+int fiq_setregs __P((fiqhandler_t *));
+
+/*
+ * void irq_init(void)
+ *
+ * Initialise the IRQ/FIQ sub system
+ */
+
+void
+irq_init()
+{
+       int loop;
+
+/* Clear all the IRQ handlers */
+
+       for (loop = 0; loop < NIRQS; ++loop)
+               irqhandlers[loop] = NULL;
+
+/* Clear the FIQ handler */
+
+       fiqhandlers = NULL;
+
+/* Clear the IRQ/FIQ masks in the IOMD */
+
+       WriteByte(IOMD_IRQMSKA, 0x00);
+       WriteByte(IOMD_IRQMSKB, 0x00);
+       WriteByte(IOMD_FIQMSK, 0x00);
+       WriteByte(IOMD_DMAMSK, 0x00);
+
+/*
+ * Setup the irqmasks for the different Interrupt Priority Levels
+ * We will start with no bits set and these will be updated as handlers
+ * are installed at different IPL's.
+ */
+
+       irqmasks[IPL_BIO]   = 0x00000000;
+       irqmasks[IPL_NET]   = 0x00000000;
+       irqmasks[IPL_TTY]   = 0x00000000;
+       irqmasks[IPL_CLOCK] = 0x00000000;
+       irqmasks[IPL_IMP]   = 0x00000000;
+
+       current_mask = 0x00000000;
+       actual_mask = 0x00000000;
+       spl_mask = 0x00000000;
+       soft_interrupts = 0x00000000;
+
+       set_spl_masks();
+
+/* Enable IRQ's and FIQ's */
+
+       enable_interrupts(I32_bit | F32_bit); 
+}
+
+
+/*
+ * int irq_claim(int irq, irqhandler_t *handler)
+ *
+ * Enable an IRQ and install a handler for it.
+ */
+
+int
+irq_claim(irq, handler)
+       int irq;
+       irqhandler_t *handler;
+{
+       int level;
+
+/* IRQ_INSTRUCT indicates that we should get the irq number from the irq structure */
+
+       if (irq == IRQ_INSTRUCT)
+               irq = handler->ih_num;
+    
+/* Make sure the irq number is valid */
+
+       if (irq < 0 || irq >= NIRQS)
+               return(-1);
+
+/* Install the handler at the top of the chain */
+
+       handler->ih_next = irqhandlers[irq];
+       irqhandlers[irq] = handler;
+
+/*     if (irq == IRQ_VSYNC)
+         {
+           irqhandler_t *x;
+           x = irqhandlers[irq];
+           while (x) {
+               printf("handler = %08x %08x\n", x, handler);
+               x = x->ih_next;
+           }
+         }*/
+
+/*
+ * Reset the flags for this handler. As it is at the top of the list it
+ * must be the active handler.
+ */
+/* amb - no needed these days */ 
+       handler->ih_flags = 0 | IRQ_FLAG_ACTIVE;
+
+/*
+ * Record the interrupt number for accounting.
+ * Done here as the accounting number may not be the same as the IRQ number
+ * though for the moment they are
+ */
+       handler->ih_num = irq;
+
+/* If this is the first interrupt to be attached make a not of any name */
+
+#ifdef IRQSTATS
+       if (handler->ih_next == NULL && handler->ih_name) {
+               extern char *_intrnames;
+               char *ptr = _intrnames + (irq * 14);
+/*             printf("intrnames=%08x ptr=%08x irq=%d\n", (u_int)_intrnames, (u_int)ptr, irq);*/
+               strcpy(ptr, "             ");
+               strncpy(ptr, handler->ih_name, min(strlen(handler->ih_name), 13));
+       }
+#endif
+
+/*
+ * Update the irq masks.
+ * This IRQ is allowable at all lower Interrupt Priority Levels.
+ */
+       if (handler->ih_level >= 0 && handler->ih_level < IRQ_LEVELS) {
+               level = handler->ih_level - 1;
+               while (level >= 0) {
+                       irqmasks[level] |= (1 << irq);
+                       --level;
+               }
+
+#include "sl.h"
+#include "ppp.h"
+#if NSL > 0 || NPPP > 0
+/* In the presence of SLIP or PPP, splimp > spltty. */
+               irqmasks[IPL_NET] &= irqmasks[IPL_TTY];
+#endif
+       }
+                 
+/*
+       for (level = 0; level < IRQ_LEVELS; ++level)
+               printf("irqmask[%d] = %08x\n", level, irqmasks[level]);
+*/
+
+/*
+ * Is this an expansion card IRQ and is there a PODULE IRQ handler
+ * installed ?
+ * If not panic as the podulebus irq handler should have been installed
+ * when the podulebus was attached.
+ */
+
+       if (irq >= IRQ_EXPCARD0 && irqhandlers[IRQ_PODULE] == NULL)
+               panic("Podule IRQ %d claimed but no podulebus handler installed\n",
+                   irq);
+
+       enable_irq(irq);
+       set_spl_masks();
+    
+       return(0);
+}
+
+
+/*
+ * int irq_release(int irq, irqhandler_t *handler)
+ *
+ * Disable an IRQ and remove a handler for it.
+ */
+
+int
+irq_release(irq, handler)
+       int irq;
+       irqhandler_t *handler;
+{
+       int level;
+
+       irqhandler_t *irqhand;
+       irqhandler_t **prehand;
+
+/* IRQ_INSTRUCT indicates that we should get the irq number from the irq structure */
+
+       if (irq == IRQ_INSTRUCT)
+               irq = handler->ih_num;
+
+/* Make sure the irq number is valid */
+
+       if (irq < 0 || irq >= NIRQS)
+               return(-1);
+
+/*
+ * Update the irq masks.
+ * Remove the IRQ from all the approriate IPL's
+ */
+  
+       if (handler->ih_level >= 0 && handler->ih_level < IRQ_LEVELS) {
+               level = handler->ih_level - 1;
+               while (level >= 0) {
+                       irqmasks[level] &= ~(1 << irq);
+                       --level;
+               }
+       }
+
+/* Locate the handler */
+
+       irqhand = irqhandlers[irq];
+       prehand = &irqhandlers[irq];
+    
+       while (irqhand && handler != irqhand) {
+               prehand = &irqhand;
+               irqhand = irqhand->ih_next;
+       }
+
+/* Remove the handler if located */
+      
+       if (irqhand)
+               *prehand = irqhand->ih_next;
+       else
+               return(-1);
+
+/* Flag the handler being removed as non active (in case it was) */ 
+/* Not needed these days - AMB */
+       irqhand->ih_flags &= ~IRQ_FLAG_ACTIVE;
+
+/* Make sure the head of the handler list is active */
+
+       if (irqhandlers[irq])
+               irqhandlers[irq]->ih_flags |= IRQ_FLAG_ACTIVE;
+
+/*
+ * Disable the appropriate mask bit if there are no handlers left for
+ * this IRQ.
+ */
+
+       if (irqhandlers[irq] == NULL)
+               disable_irq(irq);
+
+       set_spl_masks();
+      
+       return(0);
+}
+
+
+u_int
+disable_interrupts(mask)
+       u_int mask;
+{
+       register u_int cpsr;
+
+       cpsr = SetCPSR(mask, mask);
+       if ((GetCPSR() & I32_bit) == 0)
+               printf("Alert ! disable_interrupts has failed\n");
+
+       return(cpsr);
+}
+
+
+u_int
+restore_interrupts(old_cpsr)
+       u_int old_cpsr;
+{
+       register int mask = I32_bit | F32_bit;
+       return(SetCPSR(mask, old_cpsr & mask));
+}
+
+
+u_int
+enable_interrupts(mask)
+       u_int mask;
+{
+       return(SetCPSR(mask, 0));
+}
+
+
+/*
+ * void disable_irq(int irq)
+ *
+ * Disables a specific irq. The irq is removed from the master irq mask
+ */
+
+void
+disable_irq(irq)
+       int irq;
+{
+       register int oldirqstate; 
+
+       oldirqstate = disable_interrupts(I32_bit);
+       current_mask &= ~(1 << irq);
+       irq_setmasks();
+       restore_interrupts(oldirqstate);
+}  
+
+
+/*
+ * void enable_irq(int irq)
+ *
+ * Enables a specific irq. The irq is added to the master irq mask
+ * This routine should be used with caution. A handler should already
+ * be installed.
+ */
+
+void
+enable_irq(irq)
+       int irq;
+{
+       register u_int oldirqstate; 
+
+       oldirqstate = disable_interrupts(I32_bit);
+       current_mask |= (1 << irq);
+       irq_setmasks();
+       restore_interrupts(oldirqstate);
+}  
+
+
+/*
+ * void stray_irqhandler(u_int mask)
+ *
+ * Handler for stray interrupts. This gets called if a handler cannot be
+ * found for an interrupt.
+ */
+
+void
+stray_irqhandler(mask)
+       u_int mask;
+{
+/*     panic("Stray IRQ received (%08x)\n", mask);*/
+       static u_int stray_irqs = 0;
+
+       if (++stray_irqs <= 8)
+               log(LOG_ERR, "Stray interrupt %08x%s\n", mask,
+                   stray_irqs >= 8 ? ": stopped logging" : "");
+}
+
+
+void
+dosoftints()
+{
+       register u_int softints;
+    
+       softints = soft_interrupts & spl_mask;
+       if (softints & IRQMASK_SOFTCLOCK) {
+               int s;
+               
+               ++cnt.v_soft;
+               ++intrcnt[IRQ_SOFTCLOCK];
+               soft_interrupts &= ~IRQMASK_SOFTCLOCK;
+               s = lowerspl(SPL_SOFT);
+               softclock();
+               (void)splx(s);
+       }
+       if (softints & IRQMASK_SOFTNET) {
+               ++cnt.v_soft;
+               ++intrcnt[IRQ_SOFTNET];
+               soft_interrupts &= ~IRQMASK_SOFTNET;
+#ifdef INET
+#include "ether.h"
+#if NETHER > 0
+               arpintr();
+#endif
+               ipintr();
+#endif
+#ifdef IMP
+               impintr();
+#endif
+#ifdef NS
+               nsintr();
+#endif
+#ifdef ISO
+               clnlintr();
+#endif
+#ifdef CCITT
+               ccittintr();
+#endif                                                         
+#include "ppp.h"
+#if NPPP > 0
+               pppintr();
+#endif
+       }
+}
+
+extern vgone();
+extern vfinddev();
+extern idle();
+extern cpu_switch();
+extern switch_exit();
+
+void
+validate_irq_address(irqf, mask)
+       irqframe_t *irqf;
+       u_int mask;
+{
+       return;
+       if (irqf->if_pc > (int)idle && irqf->if_pc < (int)switch_exit)
+               return;
+       if (irqf->if_pc > (int)SetCPSR && irqf->if_pc < (int)GetCPSR)
+               return;
+       if ((irqf->if_spsr & PSR_MODE) != PSR_USR32_MODE) {
+               printf("Alert! IRQ while in non USR mode (%08x) pc=%08x\n",
+                   irqf->if_spsr, irqf->if_pc);
+       }
+       if ((GetCPSR() & I32_bit) == 0) {
+               printf("Alert! IRQ's enabled during IRQ handler\n");
+       }
+       if (irqf->if_pc >= (int)vgone && irqf->if_pc < (int)vfinddev)
+               printf("Alert! IRQ between vgone & vfinddev : pc=%08x\n",
+                   irqf->if_pc);
+}
+
+
+/*
+ * int fiq_claim(fiqhandler_t *handler)
+ *
+ * Claim FIQ's and install a handler for them.
+ */
+
+int
+fiq_claim(handler)
+       fiqhandler_t *handler;
+{
+/* Fail if the FIQ's are already claimed */
+
+       if (fiqhandlers)
+               return(-1);
+
+       if (handler->fh_size > 0xc0)
+               return(-1);
+
+/* Install the handler */
+
+       fiqhandlers = handler;
+
+/* Now we have to actually install the FIQ handler */
+
+/* Eventually we will copy this down but for the moment ... */
+
+       zero_page_readwrite();
+
+       WriteWord(0x0000003c, (u_int) handler->fh_func);
+    
+       zero_page_readonly();
+    
+/*     bcopy(handler->fh_func, 0x0000001c, handler->fh_size);*/
+
+/* We must now set up the FIQ registers */
+
+       fiq_setregs(handler);
+
+/* Set up the FIQ mask */
+
+       WriteWord(IOMD_FIQMSK, handler->fh_mask);
+    
+/* Make sure that the FIQ's are enabled */
+    
+       enable_interrupts(F32_bit);
+       return(0);
+}
+
+
+/*
+ * int fiq_release(fiqhandler_t *handler)
+ *
+ * Release FIQ's and remove a handler for them.
+ */
+
+int
+fiq_release(handler)
+       fiqhandler_t *handler;
+{
+/* Fail if the handler is wrong */
+
+       if (fiqhandlers != handler)
+               return(-1);
+
+/* Disable FIQ interrupts */
+      
+       disable_interrupts(F32_bit);
+
+/* Clear up the FIQ mask */
+
+       WriteWord(IOMD_FIQMSK, 0x00);
+
+/* Remove the handler */
+
+       fiqhandlers = NULL;
+       return(0);
+}
+
+/* End of irqhandler.c */
diff --git a/sys/arch/arm32/arm32/kgdb_glue.c b/sys/arch/arm32/arm32/kgdb_glue.c
new file mode 100644 (file)
index 0000000..f8ed9b6
--- /dev/null
@@ -0,0 +1,258 @@
+/*     $NetBSD: kgdb_glue.c,v 1.2 1996/03/27 22:42:16 mark Exp $       */
+
+/*
+ * Copyright (C) 1994 Wolfgang Solfrank.
+ * Copyright (C) 1994 TooLs GmbH.
+ * 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 TooLs GmbH.
+ * 4. The name of TooLs GmbH may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/reboot.h>
+
+#include <kgdb/kgdb.h>
+
+#include <machine/cpu.h>
+#include <machine/psl.h>
+#include <machine/kgdb.h>
+
+int kgdbregs[NREG];
+
+dump(p, l)
+       u_char *p;
+{
+       int i, j, n;
+       
+       while (l > 0) {
+               printf("%08x: ", p);
+               n = l > 16 ? 16 : l;
+               for (i = 4; --i >= 0;) {
+                       for (j = 4; --j >= 0;)
+                               printf(--n >= 0 ? "%02x " : "   ", *p++);
+                       printf(" ");
+               }
+               p -= 16;
+               n = l > 16 ? 16 : l;
+               n = (n + 3) & ~3;
+               for (i = 4; --i >= 0;)
+                       printf((n -= 4) >= 0 ? "%08x " : "", *((long *)p)++);
+               printf("\n");
+               l -= 16;
+       }
+}
+
+#define        NDBGSTKS        8       /* number of debugstacks */
+#define        SZDBGSTK        512     /* size of one debugstack */
+static int debugstack[NDBGSTKS * SZDBGSTK];
+static int dbgstkused;
+
+int *
+kgdb_find_stack()
+{
+       int i;
+       
+       for (i = 0; i < NDBGSTKS; i++)
+               if (!(dbgstkused&(1 << i))) {
+                       dbgstkused |= 1 << i;
+                       return debugstack + (i + 1) * SZDBGSTK;
+               }
+       panic("KGDB: no stack");
+}
+
+void
+kgdb_free_stack(sp)
+       int *sp;
+{
+       int i;
+       
+       for (i = 0; i < NDBGSTKS; i++)
+               if (sp == debugstack + (i + 1) * SZDBGSTK) {
+                       if (!(dbgstkused&(1 << i)))
+                               panic("KGDB: free free stack");
+                       dbgstkused &= ~(1 << i);
+                       return;
+               }
+       panic("KGDB: free non-stack");
+}
+
+void
+kgdbinit()
+{
+       /* initialize undefined mode & setup trap vector */
+       initmode(PSR_UND32_MODE|F32_bit|I32_bit, kgdb_find_stack());
+}
+
+void
+kgdb_connect(when)
+       int when;
+{
+       boothowto |= RB_KDB;
+       if (when == 0)
+               printf("waiting for remote GDB\n");
+       __asm(".word 0xe6000010");
+}
+
+int
+kgdb_poll()
+{
+       return 0;
+}
+
+void
+kgdb_panic()
+{
+       kgdbpanic = 1;
+       __asm(".word 0xe6000010");
+}
+
+int
+kgdb_trap_glue(regs)
+       int *regs;
+{
+       int inst;
+       int cnt;
+       
+       inst = fetchinst(regs[PC] - 4);
+       switch (inst) {
+       default:
+               /* unexpected */
+#ifdef __notyet__
+               return 0;
+#endif
+       case 0xe6000011:        /* KGDB installed breakpoint */
+               regs[PC] -= 4;
+               break;
+       case 0xe6000010:        /* breakpoint in kgdb_connect */
+               break;
+       }
+       while (1) {
+               kgdbcopy(regs, kgdbregs, sizeof kgdbregs);
+               switch (kgdbcmds()) {
+               case 1:
+                       kgdbcopy(kgdbregs, regs, sizeof kgdbregs);
+                       if ((cnt = singlestep(regs)) < 0)
+                               panic("singlestep");
+                       regs[PC] += cnt;
+                       continue;
+               default:
+                       break;
+               }
+               break;
+       }
+       kgdbcopy(kgdbregs, regs, sizeof kgdbregs);
+       if (PSR_USER(regs[PSR]) || !PSR_32(regs[PSR]))
+               panic("KGDB: invalid mode %x", regs[PSR]);
+       return 1;
+}
+
+void
+kgdbcopy(vs, vd, n)
+       void *vs, *vd;
+       int n;
+{
+       char *s = vs, *d = vd;
+       long *ls, *ld;
+       int ln;
+       
+       if (((int)s&(sizeof(long)-1)) == ((int)d&(sizeof(long)-1))
+           && n >= 2 * sizeof(long)) {
+               while (((int)s&(sizeof(long)-1)) && --n >= 0)
+                       *d++ = *s++;
+               ln = n / sizeof(long);
+               n -= ln * sizeof(long);
+               ls = (long *)s;
+               ld = (long *)d;
+               while (--ln >= 0)
+                       *ld++ = *ls++;
+               s = (char *)ls;
+               d = (char *)ld;
+       }
+       while (--n >= 0)
+               *d++ = *s++;
+}
+
+void
+kgdbzero(vd, n)
+       void *vd;
+       int n;
+{
+       char *d = vd;
+       long *ld;
+       int ln;
+       
+       if (n >= 2 * sizeof(long)) {
+               while (--n >= 0) {
+                       if (!((int)d&sizeof(long)-1))
+                               break;
+                       *d++ = 0;
+               }
+               ln = n / sizeof(long);
+               n -= ln * sizeof(long);
+               ld = (long *)d;
+               while (--ln >= 0)
+                       *ld++ = 0;
+               d = (char *)ld;
+       }
+       while (--n >= 0)
+               *d++ = 0;
+}
+
+int
+kgdbcmp(vs, vd, n)
+       void *vs, *vd;
+       int n;
+{
+       char *s = vs, *d = vd;
+       long *ls, *ld;
+       int ln;
+       
+       if (((int)s&(sizeof(long)-1)) == ((int)d&(sizeof(long)-1))
+           && n >= 2 * sizeof(long)) {
+               while (--n >= 0) {
+                       if (!((int)s&(sizeof(long)-1)))
+                               break;
+                       if (*d++ != *s++)
+                               return *--d - *--s;
+               }
+               ln = n / sizeof(long);
+               n -= ln * sizeof(long);
+               ls = (long *)s;
+               ld = (long *)d;
+               while (--ln >= 0)
+                       if (*ld++ != *ls++) {
+                               n += ++ln * sizeof(long);
+                               break;
+                       }
+               s = (char *)ls;
+               d = (char *)ld;
+       }
+       while (--n >= 0)
+               if (*d++ != *s++)
+                       return *--d - *--s;
+       return 0;
+}
diff --git a/sys/arch/arm32/arm32/kgdb_step.c b/sys/arch/arm32/arm32/kgdb_step.c
new file mode 100644 (file)
index 0000000..c3b260b
--- /dev/null
@@ -0,0 +1,440 @@
+/*     $NetBSD: kgdb_step.c,v 1.2 1996/03/27 22:42:20 mark Exp $       */
+
+/*
+ * Copyright (C) 1994 Wolfgang Solfrank.
+ * Copyright (C) 1994 TooLs GmbH.
+ * 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 TooLs GmbH.
+ * 4. The name of TooLs GmbH may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (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 <machine/cpu.h>
+#include <machine/psl.h>
+#include <machine/kgdb.h>
+
+/*
+ * Faults during instruction fetch? XXX
+ */
+int
+fetchinst(pc)
+       void *pc;
+{
+       int inst, byte, n;
+       
+       inst = 0;
+       pc += sizeof(int);
+       for (n = sizeof(int); --n >= 0;) {
+               inst <<= 8;
+               byte = kgdbfbyte(--pc);
+               if (byte < 0)
+                       return 0xe7ffffff; /* special hack! */
+               inst |= byte;
+       }
+       return inst;
+}
+
+static __inline void
+execute(inst, args, regs)
+       int inst;
+       int *args;
+       int *regs;
+{
+       int *sp;
+       
+       /*
+        * For now, no user level emulation
+        */
+       if (PSR_USER(regs[PSR]) || !PSR_32(regs[PSR]))
+               panic("execute");
+       sp = kgdb_find_stack();
+       regs[PSR] = Execute(inst, regs[PSR], args, sp);
+       kgdb_free_stack(sp);
+}
+
+static __inline int
+condition(inst, args, regs)
+       int inst;
+       int *args;
+       int *regs;
+{
+       args[0] = 0;
+       /* mov{cond} r0, #1 */
+       execute((inst&0xf0000000)|0x03a00001, args, regs);
+       return args[0];
+}
+
+static __inline int
+immediate(inst)
+       int inst;
+{
+       int imm = inst&0xff;
+       int rot = (inst >> 8)&0xf;
+       
+       rot *= 2;
+       return (imm >> rot)|(imm << (32 - rot));
+}
+
+static __inline int
+getreg(reg, ahead, regs)
+       int reg;
+       int ahead;
+       int *regs;
+{
+       if (reg == PC)
+               return regs[PC] + (ahead ? 12 : 8);
+       return regs[reg];
+}
+
+static __inline void
+setreg(reg, val, regs)
+       int reg;
+       int val;
+       int *regs;
+{
+       if (reg == PC)
+               val &= ~3;
+       regs[reg] = val;
+}
+
+int
+singlestep(regs)
+       int *regs;
+{
+       int inst;
+       int args[5];
+       int dst, idx;
+       int val;
+       
+       inst = fetchinst(regs[PC]);
+       switch (inst&0x0c000000) {
+       case 0x00000000:
+               if ((inst&0x0fb00ff0) == 0x01000090) {
+                       /* swp */
+                       dst = (inst >> 12)&0xf;
+                       if (dst == PC)
+                               return -1;
+                       idx = inst&0xf;
+                       if (idx == PC)
+                               return -1;
+                       args[0] = getreg(idx, 0, regs);
+                       args[1] = getreg(dst, 0, regs);
+                       idx = (inst >> 16)&0xf;
+                       if (idx == PC)
+                               return -1;
+                       args[2] = getreg(idx, 0, regs);
+                       execute((inst&0xf0400000)|0x01021090, args, regs);
+                       setreg(dst, args[1], regs);
+                       return 4;
+               }
+               if ((inst&0x0fbf0fff) == 0x01000090) {
+                       /* mrs */
+                       if ((regs[PSR]&0xf) == 0
+                           && (inst&0x00400000))
+                               /* mrs xx, spsr in user mode */
+                               return 4; /* ??? */
+                       dst = (inst >> 12)&0xf;
+                       if (dst == PC)
+                               return -1;
+                       if (condition(inst, args, regs))
+                               setreg(dst, regs[(inst&0x00400000) ? SPSR : PSR], regs);
+                       return 4;
+               }
+               if ((inst&0x0fbffff0) == 0x0129f000) {
+                       /* msr */
+                       if (condition(inst, args, regs)) {
+                               idx = inst&0xf;
+                               if (idx == PC)
+                                       return -1;
+                               val = getreg(idx, 0, regs);
+                               if ((regs[PSR]&0xf) == 0) {
+                                       if (inst&0x00400000)
+                                               /* msr spsr, xx in user mode */
+                                               return 4; /* ??? */
+                                       val &= 0xf0000000;
+                                       val |= regs[PSR]&0x0fffffff;
+                               }
+                               regs[(inst&0x00400000) ? SPSR : PSR] = val;
+                       }
+                       return 4;
+               }
+               if ((inst&0x0dbff000) == 0x0128f000) {
+                       /* msrf */
+                       if (condition(inst, args, regs)) {
+                               if ((regs[PSR]&0xf) == 0
+                                   && (inst&0x00400000))
+                                       /* msr spsr_flg, xx in user mode */
+                                       return 4; /* ??? */
+                               if (inst&0x02000000)
+                                       val = immediate(inst);
+                               else if (inst&0x00000ff0)
+                                       return -1;
+                               else {
+                                       idx = inst&0xf;
+                                       if (idx == PC)
+                                               return -1;
+                                       val = getreg(idx, 0, regs);
+                               }
+                               val &= 0xf0000000;
+                               val |= regs[PSR]&0x0fffffff;
+                               regs[(inst&0x00400000) ? SPSR : PSR] = val;
+                       }
+                       return 4;
+               }
+               if ((inst&0x0fc000f0) == 0x00000090) {
+                       /* mul/mla */
+                       dst = (inst >> 16)&0xf;
+                       if (dst == PC)
+                               return -1;
+                       idx = inst&0xf;
+                       if (idx == dst || idx == PC)
+                               return -1;
+                       args[1] = getreg(idx, 0, regs);
+                       idx = (inst >> 8)&0xf;
+                       if (idx == PC)
+                               return -1;
+                       args[2] = getreg(idx, 0, regs);
+                       idx = (inst >> 12)&0xf;
+                       if (idx == PC)
+                               return -1;
+                       if (idx && !(inst&0x00200000))
+                               /* mul with rn != 0 */
+                               return -1;
+                       args[0] = getreg(idx, 0, regs);
+                       args[3] = getreg(dst, 0, regs);
+                       execute((inst&0xfff00000)|0x30291, args, regs);
+                       setreg(dst, args[3], regs);
+                       return 4;
+               }
+               {
+                       /* data processing */
+                       if (condition(inst, args, regs)) {
+                               dst = (inst >> 12)&0xf;
+                               if (inst&0x00100000) {
+                                       /* S-Bit set */
+                                       if (dst == PC)
+                                               /* S-Bit set and destination is R15 */
+                                               return -1; /* not yet */
+                               } else
+                                       /* S-Bit not set */
+                                       switch ((inst >> 21)&0xf) {
+                                       case 0x8: /* TST */
+                                       case 0x9: /* TEQ */
+                                       case 0xa: /* CMP */
+                                       case 0xb: /* CMN */
+                                               return -1;
+                                       }
+                               val = ((inst&0x02000010) == 0x00000010);
+                               args[0] = getreg((inst >> 16)&0xf, val, regs);
+                               if (!(inst&0x02000000)) {
+                                       args[2] = getreg(inst&0xf, val, regs);
+                                       if (inst&0x00000010) {
+                                               if (inst&0x00000080)
+                                                       return -1;
+                                               args[3] = getreg((inst >> 8)&0xf, val, regs);
+                                               inst = (inst&0xfff000f0)|0x00001302;
+                                       } else
+                                               inst = (inst&0xfff00ff0)|0x00001002;
+                               } else
+                                       inst = (inst&0xfff00fff)|0x00001000;
+                               execute(inst, args, regs);
+                               switch ((inst >> 21)&0xf) {
+                               case 0x8: /* TST */
+                               case 0x9: /* TEQ */
+                               case 0xa: /* CMP */
+                               case 0xb: /* CMN */
+                                       break;
+                               default:
+                                       setreg(dst, args[1], regs);
+                                       break;
+                               }
+                               return dst == PC ? 0 : 4;
+                       }
+                       return 4;
+               }
+               break;
+       case 0x04000000:
+               if ((inst&0x0e000010) == 0x06000010)
+                       /* undefined */
+                       return -1;
+               {
+                       /* ldr/str */
+                       if (condition(inst, args, regs)) {
+                               dst = (inst >> 12)&0xf;
+                               if (inst&0x00100000)
+                                       args[1] = regs[dst];
+                               else
+                                       args[1] = getreg(dst, 1, regs);
+                               val = (inst >> 16)&0xf;
+                               if ((inst&0x00200000) && val == PC)
+                                       /* write back with pc as base */
+                                       return -1;
+                               args[2] = getreg(val, 0, regs);
+                               if (inst&0x02000000) {
+                                       if (inst&0x00000010)
+                                               /* shift amount in register */
+                                               return -1;
+                                       idx = inst&0xf;
+                                       if (idx == PC)
+                                               /* offset in PC */
+                                               return -1;
+                                       args[0] = getreg(idx, 0, regs);
+                                       inst = (inst&0xfff00ff0)|0x21000;
+                               } else
+                                       inst = (inst&0xfff00fff)|0x21000;
+                               execute(inst, args, regs);
+                               if (inst&0x00200000)
+                                       regs[val] = args[2];
+                               if (inst&0x00100000)
+                                       setreg(dst, args[1], regs);
+                               return dst == PC ? 0 : 4;
+                       }
+                       return 4;
+               }
+               break;
+       case 0x08000000:
+               switch (inst&0x0e000000) {
+               case 0x08000000:
+                       /* ldm/stm */
+                       if (condition(inst, args, regs)) {
+                               int cnt;
+                               int val, is1;
+                               int final;
+                               
+                               if (inst&0x00400000)
+                                       /* S-bit not yet supported */
+                                       return -1;
+                               dst = (inst >> 16)&0xf;
+                               if (dst == PC)
+                                       return -1;
+                               args[0] = final = val = getreg(dst, 0, regs);
+                               cnt = 0;
+                               is1 = 0;
+                               for (idx = 0; idx < 16; idx++)
+                                       if ((inst&(1 << idx))
+                                           && (cnt += 4) <= 4 /* count the registers */
+                                           && idx == dst)
+                                               /* indicate unmodified store */
+                                               is1 = 1;
+                               if ((inst&0x00300000) == 0x00200000
+                                   && (inst&(1 << dst))
+                                   && !is1) {
+                                       /*
+                                        * The destination is in the list of a stm
+                                        * with write-back and is not the first
+                                        * register
+                                        */
+                                       if (inst&0x00800000)
+                                               val -= cnt;
+                                       else
+                                               val += cnt;
+                               }
+                               if (!(inst&0x00800000)) {
+                                       /* lowest address involved */
+                                       args[0] -= cnt;
+                                       if (!(inst&0x01000000))
+                                               /* post-decrement */
+                                               args[0] += 4;
+                                       if (inst&0x00200000)
+                                               final -= cnt;
+                               } else {
+                                       if (inst&0x01000000)
+                                               /* pre-increment */
+                                               args[0] += 4;
+                                       if (inst&0x00200000)
+                                               final += cnt;
+                               }
+                               for (idx = 0; idx < 16; idx++)
+                                       if (inst&(1 << idx)) {
+                                               args[1] = dst == idx
+                                                         ? val
+                                                         : getreg(idx, 1, regs);
+                                               execute((inst&0xfe100000)|0x00a00002, args, regs);
+                                               if (inst&0x00100000)
+                                                       regs[idx] = args[1];
+                                       }
+                               switch (inst&0x00300000) {
+                               case 0x00300000: /* ldm! */
+                                       if (inst&(1 << dst))
+                                               break;
+                               case 0x00200000: /* stm! */
+                                       regs[dst] = final;
+                                       break;
+                               }
+                               return (inst&(1 << PC)) && (inst&0x00100000) ? 0 : 4;
+                       }
+                       return 4;
+               case 0x0a000000:
+                       /* branch */
+                       if (condition(inst, args, regs)) {
+                               if (inst&0x01000000)
+                                       regs[LR] = regs[PC] + 4;
+                               if (inst&0x00800000)
+                                       inst |= 0xff000000;
+                               else
+                                       inst &= ~0xff000000;
+                               regs[PC] += 8 + (inst << 2);
+                               return 0;
+                       }
+                       return 4;
+               }
+               break;
+       case 0x0c000000:
+               switch (inst&0x0f000000) {
+               case 0x0c000000:
+               case 0x0d000000:
+                       /* ldc/stc */
+                       return -1;
+               case 0x0f000000:
+                       /* swi */
+                       return -1;
+               case 0x0e000000:
+                       /* cdp/mrc/mcr */
+                       if ((regs[PSR]&0xf) == 0)
+                               /* user mode */
+                               return -1;
+                       if ((inst&0x00e00fff) != 0x00000f10)
+                               /* cdp, different cp# or unknown operation */
+                               return -1;
+                       dst = (inst >> 12)&0xf;
+                       if (dst == PC)
+                               args[0] = regs[PSR];
+                       else
+                               args[0] = getreg(dst, 1, regs);
+                       execute(inst&0xffff0fff, args, regs);
+                       if (!(inst&0x00100000))
+                               if (dst == PC)
+                                       regs[PSR] = (regs[PSR]&0x0fffffff)
+                                                       |(args[0]&0xf0000000);
+                               else
+                                       regs[dst] = args[0];
+                       return 4;
+               }
+               break;
+       }
+       return -1;
+}
diff --git a/sys/arch/arm32/arm32/locore.S b/sys/arch/arm32/arm32/locore.S
new file mode 100644 (file)
index 0000000..57ea480
--- /dev/null
@@ -0,0 +1,563 @@
+/* $NetBSD: locore.S,v 1.8 1996/03/20 18:57:58 mark Exp $ */
+
+/*
+ * Copyright (C) 1994 Mark Brinicombe
+ * Copyright (C) 1994 Brini
+ * 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 Brini.
+ * 4. The name of Brini may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BRINI ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL BRINI BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (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 "assym.h"
+#include <machine/asm.h>
+#include <machine/cpu.h>
+#include <machine/param.h>
+#include <sys/syscall.h>
+
+/* What size shoudl this really be ? It is only used by init_arm() */
+
+#define INIT_ARM_STACK_SIZE    2048
+
+#define PUSHFRAME \
+       str     lr, [sp, #-4]!;         /* Push the return address */ \
+       sub     sp, sp, #0x00000004;    /* Skip SVC R14 */ \
+       stmdb   sp, {r0-r14}^;          /* Push the user mode registers */ \
+       sub     sp, sp, #(4*15);        /* Adjust the stack pointer */ \
+       mrs     r0, spsr_all;           /* Put the SPSR on the stack */ \
+       str     r0, [sp, #-4]!;
+
+#define PULLFRAME \
+        ldr     r0, [sp], #0x0004;      /* Get the SPSR from stack */ \
+        msr     spsr_all, r0; \
+       add     sp, sp, #(4*15);        /* Adjust the stack pointer */ \
+        ldmdb   sp, {r0-r14}^;         /* Restore the registers (user mode) */ \
+        mov     r0, r0;                 /* NOP for previous instruction */ \
+       add     sp, sp, #0x00000004;    /* Skip SVC R14 */ \
+       ldr     lr, [sp], #0x0004;      /* Pull the return address */
+
+/* register equates */
+fp     .req    r11
+ip     .req    r12
+sp     .req    r13
+lr     .req    r14
+pc     .req    r15
+
+.text
+       .align  0
+       .global start
+start:
+       add     r1, pc, #(Lstart - . - 8)
+       ldmia   r1, { r1, r2, r13 }             /* Set initial stack and */
+       sub     r2, r2, r1                      /* get zero init data */
+       mov     r3, #0
+
+L1:
+       str     r3, [r1], #0x0004               /* Zero the bss */
+       subs    r2, r2, #4
+       bgt     L1
+
+       mov     fp, #0x00000000                 /* trace back starts here */
+       bl      _initarm                        /* Off we go */
+
+/* init arm will return the new stack pointer. */
+
+       mov     sp, r0
+
+/* Debug code */
+
+/*     mov     r1, sp
+       add     r0, pc, #(Ltext9 - . - 8)
+       bl      _printf
+*/
+
+/* Setup an initial trap frame for start_init to use */
+
+       PUSHFRAME
+
+       mov     fp, #0x00000000         /* trace back starts here */
+       mov     r0, sp                  /* parameter to main is trap frame*/ 
+
+/* Debug */
+
+#if 0
+stmfd r13!, {r0-r3}
+       ldr     r1, Lproc0
+       ldr     r2, [r1]
+/*     mov     r1, r0*/
+       add     r0, pc, #(Ltext7 - . - 8)
+       bl      _printf
+ldmfd r13!, {r0-r3}
+#endif
+
+       bl      _main                   /* Lets light the flame and start her up */
+
+       PULLFRAME                       /* Pull the trap frame, now valid */
+
+       movs    pc, lr                  /* Exit to user process */
+
+/* Never gets here */
+
+       b       .
+
+Lstart:
+       .word   _edata
+       .word   _end
+       .word   svcstk + INIT_ARM_STACK_SIZE
+
+Lproc0:
+       .word   _proc0
+
+/*
+Ltext7:
+       .asciz  "proc0=%08x %08x\n"
+       .align  0
+
+
+Ltext9:
+       .asciz  "proc0 stack at V%08x %08x\n"
+       .align  0
+*/
+
+/* What size shoudl this really be ? It is only used by init_arm() */
+
+       .bss
+svcstk:        .space  INIT_ARM_STACK_SIZE
+
+/*
+ * Instructions to copy to the bottom of zero page
+ * These are the entry point to the system exception routines
+ */
+
+       .text
+       .align  0
+       .global _page0, _page0_end
+_page0:
+       ldr     pc, [pc, #Lreset - . - 8]
+       ldr     pc, [pc, #Lundefined - . - 8]
+       ldr     pc, [pc, #Lswi - . - 8]
+       ldr     pc, [pc, #Labortpre - . - 8]
+       ldr     pc, [pc, #Labortdata - . - 8]
+       ldr     pc, [pc, #Laddrexc - . - 8]
+       ldr     pc, [pc, #Lirq - . - 8]
+       ldr     pc, [pc, #Lfiq - . - 8]
+
+Lreset:
+       .word   reset_entry
+Lundefined:
+       .word   undefined_entry
+Lswi:
+       .word   swi_entry
+Labortpre:
+       .word   prefetch_abort_entry
+Labortdata:
+       .word   data_abort_entry
+Laddrexc:
+       .word   addrexc
+Lirq:
+       .word   irq_entry
+
+Lfiq:
+       .word   fiq
+_page0_end =   .
+
+#if 0
+reset:
+       add     r0, pc, #Wreset - . - 8
+       ldmia   r0, {r0, pc}
+resetmsg:
+       .asciz  "reset"
+       .align  0
+Wreset:
+       .word   resetmsg
+       .word   _panic
+#endif
+
+reset_entry:
+       PUSHFRAME
+
+       mov     r0, sp                  /* Pass the frame to any function */
+
+       bl      _resethandler           /* It's a branch throught zero ! */
+
+       PULLFRAME
+
+       movs    pc, lr                  /* Exit */
+
+#if 0
+undefined:
+#ifndef        KGDB
+       add     r0, pc, #Wundefined - . - 8
+       ldmia   r0, {r0, pc}
+undmsg:
+       .asciz  "undefined"
+       .align  0
+Wundefined:
+       .word   undmsg
+       .word   _panic
+#else
+/*
+ * lr is the saved pc, and we make space for the saved psr
+ */
+       stmfd   sp!, {lr, pc}
+/*
+ * now save all the rest of the registers (r13&r14) are redone later
+ */
+       stmfd   sp!, {r0-lr}
+/*
+ * now switch to the old mode to get r13&r14, but disable interrupts
+*/
+/* stupid gas doesn't yet know about the psr transfers */
+       .word   0xe10f3000              @       mrs     r3, cpsr
+       .word   0xe14f2000              @       mrs     r2, spsr
+       str     r2, [sp, #64]
+       orr     r2, r2, #(PSR_FIQ32_MODE|PSR_IRQ32_MODE)
+       .word   0xe129f002              @       msr     cpsr, r2
+       mov     r0, r13
+       mov     r1, r14
+       orr     r3, r3, #(PSR_FIQ32_MODE|PSR_IRQ32_MODE)
+       .word   0xe129f003              @       msr     cpsr, r3
+       str     r0, [sp, #52]
+       str     r1, [sp, #56]
+       mov     r0, sp
+       mov     lr, pc
+       ldr     pc, [pc, #Wundefined - . - 8]
+       add     sp, sp, #52             /* adjust stack to r13 */
+/*
+ * set saved psr and get r13&r14 to new (saved) mode first
+ */
+       ldr     r2, [sp, #12]
+       ldr     r0, [sp]
+       ldr     r1, [sp, #4]
+/* stupid gas doesn't yet know about the psr transfers */
+       .word   0xe169f002              @       msr     spsr, r2
+       .word   0xe10f3000              @       mrs     r3, cpsr
+       orr     r2, r2, #(PSR_FIQ32_MODE|PSR_IRQ32_MODE)
+       .word   0xe129f002              @       msr     cpsr, r2
+       mov     r13, r0
+       mov     r14, r1
+       .word   0xe129f003              @       msr     cpsr, r3
+       ldmea   sp, {r0-r12}            /* now the rest of the registers */
+       add     sp, sp, #16             /* Adjust stack to top */
+       ldr     lr, [sp, #-8]           /* get link address */
+       movs    pc, lr                  /* return */
+Wundefined:
+       .word   _kgdb_trap_glue
+#endif
+#endif
+
+addrexc:
+       .word   0xe10f1000
+       .word   0xe14f2000
+       mov     r3, lr
+       add     r0, pc, #addrexcmsg - . - 8
+       bl      _printf
+       b       data_abort_entry
+
+addrexcmsg:
+       .asciz  "address exception CPSR=%08x SPSR=%08x lr=%08x\n"
+       .align  0
+Waddrexc:
+       .word   addrexcmsg
+       .word   _panic
+
+irq:
+       add     r0, pc, #Wirq - . - 8
+       ldmia   r0, {r0, pc}
+irqmsg:
+       .asciz  "irq"
+       .align  0
+Wirq:
+       .word   irqmsg
+       .word   _panic
+
+fiq:
+       add     r0, pc, #Wfiq - . - 8
+       ldmia   r0, {r0, pc}
+fiqmsg:
+       .asciz  "fiq"
+       .align  0
+Wfiq:
+       .word   fiqmsg
+       .word   _panic
+
+       .global _initmode
+_initmode:
+/* stupid gas doesn't yet know about the psr transfers */
+       mrs     r2, cpsr_all
+       msr     cpsr_all, r0
+       mov     sp, r1
+       msr     cpsr_all, r2
+       mov     pc, lr
+
+
+       .global _boot0
+_boot0:
+        mrs     r2, cpsr_all
+       bic     r2, r2, #(PSR_MODE)
+        orr     r2, r2, #(PSR_SVC32_MODE)
+       orr     r2, r2, #(I32_bit | F32_bit)
+        msr     cpsr_all, r2
+
+       mov     r0, #0
+        mcr     15, 0, r0, c1, c0, 0
+       mov     pc, r0
+
+
+/* Debug routine to print trace back information from stack */
+
+       .global _traceback
+
+_traceback:
+       stmfd   sp!, {r4, r5, r6, lr}
+       mov     r4, r11
+       ldr     r5, Ltracebackmin
+       ldr     r6, Ltracebackmax
+
+tbloop:
+       mov     r1, r4
+       ldr     r2, [r4, #-12]
+       ldr     r3, [r4, #-8]
+       add     r0, pc, #Ltb1 - .  - 8
+       bl      _printf
+
+/*     ldr     r1, [r4, #-4]
+       ldr     r2, [r4]
+       add     r0, pc, #Ltb2 - .  - 8
+       bl      _printf*/
+       ldr     r0, [r4, #-4]
+       ldr     r1, [r4]
+       bl      _traceback_sym
+
+       mov     r3, r4
+       ldr     r4, [r4, #-12]
+       teq     r3, r4
+       beq     tbexit
+       cmp     r4, r5
+       bls     tbexit
+       cmp     r4, r6
+       bge     tbexit
+       teq     r4, #0x00000000
+       bne     tbloop
+
+tbexit:
+       mov     r0, r4
+        ldmfd  sp!, {r4, r5, r6, pc}
+
+Ltracebackmin:
+       .word   0xefbfe000
+
+Ltracebackmax:
+       .word   0xefc00000
+
+Ltb1:
+       .asciz  "traceback: fp=%08x fp->fp=%08x fp->sp=%08x "
+
+Ltb2:
+       .asciz  "fp->lr=%08x fp->pc=%08x\n"
+
+       .align  0
+
+/* Debug routine to print trace back information from stack */
+
+       .global _simpletraceback
+
+_simpletraceback:
+       stmfd   sp!, {r4, r5, r6, lr}
+       mov     r4, r11
+       ldr     r5, Ltracebackmin
+       ldr     r6, Ltracebackmax
+
+stbloop:
+/*     ldr     r1, [r4, #-4]
+       ldr     r2, [r4]
+       add     r0, pc, #Ltb2 - .  - 8
+       bl      _printf*/
+       ldr     r0, [r4, #-4]
+       ldr     r1, [r4]
+       bl      _traceback_sym
+
+       mov     r3, r4
+       ldr     r4, [r4, #-12]
+       teq     r3, r4
+       beq     stbexit
+       cmp     r4, r5
+       bls     stbexit
+       cmp     r4, r6
+       bge     stbexit
+       teq     r4, #0x00000000
+       bne     stbloop
+
+stbexit:
+       mov     r0, r4
+        ldmfd  sp!, {r4, r5, r6, pc}
+
+
+/* Debug routine to print trace back information from stack */
+
+       .global _irqtraceback
+
+_irqtraceback:
+       stmfd   sp!, {r4, r5, r6, lr}
+       mov     r4, r0
+       mov     r5, r1
+       add     r6, r5, #(NBPG)
+
+itbloop:
+       mov     r1, r4
+       ldr     r2, [r4, #-12]
+       ldr     r3, [r4, #-8]
+       add     r0, pc, #Ltb1 - .  - 8
+       bl      _printf
+
+/*     ldr     r1, [r4, #-4]
+       ldr     r2, [r4]
+       add     r0, pc, #Ltb2 - .  - 8
+       bl      _printf*/
+       ldr     r0, [r4, #-4]
+       ldr     r1, [r4]
+       bl      _traceback_sym
+
+       mov     r3, r4
+       ldr     r4, [r4, #-12]
+       teq     r3, r4
+       beq     itbexit
+       cmp     r4, r5
+       bls     itbexit
+       cmp     r4, r6
+       bge     itbexit
+       teq     r4, #0x00000000
+       bne     itbloop
+
+itbexit:
+       mov     r0, r4
+        ldmfd  sp!, {r4, r5, r6, pc}
+
+
+       .global _user_traceback
+
+_user_traceback:
+       stmfd   sp!, {r4, r5, r6, lr}
+       mov     r4, r0
+       ldr     r5, Lusertracebackmin
+       ldr     r6, Lusertracebackmax
+
+usertbloop:
+       mov     r1, r4
+       ldr     r2, [r4, #-12]
+       ldr     r3, [r4, #-8]
+       add     r0, pc, #Lusertb1 - .  - 8
+       bl      _printf
+
+       ldr     r1, [r4, #-4]
+       ldr     r2, [r4]
+       add     r0, pc, #Lusertb2 - .  - 8
+       bl      _printf
+
+       mov     r3, r4
+       ldr     r4, [r4, #-12]
+       teq     r3, r4
+       beq     usertbexit
+       cmp     r4, r5
+       bls     tbexit
+       cmp     r4, r6
+       bge     usertbexit
+       teq     r4, #0x00000000
+       bne     usertbloop
+
+usertbexit:
+       mov     r0, r4
+        ldmfd  sp!, {r4, r5, r6, pc}
+
+Lusertracebackmin:
+       .word   0x00001000
+
+Lusertracebackmax:
+       .word   0xefbfe000
+
+Lusertb1:
+       .asciz  "traceback: fp=%08x fp->fp=%08x fp->sp=%08x "
+
+Lusertb2:
+       .asciz  "fp->lr=%08x fp->pc=%08x\n"
+
+       .align  0
+
+
+
+/*
+ * Signal trampoline; copied to top of user stack.
+ */
+       .global _sigcode
+ENTRY(sigcode)
+/*
+ * r0-r2 are our signal handler parameters
+ * r3 is the handler address
+ */
+
+       add     lr, pc, #0                      /* Set return address */
+       mov     pc, r3                          /* Call the handler */
+
+/*
+ * Call sig_return with address of the signal context
+ * Note: Don't use SIG_SCP as this make have been trashed by the program
+ */
+       add     r0, sp, #SIGF_SC
+       swi     SYS_sigreturn
+
+/* Well if that failed we better exit quick ! */
+
+       add     r0, pc, #Lsigerr - . - 8
+       swi     0x1002
+
+       swi     SYS_exit
+
+Lsigerr:
+       .asciz "sigreturn syscall failed\n"
+       .align  0
+        .globl  _esigcode
+_esigcode:
+
+/*
+ * setjump + longjmp
+ */
+       .global _setjmp
+ENTRY(setjmp)
+        stmia  r0, {r4-r14}
+        mov    r0, #0x00000000
+        mov    r15, r14
+
+       .global _longjmp
+ENTRY(longjmp)
+        ldmia  r2, {r4-r14}
+       mov     r0, #0x00000001
+       mov     r15, r14
+
+       .global _esym
+_esym: .word   _end
+
+       .global _abort
+_abort:
+       b       _abort
diff --git a/sys/arch/arm32/arm32/machdep.c b/sys/arch/arm32/arm32/machdep.c
new file mode 100644 (file)
index 0000000..6ec881a
--- /dev/null
@@ -0,0 +1,2153 @@
+/* $NetBSD: machdep.c,v 1.6 1996/03/13 21:32:39 mark Exp $ */
+
+/*
+ * Copyright (c) 1994-1996 Mark Brinicombe.
+ * Copyright (c) 1994 Brini.
+ * All rights reserved.
+ *
+ * This code is derived from software written for Brini by Mark Brinicombe
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided 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 Brini.
+ * 4. The name of the company nor the name of the author may be used to
+ *    endorse or promote products derived from this software without specific
+ *    prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BRINI ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL BRINI 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.
+ *
+ * RiscBSD kernel project
+ *
+ * machdep.c
+ *
+ * Machine dependant functions for kernel setup
+ *
+ * This file needs a lot of work. 
+ *
+ * Created      : 17/09/94
+ */
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/reboot.h>
+#include <sys/callout.h>
+#include <sys/proc.h>
+#include <sys/user.h>
+#include <sys/kernel.h>
+#include <sys/mbuf.h>
+#include <sys/msgbuf.h>
+#include <sys/buf.h>
+#include <sys/map.h>
+#include <sys/exec.h>
+#include <sys/mount.h>
+#include <sys/vnode.h>
+#include <sys/device.h>
+#include <sys/sysctl.h>
+#include <sys/syscallargs.h>
+
+#ifdef SYSVMSG
+#include <sys/msg.h>
+#endif
+#ifdef SYSVSEM
+#include <sys/sem.h>
+#endif
+#ifdef SYSVSHM
+#include <sys/shm.h>
+#endif
+
+#include <vm/vm_kern.h>
+
+#include <machine/signal.h>
+#include <machine/frame.h>
+#include <machine/bootconfig.h>
+#include <machine/katelib.h>
+#include <machine/cpu.h>
+#include <machine/pte.h>
+#include <machine/vidc.h>
+#include <machine/iomd.h>
+#include <machine/io.h>
+#include <machine/irqhandler.h>
+#include <machine/undefined.h>
+#include <machine/rtc.h>
+
+#include "hydrabus.h"
+
+/* Describe different actions to take when boot() is called */
+
+#define ACTION_HALT   0x01     /* Halt and boot */
+#define ACTION_REBOOT 0x02     /* Halt and request RiscBSD reboot */
+#define ACTION_KSHELL 0x04     /* Call kshell */
+#define ACTION_DUMP   0x08     /* Dump the system to the dump dev */
+
+#define HALT_ACTION    ACTION_HALT | ACTION_KSHELL     /* boot(RB_HALT) */
+#define REBOOT_ACTION  ACTION_REBOOT                   /* boot(0) */
+#define PANIC_ACTION   ACTION_HALT | ACTION_KSHELL     /* panic() */
+
+BootConfig bootconfig;         /* Boot config storage */
+videomemory_t videomemory;     /* Video memory descriptor */
+
+vm_offset_t physical_start;
+vm_offset_t physical_freestart;
+vm_offset_t physical_freeend;
+vm_offset_t physical_end;
+int physical_memoryblock;
+u_int free_pages;
+vm_offset_t pagetables_start;
+int physmem = 0;
+
+int debug_flags;
+int max_processes;
+int cpu_cache;
+int cpu_ctrl;
+
+u_int ramdisc_size;            /* Ramdisc size */
+
+u_int kmodule_base;
+u_int kmodule_size;
+
+u_int videodram_size;          /* Amount of DRAM to reserve for video */
+vm_offset_t videodram_start;
+
+vm_offset_t physical_pt_start;
+vm_offset_t virtual_pt_end;
+
+u_int *cursor_data;            /* Will move to the vidc code */
+
+typedef struct {
+       vm_offset_t physical;
+       vm_offset_t virtual;
+} pv_addr_t;
+
+pv_addr_t systempage;
+pv_addr_t irqstack;
+pv_addr_t undstack;
+pv_addr_t abtstack;
+pv_addr_t kernelstack;
+#if NHYDRABUS > 0
+pv_addr_t hydrascratch;
+#endif
+
+pt_entry_t kernel_pt_table[15];
+
+/* the following is used externally (sysctl_hw) */
+char machine[] = "arm32";      /* cpu "architecture" */
+
+char *boot_args;
+
+extern pt_entry_t msgbufpte;
+int    msgbufmapped;
+vm_offset_t msgbufphys;
+
+extern u_int data_abort_handler_address;
+extern u_int prefetch_abort_handler_address;
+extern u_int undefined_handler_address;
+
+extern int pmap_debug_level;
+
+#define KERNEL_PT_PAGEDIR   0
+#define KERNEL_PT_PDE       1
+#define KERNEL_PT_PTE       2
+#define KERNEL_PT_VMEM      3
+#define KERNEL_PT_SYS       4
+#define KERNEL_PT_KERNEL    5
+#define KERNEL_PT_VMDATA0   6
+#define KERNEL_PT_VMDATA1   7
+#define KERNEL_PT_VMDATA2   8
+#define KERNEL_PT_VMDATA3   9
+#define KERNEL_PT_VMDATA4  10
+#define KERNEL_PT_VMDATA5  11
+#define KERNEL_PT_VMDATA6  12
+#define KERNEL_PT_VMDATA7  13
+#define KERNEL_PT_VMDATA7  13
+#define KERNEL_PT_KSTACK   14
+
+struct user *proc0paddr;
+
+/*
+ * 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 cold = 1;
+
+/* Prototypes */
+
+void boot0     __P((void));
+void bootsync  __P((void));
+
+char *strstr   __P((char */*s1*/, char */*s2*/));
+
+void physconputchar            __P((char));
+void physcon_display_base      __P((u_int));
+void consinit                  __P((void));
+
+void map_section       __P((vm_offset_t, vm_offset_t, vm_offset_t));
+void map_pagetable     __P((vm_offset_t, vm_offset_t, vm_offset_t));
+void map_entry         __P((vm_offset_t, vm_offset_t va, vm_offset_t));
+void map_entry_ro      __P((vm_offset_t, vm_offset_t, vm_offset_t));
+
+void pmap_bootstrap            __P((vm_offset_t /*kernel_l1pt*/));
+void process_kernel_args       __P((void));
+u_long strtoul                 __P((const char */*s*/, char **/*ptr*/, int /*base*/));
+caddr_t allocsys               __P((caddr_t /*v*/));
+void identify_cpu              __P((void));
+void data_abort_handler                __P((trapframe_t */*frame*/));
+void prefetch_abort_handler    __P((trapframe_t */*frame*/));
+void undefinedinstruction_bounce       __P((trapframe_t */*frame*/));
+void set_boot_devs             __P((void));
+void configure                 __P((void));
+void zero_page_readonly                __P((void));
+void zero_page_readwrite       __P((void));
+u_int disassemble              __P((u_int /*addr*/));
+int setup_cursor               __P((void));
+void init_fpe_state            __P((struct proc *));
+
+void pmap_debug        __P((int /*level*/));
+void dumpsys   __P((void));
+void hydrastop __P((void));
+
+void vtbugreport __P((void));
+
+/*
+ * Debug function just to park the CPU
+ *
+ * This should be updated to power down an ARM7500
+ */
+
+void
+halt()
+{
+       while (1);
+}
+
+
+/*
+ * void boot(int howto)
+ *
+ * Reboots the system
+ *
+ * This gets called when a reboot is request by the user or after a panic.
+ * Call boot0() will reboot the machine. For the moment we will try and be
+ * clever and return to the booting environment. This may work if we
+ * have be booted with the Kate boot loader as long as we have not messed
+ * the system up to much. Until we have our own memory management running
+ * this should work. The only use of being able to return (to RISC OS)
+ * is so I don't have to wait while the machine reboots.
+ */
+
+/* NOTE: These variables will be removed, well some of them */
+
+extern u_int spl_mask;
+extern u_int current_mask;
+struct pcb dumppcb;
+extern u_int arm700bugcount;
+extern int ioctlconsolebug;
+
+void
+boot(howto)
+       int howto;
+{
+       int loop;
+       int action;
+
+/* Debugging here */
+
+       if (curproc == NULL)
+               printf("curproc = 0 - must have been in cpu_idle()\n");
+
+/*     if (panicstr)
+               printf("ioctlconsolebug=%d %08x\n", ioctlconsolebug, ioctlconsolebug);*/
+
+/*     if (curpcb)
+               printf("curpcb=%08x pcb_sp=%08x pcb_und_sp=%08x\n", curpcb, curpcb->pcb_sp, curpcb->pcb_und_sp);*/
+
+#if NHYDRABUS > 0
+/*
+ * If we are halting the master then we should halt the slaves :-)
+ * otherwise it can get a bit disconcerting to have 4 other
+ * processor still tearing away doing things.
+ */
+
+       hydrastop();
+#endif
+
+/* Debug info */
+
+       printf("boot: howto=%08x %08x curproc=%08x\n", howto, spl_mask, (u_int)curproc);
+
+       printf("current_mask=%08x spl_mask=%08x\n", current_mask, spl_mask);
+       printf("ipl_bio=%08x ipl_net=%08x ipl_tty=%08x ipl_clock=%08x ipl_imp=%08x\n",
+            irqmasks[IPL_BIO], irqmasks[IPL_NET], irqmasks[IPL_TTY],
+            irqmasks[IPL_CLOCK], irqmasks[IPL_IMP]);
+
+       dump_spl_masks();
+
+/*     vtbugreport();*/
+
+/* Did we encounter the ARM700 bug we discovered ? */
+
+       if (arm700bugcount > 0)
+               printf("ARM700 PREFETCH/SWI bug count = %d\n", arm700bugcount);
+
+/* Disable console buffering */
+
+       cnpollc(1);
+
+/* If we are still cold then hit the air brakes */
+
+       if (cold) {
+               printf("Halted while still in the ICE age.\n");
+               printf("Hit a key to reboot\n");
+               cngetc();
+               boot0();
+       }
+
+/*
+ * Depending on how we got here and with what intructions, choose
+ * the actions to take. (See the actions defined above)
+ */
+       if (panicstr)
+               action = PANIC_ACTION;
+       else if (howto & RB_HALT)
+               action = HALT_ACTION;
+       else
+               action = REBOOT_ACTION;
+
+/*
+ * If RB_NOSYNC was not specified sync the discs.
+ * Note: Unless cold is set to 1 here, syslogd will die during the unmount.
+ * It looks like syslogd is getting woken up only to find that it cannot
+ * page part of the binary in as the filesystem has been unmounted.
+ */
+
+
+       if (!(howto & RB_NOSYNC)) {
+               cold = 1;               /* no sleeping etc. */
+               bootsync();
+       }
+
+/* Say NO to interrupts */
+
+       splhigh();
+       
+#ifdef KSHELL
+
+/* Now enter our crude debug shell if required. Soon to be replaced with DDB */
+
+       if (action & ACTION_KSHELL)
+               shell();
+#else
+       if (action & ACTION_KSHELL) {
+               printf("Halted.\n");
+               printf("Hit a key to reboot ");
+               cngetc();
+       }
+#endif
+
+/* Auto reboot overload protection */
+
+/*
+ * This code stops the kernel entering an endless loop of reboot - panic
+ * cycles. This will only effect kernels that have been configured to
+ * reboot on a panic and will have the effect of stopping further reboots
+ * after it has rebooted 16 times after panics and clean halt or reboot
+ * will reset the counter.
+ */
+
+/*
+ * Have we done 16 reboots in a row ? If so halt rather than reboot
+ * since 16 panics in a row without 1 clean halt means something is
+ * seriously wrong
+ */
+
+       if (cmos_read(RTC_ADDR_REBOOTCNT) > 16)
+               action = (action & ~ACTION_REBOOT) | ACTION_HALT;
+
+/*
+ * If we are rebooting on a panic then up the reboot count otherwise reset
+ * This will thus be reset if the kernel changes the boot action from
+ * reboot to halt due to too any reboots.
+ */
+       if ((action & ACTION_REBOOT) && panicstr)
+               cmos_write(RTC_ADDR_REBOOTCNT,
+                  cmos_read(RTC_ADDR_REBOOTCNT) + 1);
+       else
+               cmos_write(RTC_ADDR_REBOOTCNT, 0);
+
+/*
+ * If we need a RiscBSD reboot, request it but setting a bit in the CMOS RAM
+ * This can be detected by the RiscBSD boot loader during a RISC OS boot
+ * No other way to do this as RISC OS is in ROM.
+ */
+
+       if (action & ACTION_REBOOT)
+               cmos_write(RTC_ADDR_BOOTOPTS,
+                   cmos_read(RTC_ADDR_BOOTOPTS) | 0x02);
+
+/* If we need to do a dump, do it */
+
+       if ((howto & RB_DUMP) && (action & ACTION_DUMP)) {
+               savectx(&dumppcb);
+               dumpsys();
+       }
+
+/* Run any shutdown hooks */
+
+       printf("Running shutdown hooks ...\n");
+       doshutdownhooks();
+
+/* Make sure IRQ's are disabled */
+
+       IRQdisable;
+
+/* Tell the user we are booting */
+
+       printf("boot...");
+
+/* Give the user time to read the last couple of lines of text. */
+
+       for (loop = 5; loop > 0; --loop) {
+               printf("%d..", loop);
+               delay(500000);
+       }
+
+       boot0();
+}
+
+
+/* Sync the discs and unmount the filesystems */
+
+void
+bootsync(void)
+{
+       int iter;
+       int nbusy;
+       struct buf *bp;
+       static int bootsyncdone = 0;
+
+       if (bootsyncdone) return;
+
+       bootsyncdone = 1;
+
+/* Make sure we can still manage to do things */
+
+       if (GetCPSR() & I32_bit) {
+/*
+ * If we get then boot has been called with out RB_NOSYNC and interrupts were
+ * disabled. This means the boot() call did not come from a user process e.g.
+ * shutdown, but must have come from somewhere in the kernel.
+ */
+
+               IRQenable;
+               printf("Warning IRQ's disabled during boot()\n");
+       }
+
+       vfs_shutdown();
+}
+
+
+/*
+ * Estimated loop for n microseconds
+ */
+
+/* Need to re-write this to use the timers */
+
+/* One day soon I will actually do this */
+
+void
+delay(n)
+       u_int n;
+{
+       u_int i;
+
+       while (--n > 0)
+               for (i = 8; --i;);
+}
+
+
+/*
+ * u_int initarm(BootConfig *bootconf)
+ *
+ * Initial entry point on startup. This gets called before main() is
+ * entered.
+ * It should be responcible for setting up everything that must be
+ * in place when main is called.
+ * This includes
+ *   Taking a copy of the boot configuration structure.
+ *   Initialising the physical console so characters can be printed.
+ *   Setting up page tables for the kernel
+ *   Relocating the kernel to the bottom of physical memory
+ */
+
+/* This routine is frightening mess ! This is what my mind looks like -mark */
+
+u_int
+initarm(bootconf)
+       BootConfig *bootconf;
+{
+       int loop;
+       int loop1;
+       u_int logical;
+       u_int physical;
+       u_int kerneldatasize;
+       u_int l1pagetable;
+       u_int l2pagetable;
+       extern char page0[], page0_end[];
+       struct exec *kernexec = (struct exec *)KERNEL_BASE;
+
+/* Copy the boot configuration structure */
+
+       bootconfig = *bootconf;
+
+/*
+ * Initialise the video memory descriptor
+ *
+ * This will change in the future to correctly report DRAM as well
+ * but for the moment hardwire it. This will allow the console code
+ * to use the structure now.
+ *
+ * Note: all references to the video memory virtual/physical address
+ * should go via this structure.
+ */
+
+/*
+ * In the future ...
+ *
+ * All console output will be postponed until the primary bootstrap
+ * has been completed so that we have had a chance to reserve some
+ * memory for the video system if we do not have separate VRAM.
+ */
+       videomemory.vidm_vbase = bootconfig.display_start;
+       videomemory.vidm_pbase = VRAM_BASE;
+       videomemory.vidm_type = VIDEOMEM_TYPE_VRAM;
+       videomemory.vidm_size = bootconfig.display_size;
+
+/*
+ * Initialise the physical console
+ * This is done in main() but for the moment we do it here so that
+ * we can use printf in initarm() before main() has been called.
+ */
+
+       consinit();
+
+/* Talk to the user */
+
+       printf("initarm...\n");
+
+       printf("Kernel loaded from file %s\n", bootconfig.kernelname);
+       printf("Kernel arg string %s\n", (char *)bootconfig.argvirtualbase);
+
+       printf("\nBoot configuration structure reports the following memory\n");
+
+       printf("  DRAM block 0a at %08x size %08x  DRAM block 0b at %08x size %08x\n\r",
+           bootconfig.dram[0].address,
+           bootconfig.dram[0].pages * bootconfig.pagesize,
+           bootconfig.dram[1].address,
+           bootconfig.dram[1].pages * bootconfig.pagesize);
+       printf("  DRAM block 1a at %08x size %08x  DRAM block 1b at %08x size %08x\n\r",
+           bootconfig.dram[2].address,
+           bootconfig.dram[2].pages * bootconfig.pagesize,
+           bootconfig.dram[3].address,
+           bootconfig.dram[3].pages * bootconfig.pagesize);
+       printf("  VRAM block 0  at %08x size %08x\n\r",
+           bootconfig.vram[0].address,
+           bootconfig.vram[0].pages * bootconfig.pagesize);
+
+       printf(" videomem = %08x %08x\n", bootconfig.display_start, videomemory.vidm_vbase);
+
+/* Check to make sure the page size is correct */
+
+       if (NBPG != bootconfig.pagesize)
+               panic("Page size is not %d bytes\n", NBPG);
+
+/*
+ * Ok now we have the hard bit.
+ * We have the kernel allocated up high. The rest of the memory map is
+ * available. We are still running on RISC OS page tables.
+ *
+ * We need to construct new page tables move the kernel in physical
+ * memory and switch to them.
+ *
+ * The booter will have left us 6 pages at the top of memory.
+ * Two of these are used as L2 page tables and the other 4 form the L1
+ * page table.
+ */
+
+/*
+ * Ok we must construct own own page table tables.
+ * Once we have these we can reorganise the memory as required
+ */
+
+/*
+ * We better check to make sure the booter has set up the scratch
+ * area for us correctly. We use this area to create temporary pagetables
+ * while we reorganise the memory map.
+ */
+
+       if ((bootconfig.scratchphysicalbase & 0x3fff) != 0)
+               panic("initarm: Scratch area not aligned on 16KB boundry\n");
+
+       if ((bootconfig.scratchsize < 0xc000) != 0)
+               panic("initarm: Scratch area too small (need >= 48KB)\n");
+
+/*
+ * Ok start the primary bootstrap.
+ * The primary bootstrap basically replaces the booter page tables with
+ * new ones that it creates in the boot scratch area. These page tables
+ * map the rest of the physical memory into the virtaul memory map.
+ * This allows low physical memory to be accessed to create the
+ * kernels page tables, relocate the kernel code from high physical
+ * memory to low physical memory etc.
+ */
+
+       printf("initarm: Primary bootstrap ... ");
+
+/*
+ * Update the videomemory structure to reflect the mapping changes
+ */
+       videomemory.vidm_vbase = VMEM_VBASE;
+       videomemory.vidm_pbase = VRAM_BASE;
+       videomemory.vidm_type = VIDEOMEM_TYPE_VRAM;
+       videomemory.vidm_size = bootconfig.vram[0].pages * NBPG;
+
+       kerneldatasize = bootconfig.kernsize + bootconfig.argsize;
+
+       l2pagetable = bootconfig.scratchvirtualbase;
+       l1pagetable = l2pagetable + 0x4000;
+
+/*
+ * Now we construct a L2 pagetables for the VRAM, the current kernel memory
+ * and the new kernel memory
+ */
+
+       for (logical = 0; logical < 0x200000; logical += NBPG) {
+               map_entry(l2pagetable + 0x1000, logical,
+                   bootconfig.vram[0].address + logical);
+               map_entry(l2pagetable + 0x1000, logical + 0x200000,
+                   bootconfig.vram[0].address + logical);
+       }
+
+       for (logical = 0; logical < kerneldatasize + bootconfig.scratchsize;
+           logical += NBPG) {
+               map_entry(l2pagetable + 0x3000, logical,
+                   bootconfig.kernphysicalbase + logical);
+       }
+
+#if NHYDRABUS > 0
+       for (logical = 0; logical < 0x200000; logical += NBPG) {
+               map_entry(l2pagetable + 0x2000, logical,
+                   bootconfig.dram[0].address + logical + NBPG);
+       }
+#else
+       for (logical = 0; logical < 0x200000; logical += NBPG) {
+               map_entry(l2pagetable + 0x2000, logical,
+                   bootconfig.dram[0].address + logical);
+       }
+#endif
+
+/*
+ * Now we construct the L1 pagetable. This only needs the minimum to
+ * keep us going until we can contruct the proper kernel L1 page table.
+ */
+
+       map_section(l1pagetable, VIDC_BASE,  VIDC_HW_BASE);
+       map_section(l1pagetable, IOMD_BASE,  IOMD_HW_BASE);
+
+       map_pagetable(l1pagetable, 0x00000000,
+           bootconfig.scratchphysicalbase + 0x2000);
+       map_pagetable(l1pagetable, KERNEL_BASE,
+           bootconfig.scratchphysicalbase + 0x3000);
+       map_pagetable(l1pagetable, VMEM_VBASE,
+           bootconfig.scratchphysicalbase + 0x1000);
+
+/* Print some debugging info */
+
+/*
+       printf("page tables look like this ...\n");
+       printf("V0x00000000 - %08x\n", ReadWord(l1pagetable + 0x0000));
+       printf("V0x03500000 - %08x\n", ReadWord(l1pagetable + 0x00d4));
+       printf("V0x00200000 - %08x\n", ReadWord(l1pagetable + 0x0080));
+       printf("V0xf4000000 - %08x\n", ReadWord(l1pagetable + 0x3d00));
+       printf("V0xf0000000 - %08x\n", ReadWord(l1pagetable + 0x3c00));
+       printf("page dir = P%08x\n", bootconfig.scratchphysicalbase + 0x4000);
+       printf("l1= V%08x\n", l1pagetable);
+*/
+
+/*
+ * Pheww right we are ready to switch page tables !!!
+ * The L1 table is at bootconfig.scratchphysicalbase + 0x4000
+ */
+/* Switch tables */
+
+       setttb(bootconfig.scratchphysicalbase + 0x4000);
+
+/* Since we have mapped the VRAM up into kernel space we must now update the
+ * the bootconfig and display structures by hand.
+ */
+
+       bootconfig.display_start = VMEM_VBASE;
+       physcon_display_base(VMEM_VBASE);
+
+       printf("done.\n");
+
+/*
+ * Ok we have finished the primary boot strap. All this has done is to
+ * allow us to access all the physical memory from known virtual
+ * location. We also now know that all the used pages are at the top
+ * of the physical memory and where they are in the virtual memory map.
+ *
+ * This should be the stage we are at at the end of the bootstrap when
+ * we have a two stage booter.
+ *
+ * The secondary bootstrap has the responcibility to sort locating the
+ * kernel to the correct address and for creating the kernel page tables.
+ * It must also set up various memory pointers that are used by pmap etc.  
+ */
+
+       process_kernel_args();
+
+       printf("initarm: Secondary bootstrap ... ");
+
+/* Zero down the memory we mapped in for the secondary bootstrap */
+
+       bzero(0x00000000, 0x200000);
+
+/* Set up the variables that define the availablilty of physcial memory */
+
+       physical_start = bootconfig.dram[0].address;
+       physical_freestart = physical_start;
+       physical_end = bootconfig.dram[bootconfig.dramblocks - 1].address
+           + bootconfig.dram[bootconfig.dramblocks - 1].pages * NBPG;
+       physical_freeend = physical_end;
+       physical_memoryblock = 0;
+       free_pages = bootconfig.drampages;
+    
+       for (loop = 0; loop < bootconfig.dramblocks; ++loop)
+               physmem += bootconfig.dram[loop].pages;
+    
+/*
+ * Reserve some pages at the top of the memory for later use
+ *
+ * This area is not currently used but could be used for the allocation
+ * of L1 page tables for each process.
+ * The size of this memory would be determined by the maximum number of
+ * processes.
+ *
+ * For the moment we just reserve a few pages just to make sure the
+ * system copes.
+ */
+
+       physical_freeend -= videodram_size;
+       free_pages -= (videodram_size / NBPG);
+       videodram_start = physical_freeend;
+
+       physical_freeend -= PD_SIZE * max_processes;
+       free_pages -= 4 * max_processes;
+       pagetables_start = physical_freeend;
+
+/* Right We have the bottom meg of memory mapped to 0x00000000
+ * so was can get at it. The kernel will ocupy the start of it.
+ * After the kernel/args we allocate some the the fixed page tables
+ * we need to get the system going.
+ * We allocate one page directory and 8 page tables and store the
+ * physical addresses in the kernel_pt_table array.
+ * Must remember that neither the page L1 or L2 page tables are the same
+ * size as a page !
+ *
+ * Ok the next bit of physical allocate may look complex but it is
+ * simple really. I have done it like this so that no memory gets wasted
+ * during the allocate of various pages and tables that are all different
+ * sizes.
+ * The start address will be page aligned.
+ * We allocate the kernel page directory on the first free 16KB boundry
+ * we find.
+ * We allocate the kernel page tables on the first 1KB boundry we find.
+ * We allocate 9 PT's. This means that in the process we
+ * KNOW that we will encounter at least 1 16KB boundry.
+ *
+ * Eventually if the top end of the memory gets used for process L1 page
+ * tables the kernel L1 page table may be moved up there.
+ */
+
+/*
+ * The Simtec Hydra board needs a 2MB aligned page for bootstrapping.
+ * Simplest thing is to nick the bottom page of physical memory.
+ */
+
+#if NHYDRABUS > 0
+       hydrascratch.physical = physical_start;
+       physical_start += NBPG;
+       --free_pages;
+#endif
+
+       physical = physical_start + kerneldatasize;
+/*     printf("physical=%08x next_phys=%08x\n", physical, pmap_next_phys_page(physical - NBPG));*/
+       loop1 = 1;
+       kernel_pt_table[0] = 0;
+       for (loop = 0; loop < 15; ++loop) {
+               if ((physical & (PD_SIZE-1)) == 0 && kernel_pt_table[0] == 0) {
+                       kernel_pt_table[KERNEL_PT_PAGEDIR] = physical;
+                       bzero((char *)physical - physical_start, PD_SIZE);
+                       physical += PD_SIZE; 
+               } else {
+                       kernel_pt_table[loop1] = physical;
+                       bzero((char *)physical - physical_start, PT_SIZE);
+                       physical += PT_SIZE;
+                       ++loop1;
+               }
+       }
+
+/* A bit of debugging info */
+
+/*
+       for (loop=0; loop < 10; ++loop)
+               printf("%d - P%08x\n", loop, kernel_pt_table[loop]);
+*/
+
+/* This should never be able to happen but better confirm that. */
+
+       if ((kernel_pt_table[0] & (PD_SIZE-1)) != 0)
+               panic("initarm: Failed to align the kernel page directory\n");
+
+/* Update the address of the first free page of physical memory */
+
+       physical_freestart = physical;
+/*     printf("physical_fs=%08x next_phys=%08x\n", (u_int)physical_freestart, (u_int)pmap_next_phys_page(physical_freestart - NBPG));*/
+       free_pages -= (physical - physical_start) / NBPG;
+
+/* Allocate a page for the system page mapped to 0x00000000 */
+
+       systempage.physical = physical_freestart;
+       physical_freestart += NBPG;
+/*     printf("(0)physical_fs=%08x next_phys=%08x\n", (u_int)physical_freestart, (u_int)pmap_next_phys_page(physical_freestart - NBPG));*/
+       --free_pages;
+       bzero((char *)systempage.physical - physical_start, NBPG);
+
+/* Allocate another 3 pages for the stacks in different CPU modes. */
+
+       irqstack.physical = physical_freestart;
+       physical_freestart += NBPG;
+       abtstack.physical = physical_freestart;
+       physical_freestart += NBPG;
+       undstack.physical = physical_freestart;
+       physical_freestart += NBPG;
+       bzero((char *)irqstack.physical - physical_start, 3*NBPG);
+       free_pages -= 3;
+       irqstack.virtual = KERNEL_BASE + irqstack.physical-physical_start;
+       abtstack.virtual = KERNEL_BASE + abtstack.physical-physical_start;
+       undstack.virtual = KERNEL_BASE + undstack.physical-physical_start;
+/*     printf("(1)physical_fs=%08x next_phys=%08x\n", (u_int)physical_freestart, (u_int)pmap_next_phys_page(physical_freestart - NBPG));*/
+
+       kernelstack.physical = physical_freestart;
+       physical_freestart += UPAGES * NBPG;
+       bzero((char *)kernelstack.physical - physical_start, UPAGES * NBPG);
+       free_pages -= UPAGES;
+
+/*     printf("(2)physical_fs=%08x next_phys=%08x\n", (u_int)physical_freestart, (u_int)pmap_next_phys_page(physical_freestart - NBPG));*/
+
+
+       kernelstack.virtual = KERNEL_BASE + kernelstack.physical
+           - physical_start;
+
+       msgbufphys = physical_freestart;
+       physical_freestart += round_page(sizeof(struct msgbuf));
+       free_pages -= round_page(sizeof(struct msgbuf)) / NBPG;
+
+/*     printf("physical_fs=%08x next_phys=%08x\n", (u_int)physical_freestart, (u_int)pmap_next_phys_page(physical_freestart - NBPG));*/
+
+/* Ok we have allocated physical pages for the primary kernel page tables */
+
+/* Now we fill in the L2 pagetable for the kernel code/data */
+
+       l2pagetable = kernel_pt_table[KERNEL_PT_KERNEL] - physical_start;
+
+       if (N_GETMAGIC(kernexec[0]) == ZMAGIC) {
+/*             printf("[ktext read-only] ");
+               printf("[%08x %08x %08x] \n", (u_int)kerneldatasize, (u_int)kernexec->a_text,
+                   (u_int)(kernexec->a_text+kernexec->a_data+kernexec->a_bss));*/
+/*             printf("physical start=%08x physical freestart=%08x hydra phys=%08x\n", physical_start, physical_freestart, hydrascratch.physical);*/
+               for (logical = 0; logical < 0x00/*kernexec->a_text*/;
+                   logical += NBPG)
+                       map_entry_ro(l2pagetable, logical, physical_start
+                           + logical);
+               for (; logical < kerneldatasize; logical += NBPG)
+                       map_entry(l2pagetable, logical, physical_start
+                           + logical);
+       } else
+               for (logical = 0; logical < kerneldatasize; logical += NBPG)
+                       map_entry(l2pagetable, logical, physical_start
+                           + logical);
+
+/* Map the stack pages */
+
+       map_entry(l2pagetable, irqstack.physical-physical_start,
+           irqstack.physical);
+       map_entry(l2pagetable, abtstack.physical-physical_start,
+           abtstack.physical); 
+       map_entry(l2pagetable, undstack.physical-physical_start,
+           undstack.physical); 
+       map_entry(l2pagetable, kernelstack.physical - physical_start,
+           kernelstack.physical); 
+       map_entry(l2pagetable, kernelstack.physical + NBPG - physical_start,
+           kernelstack.physical + NBPG); 
+
+       l2pagetable = kernel_pt_table[KERNEL_PT_KSTACK] - physical_start;
+
+       map_entry(l2pagetable, 0x003fe000, kernelstack.physical);
+       map_entry(l2pagetable, 0x003ff000, kernelstack.physical + NBPG);
+
+/* Now we fill in the L2 pagetable for the VRAM */
+
+/*
+ * Current architectures mean that the VRAM is always in 1 continuous
+ * bank.
+ * This means that we can just map the 2 meg that the VRAM would occupy.
+ * In theory we don't need a page table for VRAM, we could section map
+ * it but we would need the page tables if DRAM was in use.
+ */
+
+       l2pagetable = kernel_pt_table[KERNEL_PT_VMEM] - physical_start;
+
+       for (logical = 0; logical < 0x200000; logical += NBPG) {
+               map_entry(l2pagetable, logical, bootconfig.vram[0].address
+                   + logical);
+               map_entry(l2pagetable, logical + 0x200000,
+                   bootconfig.vram[0].address + logical);
+       }
+
+/* Map entries in the page table used to map PDE's */
+
+       l2pagetable = kernel_pt_table[KERNEL_PT_PDE] - physical_start;
+       map_entry(l2pagetable, 0x0000000,
+           kernel_pt_table[KERNEL_PT_PAGEDIR]);
+       map_entry(l2pagetable, 0x0001000,
+           kernel_pt_table[KERNEL_PT_PAGEDIR] + 0x1000);
+       map_entry(l2pagetable, 0x0002000,
+           kernel_pt_table[KERNEL_PT_PAGEDIR] + 0x2000);
+       map_entry(l2pagetable, 0x0003000,
+           kernel_pt_table[KERNEL_PT_PAGEDIR] + 0x3000);
+
+/*
+ * Map entries in the page table used to map PTE's
+ * Basically every kernel page table gets mapped here
+ */
+
+       l2pagetable = kernel_pt_table[KERNEL_PT_PTE] - physical_start;
+       map_entry(l2pagetable, (KERNEL_BASE >> (PGSHIFT-2)),
+           kernel_pt_table[KERNEL_PT_KERNEL]);
+       map_entry(l2pagetable, (PAGE_DIRS_BASE >> (PGSHIFT-2)),
+           kernel_pt_table[KERNEL_PT_PDE]);
+       map_entry(l2pagetable, (PROCESS_PAGE_TBLS_BASE >> (PGSHIFT-2)),
+           kernel_pt_table[KERNEL_PT_PTE]);
+       map_entry(l2pagetable, (VMEM_VBASE >> (PGSHIFT-2)),
+           kernel_pt_table[KERNEL_PT_VMEM]);
+       map_entry(l2pagetable, (0x00000000 >> (PGSHIFT-2)),
+           kernel_pt_table[KERNEL_PT_SYS]);
+       map_entry(l2pagetable, ((KERNEL_VM_BASE + 0x00000000) >> (PGSHIFT-2)),
+           kernel_pt_table[KERNEL_PT_VMDATA0]);
+       map_entry(l2pagetable, ((KERNEL_VM_BASE + 0x00400000) >> (PGSHIFT-2)),
+           kernel_pt_table[KERNEL_PT_VMDATA1]);
+       map_entry(l2pagetable, ((KERNEL_VM_BASE + 0x00800000) >> (PGSHIFT-2)),
+           kernel_pt_table[KERNEL_PT_VMDATA2]);
+       map_entry(l2pagetable, ((KERNEL_VM_BASE + 0x00c00000) >> (PGSHIFT-2)),
+           kernel_pt_table[KERNEL_PT_VMDATA3]);
+       map_entry(l2pagetable, ((KERNEL_VM_BASE + 0x01000000) >> (PGSHIFT-2)),
+           kernel_pt_table[KERNEL_PT_VMDATA4]);
+       map_entry(l2pagetable, ((KERNEL_VM_BASE + 0x01400000) >> (PGSHIFT-2)),
+           kernel_pt_table[KERNEL_PT_VMDATA5]);
+       map_entry(l2pagetable, ((KERNEL_VM_BASE + 0x01800000) >> (PGSHIFT-2)),
+           kernel_pt_table[KERNEL_PT_VMDATA6]);
+       map_entry(l2pagetable, ((KERNEL_VM_BASE + 0x01c00000) >> (PGSHIFT-2)),
+           kernel_pt_table[KERNEL_PT_VMDATA7]);
+       map_entry(l2pagetable, ((0xef800000) >> (PGSHIFT-2)),
+           kernel_pt_table[KERNEL_PT_KSTACK]);
+
+       map_entry(l2pagetable, (0xf5000000 >> (PGSHIFT-2)),
+           kernel_pt_table[KERNEL_PT_PAGEDIR] + 0x0000);
+       map_entry(l2pagetable, (0xf5400000 >> (PGSHIFT-2)),
+           kernel_pt_table[KERNEL_PT_PAGEDIR] + 0x1000);
+       map_entry(l2pagetable, (0xf5800000 >> (PGSHIFT-2)),
+           kernel_pt_table[KERNEL_PT_PAGEDIR] + 0x2000);
+       map_entry(l2pagetable, (0xf5c00000 >> (PGSHIFT-2)),
+           kernel_pt_table[KERNEL_PT_PAGEDIR] + 0x3000);
+
+/*
+ * Map the system page in the kernel page table for the bottom 1Meg
+ * of the virtual memory map.
+ */
+
+       l2pagetable = kernel_pt_table[KERNEL_PT_SYS] - physical_start;
+       map_entry(l2pagetable, 0x0000000, systempage.physical);
+
+/* Now we construct the L1 pagetable */
+
+       l1pagetable = kernel_pt_table[KERNEL_PT_PAGEDIR] - physical_start;
+
+/* Map the VIDC20, IOMD, COMBO and podules */
+
+/* Map the VIDC20 */
+
+       map_section(l1pagetable, VIDC_BASE, VIDC_HW_BASE);
+
+/* Map the IOMD (and SLOW and MEDIUM simple podules) */
+
+       map_section(l1pagetable, IOMD_BASE, IOMD_HW_BASE);
+
+/* Map the COMBO (and module space) */
+
+       map_section(l1pagetable, IO_BASE, IO_HW_BASE);
+
+/* Map the L2 pages tables in the L1 page table */
+
+       map_pagetable(l1pagetable, 0x00000000,
+           kernel_pt_table[KERNEL_PT_SYS]);
+       map_pagetable(l1pagetable, 0xef800000,
+           kernel_pt_table[KERNEL_PT_KSTACK]);
+       map_pagetable(l1pagetable, KERNEL_BASE,
+           kernel_pt_table[KERNEL_PT_KERNEL]);
+       map_pagetable(l1pagetable, KERNEL_VM_BASE + 0x00000000,
+           kernel_pt_table[KERNEL_PT_VMDATA0]);
+       map_pagetable(l1pagetable, KERNEL_VM_BASE + 0x00400000,
+           kernel_pt_table[KERNEL_PT_VMDATA1]);
+       map_pagetable(l1pagetable, KERNEL_VM_BASE + 0x00800000,
+           kernel_pt_table[KERNEL_PT_VMDATA2]);
+       map_pagetable(l1pagetable, KERNEL_VM_BASE + 0x00c00000,
+           kernel_pt_table[KERNEL_PT_VMDATA3]);
+       map_pagetable(l1pagetable, KERNEL_VM_BASE + 0x01000000,
+           kernel_pt_table[KERNEL_PT_VMDATA4]);
+       map_pagetable(l1pagetable, KERNEL_VM_BASE + 0x01400000,
+           kernel_pt_table[KERNEL_PT_VMDATA5]);
+       map_pagetable(l1pagetable, KERNEL_VM_BASE + 0x01800000,
+           kernel_pt_table[KERNEL_PT_VMDATA6]);
+       map_pagetable(l1pagetable, KERNEL_VM_BASE + 0x01c00000,
+           kernel_pt_table[KERNEL_PT_VMDATA7]);
+       map_pagetable(l1pagetable, PAGE_DIRS_BASE,
+           kernel_pt_table[KERNEL_PT_PDE]);
+       map_pagetable(l1pagetable, PROCESS_PAGE_TBLS_BASE,
+           kernel_pt_table[KERNEL_PT_PTE]);
+       map_pagetable(l1pagetable, VMEM_VBASE,
+           kernel_pt_table[KERNEL_PT_VMEM]);
+
+/* Bit more debugging info */
+
+/*
+       printf("page tables look like this ...\n");
+       printf("V0x00000000 - %08x\n", ReadWord(l1pagetable + 0x0000));
+       printf("V0x03200000 - %08x\n", ReadWord(l1pagetable + 0x00c8));
+       printf("V0x03500000 - %08x\n", ReadWord(l1pagetable + 0x00d4));
+       printf("V0xf0000000 - %08x\n", ReadWord(l1pagetable + 0x3c00));
+       printf("V0xf1000000 - %08x\n", ReadWord(l1pagetable + 0x3c40));
+       printf("V0xf2000000 - %08x\n", ReadWord(l1pagetable + 0x3c80));
+       printf("V0xf3000000 - %08x\n", ReadWord(l1pagetable + 0x3cc0));
+       printf("V0xf3300000 - %08x\n", ReadWord(l1pagetable + 0x3ccc));
+       printf("V0xf4000000 - %08x\n", ReadWord(l1pagetable + 0x3d00));
+       printf("V0xf6000000 - %08x\n", ReadWord(l1pagetable + 0x3d80));
+*/
+/*     printf("V0xefc00000 - %08x\n", ReadWord(l1pagetable + 0x3bf8));
+       printf("V0xef800000 - %08x\n", ReadWord(l1pagetable + 0x3bfc));*/
+
+/*
+ * Now we have the real page tables in place so we can switch to them.
+ * Once this is done we will be running with the REAL kernel page tables.
+ */
+
+/*
+ * The last thing we must do is copy the kernel down to the new memory.
+ * This copies all our kernel data structures and variables as well
+ * which is why it is left to the last moment.
+ */
+
+       printf("mapping ... ");
+
+       bcopy((char *)KERNEL_BASE, (char *)0x00000000, kerneldatasize);
+
+/* Switch tables */
+
+       setttb(kernel_pt_table[KERNEL_PT_PAGEDIR]);
+
+       printf("done.\n");
+
+/* Right set up the vectors at the bottom of page 0 */
+
+       bcopy(page0, (char *)0x00000000, page0_end - page0);
+
+/*
+ * Pages were allocated during the secondary bootstrap for the
+ * stacks for different CPU modes.
+ * We must now set the r13 registers in the different CPU modes to
+ * point to these stacks.
+ * Since the ARM stacks use STMFD etc. we must set r13 to the top end
+ * of the stack memory.
+ */
+
+#ifdef DIAGNOSTIC
+       printf("IRQ stack V%08x P%08x\n", (u_int) irqstack.virtual,
+           (u_int) irqstack.physical);
+       printf("ABT stack V%08x P%08x\n", (u_int) abtstack.virtual,
+           (u_int) abtstack.physical);
+       printf("UND stack V%08x P%08x\n", (u_int) undstack.virtual,
+           (u_int) undstack.physical);
+#endif
+
+       printf("init subsystems: stacks ");
+
+       set_stackptr(PSR_IRQ32_MODE, irqstack.virtual + NBPG);
+       set_stackptr(PSR_ABT32_MODE, abtstack.virtual + NBPG);
+       set_stackptr(PSR_UND32_MODE, undstack.virtual + NBPG);
+
+       if (pmap_debug_level >= 0)
+               printf("kstack V%08x P%08x\n", (int) kernelstack.virtual,
+                   (int) kernelstack.physical);
+
+/*
+ * Well we should set a data abort handler.
+ * Once things get going this will change as we will need a proper handler.
+ * Until then we will use a handler that just panics but tells us
+ * why.
+ * Initialisation of the vectors will just panic on a data abort.
+ * This just fills in a slighly better one.
+ */
+
+       printf("vectors ");
+       data_abort_handler_address = (u_int)data_abort_handler;
+       prefetch_abort_handler_address = (u_int)prefetch_abort_handler;
+       undefined_handler_address = (u_int)undefinedinstruction_bounce;
+
+/* Diagnostic stuff. while writing the boot code */
+
+/*
+       for (loop = 0x0; loop < 0x1000; ++loop) {
+               if (ReadWord(PAGE_DIRS_BASE + loop * 4) != 0)
+                       printf("Pagetable for V%08x = %08x\n", loop << 20,
+                           ReadWord(0xf2000000 + loop * 4));
+       }
+
+*/
+/* Diagnostic stuff. while writing the boot code */
+
+/*
+       for (loop = 0x0; loop < 0x400; ++loop) {
+               if (ReadWord(kernel_pt_table[KERNEL_PT_PTE] + loop * 4) != 0)
+                       printf("Pagetable for V%08x P%08x = %08x\n",
+                           loop << 22, kernel_pt_table[KERNEL_PT_PTE]+loop*4,
+                           ReadWord(kernel_pt_table[KERNEL_PT_PTE]+loop * 4));
+       }
+*/
+
+/* At last !
+ * We now have the kernel in physical memory from the bottom upwards.
+ * Kernel page tables are physically above this.
+ * The kernel is mapped to 0xf0000000
+ * The kernel data PTs will handle the mapping of 0xf1000000-0xf1ffffff
+ * 2Meg of VRAM is mapped to 0xf4000000
+ * The kernel page directory is mapped to 0xf3000000
+ * The page tables are mapped to 0xefc00000
+ * The IOMD is mapped to 0xf6000000
+ * The VIDC is mapped to 0xf6100000
+ */
+
+/* Initialise the undefined instruction handlers */
+
+       printf("undefined ");
+       undefined_init();
+
+/* Boot strap pmap telling it where the kernel page table is */
+
+       printf("pmap ");
+       pmap_bootstrap(PAGE_DIRS_BASE);
+
+/* Setup the IRQ system */
+
+       printf("irq ");
+       irq_init();
+       printf("done.\n");
+
+#ifdef DDB
+       printf("ddb: ");
+       db_machine_init();
+       ddb_init();
+
+       if (boothowto & RB_KDB)
+               Debugger();
+#endif
+
+/* We return the new stack pointer address */
+       return(kernelstack.virtual + USPACE_SVC_STACK_TOP);
+}
+
+
+/*
+ * void cpu_startup(void)
+ *
+ * Machine dependant startup code. 
+ *
+ */
+
+void
+cpu_startup()
+{
+       int loop;
+       vm_offset_t minaddr;
+       vm_offset_t maxaddr;
+       caddr_t sysbase;
+       caddr_t size;
+       vm_size_t bufsize;
+       int base, residual;
+
+/* Set the cpu control register */
+
+       cpu_ctrl = CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_32BP_ENABLE
+                  | CPU_CONTROL_32BD_ENABLE | CPU_CONTROL_SYST_ENABLE;
+                                        
+       if (cpu_cache & 1)
+               cpu_ctrl |= CPU_CONTROL_IDC_ENABLE;
+       if (cpu_cache & 2)
+               cpu_ctrl |= CPU_CONTROL_WBUF_ENABLE;
+
+       if (!(cpu_cache & 4))
+               cpu_ctrl |= CPU_CONTROL_CPCLK;
+
+#ifdef CPU_LATE_ABORT
+       cpu_ctrl |= CPU_CONTROL_LABT_ENABLE;
+#endif
+
+/* Clear out the cache */
+
+       idcflush();
+    
+       cpu_control(cpu_ctrl);
+
+/* All domains MUST be clients, permissions are VERY important */
+
+       cpu_domains(DOMAIN_CLIENT);
+
+/* Lock down zero page */
+
+       zero_page_readonly();
+
+/*
+ * Initialize error message buffer (at end of core).
+ */
+
+/* msgbufphys was setup during the secondary boot strap */
+
+       for (loop = 0; loop < btoc(sizeof(struct msgbuf)); ++loop)
+               pmap_enter(pmap_kernel(),
+                   (vm_offset_t)((caddr_t)msgbufp + loop * NBPG),
+                   msgbufphys + loop * NBPG, VM_PROT_ALL, TRUE);
+
+       msgbufmapped = 1;
+
+/*
+ * Identify ourselves for the msgbuf (everything printed earlier will
+ * not be buffered).
+ */
+       printf(version);
+
+       printf("screen: %d x %d x %d\n", bootconfig.width + 1, bootconfig.height + 1, bootconfig.framerate);
+
+       if (cmos_read(RTC_ADDR_REBOOTCNT) > 0)
+               printf("Warning: REBOOTCNT = %d\n", cmos_read(RTC_ADDR_REBOOTCNT));
+
+       printf("real mem = %d (%d pages)\n", arm_page_to_byte(physmem), physmem);
+
+       /*
+        * Find out how much space we need, allocate it,
+        * and then give everything true virtual addresses.
+        */
+                                    
+       size = allocsys((caddr_t)0);
+       sysbase = (caddr_t)kmem_alloc(kernel_map, round_page(size));
+       if (sysbase == 0)
+               panic("cpu_startup: no room for system tables %d bytes required", size);
+       if ((caddr_t)((allocsys(sysbase) - sysbase)) != size)
+               panic("cpu_startup: system table size inconsistency");
+
+/*
+ * Now allocate buffers proper.  They are different than the above
+ * in that they usually occupy more virtual memory than physical.
+ */
+
+       bufsize = MAXBSIZE * nbuf;
+       buffer_map = kmem_suballoc(kernel_map, (vm_offset_t *)&buffers,
+                                  &maxaddr, bufsize, TRUE);
+       minaddr = (vm_offset_t)buffers;
+       if (vm_map_find(buffer_map, vm_object_allocate(bufsize),
+           (vm_offset_t)0, &minaddr, bufsize, FALSE) != KERN_SUCCESS)
+               panic("startup: cannot allocate buffers");
+
+       if ((bufpages / nbuf) >= btoc(MAXBSIZE)) {
+/* don't want to alloc more physical mem than needed */
+               bufpages = btoc(MAXBSIZE) * nbuf;
+       }
+
+       base = bufpages / nbuf;
+       residual = bufpages % nbuf;
+       for (loop = 0; loop < nbuf; ++loop) {
+               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 + loop * MAXBSIZE;
+               curbufsize = CLBYTES * (loop < 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);
+
+/*
+    printf("mb_buf: map=%08x maxaddr = %08x mbutl = %08x\n", mb_map, maxaddr, mbutl);
+*/
+
+/*
+ * Initialise callouts
+ */
+
+       callfree = callout;
+
+       for (loop = 1; loop < ncallout; ++loop)
+               callout[loop - 1].c_next = &callout[loop];
+
+       printf("avail mem = %d (%d pages)\n", (int)ptoa(cnt.v_free_count),
+           (int)ptoa(cnt.v_free_count) / NBPG);
+       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();
+
+       proc0paddr = (struct user *)kernelstack.virtual;
+       proc0.p_addr = proc0paddr;
+
+       curpcb = &proc0.p_addr->u_pcb;
+       curpcb->pcb_flags = 0;
+       curpcb->pcb_und_sp = (u_int)proc0.p_addr + USPACE_UNDEF_STACK_TOP;
+       curpcb->pcb_sp = (u_int)proc0.p_addr + USPACE_SVC_STACK_TOP;
+       curpcb->pcb_pagedir = (pd_entry_t *)pmap_extract(kernel_pmap,
+           (vm_offset_t)(kernel_pmap)->pm_pdir);
+           
+       proc0.p_md.md_regs = (struct trapframe *)curpcb->pcb_sp - 1;
+#if 0
+/* Hack proc0 */
+                                 
+       proc0paddr = (struct user *)kernelstack.virtual;
+       proc0.p_addr = proc0paddr;
+
+       curpcb = &proc0.p_addr->u_pcb;
+       proc0.p_addr->u_pcb.pcb_flags = 0;
+       proc0.p_addr->u_pcb.pcb_und_sp = (u_int)proc0.p_addr + USPACE_UNDEF_STACK_TOP;
+
+       proc0.p_addr->u_pcb.pcb_pagedir = (pd_entry_t *)pmap_extract(kernel_pmap,
+           (vm_offset_t)(kernel_pmap)->pm_pdir);
+#endif
+/*
+ * Install an IRQ handler on the VSYNC interrupt to reboot if the
+ * middle mouse button is pressed.
+ */
+
+       setup_cursor();
+
+/* Allocate memory for the kmodule area if required */
+
+       if (kmodule_size) {
+               kmodule_size = round_page(kmodule_size);
+               kmodule_base = (u_int)kmem_alloc(kernel_map, kmodule_size);
+               if (kmodule_base)
+                       printf("KMODULE SPACE = %08x\n", kmodule_base);
+               else
+                       printf("\x1b[31mNO KMODULE SPACE\n\x1b[0m");
+       }
+
+/*
+ * Configure the hardware
+ */
+       configure();
+
+/* Set the root, swap and dump devices from the boot args */
+
+       set_boot_devs();
+
+       dump_spl_masks();
+
+       cold = 0;       /* We are warm now ... */
+}
+
+
+/*
+ * Allocate space for system data structures.  We are given
+ * a starting virtual address and we return a final virtual
+ * address; along the way we set each data structure pointer.
+ *
+ * We call allocsys() with 0 to find out how much space we want,
+ * allocate that much and fill it with zeroes, and then call
+ * allocsys() again with the correct base virtual address.
+ */
+
+caddr_t
+allocsys(v)
+       register caddr_t v;
+{
+
+#define valloc(name, type, num) \
+    (caddr_t)(name) = (type *)v; \
+    v = (caddr_t)((name) + (num));
+
+    valloc(callout, struct callout, ncallout);
+    valloc(swapmap, struct map, nswapmap = maxproc * 2);
+
+#ifdef SYSVSHM
+       valloc(shmsegs, struct shmid_ds, shminfo.shmmni);
+#endif
+#ifdef SYSVSEM
+       valloc(sema, struct semid_ds, seminfo.semmni);
+       valloc(sem, struct sem, seminfo.semmns);
+       /* This is pretty disgusting! */
+       valloc(semu, int, (seminfo.semmnu * seminfo.semusz) / sizeof(int));
+#endif
+#ifdef SYSVMSG
+       valloc(msgpool, char, msginfo.msgmax);
+       valloc(msgmaps, struct msgmap, msginfo.msgseg);
+       valloc(msghdrs, struct msg, msginfo.msgtql);
+       valloc(msqids, struct msqid_ds, msginfo.msgmni);
+#endif
+                                                                         
+/*
+ * Determine how many buffers to allocate.  We use 10% of the
+ * first 2MB of memory, and 5% of the rest, with a minimum of 16
+ * buffers.  We allocate 1/2 as many swap buffer headers as file
+ * i/o buffers.
+ */
+
+       if (bufpages == 0)
+               if (physmem < arm_byte_to_page(2 * 1024 * 1024))
+                       bufpages = physmem / (10 * CLSIZE);
+               else
+                       bufpages = (arm_byte_to_page(2 * 1024 * 1024)
+                                + physmem) / (20 * CLSIZE);
+
+#ifdef DIAGNOSTIC
+       if (bufpages == 0)
+               panic("bufpages = 0\n");
+#endif
+
+       if (nbuf == 0) {
+               nbuf = bufpages;
+               if (nbuf < 16)
+                       nbuf = 16;
+       }
+
+       if (nswbuf == 0) {
+               nswbuf = (nbuf / 2) & ~1;       /* force even */
+               if (nswbuf > 256)
+                       nswbuf = 256;           /* sanity */
+       }
+
+       valloc(swbuf, struct buf, nswbuf);
+       valloc(buf, struct buf, nbuf);
+
+       return(v);
+}
+
+
+/* A few functions that are used to help construct the page tables
+ * during the bootstrap process.
+ */
+
+void
+map_section(pagetable, va, pa)
+       vm_offset_t pagetable;
+       vm_offset_t va;
+       vm_offset_t pa; 
+{
+       if ((va & 0xfffff) != 0)
+               panic("initarm: Cannot allocate 1MB section on non 1MB boundry\n");
+
+       ((u_int *)pagetable)[(va >> 20)] = L1_SEC((pa & PD_MASK));
+}
+
+
+void
+map_pagetable(pagetable, va, pa)
+       vm_offset_t pagetable;
+       vm_offset_t va;
+       vm_offset_t pa;
+{
+       if ((pa & 0xc00) != 0)
+               panic("pagetables should be group allocated on pageboundry");
+       ((u_int *)pagetable)[(va >> 20) + 0] = L1_PTE((pa & PG_FRAME) + 0x000);
+       ((u_int *)pagetable)[(va >> 20) + 1] = L1_PTE((pa & PG_FRAME) + 0x400);
+       ((u_int *)pagetable)[(va >> 20) + 2] = L1_PTE((pa & PG_FRAME) + 0x800);
+       ((u_int *)pagetable)[(va >> 20) + 3] = L1_PTE((pa & PG_FRAME) + 0xc00);
+}
+
+
+void
+map_entry(pagetable, va, pa)
+       vm_offset_t pagetable;
+       vm_offset_t va;
+       vm_offset_t pa;
+{
+       WriteWord(pagetable + ((va >> 10) & 0x00000ffc),
+           L2_PTE((pa & PG_FRAME), AP_KRW));
+}
+
+
+void
+map_entry_nc(pagetable, va, pa)
+       vm_offset_t pagetable;
+       vm_offset_t va;
+       vm_offset_t pa;
+{
+       WriteWord(pagetable + ((va >> 10) & 0x00000ffc),
+           L2_PTE_NC((pa & PG_FRAME), AP_KRW));
+}
+
+
+void
+map_entry_ro(pagetable, va, pa)
+       vm_offset_t pagetable;
+       vm_offset_t va;
+       vm_offset_t pa;
+{
+       WriteWord(pagetable + ((va >> 10) & 0x00000ffc),
+           L2_PTE((pa & PG_FRAME), AP_KR));
+}
+
+
+int wdresethack = 1;
+
+void
+process_kernel_args()
+{
+       char *ptr;
+       char *args;
+
+/* Ok now we will check the arguments for interesting parameters. */
+
+       args = (char *)bootconfig.argvirtualbase;
+       max_processes = 64;
+       boothowto = 0;
+       kmodule_size = 0;
+       cpu_cache = 0x03;
+       debug_flags = 0;
+       videodram_size = 0;
+    
+/* Skip the first parameter (the boot loader filename) */
+
+       while (*args != ' ' && *args != 0)
+               ++args;
+
+       while (*args == ' ')
+               ++args;
+
+/* Skip the kernel image filename */
+
+       while (*args != ' ' && *args != 0)
+               ++args;
+
+       while (*args == ' ')
+               ++args;
+
+       boot_args = NULL;
+
+       if (*args != 0) {
+               boot_args = args;
+
+               if (strstr(args, "nocache"))
+                       cpu_cache &= ~1;
+
+               if (strstr(args, "nowritebuf"))
+                       cpu_cache &= ~2;
+
+               if (strstr(args, "fpaclk2"))
+                       cpu_cache |= 4;
+
+               ptr = strstr(args, "maxproc=");
+               if (ptr) {
+                       max_processes = (int)strtoul(ptr + 8, NULL, 10);
+                       if (max_processes < 16)
+                               max_processes = 16;
+                       if (max_processes > 256)
+                               max_processes = 256;
+                       printf("Maximum \"in memory\" processes = %d\n",
+                           max_processes);
+               }
+               ptr = strstr(args, "ramdisc=");
+               if (ptr) {
+                       ramdisc_size = (u_int)strtoul(ptr + 8, NULL, 10);
+                       ramdisc_size *= 1024;
+                       if (ramdisc_size < 32*1024)
+                               ramdisc_size = 32*1024;
+                       if (ramdisc_size > 2048*1024)
+                               ramdisc_size = 2048*1024;
+               }
+               ptr = strstr(args, "kmodule=");
+               if (ptr) {
+                       kmodule_size = (u_int)strtoul(ptr + 8, NULL, 10);
+                       kmodule_size *= 1024;
+                       if (kmodule_size < 4*1024)
+                               kmodule_size = 4*1024;
+                       if (kmodule_size > 256*1024)
+                               kmodule_size = 256*1024;
+               }
+               ptr = strstr(args, "videodram=");
+               if (ptr) {
+                       videodram_size = (u_int)strtoul(ptr + 10, NULL, 10);
+                       /* Round to 4K page */
+                       videodram_size *= 1024;
+                       videodram_size = round_page(videodram_size);
+                       if (videodram_size > 1024*1024)
+                               videodram_size = 1024*1024;
+                       printf("VIDEO DRAM = %d\n", videodram_size);
+               }
+               if (strstr(args, "single"))
+                       boothowto |= RB_SINGLE;
+               if (strstr(args, "kdb"))
+                       boothowto |= RB_KDB;
+               ptr = strstr(args, "pmapdebug=");
+               if (ptr) {
+                       pmap_debug_level = (int)strtoul(ptr + 10, NULL, 10);
+                       pmap_debug(pmap_debug_level);
+                       debug_flags |= 0x01;
+               }
+               if (strstr(args, "termdebug"))
+                       debug_flags |= 0x02;
+               if (strstr(args, "nowdreset"))
+                       wdresethack = 0;
+               if (strstr(args, "notermcls"))
+                       debug_flags |= 0x04;
+       }
+}
+
+/* This should happen in the console code - This really must move soon */
+
+int
+setup_cursor()
+{
+
+/* The cursor currently gets set up here. slightly wasteful on memory */
+
+/*
+ * This should be done in the vidc code as that is responcible for the cursor.
+ * This will probably happen when the vidc code is separated from the console
+ * (currently work in progress)
+ */
+
+       cursor_data = (u_int *)kmem_alloc(kernel_map, NBPG);
+/*     printf("Cursor data page = V%08x P%08x\n", cursor_data, pmap_extract(kernel_pmap, (vm_offset_t)cursor_data));*/
+       WriteWord(IOMD_CURSINIT, pmap_extract(kernel_pmap,
+               (vm_offset_t)cursor_data));
+       return(0);
+}
+
+
+/*
+ * Clear registers on exec
+ */
+
+void
+setregs(p, pack, stack, retval)
+       struct proc *p;
+       struct exec_package *pack;
+       u_long stack;
+       register_t *retval;
+{
+       register struct trapframe *tf;
+
+       if (pmap_debug_level >= -1)
+               printf("setregs: ip=%08x sp=%08x proc=%08x\n",
+                   (u_int) pack->ep_entry, (u_int) stack, (u_int) p);
+
+       tf = p->p_md.md_regs;
+
+       if (pmap_debug_level >= -1)
+               printf("mdregs=%08x pc=%08x lr=%08x sp=%08x\n",
+                   (u_int) tf, tf->tf_pc, tf->tf_usr_lr, tf->tf_usr_sp);
+
+       tf->tf_r11 = 0;                         /* bottom of the fp chain */
+       tf->tf_r12 = 0;                         /* ??? */
+       tf->tf_pc = pack->ep_entry;
+       tf->tf_usr_lr = pack->ep_entry;
+       tf->tf_svc_lr = 0x77777777;             /* Something we can see */
+       tf->tf_usr_sp = stack;
+       tf->tf_r10 = 0xaa55aa55;                /* Something we can see */
+       tf->tf_spsr = PSR_USR32_MODE;
+
+       p->p_addr->u_pcb.pcb_flags = 0;
+
+       retval[1] = 0;
+}
+
+
+/*
+ * Modify the current mapping for zero page to make it read only
+ *
+ * This routine is only used until things start forking. Then new
+ * system pages are mapped read only in pmap_enter().
+ */
+
+void
+zero_page_readonly()
+{
+       WriteWord(0xefc00000, L2_PTE((systempage.physical & PG_FRAME), AP_KR));
+       tlbflush();
+}
+
+
+/*
+ * Modify the current mapping for zero page to make it read/write
+ *
+ * This routine is only used until things start forking. Then system
+ * pages belonging to user processes are never made writable.
+ */
+
+void
+zero_page_readwrite()
+{
+       WriteWord(0xefc00000, L2_PTE((systempage.physical & PG_FRAME), AP_KRW));
+       tlbflush();
+}
+
+
+/*
+ * 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.
+ */
+
+void
+sendsig(catcher, sig, mask, code)
+       sig_t catcher;
+       int sig;
+       int mask;
+       u_long code;
+{
+       struct proc *p = curproc;
+       struct trapframe *tf;
+       struct sigframe *fp, frame;
+       struct sigacts *psp = p->p_sigacts;
+       int oonstack;
+       extern char sigcode[], esigcode[];
+
+       if (pmap_debug_level >= 0)
+               printf("Sendsig: sig=%d mask=%08x catcher=%08x code=%08x\n",
+                   sig, mask, (u_int)catcher, (u_int)code);
+
+       tf = p->p_md.md_regs;
+       oonstack = psp->ps_sigstk.ss_flags & SA_ONSTACK;
+
+/*
+ * Allocate space for the signal handler context.
+ */
+
+       if ((psp->ps_flags & SAS_ALTSTACK) && !oonstack &&
+           (psp->ps_sigonstack & sigmask(sig))) {
+               fp = (struct sigframe *)(psp->ps_sigstk.ss_sp +
+                   psp->ps_sigstk.ss_size - sizeof(struct sigframe));
+               psp->ps_sigstk.ss_flags |= SA_ONSTACK;
+       } else {
+               fp = (struct sigframe *)tf->tf_usr_sp - 1;
+       }
+
+/* 
+ * Build the argument list for the signal handler.
+ */
+
+       frame.sf_signum = sig;
+
+       frame.sf_code = code;
+       frame.sf_scp = &fp->sf_sc;
+       frame.sf_handler = catcher;
+
+/*
+ * Build the signal context to be used by sigreturn.
+ */
+
+       frame.sf_sc.sc_onstack = oonstack;
+       frame.sf_sc.sc_mask   = mask;
+       frame.sf_sc.sc_r0     = tf->tf_r0;
+       frame.sf_sc.sc_r1     = tf->tf_r1;
+       frame.sf_sc.sc_r2     = tf->tf_r2;
+       frame.sf_sc.sc_r3     = tf->tf_r3;
+       frame.sf_sc.sc_r4     = tf->tf_r4;
+       frame.sf_sc.sc_r5     = tf->tf_r5;
+       frame.sf_sc.sc_r6     = tf->tf_r6;
+       frame.sf_sc.sc_r7     = tf->tf_r7;
+       frame.sf_sc.sc_r8     = tf->tf_r8;
+       frame.sf_sc.sc_r9     = tf->tf_r9;
+       frame.sf_sc.sc_r10    = tf->tf_r10;
+       frame.sf_sc.sc_r11    = tf->tf_r11;
+       frame.sf_sc.sc_r12    = tf->tf_r12;
+       frame.sf_sc.sc_usr_sp = tf->tf_usr_sp;
+       frame.sf_sc.sc_usr_lr = tf->tf_usr_lr;
+       frame.sf_sc.sc_svc_lr = tf->tf_svc_lr;
+       frame.sf_sc.sc_pc     = tf->tf_pc;
+       frame.sf_sc.sc_spsr   = tf->tf_spsr;
+
+       if (copyout(&frame, fp, sizeof(frame)) != 0) {
+/*
+ * Process has trashed its stack; give it an illegal
+ * instruction to halt it in its tracks.
+ */
+
+               sigexit(p, SIGILL);
+               /* NOTREACHED */
+       }
+
+/*
+ * Build context to run handler in.
+ */
+
+       tf->tf_r0 = frame.sf_signum;
+       tf->tf_r1 = frame.sf_code;
+       tf->tf_r2 = (u_int)frame.sf_scp;
+       tf->tf_r3 = (u_int)frame.sf_handler;
+       tf->tf_usr_sp = (int)fp;
+       tf->tf_pc = (int)(((char *)PS_STRINGS) - (esigcode - sigcode));
+
+       if (pmap_debug_level >= 0)
+               printf("Sendsig: sig=%d pc=%08x\n", sig, tf->tf_pc);
+}
+
+
+
+/*
+ * 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
+ * psr to gain improper privileges 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;
+       struct sigcontext *scp, context;
+/*     register struct sigframe *fp;*/
+       register struct trapframe *tf;
+
+       if (pmap_debug_level >= 0)
+               printf("sigreturn: context=%08x\n", (int)SCARG(uap, sigcntxp));
+
+       tf = p->p_md.md_regs;
+
+       /*
+        * The trampoline code hands us the context.
+        * It is unsafe to keep track of it ourselves, in the event that a
+        * program jumps out of a signal handler.
+        */
+
+       scp = SCARG(uap, sigcntxp);
+
+       if (copyin((caddr_t)scp, &context, sizeof(*scp)) != 0)
+               return (EFAULT);
+
+/*
+ * Check for security violations.
+ */
+
+/* Make sure the processor mode has not been tampered with */
+
+       if ((context.sc_spsr & PSR_MODE) != PSR_USR32_MODE)
+               return(EINVAL);
+
+       if (context.sc_onstack & 01)
+               p->p_sigacts->ps_sigstk.ss_flags |= SA_ONSTACK;
+       else
+               p->p_sigacts->ps_sigstk.ss_flags &= ~SA_ONSTACK;
+       p->p_sigmask = context.sc_mask & ~sigcantmask;
+
+       /*
+        * Restore signal context.
+        */
+
+       tf->tf_r0    = context.sc_r0;
+       tf->tf_r1    = context.sc_r1;
+       tf->tf_r2    = context.sc_r2;
+       tf->tf_r3    = context.sc_r3;
+       tf->tf_r4    = context.sc_r4;
+       tf->tf_r5    = context.sc_r5;
+       tf->tf_r6    = context.sc_r6;
+       tf->tf_r7    = context.sc_r7;
+       tf->tf_r8    = context.sc_r8;
+       tf->tf_r9    = context.sc_r9;
+       tf->tf_r10   = context.sc_r10;
+       tf->tf_r11   = context.sc_r11;
+       tf->tf_r12   = context.sc_r12;
+       tf->tf_usr_sp = context.sc_usr_sp;
+       tf->tf_usr_lr = context.sc_usr_lr;
+       tf->tf_svc_lr = context.sc_svc_lr;
+       tf->tf_pc    = context.sc_pc;
+       tf->tf_spsr  = context.sc_spsr;
+
+#ifdef VALIDATE_TRAPFRAME
+       validate_trapframe(tf, 6);
+#endif
+       
+       return (EJUSTRETURN);
+}
+
+/*
+ * machine dependent system variables.
+ */
+
+int
+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;
+{
+       printf("cpu_sysctl: Currently stoned - Cannot support the operation\n");
+       return(EOPNOTSUPP);
+}
+
+
+/*
+ * Ok these are some development functions. They map blocks of memory
+ * into the video ram virtual memory.
+ * The idea is to follow this with a call to the vidc device to
+ * reinitialise the vidc20 for the new video ram.
+ */
+
+/* Map DRAM into the video memory */
+
+int
+vmem_mapdram()
+{
+       u_int l2pagetable;
+       u_int logical;
+
+       if (videodram_start == 0 || videodram_size == 0)
+               return(ENOMEM);
+
+/* Flush any video data in the cache */
+
+       idcflush();
+
+/* Get the level 2 pagetable for the video memory */
+
+       l2pagetable = pmap_pte(kernel_pmap, videomemory.vidm_vbase);
+
+/* Map a block of DRAM into the video memory area */
+
+       for (logical = 0; logical < 0x200000; logical += NBPG) {
+               map_entry(l2pagetable, logical, videodram_start
+                   + logical);
+               map_entry(l2pagetable, logical + 0x200000,
+                   videodram_start + logical);
+       }
+
+/* Flush the TLB so we pick up the new mappings */
+
+       tlbflush();
+
+/* Rebuild the video memory descriptor */
+
+       videomemory.vidm_vbase = VMEM_VBASE;
+       videomemory.vidm_pbase = videodram_start;
+       videomemory.vidm_type = VIDEOMEM_TYPE_DRAM;
+       videomemory.vidm_size = videodram_size;
+
+/* Reinitialise the video system */
+
+/*     video_reinit();*/
+       return(0);
+}
+
+
+/* Map VRAM into the video memory */
+
+int
+vmem_mapvram()
+{
+       u_int l2pagetable;
+       u_int logical;
+
+       if (bootconfig.vram[0].address == 0 || bootconfig.vram[0].pages == 0)
+               return(ENOMEM);
+
+/* Flush any video data in the cache */
+
+       idcflush();
+
+/* Get the level 2 pagetable for the video memory */
+
+       l2pagetable = pmap_pte(kernel_pmap, videomemory.vidm_vbase);
+
+/* Map the VRAM into the video memory area */
+
+       for (logical = 0; logical < 0x200000; logical += NBPG) {
+               map_entry(l2pagetable, logical, bootconfig.vram[0].address
+                   + logical);
+               map_entry(l2pagetable, logical + 0x200000,
+                   bootconfig.vram[0].address + logical);
+       }
+
+/* Flush the TLB so we pick up the new mappings */
+
+       tlbflush();
+
+/* Rebuild the video memory descriptor */
+
+       videomemory.vidm_vbase = VMEM_VBASE;
+       videomemory.vidm_pbase = VRAM_BASE;
+       videomemory.vidm_type = VIDEOMEM_TYPE_VRAM;
+       videomemory.vidm_size = bootconfig.vram[0].pages * NBPG;
+
+/* Reinitialise the video system */
+
+/*     video_reinit();*/
+       return(0);
+}
+
+
+/* Set the cache behaviour for the video memory */
+
+int
+vmem_cachectl(flag)
+       int flag;
+{
+       u_int l2pagetable;
+       u_int logical;
+
+       if (bootconfig.vram[0].address == 0 || bootconfig.vram[0].pages == 0)
+               return(ENOMEM);
+
+/* Flush any video data in the cache */
+
+       idcflush();
+
+/* Get the level 2 pagetable for the video memory */
+
+       l2pagetable = pmap_pte(kernel_pmap, videomemory.vidm_vbase);
+
+/* Map the VRAM into the video memory area */
+
+       if (flag & 1) {
+               for (logical = 0; logical < 0x200000; logical += NBPG) {
+                       map_entry(l2pagetable, logical, bootconfig.vram[0].address
+                           + logical);
+                       map_entry(l2pagetable, logical + 0x200000,
+                           bootconfig.vram[0].address + logical);
+               }
+       } else {
+               for (logical = 0; logical < 0x200000; logical += NBPG) {
+                       map_entry_nc(l2pagetable, logical, bootconfig.vram[0].address
+                           + logical);
+                       map_entry_nc(l2pagetable, logical + 0x200000,
+                           bootconfig.vram[0].address + logical);
+               }
+       }
+
+/* Flush the TLB so we pick up the new mappings */
+
+       tlbflush();
+
+       return(0);
+}
+
+#if 0
+extern int vtvalbug;
+extern char *vtlastbug;
+extern u_int vtbugaddr;
+extern u_int vtbugcaddr;
+
+void
+vtbugreport()
+{
+       printf("vtvalbug = %d\n", vtvalbug);
+       if (vtlastbug)
+               printf("vtlastbug = %s\n", vtlastbug);
+       printf("vtbugaddr = %08x\n", vtbugaddr);
+       printf("vtbugcaddr = %08x\n", vtbugcaddr);
+}
+#endif
+
+/* End of machdep.c */
diff --git a/sys/arch/arm32/arm32/makemodes.c b/sys/arch/arm32/arm32/makemodes.c
new file mode 100644 (file)
index 0000000..6a1f5e3
--- /dev/null
@@ -0,0 +1,362 @@
+/* $NetBSD: makemodes.c,v 1.3 1996/03/16 00:13:12 thorpej Exp $ */
+
+/*
+ * Copyright (c) 1995 Mark Brinicombe.
+ * 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 RiscBSD team.
+ * 4. The name of the group nor the name of the author may 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 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.
+ *
+ * RiscBSD kernel project
+ *
+ * makemodes.c
+ *
+ * VIDC20 mode configuration program.
+ *
+ * Builds a list of configured modes using mode specifiers to select
+ * the VIDC timings from a monitor definition file
+ *
+ * Not yet perfect, this is just experimental.
+ *
+ * Created      : 17/05/95
+ * Last updated : 17/05/95
+ */
+
+#include <stdio.h>
+
+/*#define VERBOSE*/
+
+#define MAX_MD 100     /* Support up to 100 modes from a file */
+
+struct md {
+       int     md_xres;
+       int     md_yres;
+       int     md_pixelrate;
+       int     md_htimings[6];
+       int     md_vtimings[6];
+       int     md_syncpol;
+       int     md_framerate;
+} mds[MAX_MD];
+
+int    md;     /* Number of modes defined in the mds array */
+
+
+void makemode __P((FILE *, int, int, int, int));
+
+int
+main(argc, argv)
+       int argc;
+       char *argv[];
+{
+       char line[100];         /* Line read from mdf */
+       char token[40];         /* token read from mdf line */
+       char value[60];         /* value of token read form mdf line */
+       int startmode;          /* Are we between startmode and endmode tokens */
+       char monitor[40];       /* monitor name */
+       int dpms;               /* DPMS state for monitor */
+       FILE *mdf_fd;           /* mdf file descriptor */
+       FILE *out_fd;           /* output file descriptor */
+       int loop;               /* loop counter */
+       int x, y, c, f;         /* mode specifier variables */
+       int params;
+       char *ptr;
+
+/* Check the args */
+       
+       if (argc < 3) {
+               fprintf(stderr, "Syntax: makemodes <mdf> <outfile> <modes>\n");
+               exit(10);
+       }
+
+/* Open the monitor definition file */
+       
+       mdf_fd = fopen(argv[1], "r");
+       if (!mdf_fd) {
+               fprintf(stderr, "Cannot open monitor definition file\n");
+               exit(10);
+       }
+
+/* Open the output file */
+
+       out_fd = fopen(argv[2], "w");
+       if (!out_fd) {
+               fprintf(stderr, "Cannot open output file\n");
+               exit(10);
+       }
+
+/* Initialise some variables */
+
+       startmode = 0;
+       md = 0;
+       dpms = 0;
+       monitor[0] = 0;
+
+/* Loop for each line in the monitor definition file */
+
+       do {
+
+/* get a line */
+
+               if (fgets(line, 99, mdf_fd) == NULL)
+                       break;
+
+               ptr = line;
+
+/* Skip any spaces or tabs */
+
+               while (*ptr == ' ' || *ptr == '\t')
+                       ++ptr;
+
+/* Ignore comment or blank lines */
+
+               if (*ptr == '#' || strlen(ptr) < 2)
+                       continue;
+
+/* Do we have a startmode or endmode token ? */
+
+               if (sscanf(ptr, "%s", token) == 1) {
+                       if (strcmp(token, "startmode") == 0) {
+                               if (md < MAX_MD)
+                                       startmode = 1;
+                       }
+                       if (strcmp(token, "endmode") == 0) {
+                               startmode = 0;
+                               ++md;
+                       }
+               }
+
+/* Do we have a token:value line ? */
+
+               if (sscanf(ptr, "%[^:]:%[^\n]\n", token, value) == 2) {
+                       if (strcmp(token, "monitor_title") == 0)
+                               strcpy(monitor, value);
+                       if (strcmp(token, "file_format") == 0) {
+                               if (atoi(value) != 1) {
+                                       fprintf(stderr, "Unrecognised file format\n");
+                                       exit(10);
+                               }
+                       }
+                       if (strcmp(token, "DPMS_state") == 0)
+                               dpms = atoi(value);
+                       if (strcmp(token, "x_res") == 0 && startmode)
+                               mds[md].md_xres = atoi(value);
+                       if (strcmp(token, "y_res") == 0 && startmode)
+                               mds[md].md_yres = atoi(value);
+                       if (strcmp(token, "pixel_rate") == 0 && startmode)
+                               mds[md].md_pixelrate = atoi(value);
+                       if (strcmp(token, "h_timings") == 0 && startmode)
+                               sscanf(value, "%d,%d,%d,%d,%d,%d",
+                                       &mds[md].md_htimings[0],
+                                       &mds[md].md_htimings[1],
+                                       &mds[md].md_htimings[2],
+                                       &mds[md].md_htimings[3],
+                                       &mds[md].md_htimings[4],
+                                       &mds[md].md_htimings[5]);
+                       if (strcmp(token, "v_timings") == 0 && startmode)
+                               sscanf(value, "%d,%d,%d,%d,%d,%d",
+                                       &mds[md].md_vtimings[0],
+                                       &mds[md].md_vtimings[1],
+                                       &mds[md].md_vtimings[2],
+                                       &mds[md].md_vtimings[3],
+                                       &mds[md].md_vtimings[4],
+                                       &mds[md].md_vtimings[5]);
+                       if (strcmp(token, "sync_pol") == 0 && startmode)
+                               mds[md].md_syncpol = atoi(value);
+               }
+               
+       }
+       while (!feof(mdf_fd));
+
+/* We have finished with the monitor definition file */
+       
+       fclose(mdf_fd); 
+
+#ifdef VERBOSE
+
+/* This was for debugging */
+
+       for (loop = 0; loop < md; ++loop) {
+               printf("%d x %d: %d %d [%d,%d,%d,%d,%d,%d] [%d,%d,%d,%d,%d,%d]\n",
+                       mds[loop].md_xres,
+                       mds[loop].md_yres,
+                       mds[loop].md_pixelrate,
+                       mds[loop].md_syncpol,
+                       mds[loop].md_htimings[0],
+                       mds[loop].md_htimings[1],
+                       mds[loop].md_htimings[2],
+                       mds[loop].md_htimings[3],
+                       mds[loop].md_htimings[4],
+                       mds[loop].md_htimings[5],
+                       mds[loop].md_vtimings[0],
+                       mds[loop].md_vtimings[1],
+                       mds[loop].md_vtimings[2],
+                       mds[loop].md_vtimings[3],
+                       mds[loop].md_vtimings[4],
+                       mds[loop].md_vtimings[5]);
+       }
+#endif
+
+/* Start building the output file */
+
+       fprintf(out_fd, "/*\n");
+       fprintf(out_fd, " * MACHINE GENERATED: DO NOT EDIT\n");
+       fprintf(out_fd, " *\n");
+       fprintf(out_fd, " * %s, from %s\n", argv[2], argv[1]);
+       fprintf(out_fd, " */\n\n");
+       fprintf(out_fd, "#include <sys/types.h>\n");
+       fprintf(out_fd, "#include <machine/vidc.h>\n\n");
+       fprintf(out_fd, "char *monitor=\"%s\";\n", monitor);
+       fprintf(out_fd, "int dpms=%d;\n", dpms);
+       fprintf(out_fd, "\n", dpms);
+       fprintf(out_fd, "struct vidc_mode vidcmodes[] = {\n");
+
+       loop = 3;
+
+/* Loop over the rest of the args processing then as mode specifiers */
+
+/* NOTE: A mode specifier cannot have a space in it at the moment */
+       
+       while (argv[loop]) {
+               printf("%s ==> ", argv[loop]);
+               f = -1;
+               c = 256;
+               params = sscanf(argv[loop], "X%dY%dC%dF%d", &x, &y, &c, &f);
+               if (params < 2)
+                       params = sscanf(argv[loop], "%d,%d,%d,%d", &x, &y, &c, &f);
+               if (params == 2 || params == 4)
+                       makemode(out_fd, x, y, c, f);
+               else if (params == 3)
+                       makemode(out_fd, x, y, 256, c);
+               else
+                       printf("Invalid mode specifier\n");
+               printf("\n");
+               ++loop;
+       }
+
+/* Finish off the output file */
+
+       fprintf(out_fd, "  { 0 }\n");
+       fprintf(out_fd, "};\n");
+       
+       fclose(out_fd);
+}
+
+
+/* Locate an appropriate mode for the specifier and write it to the file */
+
+void makemode(out_fd, x, y, c, f)
+       FILE *out_fd;
+       int x, y, c, f;
+{
+       int loop;               /* loop counter */
+       float framerate;        /* frame rate */
+       int fr;                 /* integer frame rate */
+       int found = -1;         /* array index of found mode */
+       int max = -1;           /* maximum frame rate found */
+       int pos = -1;           /* array index of max frame rate */
+/* Print some info */
+
+       printf("%d x %d x %d x %d : ", x, y, c, f);
+
+/* Scan the modes */
+
+       for (loop = 0; loop < md; ++loop) {
+
+/* X and Y have to match */
+
+               if (mds[loop].md_xres == x && mds[loop].md_yres == y) {
+
+/* Now calculate the frame rate */
+
+                       framerate = (float)mds[loop].md_pixelrate /
+                                       (float)(mds[loop].md_htimings[0] +
+                                       mds[loop].md_htimings[1] +
+                                       mds[loop].md_htimings[2] +
+                                       mds[loop].md_htimings[3] +
+                                       mds[loop].md_htimings[4] +
+                                       mds[loop].md_htimings[5]) /
+                                       (float)(mds[loop].md_vtimings[0] +
+                                       mds[loop].md_vtimings[1] +
+                                       mds[loop].md_vtimings[2] +
+                                       mds[loop].md_vtimings[3] +
+                                       mds[loop].md_vtimings[4] +
+                                       mds[loop].md_vtimings[5]);
+                       framerate = framerate * 1000;
+                       fr = (framerate + 0.5);
+                       mds[loop].md_framerate = fr;
+
+/* Print it as info */
+
+                       printf("%d ", fr);
+
+/* Is this a new maximum ? */
+
+                       if (max < fr) {
+                               max = fr;
+                               pos = loop;
+                       }                       
+
+/* Does it match the specified frame rate ? */
+
+                       if (fr == f)
+                               found = loop;
+               }
+       }
+
+/* No exact match so use the max */
+
+       if (found == -1)
+               found = pos;
+
+/* Do we have an entry for this X & Y resolution */
+               
+       if (found != -1) {
+               fprintf(out_fd, "  { %d,/**/%d, %d, %d, %d, %d, %d,/**/%d, %d, %d, %d, %d, %d,/**/%d,/**/%d, %d },\n",
+                       mds[found].md_pixelrate,
+                       mds[found].md_htimings[0],
+                       mds[found].md_htimings[1],
+                       mds[found].md_htimings[2],
+                       mds[found].md_htimings[3],
+                       mds[found].md_htimings[4],
+                       mds[found].md_htimings[5],
+                       mds[found].md_vtimings[0],
+                       mds[found].md_vtimings[1],
+                       mds[found].md_vtimings[2],
+                       mds[found].md_vtimings[3],
+                       mds[found].md_vtimings[4],
+                       mds[found].md_vtimings[5],
+                       ffs(c),
+                       mds[found].md_syncpol,
+                       mds[found].md_framerate);
+       }
+       else {
+               fprintf(stderr, "Cannot find mode\n");
+       }
+}
+
+/* End of makemodes.c */
diff --git a/sys/arch/arm32/arm32/mcount.S b/sys/arch/arm32/arm32/mcount.S
new file mode 100644 (file)
index 0000000..f54a8b9
--- /dev/null
@@ -0,0 +1,47 @@
+/* $NetBSD: mcount.S,v 1.1 1996/01/31 23:16:32 mark Exp $ */
+
+/*
+ * Copyright (C) 1994 Mark Brinicombe
+ * Copyright (C) 1994 Brini
+ * 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 Brini.
+ * 4. The name of Brini may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BRINI ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL BRINI BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (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: mcount.S,v 1.1.1.1 1996/04/24 11:08:27 deraadt Exp $
+ */
+
+fp     .req    r11
+ip     .req    r12
+sp     .req    r13
+lr     .req    r14
+pc     .req    r15
+
+.text
+       .align  0
+
+       .global mcount
+mcount:
+       add     pc, lr, #0x00000004
diff --git a/sys/arch/arm32/arm32/mem.c b/sys/arch/arm32/arm32/mem.c
new file mode 100644 (file)
index 0000000..13f87ad
--- /dev/null
@@ -0,0 +1,207 @@
+/* $NetBSD: mem.c,v 1.2 1996/03/27 22:42:24 mark 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.
+ */
+
+/*
+ * 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 <sys/proc.h>
+#include <sys/fcntl.h>
+
+#include <machine/cpu.h>
+
+#include <vm/vm.h>
+
+extern char *memhook;            /* poor name! */
+caddr_t zeropage;
+
+/*ARGSUSED*/
+int
+mmopen(dev, flag, mode)
+       dev_t dev;
+       int flag, mode;
+{
+       switch (minor(dev)) {
+       default:
+               break;
+       }
+       return (0);
+}
+
+/*ARGSUSED*/
+int
+mmclose(dev, flag, mode)
+       dev_t dev;
+       int flag, mode;
+{
+
+       return (0);
+}
+
+/*ARGSUSED*/
+int
+mmrw(dev, uio, flags)
+       dev_t dev;
+       struct uio *uio;
+       int flags;
+{
+       register vm_offset_t o, v;
+       register int c;
+       register struct iovec *iov;
+       int error = 0;
+       static int physlock;
+
+       if (minor(dev) == 0) {
+               /* lock against other uses of shared vmmap */
+               while (physlock > 0) {
+                       physlock++;
+                       error = tsleep((caddr_t)&physlock, PZERO | PCATCH,
+                           "mmrw", 0);
+                       if (error)
+                               return (error);
+               }
+               physlock = 1;
+       }
+       while (uio->uio_resid > 0 && error == 0) {
+               iov = uio->uio_iov;
+               if (iov->iov_len == 0) {
+                       uio->uio_iov++;
+                       uio->uio_iovcnt--;
+                       if (uio->uio_iovcnt < 0)
+                               panic("mmrw");
+                       continue;
+               }
+               switch (minor(dev)) {
+
+/* minor device 0 is physical memory */
+               case 0:
+                       v = uio->uio_offset;
+                       pmap_enter(pmap_kernel(), (vm_offset_t)memhook,
+                           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)memhook + o, c, uio);
+                       pmap_remove(pmap_kernel(), (vm_offset_t)memhook,
+                           (vm_offset_t)memhook + NBPG);
+                       continue;
+
+/* minor device 1 is kernel memory */
+               case 1:
+                       v = uio->uio_offset;
+                       c = min(iov->iov_len, MAXPHYS);
+                       if (!kernacc((caddr_t)v, c,
+                           uio->uio_rw == UIO_READ ? B_READ : B_WRITE))
+                               return (EFAULT);
+                       error = uiomove((caddr_t)v, c, uio);
+                       continue;
+
+/* minor device 2 is EOF/RATHOLE */
+               case 2:
+                       if (uio->uio_rw == UIO_WRITE)
+                               uio->uio_resid = 0;
+                       return (0);
+
+/* minor device 3 (/dev/zero) is source of nulls on read, rathole on write */
+               case 3:
+                       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;
+{
+       struct proc *p = curproc;       /* XXX */
+
+       switch (minor(dev)) {
+/* minor device 0 is physical memory */
+       case 0:
+               if (off > ctob(physmem) &&
+                   suser(p->p_ucred, &p->p_acflag) != 0)
+                       return -1;
+               return arm_byte_to_page(off);
+
+/* minor device 1 is kernel memory */
+       case 1:
+               /* XXX - writability, executability checks? */
+               if (!kernacc((caddr_t)off, NBPG, B_READ))
+                       return -1;
+               return arm_byte_to_page(vtophys(off));
+
+       default:
+               return -1;
+       }
+}
diff --git a/sys/arch/arm32/arm32/memset.S b/sys/arch/arm32/arm32/memset.S
new file mode 100644 (file)
index 0000000..4599b23
--- /dev/null
@@ -0,0 +1,136 @@
+/* $NetBSD: memset.S,v 1.1 1996/01/31 23:16:35 mark Exp $ */
+
+/*
+ * Copyright (c) 1995 Mark Brinicombe.
+ * Copyright (c) 1995 Brini.
+ * 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 Mark Brinicombe.
+ * 4. The name of the company nor the name of the author may 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 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.
+ *
+ * RiscBSD kernel project
+ *
+ * memset.S
+ *
+ * optimized memset function
+ *
+ * Created      : 16/05/95
+ * Last updated : 16/05/95
+ *
+ *    $Id: memset.S,v 1.1.1.1 1996/04/24 11:08:28 deraadt Exp $
+ */
+
+sp     .req    r13
+lr     .req    r14
+pc     .req    r15
+
+.text
+
+        .global _memset
+
+/* Sets a block of memory to the specified value
+ *
+ *  r0 - address
+ *  r1 - byte to write
+ *  r2 - number of bytes to write
+ */
+
+_memset:
+       and     r1, r1, #0x000000ff     /* We write bytes */
+
+       cmp     r2, #0x00000004         /* Do we have less than 4 bytes */
+       blt     memset_lessthanfour
+
+/* Ok first we will word align the address */
+
+       ands    r3, r0, #0x00000003     /* Get the bottom two bits */
+       beq     memset_addraligned      /* The address is word aligned */
+
+       rsb     r3, r3, #0x00000004
+       sub     r2, r2, r3
+       cmp     r3, #0x00000002
+       strb    r1, [r0], #0x0001       /* Set 1 byte */
+       strgeb  r1, [r0], #0x0001       /* Set another byte */
+       strgtb  r1, [r0], #0x0001       /* and a third */
+
+       cmp     r2, #0x00000004
+       blt     memset_lessthanfour
+
+/* Now we must be word aligned */
+
+memset_addraligned:
+
+       orr     r3, r1, r1, lsl #8      /* Repeat the byte into a word */
+       orr     r3, r3, r3, lsl #16
+
+/* We know we have at least 4 bytes ... */
+
+       cmp     r2, #0x00000020         /* If less than 32 then use words */
+       blt     memset_lessthan32
+
+/* We have at least 32 so lets use quad words */
+
+       stmfd   sp!, {r4-r6}            /* Store registers */
+       mov     r4, r3                  /* Duplicate data */
+       mov     r5, r3
+       mov     r6, r3
+
+memset_loop16:
+       stmia   r0!, {r3-r6}            /* Store 16 bytes */
+       sub     r2, r2, #0x00000010     /* Adjust count */
+       cmp     r2, #0x00000010         /* Still got at least 16 bytes ? */
+       bgt     memset_loop16
+
+       ldmfd   sp!, {r4-r6}            /* Restore registers */
+
+/* Do we need to set some words as well ? */
+
+       cmp     r2, #0x00000004
+       blt     memset_lessthanfour
+
+/* Have either less than 16 or less than 32 depending on route taken */
+
+memset_lessthan32:
+
+/* We have at least 4 bytes so copy as words */
+
+memset_loop4:
+       str     r3, [r0], #0x0004
+       sub     r2, r2, #0x0004
+       cmp     r2, #0x00000004
+       bge     memset_loop4
+
+memset_lessthanfour:
+       cmp     r2, #0x00000000
+       moveq   pc, lr                  /* Zero length so exit */
+
+       cmp     r2, #0x00000002
+       strb    r1, [r0], #0x0001       /* Set 1 byte */
+       strgeb  r1, [r0], #0x0001       /* Set another byte */
+       strgtb  r1, [r0], #0x0001       /* and a third */
+
+       mov     pc, lr                  /* Exit */
diff --git a/sys/arch/arm32/arm32/pmap.c b/sys/arch/arm32/arm32/pmap.c
new file mode 100644 (file)
index 0000000..66b5a93
--- /dev/null
@@ -0,0 +1,2571 @@
+/* $NetBSD: pmap.c,v 1.4 1996/03/13 21:25:04 mark Exp $ */
+
+/*
+ * Copyright (c) 1994-1996 Mark Brinicombe.
+ * Copyright (c) 1994 Brini.
+ * All rights reserved.
+ *
+ * This code is derived from software written for Brini by Mark Brinicombe
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided 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 Brini.
+ * 4. The name of the company nor the name of the author may be used to
+ *    endorse or promote products derived from this software without specific
+ *    prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BRINI ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL BRINI 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.
+ *
+ * RiscBSD kernel project
+ *
+ * pmap.c
+ *
+ * Machine dependant vm stuff
+ *
+ * Created      : 20/09/94
+ */
+
+/*
+ * The dram block info is currently referenced from the bootconfig.
+ * This should be placed in a separate structure
+ *
+ * Need a pmap_map() routine for multiple pmap_enter() calls
+ *
+ * sob sob sob - been looking at other pmap code ... don't think
+ * I should have base mine of the i386 code ...
+ */
+
+#define PMAPDEBUG 0
+
+/*
+ * Special compilation symbols
+ * DEBUG_PMAP
+ * PMAPDEBUG
+ */
+    
+/* Include header files */
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/proc.h>
+#include <sys/malloc.h>
+#include <sys/msgbuf.h>
+
+#include <vm/vm.h>
+#include <vm/vm_kern.h>
+#include <vm/vm_page.h>
+
+#include <machine/bootconfig.h>
+#include <machine/pmap.h>
+#include <machine/pcb.h>
+#include <machine/param.h>
+#include <machine/katelib.h>
+#include <machine/vidc.h>
+
+#include "hydrabus.h"
+
+/*#define bcopy_page(s, d) bcopy(s, d, NBPG)*/
+/*#define bzero_page(s)    bzero(s, NBPG)*/
+#define bzero_pagedir(s) bzero(s, PD_SIZE)
+
+#define VM_KERNEL_VIRTUAL_MIN     KERNEL_VM_BASE + 0x00000000
+#define VM_KERNEL_VIRTUAL_MAX     KERNEL_VM_BASE + 0x01ffffff
+
+#define pmap_pde(m, v) (&((m)->pm_pdir[((vm_offset_t)(v) >> PDSHIFT)&4095]))
+
+#define pmap_pte_pa(pte)       (*(pte) & PG_FRAME)
+#define pmap_pde_v(pde)                (*(pde) != 0)
+#define pmap_pte_v(pte)                (*(pte) != 0)
+
+#define PT_KS  0x80
+
+int pmap_debug_level = -2;
+
+struct pmap     kernel_pmap_store;
+pmap_t          kernel_pmap;
+
+pagehook_t page_hook0;
+pagehook_t page_hook1;
+char *memhook;
+pt_entry_t msgbufpte;
+
+u_char *pmap_attributes = NULL;
+pv_entry_t pv_table = NULL;
+TAILQ_HEAD(pv_page_list, pv_page) pv_page_freelist;
+int pv_nfree = 0;
+
+vm_size_t npages;
+
+extern vm_offset_t physical_start;
+extern vm_offset_t physical_freestart;
+extern vm_offset_t physical_end;
+extern vm_offset_t physical_freeend;
+extern int physical_memoryblock;
+extern unsigned int free_pages;
+extern vm_offset_t pagetables_start;
+extern int max_processes;
+extern pt_entry_t kernel_pt_table[9];
+extern videomemory_t videomemory;
+
+extern struct proc *proc1;
+
+struct pmap **pagedirectories;
+
+vm_offset_t virtual_start;
+vm_offset_t virtual_end;
+
+vm_offset_t avail_start;
+vm_offset_t avail_end;
+
+typedef struct {
+       vm_offset_t physical;
+       vm_offset_t virtual;
+} pv_addr_t;
+
+extern pv_addr_t kernelstack;
+#if NHYDRABUS > 0
+extern pv_addr_t hydrascratch;
+#endif
+
+#define ALLOC_PAGE_HOOK(x, s) \
+       x.va = virtual_start; \
+       x.pte = (pt_entry_t *)pmap_pte(kernel_pmap, virtual_start); \
+       virtual_start += s; 
+
+
+/* Local variables (not used outside this file) */
+
+/* Local function prototypes (not used outside this file) */
+
+pt_entry_t *pmap_pte __P((pmap_t /*pmap*/, vm_offset_t /*va*/));
+int pmap_page_index __P((vm_offset_t /*pa*/)); 
+void map_pagetable __P((vm_offset_t /*pagetable*/, vm_offset_t /*va*/,
+    vm_offset_t /*pa*/, unsigned int /*flags*/));
+void pmap_copy_on_write __P((vm_offset_t /*pa*/));
+
+void bzero_page __P((vm_offset_t));
+void bcopy_page __P((vm_offset_t, vm_offset_t));
+
+
+/* Function to set the debug level of the pmap code */
+
+void
+pmap_debug(level)
+       int level;
+{
+       pmap_debug_level = level;
+       printf("pmap_debug: level=%d\n", pmap_debug_level);
+}
+
+
+/*
+ * Functions for manipluation pv_entry structures. These are used to keep a
+ * record of the mappings of virtual addresses and the associated physical
+ * pages.
+ */
+
+struct pv_entry *
+pmap_alloc_pv()
+{
+       struct pv_page *pvp;
+       struct pv_entry *pv;
+       int i;
+
+/*
+ * Do we have any free pv_entry structures left ?
+ * If not allocate a page of them
+ */
+  
+       if (pv_nfree == 0) {
+               pvp = (struct pv_page *)kmem_alloc(kernel_map, NBPG);
+               if (pvp == 0)
+                       panic("pmap_alloc_pv: kmem_alloc() failed");
+               pvp->pvp_pgi.pgi_freelist = pv = &pvp->pvp_pv[1];
+               for (i = NPVPPG - 2; i; i--, pv++)
+                       pv->pv_next = pv + 1;
+               pv->pv_next = 0;
+               pv_nfree += pvp->pvp_pgi.pgi_nfree = NPVPPG - 1;
+               TAILQ_INSERT_HEAD(&pv_page_freelist, pvp, pvp_pgi.pgi_list);
+               pv = &pvp->pvp_pv[0];
+       } else {
+               --pv_nfree;
+               pvp = pv_page_freelist.tqh_first;
+               if (--pvp->pvp_pgi.pgi_nfree == 0) {
+                       TAILQ_REMOVE(&pv_page_freelist, pvp, pvp_pgi.pgi_list);
+               }
+               pv = pvp->pvp_pgi.pgi_freelist;
+#ifdef DIAGNOSTIC
+               if (pv == 0)
+                       panic("pmap_alloc_pv: pgi_nfree inconsistent");
+#endif
+               pvp->pvp_pgi.pgi_freelist = pv->pv_next;
+       }
+       return pv;
+}
+
+void
+pmap_free_pv(pv)
+       struct pv_entry *pv;
+{
+       register struct pv_page *pvp;
+
+       pvp = (struct pv_page *) trunc_page(pv);
+       switch (++pvp->pvp_pgi.pgi_nfree) {
+       case 1:
+               TAILQ_INSERT_TAIL(&pv_page_freelist, pvp, pvp_pgi.pgi_list);
+       default:
+               pv->pv_next = pvp->pvp_pgi.pgi_freelist;
+               pvp->pvp_pgi.pgi_freelist = pv;
+               ++pv_nfree;
+               break;
+       case NPVPPG:
+               pv_nfree -= NPVPPG - 1;
+               TAILQ_REMOVE(&pv_page_freelist, pvp, pvp_pgi.pgi_list);
+               kmem_free(kernel_map, (vm_offset_t)pvp, NBPG);
+               break;
+       }
+}
+
+
+void
+pmap_collect_pv()
+{
+       struct pv_page_list pv_page_collectlist;
+       struct pv_page *pvp, *npvp;
+       struct pv_entry *ph, *ppv, *pv, *npv;
+       int s;
+
+       TAILQ_INIT(&pv_page_collectlist);
+
+       for (pvp = pv_page_freelist.tqh_first; pvp; pvp = npvp) {
+               if (pv_nfree < NPVPPG)
+                       break;
+               npvp = pvp->pvp_pgi.pgi_list.tqe_next;
+               if (pvp->pvp_pgi.pgi_nfree > NPVPPG / 3) {
+                       TAILQ_REMOVE(&pv_page_freelist, pvp, pvp_pgi.pgi_list);
+                       TAILQ_INSERT_TAIL(&pv_page_collectlist, pvp, pvp_pgi.pgi_list);
+                       pv_nfree -= pvp->pvp_pgi.pgi_nfree;
+                       pvp->pvp_pgi.pgi_nfree = -1;
+               }
+       }
+
+       if (pv_page_collectlist.tqh_first == 0)
+               return;
+
+       for (ph = &pv_table[npages - 1]; ph >= &pv_table[0]; ph--) {
+               if (ph->pv_pmap == 0)
+                       continue;
+               s = splimp();
+               for (ppv = ph; (pv = ppv->pv_next) != 0; ) {
+                       pvp = (struct pv_page *) trunc_page(pv);
+                       if (pvp->pvp_pgi.pgi_nfree == -1) {
+                               pvp = pv_page_freelist.tqh_first;
+                               if (--pvp->pvp_pgi.pgi_nfree == 0) {
+                                       TAILQ_REMOVE(&pv_page_freelist, pvp, pvp_pgi.pgi_list);
+                               }
+                               npv = pvp->pvp_pgi.pgi_freelist;
+#ifdef DIAGNOSTIC
+                               if (npv == 0)
+                                       panic("pmap_collect_pv: pgi_nfree inconsistent");
+#endif
+                               pvp->pvp_pgi.pgi_freelist = npv->pv_next;
+                               *npv = *pv;
+                               ppv->pv_next = npv;
+                               ppv = npv;
+                       } else
+                               ppv = pv;
+               }
+               splx(s);
+       }
+
+       for (pvp = pv_page_collectlist.tqh_first; pvp; pvp = npvp) {
+               npvp = pvp->pvp_pgi.pgi_list.tqe_next;
+               kmem_free(kernel_map, (vm_offset_t)pvp, NBPG);
+       }
+}
+
+
+/*__inline*/ int
+pmap_enter_pv(pmap, va, pind, flags)
+       pmap_t pmap;
+       vm_offset_t va;
+       int pind;
+       u_int flags;
+{
+       register struct pv_entry *pv, *npv;
+       u_int s;
+
+       if (!pv_table)
+               return(1);
+
+       s = splimp();
+       pv = &pv_table[pind];
+
+       if (pmap_debug_level >= 5)
+               printf("pmap_enter_pv: pind=%08x pv %08x: %08x/%08x/%08x\n",
+                   pind, (int) pv, (int) pv->pv_va, (int) pv->pv_pmap, (int) pv->pv_next);
+
+       if (pv->pv_pmap == NULL) {
+/*
+ * No entries yet, use header as the first entry
+ */
+               pv->pv_va = va;
+               pv->pv_pmap = pmap;
+               pv->pv_next = NULL;
+               pv->pv_flags = flags;
+               splx(s);
+               return(1);
+       } else {
+/*
+ * There is at least one other VA mapping this page.
+ * Place this entry after the header.
+ */
+/*#ifdef DEBUG*/
+               for (npv = pv; npv; npv = npv->pv_next)
+                       if (pmap == npv->pv_pmap && va == npv->pv_va) {
+/*
+ * HACK HACK HACK - The system vector page is wired in with pmap_enter()
+ * this mapping should be deleted during switch_exit() but at the moment it
+ * is not so a duplicate mapping is possible. For the moment we just updated
+ * flags and exit ... This should work as it is a special case.
+ */
+                                       npv->pv_va = va;
+                                       npv->pv_pmap = pmap;
+                                       npv->pv_flags = flags;
+                                       printf("pmap_enter_pv: already in pv_tab  pind=%08x pv %08x: %08x/%08x/%08x",
+                                           pind, (int) pv, (int) pv->pv_va, (int) pv->pv_pmap, (int) pv->pv_next);
+                                       splx(s);
+                                       return(0);
+/*                             } else
+                                       panic("pmap_enter_pv: already in pv_tab  pind=%08x pv %08x: %08x/%08x/%08x",
+                                           pind, (int) pv, (int) pv->pv_va, (int) pv->pv_pmap, (int) pv->pv_next);*/
+                       }
+/*#endif*/
+               npv = pmap_alloc_pv();
+               npv->pv_va = va;
+               npv->pv_pmap = pmap;
+               npv->pv_flags = flags;
+               npv->pv_next = pv->pv_next;
+               pv->pv_next = npv;
+       }
+       splx(s);
+       return(0);
+}
+
+
+/* __inline*/ u_int
+pmap_remove_pv(pmap, va, pind)
+       pmap_t pmap;
+       vm_offset_t va;
+       int pind;
+{
+       register struct pv_entry *pv, *npv;
+       u_int s;
+       u_int flags = 0;
+    
+       if (pv_table == NULL)
+               return(0);
+
+/*
+ * Remove from the PV table (raise IPL since we
+ * may be called at interrupt time).
+ */
+
+       s = splimp();
+       pv = &pv_table[pind];
+
+/*     if (va == 0xefbfe000 || va == 0xefbff000 || va == 0xf1003000 || va == 0xf1004000)
+               printf("pmap_remove_pv(%08x, %08x, %d)\n",
+                   (u_int)pmap, (u_int)va, pind);*/
+
+/*
+ * 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;
+
+                       flags = npv->pv_flags;
+
+                       pmap_attributes[pind] |= flags & (PT_M | PT_H);
+
+                       pmap_free_pv(npv);
+               } else
+                       pv->pv_pmap = NULL;
+       } else {
+               for (npv = pv->pv_next; npv; pv = npv, npv = npv->pv_next) {
+                       if (pmap == npv->pv_pmap && va == npv->pv_va)
+                               break;
+               }
+               if (npv) {
+                       pv->pv_next = npv->pv_next;
+
+                       flags = npv->pv_flags;
+                       pmap_attributes[pind] |= flags & (PT_M | PT_H);
+
+                       pmap_free_pv(npv);
+               }
+       }
+       splx(s);
+       return(flags);
+}
+
+
+/*__inline */ u_int
+pmap_modify_pv(pmap, va, pind, bic_mask, eor_mask)
+       pmap_t pmap;
+       vm_offset_t va;
+       int pind;
+       u_int bic_mask;
+       u_int eor_mask;
+{
+       register struct pv_entry *pv, *npv;
+       u_int s;
+       u_int flags;
+
+       if (pmap_debug_level >= 5)
+               printf("pmap_modify_pv: pmap=%08x va=%08x pi=%08x bic_mask=%08x eor_mask=%08x\n",
+                   (int) pmap, (int) va, pind, bic_mask, eor_mask);
+
+       if (!pv_table)
+               return(0);
+
+#ifdef DIAGNOSTIC
+       if (pind > 0x00010000 || pind < 0) {
+               traceback();
+               panic("pmap_modify_pv: pind out of range pind = %08x va=%08x\n", pind, va);
+       }      
+#endif
+
+       s = splimp();
+       pv = &pv_table[pind];
+
+       if (pmap_debug_level >= 5)
+               printf("pmap_modify_pv: pind=%08x pv %08x: %08x/%08x/%08x/%08x ",
+                   pind, (int) pv, (int)pv->pv_va, (int)pv->pv_pmap, (int)pv->pv_next,
+                   pv->pv_flags);
+
+/*
+ * There is at least one VA mapping this page.
+ */
+
+       for (npv = pv; npv; npv = npv->pv_next) {
+               if (pmap == npv->pv_pmap && va == npv->pv_va) {
+                       flags = npv->pv_flags;
+                       npv->pv_flags = ((flags & ~bic_mask) ^ eor_mask);
+                       if (pmap_debug_level >= 0)
+                               printf("done flags=%08x\n", flags);
+                       splx(s);
+                       return(flags);
+               }
+       }
+
+       if (pmap_debug_level >= 0)
+               printf("done.\n");
+       splx(s);
+       return(0);
+}
+
+
+/*
+ *     Used to map a range of physical addresses into kernel
+ *     virtual address space.
+ *
+ *     For now, VM is already on, we only need to map the
+ *     specified memory.
+ */
+
+vm_offset_t
+pmap_map(va, spa, epa, prot)
+       vm_offset_t va, spa, epa;
+       int prot;
+{
+       while (spa < epa) {
+               pmap_enter(pmap_kernel(), va, spa, prot, FALSE);
+               va += NBPG;
+               spa += NBPG;
+       }
+       return(va);
+}
+
+
+/*
+ * void pmap_bootstrap(pd_entry_t *kernel_l1pt)
+ *
+ * bootstrap the pmap system. This is called from initarm and allows
+ * the pmap system to initailise any structures it requires.
+ *
+ * Currently this sets up the kernel_pmap that is statically allocated
+ * and also allocated virtual addresses for certain page hooks.
+ * Currently the only one page hook is allocated that is used
+ * to zero physical pages of memory.
+ * It also initialises the start and end address of the kernel data space.                 
+ */
+
+void
+pmap_bootstrap(kernel_l1pt)
+       pd_entry_t *kernel_l1pt;
+{
+       kernel_pmap = &kernel_pmap_store;
+
+       kernel_pmap->pm_pdir = kernel_l1pt;
+       kernel_pmap->pm_pptpt = kernel_pt_table[2];
+       simple_lock_init(&kernel_pmap->pm_lock);
+       kernel_pmap->pm_count = 1;
+
+       virtual_start = VM_KERNEL_VIRTUAL_MIN;
+       virtual_end = VM_KERNEL_VIRTUAL_MAX;
+
+       ALLOC_PAGE_HOOK(page_hook0, NBPG);
+       ALLOC_PAGE_HOOK(page_hook1, NBPG);
+
+/* The mem special device needs a virtual hook but we don't need a pte */
+
+       memhook = (char *)virtual_start;
+       virtual_start += NBPG;
+
+       msgbufp = (struct msgbuf *)virtual_start;
+       msgbufpte = (pt_entry_t)pmap_pte(kernel_pmap, virtual_start);
+       virtual_start += round_page(sizeof(struct msgbuf));
+
+#if PMAPDEBUG > 0
+       printf("pmap_bootstrap: page_hook = V%08x pte = V%08x\n",
+           page_hook_addr0, page_hook_pte0); 
+#endif
+
+#if NHYDRABUS > 0
+       hydrascratch.virtual = virtual_start;
+       virtual_start += NBPG;
+
+       *((pt_entry_t *)pmap_pte(kernel_pmap, hydrascratch.virtual)) = L2_PTE_NC(hydrascratch.physical, AP_KRW);
+       tlbflush();
+#endif
+}
+
+
+/*
+ * void pmap_init(void)
+ *
+ * Initialize the pmap module.
+ * Called by vm_init() in vm/vm_init.c in order to initialise
+ * any structures that the pmap system needs to map virtual memory.
+ */
+
+extern int physmem;
+
+void
+pmap_init()
+{
+       vm_size_t s;
+       vm_offset_t addr;
+    
+/*     printf("pmap_init:\n");*/
+
+       npages = pmap_page_index(physical_freeend - 1) + 1;
+       printf("Number of pages to handle = %ld\n", npages);
+
+/*
+ * Set the available memory vars - These do not map to real memory
+ * addresses. They are used by ps for %mem calculations.
+ */
+/*     avail_start = pmap_page_index(physical_start) * NBPG;
+       avail_end = pmap_page_index(physical_freeend) * NBPG;*/
+       avail_start = 0;
+       avail_end = physmem * NBPG;
+    
+       s = (vm_size_t) (sizeof(struct pv_entry) * npages + npages);
+/*     printf("pv_table size = %08x\n", s);*/
+       s = round_page(s);
+       addr = (vm_offset_t) kmem_alloc(kernel_map, s);
+/*     printf("addr = %08x", addr);*/
+       pv_table = (pv_entry_t) addr;
+       addr += sizeof(struct pv_entry) * npages;
+       pmap_attributes = (char *) addr;
+/*     printf(" attributes = %08x\n", pmap_attributes);*/
+
+/* Ok currently there are some difficulties in allocating the process
+ * page directories on the fly. This is because the page directories
+ * are 16KB in size and there are no garentees that we can get 16KB
+ * continuous physical memory starting on a 16KB boundry from 
+ * kmem_alloc() etc.
+ *
+ * For the moment a number of pages will have been reserved at the top
+ * of the physical memory map.
+ */
+
+       s = max_processes * sizeof(struct pmap *);
+       pagedirectories = (struct pmap **)kmem_alloc(kernel_map, s);
+
+#if PMAPDEBUG > 0
+       printf("pagedirectories pointers at %08x\n", pagedirectories);
+#endif
+
+       bzero(pagedirectories, s);
+       printf("%dKB reserved for L1 page tables\n",
+           max_processes * NBPG * 4 / 1024);
+}
+
+
+/*
+ * Create and return a physical map.
+ *
+ * If the size specified for the map is zero, the map is an actual physical
+ * map, and may be referenced by the hardware.
+ *
+ * If the size specified is non-zero, the map will be used in software only,
+ * and is bounded by that size.
+ */
+
+pmap_t
+pmap_create(size)
+       vm_size_t size;
+{
+       register pmap_t pmap;
+
+/*
+ * Software use map does not need a pmap
+ */
+
+       if (size) return NULL;
+
+/* Allocate memory for pmap structure and zero it */
+/* XXX: I assume waiting here us ok */
+
+       pmap = (pmap_t) malloc(sizeof *pmap, M_VMPMAP, M_WAITOK);
+       bzero(pmap, sizeof(*pmap));
+
+/* Now init the machine part of the pmap */
+
+       pmap_pinit(pmap);
+       return(pmap);
+}
+
+
+/*
+ * Initialize a preallocated and zeroed pmap structure,
+ * such as one in a vmspace structure.
+ *
+ * MAJOR rewrite pending 
+ */
+
+int
+pmap_allocpagedir(pmap)
+       struct pmap *pmap;
+{
+       int loop;
+       vm_offset_t pd;
+       pt_entry_t *pte;
+    
+       if (pmap_debug_level >= 0)
+               printf("pmap_allocpagedir: pmap=%08x\n", (int)pmap);
+
+/*
+ * No need to allocate page table space yet but we do need a
+ * valid page directory table.
+ */
+
+/* Ok we need a 16KB aligned check of memory */
+       for (loop = 0; loop < max_processes; ++loop) {
+/* Locate a free page directory */
+
+               if (pagedirectories[loop] == 0) {
+/* Register the pmap for this page directory */
+
+                       pagedirectories[loop] = pmap;
+
+/* Calculate the virtual address of the page directory */
+
+                       pmap->pm_pdir = (pd_entry_t *) ((PAGE_DIRS_BASE
+                           + PD_SIZE) + loop * PD_SIZE);
+                       pd = (vm_offset_t)(pagetables_start + loop * PD_SIZE);
+#if PMAP_DEBUG > 0
+                       printf("pmap_pinit: page dir at V%08x P%08x\n",
+                           pmap->pm_pdir, pde);
+#endif
+
+/* Calculate the address of the page table entry needed to map this page dir */  
+
+                       pte = (pt_entry_t *)(PROCESS_PAGE_TBLS_BASE
+                          + ((unsigned int)pmap->pm_pdir >> (PGSHIFT-2)));
+
+/* See if it is already mapped */
+
+                       if (*(pte + 0) != 0 || *(pte + 1) != 0
+                           || *(pte + 2) != 0 || *(pte + 3) != 0) {
+                               if (pmap_debug_level >= 0)
+                                       printf("pmap_pinit = V%08x (%08x) (%08x) (%08x) (%08x)\n",
+                                           (int) pte, *(pte+0), *(pte+1),
+                                           *(pte+2), *(pte+3));
+                       }
+
+/* Hook this page directory into the memory map */
+
+                       *(pte + 0) = L2_PTE((pd + (0 * NBPG)) & PG_FRAME, AP_KRW);
+                       *(pte + 1) = L2_PTE((pd + (1 * NBPG)) & PG_FRAME, AP_KRW);
+                       *(pte + 2) = L2_PTE((pd + (2 * NBPG)) & PG_FRAME, AP_KRW);
+                       *(pte + 3) = L2_PTE((pd + (3 * NBPG)) & PG_FRAME, AP_KRW);
+
+#if PMAP_DEBUG > 0
+                       printf("pmap_pinit = V%08x (%08x) (%08x) (%08x) (%08x)\n",
+                           pte, *(pte+0), *(pte+1), *(pte+2), *(pte+3));
+#endif
+
+/* Flush the TLB so that the page directory is accessible */
+
+                       tlbflush();
+
+/* Clear it down */
+
+                       bzero_pagedir(pmap->pm_pdir);
+
+/* Duplicate the kernel mapping i.e. all mappings 0xf0000000 + */
+
+                       bcopy((char *)kernel_pmap->pm_pdir + 0x3c00,
+                           (char *)pmap->pm_pdir + 0x3c00, 0x400);
+
+/* Borrow the kernel's system page as well */
+
+/*                     pmap->pm_pdir[0] = kernel_pmap->pm_pdir[0];
+                       pmap->pm_pdir[1] = kernel_pmap->pm_pdir[1];
+                       pmap->pm_pdir[2] = kernel_pmap->pm_pdir[2];
+                       pmap->pm_pdir[3] = kernel_pmap->pm_pdir[3];*/
+
+/*printf("L1 pagetable V%08x, P%08x\n", pmap->pm_pdir, pd);*/
+
+/* Allocate a page table to map all the page tables for this pmap */
+
+                       if (pmap->pm_vptpt == 0) {
+                               pmap->pm_vptpt = kmem_alloc(kernel_map, NBPG);
+                               pmap->pm_pptpt = pmap_extract(kernel_pmap,
+                                   pmap->pm_vptpt) & PG_FRAME;
+                       }
+
+/*                     printf("pagetable = V%08x P%08x\n", pagetable,
+                           pmap_extract(kernel_pmap, pagetable));
+                       printf("L1 addr = %08x\n",
+                           &((pd_entry_t **)pmap->pm_pdir)[0xefc]);
+*/
+
+/* Wire in this page table */
+
+                       pmap->pm_pdir[0xefc] = L1_PTE(pmap->pm_pptpt + 0x000);
+                       pmap->pm_pdir[0xefd] = L1_PTE(pmap->pm_pptpt + 0x400);
+                       pmap->pm_pdir[0xefe] = L1_PTE(pmap->pm_pptpt + 0x800);
+                       pmap->pm_pdir[0xeff] = L1_PTE(pmap->pm_pptpt + 0xc00);
+
+/*                     printf("copying %08x\n", (PROCESS_PAGE_TBLS_BASE
+                           + (PROCESS_PAGE_TBLS_BASE >> (PGSHIFT-2)) + 0xf00));
+*/
+
+/*
+ * Map the kernel page tables for 0xf0000000 + and 0x00000000 into
+ * the page table used to map the pmap's page tables
+ */
+
+                       bcopy((char *)(PROCESS_PAGE_TBLS_BASE
+                           + (PROCESS_PAGE_TBLS_BASE >> (PGSHIFT-2)) + 0xf00),
+                           (char *)pmap->pm_vptpt + 0xf00, 0x100);
+/*                     bcopy((char *)(PROCESS_PAGE_TBLS_BASE
+                           + (PROCESS_PAGE_TBLS_BASE >> (PGSHIFT-2)) + 0x000),
+                           (char *)pmap->pm_vptpt + 0x000, 0x004);*/
+
+/* Add a self reference reference */
+
+                       *((pt_entry_t *)(pmap->pm_vptpt + 0xefc)) =
+                           L2_PTE(pmap->pm_pptpt, AP_KRWUR);
+
+/*
+                       if (pmap_debug_level >= 0) {
+                               printf("::::%08x %08x\n",
+                                   ((pt_entry_t *)(pmap->pm_vptpt + 0xefc)),
+                                   &((pt_entry_t *)pmap->pm_vptpt)[0xefc >> 2]);
+                       }
+*/
+  
+/*
+ * Now we get nasty. We need to map the page directory to a standard address
+ * in the memory map. This means we can easily find the active page directory.
+ * This is needed by pmap_pte to hook in an alternate pmap's page tables.
+ * This means that a page table is needed in each process to map this memory
+ * as the kernel tables cannot be used as they are shared.
+ * The HACK is to borrow some of the space in the page table that maps all
+ * the pmap page tables.
+ * Mapping a 16KB page directory into that means that a 16MB chunk of the
+ * memory map will no longer be mappable.
+ * Eventually a chuck of user space (at the top end) could be reserved for
+ * this but for the moment the 16MB block at 0xf5000000 is not allocated and
+ * so has become reserved for this processes.
+ */
+                       *((pt_entry_t *)(pmap->pm_vptpt + 0xf50)) =
+                           L2_PTE(pd + 0x0000, AP_KRW);
+                       *((pt_entry_t *)(pmap->pm_vptpt + 0xf54)) =
+                           L2_PTE(pd + 0x1000, AP_KRW);
+                       *((pt_entry_t *)(pmap->pm_vptpt + 0xf58)) =
+                           L2_PTE(pd + 0x2000, AP_KRW);
+                       *((pt_entry_t *)(pmap->pm_vptpt + 0xf5c)) =
+                           L2_PTE(pd + 0x3000, AP_KRW);
+
+                       pmap->pm_count = 1;
+                       simple_lock_init(&pmap->pm_lock);
+                       return(0);
+               }
+       }
+
+       return(1);
+}
+
+
+/*
+ * Initialize a preallocated and zeroed pmap structure,
+ * such as one in a vmspace structure.
+ *
+ * MAJOR rewrite pending
+ */
+
+void
+pmap_pinit(pmap)
+       struct pmap *pmap;
+{
+       if (pmap_debug_level >= 0)
+               printf("pmap_pinit: pmap=%08x\n", (int)pmap);
+
+/* Keep looping until we succeed in allocating a page directory */
+
+       while (pmap_allocpagedir(pmap) != 0) {
+/*
+ * Ok all the allocated L1 page tables are in use so we should sleep for
+ * a while. We only sleep for 10 secs at most. Although we will be wakened
+ * if a slot became available it could be possible for things to jamup with
+ * every process waiting on a process that is waiting for a page table.
+ * If we time out then it means that all the page tables are in use and
+ * there has not be a process termination in 10 secs i.e. possible deadlock
+ */
+
+/*
+ * The snag with this routine is it is not allowed to fail. If we
+ * do detect a possible deadlock then we can report it. The Q is what to
+ * do next. We could start randomly killing processes or process groups.
+ * Since this process is only part formed it is not easy to kill. The
+ * best thing may be to kill it parent.
+ */
+
+/* What we should do here is start swapping out processes. That way
+ * the page directory for the process will be released.
+ * The pagedaemon will swap out processes but only in low memory conditions.
+ * Lack of page directories does not count so we will have to swapout
+ * processes ourselves.
+ */
+
+               if (tsleep((caddr_t)pagedirectories, PZERO, "l1ptwait", 1000)
+                   == EWOULDBLOCK)
+                       printf("Warning: Possible process deadlock due to shortage of L1 page tables\n");
+       }
+}
+
+
+/*
+ * Retire the given physical map from service.
+ * Should only be called if the map contains no valid mappings.
+ */
+
+void
+pmap_destroy(pmap)
+       pmap_t pmap;
+{
+       int count;
+
+       if (pmap_debug_level >= 0)
+               printf("pmap_destroy: pmap = %08x\n", (int) pmap);
+
+       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);
+       } else
+               printf("pmap_destroy: pm_count=%d\n", count);
+}
+
+
+void
+pmap_freepagedir(pmap)
+       register pmap_t pmap;
+{
+       int index;
+
+       index = (((u_int) pmap->pm_pdir) - PAGE_DIRS_BASE - PD_SIZE) / PD_SIZE;
+       if (pagedirectories[index] != pmap)
+               panic("pm_pdir inconsistancy found\n");
+
+       pagedirectories[index] = 0;
+
+/* Wake up any sleeping processes waiting for a l1 page table */
+
+       wakeup((caddr_t)pagedirectories);
+}
+
+
+/*
+ * Release any resources held by the given physical map.
+ * Called when a pmap initialized by pmap_pinit is being released.
+ * Should only be called if the map contains no valid mappings.
+ */
+
+void
+pmap_release(pmap)
+       register pmap_t pmap;
+{
+       if (pmap_debug_level >= 0)
+               printf("pmap_release: pmap=%08x\n", (int) pmap);
+
+       if (pmap->pm_count != 1)                /* XXX: needs sorting */
+               panic("pmap_release count");
+
+/* Free the memory used for the page table mapping */
+
+       kmem_free(kernel_map, (vm_offset_t)pmap->pm_vptpt, NBPG);
+
+       pmap_freepagedir(pmap);
+}
+
+
+/*
+ * void pmap_reference(pmap_t pmap)
+ *
+ * Add a reference to the specified pmap.
+ */
+
+void
+pmap_reference(pmap)
+       pmap_t pmap;
+{
+       if (pmap == NULL)
+               return;
+                                  
+       simple_lock(&pmap->pm_lock);
+       pmap->pm_count++;
+       simple_unlock(&pmap->pm_lock);
+}
+                                                                                     
+  
+/*
+ * void pmap_virtual_space(vm_offset_t *start, vm_offset_t *end)
+ *
+ * Return the start and end addresses of the kernel's virtual space.
+ * These values are setup in pmap_bootstrap and are updated as pages
+ * are allocated.
+ */
+
+void
+pmap_virtual_space(start, end)
+       vm_offset_t *start;
+       vm_offset_t *end;
+{
+       *start = virtual_start;
+       *end = virtual_end;
+}
+
+
+/*
+ * void pmap_pageable(pmap_t pmap, vm_offset_t sva, vm_offset_t eva,
+ *   boolean_t pageable)
+ *  
+ * 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;
+       vm_offset_t eva;
+       boolean_t pageable;
+{
+/*
+ * Ok we can only make the specified pages pageable under the following
+ * conditions.
+ * 1. pageable == TRUE
+ * 2. eva = sva + NBPG
+ * 3. the pmap is the kernel_pmap ??? - got this from i386/pmap.c ??
+ *
+ * right this will get called when making pagetables pageable
+ */
+       if (pmap_debug_level >= 5)
+               printf("pmap_pageable: pmap=%08x sva=%08x eva=%08x p=%d\n",
+                   (int) pmap, (int) sva, (int) eva, (int) pageable);
+       if (pmap == kernel_pmap && pageable && eva == (sva + NBPG)) {
+               vm_offset_t pa;
+               pt_entry_t *pte;
+
+               pte = pmap_pte(pmap, sva);
+               if (!pte)
+                       return;
+               if (!pmap_pte_v(pte))
+                       return;
+               pa = pmap_pte_pa(pte);
+
+/*
+ * Mark it unmodified to avoid pageout
+ */
+               pmap_clear_modify(pa);
+
+               if (pmap_debug_level >= 0)
+                       printf("pmap_pageable: ermm can't really do this yet (%08x)!\n",
+                           (int) sva);
+       }
+}                                     
+
+
+void
+pmap_activate(pmap, pcbp)
+       pmap_t pmap;
+       struct pcb *pcbp;
+{
+       if (pmap != NULL) {
+#if PMAP_DEBUG > 1
+               printf("pmap_activate: pagedir = V%08x\n", pmap->pm_pdir);
+#endif
+               pcbp->pcb_pagedir = (pd_entry_t *)pmap_extract(kernel_pmap,
+                   (vm_offset_t)pmap->pm_pdir);
+               if (pmap_debug_level >= 0)
+                       printf("pmap_activate: pmap=%08x pcb=%08x pdir=%08x l1=%08x\n",
+                           (int) pmap, (int) pcbp, (int) pmap->pm_pdir,
+                           (int) pcbp->pcb_pagedir);
+#if PMAP_DEBUG > 1
+               printf("pmap_activate: pagedir = P%08x\n", pcbp->pcb_pagedir);
+#endif
+
+               if (pmap == &curproc->p_vmspace->vm_pmap) {
+                       printf("pmap: Setting TTB\n");
+                       setttb((u_int)pcbp->pcb_pagedir);
+               }
+               pmap->pm_pdchanged = FALSE;
+       }
+#if PMAP_DEBUG > 1
+       printf("pmap_activate: done\n");
+#endif
+}
+
+
+/*
+ * void pmap_zero_page(vm_offset_t phys)
+ *
+ * zero fill the specific physical page. To do this the page must be
+ * mapped into the virtual memory. Then bzero can be used to zero it.
+ */
+void
+pmap_zero_page(phys)
+       vm_offset_t phys;
+{
+#if PMAPDEBUG > 4
+       printf("pmap_zero_page: pa = %08x", phys);
+#endif
+
+/* Hook the physical page into the memory at our special hook point */
+
+       *page_hook0.pte = L2_PTE(phys & PG_FRAME, AP_KRW);
+
+/* Flush the tlb - eventually this can be a purge tlb */
+
+       tlbflush();
+
+/* Zero the memory */
+
+#if PMAPDEBUG > 4
+       printf(" zeroing...");
+#endif
+       bzero_page(page_hook0.va);
+       idcflush();
+#if PMAPDEBUG > 4
+       printf("done.\n");
+#endif
+}
+
+
+/*
+ * void pmap_copy_page(vm_offset_t src, vm_offset_t dest)
+ *
+ * pmap_copy_page copies the specified page by mapping it into virtual
+ * memory and using bcopy to copy its contents.
+ */
+void
+pmap_copy_page(src, dest)
+       vm_offset_t src;
+       vm_offset_t dest;
+{
+       if (pmap_debug_level >= -1)
+               printf("pmap_copy_page: src=P%08x dest=P%08x\n",
+                   (int) src, (int) dest);
+
+/* Hook the physical page into the memory at our special hook point */
+
+       *page_hook0.pte = L2_PTE(src & PG_FRAME, AP_KRW);
+       *page_hook1.pte = L2_PTE(dest & PG_FRAME, AP_KRW);
+
+/* Flush the tlb - eventually this can be a purge tlb */
+
+       tlbflush();
+
+/* Copy the memory */
+
+       bcopy_page(page_hook0.va, page_hook1.va);
+       idcflush();
+}
+
+
+/*
+ * int pmap_next_page(vm_offset_t *addr)
+ *
+ * Allocate another physical page returning true or false depending
+ * on whether a page could be allocated.
+ *
+ * MARK - This needs optimising ... look at the amiga version
+ */
+int
+pmap_next_page(addr)
+       vm_offset_t *addr;
+{
+       if (physical_freestart == physical_freeend) {
+               if (pmap_debug_level >= 0)
+                       printf("pmap_next_page: Trying to allocate beyond memory\n");
+               return(FALSE);
+       } 
+
+       pmap_zero_page(physical_freestart);
+       *addr = physical_freestart;
+       --free_pages;
+  
+       physical_freestart += NBPG;
+       if (physical_freestart == (bootconfig.dram[physical_memoryblock].address
+           + bootconfig.dram[physical_memoryblock].pages * NBPG)) {
+               ++physical_memoryblock;
+               if (bootconfig.dram[physical_memoryblock].address != 0)
+                       physical_freestart = bootconfig.dram[physical_memoryblock].address;
+       }
+
+#if PMAPDEBUG > 10
+       printf("pmap_next_page: Allocated physpage %08x\n", *addr);
+       printf("pmap_next_page: Next page is       %08x\n", physical_freestart);
+#endif
+
+       return(TRUE);
+}
+
+
+/*
+ * int pmap_next_phys_page(vm_offset_t *addr)
+ *
+ * Allocate another physical page returning true or false depending
+ * on whether a page could be allocated.
+ */
+vm_offset_t
+pmap_next_phys_page(addr)
+       vm_offset_t addr;
+       
+{
+       int loop;
+
+       if (addr < bootconfig.dram[0].address)
+               return(bootconfig.dram[0].address);
+
+       loop = 0;
+
+       while (bootconfig.dram[loop].address != 0
+           && addr > (bootconfig.dram[loop].address + bootconfig.dram[loop].pages * NBPG))
+               ++loop;
+
+       if (bootconfig.dram[loop].address == 0)
+               return(0);
+
+       addr += NBPG;
+       
+       if (addr >= (bootconfig.dram[loop].address + bootconfig.dram[loop].pages * NBPG)) {
+               if (bootconfig.dram[loop + 1].address == 0)
+                       return(0);
+               addr = bootconfig.dram[loop + 1].address;
+       }
+
+       return(addr);
+}
+
+
+/*
+ * unsigned int pmap_free_pages(void)
+ *
+ * Returns the number of free pages the system has.
+ * free_pages is set up during initarm and decremented every time a page
+ * is allocated.
+ */
+unsigned int
+pmap_free_pages()
+{
+#if PMAPDEBUG > 0
+       printf("pmap_free_pages: %08x pages free\n", free_pages);
+#endif
+       return(free_pages);
+}
+
+
+/*
+ * int pmap_page_index(vm_offset_t pa)
+ *
+ * returns a linear index to the physical page. This routine has to take
+ * a physical address and work out the corresponding physical page number.
+ * There does not appear to be a simple way of doing this as the memory
+ * is split into a series of blocks. We search each block to determine
+ * which block the physical page is. Once we have scanned the blocks to
+ * this point we can calculate the physical page index. 
+ */
+int
+pmap_page_index(pa)
+       vm_offset_t pa;
+{
+       int index;
+       int loop;
+
+#if PMAPDEBUG > 0
+       printf("pmap_page_index: pa = P%08x", (int)pa);
+#endif
+
+       if (pa < bootconfig.dram[0].address)
+               return(-1);
+
+       index = 0;
+       for (loop = 0; loop < bootconfig.dramblocks; ++loop) {
+               if (pa < (bootconfig.dram[loop].address
+                   + bootconfig.dram[loop].pages * NBPG)) {
+                       index += (pa - bootconfig.dram[loop].address) >> PGSHIFT;
+#if PMAPDEBUG > 0
+                       printf(" index = %08x\n" ,index);
+#endif
+#ifdef DIAGNOSTIC
+                       if (index > 0x00010000 || index < 0)
+                               printf("pmap_page_index: pa = %08x\n", (int)pa);
+#endif
+                       return(index);
+               } else
+                       index += bootconfig.dram[loop].pages;
+       }
+#if PMAPDEBUG > 0
+       printf(" index = Invalid\n");
+#endif
+       if (pmap_debug_level >= 1)
+               printf("page invalid - no index %08x\n", (int) pa);
+       return(-1);
+}
+
+
+void
+pmap_remove(pmap, sva, eva)
+       struct pmap *pmap;
+       vm_offset_t sva;
+       vm_offset_t eva;
+{
+       register pt_entry_t *pte = NULL;
+       vm_offset_t pa;
+       int pind;
+       int flush = 0;
+
+       idcflush();
+
+       if (pmap_debug_level >= 0)
+               printf("pmap_remove: pmap=%08x sva=%08x eva=%08x\n", (int) pmap,
+                   (int) sva, (int) eva);
+
+       sva &= PG_FRAME;
+       eva &= PG_FRAME;
+
+/*
+ * We need to acquire a pointer to a page table page before entering
+ * the following loop.
+ */
+
+       while (sva < eva) {
+               pte = pmap_pte(pmap, sva);
+               if (pte) break;
+               sva = (sva & PD_MASK) + NBPD;
+       }
+
+       while (sva < eva) {
+/* only check once in a while */
+               if ((sva & PT_MASK) == 0) {
+                       if (!pmap_pde_v(pmap_pde(pmap, sva))) {
+/* We can race ahead here, to the next pde. */
+                                sva += NBPD;
+                                pte += arm_byte_to_page(NBPD);
+                                continue;
+                        }
+               }
+
+               if (!pmap_pte_v(pte))
+                       goto next;
+
+               flush = 1;
+
+/*
+ * Update statistics
+ */
+
+/* Wired bit done below */
+
+/*
+               if (pmap_pte_w(pte))
+                       pmap->pm_stats.wired_count--;
+*/
+               pmap->pm_stats.resident_count--;
+
+               pa = pmap_pte_pa(pte);
+
+/*
+ * 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 pte at %x(%x) ", pte, *pte);
+#endif
+
+               if ((pind = pmap_page_index(pa)) != -1) {
+/*            pmap_attributes[pind] |= *pte & (PG_M | PG_U);*/
+/* pmap_remove_pv will update pmap_attributes */
+#ifdef DIAGNOSTIC
+                       if (pind > 0x00010000 || pind < 0) {
+                               printf("eerk ! pind=%08x pa=%08x\n", pind, (int) pa);
+                               panic("The axe has fallen, were dead\n");
+                       }
+#endif
+                       if (pmap_remove_pv(pmap, sva, pind) & PT_W)
+                               pmap->pm_stats.wired_count--;
+               }
+
+               *pte = 0;
+next:
+               sva += NBPG;
+               pte++;
+       }
+
+       if (flush)
+               pmap_update();
+}
+
+
+/*
+ * 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;
+{
+       struct pv_entry *ph, *pv, *npv;
+       register pmap_t pmap;
+       register pt_entry_t *pte;
+       int pind;
+       int s;
+
+       idcflush();
+       if (pmap_debug_level >= 0)
+               printf("pmap_remove_all: pa=%08x ", (int) pa);
+#ifdef DEBUG
+       if (pmapdebug & (PDB_FOLLOW|PDB_REMOVE|PDB_PROTECT))
+               printf("pmap_remove_all(%x)", (int) pa);
+       /*pmap_pvdump(pa);*/
+#endif
+
+       if ((pind = pmap_page_index(pa)) == -1) {
+               if (pmap_debug_level >= 0)
+                       printf("no accounting\n");
+               return;
+       }
+
+       s = splimp();
+       pv = ph = &pv_table[pind];
+
+       if (ph->pv_pmap == NULL) {
+               if (pmap_debug_level >= 0)
+                       printf("free page\n");
+               splx(s);
+               return;
+       }
+
+       while (pv) {
+               pmap = pv->pv_pmap;
+               pte = pmap_pte(pmap, pv->pv_va);
+
+               if (pmap_debug_level >= 0)
+                       printf("[%08x,%08x,%08x,%08x] ", (int) pmap, *pte,
+                           (int) pv->pv_va, pv->pv_flags);
+
+#ifdef DEBUG
+               if (!pte || !pmap_pte_v(pte) || pmap_pte_pa(pte) != pa)
+                       panic("pmap_remove_all: bad mapping");
+#endif
+
+/*
+ * Update statistics
+ */
+/* Wired bit done below */
+
+/*
+               if (pmap_pte_w(pte))
+                       pmap->pm_stats.wired_count--;
+*/
+               pmap->pm_stats.resident_count--;
+
+               if (pv->pv_flags & PT_W)
+                       pmap->pm_stats.wired_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 pte at %x(%x) ", pte, *pte);
+#endif
+
+#ifdef needednotdone
+reduce wiring count on page table pages as references drop
+#endif
+
+/*
+ * Update saved attributes for managed page
+ */
+
+/*             pmap_attributes[pind] |= *pte & (PG_M | PG_U);*/
+               pmap_attributes[pind] |= pv->pv_flags & (PT_M | PT_H);
+
+               *pte = 0;
+
+               npv = pv->pv_next;
+               if (pv == ph)
+                       ph->pv_pmap = NULL;
+               else
+                       pmap_free_pv(pv);
+               pv = npv;
+       }
+       splx(s);
+
+       if (pmap_debug_level >= 0)
+               printf("done\n");
+
+       pmap_update();
+}
+
+
+/*
+ * Set the physical protection on the specified range of this map as requested.
+ */
+
+void
+pmap_protect(pmap, sva, eva, prot)
+       pmap_t pmap;
+       vm_offset_t sva;
+       vm_offset_t eva;
+       vm_prot_t prot;
+{
+       register pt_entry_t *pte = NULL;
+       register int armprot;
+       int flush = 0;
+       vm_offset_t pa;
+       int pind;
+
+       if (pmap_debug_level >= 0)
+               printf("pmap_protect: pmap=%08x %08x->%08x %08x\n",
+                   (int) pmap, (int) sva, (int) eva, prot);
+
+       if ((prot & VM_PROT_READ) == VM_PROT_NONE) {
+               pmap_remove(pmap, sva, eva);
+               return;
+       }
+       if (prot & VM_PROT_WRITE)
+               return;
+
+       sva &= PG_FRAME;
+       eva &= PG_FRAME;
+
+/*
+ * We need to acquire a pointer to a page table page before entering
+ * the following loop.
+ */
+
+       while (sva < eva) {
+               pte = pmap_pte(pmap, sva);
+               if (pte)
+                       break;
+               sva = (sva & PD_MASK) + NBPD;
+       }
+
+       while (sva < eva) {
+/*printf("pmap_protect: sva = %08x eva=%08x\n", sva, eva);*/
+/* only check once in a while */
+               if ((sva & PT_MASK) == 0) {
+                       if (!pmap_pde_v(pmap_pde(pmap, sva))) {
+/* We can race ahead here, to the next pde. */
+                               sva += NBPD;
+                               pte += arm_byte_to_page(NBPD);
+                               continue;
+                       }
+               }
+
+               if (!pmap_pte_v(pte))
+                       goto next;
+
+               flush = 1;
+
+               armprot = 0;
+/*
+               if (prot & VM_PROT_WRITE)
+                       armprot |= PT_AP(AP_W);
+*/
+               if (sva < VM_MAXUSER_ADDRESS)
+                       armprot |= PT_AP(AP_U);
+               else if (sva < VM_MAX_ADDRESS)
+                       armprot |= PT_AP(AP_W);  /* XXX Ekk what is this ? */
+               *pte = (*pte & 0xfffff00f) | armprot;
+
+               pa = pmap_pte_pa(pte);
+
+/* Get the physical page index */
+
+               if ((pind = pmap_page_index(pa)) == -1)
+                       panic("pmap_protect: pmap_page_index failed for pte %08x\n", pte); 
+
+/* Clear write flag */
+
+               pmap_modify_pv(pmap, sva, pind, PT_Wr, 0);
+next:
+               sva += NBPG;
+               pte++;
+       }
+
+       if (flush)
+               pmap_update();
+}
+
+
+/*
+ * void pmap_enter(pmap_t pmap, vm_offset_t va, vm_offset_t pa, vm_prot_t prot,
+ * boolean_t wired)
+ *  
+ *      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)
+       pmap_t pmap;
+       vm_offset_t va;
+       vm_offset_t pa;
+       vm_prot_t prot;
+       boolean_t wired;
+{
+       register pt_entry_t *pte;
+       register u_int npte;
+       int pind = -2;
+       u_int cacheable = 0;
+
+#if PMAP_DEBUG > 5
+       printf("pmap_enter: V%08x P%08x in pmap V%08x\n", va, pa, pmap);
+#endif
+
+       if (pmap_debug_level >= 5)
+               printf("pmap_enter: V%08x P%08x in pmap V%08x prot=%08x, wired = %d\n",
+                   (int) va, (int) pa, (int) pmap, prot, wired);
+
+/* Valid pmap ? */
+
+       if (pmap == NULL)
+               return;
+
+/* Valid address ? */
+                        
+       if (va >= VM_KERNEL_VIRTUAL_MAX)
+               panic("pmap_enter: too big");
+
+/*
+ * Get a pointer to the pte for this virtual address. We should always have
+ * a page table ready for us so if the page table is missing ....
+ */
+
+       pte = pmap_pte(pmap, va);
+       if (!pte) {
+               printf("pmap_enter: pde = %08x\n", (u_int) pmap_pde(pmap, va));
+               printf("pmap_enter: pte = %08x\n", (u_int) pmap_pte(pmap, va));
+               panic("Failure 01 in pmap_enter (V%08x P%08x)\n", (u_int) va, (u_int) pa);                                               
+       }
+
+/* More debugging info */
+
+       if (pmap_debug_level >= 5) {
+               printf("pmap_enter: pte for V%08x = V%08x", (u_int) va, (u_int) pte);
+               printf(" (%08x)\n", *pte);
+       }
+
+/* Is the pte valid ? If so then this page is already mapped */
+
+    if (pmap_pte_v(pte))
+      {
+        vm_offset_t opa;
+
+/* Get the physical address of the current page mapped */
+        
+        opa = pmap_pte_pa(pte);
+
+/* Are we mapping the same page ? */
+        
+        if (opa == pa)
+          {
+            int flags;
+
+/* All we must be doing is changing the protection */
+
+            if (pmap_debug_level >= 0)
+              printf("Failure 02 in pmap_enter (V%08x P%08x)\n", (u_int) va, (u_int) pa);
+
+            pind = pmap_page_index(pa);
+            cacheable = (*pte) & PT_C;
+
+/* Has the wiring changed ? */
+
+            flags = pmap_modify_pv(pmap, va, pind, 0, 0) & PT_W;
+            if (flags && !wired)
+              --pmap->pm_stats.wired_count;
+            else if (!flags && wired)
+              ++pmap->pm_stats.wired_count;
+
+          }
+        else
+          {
+/* We are replacing the page with a new one. */
+
+            idcflush();
+
+            if (pmap_debug_level >= 0)
+              printf("Failure 03 in pmap_enter (V%08x P%08x P%08x)\n",
+                  (int) va, (int) pa, (int) opa);
+
+/*
+ * If it is part of our managed memory then we must remove it from the PV list
+ */
+
+            if ((pind = pmap_page_index(opa)) != -1)
+              {
+/*                pmap_attributes[pind] |= *pte & (PG_M | PG_U);*/
+/* pmap_remove_pv updates pmap_attribute */
+/* Adjust the wiring count if the page was wired */
+                if (pmap_remove_pv(pmap, va, pind) & PT_W)
+                  --pmap->pm_stats.wired_count;
+
+              }
+
+/* Update the wiring stats for the new page */
+
+            if (wired)
+              ++pmap->pm_stats.wired_count;
+
+/*
+ * Enter on the PV list if part of our managed memory
+ */
+            if ((pind = pmap_page_index(pa)) != -1)
+              {
+                if (pmap_enter_pv(pmap, va, pind, 0))
+                  cacheable = PT_C;
+              }
+            else
+ /*
+  * Assumption: if it is not part of our managed memory
+  * then it must be device memory which may be volatile.
+  * The video memory may be double mapped but should only be accesses from
+  * one address at a time. Will be double mapped by the X server and
+  * we must keep the cache on for performance.
+  */
+            if (pa >= videomemory.vidm_pbase
+             && pa < videomemory.vidm_pbase + videomemory.vidm_size)
+              cacheable = PT_C;
+            else 
+              cacheable = 0;
+          }
+      }
+    else
+      {
+/* pte is not valid so we must be hooking in a new page */
+
+        idcflush();
+
+        ++pmap->pm_stats.resident_count;
+        if (wired)
+          ++pmap->pm_stats.wired_count;
+
+/*
+ * Enter on the PV list if part of our managed memory
+ */
+        if ((pind = pmap_page_index(pa)) != -1)
+          {
+            if (pmap_enter_pv(pmap, va, pind, 0)) 
+              cacheable = PT_C;
+          }
+        else
+ /*
+  * Assumption: if it is not part of our managed memory
+  * then it must be device memory which may be volatile.
+  */
+          {
+ /*
+  * Bit of a hack really as all doubly mapped addresses should be uncached
+  * as the cache works on virtual addresses not physical ones.
+  * However for the video memory this kill performance and the screen
+  * should be locked anyway so there should only be one process trying
+  * to write to it at once.
+  */
+            if (pa >= videomemory.vidm_pbase
+             && pa < videomemory.vidm_pbase + videomemory.vidm_size)
+              cacheable = PT_C;
+            else 
+              cacheable = 0;
+            if (pmap_debug_level > 0)
+              printf("pmap_enter: non-managed memory mapping va=%08x pa=%08x\n",
+                 (int) va, (int) pa);
+          }          
+      }
+
+/* Construct the pte, giving the correct access */
+      
+     npte = (pa & PG_FRAME) | cacheable | PT_B;
+
+if (va == 0 && (prot & VM_PROT_WRITE))
+       printf("va=0 prot=%d\n", prot);
+
+/*if (va < VM_MIN_ADDRESS)
+  printf("pmap_enter: va=%08x\n", (u_int)va);*/
+
+/*     if (va >= VM_MIN_ADDRESS && va < VM_MAXUSER_ADDRESS && !wired)
+       npte |= L2_INVAL;
+     else*/
+       npte |= L2_SPAGE;
+
+/************ not sure about wired *************/
+
+     if (prot & VM_PROT_WRITE)
+       npte |= PT_AP(AP_W);
+
+     if (va >= VM_MIN_ADDRESS) {
+       if (va < VM_MAXUSER_ADDRESS)
+         npte |= PT_AP(AP_U);
+       else if (va < VM_MAX_ADDRESS) /* This must be a page table */
+         npte |= PT_AP(AP_W);
+     }
+
+     if (va >= VM_MIN_ADDRESS && va < VM_MAXUSER_ADDRESS && pind != -1) /* Inhibit write access for user pages */
+       *pte = (npte & ~PT_AP(AP_W));
+     else
+       *pte = npte;
+
+     if (*pte == 0)
+       {
+         panic("oopss: *pte = 0 in pmap_enter() npte=%08x\n", npte);
+       }
+
+     if (pind != -1)
+       {
+         int flags = 0;
+         
+         if (wired) flags |= PT_W;
+         flags |= npte & (PT_Wr | PT_Us);
+/*         if (flags & PT_Wr) flags |= PT_M;*/
+ #ifdef DIAGNOSTIC
+         if (pind > 0x00010000 || pind < 0)
+           {
+             printf("pind=%08x\n", pind);
+           }
+ #endif
+/*         pmap_modify_pv(pmap, va, pind, 0xffffffff, flags);*/
+         pmap_modify_pv(pmap, va, pind, ~(PT_Wr | PT_Us | PT_W), flags);
+       }    
+
+/*
+ * If we are mapping in a page to where the page tables are store then we
+ * must be mapping a page table. In this case we should also map the
+ * page table into the page directory
+ */
+    if (va >= 0xefc00000 && va < 0xf0000000)
+      {
+        if (pmap_debug_level >= 0)
+          {
+            printf("Page being mapped in the page table area\n");
+            printf("page P%08x will be installed in the L1 table as well\n",
+               (int) pa);
+          }
+        pa = pa & PG_FRAME;
+        pmap->pm_pdir[((va - 0xefc00000)>>10)+0] = L1_PTE(pa + 0x000);
+        pmap->pm_pdir[((va - 0xefc00000)>>10)+1] = L1_PTE(pa + 0x400);
+        pmap->pm_pdir[((va - 0xefc00000)>>10)+2] = L1_PTE(pa + 0x800);
+        pmap->pm_pdir[((va - 0xefc00000)>>10)+3] = L1_PTE(pa + 0xc00);
+      }
+
+/* Better flush the TLB ... */
+
+    tlbflush();
+
+#if PMAP_DEBUG > 5
+     printf("pmap_enter: pte = V%08x %08x\n", pte, *pte);
+#endif
+  }
+
+
+/*
+ * 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;
+{
+       if (pmap_debug_level >= 0)
+               printf("pmap_page_protect: pa=%08x, prot=%d\n", (int) phys, 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)
+       pmap_t pmap;
+       vm_offset_t va;
+       boolean_t wired;
+{
+       register pt_entry_t *pte;
+       vm_offset_t pa;
+       int pind;
+       int current;
+
+/* Get the pte */
+
+       pte = pmap_pte(pmap, va);
+       if (!pte)
+               return;
+
+/* Extract the physical address of the page */
+
+       pa = pmap_pte_pa(pte);
+
+/* Get the physical page index */
+
+       if ((pind = pmap_page_index(pa)) == -1)
+               return; 
+
+/* Update the wired bit in the pv entry for this page. */
+
+       current = pmap_modify_pv(pmap, va, pind, PT_W, wired ? PT_W : 0) & PT_W;
+
+/* Update the statistics */
+
+       if (wired & !current)
+               pmap->pm_stats.wired_count++;
+       else if (!wired && current)
+               pmap->pm_stats.wired_count--;
+}
+
+
+/*
+ * pt_entry_t *pmap_pte(pmap_t pmap, vm_offset_t va)
+ *
+ * Return the pointer to a page table entry corresponding to the supplied
+ * virtual address.
+ *
+ * The page directory is first checked to make sure that a page table
+ * for the address in question exists and if it does a pointer to the
+ * entry is returned.
+ *
+ * The way this works is that that the kernel page tables are mapped
+ * into the memory map at 0xf3c00000 to 0xf3fffffff. This allows
+ * page tables to be located quickly.
+ */
+pt_entry_t *
+pmap_pte(pmap, va)
+       pmap_t pmap;
+       vm_offset_t va;
+{
+       pd_entry_t *pde;
+       pt_entry_t *ptp;
+       pt_entry_t *result;
+       int s;
+
+/* The pmap must be valid */
+                        
+       if (!pmap)
+               return(NULL);
+
+/* Return the address of the pte */
+
+#if PMAP_DEBUG > 10
+       printf("pmap_pte: pmap=V%08x va=V%08x pde = V%08x", pmap, va,
+          pmap_pde(pmap, va));
+       printf(" (%08x)\n", *(pmap_pde(pmap, va)));
+#endif
+
+       if (pmap_debug_level >= 10) {
+               printf("pmap_pte: pmap=V%08x va=V%08x pde = V%08x", (int) pmap,
+                   (int) va, (int) pmap_pde(pmap, va));
+               printf(" (%08x)\n", *(pmap_pde(pmap, va)));
+       }
+
+/* Do we have a valid pde ? If not we don't have a page table */
+
+       if (!pmap_pde_v(pmap_pde(pmap, va))) {
+               if (pmap_debug_level >= 0)
+                       printf("pmap_pte: failed - pde = %08x\n", (int) pmap_pde(pmap, va));
+               return(NULL); 
+       }
+
+       if (pmap_debug_level >= 10)
+               printf("pmap pagetable = P%08x current = P%08x\n", (int) pmap->pm_pptpt,
+                   (*((pt_entry_t *)(PROCESS_PAGE_TBLS_BASE
+                   + (PROCESS_PAGE_TBLS_BASE >> (PGSHIFT-2))+0xefc)) & PG_FRAME));
+
+       if (pmap == kernel_pmap || pmap->pm_pptpt
+           == (*((pt_entry_t *)(PROCESS_PAGE_TBLS_BASE
+           + ((PROCESS_PAGE_TBLS_BASE >> (PGSHIFT-2)) & ~3)+0xefc)) & PG_FRAME)) {
+               ptp = (pt_entry_t *)PROCESS_PAGE_TBLS_BASE;
+       } else {
+               pde = (pd_entry_t *)CURRENT_PAGEDIR_BASE;        
+               idcflush();
+          
+/*printf("\x1b[33mpde=%08x kernel pmap=%08x pmap=%08x\x1b[0m\n", pde, kernel_pmap, pmap);*/
+               ptp = (pt_entry_t *)ALT_PAGE_TBLS_BASE;
+               pde[(ALT_PAGE_TBLS_BASE >> 20) + 0] = L1_PTE(pmap->pm_pptpt + 0x000);
+               pde[(ALT_PAGE_TBLS_BASE >> 20) + 1] = L1_PTE(pmap->pm_pptpt + 0x400);
+               pde[(ALT_PAGE_TBLS_BASE >> 20) + 2] = L1_PTE(pmap->pm_pptpt + 0x800);
+               pde[(ALT_PAGE_TBLS_BASE >> 20) + 3] = L1_PTE(pmap->pm_pptpt + 0xc00);
+
+               *((pt_entry_t *)(PROCESS_PAGE_TBLS_BASE + ((PROCESS_PAGE_TBLS_BASE
+                   >> (PGSHIFT-2)) & ~3) + (ALT_PAGE_TBLS_BASE >> 20))) =
+                   L2_PTE(pmap->pm_pptpt, AP_KRWUR);
+               tlbflush();
+       }
+       if (pmap_debug_level >= 10)
+               printf("page tables base = %08x\n", (int) ptp);
+       result = (pt_entry_t *)((char *)ptp + ((va >> (PGSHIFT-2)) & ~3));
+       return(result);
+}                                                                         
+
+
+/*
+ * Routine:  pmap_extract
+ * Function:
+ *           Extract the physical page address associated
+ *           with the given map/virtual_address pair.
+ */
+
+vm_offset_t
+pmap_extract(pmap, va)
+       pmap_t pmap;
+       vm_offset_t va;
+{
+       register pt_entry_t *pte;
+       register vm_offset_t pa;
+/*
+       printf("pmap_extract: pmap = %08x va = V%08x\n", pmap, va);
+*/
+
+/*
+ * Get the pte for this virtual address. If there is no pte then there is
+ * no page table etc.
+ */
+  
+       pte = pmap_pte(pmap, va);
+       if (!pte)
+               return(0);
+
+/* Is the pte valid ? If not then no paged is actually mapped here */
+
+       if (!pmap_pte_v(pte))
+               return(0);
+
+/* Extract the physical address from the pte */
+
+       pa = pmap_pte_pa(pte);
+
+/* printf("pmap_extract: pa = P%08x\n", (pa | (va & ~PG_FRAME))); */  
+
+       return(pa | (va & ~PG_FRAME));
+}
+
+
+#if 0  /* Macro in pmap.h */
+pt_entry_t *
+vtopte(va)
+       vm_offset_t va;
+{
+       return((pt_entry_t *)(PROCESS_PAGE_TBLS_BASE
+               + (arm_byte_to_page(va) << 2)));
+}
+#endif
+
+#if 0  /* Macro in pmap.h */
+u_int
+vtophys(va)
+       vm_offset_t va;
+{
+       return((*vtopte(va) & PG_FRAME) | ((unsigned)(va) & ~PG_FRAME));
+}       
+#endif
+
+
+/*
+ * 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;
+{
+       if (pmap_debug_level >= 0)
+               printf("pmap_copy(%x, %x, %x, %x, %x)\n",
+                   (int) dst_pmap, (int) src_pmap, (int) dst_addr,
+                   (int) len, (int) src_addr);
+}
+
+
+void
+pmap_dump_pvlist(phys, m)
+       vm_offset_t phys;
+       char *m;
+{
+       register struct pv_entry *pv;
+
+       if (!pv_table)
+               return;
+       printf("%s %08x:", m, (int) phys);
+       pv = &pv_table[pmap_page_index(phys)];
+       if (pv->pv_pmap == NULL) {
+               printf(" no mappings\n");
+               return;
+       }
+
+       for (; pv; pv = pv->pv_next)
+               printf(" pmap %08x va %08x flags %08x", (int) pv->pv_pmap,
+                   (int) pv->pv_va, pv->pv_flags);
+
+       printf("\n");
+}
+
+
+void
+pmap_dump_pvs()
+{
+       register struct pv_entry *pv;
+       register int loop;
+
+       if (!pv_table)
+               return;
+       printf("pv dump\n");
+
+       for (loop = 0; loop < npages; ++loop) {
+               pv = &pv_table[loop];
+               if (pv->pv_pmap != NULL) {
+                       printf("%4d : ", loop);
+                       for (; pv; pv = pv->pv_next) {
+                               printf(" pmap %08x va %08x flags %08x", (int) pv->pv_pmap,
+                                   (int) pv->pv_va, pv->pv_flags);
+                       }
+                       printf("\n");
+               }
+       }
+  }
+
+
+boolean_t
+pmap_testbit(pa, setbits)
+       vm_offset_t pa;
+       int setbits;
+{
+       register struct pv_entry *pv;
+/*     register pt_entry_t *pte;*/
+       int pind;
+       int s;
+
+       if (pmap_debug_level >= 1)
+               printf("pmap_testbit: pa=%08x set=%08x\n", (int) pa, setbits);
+
+       if (pv_table == NULL || pmap_attributes == NULL)
+               return(FALSE);
+
+       if ((pind = pmap_page_index(pa)) == -1)
+               return(FALSE);
+
+       s = splimp();
+       pv = &pv_table[pind];
+
+/*
+       if (pmap_debug_level >= 0)
+               printf("pmap_attributes = %02x\n", pmap_attributes[pind]);
+*/
+
+/*
+ * Check saved info first
+ */
+
+       if (pmap_attributes[pind] & setbits) {
+               if (pmap_debug_level >= 0)
+                       printf("pmap_attributes = %02x\n", pmap_attributes[pind]);
+
+               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 = pmap_pte(pv->pv_pmap, pv->pv_va);*/
+
+/* The write bit is in the flags */
+
+                       if ((pv->pv_flags & setbits) /*|| (*pte & (setbits & PT_Wr))*/) {
+                               splx(s);
+                               return(TRUE);
+                       }
+                       if ((setbits & PT_M) && pv->pv_va >= VM_MAXUSER_ADDRESS) {
+                               splx(s);
+                               return(TRUE);
+                       }
+                       if ((setbits & PT_H) && pv->pv_va >= VM_MAXUSER_ADDRESS) {
+                               splx(s);
+                               return(TRUE);
+                       }
+               }
+       }
+
+       splx(s);
+       return(FALSE);
+}
+
+
+/*
+ * Modify pte bits for all ptes corresponding to the given physical address.
+ * We use `maskbits' rather than `clearbits' because we're always passing
+ * constants and the latter would require an extra inversion at run-time.
+ */
+
+void
+pmap_changebit(pa, setbits, maskbits)
+       vm_offset_t pa;
+       int setbits;
+       int maskbits;
+{
+       register struct pv_entry *pv;
+       register pt_entry_t *pte;
+       vm_offset_t va;
+       int pind;
+       int s;
+
+       if (pmap_debug_level >= 1)
+               printf("pmap_changebit: pa=%08x set=%08x mask=%08x\n",
+                   (int) pa, setbits, maskbits);
+
+       if (pv_table == NULL || pmap_attributes == NULL)
+               return;
+
+       if ((pind = pmap_page_index(pa)) == -1)
+               return;
+
+       s = splimp();
+       pv = &pv_table[pind];
+
+/*
+ * Clear saved attributes (modify, reference)
+ */
+
+       if (pmap_debug_level >= 0 && pmap_attributes[pind])
+               printf("pmap_attributes = %02x\n", pmap_attributes[pind]);
+
+       if (~maskbits)
+                pmap_attributes[pind] &= maskbits;
+
+/*
+ * Loop over all current mappings setting/clearing as appropos
+ */
+
+       if (pv->pv_pmap != NULL) {
+               for (; pv; pv = pv->pv_next) {
+                       va = pv->pv_va;
+
+/*
+ * XXX don't write protect pager mappings
+ */
+
+                       if (maskbits == ~PT_Wr) {
+                               extern vm_offset_t pager_sva, pager_eva;
+
+                               if (va >= pager_sva && va < pager_eva)
+                                       continue;
+                       }
+
+                       pv->pv_flags = (pv->pv_flags & maskbits) | setbits;
+                       pte = pmap_pte(pv->pv_pmap, va);
+                       if ((maskbits & PT_Wr) == 0)
+                               *pte = (*pte) & ~PT_AP(AP_W);
+                       if (setbits & PT_Wr)
+                               *pte = (*pte) | PT_AP(AP_W);
+/*
+                       if ((maskbits & PT_H) == 0)
+                               *pte = ((*pte) & ~L2_MASK) | L2_INVAL;
+*/
+               }
+               pmap_update();
+       }
+       splx(s);
+}
+
+
+void
+pmap_clear_modify(pa)
+       vm_offset_t pa;
+{
+       if (pmap_debug_level >= 0)
+               printf("pmap_clear_modify pa=%08x\n", (int) pa);
+       pmap_changebit(pa, 0, ~PT_M);
+}
+
+
+void
+pmap_clear_reference(pa)
+       vm_offset_t pa;
+{
+       if (pmap_debug_level >= 0)
+               printf("pmap_clear_reference pa=%08x\n", (int) pa);
+       pmap_changebit(pa, 0, ~PT_H);
+}
+
+
+void
+pmap_copy_on_write(pa)
+       vm_offset_t pa;
+{
+       if (pmap_debug_level >= 0)
+               printf("pmap_copy_on_write pa=%08x\n", (int) pa);
+       pmap_changebit(pa, 0, ~PT_Wr);
+}
+
+boolean_t
+pmap_is_modified(pa)
+       vm_offset_t pa;
+{
+       boolean_t result;
+    
+       result = pmap_testbit(pa, PT_M);
+       if (pmap_debug_level >= 0)
+               printf("pmap_is_modified pa=%08x %08x\n", (int) pa, result);
+
+       return(result);
+}
+
+
+boolean_t
+pmap_is_referenced(pa)
+       vm_offset_t pa;
+{
+       boolean_t result;
+/*     int pind;*/
+       
+       result = pmap_testbit(pa, PT_H);
+       if (pmap_debug_level >= 0)
+               printf("pmap_is_referenced pa=%08x %08x\n", (int) pa, result);
+
+       return(result);
+}
+
+
+int
+pmap_modified_emulation(pmap, va)
+       pmap_t pmap;
+       vm_offset_t va;
+{
+       pt_entry_t *pte;
+       vm_offset_t pa;
+       int pind;
+       u_int flags;
+
+/* Get the pte */
+
+       pte = pmap_pte(pmap, va);
+       if (!pte)
+               return(0);
+
+/* Extract the physical address of the page */
+
+       pa = pmap_pte_pa(pte);
+
+/* Get the physical page index */
+
+       if ((pind = pmap_page_index(pa)) == -1)
+               return(0); 
+
+/* Get the current flags for this page. */
+
+       flags = pmap_modify_pv(pmap, va, pind, 0, 0);
+       if (pmap_debug_level > 2)
+               printf("pmap_modified_emulation: flags = %08x\n", flags);
+
+/*
+ * Do the flags say this page is writable ? If not then it is a genuine
+ * write fault. If yes then the write fault is our fault as we did not
+ * reflect the write access in the PTE. Now we know a write has occurred
+ * we can correct this and also set the modified bit
+ */
+       if (!(flags & PT_Wr))
+               return(0);
+
+       if (pmap_debug_level > 0)
+               printf("pmap_modified_emulation: Got a hit va=%08x\n", (int) va);
+
+       if (pmap_debug_level > 0)
+               printf("pte = %08x (%08x)", (int) pte, *pte);
+       *pte = *pte | PT_AP(AP_W);
+       if (pmap_debug_level > 0)
+               printf("->(%08x)\n", *pte);
+
+       tlbflush();
+    
+/*     pmap_modify_pv(pmap, va, pind, PT_M, PT_M);*/
+
+       if (pmap_attributes)
+               pmap_attributes[pind] |= PT_M;
+
+/*     panic("pmap_modified_emulation: Not yet completed\n");*/
+
+/* Return, indicating the problem has been dealt with */
+
+       return(1);
+}
+
+
+int
+pmap_handled_emulation(pmap, va)
+       pmap_t pmap;
+       vm_offset_t va;
+{
+       pt_entry_t *pte;
+       vm_offset_t pa;
+       int pind;
+/*     u_int flags;*/
+
+       if (pmap_debug_level > 2)
+               printf("pmap_handled_emulation\n");
+
+/*     return(0);*/
+/* Get the pte */
+
+       pte = pmap_pte(pmap, va);
+       if (!pte) {
+               if (pmap_debug_level > 2)
+                       printf("no pte\n");
+               return(0);
+       }
+
+/* Check for a zero pte */
+
+       if (pmap_debug_level > 1)
+               printf("*pte=%08x\n", *pte);
+
+       if (*pte == 0)
+               return(0);
+
+       if (pmap_debug_level > 1)
+               printf("pmap_handled_emulation: non zero pte %08x\n", *pte);
+
+/* Have we marked a valid pte as invalid ? */
+
+       if (((*pte) & L2_MASK) != L2_INVAL)
+               return(0);
+
+       if (pmap_debug_level >=-1)
+               printf("Got an invalid pte\n");
+
+/* Extract the physical address of the page */
+
+       pa = pmap_pte_pa(pte);
+
+/* Get the physical page index */
+
+       if ((pind = pmap_page_index(pa)) == -1)
+               return(0); 
+
+/*
+ * Ok we just enable the pte and mark the flags as handled
+ */
+
+       if (pmap_debug_level > 0)
+               printf("pmap_handled_emulation: Got a hit va=%08x\n", (int) va);
+
+       if (pmap_debug_level > 0)
+               printf("pte = %08x (%08x)", (int) pte, *pte);
+       *pte = ((*pte) & ~L2_MASK) | L2_SPAGE;
+       if (pmap_debug_level > 0)
+               printf("->(%08x)\n", *pte);
+
+       tlbflush();
+
+       if (pmap_attributes)
+               pmap_attributes[pind] |= PT_H;
+
+/* Return, indicating the problem has been dealt with */
+
+       return(1);
+}
+
+
+void
+pmap_pagedir_dump()
+{
+       int loop;
+
+       printf("PD   pmap        PD   pmap\n");
+
+       for (loop = 0; loop < max_processes / 2; ++loop) {
+               printf("%2d %08x      %2d %08x\n", loop,
+                   (int) pagedirectories[loop], loop + max_processes / 2,
+                   (int) pagedirectories[loop + max_processes / 2]);
+       }
+}
+
+
+int
+pmap_page_attributes(va)
+       vm_offset_t va;
+{
+       vm_offset_t pa;
+       int pind;
+
+/* Get the physical page */
+
+       pa = (vm_offset_t)vtopte(va);
+
+/* Get the physical page index */
+
+       if ((pind = pmap_page_index(pa)) == -1)
+               return(-1); 
+
+       if (pmap_attributes)
+               return((int)pmap_attributes[pind]);
+
+       return(-1);
+}
+
+#if 0  /* Macro in pmap.h */
+vm_offset_t
+pmap_phys_address(ppn)
+       int ppn;
+{
+       return(arm_page_to_byte(ppn));
+}
+#endif
+
+
+void
+pmap_collect(pmap)
+       pmap_t pmap;
+{
+}
+  
+/* End of pmap.c */
diff --git a/sys/arch/arm32/arm32/postmortem.c b/sys/arch/arm32/arm32/postmortem.c
new file mode 100644 (file)
index 0000000..0b855e3
--- /dev/null
@@ -0,0 +1,336 @@
+/* $NetBSD: postmortem.c,v 1.4 1996/03/13 21:26:52 mark Exp $ */
+
+/*
+ * Copyright (c) 1994,1995 Mark Brinicombe.
+ * 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 Mark Brinicombe.
+ * 4. The name of the company nor the name of the author may 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 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.
+ *
+ * RiscBSD kernel project
+ *
+ * postmortem.c
+ *
+ * Postmortem routines
+ *
+ * Created      : 17/09/94
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/proc.h>
+#include <sys/user.h>
+#include <machine/db_machdep.h>
+#include <ddb/db_sym.h>
+#include <machine/frame.h>
+#include <machine/katelib.h>
+
+#ifdef POSTMORTEM
+
+typedef struct {
+       vm_offset_t physical;
+       vm_offset_t virtual;
+} pv_addr_t;
+
+extern pv_addr_t irqstack;
+extern pv_addr_t undstack;
+extern pv_addr_t abtstack;
+extern struct proc *proc1;
+
+int usertraceback = 0;
+
+/* dumpb - dumps memory in bytes */
+
+void
+pm_dumpb(addr, count)
+       u_char *addr;
+       int count;
+{
+       u_int byte;
+       int loop;
+
+       for (; count > 0; count -= 16) {
+               printf("%08x: ", (int)addr);
+
+               for (loop = 0; loop < 16; ++loop) {
+                       byte = addr[loop];
+                       printf("%02x ", byte);
+               }
+
+               printf(" ");
+
+               for (loop = 0; loop < 16; ++loop) {
+                       byte = addr[loop];
+                       if (byte < 0x20)
+                               printf("\x1b[31m%c\x1b[0m", byte + '@');
+                       else if (byte == 0x7f)
+                               printf("\x1b[31m?\x1b[0m");
+                       else if (byte < 0x80)
+                               printf("%c", byte);
+                       else if (byte < 0xa0)
+                               printf("\x1b[32m%c\x1b[0m", byte - '@');
+                       else if (byte == 0xff)
+                               printf("\x1b[32m?\x1b[0m");
+                       else
+                               printf("%c", byte & 0x7f);
+               }
+
+               printf("\r\n");
+               addr += 16;
+       }
+}
+
+
+/* dumpw - dumps memory in bytes */
+
+void
+pm_dumpw(addr, count)
+       u_char *addr;
+       int count;
+{
+       u_int byte;
+       int loop;
+
+       for (; count > 0; count -= 32) {
+               printf("%08x: ", (int)addr);
+
+               for (loop = 0; loop < 8; ++loop) {
+                       byte = ((u_int *)addr)[loop];
+                       printf("%08x ", byte);
+               }
+
+               printf(" ");
+
+               for (loop = 0; loop < 32; ++loop) {
+                       byte = addr[loop];
+                       if (byte < 0x20)
+                               printf("\x1b[31m%c\x1b[0m", byte + '@');
+                       else if (byte == 0x7f)
+                               printf("\x1b[31m?\x1b[0m");
+                       else if (byte < 0x80)
+                               printf("%c", byte);
+                       else if (byte < 0xa0)
+                               printf("\x1b[32m%c\x1b[0m", byte - '@');
+                       else if (byte == 0xff)
+                               printf("\x1b[32m?\x1b[0m");
+                       else
+                               printf("%c", byte & 0x7f);
+               }
+
+               printf("\r\n");
+               addr += 32;
+       }
+}
+
+
+/* Dump a trap frame */
+
+void
+dumpframe(frame)
+       trapframe_t *frame;
+{
+       u_int s;
+    
+       s = splhigh();
+       printf("frame address = %08x  ", (u_int)frame);
+       printf("spsr =%08x\n", frame->tf_spsr);
+       printf("r0 =%08x r1 =%08x r2 =%08x r3 =%08x\n", frame->tf_r0, frame->tf_r1, frame->tf_r2, frame->tf_r3);
+       printf("r4 =%08x r5 =%08x r6 =%08x r7 =%08x\n", frame->tf_r4, frame->tf_r5, frame->tf_r6, frame->tf_r7);
+       printf("r8 =%08x r9 =%08x r10=%08x r11=%08x\n", frame->tf_r8, frame->tf_r9, frame->tf_r10, frame->tf_r11);
+       printf("r12=%08x r13=%08x r14=%08x r15=%08x\n", frame->tf_r12, frame->tf_usr_sp, frame->tf_usr_lr, frame->tf_pc);
+       printf("slr=%08x\n", frame->tf_svc_lr);
+
+       (void)splx(s);
+}
+
+
+/* Dump kstack information */
+/*
+void kstack_stuff(p)
+       struct proc *p;
+{
+       struct pmap *pmap;
+
+       if (p == 0) return;
+       if (p->p_addr == 0) return;
+       if (p->p_vmspace == 0) return;
+       
+       printf("proc=%08x comm=%s pid=%d\n", (u_int)p, p->p_comm, p->p_pid);
+       
+       pmap = &p->p_vmspace->vm_pmap;
+
+       printf("pmap=%08x\n", (u_int)pmap);
+
+       printf("p->p_addr=%08x pa=%08x,%d:%08x,%d\n",
+           (u_int)p->p_addr,
+           (u_int)pmap_extract(pmap, (vm_offset_t)p->p_addr),
+           pmap_page_index(pmap_extract(pmap, (vm_offset_t)p->p_addr)),
+           (u_int)pmap_extract(pmap, (vm_offset_t)p->p_addr + NBPG),
+           pmap_page_index(pmap_extract(pmap, (vm_offset_t)p->p_addr + NBPG)));
+}
+*/
+
+void
+check_stacks(p)
+       struct proc *p;
+{
+       u_char *ptr;
+       int loop;
+
+       if (p) {
+               ptr = ((u_char *)p->p_addr) + USPACE_UNDEF_STACK_BOTTOM;
+               for (loop = 0; loop < (USPACE_UNDEF_STACK_TOP - USPACE_UNDEF_STACK_BOTTOM) && *ptr == 0xdd; ++loop, ++ptr) ;
+               printf("%d bytes of undefined stack fill pattern out of %d bytes\n", loop,
+                   USPACE_UNDEF_STACK_TOP - USPACE_UNDEF_STACK_BOTTOM);
+               ptr = ((u_char *)p->p_addr) + USPACE_SVC_STACK_BOTTOM;
+               for (loop = 0; loop < (USPACE_SVC_STACK_TOP - USPACE_SVC_STACK_BOTTOM) && *ptr == 0xdd; ++loop, ++ptr) ;
+               printf("%d bytes of svc stack fill pattern out of %d bytes\n", loop,
+                   USPACE_SVC_STACK_TOP - USPACE_SVC_STACK_BOTTOM);
+       }
+}
+
+
+/* Perform a postmortem */
+
+void
+postmortem(frame)
+       trapframe_t *frame;
+{
+       u_int s;
+       struct proc *p = curproc;
+       int loop;
+       u_int addr;
+                       
+       s = splhigh();
+
+/* Check the stack for a known pattern */
+
+       check_stacks(p);
+
+#ifdef ROTTEN_INARDS
+       addr = traceback();
+
+       dumpframe(frame);
+
+       printf("curproc=%08x paddr=%08x pcb=%08x curpcb=%08x\n",
+           (u_int) curproc, (u_int) curproc->p_addr,
+           (u_int) &curproc->p_addr->u_pcb, (u_int) curpcb);
+       printf("CPSR=%08x ", GetCPSR());
+
+       printf("Process = %08x ", (u_int)curproc);
+       printf("pid = %d ", curproc->p_pid); 
+       printf("comm = %s\n", curproc->p_comm); 
+
+       pm_dumpw(irqstack.virtual + NBPG - 0x100, 0x100);
+       pm_dumpw(undstack.virtual + NBPG - 0x20, 0x20);
+       pm_dumpw(abtstack.virtual + NBPG - 0x20, 0x20);
+
+       printf("abt_sp=%08x irq_sp=%08x und_sp=%08x svc_sp=%08x\n",
+           get_stackptr(PSR_ABT32_MODE),
+           get_stackptr(PSR_IRQ32_MODE),
+           get_stackptr(PSR_UND32_MODE),
+           get_stackptr(PSR_SVC32_MODE));
+
+       if (curpcb)
+               printf("curpcb=%08x pcb_sp=%08x pcb_und_sp=%08x\n", curpcb, curpcb->pcb_sp, curpcb->pcb_und_sp);
+
+       printf("proc0=%08x paddr=%08x pcb=%08x\n", (u_int)&proc0,
+           (u_int)proc0.p_addr, (u_int) &proc0.p_addr->u_pcb);
+
+/*
+       kstack_stuff(&proc0);
+       kstack_stuff(curproc);
+*/
+#else
+       printf("Process = %08x ", (u_int)curproc);
+       printf("pid = %d ", curproc->p_pid); 
+       printf("comm = %s\n", curproc->p_comm); 
+       printf("CPSR=%08x ", GetCPSR());
+
+       printf("Traceback info\n");
+       addr = simpletraceback();
+       printf("Trapframe PC = %08x\n", frame->tf_pc);
+       printf("Trapframe SPSR = %08x\n", frame->tf_spsr);
+
+       if (usertraceback) {
+               printf("Attempting user trackback\n");
+               user_traceback(frame->tf_r11);
+       }
+
+#endif
+       if ((frame->tf_spsr & PSR_MODE) == PSR_IRQ32_MODE
+           && addr >= irqstack.virtual && addr < (irqstack.virtual + NBPG)) {
+               printf("Trap occurred in IRQ\n");
+               printf("IRQ Traceback info\n");
+               irqtraceback(addr, irqstack.virtual);
+       }
+       (void)splx(s);
+}
+
+
+void
+buried_alive(p)
+       struct proc *p;
+{
+       printf("Ok major screw up detected on kernel stack\n");
+       printf("Putting the process down to minimise further trashing\n");
+       printf("Process was %08x pid=%d comm=%s\n", (u_int) p, p->p_pid, p->p_comm);
+
+}
+#else
+void
+postmortem(frame)
+       trapframe_t *frame;
+{
+       printf("No postmortem support compiled in\n");  
+}
+
+void
+buried_alive(p)
+       struct proc *p;
+{
+}
+#endif
+
+void
+traceback_sym(lr, pc)
+       u_int lr;
+       u_int pc;
+{
+#ifdef DDB
+       printf("fp->lr=%08x fp->pc=%08x\n", lr, pc);
+/*     printf("fp->lr=");
+       db_printsym((db_addr_t)(lr), DB_STGY_ANY);
+       printf(" fp->pc=");
+       db_printsym((db_addr_t)(pc), DB_STGY_ANY);      
+       printf("\n");*/
+#else
+       printf("fp->lr=%08x fp->pc=%08x\n", lr, pc);
+#endif
+}
+
+/* End of postmortem.c */
diff --git a/sys/arch/arm32/arm32/process_machdep.c b/sys/arch/arm32/arm32/process_machdep.c
new file mode 100644 (file)
index 0000000..2a08784
--- /dev/null
@@ -0,0 +1,178 @@
+/* $NetBSD: process_machdep.c,v 1.2 1996/03/27 22:42:26 mark Exp $ */
+
+/*
+ * Copyright (c) 1995 Frank Lancaster.  All rights reserved.
+ * Copyright (c) 1995 Tools GmbH.  All rights reserved.
+ * Copyright (c) 1995 Charles M. Hannum.  All rights reserved.
+ * Copyright (c) 1993 The Regents of the University of California.
+ * Copyright (c) 1993 Jan-Simon Pendry
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Jan-Simon Pendry.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * From:
+ *     Id: procfs_i386.c,v 4.1 1993/12/17 10:47:45 jsp Rel
+ */
+
+/*
+ * 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, sstep)
+ *     Arrange for the process to trap or not trap depending on sstep
+ *     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/reg.h>
+
+static inline struct trapframe *
+process_frame(p)
+       struct proc *p;
+{
+
+       return (p->p_md.md_regs);
+}
+
+static inline struct fp_state *
+process_fpframe(p)
+       struct proc *p;
+{
+
+        /* is this correct ? don't we need fpregs in the trapframe ?
+          or doesn't the kernel use fp ? */
+       return (&p->p_addr->u_pcb.pcb_fpstate);
+}
+
+int
+process_read_regs(p, regs)
+       struct proc *p;
+       struct reg *regs;
+{
+       struct trapframe *tf = process_frame(p);
+
+       bcopy((caddr_t)&tf->tf_r0, (caddr_t)regs->r, sizeof(regs->r));
+       regs->r_sp = tf->tf_usr_sp;
+       regs->r_lr = tf->tf_usr_lr;
+       regs->r_pc = tf->tf_pc;
+       regs->r_cpsr = tf->tf_spsr;
+
+       return (0);
+}
+
+int
+process_read_fpregs(p, regs)
+       struct proc *p;
+       struct fpreg *regs;
+{
+       struct fp_state         *statep;
+
+       /* NOTE: struct fpreg == struct fpstate */
+       statep = process_fpframe(p);
+       bcopy(statep, regs, sizeof(struct fpreg));
+       return (0);
+}
+
+int
+process_write_regs(p, regs)
+       struct proc *p;
+       struct reg *regs;
+{
+       struct trapframe *tf = process_frame(p);
+
+       bcopy((caddr_t)regs->r, (caddr_t)&tf->tf_r0, sizeof(regs->r));
+       tf->tf_usr_sp = regs->r_sp;
+       tf->tf_usr_lr = regs->r_lr;
+       tf->tf_pc = regs->r_pc;
+       tf->tf_spsr &=  ~PSR_FLAGS;
+       tf->tf_spsr |= regs->r_cpsr & PSR_FLAGS;
+
+       return (0);
+}
+
+int
+process_write_fpregs(p, regs)
+       struct proc *p;
+       struct fpreg *regs;
+{
+        struct fp_state *statep;
+
+       /* NOTE: struct fpreg == struct fpstate */
+       statep = process_fpframe(p);
+       bcopy(regs, statep, sizeof(struct fpreg));
+       return (0);
+}
+
+int
+process_sstep(p, sstep)
+       struct proc *p;
+       int sstep;
+{
+       if (sstep)
+               /* this is going to be fun, I'll start off with kgdb_step ... */
+               return (EINVAL);
+       return (0);
+}
+
+int
+process_set_pc(p, addr)
+       struct proc *p;
+       caddr_t addr;
+{
+       struct trapframe *tf = process_frame(p);
+
+       tf->tf_pc = (int)addr;
+
+       return (0);
+}
diff --git a/sys/arch/arm32/arm32/scratch.S b/sys/arch/arm32/arm32/scratch.S
new file mode 100644 (file)
index 0000000..09af00d
--- /dev/null
@@ -0,0 +1,263 @@
+/* $NetBSD: scratch.S,v 1.2 1996/02/02 02:35:49 mycroft Exp $ */
+
+/*
+ * Copyright (c) 1994,1995 Mark Brinicombe.
+ * Copyright (c) 1994 Brini.
+ * 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 Brini.
+ * 4. The name of the company nor the name of the author may be used to
+ *    endorse or promote products derived from this software without specific
+ *    prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BRINI ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL BRINI 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.
+ *
+ * RiscBSD kernel project
+ *
+ * scratch.S
+ *
+ * Miscellaneous routines scratchpad routines
+ *
+ * Created      : 02/04/95
+ * Last updated : 04/06/95
+ *
+ *    $Id: scratch.S,v 1.1.1.1 1996/04/24 11:08:28 deraadt Exp $
+ */
+
+#include "assym.h"
+
+lr     .req    r14
+pc     .req    r15
+
+.text
+
+        .global _ReadWordWithChecks
+
+/* Reads a word but traps failed faults
+ *
+ *  r0 - address to read
+ *  r1 - address to store result
+ */
+
+Lcurpcb:
+       .word   _curpcb
+
+_ReadWordWithChecks:
+       ldr     r2, Lcurpcb
+       ldr     r2, [r2]
+       teq     r2, #0x00000000
+       beq     ReadWordPCBFault
+       add     r3, pc, #ReadWordFault - . - 8
+       str     r3, [r2, #PCB_ONFAULT]
+
+       ldr     r0, [r0]
+       str     r0, [r1]
+
+       mov     r0, #0x00000000
+       str     r0, [r2, #PCB_ONFAULT]
+       mov     pc, lr
+
+ReadWordFault:
+       mov     r0, #0x00000000
+       str     r0, [r2, #PCB_ONFAULT]
+       mov     r0, #0x00000001
+       mov     pc, lr
+
+ReadWordPCBFault:
+       stmfd   sp!, {lr}
+       mov     r2, r0
+       add     r0, pc, #ReadWordText1 - . - 8
+       mov     r1, r2
+       bl      _printf
+       mov     r0, #0x00000001
+       ldmfd   sp!, {lr}
+       mov     pc, lr
+
+ReadWordText1:
+       .asciz  "Alert ! PCB = %08x during ReadWordWithChecks addr=%08x\n"
+
+
+       .global new_fuword
+
+new_fuword:
+       ldr     r2, Lcurpcb
+       ldr     r2, [r2]
+       teq     r2, #0x00000000
+       beq     fusupcbfault
+       add     r1, pc, #fusufault - . - 8
+       str     r1, [r2, #PCB_ONFAULT]
+
+       ldr     r0, [r0]
+
+       mov     r1, #0x00000000
+       str     r1, [r2, #PCB_ONFAULT]
+       mov     pc, lr
+
+       .global new_fuswintr
+
+new_fuswintr:
+       ldr     r2, Lcurpcb
+       ldr     r2, [r2]
+       teq     r2, #0x00000000
+       beq     fusupcbfault
+       add     r1, pc, #fusubailout - . - 8
+       str     r1, [r2, #PCB_ONFAULT]
+
+       ldr     r0, [r0]
+       bic     r0, r0, #0xff000000
+       bic     r0, r0, #0x00ff0000
+
+       mov     r1, #0x00000000
+       str     r1, [r2, #PCB_ONFAULT]
+       mov     pc, lr
+
+       .global new_fusword
+
+new_fusword:
+       ldr     r2, Lcurpcb
+       ldr     r2, [r2]
+       teq     r2, #0x00000000
+       beq     fusupcbfault
+       add     r1, pc, #fusufault - . - 8
+       str     r1, [r2, #PCB_ONFAULT]
+
+       ldr     r0, [r0]
+       bic     r0, r0, #0xff000000
+       bic     r0, r0, #0x00ff0000
+
+       mov     r1, #0x00000000
+       str     r1, [r2, #PCB_ONFAULT]
+       mov     pc, lr
+
+       .global new_fubyte
+
+new_fubyte:
+       ldr     r2, Lcurpcb
+       ldr     r2, [r2]
+       teq     r2, #0x00000000
+       beq     fusupcbfault
+       add     r1, pc, #fusufault - . - 8
+       str     r1, [r2, #PCB_ONFAULT]
+
+       ldrb    r0, [r0]
+
+       mov     r1, #0x00000000
+       str     r1, [r2, #PCB_ONFAULT]
+       mov     pc, lr
+
+
+fusufault:
+       mov     r0, #0x00000000
+       str     r0, [r2, #PCB_ONFAULT]
+       mvn     r0, #0x00000000
+       mov     pc, lr
+
+       .global fusubailout
+
+fusubailout:
+       mov     r0, #0x00000000
+       str     r0, [r2, #PCB_ONFAULT]
+       mvn     r0, #0x00000000
+       mov     pc, lr
+
+fusuaddrfault:
+       mvn     r0, #0x00000000
+       mov     pc, lr
+
+fusupcbfault:
+       stmfd   sp!, {lr}
+       mov     r2, r0
+       add     r0, pc, #ReadWordText1 - . - 8
+       mov     r1, r2
+       bl      _printf
+       mvn     r0, #0x00000000
+       ldmfd   sp!, {lr}
+       mov     pc, lr
+
+       .global new_suword
+
+new_suword:
+       ldr     r2, Lcurpcb
+       ldr     r2, [r2]
+       teq     r2, #0x00000000
+       beq     fusupcbfault
+       add     r3, pc, #fusufault - . - 8
+       str     r3, [r2, #PCB_ONFAULT]
+
+       str     r1, [r0]
+
+       mov     r0, #0x00000000
+       str     r0, [r2, #PCB_ONFAULT]
+       mov     pc, lr
+
+       .global new_suswintr
+
+new_suswintr:
+       ldr     r2, Lcurpcb
+       ldr     r2, [r2]
+       teq     r2, #0x00000000
+       beq     fusupcbfault
+       add     r3, pc, #fusubailout - . - 8
+       str     r3, [r2, #PCB_ONFAULT]
+
+       strb    r1, [r0, #0x0000]
+       mov     r1, r1, lsr #8
+       strb    r1, [r0, #0x0000]
+
+       mov     r0, #0x00000000
+       str     r0, [r2, #PCB_ONFAULT]
+       mov     pc, lr
+
+       .global new_susword
+
+new_susword:
+       ldr     r2, Lcurpcb
+       ldr     r2, [r2]
+       teq     r2, #0x00000000
+       beq     fusupcbfault
+       add     r3, pc, #fusufault - . - 8
+       str     r3, [r2, #PCB_ONFAULT]
+
+       strb    r1, [r0, #0x0000]
+       mov     r1, r1, lsr #8
+       strb    r1, [r0, #0x0000]
+
+       mov     r0, #0x00000000
+       str     r0, [r2, #PCB_ONFAULT]
+       mov     pc, lr
+
+       .global new_subyte
+
+new_subyte:
+       ldr     r2, Lcurpcb
+       ldr     r2, [r2]
+       teq     r2, #0x00000000
+       beq     fusupcbfault
+       add     r3, pc, #fusufault - . - 8
+       str     r3, [r2, #PCB_ONFAULT]
+
+       strb    r1, [r0]
+
+       mov     r0, #0x00000000
+       str     r0, [r2, #PCB_ONFAULT]
+       mov     pc, lr
diff --git a/sys/arch/arm32/arm32/setcpsr.S b/sys/arch/arm32/arm32/setcpsr.S
new file mode 100644 (file)
index 0000000..d62b797
--- /dev/null
@@ -0,0 +1,95 @@
+/* $NetBSD: setcpsr.S,v 1.1 1996/01/31 23:16:54 mark Exp $ */
+
+/*
+ * Copyright (c) 1994 Mark Brinicombe.
+ * Copyright (c) 1994 Brini.
+ * All rights reserved.
+ *
+ * This code is derived from software written for Brini by Mark Brinicombe
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided 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 Brini.
+ * 4. The name of the company nor the name of the author may be used to
+ *    endorse or promote products derived from this software without specific
+ *    prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BRINI ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL BRINI 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.
+ *
+ * RiscBSD kernel project
+ *
+ * setcpsr.S
+ *
+ * Miscellaneous routines to play with the CPSR register
+ *
+ * Eventually this routine can be inline assembly.
+ *
+ * Created      : 12/09/94
+ * Last updated : 28/05/95
+ *
+ * Based of kate/display/setcpsr.s
+ *
+ *    $Id: setcpsr.S,v 1.1.1.1 1996/04/24 11:08:28 deraadt Exp $
+ */
+
+fp      .req    r11
+ip      .req    r12
+sp      .req    r13
+lr     .req    r14
+pc     .req    r15
+
+.text
+
+        .global _SetCPSR
+
+/* Sets and clears bits in the CPSR register
+ *
+ *  r0 - bic mask
+ *  r1 - eor mask
+ */
+
+_SetCPSR:
+/*     mov     ip, sp
+       stmfd   sp!, {fp, ip, lr, pc}
+       sub     fp, ip, #4*/
+
+        mrs     r3, cpsr_all           /* Set the CPSR */
+       bic     r2, r3, r0
+        eor     r2, r2, r1
+        msr     cpsr_all, r2
+
+        mov    r0, r3                  /* Return the old CPSR */
+
+/*     ldmea   fp, {fp, sp, pc}*/
+       mov     pc, lr
+
+        .global _GetCPSR
+
+/* Gets the CPSR register
+ *
+ * Returns the CPSR in r0
+ */
+
+_GetCPSR:
+        mrs     r0, cpsr_all           /* Get the CPSR */
+
+       mov     pc, lr
+
diff --git a/sys/arch/arm32/arm32/setstack.S b/sys/arch/arm32/arm32/setstack.S
new file mode 100644 (file)
index 0000000..2db02ea
--- /dev/null
@@ -0,0 +1,104 @@
+/* $NetBSD: setstack.S,v 1.1 1996/01/31 23:16:59 mark Exp $ */
+
+/*
+ * Copyright (c) 1994 Mark Brinicombe.
+ * Copyright (c) 1994 Brini.
+ * All rights reserved.
+ *
+ * This code is derived from software written for Brini by Mark Brinicombe
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided 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 Brini.
+ * 4. The name of the company nor the name of the author may be used to
+ *    endorse or promote products derived from this software without specific
+ *    prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BRINI ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL BRINI 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.
+ *
+ * RiscBSD kernel project
+ *
+ * setstack.S
+ *
+ * Miscellaneous routine to play with the stack pointer in different CPU modes
+ *
+ * Eventually this routine can be inline assembly.
+ *
+ * Created      : 17/09/94
+ * Last updated : 15/10/94
+ *
+ * Based of kate/display/setstack.s
+ *
+ *    $Id: setstack.S,v 1.1.1.1 1996/04/24 11:08:28 deraadt Exp $
+ */
+
+#include <machine/cpu.h>
+
+sp     .req    r13
+lr     .req    r14
+pc     .req    r15
+
+.text
+
+       .global _set_stackptr
+
+/* To set the stack pointer for a particular mode we must switch
+ * to that mode update the banked r13 and then switch back.
+ * This routine provides an easy way of doing this for any mode
+ *
+ * r0 = CPU mode
+ * r1 = stackptr
+ */
+
+_set_stackptr:
+        mrs    r3, cpsr_all            /* Switch to the appropriate mode */
+       bic     r2, r3, #(PSR_MODE)
+       orr     r2, r2, r0
+        msr    cpsr_all, r2
+
+       mov     sp, r1                  /* Set the stack pointer */
+
+        msr    cpsr_all, r3            /* Restore the old mode */
+
+       mov     pc, lr                  /* Exit */
+
+       .global _get_stackptr
+
+/* To get the stack pointer for a particular mode we must switch
+ * to that mode copy the banked r13 and then switch back.
+ * This routine provides an easy way of doing this for any mode
+ *
+ * r0 = CPU mode
+ */
+
+_get_stackptr:
+        mrs    r3, cpsr_all            /* Switch to the appropriate mode */
+       bic     r2, r3, #(PSR_MODE)
+       orr     r2, r2, r0
+        msr    cpsr_all, r2
+
+       mov     r0, sp                  /* Set the stack pointer */
+
+        msr    cpsr_all, r3            /* Restore the old mode */
+
+       mov     pc, lr                  /* Exit */
+
+/* End of setstack.S */
diff --git a/sys/arch/arm32/arm32/spl.S b/sys/arch/arm32/arm32/spl.S
new file mode 100644 (file)
index 0000000..ac79793
--- /dev/null
@@ -0,0 +1,126 @@
+/* $NetBSD: spl.S,v 1.1 1996/03/08 18:03:15 mark Exp $ */
+
+/*
+ * Copyright (c) 1996 Mark Brinicombe.
+ * Copyright (c) Brini.
+ * 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 Brini.
+ * 4. The name of the company nor the name of the author may be used to
+ *    endorse or promote products derived from this software without specific
+ *    prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BRINI ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL BRINI 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.
+ *
+ * RiscBSD kernel project
+ *
+ * splasm.S
+ *
+ * spl routines
+ *
+ * Created      : 01/03/96
+ *
+ *    $Id: spl.S,v 1.1.1.1 1996/04/24 11:08:28 deraadt Exp $
+ */
+
+#include "assym.h"
+#include <machine/psl.h>
+
+sp     .req    r13
+lr     .req    r14
+pc     .req    r15
+
+       .text
+       .align  0
+
+Lcurrent_spl_level:
+       .word   _current_spl_level
+
+Lspl_masks:
+       .word   _spl_masks
+
+Lspl_mask:
+       .word   _spl_mask
+
+       .global _raisespl
+_raisespl:
+       mov     r3, r0                  /* Save the new value */
+       ldr     r1, Lcurrent_spl_level  /* Get the current spl level */
+       ldr     r0, [r1]
+       cmp     r3, r0
+       movle   pc, lr
+
+       str     r3, [r1]                /* Store the new spl mask */
+
+       ldr     r2, Lspl_masks          /* Get the spl mask */
+       ldr     r2, [r2, r3, lsl #2]
+
+       ldr     r1, Lspl_mask           /* Store in the current spl mask */
+       str     r2, [r1]
+
+       stmfd   sp!, {r0, lr}           /* Preserve registers */
+       bl      _irq_setmasks           /* Update the actual masks */
+       ldmfd   sp!, {r0, pc}           /* Exit */
+
+
+       .global _lowerspl
+_lowerspl:
+       mov     r3, r0                  /* Save the new value */
+       ldr     r1, Lcurrent_spl_level  /* Get the current spl level */
+       ldr     r0, [r1]
+       cmp     r3, r0
+       movge   pc, lr
+
+       str     r3, [r1]                /* Store the new spl mask */
+
+       ldr     r2, Lspl_masks          /* Get the spl mask */
+       ldr     r2, [r2, r3, lsl #2]
+
+       ldr     r1, Lspl_mask           /* Store in the current spl mask */
+       str     r2, [r1]
+
+       stmfd   sp!, {r0, lr}           /* Preserve registers */
+       bl      _irq_setmasks           /* Update the actual masks */
+       ldmfd   sp!, {r0, pc}           /* Exit */
+
+
+       .global _splx
+_splx:
+       mov     r3, r0                  /* Save the new value */
+       ldr     r1, Lcurrent_spl_level  /* Get the current spl level */
+       ldr     r0, [r1]
+       cmp     r3, r0
+       moveq   pc, lr
+
+       str     r3, [r1]                /* Store the new spl mask */
+
+       ldr     r2, Lspl_masks          /* Get the spl mask */
+       ldr     r2, [r2, r3, lsl #2]
+
+       ldr     r1, Lspl_mask           /* Store in the current spl mask */
+       str     r2, [r1]
+
+       stmfd   sp!, {r0, lr}           /* Preserve registers */
+       bl      _irq_setmasks           /* Update the actual masks */
+       ldmfd   sp!, {r0, pc}           /* Exit */
+
diff --git a/sys/arch/arm32/arm32/strstr.c b/sys/arch/arm32/arm32/strstr.c
new file mode 100644 (file)
index 0000000..5b3a0f9
--- /dev/null
@@ -0,0 +1,68 @@
+/* $NetBSD: strstr.c,v 1.2 1996/03/27 22:42:28 mark Exp $ */
+
+/*
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     from: strstr.c,v 1.4 1995/06/15 00:08:43 jtc Exp 
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+
+/*
+ * Find the first occurrence of find in s.
+ */
+
+char *
+strstr(s, find)
+       register const char *s, *find;
+{
+       register char c, sc;
+       register size_t len;
+
+       if ((c = *find++) != 0) {
+               len = strlen(find);
+               do {
+                       do {
+                               if ((sc = *s++) == 0)
+                                       return (NULL);
+                       } while (sc != c);
+               } while (strncmp(s, find, len) != 0);
+               s--;
+       }
+       return ((char *)s);
+}
+
+/* End of strstr.c */
diff --git a/sys/arch/arm32/arm32/strtoul.c b/sys/arch/arm32/arm32/strtoul.c
new file mode 100644 (file)
index 0000000..d245930
--- /dev/null
@@ -0,0 +1,83 @@
+#include <sys/param.h>
+
+#ifndef ULONG_MAX
+#define        ULONG_MAX       ((u_long)(~0L))         /* 0xFFFFFFFF */
+#endif
+
+u_long
+strtoul(s, ptr, base)
+       const char *s;
+       char **ptr;
+       int base;
+{
+       u_long total = 0;
+       u_int digit;
+       const char *start=s;
+       int did_conversion=0;
+       int overflow = 0;
+       int negate = 0;
+       u_long maxdiv, maxrem;
+
+       if (s == NULL) {
+               if (!ptr)
+                       *ptr = (char *)start;
+               return 0L;
+       }
+
+       while (*s == ' ')
+               s++;
+       if (*s == '+')
+               s++;
+       else if (*s == '-')
+               s++, negate = 1;
+       if (base==0 || base==16) { /*  the 'base==16' is for handling 0x */
+               int tmp;
+
+      /*
+       * try to infer base from the string
+       */
+               if (*s != '0')
+                       tmp = 10;       /* doesn't start with 0 - assume decimal */
+               else if (s[1] == 'X' || s[1] == 'x')
+                       tmp = 16, s += 2; /* starts with 0x or 0X - hence hex */
+               else
+                       tmp = 8;        /* starts with 0 - hence octal */
+               if (base==0)
+                       base = (int)tmp;
+       }
+
+       maxdiv = ULONG_MAX / base;
+       maxrem = ULONG_MAX % base;
+
+       while ((digit = *s) != '\0') {
+               if (digit >= '0' && digit < ('0'+base))
+                       digit -= '0';
+               else
+                       if (base > 10) {
+                               if (digit >= 'a' && digit < ('a'+(base-10)))
+                                       digit = digit - 'a' + 10;
+                               else if (digit >= 'A' && digit < ('A'+(base-10)))
+                                       digit = digit - 'A' + 10;
+                               else
+                                       break;
+                       }
+                       else
+                               break;
+                       did_conversion = 1;
+                       if (total > maxdiv
+                           || (total == maxdiv && digit > maxrem))
+                               overflow = 1;
+                       total = (total * base) + digit;
+                       s++;
+       }
+       if (overflow) {
+               if (ptr != NULL)
+                       *ptr = (char *)s;
+               return (ULONG_MAX);
+       }
+       if (ptr != NULL)
+               *ptr = (char *) ((did_conversion) ? (char *)s : (char *)start);
+       return negate ? -total : total;
+}
+
+/* End of strtoul.c */
diff --git a/sys/arch/arm32/arm32/stubs.c b/sys/arch/arm32/arm32/stubs.c
new file mode 100644 (file)
index 0000000..116bfc3
--- /dev/null
@@ -0,0 +1,618 @@
+/* $NetBSD: stubs.c,v 1.4 1996/03/08 18:41:52 mark Exp $ */
+
+/*
+ * Copyright (c) 1994,1995 Mark Brinicombe.
+ * Copyright (c) 1994 Brini.
+ * All rights reserved.
+ *
+ * This code is derived from software written for Brini by Mark Brinicombe
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided 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 Brini.
+ * 4. The name of the company nor the name of the author may be used to
+ *    endorse or promote products derived from this software without specific
+ *    prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BRINI ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL BRINI 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.
+ *
+ * RiscBSD kernel project
+ *
+ * stubs.c
+ *
+ * Routines that are temporary or do not have a home yet.
+ *
+ * Created      : 17/09/94
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/errno.h>
+#include <sys/proc.h>
+#include <sys/types.h>
+#include <sys/device.h>
+#include <sys/buf.h>
+#include <sys/exec.h>
+#include <sys/vnode.h>
+#include <sys/conf.h> 
+#include <sys/reboot.h> 
+#include <vm/vm.h>
+#include <vm/vm_kern.h>
+#include <vm/vm_page.h>
+#include <dev/ramdisk.h>
+#include <machine/param.h>
+#include <machine/vmparam.h>
+#include <machine/cpu.h>
+#include <machine/irqhandler.h>
+#include <machine/vidc.h>
+#include <machine/bootconfig.h>
+#include <machine/katelib.h>
+#include <machine/psl.h>
+
+#include "fdc.h" 
+#include "rd.h" 
+
+#define VM_MAXKERN_ADDRESS 0xf3000000
+
+extern int ffs_mountroot();
+extern int cd9660_mountroot();
+int do_mountroot();
+int (*mountroot)() = do_mountroot;
+
+extern u_int soft_interrupts;
+
+extern int msgbufmapped;
+extern dev_t rootdev;
+extern dev_t dumpdev;
+#ifdef RAMDISK_HOOKS
+extern struct rd_conf *bootrd;
+#endif
+
+extern BootConfig bootconfig;
+extern videomemory_t videomemory;
+
+int
+do_mountroot()
+{
+       struct buf *bp;
+       int loop;
+       int s;
+       int type;
+       int floppysize;
+       int error;
+
+#if (NFDC > 0 && NRD > 0 && defined(RAMDISK_HOOKS))
+
+/*
+ * Ok ideally the ramdisc would be loaded via the rd_open_hook() but since
+ * we are loading the ramdisc from floppy we only want to load it during
+ * the boot and not at any other time.
+ */
+
+/*
+ * Ok bit of bodging here. The ramdisc minor is the unit number. However if booting
+ * from the ramdisc we limit to always booting off minor 0 i.e. rd0 The ramdisc
+ * device passed as the root device is only used to identify the ramdisc major. The
+ * minor, instead of indicating the ramdisc unit is used to indicate the floppy
+ * minor that should be used for loading the boot ramdisc which is unit 0.
+ */
+
+       if (major(rootdev) == 18 && bootrd) {
+               if (load_ramdisc_from_floppy(bootrd, makedev(17, minor(rootdev))) != 0)
+                       panic("Failed to load ramdisc\n");
+               boothowto |= RB_SINGLE;
+               rootdev = makedev(major(rootdev), 0);
+       }
+#endif
+
+/*
+ * Slight bug with mounting CD's sometimes. The first mount may fail
+ * so we will try again. This only happens with the temporary ATAPI
+ * CDROM driver we are using
+ */
+
+#ifdef CD9660
+       if (major(rootdev) == 20 || major(rootdev) == 26) {
+               error = cd9660_mountroot();
+               if (error)
+                       error = cd9660_mountroot();
+       }
+       else {
+#endif
+#ifdef FFS
+               error = ffs_mountroot();
+#else
+#error FFS not configured
+#endif
+#ifdef CD9660
+               if (error)
+                       error = cd9660_mountroot();
+       }
+#endif
+       return(error);
+} 
+
+
+/*
+ * All the copyin and copyout and copystr functions need to be recoded in assembly
+ * at some point. The guts of the functions now use an assembly bcopy routine but
+ * it would be nice to code them completely in assembly. The main reason they have
+ * not been is purely because it is easier to add debugging code to check the
+ * parameters in C.
+ */
+
+#if 0
+int
+copystr(from, to, maxlen, lencopied)
+       void *from;
+       void *to;
+       size_t maxlen;
+       size_t *lencopied;
+{
+       int byte = 0;
+       int len;
+    
+       len = 0;
+
+       do {
+               if (len == maxlen)
+                       break;
+               byte = *((caddr_t)from)++;
+               *((caddr_t)to)++ = byte;
+               ++len;
+       } while (byte != 0);
+
+       if (lencopied)
+               *lencopied = len;
+     
+       if (byte == 0)
+               return(0);
+       else
+               return(ENAMETOOLONG);
+}
+
+
+#else
+int
+copystr(from, to, maxlen, lencopied)
+       void *from;
+       void *to;
+       size_t maxlen;
+       size_t *lencopied;
+
+{
+       return(copystrinout(from, to, maxlen, lencopied));
+}
+#endif
+
+int copystrinout __P((void */*from*/, void */*to*/, size_t /*maxlen*/, size_t */*lencopied*/));
+
+
+int
+copyinstr(udaddr, kaddr, len, done)
+       void *udaddr;
+       void *kaddr;
+       u_int len;
+       u_int *done;
+{
+       if (udaddr < (void *)VM_MIN_ADDRESS
+           || udaddr >= (void *)VM_MAXUSER_ADDRESS) {
+               printf("akt: copyinstr: udaddr=%08x kaddr=%08x\n",
+                   (u_int)udaddr, (u_int)kaddr);
+               return(EFAULT);
+       }
+       if (kaddr < (void *)VM_MAXUSER_ADDRESS
+           || kaddr >= (void *)VM_MAXKERN_ADDRESS) {
+               printf("akt: copyinstr: udaddr=%08x kaddr=%08x\n",
+                   (u_int)udaddr, (u_int)kaddr);
+               return(EFAULT);
+       }
+       return(copystrinout(udaddr, kaddr, len, done));
+}
+
+int
+copyoutstr(kaddr, udaddr, len, done)
+       void *kaddr;
+       void *udaddr;
+       u_int len;
+       u_int *done;
+{
+       if (udaddr < (void *)VM_MIN_ADDRESS
+           || udaddr >= (void*)VM_MAXUSER_ADDRESS) {
+               printf("akt: copyoutstr: udaddr=%08x kaddr=%08x\n",
+                   (u_int)udaddr, (u_int)kaddr);
+               return(EFAULT);
+       }
+       if (kaddr < (void *)VM_MAXUSER_ADDRESS
+           || kaddr >= (void *)VM_MAXKERN_ADDRESS) {
+               printf("akt: copyoutstr: udaddr=%08x kaddr=%08x\n",
+                   (u_int)udaddr, (u_int)kaddr);
+               return(EFAULT);
+       }
+       return(copystrinout(kaddr, udaddr, len, done));
+}
+
+int bcopyinout __P((void *, void *, u_int));
+  
+int
+copyin(udaddr, kaddr, len)
+       void *udaddr;
+       void *kaddr;
+       u_int len;
+{
+       int error;
+    
+       if (udaddr < (void *)VM_MIN_ADDRESS
+           || udaddr >= (void *)VM_MAXUSER_ADDRESS) {
+               printf("akt: copyin: udaddr=%08x kaddr=%08x\n",
+                   (u_int)udaddr, (u_int)kaddr);
+               return(EFAULT);
+       }
+       if (kaddr < (void *)VM_MAXUSER_ADDRESS
+           || kaddr >= (void *)VM_MAXKERN_ADDRESS) {
+               printf("akt: copyin: udaddr=%08x kaddr=%08x\n",
+                   (u_int)udaddr, (u_int)kaddr);
+               return(EFAULT);
+       }
+       error = bcopyinout(udaddr, kaddr, len);
+       if (error)
+               printf("akt: copyin(%08x,%08x,%08x) failed\n",
+                   (u_int)udaddr, (u_int)kaddr, len);
+       return(error);
+}
+  
+int
+copyout(kaddr, udaddr, len)
+       void *kaddr;
+       void *udaddr;
+       u_int len;
+{
+       int error;
+    
+       if (udaddr < (void*)VM_MIN_ADDRESS
+           || udaddr >= (void*)VM_MAXUSER_ADDRESS) {
+               printf("akt: copyout: udaddr=%08x kaddr=%08x\n",
+                   (u_int)udaddr, (u_int)kaddr);
+               return(EFAULT);
+       }
+       if (kaddr < (void *)VM_MAXUSER_ADDRESS
+           || kaddr >= (void *)VM_MAXKERN_ADDRESS) {
+               printf("akt: copyout: udaddr=%08x kaddr=%08x\n",
+                   (u_int)udaddr, (u_int)kaddr);
+               return(EFAULT);
+       }
+       error = bcopyinout(kaddr, udaddr, len);
+       if (error) {
+               printf("akt: copyout(%08x,%08x,%08x) failed\n",
+                   (u_int)kaddr, (u_int)udaddr, len);
+               traceback();
+       }
+       return(error);
+}
+
+void
+setsoftnet()
+{
+       soft_interrupts |= IRQMASK_SOFTNET;
+}
+
+int astpending;
+
+void
+setsoftast()
+{
+       astpending = 1;
+}
+
+extern int want_resched;
+
+void
+need_resched(void)
+{
+       want_resched = 1;
+       setsoftast();
+}
+
+
+struct queue {
+       struct queue *q_next, *q_prev;
+};
+
+/*
+ * insert an element into a queue
+ */
+
+void
+_insque(v1, v2)
+       void *v1;
+       void *v2;
+{
+       register struct queue *elem = v1, *head = v2;
+       register struct queue *next;
+
+       next = head->q_next;
+       elem->q_next = next;
+       head->q_next = elem;
+       elem->q_prev = head;
+       next->q_prev = elem;
+}
+
+/*
+ * remove an element from a queue
+ */
+
+void
+_remque(v)
+       void *v;
+{
+       register struct queue *elem = v;
+       register struct queue *next, *prev;
+
+       next = elem->q_next;
+       prev = elem->q_prev;
+       next->q_prev = prev;
+       prev->q_next = next;
+       elem->q_prev = 0;
+}
+
+
+
+/*
+ * 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);
+}
+
+
+extern pagehook_t page_hook0;
+
+/*
+ * Doadump comes here after turning off memory management and
+ * getting on the dump stack, either when called above, or by
+ * the auto-restart code.
+ */
+
+void
+dumpsys()
+{
+       daddr_t blkno;
+       int psize;
+       int error;
+       int addr;
+       int block;
+       vm_offset_t dumpspace;
+
+       msgbufmapped = 0;
+       if (dumpdev == NODEV)
+               return;
+       if (dumpsize == 0) {
+               dumpconf();
+               if (dumpsize == 0)
+                       return;
+       }
+       printf("\ndumping to dev %x, offset %d\n", (u_int)dumpdev,
+           (u_int)dumplo);
+
+       blkno = dumplo;
+       dumpspace = page_hook0.va;
+
+       psize = (*bdevsw[major(dumpdev)].d_psize)(dumpdev);
+       printf("dump ");
+       if (psize == -1) {
+               printf("area unavailable\n");
+               return;
+       }
+
+       error = 0;
+       for (block = 0; block < bootconfig.dramblocks && error == 0; ++block) {
+               for (addr = bootconfig.dram[block].address;
+                   addr < bootconfig.dram[block].address
+                   + bootconfig.dram[block].pages * NBPG; addr += NBPG) {
+                       pmap_map(dumpspace, addr, addr + NBPG, VM_PROT_READ);
+                       error = (*bdevsw[major(dumpdev)].d_dump)(dumpdev, blkno, (caddr_t) dumpspace, NBPG);
+                       if (error) break;
+                       blkno += btodb(NBPG);
+               }
+       }
+
+       if (error == 0 && videomemory.vidm_type == VIDEOMEM_TYPE_VRAM) {
+               for (addr = videomemory.vidm_pbase; addr < videomemory.vidm_pbase
+                   + videomemory.vidm_size; addr += NBPG) {
+                  pmap_map(dumpspace, addr, addr + NBPG, VM_PROT_READ);
+                       error = (*bdevsw[major(dumpdev)].d_dump)(dumpdev, blkno, (caddr_t) dumpspace, NBPG);
+                       if (error) break;
+                       blkno += btodb(NBPG);
+               }
+       }                         
+
+       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;
+
+       default:
+               printf("succeeded\n");
+               break;
+       }
+       printf("\n\n");
+       delay(1000000);
+}
+
+/*
+ * Dummy function is case no audio device has been configured
+ * Need to fix the code that uses this function (console) to check NBEEP.
+ */
+
+#include "beep.h"
+#if NBEEP == 0
+void
+beep_generate()
+{
+}
+#endif
+
+
+#if 0
+/* Debugging functions to dump the buffers linked to a vnode */
+
+void
+dumpvndbuf(vp)
+       register struct vnode *vp;
+{
+       register struct buf *bp, *nbp;
+       int s;
+
+       s = splbio();
+       for (bp = vp->v_dirtyblkhd.lh_first; bp; bp = nbp) {
+               nbp = bp->b_vnbufs.le_next;
+
+               printf("buf=%08x\n", bp);
+               printf("flags=%08x proc=%08x bufsize=%08x dev=%04x\n", bp->b_flags, bp->b_proc, bp->b_bufsize, bp->b_dev);
+               printf("vp=%08x resid=%08x count=%08x addr=%08x\n", bp->b_vp, bp->b_resid, bp->b_bcount, bp->b_un.b_addr);
+       }
+       (void)splx(s);
+}
+
+
+void
+dumpvncbuf(vp)
+       register struct vnode *vp;
+{
+       register struct buf *bp, *nbp;
+       int s;
+
+       s = splbio();
+       for (bp = vp->v_cleanblkhd.lh_first; bp; bp = nbp) {
+               nbp = bp->b_vnbufs.le_next;
+
+               printf("buf=%08x\n", bp);
+               printf("flags=%08x proc=%08x bufsize=%08x dev=%04x\n", bp->b_flags, bp->b_proc, bp->b_bufsize, bp->b_dev);
+               printf("vp=%08x resid=%08x count=%08x addr=%08x\n", bp->b_vp, bp->b_resid, bp->b_bcount, bp->b_un.b_addr);
+       }
+       (void)splx(s);
+}
+#endif
+
+
+extern u_int spl_mask;
+
+int current_spl_level = SPL_0;
+u_int spl_masks[8];
+
+int safepri = SPL_0;
+
+void
+set_spl_masks()
+{
+       spl_masks[SPL_0]        = 0xffffffff;
+       spl_masks[SPL_SOFT]     = ~IRQMASK_SOFTNET;
+       spl_masks[SPL_BIO]      = irqmasks[IPL_BIO];
+       spl_masks[SPL_NET]      = irqmasks[IPL_NET];
+       spl_masks[SPL_TTY]      = irqmasks[IPL_TTY];
+       spl_masks[SPL_CLOCK]    = irqmasks[IPL_CLOCK];
+       spl_masks[SPL_IMP]      = irqmasks[IPL_IMP];
+       spl_masks[SPL_HIGH]     = 0x00000000;
+}
+
+void
+dump_spl_masks()
+{
+       printf("spl0=%08x splsoft=%08x splbio=%08x splnet=%08x\n",
+           spl_masks[SPL_0], spl_masks[SPL_SOFT], spl_masks[SPL_BIO], spl_masks[SPL_NET]);
+       printf("spltty=%08x splclock=%08x splimp=%08x splhigh=%08x\n",
+           spl_masks[SPL_TTY], spl_masks[SPL_CLOCK], spl_masks[SPL_IMP], spl_masks[SPL_HIGH]);
+}
+
+/*
+ * Ok things are broken here. If we lower the spl level to SPL_SOFT
+ * then, for the most things work. However wd interrupts start to get
+ * lost ... i.e. you either get wdc interrupt lost messages or
+ * wdc timeout messages.
+ * The fault is the CLKF_FRAME macro uses in kern_clock.c. This
+ * currently always returns 1 thus splsoftclock() is always
+ * called before calling softclock().
+ *
+ * This is about to be fixed
+ */
+
+int
+splsoftclock()
+{
+/*     return(lowerspl(SPL_SOFT));*/
+       return(current_spl_level);
+}
+
+/* End of stubs.c */
diff --git a/sys/arch/arm32/arm32/swapgeneric.c b/sys/arch/arm32/arm32/swapgeneric.c
new file mode 100644 (file)
index 0000000..6c7a2b3
--- /dev/null
@@ -0,0 +1,60 @@
+/* $NetBSD: swapgeneric.c,v 1.2 1996/03/27 22:42:30 mark Exp $ */
+
+/*
+ * Copyright (c) 1994 Mark Brinicombe.
+ * Copyright (c) 1994 Brini.
+ * 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 Brini.
+ * 4. The name of the company nor the name of the author may be used to
+ *    endorse or promote products derived from this software without specific
+ *    prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BRINI ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL BRINI 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.
+ *
+ * RiscBSD kernel project
+ *
+ * swapgeneric.h
+ *
+ * Miscellaneous swap stuff
+ *
+ * Created      : 10/10/94
+ */
+
+#include <sys/param.h>
+#include <sys/conf.h>
+#include <sys/device.h>
+
+dev_t   rootdev = NODEV;
+dev_t   swapdev = NODEV;
+dev_t   argdev = NODEV;
+dev_t   dumpdev = NODEV;
+int     nswap;
+struct  swdevt swdevt[] = {
+       { NODEV, 0, 0 },
+       { NODEV, 0, 0 },
+       { NODEV, 0, 0 },
+       { NODEV, 0, 0 },
+};
+
+/* End of swapgeneric.c */
diff --git a/sys/arch/arm32/arm32/sys_machdep.c b/sys/arch/arm32/arm32/sys_machdep.c
new file mode 100644 (file)
index 0000000..64499aa
--- /dev/null
@@ -0,0 +1,75 @@
+/* $NetBSD: sys_machdep.c,v 1.2 1996/03/27 22:42:31 mark Exp $ */
+
+/*
+ * Copyright (c) 1995 Mark Brinicombe.
+ * 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 Mark Brinicombe
+ * 4. The name of the company nor the name of the author may 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 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.
+ *
+ * RiscBSD kernel project
+ *
+ * sys_machdep.c
+ *
+ * Machine dependant syscalls
+ *
+ * Created      : 10/01/96
+ */
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/proc.h>
+#include <sys/user.h>
+#include <sys/device.h>
+#include <sys/kernel.h>
+#include <sys/mbuf.h>
+#include <sys/buf.h>
+#include <sys/exec.h>
+#include <sys/mount.h>
+#include <sys/vnode.h>
+#include <sys/sysctl.h>
+#include <sys/syscallargs.h>
+
+int
+sys_sysarch(p, v, retval)
+       struct proc *p;
+       void *v;
+       register_t *retval;
+{
+       struct sys_sysarch_args /* {
+               syscallarg(int) op;
+               syscallarg(char *) parms;
+       } */ *uap = v;
+
+       printf("sys_sysarch: Currently stoned - Cannot support the operation (%d)\n",
+           SCARG(uap, op));
+
+       return(EINVAL);
+}
+  
+/* End of sys_machdep.c */
diff --git a/sys/arch/arm32/arm32/syscall.c b/sys/arch/arm32/arm32/syscall.c
new file mode 100644 (file)
index 0000000..318d99e
--- /dev/null
@@ -0,0 +1,573 @@
+/* $NetBSD: syscall.c,v 1.5 1996/03/13 21:21:00 mark Exp $ */
+
+/*
+ * Copyright (c) 1994,1995 Mark Brinicombe.
+ * Copyright (c) 1994 Brini.
+ * All rights reserved.
+ *
+ * This code is derived from software written for Brini by Mark Brinicombe
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided 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 Brini.
+ * 4. The name of the company nor the name of the author may be used to
+ *    endorse or promote products derived from this software without specific
+ *    prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BRINI ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL BRINI 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.
+ *
+ * RiscBSD kernel project
+ *
+ * syscall.c
+ *
+ * High level syscall handling
+ *
+ * Created      : 09/11/94
+ */
+
+#include <sys/param.h>
+#include <sys/filedesc.h>
+#include <sys/errno.h>
+#include <sys/exec.h>
+#include <sys/kernel.h>
+#include <sys/mount.h>
+#include <sys/map.h>
+#include <sys/proc.h>
+#include <sys/resourcevar.h>
+#include <sys/signalvar.h>
+#include <sys/systm.h>
+#include <sys/vnode.h>
+#include <sys/conf.h>
+#include <sys/buf.h>
+#include <sys/device.h>
+#include <sys/protosw.h>
+#include <sys/reboot.h>
+#include <sys/user.h>
+#include <sys/syscall.h>
+#include <sys/syscallargs.h>
+
+#include <vm/vm.h>
+#include <vm/vm_kern.h>
+#ifdef KTRACE
+#include <sys/ktrace.h>
+#endif
+#include <machine/cpu.h>
+#include <machine/frame.h>
+#include <machine/katelib.h>
+#include <machine/undefined.h>
+
+#include "hydrabus.h"
+
+/*
+ * CONTINUE_AFTER_SYSCALL_BUG is used to determine whether the kernel
+ * should continue running following a swi instruction in SVC mode.
+ * This was used for debugging.
+ */ 
+
+#define CONTINUE_AFTER_SYSCALL_BUG              
+
+extern int pmap_debug_level;
+extern u_int kmodule_size;
+extern u_int kmodule_base;
+u_int arm700bugcount = 0;
+extern int vnodeconsolebug;
+extern int usertraceback;
+
+#if NHYDRABUS > 0
+typedef struct {
+       vm_offset_t physical;
+       vm_offset_t virtual;
+} pv_addr_t;
+
+extern pv_addr_t hydrascratch;
+#endif
+
+void postmortem __P((trapframe_t *));
+void fpe_dump_prof __P(());
+
+#define SYSCALL_SPECIAL_RETURN                 \
+       userret(p, frame->tf_pc, sticks);       \
+       validate_trapframe(frame, 4);           \
+       return;
+
+/*
+ * syscall(frame):
+ *
+ * System call request from POSIX system call gate interface to kernel.
+ */
+
+void
+syscall(frame, code)
+       trapframe_t *frame;
+       int code;
+{
+       caddr_t params;
+       struct sysent *callp;
+       struct proc *p;
+       int error, opc;
+       u_int argsize;
+       int args[8], rval[2];
+       int nsys;
+       u_quad_t sticks;
+       int regparams;
+
+       cnt.v_syscall++;
+        
+#ifdef DIAGNOSTIC
+       if ((frame->tf_spsr & PSR_MODE) != PSR_USR32_MODE) {
+               u_int s;
+               
+               s = splhigh();
+               printf("swi code = %08x %d\n", code, code);
+               postmortem(frame);
+
+               printf("nkt: syscall in kernel mode !\n");
+#ifdef CONTINUE_AFTER_SYSCALL_BUG              
+               printf("The system should now be considered very unstable :-(\n");
+               sigexit(curproc, SIGILL);
+
+/* Not reached */
+
+               (void)splx(s);
+               userret(curproc, frame->tf_pc, curproc->p_sticks);
+
+#ifdef VALIDATE_TRAPFRAME
+               validate_trapframe(frame, 4);
+#endif
+               return;
+#else
+               panic("syscall in kernel mode !\n");
+#endif
+       }
+#endif
+
+/*
+ * ARM700/ARM710 match sticks and sellotape job ...
+ *
+ * I know this affects GPS/VLSI ARM700/ARM710.
+ *
+ * Not heard anything from ARM since I told them about this ...
+ * On occasion data aborts are mishandled and end up calling
+ * the swi vector.
+ */
+
+       if ((ReadWord(frame->tf_pc - 4) & 0x0f000000) != 0x0f000000) {
+               frame->tf_pc -= 4;
+               ++arm700bugcount;
+
+               userret(curproc, frame->tf_pc, curproc->p_sticks);
+
+#ifdef VALIDATE_TRAPFRAME
+               validate_trapframe(frame, 4);
+#endif
+               return;
+       }
+
+#ifdef DIAGNOSTIC
+       if ((GetCPSR() & PSR_MODE) != PSR_SVC32_MODE) {
+               splhigh();
+
+               printf("swi code = %08x %d\n", code, code);
+               postmortem(frame);
+               panic("syscall in non SVC mode !");
+       }
+#endif
+
+/*
+ * Enable interrupts if they were enable before the exception.
+ * Sinces all syscalls *should* come from user mode it will always
+ * be safe to enable them, but check anyway. 
+ */
+
+#ifndef BLOCK_IRQS
+       if (!(frame->tf_spsr & I32_bit))
+           enable_interrupts(I32_bit);
+#endif
+
+       p = curproc;
+       sticks = p->p_sticks;
+       p->p_md.md_regs = frame;
+       opc = frame->tf_pc;
+       params = (caddr_t)&frame->tf_r0;
+       regparams = 4;
+    
+       if (pmap_debug_level >= -1)
+               printf("\x1b[31mSYSCALL\x1b[0m: code=%08x lr=%08x pid=%d\n",
+                   code, frame->tf_pc, p->p_pid);
+
+       nsys = p->p_emul->e_nsysent;
+       callp = p->p_emul->e_sysent;
+
+       switch (code) {
+       case 0x1002:
+               printf((char *)frame->tf_r0, frame->tf_r1, frame->tf_r2, frame->tf_r3);
+               SYSCALL_SPECIAL_RETURN;
+               break;
+
+       case 0x1003:
+               printf("%s", (char *)frame->tf_r0);
+               SYSCALL_SPECIAL_RETURN;
+               break;
+
+/*     case 0x1004:
+               if (frame->tf_r0 != 0)
+                       panic((char *)frame->tf_r0, frame->tf_r1, frame->tf_r2,
+                           frame->tf_r3);
+               panic("SYSCALL 0x1004 panic\n");
+               break;*/
+
+/*     case 0x1007:
+               pmap_debug(frame->tf_r0);
+               SYSCALL_SPECIAL_RETURN;
+               break;*/
+
+       case 0x1008:
+               switch (frame->tf_r0) {
+               case 0 :
+                       debug_show_all_procs(frame->tf_r1, frame->tf_r2);
+                       break;
+#ifdef FPE
+               case 4 :
+                       fpe_dump_prof();
+                       break;
+#endif
+               case 5 :
+                       pmap_dump_pvs();
+                       break;
+               case 6:
+                       WriteWord(frame->tf_r1, frame->tf_r2);
+                       break;
+               case 7:
+                       frame->tf_r0 = ReadWord(frame->tf_r1);
+                       break;
+               case 8:
+                       WriteByte(frame->tf_r1, frame->tf_r2);
+                       break;
+               case 9:
+                       frame->tf_r0 = ReadByte(frame->tf_r1);
+                       break;
+               case 10:
+                       WriteShort(frame->tf_r1, frame->tf_r2);
+                       break;
+               case 11:
+                       frame->tf_r0 = ReadShort(frame->tf_r1);
+                       break;
+               case 16:
+                       pmap_pagedir_dump();
+                       break;
+/*             case 32:
+                       frame->tf_r0 = pmap_next_phys_page(frame->tf_r1);
+                       break;*/
+               default:
+                       printf("Unknown SYS_special call (%d)\n", frame->tf_r0);
+                       break;
+               }
+               SYSCALL_SPECIAL_RETURN;
+               break;
+
+       case 0x100a:
+               printf("Warning: This syscall is about to be revoked (0x100a)\n");
+               frame->tf_r0 = pmap_page_attributes(frame->tf_r0);
+               SYSCALL_SPECIAL_RETURN;
+               break;
+/*
+       case 0x1010:
+               frame->tf_r0 = kmodule_base;
+               SYSCALL_SPECIAL_RETURN;
+               break;
+
+       case 0x1011:
+               frame->tf_r0 = kmodule_size;
+               SYSCALL_SPECIAL_RETURN;
+               break;
+
+       case 0x1012:
+               if (frame->tf_r1 < kmodule_size) {
+                       bcopy((char *)frame->tf_r0, (char *)kmodule_base,
+                           frame->tf_r1);
+                       frame->tf_r0 = 0;
+               }
+               else
+                       frame->tf_r0 = 1;
+               SYSCALL_SPECIAL_RETURN;
+               break;
+
+       case 0x1013:
+               {
+               int (*caller)();
+           
+               caller = (void *)frame->tf_r0;
+           
+               frame->tf_r0 = (*caller)(printf, install_coproc_handler);
+               }
+               SYSCALL_SPECIAL_RETURN;
+               break;
+*/
+#if NHYDRABUS > 0
+       case 0x1014:
+               frame->tf_r0 = hydrascratch.physical;
+               SYSCALL_SPECIAL_RETURN;
+               break;
+       case 0x1015:
+               frame->tf_r0 = hydrascratch.virtual;
+               SYSCALL_SPECIAL_RETURN;
+               break;
+       case 0x1016:
+               frame->tf_r0 = (u_int)proc0.p_addr->u_pcb.pcb_pagedir;
+               SYSCALL_SPECIAL_RETURN;
+               break;
+       case 0x1017:
+               frame->tf_r0 = kmem_alloc(kernel_map, round_page(frame->tf_r0));
+               SYSCALL_SPECIAL_RETURN;
+               break;
+       case 0x1018:
+               kmem_free(kernel_map, frame->tf_r0, frame->tf_r1);
+               SYSCALL_SPECIAL_RETURN;
+               break;
+#endif
+#if 0
+       case 0x1020:
+               vprint(frame->tf_r0, frame->tf_r1);
+               SYSCALL_SPECIAL_RETURN;
+               break;
+       case 0x1021:
+               { struct vnode *vp;
+               vp = (struct vp *)frame->tf_r0;
+               if (vp->v_numoutput > 0 && vp->v_usecount == 0 && vp->v_writecount == 0) {
+                       printf("Patching vnode %08x\n", vp);
+                       vprint(NULL, vp);
+                       if (--vp->v_numoutput < 0)
+                               panic("vwakeup: neg numoutput");
+                       if ((vp->v_flag & VBWAIT) && vp->v_numoutput <= 0) {
+                               vp->v_flag &= ~VBWAIT;
+                               wakeup((caddr_t)&vp->v_numoutput);
+                       }
+               }
+               SYSCALL_SPECIAL_RETURN;
+               }
+               break;
+
+       case 0x1022:
+               { struct vnode *vp;
+               vp = (struct vp *)frame->tf_r0;
+               if (vp->v_numoutput == 0 && vp->v_usecount == 0 && vp->v_writecount == 0) {
+                       printf("Patching vnode %08x\n", vp);
+                       vprint(NULL, vp);
+                       if ((vp->v_flag & VBWAIT) && vp->v_numoutput <= 0) {
+                               vp->v_flag &= ~VBWAIT;
+                               wakeup((caddr_t)&vp->v_numoutput);
+                       }
+               }
+               SYSCALL_SPECIAL_RETURN;
+               }
+               break;
+
+       case 0x1023:
+               wakeup((caddr_t)frame->tf_r0);
+               SYSCALL_SPECIAL_RETURN;
+               break;
+/*             
+       case 0x1024:
+               dumpvndbuf((struct vnode *)frame->tf_r0);
+               SYSCALL_SPECIAL_RETURN;
+               break;
+               
+       case 0x1025:
+               dumpvncbuf((struct vnode *)frame->tf_r0);
+               SYSCALL_SPECIAL_RETURN;
+               break;
+*/             
+/*     case 0x1026:
+               vfs_bufstats();
+               SYSCALL_SPECIAL_RETURN;
+               break;
+*/     
+       case 0x1027:
+               bcopy(frame->tf_r0, frame->tf_r1, sizeof(struct vnode));
+               SYSCALL_SPECIAL_RETURN;
+               break;
+       case 0x1028:
+               vnodeconsolebug = frame->tf_r0;
+               SYSCALL_SPECIAL_RETURN;
+               break;
+#endif
+       case 0x102a:
+               usertraceback = frame->tf_r0;
+               SYSCALL_SPECIAL_RETURN;
+               break;
+
+       case 0x102b:
+               frame->tf_r0 = vmem_mapdram();
+               SYSCALL_SPECIAL_RETURN;
+               break;
+
+       case 0x102c:
+               frame->tf_r0 = vmem_mapvram();
+               SYSCALL_SPECIAL_RETURN;
+               break;
+
+       case 0x102d:
+               frame->tf_r0 = vmem_cachectl(frame->tf_r0);
+               SYSCALL_SPECIAL_RETURN;
+               break;
+
+       case SYS_syscall:
+/*             code = fuword(params);*/
+               code = ReadWord(params);
+               params += sizeof(int);
+               regparams -= 1;
+               printf("SYS_syscall: code=%d %02x", code, code);
+               break;
+       
+        case SYS___syscall:
+               if (callp != sysent)
+                       break;
+/*             code = fuword(params + _QUAD_LOWWORD * sizeof(int));*/
+
+/* Since this will be a register ... */
+
+               code = ReadWord(params + _QUAD_LOWWORD * sizeof(int));
+               params += sizeof(quad_t);
+               regparams -= 2;
+               break;
+
+        default:
+               /* do nothing by default */
+               break;
+       }
+
+       if (code < 0 || code >= nsys)
+               callp += p->p_emul->e_nosys;            /* illegal */
+       else
+               callp += code;
+
+       if (callp->sy_call == sys_nosys) {
+               printf("SYSCALL: nosys code=%08x lr=%08x proc=%08x pid=%d %s\n",
+                   code, frame->tf_pc, (u_int)p, p->p_pid, p->p_comm);
+               postmortem(frame);
+#ifdef POSTMORTEM
+               disassemble(frame->tf_pc-8);
+               disassemble(frame->tf_pc-4);
+               disassemble(frame->tf_pc);
+               disassemble(frame->tf_pc+4);
+#endif
+               pmap_debug(-2);
+       }
+
+       argsize = callp->sy_argsize;
+       if (argsize > (regparams * sizeof(int)))
+               argsize = regparams*sizeof(int);
+/*     if (argsize && (error = copyin(params, (caddr_t)args, argsize))) {
+#ifdef SYSCALL_DEBUG
+               scdebug_call(p, code, callp->sy_narg, args);
+#endif
+               goto bad;
+       }*/
+       if (argsize)
+               bcopy(params, (caddr_t)args, argsize);
+
+       argsize = callp->sy_argsize;
+       if (callp->sy_argsize > (regparams * sizeof(int))
+           && (error = copyin((caddr_t)frame->tf_usr_sp,
+           (caddr_t)&args[regparams], argsize - (regparams * sizeof(int))))) {
+#ifdef SYSCALL_DEBUG
+               scdebug_call(p, code, callp->sy_narg, args);
+#endif
+               goto bad;
+       }
+
+#ifdef SYSCALL_DEBUG
+       scdebug_call(p, code, callp->sy_narg, args);
+#endif
+#ifdef KTRACE
+       if (KTRPOINT(p, KTR_SYSCALL))
+               ktrsyscall(p->p_tracep, code, argsize, args);
+#endif
+       rval[0] = 0;
+       rval[1] = frame->tf_r1;
+
+       error = (*callp->sy_call)(p, args, rval);
+
+       switch (error) {
+       case 0:
+/*
+ * Reinitialize proc pointer `p' as it may be different
+ * if this is a child returning from fork syscall.
+ */
+               p = curproc;
+               frame->tf_r0 = rval[0];
+               frame->tf_r1 = rval[1];
+               frame->tf_spsr &= ~PSR_C_bit;   /* carry bit */
+               break;
+
+       case ERESTART:
+/*
+ * Reconstruct the pc. opc contains the odl pc address which is 
+ * the instruction after the swi.
+ */
+               frame->tf_pc = opc - 4;
+               break;
+
+       case EJUSTRETURN:
+/* nothing to do */
+               break;
+
+       default:
+       bad:
+               frame->tf_r0 = error;
+               frame->tf_spsr |= PSR_C_bit;    /* carry bit */
+               break;
+      }
+
+#ifdef SYSCALL_DEBUG
+       scdebug_ret(p, code, error, rval[0]);
+#endif
+
+       validate_trapframe(frame, 4);
+
+       userret(p, frame->tf_pc, sticks);
+
+#ifdef KTRACE
+       if (KTRPOINT(p, KTR_SYSRET))
+               ktrsysret(p->p_tracep, code, error, rval[0]);
+#endif
+
+       validate_trapframe(frame, 4);
+}
+
+
+void
+child_return(p, frame)
+       struct proc *p;
+       struct trapframe *frame;
+{
+       frame->tf_r0 = 0;
+       frame->tf_spsr &= ~PSR_C_bit;   /* carry bit */ 
+
+       userret(p, frame->tf_pc, 0);
+
+#ifdef KTRACE
+       if (KTRPOINT(p, KTR_SYSRET))
+               ktrsysret(p->p_tracep, SYS_fork, 0, 0);
+#endif
+}
+
+/* End of syscall.c */
diff --git a/sys/arch/arm32/arm32/undefined.c b/sys/arch/arm32/arm32/undefined.c
new file mode 100644 (file)
index 0000000..65f3907
--- /dev/null
@@ -0,0 +1,325 @@
+/* $NetBSD: undefined.c,v 1.2 1996/03/08 20:54:25 mark Exp $ */
+
+/*
+ * Copyright (c) 1995 Mark Brinicombe.
+ * Copyright (c) 1995 Brini.
+ * All rights reserved.
+ *
+ * This code is derived from software written for Brini by Mark Brinicombe
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided 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 Brini.
+ * 4. The name of the company nor the name of the author may be used to
+ *    endorse or promote products derived from this software without specific
+ *    prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BRINI ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL BRINI 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.
+ *
+ * RiscBSD kernel project
+ *
+ * undefined.c
+ *
+ * Fault handler
+ *
+ * Created      : 06/01/95
+ */
+
+#define CONTINUE_AFTER_RESET_BUG
+#define FAST_FPE
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/proc.h>
+#include <sys/user.h>
+#include <sys/kernel.h>
+#include <sys/syslog.h>
+#ifdef FAST_FPE
+#include <sys/acct.h>
+#endif
+
+#include <machine/cpu.h>
+#include <machine/katelib.h>
+#include <machine/frame.h>
+#include <machine/undefined.h>
+#include <machine/irqhandler.h>
+
+#ifdef FAST_FPE
+extern int want_resched;
+#endif
+
+undef_handler_t undefined_handlers[MAX_COPROCS];
+
+u_int disassemble __P((u_int));
+
+
+int
+default_undefined_handler(address, instruction, frame)
+       u_int address;
+       u_int instruction;
+       trapframe_t *frame;
+{
+       struct proc *p;
+
+       p = curproc;
+       if (p == NULL)
+               p = &proc0;
+       log(LOG_ERR, "Undefined instruction 0x%08x @ 0x%08x in process %s (pid %d)\n",
+           instruction, address, p->p_comm, p->p_pid);
+       return(1);
+}
+
+
+int
+install_coproc_handler(coproc, handler)
+       int coproc;
+       undef_handler_t handler;
+{
+       if (coproc < 0 || coproc > MAX_COPROCS)
+               return(EINVAL);
+       if (handler == (undef_handler_t)0)
+               handler = default_undefined_handler;
+      
+       undefined_handlers[coproc] = handler;
+       return(0);
+}
+
+
+void
+undefined_init()
+{
+       int loop;
+
+       for (loop = 0; loop < MAX_COPROCS; ++loop)
+               undefined_handlers[loop] = default_undefined_handler;
+}
+
+
+void
+undefinedinstruction(frame)
+       trapframe_t *frame;
+{
+       struct proc *p;
+/*     struct pcb *pcb;*/
+       u_int fault_pc;
+       int fault_instruction;
+       int s;
+       int fault_code;
+       u_quad_t sticks;
+       int coprocessor;
+
+#ifndef BLOCK_IRQS
+       if (!(frame->tf_spsr & I32_bit))
+               enable_interrupts(I32_bit);
+#endif
+    
+/* Update vmmeter statistics */
+    
+       cnt.v_trap++;
+         
+       fault_pc = frame->tf_pc - 4;
+
+/* Should use fuword() here .. but in the interests of squeezing every bit
+ * of speed we will just use ReadWord(). We know the instruction can be
+ * read as was just executed so this will never fail unless the kernel
+ * is screwed up in which case it does not really matter does it ?
+ */
+
+       fault_instruction = ReadWord(fault_pc);
+
+/* Check for coprocessor instruction */
+
+/*
+ * According to the datasheets you only need to look at bit 27 of the instruction
+ * to tell the difference between and undefined instruction and a
+ * coprocessor instruction.
+ */
+
+       if ((fault_instruction & (1 << 27)) != 0)
+               coprocessor = (fault_instruction >> 8) & 0x0f;
+       else {
+               coprocessor = 0;
+               s = splhigh();
+               disassemble(fault_pc);
+               (void)splx(s);
+       }
+               
+/* Get the current proc structure or proc0 if there is none */
+
+       if ((p = curproc) == 0)
+               p = &proc0;
+
+/*     printf("fault in process %08x %d\n", p, p->p_pid);*/
+
+       if ((frame->tf_spsr & PSR_MODE) == PSR_USR32_MODE) {
+/*             printf("USR32 mode : %08x\n", frame->tf_spsr);*/
+               sticks = p->p_sticks;
+                  
+/* Modify the fault_code to reflect the USR/SVC state at time of fault */
+
+               fault_code = FAULT_USER;
+               p->p_md.md_regs = frame;
+       } else
+               fault_code = 0;
+
+#if 0
+/* can't use curpcb, as it might be NULL; and we have p in a register anyway */
+
+    pcb = &p->p_addr->u_pcb;
+    if (pcb == 0)
+      {
+        panic("no pcb ... we're toast !\n");
+      }
+#endif
+
+/* OK this is were we do something about the instruction */
+
+/* Check for coprocessor instruction */
+
+/*
+       s = splhigh();
+       printf("Coprocessor number %d instruction fault\n", coprocessor);
+       (void)splx(s);
+*/
+
+       if ((undefined_handlers[coprocessor](fault_pc, fault_instruction,
+           frame)) != 0) {
+               s = splhigh();
+
+               if ((fault_instruction & 0x0f000010) == 0x0e000000) {
+                       printf("CDP\n");
+                       disassemble(fault_pc);
+               }
+               else if ((fault_instruction & 0x0e000000) == 0x0c000000) {
+                       printf("LDC/STC\n");
+                       disassemble(fault_pc);
+               }
+               else if ((fault_instruction & 0x0f000010) == 0x0e000010) {
+                       printf("MRC/MCR\n");
+                       disassemble(fault_pc);
+               }
+               else {
+                       printf("Undefined instruction\n");
+                       disassemble(fault_pc);
+               }
+
+               (void)splx(s);
+        
+               if ((fault_code & FAULT_USER) == 0) {
+                       printf("Undefined instruction in kernel: Heavy man !\n");
+                       postmortem(frame);
+               }
+
+               trapsignal(p, SIGILL, fault_instruction);
+       }
+
+       if ((fault_code & FAULT_USER) == 0)
+               return;
+
+#ifdef FAST_FPE
+/* Optimised exit code */
+
+       {
+               int sig;
+
+/* take pending signals */
+
+               while ((sig = (CURSIG(p))) != 0) {
+                       postsig(sig);
+               }
+
+               p->p_priority = p->p_usrpri;
+
+/*
+ * Check for reschedule request, at the moment there is only
+ * 1 ast so this code should always be run
+ */
+
+               if (want_resched) {
+        /*
+         * Since we are curproc, a clock interrupt could
+         * change our priority without changing run queues
+         * (the running process is not kept on a run queue).
+         * If this happened after we setrunqueue ourselves but
+         * before we switch()'ed, we might not be on the queue
+         * indicated by our priority
+         */
+       
+                       s = splstatclock();
+                       setrunqueue(p);
+                       p->p_stats->p_ru.ru_nivcsw++;
+
+                       mi_switch();
+
+                       (void)splx(s);
+                       while ((sig = (CURSIG(p))) != 0) {
+                               postsig(sig);
+                       }
+               }
+
+/*
+ * The profiling bit is commented out at the moment. This can be reinstated
+ * later on. Currently addupc_task is not written.
+ */
+
+               if (p->p_flag & P_PROFIL) {
+                       extern int psratio;
+                       addupc_task(p, frame->tf_pc, (int)(p->p_sticks - sticks) * psratio );
+               }
+
+               curpriority = p->p_priority;
+       }
+
+#else
+#ifdef VALIDATE_TRAPFRAME
+       validate_trapframe(frame, 5);
+#endif
+
+       userret(p, frame->tf_pc, sticks);
+
+#ifdef VALIDATE_TRAPFRAME
+       validate_trapframe(frame, 5);
+#endif
+#endif
+}
+
+
+void
+resethandler(frame)
+       trapframe_t *frame;
+{
+       postmortem(frame);
+
+#ifdef CONTINUE_AFTER_RESET_BUG
+       printf("Branch throuh zero\n");
+       printf("The system should now be considered very unstable :-)\n");
+       sigexit(curproc, SIGILL);
+
+#ifdef VALIDATE_TRAPFRAME
+       validate_trapframe(frame, 4);
+#endif
+#else
+       panic("Branch through zero..... were dead\n");
+#endif
+}
+
+/* End of undefined.c */
diff --git a/sys/arch/arm32/arm32/vm_machdep.c b/sys/arch/arm32/arm32/vm_machdep.c
new file mode 100644 (file)
index 0000000..209e368
--- /dev/null
@@ -0,0 +1,562 @@
+/* $NetBSD: vm_machdep.c,v 1.3 1996/03/13 21:16:15 mark Exp $ */
+
+/*
+ * Copyright (c) 1994-1996 Mark Brinicombe.
+ * Copyright (c) 1994 Brini.
+ * All rights reserved.
+ *
+ * This code is derived from software written for Brini by Mark Brinicombe
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided 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 Brini.
+ * 4. The name of the company nor the name of the author may be used to
+ *    endorse or promote products derived from this software without specific
+ *    prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BRINI ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL BRINI 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.
+ *
+ * RiscBSD kernel project
+ *
+ * vm_machdep.h
+ *
+ * vm machine specifiv bits
+ *
+ * Created      : 08/10/94
+ */
+
+#define DEBUG_VMMACHDEP
+/*#define FREESWAPPEDPAGEDIRS*/
+
+#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 <sys/syslog.h>
+
+#include <vm/vm.h>
+#include <vm/vm_kern.h>
+
+#include <machine/cpu.h>
+#include <machine/pmap.h>
+#include <machine/reg.h>
+#include <machine/vmparam.h>
+#include <machine/katelib.h>
+
+#ifdef ARMFPE
+#include <sys/device.h>
+#include <machine/cpus.h>
+#include <arm32/fpe-arm/armfpe.h>
+#endif
+
+typedef struct {
+       vm_offset_t physical;
+       vm_offset_t virtual;
+} pv_addr_t;
+
+extern pv_addr_t systempage;
+
+extern int pmap_debug_level;
+
+void   switch_exit     __P((struct proc */*p*/, struct proc */*proc0*/));
+int    savectx         __P((struct pcb *pcb));
+void   pmap_activate   __P((pmap_t /*pmap*/, struct pcb */*pcbp*/));
+extern void proc_trampoline    __P(());
+extern void child_return       __P(());
+
+/*
+ * Special compilation symbols
+ * DEBUG_VMMACHDEP
+ */
+
+/*
+ * 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.
+ */
+
+void
+cpu_fork(p1, p2)
+       struct proc *p1;
+       struct proc *p2;
+{
+       struct user *up = p2->p_addr;
+       struct pcb *pcb = (struct pcb *)&p2->p_addr->u_pcb;
+       struct trapframe *tf;
+       struct switchframe *sf;
+       int loop;
+       vm_offset_t addr;
+       u_char *ptr;
+       vm_offset_t muaddr = VM_MAXUSER_ADDRESS;
+       struct vm_map *vp;
+
+#ifdef DEBUG_VMMACHDEP        
+       if (pmap_debug_level >= 0)
+               printf("cpu_fork: %08x %08x %08x %08x\n", (u_int)p1, (u_int)p2,
+                  (u_int) curproc, (u_int)&proc0);
+#endif
+
+/* Sync the pcb */
+       savectx(curpcb);
+
+/* Copy the pcb */
+       *pcb = p1->p_addr->u_pcb;
+
+/* Set up the undefined stack for the process. Note: this stack is not in use if we are forking */
+       pcb->pcb_und_sp = (u_int)p2->p_addr + USPACE_UNDEF_STACK_TOP;
+       pcb->pcb_sp = (u_int)p2->p_addr + USPACE_SVC_STACK_TOP;
+
+/* Fill the undefined stack with a known pattern */
+
+       ptr = ((u_char *)p2->p_addr) + USPACE_UNDEF_STACK_BOTTOM;
+       for (loop = 0; loop < (USPACE_UNDEF_STACK_TOP - USPACE_UNDEF_STACK_BOTTOM); ++loop, ++ptr) {
+               *ptr = 0xdd;
+       }
+
+/* Fill the kernel stack with a known pattern */
+
+       ptr = ((u_char *)p2->p_addr) + USPACE_SVC_STACK_BOTTOM;
+       for (loop = 0; loop < (USPACE_SVC_STACK_TOP - USPACE_SVC_STACK_BOTTOM); ++loop, ++ptr) {
+               *ptr = 0xdd;
+       }
+
+/* Now ...
+ * vm_fork has allocated UPAGES in kernel Vm space for us. p2->p_addr
+ * points to the start of this. The i386 releases this memory in vm_fork
+ * and relocates it in cpu_fork.
+ * We can work with it allocated by vm_fork. We we must do is
+ * copy the stack and activate the p2 page directory.
+ * We activate first and then call savectx which will copy the stack.
+ * This must also set the stack pointer for p2 to its correct address
+ * NOTE: This will be different from p1 stack address.
+ */
+#ifdef DEBUG_VMMACHDEP
+       if (pmap_debug_level >= 0) {
+               printf("cpu_fork: pcb = %08x pagedir = %08x\n",
+                   (u_int)&up->u_pcb, (u_int)up->u_pcb.pcb_pagedir);
+               printf("p1->procaddr=%08x p1->procaddr->u_pcb=%08x pid=%d pmap=%08x\n",
+                   (u_int)p1->p_addr, (u_int)&p1->p_addr->u_pcb, p1->p_pid, (u_int)&p1->p_vmspace->vm_pmap);
+               printf("p2->procaddr=%08x p2->procaddr->u_pcb=%08x pid=%d pmap=%08x\n",
+                   (u_int)p2->p_addr, (u_int)&p2->p_addr->u_pcb, p2->p_pid, (u_int)&p2->p_vmspace->vm_pmap);
+       }
+#endif
+
+/* ream out old pagetables */
+
+       vp = &p2->p_vmspace->vm_map;
+       (void)vm_deallocate(vp, muaddr, VM_MAX_ADDRESS - muaddr);
+       (void)vm_allocate(vp, &muaddr, VM_MAX_ADDRESS - muaddr, FALSE);
+       (void)vm_map_inherit(vp, muaddr, VM_MAX_ADDRESS, VM_INHERIT_NONE);
+
+
+/* Get the address of the page table containing 0x00000000 */
+
+       addr = trunc_page((u_int)vtopte(0));
+
+#ifdef DEBUG_VMMACHDEP
+       if (pmap_debug_level >= 0) {
+               printf("fun time: paging in PT %08x for %08x\n", (u_int)addr, 0);
+               printf("p2->p_vmspace->vm_pmap.pm_pdir[0] = %08x\n", p2->p_vmspace->vm_pmap.pm_pdir[0]);
+               printf("p2->pm_vptpt[0] = %08x", *((int *)(p2->p_vmspace->vm_pmap.pm_vptpt + 0)));
+       }
+#endif
+
+/* Nuke the exising mapping */
+
+       p2->p_vmspace->vm_pmap.pm_pdir[0] = 0;
+       p2->p_vmspace->vm_pmap.pm_pdir[1] = 0;
+       p2->p_vmspace->vm_pmap.pm_pdir[2] = 0;
+       p2->p_vmspace->vm_pmap.pm_pdir[3] = 0;
+
+       *((int *)(p2->p_vmspace->vm_pmap.pm_vptpt + 0)) = 0;
+
+/* Wire down a page to cover the page table zero page and the start of the user are in */
+
+#ifdef DEBUG_VMMACHDEP
+       if (pmap_debug_level >= 0) {
+               printf("vm_map_pageable: addr=%08x\n", addr);
+       }
+#endif
+
+       if (vm_map_pageable(&p2->p_vmspace->vm_map, addr, addr+NBPG, FALSE) != 0) {
+               panic("Failed to fault in system page PT\n");
+       }
+
+#ifdef DEBUG_VMMACHDEP
+       if (pmap_debug_level >= 0) {
+               printf("party on! acquired a page table for 0M->(4M-1)\n");
+               printf("p2->p_vmspace->vm_pmap.pm_pdir[0] = %08x\n", p2->p_vmspace->vm_pmap.pm_pdir[0]);
+               printf("p2->pm_vptpt[0] = %08x", *((int *)(p2->p_vmspace->vm_pmap.pm_vptpt + 0)));
+       }
+#endif
+
+/* Map the system page */
+
+       pmap_enter(&p2->p_vmspace->vm_pmap, 0,
+           systempage.physical, VM_PROT_READ, TRUE);
+
+       pmap_activate(&p2->p_vmspace->vm_pmap, &up->u_pcb);
+
+#ifdef ARMFPE
+/* Initialise a new FP context for p2 and copy the context from p1 */
+       arm_fpe_core_initcontext(FP_CONTEXT(p2));
+       arm_fpe_copycontext(FP_CONTEXT(p1), FP_CONTEXT(p2));
+#endif
+
+       p2->p_md.md_regs = tf = (struct trapframe *)pcb->pcb_sp - 1;
+
+       *tf = *p1->p_md.md_regs;
+       sf = (struct switchframe *)tf - 1;
+       sf->sf_spl = SPL_0;
+       sf->sf_r4 = (u_int)child_return;
+       sf->sf_r5 = (u_int)p2;
+       sf->sf_pc = (u_int)proc_trampoline;
+       pcb->pcb_sp = (u_int)sf;
+}
+
+
+void
+cpu_set_kpc(p, pc)
+       struct proc *p;
+       u_long pc;
+{
+       struct switchframe *sf = (struct switchframe *)p->p_addr->u_pcb.pcb_sp;
+
+       sf->sf_r4 = pc;
+       sf->sf_r5 = (u_int)p;
+}
+
+
+/*
+ * cpu_exit is called as the last action during exit.
+ *
+ * We clean up a little and then call switch_exit() with the old proc as an
+ * argument.  switch_exit() first switches to proc0's context, then does the
+ * vmspace_free() and kmem_free() that we don't do here, and finally jumps
+ * into switch() to wait for another process to wake up.
+ */
+
+void
+cpu_exit(p)
+       register struct proc *p;
+{
+       struct vmspace *vm;
+       
+#ifdef ARMFPE
+/* Abort any active FP operation and deactivate the context */
+       arm_fpe_core_abort(FP_CONTEXT(p), NULL, NULL);
+       arm_fpe_core_changecontext(0);
+#endif
+
+/* Report how much stack has been used - debugging */
+
+/*     if (p) {
+               u_char *ptr;
+               int loop;
+
+               ptr = ((u_char *)p2->p_addr) + USPACE_UNDEF_STACK_BOTTOM;
+               for (loop = 0; loop < (USPACE_UNDEF_STACK_TOP - USPACE_UNDEF_STACK_BOTTOM) && *ptr == 0xdd; ++loop, ++ptr) ;
+               log(LOG_INFO, "%d bytes of undefined stack fill pattern\n", loop);
+               ptr = ((u_char *)p2->p_addr) + USPACE_SVC_STACK_BOTTOM;
+               for (loop = 0; loop < (USPACE_SVC_STACK_TOP - USPACE_SVC_STACK_BOTTOM) && *ptr == 0xdd; ++loop, ++ptr) ;
+               log(LOG_INFO, "%d bytes of svc stack fill pattern\n", loop);
+
+       }
+*/
+
+/*    printf("cpu_exit: proc=%08x pid=%d comm=%s\n", p, p->p_pid, p->p_comm);*/
+
+       vm = p->p_vmspace;
+       if (vm->vm_refcnt == 1) /* What does this do and is it needed ? */
+               vm_map_remove(&vm->vm_map, VM_MIN_ADDRESS, VM_MAXUSER_ADDRESS);
+
+       cnt.v_swtch++;
+
+       switch_exit(p, &proc0);
+}
+
+
+void
+cpu_swapin(p)
+       struct proc *p;
+{
+       vm_offset_t addr;
+       int loop;
+
+#ifdef DEBUG_VMMACHDEP
+       if (pmap_debug_level >= 0)
+               printf("cpu_swapin(%08x, %d, %s, %08x)\n", (u_int)p, p->p_pid, p->p_comm, (u_int)&p->p_vmspace->vm_pmap);
+#endif
+
+#ifdef FREESWAPPEDPAGEDIRS
+       printf("cpu_swapin(%08x, %d, %s, %08x)\n", (u_int)p, p->p_pid, p->p_comm, (u_int)&p->p_vmspace->vm_pmap);
+       if (p->p_vmspace->vm_pmap.pm_pdir)
+               printf("pdir = %08x\n", p->p_vmspace->vm_pmap.pm_pdir);
+       pmap_pinit(&p->p_vmspace->vm_pmap);
+       pmap_debug_level = 10;
+#endif
+
+/* Get the address of the page table containing 0x00000000 */
+
+       addr = trunc_page((u_int)vtopte(0));
+
+#ifdef DEBUG_VMMACHDEP
+       if (pmap_debug_level >= 0) {
+               printf("fun time: paging in PT %08x for %08x\n", (u_int)addr, 0);
+               printf("p->p_vmspace->vm_pmap.pm_pdir[0] = %08x\n", p->p_vmspace->vm_pmap.pm_pdir[0]);
+               printf("p->pm_vptpt[0] = %08x", *((int *)(p->p_vmspace->vm_pmap.pm_vptpt + 0)));
+       }
+#endif
+
+/* Wire down a page to cover the page table zero page and the start of the user are in */
+
+       vm_map_pageable(&p->p_vmspace->vm_map, addr, addr+NBPG, FALSE);
+
+#ifdef DEBUG_VMMACHDEP
+       if (pmap_debug_level >= 0) {
+               printf("party on! acquired a page table for 0M->(4M-1)\n");
+               printf("p->p_vmspace->vm_pmap.pm_pdir[0] = %08x\n", p->p_vmspace->vm_pmap.pm_pdir[0]);
+               printf("p->pm_vptpt[0] = %08x", *((int *)(p->p_vmspace->vm_pmap.pm_vptpt + 0)));
+       }
+#endif
+
+/* Map the system page */
+
+       pmap_enter(&p->p_vmspace->vm_pmap, 0,
+           systempage.physical, VM_PROT_READ, TRUE);
+}
+
+
+void
+cpu_swapout(p)
+       struct proc *p;
+{
+#ifdef DEBUG_VMMACHDEP
+       if (pmap_debug_level >= 0) {
+               printf("cpu_swapout(%08x, %d, %s, %08x)\n", (u_int)p, p->p_pid, p->p_comm, (u_int)&p->p_vmspace->vm_pmap);
+               printf("p->pm_vptpt[0] = %08x", *((int *)(p->p_vmspace->vm_pmap.pm_vptpt + 0)));
+       }
+#endif
+
+/* Free the system page mapping */
+
+       pmap_remove(&p->p_vmspace->vm_pmap, 0, NBPG);
+
+#ifdef FREESWAPPEDPAGEDIRS
+       printf("cpu_swapout(%08x, %d, %s, %08x)\n", (u_int)p, p->p_pid, p->p_comm, (u_int)&p->p_vmspace->vm_pmap);
+       printf("p->pm_vptpt[0] = %08x pdir=%08x\n", *((int *)(p->p_vmspace->vm_pmap.pm_vptpt + 0)), p->p_vmspace->vm_pmap.pm_pdir);
+       pmap_freepagedir(&p->p_vmspace->vm_pmap);
+       p->p_vmspace->vm_pmap.pm_pdir = 0;
+#endif
+
+       idcflush();
+}
+
+
+/*
+ * Move pages from one kernel virtual address to another.
+ * Both addresses are assumed to reside in the Sysmap,
+ * and size must be a multiple of CLSIZE.
+ */
+
+void
+pagemove(from, to, size)
+       caddr_t from, to;
+       int size;
+{
+       register pt_entry_t *fpte, *tpte;
+
+       if (size % CLBYTES)
+               panic("pagemove: size=%08x", size);
+
+#ifdef DEBUG_VMMACHDEP
+       if (pmap_debug_level >= 0)
+               printf("pagemove: V%08x to %08x size %08x\n", (u_int)from,
+                   (u_int)to, size);
+#endif
+       fpte = vtopte(from);
+       tpte = vtopte(to);
+
+       idcflush();
+
+       while (size > 0) {
+               *tpte++ = *fpte;
+               *fpte++ = 0;
+               size -= NBPG;
+       }
+       tlbflush();
+}
+
+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")
+ */
+
+void
+vmapbuf(bp, len)
+       struct buf *bp;
+       vm_size_t len;
+{
+       vm_offset_t faddr, taddr, off;
+       pt_entry_t *fpte, *tpte;
+       pt_entry_t *pmap_pte __P((pmap_t, vm_offset_t));
+
+       if (pmap_debug_level >= 0)
+               printf("vmapbuf: bp=%08x buf=%08x len=%08x\n", (u_int)bp,
+                   (u_int)bp->b_data, (u_int)len);
+    
+       if ((bp->b_flags & B_PHYS) == 0)
+               panic("vmapbuf");
+
+       faddr = trunc_page(bp->b_saveaddr = bp->b_data);
+       off = (vm_offset_t)bp->b_data - faddr;
+       len = round_page(off + len);
+       taddr = kmem_alloc_wait(phys_map, len);
+       bp->b_data = (caddr_t)(taddr + off);
+       /*
+        * The region is locked, so we expect that pmap_pte() will return
+        * non-NULL.
+        */
+
+       fpte = pmap_pte(vm_map_pmap(&bp->b_proc->p_vmspace->vm_map), faddr);
+       tpte = pmap_pte(vm_map_pmap(phys_map), taddr);
+
+       idcflush();
+
+       do {
+               *fpte = (*fpte) & ~PT_C;
+               *tpte++ = *fpte++;
+               len -= PAGE_SIZE;
+       } while (len > 0);
+       tlbflush();
+}
+
+/*
+ * Free the io map PTEs associated with this IO operation.
+ * We also invalidate the TLB entries and restore the original b_addr.
+ */
+
+void
+vunmapbuf(bp, len)
+       struct buf *bp;
+       vm_size_t len;
+{
+       vm_offset_t addr, off;
+
+       if (pmap_debug_level >= 0)
+               printf("vunmapbuf: bp=%08x buf=%08x len=%08x\n",
+                   (u_int)bp, (u_int)bp->b_data, (u_int)len);
+
+       if ((bp->b_flags & B_PHYS) == 0)
+               panic("vunmapbuf");
+
+       idcflush();
+
+       addr = trunc_page(bp->b_data);
+       off = (vm_offset_t)bp->b_data - addr;
+       len = round_page(off + len);
+       kmem_free_wakeup(phys_map, addr, len);
+       bp->b_data = bp->b_saveaddr;
+       bp->b_saveaddr = 0;
+
+       tlbflush();
+}
+
+/*
+ * 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_ARM6, 0);
+       chdr->c_hdrsize = ALIGN(sizeof(*chdr));
+       chdr->c_seghdrsize = ALIGN(sizeof(cseg));
+       chdr->c_cpusize = sizeof(cpustate);
+
+       /* Save integer registers. */
+       error = process_read_regs(p, &cpustate.regs);
+       if (error)
+               return error;
+       /* Save floating point registers. */
+       error = process_read_fpregs(p, &cpustate.fpregs);
+       if (error)
+               return error;
+
+       CORE_SETMAGIC(cseg, CORESEGMAGIC, MID_ARM6, 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)
+               return error;
+
+       chdr->c_nseg++;
+
+       return error;
+}
+
+/* End of vm_machdep.c */
diff --git a/sys/arch/arm32/boot/Makefile b/sys/arch/arm32/boot/Makefile
new file mode 100644 (file)
index 0000000..e97fa68
--- /dev/null
@@ -0,0 +1,96 @@
+# $NetBSD: Makefile,v 1.2 1996/02/01 22:29:25 mycroft Exp $
+
+# Copyright (c) 1994,1995 Mark Brinicombe.
+# Copyright (c) 1994 Brini.
+# All rights reserved.
+#
+# This code is derived from software written for Brini by Mark Brinicombe
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+#    notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+#    notice, this list of conditions and the following disclaimer in the
+#    documentation and/or other materials provided 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 Brini.
+# 4. The name of the company nor the name of the author may be used to
+#    endorse or promote products derived from this software without specific
+#    prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY BRINI ``AS IS'' AND ANY EXPRESS OR IMPLIED
+# 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 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.
+#
+# RiscBSD kernel project
+#
+# Makefile
+#
+# Makefile for RiscBSD bootloader for RISCOS
+#
+# Created      : 14/01/96
+# Last updated : 14/01/96
+#
+#      $Id: Makefile,v 1.1.1.1 1996/04/24 11:08:30 deraadt Exp $
+#
+
+S=     ../../..
+
+machine-links:
+       -rm -f machine && \
+           ln -s ${.CURDIR}/../include machine
+       -rm -f ${MACHINE_ARCH} && \
+           ln -s ${.CURDIR}/../include ${MACHINE_ARCH}
+
+all: machine-links boot
+
+NOPROG=        noprog
+NOMAN= noman
+
+CFLAGS=        -O3 -fno-builtin -D_LOCORE -D_KERNEL -I. -I${.CURDIR} -I$S -I${.CURDIR}/../..
+AFLAGS= -D_LOCORE -D_KERNEL -I. -I${.CURDIR} -I$S -I${.CURDIR}/../..
+
+### find out what to use for libkern and libsa
+#SAREL=
+#KERNREL=
+#.include "Makefile.inc"
+.include "$S/lib/libsa/Makefile.inc"
+.include "$S/lib/libkern/Makefile.inc"
+
+all: boot ${SALIB} ${KERNLIB}
+
+#.PATH:        $S/lib/libkern
+#.PATH:        $S/lib/libkern/arch/arm32
+
+# start.o should be first
+OBJS=  start.o strcpy.o strlen.o strncmp.o strstr.o \
+       svc32.o div.o exit.o enteros.o exitos.o setcpsr.o \
+       memcpy.o memset.o ntohl.o _bsdboot.o _main.o \
+       areahand.o vsprintf.o bsdbooter.o swiv.o
+
+boot:  ${OBJS}
+       ${LD} -Bstatic -e start -N -Ttext 0x8000 -o boot ${OBJS}
+       cp boot boot.sym
+       @strip boot
+       @sh ${.CURDIR}/rmaouthdr boot boot.tmp
+       @mv -f boot.tmp boot
+       @ls -l boot
+
+CLEANFILES+=boot boot.sym machine ${MACHINE_ARCH}
+
+clean::
+       rm -f a.out [Ee]rrs mklog core *.core
+       rm -f ${PROG} ${OBJS} ${LOBJS} ${CLEANFILES}
+
+.include <bsd.prog.mk>
diff --git a/sys/arch/arm32/boot/Makefile.inc b/sys/arch/arm32/boot/Makefile.inc
new file mode 100644 (file)
index 0000000..45bcede
--- /dev/null
@@ -0,0 +1,28 @@
+#      $NetBSD: Makefile.inc,v 1.1 1996/01/31 23:17:48 mark Exp $
+#
+#      NOTE: $S must correspond to the top of the 'sys' tree
+
+KERNDIR=       $S/lib/libkern
+
+KERNDST=       lib/kern
+KERNREL?=      ../../
+KERNLIB?=      ${KERNDST}/libkern.a
+
+${KERNLIB}:            .NOTMAIN __always_make_kernlib
+       @echo making sure the kern library is up to date...
+       @(cd ${KERNDST} && ${MAKE} -f ${KERNREL}${KERNDIR}/Makefile \
+         KERNCC="${CC}" \
+         KERNCFLAGS="${CFLAGS}" \
+         KERNREL="${KERNREL}" \
+         KERNDIR="${KERNDIR}" libkern.o)
+
+clean::                .NOTMAIN __always_make_kernlib
+       @echo cleaning the kern library objects
+       @(cd ${KERNDST} && ${MAKE} -f ${KERNREL}${KERNDIR}/Makefile \
+         KERNCC="${CC}" \
+         KERNCFLAGS="${CFLAGS}" \
+         KERNREL="${KERNREL}" \
+         KERNDIR="${KERNDIR}" clean)
+
+__always_make_kernlib: .NOTMAIN
+       @([ -d ${KERNDST} ] || mkdir -p ${KERNDST})
diff --git a/sys/arch/arm32/boot/README b/sys/arch/arm32/boot/README
new file mode 100644 (file)
index 0000000..27aa484
--- /dev/null
@@ -0,0 +1,7 @@
+Ok, this is the bootloader source that can be used to boot NetBSD/arm32
+from RISCOS. This code was written for use with Norcroft C and
+objasm under RISCOS. It has been modified to compile under NetBSD/arm32
+but is as yet untested.
+
+It is provided here for the moment as example code for a boot loader
+and will be updated shortly to compile under NetBSD/arm32
diff --git a/sys/arch/arm32/boot/_bsdboot.S b/sys/arch/arm32/boot/_bsdboot.S
new file mode 100644 (file)
index 0000000..c9be417
--- /dev/null
@@ -0,0 +1,55 @@
+/* $NetBSD: _bsdboot.S,v 1.1 1996/01/31 23:17:52 mark Exp $ */
+
+/* Copyright (c) 1994 Mark Brinicombe.
+ * Copyright (c) 1994 Brini.
+ * All rights reserved.
+ *
+ * This code is derived from software written for Brini by Mark Brinicombe
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided 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 Brini.
+ * 4. The name of the company nor the name of the author may be used to
+ *    endorse or promote products derived from this software without specific
+ *    prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BRINI ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * 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.
+ *
+ * RiscBSD kernel project
+ *
+ * _boot.s
+ *
+ * Kernel entry/exit code
+ *
+ * Created      : 12/09/94
+ * Last updated : 12/09/94
+ *
+ * Based on kate/boot/_boot.s
+ *
+ *     $Id: _bsdboot.S,v 1.1.1.1 1996/04/24 11:08:31 deraadt Exp $
+ */
+
+#include "regs.h"
+
+       .text
+       .global __bsdboot
+__bsdboot:
+       mov     pc, r1
diff --git a/sys/arch/arm32/boot/_main.S b/sys/arch/arm32/boot/_main.S
new file mode 100644 (file)
index 0000000..c0bdb9e
--- /dev/null
@@ -0,0 +1,141 @@
+/* $NetBSD: _main.S,v 1.1 1996/01/31 23:17:57 mark Exp $ */
+
+/* Copyright (c) 1994 Mark Brinicombe.
+ * Copyright (c) 1994 Brini.
+ * All rights reserved.
+ *
+ * This code is derived from software written for Brini by Mark Brinicombe
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided 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 Brini.
+ * 4. The name of the company nor the name of the author may be used to
+ *    endorse or promote products derived from this software without specific
+ *    prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BRINI ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * 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.
+ *
+ * RiscBSD kernel project
+ *
+ * _main.s
+ *
+ * Kernel entry/exit code
+ *
+ * Created      : 12/09/94
+ * Last updated : 12/09/94
+ *
+ * Based on kate/boot/_main.s
+ *
+ *     $Id: _main.S,v 1.1.1.1 1996/04/24 11:08:31 deraadt Exp $
+ */
+
+#include "regs.h"
+
+       .global ___main
+___main:
+       swi     0x20010
+       mov     sp, r1
+       sub     sl, sp, #2048
+
+       ldr     r3, [pc, #cli_ptr - . - 8]
+       str     r0, [r3]
+#if 0
+        LDR     a4,[pc,#|__cli_ptr|-.-8]
+        STR     a1,[a4,#0]
+        LDR     a4,[pc,#|__himem_ptr|-.-8]
+        STR     a2,[a4,#0]
+        LDR     a4,[pc,#|__stack_ptr|-.-8]
+        STR     sl,[a4,#0]
+        LDR     a4,[pc,#|__robase_ptr|-.-8]
+        LDR     a1,[a4,#0]
+        LDR     a4,[pc,#|__base_ptr|-.-8]
+        STR     a1,[a4,#0]
+        LDR     a4,[pc,#|__rwlimit_ptr|-.-8]
+        LDR     a1,[a4,#0]
+        LDR     a4,[pc,#|__lomem_ptr|-.-8]
+        STR     a1,[a4,#0]
+        LDR     a4,[pc,#|__break_ptr|-.-8]
+        STR     a1,[a4,#0]
+#endif
+#if 0
+       cmp     sl, r0
+       movlss  pc, lr  /* no stack - exit fast */
+       add     sl, sl, #256
+#endif
+       mov     fp, #0
+       b       __main
+
+cli_ptr:
+       .word   ___cli
+
+       .data
+       .global ___cli
+___cli:
+       .word   0
+
+#if 0
+
+|__cli_ptr|
+        DCD     |__cli|
+
+|__robase_ptr|
+        DCD     |__robase|
+|__base_ptr|
+        DCD     |__base|
+|__rwbase_ptr|
+        DCD     |__rwbase|
+|__rwlimit_ptr|
+        DCD     |__rwlimit|
+|__himem_ptr|
+        DCD     |__himem|
+|__lomem_ptr|
+        DCD     |__lomem|
+
+|__break_ptr|
+        DCD     |__break|
+|__stack_ptr|
+        DCD     |__stack|
+
+|__time_ptr|
+        DCD     |__time|
+
+        EXPORT  |__cli|         ; CLI from OS_GetEnv
+|__cli|
+        DCD     0
+
+        EXPORT  |__base|        ; BASE (application = 0x8000)
+|__base|
+        DCD     0
+        EXPORT  |__lomem|       ; LOMEM
+|__lomem|
+        DCD     0
+        EXPORT  |__himem|       ; HIMEM from OS_GetEnv
+|__himem|
+        DCD     0
+
+        EXPORT  |__break|       ; the 'break'
+|__break|
+        DCD     0
+        EXPORT  |__stack|       ; stack limit
+|__stack|
+        DCD     0
+
+#endif
diff --git a/sys/arch/arm32/boot/areahand.S b/sys/arch/arm32/boot/areahand.S
new file mode 100644 (file)
index 0000000..6955ec3
--- /dev/null
@@ -0,0 +1,98 @@
+/* $NetBSD: areahand.S,v 1.1 1996/01/31 23:18:01 mark Exp $ */
+
+/*
+ * Copyright (c) 1994 Mark Brinicombe.
+ * Copyright (c) 1994 Brini.
+ * All rights reserved.
+ *
+ * This code is derived from software written for Brini by Mark Brinicombe
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided 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 Brini.
+ * 4. The name of the company nor the name of the author may be used to
+ *    endorse or promote products derived from this software without specific
+ *    prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BRINI ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * 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.
+ *
+ * RiscBSD kernel project
+ *
+ * areahand.s
+ *
+ *
+ *
+ * Created      : 12/09/94
+ * Last updated : 12/09/94
+ *
+ *    $Id: areahand.S,v 1.1.1.1 1996/04/24 11:08:31 deraadt Exp $
+ */
+
+#include "regs.h"
+
+       .text
+       .global _kernarea_handler
+/*
+ * r0 - code
+ * r1 - page block
+ * r2 - entries
+ * r3 - size increase
+ * r4 - current size
+ * r5 - pagesize
+ * r12 - arrangement table
+ */
+
+_kernarea_handler:
+/* Is it a pregrow request ? */
+       teq     r0, #0x00000000
+       bicnes  pc, lr, #1<<28
+
+/* Make sure that the area is currently 0 in size */
+       teq     r4, #0x00000000
+       movne   r0, #0x000000
+       orrnes  pc, lr, #1<<28
+
+       teq     r1, #0x00000000
+       biceqs  pc, lr, #1<<28
+
+/* Store registers */
+       stmfd   sp!, {r0-r12}
+
+/* Get first page number */
+       ldr     r8, [r12, #0x0004]
+       sub     r8, r8, r2
+       mov     r8, #0x00000700
+       str     r1, [r12]
+
+loop:
+       str     r8, [r1], #0x000c
+       add     r8, r8, #0x00000001
+       subs    r2, r2, #0x00000001
+       bne     loop
+
+       ldmfd   sp!, {r0-r12}
+/*     bics    pc, lr, #1<<28 */
+       adr     r0, error1
+       orrs    pc, lr, #1<<28
+
+error1:
+       .word   0
+       .asciz  "error1"
diff --git a/sys/arch/arm32/boot/arm6.h b/sys/arch/arm32/boot/arm6.h
new file mode 100644 (file)
index 0000000..9c52ce6
--- /dev/null
@@ -0,0 +1,161 @@
+; ARM6 PSR transfer macros
+
+; Condition code symbols
+
+Cond_EQ *       0  :SHL: 28
+Cond_NE *       1  :SHL: 28
+Cond_CS *       2  :SHL: 28
+Cond_HS * Cond_CS
+Cond_CC *       3  :SHL: 28
+Cond_LO * Cond_CC
+Cond_MI *       4  :SHL: 28
+Cond_PL *       5  :SHL: 28
+Cond_VS *       6  :SHL: 28
+Cond_VC *       7  :SHL: 28
+Cond_HI *       8  :SHL: 28
+Cond_LS *       9  :SHL: 28
+Cond_GE *       10 :SHL: 28
+Cond_LT *       11 :SHL: 28
+Cond_GT *       12 :SHL: 28
+Cond_LE *       13 :SHL: 28
+Cond_AL *       14 :SHL: 28
+Cond_   * Cond_AL
+Cond_NV *       15 :SHL: 28
+
+; New positions of I and F bits in 32-bit PSR
+
+I32_bit *       1 :SHL: 7
+F32_bit *       1 :SHL: 6
+IF32_26Shift *  26-6
+
+; Processor mode numbers
+
+USR26_mode      *       2_00000
+FIQ26_mode      *       2_00001
+IRQ26_mode      *       2_00010
+SVC26_mode      *       2_00011
+USR32_mode      *       2_10000
+FIQ32_mode      *       2_10001
+IRQ32_mode      *       2_10010
+SVC32_mode      *       2_10011
+ABT32_mode      *       2_10111
+UND32_mode      *       2_11011
+
+; New register names
+
+r13_abort       RN      13
+r14_abort       RN      14
+lr_abort        RN      14
+
+r13_undef       RN      13
+r14_undef       RN      14
+lr_undef        RN      14
+
+        MACRO
+        mrs     $cond, $rd, $psrs
+        LCLA    psrtype
+psrtype SETA    -1
+ [ "$psrs" = "CPSR" :LOR: "$psrs" = "CPSR_all"
+psrtype SETA    0 :SHL: 22
+ ]
+ [ "$psrs" = "SPSR" :LOR: "$psrs" = "SPSR_all"
+psrtype SETA    1 :SHL: 22
+ ]
+        ASSERT  psrtype <> -1
+        ASSERT  $rd <> 15
+        &       Cond_$cond :OR: 2_00000001000011110000000000000000 :OR: psrtype :OR: ($rd :SHL: 12)
+        MEND
+
+        MACRO
+        msr     $cond, $psrl, $op2a, $op2b
+        LCLA    psrtype
+        LCLS    op2as
+        LCLA    op
+        LCLA    shift
+psrtype SETA    -1
+ [ "$psrl" = "CPSR" :LOR: "$psrl" = "CPSR_all"
+psrtype SETA    (0:SHL:22) :OR: (1:SHL:19) :OR: (1:SHL:16)
+ ]
+ [ "$psrl" = "CPSR_flg"
+psrtype SETA    (0:SHL:22) :OR: (1:SHL:19) :OR: (0:SHL:16)
+ ]
+ [ "$psrl" = "CPSR_ctl"
+psrtype SETA    (0:SHL:22) :OR: (0:SHL:19) :OR: (1:SHL:16)
+ ]
+ [ "$psrl" = "SPSR" :LOR: "$psrl" = "SPSR_all"
+psrtype SETA    (1:SHL:22) :OR: (1:SHL:19) :OR: (1:SHL:16)
+ ]
+ [ "$psrl" = "SPSR_flg"
+psrtype SETA    (1:SHL:22) :OR: (1:SHL:19) :OR: (0:SHL:16)
+ ]
+ [ "$psrl" = "SPSR_ctl"
+psrtype SETA    (1:SHL:22) :OR: (0:SHL:19) :OR: (1:SHL:16)
+ ]
+        ASSERT  psrtype <> -1
+ [ ("$op2a" :LEFT: 1) = "#"
+ ; Immediate operand
+
+op2as   SETS    "$op2a" :RIGHT: ((:LEN: "$op2a")-1)
+op      SETA    $op2as
+
+  [ "$op2b" = ""
+  ; Rotate not specified in immediate operand
+shift   SETA    0
+        WHILE   (op :AND: &FFFFFF00)<>0 :LAND: shift<16
+op      SETA    ((op:SHR:30):AND:3):OR:(op:SHL:2)
+shift   SETA    shift + 1
+        WEND
+        ASSERT  (op :AND: &FFFFFF00)=0
+  |
+  ; Rotate of immediate operand specified explicitly
+        ASSERT  (($op2b):AND:&FFFFFFE1)=0
+shift   SETA    ($opt2b):SHR:1
+  ]
+op      SETA    (shift :SHL: 8) :OR: op :OR: (1:SHL:25)
+ |
+
+ ; Not an immediate operand
+  [ "$op2b" = ""
+  ; Unshifted register
+op      SETA    ($op2a) :OR: (0:SHL:25)
+  |
+        ! 1, "Shifted register not yet implemented in this macro!"
+  ]
+ ]
+        &       Cond_$cond :OR: 2_00000001001000001111000000000000 :OR: op :OR: psrtype
+        MEND
+
+; SetMode newmode, reg1, regoldpsr
+;
+; Sets processor mode to constant value newmode
+; using register reg1 as a temporary.
+; If regoldpsr is specified, then this register
+; on exit holds the old PSR before the mode change
+; reg1 on exit always holds the new PSR after the mode change
+
+;        MACRO
+;        SetMode $newmode, $reg1, $regoldpsr
+; [ "$regoldpsr"=""
+;        mrs     AL, $reg1, CPSR_all
+;        BIC     $reg1, $reg1, #&1F
+;        ORR     $reg1, $reg1, #$newmode
+;        msr     AL, CPSR_all, $reg1
+; |
+;        mrs     AL, $regoldpsr, CPSR_all
+;        BIC     $reg1, $regoldpsr, #&1F
+;        ORR     $reg1, $reg1, #$newmode
+;        msr     AL, CPSR_all, $reg1
+; ]
+;        MEND
+
+        MACRO
+        mrc     $cond, $coproc, $op, $rd, $crn, $crm, $info
+        &       Cond_$cond :OR: 2_00001110000100000000000000010000 :OR: ($coproc :SHL: 8) :OR: ($op :SHL: 21) :OR: ($rd :SHL: 12) :OR: ($crn :SHL: 16) :OR: $crm :OR: ($info :SHL: 5)
+        MEND
+
+        MACRO
+        mcr     $cond, $coproc, $op, $rd, $crn, $crm, $info
+        &       Cond_$cond :OR: 2_00001110000000000000000000010000 :OR: ($coproc :SHL: 8) :OR: ($op :SHL: 21) :OR: ($rd :SHL: 12) :OR: ($crn :SHL: 16) :OR: $crm :OR: ($info :SHL: 5)
+        MEND
+
+       END
diff --git a/sys/arch/arm32/boot/bsdbooter.c b/sys/arch/arm32/boot/bsdbooter.c
new file mode 100644 (file)
index 0000000..c187335
--- /dev/null
@@ -0,0 +1,777 @@
+/* $NetBSD: bsdbooter.c,v 1.1 1996/01/31 23:18:08 mark Exp $ */
+
+/*
+ * Copyright (c) 1994,1995 Mark Brinicombe.
+ * Copyright (c) 1994,1995 Brini.
+ * All rights reserved.
+ *
+ * This code is derived from software written for Brini by Mark Brinicombe
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided 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 Mark Brinicombe.
+ * 4. The name of the company nor the name of the author may 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.
+ *
+ * RiscBSD kernel project
+ *
+ * bsdbooter.c
+ *
+ * RiscBSD boot loader
+ *
+ * Created      : 12/09/94
+ * Last updated : 08/03/95
+ *
+ * Based on kate/boot/boot.c
+ *
+ *    $Id: bsdbooter.c,v 1.1.1.1 1996/04/24 11:08:31 deraadt Exp $
+ */
+
+/* Include standard header files */
+
+# include <stdlib.h>
+# include <string.h>
+# include <stdarg.h>
+
+/* Include local headers */
+
+#include <sys/types.h>
+#include <sys/exec.h>
+#include <machine/cpu.h>
+#include <machine/katelib.h>
+#include <machine/bootconfig.h>
+#include "swiv.h"
+#include "swis.h"
+
+/*
+ * Declare global variables
+ */
+
+# define VERSION "2.10"
+
+# define USE_MODULEAREA
+
+# define KERNAREA 512
+# define KERNBASE 0xf0000000
+
+# define TABLEAREA 513
+# define LOADAREA 514
+
+# define SCRATCHSIZE 0xc000
+
+
+# define OS_DynamicArea 0x66
+# define OS_Memory      0x68
+# define OS_MMUControl  0x6b
+
+# define FASTBOOT_FILENAME "<BtRiscBSD$Dir>.booter.fastboot"
+
+/*
+ * Declare external variables
+ */
+
+extern char *__cli;
+
+/*
+ * Local vars. Some of these have to be global because they are used after
+ * the processor has been switches to SVC mode local variables would be
+ * lost as they would be on the USR mode stack.
+ */
+
+typedef struct exec aout_t;
+
+BootConfig bootconfig;
+int in[3], out[3];
+char kernelname[1024];
+unsigned char *buffer;
+static aout_t aout;
+unsigned int kernelsize;
+unsigned int logical;
+unsigned int physical;
+unsigned int filesize;
+unsigned int copysize;
+
+/*
+ * Local function prototypes
+ */
+
+void fatal(struct Error *error);
+unsigned char *locate_memory_blocks(void);
+void uprintf(char *formattoken, ...);
+void _bsdboot(BootConfig *bootconfig, unsigned int address);
+int vsprintf(char *buf, const char *fmt, va_list args);
+
+/* Now for the main code */
+
+extern int main (int, char **);
+
+void __exit(int);
+
+void _main(void)
+  {
+       uprintf("_main entered\n");
+    __exit (main (0, (char **)0));     /* ... ignition */
+
+/* not reached */
+  }
+
+/* The main booter code */
+
+int main(int argc, char *argv[])
+  {
+    char *cliptr;
+    int loop;
+    int filehandle;
+    unsigned char *arrangementtable;
+
+       uprintf("main entered\n");
+
+/* Analyse the command line */
+
+    cliptr = __cli;
+
+       uprintf("command line is %s\n", cliptr);
+       
+/* Skip the command name */
+
+    while (*cliptr != ' ' && *cliptr != 0)
+      ++cliptr;
+
+/* Skip any spaces */
+
+    while (*cliptr == ' ')
+      ++cliptr;
+
+/* Check for another parameter */
+
+    if (*cliptr != 0)
+      {
+        for (loop = 0; *cliptr != ' ' && *cliptr != 0; ++loop,++cliptr)
+          {
+            kernelname[loop] = *cliptr;
+          }
+        kernelname[loop] = 0;
+      }
+    else
+      strcpy(kernelname, "riscbsd");
+
+    strcpy(bootconfig.kernelname, kernelname);
+
+/* Write the command line used to a fastboot file. Execing or Obeying
+ * this file will boot RiscBSD. This can be used during the RiscOS bootup
+ * to enable a fast boot.
+ */
+
+/*
+ * Open the autoboot file. Just skip if file cannot be opened.
+ */
+
+    swi(OS_Find, IN(R0|R1)|OUT(R0), 0x80, FASTBOOT_FILENAME, &filehandle);
+    if (filehandle != 0)
+      {
+        swi(OS_GBPB, IN(R0|R1|R2|R3|R4), 2, filehandle, __cli,
+          strlen(__cli), 0);
+        swi(OS_GBPB, IN(R0|R1|R2|R3|R4), 2, filehandle, "\n", 1, 0);
+
+/* Close the file */
+
+        swi(OS_Find, IN(R0|R1), 0, filehandle);
+
+        swi(OS_File, IN(R0|R1|R2), 18, FASTBOOT_FILENAME, 0xfeb);
+      }
+    else
+      {
+        uprintf("Warning: Cannot write fastboot file %s\n\r", FASTBOOT_FILENAME);
+      }
+
+/* Set the screen mode ... */
+
+/* I know this is messy. It is currently just a hack to try things out
+ * Why didn't Acorn add a SWI call to interpret the mode string and return
+ * a mode specifer ?
+ */
+
+/* Also this is temporary as eventually the console driver will set the VIDC
+ * up as required.
+ * It sort of expects the screenmode= options to be at the end of the string.
+ */
+
+    {
+      char *modeptr;
+      int modespec[6];
+
+      modeptr = strstr(__cli, "screenmode=");
+      if (modeptr)
+        {
+          modeptr += 11;
+          modespec[0] = 0x00000001;
+          modespec[1] = 0x00000000;
+          modespec[2] = 0x00000000;
+          modespec[3] = 0x00000003;
+          modespec[4] = 0x00000000;
+          modespec[5] = -1;
+
+          while (*modeptr)
+            {
+              switch (*modeptr)
+                {
+                  case 'X':
+                  case 'x':
+                    ++modeptr;
+                    while (*modeptr >= '0' && *modeptr <= '9')
+                      {
+                        modespec[1] = (modespec[1] * 10) + (*modeptr - '0');
+                        ++modeptr;
+                      }
+                    break;
+
+                  case 'Y':
+                  case 'y':
+                    ++modeptr;
+                    while (*modeptr >= '0' && *modeptr <= '9')
+                      {
+                        modespec[2] = (modespec[2] * 10) + (*modeptr - '0');
+                        ++modeptr;
+                      }
+                    break;
+/*
+                  case 'C':
+                  case 'c':
+                  case 'G':
+                  case 'g':
+                    ++modeptr;
+                    while (*modeptr >= '0' && *modeptr <= '9')
+                      {
+                        modespec[3] = (modespec[3] * 10) + (*modeptr - '0');
+                        ++modeptr;
+                      }
+                    break;
+*/
+                  case 'F':
+                  case 'f':
+                    ++modeptr;
+                    while (*modeptr >= '0' && *modeptr <= '9')
+                      {
+                        modespec[4] = (modespec[4] * 10) + (*modeptr - '0');
+                        ++modeptr;
+                      }
+                    break;
+
+                  default:
+                    ++modeptr;
+                    break;
+                }
+            }
+          if (modespec[4] == 0) modespec[4] = -1;
+/*          uprintf("x=%d y=%d c=%d f=%d\n", modespec[1], modespec[2],
+            modespec[3], modespec[4]);*/
+          fatal(swix(Wimp_SetMode, IN(R0), &modespec));
+          bootconfig.framerate = modespec[4];
+        }
+      else
+        bootconfig.framerate = 0;
+    }
+
+/* Announcement time .. */
+/* Used to be above but now moved to after the mode change */
+
+
+    if (strstr(__cli, "verbose") != 0)
+      uprintf("RiscBSD BootLoader " VERSION " " __DATE__ "\n\r");
+
+/* A bit of info */
+
+    if (strstr(__cli, "verbose") != 0)
+      uprintf("Kernel: %s\n\r", kernelname);
+
+/* Get the machine id */
+
+    fatal(swix(OS_ReadSysInfo, IN(R0)|OUT(R3), 2, &bootconfig.machine_id));
+
+/* Get the display variables. Failure on any of these will abort the boot */
+
+    in[0] = 149;
+    in[1] = 150;
+    in[2] = -1;
+
+    fatal(swix(OS_ReadVduVariables, IN(R0|R1), &in, &out));
+
+    bootconfig.display_start = out[0];
+    bootconfig.display_size = out[1];
+
+    fatal(swix(OS_ReadModeVariable, IN(R0|R1) | OUT(R2), -1, 9,
+      &bootconfig.bitsperpixel));
+    fatal(swix(OS_ReadModeVariable, IN(R0|R1) | OUT(R2), -1, 11,
+      &bootconfig.width));
+    fatal(swix(OS_ReadModeVariable, IN(R0|R1) | OUT(R2), -1, 12,
+      &bootconfig.height));
+
+/* Will the kernel support this mode ? */
+
+    if (bootconfig.bitsperpixel > 3)
+      {
+        swi(OS_Write0, IN(R0),
+          "Error: Only 1, 2, 4 or 8 bpp modes are currently supported\n\r");
+        return(0);
+      }
+
+/* Get the arrangement table for the memory */
+
+    arrangementtable = locate_memory_blocks();
+
+/*
+ * Ok we will support a.out files as well. This means that we need to
+ * identify the format.
+ */
+
+/* Get the size of the file */
+
+    fatal(swix(OS_File, IN(R0|R1)|OUT(R4), 5, kernelname, &filesize));
+
+/*
+ * Read the start of the file so that we change check for the a.out
+ * magic number.
+ */
+
+    swi(OS_Find, IN(R0|R1)|OUT(R0), 0x40, kernelname, &filehandle);
+    if (filehandle == 0)
+      {
+        uprintf("Error: Cannot read kernel file %s\n\r", kernelname);
+        return(0);
+      }
+
+    aout.a_midmag = 0;
+
+    fatal(swix(OS_GBPB, IN(R0|R1|R2|R3|R4), 3, filehandle, &aout,
+      sizeof(aout_t), 0));
+
+/* Do we have an a.out file ? */
+
+    switch(N_GETMAGIC(aout)) {
+      case NMAGIC:
+        if (strstr(__cli, "verbose") != 0)
+          swi(OS_Write0, IN(R0), "Kernel binary is NMAGIC a.out format\n\r");
+        kernelsize = (unsigned int)(aout.a_text + aout.a_data + aout.a_bss);
+        copysize = (unsigned int)(aout.a_text + aout.a_data);
+       break;
+      case OMAGIC:
+        if (strstr(__cli, "verbose") != 0)
+          swi(OS_Write0, IN(R0), "Kernel binary is OMAGIC a.out format\n\r");
+        kernelsize = (unsigned int)(aout.a_text + aout.a_data + aout.a_bss);
+        copysize = (unsigned int)(aout.a_text + aout.a_data);
+       break;
+      case ZMAGIC:
+        if (strstr(__cli, "verbose") != 0)
+          swi(OS_Write0, IN(R0), "Kernel binary is ZMAGIC a.out format\n\r");
+        kernelsize = (unsigned int)(aout.a_text + aout.a_data + aout.a_bss);
+        copysize = (unsigned int)(aout.a_text + aout.a_data);
+       break;
+      default:
+        if (strstr(__cli, "verbose") != 0)
+          swi(OS_Write0, IN(R0), "Kernel binary is AIF format\n\r");
+        kernelsize = filesize;
+        copysize = filesize;
+        break;
+    }
+
+/* Give ourselves 16K of spare space and round off to a page */
+
+/*
+ * This is messy. We should read the memory info first, but I have not
+ * changed things yet. This is part of the hack to support a.out files
+ * as well
+ */
+
+    kernelsize = (kernelsize + 0x4000) & ~(bootconfig.pagesize-1);
+
+/* Set the virtual address of the kernel in the bootconfig structure */
+
+    bootconfig.kernvirtualbase = KERNBASE;
+    bootconfig.kernsize = kernelsize;
+    bootconfig.argvirtualbase = bootconfig.kernvirtualbase
+                              + bootconfig.kernsize;
+    bootconfig.argsize = bootconfig.pagesize;
+    bootconfig.scratchvirtualbase = bootconfig.argvirtualbase
+                                  + bootconfig.argsize;
+    bootconfig.scratchsize = SCRATCHSIZE;
+
+    kernelsize += bootconfig.argsize;
+
+    kernelsize += bootconfig.scratchsize;
+
+/* Verbose info to the user. This is mainly debugging */
+
+    if (strstr(__cli, "verbose") != 0)
+      {
+        uprintf("filesize = %08x\n\r", filesize);
+        uprintf("bootconfig.kernvirtualbase = %08x\n\r",
+          bootconfig.kernvirtualbase);
+        uprintf("bootconfig.kernsize = %08x\n\r", bootconfig.kernsize);
+        uprintf("bootconfig.argvirtualbase = %08x\n\r",
+          bootconfig.argvirtualbase);
+        uprintf("bootconfig.argsize = %08x\n\r", bootconfig.argsize);
+        uprintf("bootconfig.scratchvirtualbase = %08x\n\r",
+          bootconfig.scratchvirtualbase);
+        uprintf("bootconfig.scratchsize = %08x\n\r", bootconfig.scratchsize);
+        uprintf("kernelsize = %08x\n\r", kernelsize);
+        uprintf("copysize = %08x\n\r", copysize);
+      }
+
+# ifdef USE_MODULEAREA
+
+/* Allocate memory in module area to hold the data we are loading */
+
+    fatal(swix(OS_Module, IN(R0|R3)|OUT(R2), 6, filesize, &buffer));
+
+# else
+
+/* Allocate memory to hold the data we are loading */
+
+    swix(OS_DynamicArea, IN(R0|R1), 1, LOADAREA);
+
+    fatal(swix(OS_DynamicArea, IN(R0|R1|R2|R3|R4|R5|R6|R7|R8)|OUT(R3), 0,
+      LOADAREA, filesize, -1, 0x80, filesize, 0, 0, "Kate Data", &buffer));
+
+# endif
+
+/* Load the appropriate part depending on the file type */
+
+    switch (N_GETMAGIC(aout)) {
+      case OMAGIC:
+      case NMAGIC:
+        swi(OS_GBPB, IN(R0|R1|R2|R3|R4), 3, filehandle, buffer,
+          filesize, sizeof(aout_t));
+       break;
+      case ZMAGIC:
+      default:
+        swi(OS_GBPB, IN(R0|R1|R2|R3|R4), 3, filehandle, buffer,
+          filesize, 0);
+        break;
+    }
+
+/* Close the file */
+
+    fatal(swix(OS_Find, IN(R0|R1), 0, filehandle));
+
+
+/* This is redundant at the moment */
+
+    swix(OS_DynamicArea, IN(R0|R1), 1, KERNAREA);
+
+    fatal(swix(OS_DynamicArea, IN(R0|R1|R2|R3|R4|R5|R6|R7|R8), 0,
+      KERNAREA, 0, KERNBASE, 0x80, 0x1000, 0, 0, "Kate Kernel"));
+
+/* Shutdown RiscOS cleanly ... */
+
+/* Close all open files and shutdown filing systems */
+
+    swix(OS_FSControl, IN(R0), 23);
+
+/* Issue a pre-reset service call to reset the podules */
+
+    swix(OS_ServiceCall, IN(R1), 0x45);
+
+/* Kill the etherH module to avoid locks up on reboot */
+
+    swix(OS_Module, IN(R0|R1), 4, "EtherH");
+
+/* More user information describing the memory found */
+
+    if (strstr(__cli, "verbose") != 0)
+      {
+        uprintf("DRAM bank 0a = %08x %08x\n\r", bootconfig.dram[0].address,
+          bootconfig.dram[0].pages * bootconfig.pagesize);
+        uprintf("DRAM bank 0b = %08x %08x\n\r", bootconfig.dram[1].address,
+          bootconfig.dram[1].pages * bootconfig.pagesize);
+        uprintf("DRAM bank 1a = %08x %08x\n\r", bootconfig.dram[2].address,
+          bootconfig.dram[2].pages * bootconfig.pagesize);
+        uprintf("DRAM bank 1b = %08x %08x\n\r", bootconfig.dram[3].address,
+          bootconfig.dram[3].pages * bootconfig.pagesize);
+        uprintf("VRAM bank 0  = %08x %08x\n\r", bootconfig.vram[0].address,
+          bootconfig.vram[0].pages * bootconfig.pagesize);
+    }
+
+/* Hack for 2 Meg VRAM until the new console code is in place */
+
+/*    if (strstr(__cli, "vramhack") != 0)
+      {
+        bootconfig.display_size /= 1;
+        bootconfig.vram[0].pages /= 2;
+
+        uprintf("VRAM bank 0  = %08x %08x\n\r", bootconfig.vram[0].address,
+          bootconfig.vram[0].pages * bootconfig.pagesize);
+      }*/
+
+/* Jump to SVC26 mode - remember we have no local vars now ! */
+
+    EnterOS();
+
+/* Find the number of the upper most bank of DRAM available */
+
+    loop = 3;
+    while (bootconfig.dram[loop].address == 0)
+      --loop;
+
+/* Allocate the physical addresses for the kernel in this bank */
+
+    physical = bootconfig.dram[loop].address - kernelsize
+             + bootconfig.dram[loop].pages * bootconfig.pagesize;
+    bootconfig.kernphysicalbase = physical;
+    bootconfig.argphysicalbase = bootconfig.kernphysicalbase
+                               + bootconfig.kernsize;
+    bootconfig.scratchphysicalbase = bootconfig.argphysicalbase
+                                   + bootconfig.argsize;
+
+/* Yet more debugging info */
+
+    if (strstr(__cli, "verbose") != 0)
+      {
+        uprintf("buffer = %08x\n\r", buffer);
+        uprintf("physical = %08x\n\r", physical);
+        uprintf("bootconfig.kernphysicalbase = %08x\n\r",
+          bootconfig.kernphysicalbase);
+        uprintf("bootconfig.argphysicalbase = %08x\n\r",
+          bootconfig.argphysicalbase);
+        uprintf("bootconfig.scratchphysicalbase = %08x\n\r",
+          bootconfig.scratchphysicalbase);
+      }
+
+/*
+ * Ok just check to see if anything is mapped where we are about to map
+ * the kernel.
+ */
+
+/*
+    for (logical = KERNBASE; logical < KERNBASE + kernelsize;
+     logical += bootconfig.pagesize)
+      {
+        if (ReadWord(0x02c00000 + (logical >> 10) & 0xfffffffc) != 0)
+          {
+            uprintf("Error: Memory required for RiscBSD boot not available\n\r");
+            return(0);
+          }
+      }
+*/
+/* Get out clause */
+
+    if (strstr(__cli, "noboot") != 0)
+      {
+        ExitOS();
+        return(0);
+      }
+
+/*
+ * Hook the physical pages to the required virtual address directly by
+ * writing into RiscOS's page tables. This should be done via a
+ * dynamic area handler but I cannot get it to work as documented.
+ */
+
+    for (logical = KERNBASE; logical < KERNBASE + kernelsize;
+     logical += bootconfig.pagesize)
+      {
+        WriteWord(0x02c00000 + (logical >> 10) & 0xfffffffc,
+          0x00000ffe | (physical & 0xfffff000));
+        physical += bootconfig.pagesize;
+      }
+
+/* Map the IO up high so we can get at it */
+
+    WriteWord(0x02c0c000 + (0xf6000000 >> 18) & 0xfffffffc,
+      0x00000412 | (0x03200000 & 0xfffff000));
+    WriteWord(0x02c0c000 + (0xf6100000 >> 18) & 0xfffffffc,
+      0x00000412 | (0x03400000 & 0xfffff000));
+
+    memset((char *)bootconfig.display_start, 0xcc, 0x4000);
+
+/* Disable IRQ and FIQ interrupts */
+
+    SetCPSR(I32_bit | F32_bit, I32_bit | F32_bit);
+
+    memset((char *)bootconfig.display_start + 0x4000, 0x55, 0x4000);
+
+    memcpy((char *)bootconfig.argvirtualbase, __cli, bootconfig.argsize);
+
+    memset((char *)bootconfig.display_start + 0x8000, 0x80, 0x4000);
+
+    memset((char *)bootconfig.argvirtualbase, SCRATCHSIZE, 0);
+
+    memset((char *)bootconfig.display_start + 0xC000, 0xbb, 0x4000);
+
+    memcpy((char *)bootconfig.kernvirtualbase, buffer, copysize);
+
+    memset((char *)bootconfig.display_start + 0x10000, 0xaa, 0x4000);
+
+/* Real late debugging get out clause */
+
+    if (strstr(__cli, "nearboot") != 0)
+      {
+        SetCPSR(I32_bit | F32_bit, 0);
+        ExitOS();
+        return(0);
+      }
+
+/* Punch into SVC32 mode */
+
+    SVC32();
+
+/* Point of no return */
+
+    switch (N_GETMAGIC(aout)) {
+      case OMAGIC:
+      case NMAGIC:
+      case ZMAGIC:
+        _bsdboot(&bootconfig, (unsigned int)aout.a_entry);
+        break;
+      default:
+        _bsdboot(&bootconfig, KERNBASE);
+        break;
+    }
+
+    return(0);
+  }
+
+
+/* Report an error */
+
+void fatal(struct Error *error)
+  {
+    if (error)
+      {
+        swi(OS_GenerateError, IN(R0), error);
+      }
+  }
+
+
+/* Locate all the blocks of memory in the system */
+
+unsigned char *locate_memory_blocks(void)
+  {
+    int loop;
+    int page;
+    int currentpage;
+    int currentpages;
+    int currentaddr;
+    unsigned char *table;
+    unsigned int pagesize;
+    unsigned int tablesize;
+    int dramblocks = 0;
+    int vramblocks = 0;
+
+/* Get table size and page size */
+
+    fatal(swix(OS_Memory, IN(R0)|OUT(R1|R2), 6, &tablesize, &pagesize));
+
+/* Allocate memory for table */
+
+/*# ifdef USE_MODULEAREA*/
+
+    fatal(swix(OS_Module, IN(R0|R3)|OUT(R2), 6, tablesize, &table));
+
+/*# else*/
+
+/* Allocate memory to hold the data we are loading */
+
+/*    swix(OS_DynamicArea, IN(R0|R1), 1, TABLEAREA);
+
+    fatal(swix(OS_DynamicArea, IN(R0|R1|R2|R3|R4|R5|R6|R7|R8)|OUT(R3), 0,
+      TABLEAREA, tablesize, -1, 0x80, tablesize, 0, 0, "Kate Table", &table));
+
+# endif*/
+
+
+/* read the table */
+
+    fatal(swix(OS_Memory, IN(R0|R1), 7, table));
+
+/* Loop round locating all the valid blocks of memory */
+
+    currentpage = -1;
+
+    for (loop = 0; loop < tablesize * 2; ++loop)
+      {
+        page = table[loop / 2];
+        if (loop % 2)
+          page = page >> 4;
+
+        page = page & 0x07;
+
+        if (page != currentpage)
+          {
+            switch (currentpage)
+              {
+                case 1:
+                  bootconfig.dram[dramblocks].address = currentaddr * pagesize;
+                  bootconfig.dram[dramblocks].pages = currentpages;
+                  ++dramblocks;
+                  break;
+
+                case 2:
+                  bootconfig.vram[vramblocks].address = currentaddr * pagesize;
+                  bootconfig.vram[vramblocks].pages = currentpages;
+                  ++vramblocks;
+                  break;
+
+                default :
+                  break;
+              }
+
+            currentpage = page;
+            currentaddr = loop;
+            currentpages = 0;
+          }
+        ++currentpages;
+      }
+
+/* Get the number of dram and vram pages */
+
+    fatal(swix(OS_Memory, IN(R0)|OUT(R1), 0x00000108, &bootconfig.drampages));
+    fatal(swix(OS_Memory, IN(R0)|OUT(R1), 0x00000208, &bootconfig.vrampages));
+
+/* Fill in more bootconfig parameters */
+
+    bootconfig.pagesize = pagesize;
+
+    bootconfig.dramblocks = dramblocks;
+    bootconfig.vramblocks = vramblocks;
+
+    return(table);
+  }
+
+
+/* printf ... */
+
+void uprintf(char *formattoken, ...)
+  {
+    va_list ap;
+    char temp[1024];
+
+    temp[0] = '\0';
+
+    va_start(ap, formattoken);
+    vsprintf(temp, formattoken, ap);
+    va_end(ap);
+
+    swi(OS_Write0, IN(R0), temp);
+  }
+
+/* End of bsdbooter.c */
diff --git a/sys/arch/arm32/boot/enteros.S b/sys/arch/arm32/boot/enteros.S
new file mode 100644 (file)
index 0000000..1dfb78a
--- /dev/null
@@ -0,0 +1,65 @@
+/* $NetBSD: enteros.S,v 1.1 1996/01/31 23:18:11 mark Exp $ */
+
+/*
+ * Copyright (c) 1994,1995 Mark Brinicombe.
+ * Copyright (c) 1994 Brini.
+ * All rights reserved.
+ *
+ * This code is derived from software written for Brini by Mark Brinicombe
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided 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 Brini.
+ * 4. The name of the company nor the name of the author may be used to
+ *    endorse or promote products derived from this software without specific
+ *    prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BRINI ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * 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.
+ *
+ * RiscBSD kernel project
+ *
+ * enteros.s
+ *
+ * Created      : 12/09/94
+ * Last updated : 12/09/94
+ *
+ * Based on kate/library/enteros.s
+ *
+ *    $Id: enteros.S,v 1.1.1.1 1996/04/24 11:08:31 deraadt Exp $
+ */
+
+#include "regs.h"
+
+#define OS_EnterOS     0x0016
+
+/*
+ * Enters SVC26 mode
+ */
+
+       .text
+       .global _EnterOS
+_EnterOS:
+       mov     r1, lr
+       swi     OS_EnterOS
+
+       mov     r0, pc
+       mov     pc, r1
+
diff --git a/sys/arch/arm32/boot/exit.S b/sys/arch/arm32/boot/exit.S
new file mode 100644 (file)
index 0000000..e4e72ca
--- /dev/null
@@ -0,0 +1,64 @@
+/* $NetBSD: exit.S,v 1.1 1996/01/31 23:18:14 mark Exp $ */
+
+/*
+ * Copyright (c) 1994,1995 Mark Brinicombe.
+ * Copyright (c) 1994 Brini.
+ * All rights reserved.
+ *
+ * This code is derived from software written for Brini by Mark Brinicombe
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided 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 Brini.
+ * 4. The name of the company nor the name of the author may be used to
+ *    endorse or promote products derived from this software without specific
+ *    prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BRINI ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * 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.
+ *
+ * RiscBSD kernel project
+ *
+ * _exit.s
+ *
+ * Boot loader exit point
+ *
+ * Created      : 12/09/94
+ * Last updated : 12/09/94
+ *
+ * Based on kate/boot/_exit.s
+ *
+ *    $Id: exit.S,v 1.1.1.1 1996/04/24 11:08:32 deraadt Exp $
+ */
+
+#include "regs.h"
+
+#define OS_Exit        0x00000011
+
+       .text
+       .global ___exit
+___exit:
+       mov     r2, r0
+       ldr     r1, [pc, #Lexit_word - . - 8]
+       mov     r0, #0x00000000
+       swi     OS_Exit
+
+Lexit_word:
+       .word   0x58454241
diff --git a/sys/arch/arm32/boot/exitos.S b/sys/arch/arm32/boot/exitos.S
new file mode 100644 (file)
index 0000000..45a5af2
--- /dev/null
@@ -0,0 +1,63 @@
+/* $NetBSD: exitos.S,v 1.1 1996/01/31 23:18:16 mark Exp $ */
+
+/*
+ * Copyright (c) 1994,1995 Mark Brinicombe.
+ * Copyright (c) 1994 Brini.
+ * All rights reserved.
+ *
+ * This code is derived from software written for Brini by Mark Brinicombe
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided 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 Brini.
+ * 4. The name of the company nor the name of the author may be used to
+ *    endorse or promote products derived from this software without specific
+ *    prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BRINI ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * 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.
+ *
+ * RiscBSD kernel project
+ *
+ * exitos.s
+ *
+ *
+ *
+ * Created      : 12/09/94
+ * Last updated : 12/09/94
+ *
+ * Based on kate/library/exitos.s
+ *
+ *    $Id: exitos.S,v 1.1.1.1 1996/04/24 11:08:32 deraadt Exp $
+ *
+ */
+
+#include "regs.h"
+
+/*
+ * Returns from SVC26 mode to USR26 mode
+ */
+
+       .text
+       .global _ExitOS
+_ExitOS:
+       mov     r2, lr
+       bic     r2, r2, #0x00000003
+       movs    pc, r2
diff --git a/sys/arch/arm32/boot/memcpy.S b/sys/arch/arm32/boot/memcpy.S
new file mode 100644 (file)
index 0000000..c1d5845
--- /dev/null
@@ -0,0 +1,113 @@
+/* $NetBSD: memcpy.S,v 1.1 1996/01/31 23:18:17 mark Exp $ */
+
+/*
+ * Copyright (c) 1995 Mark Brinicombe.
+ * Copyright (c) 1995 Brini.
+ * All rights reserved.
+ *
+ * This code is derived from software written for Brini by Mark Brinicombe
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided 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 Brini.
+ * 4. The name of the company nor the name of the author may be used to
+ *    endorse or promote products derived from this software without specific
+ *    prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BRINI ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL BRINI 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.
+ *
+ * RiscBSD kernel project
+ *
+ * memset.S
+ *
+ * optimized memset function
+ *
+ * Created      : 16/05/95
+ * Last updated : 16/05/95
+ *
+ *    $Id: memcpy.S,v 1.1.1.1 1996/04/24 11:08:32 deraadt Exp $
+ */
+
+sp     .req    r13
+lr     .req    r14
+pc     .req    r15
+
+.text
+       .global _bcopy
+       .global _ovbcopy
+
+_bcopy:
+_ovbcopy:
+       teq     r2, #0x00000000
+       moveq   r0, #0x00000000
+       moveq   pc, lr
+       cmp     r0, r1
+       blt     bcopy_back
+
+bcopy_loop:
+       ldrb    r3, [r0], #0x0001
+       strb    r3, [r1], #0x0001
+       subs    r2, r2, #0x00000001
+       bne     bcopy_loop
+
+       mov     pc, r14
+
+bcopy_back:
+       add     r0, r0, r2
+       add     r1, r1, r2
+
+bcopy_bloop:
+       ldrb    r3, [r0, #-0x0001]!
+       strb    r3, [r1, #-0x0001]!
+       subs    r2, r2, #0x00000001
+       bne     bcopy_bloop
+
+       mov     pc, r14
+
+
+       .global _memcpy
+
+_memcpy:
+       teq     r2, #0x00000000
+       moveq   r0, #0x00000000
+       moveq   pc, lr
+       cmp     r1, r0
+       blt     memcpy_back
+
+memcpy_loop:
+       ldrb    r3, [r1], #0x0001
+       strb    r3, [r0], #0x0001
+       subs    r2, r2, #0x00000001
+       bne     memcpy_loop
+
+       mov     pc, r14
+
+memcpy_back:
+       add     r0, r0, r2
+       add     r1, r1, r2
+
+memcpy_bloop:
+       ldrb    r3, [r1, #-0x0001]!
+       strb    r3, [r0, #-0x0001]!
+       subs    r2, r2, #0x00000001
+       bne     memcpy_bloop
+
+       mov     pc, r14
diff --git a/sys/arch/arm32/boot/memset.S b/sys/arch/arm32/boot/memset.S
new file mode 100644 (file)
index 0000000..0a606ac
--- /dev/null
@@ -0,0 +1,136 @@
+/* $NetBSD: memset.S,v 1.1 1996/01/31 23:18:19 mark Exp $ */
+
+/*
+ * Copyright (c) 1995 Mark Brinicombe.
+ * Copyright (c) 1995 Brini.
+ * 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 Mark Brinicombe.
+ * 4. The name of the company nor the name of the author may 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 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.
+ *
+ * RiscBSD kernel project
+ *
+ * memset.S
+ *
+ * optimized memset function
+ *
+ * Created      : 16/05/95
+ * Last updated : 16/05/95
+ *
+ *    $Id: memset.S,v 1.1.1.1 1996/04/24 11:08:32 deraadt Exp $
+ */
+
+sp     .req    r13
+lr     .req    r14
+pc     .req    r15
+
+.text
+
+        .global _memset
+
+/* Sets a block of memory to the specified value
+ *
+ *  r0 - address
+ *  r1 - byte to write
+ *  r2 - number of bytes to write
+ */
+
+_memset:
+       and     r1, r1, #0x000000ff     /* We write bytes */
+
+       cmp     r2, #0x00000004         /* Do we have less than 4 bytes */
+       blt     memset_lessthanfour
+
+/* Ok first we will word align the address */
+
+       ands    r3, r0, #0x00000003     /* Get the bottom two bits */
+       beq     memset_addraligned      /* The address is word aligned */
+
+       rsb     r3, r3, #0x00000004
+       sub     r2, r2, r3
+       cmp     r3, #0x00000002
+       strb    r1, [r0], #0x0001       /* Set 1 byte */
+       strgeb  r1, [r0], #0x0001       /* Set another byte */
+       strgtb  r1, [r0], #0x0001       /* and a third */
+
+       cmp     r2, #0x00000004
+       blt     memset_lessthanfour
+
+/* Now we must be word aligned */
+
+memset_addraligned:
+
+       orr     r3, r1, r1, lsl #8      /* Repeat the byte into a word */
+       orr     r3, r3, r3, lsl #16
+
+/* We know we have at least 4 bytes ... */
+
+       cmp     r2, #0x00000020         /* If less than 32 then use words */
+       blt     memset_lessthan32
+
+/* We have at least 32 so lets use quad words */
+
+       stmfd   sp!, {r4-r6}            /* Store registers */
+       mov     r4, r3                  /* Duplicate data */
+       mov     r5, r3
+       mov     r6, r3
+
+memset_loop16:
+       stmia   r0!, {r3-r6}            /* Store 16 bytes */
+       sub     r2, r2, #0x00000010     /* Adjust count */
+       cmp     r2, #0x00000010         /* Still got at least 16 bytes ? */
+       bgt     memset_loop16
+
+       ldmfd   sp!, {r4-r6}            /* Restore registers */
+
+/* Do we need to set some words as well ? */
+
+       cmp     r2, #0x00000004
+       blt     memset_lessthanfour
+
+/* Have either less than 16 or less than 32 depending on route taken */
+
+memset_lessthan32:
+
+/* We have at least 4 bytes so copy as words */
+
+memset_loop4:
+       str     r3, [r0], #0x0004
+       sub     r2, r2, #0x0004
+       cmp     r2, #0x00000004
+       bge     memset_loop4
+
+memset_lessthanfour:
+       cmp     r2, #0x00000000
+       moveq   pc, lr                  /* Zero length so exit */
+
+       cmp     r2, #0x00000002
+       strb    r1, [r0], #0x0001       /* Set 1 byte */
+       strgeb  r1, [r0], #0x0001       /* Set another byte */
+       strgtb  r1, [r0], #0x0001       /* and a third */
+
+       mov     pc, lr                  /* Exit */
diff --git a/sys/arch/arm32/boot/regs.h b/sys/arch/arm32/boot/regs.h
new file mode 100644 (file)
index 0000000..c98be1d
--- /dev/null
@@ -0,0 +1,52 @@
+/* $NetBSD: regs.h,v 1.1 1996/01/31 23:18:21 mark Exp $ */
+
+/* Copyright (c) 1994,1995 Mark Brinicombe.
+ * Copyright (c) 1994 Brini.
+ * All rights reserved.
+ *
+ * This code is derived from software written for Brini by Mark Brinicombe
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided 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 Brini.
+ * 4. The name of the company nor the name of the author may be used to
+ *    endorse or promote products derived from this software without specific
+ *    prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BRINI ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * 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.
+ *
+ * RiscBSD kernel project
+ *
+ * regs.h
+ *
+ * Assembly register definitions
+ *
+ * Created      : 14/01/96
+ * Last updated : 14/01/96
+ *
+ *     $Id: regs.h,v 1.1.1.1 1996/04/24 11:08:32 deraadt Exp $
+ */
+
+fp     .req    r11
+sl     .req    r12
+sp     .req    r13
+lr     .req    r14
+pc     .req    r15
diff --git a/sys/arch/arm32/boot/rmaouthdr b/sys/arch/arm32/boot/rmaouthdr
new file mode 100644 (file)
index 0000000..39e0984
--- /dev/null
@@ -0,0 +1,4 @@
+#!/bin/sh
+#      $NetBSD: rmaouthdr,v 1.1 1996/01/31 23:18:23 mark Exp $
+
+dd if=$1 of=$2 ibs=32 skip=1 obs=1024b
diff --git a/sys/arch/arm32/boot/setcpsr.S b/sys/arch/arm32/boot/setcpsr.S
new file mode 100644 (file)
index 0000000..3a9be1c
--- /dev/null
@@ -0,0 +1,95 @@
+/* $NetBSD: setcpsr.S,v 1.1 1996/01/31 23:18:27 mark Exp $ */
+
+/*
+ * Copyright (c) 1994 Mark Brinicombe.
+ * Copyright (c) 1994 Brini.
+ * All rights reserved.
+ *
+ * This code is derived from software written for Brini by Mark Brinicombe
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided 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 Brini.
+ * 4. The name of the company nor the name of the author may be used to
+ *    endorse or promote products derived from this software without specific
+ *    prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BRINI ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL BRINI 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.
+ *
+ * RiscBSD kernel project
+ *
+ * setcpsr.S
+ *
+ * Miscellaneous routines to play with the CPSR register
+ *
+ * Eventually this routine can be inline assembly.
+ *
+ * Created      : 12/09/94
+ * Last updated : 28/05/95
+ *
+ * Based of kate/display/setcpsr.s
+ *
+ *    $Id: setcpsr.S,v 1.1.1.1 1996/04/24 11:08:32 deraadt Exp $
+ */
+
+fp      .req    r11
+ip      .req    r12
+sp      .req    r13
+lr     .req    r14
+pc     .req    r15
+
+.text
+
+        .global _SetCPSR
+
+/* Sets and clears bits in the CPSR register
+ *
+ *  r0 - bic mask
+ *  r1 - eor mask
+ */
+
+_SetCPSR:
+/*     mov     ip, sp
+       stmfd   sp!, {fp, ip, lr, pc}
+       sub     fp, ip, #4*/
+
+        mrs     r3, cpsr_all           /* Set the CPSR */
+       bic     r2, r3, r0
+        eor     r2, r2, r1
+        msr     cpsr_all, r2
+
+        mov    r0, r3                  /* Return the old CPSR */
+
+/*     ldmea   fp, {fp, sp, pc}*/
+       mov     pc, lr
+
+        .global _GetCPSR
+
+/* Gets the CPSR register
+ *
+ * Returns the CPSR in r0
+ */
+
+_GetCPSR:
+        mrs     r0, cpsr_all           /* Get the CPSR */
+
+       mov     pc, lr
+
diff --git a/sys/arch/arm32/boot/start.S b/sys/arch/arm32/boot/start.S
new file mode 100644 (file)
index 0000000..6c6b1f8
--- /dev/null
@@ -0,0 +1,54 @@
+/* $NetBSD: start.S,v 1.1 1996/01/31 23:18:30 mark Exp $ */
+
+/* Copyright (c) 1994 Mark Brinicombe.
+ * Copyright (c) 1994 Brini.
+ * All rights reserved.
+ *
+ * This code is derived from software written for Brini by Mark Brinicombe
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided 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 Brini.
+ * 4. The name of the company nor the name of the author may be used to
+ *    endorse or promote products derived from this software without specific
+ *    prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BRINI ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * 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.
+ *
+ * RiscBSD kernel project
+ *
+ * _main.s
+ *
+ * Kernel entry/exit code
+ *
+ * Created      : 12/09/94
+ * Last updated : 12/09/94
+ *
+ * Based on kate/boot/_main.s
+ *
+ *     $Id: start.S,v 1.1.1.1 1996/04/24 11:08:32 deraadt Exp $
+ */
+
+#include "regs.h"
+
+       .global start
+start:
+       b ___main
diff --git a/sys/arch/arm32/boot/strstr.c b/sys/arch/arm32/boot/strstr.c
new file mode 100644 (file)
index 0000000..0efc0ff
--- /dev/null
@@ -0,0 +1,70 @@
+/* $NetBSD: strstr.c,v 1.1 1996/01/31 23:18:34 mark Exp $ */
+
+/*
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     from: strstr.c,v 1.4 1995/06/15 00:08:43 jtc Exp 
+ *
+ *     $Id: strstr.c,v 1.1.1.1 1996/04/24 11:08:32 deraadt Exp $
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+
+/*
+ * Find the first occurrence of find in s.
+ */
+
+char *
+strstr(s, find)
+       register const char *s, *find;
+{
+       register char c, sc;
+       register size_t len;
+
+       if ((c = *find++) != 0) {
+               len = strlen(find);
+               do {
+                       do {
+                               if ((sc = *s++) == 0)
+                                       return (NULL);
+                       } while (sc != c);
+               } while (strncmp(s, find, len) != 0);
+               s--;
+       }
+       return ((char *)s);
+}
+
+/* End of strstr.c */
diff --git a/sys/arch/arm32/boot/svc32.S b/sys/arch/arm32/boot/svc32.S
new file mode 100644 (file)
index 0000000..0274c10
--- /dev/null
@@ -0,0 +1,66 @@
+/* $NetBSD: svc32.S,v 1.1 1996/01/31 23:18:38 mark Exp $ */
+
+/*
+ * Copyright (c) 1994,1955 Mark Brinicombe.
+ * Copyright (c) 1994 Brini.
+ * All rights reserved.
+ *
+ * This code is derived from software written for Brini by Mark Brinicombe
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided 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 Brini.
+ * 4. The name of the company nor the name of the author may be used to
+ *    endorse or promote products derived from this software without specific
+ *    prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BRINI ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * 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.
+ *
+ * RiscBSD kernel project
+ *
+ * svc32.s
+ *
+ * Created      : 12/09/94
+ * Last updated : 12/09/94
+ *
+ * Based on kate/library/svc32.s
+ *
+ *    $Id: svc32.S,v 1.1.1.1 1996/04/24 11:08:32 deraadt Exp $
+ */
+
+#include "regs.h"
+#include <machine/cpu.h>
+
+/*
+ * Switches from SVC26 mode to SVC32 mode
+ */
+
+       .text
+       .global _SVC32
+_SVC32:
+       mrs     r1, cpsr_all
+       bic     r1, r1, #(PSR_MODE)
+       orr     r1, r1, #(PSR_SVC32_MODE)
+       msr     cpsr_all, r1
+
+       bic     lr, lr, #0xfc000000
+
+       mov     pc, lr
diff --git a/sys/arch/arm32/boot/swis.h b/sys/arch/arm32/boot/swis.h
new file mode 100644 (file)
index 0000000..e1282b1
--- /dev/null
@@ -0,0 +1,596 @@
+/*
+  Title:      Swi numbers for RiscOs
+  Copyright (C) 1989, Acorn Computers Ltd., Cambridge, England
+  $Revision: 1.1.1.1 $ SWI_LIST 1.00 02-May-89 (Program generated)
+*/
+
+#ifndef __swis_h
+#define __swis_h
+
+#define XOS_Bit                        0x020000
+
+#define OS_WriteI                      0x000100
+
+#define OS_WriteC                      0x000000
+#define OS_WriteS                      0x000001
+#define OS_Write0                      0x000002
+#define OS_NewLine                     0x000003
+#define OS_ReadC                       0x000004
+#define OS_CLI                         0x000005
+#define OS_Byte                        0x000006
+#define OS_Word                        0x000007
+#define OS_File                        0x000008
+#define OS_Args                        0x000009
+#define OS_BGet                        0x00000a
+#define OS_BPut                        0x00000b
+#define OS_GBPB                        0x00000c
+#define OS_Find                        0x00000d
+#define OS_ReadLine                    0x00000e
+#define OS_Control                     0x00000f
+#define OS_GetEnv                      0x000010
+#define OS_Exit                        0x000011
+#define OS_SetEnv                      0x000012
+#define OS_IntOn                       0x000013
+#define OS_IntOff                      0x000014
+#define OS_CallBack                    0x000015
+#define OS_EnterOS                     0x000016
+#define OS_BreakPt                     0x000017
+#define OS_BreakCtrl                   0x000018
+#define OS_UnusedSWI                   0x000019
+#define OS_UpdateMEMC                  0x00001a
+#define OS_SetCallBack                 0x00001b
+#define OS_Mouse                       0x00001c
+#define OS_Heap                        0x00001d
+#define OS_Module                      0x00001e
+#define OS_Claim                       0x00001f
+#define OS_Release                     0x000020
+#define OS_ReadUnsigned                0x000021
+#define OS_GenerateEvent               0x000022
+#define OS_ReadVarVal                  0x000023
+#define OS_SetVarVal                   0x000024
+#define OS_GSInit                      0x000025
+#define OS_GSRead                      0x000026
+#define OS_GSTrans                     0x000027
+#define OS_BinaryToDecimal             0x000028
+#define OS_FSControl                   0x000029
+#define OS_ChangeDynamicArea           0x00002a
+#define OS_GenerateError               0x00002b
+#define OS_ReadEscapeState             0x00002c
+#define OS_EvaluateExpression          0x00002d
+#define OS_SpriteOp                    0x00002e
+#define OS_ReadPalette                 0x00002f
+#define OS_ServiceCall                 0x000030
+#define OS_ReadVduVariables            0x000031
+#define OS_ReadPoint                   0x000032
+#define OS_UpCall                      0x000033
+#define OS_CallAVector                 0x000034
+#define OS_ReadModeVariable            0x000035
+#define OS_RemoveCursors               0x000036
+#define OS_RestoreCursors              0x000037
+#define OS_SWINumberToString           0x000038
+#define OS_SWINumberFromString         0x000039
+#define OS_ValidateAddress             0x00003a
+#define OS_CallAfter                   0x00003b
+#define OS_CallEvery                   0x00003c
+#define OS_RemoveTickerEvent           0x00003d
+#define OS_InstallKeyHandler           0x00003e
+#define OS_CheckModeValid              0x00003f
+#define OS_ChangeEnvironment           0x000040
+#define OS_ClaimScreenMemory           0x000041
+#define OS_ReadMonotonicTime           0x000042
+#define OS_SubstituteArgs              0x000043
+#define OS_PrettyPrint                 0x000044
+#define OS_Plot                        0x000045
+#define OS_WriteN                      0x000046
+#define OS_AddToVector                 0x000047
+#define OS_WriteEnv                    0x000048
+#define OS_ReadArgs                    0x000049
+#define OS_ReadRAMFsLimits             0x00004a
+#define OS_ClaimDeviceVector           0x00004b
+#define OS_ReleaseDeviceVector         0x00004c
+#define OS_DelinkApplication           0x00004d
+#define OS_RelinkApplication           0x00004e
+#define OS_HeapSort                    0x00004f
+#define OS_ExitAndDie                  0x000050
+#define OS_ReadMemMapInfo              0x000051
+#define OS_ReadMemMapEntries           0x000052
+#define OS_SetMemMapEntries            0x000053
+#define OS_AddCallBack                 0x000054
+#define OS_ReadDefaultHandler          0x000055
+#define OS_SetECFOrigin                0x000056
+#define OS_SerialOp                    0x000057
+#define OS_ReadSysInfo                 0x000058
+#define OS_Confirm                     0x000059
+#define OS_ChangedBox                  0x00005a
+#define OS_CRC                         0x00005b
+#define OS_ReadDynamicArea             0x00005c
+#define OS_PrintChar                   0x00005d
+#define OS_ChangeRedirection           0x00005e
+#define OS_RemoveCallBack              0x00005f
+#define OS_FindMemMapEntries           0x000060
+#define OS_SetColour                   0x000061
+#define OS_ConvertStandardDateAndTime  0x0000c0
+#define OS_ConvertDateAndTime          0x0000c1
+#define OS_ConvertHex1                 0x0000d0
+#define OS_ConvertHex2                 0x0000d1
+#define OS_ConvertHex4                 0x0000d2
+#define OS_ConvertHex6                 0x0000d3
+#define OS_ConvertHex8                 0x0000d4
+#define OS_ConvertCardinal1            0x0000d5
+#define OS_ConvertCardinal2            0x0000d6
+#define OS_ConvertCardinal3            0x0000d7
+#define OS_ConvertCardinal4            0x0000d8
+#define OS_ConvertInteger1             0x0000d9
+#define OS_ConvertInteger2             0x0000da
+#define OS_ConvertInteger3             0x0000db
+#define OS_ConvertInteger4             0x0000dc
+#define OS_ConvertBinary1              0x0000dd
+#define OS_ConvertBinary2              0x0000de
+#define OS_ConvertBinary3              0x0000df
+#define OS_ConvertBinary4              0x0000e0
+#define OS_ConvertSpacedCardinal1      0x0000e1
+#define OS_ConvertSpacedCardinal2      0x0000e2
+#define OS_ConvertSpacedCardinal3      0x0000e3
+#define OS_ConvertSpacedCardinal4      0x0000e4
+#define OS_ConvertSpacedInteger1       0x0000e5
+#define OS_ConvertSpacedInteger2       0x0000e6
+#define OS_ConvertSpacedInteger3       0x0000e7
+#define OS_ConvertSpacedInteger4       0x0000e8
+#define OS_ConvertFixedNetStation      0x0000e9
+#define OS_ConvertNetStation           0x0000ea
+#define OS_ConvertFixedFileSize        0x0000eb
+#define OS_ConvertFileSize             0x0000ec
+#define IIC_Control                    0x000240
+#define Cache_Control                  0x000280
+#define Cache_Cacheable                0x000281
+#define Cache_Updateable               0x000282
+#define Cache_Disruptive               0x000283
+#define Cache_Flush                    0x000284
+#define Trace_R0                       0x00bf00
+#define Trace_R1                       0x00bf01
+#define Trace_R2                       0x00bf02
+#define Trace_R3                       0x00bf03
+#define Trace_R4                       0x00bf04
+#define Trace_R5                       0x00bf05
+#define Trace_R6                       0x00bf06
+#define Trace_R7                       0x00bf07
+#define Trace_R8                       0x00bf08
+#define Trace_R9                       0x00bf09
+#define Trace_R10                      0x00bf0a
+#define Trace_R11                      0x00bf0b
+#define Trace_R12                      0x00bf0c
+#define Trace_R13                      0x00bf0d
+#define Trace_R14                      0x00bf0e
+#define Trace_R15                      0x00bf0f
+#define Trace_Regs                     0x00bf10
+#define Trace_WriteC                   0x00bf11
+#define Trace_NewLine                  0x00bf12
+#define Trace_WriteS                   0x00bf13
+#define Trace_Write0                   0x00bf14
+#define Font_CacheAddr                 0x040080
+#define Font_FindFont                  0x040081
+#define Font_LoseFont                  0x040082
+#define Font_ReadDefn                  0x040083
+#define Font_ReadInfo                  0x040084
+#define Font_StringWidth               0x040085
+#define Font_Paint                     0x040086
+#define Font_Caret                     0x040087
+#define Font_ConverttoOS               0x040088
+#define Font_Converttopoints           0x040089
+#define Font_SetFont                   0x04008a
+#define Font_CurrentFont               0x04008b
+#define Font_FutureFont                0x04008c
+#define Font_FindCaret                 0x04008d
+#define Font_CharBBox                  0x04008e
+#define Font_ReadScaleFactor           0x04008f
+#define Font_SetScaleFactor            0x040090
+#define Font_ListFonts                 0x040091
+#define Font_SetFontColours            0x040092
+#define Font_SetPalette                0x040093
+#define Font_ReadThresholds            0x040094
+#define Font_SetThresholds             0x040095
+#define Font_FindCaretJ                0x040096
+#define Font_StringBBox                0x040097
+#define Font_ReadColourTable           0x040098
+#define Font_MakeBitmap                0x040099
+#define Font_UnCacheFile               0x04009a
+#define Font_SetFontMax                0x04009b
+#define Font_ReadFontMax               0x04009c
+#define Font_ReadFontPrefix            0x04009d
+#define Font_SwitchOutputToBuffer      0x04009e
+#define Font_ReadFontMetrics           0x04009f
+#define Font_DecodeMenu                0x0400a0
+#define Font_ScanString                0x0400a1
+#define Font_SetColourTable            0x0400a2
+#define Font_CurrentRGB                0x0400a3
+#define Font_FutureRGB                 0x0400a4
+#define Font_ReadEncodingFilename      0x0400a5
+#define Font_FindField                 0x0400a6
+#define Font_ApplyFields               0x0400a7
+#define Font_LookupFont                0x0400a8
+#define Wimp_Initialise                0x0400c0
+#define Wimp_CreateWindow              0x0400c1
+#define Wimp_CreateIcon                0x0400c2
+#define Wimp_DeleteWindow              0x0400c3
+#define Wimp_DeleteIcon                0x0400c4
+#define Wimp_OpenWindow                0x0400c5
+#define Wimp_CloseWindow               0x0400c6
+#define Wimp_Poll                      0x0400c7
+#define Wimp_RedrawWindow              0x0400c8
+#define Wimp_UpdateWindow              0x0400c9
+#define Wimp_GetRectangle              0x0400ca
+#define Wimp_GetWindowState            0x0400cb
+#define Wimp_GetWindowInfo             0x0400cc
+#define Wimp_SetIconState              0x0400cd
+#define Wimp_GetIconState              0x0400ce
+#define Wimp_GetPointerInfo            0x0400cf
+#define Wimp_DragBox                   0x0400d0
+#define Wimp_ForceRedraw               0x0400d1
+#define Wimp_SetCaretPosition          0x0400d2
+#define Wimp_GetCaretPosition          0x0400d3
+#define Wimp_CreateMenu                0x0400d4
+#define Wimp_DecodeMenu                0x0400d5
+#define Wimp_WhichIcon                 0x0400d6
+#define Wimp_SetExtent                 0x0400d7
+#define Wimp_SetPointerShape           0x0400d8
+#define Wimp_OpenTemplate              0x0400d9
+#define Wimp_CloseTemplate             0x0400da
+#define Wimp_LoadTemplate              0x0400db
+#define Wimp_ProcessKey                0x0400dc
+#define Wimp_CloseDown                 0x0400dd
+#define Wimp_StartTask                 0x0400de
+#define Wimp_ReportError               0x0400df
+#define Wimp_GetWindowOutline          0x0400e0
+#define Wimp_PollIdle                  0x0400e1
+#define Wimp_PlotIcon                  0x0400e2
+#define Wimp_SetMode                   0x0400e3
+#define Wimp_SetPalette                0x0400e4
+#define Wimp_ReadPalette               0x0400e5
+#define Wimp_SetColour                 0x0400e6
+#define Wimp_SendMessage               0x0400e7
+#define Wimp_CreateSubMenu             0x0400e8
+#define Wimp_SpriteOp                  0x0400e9
+#define Wimp_BaseOfSprites             0x0400ea
+#define Wimp_BlockCopy                 0x0400eb
+#define Wimp_SlotSize                  0x0400ec
+#define Wimp_ReadPixTrans              0x0400ed
+#define Wimp_ClaimFreeMemory           0x0400ee
+#define Wimp_CommandWindow             0x0400ef
+#define Wimp_TextColour                0x0400f0
+#define Wimp_TransferBlock             0x0400f1
+#define Wimp_ReadSysInfo               0x0400f2
+#define Wimp_SetFontColours            0x0400f3
+#define Wimp_GetMenuState              0x0400f4
+#define Wimp_RegisterFilter            0x0400f5
+#define Wimp_AddMessages               0x0400f6
+#define Wimp_RemoveMessages            0x0400f7
+#define Wimp_SetColourMapping          0x0400f8
+#define Sound_Configure                0x040140
+#define Sound_Enable                   0x040141
+#define Sound_Stereo                   0x040142
+#define Sound_Speaker                  0x040143
+#define Sound_Volume                   0x040180
+#define Sound_SoundLog                 0x040181
+#define Sound_LogScale                 0x040182
+#define Sound_InstallVoice             0x040183
+#define Sound_RemoveVoice              0x040184
+#define Sound_AttachVoice              0x040185
+#define Sound_ControlPacked            0x040186
+#define Sound_Tuning                   0x040187
+#define Sound_Pitch                    0x040188
+#define Sound_Control                  0x040189
+#define Sound_AttachNamedVoice         0x04018a
+#define Sound_ReadControlBlock         0x04018b
+#define Sound_WriteControlBlock        0x04018c
+#define Sound_QInit                    0x0401c0
+#define Sound_QSchedule                0x0401c1
+#define Sound_QRemove                  0x0401c2
+#define Sound_QFree                    0x0401c3
+#define Sound_QSDispatch               0x0401c4
+#define Sound_QTempo                   0x0401c5
+#define Sound_QBeat                    0x0401c6
+#define Sound_QInterface               0x0401c7
+#define ADFS_DiscOp                    0x040240
+#define ADFS_HDC                       0x040241
+#define ADFS_Drives                    0x040242
+#define ADFS_FreeSpace                 0x040243
+#define ADFS_Retries                   0x040244
+#define ADFS_DescribeDisc              0x040245
+#define ADFS_VetFormat                 0x040246
+#define ADFS_FlpProcessDCB             0x040247
+#define ADFS_ControllerType            0x040248
+#define ADFS_PowerControl              0x040249
+#define ADFS_SetIDEController          0x04024a
+#define ADFS_IDEUserOp                 0x04024b
+#define ADFS_MiscOp                    0x04024c
+#define ADFS_ECCSAndRetries            0x040250
+#define Podule_ReadID                  0x040280
+#define Podule_ReadHeader              0x040281
+#define Podule_EnumerateChunks         0x040282
+#define Podule_ReadChunk               0x040283
+#define Podule_ReadBytes               0x040284
+#define Podule_WriteBytes              0x040285
+#define Podule_CallLoader              0x040286
+#define Podule_RawRead                 0x040287
+#define Podule_RawWrite                0x040288
+#define Podule_HardwareAddress         0x040289
+#define Podule_EnumerateChunksWithInfo 0x04028a
+#define Podule_HardwareAddresses       0x04028b
+#define Podule_ReturnNumber            0x04028c
+#define PCEmMod_KeyEvent_Init          0x0402c0
+#define PCEmMod_KeyEvent_Info          0x0402c1
+#define PCEmMod_KeyEvent_Accept        0x0402c2
+#define PCEmMod_KeyEvent_Ignore        0x0402c3
+#define PCEmMod_KeyEvent_Check         0x0402c4
+#define PCEmMod_KeyEvent_Get           0x0402c5
+#define PCEmMod_KeyEvent_Put           0x0402c6
+#define PCEmMod_MicroTimer_Get         0x0402c7
+#define PCEmMod_PCEvent_Init           0x0402c8
+#define PCEmMod_PCEvent_Accept         0x0402c9
+#define PCEmMod_PCEvent_Ignore         0x0402ca
+#define PCEmMod_PCEvent_Check          0x0402cb
+#define PCEmMod_PCEvent_Get            0x0402cc
+#define PCEmMod_DelayFor               0x0402cd
+#define PCEmMod_CodeBase               0x0402ce
+#define PCEmMod_Profile_Init           0x0402cf
+#define PCEmMod_Profile_On             0x0402d0
+#define PCEmMod_Profile_Off            0x0402d1
+#define PCEmMod_Profile_Write          0x0402d2
+#define PCEmMod_InterceptMouse         0x0402d3
+#define PCEmMod_RestoreMouse           0x0402d4
+#define PCEmMod_ReadMouse              0x0402d5
+#define Debugger_Disassemble           0x040380
+#define SCSI_Version                   0x0403c0
+#define SCSI_Initialise                0x0403c1
+#define SCSI_Control                   0x0403c2
+#define SCSI_Op                        0x0403c3
+#define SCSI_Status                    0x0403c4
+#define SCSI_Reserve                   0x0403c7
+#define SCSI_List                      0x0403c8
+#define FPEmulator_Version             0x040480
+#define FileCore_DiscOp                0x040540
+#define FileCore_Create                0x040541
+#define FileCore_Drives                0x040542
+#define FileCore_FreeSpace             0x040543
+#define FileCore_FloppyStructure       0x040544
+#define FileCore_DescribeDisc          0x040545
+#define FileCore_DiscardReadSectorsCache 0x040546
+#define FileCore_DiscFormat            0x040547
+#define FileCore_LayoutStructure       0x040548
+#define FileCore_MiscOp                0x040549
+#define Shell_Create                   0x0405c0
+#define Shell_Destroy                  0x0405c1
+#define Hourglass_On                   0x0406c0
+#define Hourglass_Off                  0x0406c1
+#define Hourglass_Smash                0x0406c2
+#define Hourglass_Start                0x0406c3
+#define Hourglass_Percentage           0x0406c4
+#define Hourglass_LEDs                 0x0406c5
+#define Hourglass_Colours              0x0406c6
+#define Draw_ProcessPath               0x040700
+#define Draw_ProcessPathFP             0x040701
+#define Draw_Fill                      0x040702
+#define Draw_FillFP                    0x040703
+#define Draw_Stroke                    0x040704
+#define Draw_StrokeFP                  0x040705
+#define Draw_StrokePath                0x040706
+#define Draw_StrokePathFP              0x040707
+#define Draw_FlattenPath               0x040708
+#define Draw_FlattenPathFP             0x040709
+#define Draw_TransformPath             0x04070a
+#define Draw_TransformPathFP           0x04070b
+#define ColourTrans_SelectTable        0x040740
+#define ColourTrans_SelectGCOLTable    0x040741
+#define ColourTrans_ReturnGCOL         0x040742
+#define ColourTrans_SetGCOL            0x040743
+#define ColourTrans_ReturnColourNumber 0x040744
+#define ColourTrans_ReturnGCOLForMode  0x040745
+#define ColourTrans_ReturnColourNumberForMode 0x040746
+#define ColourTrans_ReturnOppGCOL      0x040747
+#define ColourTrans_SetOppGCOL         0x040748
+#define ColourTrans_ReturnOppColourNumber 0x040749
+#define ColourTrans_ReturnOppGCOLForMode 0x04074a
+#define ColourTrans_ReturnOppColourNumberForMode 0x04074b
+#define ColourTrans_GCOLToColourNumber 0x04074c
+#define ColourTrans_ColourNumberToGCOL 0x04074d
+#define ColourTrans_ReturnFontColours  0x04074e
+#define ColourTrans_SetFontColours     0x04074f
+#define ColourTrans_InvalidateCache    0x040750
+#define ColourTrans_SetCalibration     0x040751
+#define ColourTrans_ReadCalibration    0x040752
+#define ColourTrans_ConvertDeviceColour 0x040753
+#define ColourTrans_ConvertDevicePalette 0x040754
+#define ColourTrans_ConvertRGBToCIE    0x040755
+#define ColourTrans_ConvertCIEToRGB    0x040756
+#define ColourTrans_WriteCalibrationToFile 0x040757
+#define ColourTrans_ConvertRGBToHSV    0x040758
+#define ColourTrans_ConvertHSVToRGB    0x040759
+#define ColourTrans_ConvertRGBToCMYK   0x04075a
+#define ColourTrans_ConvertCMYKToRGB   0x04075b
+#define ColourTrans_ReadPalette        0x04075c
+#define ColourTrans_WritePalette       0x04075d
+#define ColourTrans_SetColour          0x04075e
+#define ColourTrans_MiscOp             0x04075f
+#define ColourTrans_WriteLoadingsToFile 0x040760
+#define ColourTrans_SetTextColour      0x040761
+#define ColourTrans_SetOppTextColour   0x040762
+#define ColourTrans_GenerateTable      0x040763
+#define SCSIFS_DiscOp                  0x040980
+#define SCSIFS_Drives                  0x040982
+#define SCSIFS_FreeSpace               0x040983
+#define SCSIFS_DescribeDisc            0x040985
+#define SCSIFS_TestReady               0x040986
+#define Super_Sample90                 0x040d80
+#define Super_Sample45                 0x040d81
+#define FilerAction_SendSelectedDirectory 0x040f80
+#define FilerAction_SendSelectedFile   0x040f81
+#define FilerAction_SendStartOperation 0x040f82
+#define SCSI_LogVersion                0x041080
+#define SCSI_LogList                   0x041081
+#define MessageTrans_FileInfo          0x041500
+#define MessageTrans_OpenFile          0x041501
+#define MessageTrans_Lookup            0x041502
+#define MessageTrans_MakeMenus         0x041503
+#define MessageTrans_CloseFile         0x041504
+#define MessageTrans_EnumerateTokens   0x041505
+#define MessageTrans_ErrorLookup       0x041506
+#define MessageTrans_GSLookup          0x041507
+#define MessageTrans_CopyError         0x041508
+#define PDumper_Info                   0x041b00
+#define PDumper_Claim                  0x041b01
+#define PDumper_Free                   0x041b02
+#define PDumper_Find                   0x041b03
+#define PDumper_StartJob               0x041b04
+#define PDumper_TidyJob                0x041b05
+#define PDumper_SetColour              0x041b06
+#define PDumper_PrepareStrip           0x041b07
+#define PDumper_LookupError            0x041b08
+#define PDumper_CopyFilename           0x041b09
+#define ResourceFS_RegisterFiles       0x041b40
+#define ResourceFS_DeregisterFiles     0x041b41
+#define DragASprite_Start              0x042400
+#define DragASprite_Stop               0x042401
+#define DDEUtils_Prefix                0x042580
+#define DDEUtils_SetCLSize             0x042581
+#define DDEUtils_SetCL                 0x042582
+#define DDEUtils_GetCLSize             0x042583
+#define DDEUtils_GetCl                 0x042584
+#define DDEUtils_ThrowbackRegister     0x042585
+#define DDEUtils_ThrowbackUnRegister   0x042586
+#define DDEUtils_ThrowbackStart        0x042587
+#define DDEUtils_ThrowbackSend         0x042588
+#define DDEUtils_ThrowbackEnd          0x042589
+#define Filter_RegisterPreFilter       0x042640
+#define Filter_RegisterPostFilter      0x042641
+#define Filter_DeRegisterPreFilter     0x042642
+#define Filter_DeRegisterPostFilter    0x042643
+#define TaskManager_TaskNameFromHandle 0x042680
+#define TaskManager_EnumerateTasks     0x042681
+#define TaskManager_Shutdown           0x042682
+#define Squash_Compress                0x042700
+#define Squash_Decompress              0x042701
+#define DeviceFS_Register              0x042740
+#define DeviceFS_Deregister            0x042741
+#define DeviceFS_RegisterObjects       0x042742
+#define DeviceFS_DeregisterObjects     0x042743
+#define DeviceFS_CallDevice            0x042744
+#define DeviceFS_Threshold             0x042745
+#define DeviceFS_ReceivedCharacter     0x042746
+#define DeviceFS_TransmitCharacter     0x042747
+#define Impulse_Initialise             0x0428c0
+#define Impulse_Decode                 0x0428c1
+#define Impulse_SendMessage            0x0428c2
+#define Impulse_TransmitData           0x0428c3
+#define Impulse_FetchData              0x0428c4
+#define Impulse_CloseDown              0x0428c5
+#define Impulse_DeferReply             0x0428c6
+#define Buffer_Create                  0x042940
+#define Buffer_Remove                  0x042941
+#define Buffer_Register                0x042942
+#define Buffer_Deregister              0x042943
+#define Buffer_ModifyFlags             0x042944
+#define Buffer_LinkDevice              0x042945
+#define Buffer_UnlinkDevice            0x042946
+#define Buffer_GetInfo                 0x042947
+#define Buffer_Threshold               0x042948
+#define BASICTrans_HELP                0x042c80
+#define BASICTrans_Error               0x042c81
+#define BASICTrans_Message             0x042c82
+#define Parallel_HardwareAddress       0x042ec0
+#define Parallel_Op                    0x042ec1
+#define Territory_Number               0x043040
+#define Territory_Register             0x043041
+#define Territory_Deregister           0x043042
+#define Territory_NumberToName         0x043043
+#define Territory_Exists               0x043044
+#define Territory_AlphabetNumberToName 0x043045
+#define Territory_SelectAlphabet       0x043046
+#define Territory_SetTime              0x043047
+#define Territory_ReadCurrentTimeZone  0x043048
+#define Territory_ConvertTimeToUTCOrdinals 0x043049
+#define Territory_ReadTimeZones        0x04304a
+#define Territory_ConvertDateAndTime   0x04304b
+#define Territory_ConvertStandardDateAndTime 0x04304c
+#define Territory_ConvertStandardDate  0x04304d
+#define Territory_ConvertStandardTime  0x04304e
+#define Territory_ConvertTimeToOrdinals 0x04304f
+#define Territory_ConvertTimeStringToOrdinals 0x043050
+#define Territory_ConvertOrdinalsToTime 0x043051
+#define Territory_Alphabet             0x043052
+#define Territory_AlphabetIdentifier   0x043053
+#define Territory_SelectKeyboardHandler 0x043054
+#define Territory_WriteDirection       0x043055
+#define Territory_CharacterPropertyTable 0x043056
+#define Territory_LowerCaseTable       0x043057
+#define Territory_UpperCaseTable       0x043058
+#define Territory_ControlTable         0x043059
+#define Territory_PlainTable           0x04305a
+#define Territory_ValueTable           0x04305b
+#define Territory_RepresentationTable  0x04305c
+#define Territory_Collate              0x04305d
+#define Territory_ReadSymbols          0x04305e
+#define Territory_ReadCalendarInformation 0x04305f
+#define Territory_NameToNumber         0x043060
+#define Territory_TransformString      0x043061
+#define Territory_Reserved1            0x043062
+#define Territory_Reserved2            0x043063
+#define Territory_Reserved3            0x043064
+#define Territory_Reserved4            0x043065
+#define Territory_Reserved5            0x043066
+#define Territory_Reserved6            0x043067
+#define Territory_Reserved7            0x043068
+#define Territory_Reserved8            0x043069
+#define Territory_Reserved9            0x04306a
+#define Territory_Reserved10           0x04306b
+#define Territory_Reserved11           0x04306c
+#define Territory_Reserved12           0x04306d
+#define Territory_Reserved13           0x04306e
+#define Territory_Reserved14           0x04306f
+#define Territory_Reserved15           0x043070
+#define Territory_Reserved16           0x043071
+#define Territory_Reserved17           0x043072
+#define Territory_Reserved18           0x043073
+#define Territory_Reserved19           0x043074
+#define Territory_ConvertTextToString  0x043075
+#define ScreenBlanker_Control          0x043100
+#define TaskWindow_TaskInfo            0x043380
+#define Free_Register                  0x0444c0
+#define Free_DeRegister                0x0444c1
+#define DOSFS_DiscFormat               0x044b00
+#define DOSFS_LayoutStructure          0x044b01
+#define PDriver_Info                   0x080140
+#define PDriver_SetInfo                0x080141
+#define PDriver_CheckFeatures          0x080142
+#define PDriver_PageSize               0x080143
+#define PDriver_SetPageSize            0x080144
+#define PDriver_SelectJob              0x080145
+#define PDriver_CurrentJob             0x080146
+#define PDriver_FontSWI                0x080147
+#define PDriver_EndJob                 0x080148
+#define PDriver_AbortJob               0x080149
+#define PDriver_Reset                  0x08014a
+#define PDriver_GiveRectangle          0x08014b
+#define PDriver_DrawPage               0x08014c
+#define PDriver_GetRectangle           0x08014d
+#define PDriver_CancelJob              0x08014e
+#define PDriver_ScreenDump             0x08014f
+#define PDriver_EnumerateJobs          0x080150
+#define PDriver_SetPrinter             0x080151
+#define PDriver_CancelJobWithError     0x080152
+#define PDriver_SelectIllustration     0x080153
+#define PDriver_InsertIllustration     0x080154
+#define PDriver_DeclareFont            0x080155
+#define PDriver_DeclareDriver          0x080156
+#define PDriver_RemoveDriver           0x080157
+#define PDriver_SelectDriver           0x080158
+#define PDriver_EnumerateDrivers       0x080159
+#define PDriver_MiscOp                 0x08015a
+#define PDriver_MiscOpForDriver        0x08015b
+#define PDriver_SetDriver              0x08015c
+#define SharedCLibrary_LibInitAPCS_A   0x080680
+#define SharedCLibrary_LibInitAPCS_R   0x080681
+#define SharedCLibrary_LibInitModule   0x080682
+#define FrontEnd_ExtendedCmdLine       0x081400
+#define FrontEnd_FreeCmdLine           0x081401
+
+#endif
diff --git a/sys/arch/arm32/boot/swiv.S b/sys/arch/arm32/boot/swiv.S
new file mode 100644 (file)
index 0000000..6e42afa
--- /dev/null
@@ -0,0 +1,80 @@
+#include "regs.h"
+
+       .text
+
+SWIReturnInst:
+       ldr     pc, [sp, #0*4]
+
+       .global _swix
+_swix:
+       orr     r0, r0, #0x20000
+
+       .global _swi
+_swi:
+
+/*
+ * Construct a stack frame that looks something like this:
+ *       returnval
+ *       LDMIA   r12!, {r0..rn}
+ *       SWI     xxxxxx
+ *       LDR     pc, [sp]
+ *       saved r4-r11,lr
+ *       saved r1
+ *       saved input values (r2...rn)
+ */
+
+       mov     pc, lr
+
+       stmfd   sp!, {r1-r3}            /* Save r1 and put 1st two variadic args on stack */
+       bic     r2, r0, #0xff000000
+       orr     r2, r2, #0xef000000     /* Construct SWI instruction */
+       adr     r0, SWIReturn
+       tst     r1, #0x20000            /* bit for write flags */
+       adrne   r0, SWIReturnFlags
+       bic     r1, r1, #0xff000000     /* Construct LDMIA R12!, {regs} instruction, if */
+       bics    r1, r1, #0x00ff0000     /* {regs} = {} (IE no input regs) we must not */
+       orrne   r1, r1, #0xe8000000     /* use an LDMIA R12!, {} instruction as this is an */
+       orrne   r1, r1, #0x00bc0000     /* invalid instruction, we use a suitable NOP instead */
+       moveq   r1, #0                  /* 0 = opcode for ANDEQ r0, r0, r0 (a suitable NOP) */
+       ldr     r3, SWIReturnInst
+       stmfd   sp!, {r0-r9, r11, lr}   /* Save regs and set up SWI call routine (in R0-R3) */
+       add     r12, sp, #(12+1)*4      /* Point R12 at input regs on stack. */
+       add     pc, sp, #4              /* Call routine on stack */
+SWIReturnFlags:
+       ldr     r11, [r12], #4
+       str     pc, [r11]               /* write flags */
+SWIReturn:
+       ldr     lr, [sp, #(12+0)*4]     /* Fetch reg mask again */
+       movs    lr, lr, asl #1          /* Shift out setting C if R0 to be written, N */
+       ldrcs   r11, [r12], #4          /* if R1 to be written. */
+       strcs   r0, [r11]
+       ldrmi   r11, [r12], #4
+       strmi   r1, [r11]
+       movs    lr, lr, asl #2          /* Shift 2 bits each time for the next 2 regs */
+       ldrcs   r11, [r12], #4
+       strcs   r2, [r11]
+       ldrmi   r11, [r12], #4
+       strmi   r3, [r11]
+       movs    lr, lr, asl #2
+       ldrcs   r11, [r12], #4
+       strcs   r4, [r11]
+       ldrmi   r11, [r12], #4
+       strmi   r5, [r11]
+       movs    lr, lr, asl #2
+       ldrcs   r11, [r12], #4
+       strcs   r6, [r11]
+       ldrmi   r11, [r12], #4
+       strmi   r7, [r11]
+       movs    lr, lr, asl #2
+       ldrcs   r11, [r12], #4
+       strcs   r8, [r11]
+       ldrmi   r11, [r12], #4
+       strmi   r9, [r11]
+       ldr     r1, [sp, #2*4]
+       tst     r1, #0x20000            /* X-bit clear */
+       cmpeq   pc, #0x80000000         /* SET V flag if so, so R0 not cleared */
+       movvc   r0, #0                  /* Clear R0 if no error (or X-bit clear) */
+       add     sp, sp, #4*4            /* Drop SWI call routine */
+       ldmia   sp!, {r4-r9,r11,lr}
+       add     sp, sp, #3*4            /* Drop saved R1 and 1st two variadic args. */
+       movs    pc, lr
diff --git a/sys/arch/arm32/boot/swiv.h b/sys/arch/arm32/boot/swiv.h
new file mode 100644 (file)
index 0000000..d60ee2e
--- /dev/null
@@ -0,0 +1,80 @@
+/* SWI veneers:
+ *  Written by Edward Nevill and Jonathan Roach in an idle moment between projects.
+ *  Hacked by BDB to add flag returning 
+ */
+
+/* Anonymous Error type */
+
+struct Error { int num; char msg[4]; };
+
+typedef struct Error Error;
+
+/* Generic SWI interface
+ *  swi(swino,mask,regs...)
+ *   swino = SWI number to call as defined in h.swis, X bit set if you wish the
+ *           X form of the SWI to be called, clear if you want the non X form.
+ *   reg_mask = mask of in / out registers
+ *              bits 0-9:   Bit N set => Register N specified on input
+ *                          Bit N clear => Register N unspecified on input
+ *              bits 22-31: Bit N set => Register N-22 on output stored
+ *                              in address specified in varargs list.
+ *   ...        In order, input registers followed by output registers,
+ *                      starting at r0 and going up.
+ *   returns 0 or errorblock pointer if X-bit set
+ *   returns r0 if X-bit clear
+ *  swix(swino,mask,regs...)
+ *   This behaves identically to 'swi' except that it always calls the X form.
+ *
+ * Eg:
+ *   swi(OS_SWINumberToString, IN(R0|R1|R2), n, buf, 255);
+ *   e = swi(XOS_SWINumberFromString, IN(R1)|OUT(R0), str, &n);
+ *       - Error block pointer (or 0) is returned so must get returned R0
+ *       - via argument list.
+ *   e = swix(OS_SWINumberFromString, IN(R1)|OUT(R0), str, &n);
+ *       - As above but uses the swix function rather that setting the X bit
+ *         explicitly (saves one instruction on SWI call).
+ *   e = swi(OS_File, IN(R0|R1|R2|R3)|OUT(R4), 255, name, buff, 0, &len);
+ *       - We don't care about the load, exec or attrs so don't specify
+ *         them in the output registers.
+ */
+
+extern Error *swix(int swino, int reg_mask, ...);
+extern int swi(int swino, int reg_mask, ...);
+
+/* Register mask macros
+ *  The bits in the register mask are arranged as follows:
+ *  31 30 29 ... 22 ...  8 ...  2  1  0
+ *  O0 O1 O2 ... O9     I9 ... I2 I1 I0  I(N) = bit set if R(N) used on entry
+ *                                       O(N) = bit set if R(N) written on exit
+ *  The bits are arranged like this to optimise the case where a SWI is being
+ *  called with a small number of input and output registers. For example, a SWI
+ *  call which uses R0-R5 on entry and R0-R1 on exit will have a register mask
+ *  of 0xC000003f which can be loaded into an ARM register in one instruction
+ *  (the compiler performs this optimisation, even when the constant wraps
+ *  around between bits 0 and 31). Using the more obvious coding of I0-I9 in bits
+ *  0 - 9 and O0-O9 in bits 16-23 leads to a constant of 0x0003003f which require
+ *  two instructions.
+ */
+#define IN(m) (m)
+/* old, incorrect version
+#define OUT(m) ((unsigned)(m&1)<<31|(m&2)<<29|(m&4)<<27|(m&8)<<25|(m&16)<<23|\
+                (m&32)<<21|(m&64)<<19|(m&128)<<17|(m&256)<<15|(m&512)<<13)
+*/
+#define OUT(m) ((unsigned)((m)&1)<<31|((m)&2)<<29|((m)&4)<<27|\
+                ((m)&8)<<25|((m)&16)<<23|((m)&32)<<21|((m)&64)<<19|\
+                ((m)&128)<<17|((m)&256)<<15|((m)&512)<<13|((m)&1024)<<11)
+
+/* The register names
+ *  Change these to use different names if you use R0 - R9 elsewhere in your program
+ */
+#define PSW 0x400       /* Use only in OUT, orders BEFORE others */
+#define R0 0x001
+#define R1 0x002
+#define R2 0x004
+#define R3 0x008
+#define R4 0x010
+#define R5 0x020
+#define R6 0x040
+#define R7 0x080
+#define R8 0x100
+#define R9 0x200
diff --git a/sys/arch/arm32/boot/vsprintf.c b/sys/arch/arm32/boot/vsprintf.c
new file mode 100644 (file)
index 0000000..3e6e9ff
--- /dev/null
@@ -0,0 +1,275 @@
+#include <stdarg.h>
+#include <string.h>
+
+# define toupper(x) ((x >= 'a' && x <= 'z') ? (x & 0xdf) : x)
+/*# define tolower(x) ((x >= 'A' && x <= 'Z') ? (x | 0x20) : x)*/
+# define islower(x) ((x >= 'a' && x <= 'z') ? 1 : 0)
+# define isdigit(x) ((x >= '0' && x <= '9') ? 1 : 0)
+# define isxdigit(x) (((x >= '0' && x <= '9') || (x >= 'a' && x <= 'f') || (x >= 'A' && x <= 'F')) ? 1 : 0)
+
+unsigned long simple_strtoul(const char *cp,char **endp,unsigned int base)
+{
+       unsigned long result = 0,value;
+
+       if (!base) {
+               base = 10;
+               if (*cp == '0') {
+                       base = 8;
+                       cp++;
+                       if ((*cp == 'x') && isxdigit(cp[1])) {
+                               cp++;
+                               base = 16;
+                       }
+               }
+       }
+       while (isxdigit(*cp) && (value = isdigit(*cp) ? *cp-'0' : (islower(*cp)
+           ? toupper(*cp) : *cp)-'A'+10) < base) {
+               result = result*base + value;
+               cp++;
+       }
+       if (endp)
+               *endp = (char *)cp;
+       return result;
+}
+
+/* we use this so that we can do without the ctype library */
+#define is_digit(c)    ((c) >= '0' && (c) <= '9')
+
+static int skip_atoi(const char **s)
+{
+       int i=0;
+
+       while (is_digit(**s))
+               i = i*10 + *((*s)++) - '0';
+       return i;
+}
+
+#define ZEROPAD        1               /* pad with zero */
+#define SIGN   2               /* unsigned/signed long */
+#define PLUS   4               /* show plus */
+#define SPACE  8               /* space if plus */
+#define LEFT   16              /* left justified */
+#define SPECIAL        32              /* 0x */
+#define SMALL  64              /* use 'abcdef' instead of 'ABCDEF' */
+
+static unsigned int do_div(unsigned int *n, unsigned int base)
+  {
+    unsigned int d;
+
+    d = *n % base;
+    *n /= base;
+
+    return(d);
+  }
+
+static char * number(char * str, int num, int base, int size, int precision
+       ,int type)
+{
+       char c,sign,tmp[36];
+       const char *digits="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
+       int i;
+
+       if (type&SMALL) digits="0123456789abcdefghijklmnopqrstuvwxyz";
+       if (type&LEFT) type &= ~ZEROPAD;
+       if (base<2 || base>36)
+               return 0;
+       c = (type & ZEROPAD) ? '0' : ' ' ;
+       if (type&SIGN && num<0) {
+               sign='-';
+               num = -num;
+       } else
+               sign=(type&PLUS) ? '+' : ((type&SPACE) ? ' ' : 0);
+       if (sign) size--;
+       if (type&SPECIAL) {
+               if (base==16) size -= 2;
+               else if (base==8) size--;
+       }
+       i=0;
+       if (num==0)
+               tmp[i++]='0';
+       else while (num!=0)
+               tmp[i++]=digits[do_div((unsigned int *)&num,base)];
+       if (i>precision) precision=i;
+       size -= precision;
+       if (!(type&(ZEROPAD+LEFT)))
+               while(size-->0)
+                       *str++ = ' ';
+       if (sign)
+               *str++ = sign;
+       if (type&SPECIAL) {
+               if (base==8)
+                       *str++ = '0';
+               else if (base==16) {
+                       *str++ = '0';
+                       *str++ = digits[33];
+               }
+       }
+       if (!(type&LEFT))
+               while(size-->0)
+                       *str++ = c;
+       while(i<precision--)
+               *str++ = '0';
+       while(i-->0)
+               *str++ = tmp[i];
+       while(size-->0)
+               *str++ = ' ';
+       return str;
+}
+
+int vsprintf(char *buf, const char *fmt, va_list args)
+{
+       int len;
+       int i;
+       char * str;
+       char *s;
+       int *ip;
+
+       int flags;              /* flags to number() */
+
+       int field_width;        /* width of output field */
+       int precision;          /* min. # of digits for integers; max
+                                  number of chars for from string */
+       int qualifier;          /* 'h', 'l', or 'L' for integer fields */
+
+       for (str=buf ; *fmt ; ++fmt) {
+               if (*fmt != '%') {
+                       *str++ = *fmt;
+                       continue;
+               }
+
+               /* process flags */
+               flags = 0;
+               repeat:
+                       ++fmt;          /* this also skips first '%' */
+                       switch (*fmt) {
+                               case '-': flags |= LEFT; goto repeat;
+                               case '+': flags |= PLUS; goto repeat;
+                               case ' ': flags |= SPACE; goto repeat;
+                               case '#': flags |= SPECIAL; goto repeat;
+                               case '0': flags |= ZEROPAD; goto repeat;
+                               }
+
+               /* get field width */
+               field_width = -1;
+               if (is_digit(*fmt))
+                       field_width = skip_atoi(&fmt);
+               else if (*fmt == '*') {
+                       /* it's the next argument */
+                       field_width = va_arg(args, int);
+                       if (field_width < 0) {
+                               field_width = -field_width;
+                               flags |= LEFT;
+                       }
+               }
+
+               /* get the precision */
+               precision = -1;
+               if (*fmt == '.') {
+                       ++fmt;
+                       if (is_digit(*fmt))
+                               precision = skip_atoi(&fmt);
+                       else if (*fmt == '*') {
+                               /* it's the next argument */
+                               precision = va_arg(args, int);
+                       }
+                       if (precision < 0)
+                               precision = 0;
+               }
+
+               /* get the conversion qualifier */
+               qualifier = -1;
+               if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L') {
+                       qualifier = *fmt;
+                       ++fmt;
+               }
+
+               switch (*fmt) {
+               case 'c':
+                       if (!(flags & LEFT))
+                               while (--field_width > 0)
+                                       *str++ = ' ';
+                       *str++ = (unsigned char) va_arg(args, int);
+                       while (--field_width > 0)
+                               *str++ = ' ';
+                       break;
+
+               case 's':
+                       s = va_arg(args, char *);
+                       if (!s)
+                               s = "<NULL>";
+                       len = strlen(s);
+                       if (precision < 0)
+                               precision = len;
+                       else if (len > precision)
+                               len = precision;
+
+                       if (!(flags & LEFT))
+                               while (len < field_width--)
+                                       *str++ = ' ';
+                       for (i = 0; i < len; ++i)
+                               *str++ = *s++;
+                       while (len < field_width--)
+                               *str++ = ' ';
+                       break;
+
+               case 'o':
+                       str = number(str, va_arg(args, unsigned long), 8,
+                               field_width, precision, flags);
+                       break;
+
+               case 'p':
+                       if (field_width == -1) {
+                               field_width = 8;
+                               flags |= ZEROPAD;
+                       }
+                       str = number(str,
+                               (unsigned long) va_arg(args, void *), 16,
+                               field_width, precision, flags);
+                       break;
+
+               case 'x':
+                       flags |= SMALL;
+               case 'X':
+                       str = number(str, va_arg(args, unsigned long), 16,
+                               field_width, precision, flags);
+                       break;
+
+               case 'd':
+               case 'i':
+                       flags |= SIGN;
+               case 'u':
+                       str = number(str, va_arg(args, unsigned long), 10,
+                               field_width, precision, flags);
+                       break;
+
+               case 'n':
+                       ip = va_arg(args, int *);
+                       *ip = (str - buf);
+                       break;
+
+               default:
+                       if (*fmt != '%')
+                               *str++ = '%';
+                       if (*fmt)
+                               *str++ = *fmt;
+                       else
+                               --fmt;
+                       break;
+               }
+       }
+       *str = '\0';
+       return str-buf;
+}
+
+
+int sprintf(char * buf, const char *fmt, ...)
+{
+       va_list args;
+       int i;
+
+       va_start(args, fmt);
+       i=vsprintf(buf,fmt,args);
+       va_end(args);
+       return i;
+}
+
diff --git a/sys/arch/arm32/compile/.keep_me b/sys/arch/arm32/compile/.keep_me
new file mode 100644 (file)
index 0000000..284b348
--- /dev/null
@@ -0,0 +1,3 @@
+$NetBSD: .keep_me,v 1.1 1996/01/31 23:19:04 mark Exp $
+
+This file must remain so that 'cvs checkout' makes the compile directory.
diff --git a/sys/arch/arm32/conf/BETA b/sys/arch/arm32/conf/BETA
new file mode 100644 (file)
index 0000000..7a60803
--- /dev/null
@@ -0,0 +1,186 @@
+#
+#      BETA -- Kernel configuration used for beta kernels
+#
+
+include        "std.arm32"
+
+# estimated number of users
+
+maxusers       8
+
+# Standard system options
+
+options                TIMEZONE=0      # time zone to adjust RTC time by
+options                DST=0           # daylight savings time used by RTC
+options                SWAPPAGER       # paging; REQUIRED
+options                VNODEPAGER      # mmap() of files
+options                DEVPAGER        # mmap() of devices
+
+# CPU options
+
+options                CPU_ARM6
+options                CPU_LATE_ABORT  # ARM7XX compatibility
+
+# FPA options
+
+options                FPE             # Single precision FPE
+options                ARMFPE          # ARM Ltd FPE
+
+# File system options
+
+options                FFS             # UFS
+#options               QUOTA           # UFS quotas
+#options               LFS             # log-structured file system
+#options               MFS             # memory file system
+
+options                CD9660          # ISO 9660 + Rock Ridge file system
+options                MSDOSFS         # MS-DOS file system
+options                FDESC           # /dev/fd
+options                FIFO            # FIFOs; RECOMMENDED
+options                KERNFS          # /kern
+#options               NULLFS          # loopback file system
+#options               PORTAL          # ?
+options                PROCFS          # /proc
+#options               UMAPFS          # NULLFS + uid and gid remapping
+options                UNION           # union file system
+
+# Networking options
+
+options                NFSCLIENT
+options                NFSSERVER
+#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
+
+# Compatibility options
+
+options                COMPAT_43
+options                COMPAT_10
+options                COMPAT_09
+options         TCP_COMPAT_42   # TCP bug compatibility with 4.2BSD
+
+# Shared memory options
+
+#options       SYSVMSG         # System V-like message queues
+#options       SYSVSEM         # System V-like semaphores
+#options       SYSVSHM         # System V-like memory sharing
+#options       SHMMAXPGS=1024  # 1024 pages is the default
+
+# Device options
+
+options                RAMDISK_HOOKS   # boottime setup of ramdisk
+options                RAMDISK_SIZE=0  # Size in KBytes
+options                PLIP            # Build plip device into lpt driver
+
+# Development options
+
+options                DIAGNOSTIC      # internally consistency checks
+options                KTRACE          # system call tracing, a la ktrace(1)
+options                IRQSTATS        # IRQ statistics
+options                POSTMORTEM      # perform postmortem on panic
+#options               ROTTEN_INNARDS  # show the gory bit of the postmortem
+options                KSHELL          # kernel developemnt shell (debug)
+#options               LKM             # loadable kernel modules
+#options       DEBUGTERM       # create a debug console
+#options       KGDB            # remote kernel debugging
+#options       DDB             # in-kernel debugger
+#makeoptions   DEBUG="-g"      # compile full symbol table
+
+config         netbsd  swap generic
+options                GENERIC
+
+# The main bus device
+mainbus0 at root
+
+# The boot cpu
+cpu0 at mainbus?
+
+# The vidc
+vidcvideo0     at mainbus?
+
+# generic VT console device
+vt0     at mainbus?
+vt1     at mainbus?
+vt2     at mainbus?
+vt3     at mainbus?
+vt4     at mainbus?
+vt5     at mainbus?
+
+# IDE disk controller
+wdc0    at mainbus? base 0x002107c0 irq 9
+wd0     at wdc? drive ?
+wd1     at wdc? drive ?
+
+# Floppy disk controller
+fdc0    at mainbus? base 0x00210fc0 irq 12 dack 0x00002000
+fd0     at fdc? drive ?
+
+# kbd via IOMD
+kbd0   at mainbus? base 0x00000000
+
+# quadrature mouse
+quadmouse0     at mainbus? base 0x00000000
+
+# Serial ports
+com0    at mainbus? base 0x00210fe0 irq 10
+#com1    at mainbus? base 0x00210be0
+
+# Parallel ports
+lpt0    at mainbus? base 0x002109e0 irq 0
+
+# Crude sound device
+beep0  at mainbus? base 0x00000000
+
+# IIC bus device
+iic0   at mainbus?
+
+# RTC device
+rtc0   at iic? addr 0xa0
+
+# Podule bus device
+podulebus0     at root
+
+asc0   at podulebus?                   # Acorn SCSI card
+scsibus* at asc?
+
+csc0   at podulebus?                   # Cumana SCSI II card
+scsibus* at csc?
+
+ptsc0  at podulebus?                   # Power-Tec SCSI II card
+scsibus* at ptsc?
+
+oak0   at podulebus?                   # Oak SCSI I card
+scsibus* at oak?
+
+sd*    at scsibus? target ? lun ?      # SCSI disk drives
+st*    at scsibus? target ? lun ?      # SCSI tape drives
+cd*    at scsibus? target ? lun ?      # SCSI CD-ROM drives
+ch*    at scsibus? target ? lun ?      # SCSI auto-changers
+uk*    at scsibus? target ? lun ?      # SCSI unknown device
+
+#kie*  at podulebus? slot ? offset ?
+
+ea0    at podulebus?                   # Ether3 podules
+eb0    at podulebus?                   # EtherB network slot cards
+eh0    at podulebus?                   # EtherH network slot cards
+ie0    at podulebus?                   # Ether1 podules
+
+pseudo-device  loop    1               # network loopback
+pseudo-device   bpfilter 8              # packet filter
+pseudo-device  sl      2               # CSLIP
+pseudo-device  ppp     2               # PPP
+pseudo-device  tun     2               # network tunneling over tty
+
+pseudo-device   pty     32              # pseudo-terminals
+pseudo-device  tb      1               # tablet line discipline
+pseudo-device   vnd     4               # paging to files
+pseudo-device  ccd     2               # concatenated disk devices
+
+pseudo-device  rd      1               # Ramdisk driver
+
+makeoptions MONITOR="Taxan875+LR"
+#makeoptions MONITOR="AKF60"
+makeoptions MODES="1024,768,60 1024,768,70 800,600,60 640,480,60 1280,1024 1152,900"
diff --git a/sys/arch/arm32/conf/CLAIRE b/sys/arch/arm32/conf/CLAIRE
new file mode 100644 (file)
index 0000000..ebf0d05
--- /dev/null
@@ -0,0 +1,185 @@
+#
+#      CLAIRE -- Nut's development machine
+#
+
+include        "std.arm32"
+
+# estimated number of users
+
+maxusers       8
+
+# Standard system options
+
+options                TIMEZONE=0      # time zone to adjust RTC time by
+options                DST=0           # daylight savings time used by RTC
+options                SWAPPAGER       # paging; REQUIRED
+options                VNODEPAGER      # mmap() of files
+options                DEVPAGER        # mmap() of devices
+
+# CPU options
+
+options                CPU_ARM6
+options                CPU_LATE_ABORT  # ARM7XX compatibility
+
+# FPA options
+
+options                FPE             # Single precision FPE
+options                ARMFPE          # ARM Ltd FPE
+
+# File system options
+
+options                FFS             # UFS
+#options               QUOTA           # UFS quotas
+#options               LFS             # log-structured file system
+#options               MFS             # memory file system
+
+options                CD9660          # ISO 9660 + Rock Ridge file system
+options                MSDOSFS         # MS-DOS file system
+#options               FDESC           # /dev/fd
+options                FIFO            # FIFOs; RECOMMENDED
+options                KERNFS          # /kern
+#options               NULLFS          # loopback file system
+#options               PORTAL          # ?
+options                PROCFS          # /proc
+#options               UMAPFS          # NULLFS + uid and gid remapping
+#options               UNION           # union file system
+
+# Networking options
+
+options                NFSCLIENT
+options                NFSSERVER
+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
+
+# Compatibility options
+
+options                COMPAT_43
+options                COMPAT_10
+options                COMPAT_09
+options         TCP_COMPAT_42   # TCP bug compatibility with 4.2BSD
+
+# Shared memory options
+
+#options       SYSVMSG         # System V-like message queues
+#options       SYSVSEM         # System V-like semaphores
+#options       SYSVSHM         # System V-like memory sharing
+#options       SHMMAXPGS=1024  # 1024 pages is the default
+
+# Device options
+
+options                RAMDISK_HOOKS   # boottime setup of ramdisk
+options                RAMDISK_SIZE=0  # Size in KBytes
+options                PLIP            # Build plip device into lpt driver
+
+# Development options
+
+options                DIAGNOSTIC      # internally consistency checks
+options                KTRACE          # system call tracing, a la ktrace(1)
+options                IRQSTATS        # IRQ statistics
+options                POSTMORTEM      # perform postmortem on panic
+#options               ROTTEN_INNARDS  # show the gory bit of the postmortem
+options                KSHELL          # kernel developemnt shell (debug)
+options                LKM             # loadable kernel modules
+#options       DEBUGTERM       # create a debug console
+#options       KGDB            # remote kernel debugging
+#options       DDB             # in-kernel debugger
+#makeoptions   DEBUG="-g"      # compile full symbol table
+
+config         netbsd  swap generic
+options                GENERIC
+
+# The main bus device
+mainbus0 at root
+
+# The boot cpu
+cpu0 at mainbus?
+
+# The vidc
+vidcvideo0     at mainbus?
+
+# generic VT console device
+vt0     at mainbus?
+vt1     at mainbus?
+vt2     at mainbus?
+vt3     at mainbus?
+vt4     at mainbus?
+vt5     at mainbus?
+
+# IDE disk controller
+wdc0    at mainbus? base 0x002107c0 irq 9
+wd0     at wdc? drive ?
+wd1     at wdc? drive ?
+
+# Floppy disk controller
+fdc0    at mainbus? base 0x00210fc0 irq 12 dack 0x00002000
+fd0     at fdc? drive ?
+
+# kbd via IOMD
+kbd0   at mainbus? base 0x00000000
+
+# quadrature mouse
+quadmouse0     at mainbus? base 0x00000000
+
+# Serial ports
+com0    at mainbus? base 0x00210fe0 irq 10
+#com1    at mainbus? base 0x00210be0
+
+# Parallel ports
+lpt0    at mainbus? base 0x002109e0 irq 0
+
+# Crude sound device
+beep0  at mainbus? base 0x00000000
+
+# IIC bus device
+iic0   at mainbus?
+
+# RTC device
+rtc0   at iic? addr 0xa0
+
+# Podule bus device
+podulebus0     at root
+
+#asc0  at podulebus?                   # Acorn SCSI card
+#scsibus* at asc?
+
+#csc0  at podulebus?                   # Cumana SCSI II card
+#scsibus* at csc?
+
+#ptsc0 at podulebus?                   # Power-Tec SCSI II card
+#scsibus* at ptsc?
+
+oak0   at podulebus?                   # Oak SCSI I card
+scsibus* at oak?
+
+sd*    at scsibus? target ? lun ?      # SCSI disk drives
+st*    at scsibus? target ? lun ?      # SCSI tape drives
+cd*    at scsibus? target ? lun ?      # SCSI CD-ROM drives
+ch*    at scsibus? target ? lun ?      # SCSI auto-changers
+uk*    at scsibus? target ? lun ?      # SCSI unknown device
+
+#kie*  at podulebus? slot ? offset ?
+
+#ea0   at podulebus?                   # Ether3 podules
+#eb0   at podulebus?                   # EtherB network slot cards
+eh0    at podulebus?                   # EtherH network slot cards
+ie0    at podulebus?                   # Ether1 podules
+
+pseudo-device  loop    1               # network loopback
+pseudo-device   bpfilter 8              # packet filter
+pseudo-device  sl      2               # CSLIP
+pseudo-device  ppp     2               # PPP
+pseudo-device  tun     2               # network tunneling over tty
+
+pseudo-device   pty     32              # pseudo-terminals
+pseudo-device  tb      1               # tablet line discipline
+pseudo-device   vnd     4               # paging to files
+pseudo-device  ccd     2               # concatenated disk devices
+
+pseudo-device  rd      1               # Ramdisk driver
+
+makeoptions MONITOR="AKF60"
+makeoptions MODES="1024,768,60 1024,768,70 800,600,60 640,480,60 1280,1024 1152,900"
diff --git a/sys/arch/arm32/conf/GENERIC b/sys/arch/arm32/conf/GENERIC
new file mode 100644 (file)
index 0000000..c54ee1a
--- /dev/null
@@ -0,0 +1,198 @@
+#
+#      GENERIC -- everything that's currently supported
+#
+
+include        "std.arm32"
+
+# estimated number of users
+
+maxusers       32
+
+# Standard system options
+
+options                TIMEZONE=0      # time zone to adjust RTC time by
+options                DST=0           # daylight savings time used by RTC
+options                SWAPPAGER       # paging; REQUIRED
+options                VNODEPAGER      # mmap() of files
+options                DEVPAGER        # mmap() of devices
+
+# CPU options
+
+options                CPU_ARM6
+options                CPU_LATE_ABORT  # ARM7XX compatibility
+
+# FPA options
+
+options                FPE             # Single precision FPE
+options                ARMFPE          # ARM Ltd FPE
+
+# File system options
+
+options                FFS             # UFS
+options                QUOTA           # UFS quotas
+options                LFS             # log-structured file system
+options                MFS             # memory file system
+
+options                CD9660          # ISO 9660 + Rock Ridge file system
+options                MSDOSFS         # MS-DOS file system
+options                FDESC           # /dev/fd
+options                FIFO            # FIFOs; RECOMMENDED
+options                KERNFS          # /kern
+options                NULLFS          # loopback file system
+options                PORTAL          # ?
+options                PROCFS          # /proc
+options                UMAPFS          # NULLFS + uid and gid remapping
+options                UNION           # union file system
+
+# Networking options
+
+options                NFSCLIENT
+options                NFSSERVER
+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
+
+# Compatibility options
+
+options                COMPAT_43
+options                COMPAT_10
+options                COMPAT_09
+options         TCP_COMPAT_42   # TCP bug compatibility with 4.2BSD
+
+# Shared memory options
+
+#options       SYSVMSG         # System V-like message queues
+#options       SYSVSEM         # System V-like semaphores
+#options       SYSVSHM         # System V-like memory sharing
+#options       SHMMAXPGS=1024  # 1024 pages is the default
+
+# Device options
+
+options                RAMDISK_HOOKS   # boottime setup of ramdisk
+options                RAMDISK_SIZE=0  # Size in KBytes
+options                PLIP            # Build plip device into lpt driver
+
+# Development options
+
+options                DIAGNOSTIC      # internally consistency checks
+options                KTRACE          # system call tracing, a la ktrace(1)
+options                IRQSTATS        # IRQ statistics
+options                POSTMORTEM      # perform postmortem on panic
+#options               ROTTEN_INNARDS  # show the gory bit of the postmortem
+options                KSHELL          # kernel developemnt shell (debug)
+options                LKM             # loadable kernel modules
+#options       DEBUGTERM       # create a debug console
+#options       KGDB            # remote kernel debugging
+options                DDB             # in-kernel debugger
+#makeoptions   DEBUG="-g"      # compile full symbol table
+
+config         netbsd  swap generic
+options                GENERIC
+
+# The main bus device
+mainbus0 at root
+
+# The boot cpu
+cpu0 at mainbus?
+
+# The hydra multiprocessor device
+#hydrabus0 at mainbus?
+
+#cpu1 at hydrabus?
+#cpu2 at hydrabus?
+#cpu3 at hydrabus?
+#cpu4 at hydrabus?
+
+# The vidc
+vidcvideo0     at mainbus?
+
+# generic VT console device
+vt0     at mainbus?
+vt1     at mainbus?
+vt2     at mainbus?
+vt3     at mainbus?
+vt4     at mainbus?
+vt5     at mainbus?
+
+# IDE disk controller
+wdc0    at mainbus? base 0x002107c0 irq 9
+wd0     at wdc? drive ?
+wd1     at wdc? drive ?
+
+# Floppy disk controller
+fdc0    at mainbus? base 0x00210fc0 irq 12 dack 0x00002000
+fd0     at fdc? drive ?
+
+# kbd via IOMD
+kbd0   at mainbus? base 0x00000000
+
+# quadrature mouse
+quadmouse0     at mainbus? base 0x00000000
+
+# PS2 mouse
+pms0   at mainbus? base 0x00000000
+
+# Serial ports
+com0    at mainbus? base 0x00210fe0 irq 10
+#com1    at mainbus? base 0x00210be0
+
+# Parallel ports
+lpt0    at mainbus? base 0x002109e0 irq 0
+
+# Crude sound device
+beep0  at mainbus? base 0x00000000
+
+# IIC bus device
+iic0   at mainbus?
+
+# RTC device
+rtc0   at iic? addr 0xa0
+
+# Podule bus device
+podulebus0     at root
+
+asc0   at podulebus?                   # Acorn SCSI card
+scsibus* at asc?
+
+#csc0  at podulebus?                   # Cumana SCSI II card
+#scsibus* at csc?
+
+ptsc0  at podulebus?                   # Power-Tec SCSI II card
+scsibus* at ptsc?
+
+oak0   at podulebus?                   # Oak SCSI I card
+scsibus* at oak?
+
+sd*    at scsibus? target ? lun ?      # SCSI disk drives
+st*    at scsibus? target ? lun ?      # SCSI tape drives
+cd*    at scsibus? target ? lun ?      # SCSI CD-ROM drives
+ch*    at scsibus? target ? lun ?      # SCSI auto-changers
+uk*    at scsibus? target ? lun ?      # SCSI unknown device
+ss*    at scsibus? target ? lun ?      # SCSI scanner
+
+#kie*  at podulebus? slot ? offset ?
+
+ea0    at podulebus?                   # Ether3 podules
+eb0    at podulebus?                   # EtherB network slot cards
+eh0    at podulebus?                   # EtherH network slot cards
+ie0    at podulebus?                   # Ether1 podules
+
+pseudo-device  loop    1               # network loopback
+pseudo-device   bpfilter 8              # packet filter
+pseudo-device  sl      2               # CSLIP
+pseudo-device  ppp     2               # PPP
+pseudo-device  tun     2               # network tunneling over tty
+
+pseudo-device   pty     32              # pseudo-terminals
+pseudo-device  tb      1               # tablet line discipline
+pseudo-device   vnd     4               # paging to files
+pseudo-device  ccd     2               # concatenated disk devices
+
+pseudo-device  rd      1               # Ramdisk driver
+
+makeoptions MONITOR="Taxan875+LR"
+#makeoptions MONITOR="AKF60"
+makeoptions MODES="1024,768,60 1024,768,70 800,600,60 640,480,60 1280,1024 1152,900"
diff --git a/sys/arch/arm32/conf/Makefile.arm32 b/sys/arch/arm32/conf/Makefile.arm32
new file mode 100644 (file)
index 0000000..10cc987
--- /dev/null
@@ -0,0 +1,186 @@
+#      $NetBSD: Makefile.arm32,v 1.10 1996/02/29 20:55:24 cgd Exp $
+
+# Makefile for NetBSD
+#
+# This makefile is constructed from a machine description:
+#      config machineid
+# Most changes should be made in the machine description
+#      /sys/arch/arm32/conf/``machineid''
+# after which you should do
+#      config machineid
+# Machine generic makefile changes should be made in
+#      /sys/arch/arm32/conf/Makefile.arm32
+# after which config should be rerun for all machines of that type.
+#
+# N.B.: NO DEPENDENCIES ON FOLLOWING FLAGS ARE VISIBLE TO MAKEFILE
+#      IF YOU CHANGE THE DEFINITION OF ANY OF THESE RECOMPILE EVERYTHING
+#
+# -DTRACE      compile in kernel tracing hooks
+# -DQUOTA      compile in file system quotas
+
+# DEBUG is set to -g if debugging.
+# PROF is set to -pg if profiling.
+
+AS?=   as
+CC?=   cc
+CPP?=  cpp
+LD?=   ld
+STRIP?=        strip -d
+TOUCH?=        touch -f -c
+
+# source tree is located via $S relative to the compilation directory
+S=     ../../../..
+ARM32= ../..
+
+INCLUDES=      -I. -I$S/arch -I$S
+CPPFLAGS=      ${INCLUDES} ${IDENT} -D_KERNEL -Darm32
+CFLAGS=                ${DEBUG} -O2 -Werror -fno-builtin
+AFLAGS=                -x assembler-with-cpp -traditional-cpp -D_LOCORE
+LINKFLAGS=     -Ttext F0000020 -e start
+
+### find out what to use for libkern
+.include "$S/lib/libkern/Makefile.inc"
+.ifndef PROF
+LIBKERN=       ${KERNLIB}
+.else
+LIBKERN=       ${KERNLIB_PROF}
+.endif
+
+### find out what to use for libcompat
+.include "$S/compat/common/Makefile.inc"
+.ifndef PROF
+LIBCOMPAT=     ${COMPATLIB}
+.else
+LIBCOMPAT=     ${COMPATLIB_PROF}
+.endif
+
+# compile rules: rules are named ${TYPE}_${SUFFIX}${CONFIG_DEP}
+# where TYPE is NORMAL, DRIVER, or PROFILE}; SUFFIX is the file suffix,
+# capitalized (e.g. C for a .c file), and CONFIG_DEP is _C if the file
+# is marked as config-dependent.
+
+NORMAL_C=      ${CC} ${CFLAGS} ${CPPFLAGS} ${PROF} -c $<
+NORMAL_C_C=    ${CC} ${CFLAGS} ${CPPFLAGS} ${PROF} ${PARAM} -c $<
+
+DRIVER_C=      ${CC} ${CFLAGS} ${CPPFLAGS} ${PROF} -c $<
+DRIVER_C_C=    ${CC} ${CFLAGS} ${CPPFLAGS} ${PROF} ${PARAM} -c $<
+
+NORMAL_S=      ${CC} ${AFLAGS} ${CPPFLAGS} -c $<
+NORMAL_S_C=    ${CC} ${AFLAGS} ${CPPFLAGS} ${PARAM} -c $<
+
+%OBJS
+
+%CFILES
+
+%SFILES
+
+# load lines for config "xxx" will be emitted as:
+# xxx: ${SYSTEM_DEP} swapxxx.o
+#      ${SYSTEM_LD_HEAD}
+#      ${SYSTEM_LD} swapxxx.o
+#      ${SYSTEM_LD_TAIL}
+SYSTEM_OBJ=    locore.o modedefs.o \
+               param.o ioconf.o ${OBJS} ${LIBKERN} ${LIBCOMPAT}
+SYSTEM_DEP=    Makefile ${SYSTEM_OBJ}
+SYSTEM_LD_HEAD=        rm -f $@
+SYSTEM_LD=     @echo ${LD} ${LINKFLAGS} -o $@ '$${SYSTEM_OBJ}' vers.o; \
+               ${LD} ${LINKFLAGS} -o $@ ${SYSTEM_OBJ} vers.o
+SYSTEM_LD_TAIL=        @size $@; chmod 755 $@
+
+DEBUG?=
+.if ${DEBUG} == "-g"
+LINKFLAGS+=    -X
+SYSTEM_LD_TAIL+=; \
+               echo cp $@ $@.gdb; rm -f $@.gdb; cp $@ $@.gdb; \
+               echo ${STRIP} $@; ${STRIP} $@
+.else
+LINKFLAGS+=    -x
+.endif
+
+%LOAD
+
+assym.h: genassym
+       ./genassym >assym.h
+
+genassym: genassym.o
+       ${CC} -o $@ genassym.o
+
+genassym.o: ${ARM32}/arm32/genassym.c
+       ${NORMAL_C_C}
+
+param.c: $S/conf/param.c
+       rm -f param.c
+       cp $S/conf/param.c .
+
+param.o: param.c Makefile
+       ${NORMAL_C_C}
+
+ioconf.o: ioconf.c
+       ${NORMAL_C}
+
+newvers: ${SYSTEM_DEP} ${SYSTEM_SWAP_DEP}
+       sh $S/conf/newvers.sh
+       ${CC} ${CFLAGS} ${CPPFLAGS} ${PROF} -c vers.c
+
+
+clean::
+       rm -f eddep *netbsd netbsd.gdb tags *.[io] [a-z]*.s \
+           [Ee]rrs linterrs makelinks genassym genassym.o assym.h
+
+lint:
+       @lint -hbxncez -DGENERIC -Dvolatile= ${CPPFLAGS} ${PARAM} -UKGDB \
+           ${ARM32}/arm32/Locore.c ${CFILES} ${ARM32}/arm32/swapgeneric.c \
+           ioconf.c param.c | \
+           grep -v 'static function .* unused'
+
+tags:
+       @echo "see $S/kern/Makefile for tags"
+
+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
+
+SRCS=  ${ARM32}/arm32/locore.S modedefs.c \
+       param.c ioconf.c ${CFILES} ${SFILES}
+depend: .depend
+.depend: ${SRCS} assym.h param.c
+       mkdep ${AFLAGS} ${CPPFLAGS} ${ARM32}/arm32/locore.S
+       mkdep -a ${CFLAGS} ${CPPFLAGS} modedefs.c
+       mkdep -a ${CFLAGS} ${CPPFLAGS} param.c ioconf.c ${CFILES}
+       mkdep -a ${AFLAGS} ${CPPFLAGS} ${SFILES}
+       mkdep -a ${CFLAGS} ${CPPFLAGS} ${PARAM} ${ARM32}/arm32/genassym.c
+
+
+# depend on root or device configuration
+autoconf.o conf.o: Makefile
+# depend on network or filesystem configuration 
+uipc_proto.o vfs_conf.o: Makefile 
+
+# depend on maxusers
+genassym.o machdep.o: Makefile
+
+# depend on CPU configuration 
+cpuswitch.o fault.o machdep.o: Makefile
+
+
+locore.o: ${ARM32}/arm32/locore.S assym.h
+       ${NORMAL_S}
+
+modedefs.c: makemodes ${ARM32}/conf/monitors/${MONITOR} Makefile
+       ./makemodes ${ARM32}/conf/monitors/${MONITOR} modedefs.c ${MODES}
+
+modedefs.o: modedefs.c
+       ${NORMAL_C}
+
+makemodes: makemodes.o
+       ${CC} -o $@ makemodes.o
+
+makemodes.o: ${ARM32}/arm32/makemodes.c
+       ${NORMAL_C_C}
+
+%RULES
diff --git a/sys/arch/arm32/conf/PHARM b/sys/arch/arm32/conf/PHARM
new file mode 100644 (file)
index 0000000..517b4d4
--- /dev/null
@@ -0,0 +1,194 @@
+#
+#      PHARM -- Mark's development machine in the office
+#
+
+include        "std.arm32"
+
+# estimated number of users
+
+maxusers       32
+
+# Standard system options
+
+options                TIMEZONE=0      # time zone to adjust RTC time by
+options                DST=0           # daylight savings time used by RTC
+options                SWAPPAGER       # paging; REQUIRED
+options                VNODEPAGER      # mmap() of files
+options                DEVPAGER        # mmap() of devices
+
+# CPU options
+
+options                CPU_ARM6
+options                CPU_LATE_ABORT  # ARM7XX compatibility
+
+# FPA options
+
+#options       FPE             # Single precision FPE
+options                ARMFPE          # ARM Ltd FPE
+
+# File system options
+
+options                FFS             # UFS
+#options               QUOTA           # UFS quotas
+#options               LFS             # log-structured file system
+#options               MFS             # memory file system
+
+options                CD9660          # ISO 9660 + Rock Ridge file system
+options                MSDOSFS         # MS-DOS file system
+options                FDESC           # /dev/fd
+options                FIFO            # FIFOs; RECOMMENDED
+options                KERNFS          # /kern
+#options               NULLFS          # loopback file system
+#options               PORTAL          # ?
+options                PROCFS          # /proc
+#options               UMAPFS          # NULLFS + uid and gid remapping
+options                UNION           # union file system
+
+# Networking options
+
+options                NFSCLIENT
+options                NFSSERVER
+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
+
+# Compatibility options
+
+options                COMPAT_43
+options                COMPAT_10
+options                COMPAT_09
+options         TCP_COMPAT_42   # TCP bug compatibility with 4.2BSD
+
+# Shared memory options
+
+#options       SYSVMSG         # System V-like message queues
+#options       SYSVSEM         # System V-like semaphores
+#options       SYSVSHM         # System V-like memory sharing
+#options       SHMMAXPGS=1024  # 1024 pages is the default
+
+# Device options
+
+options                RAMDISK_HOOKS   # boottime setup of ramdisk
+options                RAMDISK_SIZE=0  # Size in KBytes
+options                PLIP            # Build plip device into lpt driver
+
+# Development options
+
+options                DIAGNOSTIC      # internally consistency checks
+options                KTRACE          # system call tracing, a la ktrace(1)
+options                IRQSTATS        # IRQ statistics
+options                POSTMORTEM      # perform postmortem on panic
+#options               ROTTEN_INNARDS  # show the gory bit of the postmortem
+options                KSHELL          # kernel developemnt shell (debug)
+options                LKM             # loadable kernel modules
+#options       DEBUGTERM       # create a debug console
+#options       KGDB            # remote kernel debugging
+options                DDB             # in-kernel debugger
+#makeoptions   DEBUG="-g"      # compile full symbol table
+
+config         netbsd  swap generic
+options                GENERIC
+
+# The main bus device
+mainbus0 at root
+
+# The boot cpu
+cpu0 at mainbus?
+
+# The hydra multiprocessor device
+#hydrabus0 at mainbus?
+
+#cpu1 at hydrabus?
+#cpu2 at hydrabus?
+#cpu3 at hydrabus?
+#cpu4 at hydrabus?
+
+# The vidc
+vidcvideo0     at mainbus?
+
+# generic VT console device
+vt0     at mainbus?
+vt1     at mainbus?
+vt2     at mainbus?
+vt3     at mainbus?
+vt4     at mainbus?
+vt5     at mainbus?
+
+# IDE disk controller
+wdc0    at mainbus? base 0x002107c0 irq 9
+wd0     at wdc? drive ?
+wd1     at wdc? drive ?
+
+# Floppy disk controller
+fdc0    at mainbus? base 0x00210fc0 irq 12 dack 0x00002000
+fd0     at fdc? drive ?
+
+# kbd via IOMD
+kbd0   at mainbus? base 0x00000000
+
+# quadrature mouse
+quadmouse0     at mainbus? base 0x00000000
+
+# Serial ports
+com0    at mainbus? base 0x00210fe0 irq 10
+#com1    at mainbus? base 0x00210be0
+
+# Parallel ports
+lpt0    at mainbus? base 0x002109e0 irq 0
+
+# Crude sound device
+beep0  at mainbus? base 0x00000000
+
+# IIC bus device
+iic0   at mainbus?
+
+# RTC device
+rtc0   at iic? addr 0xa0
+
+# Podule bus device
+podulebus0     at root
+
+#asc0  at podulebus?                   # Acorn SCSI card
+#scsibus* at asc?
+
+#csc0  at podulebus?                   # Cumana SCSI II card
+#scsibus* at csc?
+
+ptsc0  at podulebus?                   # Power-Tec SCSI II card
+scsibus* at ptsc?
+
+#oak0  at podulebus?                   # Oak SCSI I card
+#scsibus* at oak?
+
+sd*    at scsibus? target ? lun ?      # SCSI disk drives
+st*    at scsibus? target ? lun ?      # SCSI tape drives
+cd*    at scsibus? target ? lun ?      # SCSI CD-ROM drives
+ch*    at scsibus? target ? lun ?      # SCSI auto-changers
+uk*    at scsibus? target ? lun ?      # SCSI unknown device
+
+#kie*  at podulebus? slot ? offset ?
+
+#ea0   at podulebus?                   # Ether3 podules
+eb0    at podulebus?                   # EtherB network slot cards
+#eh0   at podulebus?                   # EtherH network slot cards
+#ie0   at podulebus?                   # Ether1 podules
+
+pseudo-device  loop    1               # network loopback
+pseudo-device   bpfilter 8              # packet filter
+pseudo-device  sl      2               # CSLIP
+pseudo-device  ppp     2               # PPP
+pseudo-device  tun     2               # network tunneling over tty
+
+pseudo-device   pty     32              # pseudo-terminals
+pseudo-device  tb      1               # tablet line discipline
+pseudo-device   vnd     4               # paging to files
+pseudo-device  ccd     2               # concatenated disk devices
+
+pseudo-device  rd      1               # Ramdisk driver
+
+makeoptions MONITOR="Taxan875+LR"
+#makeoptions MONITOR="AKF60"
+makeoptions MODES="1024,768,60 1024,768,70 800,600,60 640,480,60 1280,1024 1152,900"
diff --git a/sys/arch/arm32/conf/REMY b/sys/arch/arm32/conf/REMY
new file mode 100644 (file)
index 0000000..f0f15ca
--- /dev/null
@@ -0,0 +1,329 @@
+#
+#      REMY -- Scott's development machine
+#
+
+include        "std.arm32"
+
+# estimated number of users
+
+maxusers       8
+
+# Standard system options
+
+options                TIMEZONE=0      # time zone to adjust RTC time by
+options                DST=0           # daylight savings time used by RTC
+options                SWAPPAGER       # paging; REQUIRED
+options                VNODEPAGER      # mmap() of files
+options                DEVPAGER        # mmap() of devices
+
+# CPU options
+
+options                CPU_ARM6
+options                CPU_LATE_ABORT  # ARM7XX compatibility
+
+# FPA options
+
+options                FPE             # Single precision FPE
+options                ARMFPE          # ARM Ltd FPE
+
+# File system options
+
+options                FFS             # UFS
+#options               QUOTA           # UFS quotas
+#options               LFS             # log-structured file system
+#options               MFS             # memory file system
+
+options                CD9660          # ISO 9660 + Rock Ridge file system
+options                MSDOSFS         # MS-DOS file system
+options                FDESC           # /dev/fd
+options                FIFO            # FIFOs; RECOMMENDED
+options                KERNFS          # /kern
+#options               NULLFS          # loopback file system
+#options               PORTAL          # ?
+options                PROCFS          # /proc
+#options               UMAPFS          # NULLFS + uid and gid remapping
+options                UNION           # union file system
+
+# Networking options
+
+options                NFSCLIENT
+options                NFSSERVER
+#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
+
+# Compatibility options
+
+options                COMPAT_43
+options                COMPAT_10
+options                COMPAT_09
+options         TCP_COMPAT_42   # TCP bug compatibility with 4.2BSD
+
+# Shared memory options
+
+#options       SYSVMSG         # System V-like message queues
+#options       SYSVSEM         # System V-like semaphores
+#options       SYSVSHM         # System V-like memory sharing
+#options       SHMMAXPGS=1024  # 1024 pages is the default
+
+# Device options
+
+options                RAMDISK_HOOKS   # boottime setup of ramdisk
+options                RAMDISK_SIZE=0  # Size in KBytes
+options                PLIP            # Build plip device into lpt driver
+
+# Development options
+
+options                DIAGNOSTIC      # internally consistency checks
+options                KTRACE          # system call tracing, a la ktrace(1)
+options                IRQSTATS        # IRQ statistics
+options                POSTMORTEM      # perform postmortem on panic
+#options               ROTTEN_INNARDS  # show the gory bit of the postmortem
+options                KSHELL          # kernel developemnt shell (debug)
+options                LKM             # loadable kernel modules
+#options       DEBUGTERM       # create a debug console
+#options       KGDB            # remote kernel debugging
+#options       DDB             # in-kernel debugger
+#makeoptions   DEBUG="-g"      # compile full symbol table
+
+config         netbsd  swap generic
+options                GENERIC
+
+# The main bus device
+mainbus0 at root
+
+# The boot cpu
+cpu0 at mainbus?
+
+# The vidc
+vidcvideo0     at mainbus?
+
+# generic VT console device
+vt0     at mainbus?
+vt1     at mainbus?
+vt2     at mainbus?
+vt3     at mainbus?
+vt4     at mainbus?
+vt5     at mainbus?
+
+# IDE disk controller
+wdc0    at mainbus? base 0x002107c0 irq 9
+wd0     at wdc? drive ?
+wd1     at wdc? drive ?
+
+# Floppy disk controller
+fdc0    at mainbus? base 0x00210fc0 irq 12 dack 0x00002000
+fd0     at fdc? drive ?
+
+# kbd via IOMD
+kbd0   at mainbus? base 0x00000000
+
+# quadrature mouse
+quadmouse0     at mainbus? base 0x00000000
+
+# Serial ports
+com0    at mainbus? base 0x00210fe0 irq 10
+#com1    at mainbus? base 0x00210be0
+
+# Parallel ports
+lpt0    at mainbus? base 0x002109e0 irq 0
+
+# Crude sound device
+beep0  at mainbus? base 0x00000000
+
+# IIC bus device
+iic0   at mainbus?
+
+# RTC device
+rtc0   at iic? addr 0xa0
+
+# Podule bus device
+podulebus0     at root
+
+sd*    at scsibus? target ? lun ?      # SCSI disk drives
+st*    at scsibus? target ? lun ?      # SCSI tape drives
+cd*    at scsibus? target ? lun ?      # SCSI CD-ROM drives
+ch*    at scsibus? target ? lun ?      # SCSI auto-changers
+uk*    at scsibus? target ? lun ?      # SCSI unknown device
+
+asc0   at podulebus0   slot 0          # Acorn SCSI card
+asc1   at podulebus0   slot 1          # Acorn SCSI card
+asc2   at podulebus0   slot 2          # Acorn SCSI card
+asc3   at podulebus0   slot 3          # Acorn SCSI card
+csc0   at podulebus0   slot 0          # Cumana SCSI card
+csc1   at podulebus0   slot 1          # Cumana SCSI card
+csc2   at podulebus0   slot 2          # Cumana SCSI card
+csc3   at podulebus0   slot 3          # Cumana SCSI card
+ptsc0  at podulebus0   slot 0          # Power-tec SCSI card
+ptsc1  at podulebus0   slot 1          # Power-tec SCSI card
+ptsc2  at podulebus0   slot 2          # Power-tec SCSI card
+ptsc3  at podulebus0   slot 3          # Power-tec SCSI card
+#oak0  at podulebus0   slot 0          # Oak SCSI card
+#oak1  at podulebus0   slot 1          # Oak SCSI card
+#oak2  at podulebus0   slot 2          # Oak SCSI card
+#oak3  at podulebus0   slot 3          # Oak SCSI card
+
+scsibus0 at asc0
+scsibus1 at asc1
+scsibus2 at asc2
+scsibus3 at asc3
+scsibus0 at csc0
+scsibus1 at csc1
+scsibus2 at csc2
+scsibus3 at csc3
+scsibus0 at ptsc0
+scsibus1 at ptsc1
+scsibus2 at ptsc2
+scsibus3 at ptsc3
+#scsibus0 at oak0
+#scsibus1 at oak1
+#scsibus2 at oak2
+#scsibus3 at oak3
+
+# First SCSI bus
+sd0    at scsibus0 target 0 lun ?      # SCSI disk drive
+sd1    at scsibus0 target 1 lun ?      # SCSI disk drive
+sd2    at scsibus0 target 2 lun ?      # SCSI disk drive
+sd3    at scsibus0 target 3 lun ?      # SCSI disk drive
+sd4    at scsibus0 target 4 lun ?      # SCSI disk drive
+sd5    at scsibus0 target 5 lun ?      # SCSI disk drive
+sd6    at scsibus0 target 6 lun ?      # SCSI disk drive
+st0    at scsibus0 target 0 lun ?      # SCSI tape drive
+st1    at scsibus0 target 1 lun ?      # SCSI tape drive
+st2    at scsibus0 target 2 lun ?      # SCSI tape drive
+st3    at scsibus0 target 3 lun ?      # SCSI tape drive
+st4    at scsibus0 target 4 lun ?      # SCSI tape drive
+st5    at scsibus0 target 5 lun ?      # SCSI tape drive
+st6    at scsibus0 target 6 lun ?      # SCSI tape drive
+cd0    at scsibus0 target 0 lun ?      # SCSI CD-ROM drive
+cd1    at scsibus0 target 1 lun ?      # SCSI CD-ROM drive
+cd2    at scsibus0 target 2 lun ?      # SCSI CD-ROM drive
+cd3    at scsibus0 target 3 lun ?      # SCSI CD-ROM drive
+cd4    at scsibus0 target 4 lun ?      # SCSI CD-ROM drive
+cd5    at scsibus0 target 5 lun ?      # SCSI CD-ROM drive
+cd6    at scsibus0 target 6 lun ?      # SCSI CD-ROM drive
+uk0    at scsibus0 target 0 lun ?      # SCSI Unknown device
+uk1    at scsibus0 target 1 lun ?      # SCSI Unknown device
+uk2    at scsibus0 target 2 lun ?      # SCSI Unknown device
+uk3    at scsibus0 target 3 lun ?      # SCSI Unknown device
+uk4    at scsibus0 target 4 lun ?      # SCSI Unknown device
+uk5    at scsibus0 target 5 lun ?      # SCSI Unknown device
+uk6    at scsibus0 target 6 lun ?      # SCSI Unknown device
+
+# Second SCSI bus
+sd8    at scsibus1 target 0 lun ?      # SCSI disk drive
+sd9    at scsibus1 target 1 lun ?      # SCSI disk drive
+sd10   at scsibus1 target 2 lun ?      # SCSI disk drive
+sd11   at scsibus1 target 3 lun ?      # SCSI disk drive
+sd12   at scsibus1 target 4 lun ?      # SCSI disk drive
+sd13   at scsibus1 target 5 lun ?      # SCSI disk drive
+sd14   at scsibus1 target 6 lun ?      # SCSI disk drive
+st8    at scsibus1 target 0 lun ?      # SCSI tape drive
+st9    at scsibus1 target 1 lun ?      # SCSI tape drive
+st10   at scsibus1 target 2 lun ?      # SCSI tape drive
+st11   at scsibus1 target 3 lun ?      # SCSI tape drive
+st12   at scsibus1 target 4 lun ?      # SCSI tape drive
+st13   at scsibus1 target 5 lun ?      # SCSI tape drive
+st14   at scsibus1 target 6 lun ?      # SCSI tape drive
+cd8    at scsibus1 target 0 lun ?      # SCSI CD-ROM drive
+cd9    at scsibus1 target 1 lun ?      # SCSI CD-ROM drive
+cd10   at scsibus1 target 2 lun ?      # SCSI CD-ROM drive
+cd11   at scsibus1 target 3 lun ?      # SCSI CD-ROM drive
+cd12   at scsibus1 target 4 lun ?      # SCSI CD-ROM drive
+cd13   at scsibus1 target 5 lun ?      # SCSI CD-ROM drive
+cd14   at scsibus1 target 6 lun ?      # SCSI CD-ROM drive
+uk8    at scsibus1 target 0 lun ?      # SCSI Unknown device
+uk9    at scsibus1 target 1 lun ?      # SCSI Unknown device
+uk10   at scsibus1 target 2 lun ?      # SCSI Unknown device
+uk11   at scsibus1 target 3 lun ?      # SCSI Unknown device
+uk12   at scsibus1 target 4 lun ?      # SCSI Unknown device
+uk13   at scsibus1 target 5 lun ?      # SCSI Unknown device
+uk14   at scsibus1 target 6 lun ?      # SCSI Unknown device
+
+# Third SCSI bus
+sd16   at scsibus2 target 0 lun ?      # SCSI disk drive
+sd17   at scsibus2 target 1 lun ?      # SCSI disk drive
+sd18   at scsibus2 target 2 lun ?      # SCSI disk drive
+sd19   at scsibus2 target 3 lun ?      # SCSI disk drive
+sd20   at scsibus2 target 4 lun ?      # SCSI disk drive
+sd21   at scsibus2 target 5 lun ?      # SCSI disk drive
+sd22   at scsibus2 target 6 lun ?      # SCSI disk drive
+st16   at scsibus2 target 0 lun ?      # SCSI tape drive
+st17   at scsibus2 target 1 lun ?      # SCSI tape drive
+st18   at scsibus2 target 2 lun ?      # SCSI tape drive
+st19   at scsibus2 target 3 lun ?      # SCSI tape drive
+st20   at scsibus2 target 4 lun ?      # SCSI tape drive
+st21   at scsibus2 target 5 lun ?      # SCSI tape drive
+st22   at scsibus2 target 6 lun ?      # SCSI tape drive
+cd16   at scsibus2 target 0 lun ?      # SCSI CD-ROM drive
+cd17   at scsibus2 target 1 lun ?      # SCSI CD-ROM drive
+cd18   at scsibus2 target 2 lun ?      # SCSI CD-ROM drive
+cd19   at scsibus2 target 3 lun ?      # SCSI CD-ROM drive
+cd20   at scsibus2 target 4 lun ?      # SCSI CD-ROM drive
+cd21   at scsibus2 target 5 lun ?      # SCSI CD-ROM drive
+cd22   at scsibus2 target 6 lun ?      # SCSI CD-ROM drive
+uk16   at scsibus2 target 0 lun ?      # SCSI Unknown device
+uk17   at scsibus2 target 1 lun ?      # SCSI Unknown device
+uk18   at scsibus2 target 2 lun ?      # SCSI Unknown device
+uk19   at scsibus2 target 3 lun ?      # SCSI Unknown device
+uk20   at scsibus2 target 4 lun ?      # SCSI Unknown device
+uk21   at scsibus2 target 5 lun ?      # SCSI Unknown device
+uk22   at scsibus2 target 6 lun ?      # SCSI Unknown device
+
+# Fourth SCSI bus
+sd24   at scsibus3 target 0 lun ?      # SCSI disk drive
+sd25   at scsibus3 target 1 lun ?      # SCSI disk drive
+sd26   at scsibus3 target 2 lun ?      # SCSI disk drive
+sd27   at scsibus3 target 3 lun ?      # SCSI disk drive
+sd28   at scsibus3 target 4 lun ?      # SCSI disk drive
+sd29   at scsibus3 target 5 lun ?      # SCSI disk drive
+sd30   at scsibus3 target 6 lun ?      # SCSI disk drive
+st24   at scsibus3 target 0 lun ?      # SCSI tape drive
+st25   at scsibus3 target 1 lun ?      # SCSI tape drive
+st26   at scsibus3 target 2 lun ?      # SCSI tape drive
+st27   at scsibus3 target 3 lun ?      # SCSI tape drive
+st28   at scsibus3 target 4 lun ?      # SCSI tape drive
+st29   at scsibus3 target 5 lun ?      # SCSI tape drive
+st30   at scsibus3 target 6 lun ?      # SCSI tape drive
+cd24   at scsibus3 target 0 lun ?      # SCSI CD-ROM drive
+cd25   at scsibus3 target 1 lun ?      # SCSI CD-ROM drive
+cd26   at scsibus3 target 2 lun ?      # SCSI CD-ROM drive
+cd27   at scsibus3 target 3 lun ?      # SCSI CD-ROM drive
+cd28   at scsibus3 target 4 lun ?      # SCSI CD-ROM drive
+cd29   at scsibus3 target 5 lun ?      # SCSI CD-ROM drive
+cd30   at scsibus3 target 6 lun ?      # SCSI CD-ROM drive
+uk24   at scsibus3 target 0 lun ?      # SCSI Unknown device
+uk25   at scsibus3 target 1 lun ?      # SCSI Unknown device
+uk26   at scsibus3 target 2 lun ?      # SCSI Unknown device
+uk27   at scsibus3 target 3 lun ?      # SCSI Unknown device
+uk28   at scsibus3 target 4 lun ?      # SCSI Unknown device
+uk29   at scsibus3 target 5 lun ?      # SCSI Unknown device
+uk30   at scsibus3 target 6 lun ?      # SCSI Unknown device
+
+ch*    at scsibus? target ? lun ?      # SCSI auto-changers
+
+#kie*  at podulebus? slot ? offset ?
+
+#ea0   at podulebus?                   # Ether3 podules
+#eb0   at podulebus?                   # EtherB network slot cards
+#eh0   at podulebus?                   # EtherH network slot cards
+#ie0   at podulebus?                   # Ether1 podules
+
+pseudo-device  loop    1               # network loopback
+pseudo-device   bpfilter 8              # packet filter
+pseudo-device  sl      2               # CSLIP
+pseudo-device  ppp     2               # PPP
+pseudo-device  tun     2               # network tunneling over tty
+
+pseudo-device   pty     32              # pseudo-terminals
+pseudo-device  tb      1               # tablet line discipline
+pseudo-device   vnd     4               # paging to files
+pseudo-device  ccd     2               # concatenated disk devices
+
+pseudo-device  rd      1               # Ramdisk driver
+
+makeoptions MONITOR="AKF85"
+makeoptions MODES="1280,1024 1024,768,60 1024,768,70 800,600,60 640,480,60 1152,900"
diff --git a/sys/arch/arm32/conf/VOYAGER b/sys/arch/arm32/conf/VOYAGER
new file mode 100644 (file)
index 0000000..00cf429
--- /dev/null
@@ -0,0 +1,197 @@
+#
+#      VOYAGER -- Mark's master development machine
+#
+
+include        "std.arm32"
+
+# estimated number of users
+
+maxusers       32
+
+# Standard system options
+
+options                TIMEZONE=0      # time zone to adjust RTC time by
+options                DST=0           # daylight savings time used by RTC
+options                SWAPPAGER       # paging; REQUIRED
+options                VNODEPAGER      # mmap() of files
+options                DEVPAGER        # mmap() of devices
+
+# CPU options
+
+options                CPU_ARM6
+options                CPU_LATE_ABORT  # ARM7XX compatibility
+
+# FPA options
+
+#options               FPE             # Single precision FPE
+options                ARMFPE          # ARM Ltd FPE
+
+# File system options
+
+options                FFS             # UFS
+#options       QUOTA           # UFS quotas
+#options       LFS             # log-structured file system
+options                MFS             # memory file system
+
+options                CD9660          # ISO 9660 + Rock Ridge file system
+options                MSDOSFS         # MS-DOS file system
+options                FDESC           # /dev/fd
+options                FIFO            # FIFOs; RECOMMENDED
+options                KERNFS          # /kern
+options                NULLFS          # loopback file system
+#options       PORTAL          # ?
+options                PROCFS          # /proc
+#options       UMAPFS          # NULLFS + uid and gid remapping
+options                UNION           # union file system
+
+# Networking options
+
+options                NFSCLIENT
+options                NFSSERVER
+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
+
+# Compatibility options
+
+options                COMPAT_43
+options                COMPAT_10
+options                COMPAT_09
+options         TCP_COMPAT_42   # TCP bug compatibility with 4.2BSD
+
+# Shared memory options
+
+#options       SYSVMSG         # System V-like message queues
+#options       SYSVSEM         # System V-like semaphores
+#options       SYSVSHM         # System V-like memory sharing
+#options       SHMMAXPGS=1024  # 1024 pages is the default
+
+# Device options
+
+options                RAMDISK_HOOKS   # boottime setup of ramdisk
+options                RAMDISK_SIZE=0  # Size in KBytes
+options                PLIP            # Build plip device into lpt driver
+
+# Development options
+
+options                DIAGNOSTIC      # internally consistency checks
+options                KTRACE          # system call tracing, a la ktrace(1)
+options                IRQSTATS        # IRQ statistics
+options                POSTMORTEM      # perform postmortem on panic
+#options       ROTTEN_INNARDS  # show the gory bit of the postmortem
+options                KSHELL          # kernel developemnt shell (debug)
+options                LKM             # loadable kernel modules
+#options       DEBUGTERM       # create a debug console
+#options       KGDB            # remote kernel debugging
+options                DDB             # in-kernel debugger
+#makeoptions   DEBUG="-g"      # compile full symbol table
+
+config         netbsd  swap generic
+options                GENERIC
+
+# The main bus device
+mainbus0 at root
+
+# The boot cpu
+cpu0 at mainbus?
+
+# The hydra multiprocessor device
+hydrabus0 at mainbus?
+
+#cpu1 at hydrabus?
+#cpu2 at hydrabus?
+#cpu3 at hydrabus?
+#cpu4 at hydrabus?
+
+# The vidc
+vidcvideo0     at mainbus?
+
+# generic VT console device
+vt0     at mainbus?
+vt1     at mainbus?
+vt2     at mainbus?
+vt3     at mainbus?
+vt4     at mainbus?
+vt5     at mainbus?
+
+# IDE disk controller
+wdc0    at mainbus? base 0x002107c0 irq 9
+wd*     at wdc? drive ?
+
+# Floppy disk controller
+fdc0    at mainbus? base 0x00210fc0 irq 12 dack 0x00002000
+fd0     at fdc? drive ?
+
+# kbd via IOMD
+kbd0   at mainbus? base 0x00000000
+
+# quadrature mouse
+quadmouse0     at mainbus? base 0x00000000
+
+# PS2 mouse
+pms0   at mainbus? base 0x00000000
+
+# Serial ports
+com0    at mainbus? base 0x00210fe0 irq 10
+#com1    at mainbus? base 0x00210be0
+
+# Parallel ports
+lpt0    at mainbus? base 0x002109e0 irq 0
+
+# Crude sound device
+beep0  at mainbus? base 0x00000000
+
+# IIC bus device
+iic0   at mainbus?
+
+# RTC device
+rtc0   at iic? addr 0xa0
+
+# Podule bus device
+podulebus0     at root
+
+asc0   at podulebus?                   # Acorn SCSI card
+scsibus* at asc?
+
+csc0   at podulebus?                   # Cumana SCSI II card
+scsibus* at csc?
+
+ptsc0  at podulebus?                   # Power-Tec SCSI II card
+scsibus* at ptsc?
+
+oak0   at podulebus?                   # Oak SCSI I card
+scsibus* at oak?
+
+sd*    at scsibus? target ? lun ?      # SCSI disk drives
+st*    at scsibus? target ? lun ?      # SCSI tape drives
+cd*    at scsibus? target ? lun ?      # SCSI CD-ROM drives
+ch*    at scsibus? target ? lun ?      # SCSI auto-changers
+uk*    at scsibus? target ? lun ?      # SCSI unknown device
+ss*    at scsibus? target ? lun ?      # SCSI scanner
+
+#kie*  at podulebus? slot ? offset ?
+
+ea0    at podulebus?                   # Ether3 podules
+eb0    at podulebus?                   # EtherB network slot cards
+eh0    at podulebus?                   # EtherH network slot cards
+ie0    at podulebus?                   # Ether1 podules
+
+pseudo-device  loop    1               # network loopback
+pseudo-device   bpfilter 8              # packet filter
+pseudo-device  sl      2               # CSLIP
+pseudo-device  ppp     2               # PPP
+pseudo-device  tun     2               # network tunneling over tty
+
+pseudo-device   pty     32              # pseudo-terminals
+pseudo-device  tb      1               # tablet line discipline
+pseudo-device   vnd     4               # paging to files
+pseudo-device  ccd     2               # concatenated disk devices
+
+pseudo-device  rd      1               # Ramdisk device
+
+makeoptions MONITOR="Taxan875+LR"
+#makeoptions MONITOR="AKF60"
+makeoptions MODES="1024,768,60 1024,768,70 800,600,60 640,480,60 1280,1024 1152,900"
diff --git a/sys/arch/arm32/conf/files.arm32 b/sys/arch/arm32/conf/files.arm32
new file mode 100644 (file)
index 0000000..ac8d54f
--- /dev/null
@@ -0,0 +1,271 @@
+#
+# First try for arm-specific configuration info
+#
+
+maxpartitions  8
+maxusers 2 8 64
+
+device mainbus { [base = -1], [dack = -1], [irq = -1] }
+attach mainbus at root
+file   arch/arm32/mainbus/mainbus.c            mainbus
+
+device hydrabus { [slot = -1] }
+attach hydrabus at mainbus
+file   arch/arm32/mainbus/exp/hydra.c                  hydrabus needs-flag
+file   arch/arm32/mainbus/exp/hydraboot.S              hydrabus
+
+device cpu
+attach cpu at mainbus, hydrabus
+file   arch/arm32/mainbus/cpu.c                        cpu needs-flag
+major  {cpu = 38}
+
+#Standard NetBSD wd driver
+device  wdc {drive = -1}
+attach wdc at mainbus
+device  wd: disk
+attach wd at wdc
+file    arch/arm32/mainbus/wd.c                        wdc needs-flag
+major   {wd = 16}
+
+#Hacked NetBSD wd driver with cd and atapi support - nasty hack atm
+#device  wdc {drive = -1}
+#attach  wdc at mainbus
+#device  wd: disk
+#attach  wd at wdc
+#file    arch/arm32/mainbus/exp/wd.c           wdc needs-flag
+#major   {wd = 16}
+
+device  atapi: disk
+attach atapi at mainbus
+file    arch/arm32/mainbus/exp/atapi.c         atapi needs-flag
+
+device  wcd: disk
+attach wcd at mainbus
+file    arch/arm32/mainbus/exp/wcd.c           wcd needs-flag
+major   {wcd = 20}
+
+#Standard NetBSD fd driver
+device  fdc {drive = -1}
+attach fdc at mainbus
+device  fd: disk
+attach fd at fdc
+file    arch/arm32/mainbus/fd.c                        fdc needs-flag
+major   {fd = 17}
+
+# RAM disk driver
+pseudo-device  rd
+file   dev/ramdisk.c                           rd needs-count
+file   arch/arm32/dev/rd_hooks.c               rd | ramdisk_hooks
+major   {rd = 18}
+
+device  lpt: tty, ether, ifnet
+attach lpt at mainbus
+file    arch/arm32/mainbus/lpt.c               lpt needs-flag
+major   {lpt = 8}
+
+device  com: tty
+attach com at mainbus
+file    arch/arm32/mainbus/com.c               com needs-flag
+major   {com = 12}
+
+# Mouse devices
+device  quadmouse: tty
+attach quadmouse at mainbus
+file    arch/arm32/mainbus/qmouse.c            quadmouse needs-flag
+major   {quadmouse = 9}
+
+device  pms: tty
+attach pms at mainbus
+file    arch/arm32/mainbus/pms.c               pms needs-flag
+major   {pms = 40}
+
+# Audio devices
+device beep
+attach beep at mainbus
+file    arch/arm32/mainbus/beep.c                      beep needs-flag
+major   {beep = 10}
+
+device audio: audio
+attach audio at mainbus
+file   arch/arm32/mainbus/vidcaudio.c          vidcaudio needs-flag
+major   {audio = 36}
+
+device kbd
+attach kbd at mainbus
+file    arch/arm32/mainbus/kbd.c                       kbd needs-flag
+major   {kbd = 11}
+
+# Podule bus device
+device podulebus { [slot = -1] }
+attach podulebus at root
+file   arch/arm32/podulebus/podulebus.c                podulebus
+
+# Ethernet devices
+device ea: ether, ifnet
+attach ea at podulebus
+file   arch/arm32/podulebus/if_ea.c            ea
+
+device eb: ether, ifnet
+attach eb at podulebus
+file   arch/arm32/podulebus/if_eb.c            eb
+
+device eh: ether, ifnet
+attach eh at podulebus
+file   arch/arm32/podulebus/if_eh.c            eh
+
+device ie: ether, ifnet
+attach ie at podulebus
+file   arch/arm32/podulebus/if_ie.c            ie
+
+# IIC/RTC files
+device iic { addr = -1 }
+attach iic at mainbus
+file   arch/arm32/mainbus/iic_asm.S            iic
+file   arch/arm32/mainbus/iic.c                iic     needs-flag
+
+device rtc
+attach rtc at iic
+file   arch/arm32/mainbus/rtc.c                rtc     needs-count
+
+#define        kgdb
+
+#device kie: kgdb
+#attach kie at podule
+#file  arch/arm32/podulebus/kgdb_ie.c          kie
+
+#file  arch/arm32/arm32/kgdb_glue.c                    kgdb
+#file  arch/arm32/arm32/kgdb_step.c                    kgdb
+
+#
+# Machine-independent SCSI drivers
+#
+
+include "../../../scsi/files.scsi"
+major   {sd = 24}
+major   {st = 25}
+major   {cd = 26}
+major   {ch = 27}
+major  {uk = 28}
+major  {ss = 29}
+
+# Generic sbic (WD3393) driver
+define sbic
+file   arch/arm32/podulebus/sbic.c             sbic
+
+# Acorn SCSI I specific layer for sbic
+device  asc: scsi, sbic
+attach asc at podulebus
+file   arch/arm32/podulebus/asc.c              asc
+
+# Generic fas216 + esp216 driver
+define sfas
+file   arch/arm32/podulebus/sfas.c     sfas
+
+# Cumana specific layer for sfas
+device csc: scsi, sfas
+attach csc at podulebus
+file   arch/arm32/podulebus/exp/csc.c  csc
+
+device ptsc: scsi, sfas
+attach ptsc at podulebus
+file   arch/arm32/podulebus/ptsc.c     ptsc
+
+# Generic NCR driver
+define ncr
+file   arch/arm32/podulebus/ncr5380sbc.c       ncr
+
+# Oak specific layer for ncr
+device oak: scsi, ncr
+attach oak at podulebus
+file   arch/arm32/podulebus/oak.c      oak
+
+device  vidcvideo
+attach vidcvideo at mainbus
+major  {vidcvideo = 37}
+device  vt: tty
+attach vt at mainbus
+file    arch/arm32/dev/console/console.c       vt needs-count
+file    arch/arm32/dev/console/vidcconsole.c   vt needs-count
+file   arch/arm32/dev/console/vidc_mc.S        vt needs-count
+file    arch/arm32/dev/console/vidc.c          vt needs-count
+file    arch/arm32/dev/console/vt220.c         vt needs-count
+file   arch/arm32/dev/console/debugconsole.c   vt needs-count
+file   arch/arm32/dev/console/dumb.c           vt needs-count
+
+file   arch/arm32/arm32/autoconf.c
+file   arch/arm32/arm32/blockio.S
+file   arch/arm32/arm32/clock.c
+file   arch/arm32/arm32/conf.c
+file   arch/arm32/arm32/cpuswitch.S
+file   arch/arm32/arm32/disksubr.c             disk
+file   arch/arm32/arm32/stubs.c
+file   arch/arm32/arm32/exception.S
+file   arch/arm32/arm32/syscall.c
+file   arch/arm32/arm32/ast.c
+file   arch/arm32/arm32/fault.c
+file   arch/arm32/arm32/undefined.c
+file   arch/arm32/arm32/mem.c
+file   arch/arm32/arm32/scratch.S
+file   arch/arm32/arm32/process_machdep.c
+file   arch/arm32/arm32/machdep.c
+file   arch/arm32/arm32/sys_machdep.c
+file   arch/arm32/arm32/vm_machdep.c
+file   arch/arm32/arm32/pmap.c
+file   arch/arm32/arm32/fusu.c
+
+file   netinet/in_cksum.c              inet
+file   netns/ns_cksum.c                ns
+
+# IRQ/FIQ files
+file   arch/arm32/arm32/spl.S
+file   arch/arm32/arm32/irq.S
+file   arch/arm32/arm32/irqhandler.c
+file   arch/arm32/arm32/fiq.S
+
+# library functions
+file   arch/arm32/arm32/strstr.c
+file   arch/arm32/arm32/strtoul.c
+file   arch/arm32/arm32/memset.S
+file   arch/arm32/arm32/bcopy_page.S
+file   arch/arm32/arm32/bcopy.S
+file   arch/arm32/arm32/bcopyinout.S
+file   arch/arm32/arm32/copystr.S
+file   arch/arm32/arm32/coproc15.S
+file   arch/arm32/arm32/setcpsr.S
+file   arch/arm32/arm32/setstack.S
+
+# files related to the shell
+file   arch/arm32/kshell/shell_input.c         kshell
+file   arch/arm32/kshell/shell_shell.c         kshell
+file   arch/arm32/kshell/shell_disassem.c      kshell
+file   arch/arm32/kshell/strchr.c              kshell
+file   arch/arm32/kshell/dumphex.c             kshell
+
+# files related to debugging
+file   arch/arm32/arm32/debug.c
+file   arch/arm32/arm32/disassem.c
+file   arch/arm32/arm32/postmortem.c
+file    dev/cons.c
+file   dev/cninit.c
+
+# Signal precision FPE
+file   arch/arm32/fpe-sp/fpe.c                 fpe
+file   arch/arm32/fpe-sp/fpeadd.S              fpe
+file   arch/arm32/fpe-sp/fpesub.S              fpe
+file   arch/arm32/fpe-sp/fpemul.S              fpe
+file   arch/arm32/fpe-sp/fpediv.S              fpe
+file   arch/arm32/fpe-sp/fpefix.S              fpe
+file   arch/arm32/fpe-sp/fpecmf.S              fpe
+file   arch/arm32/fpe-sp/fpetoe.S              fpe
+
+# ARM FPE
+file   arch/arm32/fpe-arm/armfpe_glue.S        armfpe
+file   arch/arm32/fpe-arm/armfpe_init.c        armfpe
+file   arch/arm32/fpe-arm/armfpe.s             armfpe
+
+# DDB
+file   arch/arm32/arm32/db_disasm.c            ddb
+file   arch/arm32/arm32/db_interface.c         ddb
+file   arch/arm32/arm32/db_trace.c             ddb
+file   arch/arm32/arm32/db_machdep.c           ddb
diff --git a/sys/arch/arm32/conf/monitors/AKF60 b/sys/arch/arm32/conf/monitors/AKF60
new file mode 100644 (file)
index 0000000..a420a66
--- /dev/null
@@ -0,0 +1,360 @@
+# Modefile written by !MakeModes version 0.19 (22-Aug-1994)
+# Monitor description file for Acorn AKF60 monitor
+# Line rate: 30 - 50 kHz
+
+file_format:1
+monitor_title:Acorn AKF60
+DPMS_state:1
+
+# Letterbox modes
+
+# 240 x 352 (70Hz)
+startmode
+mode_name:
+x_res:240
+y_res:352
+pixel_rate:9440
+h_timings:18,16,8,240,8,10
+v_timings:2,58,0,352,0,37
+sync_pol:2
+endmode
+
+# 320 x 250 (70Hz - Modes 6,7)
+# Low band
+startmode
+mode_name:
+x_res:320
+y_res:250
+pixel_rate:12587
+h_timings:36,14,12,320,12,6
+v_timings:2,109,0,250,0,88
+sync_pol:2
+endmode
+
+# 320 x 256 (70Hz - Modes 1,2,5,9,10,13)
+# Low band
+startmode
+mode_name:
+x_res:320
+y_res:256
+pixel_rate:12587
+h_timings:36,14,12,320,12,6
+v_timings:2,106,0,256,0,85
+sync_pol:2
+endmode
+
+# 384 x 288 (70Hz)
+# Low band
+startmode
+mode_name:
+x_res:384
+y_res:288
+pixel_rate:18881
+h_timings:64,16,66,384,66,4
+v_timings:2,58,32,288,32,37
+sync_pol:2
+endmode
+
+# 480 x 352 (70Hz)
+# Low band
+startmode
+mode_name:480 x 352
+x_res:480
+y_res:352
+pixel_rate:18881
+h_timings:64,16,18,480,18,4
+v_timings:2,58,0,352,0,37
+sync_pol:2
+endmode
+
+# 640 x 200 (70Hz - Modes 44,45,46)
+# Low band
+startmode
+mode_name:
+x_res:640
+y_res:200
+pixel_rate:25175
+h_timings:88,22,22,640,22,6
+v_timings:2,134,0,200,0,113
+sync_pol:2
+endmode
+
+# 640 x 250 (70Hz - Modes 3,11,14)
+# Low band
+startmode
+mode_name:
+x_res:640
+y_res:250
+pixel_rate:25175
+h_timings:88,22,22,640,22,6
+v_timings:2,109,0,250,0,88
+sync_pol:2
+endmode
+
+# 640 x 256 (70Hz - Modes 0,4,8,12,15)
+# Low band
+startmode
+mode_name:
+x_res:640
+y_res:256
+pixel_rate:25175
+h_timings:88,22,22,640,22,6
+v_timings:2,106,0,256,0,85
+sync_pol:2
+endmode
+
+# 640 x 352 (70Hz - Modes 41,42,43)
+# Low band
+startmode
+mode_name:
+x_res:640
+y_res:352
+pixel_rate:25175
+h_timings:88,22,22,640,22,6
+v_timings:2,58,0,352,0,37
+sync_pol:2
+endmode
+
+# Other modes (some also numbered)
+
+# 320 x 480 (60Hz - Games modes 48,49)
+# Low band
+startmode
+mode_name:
+x_res:320
+y_res:480
+pixel_rate:12587
+h_timings:36,14,12,320,12,6
+v_timings:2,32,0,480,0,11
+sync_pol:3
+endmode
+
+# 320 x 480 (72Hz)
+# Mid band
+startmode
+mode_name:
+x_res:320
+y_res:480
+pixel_rate:15750
+h_timings:28,30,16,320,16,6
+v_timings:3,28,0,480,0,9
+sync_pol:3
+endmode
+
+# 320 x 480 (75Hz)
+# Mid band
+startmode
+mode_name:
+x_res:320
+y_res:480
+pixel_rate:15750
+h_timings:26,34,16,320,16,8
+v_timings:3,16,0,480,0,1
+sync_pol:3
+endmode
+
+# 360 x 480 (60Hz - PCSoft mode 47)
+# Low band
+startmode
+mode_name:
+x_res:360
+y_res:480
+pixel_rate:16783
+h_timings:62,44,16,360,16,34
+v_timings:2,32,0,480,0,11
+sync_pol:3
+endmode
+
+# 640 x 480 (60Hz - Modes 25,26,27,28)
+# Low band
+startmode
+mode_name:640 x 480
+x_res:640
+y_res:480
+pixel_rate:25175
+h_timings:88,22,22,640,22,6
+v_timings:2,32,0,480,0,11
+sync_pol:3
+endmode
+
+# 640 x 480 (72Hz)
+# Mid band
+startmode
+mode_name:640 x 480
+x_res:640
+y_res:480
+pixel_rate:31500
+h_timings:52,64,30,640,30,14
+#    VESA:40,128,0,640,0,24
+v_timings:3,28,0,480,0,9
+sync_pol:3
+endmode
+
+# 640 x 480 (75Hz)
+# Mid band
+startmode
+mode_name:640 x 480
+x_res:640
+y_res:480
+pixel_rate:31500
+h_timings:62,64,30,640,30,14
+#    VESA:64,120,0,640,0,16
+v_timings:3,16,0,480,0,1
+sync_pol:3
+endmode
+
+# 800 x 600 (56Hz - Modes 29,30,31)
+# Mid band
+startmode
+mode_name:800 x 600
+x_res:800
+y_res:600
+pixel_rate:36000
+h_timings:70,74,34,800,34,12
+#    VESA:72,128,0,800,0,24
+v_timings:2,22,0,600,0,1
+sync_pol:0
+endmode
+
+# 800 x 600 (60Hz)
+# Mid band
+startmode
+mode_name:800 x 600
+x_res:800
+y_res:600
+pixel_rate:40000
+h_timings:112,64,40,800,40,0
+#    VESA:128,88, 0,800,0,40
+v_timings:4,23,0,600,0,1
+sync_pol:0
+endmode
+
+# 800 x 600 (72Hz)
+# High band
+startmode
+mode_name:800 x 600
+x_res:800
+y_res:600
+pixel_rate:50000
+h_timings:88,34,42,800,42,34
+#    VESA:120,64, 0,800,0,56
+v_timings:6,23,0,600,0,37
+sync_pol:0
+endmode
+
+# 800 x 600 (75Hz)
+# High band
+startmode
+mode_name:800 x 600
+x_res:800
+y_res:600
+pixel_rate:49500
+h_timings:80,46,42,800,42,46
+#    VESA:80,160,0,800,0,16
+v_timings:3,21,0,600,0,1
+sync_pol:0
+endmode
+
+# 1024 x 768 (60Hz)
+# High band
+startmode
+mode_name:1024 x 768
+x_res:1024
+y_res:768
+pixel_rate:65000
+h_timings:128,36,60,1024,60,36
+#    VESA:136,160,0,1024,0,24
+v_timings:6,29,0,768,0,3
+sync_pol:0
+endmode
+
+# Pixel-doubled modes
+
+# 1280 x 480 (60Hz)
+# Low band
+startmode
+mode_name:1280 x 480
+x_res:1280
+y_res:480
+pixel_rate:50350
+h_timings:176,44,44,1280,44,12
+v_timings:2,32,0,480,0,11
+sync_pol:3
+endmode
+
+# 1280 x 480 (72Hz)
+# Mid band
+startmode
+mode_name:1280 x 480
+x_res:1280
+y_res:480
+pixel_rate:63000
+h_timings:104,128,60,1280,60,28
+#    VESA:80,256,0,1280,0,48
+v_timings:3,28,0,480,0,9
+sync_pol:3
+endmode
+
+# 1280 x 480 (75Hz)
+# Mid band
+startmode
+mode_name:1280 x 480
+x_res:1280
+y_res:480
+pixel_rate:63000
+h_timings:124,128,60,1280,60,28
+#    VESA:128,240,0,1280,0,32
+v_timings:3,16,0,480,0,1
+sync_pol:3
+endmode
+
+# 1600 x 600 (56Hz)
+# Mid band
+startmode
+mode_name:1600 x 600
+x_res:1600
+y_res:600
+pixel_rate:72000
+h_timings:140,148,68,1600,68,24
+v_timings:2,22,0,600,0,1
+sync_pol:0
+endmode
+
+# 1600 x 600 (60Hz)
+# Mid band
+startmode
+mode_name:1600 x 600
+x_res:1600
+y_res:600
+pixel_rate:80000
+h_timings:224,128,80,1600,80,0
+#    VESA:256,176, 0,1600,0,80
+v_timings:4,23,0,600,0,1
+sync_pol:0
+endmode
+
+# 1600 x 600 (72Hz)
+# High band
+startmode
+mode_name:1600 x 600
+x_res:1600
+y_res:600
+pixel_rate:100000
+h_timings:176,68,84,1600,84,68
+#    VESA:240,128, 0,1600,0,112
+v_timings:6,23,0,600,0,37
+sync_pol:0
+endmode
+
+# 1600 x 600 (75Hz)
+# High band
+startmode
+mode_name:1600 x 600
+x_res:1600
+y_res:600
+pixel_rate:99000
+h_timings:160,92,84,1600,84,92
+#    VESA:160,320,0,1600,0,32
+v_timings:3,21,0,600,0,1
+sync_pol:0
+endmode
diff --git a/sys/arch/arm32/conf/monitors/AKF85 b/sys/arch/arm32/conf/monitors/AKF85
new file mode 100644 (file)
index 0000000..7813bf9
--- /dev/null
@@ -0,0 +1,397 @@
+# Modefile written by !MakeModes version 0.19 (22-Aug-1994)
+# Monitor description file for Acorn AKF85 monitor
+# Line rate: 30 - 82 kHz
+# Frame rate: 50 - 120 Hz
+# Dot rate: Up to 135 MHz
+
+
+file_format:1
+monitor_title:Acorn AKF85
+DPMS_state:0
+
+# 240 x 352 (70Hz)
+startmode
+mode_name:
+x_res:240
+y_res:352
+pixel_rate:9440
+h_timings:20,16,8,240,8,8
+v_timings:2,58,0,352,0,37
+sync_pol:2
+endmode
+
+# 320 x 250 (70Hz)
+startmode
+mode_name:
+x_res:320
+y_res:250
+pixel_rate:12587
+h_timings:42,14,12,320,12,0
+v_timings:2,109,0,250,0,88
+sync_pol:2
+endmode
+
+# 320 x 256 (70Hz)
+startmode
+mode_name:
+x_res:320
+y_res:256
+pixel_rate:12587
+h_timings:42,14,12,320,12,0
+v_timings:2,106,0,256,0,85
+sync_pol:2
+endmode
+
+# 320 x 480 (60Hz)
+startmode
+mode_name:
+x_res:320
+y_res:480
+pixel_rate:12587
+h_timings:42,14,12,320,12,0
+v_timings:2,32,0,480,0,11
+sync_pol:3
+endmode
+
+# 320 x 480 (73Hz)
+startmode
+mode_name:
+x_res:320
+y_res:480
+pixel_rate:15750
+h_timings:24,40,16,320,16,0
+v_timings:3,28,0,480,0,9
+sync_pol:3
+endmode
+
+# 320 x 480 (75Hz)
+startmode
+mode_name:
+x_res:320
+y_res:480
+pixel_rate:15750
+h_timings:24,44,16,320,16,0
+v_timings:3,16,0,480,0,1
+sync_pol:3
+endmode
+
+# 360 x 480 (60Hz)
+startmode
+mode_name:
+x_res:360
+y_res:480
+pixel_rate:16783
+h_timings:64,46,16,360,16,30
+v_timings:2,32,0,480,0,11
+sync_pol:3
+endmode
+
+# 384 x 288 (70Hz)
+startmode
+mode_name:
+x_res:384
+y_res:288
+pixel_rate:18881
+h_timings:68,16,66,384,66,0
+v_timings:2,58,32,288,32,37
+sync_pol:2
+endmode
+
+# 480 x 352 (70Hz)
+startmode
+mode_name:480 x 352
+x_res:480
+y_res:352
+pixel_rate:18881
+h_timings:68,16,18,480,18,0
+v_timings:2,58,0,352,0,37
+sync_pol:2
+endmode
+
+# 640 x 200 (70Hz)
+startmode
+mode_name:
+x_res:640
+y_res:200
+pixel_rate:25175
+h_timings:92,24,22,640,22,0
+v_timings:2,134,0,200,0,113
+sync_pol:2
+endmode
+
+# 640 x 250 (70Hz)
+startmode
+mode_name:
+x_res:640
+y_res:250
+pixel_rate:25175
+h_timings:92,24,22,640,22,0
+v_timings:2,109,0,250,0,88
+sync_pol:2
+endmode
+
+# 640 x 256 (70Hz)
+startmode
+mode_name:
+x_res:640
+y_res:256
+pixel_rate:25175
+h_timings:92,24,22,640,22,0
+v_timings:2,106,0,256,0,85
+sync_pol:2
+endmode
+
+# 640 x 352 (70Hz)
+startmode
+mode_name:
+x_res:640
+y_res:352
+pixel_rate:25175
+h_timings:92,24,22,640,22,0
+v_timings:2,58,0,352,0,37
+sync_pol:2
+endmode
+
+# 640 x 480 (60Hz)
+startmode
+mode_name:640 x 480
+x_res:640
+y_res:480
+pixel_rate:25175
+h_timings:94,22,22,640,22,0
+v_timings:2,32,0,480,0,11
+sync_pol:3
+endmode
+
+# 640 x 480 (73Hz)
+startmode
+mode_name:640 x 480
+x_res:640
+y_res:480
+pixel_rate:31500
+h_timings:48,84,30,640,30,0
+v_timings:3,28,0,480,0,9
+sync_pol:3
+endmode
+
+# 640 x 480 (75Hz)
+startmode
+mode_name:640 x 480
+x_res:640
+y_res:480
+pixel_rate:31500
+h_timings:64,76,30,640,30,0
+v_timings:3,16,0,480,0,1
+sync_pol:3
+endmode
+
+# 640 x 480 (120Hz)
+startmode
+mode_name:640 x 480
+x_res:640
+y_res:480
+pixel_rate:52600
+h_timings:64,76,30,640,46,18
+v_timings:3,16,0,480,0,1
+sync_pol:3
+endmode
+
+# 800 x 600 (60Hz)
+startmode
+mode_name:800 x 600
+x_res:800
+y_res:600
+pixel_rate:40000
+h_timings:128,48,40,800,40,0
+v_timings:4,23,0,600,0,1
+sync_pol:0
+endmode
+
+# 800 x 600 (75Hz)
+startmode
+mode_name:800 x 600
+x_res:800
+y_res:600
+pixel_rate:49500
+h_timings:80,92,42,800,42,0
+v_timings:3,21,0,600,0,1
+sync_pol:0
+endmode
+
+# 800 x 600 (100Hz)
+startmode
+mode_name:800 x 600
+x_res:800
+y_res:600
+pixel_rate:69350
+h_timings:100,104,0,800,66,42
+v_timings:3,21,0,600,0,1
+sync_pol:0
+endmode
+
+# 1024 x 768 (60Hz)
+startmode
+mode_name:1024 x 768
+x_res:1024
+y_res:768
+pixel_rate:65000
+h_timings:136,64,60,1024,60,0
+v_timings:6,29,0,768,0,3
+sync_pol:0
+endmode
+
+# 1024 x 768 (70Hz)
+startmode
+mode_name:1024 x 768
+x_res:1024
+y_res:768
+pixel_rate:75000
+h_timings:124,36,72,1024,72,0
+v_timings:6,29,0,768,0,3
+sync_pol:0
+endmode
+
+# 1024 x 768 (75Hz)
+startmode
+mode_name:1024 x 768
+x_res:1024
+y_res:768
+pixel_rate:80310
+h_timings:122,86,30,1024,76,0
+v_timings:3,28,0,768,0,1
+sync_pol:0
+endmode
+
+# 1024 x 768 (102Hz)
+startmode
+mode_name:1024 x 768
+x_res:1024
+y_res:768
+pixel_rate:119000
+h_timings:130,96,46,1024,106,50
+v_timings:3,28,0,768,0,1
+sync_pol:0
+endmode
+
+# 1152 x 900 (55Hz)
+startmode
+mode_name:1152 x 900
+x_res:1152
+y_res:900
+pixel_rate:80000
+h_timings:156,40,98,1152,124,0
+v_timings:1,28,0,900,0,3
+sync_pol:0
+endmode
+
+# 1152 x 900 (86Hz)
+startmode
+mode_name:1152 x 900
+x_res:1152
+y_res:900
+pixel_rate:134480
+h_timings:132,70,124,1152,124,70
+v_timings:1,28,0,900,0,3
+sync_pol:0
+endmode
+
+# 1280 x 480 (60Hz)
+startmode
+mode_name:1280 x 480
+x_res:1280
+y_res:480
+pixel_rate:50350
+h_timings:188,44,44,1280,44,0
+v_timings:2,32,0,480,0,11
+sync_pol:3
+endmode
+
+# 1280 x 480 (73Hz)
+startmode
+mode_name:1280 x 480
+x_res:1280
+y_res:480
+pixel_rate:63000
+h_timings:96,172,58,1280,58,0
+v_timings:3,28,0,480,0,9
+sync_pol:3
+endmode
+
+# 1280 x 480 (75Hz)
+startmode
+mode_name:1280 x 480
+x_res:1280
+y_res:480
+pixel_rate:63000
+h_timings:128,156,58,1280,58,0
+v_timings:3,16,0,480,0,1
+sync_pol:3
+endmode
+
+# 1280 x 1024 (76Hz)
+startmode
+mode_name:1280 x 1024
+x_res:1280
+y_res:1024
+pixel_rate:139000
+h_timings:166,90,96,1280,96,0
+v_timings:3,32,0,1024,0,3
+sync_pol:0
+endmode
+
+# 1600 x 600 (56Hz)
+startmode
+mode_name:1600 x 600
+x_res:1600
+y_res:600
+pixel_rate:72000
+h_timings:144,168,68,1600,68,0
+v_timings:2,22,0,600,0,1
+sync_pol:0
+endmode
+
+# 1600 x 600 (60Hz)
+startmode
+mode_name:1600 x 600
+x_res:1600
+y_res:600
+pixel_rate:80000
+h_timings:256,98,78,1600,78,2
+v_timings:4,23,0,600,0,1
+sync_pol:0
+endmode
+
+# 1600 x 600 (72Hz)
+startmode
+mode_name:1600 x 600
+x_res:1600
+y_res:600
+pixel_rate:100000
+h_timings:226,58,84,1600,84,28
+v_timings:6,23,0,600,0,37
+sync_pol:0
+endmode
+
+# 1600 x 600 (75Hz)
+startmode
+mode_name:1600 x 600
+x_res:1600
+y_res:600
+pixel_rate:99000
+h_timings:160,188,82,1600,82,0
+v_timings:3,21,0,600,0,1
+sync_pol:0
+endmode
+
+# 1600 x 1200 (50Hz)
+startmode
+mode_name:1600 x 1200
+x_res:1600
+y_res:1200
+pixel_rate:131000
+h_timings:166,90,96,1600,128,44
+v_timings:3,32,0,1200,0,3
+sync_pol:0
+endmode
+
+# End
diff --git a/sys/arch/arm32/conf/monitors/Taxan875+LR b/sys/arch/arm32/conf/monitors/Taxan875+LR
new file mode 100644 (file)
index 0000000..4a02e25
--- /dev/null
@@ -0,0 +1,412 @@
+# Modefile written by !MakeModes version 0.19 (22-Aug-1994)
+# Monitor description file for Taxan 875+LR monitor
+# Line rate: 30 - 82 kHz
+# Frame rate: 50 - 120 Hz
+# Dot rate: Up to 135 MHz
+
+file_format:1
+monitor_title:Taxan 875+LR
+DPMS_state:0
+
+# Letterbox modes
+
+# 240 x 352 (70Hz)
+startmode
+mode_name:
+x_res:240
+y_res:352
+pixel_rate:9440
+h_timings:20,16,8,240,8,8
+v_timings:2,58,0,352,0,37
+sync_pol:2
+endmode
+
+# 320 x 250 (70Hz - Modes 6,7)
+startmode
+mode_name:
+x_res:320
+y_res:250
+pixel_rate:12587
+h_timings:42,14,12,320,12,0
+v_timings:2,109,0,250,0,88
+sync_pol:2
+endmode
+
+# 320 x 256 (70Hz - Modes 1,2,5,9,10,13)
+startmode
+mode_name:
+x_res:320
+y_res:256
+pixel_rate:12587
+h_timings:42,14,12,320,12,0
+v_timings:2,106,0,256,0,85
+sync_pol:2
+endmode
+
+# 384 x 288 (70Hz)
+startmode
+mode_name:
+x_res:384
+y_res:288
+pixel_rate:18881
+h_timings: 68,16,66,384,66,0
+v_timings: 2,58,32,288,32,37
+sync_pol:2
+endmode
+
+# 480 x 352 (70Hz)
+startmode
+mode_name:480 x 352
+x_res:480
+y_res:352
+pixel_rate:18881
+h_timings: 68,16,18,480,18,0
+v_timings: 2,58,0,352,0,37
+sync_pol:2
+endmode
+
+# 640 x 200 (70Hz - Modes 44,45,46)
+startmode
+mode_name:
+x_res:640
+y_res:200
+pixel_rate:25175
+h_timings:92,24,22,640,22,0
+v_timings:2,134,0,200,0,113
+sync_pol:2
+endmode
+
+# 640 x 250 (70Hz - Modes 3,11,14)
+startmode
+mode_name:
+x_res:640
+y_res:250
+pixel_rate:25175
+h_timings:92,24,22,640,22,0
+v_timings:2,109,0,250,0,88
+sync_pol:2
+endmode
+
+# 640 x 256 (70Hz - Modes 0,4,8,12,15)
+startmode
+mode_name:
+x_res:640
+y_res:256
+pixel_rate:25175
+h_timings:92,24,22,640,22,0
+v_timings:2,106,0,256,0,85
+sync_pol:2
+endmode
+
+# 640 x 352 (70Hz - Modes 41,42,43)
+startmode
+mode_name:
+x_res:640
+y_res:352
+pixel_rate:25175
+h_timings:92,24,22,640,22,0
+v_timings:2,58,0,352,0,37
+sync_pol:2
+endmode
+
+# Other modes (some also numbered)
+
+# 320 x 480 (60Hz - Games modes 48,49)
+startmode
+mode_name:
+x_res:320
+y_res:480
+pixel_rate:12587
+h_timings:42,14,12,320,12,0
+v_timings:2,32,0,480,0,11
+sync_pol:3
+endmode
+
+# 320 x 480 (72Hz)
+startmode
+mode_name:
+x_res:320
+y_res:480
+pixel_rate:15750
+h_timings:24,40,16,320,16,0
+v_timings:3,28,0,480,0,9
+sync_pol:3
+endmode
+
+# 320 x 480 (75Hz)
+startmode
+mode_name:
+x_res:320
+y_res:480
+pixel_rate:15750
+h_timings:24,44,16,320,16,0
+v_timings:3,16,0,480,0,1
+sync_pol:3
+endmode
+
+# 360 x 480 (60Hz - PCSoft mode 47)
+startmode
+mode_name:
+x_res:360
+y_res:480
+pixel_rate:16783
+h_timings:64,46,16,360,16,30
+v_timings:2,32,0,480,0,11
+sync_pol:3
+endmode
+
+# 640 x 480 (60Hz - Modes 25,26,27,28)
+startmode
+mode_name:640 x 480
+x_res:640
+y_res:480
+pixel_rate:25175
+h_timings:94,22,22,640,22,0
+v_timings:2,32,0,480,0,11
+sync_pol:3
+endmode
+
+# 640 x 480 (72Hz)
+startmode
+mode_name:640 x 480
+x_res:640
+y_res:480
+pixel_rate:31500
+h_timings:48,84,30,640,30,0
+#    VESA:40,128,0,640,0,24
+v_timings:3,28,0,480,0,9
+sync_pol:3
+endmode
+
+# 640 x 480 (75Hz)
+startmode
+mode_name:640 x 480
+x_res:640
+y_res:480
+pixel_rate:31500
+h_timings:64,76,30,640,30,0
+#    VESA:64,120,0,640,0,16
+v_timings:3,16,0,480,0,1
+sync_pol:3
+endmode
+
+# 800 x 600 (56Hz - Modes 29,30,31)
+startmode
+mode_name:800 x 600
+x_res:800
+y_res:600
+pixel_rate:36000
+h_timings:72,84,34,800,34,0
+#    VESA:72,128,0,800,0,24
+v_timings:2,22,0,600,0,1
+sync_pol:0
+endmode
+
+# 800 x 600 (60Hz)
+startmode
+mode_name:800 x 600
+x_res:800
+y_res:600
+pixel_rate:40000
+h_timings:128,48,40,800,40,0
+#    VESA:128,88, 0,800,0,40
+v_timings:4,23,0,600,0,1
+sync_pol:0
+endmode
+
+# 800 x 600 (72Hz)
+startmode
+mode_name:800 x 600
+x_res:800
+y_res:600
+pixel_rate:50000
+h_timings:100,42,42,800,42,14
+#    VESA:120,64, 0,800,0,56
+v_timings:6,23,0,600,0,37
+sync_pol:0
+endmode
+
+# Stick with just the 72Hz mode as this is a factory default
+# 800 x 600 (75Hz)
+#startmode
+#mode_name:800 x 600
+#x_res:800
+#y_res:600
+#pixel_rate:49500
+#h_timings:80,92,42,800,42,0
+#    VESA:80,160,0,800,0,16
+#v_timings:3,21,0,600,0,1
+#sync_pol:0
+#endmode
+
+# 1024 x 768 (60Hz)
+startmode
+mode_name:1024 x 768
+x_res:1024
+y_res:768
+pixel_rate:65000
+h_timings:136,64,60,1024,60,0
+#    VESA:136,160,0,1024,0,24
+v_timings:6,29,0,768,0,3
+sync_pol:0
+endmode
+
+# 1024 x 768 (70Hz)
+startmode
+mode_name:1024 x 768
+x_res:1024
+y_res:768
+pixel_rate:75000
+h_timings:124,36,72,1024,72,0
+#    VESA:136,144,0,1024,0,24
+v_timings:6,29,0,768,0,3
+sync_pol:0
+endmode
+
+# this has been removed so that it does not get selected for the 16 colour
+# version. 70Hz 1024x768 is a build in setting, 75Hz ain't !
+# 1024 x 768 (75Hz)
+#startmode
+#mode_name:1024 x 768
+#x_res:1024
+#y_res:768
+#pixel_rate:80310
+#     VESA:78750
+#h_timings:122,86,30,1024,76,0
+#    VESA: 96,176,0,1024,0,16
+#v_timings:3,28,0,768,0,1
+#sync_pol:0
+#endmode
+
+# 1152 x 900 (53Hz)
+startmode
+mode_name:1152 x 900
+x_res:1152
+y_res:900
+pixel_rate:76000
+h_timings:152,64,60,1152,100,0
+v_timings:6,29,0,900,0,3
+sync_pol:3
+endmode
+
+# 1152 x 900 (76Hz)
+startmode
+mode_name:1152 x 900
+x_res:1152
+y_res:900
+pixel_rate:117000
+h_timings:170,96,96,1152,104,12
+v_timings:3,33,0,900,0,3
+sync_pol:3
+endmode
+
+# 1280 x 1024 (60Hz)
+startmode
+mode_name:1280 x 1024
+x_res:1280
+y_res:1024
+pixel_rate:110000
+h_timings:166,90,96,1280,96,0
+#h_timings:128,256,0,1280,0,64
+v_timings:3,32,0,1024,0,3
+sync_pol:0
+endmode
+
+# The taxan has a 70Hz 1280 x 768 build in just got to find it.
+# 1280 x 1024 (70Hz)
+startmode
+mode_name:1280 x 1024
+x_res:1280
+y_res:1024
+pixel_rate:128000
+h_timings:160,88,96,1280,96,0
+#h_timings:166,90,96,1280,96,0
+#h_timings:128,256,0,1280,0,64
+v_timings:3,32,0,1024,0,3
+sync_pol:0
+endmode
+
+# Pixel-doubled modes
+
+# 1280 x 480 (60Hz)
+startmode
+mode_name:1280 x 480
+x_res:1280
+y_res:480
+pixel_rate:50350
+h_timings:188,44,44,1280,44,0
+v_timings:2,32,0,480,0,11
+sync_pol:3
+endmode
+
+# 1280 x 480 (72Hz)
+startmode
+mode_name:1280 x 480
+x_res:1280
+y_res:480
+pixel_rate:63000
+h_timings:96,172,58,1280,58,0
+#    VESA:80,256,0,1280,0,48
+v_timings:3,28,0,480,0,9
+sync_pol:3
+endmode
+
+# 1280 x 480 (75Hz)
+startmode
+mode_name:1280 x 480
+x_res:1280
+y_res:480
+pixel_rate:63000
+h_timings:128,156,58,1280,58,0
+#    VESA:128,240,0,1280,0,32
+v_timings:3,16,0,480,0,1
+sync_pol:3
+endmode
+
+# 1600 x 600 (56Hz)
+startmode
+mode_name:1600 x 600
+x_res:1600
+y_res:600
+pixel_rate:72000
+h_timings:144,168,68,1600,68,0
+v_timings:2,22,0,600,0,1
+sync_pol:0
+endmode
+
+# 1600 x 600 (60Hz)
+startmode
+mode_name:1600 x 600
+x_res:1600
+y_res:600
+pixel_rate:80000
+h_timings:256,98,78,1600,78,2
+#    VESA:256,176, 0,1600,0,80
+v_timings:4,23,0,600,0,1
+sync_pol:0
+endmode
+
+# 1600 x 600 (72Hz)
+startmode
+mode_name:1600 x 600
+x_res:1600
+y_res:600
+pixel_rate:100000
+h_timings:226,58,84,1600,84,28
+#    VESA:240,128, 0,1600,0,112
+v_timings:6,23,0,600,0,37
+sync_pol:0
+endmode
+
+# 1600 x 600 (75Hz)
+startmode
+mode_name:1600 x 600
+x_res:1600
+y_res:600
+pixel_rate:99000
+h_timings:160,188,82,1600,82,0
+#    VESA:160,320,0,1600,0,32
+v_timings:3,21,0,600,0,1
+sync_pol:0
+endmode
+
diff --git a/sys/arch/arm32/conf/std.arm32 b/sys/arch/arm32/conf/std.arm32
new file mode 100644 (file)
index 0000000..053df99
--- /dev/null
@@ -0,0 +1,5 @@
+# standard NetBSD/arm32 options
+
+machine        arm32
+
+options                MACHINE_NONCONTIG       # temporary kludge
diff --git a/sys/arch/arm32/dev/console/console.c b/sys/arch/arm32/dev/console/console.c
new file mode 100644 (file)
index 0000000..6d0b1db
--- /dev/null
@@ -0,0 +1,1219 @@
+/* $NetBSD: console.c,v 1.6 1996/04/19 20:03:37 mark Exp $ */
+
+/*
+ * Copyright (c) 1994-1995 Melvyn Tang-Richardson
+ * Copyright (c) 1994-1995 RiscBSD kernel team
+ * 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 RiscBSD kernel team
+ * 4. The name of the company nor the name of the author may be used to
+ *    endorse or promote products derived from this software without specific
+ *    prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE RISCBSD TEAM ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS 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.
+ *
+ * RiscBSD kernel project
+ *
+ * console.c
+ *
+ * Console functions
+ *
+ * Created      : 17/09/94
+ */
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/conf.h>
+#include <sys/proc.h>
+#include <sys/device.h>
+#include <sys/time.h>
+#include <sys/systm.h>
+#include <sys/errno.h>
+#include <sys/tty.h>
+#include <sys/ioctl.h>
+#include <sys/uio.h>
+#include <sys/malloc.h>
+#include <sys/msgbuf.h>
+#include <sys/user.h>
+#include <sys/sysctl.h>
+#include <sys/syslog.h>
+
+#include <dev/cons.h>
+
+#include <machine/vidc.h>
+#include <machine/vconsole.h>
+#include <machine/katelib.h>
+
+#include "vt.h"
+
+#define CONSOLE_VERSION "[V203C] "
+
+/*
+ * Externals
+ */
+
+extern struct tty *constty;
+extern int debug_flags;
+#define consmap_col(x) (x & 0x3)
+#define CONSMAP_BOLD   8
+#define CONSMAP_ITALIC 16
+
+/*
+ * Local variables (to this file) 
+ */
+
+int locked=0;                  /* Nut - is this really safe ? */
+struct tty *physcon_tty[NVT];
+struct vconsole vconsole_master_store;
+struct vconsole *vconsole_master = &vconsole_master_store;
+struct vconsole *vconsole_current;
+struct vconsole *vconsole_head;
+struct vconsole *vconsole_default;
+struct cfdriver rpc_cd;
+extern struct vconsole *debug_vc;      /* rename this to vconsole_debug */
+int physcon_major=4;
+static char undefined_string[] = "UNDEFINED";
+int lastconsole;
+static int printing=0;
+static int want_switch=-1;
+
+/*
+ * Prototypes
+ */
+
+int    physcon_switch  __P((u_int /*number*/));
+void   physconstart    __P((struct tty */*tp*/));
+static struct vconsole *vconsole_spawn __P((dev_t , struct vconsole *));
+int    physconparam    __P((struct tty */*tp*/, struct termios */*t*/));
+void   consinit        __P((void));
+int    physcon_switchup __P((void));
+int    physcon_switchdown      __P((void));
+
+/*
+ * Exported variables
+ */
+
+#define BLANKINIT      (10*60*60)
+int vconsole_pending=0;
+int vconsole_blankinit=BLANKINIT;
+int vconsole_blankcounter=BLANKINIT;
+
+/*
+ * Now list all my render engines and terminal emulators
+ */
+
+extern struct render_engine vidcconsole;
+extern struct terminal_emulator vt220;
+
+/*
+ * These find functions should move the console it finds to the top of
+ * the list to achieve a caching type of operation.  A doubly
+ * linked list would be faster methinks. 
+ */
+
+struct tty *
+find_tp(dev)
+       dev_t dev;
+{
+       struct vconsole *vc;
+       struct vconsole *last=0;
+       int unit = minor (dev);
+       int s;
+
+       s = spltty();
+       for (vc=vconsole_head; vc != NULL; vc=vc->next) {
+               if (vc->number==unit) {
+                       if (vc != vconsole_head) {
+                               last->next = vc->next;
+                               vc->next = vconsole_head;
+                               vconsole_head = vc;
+                       }
+                       (void)splx(s);
+                       return vc->tp;
+               }
+               last = vc;
+       }
+       (void)splx(s);
+       return NULL;
+}
+
+struct vconsole *
+find_vc(dev)
+       dev_t dev;
+{
+       struct vconsole *vc;
+       struct vconsole *last=NULL;
+       int unit = minor (dev);
+       int s;
+
+       s = spltty();
+
+       for (vc=vconsole_head; vc!=NULL; vc=vc->next) {
+               if (vc->number==unit) {
+                       if (vc!=vconsole_head) {
+                               last->next = vc->next;
+                               vc->next = vconsole_head;
+                               vconsole_head = vc;
+                       }
+                       (void)splx(s);
+                       return vc;
+               }
+               last=vc;
+       }
+       (void)splx(s);
+       return NULL;
+}
+
+struct tty *console_tty = NULL;
+
+/*
+ * Place a graphics driver under virtual console switching control.
+ */
+
+struct vconsole *
+vconsole_spawn_re(dev, vc)
+       dev_t dev;
+       struct vconsole *vc;
+{
+       struct vconsole *new;
+       register int num = minor(dev);
+
+       MALLOC(new, struct vconsole *, sizeof(struct vconsole),
+           M_DEVBUF,M_NOWAIT );
+
+       bzero ( (char *)new, sizeof(struct vconsole) );
+       *new = *vc;
+       new->number = num;
+       new->next = vconsole_head;
+       new->tp = vc->tp;       /* Implied */
+       new->data=0;
+       new->t_scrolledback=0;
+       new->r_scrolledback=0;
+       new->r_data=0;
+       new->flags=LOSSY;
+       new->vtty = 0;
+       vconsole_head = new;
+       new->R_INIT ( new );
+       new->SPAWN ( new );
+       new->data = 0;
+       /*new->charmap = 0;*/
+       new->flags=LOSSY;
+       new->proc = curproc;
+       new->vtty = 0;
+       return new;
+}
+
+static struct vconsole *
+vconsole_spawn(dev, vc)
+       dev_t dev;
+       struct vconsole *vc;
+{
+       struct vconsole *new;
+       register int num = minor(dev);
+
+       if ( find_vc ( dev ) != 0 )
+               return 0;
+
+       MALLOC(new, struct vconsole *, sizeof(struct vconsole),
+           M_DEVBUF, M_NOWAIT );
+
+       bzero ( (char *)new, sizeof(struct vconsole) );
+       *new = *vc;
+       new->number = num;
+       new->next = vconsole_head;
+       new->tp=NULL;
+       new->opened=0;
+       new->data=0;
+       new->t_scrolledback=0;
+       new->r_scrolledback=0;
+       new->r_data=0;
+       new->vtty = 1;
+       vconsole_head = new;
+       new->R_INIT ( new );
+       new->FLASH ( new, 1 );
+       new->CURSOR_FLASH ( new, 1 );
+       new->SPAWN ( new );
+       new->vtty = 1;
+
+       MALLOC (new->charmap, int *, sizeof(int)*((new->xchars)*(new->ychars)), 
+           M_DEVBUF, M_NOWAIT );
+
+       if (new->charmap==0)
+               return 0;
+       {
+           int counter=0;
+           for ( counter=0; counter<((new->xchars)*(new->ychars)); counter++ )
+                   (new->charmap)[counter]=' ';
+       }
+       new->TERM_INIT ( new );
+       new->proc = curproc;
+       return new;
+}
+
+void
+vconsole_addcharmap(vc)
+       struct vconsole *vc;
+{
+       int counter=0;
+
+       MALLOC (vc->charmap, int *, sizeof(int)*((vc->xchars)*(vc->ychars)),
+           M_DEVBUF, M_NOWAIT );
+       for ( counter=0; counter<((vc->xchars)*(vc->ychars)); counter++ )
+               (vc->charmap)[counter]=' ';
+}
+
+int
+physconopen(dev, flag, mode, p)
+       dev_t dev;
+       int flag;
+       int mode;
+       struct proc *p;
+{
+       struct vconsole *new;
+
+       struct vconsole *vc;
+       int unit = minor(dev);
+       int found=0;
+       int majorhack=0;
+       int ret;
+
+       /*
+        * To allow the raw consoles a permanat hook for ioctls
+        * Spawning another virtual console will actuall configure it
+        */
+
+       if ( unit >= NVT ) {
+               if ( find_vc(dev)==0 )
+                       return ENXIO;
+       }
+/*
+       if (unit >= rpc_cd.cd_ndevs || !rpc_cd.cd_devs[unit])
+               return ENXIO;
+*/
+
+    /* If this virtual console is the real virtual console and hasn't got  */
+    /* a charmap then to allocate it one.  We can be sure addcharmap works */
+    /* here since this is the open routine.  This is incase the console    */
+    /* was initialised before the system was brought up                    */
+
+       if ((unit==0)&&(vconsole_master->charmap==0)) {
+               if (vconsole_master==vconsole_current)
+                       majorhack=1;
+               vconsole_addcharmap ( vconsole_master );
+               vconsole_master->flags &= ~LOSSY;
+       }
+
+    /* Check to see if this console has already been spawned */
+
+       for ( vc = vconsole_head; vc!=NULL; vc=vc->next ) {
+               if ( vc->number == unit ) {
+                       found=1;
+                       break;
+               }
+       }
+
+    /* Sanity check.  If we have no default console, set it to the master one */
+
+       if ( vconsole_default==0 )
+               vconsole_default = vconsole_master;
+
+    /* Ensure we have a vconsole structure.  Allocate one if we dont already */
+
+       if (found==0)
+               new = vconsole_spawn ( dev, vconsole_default );
+       else
+               new = vc;
+
+       new->proc = p;
+
+    /* Initialise the terminal subsystem for this device */
+
+#define TP (new->tp)
+
+       if (TP == NULL)
+               TP = ttymalloc();
+
+       physcon_tty[unit] = TP;
+
+       TP->t_oproc = physconstart;
+       TP->t_param = physconparam;
+       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;
+               TP->t_lflag = TTYDEF_LFLAG;
+               TP->t_ispeed = TP->t_ospeed = TTYDEF_SPEED;
+               physconparam(TP, &TP->t_termios);
+               ttsetwater(TP);
+       } else if (TP->t_state&TS_XCLUDE && p->p_ucred->cr_uid != 0)
+               return EBUSY;
+       TP->t_state |= TS_CARR_ON;
+
+       new->opened=1;
+   
+       TP->t_winsize.ws_col = new->xchars;
+       TP->t_winsize.ws_row = new->ychars;
+       ret = ((*linesw[TP->t_line].l_open)(dev, TP));
+       if ( majorhack==1 ) {
+               struct vconsole *vc_store;
+               int counter;
+               int end;
+               int lines;
+               int xs;
+
+               end = msgbufp->msg_bufx-1;
+               if (end>=MSG_BSIZE) end-=MSG_BSIZE;
+
+       /*
+        * Try some cute things.  Count the number of lines in the msgbuf
+        * then scroll the real screen up, just to fit the msgbuf on the
+        * screen, then sink all output, and spew the msgbuf to the
+        * new consoles charmap!
+        */ 
+
+               lines = 0; xs=0; 
+
+               for (counter=0;counter<end;counter++) {
+                       xs++;
+                       if (*((msgbufp->msg_bufc)+counter)==0x0a) {
+                               if (xs>vc->xchars) lines++;     
+                               lines++;
+                               xs=0;
+                       }
+               }
+
+               if ( lines < vc->ychars ) {
+                       counter=vc->ycur;
+                       while ( (counter--) > lines )
+                               new->PUTSTRING ( "\x0a", 1, new );
+               }
+
+               new->SLEEP(new);
+
+               vc_store = vconsole_current;
+               vconsole_current = 0; /* !!! */
+
+               /* HAHA, cant do this */
+               /* new->CLS ( new ); */
+
+               new->PUTSTRING ( "\x0c", 1, new );
+
+       /*
+        * Hmmm, I could really pass the whole damn thing to putstring
+        * since it doesn't have zeros, but I need to do the crlf
+        * conversion
+        */
+
+               xs=0;
+       
+               if ( end < 0 )
+                       panic ( "msgbuf trashed reboot and try again" );
+
+               for (counter=0;counter<end;counter++) {
+                       if (*((msgbufp->msg_bufc)+counter)==0x0a) {
+                               new->PUTSTRING ( "\x0d", 1, new );
+                               xs=0;
+                       }
+                       if ( (xs++)<new->xchars )
+                               new->PUTSTRING ((msgbufp->msg_bufc)+counter, 1, new );
+               }
+               vconsole_master->ycur = lines;
+               vconsole_current = vc_store;
+               new->WAKE(new);
+               vconsole_current->xcur = 0;
+
+               printf ( "\x0a" );
+           }    
+
+       return(ret);
+}
+
+/*
+ * int physconclose(dev_t dev, int flag, int mode, struct proc *p)
+ *
+ * Close the physical console
+ */
+
+int
+physconclose(dev, flag, mode, p)
+       dev_t dev;
+       int flag;
+       int mode;
+       struct proc *p;
+{
+       register struct tty *tp;
+
+       tp = find_tp ( dev );
+       if (tp == NULL) {
+               printf("physconclose: tp=0 dev=%04x\n", dev);
+               return(ENXIO);
+       }
+       (*linesw[tp->t_line].l_close)(tp, flag);
+       ttyclose(tp);
+
+       return(0);
+}
+
+int
+physconread(dev, uio, flag)
+       dev_t dev;
+       struct uio *uio;
+       int flag;
+{
+       register struct tty *tp = find_tp ( dev );
+       if (tp == NULL) {
+               printf("physconread: tp=0 dev=%04x\n", dev);
+               return(ENXIO);
+       }
+       return ((*linesw[tp->t_line].l_read)(tp, uio, flag));
+}
+
+int
+physconwrite(dev, uio, flag)
+       dev_t dev;
+       struct uio *uio;
+       int flag;
+{
+       register struct tty *tp;
+
+       tp = find_tp(dev);
+
+       if (tp == NULL) {
+               printf("physconwrite: tp=0 dev=%04x\n", dev);
+               return(ENXIO);
+       }
+
+       return((*linesw[tp->t_line].l_write)(tp, uio, flag));
+}
+
+struct tty *
+physcontty(dev)
+       dev_t dev;
+{
+       return(find_tp(dev));
+}
+
+int ioctlconsolebug;
+
+int
+physconioctl(dev, cmd, data, flag, p)
+       dev_t dev;
+       int cmd;
+       caddr_t data;
+       int flag;
+       struct proc *p;
+{
+       struct vconsole vconsole_new;
+       struct tty *tp=(struct tty *)0xDEADDEAD ;
+       int error;
+       int s;
+       struct vconsole *vc = find_vc(dev);
+
+       ioctlconsolebug = cmd;
+
+       tp = find_tp(dev);
+
+       if ((vc==0)||(tp==0))
+               return ENXIO;
+
+       switch ( cmd ) {
+       case CONSOLE_SWITCHUP:
+               physcon_switchup ();
+               return 0;
+       case CONSOLE_SWITCHDOWN:
+               physcon_switchdown ();
+               return 0;
+       case CONSOLE_SWITCHTO:
+               if (!physcon_switch ( *(int *)data ))
+                       return 0;
+               else
+                       return EINVAL;
+       case CONSOLE_SWITCHPREV:
+               physcon_switch ( lastconsole );
+               return 0;
+       case CONSOLE_CREATE:
+               if ( vconsole_spawn ( makedev ( physcon_major, *(int *)data ),
+                   vconsole_default ) == 0 )
+                       return ENOMEM;
+               else
+                       return 0;
+               break;
+
+       case CONSOLE_RENDERTYPE:
+               strncpy ( (char *)data, vc->T_NAME, 20 );
+               return 0;
+
+       case CONSOLE_TERMTYPE:
+               strncpy ( (char *)data, vc->T_NAME, 20 );
+               return 0;
+
+       case CONSOLE_LOCK:
+               s = spltty();
+               locked++;
+               (void)splx(s);
+               return 0;
+       case CONSOLE_UNLOCK:
+               s = spltty();
+               locked--;
+               if ( locked<0 )
+                       locked=0;
+               (void)splx(s);
+               return 0;
+       case CONSOLE_SPAWN_VIDC:
+/*
+               vconsole_new = *vconsole_default;
+*/
+               vconsole_new = *vc;
+               vconsole_new.render_engine = &vidcconsole;
+               if ( vconsole_spawn_re ( 
+                   makedev ( physcon_major, *(int *)data ),
+                   &vconsole_new ) == 0 )
+                       return ENOMEM;
+               else
+                       return 0;
+
+       case CONSOLE_GETVC:
+           {
+/*             struct vconsole *vc_p;  
+               vc_p = find_vc(dev);
+               *(int *)data = vc_p->number;*/
+               *(int *)data = vconsole_current->number;
+               return 0;
+           }
+
+       case CONSOLE_CURSORFLASHRATE:
+               vc->CURSORFLASHRATE ( vc, *(int *)data );               
+               return 0;
+
+       case CONSOLE_BLANKTIME:
+               vconsole_blankinit = *(int *)data;              
+               return 0;
+
+       case CONSOLE_DEBUGPRINT:
+               {
+                   struct vconsole *vc_p;      
+
+                   vc_p = find_vc(makedev(physcon_major,*(int*)data));
+                   if (vc_p==0) return EINVAL;
+                   printf ( "DEBUGPRINT for console %d\n", *(int*)data );
+                   printf ( "flags %08x vtty %01x\n", vc_p->flags, vc_p->vtty );
+                   printf ( "TTY INFO - winsize (%d, %d)\n",
+                               vc_p->tp->t_winsize.ws_col,
+                               vc_p->tp->t_winsize.ws_row);
+                   vc_p->R_DEBUGPRINT ( vc_p );
+                   vc_p->T_DEBUGPRINT ( vc_p );
+                   return 0;
+               }
+               
+       default: 
+               error = vc->IOCTL ( vc, dev, cmd, data, flag, p );
+               if ( error >=0 )
+                       return 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;
+       } 
+       return(ENOTTY);
+}
+
+int
+physconmmap(dev, offset, nprot)
+       dev_t dev;
+       int offset;
+       int nprot;
+{
+       struct vconsole *vc = find_vc(dev);
+       u_int physaddr;
+
+       if (minor(dev) < 64) {
+               log(LOG_WARNING, "You should no longer use ttyv to mmap a frame buffer\n");
+               log(LOG_WARNING, "For vidc use /dev/vidcvideo0\n");
+       }
+       physaddr = vc->MMAP(vc, offset, nprot);
+       return(physaddr);
+}
+
+/*
+ * Perform output on specified tty stream
+ */
+
+void
+physconstart(tp)
+       struct tty *tp;
+{
+       int s, len;
+       struct clist *cl;
+       struct vconsole *vc;
+       u_char buf[128];
+
+       s = spltty();
+
+       vc = find_vc ( tp->t_dev );
+
+       /* Are we ready to perform output */
+
+       if (tp->t_state & (TS_TIMEOUT | TS_BUSY | TS_TTSTOP)) {
+               (void)splx(s);
+               return;
+       }
+
+       tp->t_state |= TS_BUSY;
+
+       /* Fill our buffer with the data to print */
+
+       cl = &tp->t_outq;
+
+       if ( vc->r_scrolledback ) vc->R_SCROLLBACKEND ( vc );
+       if ( vc->t_scrolledback ) vc->T_SCROLLBACKEND ( vc );
+
+       (void)splx(s);
+
+    /* Apparently we do this out of spl since it _IS_ fairly expensive */
+    /* and it stops the serial ports overflowing                      */
+
+       while ( (len = q_to_b(cl, buf, 128)) ) {
+               if ( vc!=NULL )
+                       vc->PUTSTRING(buf, len, vc);
+       }
+
+       s = spltty ();
+
+       tp->t_state &= ~TS_BUSY;
+
+       if (cl->c_cc) {
+               tp->t_state |= TS_TIMEOUT;
+               timeout(ttrstrt, tp, 1);
+       }
+
+       if (cl->c_cc <= tp->t_lowat) {
+               if (tp->t_state & TS_ASLEEP) {
+                       tp->t_state &= ~TS_ASLEEP;
+                       wakeup(cl);
+               }
+               selwakeup(&tp->t_wsel);
+       }
+
+       if ( want_switch != -1 ) {
+               physcon_switch ( want_switch );
+               want_switch=-1;
+       }
+
+       (void)splx(s);
+}
+
+int
+physconparam(tp, t)
+       struct tty *tp;
+       struct termios *t;
+{
+       tp->t_ispeed = t->c_ispeed;
+       tp->t_ospeed = t->c_ospeed;
+       tp->t_cflag = t->c_cflag;
+       return(0);
+}
+
+void
+physconstop(tp, flag)
+       struct tty *tp;
+       int flag;
+{
+       /* Nothing necessary */
+}
+
+int
+physconkbd(key)
+       int key;
+{
+       char *string;
+       register struct tty *tp;
+       int s;
+
+       s = spltty();
+
+       tp = vconsole_current->tp;
+
+       if (tp == NULL) return(1);
+
+       if ((tp->t_state & TS_ISOPEN) == 0) {
+               (void)splx(s);
+               return(1);
+       }
+
+       if (key < 0x100)
+               (*linesw[tp->t_line].l_rint)(key, tp);
+       else {
+               switch (key) {
+               case 0x100:
+                       string = "\x1b[A";
+                       break;
+               case 0x101:
+                       string = "\x1b[B";
+                       break;
+               case 0x102:
+                       string = "\x1b[D";
+                       break;
+               case 0x103:
+                       string = "\x1b[C";
+                       break;
+               case 0x104:
+                       string = "\x1b[6~";
+                       break;
+               case 0x105:
+                       string = "\x1b[5~";
+                       break;
+               case 0x108:
+                       string = "\x1b[2~";
+                       break;
+               case 0x109:
+                       string = "\x7f";
+                       break;
+               default:
+                       string = "";
+                       break;
+               }
+               while (*string != 0) {
+                       (*linesw[tp->t_line].l_rint)(*string, tp);
+                       ++string;
+               }
+       }
+       (void)splx(s);
+       return(0);
+}
+
+static int physconinit_called = 0;
+
+void
+physconinit(cp)
+       struct consdev *cp;
+{
+       int *test;
+       int counter;
+
+    /*
+     * Incase we're called more than once.  All routines below here
+     * undergo once time initialisation
+     */
+
+       if ( physconinit_called )
+               return;
+
+       physconinit_called=1;
+
+       locked=0;
+
+       physcon_major = major ( cp->cn_dev );
+
+       /*
+        * Create the master console
+        */
+
+       vconsole_master->next = NULL;
+       vconsole_master->number = 0;
+       vconsole_master->opened = 1;
+       vconsole_master->tp = NULL;
+
+       /*
+        * Right, here I can choose some render routines
+        */
+
+       vconsole_master->render_engine = &vidcconsole;
+       vconsole_master->terminal_emulator = &vt220;
+
+       /*
+        * We will very soon loose the master console, and number 0 will
+        * become the current console so as not to waste a struct vconsole
+        */
+       vconsole_current = vconsole_head = vconsole_master;
+       vconsole_master->data = NULL;
+       vconsole_master->vtty = 1;
+
+       /*
+        * Perform initial checking
+        */
+
+       if ( vconsole_master->terminal_emulator->name == 0 )
+               vconsole_master->terminal_emulator->name = undefined_string;
+       if ( vconsole_master->render_engine->name == 0 )
+               vconsole_master->render_engine->name = undefined_string;
+
+       /*
+        * Right, I have to assume the init and print procedures are ok
+        * or there's nothing else that can be done
+        */
+
+       vconsole_master->R_INIT ( vconsole_master);
+       vconsole_master->SPAWN ( vconsole_master );
+       vconsole_master->TERM_INIT (vconsole_master);
+       vconsole_master->flags = LOSSY;
+
+       /*
+        * Now I can do some productive verification
+        */
+
+       /* Ensure there are no zeros in the termulation and render_engine */
+
+       test = (int *) vconsole_master->render_engine;
+       for ( counter=0; counter<(sizeof(struct render_engine)/4)-1; counter++ )
+               if (test[counter]==0)
+                       panic ( "Render engine %i is missins a routine",
+                           vconsole_master->render_engine->name );
+  
+       test = (int *) vconsole_master->terminal_emulator;
+       for ( counter=0; counter<(sizeof(struct terminal_emulator)/4)-1; counter++ )
+               if (test[counter]==0)
+                       panic ( "Render engine %i is missing a routine",
+                           vconsole_master->terminal_emulator->name );
+}
+
+/*
+ * void physconputstring(char *string, int length)
+ *
+ * Render a string on the physical console
+ */
+
+void
+physconputstring(string, length)
+       char *string;
+       int length;
+{
+       vconsole_current->PUTSTRING(string, length, vconsole_current);
+}
+
+/*
+ * void physcongetchar(void)
+ *
+ * Get a character from the physical console
+ */
+
+int getkey_polled __P(());
+
+char
+physcongetchar(void)
+{
+       return(getkey_polled());
+}
+
+void
+consinit(void)
+{
+       static int consinit_called = 0;
+
+       if (consinit_called != 0)
+               return;
+
+       consinit_called = 1;
+       cninit();
+
+/* Ok get our start up message in early ! */
+
+       printf("\x0cRiscBSD booting...\n%s\n", version);
+}
+
+void
+rpcconsolecnprobe(cp)
+       struct consdev *cp;
+{
+       int major;
+
+/*     printf("rpcconsoleprobe: pc=%08x\n", cp);*/
+
+/*
+ * Locate the major number for the physical console device
+ * We do this by searching the character device list until we find
+ * the device with the open function for the physical console
+ */
+
+       for (major = 0; major < nchrdev; ++major) {
+               if (cdevsw[major].d_open == physconopen)
+                       break;
+       }
+
+/* Initialise the required fields */
+
+       cp->cn_dev = makedev(major, 0);
+       cp->cn_pri = CN_INTERNAL;
+}
+
+#define RPC_BUF_LEN    (64)
+char rpc_buf[RPC_BUF_LEN];
+int rpc_buf_ptr = 0;
+
+#define RPC_BUF_FLUSH  \
+{                      \
+       vconsole_current->PUTSTRING ( rpc_buf, rpc_buf_ptr, vconsole_current ); \
+       rpc_buf_ptr=0;  \
+}
+
+void
+rpcconsolecninit(cp)
+       struct consdev *cp;
+{
+       physconinit(cp);        /* woo Woo WOO!!!, woo, woo, yes ok bye */
+}
+
+void
+rpcconsolecnputc(dev, character)
+       dev_t dev;
+       char character;
+{
+       extern int cold;
+
+       if (( rpc_buf_ptr==RPC_BUF_LEN ) || (cold==0) )
+               RPC_BUF_FLUSH
+
+       rpc_buf[rpc_buf_ptr++] = character;
+
+       if ((character == 0x0a )||(character==0x0d)||(character=='.'))
+               RPC_BUF_FLUSH
+}
+
+int
+console_switchdown()
+{
+       physcon_switchdown ();
+       return 0;
+}
+
+int
+console_switchup()
+{
+       physcon_switchup ();
+       return 0;
+}
+
+int
+console_unblank()
+{
+       vconsole_blankcounter = vconsole_blankinit;
+       vconsole_current->BLANK ( vconsole_current, BLANK_NONE );
+       return 0;
+}
+
+int
+console_scrollback ()
+{
+       if (vconsole_current==NULL)
+               return 0;
+       if ( vconsole_current->R_SCROLLBACK(vconsole_current) ==-1 ) {
+               if ( vconsole_current->T_SCROLLBACK(vconsole_current)==-1 ) {  
+               }
+       }
+       return 0;
+}
+
+int
+console_scrollforward ()
+{
+       if (vconsole_current==NULL)
+               return 0;
+       if ( vconsole_current->R_SCROLLFORWARD(vconsole_current) ==-1 ) {
+               if ( vconsole_current->T_SCROLLFORWARD(vconsole_current)==-1 ) {  
+               }
+       }
+       return 0;
+}
+
+int
+console_switchlast ()
+{
+       return (physcon_switch ( lastconsole ));
+}
+
+int
+physcon_switchdown ()
+{
+       int start;
+       int next = (vconsole_current->number);
+       start=next;
+       do {    
+               next--;
+               next = next&0xff;
+               if (next==start) return 0;
+       } while (physcon_switch ( next ));
+        return 0;
+}
+
+int
+physcon_switchup ()
+{
+       int start;
+       int next = (vconsole_current->number);
+       start=next;
+       do {    
+               next++;
+               next = next&0xff;
+               if (next==start) return 0;
+       } while (physcon_switch ( next ));
+       return 0;
+}
+
+void
+console_switch(number)
+       u_int number;
+{
+       physcon_switch ( number );
+}
+
+/* switchto */
+int 
+physcon_switch(number)
+       u_int number;
+{
+       register struct vconsole *vc;
+        int s = spltty ();
+        int ret;
+
+       if ( locked!=0 ) {
+               ret=0;
+               goto out;
+        }
+
+       if ( printing ) {
+               want_switch = number;
+               ret=0;
+               goto out;
+       }
+
+       vc = find_vc ( makedev ( physcon_major, number ) );
+
+       if ( vc==0 ) {
+               ret = 1;
+               goto out;
+       }
+
+       if ( vc==vconsole_current ) {
+               ret = 1;
+               goto out;
+       }
+
+       /* Point of no return */
+
+       locked++;               /* We cannot reenter this routine now */
+
+       /* De-activate the render engine functions */
+       if ( vconsole_current->vtty==1 ) {
+               vconsole_current->SLEEP(vconsole_current);
+               vconsole_current->FLASH ( vc, 0 );
+               vconsole_current->CURSOR_FLASH ( vc, 0 );
+       }
+
+       /* Swap in the new consoles state */
+
+       lastconsole = vconsole_current->number;
+       vconsole_current=vc;
+       vconsole_current->R_SWAPIN ( vc );
+
+       /* Re-activate the render engine functions */
+
+       if ( vconsole_current->vtty==1 ) {
+               vconsole_current->T_SWAPIN ( vc );
+               vconsole_current->WAKE(vconsole_current);
+               vconsole_current->FLASH ( vc, 1 );
+               vconsole_current->CURSOR_FLASH ( vc, 1 );
+       }
+
+       locked--;
+
+       /* Tell the process about the switch, like the X server */
+
+       if ( vc->proc )
+               psignal ( vc->proc, SIGIO );
+
+       ret = 0;
+out:
+       (void)splx(s);
+       return(ret);
+}
+
+char
+rpcconsolecngetc(dev)
+       dev_t dev;
+{
+       return( physcongetchar () );
+}
+
+void
+rpcconsolecnpollc(dev, on)
+       dev_t dev;
+       int on;
+{
+       RPC_BUF_FLUSH
+}
+
+int
+rpcprobe(parent, match, aux)
+       struct device *parent;
+       void *match;
+       void *aux;
+{
+       return(1);
+}
+
+void
+rpcattach(parent, self, aux)
+       struct device *parent;
+       struct device *self;
+       void *aux;
+{
+       printf(" riscbsd generic console driver %susing %s %s\n",
+           CONSOLE_VERSION, vconsole_master->terminal_emulator->name,
+           vconsole_master->render_engine->name);
+
+       vconsole_master->T_ATTACH(vconsole_master, parent, self, aux);
+       vconsole_master->R_ATTACH(vconsole_master, parent, self, aux);
+}
+
+/*
+struct cfattach rpc_ca = {
+       sizeof(struct device), rpcprobe, rpcattach
+};
+
+struct cfdriver rpc_cd = {
+       NULL, "rpc", DV_TTY
+};
+*/
+
+struct cfattach vt_ca = {
+       sizeof(struct device), rpcprobe, rpcattach
+};
+
+struct cfdriver vt_cd = {
+       NULL, "rpc", DV_TTY
+};
+
+extern struct terminal_emulator vt220;
+
+struct render_engine *render_engine_tab[] = {
+        &vidcconsole,
+};
+
+struct terminal_emulator *terminal_emulator_tab[] = {
+        &vt220,
+};
diff --git a/sys/arch/arm32/dev/console/debugconsole.c b/sys/arch/arm32/dev/console/debugconsole.c
new file mode 100644 (file)
index 0000000..2fc947b
--- /dev/null
@@ -0,0 +1,88 @@
+/* $NetBSD: debugconsole.c,v 1.2 1996/03/18 19:33:04 mark Exp $ */
+
+/*
+ * Copyright (c) 1994-1995 Melvyn Tang-Richardson
+ * Copyright (c) 1994-1995 RiscBSD kernel team
+ * 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 RiscBSD kernel team
+ * 4. The name of the company nor the name of the author may be used to
+ *    endorse or promote products derived from this software without specific
+ *    prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE RISCBSD TEAM ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS 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.
+ *
+ * RiscBSD kernel project
+ *
+ * debugconsole.c
+ *
+ * Console functions
+ *
+ * Created      : 17/09/94
+ */
+
+#ifdef DEBUGTERM
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/tty.h>
+#include <machine/stdarg.h>
+#include <machine/vconsole.h>
+
+#define TOTTY 0x02
+
+/*
+ * This code allows the kernel developer to have a 'nice' virtual
+ * console for debugging information.
+ *
+ * It is more useful than say, printf since the output is
+ *
+ * a) isolated
+ *
+ */
+
+struct vconsole *debug_vc=0;
+struct tty *debug_tty=0;
+
+void
+dprintf(fmt, va_alist)
+       char *fmt;
+{
+       if ( debug_vc==0 )
+               return;
+
+       dumb_putstring ( fmt, strlen(fmt), debug_vc );
+/*
+       va_list *ap;
+
+       if ( debug_tty == NULL )
+               return;
+
+       va_start(ap, fmt);
+       kprintf(fmt, TOTTY, debug_tty, ap);
+       va_end(ap);
+*/
+}
+
+#endif
+
diff --git a/sys/arch/arm32/dev/console/dumb.c b/sys/arch/arm32/dev/console/dumb.c
new file mode 100644 (file)
index 0000000..40396cb
--- /dev/null
@@ -0,0 +1,146 @@
+/* $NetBSD: dumb.c,v 1.2 1996/03/18 19:33:05 mark Exp $ */
+
+/*
+ * Copyright (c) 1994-1995 Melvyn Tang-Richardson
+ * Copyright (c) 1994-1995 RiscBSD kernel team
+ * 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 RiscBSD kernel team
+ * 4. The name of the company nor the name of the author may be used to
+ *    endorse or promote products derived from this software without specific
+ *    prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE RISCBSD TEAM ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS 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.
+ *
+ * RiscBSD kernel project
+ *
+ * dumb.c
+ *
+ * Console functions
+ *
+ * Created      : 17/09/94
+ */
+
+#include <sys/cdefs.h>
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/malloc.h>
+#include <sys/device.h>
+#include <machine/param.h>
+#include <machine/katelib.h>
+#include <machine/cpu.h>
+#include <machine/bootconfig.h>
+#include <machine/iomd.h>
+#include <machine/vidc.h>
+#include <machine/vconsole.h>
+
+#define TERMTYPE_PUTSTRING     dumb_putstring
+#define TERMTYPE_INIT  dumb_init
+
+int
+TERMTYPE_INIT(vc)
+       struct vconsole *vc;
+{
+       /* This dumb termial is so dumb it requires very little init */
+       return 0;
+}
+
+static void
+do_scrollup(vc)
+       struct vconsole *vc;
+{
+
+       if (vc==vconsole_current)
+               vc->SCROLLUP ( vc, 0, vc->ychars-1 );
+
+       vc->ycur=vc->ychars-1;
+
+       if ( ((vc->flags)&(LOSSY)) == 0 ) {
+               int counter;
+               for ( counter=vc->xchars; counter < ((vc->ychars)*(vc->xchars)); counter++ ) {
+                       vc->charmap[counter-vc->xchars] = vc->charmap[counter];
+               }
+               for ( counter=vc->xchars*(vc->ychars-1); counter < (vc->xchars*vc->ychars); counter++ ) {
+                       vc->charmap[counter]=0x20;
+               }
+       }
+}
+
+static int
+do_render(c, vc)
+       char c;
+       struct vconsole *vc;
+{
+       /* THE RENDER STAGE **********************************/
+       if ((c>=0x20)&&(c<=0x7f)) {
+               if (((vc->flags)&(LOSSY))==0) {
+                       vc->charmap[ vc->xcur + vc->ycur*vc->xchars ] = c | 7<<8;
+               }
+
+               if ( vc==vconsole_current )
+                       vc->RENDER ( vc, c );
+
+               vc->xcur++;
+       }
+
+       if ( vc->xcur >= vc->xchars ) {
+               vc->xcur=0;
+               vc->ycur++;
+       }
+
+       if ( vc->ycur >= vc->ychars ) {
+               do_scrollup ( vc );
+               vc->xcur=0;
+               vc->ycur=vc->ychars-1;
+       }
+}
+       
+int
+TERMTYPE_PUTSTRING(string, length, vc)
+       char *string;
+       int length;
+       struct vconsole *vc;
+{
+       char c;
+
+       while ( ((c=*(string++))!=0) && ((length--)>0)) {
+               if ((c<31)||(c>127)) c='*';
+               switch (c) {
+               case 0x0a:
+                       vc->ycur++;
+                       if ( vc->ycur>=vc->ychars ) {
+                               do_scrollup ( vc );
+                               vc->ycur=vc->ychars-1;
+                       }
+                       break;
+
+               case 0x0d:
+                       vc->xcur=0;
+                       break;
+
+               default:
+                       do_render ( c, vc );
+                       break;
+               }
+       }
+}
diff --git a/sys/arch/arm32/dev/console/fonts/font_bold.h b/sys/arch/arm32/dev/console/fonts/font_bold.h
new file mode 100644 (file)
index 0000000..7aa9f18
--- /dev/null
@@ -0,0 +1,265 @@
+/* $NetBSD: font_bold.h,v 1.1 1996/01/31 23:20:07 mark Exp $ */
+
+/*
+ * Copyright (c) 1994 Mark Brinicombe.
+ * Copyright (c) 1994 Brini.
+ * All rights reserved.
+ *
+ * This code is derived from software written for Brini by Mark Brinicombe
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided 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 Brini.
+ * 4. The name of the company nor the name of the author may be used to
+ *    endorse or promote products derived from this software without specific
+ *    prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BRINI ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL BRINI 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.
+ *
+ * RiscBSD kernel project
+ *
+ * font_terminal14_bold.h
+ *
+ * Font for physical console driver
+ *
+ * Created      : 18/09/94
+ * Last updated : 15/10/94
+ *
+ * Based on kate/display/14bold.h
+ *
+ *    $Id: font_bold.h,v 1.1.1.1 1996/04/24 11:08:37 deraadt Exp $
+ */
+unsigned char font_terminal_14bold_data[] = {
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x36, 0x36, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x24, 0x24, 0x7e, 0x7e, 0x24, 0x7e, 0x7e, 0x24, 0x24, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x10, 0x38, 0x6c, 0x0c, 0x38, 0x60, 0x6c, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x6c, 0x76, 0x3c, 0x30, 0x18, 0x78, 0xdc, 0x6c, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x18, 0x34, 0x34, 0x98, 0x7c, 0x66, 0x66, 0xbc, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x18, 0x18, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x60, 0x30, 0x30, 0x18, 0x18, 0x18, 0x18, 0x30, 0x30, 0x60, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x06, 0x0c, 0x0c, 0x18, 0x18, 0x18, 0x18, 0x0c, 0x0c, 0x06, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x10, 0x54, 0x38, 0xfe, 0x38, 0x54, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x7e, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x0c, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x0c, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x60, 0x60, 0x30, 0x30, 0x18, 0x18, 0x0c, 0x0c, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x18, 0x24, 0x66, 0x66, 0x66, 0x66, 0x24, 0x18, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x18, 0x1c, 0x1a, 0x18, 0x18, 0x18, 0x18, 0x7e, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, 0x70, 0x38, 0x1c, 0x0e, 0x66, 0x7e, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, 0x60, 0x38, 0x60, 0x60, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x60, 0x70, 0x68, 0x64, 0x66, 0xfe, 0x60, 0x60, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x3e, 0x06, 0x06, 0x3e, 0x60, 0x60, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x3c, 0x06, 0x06, 0x3e, 0x66, 0x66, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x7c, 0x60, 0x60, 0x30, 0x30, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, 0x66, 0x3c, 0x66, 0x66, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, 0x66, 0x66, 0x7c, 0x60, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x18, 0x18, 0x0c, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x60, 0x30, 0x18, 0x0c, 0x0c, 0x18, 0x30, 0x60, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x7e, 0x00, 0x7e, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x06, 0x0c, 0x18, 0x30, 0x30, 0x18, 0x0c, 0x06, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x3c, 0x66, 0x66, 0x60, 0x30, 0x18, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x7c, 0x8e, 0xe6, 0xb6, 0xb6, 0xe6, 0x0e, 0x7c, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x18, 0x3c, 0x66, 0x66, 0x7e, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x3e, 0x66, 0x66, 0x3e, 0x66, 0x66, 0x66, 0x3e, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, 0x06, 0x06, 0x06, 0x06, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x3e, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x3e, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x7c, 0x0c, 0x0c, 0x3c, 0x0c, 0x0c, 0x0c, 0x7c, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x7c, 0x0c, 0x0c, 0x3c, 0x0c, 0x0c, 0x0c, 0x0c, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, 0x06, 0x76, 0x66, 0x66, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0x7e, 0x66, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x7e, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x3c, 0x30, 0x30, 0x30, 0x30, 0x30, 0x36, 0x1c, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0xc6, 0x66, 0x36, 0x1e, 0x1e, 0x36, 0x66, 0xc6, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x7c, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0xc6, 0xee, 0xfe, 0xd6, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x6e, 0x6e, 0x76, 0x76, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x3e, 0x66, 0x66, 0x66, 0x3e, 0x06, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, 0x66, 0x66, 0x66, 0x66, 0x76, 0x3c, 0x60, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x3e, 0x66, 0x66, 0x66, 0x3e, 0x36, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, 0x06, 0x3e, 0x7c, 0x60, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xd6, 0xd6, 0xd6, 0x7c, 0x28, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x3c, 0x18, 0x18, 0x3c, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x7e, 0x60, 0x70, 0x38, 0x1c, 0x0e, 0x06, 0x7e, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x3c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x3c, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x06, 0x06, 0x0c, 0x0c, 0x18, 0x18, 0x30, 0x30, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x3c, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x3c, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x18, 0x3c, 0x66, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x7e, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x18, 0x18, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x60, 0x7c, 0x66, 0x66, 0xfc, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x06, 0x06, 0x3e, 0x66, 0x66, 0x66, 0x66, 0x3e, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, 0x06, 0x06, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x60, 0x60, 0x7c, 0x66, 0x66, 0x66, 0x66, 0x7c, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, 0x7e, 0x06, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x38, 0x6c, 0x0c, 0x3e, 0x0c, 0x0c, 0x0c, 0x0c, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x66, 0x66, 0x66, 0x7c, 0x60, 0x3c, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x06, 0x06, 0x3e, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x1c, 0x18, 0x18, 0x18, 0x18, 0x7e, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x30, 0x30, 0x00, 0x3c, 0x30, 0x30, 0x30, 0x30, 0x30, 0x1e, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x06, 0x06, 0x66, 0x36, 0x1e, 0x1e, 0x36, 0x66, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x1c, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x7e, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6e, 0xd6, 0xd6, 0xd6, 0xd6, 0xc6, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x66, 0x66, 0x66, 0x66, 0x3e, 0x06, 0x06, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x66, 0x66, 0x66, 0x66, 0x7c, 0x60, 0x60, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xcc, 0x0c, 0x0c, 0x0c, 0x0c, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x46, 0x3e, 0x7c, 0x62, 0x3c, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x0c, 0x0c, 0x3e, 0x0c, 0x0c, 0x0c, 0x6c, 0x38, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x7c, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0x2c, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xd6, 0xd6, 0xd6, 0xfe, 0x6c, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0x6c, 0x38, 0x38, 0x6c, 0xc6, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x7c, 0x60, 0x60, 0x3c, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x70, 0x38, 0x1c, 0x0e, 0x7e, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x70, 0x18, 0x18, 0x30, 0x1c, 0x30, 0x18, 0x18, 0x18, 0x70, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x0e, 0x18, 0x18, 0x0c, 0x38, 0x0c, 0x18, 0x18, 0x18, 0x0e, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x4c, 0x7e, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0xfc, 0x36, 0x36, 0x76, 0x36, 0x36, 0x36, 0xfc, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xd6, 0xf6, 0x16, 0xd6, 0x7c, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x66, 0x66, 0x00, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x3c, 0x66, 0x06, 0x66, 0x3c, 0x18, 0x18, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x78, 0x4c, 0x0c, 0x3e, 0x0c, 0x0c, 0xde, 0x7a, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x6c, 0x38, 0x6c, 0x6c, 0x38, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x42, 0x66, 0x3c, 0x18, 0x7e, 0x18, 0x7e, 0x18, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x3c, 0x66, 0x0e, 0x3c, 0x66, 0x66, 0x3c, 0x70, 0x66, 0x3c, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x7e, 0xc3, 0xdb, 0xcb, 0xcb, 0xdb, 0xc3, 0x7e, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x1c, 0x30, 0x3c, 0x36, 0x3c, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x6c, 0x36, 0x6c, 0xd8, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x7e, 0x7e, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x3c, 0x7e, 0x81, 0x9d, 0xad, 0x9d, 0xad, 0x81, 0x7e, 0x3c, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x7e, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x1c, 0x36, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x18, 0x18, 0x7e, 0x18, 0x18, 0x00, 0x7e, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x1c, 0x32, 0x30, 0x1c, 0x06, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x1c, 0x32, 0x18, 0x30, 0x32, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x30, 0x18, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0xfe, 0x06, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0xfc, 0x5e, 0x5e, 0x5e, 0x5e, 0x5c, 0x58, 0x58, 0x58, 0x58, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x0c, 0x00, 0x00,
+    0x00, 0x00, 0x18, 0x1c, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x1c, 0x36, 0x36, 0x36, 0x1c, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1b, 0x36, 0x6c, 0x36, 0x1b, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x0c, 0x0e, 0x8c, 0x4c, 0x3e, 0x10, 0x68, 0x74, 0x6a, 0xfd, 0x60, 0x60, 0x00, 0x00, 0x00,
+    0x00, 0x0c, 0x0e, 0x8c, 0x4c, 0x3e, 0x10, 0x68, 0xd4, 0xc2, 0x61, 0x30, 0xf0, 0x00, 0x00, 0x00,
+    0x00, 0x0c, 0x1e, 0x98, 0x4c, 0x38, 0x1e, 0x6c, 0x74, 0x6a, 0xfd, 0x60, 0x60, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x18, 0x18, 0x0c, 0x46, 0x66, 0x3c, 0x00, 0x00, 0x00,
+    0x00, 0x0c, 0x18, 0x00, 0x18, 0x3c, 0x66, 0x66, 0x7e, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x30, 0x18, 0x00, 0x18, 0x3c, 0x66, 0x66, 0x7e, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x18, 0x3c, 0x00, 0x18, 0x3c, 0x66, 0x66, 0x7e, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x5c, 0x3a, 0x00, 0x18, 0x3c, 0x66, 0x66, 0x7e, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x66, 0x66, 0x00, 0x18, 0x3c, 0x66, 0x66, 0x7e, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00,
+    0x18, 0x2c, 0x2c, 0x18, 0x18, 0x3c, 0x66, 0x66, 0x7e, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0xfc, 0x36, 0x36, 0x76, 0x3e, 0x36, 0x36, 0xf6, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, 0x06, 0x06, 0x06, 0x06, 0x66, 0x3c, 0x10, 0x18, 0x00, 0x00,
+    0x00, 0x18, 0x30, 0x00, 0x7c, 0x0c, 0x0c, 0x3c, 0x0c, 0x0c, 0x0c, 0x7c, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x60, 0x30, 0x00, 0x7c, 0x0c, 0x0c, 0x3c, 0x0c, 0x0c, 0x0c, 0x7c, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x18, 0x3c, 0x00, 0x7c, 0x0c, 0x0c, 0x3c, 0x0c, 0x0c, 0x0c, 0x7c, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x6c, 0x6c, 0x00, 0x7c, 0x0c, 0x0c, 0x3c, 0x0c, 0x0c, 0x0c, 0x7c, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x0c, 0x18, 0x00, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x7e, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x30, 0x18, 0x00, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x7e, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x18, 0x3c, 0x00, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x7e, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x66, 0x66, 0x00, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x7e, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x1c, 0x2c, 0x4c, 0x4c, 0x5e, 0x4c, 0x2c, 0x1c, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x5c, 0x3a, 0x00, 0x66, 0x66, 0x6e, 0x6e, 0x76, 0x76, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x0c, 0x18, 0x00, 0x3c, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x30, 0x18, 0x00, 0x3c, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x18, 0x3c, 0x00, 0x3c, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x5c, 0x3a, 0x00, 0x3c, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x66, 0x66, 0x00, 0x3c, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x3c, 0x18, 0x3c, 0x66, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x80, 0x78, 0x6c, 0x6c, 0x7c, 0x7c, 0x6c, 0x6c, 0x3c, 0x02, 0x00, 0x00, 0x00,
+    0x00, 0x0c, 0x18, 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x30, 0x18, 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x18, 0x3c, 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x66, 0x66, 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x30, 0x18, 0x00, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x1e, 0x0c, 0x3c, 0x6c, 0x6c, 0x3c, 0x0c, 0x1e, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, 0x66, 0x36, 0x66, 0x66, 0x66, 0x36, 0x02, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x18, 0x30, 0x00, 0x3c, 0x60, 0x7c, 0x66, 0x66, 0xfc, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x30, 0x18, 0x00, 0x3c, 0x60, 0x7c, 0x66, 0x66, 0xfc, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x18, 0x3c, 0x00, 0x3c, 0x60, 0x7c, 0x66, 0x66, 0xfc, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x58, 0x34, 0x00, 0x3c, 0x60, 0x7c, 0x66, 0x66, 0xfc, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x6c, 0x6c, 0x00, 0x3c, 0x60, 0x7c, 0x66, 0x66, 0xfc, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x3c, 0x6e, 0x3c, 0x00, 0x3c, 0x60, 0x7c, 0x66, 0x66, 0xdc, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xb2, 0xfc, 0x36, 0xb6, 0x6c, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, 0x06, 0x06, 0x66, 0x3c, 0x10, 0x18, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x0c, 0x18, 0x00, 0x3c, 0x66, 0x7e, 0x06, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x30, 0x18, 0x00, 0x3c, 0x66, 0x7e, 0x06, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x18, 0x3c, 0x00, 0x3c, 0x66, 0x7e, 0x06, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x66, 0x66, 0x00, 0x3c, 0x66, 0x7e, 0x06, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x0c, 0x18, 0x00, 0x1c, 0x18, 0x18, 0x18, 0x18, 0x7e, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x30, 0x18, 0x00, 0x1c, 0x18, 0x18, 0x18, 0x18, 0x7e, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x18, 0x3c, 0x00, 0x1c, 0x18, 0x18, 0x18, 0x18, 0x7e, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x36, 0x36, 0x00, 0x1c, 0x18, 0x18, 0x18, 0x18, 0x7e, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x24, 0x18, 0x1c, 0x30, 0x7c, 0x66, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x5c, 0x3a, 0x00, 0x3e, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x0c, 0x18, 0x00, 0x3c, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x30, 0x18, 0x00, 0x3c, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x18, 0x3c, 0x00, 0x3c, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x5c, 0x3a, 0x00, 0x3c, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x66, 0x66, 0x00, 0x3c, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x7e, 0x7e, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb8, 0x6c, 0x7c, 0x7c, 0x6c, 0x3a, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x0c, 0x18, 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x7c, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x30, 0x18, 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x7c, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x18, 0x3c, 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x7c, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x66, 0x66, 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x7c, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x30, 0x18, 0x00, 0x66, 0x66, 0x66, 0x66, 0x7c, 0x60, 0x66, 0x3c, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x0c, 0x0c, 0x0c, 0x3c, 0x6c, 0x6c, 0x6c, 0x6c, 0x3c, 0x0c, 0x0c, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x66, 0x66, 0x00, 0x66, 0x66, 0x66, 0x66, 0x7c, 0x60, 0x66, 0x3c, 0x00, 0x00,
+    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+    0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa,
+    0x00, 0x00, 0x00, 0x08, 0x1c, 0x2a, 0x49, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x49, 0x2a, 0x1c, 0x08, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x08, 0x04, 0x02, 0xff, 0x02, 0x04, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x10, 0x20, 0x40, 0xff, 0x40, 0x20, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,
+};
+
+font_struct font_terminal_14bold = {
+    199,
+    1,
+    16,
+    8,
+    16,
+    8,
+    16,
+    3184,
+    font_terminal_14bold_data
+};
+
+/* End of font14bold.h */
diff --git a/sys/arch/arm32/dev/console/fonts/font_italic.h b/sys/arch/arm32/dev/console/fonts/font_italic.h
new file mode 100644 (file)
index 0000000..7abc07d
--- /dev/null
@@ -0,0 +1,265 @@
+/* $NetBSD: font_italic.h,v 1.1 1996/01/31 23:20:13 mark Exp $ */
+
+/*
+ * Copyright (c) 1994 Mark Brinicombe.
+ * Copyright (c) 1994 Brini.
+ * All rights reserved.
+ *
+ * This code is derived from software written for Brini by Mark Brinicombe
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided 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 Brini.
+ * 4. The name of the company nor the name of the author may be used to
+ *    endorse or promote products derived from this software without specific
+ *    prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BRINI ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL BRINI 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.
+ *
+ * RiscBSD kernel project
+ *
+ * font_terminal14_italic.h
+ *
+ * Font for physical console driver
+ *
+ * Created      : 18/09/94
+ * Last updated : 15/10/94
+ *
+ * Based on kate/display/14norm.h
+ *
+ *    $Id: font_italic.h,v 1.1.1.1 1996/04/24 11:08:37 deraadt Exp $
+ */
+unsigned char font_terminal_14italic_data[] = {
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x24, 0x24, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x24, 0x24, 0x7e, 0x24, 0x7e, 0x24, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x54, 0x18, 0x30, 0x54, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x24, 0x3a, 0x14, 0x10, 0x08, 0x28, 0x54, 0x24, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x08, 0x14, 0x14, 0x08, 0x54, 0x22, 0x22, 0x5c, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x10, 0x10, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x20, 0x10, 0x10, 0x08, 0x08, 0x08, 0x08, 0x10, 0x10, 0x20, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x04, 0x08, 0x08, 0x10, 0x10, 0x10, 0x10, 0x08, 0x08, 0x04, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x10, 0x54, 0x38, 0x38, 0x54, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x7c, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x08, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x20, 0x20, 0x10, 0x10, 0x08, 0x08, 0x04, 0x04, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x18, 0x24, 0x42, 0x42, 0x42, 0x42, 0x24, 0x18, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x10, 0x18, 0x14, 0x10, 0x10, 0x10, 0x10, 0x7c, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x3c, 0x42, 0x40, 0x20, 0x18, 0x04, 0x02, 0x7e, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x3c, 0x42, 0x40, 0x38, 0x40, 0x40, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x20, 0x30, 0x28, 0x24, 0x22, 0x7e, 0x20, 0x20, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x7e, 0x02, 0x02, 0x3e, 0x42, 0x40, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x38, 0x04, 0x02, 0x3e, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x7e, 0x40, 0x20, 0x10, 0x08, 0x08, 0x04, 0x04, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x3c, 0x42, 0x42, 0x3c, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x3c, 0x42, 0x42, 0x42, 0x7c, 0x40, 0x20, 0x1c, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x00, 0x00, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x00, 0x00, 0x08, 0x08, 0x04, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x10, 0x08, 0x04, 0x08, 0x10, 0x20, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x08, 0x10, 0x20, 0x10, 0x08, 0x04, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x1c, 0x22, 0x20, 0x10, 0x08, 0x08, 0x00, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x3c, 0x42, 0x72, 0x4a, 0x4a, 0x72, 0x02, 0x3c, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x18, 0x24, 0x42, 0x42, 0x7e, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x3e, 0x42, 0x42, 0x3e, 0x42, 0x42, 0x42, 0x3e, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x3c, 0x42, 0x02, 0x02, 0x02, 0x02, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x3e, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3e, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x7c, 0x04, 0x04, 0x3c, 0x04, 0x04, 0x04, 0x7c, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x7c, 0x04, 0x04, 0x3c, 0x04, 0x04, 0x04, 0x04, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x3c, 0x42, 0x02, 0x72, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x42, 0x42, 0x42, 0x7e, 0x42, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x7c, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x7c, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x78, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x1c, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x44, 0x24, 0x14, 0x0c, 0x0c, 0x14, 0x24, 0x44, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x7c, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x82, 0xc6, 0xaa, 0xaa, 0x92, 0x92, 0x82, 0x82, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x42, 0x46, 0x4a, 0x4a, 0x52, 0x52, 0x62, 0x42, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x3c, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x3e, 0x42, 0x42, 0x42, 0x3e, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x3c, 0x42, 0x42, 0x42, 0x42, 0x4a, 0x52, 0x3c, 0x40, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x3e, 0x42, 0x42, 0x42, 0x3e, 0x12, 0x22, 0x42, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x3c, 0x42, 0x02, 0x3c, 0x40, 0x40, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x7c, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x82, 0x82, 0x44, 0x44, 0x28, 0x28, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x82, 0x82, 0x82, 0x92, 0x92, 0x92, 0x92, 0x6c, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0xc6, 0x44, 0x28, 0x10, 0x10, 0x28, 0x44, 0xc6, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x82, 0x82, 0x44, 0x28, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x7e, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x7e, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x38, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x38, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x04, 0x04, 0x08, 0x08, 0x10, 0x10, 0x20, 0x20, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x1c, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x1c, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x10, 0x28, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x10, 0x10, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x40, 0x7c, 0x42, 0x42, 0xbc, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x3a, 0x46, 0x42, 0x42, 0x42, 0x3e, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x42, 0x02, 0x02, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x40, 0x40, 0x5c, 0x62, 0x42, 0x42, 0x42, 0x7c, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x42, 0x7e, 0x02, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x70, 0x08, 0x08, 0x3c, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x1c, 0x22, 0x22, 0x1c, 0x02, 0x3c, 0x42, 0x3c, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x3a, 0x46, 0x42, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x10, 0x10, 0x00, 0x18, 0x10, 0x10, 0x10, 0x10, 0x7c, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x20, 0x20, 0x00, 0x38, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x1c, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x22, 0x12, 0x0e, 0x12, 0x22, 0x42, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x18, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x7c, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6e, 0x92, 0x92, 0x92, 0x82, 0x82, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3a, 0x46, 0x42, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x42, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3a, 0x46, 0x42, 0x42, 0x42, 0x3e, 0x02, 0x02, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x42, 0x42, 0x42, 0x62, 0x5c, 0x40, 0x40, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0x4c, 0x04, 0x04, 0x04, 0x04, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x42, 0x3c, 0x40, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x3c, 0x08, 0x08, 0x08, 0x48, 0x30, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x42, 0x42, 0x42, 0x62, 0x5c, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x44, 0x28, 0x28, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x82, 0x82, 0x92, 0x92, 0x92, 0x6c, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x24, 0x18, 0x18, 0x24, 0x66, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x42, 0x42, 0x42, 0x7c, 0x40, 0x42, 0x3c, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x20, 0x10, 0x08, 0x04, 0x7e, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x30, 0x08, 0x08, 0x10, 0x0c, 0x10, 0x08, 0x08, 0x08, 0x30, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x0c, 0x10, 0x10, 0x08, 0x30, 0x08, 0x10, 0x10, 0x10, 0x0c, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x4c, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0xfc, 0x12, 0x12, 0x72, 0x12, 0x12, 0x12, 0xfc, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6c, 0x92, 0xf2, 0x12, 0x92, 0x6c, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x24, 0x24, 0x00, 0x82, 0x82, 0x44, 0x28, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x10, 0x10, 0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x10, 0x10, 0x38, 0x54, 0x14, 0x54, 0x38, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x30, 0x48, 0x48, 0x08, 0x08, 0x3c, 0x08, 0x8c, 0x76, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x44, 0x38, 0x44, 0x44, 0x44, 0x38, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x44, 0x44, 0x28, 0x7c, 0x10, 0x7c, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x38, 0x44, 0x04, 0x38, 0x44, 0x44, 0x38, 0x40, 0x44, 0x38, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x24, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x7c, 0x82, 0xb2, 0x8a, 0x8a, 0xb2, 0x82, 0x7c, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x0c, 0x10, 0x1c, 0x12, 0x1c, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x24, 0x12, 0x24, 0x48, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x7e, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x7c, 0x82, 0x9a, 0xaa, 0x9a, 0xaa, 0x82, 0x7c, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x08, 0x14, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x7c, 0x10, 0x10, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x18, 0x24, 0x10, 0x08, 0x04, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x18, 0x24, 0x10, 0x20, 0x24, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x20, 0x10, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x24, 0x24, 0x12, 0x12, 0x6d, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x7c, 0x2e, 0x2e, 0x2e, 0x2c, 0x28, 0x28, 0x28, 0x28, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x18, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x08, 0x0c, 0x08, 0x08, 0x08, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x0c, 0x12, 0x12, 0x12, 0x0c, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x24, 0x48, 0x24, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x04, 0x06, 0x44, 0x24, 0x1e, 0x48, 0x64, 0x52, 0xf8, 0x40, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x04, 0x06, 0x44, 0x24, 0x1e, 0x68, 0x94, 0x42, 0x20, 0xf0, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x0c, 0x12, 0x08, 0x52, 0x2c, 0x50, 0x68, 0x54, 0xfa, 0x40, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x10, 0x10, 0x00, 0x10, 0x10, 0x10, 0x08, 0x04, 0x44, 0x38, 0x00, 0x00, 0x00,
+    0x00, 0x08, 0x10, 0x00, 0x18, 0x24, 0x42, 0x42, 0x7e, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x10, 0x08, 0x00, 0x18, 0x24, 0x42, 0x42, 0x7e, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x18, 0x24, 0x00, 0x18, 0x24, 0x42, 0x42, 0x7e, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x4c, 0x32, 0x00, 0x18, 0x24, 0x42, 0x42, 0x7e, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x24, 0x24, 0x00, 0x18, 0x24, 0x42, 0x42, 0x7e, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x18, 0x24, 0x18, 0x18, 0x24, 0x42, 0x42, 0x7e, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0xf8, 0x14, 0x14, 0x72, 0x1e, 0x12, 0x12, 0xf2, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x3c, 0x42, 0x02, 0x02, 0x02, 0x02, 0x42, 0x3c, 0x10, 0x08, 0x00, 0x00,
+    0x00, 0x08, 0x10, 0x00, 0x7c, 0x04, 0x04, 0x3c, 0x04, 0x04, 0x04, 0x7c, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x20, 0x10, 0x00, 0x7c, 0x04, 0x04, 0x3c, 0x04, 0x04, 0x04, 0x7c, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x30, 0x48, 0x00, 0x7c, 0x04, 0x04, 0x3c, 0x04, 0x04, 0x04, 0x7c, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x28, 0x28, 0x00, 0x7c, 0x04, 0x04, 0x3c, 0x04, 0x04, 0x04, 0x7c, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x08, 0x10, 0x00, 0x7c, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x7c, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x20, 0x10, 0x00, 0x7c, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x7c, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x10, 0x28, 0x00, 0x7c, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x7c, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x28, 0x28, 0x00, 0x7c, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x7c, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x38, 0x48, 0x48, 0x48, 0x5c, 0x48, 0x48, 0x38, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x4c, 0x32, 0x00, 0x42, 0x46, 0x4a, 0x4a, 0x52, 0x52, 0x62, 0x42, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x08, 0x10, 0x00, 0x3c, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x10, 0x08, 0x00, 0x3c, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x18, 0x24, 0x00, 0x3c, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x4c, 0x32, 0x00, 0x3c, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x24, 0x24, 0x00, 0x3c, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x28, 0x10, 0x28, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0xbc, 0x42, 0x62, 0x52, 0x52, 0x4a, 0x46, 0x3e, 0x01, 0x00, 0x00, 0x00,
+    0x00, 0x08, 0x10, 0x00, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x10, 0x08, 0x00, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x18, 0x24, 0x00, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x24, 0x24, 0x00, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x30, 0x08, 0x00, 0x82, 0x82, 0x44, 0x28, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x0e, 0x04, 0x3c, 0x44, 0x44, 0x3c, 0x04, 0x0e, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x38, 0x44, 0x44, 0x26, 0x44, 0x44, 0x44, 0x34, 0x02, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x08, 0x10, 0x00, 0x3c, 0x40, 0x7c, 0x42, 0x42, 0xbc, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x20, 0x10, 0x00, 0x3c, 0x40, 0x7c, 0x42, 0x42, 0xbc, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x18, 0x24, 0x00, 0x3c, 0x40, 0x7c, 0x42, 0x42, 0xbc, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x58, 0x34, 0x00, 0x3c, 0x40, 0x7c, 0x42, 0x42, 0xbc, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x48, 0x48, 0x00, 0x3c, 0x40, 0x7c, 0x42, 0x42, 0xbc, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x38, 0x44, 0x38, 0x00, 0x3c, 0x40, 0x7c, 0x42, 0x42, 0xbc, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6e, 0x90, 0xfc, 0x12, 0x92, 0x6c, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x42, 0x02, 0x02, 0x42, 0x3c, 0x08, 0x04, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x08, 0x10, 0x00, 0x3c, 0x42, 0x7e, 0x02, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x20, 0x10, 0x00, 0x3c, 0x42, 0x7e, 0x02, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x18, 0x24, 0x00, 0x3c, 0x42, 0x7e, 0x02, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x24, 0x24, 0x00, 0x3c, 0x42, 0x7e, 0x02, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x08, 0x10, 0x00, 0x18, 0x10, 0x10, 0x10, 0x10, 0x7c, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x10, 0x08, 0x00, 0x18, 0x10, 0x10, 0x10, 0x10, 0x7c, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x18, 0x24, 0x00, 0x18, 0x10, 0x10, 0x10, 0x10, 0x7c, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x28, 0x28, 0x00, 0x18, 0x10, 0x10, 0x10, 0x10, 0x7c, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x12, 0x0c, 0x0c, 0x12, 0x3c, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x58, 0x34, 0x00, 0x3a, 0x46, 0x42, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x08, 0x10, 0x00, 0x3c, 0x42, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x10, 0x08, 0x00, 0x3c, 0x42, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x18, 0x24, 0x00, 0x3c, 0x42, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x58, 0x34, 0x00, 0x3c, 0x42, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x24, 0x24, 0x00, 0x3c, 0x42, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x00, 0x7c, 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x7c, 0x62, 0x52, 0x4a, 0x46, 0x3e, 0x01, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x08, 0x10, 0x00, 0x42, 0x42, 0x42, 0x42, 0x62, 0x5c, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x10, 0x08, 0x00, 0x42, 0x42, 0x42, 0x42, 0x62, 0x5c, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x18, 0x24, 0x00, 0x42, 0x42, 0x42, 0x42, 0x62, 0x5c, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x24, 0x24, 0x00, 0x42, 0x42, 0x42, 0x42, 0x62, 0x5c, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x20, 0x10, 0x00, 0xc6, 0x44, 0x44, 0x28, 0x30, 0x10, 0x12, 0x0c, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x04, 0x3c, 0x44, 0x44, 0x3c, 0x04, 0x0e, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x28, 0x28, 0x00, 0xc6, 0x44, 0x44, 0x28, 0x28, 0x10, 0x12, 0x0c, 0x00, 0x00,
+    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+    0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa,
+    0x00, 0x00, 0x00, 0x08, 0x1c, 0x2a, 0x49, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x49, 0x2a, 0x1c, 0x08, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x08, 0x04, 0x02, 0xff, 0x02, 0x04, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x10, 0x20, 0x40, 0xff, 0x40, 0x20, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,
+};
+
+font_struct font_terminal_14italic = {
+    199,
+    1,
+    16,
+    8,
+    16,
+    8,
+    16,
+    3184,
+    font_terminal_14italic_data
+};
+
+/* End of font14norm.h */
diff --git a/sys/arch/arm32/dev/console/fonts/font_normal.h b/sys/arch/arm32/dev/console/fonts/font_normal.h
new file mode 100644 (file)
index 0000000..7a159a8
--- /dev/null
@@ -0,0 +1,265 @@
+/* $NetBSD: font_normal.h,v 1.1 1996/01/31 23:20:16 mark Exp $ */
+
+/*
+ * Copyright (c) 1994 Mark Brinicombe.
+ * Copyright (c) 1994 Brini.
+ * All rights reserved.
+ *
+ * This code is derived from software written for Brini by Mark Brinicombe
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided 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 Brini.
+ * 4. The name of the company nor the name of the author may be used to
+ *    endorse or promote products derived from this software without specific
+ *    prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BRINI ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL BRINI 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.
+ *
+ * RiscBSD kernel project
+ *
+ * font_terminal14_normal.h
+ *
+ * Font for physical console driver
+ *
+ * Created      : 18/09/94
+ * Last updated : 15/10/94
+ *
+ * Based on kate/display/14norm.h
+ *
+ *    $Id: font_normal.h,v 1.1.1.1 1996/04/24 11:08:38 deraadt Exp $
+ */
+unsigned char font_terminal_14normal_data[] = {
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x24, 0x24, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x24, 0x24, 0x7e, 0x24, 0x7e, 0x24, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x54, 0x18, 0x30, 0x54, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x24, 0x3a, 0x14, 0x10, 0x08, 0x28, 0x54, 0x24, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x08, 0x14, 0x14, 0x08, 0x54, 0x22, 0x22, 0x5c, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x10, 0x10, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x20, 0x10, 0x10, 0x08, 0x08, 0x08, 0x08, 0x10, 0x10, 0x20, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x04, 0x08, 0x08, 0x10, 0x10, 0x10, 0x10, 0x08, 0x08, 0x04, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x10, 0x54, 0x38, 0x38, 0x54, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x7c, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x08, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x20, 0x20, 0x10, 0x10, 0x08, 0x08, 0x04, 0x04, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x18, 0x24, 0x42, 0x42, 0x42, 0x42, 0x24, 0x18, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x10, 0x18, 0x14, 0x10, 0x10, 0x10, 0x10, 0x7c, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x3c, 0x42, 0x40, 0x20, 0x18, 0x04, 0x02, 0x7e, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x3c, 0x42, 0x40, 0x38, 0x40, 0x40, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x20, 0x30, 0x28, 0x24, 0x22, 0x7e, 0x20, 0x20, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x7e, 0x02, 0x02, 0x3e, 0x42, 0x40, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x38, 0x04, 0x02, 0x3e, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x7e, 0x40, 0x20, 0x10, 0x08, 0x08, 0x04, 0x04, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x3c, 0x42, 0x42, 0x3c, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x3c, 0x42, 0x42, 0x42, 0x7c, 0x40, 0x20, 0x1c, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x00, 0x00, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x00, 0x00, 0x08, 0x08, 0x04, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x10, 0x08, 0x04, 0x08, 0x10, 0x20, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x08, 0x10, 0x20, 0x10, 0x08, 0x04, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x1c, 0x22, 0x20, 0x10, 0x08, 0x08, 0x00, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x3c, 0x42, 0x72, 0x4a, 0x4a, 0x72, 0x02, 0x3c, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x18, 0x24, 0x42, 0x42, 0x7e, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x3e, 0x42, 0x42, 0x3e, 0x42, 0x42, 0x42, 0x3e, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x3c, 0x42, 0x02, 0x02, 0x02, 0x02, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x3e, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3e, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x7c, 0x04, 0x04, 0x3c, 0x04, 0x04, 0x04, 0x7c, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x7c, 0x04, 0x04, 0x3c, 0x04, 0x04, 0x04, 0x04, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x3c, 0x42, 0x02, 0x72, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x42, 0x42, 0x42, 0x7e, 0x42, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x7c, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x7c, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x78, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x1c, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x44, 0x24, 0x14, 0x0c, 0x0c, 0x14, 0x24, 0x44, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x7c, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x82, 0xc6, 0xaa, 0xaa, 0x92, 0x92, 0x82, 0x82, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x42, 0x46, 0x4a, 0x4a, 0x52, 0x52, 0x62, 0x42, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x3c, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x3e, 0x42, 0x42, 0x42, 0x3e, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x3c, 0x42, 0x42, 0x42, 0x42, 0x4a, 0x52, 0x3c, 0x40, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x3e, 0x42, 0x42, 0x42, 0x3e, 0x12, 0x22, 0x42, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x3c, 0x42, 0x02, 0x3c, 0x40, 0x40, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x7c, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x82, 0x82, 0x44, 0x44, 0x28, 0x28, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x82, 0x82, 0x82, 0x92, 0x92, 0x92, 0x92, 0x6c, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0xc6, 0x44, 0x28, 0x10, 0x10, 0x28, 0x44, 0xc6, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x82, 0x82, 0x44, 0x28, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x7e, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x7e, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x38, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x38, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x04, 0x04, 0x08, 0x08, 0x10, 0x10, 0x20, 0x20, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x1c, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x1c, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x10, 0x28, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x10, 0x10, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x40, 0x7c, 0x42, 0x42, 0xbc, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x3a, 0x46, 0x42, 0x42, 0x42, 0x3e, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x42, 0x02, 0x02, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x40, 0x40, 0x5c, 0x62, 0x42, 0x42, 0x42, 0x7c, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x42, 0x7e, 0x02, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x70, 0x08, 0x08, 0x3c, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x1c, 0x22, 0x22, 0x1c, 0x02, 0x3c, 0x42, 0x3c, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x3a, 0x46, 0x42, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x10, 0x10, 0x00, 0x18, 0x10, 0x10, 0x10, 0x10, 0x7c, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x20, 0x20, 0x00, 0x38, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x1c, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x22, 0x12, 0x0e, 0x12, 0x22, 0x42, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x18, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x7c, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6e, 0x92, 0x92, 0x92, 0x82, 0x82, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3a, 0x46, 0x42, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x42, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3a, 0x46, 0x42, 0x42, 0x42, 0x3e, 0x02, 0x02, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x42, 0x42, 0x42, 0x62, 0x5c, 0x40, 0x40, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0x4c, 0x04, 0x04, 0x04, 0x04, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x42, 0x3c, 0x40, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x3c, 0x08, 0x08, 0x08, 0x48, 0x30, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x42, 0x42, 0x42, 0x62, 0x5c, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x44, 0x28, 0x28, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x82, 0x82, 0x92, 0x92, 0x92, 0x6c, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x24, 0x18, 0x18, 0x24, 0x66, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x42, 0x42, 0x42, 0x7c, 0x40, 0x42, 0x3c, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x20, 0x10, 0x08, 0x04, 0x7e, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x30, 0x08, 0x08, 0x10, 0x0c, 0x10, 0x08, 0x08, 0x08, 0x30, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x0c, 0x10, 0x10, 0x08, 0x30, 0x08, 0x10, 0x10, 0x10, 0x0c, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x4c, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0xfc, 0x12, 0x12, 0x72, 0x12, 0x12, 0x12, 0xfc, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6c, 0x92, 0xf2, 0x12, 0x92, 0x6c, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x24, 0x24, 0x00, 0x82, 0x82, 0x44, 0x28, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x10, 0x10, 0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x10, 0x10, 0x38, 0x54, 0x14, 0x54, 0x38, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x30, 0x48, 0x48, 0x08, 0x08, 0x3c, 0x08, 0x8c, 0x76, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x44, 0x38, 0x44, 0x44, 0x44, 0x38, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x44, 0x44, 0x28, 0x7c, 0x10, 0x7c, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x38, 0x44, 0x04, 0x38, 0x44, 0x44, 0x38, 0x40, 0x44, 0x38, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x24, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x7c, 0x82, 0xb2, 0x8a, 0x8a, 0xb2, 0x82, 0x7c, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x0c, 0x10, 0x1c, 0x12, 0x1c, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x24, 0x12, 0x24, 0x48, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x7e, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x7c, 0x82, 0x9a, 0xaa, 0x9a, 0xaa, 0x82, 0x7c, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x08, 0x14, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x7c, 0x10, 0x10, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x18, 0x24, 0x10, 0x08, 0x04, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x18, 0x24, 0x10, 0x20, 0x24, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x20, 0x10, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x24, 0x24, 0x12, 0x12, 0x6d, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x7c, 0x2e, 0x2e, 0x2e, 0x2c, 0x28, 0x28, 0x28, 0x28, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x18, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x08, 0x0c, 0x08, 0x08, 0x08, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x0c, 0x12, 0x12, 0x12, 0x0c, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x24, 0x48, 0x24, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x04, 0x06, 0x44, 0x24, 0x1e, 0x48, 0x64, 0x52, 0xf8, 0x40, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x04, 0x06, 0x44, 0x24, 0x1e, 0x68, 0x94, 0x42, 0x20, 0xf0, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x0c, 0x12, 0x08, 0x52, 0x2c, 0x50, 0x68, 0x54, 0xfa, 0x40, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x10, 0x10, 0x00, 0x10, 0x10, 0x10, 0x08, 0x04, 0x44, 0x38, 0x00, 0x00, 0x00,
+    0x00, 0x08, 0x10, 0x00, 0x18, 0x24, 0x42, 0x42, 0x7e, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x10, 0x08, 0x00, 0x18, 0x24, 0x42, 0x42, 0x7e, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x18, 0x24, 0x00, 0x18, 0x24, 0x42, 0x42, 0x7e, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x4c, 0x32, 0x00, 0x18, 0x24, 0x42, 0x42, 0x7e, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x24, 0x24, 0x00, 0x18, 0x24, 0x42, 0x42, 0x7e, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x18, 0x24, 0x18, 0x18, 0x24, 0x42, 0x42, 0x7e, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0xf8, 0x14, 0x14, 0x72, 0x1e, 0x12, 0x12, 0xf2, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x3c, 0x42, 0x02, 0x02, 0x02, 0x02, 0x42, 0x3c, 0x10, 0x08, 0x00, 0x00,
+    0x00, 0x08, 0x10, 0x00, 0x7c, 0x04, 0x04, 0x3c, 0x04, 0x04, 0x04, 0x7c, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x20, 0x10, 0x00, 0x7c, 0x04, 0x04, 0x3c, 0x04, 0x04, 0x04, 0x7c, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x30, 0x48, 0x00, 0x7c, 0x04, 0x04, 0x3c, 0x04, 0x04, 0x04, 0x7c, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x28, 0x28, 0x00, 0x7c, 0x04, 0x04, 0x3c, 0x04, 0x04, 0x04, 0x7c, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x08, 0x10, 0x00, 0x7c, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x7c, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x20, 0x10, 0x00, 0x7c, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x7c, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x10, 0x28, 0x00, 0x7c, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x7c, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x28, 0x28, 0x00, 0x7c, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x7c, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x38, 0x48, 0x48, 0x48, 0x5c, 0x48, 0x48, 0x38, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x4c, 0x32, 0x00, 0x42, 0x46, 0x4a, 0x4a, 0x52, 0x52, 0x62, 0x42, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x08, 0x10, 0x00, 0x3c, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x10, 0x08, 0x00, 0x3c, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x18, 0x24, 0x00, 0x3c, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x4c, 0x32, 0x00, 0x3c, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x24, 0x24, 0x00, 0x3c, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x28, 0x10, 0x28, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0xbc, 0x42, 0x62, 0x52, 0x52, 0x4a, 0x46, 0x3e, 0x01, 0x00, 0x00, 0x00,
+    0x00, 0x08, 0x10, 0x00, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x10, 0x08, 0x00, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x18, 0x24, 0x00, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x24, 0x24, 0x00, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x30, 0x08, 0x00, 0x82, 0x82, 0x44, 0x28, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x0e, 0x04, 0x3c, 0x44, 0x44, 0x3c, 0x04, 0x0e, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x38, 0x44, 0x44, 0x26, 0x44, 0x44, 0x44, 0x34, 0x02, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x08, 0x10, 0x00, 0x3c, 0x40, 0x7c, 0x42, 0x42, 0xbc, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x20, 0x10, 0x00, 0x3c, 0x40, 0x7c, 0x42, 0x42, 0xbc, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x18, 0x24, 0x00, 0x3c, 0x40, 0x7c, 0x42, 0x42, 0xbc, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x58, 0x34, 0x00, 0x3c, 0x40, 0x7c, 0x42, 0x42, 0xbc, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x48, 0x48, 0x00, 0x3c, 0x40, 0x7c, 0x42, 0x42, 0xbc, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x38, 0x44, 0x38, 0x00, 0x3c, 0x40, 0x7c, 0x42, 0x42, 0xbc, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6e, 0x90, 0xfc, 0x12, 0x92, 0x6c, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x42, 0x02, 0x02, 0x42, 0x3c, 0x08, 0x04, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x08, 0x10, 0x00, 0x3c, 0x42, 0x7e, 0x02, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x20, 0x10, 0x00, 0x3c, 0x42, 0x7e, 0x02, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x18, 0x24, 0x00, 0x3c, 0x42, 0x7e, 0x02, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x24, 0x24, 0x00, 0x3c, 0x42, 0x7e, 0x02, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x08, 0x10, 0x00, 0x18, 0x10, 0x10, 0x10, 0x10, 0x7c, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x10, 0x08, 0x00, 0x18, 0x10, 0x10, 0x10, 0x10, 0x7c, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x18, 0x24, 0x00, 0x18, 0x10, 0x10, 0x10, 0x10, 0x7c, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x28, 0x28, 0x00, 0x18, 0x10, 0x10, 0x10, 0x10, 0x7c, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x12, 0x0c, 0x0c, 0x12, 0x3c, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x58, 0x34, 0x00, 0x3a, 0x46, 0x42, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x08, 0x10, 0x00, 0x3c, 0x42, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x10, 0x08, 0x00, 0x3c, 0x42, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x18, 0x24, 0x00, 0x3c, 0x42, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x58, 0x34, 0x00, 0x3c, 0x42, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x24, 0x24, 0x00, 0x3c, 0x42, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x00, 0x7c, 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x7c, 0x62, 0x52, 0x4a, 0x46, 0x3e, 0x01, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x08, 0x10, 0x00, 0x42, 0x42, 0x42, 0x42, 0x62, 0x5c, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x10, 0x08, 0x00, 0x42, 0x42, 0x42, 0x42, 0x62, 0x5c, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x18, 0x24, 0x00, 0x42, 0x42, 0x42, 0x42, 0x62, 0x5c, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x24, 0x24, 0x00, 0x42, 0x42, 0x42, 0x42, 0x62, 0x5c, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x20, 0x10, 0x00, 0xc6, 0x44, 0x44, 0x28, 0x30, 0x10, 0x12, 0x0c, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x04, 0x3c, 0x44, 0x44, 0x3c, 0x04, 0x0e, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x28, 0x28, 0x00, 0xc6, 0x44, 0x44, 0x28, 0x28, 0x10, 0x12, 0x0c, 0x00, 0x00,
+    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+    0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa,
+    0x00, 0x00, 0x00, 0x08, 0x1c, 0x2a, 0x49, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x49, 0x2a, 0x1c, 0x08, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x08, 0x04, 0x02, 0xff, 0x02, 0x04, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x10, 0x20, 0x40, 0xff, 0x40, 0x20, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,
+};
+
+font_struct font_terminal_14normal = {
+    199,
+    1,
+    16,
+    8,
+    16,
+    8,
+    16,
+    3184,
+    font_terminal_14normal_data
+};
+
+/* End of font14norm.h */
diff --git a/sys/arch/arm32/dev/console/fonts/font_wide.h b/sys/arch/arm32/dev/console/fonts/font_wide.h
new file mode 100644 (file)
index 0000000..c59c451
--- /dev/null
@@ -0,0 +1,259 @@
+/* $NetBSD: font_wide.h,v 1.1 1996/01/31 23:20:22 mark Exp $ */
+
+/*
+ * Copyright (c) 1994 Mark Brinicombe.
+ * Copyright (c) 1994 Brini.
+ * All rights reserved.
+ *
+ * This code is derived from software written for Brini by Mark Brinicombe
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided 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 Brini.
+ * 4. The name of the company nor the name of the author may be used to
+ *    endorse or promote products derived from this software without specific
+ *    prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BRINI ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL BRINI 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.
+ *
+ * RiscBSD kernel project
+ *
+ * font_terminal14_wide.h
+ *
+ * Font for physical console driver
+ *
+ * Created      : 18/09/94
+ * Last updated : 15/10/94
+ *
+ * Based on kate/display/14widen.h
+ *
+ *    $Id: font_wide.h,v 1.1.1.1 1996/04/24 11:08:38 deraadt Exp $
+ */
+unsigned char font_terminal_14widen_data[] = {
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 
+    0x00, 0x60, 0x00, 0x60, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 
+    0x00, 0x00, 0x00, 0x00, 0x30, 0x03, 0x30, 0x03, 0x30, 0x03, 0x00, 0x00, 0x00, 
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x98, 0x01, 0x98, 0x01, 0xfe, 0x07, 0x98, 
+    0x01, 0xfe, 0x07, 0x98, 0x01, 0x98, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0xfc, 0x03, 0x66, 0x04, 0xfc, 
+    0x03, 0x60, 0x06, 0x66, 0x06, 0xfc, 0x03, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x06, 0x44, 0x03, 0xb8, 0x01, 0xc0, 
+    0x00, 0x60, 0x00, 0xb0, 0x03, 0x58, 0x04, 0x8c, 0x03, 0x00, 0x00, 0x00, 0x00, 
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x98, 0x01, 0x98, 0x01, 0xf0, 
+    0x04, 0x8c, 0x05, 0x06, 0x03, 0x06, 0x03, 0xfc, 0x04, 0x00, 0x00, 0x00, 0x00, 
+    0x00, 0x00, 0x00, 0x00, 0xc0, 0x00, 0xc0, 0x00, 0x80, 0x00, 0x40, 0x00, 0x00, 
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+    0x00, 0x00, 0x00, 0x00, 0x80, 0x03, 0xc0, 0x00, 0x60, 0x00, 0x30, 0x00, 0x30, 
+    0x00, 0x30, 0x00, 0x30, 0x00, 0x60, 0x00, 0xc0, 0x00, 0x80, 0x03, 0x00, 0x00, 
+    0x00, 0x00, 0x00, 0x00, 0x38, 0x00, 0x60, 0x00, 0xc0, 0x00, 0x80, 0x01, 0x80, 
+    0x01, 0x80, 0x01, 0x80, 0x01, 0xc0, 0x00, 0x60, 0x00, 0x38, 0x00, 0x00, 0x00, 
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x66, 0x06, 0xf8, 0x01, 0xf8, 
+    0x01, 0x66, 0x06, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x60, 0x00, 0xfe, 
+    0x07, 0x60, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x30, 0x00, 0x18, 0x00, 0x00, 0x00, 
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 
+    0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x03, 0x80, 0x01, 0xc0, 
+    0x00, 0x60, 0x00, 0x30, 0x00, 0x18, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x0c, 0x03, 0x06, 0x06, 0x06, 
+    0x06, 0x06, 0x06, 0x06, 0x06, 0x0c, 0x03, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x60, 0x00, 0x70, 0x00, 0x78, 
+    0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0xfc, 0x03, 0x00, 0x00, 0x00, 0x00, 
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x03, 0x06, 0x06, 0x00, 0x06, 0x80, 
+    0x03, 0xe0, 0x01, 0x78, 0x00, 0x1e, 0x00, 0xfe, 0x07, 0x00, 0x00, 0x00, 0x00, 
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x03, 0x06, 0x06, 0x00, 0x06, 0xe0, 
+    0x03, 0x00, 0x06, 0x00, 0x06, 0x06, 0x06, 0xfc, 0x03, 0x00, 0x00, 0x00, 0x00, 
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0xc0, 0x01, 0xa0, 0x01, 0x90, 
+    0x01, 0x88, 0x01, 0x84, 0x01, 0xfe, 0x07, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x07, 0x06, 0x00, 0x06, 0x00, 0xfe, 
+    0x03, 0x06, 0x06, 0x00, 0x06, 0x06, 0x06, 0xfc, 0x03, 0x00, 0x00, 0x00, 0x00, 
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x03, 0x0c, 0x00, 0x06, 0x00, 0xfe, 
+    0x03, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0xfc, 0x03, 0x00, 0x00, 0x00, 0x00, 
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x03, 0x00, 0x03, 0x80, 0x01, 0xc0, 
+    0x00, 0x60, 0x00, 0x30, 0x00, 0x18, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x03, 0x06, 0x06, 0x06, 0x06, 0xfc, 
+    0x03, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0xfc, 0x03, 0x00, 0x00, 0x00, 0x00, 
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x03, 0x06, 0x06, 0x06, 0x06, 0x06, 
+    0x06, 0xfc, 0x07, 0x00, 0x06, 0x00, 0x03, 0xfc, 0x01, 0x00, 0x00, 0x00, 0x00, 
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x30, 
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x30, 
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x30, 0x00, 0x18, 0x00, 0x00, 0x00, 
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xc0, 0x00, 0x30, 
+    0x00, 0x0c, 0x00, 0x30, 0x00, 0xc0, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 
+    0x07, 0x00, 0x00, 0xfc, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x30, 0x00, 0xc0, 
+    0x00, 0x00, 0x03, 0xc0, 0x00, 0x30, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x03, 0x06, 0x06, 0x00, 0x06, 0xc0, 
+    0x03, 0x60, 0x00, 0x00, 0x00, 0x60, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x03, 0x06, 0x06, 0xc6, 0x07, 0x66, 
+    0x06, 0x66, 0x06, 0xc6, 0x07, 0x06, 0x00, 0xfc, 0x07, 0x00, 0x00, 0x00, 0x00, 
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x98, 0x01, 0x0c, 0x03, 0x0c, 
+    0x03, 0xfe, 0x07, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00, 
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x03, 0x06, 0x06, 0x06, 0x06, 0xfe, 
+    0x03, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0xfe, 0x03, 0x00, 0x00, 0x00, 0x00, 
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x03, 0x06, 0x06, 0x06, 0x00, 0x06, 
+    0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x06, 0xfc, 0x03, 0x00, 0x00, 0x00, 0x00, 
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x03, 0x06, 0x06, 0x06, 0x06, 0x06, 
+    0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0xfe, 0x03, 0x00, 0x00, 0x00, 0x00, 
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x07, 0x0c, 0x00, 0x0c, 0x00, 0xfc, 
+    0x03, 0x0c, 0x00, 0x0c, 0x00, 0x0c, 0x00, 0xfc, 0x07, 0x00, 0x00, 0x00, 0x00, 
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x07, 0x0c, 0x00, 0x0c, 0x00, 0x0c, 
+    0x00, 0xfc, 0x03, 0x0c, 0x00, 0x0c, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x03, 0x06, 0x06, 0x06, 0x00, 0x06, 
+    0x00, 0x86, 0x07, 0x06, 0x06, 0x06, 0x06, 0xfc, 0x03, 0x00, 0x00, 0x00, 0x00, 
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0xfe, 
+    0x07, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00, 
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x07, 0x60, 0x00, 0x60, 0x00, 0x60, 
+    0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0xfe, 0x07, 0x00, 0x00, 0x00, 0x00, 
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x07, 0x80, 0x01, 0x80, 0x01, 0x80, 
+    0x01, 0x80, 0x01, 0x80, 0x01, 0x86, 0x01, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x06, 0x86, 0x01, 0x66, 0x00, 0x1e, 
+    0x00, 0x1e, 0x00, 0x66, 0x00, 0x86, 0x01, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00, 
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x0c, 0x00, 0x0c, 0x00, 0x0c, 
+    0x00, 0x0c, 0x00, 0x0c, 0x00, 0x0c, 0x00, 0xfc, 0x07, 0x00, 0x00, 0x00, 0x00, 
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x06, 0x0e, 0x07, 0x9e, 0x07, 0xf6, 
+    0x06, 0x66, 0x06, 0x66, 0x06, 0x06, 0x06, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00, 
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x06, 0x0e, 0x06, 0x1e, 0x06, 0x36, 
+    0x06, 0x66, 0x06, 0xc6, 0x06, 0x86, 0x07, 0x06, 0x07, 0x00, 0x00, 0x00, 0x00, 
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x03, 0x06, 0x06, 0x06, 0x06, 0x06, 
+    0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0xfc, 0x03, 0x00, 0x00, 0x00, 0x00, 
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x03, 0x06, 0x06, 0x06, 0x06, 0x06, 
+    0x06, 0xfe, 0x03, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x03, 0x06, 0x06, 0x06, 0x06, 0x06, 
+    0x06, 0x06, 0x06, 0x06, 0x06, 0x86, 0x07, 0xfc, 0x03, 0x00, 0x06, 0x00, 0x00, 
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x03, 0x06, 0x06, 0x06, 0x06, 0x06, 
+    0x06, 0xfe, 0x03, 0x86, 0x01, 0x06, 0x03, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00, 
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x03, 0x06, 0x06, 0x06, 0x00, 0xfc, 
+    0x03, 0x00, 0x06, 0x00, 0x06, 0x06, 0x06, 0xfc, 0x03, 0x00, 0x00, 0x00, 0x00, 
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x07, 0x60, 0x00, 0x60, 0x00, 0x60, 
+    0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 
+    0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0xfc, 0x03, 0x00, 0x00, 0x00, 0x00, 
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 
+    0x06, 0x0c, 0x03, 0x98, 0x01, 0xf0, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x66, 
+    0x06, 0x66, 0x06, 0xf6, 0x06, 0x9c, 0x03, 0x08, 0x01, 0x00, 0x00, 0x00, 0x00, 
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x06, 0x0c, 0x03, 0x98, 0x01, 0xf0, 
+    0x00, 0xf0, 0x00, 0x98, 0x01, 0x0c, 0x03, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00, 
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x06, 0x0c, 0x03, 0x98, 0x01, 0xf0, 
+    0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x03, 0x80, 0x01, 0xc0, 0x00, 0x60, 
+    0x00, 0x30, 0x00, 0x18, 0x00, 0x0c, 0x00, 0xfe, 0x03, 0x00, 0x00, 0x00, 0x00, 
+    0x00, 0x00, 0x00, 0x00, 0xf0, 0x03, 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0x30, 
+    0x00, 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0xf0, 0x03, 0x00, 0x00, 
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x18, 0x00, 0x30, 0x00, 0x60, 
+    0x00, 0xc0, 0x00, 0x80, 0x01, 0x00, 0x03, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 
+    0x00, 0x00, 0x00, 0x00, 0xf8, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 
+    0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0xf8, 0x01, 0x00, 0x00, 
+    0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x98, 0x01, 0x06, 0x06, 0x00, 0x00, 0x00, 
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x07, 0x00, 0x00, 0x00, 0x00, 
+    0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x60, 0x00, 0x20, 0x00, 0x40, 0x00, 0x00, 
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x03, 0x00, 
+    0x06, 0xfc, 0x07, 0x06, 0x06, 0x06, 0x06, 0xfc, 0x0d, 0x00, 0x00, 0x00, 0x00, 
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x06, 0x00, 0xf6, 0x03, 0x0e, 
+    0x06, 0x06, 0x06, 0x06, 0x06, 0x0e, 0x06, 0xf6, 0x03, 0x00, 0x00, 0x00, 0x00, 
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x03, 0x06, 
+    0x06, 0x06, 0x00, 0x06, 0x00, 0x06, 0x06, 0xfc, 0x03, 0x00, 0x00, 0x00, 0x00, 
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x06, 0xfc, 0x06, 0x06, 
+    0x07, 0x06, 0x06, 0x06, 0x06, 0x06, 0x07, 0xfc, 0x06, 0x00, 0x00, 0x00, 0x00, 
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x03, 0x06, 
+    0x06, 0xfe, 0x07, 0x06, 0x00, 0x06, 0x06, 0xfc, 0x03, 0x00, 0x00, 0x00, 0x00, 
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x07, 0x18, 0x00, 0x18, 0x00, 0xfe, 
+    0x03, 0x18, 0x00, 0x18, 0x00, 0x18, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x07, 0x06, 
+    0x06, 0x06, 0x06, 0x06, 0x06, 0xfc, 0x07, 0x00, 0x06, 0x00, 0x03, 0xfc, 0x00, 
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x06, 0x00, 0xf6, 0x03, 0x0e, 
+    0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00, 
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x78, 0x00, 0x60, 
+    0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0xfe, 0x07, 0x00, 0x00, 0x00, 0x00, 
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0xe0, 0x03, 0x00, 
+    0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0xf8, 0x01, 
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x06, 0x00, 0x86, 0x01, 0x66, 
+    0x00, 0x1e, 0x00, 0x66, 0x00, 0x86, 0x01, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00, 
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 
+    0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0xfe, 0x07, 0x00, 0x00, 0x00, 0x00, 
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9e, 0x03, 0x66, 
+    0x06, 0x66, 0x06, 0x66, 0x06, 0x66, 0x06, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00, 
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf6, 0x03, 0x0e, 
+    0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00, 
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x03, 0x06, 
+    0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0xfc, 0x03, 0x00, 0x00, 0x00, 0x00, 
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf6, 0x03, 0x0e, 
+    0x06, 0x06, 0x06, 0x06, 0x06, 0x0e, 0x06, 0xf6, 0x03, 0x06, 0x00, 0x06, 0x00, 
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x06, 0x06, 
+    0x07, 0x06, 0x06, 0x06, 0x06, 0x06, 0x07, 0xfc, 0x06, 0x00, 0x06, 0x00, 0x06, 
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x03, 0x38, 
+    0x06, 0x18, 0x00, 0x18, 0x00, 0x18, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x03, 0x06, 
+    0x04, 0xfc, 0x03, 0x00, 0x06, 0x06, 0x06, 0xfc, 0x03, 0x00, 0x00, 0x00, 0x00, 
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x18, 0x00, 0xfe, 0x01, 0x18, 
+    0x00, 0x18, 0x00, 0x18, 0x00, 0x18, 0x00, 0xf0, 0x03, 0x00, 0x00, 0x00, 0x00, 
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x06, 0x06, 
+    0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x07, 0xfc, 0x06, 0x00, 0x00, 0x00, 0x00, 
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x06, 0x06, 
+    0x06, 0x0c, 0x03, 0x98, 0x01, 0xf0, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x06, 0x06, 
+    0x06, 0x66, 0x06, 0x66, 0x06, 0xf6, 0x06, 0x9c, 0x03, 0x00, 0x00, 0x00, 0x00, 
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x07, 0x98, 
+    0x01, 0xf0, 0x00, 0xf0, 0x00, 0x98, 0x01, 0x0e, 0x07, 0x00, 0x00, 0x00, 0x00, 
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x06, 0x06, 
+    0x06, 0x0c, 0x03, 0x98, 0x01, 0xf0, 0x00, 0x60, 0x00, 0x30, 0x00, 0x1c, 0x00, 
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x07, 0x00, 
+    0x07, 0xc0, 0x01, 0x70, 0x00, 0x1c, 0x00, 0xfc, 0x07, 0x00, 0x00, 0x00, 0x00, 
+    0x00, 0x00, 0x00, 0x00, 0xe0, 0x03, 0x30, 0x00, 0x30, 0x00, 0x60, 0x00, 0x3c, 
+    0x00, 0x60, 0x00, 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0xe0, 0x03, 0x00, 0x00, 
+    0x00, 0x00, 0x00, 0x00, 0xc0, 0x00, 0xc0, 0x00, 0xc0, 0x00, 0xc0, 0x00, 0xc0, 
+    0x00, 0xc0, 0x00, 0xc0, 0x00, 0xc0, 0x00, 0xc0, 0x00, 0xc0, 0x00, 0x00, 0x00, 
+    0x00, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x80, 0x01, 0x80, 0x01, 0xc0, 0x00, 0x80, 
+    0x07, 0xc0, 0x00, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0xf8, 0x00, 0x00, 0x00, 
+    0x00, 0x00, 0x00, 0x00, 0x3c, 0x06, 0x66, 0x06, 0xc6, 0x03, 0x00, 0x00, 0x00, 
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x07, 0x66, 0x00, 0x66, 0x00, 0xe6, 
+    0x01, 0x66, 0x00, 0x66, 0x00, 0x66, 0x00, 0xfc, 0x07, 0x00, 0x00, 0x00, 0x00, 
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x03, 0x66, 
+};
+
+font_struct font_terminal_14widen = {
+    193,
+    2,
+    13,
+    12,
+    13,
+    12,
+    13,
+    5018,
+    font_terminal_14widen_data
+};
+
+/* End of font14widen.h */
diff --git a/sys/arch/arm32/dev/console/vidc.c b/sys/arch/arm32/dev/console/vidc.c
new file mode 100644 (file)
index 0000000..e289593
--- /dev/null
@@ -0,0 +1,255 @@
+/* $NetBSD: vidc.c,v 1.2 1996/03/18 19:33:07 mark Exp $ */
+
+/*
+ * Copyright (c) 1994-1995 Melvyn Tang-Richardson
+ * Copyright (c) 1994-1995 RiscBSD kernel team
+ * 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 RiscBSD kernel team
+ * 4. The name of the company nor the name of the author may be used to
+ *    endorse or promote products derived from this software without specific
+ *    prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE RISCBSD TEAM ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS 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.
+ *
+ * RiscBSD kernel project
+ *
+ * vidc.c
+ *
+ * Old console ioctl declarations
+ *
+ * Created      : 17/09/94
+ */
+
+#include <sys/types.h>
+#include <machine/vidc.h>
+#include <machine/katelib.h>
+
+/* VIDC STUFF */
+
+/*
+ * A structure containing ALL the information required to restore
+ * the VIDC20 to any given state.  ALL vidc transactions should
+ * go through these procedures, which record the vidc's state.
+ * it may be an idea to set the permissions of the vidc base address
+ * so we get a fault, so the fault routine can record the state but
+ * I guess that's not really necessary for the time being, since we
+ * can make the kernel more secure later on.  Also, it is possible
+ * to write a routine to allow 'reading' of the vidc registers.
+ */
+
+struct vidc_state vidc_lookup = {      
+       { 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,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, 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,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, 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,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, 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,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,
+          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,0,0,0,0
+       },
+
+       VIDC_PALREG,
+       VIDC_BCOL,
+       VIDC_CP1 ,
+       VIDC_CP2,
+       VIDC_CP3,
+       VIDC_HCR,
+       VIDC_HSWR,
+       VIDC_HBSR,
+       VIDC_HDSR,
+       VIDC_HDER,
+       VIDC_HBER,
+       VIDC_HCSR,
+       VIDC_HIR,
+       VIDC_VCR,
+       VIDC_VSWR,
+       VIDC_VBSR,
+       VIDC_VDSR,
+       VIDC_VDER,
+       VIDC_VBER,
+       VIDC_VCSR,
+       VIDC_VCER,
+       VIDC_EREG,
+       VIDC_FSYNREG,
+       VIDC_CONREG,
+       VIDC_DCTL
+};
+
+struct vidc_state vidc_current[1];
+int
+vidc_write(reg, value)
+       u_int reg;
+       int value;
+{
+       int counter;
+
+       int *current;
+       int *tab;
+
+       tab     = (int *)&vidc_lookup;
+       current = (int *)vidc_current; 
+
+       /* End higly doddgy code */
+/*
+WriteWord ( VIDC_BASE, reg | value );
+return 1;
+*/
+
+       /*
+        * OK, the VIDC_PALETTE register is handled differently
+        * to the others on the VIDC, so take that into account here
+        */
+       if (reg==VIDC_PALREG) {
+               vidc_current->palreg = 0;
+               WriteWord ( VIDC_BASE, reg | value );
+               return 0;
+       }
+
+       if (reg==VIDC_PALETTE) {
+               WriteWord ( VIDC_BASE, reg | value );
+               vidc_current->palette[vidc_current->palreg] = value;
+               vidc_current->palreg++;
+               vidc_current->palreg = vidc_current->palreg & 0xff;
+               return 0;
+       }
+
+       /*
+        * Undefine SAFER if you wish to speed things up (a little)
+        * although this means the function will assume things abou
+        * the structure of vidc_state. i.e. the first 256 words are
+        * the palette array
+        */
+
+#define SAFER
+
+#ifdef         SAFER
+#define INITVALUE 0
+#else
+#define INITVALUE 256
+#endif
+
+       for ( counter=INITVALUE; counter<= sizeof(struct vidc_state); counter++ ) {
+               if ( reg==tab[counter] ) {
+                       WriteWord ( VIDC_BASE, reg | value );
+                       current[counter] = value;
+                       return 0;
+               }
+       }
+       return -1;
+}
+
+void
+vidc_setpalette(vidc)
+       struct vidc_state *vidc;
+{
+       int counter = 0;
+
+       vidc_write(VIDC_PALREG, 0x00000000);
+       for (counter = 0; counter < 255; counter++)
+               vidc_write(VIDC_PALETTE, vidc->palette[counter]);
+}
+
+void
+vidc_setstate(vidc)
+       struct vidc_state *vidc;
+{
+       vidc_write ( VIDC_PALREG,       vidc->palreg    );
+       vidc_write ( VIDC_BCOL,         vidc->bcol      );
+       vidc_write ( VIDC_CP1,          vidc->cp1       );
+       vidc_write ( VIDC_CP2,          vidc->cp2       );
+       vidc_write ( VIDC_CP3,          vidc->cp3       );
+       vidc_write ( VIDC_HCR,          vidc->hcr       );
+       vidc_write ( VIDC_HSWR,         vidc->hswr      );
+       vidc_write ( VIDC_HBSR,         vidc->hbsr      );
+       vidc_write ( VIDC_HDSR,         vidc->hdsr      );
+       vidc_write ( VIDC_HDER,         vidc->hder      );
+       vidc_write ( VIDC_HBER,         vidc->hber      );
+       vidc_write ( VIDC_HCSR,         vidc->hcsr      );
+       vidc_write ( VIDC_HIR,          vidc->hir       );
+       vidc_write ( VIDC_VCR,          vidc->vcr       );
+       vidc_write ( VIDC_VSWR,         vidc->vswr      );
+       vidc_write ( VIDC_VBSR,         vidc->vbsr      );
+       vidc_write ( VIDC_VDSR,         vidc->vdsr      );
+       vidc_write ( VIDC_VDER,         vidc->vder      );
+       vidc_write ( VIDC_VBER,         vidc->vber      );
+       vidc_write ( VIDC_VCSR,         vidc->vcsr      );
+       vidc_write ( VIDC_VCER,         vidc->vcer      );
+/*
+ * Right, dunno what to set these to yet, but let's keep RiscOS's
+ * ones for now, until the time is right to finish this code
+ */    
+
+/*     vidc_write ( VIDC_EREG,         vidc->ereg      );      */
+/*     vidc_write ( VIDC_FSYNREG,      vidc->fsynreg   );      */
+/*     vidc_write ( VIDC_CONREG,       vidc->conreg    );      */
+/*     vidc_write ( VIDC_DCTL,         vidc->dctl      );      */
+
+}
+
+
+void
+vidc_getstate(vidc)
+       struct vidc_state *vidc;
+{
+       *vidc = *vidc_current;
+}
+
+void
+vidc_stdpalette()
+{
+        WriteWord(VIDC_BASE, VIDC_PALREG | 0x00000000);
+        WriteWord(VIDC_BASE, VIDC_PALETTE | VIDC_COL(  0,   0,   0));
+        WriteWord(VIDC_BASE, VIDC_PALETTE | VIDC_COL(255,   0,   0));
+        WriteWord(VIDC_BASE, VIDC_PALETTE | VIDC_COL(  0, 255,   0));
+        WriteWord(VIDC_BASE, VIDC_PALETTE | VIDC_COL(255, 255,   0));
+        WriteWord(VIDC_BASE, VIDC_PALETTE | VIDC_COL(  0,   0, 255));
+        WriteWord(VIDC_BASE, VIDC_PALETTE | VIDC_COL(255,   0, 255));
+        WriteWord(VIDC_BASE, VIDC_PALETTE | VIDC_COL(  0, 255, 255));
+        WriteWord(VIDC_BASE, VIDC_PALETTE | VIDC_COL(255, 255, 255));
+        WriteWord(VIDC_BASE, VIDC_PALETTE | VIDC_COL(128, 128, 128));
+        WriteWord(VIDC_BASE, VIDC_PALETTE | VIDC_COL(255, 128, 128));
+        WriteWord(VIDC_BASE, VIDC_PALETTE | VIDC_COL(128, 255, 128));
+        WriteWord(VIDC_BASE, VIDC_PALETTE | VIDC_COL(255, 255, 128));
+        WriteWord(VIDC_BASE, VIDC_PALETTE | VIDC_COL(128, 128, 255));
+        WriteWord(VIDC_BASE, VIDC_PALETTE | VIDC_COL(255, 128, 255));
+        WriteWord(VIDC_BASE, VIDC_PALETTE | VIDC_COL(128, 255, 255));
+        WriteWord(VIDC_BASE, VIDC_PALETTE | VIDC_COL(255, 255, 255));
+}
+
+#if 0
+int
+vidc_col(red, green, blue)
+       int red;
+       int green;
+       int blue;
+{
+       red     = red   & 0xFF;
+       green   = green & 0xFF;
+       blue    = blue  & 0xFF;
+
+       return ( (blue<<16) + (green<<8) + red );
+}
+
+#endif
diff --git a/sys/arch/arm32/dev/console/vidc_mc.S b/sys/arch/arm32/dev/console/vidc_mc.S
new file mode 100644 (file)
index 0000000..d22ece5
--- /dev/null
@@ -0,0 +1,213 @@
+/* $NetBSD: vidc_mc.S,v 1.3 1996/03/18 19:33:08 mark Exp $ */
+
+/*
+ * Copyright (c) 1994-1995 Melvyn Tang-Richardson
+ * Copyright (c) 1994-1995 RiscBSD kernel team
+ * 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 RiscBSD kernel team
+ * 4. The name of the company nor the name of the author may be used to
+ *    endorse or promote products derived from this software without specific
+ *    prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE RISCBSD TEAM ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS 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.
+ *
+ * RiscBSD kernel project
+ *
+ * vidc_mc.S
+ *
+ * Console assembly functions
+ *
+ * Created      : 17/09/94
+ */
+
+#include "assym.h"
+#include <machine/iomd.h>
+
+lr     .req    r14
+pc     .req    r15
+sp     .req    r13
+
+.text
+       .global _vidcconsole_loadtab
+_vidcconsole_loadtab:
+       mov     r0, r0
+       ldmia   r0!, { r2     }
+       ldmia   r0!, { r2-r3  }
+       ldmia   r0!, { r2-r4  }
+       ldmia   r0!, { r2-r5  }
+       ldmia   r0!, { r2-r6  }
+       ldmia   r0!, { r2-r7  }
+       ldmia   r0!, { r2-r8  }
+       ldmia   r0!, { r2-r9  }
+       ldmia   r0!, { r2-r10 }
+       ldmia   r0!, { r2-r11 }
+       ldmia   r0!, { r2-r12 }
+       ldmia   r0!, { r2-r12, r14 }
+
+       .global _vidcconsole_storetab
+_vidcconsole_storetab:
+       mov     r0, r0
+       stmia   r0!, { r2     }
+       stmia   r0!, { r2-r3  }
+       stmia   r0!, { r2-r4  }
+       stmia   r0!, { r2-r5  }
+       stmia   r0!, { r2-r6  }
+       stmia   r0!, { r2-r7  }
+       stmia   r0!, { r2-r8  }
+       stmia   r0!, { r2-r9  }
+       stmia   r0!, { r2-r10 }
+       stmia   r0!, { r2-r11 }
+       stmia   r0!, { r2-r12 }
+       stmia   r0!, { r2-r12, r14 }
+
+       .global _vidcconsole_pushtab
+_vidcconsole_pushtab:
+       mov     r0, r0
+       stmfd   r13!, { r0-r3 }
+       stmfd   r13!, { r0-r7 }
+       stmfd   r13!, { r0-r11 }
+       stmfd   r13!, { r0-r14 }
+
+       .global _vidcconsole_poptab
+_vidcconsole_poptab:
+       mov     r0, r0
+       ldmfd   r13!, { r0-r3 }
+       ldmfd   r13!, { r0-r7 }
+       ldmfd   r13!, { r0-r11 }
+       ldmfd   r13!, { r0-r14 }
+
+       .global _vidcconsole_enter
+_vidcconsole_enter:
+       stmfd r13!, { r15 }
+
+       .global _vidcconsole_exit
+_vidcconsole_exit:
+       stmfd r13!, { r15 }
+
+       .global _vidcconsolemc_render
+
+       /* On entry r0 = addr */
+       /*          r1 = font */
+       /*          r2 = col  */
+       /*          r3 = xres */
+
+       /* Optimise for 8x16 font */
+       /* At the moment */
+
+_vidcconsolemc_render:
+
+       stmfd   r13!, {r0-r9, lr}
+
+       /* Generate colour mask */
+
+       mov     r9, r2, lsr #16
+       mov     r4, r2, lsr #8
+       and     r9, r9, #0xff
+       and     r4, r4, #0xff
+       and     r2, r2, #0xff
+
+       /* For each row (8 pixels) */
+
+xloop:
+       ldrb    r5, [r1], #1
+
+       mov     r7, #0
+       mov     r8, #0
+
+/* This loop will get *SOOOO* much faster with */
+/* the new algorithmn */
+       tst     r5, #8
+       orrne   r7, r2, r7, lsl #8
+       orreq   r7, r4, r7, lsl #8
+       tst     r5, #4
+       orrne   r7, r2, r7, lsl #8
+       orreq   r7, r4, r7, lsl #8
+       tst     r5, #2
+       orrne   r7, r2, r7, lsl #8
+       orreq   r7, r4, r7, lsl #8
+       tst     r5, #1
+       orrne   r7, r2, r7, lsl #8
+       orreq   r7, r4, r7, lsl #8
+       tst     r5, #0x80
+       orrne   r8, r2, r8, lsl #8
+       orreq   r8, r4, r8, lsl #8
+       tst     r5, #0x40
+       orrne   r8, r2, r8, lsl #8
+       orreq   r8, r4, r8, lsl #8
+       tst     r5, #0x20
+       orrne   r8, r2, r8, lsl #8
+       orreq   r8, r4, r8, lsl #8
+       tst     r5, #0x10
+       orrne   r8, r2, r8, lsl #8
+       orreq   r8, r4, r8, lsl #8
+
+       stmia   r0, {r7, r8}
+       add     r0, r0, r3
+
+       subs    r9, r9, #1
+       bne     xloop
+
+       ldmfd   r13!, {r0-r9, pc}
+
+       .global _vidcconsolemc_cls
+       
+       /* On entry r0 = start */
+       /*          r1 = end   */
+       /*          r2 = col   */
+
+
+_vidcconsolemc_cls:
+       stmfd   r13!, {r0-r9, lr}
+       
+       mov     r3, r2
+       mov     r4, r2
+       mov     r5, r2
+       mov     r6, r2
+       mov     r7, r2
+       mov     r8, r2
+       mov     r9, r2
+
+loop:
+       stmia   r0!, { r2-r9 }
+       stmia   r0!, { r2-r9 }
+       stmia   r0!, { r2-r9 }
+       stmia   r0!, { r2-r9 }
+       stmia   r0!, { r2-r9 }
+       stmia   r0!, { r2-r9 }
+       stmia   r0!, { r2-r9 }
+       stmia   r0!, { r2-r9 }
+       stmia   r0!, { r2-r9 }
+       stmia   r0!, { r2-r9 }
+       stmia   r0!, { r2-r9 }
+       stmia   r0!, { r2-r9 }
+       stmia   r0!, { r2-r9 }
+       stmia   r0!, { r2-r9 }
+       stmia   r0!, { r2-r9 }
+       stmia   r0!, { r2-r9 }
+       
+       cmp     r0, r1
+       ble     loop
+
+       ldmfd   r13!, {r0-r9, pc}
+
diff --git a/sys/arch/arm32/dev/console/vidcconsole.c b/sys/arch/arm32/dev/console/vidcconsole.c
new file mode 100644 (file)
index 0000000..bd8305e
--- /dev/null
@@ -0,0 +1,1818 @@
+/* $NetBSD: vidcconsole.c,v 1.7 1996/03/28 21:18:40 mark Exp $ */
+
+/*
+ * Copyright (c) 1996 Robert Black
+ * Copyright (c) 1994-1995 Melvyn Tang-Richardson
+ * Copyright (c) 1994-1995 RiscBSD kernel team
+ * 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 RiscBSD kernel team
+ * 4. The name of the company nor the name of the author may be used to
+ *    endorse or promote products derived from this software without specific
+ *    prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE RISCBSD TEAM ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS 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.
+ *
+ * RiscBSD kernel project
+ *
+ * vidcconsole.c
+ *
+ * Console assembly functions
+ *
+ * Created      : 17/09/94
+ * Last updated : 07/02/96
+ */
+
+/* woo */
+
+#include <sys/cdefs.h>
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/malloc.h>
+#include <sys/ioctl.h>
+#include <sys/conf.h>
+#include <sys/tty.h>
+#include <sys/device.h>
+#include <sys/map.h>
+#include <sys/proc.h>
+#include <sys/user.h>
+#include <sys/syslog.h>
+#include <sys/resourcevar.h>
+#include <vm/vm.h>
+
+#include <machine/cpu.h>
+#include <machine/param.h>
+#include <machine/katelib.h>
+#include <machine/cpu.h>
+#include <machine/bootconfig.h>
+#include <machine/iomd.h>
+#include <machine/irqhandler.h>
+#include <machine/pmap.h>
+#include <machine/vidc.h>
+#include <machine/vconsole.h>
+
+#include <arm32/dev/console/fonts/font_normal.h>
+#include <arm32/dev/console/fonts/font_bold.h>
+#include <arm32/dev/console/fonts/font_italic.h>
+
+
+#define BCOPY bcopy
+
+#ifndef DEBUGTERM
+#define dprintf(x)     ;
+#endif
+
+/* Options ************************************/
+#define ACTIVITY_WARNING
+#define SCREENBLANKER
+#undef INVERSE_CONSOLE
+/**********************************************/
+
+/* Internal defines only **********************/
+#define DEVLOPING
+#undef SELFTEST
+#undef SILLIES
+/**********************************************/
+
+#ifdef SILLIES
+#define PRETTYCURSOR
+#endif
+
+extern int physcon_major;
+extern struct vconsole *vconsole_default;
+
+extern videomemory_t videomemory;
+
+extern font_struct font_terminal_14normal;
+extern font_struct font_terminal_14bold;
+extern font_struct font_terminal_14italic;
+
+#define font_normal    font_terminal_14normal
+#define font_bold      font_terminal_14bold
+#define font_italic    font_terminal_14italic
+
+#define VIDC_ENGINE_NAME "VIDC"
+#define R_DATA ((struct vidc_info *)vc->r_data)
+#define MODE (R_DATA->mode)
+
+static int cold_init = 0;
+
+extern struct vconsole *vconsole_master;
+extern struct vconsole *vconsole_current;
+static struct vidc_mode vidc_initialmode;
+static struct vidc_mode *vidc_currentmode;
+
+unsigned int dispstart;
+unsigned int dispsize;
+unsigned int dispbase;
+unsigned int dispend;
+unsigned int ptov;
+unsigned int transfersize;
+unsigned int vmem_base;
+unsigned int phys_base;
+int    flash;
+int    cursor_flash;
+char *cursor_normal;
+char *cursor_transparent;
+int p_cursor_normal;
+int p_cursor_transparent;
+
+/* Local function prototypes */
+static void    vidcconsole_cls         __P(( struct vconsole */*vc*/ ));
+static int     vidc_cursor_init        __P(( struct vconsole */*vc*/ ));
+static int     vidcconsole_cursorintr  __P(( struct vconsole */*vc*/ ));
+int            vidcconsole_flashintr   __P(( struct vconsole */*vc*/ ));
+static int     vidcconsole_textpalette __P(( struct vconsole */*vc*/ ));
+static void    vidcconsole_render      __P(( struct vconsole */*vc*/, char /*c*/ ));
+static void    vidcconsole_mode        __P(( struct vconsole */*vc*/, struct vidc_mode */*mode*/ ));
+int            vidcconsole_flash       __P(( struct vconsole */*vc*/, int /*flash*/ ));
+int            vidcconsole_cursorflash __P(( struct vconsole */*vc*/, int /*flash*/ ));
+int            vidcconsole_flash_go    __P(( struct vconsole */*vc*/ ));
+int            vidcconsole_blank       __P(( struct vconsole */*vc*/, int /*type*/ ));
+void           vidcconsole_putchar     __P(( dev_t dev, char c, struct vconsole *vc));
+extern int     vidcconsolemc_cls       __P(( unsigned char *, unsigned char *, int ));
+
+void           (*line_cpfunc)          __P(( char *, char * ));
+
+/*
+ * This will be called while still in the mode that we were left
+ * in after exiting from riscos
+ */
+
+static irqhandler_t cursor_ih;
+irqhandler_t flash_ih;
+
+
+#ifndef HARDCODEDMODES
+/* The table of modes is separately compiled */
+extern struct vidc_mode vidcmodes[];
+#else /* HARDCODEDMODES */
+#ifdef RC7500
+static struct vidc_mode vidcmodes[] = {
+       {31500,/**/48,  84, 30, 640,  30, 0,/**/3, 28, 0, 480, 0, 9,/**/0,/**/3},
+       {36000,/**/72,  84, 34, 800,  34, 0,/**/2, 22, 0, 600, 0, 1,/**/0,/**/3},
+};
+#else /* RC7500 */
+/* We have a hard compiled table of modes and a list of definable modes */
+static struct vidc_mode vidcmodes[] = {
+       {32500,/**/52,  64, 30, 640,  30, 14,/**/3, 28, 0, 480, 0, 9,/**/0,/**/3},
+       {65000,/**/128, 36, 60, 1024, 60 ,36,/**/6, 29, 0, 768, 0, 3,/**/0,/**/3},
+};
+#endif /* RC7500 */
+#endif /* HARDCODEDMODES */
+
+#ifdef RC7500
+struct vfreq {
+       u_int frqcon;
+       int freq;
+};
+
+static struct vfreq vfreq[] = {
+       { VIDFREQ_25_18, 25175},
+       { VIDFREQ_25_18, 25180},
+       { VIDFREQ_28_32, 28320},
+       { VIDFREQ_31_50, 31500},
+       { VIDFREQ_36_00, 36000},
+       { VIDFREQ_40_00, 40000},
+       { VIDFREQ_44_90, 44900},
+       { VIDFREQ_50_00, 50000},
+       { VIDFREQ_65_00, 65000},
+       { VIDFREQ_72_00, 72000},
+       { VIDFREQ_75_00, 75000},
+       { VIDFREQ_77_00, 77000},
+       { VIDFREQ_80_00, 80000},
+       { VIDFREQ_94_50, 94500},
+       { VIDFREQ_110_0, 110000},
+       { VIDFREQ_120_0, 120000},
+       { VIDFREQ_130_0, 130000}
+};
+
+#define NFREQ  (sizeof (vfreq) / sizeof(struct vfreq))
+u_int vfreqcon = 0;
+#else /* RC7500 */
+
+struct fsyn {
+       int r, v, f;
+};
+
+static struct fsyn fsyn_pref[] = {
+       { 6,   2,  8000 },
+       { 4,   2, 12000 },
+       { 3,   2, 16000 },
+       { 2,   2, 24000 },
+       { 41, 43, 25171 },
+       { 50, 59, 28320 },
+       { 3,   4, 32000 },
+       { 2,   3, 36000 },
+       { 31, 58, 44903 },
+       { 12, 35, 70000 },
+       { 0,   0, 00000 }
+};
+#endif /* RC7500 */
+
+static inline int
+mod ( int n )
+{
+       if (n<0) return (-n);
+       else     return n;
+}
+
+static int
+vidcconsole_coldinit(vc)
+       struct vconsole *vc;
+{
+       int found;
+       int loop;
+
+       line_cpfunc = NULL;
+
+       /* Do this first so it dont look messy */
+
+       vidc_write ( VIDC_CP1, 0x0 );
+       vidc_write ( VIDC_CP2, 0x0 );
+       vidc_write ( VIDC_CP3, 0x0 );
+
+    /* Try to determine the current mode */
+       vidc_initialmode.hder = bootconfig.width+1;
+       vidc_initialmode.vder = bootconfig.height+1;
+/*
+       vidc_initialmode.hder = 1024;
+       vidc_initialmode.vder = 768;
+*/
+       vidc_initialmode.bitsperpixel = 1 << bootconfig.bitsperpixel;
+
+/* Nut - should be using videomemory.vidm_vbase - mark */
+
+       dispbase = vmem_base = dispstart = bootconfig.display_start;
+       phys_base = videomemory.vidm_pbase;
+
+/* Nut - should be using videomemory.vidm_size - mark */
+
+#ifdef RC7500
+       dispsize = videomemory.vidm_size;
+       transfersize = 16;
+#else /* RC7500 */
+       dispsize = bootconfig.vram[0].pages * NBPG;
+       transfersize = dispsize >> 10;
+#endif /* RC7500 */
+    
+       ptov = dispbase - phys_base;
+
+       dispend = dispstart+dispsize;
+       vidc_currentmode = &vidcmodes[0];
+       loop = 0;
+       found = 0;
+  
+       while (vidcmodes[loop].pixel_rate != 0) {
+               if (vidcmodes[loop].hder == (bootconfig.width + 1)
+                   && vidcmodes[loop].vder == (bootconfig.height + 1)
+                   && vidcmodes[loop].frame_rate == bootconfig.framerate) {
+                       vidc_currentmode = &vidcmodes[loop];
+                       found = 1;
+               }
+               ++loop;
+       }
+
+       if (!found) {
+               vidc_currentmode = &vidcmodes[0];
+               loop = 0;
+               found = 0;
+
+               while (vidcmodes[loop].pixel_rate != 0) {
+                       if (vidcmodes[loop].hder == (bootconfig.width + 1)
+                           && vidcmodes[loop].vder == (bootconfig.height + 1)) {
+                               vidc_currentmode = &vidcmodes[loop];
+                               found = 1;
+                       }
+                       ++loop;
+               }
+       }
+
+       /* vidc_currentmode = &vidcmodes[0];*/
+       vidc_currentmode->bitsperpixel = 1 << bootconfig.bitsperpixel;
+
+       R_DATA->flash = R_DATA->cursor_flash = 0;
+
+       dispstart = dispbase;
+       dispend = dispstart+dispsize;
+    
+       WriteWord ( IOMD_VIDINIT, dispstart-ptov );
+       WriteWord ( IOMD_VIDSTART, dispstart-ptov );
+       WriteWord ( IOMD_VIDEND, (dispend-transfersize)-ptov );
+       return 0;
+}
+
+struct vidc_mode newmode;
+
+static const int bpp_mask_table[] = {
+       0,  /* 1bpp */
+       1,  /* 2bpp */
+       2,  /* 4bpp */
+       3,  /* 8bpp */
+       4,  /* 16bpp */
+       6   /* 32bpp */
+};
+
+void
+vidcconsole_mode(vc, mode)
+       struct vconsole *vc;
+       struct vidc_mode *mode;
+{    
+       register int acc;
+       int bpp_mask;
+        int log_bpp;
+        int tmp_bpp;
+
+#ifndef RC7500
+       int best_r, best_v, best_match;
+#endif
+
+/*
+ * Find out what bit mask we need to or with the vidc20 control register
+ * in order to generate the desired number of bits per pixel.
+ * log_bpp is log base 2 of the number of bits per pixel.
+ */
+
+       tmp_bpp = mode->bitsperpixel;
+       if (tmp_bpp < 1 || tmp_bpp > 32)
+               tmp_bpp = 8; /* Set 8 bpp if we get asked for something silly */
+
+       for (log_bpp = 0; tmp_bpp != 1; tmp_bpp >>= 1)
+               log_bpp++;
+
+       bpp_mask = bpp_mask_table[log_bpp];
+
+/*
+       printf ( "res = (%d, %d) rate = %d\n", mode->hder, mode->vder, mode->pixel_rate );
+*/
+
+       newmode = *mode;
+       vidc_currentmode = &newmode;
+
+#ifdef RC7500
+       {
+               int i;
+               int old, new;
+               u_int nfreq;
+
+               old = vfreq[0].freq;
+               nfreq = vfreq[0].frqcon;
+               for (i = 0; i < (NFREQ - 1); i++) {
+                       new = vfreq[i].freq - mode->pixel_rate;
+                       if (new < 0)
+                               new = -new;
+                       if (new < old) {
+                               nfreq = vfreq[i].frqcon;
+                               old = new;
+                       }
+                       if (new == 0)
+                               break;
+               }
+               nfreq |= (vfreqcon & 0xf0);
+               vfreqcon = nfreq;
+       }
+#else /* RC7500 */
+    /* Program the VCO Look up a preferred value before choosing one */
+       {
+               int least_error = mod (fsyn_pref[0].f - vidc_currentmode->pixel_rate);
+               int counter;
+               best_r = fsyn_pref[0].r;
+               best_match = fsyn_pref[0].f;
+               best_v = fsyn_pref[0].v;
+        
+       /* Look up */
+        
+               counter=0;
+        
+               while ( fsyn_pref[counter].r != 0 ) {
+                       if (least_error > mod (fsyn_pref[counter].f - vidc_currentmode->pixel_rate)) {
+                               best_match = fsyn_pref[counter].f;
+                               least_error = mod (fsyn_pref[counter].f - vidc_currentmode->pixel_rate);
+                               best_r = fsyn_pref[counter].r;
+                               best_v = fsyn_pref[counter].v;
+                       }
+                       counter++;
+               }
+
+               if ( least_error > 0) { /* Accuracy of 1000Hz */
+                       int r, v, f;
+                       for ( v=63; v>0; v-- )
+                               for ( r=63; r>0; r-- ) {
+                                       f = (v * VIDC_FREF/1000) / r;
+                                       if (least_error >= mod (f - vidc_currentmode->pixel_rate)) {
+                                               best_match = f;
+                                               least_error = mod (f - vidc_currentmode->pixel_rate);
+                                               best_r = r;
+                                               best_v = v;
+                                       }
+                               }
+               }
+    
+               if ( best_r>63 ) best_r=63;
+               if ( best_v>63 ) best_v=63;
+               if ( best_r<1 )  best_r= 1;
+               if ( best_v<1 )  best_v= 1;
+    
+       }
+/*
+       printf ( "best_v = %d  best_r = %d best_f = %d\n", best_v, best_r, best_match );
+*/
+#endif /* RC7500 */
+
+       if (vc==vconsole_current) {
+#ifdef RC7500
+               outb(FREQCON, vfreqcon);
+               /*
+                * Need to program the control register first.
+                */
+               if ( dispsize>1024*1024 ) {
+                       if ( vidc_currentmode->hder>=800 )
+                               vidc_write ( VIDC_CONREG, 7<<8 | bpp_mask<<5);
+                       else
+                               vidc_write ( VIDC_CONREG, 6<<8 | bpp_mask<<5);
+               } else {
+                       vidc_write ( VIDC_CONREG, 7<<8 | bpp_mask<<5);
+               }
+
+               /*
+                * We don't use VIDC_FSYNREG.  Program it low.
+                */
+               vidc_write(VIDC_FSYNREG, 0x2020);
+#else /* RC7500 */
+               vidc_write ( VIDC_FSYNREG, (best_v-1)<<8 | (best_r-1)<<0 );
+#endif /* RC7500 */
+               acc=0;
+               acc+=vidc_currentmode->hswr;vidc_write(VIDC_HSWR,(acc  - 8  )& (~1)     );
+               acc+=vidc_currentmode->hbsr;vidc_write(VIDC_HBSR,(acc  - 12 )& (~1)     );
+               acc+=vidc_currentmode->hdsr;vidc_write(VIDC_HDSR,(acc  - 18 )& (~1)     );
+               acc+=vidc_currentmode->hder;vidc_write(VIDC_HDER,(acc  - 18 )& (~1)     );
+               acc+=vidc_currentmode->hber;vidc_write(VIDC_HBER,(acc  - 12 )& (~1)     );
+               acc+=vidc_currentmode->hcr ;vidc_write(VIDC_HCR ,(acc  - 8)&(~3));
+
+               acc=0;
+               acc+=vidc_currentmode->vswr;    vidc_write(VIDC_VSWR,(acc  - 1 ));
+               acc+=vidc_currentmode->vbsr;    vidc_write(VIDC_VBSR,(acc  - 1 ));
+               acc+=vidc_currentmode->vdsr;    vidc_write(VIDC_VDSR,(acc  - 1 ));
+               acc+=vidc_currentmode->vder;    vidc_write(VIDC_VDER,(acc  - 1 ));
+               acc+=vidc_currentmode->vber;    vidc_write(VIDC_VBER,(acc  - 1 ));
+               acc+=vidc_currentmode->vcr;             vidc_write(VIDC_VCR ,(acc  - 1 ));
+
+               WriteWord(IOMD_FSIZE, vidc_currentmode->vcr
+                   + vidc_currentmode->vswr
+                   + vidc_currentmode->vber
+                   + vidc_currentmode->vbsr - 1 );
+
+               if ( dispsize==1024*1024 )
+                       vidc_write ( VIDC_DCTL, vidc_currentmode->hder>>2 | 1<<16 | 1<<12);
+               else
+                       vidc_write ( VIDC_DCTL, vidc_currentmode->hder>>2 | 3<<16 | 1<<12);
+
+               vidc_write ( VIDC_EREG, 1<<12 );
+               if ( dispsize>1024*1024) {
+                       if ( vidc_currentmode->hder>=800 )
+                               vidc_write ( VIDC_CONREG, 7<<8 | bpp_mask<<5);
+                       else
+                               vidc_write ( VIDC_CONREG, 6<<8 | bpp_mask<<5);
+               } else {
+                       vidc_write ( VIDC_CONREG, 7<<8 | bpp_mask<<5);
+               }
+       }
+
+       R_DATA->mode = *vidc_currentmode;
+       R_DATA->screensize = R_DATA->XRES * R_DATA->YRES * R_DATA->BITSPERPIXEL/8;
+       R_DATA->pixelsperbyte = 8 / R_DATA->BITSPERPIXEL;
+       R_DATA->frontporch = MODE.hswr + MODE.hbsr + MODE.hdsr;
+       R_DATA->topporch = MODE.vswr + MODE.vbsr + MODE.vdsr;
+       R_DATA->bytes_per_line = R_DATA->XRES *
+           R_DATA->font->y_spacing/R_DATA->pixelsperbyte;
+       R_DATA->bytes_per_scroll = (vc->ycur % R_DATA->font->y_spacing)
+           * vc->xcur / R_DATA->pixelsperbyte;
+       R_DATA->text_width = R_DATA->XRES / R_DATA->font->x_spacing;
+       R_DATA->text_height = R_DATA->YRES / R_DATA->font->y_spacing;
+       vc->xchars = R_DATA->text_width;
+       vc->ychars = R_DATA->text_height;
+}
+
+void
+physcon_display_base(base)
+       u_int base;
+{
+       dispstart = dispstart-dispbase + base;
+       dispbase = vmem_base = base;
+       dispend = base + dispsize;
+       ptov = dispbase - phys_base;
+}
+
+static struct vidc_info masterinfo;
+static int cursor_init = 0;
+
+int
+vidcconsole_init(vc)
+       struct vconsole *vc;
+{
+       struct vidc_info *new;
+       int loop;
+
+       if ( cold_init==0 ) {
+               vidcconsole_coldinit ( vc );
+       } else {
+               if ( cursor_init == 0 )
+                       vidcconsole_flash_go ( vc );
+       }
+
+    /*
+     * If vc->r_data is initialised then this means that the previous
+     * render engine on this vconsole was not freed properly.  I should
+     * not try to clear it up, since I could panic the kernel.  Instead
+     * I forget about its memory, which could cause a memory leak, but
+     * this would be easily detectable and fixable
+     */
+     
+#ifdef SELFTEST
+       if ( vc->r_data != 0 ) {
+               printf( "*********************************************************\n" );
+               printf( "You have configured SELFTEST mode in the console driver\n" );
+               printf( "vc->rdata non zero.  This could mean a new console\n"      );
+               printf( "render engine has not freed up its data structure when\n"  );
+               printf( "exiting.\n"                                                 );
+               printf( "DO NOT COMPILE NON DEVELOPMENT KERNELS WITH SELFTEST\n"    );
+               printf( "*********************************************************" );
+       }
+#endif
+
+       if ( vc==vconsole_master ) {
+               vc->r_data = (char *)&masterinfo;
+       } else {
+               MALLOC ( (vc->r_data), char *, sizeof(struct vidc_info),
+                   M_DEVBUF, M_NOWAIT );
+       }
+    
+       if (vc->r_data==0)
+               panic ( "render engine initialisation failed.  CLEAN THIS UP!" );
+
+       R_DATA->normalfont = &font_normal;
+       R_DATA->italicfont = &font_italic;
+       R_DATA->boldfont   = &font_bold;
+       R_DATA->font = R_DATA->normalfont;
+
+       vidcconsole_mode ( vc, vidc_currentmode );
+       R_DATA->scrollback_end = dispstart;
+    
+       new = (struct vidc_info *)vc->r_data;
+
+       R_DATA->text_colours = 1 << R_DATA->BITSPERPIXEL;
+       if ( R_DATA->text_colours > 8 ) R_DATA->text_colours = 8;
+    
+#ifdef INVERSE_CONSOLE
+       R_DATA->n_backcolour = R_DATA->text_colours - 1;
+       R_DATA->n_forecolour = 0;
+#else
+       R_DATA->n_backcolour = 0;
+       R_DATA->n_forecolour = R_DATA->text_colours - 1;
+#endif
+
+       R_DATA->backcolour = R_DATA->n_backcolour;
+       R_DATA->forecolour = R_DATA->n_forecolour;
+
+       R_DATA->forefillcolour = 0;
+       R_DATA->backfillcolour = 0;
+
+       R_DATA->bold = 0;
+       R_DATA->reverse = 0;
+
+       for (loop = 0; loop < R_DATA->pixelsperbyte; ++loop) {
+               R_DATA->forefillcolour |= (R_DATA->forecolour <<
+                   loop * R_DATA->BITSPERPIXEL);
+               R_DATA->backfillcolour |= (R_DATA->backcolour <<
+                   loop * R_DATA->BITSPERPIXEL);
+       }
+
+       R_DATA->fast_render = R_DATA->forecolour | (R_DATA->backcolour<<8) | (R_DATA->font->pixel_height<<16);
+       R_DATA->blanked=0;
+       vc->BLANK ( vc, BLANK_NONE );
+    
+       if ( vc == vconsole_current )
+               vidcconsole_textpalette ( vc );
+
+       vidc_cursor_init ( vc ) ;
+
+       if ( cold_init == 0 ) {
+               vidc_write ( VIDC_CP1, 0x0 );
+               vidc_write ( VIDC_CP2, 0x0 );
+               vidc_write ( VIDC_CP3, 0x0 );
+       }
+       cold_init=1;
+       return 0;
+}
+
+void
+vidcconsole_putchar(dev, c, vc)
+       dev_t dev;
+       char c;
+       struct vconsole *vc;
+{
+       vc->PUTSTRING ( &c, 1, vc );
+}
+
+int
+vidcconsole_spawn(vc)
+       struct vconsole *vc;
+{
+       vc->xchars = R_DATA->text_width;
+       vc->ychars = R_DATA->text_height;
+       vc->xcur = 0;
+       vc->ycur = 0;
+       vc->flags = 0;
+       return 0;
+}
+
+int
+vidcconsole_redraw(vc, x, y, a, b)
+       struct vconsole *vc;
+       int x, y;
+       int a, b;
+{
+       int xs, ys;
+       struct vidc_state vidc;
+       font_struct *p_font = R_DATA->font;
+       int p_forecol = R_DATA->forecolour;
+       int p_backcol = R_DATA->backcolour;
+       if (x<0) x=0;
+       if (y<0) y=0;
+       if (x>(vc->xchars-1)) x=vc->xchars-1;
+       if (y>(vc->ychars-1)) x=vc->ychars-1;
+
+       if (a>(vc->xchars-1)) a=vc->xchars-1;
+       if (b>(vc->ychars-1)) b=vc->ychars-1;
+
+       if (a<x) a=x;
+       if (b<y) b=y;
+
+
+       vidc = *vidc_current;
+       xs=vc->xcur;
+       ys=vc->ycur;
+
+       vc->xcur = 0;
+       vc->ycur = 0;
+       if ( (vc->flags&LOSSY) == 0 )
+       {
+                register int c;
+                /* This has *GOT* to be turboed */
+                for ( vc->ycur=y; vc->ycur<=b; vc->ycur++ )
+                {
+                        for ( vc->xcur=x; vc->xcur<=a; vc->xcur++ )
+                        {
+                                c = (vc->charmap)[vc->xcur+vc->ycur*vc->xchars];
+                               if ((c&BOLD)!=0)
+                                       R_DATA->font = R_DATA->boldfont;
+                               else    
+                                       R_DATA->font = R_DATA->normalfont;
+R_DATA->fast_render = ((c>>8)&0x7)|(((c>>11)&0x7)<<8)| (R_DATA->font->pixel_height<<16);
+if ( c & BLINKING )
+ c+=1<<8 | 1;
+                               if ((c&BLINKING)!=0)
+                               {
+                                   R_DATA->forecolour+=16;
+                                   R_DATA->backcolour+=16;
+                               }
+                                vidcconsole_render( vc, c&0xff );
+                        }
+                }
+       }
+       vc->xcur = xs;
+       vc->ycur = ys;
+       R_DATA->forecolour = p_forecol;
+       R_DATA->backcolour = p_backcol;
+       R_DATA->font = p_font;
+       return 0;
+}
+
+
+int
+vidcconsole_swapin(vc)
+       struct vconsole *vc;
+{
+       register int counter;
+       int xs, ys;
+       struct vidc_state vidc;
+       font_struct *p_font = R_DATA->font;
+       int p_forecol = R_DATA->forecolour;
+       int p_backcol = R_DATA->backcolour;
+
+#ifdef ACTIVITY_WARNING
+       vconsole_pending = 0;
+#endif
+       vidc_write ( VIDC_CP1, 0x0 );
+
+       vidc = *vidc_current;
+       vidc_write ( VIDC_PALREG, 0x00000000 );
+       for ( counter=0; counter<255; counter++ )
+               vidc_write ( VIDC_PALETTE, 0x00000000 );
+       xs=vc->xcur;
+       ys=vc->ycur;
+/*TODO This needs to be vidc_restore (something) */
+        vidcconsole_mode ( vc, &MODE );
+
+       vc->xcur = 0;
+       vc->ycur = 0;
+       if ( (vc->flags&LOSSY) == 0 )
+       {
+                register int c;
+                /* This has *GOT* to be turboed */
+                for ( vc->ycur=0; vc->ycur<vc->ychars; vc->ycur++ )
+                {
+                        for ( vc->xcur=0; vc->xcur<vc->xchars; vc->xcur++ )
+                        {
+                                c = (vc->charmap)[vc->xcur+vc->ycur*vc->xchars];
+                               if ((c&BOLD)!=0)
+                                       R_DATA->font = R_DATA->boldfont;
+                               else    
+                                       R_DATA->font = R_DATA->normalfont;
+/*
+                               R_DATA->forecolour = ((c>>8)&0x7);
+                               R_DATA->backcolour = ((c>>11)&0x7);
+*/
+R_DATA->fast_render = ((c>>8)&0x7)|(((c>>11)&0x7)<<8)| (R_DATA->font->pixel_height<<16);
+if ( c & BLINKING )
+ c+=1<<8 | 1;
+                               if ((c&BLINKING)!=0)
+                               {
+                                   R_DATA->forecolour+=16;
+                                   R_DATA->backcolour+=16;
+                               }
+                                vidcconsole_render( vc, c&0xff );
+                        }
+                }
+       }
+       else
+       {
+           vc->CLS ( vc );
+       }
+
+       if ( vc->vtty==1 )
+       {
+           vc->xcur = xs;
+           vc->ycur = ys;
+           vidcconsole_textpalette ( vc );
+           vidc_write ( VIDC_CP1, 0xffffff );
+           R_DATA->forecolour = p_forecol;
+           R_DATA->backcolour = p_backcol;
+           R_DATA->font = p_font;
+       }
+/* Make the cursor blank */
+        WriteWord(IOMD_CURSINIT,p_cursor_transparent);
+       return 0;
+
+}
+
+int
+vidcconsole_mmap(vc, offset, nprot)
+       struct vconsole *vc;
+       int offset;
+       int nprot;
+{
+       if (offset > videomemory.vidm_size)
+               return (-1);
+       return(arm_byte_to_page(((videomemory.vidm_pbase) + (offset))));
+}
+
+extern void vidcconsolemc_render __P(( unsigned char *addr, unsigned char *fontaddr,
+                             int fast_render, int xres ));
+
+void
+vidcconsole_render(vc, c)
+       struct vconsole *vc;
+       char c;
+{
+       register unsigned char *fontaddr;
+       register unsigned char *addr;
+
+       /* Calculate the font's address */
+
+       fontaddr = R_DATA->font->data
+            + ((c-(0x20)) * R_DATA->font->height
+            * R_DATA->font->width);
+
+       addr = (unsigned char *)dispstart
+            + (vc->xcur * R_DATA->font->x_spacing)
+            + (vc->ycur * R_DATA->bytes_per_line);
+
+       vidcconsolemc_render ( addr, fontaddr, R_DATA->fast_render,
+           R_DATA->XRES );
+}
+
+/*
+ * Uugh.  vidc graphics dont support scrolling regions so we have to emulate
+ * it here.  This would normally require much software scrolling which is
+ * horriblly slow, so I'm going to try and do a composite scroll, which
+ * causes problems for scrollback but it's less speed critical
+ */
+
+void
+vidcconsole_scrollup(vc, low, high)
+       struct vconsole *vc;
+       int low;
+       int high;
+{
+    unsigned char *start, *end;
+
+    if ( ( low==0 ) && ( high==vc->ychars-1 ))
+    {
+       /* All hardware scroll */
+        dispstart+=R_DATA->bytes_per_line;
+        if ( dispstart >= dispend )
+           dispstart -= dispsize;
+
+       high=high+1;    /* Big hack */
+
+        WriteWord(IOMD_VIDINIT, dispstart - ptov );
+    }
+    else
+    {
+        char *oldstart=(char *)dispstart;
+
+       /* Composite scroll */
+
+       if ( (high-low) > (vc->ychars>>1) )
+       {
+           /* Scroll region greater than half the screen */
+
+            dispstart+=R_DATA->bytes_per_line;
+            if ( dispstart >= dispend ) dispstart -= dispsize;
+
+            WriteWord(IOMD_VIDINIT, dispstart - ptov );
+
+           if ( low!=0 )
+           {
+               start = (unsigned char *)oldstart;
+               end=(unsigned char*)oldstart+((low+1) * R_DATA->bytes_per_line);
+               BCOPY ( start, start+R_DATA->bytes_per_line,
+                   end-start-R_DATA->bytes_per_line);
+           }
+
+           if ( high!=(vc->ychars-1) )
+           {
+               start =(unsigned char *)dispstart+(high)*R_DATA->bytes_per_line;
+               end=(unsigned char*)dispstart+((vc->ychars)*R_DATA->bytes_per_line);
+               BCOPY ( start, start+R_DATA->bytes_per_line,
+                   end-start-R_DATA->bytes_per_line);
+           }
+           high++;
+       }
+       else
+       {
+           /* Scroll region less than half the screen */
+
+           /* NO COMPOSITE SCROLL YET */
+
+           high++;
+           if (low<0) low=0;
+           if (high>(vc->ychars)) high=vc->ychars;
+           if (low>high) return;       /* yuck */
+           start = (unsigned char *)dispstart + ((low)*R_DATA->bytes_per_line);
+           end = (unsigned char *)dispstart +  ((high)*R_DATA->bytes_per_line);
+           BCOPY ( start+R_DATA->bytes_per_line, start,
+               (end-start)-R_DATA->bytes_per_line );
+           R_DATA->scrollback_end = dispstart;
+       }
+    }
+    memset ( (char *) dispstart + ((high-1)*R_DATA->bytes_per_line) ,
+            R_DATA->backfillcolour,
+            R_DATA->bytes_per_line   );
+}
+
+void
+vidcconsole_scrolldown(vc, low, high)
+       struct vconsole *vc;
+       int low;
+       int high;
+{
+    unsigned char *start;
+    unsigned char *end;
+
+    if ( low<0 ) low = 0;
+    if ( high>(vc->ychars-1) ) high=vc->ychars-1;
+    
+    if ( ( low==0 ) && ( high==vc->ychars-1 ))
+    {
+        dispstart-=R_DATA->bytes_per_line;
+
+        if ( dispstart < dispbase )
+           dispstart += dispsize;
+
+        WriteWord(IOMD_VIDINIT, dispstart - ptov );
+    }
+    else
+    {
+       if ( ((high-low) > (vc->ychars>>1)) )
+       {
+high--;
+           if (high!=(vc->ychars-1))
+           {
+               start =(unsigned char*)dispstart+((high+1)*R_DATA->bytes_per_line);
+               end=(unsigned char*)dispstart+((vc->ychars)*R_DATA->bytes_per_line);
+               BCOPY ( start+R_DATA->bytes_per_line, start,
+                   (end-start)-R_DATA->bytes_per_line );
+           }
+
+            dispstart-=R_DATA->bytes_per_line;
+            if ( dispstart < dispbase )
+               dispstart += dispsize;
+            WriteWord(IOMD_VIDINIT, dispstart - ptov );
+           start = (unsigned char *)dispstart + (low * R_DATA->bytes_per_line);
+
+           if (low!=0)
+           {
+               end = (unsigned char *)dispstart + ((low+1)*R_DATA->bytes_per_line);
+               BCOPY ( (char*)(dispstart+R_DATA->bytes_per_line),
+                       (char *)dispstart,
+                   (int)((end-dispstart)-R_DATA->bytes_per_line ));
+           }
+       }
+        else
+       {
+           start = (unsigned char *)dispstart + (low * R_DATA->bytes_per_line);
+           end = (unsigned char *)dispstart  + ((high+1) * R_DATA->bytes_per_line);
+           BCOPY ( start, start+R_DATA->bytes_per_line, end-start-R_DATA->bytes_per_line);
+       }
+
+    }
+    memset ((char*) dispstart + (low*R_DATA->bytes_per_line) ,
+               R_DATA->backfillcolour, R_DATA->bytes_per_line );
+}
+
+void
+vidcconsole_cls(vc)
+       struct vconsole *vc;
+{
+#ifdef RC7500
+       dispstart = dispbase;
+       dispend = dispstart+dispsize;
+    
+       WriteWord ( IOMD_VIDINIT, dispstart-ptov );
+       WriteWord ( IOMD_VIDSTART, dispstart-ptov );
+       WriteWord ( IOMD_VIDEND, (dispend-transfersize)-ptov );
+#endif
+    
+       vidcconsolemc_cls ( (char *)dispstart, (char *)dispstart+R_DATA->screensize, R_DATA->backfillcolour );
+    /*
+       memset((char *)dispstart,
+               R_DATA->backfillcolour, R_DATA->screensize);
+    */  
+       vc->xcur = vc->ycur = 0;
+}
+
+void
+vidcconsole_update(vc)
+       struct vconsole *vc;
+{
+}
+
+static char vidcconsole_name[] = VIDC_ENGINE_NAME;
+
+static int scrollback_ptr = 0;
+
+int
+vidcconsole_scrollback(vc)
+       struct vconsole *vc;
+{
+       int temp;
+
+       if (scrollback_ptr==0)
+           scrollback_ptr=dispstart;
+
+       temp = scrollback_ptr;
+
+       scrollback_ptr-=R_DATA->bytes_per_line * (vc->ychars-2);
+       
+        if ( scrollback_ptr < dispbase )
+           scrollback_ptr += dispsize;
+
+       if (    (scrollback_ptr>dispstart)&&
+               (scrollback_ptr<(dispstart+R_DATA->screensize) ) )
+       {
+           scrollback_ptr=temp;
+           return 0;
+       }
+
+       vc->r_scrolledback = 1;
+
+        WriteWord(IOMD_VIDINIT, scrollback_ptr - ptov );
+       return 0;
+}
+
+int
+vidcconsole_scrollforward(vc)
+       struct vconsole *vc;
+{
+       register int temp;
+
+       if (scrollback_ptr==0)
+           return 0;
+       
+       temp = scrollback_ptr;
+
+       scrollback_ptr+=R_DATA->bytes_per_line * (vc->ychars - 2);
+       
+        if ( scrollback_ptr >= dispend )
+           scrollback_ptr -= dispsize;
+
+       if ( scrollback_ptr == dispstart )
+       {
+            WriteWord(IOMD_VIDINIT, scrollback_ptr - ptov );
+           scrollback_ptr=0;
+           vc->r_scrolledback = 0;
+           return 0;
+       }
+
+        WriteWord(IOMD_VIDINIT, scrollback_ptr - ptov );
+       return 0;
+}
+
+int
+vidcconsole_scrollbackend(vc)
+       struct vconsole *vc;
+{
+       scrollback_ptr = 0;
+        WriteWord(IOMD_VIDINIT, dispstart - ptov );
+       vc->r_scrolledback = 0;
+       return 0;
+}
+
+int
+vidcconsole_clreos(vc, code)
+       struct vconsole *vc;
+       int code;
+{
+    char *addr;
+    char *endofscreen;
+
+    addr = (unsigned char *)dispstart
+         + (vc->xcur * R_DATA->font->x_spacing)
+         + (vc->ycur * R_DATA->bytes_per_line);
+
+    endofscreen = (unsigned char *)dispstart
+         + (vc->xchars * R_DATA->font->x_spacing)
+         + (vc->ychars * R_DATA->bytes_per_line);
+
+
+       switch (code)
+       {
+               case 0:
+                       vidcconsolemc_cls ( addr, 
+                               (unsigned char *)dispend, 
+                               R_DATA->backfillcolour );
+                       if ((unsigned char *)endofscreen > (unsigned char *)dispend) {
+                               char string[80];
+                               sprintf(string, "(addr=%08x eos=%08x dispend=%08x dispstart=%08x base=%08x)",
+                                  (u_int)addr, (u_int)endofscreen, dispend, dispstart, dispbase);
+                               dprintf(string);
+                               vidcconsolemc_cls((unsigned char *)dispbase, (unsigned char *)(dispbase + (endofscreen - dispend)), R_DATA->backfillcolour);
+                       }
+                       break;
+
+               case 1:
+                       vidcconsolemc_cls ( (unsigned char *)dispstart+R_DATA->screensize, 
+                               addr, 
+                               R_DATA->backfillcolour );
+                       break;
+                       
+               case 2:
+               default:
+                       vidcconsole_cls ( vc );
+                       break;
+       }
+       return 0;
+}
+
+#define VIDC R_DATA->vidc
+
+int
+vidcconsole_debugprint(vc)
+       struct vconsole *vc;
+{
+#ifdef DEVLOPING
+    printf ( "VIDCCONSOLE DEBUG INFORMATION\n\n" );
+    printf ( "res (%d, %d) charsize (%d, %d) cursor (%d, %d)\n"
+                                                             , R_DATA->XRES, R_DATA->YRES
+                                                             , vc->xchars, vc->ychars, vc->xcur, vc->ycur );
+    printf ( "bytes_per_line %d\n"                           , R_DATA->bytes_per_line               );
+    printf ( "pixelsperbyte  %d\n"                           , R_DATA->pixelsperbyte                );
+    printf ( "dispstart      %08x\n"                         , dispstart                    );
+    printf ( "dispend        %08x\n"                         , dispend                      );
+    printf ( "screensize     %08x\n"                         , R_DATA->screensize                   );
+
+    printf ( "fontwidth      %08x\n"                         , R_DATA->font->pixel_width            );
+    printf ( "fontheight     %08x\n"                         , R_DATA->font->pixel_height           );
+    printf ( "\n"                                                                                   );
+    printf ( "palreg = %08x  bcol    = %08x\n"               , VIDC.palreg, VIDC.bcol               );
+    printf ( "cp1    = %08x  cp2     = %08x  cp3    = %08x\n" , VIDC.cp1, VIDC.cp2, VIDC.cp3         );
+    printf ( "hcr    = %08x  hswr    = %08x  hbsr   = %08x\n" , VIDC.hcr, VIDC.hswr, VIDC.hbsr       );
+    printf ( "hder   = %08x  hber    = %08x  hcsr   = %08x\n" , VIDC.hder, VIDC.hber, VIDC.hcsr      );
+    printf ( "hir    = %08x\n"                               , VIDC.hir                             );
+    printf ( "vcr    = %08x  vswr    = %08x  vbsr   = %08x\n" , VIDC.vcr, VIDC.vswr, VIDC.vbsr       );
+    printf ( "vder   = %08x  vber    = %08x  vcsr   = %08x\n" , VIDC.vder, VIDC.vber, VIDC.vcsr      );
+    printf ( "vcer   = %08x\n"                               , VIDC.vcer                            );
+    printf ( "ereg   = %08x  fsynreg = %08x  conreg = %08x\n" , VIDC.ereg, VIDC.fsynreg, VIDC.conreg );
+    printf ( "\n" );
+    printf ( "flash %08x, cursor_flash %08x", R_DATA->flash, R_DATA->cursor_flash );
+#else
+    printf ( "VIDCCONSOLE - NO DEBUG INFO\n" );
+#endif
+    return 0;
+}
+
+#ifdef NICE_UPDATE
+static int need_update = 0;
+
+void
+vidcconsole_updatecursor(arg)
+       void *arg;
+{
+       struct vconsole *vc = vconsole_current;
+
+       vidc_write(VIDC_HCSR, R_DATA->frontporch-17+ (vc->xcur)*R_DATA->font->pixel_width );
+       vidc_write(VIDC_VCSR, R_DATA->topporch-2+ (vc->ycur+1)*R_DATA->font->pixel_height-2 + 3
+           - R_DATA->font->pixel_height);
+       vidc_write(VIDC_VCER, R_DATA->topporch-2+ (vc->ycur+3)*R_DATA->font->pixel_height+2 + 3 );
+       return;
+}
+
+int
+vidcconsole_cursorupdate(vc)
+       struct vconsole *vc;
+{
+    timeout ( vidcconsole_updatecursor, NULL, 20 );
+    return 0;
+}
+
+#else
+
+static int
+vidcconsole_cursorupdate(vc)
+       struct vconsole *vc;
+{
+       vidc_write(VIDC_HCSR, R_DATA->frontporch-17+ (vc->xcur)*R_DATA->font->pixel_width );
+       vidc_write(VIDC_VCSR, R_DATA->topporch-2+ (vc->ycur+1)*R_DATA->font->pixel_height-2 + 3
+           - R_DATA->font->pixel_height);
+       vidc_write(VIDC_VCER, R_DATA->topporch-2+ (vc->ycur+3)*R_DATA->font->pixel_height+2 + 3 );
+       return (0);
+}
+
+#endif
+
+#define DEFAULT_CURSORSPEED (25)
+
+static int CURSORSPEED = DEFAULT_CURSORSPEED;
+
+static int
+vidcconsole_cursorflashrate(vc, rate)
+       struct vconsole *vc;
+       int rate;
+{
+       CURSORSPEED = 60/rate;
+}
+
+static int cursorcounter=DEFAULT_CURSORSPEED;
+static int flashcounter=DEFAULT_CURSORSPEED;
+#ifdef PRETTYCURSOR
+static int pretty=0xff;
+#endif
+
+static int cursor_col = 0x0;
+
+static int
+vidcconsole_cursorintr(vc)
+       struct vconsole *vc;
+{
+       if ( cursor_flash==0 )
+               return 0;
+
+       /*
+        * We don't need this.
+        */
+#ifndef RC7500
+       vconsole_blankcounter--;
+
+       if ( vconsole_blankcounter<0 ) {
+               vconsole_blankcounter=vconsole_blankinit;
+               vidcconsole_blank ( vc, BLANK_OFF );
+       }
+#endif
+
+       cursorcounter--;
+       if (cursorcounter<=0) {
+               cursorcounter=CURSORSPEED;
+               cursor_col = cursor_col ^ 0xffffff;
+#ifdef ACTIVITY_WARNING
+               if (vconsole_pending)  {
+                       if ( cursor_col==0 )
+                               WriteWord(IOMD_CURSINIT,p_cursor_transparent);
+                       else
+                               WriteWord(IOMD_CURSINIT,p_cursor_normal);
+                       vidc_write ( VIDC_CP1, cursor_col&0xff );
+               } else
+#endif
+               {
+                       if ( cursor_col==0 )
+                               WriteWord(IOMD_CURSINIT,p_cursor_transparent);
+                       else
+                               WriteWord(IOMD_CURSINIT,p_cursor_normal);
+                       vidc_write ( VIDC_CP1, 0xffffff );
+               }
+       }
+       return(0);
+}
+
+int
+vidcconsole_flashintr(vc)
+       struct vconsole *vc;
+{
+       if ( flash==0 )
+               return 0;
+
+       flashcounter--;
+       if (flashcounter<=0) {
+               flashcounter=CURSORSPEED;
+               if ( cursor_col == 0 ) {
+
+                       vidc_write(VIDC_PALREG, 0x00000010);
+                       vidc_write(VIDC_PALETTE, VIDC_COL(  0,   0,   0));
+                       vidc_write(VIDC_PALETTE, VIDC_COL(255,   0,   0));
+                       vidc_write(VIDC_PALETTE, VIDC_COL(  0, 255,   0));
+                       vidc_write(VIDC_PALETTE, VIDC_COL(255, 255,   0));
+                       vidc_write(VIDC_PALETTE, VIDC_COL(  0,   0, 255));
+                       vidc_write(VIDC_PALETTE, VIDC_COL(255,   0, 255));
+                       vidc_write(VIDC_PALETTE, VIDC_COL(  0, 255, 255));
+                       vidc_write(VIDC_PALETTE, VIDC_COL(255, 255, 255));
+                       vidc_write(VIDC_PALETTE, VIDC_COL(128, 128, 128));
+                       vidc_write(VIDC_PALETTE, VIDC_COL(255, 128, 128));
+                       vidc_write(VIDC_PALETTE, VIDC_COL(128, 255, 128));
+                       vidc_write(VIDC_PALETTE, VIDC_COL(255, 255, 128));
+                       vidc_write(VIDC_PALETTE, VIDC_COL(128, 128, 255));
+                       vidc_write(VIDC_PALETTE, VIDC_COL(255, 128, 255));
+                       vidc_write(VIDC_PALETTE, VIDC_COL(255, 255, 255));
+               } else {
+                       vidc_write(VIDC_PALREG, 0x00000010);
+                       vidc_write(VIDC_PALETTE, VIDC_COL(  0,   0,   0));
+                       vidc_write(VIDC_PALETTE, VIDC_COL(  0,   0,   0));
+                       vidc_write(VIDC_PALETTE, VIDC_COL(  0,   0,   0));
+                       vidc_write(VIDC_PALETTE, VIDC_COL(  0,   0,   0));
+                       vidc_write(VIDC_PALETTE, VIDC_COL(  0,   0,   0));
+                       vidc_write(VIDC_PALETTE, VIDC_COL(  0,   0,   0));
+                       vidc_write(VIDC_PALETTE, VIDC_COL(  0,   0,   0));
+                       vidc_write(VIDC_PALETTE, VIDC_COL(  0,   0,   0));
+                       vidc_write(VIDC_PALETTE, VIDC_COL(  0,   0,   0));
+                       vidc_write(VIDC_PALETTE, VIDC_COL(  0,   0,   0));
+                       vidc_write(VIDC_PALETTE, VIDC_COL(  0,   0,   0));
+                       vidc_write(VIDC_PALETTE, VIDC_COL(  0,   0,   0));
+                       vidc_write(VIDC_PALETTE, VIDC_COL(  0,   0,   0));
+                       vidc_write(VIDC_PALETTE, VIDC_COL(  0,   0,   0));
+                       vidc_write(VIDC_PALETTE, VIDC_COL(  0,   0,   0));
+                       vidc_write(VIDC_PALETTE, VIDC_COL(  0,   0,   0));
+               }
+       }
+       return(0);
+}
+
+static int
+vidc_cursor_init(vc)
+       struct vconsole *vc;
+{
+       extern char *cursor_data;
+       int counter;
+       int line;
+
+       /* Blank the cursor while initialising it's sprite */
+
+       vidc_write ( VIDC_CP1, 0x0 );
+       vidc_write ( VIDC_CP2, 0x0 );
+       vidc_write ( VIDC_CP3, 0x0 );
+
+       cursor_normal       = cursor_data;
+       cursor_transparent  = cursor_data + (R_DATA->font->pixel_height *
+                                       R_DATA->font->pixel_width);
+
+       cursor_transparent += 32;
+       cursor_transparent = (char *)((int)cursor_transparent & (~31) );
+
+       for ( line = 0; line<R_DATA->font->pixel_height; ++ line )
+       {
+           for ( counter=0; counter<R_DATA->font->pixel_width/4;counter++ )
+               cursor_normal[line*R_DATA->font->pixel_width + counter]=0x55;
+           for ( ; counter<8; counter++ )
+               cursor_normal[line*R_DATA->font->pixel_width + counter]=0;
+       }
+
+       for ( line = 0; line<R_DATA->font->pixel_height; ++ line )
+       {
+           for ( counter=0; counter<R_DATA->font->pixel_width/4;counter++ )
+               cursor_transparent[line*R_DATA->font->pixel_width + counter]=0x00;
+           for ( ; counter<8; counter++ )
+               cursor_transparent[line*R_DATA->font->pixel_width + counter]=0;
+       }
+
+
+       p_cursor_normal = pmap_extract(kernel_pmap,(vm_offset_t)cursor_normal );
+       p_cursor_transparent = pmap_extract(kernel_pmap,(vm_offset_t)cursor_transparent);
+
+/*
+       memset ( cursor_normal, 0x55,
+               R_DATA->font->pixel_width*R_DATA->font->pixel_height );
+
+       memset ( cursor_transparent, 0x55,
+               R_DATA->font->pixel_width*R_DATA->font->pixel_height );
+*/
+
+       /* Ok, now see the cursor */
+
+       vidc_write ( VIDC_CP1, 0xffffff );
+        return 0;
+}
+
+int
+vidcconsole_setfgcol(vc, col)
+       struct vconsole *vc;
+       int col;
+{
+       register int loop;
+
+       if ( R_DATA->forecolour >= 16 )
+               R_DATA->forecolour=16;
+       else
+               R_DATA->forecolour=0;
+    
+       R_DATA->forefillcolour = 0;
+    
+       R_DATA->forecolour += col;
+    
+/*TODO
+       if ( R_DATA->forecolour >> 1<<R_DATA->BITSPERPIXEL )
+               R_DATA->forecolour>>1;
+*/
+
+       for (loop = 0; loop < R_DATA->pixelsperbyte; ++loop) {
+               R_DATA->forefillcolour |= (R_DATA->forecolour <<
+                   loop * R_DATA->BITSPERPIXEL);
+       }
+       R_DATA->fast_render = R_DATA->forecolour | (R_DATA->backcolour<<8) | (R_DATA->font->pixel_height<<16);
+       return 0;
+}
+
+int
+vidcconsole_setbgcol(vc, col)
+       struct vconsole *vc;
+       int col;
+{
+       register int loop;
+
+       if ( R_DATA->backcolour >= 16 )
+               R_DATA->backcolour=16;
+       else
+               R_DATA->backcolour=0;
+
+       R_DATA->backfillcolour = 0;
+       R_DATA->backcolour += col;
+ /*TODO   
+       if ( R_DATA->backcolour >> 1<<R_DATA->BITSPERPIXEL )
+               R_DATA->backcolour>>1;
+*/
+
+       for (loop = 0; loop < R_DATA->pixelsperbyte; ++loop) {
+               R_DATA->backfillcolour |= (R_DATA->backcolour <<
+                   loop * R_DATA->BITSPERPIXEL);
+       }
+       return 0;
+}
+
+int
+vidcconsole_textpalette(vc)
+       struct vconsole *vc;
+{
+        R_DATA->forecolour = COLOUR_WHITE_8;
+        R_DATA->backcolour = COLOUR_BLACK_8;
+
+        vidc_write( VIDC_PALREG , 0x00000000);
+        vidc_write( VIDC_PALETTE , VIDC_COL(  0,   0,   0));
+        vidc_write( VIDC_PALETTE , VIDC_COL(255,   0,   0));
+        vidc_write( VIDC_PALETTE , VIDC_COL(  0, 255,   0));
+        vidc_write( VIDC_PALETTE , VIDC_COL(255, 255,   0));
+        vidc_write( VIDC_PALETTE , VIDC_COL(  0,   0, 255));
+        vidc_write( VIDC_PALETTE , VIDC_COL(255,   0, 255));
+        vidc_write( VIDC_PALETTE , VIDC_COL(  0, 255, 255));
+        vidc_write( VIDC_PALETTE , VIDC_COL(255, 255, 255));
+        vidc_write( VIDC_PALETTE , VIDC_COL(128, 128, 128));
+        vidc_write( VIDC_PALETTE , VIDC_COL(255, 128, 128));
+        vidc_write( VIDC_PALETTE , VIDC_COL(128, 255, 128));
+        vidc_write( VIDC_PALETTE , VIDC_COL(255, 255, 128));
+        vidc_write( VIDC_PALETTE , VIDC_COL(128, 128, 255));
+        vidc_write( VIDC_PALETTE , VIDC_COL(255, 128, 255));
+        vidc_write( VIDC_PALETTE , VIDC_COL(255, 255, 255));
+
+R_DATA->fast_render = R_DATA->forecolour | (R_DATA->backcolour<<8) | (R_DATA->font->pixel_height<<16);
+    return 0;
+}
+
+int
+vidcconsole_sgr (vc, type)
+       struct vconsole *vc;
+       int type;
+{
+    switch ( type )
+    {
+        case 0: /* Normal */
+           if (R_DATA->BITSPERPIXEL == 8)
+           {
+               R_DATA->n_forecolour = COLOUR_WHITE_8;
+               R_DATA->n_backcolour = COLOUR_BLACK_8;
+           }
+
+           R_DATA->forecolour = R_DATA->n_forecolour;
+            R_DATA->backcolour = R_DATA->n_backcolour;
+            R_DATA->font = R_DATA->normalfont;
+            break;
+
+       case 1: /* bold */
+            R_DATA->font = R_DATA->boldfont;
+           break;      
+
+       case 22: /* not bold */
+            R_DATA->font = R_DATA->normalfont;
+           break;      
+
+        case 5:        /* blinking */
+           if ( R_DATA->forecolour < 16 )
+           {
+               R_DATA->forecolour+=16;
+               R_DATA->backcolour+=16;
+               R_DATA->n_forecolour+=16;
+               R_DATA->n_backcolour+=16;
+           }
+           break;
+
+        case 25: /* not blinking */
+           if ( R_DATA->forecolour >= 16 )
+           {
+               R_DATA->forecolour-=16;
+               R_DATA->backcolour-=16;
+               R_DATA->n_forecolour-=16;
+               R_DATA->n_backcolour-=16;
+           }
+           break;
+
+        case 7: /* reverse */
+           R_DATA->forecolour = R_DATA->n_backcolour;
+            R_DATA->backcolour = R_DATA->n_forecolour;
+           break;
+            
+        case 27: /* not reverse */
+           R_DATA->forecolour = R_DATA->n_forecolour;
+            R_DATA->backcolour = R_DATA->n_backcolour;
+           break;
+    }
+R_DATA->fast_render = R_DATA->forecolour | (R_DATA->backcolour<<8) | (R_DATA->font->pixel_height<<16);
+    return 0;
+}
+
+int
+vidcconsole_scrollregion(vc, low, high)
+       struct vconsole *vc;
+       int low;
+       int high;
+{
+    return 0;
+}
+
+int
+vidcconsole_blank(vc, type)
+       struct vconsole *vc;
+       int type;
+{
+       vc->blanked=type;
+       switch (type) {
+       case 0:
+#ifdef RC7500
+               vidc_write ( VIDC_EREG, 0x51<<12 );
+#else
+               vidc_write ( VIDC_EREG, 1<<12 );
+#endif
+               break;
+               
+       case 1: /* not implemented yet */
+       case 2:
+       case 3:
+               vidc_write ( VIDC_EREG, 0 );
+               break;
+       }
+       return 0;
+}
+
+extern struct tty *find_tp __P((dev_t dev));
+
+int vidcconsole_ioctl ( struct vconsole *vc, dev_t dev, int cmd, caddr_t data,
+                       int flag, struct proc *p )
+{
+       int error;
+       struct tty *tp;
+       struct winsize ws;
+       switch ( cmd )
+       {
+               case CONSOLE_MODE:
+                       tp = find_tp(dev);
+                       printf ( "mode ioctl called\n" );
+                       vidcconsole_mode ( vc, (struct vidc_mode *)data );
+                       vc->MODECHANGE ( vc );
+                       ws.ws_row=vc->ychars;
+                       ws.ws_col=vc->xchars;
+                       error = (*linesw[tp->t_line].l_ioctl)(tp, TIOCSWINSZ, (char *)&ws, flag, p);
+                        error = ttioctl(tp, TIOCSWINSZ, (char *)&ws, flag, p);
+                       return 0;
+                       break;
+
+       case CONSOLE_RESETSCREEN:
+       {
+       extern unsigned int dispbase;
+       extern unsigned int dispsize;
+       extern unsigned int ptov;
+       extern unsigned int transfersize;
+
+       WriteWord ( IOMD_VIDINIT, dispbase-ptov );
+       WriteWord ( IOMD_VIDSTART, dispbase-ptov );
+       WriteWord ( IOMD_VIDEND, (dispbase+dispsize-transfersize)-ptov );
+       return 0;
+        }
+       case CONSOLE_RESTORESCREEN:
+       {
+               extern unsigned int dispstart;
+               extern unsigned int dispsize;
+               extern unsigned int ptov;
+               extern unsigned int transfersize;
+
+               WriteWord ( IOMD_VIDINIT, dispstart-ptov );
+               WriteWord ( IOMD_VIDSTART, dispstart-ptov );
+               WriteWord ( IOMD_VIDEND, (dispstart+dispsize-transfersize)-ptov );
+               vidc_stdpalette();
+               return 0;
+        }
+       case CONSOLE_GETINFO:
+       {
+               extern videomemory_t videomemory;
+               register struct console_info *inf = (void *)data;
+
+
+               inf->videomemory = videomemory;
+               inf->width = R_DATA->mode.hder;
+               inf->height = R_DATA->mode.vder;
+               inf->bpp = R_DATA->mode.bitsperpixel;
+               return 0;
+       }
+       case CONSOLE_PALETTE:
+       {
+               register struct console_palette *pal = (void *)data;
+               vidc_write(VIDC_PALREG, pal->entry);
+               vidc_write(VIDC_PALETTE, VIDC_COL(pal->red, pal->green, pal->blue));
+               return 0;
+       }
+       }
+       return -1;
+}
+
+int
+vidcconsole_attach(vc, parent, self, aux)
+       struct vconsole *vc;
+       struct device *parent;
+       struct device *self;
+       void *aux;
+{
+       vidc_cursor_init ( vc );
+       vidcconsole_flash_go ( vc );
+       return 0;
+}
+
+int
+vidcconsole_flash_go(vc)
+       struct vconsole *vc;
+{
+       static lock=0;
+       if (lock==1)
+               return -1;
+       lock=0;
+
+       cursor_ih.ih_func = vidcconsole_cursorintr;
+       cursor_ih.ih_arg = vc;
+       cursor_ih.ih_level = IPL_TTY;
+       cursor_ih.ih_name = "vsync";
+       irq_claim ( IRQ_FLYBACK, &cursor_ih );
+
+       cursor_init = 0;
+       return 0;
+}
+
+/* What does this function do ? */
+int 
+vidcconsole_flash(vc, flash)
+       struct vconsole *vc;
+       int flash;
+{
+       flash = flash;
+}
+
+int
+vidcconsole_cursorflash(vc, flash)
+       struct vconsole *vc;
+       int flash;
+{
+       cursor_flash = flash;
+       return(0);
+}
+
+struct render_engine vidcconsole = {
+       vidcconsole_name,
+       vidcconsole_init,
+       
+       vidcconsole_putchar,
+
+       vidcconsole_spawn,
+       vidcconsole_swapin,
+       vidcconsole_mmap,
+       vidcconsole_render,
+       vidcconsole_scrollup,
+       vidcconsole_scrolldown,
+       vidcconsole_cls,
+       vidcconsole_update,
+       vidcconsole_scrollback,
+       vidcconsole_scrollforward,
+       vidcconsole_scrollbackend,
+       vidcconsole_clreos,
+       vidcconsole_debugprint,
+       vidcconsole_cursorupdate,
+       vidcconsole_cursorflashrate,
+       vidcconsole_setfgcol,
+       vidcconsole_setbgcol,
+       vidcconsole_textpalette,
+       vidcconsole_sgr,
+       vidcconsole_blank,
+       vidcconsole_ioctl,
+       vidcconsole_redraw,
+       vidcconsole_attach,
+       vidcconsole_flash,
+       vidcconsole_cursorflash
+};
+
+
+
+
+
+
+
+struct vidcvideo_softc {
+       struct device device;
+       int sc_opened;
+};
+
+int
+vidcvideo_probe(parent, match, aux)
+       struct device *parent;
+       void *match;
+       void *aux;
+{
+/*
+       struct vidcvideo_softc *vidcvideosoftc = (void *)match;
+       struct mainbus_attach_args *mb = aux;
+*/
+
+       return 1;
+}
+
+void
+vidcvideo_attach(parent, self, aux)
+       struct device *parent;
+       struct device *self;
+       void *aux;
+{
+       struct vidcvideo_softc *vidcvideosoftc = (void *)self;
+       vidcvideosoftc->sc_opened=0;
+
+       printf ( ": vidc 20\n" );
+}
+
+struct cfattach vidcvideo_ca = {
+       sizeof (struct vidcvideo_softc), vidcvideo_probe, vidcvideo_attach
+};
+
+struct cfdriver vidcvideo_cd = {
+       NULL, "vidcvideo", DV_DULL
+};
+
+int
+vidcvideoopen(dev, flags, fmt, p)
+       dev_t dev;
+       int flags;
+       int fmt;
+       struct proc *p;
+{
+       struct vidcvideo_softc *sc;
+       struct vconsole vconsole_new;
+       int unit = minor(dev);
+       int s;
+
+       if ( unit >= vidcvideo_cd.cd_ndevs )
+               return ENXIO;
+       sc = vidcvideo_cd.cd_devs[unit];
+       if (!sc)
+               return ENXIO;
+
+       s = spltty();
+/*     if (sc->sc_opened) {
+               (void)splx(s);
+               return(EBUSY);
+       }*/
+       ++sc->sc_opened;
+       (void)splx(s);
+
+       if (sc->sc_opened == 1) {
+               vconsole_new = *vconsole_default;
+               vconsole_new.render_engine = &vidcconsole;
+               vconsole_spawn_re (
+               makedev ( physcon_major, 64 + minor(dev) ),
+                   &vconsole_new );
+       } else {
+               log(LOG_WARNING, "Multiple open of/dev/vidcvideo0 by proc %d\n", p->p_pid);
+       }
+
+       return 0;
+}
+
+int
+vidcvideoclose(dev, flags, fmt, p)
+       dev_t dev;
+       int flags;
+       int fmt;
+       struct proc *p;
+{
+       struct vidcvideo_softc *sc;
+       int unit = minor(dev);
+       int s;
+
+       if ( unit >= vidcvideo_cd.cd_ndevs )
+               return ENXIO;
+       sc = vidcvideo_cd.cd_devs[unit];
+       if (!sc)
+               return ENXIO;
+
+       s = spltty();
+       --sc->sc_opened;
+       (void)splx(s);
+
+       return 0;
+}
+
+extern int physconioctl __P(( dev_t, int, caddr_t, int,        struct proc *));
+
+int
+vidcvideoioctl(dev, cmd, data, flag, p)
+       dev_t dev;
+       int cmd;
+       caddr_t data;
+       int flag;
+       struct proc *p;
+{
+       dev = makedev(physcon_major, 64 + minor(dev));
+       return ( physconioctl ( dev, cmd, data, flag, p ));
+}
+
+extern int physconmmap __P((dev_t, int, int));
+
+int
+vidcvideommap(dev, offset, prot)
+       dev_t dev;
+       int offset;
+       int prot;
+{
+       dev = makedev(physcon_major, 64 + minor(dev));
+       return(physconmmap(dev, offset, prot));
+}
+
diff --git a/sys/arch/arm32/dev/console/vt220.c b/sys/arch/arm32/dev/console/vt220.c
new file mode 100644 (file)
index 0000000..41bb883
--- /dev/null
@@ -0,0 +1,2008 @@
+/* $NetBSD: vt220.c,v 1.3 1996/03/18 19:33:10 mark Exp $ */
+
+/*
+ * Copyright (c) 1994-1995 Melvyn Tang-Richardson
+ * Copyright (c) 1994-1995 RiscBSD kernel team
+ * 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 RiscBSD kernel team
+ * 4. The name of the company nor the name of the author may be used to
+ *    endorse or promote products derived from this software without specific
+ *    prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE RISCBSD TEAM ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS 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.
+ *
+ * RiscBSD kernel project
+ *
+ * vt220.c
+ *
+ * VT220 emulation functions
+ *
+ * Created      : 17/09/94
+ */
+
+#include <sys/cdefs.h>
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/malloc.h>
+#include <sys/tty.h>
+#include <sys/conf.h>
+#include <sys/device.h>
+#include <sys/systm.h>
+#include <sys/syslog.h>
+#include <machine/param.h>
+#include <machine/katelib.h>
+#include <machine/cpu.h>
+#include <machine/bootconfig.h>
+#include <machine/iomd.h>
+#include <machine/vconsole.h>
+#include <machine/vidc.h>
+
+#include <arm32/dev/console/vt220.h>
+
+/* Temporary for debugging the vnode bug */
+
+int vnodeconsolebug = 0;
+u_int vnodeconsolebug1 = 0;
+u_int vnodeconsolebug2 = 0;
+
+static char vt220_name[] = "vt100";
+
+/* These defines are for the developer only !!!! */
+#define SELFTEST
+#define dprintf(x)     ;
+
+/*************************************************/
+
+#define FGCOL  0x0700
+#define BGCOL  0x3800
+
+/* Options */
+#define HARD_RESET_AT_INIT
+#undef SIMPLE_CURSOR   /* Define if any render engine is cursorless */
+
+/*************************************************/
+
+#define DA_VT220     "\033[?62;1;2;6;7;8;9c"
+
+char console_proc[41]; /* Is this debugging ? */
+
+#ifdef SIMPLE_CURSOR
+#define SIMPLE_CURSOR_CHAR ('_')
+#endif
+
+#define TERMTYPE_PUTSTRING     vt220_putstring
+#define TERMTYPE_INIT  vt220_init
+
+extern struct vconsole *vconsole_master;
+
+static int default_beepstate = 0;
+
+#define CDATA struct vt220_info *cdata = (struct vt220_info *)vc->data
+
+struct vt220_info master_termdata_store;
+struct vt220_info *master_termdata = &master_termdata_store;
+
+int do_render __P(( char /*c*/, struct vconsole */*vc*/ ));
+void do_render_noscroll __P(( char /*c*/, struct vconsole */*vc*/ ));
+void do_scrollcheck __P(( struct vconsole */*vc*/ ));
+void vt_ris __P((struct vconsole */*vc*/));
+
+void
+clr_params(cdata)
+       struct vt220_info *cdata;
+{
+       int i;
+       for (i=0; i<MAXPARMS; i++)
+               cdata->param[i] = 0;
+       cdata->parami = 0;
+}
+
+int
+TERMTYPE_INIT(vc)
+       struct vconsole *vc;
+{
+       struct vt220_info *cdata;
+
+       if (vc->data==NULL) {
+               if ( vc==vconsole_master ) {
+                       vc->data = (char *) master_termdata;
+               } else {
+                       MALLOC ( vc->data, char *, sizeof(struct vt220_info),
+                           M_DEVBUF, M_NOWAIT );
+               }
+       }
+
+       cdata = (struct vt220_info *)vc->data;
+
+       bzero ( (char *)cdata, sizeof (cdata) );
+
+#ifdef HARD_RESET_AT_INIT
+       vt_ris ( vc );
+#else
+       cdata->state = STATE_INIT;
+       cdata->disable_function = 1;
+       cdata->m_om = 0;
+       vc->xcur = vc->ycur = 0;
+       cdata->beepoff=default_beepstate;
+       cdata->simple_cursor_store = ' ';
+       cdata->scrr_beg = 0;
+       cdata->scrr_len = vc->ychars;
+       cdata->scrr_end = vc->ychars-1;
+       cdata->simple_cursor_on = 0;
+
+       for ( counter=0; counter<MAXTABSTOPS; counter++ ) {
+               if ( !(counter%8) )
+                       cdata->tab_stops[counter] = 1;
+               else
+                       cdata->tab_stops[counter] = 0;
+       }
+#endif
+       return 0;
+}
+
+int
+mapped_cls(vc)
+       struct vconsole *vc;
+{
+       int ptr;
+       if (vc->charmap == NULL)
+               return -1;
+       for ( ptr=0; ptr<(vc->xchars*vc->ychars); ptr++ )
+               vc->charmap[ptr]=0x20;
+       return 0;
+}
+
+void
+do_scrolldown(vc)
+       struct vconsole *vc;
+{
+       struct vt220_info *cdata = (struct vt220_info *)vc->data;
+
+/*
+       if ( ( cdata->scrr_beg<0 ) || ( cdata->scrr_end>=vc->ychars) )
+               dprintf ( "INVALID SCROLLDOWN" );
+*/
+
+       /* Clean up */
+
+/*
+       if ( cdata->scrr_beg < 0 ) cdata->scrr_beg = 0;
+*/
+       if ( cdata->scrr_end >= vc->ychars ) cdata->scrr_end=vc->ychars-1;
+       
+
+       if (vc==vconsole_current)
+               vc->SCROLLDOWN ( vc, cdata->scrr_beg, cdata->scrr_end );
+       else
+               vconsole_pending=vc->number;
+
+       if (vnodeconsolebug) {
+               if (ReadWord(0xf148a000) != vnodeconsolebug2) {
+                       log(LOG_WARNING, "vnode 0xf148a000 v_flag changed from %08x to %08x in do_scrolldown(1)\n",
+                           vnodeconsolebug2, ReadWord(0xf148a000));
+                       log(LOG_WARNING, "vc=%08x vcur=%08x charmap=%08x\n", vc, vconsole_current, vc->charmap);
+               }
+       }
+
+/*
+ * This version of the following code was responcible for the vnode bug
+ * It can trash part of the word that follows the allocated block
+ * e.g. charmap = 0xf1484000, size 0x6000
+ *      vnode = 0xf148a000
+ *     first word of vnode is trashed.
+ * bug is an adjustment of -1 for counting backwards was not made.
+       if ( ((vc->flags)&(LOSSY)) == 0 ) {
+               int counter;
+               for ( counter=((cdata->scrr_end+1)*(vc->xchars)); 
+                       counter > (cdata->scrr_beg+1)*(vc->xchars) ; counter-- ) {
+                       vc->charmap[counter] = vc->charmap[counter-vc->xchars];
+               }
+
+               for ( counter=(cdata->scrr_beg)*(vc->xchars);
+                       counter < (cdata->scrr_beg+1)*(vc->xchars); counter++ ) {
+                       vc->charmap[counter]=0x20;
+               }
+       }
+*/
+       if ( ((vc->flags)&(LOSSY)) == 0 ) {
+               int counter;
+               for ( counter=((cdata->scrr_end+1)*(vc->xchars)) - 1; 
+                       counter >= (cdata->scrr_beg+1)*(vc->xchars) ; counter-- ) {
+                       vc->charmap[counter] = vc->charmap[counter-vc->xchars];
+               }
+
+               for ( counter=(cdata->scrr_beg)*(vc->xchars);
+                       counter < (cdata->scrr_beg+1)*(vc->xchars); counter++ ) {
+                       vc->charmap[counter]=0x20;
+               }
+       }
+       if (vnodeconsolebug) {
+               if (ReadWord(0xf148a000) != vnodeconsolebug2) {
+                       log(LOG_WARNING, "vnode 0xf148a000 v_flag changed from %08x to %08x in do_scrolldown(2)\n",
+                           vnodeconsolebug2, ReadWord(0xf148a000));
+                       log(LOG_WARNING, "vc=%08x vcur=%08x charmap=%08x\n", vc, vconsole_current, vc->charmap);
+               }
+       }
+}
+
+void
+do_scrollup(vc)
+       struct vconsole *vc;
+{
+       struct vt220_info *cdata = (struct vt220_info *)vc->data;
+
+       if (vc==vconsole_current)
+               vc->SCROLLUP ( vc, cdata->scrr_beg, cdata->scrr_end );
+       else
+               vconsole_pending = vc->number;
+
+       if ( cdata->scrr_end == 0 )
+               vc->ycur=vc->ychars-1;
+       else
+               vc->ycur=cdata->scrr_end;
+
+/* Do a cyclic buffer for this !!!!!!!!!!!!!! */       
+       if ( ((vc->flags)&(LOSSY)) == 0 ) {
+/* bcopy was weird, do this for now */
+               int counter;
+               for ( counter=(cdata->scrr_beg+1)*vc->xchars; 
+                   counter < ((cdata->scrr_end+1)*(vc->xchars)); counter++ ) {
+                       vc->charmap[counter-vc->xchars] = vc->charmap[counter];
+               }
+               for ( counter=vc->xchars*(cdata->scrr_end);
+                   counter < (vc->xchars*(cdata->scrr_end+1)); counter++ ) {
+                       vc->charmap[counter]=0x20;
+               }
+       }
+}
+
+void
+respond(vc)
+       struct vconsole *vc;
+{
+       struct vt220_info *cdata = (struct vt220_info *)vc->data;
+
+        while (*cdata->report_chars && cdata->report_count > 0) {
+                (*linesw[vc->tp->t_line].l_rint)
+                        (*cdata->report_chars++ & 0xff, vc->tp);
+                cdata->report_count--;
+        }
+}
+
+void
+vt_curadr(vc)
+       struct vconsole *vc;
+{
+    struct vt220_info *cdata = (struct vt220_info *)vc->data;
+
+#ifdef SELFTEST
+strcpy ( console_proc, "vt_curadr" );
+#endif
+
+    if ( cdata->m_om ) /* relative to scrolling region */
+    {
+       cdata->param[0]+=cdata->scrr_beg;
+       if ( (cdata->param[0]==0) && (cdata->param[1]==0) )
+       {
+               vc->xcur = 0;
+               vc->ycur = 0;
+               return;
+       }
+       /* Limit checking */
+       cdata->param[0] = (cdata->param[0] <= 0) ? 1 : cdata->param[0];
+       cdata->param[0] = (cdata->param[0] > vc->ychars) ? vc->ychars : cdata->param[0];
+       cdata->param[1] = (cdata->param[1] <= 0) ? 1 : cdata->param[1];
+       cdata->param[1] = (cdata->param[1] >= vc->xchars) ? (vc->xchars-1) : cdata->param[1];
+       (cdata->param[0])--;
+       (cdata->param[1])--;
+       vc->ycur = cdata->param[0];
+       vc->xcur = cdata->param[1];
+    }
+    else
+    {
+       if ( (cdata->param[0]==0) && (cdata->param[1]==0) )
+       {
+               vc->xcur = 0;
+               vc->ycur = 0;
+               return;
+       }
+       /* Limit checking */
+
+       (cdata->param[0])--;
+       (cdata->param[1])--;
+
+       vc->ycur = cdata->param[0];
+       vc->xcur = cdata->param[1];
+
+{
+       char buf[80];
+       sprintf ( buf, "vc->xcur %d vc->ycur %d", vc->xcur, vc->ycur );
+       dprintf ( buf );
+}
+    }
+}
+
+extern void beep_generate(void);
+
+void
+vt_reset_dec_priv_qm(vc)
+       struct vconsole *vc;
+{
+    struct vt220_info *cdata = (struct vt220_info *)vc->data;
+#ifdef SELFTEST
+strcpy ( console_proc, "vt_reset_dec_priv_qm" );
+#endif
+    switch(cdata->param[0])
+    {
+        case 7:         /* AWM - auto wrap mode */
+               beep_generate();
+               cdata->flags &= ~F_AWM;
+               break;
+        case 0:         /* error, ignored */
+        case 1:         /* CKM - cursor key mode */
+        case 2:         /* ANM - ansi/vt52 mode */
+        case 3:         /* COLM - column mode */
+        case 4:         /* SCLM - scrolling mode */
+        case 5:         /* SCNM - screen mode */
+        case 8:         /* ARM - auto repeat mode */
+        case 9:         /* INLM - interlace mode */
+        case 10:        /* EDM - edit mode */
+        case 11:        /* LTM - line transmit mode */
+        case 12:        /* */
+        case 13:        /* SCFDM - space compression / field delimiting */
+        case 14:        /* TEM - transmit execution mode */
+        case 15:        /* */
+        case 16:        /* EKEM - edit key execution mode */
+        case 25:        /* TCEM - text cursor enable mode */
+        case 42:        /* NRCM - 7bit NRC characters */
+            break;
+
+        case 6:         /* OM - origin mode */
+            cdata->m_om = 0;
+            break;
+       }
+}
+
+void
+vt_sc(vc)
+       struct vconsole *vc;
+{
+       struct vt220_info *cdata = (struct vt220_info *)vc->data;
+
+#ifdef SELFTEST
+       strcpy ( console_proc, "vt_sc" );
+#endif
+
+       cdata->sc_G0    = cdata->G0;
+       cdata->sc_G1    = cdata->G1;
+       cdata->sc_G2    = cdata->G2;
+       cdata->sc_G3    = cdata->G3;
+       cdata->sc_GL    = cdata->GL;
+       cdata->sc_GR    = cdata->GR;
+       cdata->sc_xcur  = vc->xcur;
+       cdata->sc_ycur  = vc->ycur;
+       cdata->sc_om    = cdata->m_om;
+       cdata->sflags   = cdata->flags;
+/*
+       cdata->sc_attr  = cdata->c_attr;
+       cdata->sc_awm   = cdata->m_awm;
+       cdata->sc_sel   = cdata->selchar;
+       cdata->sc_vtsgr = cdata->vtsgr;
+       cdata->sc_flag  = 1;
+*/
+}
+
+void
+vt_rc(vc)
+       struct vconsole *vc;
+{
+       struct vt220_info *cdata = (struct vt220_info *)vc->data;
+       cdata->G0       = cdata->sc_G0;
+       cdata->G1       = cdata->sc_G1;
+       cdata->G2       = cdata->sc_G2;
+       cdata->G3       = cdata->sc_G3;
+       cdata->GL       = cdata->sc_GL;
+       cdata->GR       = cdata->sc_GR;
+       vc->xcur        = cdata->sc_xcur;
+       vc->ycur        = cdata->sc_ycur;
+       cdata->m_om     = cdata->sc_om;
+       cdata->flags = cdata->sflags;
+
+/*
+       cdata->c_attr   = cdata->sc_attr;
+       cdata->awm      = cdata->sc_awm;
+       cdata->sel      = cdata->sc_selchar;
+       cdata->vtsgr    = cdata->sc_vtsgr;
+       cdata->flag     = 0;
+*/
+}
+
+void
+vt_clreol(vc)
+       struct vconsole *vc;
+{
+/*
+       struct vt220_info *cdata = (struct vt220_info *)vc->data;
+*/
+       int counter;
+       int x = vc->xcur;
+       int y = vc->ycur;
+
+#ifdef SELFTEST
+       strcpy ( console_proc, "vt_clreol" );
+#endif
+
+       for ( counter=vc->xcur; counter<vc->xchars; counter++ )
+               do_render_noscroll ( ' ', vc );
+
+       vc->xcur = x;
+       vc->ycur = y;
+}
+
+/* index, move cursor down */
+
+void
+vt_ind(vc)
+       struct vconsole *vc;
+{
+       struct vt220_info *cdata = (struct vt220_info *)vc->data;
+
+#ifdef SELFTEST
+       strcpy ( console_proc, "vt_ind" );
+#endif
+
+       vc->ycur++;
+
+       {
+               char buf[80];
+               sprintf ( buf, "{vt_ind [%d,%d] [%d,%d] }",
+                       vc->xcur, vc->ycur, cdata->scrr_beg, cdata->scrr_end);
+               dprintf ( buf );
+       }
+
+       do_scrollcheck ( vc );
+}
+
+void
+vt_nel(vc)
+       struct vconsole *vc;
+{
+       vc->ycur++;
+       do_scrollcheck ( vc );
+       vc->xcur=0;
+}
+
+void
+vt_ri(vc)
+       struct vconsole *vc;
+{
+        struct vt220_info *cdata = (struct vt220_info *)vc->data;
+
+       if (vnodeconsolebug & 1)
+               vnodeconsolebug2 = ReadWord(0xf148a000);
+
+       vc->ycur--;
+
+        if (vc->ycur<=cdata->scrr_beg)
+               vc->ycur = cdata->scrr_beg;
+
+
+       if (vc->ycur <= cdata->scrr_beg) {
+               if (vnodeconsolebug & 4) {
+                       if (ReadWord(0xf148a000) != vnodeconsolebug2) {
+                               log(LOG_WARNING, "vnode 0xf148a000 v_flag changed from %08x to %08x in vt_ri(1)\n",
+                                   vnodeconsolebug2, ReadWord(0xf148a000));
+                               log(LOG_WARNING, "vc=%08x ycur=%d scrr_beg=%d\n", vc, vc->ycur, cdata->scrr_beg);
+                               vnodeconsolebug2 = ReadWord(0xf148a000);
+                       }
+               }
+               do_scrolldown ( vc );
+               if (vnodeconsolebug & 4) {
+                       if (ReadWord(0xf148a000) != vnodeconsolebug2) {
+                               log(LOG_WARNING, "vnode 0xf148a000 v_flag changed from %08x to %08x in vt_ri(2)\n",
+                                   vnodeconsolebug2, ReadWord(0xf148a000));
+                               log(LOG_WARNING, "vc=%08x ycur=%d scrr_beg=%d charmap=%08x\n", vc, vc->ycur, cdata->scrr_beg, vc->charmap);
+                               vnodeconsolebug2 = ReadWord(0xf148a000);
+                       }
+               }
+               vc->ycur = cdata->scrr_beg;
+       }
+}
+
+/* selective in line erase */
+
+int
+vt_sel(vc)
+       struct vconsole *vc;
+{
+    struct vt220_info *cdata = (struct vt220_info *)vc->data;
+    register int counter;
+    register int x = vc->xcur;
+    register int y = vc->ycur;
+
+    switch ( cdata->param[0] )
+    {
+       case 0:         /* Delete to the end of the line */
+           for ( counter=x; counter<vc->xchars; counter++ )
+               do_render_noscroll ( ' ', vc );
+           break;
+               
+       case 1:         /* Delete to the beginning of the line */
+           vc->xcur = 0;
+           for ( counter=0; counter<x; counter++ )
+               do_render_noscroll ( ' ', vc );
+           break;
+
+       case 2:         /* Delete the whole line */
+       default:
+           vc->xcur = 0;
+           for ( counter=0; counter<vc->xchars; counter++ )
+               do_render_noscroll ( ' ', vc );
+           break;
+         }
+
+    vc->xcur = x;
+    vc->ycur = y;
+    return 0;
+}
+
+void
+vt_cuu(vc)
+       struct vconsole *vc;
+{
+        struct vt220_info *cdata = (struct vt220_info *)vc->data;
+       cdata->param[0] = (cdata->param[0] <= 0) ? 1 : cdata->param[0];
+       vc->ycur -= cdata->param[0];
+       vc->ycur = vc->ycur < 0 ? 0 : vc->ycur;
+}
+
+void
+vt_cub(vc)
+       struct vconsole *vc;
+{
+        struct vt220_info *cdata = (struct vt220_info *)vc->data;
+
+       cdata->param[0] = (cdata->param[0] <= 0) ? 1 : cdata->param[0];
+
+       vc->xcur -= cdata->param[0];
+       cdata->param[0] = (cdata->param[0] < 0 ) ? 0 : cdata->param[0];
+}
+
+void
+vt_da(vc)
+       struct vconsole *vc;
+{
+        struct vt220_info *cdata = (struct vt220_info *)vc->data;
+        static u_char *response = (u_char *)DA_VT220;
+
+        cdata->report_chars = response;
+        cdata->report_count = 18;
+        respond(vc);
+}
+
+void
+vt_str(vc)
+       struct vconsole *vc;
+{
+    struct vt220_info *cdata = (struct vt220_info *)vc->data;
+    int counter;
+
+    if (cdata == NULL) {
+       return;
+    }
+
+    clr_params ( cdata );
+
+    cdata->state = STATE_INIT;
+    cdata->disable_function = 1;
+    cdata->m_om = 0; /* origin mode */
+    vc->xcur = vc->ycur = 0;
+    cdata->beepoff=default_beepstate;
+    cdata->simple_cursor_store = ' ';
+    cdata->scrr_beg = 0;
+    cdata->scrr_len = vc->ychars;
+    cdata->scrr_end = vc->ychars-1;
+    cdata->simple_cursor_on = 0;
+    cdata->nfgcol = 7;
+    cdata->nbgcol = 0;
+    cdata->fgcol = cdata->nfgcol;
+    cdata->bgcol = cdata->nbgcol;
+    cdata->attribs=cdata->fgcol<<8 | cdata->bgcol<<11;
+    cdata->sc_flag = 0;                      /* save cursor position */
+    cdata->flags = F_AWM;
+    cdata->irm = 0;
+
+    for ( counter=0; counter<MAXTABSTOPS; counter++ )
+    {
+        if ( !(counter%8) )
+                cdata->tab_stops[counter] = 1;
+        else
+                cdata->tab_stops[counter] = 0;
+    }
+}
+
+void
+vt_ris(vc)
+       struct vconsole *vc;
+{
+       vc->xcur = vc->ycur = 0;
+        vt_str(vc);                   /* and soft terminal reset */
+}
+
+void
+vt_cud(vc)
+       struct vconsole *vc;
+{
+        struct vt220_info *cdata = (struct vt220_info *)vc->data;
+
+       cdata->param[0] = (cdata->param[0] <= 0) ? 1 : cdata->param[0];
+
+       cdata->param[0] = (cdata->param[0] > (cdata->scrr_end-vc->ycur))
+                       ? (cdata->scrr_end-vc->ycur) : cdata->param[0];
+
+       vc->ycur += cdata->param[0];
+
+       do_scrollcheck ( vc );
+}
+
+void
+vt_tst(vc)
+       struct vconsole *vc;
+{
+    int counter, times;
+
+    for ( times=0; times<100; times++ );
+       for ( counter=32; counter<127; counter++ )
+               do_render ( counter, vc );
+}
+
+void
+vt_il(vc)
+       struct vconsole *vc;
+{
+    struct vt220_info *cdata = (struct vt220_info *)vc->data;
+    register int beg, end;
+
+    if ( vc->ycur >= (vc->ychars-2) )
+       return;
+
+    cdata->param[0] = cdata->param[0]<=0 ? 1 : cdata->param[0];
+
+    beg = cdata->scrr_beg;
+    end = cdata->scrr_end;
+
+    cdata->scrr_beg = vc->ycur;
+    cdata->scrr_end = vc->ychars-1;
+
+    for ( ; cdata->param[0]>0; cdata->param[0]-- )
+        do_scrolldown( vc );
+
+    cdata->scrr_beg = beg;
+    cdata->scrr_end = end;
+}
+
+void
+vt_ic(vc)
+       struct vconsole *vc;
+{
+    int counter;
+    int ox, oy;
+    int *ptr = vc->charmap + (vc->xcur + vc->ycur*vc->xchars);
+    for ( counter=vc->xchars-vc->xcur; counter>=0; counter-- )
+        ptr[counter+1] = ptr[counter];
+    ptr[0] =  ' ';
+    ox = vc->xcur; oy = vc->ycur;
+
+    for ( ; vc->xcur < vc->xchars; )
+        do_render_noscroll ( vc->charmap[vc->xcur+vc->ycur*vc->xchars], vc );
+    vc->xcur = ox; vc->ycur = oy;
+}
+
+void
+vt_dch(vc)
+       struct vconsole *vc;
+{
+    int counter;
+    int ox, oy;
+    int *ptr = vc->charmap + (vc->ycur*vc->xchars);
+
+    for ( counter=vc->xcur; counter<(vc->xchars-1); counter++ )
+        ptr[counter] = ptr[counter+1];
+
+    ptr[vc->xchars] =  ' ';
+
+    ox = vc->xcur; oy = vc->ycur;
+
+    for ( ; vc->xcur < vc->xchars; )
+        do_render_noscroll ( vc->charmap[vc->xcur+vc->ycur*vc->xchars], vc );
+
+    vc->xcur = ox; vc->ycur = oy;
+}
+
+void
+vt_dl(vc)
+       struct vconsole *vc;
+{
+    struct vt220_info *cdata = (struct vt220_info *)vc->data;
+    register int beg, end;
+
+    cdata->param[0] = cdata->param[0]<=0 ? 1 : cdata->param[0];
+    cdata->param[0] = cdata->param[0]>vc->xchars ? vc->xchars : cdata->param[0];
+
+/*
+    vc->xcur=0;
+*/
+
+    beg = cdata->scrr_beg;
+    end = cdata->scrr_end;
+
+    cdata->scrr_beg = vc->ycur;
+    cdata->scrr_end = vc->ychars-1;
+
+    for ( ; cdata->param[0]>0; cdata->param[0]-- )
+        do_scrollup( vc );
+
+    cdata->scrr_beg = beg;
+    cdata->scrr_end = end;
+}
+
+/* Set scrolling region */
+
+void
+vt_stbm(vc)
+       struct vconsole *vc;
+{
+    struct vt220_info *cdata = (struct vt220_info *)vc->data;
+
+    if((cdata->param[0] == 0) && (cdata->param[1] == 0))
+    {
+        cdata->xcur = 0;
+        cdata->ycur = 0;
+        cdata->scrr_beg = 0;
+        cdata->scrr_len = vc->ychars;
+        cdata->scrr_end = cdata->scrr_len - 1;
+        return;
+    }
+    if(cdata->param[1] <= cdata->param[0])
+            return;
+
+    /* range parm 1 */
+
+    cdata->scrr_beg = cdata->param[0]-1;
+    cdata->scrr_len = cdata->param[1] - cdata->param[0] + 1;
+    cdata->scrr_end = cdata->param[1]-1;
+
+/*
+    if (cdata->scrr_beg<0)
+       cdata->scrr_beg = 0;
+*/
+
+    if (cdata->scrr_end>(vc->ychars-1))
+       cdata->scrr_end = vc->ychars-1;
+
+    cdata->scrr_len = cdata->scrr_end - cdata->scrr_beg - 1;
+{
+       char buf[80];
+       sprintf ( buf, "scrr_beg %d, scrr_end %d", cdata->scrr_beg,
+                               cdata->scrr_end );
+       dprintf ( buf );
+}
+
+    cdata->flags &= ~F_LASTCHAR;
+}
+
+void
+vt_dsr(vc)
+       struct vconsole *vc;
+{
+    struct vt220_info *cdata = (struct vt220_info *)vc->data;
+    static u_char *answr = (u_char *)"\033[0n";
+    static u_char *panswr = (u_char *)"\033[?13n"; /* Printer Unattached */
+    static u_char *udkanswr = (u_char *)"\033[?21n"; /* UDK Locked */
+    static u_char *langanswr = (u_char *)"\033[?27;1n"; /* North American*/
+    static u_char buffer[16];
+    int i = 0;
+
+    switch(cdata->param[0])
+    {
+            case 5:         /* return status */
+                    cdata->report_chars = answr;
+                    cdata->report_count = 4;
+                    respond(vc);
+                    break;
+
+            case 6:         /* return cursor position */
+                    buffer[i++] = 0x1b;
+                    buffer[i++] = '[';
+                    if((vc->ycur+1) > 10)
+                            buffer[i++] = ((vc->ycur+1) / 10) + '0';
+                    buffer[i++] = ((vc->ycur+1) % 10) + '0';
+                    buffer[i++] = ';';
+                    if((vc->xcur+1) > 10)
+                            buffer[i++] = ((cdata->xcur+1) / 10) + '0';
+                    buffer[i++] = ((vc->xcur+1) % 10) + '0';
+                    buffer[i++] = 'R';
+                    buffer[i++] = '\0';
+
+                    cdata->report_chars = buffer;
+                    cdata->report_count = i;
+                    respond(vc);
+                    break;
+
+            case 15:        /* return printer status */
+                    cdata->report_chars = panswr;
+                    cdata->report_count = 6;
+                    respond(vc);
+                    break;
+
+            case 25:        /* return udk status */
+                    cdata->report_chars = udkanswr;
+                    cdata->report_count = 6;
+                    respond(vc);
+                    break;
+
+            case 26:        /* return language status */
+                    cdata->report_chars = langanswr;
+                    cdata->report_count = 8;
+                    respond(vc);
+                    break;
+
+            default:        /* nothing else valid */
+                    break;
+    }
+}
+
+void
+vt_su(vc)
+       struct vconsole *vc;
+{
+    struct vt220_info *cdata = (struct vt220_info *)vc->data;
+
+    cdata->param[0] = cdata->param[0]<=0 ? 1 : cdata->param[0];
+    cdata->param[0] = cdata->param[0]>(vc->xchars-1) ? vc->xchars-1 : cdata->param[0];
+
+    do_scrollup ( vc );
+}
+
+void
+vt_set_dec_priv_qm(vc)
+       struct vconsole *vc;
+{
+    struct vt220_info *cdata = (struct vt220_info *)vc->data;
+
+    switch(cdata->param[0])
+    {
+        case 7:         /* AWM - auto wrap mode */
+               cdata->flags |= F_AWM;
+               break;
+
+       /* Implement these */
+        case 1:         /* CKM - cursor key mode */
+        case 3:         /* COLM - column mode */
+        case 6:         /* OM - origin mode */
+        case 8:         /* ARM - auto repeat mode */
+       case 25:        /* TCEM - text cursor enable mode */
+                break;
+
+        case 0:         /* error, ignored */
+        case 2:         /* ANM - ansi/vt52 mode */
+        case 4:         /* SCLM - scrolling mode */
+        case 5:         /* SCNM - screen mode */
+        case 9:         /* INLM - interlace mode */
+        case 10:        /* EDM - edit mode */
+        case 11:        /* LTM - line transmit mode */
+        case 12:        /* */
+        case 13:        /* SCFDM - space compression / field delimiting */
+        case 14:        /* TEM - transmit execution mode */
+        case 15:        /* */
+        case 16:        /* EKEM - edit key execution mode */
+        case 42:        /* NRCM - 7bit NRC characters */
+                break;
+    }
+}
+
+void
+vt_keyappl(vc)
+       struct vconsole *vc;
+{
+       dprintf ( "VT_KEYAPPL" );
+}
+
+void
+vt_clrtab(vc)
+       struct vconsole *vc;
+{
+    struct vt220_info *cdata = (struct vt220_info *)vc->data;
+    int i;
+
+    if(cdata->param[0] == 0)
+            cdata->tab_stops[vc->xcur] = 0;
+    else if(cdata->param[0] == 3)
+    {
+            for(i=0; i<MAXTABSTOPS; i++)
+                    cdata->tab_stops[i] = 0;
+    }
+}
+
+/*
+void
+vt_cuf(vc)
+       struct vconsole *vc;
+{
+        struct vt220_info *cdata = (struct vt220_info *)vc->data;
+
+       cdata->param[0] = (cdata->param[0] <= 0) ? 1 : cdata->param[0];
+
+       vc->xcur += cdata->param[0];
+
+       cdata->param[0] = (cdata->param[0] > vc->xchars ) ? vc->xchars : cdata->param[0];
+}
+*/
+
+void
+vt_cuf(vc)
+       struct vconsole *vc;
+{
+        struct vt220_info *cdata = (struct vt220_info *)vc->data;
+        register int p = cdata->param[0];
+
+        if(vc->xcur == ((vc->xchars)-1))         /* already at right margin */
+                return;
+        if(p <= 0)                      /* parameter min = 1 */
+                p = 1;
+        else if(p > ((vc->xchars)-1))         /* parameter max = 79 */
+                p = ((vc->xchars)-1);
+        if((vc->xcur + p) > ((vc->xchars)-1))                /* not more than */
+               p = ((vc->xchars)-1) - vc->xcur;
+        vc->xcur += p;
+}
+
+void
+vt_sgr(vc)
+       struct vconsole *vc;
+{
+    struct vt220_info *cdata = (struct vt220_info *)vc->data;
+    register int i=0;
+    
+    do
+    {
+       vc->SGR ( vc, cdata->param[i] );
+        switch ( cdata->param[i++] )
+        {
+            case 0:    /* reset to normal attributes */
+               cdata->fgcol = cdata->nfgcol;
+               cdata->bgcol = cdata->nbgcol;
+    cdata->attribs=cdata->fgcol<<8 | cdata->bgcol<<11;
+               break;
+            case 1:    /* bold */
+               cdata->attribs |= BOLD;
+               break;
+            case 4:    /* underline */
+               cdata->attribs |= UNDERLINE;
+               break;
+            case 5:    /* blinking */
+               cdata->attribs |= BLINKING;
+               break;
+            case 7:    /* reverse */
+               cdata->fgcol = cdata->nbgcol;
+               cdata->bgcol = cdata->nfgcol;
+               cdata->attribs |= REVERSE;
+    cdata->attribs&=~0x3F00;
+    cdata->attribs|=cdata->fgcol<<8 | cdata->bgcol<<11;
+               break;
+            case 22:   /* not bold */
+               cdata->attribs &= ~BOLD;
+               break;
+            case 24:   /* not underlined */
+               cdata->attribs &= ~UNDERLINE;
+               break;
+            case 25:   /* not blinking */
+               cdata->attribs &= ~BLINKING;
+               break;
+            case 27:   /* not reverse */
+               cdata->attribs &= ~REVERSE;
+               cdata->fgcol = cdata->nfgcol;
+               cdata->bgcol = cdata->nbgcol;
+    cdata->attribs&=~0x3F00;
+    cdata->attribs|=cdata->fgcol<<8 | cdata->bgcol<<11;
+               break;
+               
+           default:
+               if ( ( cdata->param[i-1] > 29 )&&( cdata->param[i-1] < 38 ) )
+               {
+                       vc->SETFGCOL ( vc, cdata->param[i-1] - 30 );
+                       cdata->fgcol = cdata->param[i-1] - 30;
+    cdata->attribs&=~0x3F00;
+    cdata->attribs|=cdata->fgcol<<8 | cdata->bgcol<<11;
+
+               }
+               if ( ( cdata->param[i-1] > 39 )&&( cdata->param[i-1] < 48 ) )
+               {
+                       vc->SETBGCOL ( vc, cdata->param[i-1] - 40 );
+                       cdata->bgcol = cdata->param[i-1] - 40;
+    cdata->attribs&=~0x3F00;
+    cdata->attribs|=cdata->fgcol<<8 | cdata->bgcol<<11;
+               }
+       }
+    } while ( i<=cdata->parami );
+}
+
+void
+vt_clreos(vc)
+       struct vconsole *vc;
+{
+    struct vt220_info *cdata = (struct vt220_info *)vc->data;
+    int ptr;
+    if ( vc == vconsole_current )
+        vc->R_CLREOS ( vc, cdata->param[0] );
+    else
+       vconsole_pending = vc->number;
+
+    switch ( cdata->param[0] )
+    {
+       case 0: /* Erase from cursor to end of screen */
+               for ( ptr=vc->xcur + vc->ycur * vc->xchars
+                               ; ptr<(vc->xchars*vc->ychars); ptr++ )
+                       vc->charmap[ptr]=0x20;
+               break;
+
+       case 1: /* Erase from start to cursor */
+               for (   ptr=0;
+                       ptr<vc->ycur*vc->xchars + vc->xcur;
+                       ptr++ )
+                       vc->charmap[ptr]=0x20;
+               break;
+
+       case 2: /* Blitz the whole bloody thing */
+               if ((vc->flags&LOSSY)==0)
+                       mapped_cls(vc);
+               if (vc==vconsole_current)
+                    vc->CLS(vc);
+               else
+                    vconsole_pending = vc->number;
+               break;
+    }
+}
+
+void
+vt_set_ansi(vc)
+       struct vconsole *vc;
+{
+    struct vt220_info *cdata = (struct vt220_info *)vc->data;
+
+    switch(cdata->param[0])
+    {
+            case 0:         /* error, ignored */
+            case 1:         /* GATM - guarded area transfer mode */
+            case 2:         /* KAM - keyboard action mode */
+            case 3:         /* CRM - Control Representation mode */
+            case 20:        /* LNM - line feed / newline mode */
+                    break;
+
+            case 4:         /* IRM - insert replacement mode */
+               cdata->irm = 1;
+               break;
+
+            case 5:         /* SRTM - status report transfer mode */
+            case 6:         /* ERM - erasue mode */
+            case 7:         /* VEM - vertical editing mode */
+            case 10:        /* HEM - horizontal editing mode */
+            case 11:        /* PUM - position unit mode */
+            case 12:        /* SRM - send-receive mode */
+            case 13:        /* FEAM - format effector action mode */
+            case 14:        /* FETM - format effector transfer mode */
+            case 15:        /* MATM - multiple area transfer mode */
+            case 16:        /* TTM - transfer termination */
+            case 17:        /* SATM - selected area transfer mode */
+            case 18:        /* TSM - tabulation stop mode */
+            case 19:        /* EBM - editing boundary mode */
+                    break;
+    }
+}
+
+void
+vt_reset_ansi(vc)
+       struct vconsole *vc;
+{
+    struct vt220_info *cdata = (struct vt220_info *)vc->data;
+
+    switch(cdata->param[0])
+    {
+           /* Implement these */
+            case 0:         /* error, ignored */
+            case 1:         /* GATM - guarded area transfer mode */
+            case 2:         /* KAM - keyboard action mode */
+            case 3:         /* CRM - Control Representation mode */
+            case 20:        /* LNM - line feed / newline mode */
+                    break;
+
+            case 4:         /* IRM - insert replacement mode */
+               cdata->irm = 0;
+               break;
+
+            case 5:         /* SRTM - status report transfer mode */
+            case 6:         /* ERM - erasue mode */
+            case 7:         /* VEM - vertical editing mode */
+            case 10:        /* HEM - horizontal editing mode */
+            case 11:        /* PUM - position unit mode */
+            case 12:        /* SRM - send-receive mode */
+            case 13:        /* FEAM - format effector action mode */
+            case 14:        /* FETM - format effector transfer mode */
+            case 15:        /* MATM - multiple area transfer mode */
+            case 16:        /* TTM - transfer termination */
+            case 17:        /* SATM - selected area transfer mode */
+            case 18:        /* TSM - tabulation stop mode */
+            case 19:        /* EBM - editing boundary mode */
+                    break;
+    }
+}
+
+/* DRN */
+
+void
+do_render_noscroll(c, vc)
+       char c;
+       struct vconsole *vc;
+{
+    struct vt220_info *cdata = (struct vt220_info *)vc->data;
+    /* THE RENDER STAGE **********************************/
+
+    if ((c>=0x20)&&(c<=0x7f))
+    {
+       if (((vc->flags)&(LOSSY))==0)
+       {
+          if ( vc->charmap[vc->xcur+vc->ycur*vc->xchars] != c|cdata->attribs )
+          {
+           if ( vc==vconsole_current )
+               vc->RENDER ( vc, c );
+           else
+               vconsole_pending = vc->number;
+         }
+         vc->charmap[ vc->xcur + vc->ycur*vc->xchars ] = c|cdata->attribs;
+       }
+       else
+       {
+           if ( vc==vconsole_current )
+               vc->RENDER ( vc, c );
+           else
+               vconsole_pending = vc->number;
+        }
+    }
+
+    vc->xcur++;
+
+    /*do_scrollcheck ( vc );*/
+}
+
+#ifdef SIMPLE_CURSOR
+void
+simple_cursor_on(vc)
+       struct vconsole *vc;
+{
+    struct vt220_info *cdata = (struct vt220_info *)vc->data;
+    if (cdata->simple_cursor_on)
+       return 0;
+    if (vc!=vconsole_current)
+       return 0;
+    if (((vc->flags)&(LOSSY))==0)
+    {
+       cdata->simple_cursor_store = vc->charmap[ vc->xcur + vc->ycur*vc->xchars ];
+       vc->RENDER ( vc, SIMPLE_CURSOR_CHAR );
+    }
+    cdata->simple_cursor_on = 1;
+}
+
+void
+simple_cursor_off(vc)
+       struct vconsole *vc;
+{
+    struct vt220_info *cdata = (struct vt220_info *)vc->data;
+     if (!cdata->simple_cursor_on)
+       return 0;
+   if (vc!=vconsole_current)
+       return 0;
+    if (((vc->flags)&(LOSSY))==0)
+    {
+       vc->RENDER ( vc, cdata->simple_cursor_store );
+    }
+    cdata->simple_cursor_on = 0;
+}
+#endif
+
+/* DSC */
+void
+do_scrollcheck(vc)
+       struct vconsole *vc;
+{
+    struct vt220_info *cdata = (struct vt220_info *)vc->data;
+
+    /* BOUNDARY CHECK ************************************/
+    if ((vc->xcur >= (vc->xchars))&&((cdata->flags&F_AWM)!=0))
+    {
+       cdata->flags|=F_LASTCHAR;
+       cdata->lastpos = vc->ycur*vc->xchars+vc->xcur;
+    }
+
+    /* SCROLL CHECK *************************************/
+    if ( vc->ycur >= cdata->scrr_end+1 )
+    {
+       do_scrollup ( vc );
+    }
+}
+
+/* DR */
+
+int
+do_render(c, vc)
+       char c;
+       struct vconsole *vc;
+{
+    struct vt220_info *cdata = (struct vt220_info *)vc->data;
+    /* THE RENDER STAGE **********************************/
+
+    if (((cdata->flags&F_AWM)==0)&&(vc->xcur >= 20))
+       return 0;
+
+    if ( cdata->flags & F_LASTCHAR )
+    {
+       if ( cdata->lastpos==vc->ycur*vc->xchars+vc->xchars)
+       {
+           vc->ycur++;
+           vc->xcur = 0;
+           cdata->flags &= ~F_LASTCHAR;
+           do_scrollcheck(vc);
+       }
+         else
+       {
+           cdata->flags &= ~F_LASTCHAR;
+       }
+    }
+
+    if ((c>=0x20)&&(c<=0x7f))
+    {
+       if (((vc->flags)&(LOSSY))==0)
+       {
+           if ( cdata->irm == 0 )
+           {
+                if(vc->charmap[vc->xcur+vc->ycur*vc->xchars]!=c|cdata->attribs )
+                {
+                   if ( vc==vconsole_current )
+                       vc->RENDER ( vc, c );
+                   else
+                       vconsole_pending = vc->number;
+               }
+               vc->charmap[vc->xcur+vc->ycur*vc->xchars ] = c|cdata->attribs;
+            }
+           else
+           {
+               int counter;
+               int ox, oy;
+               int *ptr = vc->charmap + (vc->xcur + vc->ycur*vc->xchars);
+               for ( counter=vc->xchars-vc->xcur; counter>=0; counter-- )
+                   ptr[counter+1] = ptr[counter];
+               ptr[0] = c;
+               ox = vc->xcur; oy = vc->ycur;
+
+               for ( ; vc->xcur < vc->xchars; )
+                   do_render_noscroll ( vc->charmap[vc->xcur+vc->ycur*vc->xchars], vc );
+               vc->xcur = ox; vc->ycur = oy;
+       
+           }
+       }
+       else
+        {
+            if ( vc==vconsole_current )
+               vc->RENDER ( vc, c );
+           else
+               vconsole_pending = vc->number;
+        }
+    }
+
+    vc->xcur++;
+
+    do_scrollcheck ( vc );
+
+    if ( cdata->flags & F_LASTCHAR )
+       vc->xcur--;
+    return 0;
+}
+
+int
+TERMTYPE_PUTSTRING(string, length, vc)
+       char *string;
+       int length;
+       struct vconsole *vc;
+{
+    struct vt220_info *cdata;
+    register char c;
+    char dc[] = "x\0";
+    cdata = (struct vt220_info *)vc->data;
+
+    /* A piece of saftey code */
+    if ( vconsole_current->vtty == 0 )
+       return 0;
+
+#ifdef SIMPLE_CURSOR
+    if ( vc==vconsole_current )
+        if ( vc->CURSORUPDATE(vc)==-1 ) simple_cursor_off ( vc );
+#else
+    if ( vc==vconsole_current )
+       vc->CURSORUPDATE (vc);
+#endif
+
+    while ( ((c=*(string++))!=0) && ((length--)>0) )
+    { 
+
+    if ( cdata->state != STATE_INIT )
+       cdata->flags &= ~F_LASTCHAR;
+
+    if ( ( c == 0x0a ) || ( c== 0x0d ) )
+       cdata->flags &= ~F_LASTCHAR;
+
+/* Middle mouse button freezes the display while active */
+
+        while ((ReadByte(IO_MOUSE_BUTTONS) & MOUSE_BUTTON_MIDDLE) == 0);
+
+/* Left mouse button slows down the display speed */
+
+        if ((ReadByte(IO_MOUSE_BUTTONS) & MOUSE_BUTTON_LEFT) == 0)
+          delay(5000);
+
+/* Always process characters in the range of 0x00 to 0x1f */
+
+
+#ifdef DEBUGTERM
+*dc = c;
+switch (c)
+{
+       case 0x0a:      dprintf ( "[0a]" ); break;
+       case 0x0d:      dprintf ( "[0d]" ); break;
+       case 0x0c:      dprintf ( "[0c]" ); break;
+       case 0x1b:      dprintf ( "[1b]" ); break;
+}
+#endif
+       if ( c <= 0x1f )
+       {
+               if ( cdata->disable_function ) 
+               {
+                       if ( cdata->flags & F_LASTCHAR )
+                       {
+                         if ( cdata->lastpos==vc->ycur*vc->xchars+vc->xchars)
+                         {
+                           vc->ycur++;
+                           vc->xcur = 0;
+                           cdata->flags &= ~F_LASTCHAR;
+                           do_scrollcheck(vc);
+                         }
+                         else
+                         {
+                           cdata->flags &= ~F_LASTCHAR;
+                         }
+                       }
+
+                       switch (c)
+                       {
+                               case 0x00:      /* NUL */
+                               case 0x01:      /* SOH */
+                               case 0x02:      /* STX */
+                               case 0x03:      /* ETX */
+                               case 0x04:      /* EOT */
+                               case 0x05:      /* ENQ */
+                               case 0x06:      /* ACK */
+                                       break;
+
+                               case 0x07:      /* BEL */
+                                       beep_generate();
+                                       if ( !cdata->beepoff )
+                                               c = 'G';
+                                       break;
+
+                               case 0x08:      /* BS */
+       cdata->flags &= ~F_LASTCHAR;
+                                       if ( vc->xcur>0 )
+                                               vc->xcur--;
+                                       break;
+
+                               case 0x09:      /* TAB */
+                                       while ( vc->xcur < vc->xchars-1 )
+                                       {
+                                               vc->xcur++;
+                                               if (cdata->tab_stops[vc->xcur])
+                                                   break;
+                                       }
+                                       break;
+
+                               case 0x0a:
+       cdata->flags &= ~F_LASTCHAR;
+                                       vc->ycur++;
+                                               do_scrollcheck ( vc );
+                                       break;
+
+                               case 0x0c:
+       cdata->flags &= ~F_LASTCHAR;
+                                       if ((vc->flags&LOSSY)==0)
+                                               mapped_cls(vc);
+                                       if (vc==vconsole_current)
+                                            vc->CLS(vc);
+                                       vc->xcur=0;
+                                       vc->ycur=0;
+
+                                       break;
+                               case 0x0d:
+       cdata->flags &= ~F_LASTCHAR;
+                                       vc->xcur=0;
+                                       break;
+               
+                               case 0x10:      /* DLE */
+                               case 0x11:      /* DC1/XON */
+                               case 0x12:      /* DC2 */
+                               case 0x13:      /* DC3/XOFF */
+                               case 0x14:      /* DC4 */
+                               case 0x15:      /* NAK */
+                               case 0x16:      /* SYN */
+                               case 0x17:      /* ETB */
+                                       break;
+
+                               case 0x18:      /* CAN */
+                                       cdata->state = STATE_INIT;
+                                       clr_params(cdata);
+                                       break;
+                               
+                               case 0x19:      /* EM */
+                                       break;
+
+                               case 0x1a:      /* SUB */
+                                       cdata->state = STATE_INIT;
+                                       clr_params(cdata);
+                                       break;
+
+                               case 0x1b:      /* ESC */
+                                       cdata->state = STATE_ESC;
+                                       clr_params(cdata);
+                                       break;
+
+                               case 0x1c:      /* FS */
+                               case 0x1d:      /* GS */
+                               case 0x1e:      /* RS */
+                               case 0x1f:      /* US */
+                                       break;
+                       }       
+               }
+       }
+       else
+       {
+               /* 0x20 to 0xff depends on current state */
+               switch ( cdata->state )
+               {
+                       case STATE_INIT:
+                           do_render ( c, vc );
+                           break;
+
+                       case STATE_ESC:
+#ifdef DEBUGTERM
+{
+    char buf[]="x";
+    buf[0] = c;
+    dprintf ( buf );
+}
+#endif
+                           switch (c)
+                           {
+                               case '7':       /* SAVE CUSOR */
+                                   vt_sc ( vc );
+                                   cdata->state = STATE_INIT;
+                                   break;
+
+                               case '8':       /* RESTORE CUSOR */
+                                   vt_rc ( vc );
+                                   cdata->state = STATE_INIT;
+                                   break;
+
+                               case '=':
+                                   vt_keyappl ( vc );
+                                   cdata->state = STATE_INIT;
+                                   break;
+
+                               case '>':       /* Keypad numeric mode */
+#ifdef DEBUGTERM
+dprintf ( "\r\nKEYPAD NUMERIC MODE\r\n ");
+#endif
+                                   cdata->state = STATE_INIT;
+                                   break;
+
+                               case 'D':
+                                   vt_ind ( vc );
+                                   cdata->state = STATE_INIT;
+                                   break;                              
+
+                               case 'E':
+                                   vt_nel ( vc );
+                                   cdata->state = STATE_INIT;
+                                   break;                              
+
+                               case 'H':
+                                   cdata->tab_stops[vc->xcur] = 1;
+                                   cdata->state = STATE_INIT;
+                                   break;
+
+                               case 'M':
+                                   vt_ri ( vc );
+                                   cdata->state = STATE_INIT;
+                                   break;                              
+
+                               case 'N':
+                                   cdata->Gs = cdata->G2;
+                                   cdata->ss = 1;
+                                   cdata->state = STATE_INIT;
+                                   break;                              
+
+                               case 'O':
+                                   cdata->Gs = cdata->G3;
+                                   cdata->ss = 1;
+                                   cdata->state = STATE_INIT;
+                                   break;                              
+
+                               case 'P':
+                                   cdata->dcs_state = DCS_INIT;
+                                   cdata->state = STATE_DCS;
+                                   break;
+
+                               case 'Z':
+                                   vt_da ( vc );
+                                   cdata->state = STATE_INIT;
+                                   break;
+
+                               case '~':
+                                   cdata->GR = cdata->G1;
+                                   cdata->state = STATE_INIT;
+                                   break;                              
+
+                               case '[':
+                                   clr_params ( cdata );
+                                   cdata->state = STATE_CSI;
+                                   break;                              
+
+                               case '\\':
+                                   cdata->state = STATE_INIT;
+                                   break;                              
+
+                               case 'c':
+                                   vt_ris ( vc );
+                                   cdata->state = STATE_CSI;
+                                   break;                              
+
+                               case 'n':
+                                   cdata->GL = cdata->G2;
+                                   cdata->state = STATE_INIT;
+                                   break;                              
+
+                               case 'o':
+                                   cdata->GL = cdata->G3;
+                                   cdata->state = STATE_INIT;
+                                   break;                              
+
+                               case '}':
+                                   cdata->GR = cdata->G2;
+                                   cdata->state = STATE_INIT;
+                                   break;                              
+
+                               case '|':
+                                   cdata->GR = cdata->G3;
+                                   cdata->state = STATE_INIT;
+                                   break;                              
+
+                               default:
+                                   do_render ( c, vc );
+                                   cdata->state = STATE_INIT;
+                                   break;
+                           }
+                           break;
+
+                       case STATE_CSIQM:
+#ifdef DEBUGTERM
+{
+    char buf[]="x";
+    buf[0] = c;
+    dprintf ( buf );
+}
+#endif
+                           switch (c)
+                           {
+                               case '0':
+                               case '1':
+                               case '2':
+                               case '3':
+                               case '4':
+                               case '5':
+                               case '6':
+                               case '7':
+                               case '8':
+                               case '9':       /* parameters */
+                                   cdata->param[cdata->parami] *= 10;
+                                   cdata->param[cdata->parami] += (c-'0');
+                                   break;
+
+                               case ';':       /* next parameter */
+                                   cdata->parami =
+                                       (cdata->parami+1 < MAXPARMS) ?
+                                       cdata->parami+1 : cdata->parami;
+                                   break;
+
+                               case 'h':
+                                   vt_set_dec_priv_qm ( vc );
+                                   cdata->state = STATE_INIT;
+                                   break;
+
+                               case 'l':
+                                   vt_reset_dec_priv_qm ( vc );
+                                   cdata->state = STATE_INIT;
+                                   break;
+
+                               case 'n':
+                                   vt_dsr ( vc );
+                                   cdata->state = STATE_INIT;
+                                   break;
+
+                               case 'K':
+                                   vt_sel ( vc );
+                                   cdata->state = STATE_INIT;
+                                   break;
+
+                               default:
+                                   do_render ( '[', vc );
+                                   do_render ( c, vc );
+                                   cdata->state = STATE_INIT;
+       {
+               register int counter;
+               for ( counter=0; counter<=cdata->parami; counter++ )
+               {
+                       do_render ( '@', vc );
+               }
+       }
+                                   do_render ( c, vc );
+                                   break;
+                           }
+
+                       case STATE_CSI:
+#ifdef DEBUGTERM
+{
+    char buf[]="x";
+    buf[0] = c;
+    dprintf ( buf );
+}
+#endif
+                           switch (c)
+                           {
+                               case '0':
+                               case '1':
+                               case '2':
+                               case '3':
+                               case '4':
+                               case '5':
+                               case '6':
+                               case '7':
+                               case '8':
+                               case '9':       /* parameters */
+                                   cdata->param[cdata->parami] *= 10;
+                                   cdata->param[cdata->parami] += (c-'0');
+                                   break;
+
+                               case ';':       /* next parameter */
+                                   cdata->parami =
+                                       (cdata->parami+1 < MAXPARMS) ?
+                                       cdata->parami+1 : cdata->parami;
+                                   break;
+
+                               case '?':       /* ESC [ ? family */
+                                   cdata->state = STATE_CSIQM;
+                                   break;
+
+                               case '@':       /* insert char */
+                                   vt_ic ( vc );
+                                   cdata->state = STATE_INIT;
+                                   break;      
+
+                               /*
+                               case '!':
+                                   cdata->state = STATE_STR;
+                                   break;      
+                               */
+
+                               case 'A':       /* cursor up */
+                                   vt_cuu ( vc );
+                                   cdata->state = STATE_INIT;
+                                   break;      
+
+                               case 'B':       /* cursor down */
+                                   vt_cud ( vc );
+                                   cdata->state = STATE_INIT;
+                                   break;
+
+                               case 'C':
+                                   vt_cuf ( vc );
+                                   cdata->state = STATE_INIT;
+                                   break;
+
+                               case 'D':       /* cursor back */
+                                   vt_cub ( vc );
+                                   cdata->state = STATE_INIT;
+                                   break;
+
+                               case 'H':       /* direct cursor addressing */
+                                   vt_curadr ( vc );
+                                   cdata->state = STATE_INIT;
+                                   break;
+                               
+                               case 'J':       /* erase screen */
+                                   vt_clreos ( vc );
+                                   cdata->state = STATE_INIT;
+                                   break;
+
+                                   cdata->state = STATE_INIT;
+                                   break;
+
+                               case 'K':       /* erase line */
+                                   vt_clreol ( vc );
+                                   cdata->state = STATE_INIT;
+                                   break;
+
+                               case 'L':       /* insert line */
+                                   vt_il ( vc );
+                                   cdata->state = STATE_INIT;
+                                   break;
+
+                               case 'M':       /* delete line */
+                                   vt_dl ( vc );
+                                   cdata->state = STATE_INIT;
+                                   break;
+
+                               case 'P':       /* Delete chars */
+                                   vt_dch ( vc );
+                                   cdata->state = STATE_INIT;
+                                   break;
+
+                               case 'S':       /* scroll up */
+                                   vt_su ( vc );
+                                   cdata->state = STATE_INIT;
+                                   break;
+
+                               case 'c':
+                                   vt_da ( vc );
+                                   cdata->state = STATE_INIT;
+                                   break;
+
+                               case 'f':
+                                   vt_curadr ( vc );
+                                   cdata->state = STATE_INIT;
+                                   break;
+
+                               case 'h':
+                                   vt_set_ansi ( vc );
+                                   cdata->state = STATE_INIT;
+                                   break;
+
+                               case 'l':
+                                   vt_reset_ansi ( vc );
+                                   cdata->state = STATE_INIT;
+                                   break;
+
+                               case 'm':       /* select graphic rendition */
+                                   vt_sgr( vc );
+                                   cdata->state = STATE_INIT;
+                                   break;
+
+                               case 'n':
+                                   vt_dsr ( vc );
+                                   cdata->state = STATE_INIT;
+                                   break;
+
+                               case 'r':       /* set scrolling region */
+                                   vt_stbm ( vc );
+                                   cdata->state = STATE_INIT;
+                                   break;
+
+                               case 'y':
+                                   vt_tst ( vc );
+                                   cdata->state = STATE_INIT;
+                                   break;
+
+                               default:
+                                   do_render ( '[', vc );
+                                   do_render ( c, vc );
+                                   cdata->state = STATE_INIT;
+       {
+               register int counter;
+               for ( counter=0; counter<=cdata->parami; counter++ )
+               {
+                       do_render ( '@', vc );
+               }
+       }
+                                   do_render ( c, vc );
+                                   cdata->state = STATE_INIT;
+                                   break;
+                            } 
+                           break;
+
+                       default:
+                           cdata->state = STATE_INIT;
+                           break;
+               }
+       }
+  }
+#ifdef SIMPLE_CURSOR
+       if ( vc==vconsole_current )
+               if ( vc->CURSORUPDATE(vc)==-1 )
+                       simple_cursor_on ( vc );
+#else
+       if ( vc==vconsole_current )
+               vc->CURSORUPDATE (vc);
+#endif
+       return 0;
+}
+
+void
+console_debug()
+{
+}
+
+int
+vt220_swapin(vc)
+       struct vconsole *vc;
+{
+#ifdef SIMPLE_CURSOR
+       if ( vc==vconsole_current )
+               if ( vc->CURSORUPDATE(vc)==-1 ) simple_cursor_on ( vc );
+#else
+       if ( vc==vconsole_current )
+               vc->CURSORUPDATE (vc);
+#endif
+       return 0;
+}
+
+int
+vt220_swapout(vc)
+       struct vconsole *vc;
+{
+       return 0;
+}
+
+
+int
+vt220_sleep(vc)
+       struct vconsole *vc;
+{
+#ifdef SIMPLE_CURSOR
+       if ( vc==vconsole_current )
+               if ( vc->CURSORUPDATE(vc)==-1 ) simple_cursor_off ( vc );
+#else
+       if ( vc==vconsole_current )
+               vc->CURSORUPDATE (vc);
+#endif
+       vc->FLASH        ( vc, 0 );
+       vc->CURSOR_FLASH ( vc, 0 );
+       return 0;
+}
+
+int
+vt220_wake(vc)
+       struct vconsole *vc;
+{
+       vc->FLASH        ( vc, 1 );
+       vc->CURSOR_FLASH ( vc, 1 );
+
+#ifdef SIMPLE_CURSOR
+       if ( vc==vconsole_current )
+               if ( vc->CURSORUPDATE(vc)==-1 )
+                       simple_cursor_on ( vc );
+#else
+       if ( vc==vconsole_current )
+               vc->CURSORUPDATE (vc);
+#endif
+       return 0;
+}
+
+int
+vt220_scrollback(vc)
+       struct vconsole *vc;
+{
+       return -1;
+}
+
+int
+vt220_scrollforward(vc)
+       struct vconsole *vc;
+{
+       return -1;
+}
+
+int
+vt220_scrollbackend(vc)
+       struct vconsole *vc;
+{
+       return -1;
+}
+
+int
+vt220_debugprint(vc)
+       struct vconsole *vc;
+{
+       printf ( "VT220 TERMINAL EMULATOR\n\n" );
+       printf ( "no information\n" );
+       printf ( "\n" );
+       return 0;
+}
+
+int
+vt220_modechange(vc)
+       struct vconsole *vc;
+{
+       if (vc->number >= 64)
+               return(0);
+
+       if (vc == NULL) {
+               return(EINVAL);
+       }
+       vt_str ( vc );
+       if (vc->charmap)
+        {
+               free ( vc->charmap, M_DEVBUF );
+
+               MALLOC (vc->charmap, int *, sizeof(int)*((vc->xchars)*(vc->ychars)), M_DEVBUF, M_NOWAIT );
+               if ((vc->flags&LOSSY)==0)
+                       mapped_cls(vc);
+               if (vc==vconsole_current)
+                       vc->CLS(vc);
+       vc->xcur=0;
+       vc->ycur=0;
+       }
+
+       return 0;
+}
+
+int
+vt220_attach(vc, a, b, aux)
+       struct vconsole *vc;
+       struct device *a;
+       struct device *b;
+       void *aux;
+{
+       return 0;
+}
+
+struct terminal_emulator vt220 = {
+       vt220_name,
+       vt220_init,
+       vt220_putstring,
+       vt220_swapin,
+       vt220_swapout,
+       vt220_sleep,
+       vt220_wake,
+       vt220_scrollback,
+       vt220_scrollforward,
+       vt220_scrollbackend,
+       vt220_debugprint,
+       vt220_modechange,
+       vt220_attach
+};
diff --git a/sys/arch/arm32/dev/console/vt220.h b/sys/arch/arm32/dev/console/vt220.h
new file mode 100644 (file)
index 0000000..ef877f0
--- /dev/null
@@ -0,0 +1,117 @@
+/* $NetBSD: vt220.h,v 1.2 1996/03/18 19:33:12 mark Exp $ */
+
+/*
+ * Copyright (c) 1994-1995 Melvyn Tang-Richardson
+ * Copyright (c) 1994-1995 RiscBSD kernel team
+ * 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 RiscBSD kernel team
+ * 4. The name of the company nor the name of the author may be used to
+ *    endorse or promote products derived from this software without specific
+ *    prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE RISCBSD TEAM ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS 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.
+ *
+ * RiscBSD kernel project
+ *
+ * vt220.h
+ *
+ * VT220 emulation header file
+ *
+ * Created      : 17/09/94
+ */
+
+#define MAXTABSTOPS    132
+
+#define STATE_INIT     0
+#define STATE_HASH     1
+#define STATE_BROPN    2
+#define STATE_BRCLO    3
+#define STATE_STAR     4
+#define STATE_PLUS     5
+#define STATE_MINUS    6
+#define STATE_DOT      7
+#define STATE_SLASH    8
+#define STATE_AMPSND   9
+#define SHP_INIT       10
+#define STATE_ESC      11
+#define STATE_CSIQM    14
+#define STATE_CSI      15
+#define STATE_DCS      16
+#define STATE_SCA      17
+#define STATE_STR      18
+
+/* sub-states for Device Control String processing */
+
+#define DCS_INIT        0       /* got ESC P ... */
+#define DCS_AND_UDK     1       /* got ESC P ... | */
+#define DCS_UDK_DEF     2       /* got ESC P ... | fnckey / */
+#define DCS_UDK_ESC     3       /* got ESC P ... | fnckey / ... ESC */
+#define DCS_DLD_DSCS    4       /* got ESC P ... { */
+#define DCS_DLD_DEF     5       /* got ESC P ... { dscs */
+#define DCS_DLD_ESC     6       /* got ESC P ... { dscs ... / ... ESC */
+
+#define F_AWM          (1)
+#define F_LASTCHAR     (2)
+#define F_IRM          (3)
+
+#define MAXPARMS       10
+
+struct vt220_info {
+       int tab_stops[MAXTABSTOPS];
+       int state;
+       int hp_state;
+       int disable_function;
+       int lastchar;
+       int beepoff;
+       int param[MAXPARMS];
+       int parami;
+       u_char m_om, sc_om;             /* flag, vt100 mode, origin mode */     
+       u_char scrr_beg;
+       u_char scrr_len;
+       u_char scrr_end;
+       int simple_cursor_store;
+       int simple_cursor_on;
+
+       int dcs_state;
+
+       int G0, G1, G2, G3, GL, GR, sc_G0, sc_G1, sc_G2, sc_G3, sc_GL, sc_GR;
+       int Gs, ss;
+       int xcur, ycur, sc_xcur, sc_ycur;
+       int sc_flag;
+
+       char *report_chars;
+       int report_count;
+       int cursor_on;
+
+       int fgcol, bgcol;
+       int nfgcol, nbgcol;
+
+       int attribs;
+       int flags;
+       int sflags;
+
+       int lastpos;
+       int irm;
+};
+
diff --git a/sys/arch/arm32/dev/rd_hooks.c b/sys/arch/arm32/dev/rd_hooks.c
new file mode 100644 (file)
index 0000000..7aa9732
--- /dev/null
@@ -0,0 +1,98 @@
+/* $NetBSD: rd_hooks.c,v 1.5 1996/03/28 21:14:13 mark Exp $ */
+
+/*
+ * Copyright (c) 1995 Gordon W. Ross
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * 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 <sys/device.h>
+
+#include <vm/vm.h>
+#include <vm/vm_map.h>
+#include <vm/vm_kern.h>
+
+#include <dev/ramdisk.h>
+
+#ifndef RAMDISK_SIZE
+#define RAMDISK_SIZE 0
+#endif
+
+/*extern int boothowto;*/
+extern u_int ramdisc_size;
+struct rd_conf *bootrd = NULL;
+
+int load_ramdisc_from_floppy __P((struct rd_conf *rd, dev_t dev));
+
+/*
+ * This is called during autoconfig.
+ */
+int
+rd_match_hook(parent, self, aux)
+       struct device   *parent;
+       void    *self;
+       void    *aux;
+{
+       return (1);
+}
+
+void
+rd_attach_hook(unit, rd)
+       int unit;
+       struct rd_conf *rd;
+{
+       if (unit == 0) {
+               if (ramdisc_size == 0 && RAMDISK_SIZE)
+                       ramdisc_size = (RAMDISK_SIZE * 1024);
+
+               if (ramdisc_size != 0) {
+                       rd->rd_size = round_page(ramdisc_size);
+                       rd->rd_addr = (caddr_t)kmem_alloc(kernel_map, ramdisc_size);
+                       rd->rd_type = RD_KMEM_FIXED;
+                       bootrd = rd;
+               }
+       }
+       printf("rd%d: allocated %dK (%d blocks)\n", unit, rd->rd_size / 1024, rd->rd_size / DEV_BSIZE);
+}
+
+
+/*
+ * This is called during open (i.e. mountroot)
+ */
+
+void
+rd_open_hook(unit, rd)
+       int unit;
+       struct rd_conf *rd;
+{
+/* I use the ramdisc for other testing ... */
+#if 0
+       if (unit == 0) {
+               /* The root ramdisk only works single-user. */
+               boothowto |= RB_SINGLE;
+       }
+#endif
+}
diff --git a/sys/arch/arm32/doc/bootloader b/sys/arch/arm32/doc/bootloader
new file mode 100644 (file)
index 0000000..4bab605
--- /dev/null
@@ -0,0 +1,12 @@
+Currently the bootloader can only be built under RiscOS as this
+is the platform which it runs on. A spark file version of the
+bootloader source code is also available
+
+[ From boot/README ]
+Ok, this is the bootloader source that can be used to boot NetBSD/arm32
+from RISCOS. This code was written for use with Norcroft C and
+objasm under RISCOS. It has been modified to compile under NetBSD/arm32
+but is as yet untested.
+
+It is provided here for the moment as example code for a boot loader
+and will be updated shortly to compile under NetBSD/arm32
diff --git a/sys/arch/arm32/doc/history b/sys/arch/arm32/doc/history
new file mode 100644 (file)
index 0000000..5180a93
--- /dev/null
@@ -0,0 +1,451 @@
+3135   - fixed mode selection on boot
+       - page up/down, insert and delete now generate the correct codes in
+         the console
+       - the configured modesare now compiled in a separate file rather
+         than in vidcconsole.c
+       - The eb timeout reduced to 30 secs
+
+       - clreos problems fixed
+       - / on the keypad generated the correct code
+       - the block cursor hove down 2 scan lines to align with characters
+       - extended irq renamed netslot
+       - extra double mapping of kstack removed
+       - kstack located at efbfe000
+       - implementation of cpu_swapin() to remap the kstack
+       - patch to vm_glue to use kmem_alloc for the kstack
+       - extra pmap debugging code added with DEBUG669
+       - the pventry tables can not be dumped from the kshell
+         or from a running system.
+
+       - merged console code v133 into kernel
+       - the disklabel code no longer prints a warning if a HD is found
+         without a adfs partition
+       - the kbd driver now is capable of setting the keyboard leds.
+       - added ioctl to set the keyboard leds.
+       - added a routine to read the keyboard state.
+       - added a routine to set the keyboard state.
+       - added some prototypes to kbd.h
+       - implmented irq_setmasks() as an assembly function.
+       - added an extra disable irq mask
+       - the irq bits from IOMD reg A are cleared as soon as req A is read
+       - Debugged the plip driver. The ip packet is now word aligned when
+         passed to the upper network levels
+
+20/09/95
+       - the cpu_switch routine checks the amount of stack space used when
+         swapping in a task and prints a warning when 6K has been used
+       - removed the remnants of the old kstack double mapping
+       - a separate message is printed for umounts during a halt.
+       - added extra validation in copyin() copyout() copyinstr() and
+          copyoutstr()
+       - podule irq handler no longer panics
+       - Lark A16 podule now recognised
+       - section permission faults now cause bus errors
+       - the syscall handler now correctly uses bcopy to copy the register
+         passed parameters
+       - the copyin() function now validates the uaddrs argumant
+       - the kstack is filled with a know pattern on a fork()
+       - the postmortem code will check the size of the kstack fill pattern
+       - the assembly bcopyinout() now returns EFAULT on error
+       - the copyin() copyout() copyinstr() copyoutstr() now return EFAULT
+         if the validation checks fail.
+23/09/95
+       - the fault handler will report faults from (fu/su)iwintr()
+       - added new pmap function to return the address of the next physical
+         page (pmap_next_phys_page).
+       - added code to machdep.c to compare the page number against
+         pmap_next_phys_page() to try and locate source to kernel size
+         limit
+       - added option to syscall_special (32) to return the address of the
+         next physical page.
+       - fixed the primary bootstrap to map more memory for the secondary
+         bootstrap to use.
+       - The 936K kernel size limit has been removed.
+       - Added support for KTRACE in syscall.c
+       - Seondary bootstrap now zeros down its memory
+       - cpu_switch now zeros curpcb while there is no valid process
+       -
+1/10/95
+       - cpuswitch now detects trahsed stacks.
+       - new compile option for generation of enhanced postmortem debugging
+       - merged console code 183b
+       - implemented a memcpy routine
+       - removed remnants of the kstackpte's
+       - cleaned old commented debugging code out of cpu_switch
+       - Added new comments in exception.S
+       - userret() check for a non-zero proc pointer
+       - extended postmortem debug for cpu_switch bug
+       - updated prototype declarations in machdep.c
+       - fixed passing of proc0 pointer into cpu_switch from switch_exit
+       - podulebus now recognised Lingenuity podules
+       - Lingenuity 16bit SCSI card recognised
+
+3/10/95
+       - new compile option ROTTEN_INARDS to dump full debugging info on
+         postmortem
+       - Rewritten postmortem debug information printout
+       - Postmortem will now examine the IRQ stack for traceback info
+       - Fix cpu_exit() bug thus could result in the idle being entered at
+         splhigh()
+       - Added function prototypes for functions called in vm_machdep.c
+       - boot0() now makes sure IRQ's and FIQ's have been disabled
+       - The ARM700 FPA is now correctly turned off during boot
+       - A major has been allocated for the vidcaudio device (36)
+       - vidcaudio.c added to mainbus/ and associated support added in
+         conf/ and conf.c
+       - Patch to the console code to report the version number
+       - Latest version of dev/isa/com.c merged into mainbus/com.c
+       - Latest version of dev/isa/lpt.c merged into mainbus/lpt.c
+       - Latest version of dev/isa/wd.c merged into mainbus/wd.c
+       - new assembly version of copystr added
+       - buffer address for beep0 removed from attach message
+       - unrecognised undefined instructions are now logged as errors to
+         syslog
+       - fpe now attaches a coproc2 handler to stap coproc2 FP instructions
+         and report an error
+       - New compile option FPE_INLINE added to fpe.c to inline some of the
+         conversion functions
+       - Added new compile option FPE_PROF to fpe.c to compile in FP profiling
+         code
+       - 
+
+14/10/95
+       - added podule id for laser direct card
+       - added podule id for morley SCSI card
+       - added podule id for AXRE SCSI card
+       - added podule id for CC midi max card
+       - modified primary/secondary bootstraps to reserve special boot
+       - memory for hydra board
+       - added hydra device
+       - Added cpu identification for all hydra processors
+       - Private stacks are allocated to all slave processors
+       - All hydra processors are halted on reboot
+       - podule code checks for chunk directories but does not try to read
+         them yet.
+       - polling, immediate execution asc driver written for Acorn SCSI
+         card
+       - new special syscalls added to aid development of hydra software
+
+01/11/95
+       - kernel built with new netbsd-current source tree
+       - arm32 source updated to conform to latest netbsd-current source
+         tree
+
+03/11/95
+       - ALT-Cursor Left/Right now work the correct way round
+       - ALT-F6 now gernerates the correct code
+       - alpha version of the cumana SCSI II driver added
+       - alpha version of the ether1 driver added
+       - console code upgraded to V191
+       - driver directory structure changed.
+       - ./src/patch directory updated
+       - alpha version of ATAPI CDROM driver added
+       - mainbus and podulebus directories split in to public and private
+         directories.
+       - warnings from validate_trapframe() are prefixed with "VTF"
+       - old rpc console stuff removed from files.arm32 and source moved to
+         arch/arm32/old/
+       - the arch/arm32/pmap_stuff dir has been moved to arch/arm32/old/
+       - the _mcount.S and belgium.S files have been moved to old and
+         removed from files.arm32
+       - the device name to major code in autoconf.c now recognised /dev/cd
+         and /dev/wcd
+       - the mountroot code in stubs.c will call cd9660_mountroot() instead
+         of ffs_mountroot() is the root dev is a CDROM major.
+       - major 36 allocated to audio device
+       - major 37 allocated to vidcvideo device
+       - major 38 allocated to hydra device
+
+
+07/11/95
+       - cpu_fork() now maps in a page table for each process covering the
+         0M-4M block of memory.
+       - VM_MIN_ADDRESS lowered to 0x1000
+       - cpu_swapout() unmaps the system page at 0x00000000 from its page
+         table
+       - cpu_swapin() wires down the pagetable covering 0x00000000 and
+         maps in the system page at 0x00000000
+       - cpu_swapin() and cpu_swapout() moved to vm_machdep.c
+       - pmap_enter_pv() no longer panics on duplicate mapping, it just
+         prints an warning.
+       - alpha version of the powertec SCSI driver
+
+15/11/95
+       - switch_exit now unmaps the system page.
+       - added newline to printf in disksubr.c
+       - the console code has been moved to the dev directory
+       - cumana SCSI II driver upgraded to support interrupts
+       - powertec SCSI II driver upgraded to support interrupts
+       - the mount root code in stubs.c will attempt to mount
+         a hd partition as cd9660 if the ffs_mountroot() fails.
+       - added missing copyright notices
+       - updated some declarations in header files
+       - removed DEBUG669 code from pmap.c
+       - new syncing routine written for boot()
+       - syncing no longer requires kshell support
+       - Added extra comments to the boot() function
+       - Implemented cpu_sysctl() function (just returns not supported
+         error)
+       - The nosync kernel interrupt now correctly uses RB_NOSYNC
+       - 
+
+20/11/95
+       - restructure of directories contains device files
+       - fixed bug in pmap_pte() that could result in non-word
+         aligned pointers being returned in a off page boundry virtual
+         address was specified.
+       -
+
+24/11/95
+       - merged in new netbsd-current source tree 
+       - removed all the validate_trapframe() calls
+       - the ioctl CONSOLE_BLANKTIME now reloads the blank timer
+       - the ioctl CONSOLE_BLANKTIME uses the default blank time if a
+         negative time is specified.
+       - the machine id is now passed in the bootconfig structure
+       - the eb0 driver will set the MAC address from the machine id
+         if the address has not already been set.
+
+26/11/95
+       - Fixed the definition of va_dcl in arm32/include/varargs.h
+       - 
+
+02/12/95
+       - Fixed the WriteShort() macro
+       - Removed some redundant code from machdep.c
+       - cpu_sysctl is now declared to return an int
+       - stubs.c now has prototypes for the floppy driver functions it
+         calls when loading the ramdisc.
+       - further debugging work on the ether3 driver
+
+10/12/95
+       - Added uk device for unknown scsi devices to configuration files
+         and conf.c
+       - Alpha version of the ether3 ea device driver
+
+14/12/95
+       - Merged in beta version of the ether1 (ie) device driver
+       - added ifdefs to stubs.c so the cd9660_mountroot() is only called
+         when the kernel is compiled with CD9660
+       - created new text file to track all major and minor numbers
+
+16/12/95
+       - define __FORK_BRAINDAMAGE for compilation with the latest NetBSD
+         sources
+       - boot() now calls doshutdownhooks()
+       - merged in frank's new debugger code (process_machdep.c, ptrace.h,
+         regs.h)
+       - patches stub.c to take account of frank's new code
+       - patch cpu.h to give more detail on the PSR bits
+       - fixed the setting of p->p_mdregs to point to the trapframe in
+         the kernel mapping of kstack rather than the current mapping.
+       - removed some redundant code from mem.c
+       - commented out all the trace_debug code
+       - cpu_coredump moved from stubs.c to vm_machdep.c
+       - implemented ptrace.S in libc
+       - boot() no longer sets the curproc to proc0 if it was zero.
+       - spl's added to the console locking code
+       -
+
+19/12/95
+       - merged in new console code (V203) from Nut
+       - dosoftints() now calls pppintr()
+
+21/12/95
+       - sys_sysarch() no longer panics but returns EINVAL instead.
+       - added 3 new debugging syscalls for tracing the vnode bug
+       - identified what goes wrong with vnodes resulting in a lockup
+       - fixed a number of source file headers
+       - Added new comments to a number of routines.
+       - readdisklabel() now sets the B_AGE flag on its buffer
+       - ether3 drive now reports the controller chip type
+       - removed all stand and glue code from kshell
+       - added a new debugging syscall to all wakeup() to be called
+
+24/12/95
+       - removed redundant physconinit() call in initarm().
+       - updated comments in machdep.c
+       - added support for mulitple swap devices to be specified at boot
+         time
+       - changed debugging output in userret()
+       - added extra debugging
+       - added new debugging syscalls for tracubg the vnode bug
+       - added new debugging commands to the kshell
+       - added a new insw16() function for faster block transfers
+       - created a patch to fix p_nice
+       - the wd driver now supports multisector transfers
+       - added a new outsw16() function for faster block transfers but is
+         currently untested
+       - the existing arm32/fpe directory has been renamed to
+         arm32/fpe-sp
+       - started work on integrating the ARM FPE
+       - a new fpe directory arm32/fpe-arm has been created for the new FPE
+       - file arm32/cpu.S renamed to arm32/cpuswitch.S
+       - created new mainbus device 'cpu' (mainbus/cpu.c)
+       - created new header file include/cpus.h to hold macros and
+         structure definitions for cpus.
+       - all identify functions for the processor and FPA have been moved
+         to mainbus/cpu.c
+       - FPE is now attached during the cpu attachment during
+         autoconfiguration
+       - Identification of CPU and FPU split into separate functions in
+         mainbus/cpu.c
+       - Added new function initialise_fpe() to fpe-sp/fpe.c This is the
+         new initialisation point for the FPE. All vector claiming is done
+         in this routine. Routine is also responcible for IDing the FPE.
+       - ramdisc memory allocation now only ever done in the ramdisc driver
+       - cpu_model now declared in mainbus/cpu.c
+       - rpc_configure() renamed to configure()
+       - added function need_proftick() to clock.c
+       - further development work ARM FPE driver
+       - glue code for ARM FPE written and tested.
+       - ARM FPE now gets first chance as being installed with
+         the existing FPE installed as a fallback if the ARM FPE
+         installation failed.
+       - Hooks for the ARM FPE added in cpu_fork() cpu_exit() and
+         cpu_switch()
+       - Recoding of ether3 driver started.
+       - More debugging code added to trace vnode bug
+       - macro added to syscall.c to handle exit from the syscall handler
+         for special development syscalls.
+       - Vnode bug idenitfied as a corruption of the first word (v_flag)
+         of certain vnodes.
+       - Ether3 driver rewritten and debugged. Now a beta stage driver
+       - Vnode corruption traced to console code.
+       - Ether3 drive now has interface buffer memory tests
+       - vnode corruption traced to do_scrolldown() routine in the
+         console driver.
+       - vnode corruption bug located and fixed. Incorrect loop start and
+         end points when scrolling the character map down (writing beyond
+         allocated memory).
+       - Started work on rewriting the etherB driver
+       - cleaned up various header files
+       - removed stub.c as it was no longer needed
+       - updated strstr.c
+       - hydra code hooks now only compiled in if hydra device is
+         configured
+       - EtherB driver rewritten to match recoding of ether3 driver
+       - EtherB driver now a beta stage driver
+       - Work started on generic driver code for SEEQ EDLC's
+       - vidcvideo device now supports multiple openings
+       - EtherB driver now puts the controller to sleep when not active
+       - strstr() replaced with version borrowed from libc/string/strstr.c
+
+05/01/96
+       - Further development of ARM FPE
+       - generic fas216 code no longer experimental/NDA
+       - powertec scsi driver no longer experimental/NDA
+       - entry to undefined instruction handlers is now indirected in
+         exception.s
+       - entry to the undefined instruction handlers is made a trapframe
+         on the stack and r0-r12 preserved from exception.
+       - bounce code added so the existing undefined instuction handler
+         can be called with r0 pointing to the trapframe.
+       - new function arm_fpe_copycontext created
+       - fixed the use of FP instructions in sfas.c
+       - fixed errors in the softint code
+       - netns support can be be compiled in the kernel
+       - fixed warnings in fpe-sp/fpe.c and mainbus/cpu.c
+
+10/01/96
+       - exception.S updated pending new undefined instruction handling
+         code
+       - merged in new wd driver from NetBSD-current
+       - merged in new com driver from NetBSD-current
+       - merged in new fd driver from NetBSD-current
+       - created new file sys_machdep.c for machine dependant syscall stuff
+       - moved sys_sysctl from machdep.c to sys_machdep.c
+       - fixed nested comments in iic.S
+       - removed old bug tracing code from cpuswitch.S
+       - debugged new fd driver
+
+13/01/96
+       - undefined mode r13 added to the pcb structure
+       - new version of the ARM fpe built
+       - ARM FPE now has core deactivate routine accessable
+       - Call back from ARM FPE added on instruction completion
+       - cpu_switch() now switches UND32 mode r13
+       - cpu_fork() now sets up UND32 mode r13 in pcb
+       - undefined vector now calls stub routine that indirects
+         via address held in data area.
+       - data abort handler address now held in data area rather
+         than text area.
+       - prefetch abort handler address now held in data area rather
+         than text area.
+       - disabled warnings about soft errors from the fd driver
+
+17/01/96
+       - implemented pmap_resident_count()
+       - fixed the kernel avail_start and avail_end variable. This
+         fixes the divide by zero bug in /bin/ps
+       - ps now reports the correct resident size
+
+19/01/96
+       - kernel now supports permission faults in UND32 mode.
+       - kernel shell now has kshell> prompt instead of #
+       - ramdisc loading code has been moved from stubs.c to fd.c
+       - ramdisc loading code now uses a rd_conf structure to
+         describe the ramdisc.
+       - rd_hooks.c file added to the arm32/dev directory in
+         order to support the generic ramdisk.
+       - patch to generic ramdisc driver to allow a device match hook
+       - mainbus/ramdisc.c removed.
+       - generic ramdisc has now replaces to mainbus/ramdisc.
+       - fault.c reformatted
+       - new compile symbols introduced to comile in debug code for
+         fault correction.
+       - all remnants of the trace_debug code removed.
+       - armfpe code moved from arm32/fpe-arm/arm32 to arm32/fpe-arm/
+       - fu*() su*() functions moved from libkern into arm32/fusu.c
+       - added code to locore.S to traceback frames on the user process
+         stack
+       - added variable to enable / disable tracing back of user process
+         stacks
+       - added syscall to control user stack trackbacks.
+       - optimised ARM FPE exception delivery code
+       - implemented ARM FPE post processing callback glue
+       - ARM FPE post processor now calls user
+       - ARM FPE post processor optimised to recover some of the
+         performance lost by calling userret()
+       - integrated alpha version of the etherH driver
+       - updated ramdisc hooks to removed the need for a rd_match_hook()
+         function
+       - added Oak to the list of podule manufacturers
+       - kernel now reconised Oak SCSI I cards.
+       - Added generic NCR5380 SCSI driver code
+       - integrating in alpha version of the oak SCSI driver
+
+26/01/96
+       - merged in latest updates from the NetBSD-current source tree
+
+29/01/96
+       - code updated for merging into NetBSD source tree
+
+02/02/96
+       - assembly symbol file now names assym.h instead of assym.s
+       - The symbol LOCORE has been replaced with _LOCORE
+       - ramdisc loading code in now compiled in conditionally on
+         RAMDISK_HOOKS
+       - Further development of hydrabus device.
+       - cpus can noe be attached to both the mainbus and the hydrabus
+       - hooks for hydrabus device updated in pmap.c syscall.c and
+         machdep.c
+       - Extra comments added in exception.S
+       - sizeof(struct trapframe) now defined in assym.h
+       - register fixup for data transfer instruction aborts now handles
+         LDC/STC instructions i.e. hardware executed LDF/STF
+       - configuration files updated for latest devices
+       - fixed use of mkdepend in makefile
+       - fixed the bug that caused panics when issuing the mode change
+         ioctl to the vidcvideo device
+       - console code version number updated
+       - Updated armfpe_post_proc() to take a trapframe pointer as the
+         second argument
+       - updated the armfpe_post_proc_glue() code to fake a trapframe
+         structure from the FPE frame before calling the post proc handler
+         so that sendsig has a valid trapframe in p->p_md.md_regs
+       - updated the armfpe_post_proc_glue() code to patch the FPE frame
+         with data from the trapframe on return from the post proc handler.
+       - signal delivery is now working during FP instructions.
+       - mondef code resurrected and renamed to setdisplay and moved to the
+         stand directory.
diff --git a/sys/arch/arm32/doc/majors+minors b/sys/arch/arm32/doc/majors+minors
new file mode 100644 (file)
index 0000000..2b0463a
--- /dev/null
@@ -0,0 +1,246 @@
+/* $NetBSD: majors+minors,v 1.3 1996/04/19 20:04:29 mark Exp $ */
+
+/*
+ * Copyright (c) 1994 Mark Brinicombe.
+ * 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 Mark Brinicombe.
+ * 4. The name of the company nor the name of the author may 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 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.
+ *
+ * RiscBSD kernel project
+ *
+ * majors
+ *
+ * list of all allocated major numbers
+ *
+ * Created      : 17/09/94
+ * Last updated : 30/12/95
+ *
+ *    $Id: majors+minors,v 1.1.1.1 1996/04/24 11:08:39 deraadt Exp $
+ */
+
+List of allocated and reserved major and minor numbers
+
+The block and character major numbers are ALWAYS allocated together to the
+same device driver even if the driver does not require both.
+ 0 B   - reserved
+ 0 C   - memory device
+         minor = 0 - /dev/mem
+         minor = 1 - /dev/kmem
+         minor = 2 - /dev/null
+         minor = 3 - /dev/zero
+ 1 B   - swap device
+ 1 C   - psuedo swap device
+         minor = 0 - /dev/drum
+ 2 B   - reserved
+ 2 C   - console device
+         minor = 0 - /dev/console
+ 3 B   - reserved
+ 3 C   - controlling terminal
+         minor = 0 - /dev/tty
+ 4 B   - reserved
+ 4 C   - virtual console
+         /dev/ttyv{unit}
+         unit = minor
+ 5 B   - reserved
+ 5 C   - kernel log device
+         minor = 0 - /dev/klog
+ 6 B   - reserved
+ 6 C   - psuedo tty master
+         /dev/pty{class}{unit}
+         unit = minor % 16
+         minor / 16 = 0 - class = p
+         minor / 16 = 1 - class = q
+         minor / 16 = 2 - class = r
+         minor / 16 = 3 - class = s
+         minor / 16 = 4 - class = t
+ 7 B   - reserved
+ 7 C   - psuedo tty slave
+         /dev/tty{class}{unit}
+         unit = minor % 16
+         minor / 16 = 0 - class = p
+         minor / 16 = 1 - class = q
+         minor / 16 = 2 - class = r
+         minor / 16 = 3 - class = s
+         minor / 16 = 4 - class = t
+ 8 B   - reserved
+ 8 C   - parallel printer
+         /dev/lp{class}{unit}
+         unit = minor & 0x1f
+         minor & 0x80 = 0x00 - class = t - interrupt driver
+         minor & 0x80 = 0x80 - class = a - polling driver
+         e.g.
+           0 - /dev/lpt0
+         128 - /dev/lpa0
+ 9 B   - reserved
+ 9 C   - quadrature mouse
+         minor = 0 - /dev/quadmouse
+10 B   - reserved
+10 C   - beep device
+         minor = 0 - /dev/beep
+11 B   - reserved
+11 C   - keyboard device
+         minor = 0 - /dev/kbd
+12 B   - reserved
+12 C   - serial port
+         /dev/tty0{unit}
+         unit = minor
+13 B   - reserver
+13 C   - reserved
+14 B   - reserved
+14 C   - reserved
+15 B   - reserved
+15 C   - reserved
+16 B   - ST506/ESDI/IDE disk
+         /dev/wd{unit}{partition}
+         partition = minor % 8
+         unit = minor / 8
+16 C   - ST506/ESDI/IDE disk
+         /dev/rwd{unit}{partition}
+         partition = minor % 8
+         unit = minor / 8
+17 B   - floppy disk
+         /dev/fd{unit}{partition}
+         partition = minor % 8
+         unit = minor / 8
+17 C   - floppy disk
+         /dev/rfd{unit}{partition}
+         partition = minor % 8
+         unit = minor / 8
+18 B   - ram disk
+         /dev/rd{unit}{partition}
+         partition = minor % 8
+         unit = minor / 8
+18 C   - ram disk
+         /dev/rrd{unit}{partition}
+         partition = minor % 8
+         unit = minor / 8
+19 B   - vnode disk driver
+         /dev/vnd{unit}{partition}
+         partition = minor % 8
+         unit = minor / 8
+19 C   - vnode disk driver
+         /dev/rvnd{unit}{partition}
+         partition = minor % 8
+         unit = minor / 8
+20 B   - reserved (ATAPI CDROM)
+         /dev/wcd{unit}{partition}
+         partition = minor % 8
+         unit = minor / 8
+20 C   - reserved (ATAPI CDROM)
+         /dev/rwcd{unit}{partition}
+         partition = minor % 8
+         unit = minor / 8
+21 B   - concatenated disk driver
+         /dev/ccd{unit}{partition}
+         partition = minor % 8
+         unit = minor / 8
+21 C   - concatenated disk driver
+         /dev/rccd{unit}{partition}
+         partition = minor % 8
+         unit = minor / 8
+22 B   - reserved
+22 C   - reserved
+23 B   - reserved
+23 C   - reserved
+24 B   - SCSI disk
+         /dev/sd{unit}{partition}
+         partition = minor % 8
+         unit = minor / 8
+24 C   - SCSI disk
+         /dev/rsd{unit}{partition}
+         partition = minor % 8
+         unit = minor / 8
+25 B   - SCSI tape
+25 C   - SCSI tape
+26 B   - SCSI cdrom
+         /dev/cd{unit}{partition}
+         partition = minor % 8
+         unit = minor / 8
+26 C   - SCSI cdrom
+         /dev/rcd{unit}{partition}
+         partition = minor % 8
+         unit = minor / 8
+27 B   - reserved
+27 C   - SCSI autochanger
+         /dev/ch{unit}
+         unit = minor
+28 B   - reserved
+28 C   - SCSI unknown device
+         /dev/uk{unit}
+         unit = minor
+29 B   - reserved
+29 C   - SCSI scanner device
+         /dev/ss{unit}
+         unit = minor
+30 B   - reserved
+30 C   - reserved
+31 B   - reserved
+31 C   - reserved
+32 B   - reserved
+32 C   - Berkeley packet filter
+         /dev/bpf{unit}
+         unit = minor
+         minor = 0 - /dev/bpf0
+         minor = 1 - /dev/bpf1
+         minor = 2 - /dev/bpf2
+         minor = 3 - /dev/bpf3
+33 B   - reserved
+33 C   - network tunnel
+         /dev/tun{unit}
+         unit = minor
+         minor = 0 - /dev/tun0
+         minor = 1 - /dev/tun1
+         minor = 2 - /dev/tun2
+34 B   - reserved
+34 C   - file descriptor pseudo-device
+         minor = 0 - /dev/stdin
+         minor = 1 - /dev/stdout
+         minor = 2 - /dev/stderr
+35 B   - reserved
+35 C   - loadable module driver
+         minor = 0 - /dev/lkm
+36 B   - reserved
+36 C   - generic audio device
+37 B   - reserved
+37 C   - vidcvideo device
+         minor = 0 - /dev/vidcvideo
+38 B   - reserved
+38 C   - cpu/hydra
+         minor = 0 - /dev/cpu0
+39 B   - reserved
+39 C   - reserved
+40 B   - reserved
+40 C   - PS2 mouse
+         minor = 0 - /dev/pms
+41 B   - reserved
+41 C   - reserved
+42 B   - reserved
+42 C   - IIC device
+43 B   - reserved
+43 C   - RTC device
diff --git a/sys/arch/arm32/doc/note.users b/sys/arch/arm32/doc/note.users
new file mode 100644 (file)
index 0000000..bfe56a9
--- /dev/null
@@ -0,0 +1,13 @@
+Ok there are a number of things that need to be done that I do not
+have time to do and am unlikely to have time to do them in the near
+future.
+These are currently being left in the hope that users will do them
+instead.
+
+1. replace netinet/in_cksum.c with an assembly version
+2. replace netns/ns_chsum.c with an assembly version
+3. drivers for currently unsupported podules
+4. replacing the C string functions in libc with assembly ones (work
+   started but not finished)
+5. porting libpthread to arm32 architecture
+
diff --git a/sys/arch/arm32/fpe-arm/armfpe.h b/sys/arch/arm32/fpe-arm/armfpe.h
new file mode 100644 (file)
index 0000000..fbcdaf4
--- /dev/null
@@ -0,0 +1,137 @@
+/*
+ * $NetBSD: armfpe.h,v 1.3 1996/03/18 19:54:53 mark Exp $
+ *
+ * Copyright (c) 1995 Neil A Carson.
+ * 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 Brini.
+ * 4. The name of the company nor the name of the author may 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 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.
+ *
+ * RiscBSD kernel project
+ *
+ * armfpe.h
+ *
+ * Details of functions and structures needed for ARM FP cor
+ * support in RiscBSD
+ *
+ * Created      : 04/01/96
+ */
+
+#ifndef __ARM32_ARM_FPE_H
+#define __ARM32_ARM_FPE_H
+
+/************************************ Types ***********************************/
+
+/*
+ * An extended precision floating point number
+ */
+typedef struct {
+       u_int32_t exponent;
+       u_int32_t mantissa_hi;
+       u_int32_t mantissa_lo;
+} fp_extended_precision_t;
+
+/*
+ * Type for a saved FP context, if we want to translate the context to a
+ * user-readable form
+ */
+typedef struct fp_context_frame {
+       u_int32_t fpsr;
+       fp_extended_precision_t regs[8];
+} fp_context_frame_t;
+
+/************************************* Module *********************************/
+
+typedef struct {
+       /*
+        * Addresses of procedures/functions
+        */
+
+       u_int32_t core_abort_addr;
+       u_int32_t core_initws_addr;
+       u_int32_t core_initcontext_addr;
+       u_int32_t core_changecontext_addr;
+       u_int32_t core_shutdown_addr;
+       u_int32_t core_activatecontext_addr;
+       u_int32_t core_deactivatecontext_addr;
+       u_int32_t core_savecontext_addr;
+       u_int32_t core_loadcontext_addr;
+       u_int32_t core_disable_addr;
+       u_int32_t core_enable_addr;
+
+       /*
+        * Addresses of things that need to be filled in by the kernel on startup
+        */
+
+       u_int32_t *main_ws_ptr_addr;
+       u_int32_t *local_handler_ptr_addr;
+       u_int32_t *old_handler_ptr_addr;
+       u_int32_t *exc_handler_ptr_addr;
+       u_int32_t *fp_post_proc_addr;
+
+       /*
+        * Numbers that the kernel needs - these are not pointers so do not need to
+        * be relocated!
+        */
+
+       u_int32_t WorkspaceLength;
+       u_int32_t ContextLength;
+} arm_fpe_mod_hdr_t;
+
+/**************************** Procedures in arm_fpe.c *************************/
+
+#ifdef _KERNEL
+
+/* macro to return the FP context for a process */
+
+#define FP_CONTEXT(p) ((u_int)(((u_char *)(p)->p_addr) + sizeof(struct user)))
+
+/* Prototypes */
+
+void arm_fpe_mod_reloc __P((void));
+int arm_fpe_boot       __P((void));
+int initialise_arm_fpe __P((cpu_t *cpu));
+void arm_fpe_postproc  __P((u_int fpframe, struct trapframe *frame));
+void arm_fpe_exception __P((int exception, u_int pc, u_int fpframe));
+
+void arm_fpe_core_disable      __P((void));
+void arm_fpe_core_enable       __P((void));
+u_int arm_fpe_core_initws      __P((u_int workspace, int handler1, int handler2));
+u_int arm_fpe_core_abort       __P((u_int context, int r12, int pc));
+void arm_fpe_core_initcontext  __P((u_int context));
+u_int arm_fpe_core_changecontext       __P((u_int context));
+void arm_fpe_core_shutdown             __P((void));
+void arm_fpe_core_activatecontext      __P((u_int context));
+u_int arm_fpe_core_deactivatecontext   __P((void));
+u_int arm_fpe_core_savecontext __P((u_int context, int *savearea, int pc));
+void arm_fpe_core_loadcontext  __P((u_int context, int *loadarea));
+void arm_fpe_copycontext       __P((u_int c1, u_int c2));
+#endif
+
+#endif
diff --git a/sys/arch/arm32/fpe-arm/armfpe.s b/sys/arch/arm32/fpe-arm/armfpe.s
new file mode 100644 (file)
index 0000000..71066ca
--- /dev/null
@@ -0,0 +1,7459 @@
+/* $NetBSD: armfpe.s,v 1.2 1996/03/18 19:54:55 mark Exp $ */
+
+/*
+ * Copyright (c) 1996 Neil A Carson.
+ * Copyright (c) 1996 Advanced Risc Machines Ltd.
+ * 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 RiscBSD kernel team.
+ * 4. The name of the company nor the name of the author may 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 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.
+ *
+ * RiscBSD kernel project
+ *
+ * armfpe.s
+ *
+ * ARM FPE core
+ *
+ * Created      : 05/01/96
+ */
+
+/* DO NOT MODIFY - THIS FILE IS AUTOMATICALLY GENERATED. */
+
+/* Generated from KernelFPE */
+
+.text
+.global _arm_fpe_mod
+_arm_fpe_mod:
+       .word   0x00006cc0
+       .word   0x00006e54
+       .word   0x00006ebc
+       .word   0x00006f5c
+       .word   0x0000706c
+       .word   0x00006fd8
+       .word   0x00006f64
+       .word   0x00007140
+       .word   0x0000722c
+       .word   0x0000707c
+       .word   0x000070d0
+       .word   0x000072e4
+       .word   0x000072fc
+       .word   0x00007314
+       .word   0x00007364
+       .word   0x000072e8
+       .word   0x0000000c
+       .word   0x00000088
+       .word   0x00000000
+       .word   0x00000000
+       .word   0x00000000
+       .word   0xe24dd040
+       .word   0xe8cd7fff
+       .word   0xe58de03c
+       .word   0xe1a0c00d
+       .word   0xe10fa000
+       .word   0xe14f9000
+       .word   0xe92d0600
+       .word   0xe319000f
+       .word   0xe24e9004
+       .word   0x04b9b000
+       .word   0x1599b000
+       .word   0xe92d4000
+       .word   0xeb001c90
+       .word   0xe8bd0400
+       .word   0xe8bd4000
+       .word   0xe31b0302
+       .word   0x0a000849
+       .word   0xe20b9c0f
+       .word   0xe3590c01
+       .word   0x1a000015
+       .word   0xe59aa000
+       .word   0xee509110
+       .word   0xe2098c0f
+       .word   0xee307110
+       .word   0xe08ff328
+       .word   0x00000000
+       .word   0xea001ca9
+       .word   0xea001ca8
+       .word   0xea001ca7
+       .word   0xea001ca6
+       .word   0xea000103
+       .word   0xea0002b1
+       .word   0xea00002e
+       .word   0xea0002af
+       .word   0xea00018f
+       .word   0xea0002b8
+       .word   0xea00018d
+       .word   0xea0002b6
+       .word   0xea0000fb
+       .word   0xea0002ad
+       .word   0xea000026
+       .word   0xea0002ab
+       .word   0xe3590c02
+       .word   0x1a00082e
+       .word   0xe59aa000
+       .word   0xee509110
+       .word   0xe2098c0f
+       .word   0xee307110
+       .word   0xe08ff328
+       .word   0x00000000
+       .word   0xea001c91
+       .word   0xea001c90
+       .word   0xea001c8f
+       .word   0xea001c8e
+       .word   0xea0000e7
+       .word   0xea000299
+       .word   0xea000008
+       .word   0xea000297
+       .word   0xea00081b
+       .word   0xea0002a0
+       .word   0xea000819
+       .word   0xea00029e
+       .word   0xea0000df
+       .word   0xea000295
+       .word   0xea000000
+       .word   0xea000293
+       .word   0xe3190010
+       .word   0x13190601
+       .word   0x0a00000d
+       .word   0xe59c803c
+       .word   0xe2488004
+       .word   0xe58c803c
+       .word   0xe91c0300
+       .word   0xe129f009
+       .word   0xe169f008
+       .word   0xe1a0d00c
+       .word   0xe8dc7fff
+       .word   0xe1a00000
+       .word   0xe28dd03c
+       .word   0xe8fd8000
+       .word   0xe3190010
+       .word   0x13190601
+       .word   0x1a00011d
+       .word   0xe389b402
+       .word   0xe3170b01
+       .word   0x059c803c
+       .word   0x02488004
+       .word   0x058c803c
+       .word   0xe10f8000
+       .word   0xe3c88080
+       .word   0xe129f008
+       .word   0xe1a00000
+       .word   0xe31b0901
+       .word   0x0d2d020c
+       .word   0x1d2d420c
+       .word   0xe20b8a03
+       .word   0xe0888088
+       .word   0xe08d8528
+       .word   0xe8980007
+       .word   0xe28dd030
+       .word   0xe3c03103
+       .word   0xe2000103
+       .word   0xe20b8301
+       .word   0xe18335a8
+       .word   0xe3530903
+       .word   0x22433801
+       .word   0xe20b50e0
+       .word   0xe20b8702
+       .word   0xe18555a8
+       .word   0xe20b4201
+       .word   0xe31b0102
+       .word   0x02644000
+       .word   0xea00001e
+       .word   0x00003f81
+       .word   0x0000407e
+       .word   0x00003f81
+       .word   0x0000407e
+       .word   0x00003f81
+       .word   0x0000407e
+       .word   0x00003f81
+       .word   0x0000407e
+       .word   0x00003c01
+       .word   0x000043fe
+       .word   0x00003c01
+       .word   0x000043fe
+       .word   0x00003c01
+       .word   0x000043fe
+       .word   0x00003c01
+       .word   0x000043fe
+       .word   0x00000000
+       .word   0x00007ffe
+       .word   0x00000000
+       .word   0x00007ffe
+       .word   0x00000000
+       .word   0x00007ffe
+       .word   0x00000000
+       .word   0x00007ffe
+       .word   0xe3100101
+       .word   0x1a00000f
+       .word   0xe20b50e0
+       .word   0xe20b8702
+       .word   0xe18555a8
+       .word   0xe3a04000
+       .word   0xeb000bbe
+       .word   0xe24f8084
+       .word   0xe0888125
+       .word   0xe8980300
+       .word   0xe1530009
+       .word   0xd1580003
+       .word   0xca000015
+       .word   0xe1800003
+       .word   0xe3540000
+       .word   0x11b08aa7
+       .word   0x33877010
+       .word   0x8b000d35
+       .word   0xe92d0007
+       .word   0xe20b8a07
+       .word   0xe08f84a8
+       .word   0xe1a0e00f
+       .word   0xe288f044
+       .word   0xee207110
+       .word   0xe92d4000
+       .word   0xeb001c01
+       .word   0xe8bd4000
+       .word   0xe91c0300
+       .word   0xe129f009
+       .word   0xe169f008
+       .word   0xe1a0d00c
+       .word   0xe8dc7fff
+       .word   0xe1a00000
+       .word   0xe28dd03c
+       .word   0xe8fd8000
+       .word   0xe24fe05c
+       .word   0xe0588003
+       .word   0xca000c8f
+       .word   0xea000c18
+       .word   0xecbd8203
+       .word   0xe1a0f00e
+       .word   0xecbd9203
+       .word   0xe1a0f00e
+       .word   0xecbda203
+       .word   0xe1a0f00e
+       .word   0xecbdb203
+       .word   0xe1a0f00e
+       .word   0xecbdc203
+       .word   0xe1a0f00e
+       .word   0xecbdd203
+       .word   0xe1a0f00e
+       .word   0xecbde203
+       .word   0xe1a0f00e
+       .word   0xecbdf203
+       .word   0xe1a0f00e
+       .word   0xe20b3a0f
+       .word   0xe3530a0d
+       .word   0x2a000011
+       .word   0xe79c6523
+       .word   0xeb000f16
+       .word   0xe20b50e0
+       .word   0xe20b8702
+       .word   0xe18555a8
+       .word   0xe3a04000
+       .word   0xeb000b84
+       .word   0xe1800003
+       .word   0xe3540000
+       .word   0x11b08aa7
+       .word   0x33877010
+       .word   0x8b000d01
+       .word   0xe92d0007
+       .word   0xe20b8807
+       .word   0xe08f86a8
+       .word   0xe1a0e00f
+       .word   0xe248f08c
+       .word   0xeaffffca
+       .word   0xe3530a0f
+       .word   0x0a00000c
+       .word   0xe51c8008
+       .word   0xe218800f
+       .word   0x0affffe8
+       .word   0xe3888090
+       .word   0xe10f9000
+       .word   0xe3c9601f
+       .word   0xe1868008
+       .word   0xe129f008
+       .word   0xe3530a0d
+       .word   0x01a0600d
+       .word   0x11a0600e
+       .word   0xe129f009
+       .word   0xeaffffdf
+       .word   0xe59c603c
+       .word   0xe2866008
+       .word   0xeaffffdc
+       .word   0xe31b0702
+       .word   0x131b0080
+       .word   0x1a00076c
+       .word   0xe31b0010
+       .word   0x0a000042
+       .word   0xe20b860f
+       .word   0xe08ff928
+       .word   0x00000000
+       .word   0xeaffffcf
+       .word   0xea0000a0
+       .word   0xea000764
+       .word   0xea000763
+       .word   0xea000762
+       .word   0xea000761
+       .word   0xea000760
+       .word   0xea00075f
+       .word   0xea00075e
+       .word   0xea000081
+       .word   0xea00075c
+       .word   0xea00007f
+       .word   0xea00075a
+       .word   0xea00007d
+       .word   0xea000758
+       .word   0xea00007b
+       .word   0x00000000
+       .word   0x00000000
+       .word   0x00000000
+       .word   0x00000000
+       .word   0x00003fff
+       .word   0x80000000
+       .word   0x00000000
+       .word   0x00000000
+       .word   0x00004000
+       .word   0x80000000
+       .word   0x00000000
+       .word   0x00000000
+       .word   0x00004000
+       .word   0xc0000000
+       .word   0x00000000
+       .word   0x00000000
+       .word   0x00004001
+       .word   0x80000000
+       .word   0x00000000
+       .word   0x00000000
+       .word   0x00004001
+       .word   0xa0000000
+       .word   0x00000000
+       .word   0x00000000
+       .word   0x00003ffe
+       .word   0x80000000
+       .word   0x00000000
+       .word   0x00000000
+       .word   0x00004002
+       .word   0xa0000000
+       .word   0x00000000
+       .word   0x00000000
+       .word   0xe3190010
+       .word   0x13190601
+       .word   0x0a000003
+       .word   0xeaffff21
+       .word   0xe3190010
+       .word   0x13190601
+       .word   0x1a00004a
+       .word   0xe389b402
+       .word   0xe3170b01
+       .word   0x059c803c
+       .word   0x02488004
+       .word   0x058c803c
+       .word   0xe10f8000
+       .word   0xe3c88080
+       .word   0xe129f008
+       .word   0xe1a00000
+       .word   0xe31b0902
+       .word   0x1a000020
+       .word   0xed2d420c
+       .word   0xed2d020c
+       .word   0xe20b8807
+       .word   0xe0888088
+       .word   0xe08d8728
+       .word   0xe8980007
+       .word   0xe1b09e8b
+       .word   0x208f8ca9
+       .word   0x224880ec
+       .word   0x308d8da9
+       .word   0x30888d29
+       .word   0xe8980038
+       .word   0xe28dd060
+       .word   0xe24fefb7
+       .word   0xe20b860f
+       .word   0xe08ff928
+       .word   0x00000000
+       .word   0xea0012b1
+       .word   0xea0012e9
+       .word   0xea0012af
+       .word   0xea0012ae
+       .word   0xea001327
+       .word   0xea001326
+       .word   0xea001616
+       .word   0xea001615
+       .word   0xea001120
+       .word   0xea0012e1
+       .word   0xea001321
+       .word   0xea001320
+       .word   0xea001912
+       .word   0xea000706
+       .word   0xea000705
+       .word   0xea000704
+       .word   0xe1b09e8b
+       .word   0x208f8ca9
+       .word   0x22488f56
+       .word   0x2a000004
+       .word   0x5d2d020c
+       .word   0x4d2d420c
+       .word   0xe3c99102
+       .word   0xe08d8da9
+       .word   0xe0888d29
+       .word   0xe8980007
+       .word   0x328dd030
+       .word   0xe24fefd6
+       .word   0xe20b860f
+       .word   0xe08ff928
+       .word   0x00000000
+       .word   0xea0013d3
+       .word   0xea0013d2
+       .word   0xea0013d1
+       .word   0xea0011f2
+       .word   0xea00112c
+       .word   0xea0014cf
+       .word   0xea0014ce
+       .word   0xea001582
+       .word   0xea001709
+       .word   0xea001708
+       .word   0xea001842
+       .word   0xea001799
+       .word   0xea001798
+       .word   0xea001916
+       .word   0xea0013f8
+       .word   0xea0013ea
+       .word   0xe02b8009
+       .word   0xe59f90f8
+       .word   0xe1180009
+       .word   0x1afffecf
+       .word   0xe10f8000
+       .word   0xe3c88080
+       .word   0xe129f008
+       .word   0xe1a00000
+       .word   0xe31b0502
+       .word   0x0a000016
+       .word   0xed2d420c
+       .word   0xed2d020c
+       .word   0xe20b8807
+       .word   0xe0888088
+       .word   0xe08d8728
+       .word   0xe8980007
+       .word   0xe1b09e8b
+       .word   0x208f8ca9
+       .word   0x22488f85
+       .word   0x308d8da9
+       .word   0x30888d29
+       .word   0xe8980038
+       .word   0xe28dd060
+       .word   0xeb0013fb
+       .word   0xe20b3a0f
+       .word   0xe3330a0f
+       .word   0x1a000012
+       .word   0xe51c8008
+       .word   0xe3c8820f
+       .word   0xe206620f
+       .word   0xe1888006
+       .word   0xe50c8008
+       .word   0xeaffff0d
+       .word   0xe1b09e8b
+       .word   0x208f8ca9
+       .word   0x22488f96
+       .word   0x2a000004
+       .word   0x5d2d020c
+       .word   0x4d2d420c
+       .word   0xe3c99102
+       .word   0xe08d8da9
+       .word   0xe0888d29
+       .word   0xe8980007
+       .word   0x328dd030
+       .word   0xeb00141e
+       .word   0xe20b3a0f
+       .word   0xe3530a0d
+       .word   0x2a000001
+       .word   0xe78c6523
+       .word   0xeafffefc
+       .word   0xe3330a0f
+       .word   0x0affffe6
+       .word   0xe51c8008
+       .word   0xe218800f
+       .word   0x0afffff8
+       .word   0xe3888090
+       .word   0xe10f9000
+       .word   0xe3c9401f
+       .word   0xe1848008
+       .word   0xe129f008
+       .word   0xe3530a0d
+       .word   0x01a0d006
+       .word   0x11a0e006
+       .word   0xe129f009
+       .word   0xeafffeed
+       .word   0x00ff00ff
+       .word   0xe10f8000
+       .word   0xe3c88080
+       .word   0xe129f008
+       .word   0xe1a00000
+       .word   0xe31b0402
+       .word   0x1affff2d
+       .word   0xe20b5501
+       .word   0xe1a05725
+       .word   0xe20b8902
+       .word   0xe1855428
+       .word   0xe3550d06
+       .word   0x0a00005f
+       .word   0xe31b0901
+       .word   0x0d2d020c
+       .word   0x1d2d420c
+       .word   0xe20b8a03
+       .word   0xe0888088
+       .word   0xe08d8528
+       .word   0xe8980007
+       .word   0xe28dd030
+       .word   0xeb00069b
+       .word   0xe20b380f
+       .word   0xe51c8008
+       .word   0xe218800f
+       .word   0x1a00001b
+       .word   0xe353080f
+       .word   0x2a00000d
+       .word   0xe79c4723
+       .word   0xe20b80ff
+       .word   0xe31b0502
+       .word   0x10848108
+       .word   0x00448108
+       .word   0xe31b0602
+       .word   0x178c8723
+       .word   0xe31b0401
+       .word   0x11a04008
+       .word   0xe3550080
+       .word   0xe4a40004
+       .word   0x24a41004
+       .word   0x84a42000
+       .word   0xeafffec3
+       .word   0xe59c403c
+       .word   0xe2844004
+       .word   0xe31b0401
+       .word   0x120b80ff
+       .word   0x10444108
+       .word   0x131b0502
+       .word   0x10844188
+       .word   0xe3550080
+       .word   0xe4a40004
+       .word   0x24a41004
+       .word   0x84a42000
+       .word   0xeafffeb7
+       .word   0xe353080d
+       .word   0x2a00000d
+       .word   0xe79c4723
+       .word   0xe20b80ff
+       .word   0xe31b0502
+       .word   0x10848108
+       .word   0x00448108
+       .word   0xe31b0602
+       .word   0x178c8723
+       .word   0xe31b0401
+       .word   0x11a04008
+       .word   0xe3550080
+       .word   0x38840001
+       .word   0x08840003
+       .word   0x88840007
+       .word   0xeafffea7
+       .word   0xe353080f
+       .word   0x1a00000b
+       .word   0xe59c403c
+       .word   0xe2844004
+       .word   0xe31b0401
+       .word   0x120b80ff
+       .word   0x10444108
+       .word   0x131b0502
+       .word   0x10844188
+       .word   0xe3550080
+       .word   0x38840001
+       .word   0x08840003
+       .word   0x88840007
+       .word   0xeafffe99
+       .word   0xe3888090
+       .word   0xe10f9000
+       .word   0xe3c9401f
+       .word   0xe1848008
+       .word   0xe129f008
+       .word   0xe353080d
+       .word   0x01a0400d
+       .word   0x11a0400e
+       .word   0xe20b80ff
+       .word   0xe31b0502
+       .word   0x10848108
+       .word   0x00448108
+       .word   0xe31b0602
+       .word   0x0a000002
+       .word   0xe353080d
+       .word   0x01a0d008
+       .word   0x11a0e008
+       .word   0xe31b0401
+       .word   0x11a04008
+       .word   0xe129f009
+       .word   0xe3550080
+       .word   0x38840001
+       .word   0x08840003
+       .word   0x88840007
+       .word   0xeafffe80
+       .word   0xe31b0601
+       .word   0x1a00005e
+       .word   0xe31b0901
+       .word   0x0d2d020c
+       .word   0x1d2d420c
+       .word   0xe20b8a03
+       .word   0xe0888088
+       .word   0xe08d8528
+       .word   0xe8980007
+       .word   0xe28dd030
+       .word   0xeb000775
+       .word   0xe20b380f
+       .word   0xe51c8008
+       .word   0xe218800f
+       .word   0x1a00001d
+       .word   0xe353080f
+       .word   0x2a00000e
+       .word   0xe79c4723
+       .word   0xe20b80ff
+       .word   0xe31b0502
+       .word   0x10848108
+       .word   0x00448108
+       .word   0xe31b0602
+       .word   0x178c8723
+       .word   0xe31b0401
+       .word   0x11a04008
+       .word   0xe3170b02
+       .word   0xe4a40004
+       .word   0xe4a41004
+       .word   0xe4a42004
+       .word   0x14a46000
+       .word   0xeafffe60
+       .word   0xe59c403c
+       .word   0xe2844004
+       .word   0xe31b0401
+       .word   0x120b80ff
+       .word   0x10444108
+       .word   0x131b0502
+       .word   0x10844188
+       .word   0xe3170b02
+       .word   0xe4a40004
+       .word   0xe4a41004
+       .word   0xe4a42004
+       .word   0x14a46000
+       .word   0xeafffe53
+       .word   0xe353080d
+       .word   0x2a00000c
+       .word   0xe79c4723
+       .word   0xe20b80ff
+       .word   0xe31b0502
+       .word   0x10848108
+       .word   0x00448108
+       .word   0xe31b0602
+       .word   0x178c8723
+       .word   0xe31b0401
+       .word   0x11a04008
+       .word   0xe3170b02
+       .word   0x08840007
+       .word   0x88840047
+       .word   0xeafffe44
+       .word   0xe353080f
+       .word   0x1a00000a
+       .word   0xe59c403c
+       .word   0xe2844004
+       .word   0xe31b0401
+       .word   0x120b80ff
+       .word   0x10444108
+       .word   0x131b0502
+       .word   0x10844188
+       .word   0xe3170b02
+       .word   0x08840007
+       .word   0x88840047
+       .word   0xeafffe37
+       .word   0xe3888090
+       .word   0xe10f9000
+       .word   0xe3c9401f
+       .word   0xe1848008
+       .word   0xe129f008
+       .word   0xe353080d
+       .word   0x01a0400d
+       .word   0x11a0400e
+       .word   0xe20b80ff
+       .word   0xe31b0502
+       .word   0x10848108
+       .word   0x00448108
+       .word   0xe31b0602
+       .word   0x0a000002
+       .word   0xe353080d
+       .word   0x01a0d008
+       .word   0x11a0e008
+       .word   0xe31b0401
+       .word   0x11a04008
+       .word   0xe129f009
+       .word   0xe3170b02
+       .word   0x08840007
+       .word   0x88840047
+       .word   0xeafffe1f
+       .word   0xe20b380f
+       .word   0xe51c8008
+       .word   0xe218800f
+       .word   0x1a00001f
+       .word   0xe353080f
+       .word   0x2a000015
+       .word   0xe79c4723
+       .word   0xe20b80ff
+       .word   0xe31b0502
+       .word   0x10848108
+       .word   0x00448108
+       .word   0xe31b0602
+       .word   0x178c8723
+       .word   0xe31b0401
+       .word   0x11a04008
+       .word   0xe3170b02
+       .word   0xe4b40004
+       .word   0xe4b41004
+       .word   0xe4b42004
+       .word   0x14b46000
+       .word   0xeb00085d
+       .word   0xe92d0007
+       .word   0xe20b8a07
+       .word   0xe08f84a8
+       .word   0xe288805c
+       .word   0xe1a0e00f
+       .word   0xe248fb02
+       .word   0xeafffe03
+       .word   0xe59c403c
+       .word   0xe2844004
+       .word   0xe31b0401
+       .word   0x120b80ff
+       .word   0x10444108
+       .word   0x131b0502
+       .word   0x10844188
+       .word   0xeaffffea
+       .word   0xe353080d
+       .word   0x2a00000c
+       .word   0xe79c4723
+       .word   0xe20b80ff
+       .word   0xe31b0502
+       .word   0x10848108
+       .word   0x00448108
+       .word   0xe31b0602
+       .word   0x178c8723
+       .word   0xe31b0401
+       .word   0x11a04008
+       .word   0xe3170b02
+       .word   0x08940007
+       .word   0x88940047
+       .word   0xeaffffe0
+       .word   0xe353080f
+       .word   0x1a000007
+       .word   0xe59c403c
+       .word   0xe2844004
+       .word   0xe31b0401
+       .word   0x120b80ff
+       .word   0x10444108
+       .word   0x131b0502
+       .word   0x10844188
+       .word   0xeafffff1
+       .word   0xe3888090
+       .word   0xe10f9000
+       .word   0xe3c9401f
+       .word   0xe1848008
+       .word   0xe129f008
+       .word   0xe353080d
+       .word   0x01a0400d
+       .word   0x11a0400e
+       .word   0xe20b80ff
+       .word   0xe31b0502
+       .word   0x10848108
+       .word   0x00448108
+       .word   0xe31b0602
+       .word   0x0a000002
+       .word   0xe353080d
+       .word   0x01a0d008
+       .word   0x11a0e008
+       .word   0xe31b0401
+       .word   0x11a04008
+       .word   0xe129f009
+       .word   0xeaffffdc
+       .word   0xe59a9084
+       .word   0xe3190c02
+       .word   0x1afffd6c
+       .word   0xeafffe48
+       .word   0xee309110
+       .word   0xe58a9080
+       .word   0xed8a0200
+       .word   0xed8a420c
+       .word   0xe59a9084
+       .word   0xe3c99b02
+       .word   0xe58a9084
+       .word   0xe59c903c
+       .word   0xe2499004
+       .word   0xe58c903c
+       .word   0xea0019cf
+       .word   0xe24dd040
+       .word   0xe8cd7fff
+       .word   0xe58de03c
+       .word   0xe1a0c00d
+       .word   0xe10fa000
+       .word   0xe14f9000
+       .word   0xe92d0600
+       .word   0xe319000f
+       .word   0xe24e9004
+       .word   0x04b9b000
+       .word   0x1599b000
+       .word   0xe92d4000
+       .word   0xeb0019af
+       .word   0xe8bd0400
+       .word   0xe8bd4000
+       .word   0xe31b0302
+       .word   0x0a000568
+       .word   0xe20b9c0f
+       .word   0xe3590c01
+       .word   0x1a00048b
+       .word   0xe59aa000
+       .word   0xe59a8084
+       .word   0xe3380000
+       .word   0x1a000481
+       .word   0xe10f8000
+       .word   0xe3c88080
+       .word   0xe129f008
+       .word   0xe1a00000
+       .word   0xe59a7080
+       .word   0xe31b0402
+       .word   0x1a0003bf
+       .word   0xe1a0948b
+       .word   0xe209920a
+       .word   0xe31b0902
+       .word   0x13899101
+       .word   0xe20b380f
+       .word   0xe353080f
+       .word   0x23899201
+       .word   0xe51c8008
+       .word   0xe218800f
+       .word   0x13899302
+       .word   0xe2095103
+       .word   0xe08ffca9
+       .word   0x00000000
+       .word   0xea00001e
+       .word   0xea000039
+       .word   0xea000063
+       .word   0xea000070
+       .word   0xea0001ab
+       .word   0xea0001cc
+       .word   0xea000207
+       .word   0xea00020e
+       .word   0xea000079
+       .word   0xea000095
+       .word   0xea0000bf
+       .word   0xea0000cd
+       .word   0xea000212
+       .word   0xea000237
+       .word   0xea000275
+       .word   0xea00027c
+       .word   0xea0000d6
+       .word   0xea0000f3
+       .word   0xea00011d
+       .word   0xea00012c
+       .word   0xea000280
+       .word   0xea0002a3
+       .word   0xea0002de
+       .word   0xea0002e5
+       .word   0xea000135
+       .word   0xea000148
+       .word   0xea000175
+       .word   0xea000185
+       .word   0xea0002e9
+       .word   0xea0002fb
+       .word   0xea000323
+       .word   0xea00032a
+       .word   0xe20b8a07
+       .word   0xe08a8428
+       .word   0xe8980007
+       .word   0xe1a05ba5
+       .word   0xeb000535
+       .word   0xe20b380f
+       .word   0xe79c4723
+       .word   0xe20b80ff
+       .word   0xe31b0502
+       .word   0x10848108
+       .word   0x00448108
+       .word   0xe31b0401
+       .word   0x11a04008
+       .word   0xe31b0602
+       .word   0x178c8723
+       .word   0xe4a40000
+       .word   0xe58a7080
+       .word   0xe92d4000
+       .word   0xeb001964
+       .word   0xe8bd4000
+       .word   0xe91c0300
+       .word   0xe129f009
+       .word   0xe169f008
+       .word   0xe1a0d00c
+       .word   0xe8dc7fff
+       .word   0xe1a00000
+       .word   0xe28dd03c
+       .word   0xe8fd8000
+       .word   0xe20b8a07
+       .word   0xe08a8428
+       .word   0xe8980007
+       .word   0xe1a05ba5
+       .word   0xeb000519
+       .word   0xe20b380f
+       .word   0xe353080d
+       .word   0x2a00000a
+       .word   0xe79c4723
+       .word   0xe20b80ff
+       .word   0xe31b0502
+       .word   0x10848108
+       .word   0x00448108
+       .word   0xe31b0401
+       .word   0x11a04008
+       .word   0xe31b0602
+       .word   0x178c8723
+       .word   0xe8840001
+       .word   0xea00031b
+       .word   0xe51c8008
+       .word   0xe218800f
+       .word   0xe10f9000
+       .word   0xe3888090
+       .word   0xe3c9401f
+       .word   0xe1848008
+       .word   0xe129f008
+       .word   0xe353080d
+       .word   0x01a0400d
+       .word   0x11a0400e
+       .word   0xe20b80ff
+       .word   0xe31b0502
+       .word   0x10848108
+       .word   0x00448108
+       .word   0xe31b0401
+       .word   0x11a04008
+       .word   0xe31b0602
+       .word   0x0a000002
+       .word   0xe353080d
+       .word   0x01a0d008
+       .word   0x11a0e008
+       .word   0xe129f009
+       .word   0xe8840001
+       .word   0xea000303
+       .word   0xe20b8a07
+       .word   0xe08a8428
+       .word   0xe8980007
+       .word   0xe1a05ba5
+       .word   0xeb0004ee
+       .word   0xe59c403c
+       .word   0xe2844004
+       .word   0xe31b0401
+       .word   0x120b80ff
+       .word   0x10444108
+       .word   0x131b0502
+       .word   0x10844188
+       .word   0xe4a40000
+       .word   0xea0002f5
+       .word   0xe20b8a07
+       .word   0xe08a8428
+       .word   0xe8980007
+       .word   0xe1a05ba5
+       .word   0xeb0004e0
+       .word   0xe59c403c
+       .word   0xe2844004
+       .word   0xe31b0401
+       .word   0x120b80ff
+       .word   0x10444108
+       .word   0x131b0502
+       .word   0x10844188
+       .word   0xe8840001
+       .word   0xea0002e7
+       .word   0xe20b8a07
+       .word   0xe08a8428
+       .word   0xe8980007
+       .word   0xe1a05ba5
+       .word   0xeb000527
+       .word   0xe20b380f
+       .word   0xe79c4723
+       .word   0xe20b80ff
+       .word   0xe31b0502
+       .word   0x10848108
+       .word   0x00448108
+       .word   0xe31b0401
+       .word   0x11a04008
+       .word   0xe31b0602
+       .word   0x178c8723
+       .word   0xe4a40004
+       .word   0xe4241004
+       .word   0xe58a7080
+       .word   0xe92d4000
+       .word   0xeb001900
+       .word   0xe8bd4000
+       .word   0xe91c0300
+       .word   0xe129f009
+       .word   0xe169f008
+       .word   0xe1a0d00c
+       .word   0xe8dc7fff
+       .word   0xe1a00000
+       .word   0xe28dd03c
+       .word   0xe8fd8000
+       .word   0xe20b8a07
+       .word   0xe08a8428
+       .word   0xe8980007
+       .word   0xe1a05ba5
+       .word   0xeb00050a
+       .word   0xe20b380f
+       .word   0xe353080d
+       .word   0x2a00000a
+       .word   0xe79c4723
+       .word   0xe20b80ff
+       .word   0xe31b0502
+       .word   0x10848108
+       .word   0x00448108
+       .word   0xe31b0401
+       .word   0x11a04008
+       .word   0xe31b0602
+       .word   0x178c8723
+       .word   0xe8840003
+       .word   0xea0002b7
+       .word   0xe51c8008
+       .word   0xe218800f
+       .word   0xe10f9000
+       .word   0xe3888090
+       .word   0xe3c9401f
+       .word   0xe1848008
+       .word   0xe129f008
+       .word   0xe353080d
+       .word   0x01a0400d
+       .word   0x11a0400e
+       .word   0xe20b80ff
+       .word   0xe31b0502
+       .word   0x10848108
+       .word   0x00448108
+       .word   0xe31b0401
+       .word   0x11a04008
+       .word   0xe31b0602
+       .word   0x0a000002
+       .word   0xe353080d
+       .word   0x01a0d008
+       .word   0x11a0e008
+       .word   0xe129f009
+       .word   0xe8840003
+       .word   0xea00029f
+       .word   0xe20b8a07
+       .word   0xe08a8428
+       .word   0xe8980007
+       .word   0xe1a05ba5
+       .word   0xeb0004df
+       .word   0xe59c403c
+       .word   0xe2844004
+       .word   0xe31b0401
+       .word   0x120b80ff
+       .word   0x10444108
+       .word   0x131b0502
+       .word   0x10844188
+       .word   0xe4a40004
+       .word   0xe4241004
+       .word   0xea000290
+       .word   0xe20b8a07
+       .word   0xe08a8428
+       .word   0xe8980007
+       .word   0xe1a05ba5
+       .word   0xeb0004d0
+       .word   0xe59c403c
+       .word   0xe2844004
+       .word   0xe31b0401
+       .word   0x120b80ff
+       .word   0x10444108
+       .word   0x131b0502
+       .word   0x10844188
+       .word   0xe8840003
+       .word   0xea000282
+       .word   0xe20b8a07
+       .word   0xe08a8428
+       .word   0xe8980007
+       .word   0xe1a05ba5
+       .word   0xeb00051d
+       .word   0xe20b380f
+       .word   0xe79c4723
+       .word   0xe20b80ff
+       .word   0xe31b0502
+       .word   0x10848108
+       .word   0x00448108
+       .word   0xe31b0401
+       .word   0x11a04008
+       .word   0xe31b0602
+       .word   0x178c8723
+       .word   0xe4a40004
+       .word   0xe4a41004
+       .word   0xe4242008
+       .word   0xe58a7080
+       .word   0xe92d4000
+       .word   0xeb00189a
+       .word   0xe8bd4000
+       .word   0xe91c0300
+       .word   0xe129f009
+       .word   0xe169f008
+       .word   0xe1a0d00c
+       .word   0xe8dc7fff
+       .word   0xe1a00000
+       .word   0xe28dd03c
+       .word   0xe8fd8000
+       .word   0xe20b8a07
+       .word   0xe08a8428
+       .word   0xe8980007
+       .word   0xe1a05ba5
+       .word   0xeb0004ff
+       .word   0xe20b380f
+       .word   0xe353080d
+       .word   0x2a00000a
+       .word   0xe79c4723
+       .word   0xe20b80ff
+       .word   0xe31b0502
+       .word   0x10848108
+       .word   0x00448108
+       .word   0xe31b0401
+       .word   0x11a04008
+       .word   0xe31b0602
+       .word   0x178c8723
+       .word   0xe8840007
+       .word   0xea000251
+       .word   0xe51c8008
+       .word   0xe218800f
+       .word   0xe10f9000
+       .word   0xe3888090
+       .word   0xe3c9401f
+       .word   0xe1848008
+       .word   0xe129f008
+       .word   0xe353080d
+       .word   0x01a0400d
+       .word   0x11a0400e
+       .word   0xe20b80ff
+       .word   0xe31b0502
+       .word   0x10848108
+       .word   0x00448108
+       .word   0xe31b0401
+       .word   0x11a04008
+       .word   0xe31b0602
+       .word   0x0a000002
+       .word   0xe353080d
+       .word   0x01a0d008
+       .word   0x11a0e008
+       .word   0xe129f009
+       .word   0xe8840007
+       .word   0xea000239
+       .word   0xe20b8a07
+       .word   0xe08a8428
+       .word   0xe8980007
+       .word   0xe1a05ba5
+       .word   0xeb0004d4
+       .word   0xe59c403c
+       .word   0xe2844004
+       .word   0xe31b0401
+       .word   0x120b80ff
+       .word   0x10444108
+       .word   0x131b0502
+       .word   0x10844188
+       .word   0xe4a40004
+       .word   0xe4a41004
+       .word   0xe4242008
+       .word   0xea000229
+       .word   0xe20b8a07
+       .word   0xe08a8428
+       .word   0xe8980007
+       .word   0xe1a05ba5
+       .word   0xeb0004c4
+       .word   0xe59c403c
+       .word   0xe2844004
+       .word   0xe31b0401
+       .word   0x120b80ff
+       .word   0x10444108
+       .word   0x131b0502
+       .word   0x10844188
+       .word   0xe8840007
+       .word   0xea00021b
+       .word   0xe20b8a07
+       .word   0xe08a8428
+       .word   0xe8980007
+       .word   0xeb00053f
+       .word   0xe20b380f
+       .word   0xe79c4723
+       .word   0xe20b80ff
+       .word   0xe31b0502
+       .word   0x10848108
+       .word   0x00448108
+       .word   0xe31b0401
+       .word   0x11a04008
+       .word   0xe31b0602
+       .word   0x178c8723
+       .word   0xe3170b02
+       .word   0xe4a40004
+       .word   0xe4a41004
+       .word   0xe4a42004
+       .word   0x14a46000
+       .word   0xea000207
+       .word   0xe20b8a07
+       .word   0xe08a8428
+       .word   0xe8980007
+       .word   0xeb00052b
+       .word   0xe20b380f
+       .word   0xe353080d
+       .word   0x2a00000c
+       .word   0xe79c4723
+       .word   0xe20b80ff
+       .word   0xe31b0502
+       .word   0x10848108
+       .word   0x00448108
+       .word   0xe31b0401
+       .word   0x11a04008
+       .word   0xe31b0602
+       .word   0x178c8723
+       .word   0xe3170b02
+       .word   0x08840007
+       .word   0x18840047
+       .word   0xea0001f3
+       .word   0xe51c8008
+       .word   0xe218800f
+       .word   0xe10f9000
+       .word   0xe3888090
+       .word   0xe3c9401f
+       .word   0xe1848008
+       .word   0xe129f008
+       .word   0xe353080d
+       .word   0x01a0400d
+       .word   0x11a0400e
+       .word   0xe20b80ff
+       .word   0xe31b0502
+       .word   0x10848108
+       .word   0x00448108
+       .word   0xe31b0401
+       .word   0x11a04008
+       .word   0xe31b0602
+       .word   0x0a000002
+       .word   0xe353080d
+       .word   0x01a0d008
+       .word   0x11a0e008
+       .word   0xe129f009
+       .word   0xe3170b02
+       .word   0x08840007
+       .word   0x18840047
+       .word   0xea0001d9
+       .word   0xe20b8a07
+       .word   0xe08a8428
+       .word   0xe8980007
+       .word   0xeb0004fd
+       .word   0xe59c403c
+       .word   0xe2844004
+       .word   0xe31b0401
+       .word   0x120b80ff
+       .word   0x10444108
+       .word   0x131b0502
+       .word   0x10844188
+       .word   0xe3170b02
+       .word   0xe4a40004
+       .word   0xe4a41004
+       .word   0xe4a42004
+       .word   0x14a46000
+       .word   0xea0001c8
+       .word   0xe20b8a07
+       .word   0xe08a8428
+       .word   0xe8980007
+       .word   0xeb0004ec
+       .word   0xe59c403c
+       .word   0xe2844004
+       .word   0xe31b0401
+       .word   0x120b80ff
+       .word   0x10444108
+       .word   0x131b0502
+       .word   0x10844188
+       .word   0xe3170b02
+       .word   0x08840007
+       .word   0x18840047
+       .word   0xea0001b9
+       .word   0xe79c4723
+       .word   0xe20b80ff
+       .word   0xe31b0502
+       .word   0x10848108
+       .word   0x00448108
+       .word   0xe31b0401
+       .word   0x11a04008
+       .word   0xe31b0602
+       .word   0x178c8723
+       .word   0xe4b40000
+       .word   0xe1b00080
+       .word   0xe1a01380
+       .word   0xe1a00ba0
+       .word   0x12800c7f
+       .word   0xe1a00060
+       .word   0x13811102
+       .word   0xe3a02000
+       .word   0xe1b08c80
+       .word   0x323884fe
+       .word   0x03800101
+       .word   0xe20b8a07
+       .word   0xe08a8428
+       .word   0xe8880007
+       .word   0xe92d4000
+       .word   0xeb0017cd
+       .word   0xe8bd4000
+       .word   0xe91c0300
+       .word   0xe129f009
+       .word   0xe169f008
+       .word   0xe1a0d00c
+       .word   0xe8dc7fff
+       .word   0xe1a00000
+       .word   0xe28dd03c
+       .word   0xe8fd8000
+       .word   0xe353080d
+       .word   0x2a000021
+       .word   0xe79c4723
+       .word   0xe20b80ff
+       .word   0xe31b0502
+       .word   0x10848108
+       .word   0x00448108
+       .word   0xe31b0401
+       .word   0x11a04008
+       .word   0xe31b0602
+       .word   0x178c8723
+       .word   0xe8940001
+       .word   0xe1b00080
+       .word   0xe1a01380
+       .word   0xe1a00ba0
+       .word   0x12800c7f
+       .word   0xe1a00060
+       .word   0x13811102
+       .word   0xe3a02000
+       .word   0xe1b08c80
+       .word   0x323884fe
+       .word   0x03800101
+       .word   0xe20b8a07
+       .word   0xe08a8428
+       .word   0xe8880007
+       .word   0xe92d4000
+       .word   0xeb0017a9
+       .word   0xe8bd4000
+       .word   0xe91c0300
+       .word   0xe129f009
+       .word   0xe169f008
+       .word   0xe1a0d00c
+       .word   0xe8dc7fff
+       .word   0xe1a00000
+       .word   0xe28dd03c
+       .word   0xe8fd8000
+       .word   0xe51c8008
+       .word   0xe218800f
+       .word   0xe10f9000
+       .word   0xe3888090
+       .word   0xe3c9401f
+       .word   0xe1848008
+       .word   0xe129f008
+       .word   0xe353080d
+       .word   0x01a0400d
+       .word   0x11a0400e
+       .word   0xe20b80ff
+       .word   0xe31b0502
+       .word   0x10848108
+       .word   0x00448108
+       .word   0xe31b0401
+       .word   0x11a04008
+       .word   0xe31b0602
+       .word   0x0a000002
+       .word   0xe353080d
+       .word   0x01a0d008
+       .word   0x11a0e008
+       .word   0xe129f009
+       .word   0xe8940001
+       .word   0xeaffffcf
+       .word   0xe59c403c
+       .word   0xe2844004
+       .word   0xe31b0401
+       .word   0x120b80ff
+       .word   0x10444108
+       .word   0x131b0502
+       .word   0x10844188
+       .word   0xeaffffa2
+       .word   0xe59c403c
+       .word   0xe2844004
+       .word   0xe31b0401
+       .word   0x120b80ff
+       .word   0x10444108
+       .word   0x131b0502
+       .word   0x10844188
+       .word   0xe8940001
+       .word   0xeaffffbe
+       .word   0xe79c4723
+       .word   0xe20b80ff
+       .word   0xe31b0502
+       .word   0x10848108
+       .word   0x00448108
+       .word   0xe31b0401
+       .word   0x11a04008
+       .word   0xe31b0602
+       .word   0x178c8723
+       .word   0xe4b40004
+       .word   0xe4342004
+       .word   0xe1b00080
+       .word   0x03320000
+       .word   0xe1a01500
+       .word   0xe1a00a20
+       .word   0xe1811aa2
+       .word   0xe1a02582
+       .word   0x12800b1e
+       .word   0xe1a00060
+       .word   0x13811102
+       .word   0xe1b08b00
+       .word   0x32288103
+       .word   0x323885ff
+       .word   0x03800101
+       .word   0xe20b8a07
+       .word   0xe08a8428
+       .word   0xe8880007
+       .word   0xe92d4000
+       .word   0xeb00175a
+       .word   0xe8bd4000
+       .word   0xe91c0300
+       .word   0xe129f009
+       .word   0xe169f008
+       .word   0xe1a0d00c
+       .word   0xe8dc7fff
+       .word   0xe1a00000
+       .word   0xe28dd03c
+       .word   0xe8fd8000
+       .word   0xe353080d
+       .word   0x2a000024
+       .word   0xe79c4723
+       .word   0xe20b80ff
+       .word   0xe31b0502
+       .word   0x10848108
+       .word   0x00448108
+       .word   0xe31b0401
+       .word   0x11a04008
+       .word   0xe31b0602
+       .word   0x178c8723
+       .word   0xe8940005
+       .word   0xe1b00080
+       .word   0x03320000
+       .word   0xe1a01500
+       .word   0xe1a00a20
+       .word   0xe1811aa2
+       .word   0xe1a02582
+       .word   0x12800b1e
+       .word   0xe1a00060
+       .word   0x13811102
+       .word   0xe1b08b00
+       .word   0x32288103
+       .word   0x323885ff
+       .word   0x03800101
+       .word   0xe20b8a07
+       .word   0xe08a8428
+       .word   0xe8880007
+       .word   0xe92d4000
+       .word   0xeb001733
+       .word   0xe8bd4000
+       .word   0xe91c0300
+       .word   0xe129f009
+       .word   0xe169f008
+       .word   0xe1a0d00c
+       .word   0xe8dc7fff
+       .word   0xe1a00000
+       .word   0xe28dd03c
+       .word   0xe8fd8000
+       .word   0xe51c8008
+       .word   0xe218800f
+       .word   0xe10f9000
+       .word   0xe3888090
+       .word   0xe3c9401f
+       .word   0xe1848008
+       .word   0xe129f008
+       .word   0xe353080d
+       .word   0x01a0400d
+       .word   0x11a0400e
+       .word   0xe20b80ff
+       .word   0xe31b0502
+       .word   0x10848108
+       .word   0x00448108
+       .word   0xe31b0401
+       .word   0x11a04008
+       .word   0xe31b0602
+       .word   0x0a000002
+       .word   0xe353080d
+       .word   0x01a0d008
+       .word   0x11a0e008
+       .word   0xe129f009
+       .word   0xe8940005
+       .word   0xeaffffcc
+       .word   0xe59c403c
+       .word   0xe2844004
+       .word   0xe31b0401
+       .word   0x120b80ff
+       .word   0x10444108
+       .word   0x131b0502
+       .word   0x10844188
+       .word   0xeaffff9b
+       .word   0xe59c403c
+       .word   0xe2844004
+       .word   0xe31b0401
+       .word   0x120b80ff
+       .word   0x10444108
+       .word   0x131b0502
+       .word   0x10844188
+       .word   0xe8940005
+       .word   0xeaffffbb
+       .word   0xe79c4723
+       .word   0xe20b80ff
+       .word   0xe31b0502
+       .word   0x10848108
+       .word   0x00448108
+       .word   0xe31b0401
+       .word   0x11a04008
+       .word   0xe31b0602
+       .word   0x178c8723
+       .word   0xe4b40004
+       .word   0xe4b41004
+       .word   0xe4342008
+       .word   0xe3c009fe
+       .word   0xe3c005ff
+       .word   0xe3110102
+       .word   0x11e08000
+       .word   0x11b08888
+       .word   0x03800101
+       .word   0x13c00101
+       .word   0xe1818002
+       .word   0xe1988880
+       .word   0x03c00101
+       .word   0xe20b8a07
+       .word   0xe08a8428
+       .word   0xe8880007
+       .word   0xe92d4000
+       .word   0xeb0016e6
+       .word   0xe8bd4000
+       .word   0xe91c0300
+       .word   0xe129f009
+       .word   0xe169f008
+       .word   0xe1a0d00c
+       .word   0xe8dc7fff
+       .word   0xe1a00000
+       .word   0xe28dd03c
+       .word   0xe8fd8000
+       .word   0xe353080d
+       .word   0x2a000021
+       .word   0xe79c4723
+       .word   0xe20b80ff
+       .word   0xe31b0502
+       .word   0x10848108
+       .word   0x00448108
+       .word   0xe31b0401
+       .word   0x11a04008
+       .word   0xe31b0602
+       .word   0x178c8723
+       .word   0xe8940007
+       .word   0xe3c009fe
+       .word   0xe3c005ff
+       .word   0xe3110102
+       .word   0x11e08000
+       .word   0x11b08888
+       .word   0x03800101
+       .word   0x13c00101
+       .word   0xe1818002
+       .word   0xe1988880
+       .word   0x03c00101
+       .word   0xe20b8a07
+       .word   0xe08a8428
+       .word   0xe8880007
+       .word   0xe92d4000
+       .word   0xeb0016c2
+       .word   0xe8bd4000
+       .word   0xe91c0300
+       .word   0xe129f009
+       .word   0xe169f008
+       .word   0xe1a0d00c
+       .word   0xe8dc7fff
+       .word   0xe1a00000
+       .word   0xe28dd03c
+       .word   0xe8fd8000
+       .word   0xe51c8008
+       .word   0xe218800f
+       .word   0xe10f9000
+       .word   0xe3888090
+       .word   0xe3c9401f
+       .word   0xe1848008
+       .word   0xe129f008
+       .word   0xe353080d
+       .word   0x01a0400d
+       .word   0x11a0400e
+       .word   0xe20b80ff
+       .word   0xe31b0502
+       .word   0x10848108
+       .word   0x00448108
+       .word   0xe31b0401
+       .word   0x11a04008
+       .word   0xe31b0602
+       .word   0x0a000002
+       .word   0xe353080d
+       .word   0x01a0d008
+       .word   0x11a0e008
+       .word   0xe129f009
+       .word   0xe8940007
+       .word   0xeaffffcf
+       .word   0xe59c403c
+       .word   0xe2844004
+       .word   0xe31b0401
+       .word   0x120b80ff
+       .word   0x10444108
+       .word   0x131b0502
+       .word   0x10844188
+       .word   0xeaffffa0
+       .word   0xe59c403c
+       .word   0xe2844004
+       .word   0xe31b0401
+       .word   0x120b80ff
+       .word   0x10444108
+       .word   0x131b0502
+       .word   0x10844188
+       .word   0xe8940007
+       .word   0xeaffffbe
+       .word   0xe79c4723
+       .word   0xe20b80ff
+       .word   0xe31b0502
+       .word   0x10848108
+       .word   0x00448108
+       .word   0xe31b0401
+       .word   0x11a04008
+       .word   0xe31b0602
+       .word   0x178c8723
+       .word   0xe3170b02
+       .word   0xe4b40004
+       .word   0xe4b41004
+       .word   0xe4b42004
+       .word   0x14b46000
+       .word   0xeb0004cf
+       .word   0xe20b8a07
+       .word   0xe08a8428
+       .word   0xe8880007
+       .word   0xea000050
+       .word   0xe353080d
+       .word   0x2a00000c
+       .word   0xe79c4723
+       .word   0xe20b80ff
+       .word   0xe31b0502
+       .word   0x10848108
+       .word   0x00448108
+       .word   0xe31b0401
+       .word   0x11a04008
+       .word   0xe31b0602
+       .word   0x178c8723
+       .word   0xe3170b02
+       .word   0x08940007
+       .word   0x18940047
+       .word   0xeaffffeb
+       .word   0xe51c8008
+       .word   0xe218800f
+       .word   0xe10f9000
+       .word   0xe3888090
+       .word   0xe3c9401f
+       .word   0xe1848008
+       .word   0xe129f008
+       .word   0xe353080d
+       .word   0x01a0400d
+       .word   0x11a0400e
+       .word   0xe20b80ff
+       .word   0xe31b0502
+       .word   0x10848108
+       .word   0x00448108
+       .word   0xe31b0401
+       .word   0x11a04008
+       .word   0xe31b0602
+       .word   0x0a000002
+       .word   0xe353080d
+       .word   0x01a0d008
+       .word   0x11a0e008
+       .word   0xe129f009
+       .word   0xe3170b02
+       .word   0x08940007
+       .word   0x18940047
+       .word   0xeaffffd1
+       .word   0xe59c403c
+       .word   0xe2844004
+       .word   0xe31b0401
+       .word   0x120b80ff
+       .word   0x10444108
+       .word   0x131b0502
+       .word   0x10844188
+       .word   0xeaffffc4
+       .word   0xe59c403c
+       .word   0xe2844004
+       .word   0xe31b0401
+       .word   0x120b80ff
+       .word   0x10444108
+       .word   0x131b0502
+       .word   0x10844188
+       .word   0xe3170b02
+       .word   0x08940007
+       .word   0x18940047
+       .word   0xeaffffbe
+       .word   0xe3100101
+       .word   0x1a00000f
+       .word   0xe20b50e0
+       .word   0xe20b8702
+       .word   0xe18555a8
+       .word   0xe3a04000
+       .word   0xeb0005e4
+       .word   0xe28f8070
+       .word   0xe0888125
+       .word   0xe8980300
+       .word   0xe1530009
+       .word   0xd1580003
+       .word   0xca000013
+       .word   0xe1800003
+       .word   0xe3540000
+       .word   0x11b08aa7
+       .word   0x33877010
+       .word   0x8b00075b
+       .word   0xe20b8a07
+       .word   0xe08a8428
+       .word   0xe8880007
+       .word   0xe58a7080
+       .word   0xe92d4000
+       .word   0xeb001629
+       .word   0xe8bd4000
+       .word   0xe91c0300
+       .word   0xe129f009
+       .word   0xe169f008
+       .word   0xe1a0d00c
+       .word   0xe8dc7fff
+       .word   0xe1a00000
+       .word   0xe28dd03c
+       .word   0xe8fd8000
+       .word   0xe24fe054
+       .word   0xe0588003
+       .word   0xca0006b7
+       .word   0xea000640
+       .word   0x00003f81
+       .word   0x0000407e
+       .word   0x00003f81
+       .word   0x0000407e
+       .word   0x00003f81
+       .word   0x0000407e
+       .word   0x00003f81
+       .word   0x0000407e
+       .word   0x00003c01
+       .word   0x000043fe
+       .word   0x00003c01
+       .word   0x000043fe
+       .word   0x00003c01
+       .word   0x000043fe
+       .word   0x00003c01
+       .word   0x000043fe
+       .word   0x00000000
+       .word   0x00007ffe
+       .word   0x00000000
+       .word   0x00007ffe
+       .word   0x00000000
+       .word   0x00007ffe
+       .word   0x00000000
+       .word   0x00007ffe
+       .word   0x00000000
+       .word   0x00000000
+       .word   0x00000000
+       .word   0x00000000
+       .word   0x00003fff
+       .word   0x80000000
+       .word   0x00000000
+       .word   0x00000000
+       .word   0x00004000
+       .word   0x80000000
+       .word   0x00000000
+       .word   0x00000000
+       .word   0x00004000
+       .word   0xc0000000
+       .word   0x00000000
+       .word   0x00000000
+       .word   0x00004001
+       .word   0x80000000
+       .word   0x00000000
+       .word   0x00000000
+       .word   0x00004001
+       .word   0xa0000000
+       .word   0x00000000
+       .word   0x00000000
+       .word   0x00003ffe
+       .word   0x80000000
+       .word   0x00000000
+       .word   0x00000000
+       .word   0x00004002
+       .word   0xa0000000
+       .word   0x00000000
+       .word   0x00000000
+       .word   0xe31b0702
+       .word   0x131b0080
+       .word   0x1a000193
+       .word   0xe31b0010
+       .word   0x1a000036
+       .word   0xe31b0902
+       .word   0x1a00001b
+       .word   0xe20b8807
+       .word   0xe08a8628
+       .word   0xe8980007
+       .word   0xe1b09e8b
+       .word   0x208f8ca9
+       .word   0x224880b4
+       .word   0x308a8ca9
+       .word   0xe8980038
+       .word   0xe20b860f
+       .word   0xe24fef6f
+       .word   0xe08ff928
+       .word   0x00000000
+       .word   0xea00095b
+       .word   0xea0009bf
+       .word   0xea000959
+       .word   0xea000958
+       .word   0xea000a5c
+       .word   0xea000a5b
+       .word   0xea001085
+       .word   0xea001084
+       .word   0xea000b8f
+       .word   0xea0009b7
+       .word   0xea000a56
+       .word   0xea000a55
+       .word   0xea001381
+       .word   0xea000175
+       .word   0xea000174
+       .word   0xea000173
+       .word   0xe1b09e8b
+       .word   0x208f8ca9
+       .word   0x22488f46
+       .word   0x308a8ca9
+       .word   0xe8980007
+       .word   0xe20b860f
+       .word   0xe24fee22
+       .word   0xe08ff928
+       .word   0x00000000
+       .word   0xea000c2b
+       .word   0xea000c2a
+       .word   0xea000c29
+       .word   0xea000c67
+       .word   0xea000ba1
+       .word   0xea000f44
+       .word   0xea000f43
+       .word   0xea000ff7
+       .word   0xea00117e
+       .word   0xea00117d
+       .word   0xea0012b7
+       .word   0xea00120e
+       .word   0xea00120d
+       .word   0xea00138b
+       .word   0xea000c38
+       .word   0xea000c26
+       .word   0xe20b860f
+       .word   0xe08ff928
+       .word   0x00000000
+       .word   0xea000055
+       .word   0xea00000d
+       .word   0xea00003a
+       .word   0xea000024
+       .word   0xea000152
+       .word   0xea000151
+       .word   0xea000150
+       .word   0xea00014f
+       .word   0xea00014e
+       .word   0xea00000c
+       .word   0xea00014c
+       .word   0xea00000a
+       .word   0xea00014a
+       .word   0xea000008
+       .word   0xea000148
+       .word   0xea000006
+       .word   0xe1b09e8b
+       .word   0x208f8ca9
+       .word   0x22488f72
+       .word   0x308a8ca9
+       .word   0xe8980007
+       .word   0xe28fe04c
+       .word   0xea000cac
+       .word   0xe20b8807
+       .word   0xe08a8628
+       .word   0xe8980007
+       .word   0xe1b09e8b
+       .word   0x208f8ca9
+       .word   0x22488e1f
+       .word   0x308a8ca9
+       .word   0xe8980038
+       .word   0xeb000c8a
+       .word   0xe20b3a0f
+       .word   0xe3330a0f
+       .word   0x1a000007
+       .word   0xe51c8008
+       .word   0xe3c8820f
+       .word   0xe206620f
+       .word   0xe1888006
+       .word   0xe50c8008
+       .word   0xeaffff4f
+       .word   0xe1a06007
+       .word   0xe20b3a0f
+       .word   0xe3530a0d
+       .word   0x2a000001
+       .word   0xe78c6523
+       .word   0xeaffff49
+       .word   0xe3330a0f
+       .word   0x0afffff1
+       .word   0xe51c8008
+       .word   0xe218800f
+       .word   0x0afffff8
+       .word   0xe3888090
+       .word   0xe10f9000
+       .word   0xe3c9401f
+       .word   0xe1848008
+       .word   0xe129f008
+       .word   0xe3530a0d
+       .word   0x01a0d006
+       .word   0x11a0e006
+       .word   0xe129f009
+       .word   0xeaffff3a
+       .word   0xe20b3a0f
+       .word   0xe3530a0d
+       .word   0x2a000003
+       .word   0xe79c6523
+       .word   0xe3c664ff
+       .word   0xe3867401
+       .word   0xeaffff33
+       .word   0xe3530a0f
+       .word   0x0a00000c
+       .word   0xe51c8008
+       .word   0xe218800f
+       .word   0x0afffff6
+       .word   0xe3888090
+       .word   0xe10f9000
+       .word   0xe3c9601f
+       .word   0xe1868008
+       .word   0xe129f008
+       .word   0xe3530a0d
+       .word   0x01a0600d
+       .word   0x11a0600e
+       .word   0xe129f009
+       .word   0xeaffffed
+       .word   0xe59c603c
+       .word   0xe2866008
+       .word   0xeaffffea
+       .word   0xe20b3a0f
+       .word   0xe3530a0d
+       .word   0x2a00000f
+       .word   0xe79c6523
+       .word   0xeb000880
+       .word   0xe20b50e0
+       .word   0xe20b8702
+       .word   0xe18555a8
+       .word   0xe3a04000
+       .word   0xeb0004ee
+       .word   0xe1800003
+       .word   0xe3540000
+       .word   0x11b08aa7
+       .word   0x33877010
+       .word   0x8b00066b
+       .word   0xe20b8807
+       .word   0xe08a8628
+       .word   0xe8880007
+       .word   0xeaffff0e
+       .word   0xe3530a0f
+       .word   0x0a00000c
+       .word   0xe51c8008
+       .word   0xe218800f
+       .word   0x0affffea
+       .word   0xe3888090
+       .word   0xe10f9000
+       .word   0xe3c9601f
+       .word   0xe1868008
+       .word   0xe129f008
+       .word   0xe3530a0d
+       .word   0x01a0600d
+       .word   0x11a0600e
+       .word   0xe129f009
+       .word   0xeaffffe1
+       .word   0xe59c603c
+       .word   0xe2866008
+       .word   0xeaffffde
+       .word   0xe3a08000
+       .word   0xe58a8084
+       .word   0xe59c803c
+       .word   0xe2488004
+       .word   0xe58c803c
+       .word   0xea00152f
+       .word   0xe3590c02
+       .word   0x1a0000d7
+       .word   0xe59aa000
+       .word   0xe59a8084
+       .word   0xe3380000
+       .word   0x1afffff3
+       .word   0xe10f8000
+       .word   0xe3c88080
+       .word   0xe129f008
+       .word   0xe1a00000
+       .word   0xe31b0402
+       .word   0x1a0000c9
+       .word   0xe1a0958b
+       .word   0xe2099102
+       .word   0xe20b380f
+       .word   0xe353080f
+       .word   0x23899101
+       .word   0xe51c8008
+       .word   0xe218800f
+       .word   0x13899202
+       .word   0xe1a0548b
+       .word   0xe2055102
+       .word   0xe31b0902
+       .word   0x13855101
+       .word   0xe08ffda9
+       .word   0x00000000
+       .word   0xea000006
+       .word   0xea00001a
+       .word   0xea000045
+       .word   0xea00004c
+       .word   0xea000053
+       .word   0xea000070
+       .word   0xea0000a4
+       .word   0xea0000ab
+       .word   0xe79c4723
+       .word   0xe20b80ff
+       .word   0xe31b0502
+       .word   0x10848108
+       .word   0x00448108
+       .word   0xe31b0401
+       .word   0x11a04008
+       .word   0xe31b0602
+       .word   0x178c8723
+       .word   0xe20b3a07
+       .word   0xe1a03883
+       .word   0xe28a9000
+       .word   0xe0898ca3
+       .word   0xe8980007
+       .word   0xe4a40004
+       .word   0xe4a41004
+       .word   0xe4a42004
+       .word   0xe2833202
+       .word   0xe2555101
+       .word   0x1afffff7
+       .word   0xeafffec0
+       .word   0xe353080d
+       .word   0x2a000012
+       .word   0xe79c4723
+       .word   0xe20b80ff
+       .word   0xe31b0502
+       .word   0x10848108
+       .word   0x00448108
+       .word   0xe31b0401
+       .word   0x11a04008
+       .word   0xe31b0602
+       .word   0x178c8723
+       .word   0xe20b3a07
+       .word   0xe1a03883
+       .word   0xe28a9000
+       .word   0xe0898ca3
+       .word   0xe8980007
+       .word   0xe8a40007
+       .word   0xe2833202
+       .word   0xe2555101
+       .word   0x1afffff9
+       .word   0xeafffeab
+       .word   0xe51c8008
+       .word   0xe218800f
+       .word   0xe10f9000
+       .word   0xe3888090
+       .word   0xe3c9401f
+       .word   0xe1848008
+       .word   0xe129f008
+       .word   0xe353080d
+       .word   0x01a0400d
+       .word   0x11a0400e
+       .word   0xe20b80ff
+       .word   0xe31b0502
+       .word   0x10848108
+       .word   0x00448108
+       .word   0xe31b0401
+       .word   0x11a04008
+       .word   0xe31b0602
+       .word   0x0a000002
+       .word   0xe353080d
+       .word   0x01a0d008
+       .word   0x11a0e008
+       .word   0xe129f009
+       .word   0xeaffffde
+       .word   0xe59c403c
+       .word   0xe2844004
+       .word   0xe31b0401
+       .word   0x120b80ff
+       .word   0x10444108
+       .word   0x131b0502
+       .word   0x10844188
+       .word   0xeaffffbf
+       .word   0xe59c403c
+       .word   0xe2844004
+       .word   0xe31b0401
+       .word   0x120b80ff
+       .word   0x10444108
+       .word   0x131b0502
+       .word   0x10844188
+       .word   0xeaffffce
+       .word   0xe79c4723
+       .word   0xe20b80ff
+       .word   0xe31b0502
+       .word   0x10848108
+       .word   0x00448108
+       .word   0xe31b0401
+       .word   0x11a04008
+       .word   0xe31b0602
+       .word   0x178c8723
+       .word   0xe20b3a07
+       .word   0xe1a03883
+       .word   0xe28a9000
+       .word   0xe4b40004
+       .word   0xe4b41004
+       .word   0xe4b42004
+       .word   0xe3c009fe
+       .word   0xe3c005ff
+       .word   0xe3110102
+       .word   0x11e08000
+       .word   0x11b08888
+       .word   0xe1818080
+       .word   0x03800101
+       .word   0xe1988002
+       .word   0x03c00101
+       .word   0xe0898ca3
+       .word   0xe8880007
+       .word   0xe2833202
+       .word   0xe2555101
+       .word   0x1affffee
+       .word   0xeafffe66
+       .word   0xe353080d
+       .word   0x2a00001b
+       .word   0xe79c4723
+       .word   0xe20b80ff
+       .word   0xe31b0502
+       .word   0x10848108
+       .word   0x00448108
+       .word   0xe31b0401
+       .word   0x11a04008
+       .word   0xe31b0602
+       .word   0x178c8723
+       .word   0xe20b3a07
+       .word   0xe1a03883
+       .word   0xe28a9000
+       .word   0xe8b40007
+       .word   0xe3c009fe
+       .word   0xe3c005ff
+       .word   0xe3110102
+       .word   0x11e08000
+       .word   0x11b08888
+       .word   0xe1818080
+       .word   0x03800101
+       .word   0xe1988002
+       .word   0x03c00101
+       .word   0xe0898ca3
+       .word   0xe8880007
+       .word   0xe2833202
+       .word   0xe2555101
+       .word   0x1afffff0
+       .word   0xeafffe48
+       .word   0xe51c8008
+       .word   0xe218800f
+       .word   0xe10f9000
+       .word   0xe3888090
+       .word   0xe3c9401f
+       .word   0xe1848008
+       .word   0xe129f008
+       .word   0xe353080d
+       .word   0x01a0400d
+       .word   0x11a0400e
+       .word   0xe20b80ff
+       .word   0xe31b0502
+       .word   0x10848108
+       .word   0x00448108
+       .word   0xe31b0401
+       .word   0x11a04008
+       .word   0xe31b0602
+       .word   0x0a000002
+       .word   0xe353080d
+       .word   0x01a0d008
+       .word   0x11a0e008
+       .word   0xe129f009
+       .word   0xeaffffd5
+       .word   0xe59c403c
+       .word   0xe2844004
+       .word   0xe31b0401
+       .word   0x120b80ff
+       .word   0x10444108
+       .word   0x131b0502
+       .word   0x10844188
+       .word   0xeaffffad
+       .word   0xe59c403c
+       .word   0xe2844004
+       .word   0xe31b0401
+       .word   0x120b80ff
+       .word   0x10444108
+       .word   0x131b0502
+       .word   0x10844188
+       .word   0xeaffffc5
+       .word   0xe92d4000
+       .word   0xeb001444
+       .word   0xe8bd0400
+       .word   0xe8bd4000
+       .word   0xe91c0300
+       .word   0xe129f009
+       .word   0xe169f008
+       .word   0xe59ab004
+       .word   0xe59bb000
+       .word   0xe59ca03c
+       .word   0xe28c9040
+       .word   0xe9090e00
+       .word   0xe919ffff
+       .word   0xe3550080
+       .word   0x0a000093
+       .word   0x8a0000b1
+       .word   0xea000036
+       .word   0xe3a05000
+       .word   0xe3100101
+       .word   0x1a000035
+       .word   0xe3110102
+       .word   0x01a0f00e
+       .word   0xe3c03103
+       .word   0xe2000102
+       .word   0xe1924c01
+       .word   0x1a00000a
+       .word   0xe28f8fc9
+       .word   0xe8980300
+       .word   0xe1530009
+       .word   0xd1580003
+       .word   0xc92d4000
+       .word   0xca000023
+       .word   0xe1800421
+       .word   0xe3c00502
+       .word   0xe2438dfe
+       .word   0xe1800b88
+       .word   0xe1a0f00e
+       .word   0xe92d4000
+       .word   0xe3a04000
+       .word   0xe3a06000
+       .word   0xeb0003e2
+       .word   0xe28f8fba
+       .word   0xe8980300
+       .word   0xe1530009
+       .word   0xd1580003
+       .word   0xca000015
+       .word   0xe1800003
+       .word   0xe3540000
+       .word   0x11b08aa7
+       .word   0x33877010
+       .word   0x8b000540
+       .word   0xe8bd4000
+       .word   0xe1d18080
+       .word   0x5a000006
+       .word   0xe2300080
+       .word   0xe1a08081
+       .word   0xe1a084a8
+       .word   0xe1880b80
+       .word   0x53c00102
+       .word   0x43800102
+       .word   0xe1a0f00e
+       .word   0xe1b007c0
+       .word   0x33c10102
+       .word   0x23810102
+       .word   0xe1a00440
+       .word   0x53c00102
+       .word   0x43800102
+       .word   0xe1a0f00e
+       .word   0xe24fe05c
+       .word   0xe0588003
+       .word   0xca000502
+       .word   0xea000429
+       .word   0xe3100101
+       .word   0x0affffc9
+       .word   0xe1a08880
+       .word   0xe3780802
+       .word   0x30088001
+       .word   0xe0188080
+       .word   0x4a00000e
+       .word   0xe1918002
+       .word   0x02000102
+       .word   0x01a0f00e
+       .word   0xe3c03103
+       .word   0xe3110102
+       .word   0x13530b0f
+       .word   0x1affffe6
+       .word   0xe2000102
+       .word   0xe3110102
+       .word   0x13c11102
+       .word   0x12833001
+       .word   0xe92d4000
+       .word   0xeb000731
+       .word   0xe8bd4000
+       .word   0xeaffffb9
+       .word   0xe1928081
+       .word   0x0affffdc
+       .word   0xe92d4000
+       .word   0xeb000559
+       .word   0xe3360000
+       .word   0x5b000595
+       .word   0xe8bd4000
+       .word   0xeaffffcd
+       .word   0xe3a05080
+       .word   0xe3100101
+       .word   0x1a00003b
+       .word   0xe3110102
+       .word   0x01a0f00e
+       .word   0xe3c03103
+       .word   0xe2000102
+       .word   0xe1b04a82
+       .word   0x1a00000c
+       .word   0xe28f8f76
+       .word   0xe8980300
+       .word   0xe1530009
+       .word   0xd1580003
+       .word   0xc92d4000
+       .word   0xca000029
+       .word   0xe18005a1
+       .word   0xe3c00601
+       .word   0xe2438b0f
+       .word   0xe1800a08
+       .word   0xe1a01a81
+       .word   0xe18115a2
+       .word   0xe1a0f00e
+       .word   0xe92d4000
+       .word   0xe3a04000
+       .word   0xe3a06000
+       .word   0xeb00039e
+       .word   0xe28f8f65
+       .word   0xe8980300
+       .word   0xe1530009
+       .word   0xd1580003
+       .word   0xca000019
+       .word   0xe1800003
+       .word   0xe3540000
+       .word   0x11b08aa7
+       .word   0x33877010
+       .word   0x8b0004eb
+       .word   0xe8bd4000
+       .word   0xe1d18080
+       .word   0x5a000008
+       .word   0xe2300b01
+       .word   0xe1a08081
+       .word   0xe1a08628
+       .word   0xe1880a00
+       .word   0x53c00102
+       .word   0x43800102
+       .word   0xe1a01a81
+       .word   0xe18115a2
+       .word   0xe1a0f00e
+       .word   0xe1b007c0
+       .word   0x33c10102
+       .word   0x23810102
+       .word   0xe1a005c0
+       .word   0x53c00102
+       .word   0x43800102
+       .word   0xe1a01a81
+       .word   0xe18115a2
+       .word   0xe1a0f00e
+       .word   0xe24fe06c
+       .word   0xe0588003
+       .word   0xca0004a7
+       .word   0xea0003ce
+       .word   0xe3100101
+       .word   0x0affffc3
+       .word   0xe1a08880
+       .word   0xe3780802
+       .word   0x30088001
+       .word   0xe0188080
+       .word   0x4a00000e
+       .word   0xe1918002
+       .word   0x02000102
+       .word   0x01a0f00e
+       .word   0xe3c03103
+       .word   0xe3110102
+       .word   0x13530dfe
+       .word   0x1affffe4
+       .word   0xe2000102
+       .word   0xe3110102
+       .word   0x13c11102
+       .word   0x12833001
+       .word   0xe92d4000
+       .word   0xeb0006d6
+       .word   0xe8bd4000
+       .word   0xeaffffb3
+       .word   0xe1928081
+       .word   0x0affffda
+       .word   0xe92d4000
+       .word   0xeb0004fe
+       .word   0xe3360000
+       .word   0x5b00053a
+       .word   0xe8bd4000
+       .word   0xeaffffc9
+       .word   0xe3a05c01
+       .word   0xe3100101
+       .word   0x01a0f00e
+       .word   0xe1a08880
+       .word   0xe3780802
+       .word   0x30088001
+       .word   0xe0188080
+       .word   0x4a00000b
+       .word   0xe1918002
+       .word   0x02000102
+       .word   0x01a0f00e
+       .word   0xe1a06880
+       .word   0xe2000102
+       .word   0xe3110102
+       .word   0x13c11102
+       .word   0x12866802
+       .word   0xe3360000
+       .word   0x1a00063d
+       .word   0xe2000102
+       .word   0xe1a0f00e
+       .word   0xe1928081
+       .word   0x0a000004
+       .word   0xe92d4000
+       .word   0xeb0004e2
+       .word   0xe3360000
+       .word   0x5b00051e
+       .word   0xe8bd4000
+       .word   0xe1110080
+       .word   0xe3c00101
+       .word   0x51a0f00e
+       .word   0xe1928081
+       .word   0x11a0f00e
+       .word   0xe38000ff
+       .word   0xe3800c7f
+       .word   0xe3c11102
+       .word   0xe1a0f00e
+       .word   0x00003f81
+       .word   0x0000407e
+       .word   0x00003c01
+       .word   0x000043fe
+       .word   0xe1a08880
+       .word   0xe3780802
+       .word   0x30088001
+       .word   0xe0188080
+       .word   0x4a00000d
+       .word   0xe1916002
+       .word   0x02000102
+       .word   0x01a0f00e
+       .word   0xe3c03103
+       .word   0xe3110102
+       .word   0x13c11102
+       .word   0x12833001
+       .word   0xe92d4000
+       .word   0xeb000696
+       .word   0xe8bd4000
+       .word   0xe3c00101
+       .word   0xe3c04103
+       .word   0xe0444003
+       .word   0xea000053
+       .word   0xe1918002
+       .word   0x0a000003
+       .word   0xe3100101
+       .word   0x1a000001
+       .word   0xe3170801
+       .word   0x1a0005b6
+       .word   0xe1a085a2
+       .word   0xe1888a81
+       .word   0xe3c8820e
+       .word   0xe3c15103
+       .word   0xe1a05425
+       .word   0xe1a04982
+       .word   0xe3c44103
+       .word   0xe1855b08
+       .word   0xe1844528
+       .word   0xe2000102
+       .word   0xe38006ff
+       .word   0xe3800aff
+       .word   0xe1918002
+       .word   0x13800b02
+       .word   0xe3a06000
+       .word   0xe3a02000
+       .word   0xe3a01b02
+       .word   0xe1a09005
+       .word   0xe1a08125
+       .word   0xe1888f04
+       .word   0xe0555008
+       .word   0xe0c44124
+       .word   0xe1a08225
+       .word   0xe1888e04
+       .word   0xe0955008
+       .word   0xe0a44224
+       .word   0xe1a08425
+       .word   0xe1888c04
+       .word   0xe0955008
+       .word   0xe0a44424
+       .word   0xe1a08825
+       .word   0xe1888804
+       .word   0xe0955008
+       .word   0xe0a44824
+       .word   0xe0955004
+       .word   0xe2a44000
+       .word   0xe1a051a5
+       .word   0xe1855e84
+       .word   0xe1a041a4
+       .word   0xe0858105
+       .word   0xe0498088
+       .word   0xe358000a
+       .word   0x2248800a
+       .word   0xe2b55000
+       .word   0xe2a44000
+       .word   0xe1b06226
+       .word   0xe1866e02
+       .word   0xe1a02222
+       .word   0xe1822e01
+       .word   0xe1a01221
+       .word   0xe1811e08
+       .word   0x3affffdc
+       .word   0xe3170b02
+       .word   0x0a000008
+       .word   0xe1a06a26
+       .word   0xe1866602
+       .word   0xe1a02a22
+       .word   0xe1822601
+       .word   0xe1a01a21
+       .word   0xe1811a00
+       .word   0xe3800eff
+       .word   0xe380000f
+       .word   0xe1a0f00e
+       .word   0xe1800a21
+       .word   0xe1a01601
+       .word   0xe1811a22
+       .word   0xe1a02602
+       .word   0xe1822a26
+       .word   0xe1a0f00e
+       .word   0x00003ffe
+       .word   0x00013441
+       .word   0xe3100101
+       .word   0x1affff9d
+       .word   0xe3c03103
+       .word   0xe1916002
+       .word   0x02000102
+       .word   0x01a0f00e
+       .word   0xe3a04000
+       .word   0xe92d4000
+       .word   0xe24f8030
+       .word   0xe8980300
+       .word   0xe0536008
+       .word   0x82899001
+       .word   0xe0090996
+       .word   0xe1b06949
+       .word   0x51a08006
+       .word   0x0a000022
+       .word   0x42668000
+       .word   0xe24dd028
+       .word   0xe1a09407
+       .word   0xe3899003
+       .word   0xe58d9000
+       .word   0xe10f9000
+       .word   0xe3899080
+       .word   0xe129f009
+       .word   0xe1a00000
+       .word   0xe3c7981f
+       .word   0xe3c9901f
+       .word   0xee209110
+       .word   0xe28d901c
+       .word   0xed490206
+       .word   0xe8890007
+       .word   0xed998200
+       .word   0xe358001c
+       .word   0xaa0000a7
+       .word   0xe28f9fae
+       .word   0xe0899208
+       .word   0xedd91100
+       .word   0xe3360000
+       .word   0x5e480101
+       .word   0x4e180101
+       .word   0xee308110
+       .word   0xe2088010
+       .word   0xe28d901c
+       .word   0xed898200
+       .word   0xe8990007
+       .word   0xed590206
+       .word   0xe28dd028
+       .word   0xe10f9000
+       .word   0xe3c99080
+       .word   0xe129f009
+       .word   0xe1a00000
+       .word   0xe3c03103
+       .word   0xe0433004
+       .word   0xe2000102
+       .word   0xe3170b02
+       .word   0x03a09011
+       .word   0x13a09015
+       .word   0xe2633002
+       .word   0xe2833901
+       .word   0xe263e020
+       .word   0xe1a04e12
+       .word   0xe1a02332
+       .word   0xe1822e11
+       .word   0xe1a01331
+       .word   0xe3a03000
+       .word   0xe311020f
+       .word   0x1a00000a
+       .word   0xe2466001
+       .word   0xe0944004
+       .word   0xe0b22002
+       .word   0xe0a11001
+       .word   0xe1a05f24
+       .word   0xe0944104
+       .word   0xe1a0ef22
+       .word   0xe1855102
+       .word   0xe0b22102
+       .word   0xe18ee101
+       .word   0xe0a1100e
+       .word   0xe1a03203
+       .word   0xe1833e21
+       .word   0xe3c1120f
+       .word   0xe2499001
+       .word   0xe3340000
+       .word   0x1affffef
+       .word   0xe3a05000
+       .word   0xe0922002
+       .word   0xe0a11001
+       .word   0xe1a0ef22
+       .word   0xe0922102
+       .word   0xe18ee101
+       .word   0xe0a1100e
+       .word   0xe1a04204
+       .word   0xe1844e25
+       .word   0xe1a05205
+       .word   0xe1855e23
+       .word   0xe1a03203
+       .word   0xe1833e21
+       .word   0xe3c1120f
+       .word   0xe2599001
+       .word   0x1afffff0
+       .word   0xe1889001
+       .word   0xe1899002
+       .word   0xe1921281
+       .word   0x3a000005
+       .word   0x02031001
+       .word   0x0a000003
+       .word   0xe2933001
+       .word   0xe203800f
+       .word   0xe338000a
+       .word   0x0a00003e
+       .word   0xe3360000
+       .word   0x43800101
+       .word   0x42666000
+       .word   0xe3a08000
+       .word   0xe3560efa
+       .word   0x22466efa
+       .word   0x23888901
+       .word   0xe3560e7d
+       .word   0x22466e7d
+       .word   0x23888a02
+       .word   0xe3560ffa
+       .word   0x22466ffa
+       .word   0x23888a01
+       .word   0xe3560e32
+       .word   0x22466e32
+       .word   0x23888b02
+       .word   0xe3560e19
+       .word   0x22466e19
+       .word   0x23888b01
+       .word   0xe35600c8
+       .word   0x224660c8
+       .word   0x23888c02
+       .word   0xe3560064
+       .word   0x22466064
+       .word   0x23888c01
+       .word   0xe3560050
+       .word   0x22466050
+       .word   0x23888080
+       .word   0xe3560028
+       .word   0x22466028
+       .word   0x23888040
+       .word   0xe3560014
+       .word   0x22466014
+       .word   0x23888020
+       .word   0xe356000a
+       .word   0x22866006
+       .word   0xe0888006
+       .word   0xe3170b02
+       .word   0x0a00000b
+       .word   0xe1800008
+       .word   0xe1a01604
+       .word   0xe1811a25
+       .word   0xe1a02605
+       .word   0xe1822a23
+       .word   0xe1a06603
+       .word   0xe3390000
+       .word   0x08bd8000
+       .word   0xe3170601
+       .word   0x03877010
+       .word   0x1b0003c6
+       .word   0xe8bd8000
+       .word   0xe1800608
+       .word   0xe1800404
+       .word   0xe1800c25
+       .word   0xe1a01405
+       .word   0xe1811c23
+       .word   0xe1a02403
+       .word   0xe3390000
+       .word   0x08bd8000
+       .word   0xe3170601
+       .word   0x03877010
+       .word   0x1b0003ad
+       .word   0xe8bd8000
+       .word   0xe3a01011
+       .word   0xe1811401
+       .word   0xe1811801
+       .word   0xe1812081
+       .word   0xe0828063
+       .word   0xe02880a3
+       .word   0xe0188181
+       .word   0xe08330a8
+       .word   0xe0833128
+       .word   0x5affffb6
+       .word   0xe2955001
+       .word   0xe0828065
+       .word   0xe02880a5
+       .word   0xe0188181
+       .word   0xe08550a8
+       .word   0xe0855128
+       .word   0x5affffaf
+       .word   0xe2944001
+       .word   0xe0828064
+       .word   0xe02880a4
+       .word   0xe0088181
+       .word   0xe08440a8
+       .word   0xe0844128
+       .word   0xe1b08627
+       .word   0x33140010
+       .word   0x23140601
+       .word   0x11a04224
+       .word   0x12866001
+       .word   0xeaffffa3
+       .word   0xe1a090a8
+       .word   0xeb000075
+       .word   0xe3360000
+       .word   0x5e480101
+       .word   0x4e180101
+       .word   0xe3180001
+       .word   0x1e19110f
+       .word   0xeaffff52
+       .word   0x00003fff
+       .word   0x80000000
+       .word   0x00000000
+       .word   0x00000000
+       .word   0x00004002
+       .word   0xa0000000
+       .word   0x00000000
+       .word   0x00000000
+       .word   0x00004005
+       .word   0xc8000000
+       .word   0x00000000
+       .word   0x00000000
+       .word   0x00004008
+       .word   0xfa000000
+       .word   0x00000000
+       .word   0x00000000
+       .word   0x0000400c
+       .word   0x9c400000
+       .word   0x00000000
+       .word   0x00000000
+       .word   0x0000400f
+       .word   0xc3500000
+       .word   0x00000000
+       .word   0x00000000
+       .word   0x00004012
+       .word   0xf4240000
+       .word   0x00000000
+       .word   0x00000000
+       .word   0x00004016
+       .word   0x98968000
+       .word   0x00000000
+       .word   0x00000000
+       .word   0x00004019
+       .word   0xbebc2000
+       .word   0x00000000
+       .word   0x00000000
+       .word   0x0000401c
+       .word   0xee6b2800
+       .word   0x00000000
+       .word   0x00000000
+       .word   0x00004020
+       .word   0x9502f900
+       .word   0x00000000
+       .word   0x00000000
+       .word   0x00004023
+       .word   0xba43b740
+       .word   0x00000000
+       .word   0x00000000
+       .word   0x00004026
+       .word   0xe8d4a510
+       .word   0x00000000
+       .word   0x00000000
+       .word   0x0000402a
+       .word   0x9184e72a
+       .word   0x00000000
+       .word   0x00000000
+       .word   0x0000402d
+       .word   0xb5e620f4
+       .word   0x80000000
+       .word   0x00000000
+       .word   0x00004030
+       .word   0xe35fa931
+       .word   0xa0000000
+       .word   0x00000000
+       .word   0x00004034
+       .word   0x8e1bc9bf
+       .word   0x04000000
+       .word   0x00000000
+       .word   0x00004037
+       .word   0xb1a2bc2e
+       .word   0xc5000000
+       .word   0x00000000
+       .word   0x0000403a
+       .word   0xde0b6b3a
+       .word   0x76400000
+       .word   0x00000000
+       .word   0x0000403e
+       .word   0x8ac72304
+       .word   0x89e80000
+       .word   0x00000000
+       .word   0x00004041
+       .word   0xad78ebc5
+       .word   0xac620000
+       .word   0x00000000
+       .word   0x00004044
+       .word   0xd8d726b7
+       .word   0x177a8000
+       .word   0x00000000
+       .word   0x00004048
+       .word   0x87867832
+       .word   0x6eac9000
+       .word   0x00000000
+       .word   0x0000404b
+       .word   0xa968163f
+       .word   0x0a57b400
+       .word   0x00000000
+       .word   0x0000404e
+       .word   0xd3c21bce
+       .word   0xcceda100
+       .word   0x00000000
+       .word   0x00004052
+       .word   0x84595161
+       .word   0x401484a0
+       .word   0x00000000
+       .word   0x00004055
+       .word   0xa56fa5b9
+       .word   0x9019a5c8
+       .word   0x00000000
+       .word   0x00004058
+       .word   0xcecb8f27
+       .word   0xf4200f3a
+       .word   0x00000000
+       .word   0xe1a0000e
+       .word   0xe3a01000
+       .word   0xe1a02009
+       .word   0xe352001c
+       .word   0x21a020a2
+       .word   0x22811001
+       .word   0x2afffffb
+       .word   0xe24fef79
+       .word   0xe08e2202
+       .word   0xedd21100
+       .word   0xe3510001
+       .word   0x31a0f000
+       .word   0xee191101
+       .word   0xe1b02139
+       .word   0xe2411001
+       .word   0x2e19110f
+       .word   0xeafffff8
+       .word   0xe92d4000
+       .word   0xe1a08200
+       .word   0xe3170b02
+       .word   0x03a09004
+       .word   0x13a09007
+       .word   0xe3a05000
+       .word   0xeb000141
+       .word   0xe1b08627
+       .word   0x23a09008
+       .word   0x21b08001
+       .word   0x21a01002
+       .word   0x21a02006
+       .word   0x33a09003
+       .word   0x31b08a00
+       .word   0xe1a06085
+       .word   0x43866001
+       .word   0xe3a05000
+       .word   0xe3a04000
+       .word   0xe3a03000
+       .word   0xeb000134
+       .word   0xe1a08001
+       .word   0xe3a09008
+       .word   0xeb000131
+       .word   0xe1a08002
+       .word   0xe3a09008
+       .word   0xeb00012e
+       .word   0xe3170b02
+       .word   0x03a08c41
+       .word   0x13a088fe
+       .word   0xe15800a6
+       .word   0x9a000111
+       .word   0xe1a060a6
+       .word   0xe1838004
+       .word   0xe1988005
+       .word   0x02000102
+       .word   0x08bd8000
+       .word   0xe3100101
+       .word   0x12666000
+       .word   0xe3170b02
+       .word   0x02466012
+       .word   0x12466017
+       .word   0xe2000102
+       .word   0xe2800901
+       .word   0x0280003e
+       .word   0x03a08000
+       .word   0x1280004e
+       .word   0x11a08805
+       .word   0x11a05825
+       .word   0x11855804
+       .word   0x11a04824
+       .word   0x11844803
+       .word   0xe3340000
+       .word   0x4a000004
+       .word   0xe0988008
+       .word   0xe0b55005
+       .word   0xe0b44004
+       .word   0xe2400001
+       .word   0x5afffffa
+       .word   0xe3380102
+       .word   0x01f08f85
+       .word   0x4a000003
+       .word   0xe2955001
+       .word   0xe2b44000
+       .word   0x21a04064
+       .word   0x22800001
+       .word   0xe24dd034
+       .word   0xe1a09407
+       .word   0xe3899007
+       .word   0xe58d9000
+       .word   0xe10f9000
+       .word   0xe3899080
+       .word   0xe129f009
+       .word   0xe1a00000
+       .word   0xe3c7981f
+       .word   0xe3c9901f
+       .word   0xee209110
+       .word   0xe28d9028
+       .word   0xed498209
+       .word   0xe8890031
+       .word   0xed998200
+       .word   0xe3380000
+       .word   0x1e309110
+       .word   0x13899010
+       .word   0x1e209110
+       .word   0xe1b09006
+       .word   0x4a000009
+       .word   0x0a000011
+       .word   0xe3590a01
+       .word   0x8a000020
+       .word   0xe359001c
+       .word   0xb24f8fdd
+       .word   0xb0888209
+       .word   0xbdd81100
+       .word   0xabffff90
+       .word   0xee180101
+       .word   0xea000008
+       .word   0xe2699000
+       .word   0xe3590a01
+       .word   0x8a00006c
+       .word   0xe359001c
+       .word   0xb24f8fe7
+       .word   0xb0888209
+       .word   0xbdd81100
+       .word   0xabffff86
+       .word   0xee480101
+       .word   0xee308110
+       .word   0xe3180010
+       .word   0xe28d9028
+       .word   0xed898200
+       .word   0xe8990007
+       .word   0xed598209
+       .word   0xe28dd034
+       .word   0xe10f9000
+       .word   0xe3c99080
+       .word   0xe129f009
+       .word   0xe1a00000
+       .word   0x08bd8000
+       .word   0xe3170601
+       .word   0x03877010
+       .word   0x13a04102
+       .word   0x1b000262
+       .word   0xe8bd8000
+       .word   0xe3590a02
+       .word   0x8a000028
+       .word   0xe1a06009
+       .word   0xe1a090a9
+       .word   0xebffff6f
+       .word   0xe28f9fa6
+       .word   0xed99a200
+       .word   0xee180102
+       .word   0xee180101
+       .word   0xe3160001
+       .word   0x1e19110f
+       .word   0xee181101
+       .word   0xe28f9fa2
+       .word   0xed998200
+       .word   0xee190100
+       .word   0xee309110
+       .word   0xe3190004
+       .word   0x0affffdc
+       .word   0xee190102
+       .word   0xee308110
+       .word   0xe3180010
+       .word   0xe28d9028
+       .word   0xed898200
+       .word   0xe8990007
+       .word   0xed598209
+       .word   0xe28dd034
+       .word   0xe10f9000
+       .word   0xe3c99080
+       .word   0xe129f009
+       .word   0xe1a00000
+       .word   0xe3c03103
+       .word   0xe2833a06
+       .word   0xe2000102
+       .word   0x03a04000
+       .word   0x13a04102
+       .word   0xe3a05002
+       .word   0xeb000136
+       .word   0xe3340000
+       .word   0x08bd8000
+       .word   0xe3170601
+       .word   0x03877010
+       .word   0x1b000237
+       .word   0xe8bd8000
+       .word   0xe3590901
+       .word   0x2a000014
+       .word   0xe1a06009
+       .word   0xe1a09129
+       .word   0xebffff44
+       .word   0xe28f9f7b
+       .word   0xed99a200
+       .word   0xee180102
+       .word   0xee180101
+       .word   0xee180101
+       .word   0xee180102
+       .word   0xe3160002
+       .word   0x1e19110f
+       .word   0xee180101
+       .word   0xe3160001
+       .word   0x1e19110f
+       .word   0xee180101
+       .word   0xee309110
+       .word   0xe3190004
+       .word   0x0affffd3
+       .word   0xe28d9028
+       .word   0xed898200
+       .word   0xe8990007
+       .word   0xe28d9028
+       .word   0xed598209
+       .word   0xe28dd034
+       .word   0xe10f9000
+       .word   0xe3c99080
+       .word   0xe129f009
+       .word   0xe1a00000
+       .word   0xe2000102
+       .word   0xe3a01102
+       .word   0xe3a02000
+       .word   0xe3a03401
+       .word   0xe3a04102
+       .word   0xe3a05002
+       .word   0xeb00010b
+       .word   0xe3340000
+       .word   0x08bd8000
+       .word   0xe3170601
+       .word   0x03877010
+       .word   0x1b00020c
+       .word   0xe8bd8000
+       .word   0xe3590a02
+       .word   0x8a000029
+       .word   0xe1a06009
+       .word   0xe1a090a9
+       .word   0xebffff19
+       .word   0xe28f9f53
+       .word   0xed99a200
+       .word   0xee180102
+       .word   0xee480101
+       .word   0xe3160001
+       .word   0x1e19110f
+       .word   0xee481101
+       .word   0xe28f9f49
+       .word   0xed998200
+       .word   0xee190100
+       .word   0xee309110
+       .word   0xe3190008
+       .word   0x0affff86
+       .word   0xee190102
+       .word   0xee308110
+       .word   0xe3180010
+       .word   0xe28d9028
+       .word   0xed898200
+       .word   0xe8990007
+       .word   0xed598209
+       .word   0xe28dd034
+       .word   0xe10f9000
+       .word   0xe3c99080
+       .word   0xe129f009
+       .word   0xe1a00000
+       .word   0xe3c03103
+       .word   0xe2433a06
+       .word   0xe2000102
+       .word   0x03a04000
+       .word   0x13a04102
+       .word   0xe3a05002
+       .word   0xe2638000
+       .word   0xeb000155
+       .word   0xe3340000
+       .word   0x08bd8000
+       .word   0xe3170601
+       .word   0x03877010
+       .word   0x1b0001e0
+       .word   0xe8bd8000
+       .word   0xe3590901
+       .word   0x2a000014
+       .word   0xe1a06009
+       .word   0xe1a09129
+       .word   0xebfffeed
+       .word   0xe28f909c
+       .word   0xed99a200
+       .word   0xee180102
+       .word   0xee480101
+       .word   0xee480101
+       .word   0xee180102
+       .word   0xe3160002
+       .word   0x1e19110f
+       .word   0xee480101
+       .word   0xe3160001
+       .word   0x1e19110f
+       .word   0xee480101
+       .word   0xee309110
+       .word   0xe3190008
+       .word   0x0affffd2
+       .word   0xe28d9028
+       .word   0xed898200
+       .word   0xe8990007
+       .word   0xe28d9028
+       .word   0xed598209
+       .word   0xe28dd034
+       .word   0xe10f9000
+       .word   0xe3c99080
+       .word   0xe129f009
+       .word   0xe1a00000
+       .word   0xe2000102
+       .word   0xe3a01102
+       .word   0xe3a02000
+       .word   0xe3a034ff
+       .word   0xe3a04102
+       .word   0xe3a05002
+       .word   0xeb00012a
+       .word   0xe3340000
+       .word   0x08bd8000
+       .word   0xe3170601
+       .word   0x03877010
+       .word   0x1b0001b5
+       .word   0xe8bd8000
+       .word   0x00000fff
+       .word   0x80000000
+       .word   0x00000000
+       .word   0x00006fff
+       .word   0x80000000
+       .word   0x00000000
+       .word   0x6f05b59d
+       .word   0x3b200000
+       .word   0x16ef0a57
+       .word   0xb4000000
+       .word   0xe3160001
+       .word   0x0a000005
+       .word   0xe3170b02
+       .word   0x024f8024
+       .word   0x124f8020
+       .word   0xe8980006
+       .word   0xe0555002
+       .word   0xe0c44001
+       .word   0xe1a08b25
+       .word   0xe1888504
+       .word   0xe3c8820e
+       .word   0xe3c42103
+       .word   0xe1a029a2
+       .word   0xe1a01405
+       .word   0xe3c11103
+       .word   0xe1822588
+       .word   0xe1811aa8
+       .word   0xe2000102
+       .word   0xe3800101
+       .word   0xe3800c7f
+       .word   0xe38000ff
+       .word   0xe3160001
+       .word   0x13811101
+       .word   0xe1a0f00e
+       .word   0xe1a03183
+       .word   0xe1833ea4
+       .word   0xe1a04184
+       .word   0xe1844ea5
+       .word   0xe1a05185
+       .word   0xe0955125
+       .word   0x20855f04
+       .word   0x30955f04
+       .word   0xe0b44124
+       .word   0x20844f03
+       .word   0x30944f03
+       .word   0xe0a33123
+       .word   0xe0955e28
+       .word   0xe2b44000
+       .word   0xe2a33000
+       .word   0xe1a08208
+       .word   0xe2599001
+       .word   0x1affffed
+       .word   0xe1a0f00e
+       .word   0xe1b08425
+       .word   0x2a000024
+       .word   0x0a000010
+       .word   0xe1b08086
+       .word   0xe18082e5
+       .word   0x23888101
+       .word   0x13888202
+       .word   0xe3340000
+       .word   0x01b06f82
+       .word   0x43888201
+       .word   0xe28f6038
+       .word   0xe7d66e68
+       .word   0xe1b080a6
+       .word   0x22922001
+       .word   0x22911001
+       .word   0x23a01102
+       .word   0x22833001
+       .word   0xe3160002
+       .word   0x11a04c06
+       .word   0xe1a0f00e
+       .word   0xe1868002
+       .word   0xe1988c81
+       .word   0xe18082e5
+       .word   0x23888101
+       .word   0x13888202
+       .word   0xe3340000
+       .word   0x01b06b81
+       .word   0x43888201
+       .word   0xe3a02000
+       .word   0xe3c110ff
+       .word   0xe28f6068
+       .word   0xe7d66e68
+       .word   0xe1b080a6
+       .word   0x22911c01
+       .word   0x23a01102
+       .word   0x22833001
+       .word   0xe3160002
+       .word   0x11a04c06
+       .word   0xe1a0f00e
+       .word   0xe1968b02
+       .word   0xe18082e5
+       .word   0x23888101
+       .word   0x13888202
+       .word   0xe3340000
+       .word   0x01b06a02
+       .word   0x43888201
+       .word   0xe3c220ff
+       .word   0xe3c22c07
+       .word   0xe24f6020
+       .word   0xe7d66e68
+       .word   0xe1b080a6
+       .word   0x22922b02
+       .word   0x22911001
+       .word   0x23a01102
+       .word   0x22833001
+       .word   0xe3160002
+       .word   0x11a04c06
+       .word   0xe1a0f00e
+       .word   0xfefe0000
+       .word   0x030303fe
+       .word   0xfefe0000
+       .word   0x030303fe
+       .word   0x03030000
+       .word   0x03030303
+       .word   0xfefe0000
+       .word   0xfefefefe
+       .word   0xfefe0000
+       .word   0xfefefefe
+       .word   0x03030000
+       .word   0x03030303
+       .word   0xfefe0000
+       .word   0xfefefefe
+       .word   0xfefe0000
+       .word   0xfefefefe
+       .word   0x40007fff
+       .word   0x00000000
+       .word   0x00000000
+       .word   0x0000407e
+       .word   0xffffff00
+       .word   0x00000000
+       .word   0x000043fe
+       .word   0xffffffff
+       .word   0xfffff800
+       .word   0x00007ffe
+       .word   0xffffffff
+       .word   0xffffffff
+       .word   0xc0007fff
+       .word   0x00000000
+       .word   0x00000000
+       .word   0x8000407e
+       .word   0xffffff00
+       .word   0x00000000
+       .word   0x800043fe
+       .word   0xffffffff
+       .word   0xfffff800
+       .word   0x80007ffe
+       .word   0xffffffff
+       .word   0xffffffff
+       .word   0x00000030
+       .word   0x00000000
+       .word   0x0000003c
+       .word   0x00000000
+       .word   0x00000030
+       .word   0x0000000c
+       .word   0x0000003c
+       .word   0x0000000c
+       .word   0x00000030
+       .word   0x00000000
+       .word   0x00000048
+       .word   0x00000000
+       .word   0x00000030
+       .word   0x00000018
+       .word   0x00000048
+       .word   0x00000018
+       .word   0x00000030
+       .word   0x00000000
+       .word   0x00000054
+       .word   0x00000000
+       .word   0x00000030
+       .word   0x00000024
+       .word   0x00000054
+       .word   0x00000024
+       .word   0xe3170701
+       .word   0x1a00000c
+       .word   0xe3877004
+       .word   0xe24f1074
+       .word   0xe0811125
+       .word   0xe8910006
+       .word   0xe3100102
+       .word   0xe24f00e4
+       .word   0x10800001
+       .word   0x00800002
+       .word   0xe8900007
+       .word   0xe3100101
+       .word   0x13a04001
+       .word   0x03e04000
+       .word   0xe1a0f00e
+       .word   0xe92d4c28
+       .word   0xe3540102
+       .word   0x13540000
+       .word   0xc3a04001
+       .word   0xb3e04000
+       .word   0xee207110
+       .word   0xe24dd004
+       .word   0xe28f8e17
+       .word   0xe20b9010
+       .word   0xe7989129
+       .word   0xe31b0902
+       .word   0x11a09829
+       .word   0xe20b860f
+       .word   0xe1a08a28
+       .word   0xe1a09839
+       .word   0xe0099fa7
+       .word   0xe1c99527
+       .word   0xe0099cab
+       .word   0xe3150c01
+       .word   0x1a00002b
+       .word   0xe3150080
+       .word   0x1a000014
+       .word   0xe24330c0
+       .word   0xe59f8124
+       .word   0xe1530008
+       .word   0xd1800003
+       .word   0xc28f0f43
+       .word   0xc8900007
+       .word   0xe92d0007
+       .word   0xe1a03009
+       .word   0xeb000fc2
+       .word   0xe24dd010
+       .word   0xe1a08407
+       .word   0xe3888001
+       .word   0xe58d8000
+       .word   0xe10f8000
+       .word   0xe3888080
+       .word   0xe129f008
+       .word   0xe1a00000
+       .word   0xe28d8010
+       .word   0xed088203
+       .word   0xed980100
+       .word   0xea000028
+       .word   0xe2433c06
+       .word   0xe59f80d4
+       .word   0xe1530008
+       .word   0xd1800003
+       .word   0xc28f00b8
+       .word   0xc8900007
+       .word   0xe92d0007
+       .word   0xe1a03009
+       .word   0xeb000fad
+       .word   0xe24dd010
+       .word   0xe1a08407
+       .word   0xe3888001
+       .word   0xe58d8000
+       .word   0xe10f8000
+       .word   0xe3888080
+       .word   0xe129f008
+       .word   0xe1a00000
+       .word   0xe28d8010
+       .word   0xed088203
+       .word   0xed988100
+       .word   0xea000013
+       .word   0xe2433a06
+       .word   0xe59f8084
+       .word   0xe1530008
+       .word   0xd1800003
+       .word   0xc28f0064
+       .word   0xc8900007
+       .word   0xe92d0007
+       .word   0xe1a03009
+       .word   0xeb000f98
+       .word   0xe24dd010
+       .word   0xe1a08407
+       .word   0xe3888001
+       .word   0xe58d8000
+       .word   0xe10f8000
+       .word   0xe3888080
+       .word   0xe129f008
+       .word   0xe1a00000
+       .word   0xe28d8010
+       .word   0xed088203
+       .word   0xedd80100
+       .word   0xee307110
+       .word   0xe28d8010
+       .word   0xed888200
+       .word   0xe8980007
+       .word   0xed188203
+       .word   0xe28dd020
+       .word   0xe10f8000
+       .word   0xe3c88080
+       .word   0xe129f008
+       .word   0xe1a00000
+       .word   0xe8bd8c28
+       .word   0x40007fff
+       .word   0x40000200
+       .word   0x00000000
+       .word   0x0000407e
+       .word   0x000043fe
+       .word   0x00007ffe
+       .word   0xc0070e3f
+       .word   0x00010001
+       .word   0xe92d4000
+       .word   0xe3170702
+       .word   0x1a000025
+       .word   0xe0833008
+       .word   0xe1a092a8
+       .word   0xe1c88289
+       .word   0xe3590002
+       .word   0x33390000
+       .word   0xe2689020
+       .word   0xe1a06912
+       .word   0xe1a02832
+       .word   0xe1822911
+       .word   0xe1a01831
+       .word   0x0a000003
+       .word   0x11866106
+       .word   0x11826126
+       .word   0x11a02001
+       .word   0x13a01000
+       .word   0x3a000004
+       .word   0x21866002
+       .word   0x21866106
+       .word   0x21816126
+       .word   0x23a02000
+       .word   0x23a01000
+       .word   0xebfffef6
+       .word   0xe3170c01
+       .word   0x13310102
+       .word   0x11918002
+       .word   0x13a01000
+       .word   0x13a02000
+       .word   0x13e04000
+       .word   0x03360000
+       .word   0x13877008
+       .word   0xe1916002
+       .word   0x08bd8000
+       .word   0xe3330000
+       .word   0x1b000280
+       .word   0x03110102
+       .word   0x03800101
+       .word   0xe1800003
+       .word   0xe8bd8000
+       .word   0xe92d4c28
+       .word   0xe3540102
+       .word   0x13540000
+       .word   0xc3a04001
+       .word   0xb3e04000
+       .word   0xee207110
+       .word   0xe24dd004
+       .word   0xe24f80d0
+       .word   0xe20b9010
+       .word   0xe7989129
+       .word   0xe31b0902
+       .word   0x11a09829
+       .word   0xe20b860f
+       .word   0xe1a08a28
+       .word   0xe1a09839
+       .word   0xe0099fa7
+       .word   0xe1c99527
+       .word   0xe0099cab
+       .word   0xe3150c01
+       .word   0x1a000015
+       .word   0xe3150080
+       .word   0x1a000009
+       .word   0xe28330c0
+       .word   0xe59f8078
+       .word   0xe1530008
+       .word   0xa1800003
+       .word   0xb28f0060
+       .word   0xb8900007
+       .word   0xe92d0007
+       .word   0xe1a03009
+       .word   0xeb000f34
+       .word   0xeaffff6e
+       .word   0xe2833c06
+       .word   0xe59f8054
+       .word   0xe1530008
+       .word   0xa1800003
+       .word   0xb28f0038
+       .word   0xb8900007
+       .word   0xe92d0007
+       .word   0xe1a03009
+       .word   0xeb000f2a
+       .word   0xeaffff79
+       .word   0xe2833a06
+       .word   0xe3a08000
+       .word   0xe1530008
+       .word   0xa1800003
+       .word   0xb28f0010
+       .word   0xb8900007
+       .word   0xe92d0007
+       .word   0xe1a03009
+       .word   0xeb000f20
+       .word   0xeaffff84
+       .word   0x40007fff
+       .word   0x40000300
+       .word   0x00000000
+       .word   0x00003f81
+       .word   0x00003c01
+       .word   0xe92d4000
+       .word   0xe3170702
+       .word   0x1affffc3
+       .word   0xe0833008
+       .word   0xe1a092a8
+       .word   0xe1c88289
+       .word   0xe3590002
+       .word   0x33390000
+       .word   0xe2689020
+       .word   0xe1a06912
+       .word   0xe1a02832
+       .word   0xe1822911
+       .word   0xe1a01831
+       .word   0x0a000003
+       .word   0x11866106
+       .word   0x11826126
+       .word   0x11a02001
+       .word   0x13a01000
+       .word   0x3a000004
+       .word   0x21866002
+       .word   0x21866106
+       .word   0x21816126
+       .word   0x23a02000
+       .word   0x23a01000
+       .word   0xebfffe94
+       .word   0xe3170c01
+       .word   0x13310102
+       .word   0x11918002
+       .word   0x13a01000
+       .word   0x13a02000
+       .word   0x13e04000
+       .word   0x03360000
+       .word   0x13877008
+       .word   0xe1916002
+       .word   0x08bd8000
+       .word   0xe3310102
+       .word   0x13800101
+       .word   0x13330000
+       .word   0x12433001
+       .word   0x13811102
+       .word   0xe1800003
+       .word   0xe8bd8000
+       .word   0xe3a08000
+       .word   0xea000004
+       .word   0xe3a08001
+       .word   0xea000002
+       .word   0xe3a08002
+       .word   0xea000000
+       .word   0xe1a083a5
+       .word   0xe92d4c28
+       .word   0xe3540102
+       .word   0x13540000
+       .word   0xc3a04001
+       .word   0xb3e04000
+       .word   0xee207110
+       .word   0xe24dd004
+       .word   0xe92d0007
+       .word   0xe24f8f9f
+       .word   0xe20b3010
+       .word   0xe7983123
+       .word   0xe31b0902
+       .word   0x11a03823
+       .word   0xe20b860f
+       .word   0xe1a08a28
+       .word   0xe1a03833
+       .word   0xe0033fa7
+       .word   0xe1c33527
+       .word   0xe0033cab
+       .word   0xe3580001
+       .word   0x8a000004
+       .word   0x0a000001
+       .word   0xeb000ed4
+       .word   0xeaffff0c
+       .word   0xeb000ed2
+       .word   0xeaffff1f
+       .word   0xeb000ed0
+       .word   0xeaffff32
+       .word   0xe92d4c28
+       .word   0xe3540102
+       .word   0x13540000
+       .word   0xc3a04001
+       .word   0xb3e04000
+       .word   0xee207110
+       .word   0xe24dd010
+       .word   0xe3a03000
+       .word   0xeb000ec6
+       .word   0xee307110
+       .word   0xe49d6010
+       .word   0xe8bd8c28
+       .word   0xe92d4c28
+       .word   0xe3540102
+       .word   0x13540000
+       .word   0xc3a04001
+       .word   0xb3e04000
+       .word   0xee207110
+       .word   0xe24dd010
+       .word   0xe3a03000
+       .word   0xeb000eba
+       .word   0xee307110
+       .word   0xe89d0007
+       .word   0xe28dd010
+       .word   0xe8bd8c28
+       .word   0xe92d4c28
+       .word   0xe3540102
+       .word   0x13540000
+       .word   0xc3a04001
+       .word   0xb3e04000
+       .word   0xee207110
+       .word   0xe24dd010
+       .word   0xe3a03000
+       .word   0xeb000ead
+       .word   0xee307110
+       .word   0xe8bd0047
+       .word   0xe8bd8c28
+       .word   0xe3c08103
+       .word   0xe3a090ff
+       .word   0xe3899c43
+       .word   0xe1580009
+       .word   0x81a0648b
+       .word   0x91e0648b
+       .word   0x0006680b
+       .word   0x11c6680b
+       .word   0xe3360000
+       .word   0x52176c02
+       .word   0x11a0f00e
+       .word   0xe1b06b08
+       .word   0x31a06fa6
+       .word   0x22026001
+       .word   0xe31b0902
+       .word   0x12266001
+       .word   0xe31b0501
+       .word   0x13a06000
+       .word   0xe1a0f00e
+       .word   0xe3c08103
+       .word   0xe3a090ff
+       .word   0xe3899c43
+       .word   0xe1580009
+       .word   0x81a0660b
+       .word   0x91e0660b
+       .word   0x00066c0b
+       .word   0x11c66c0b
+       .word   0xe3360000
+       .word   0x52176c02
+       .word   0x11a0f00e
+       .word   0xe1b06b08
+       .word   0x31a06fa6
+       .word   0x22026001
+       .word   0xe31b0080
+       .word   0x12266001
+       .word   0xe31b0702
+       .word   0x13a06000
+       .word   0xe1a0f00e
+       .word   0xe1928081
+       .word   0x0a000005
+       .word   0xe3110101
+       .word   0x0a000019
+       .word   0xe1958084
+       .word   0x0a000017
+       .word   0xe3140101
+       .word   0x1a000015
+       .word   0xe2148101
+       .word   0x1a000003
+       .word   0xe3170801
+       .word   0x1a00009b
+       .word   0xe3877001
+       .word   0xe3844101
+       .word   0xe1a00003
+       .word   0xe1a01004
+       .word   0xe1a02005
+       .word   0xea000011
+       .word   0x0a000010
+       .word   0xe2118101
+       .word   0x1a00000e
+       .word   0xe3170801
+       .word   0x1a000053
+       .word   0xea000009
+       .word   0x0a00000a
+       .word   0xe2118101
+       .word   0x1a000008
+       .word   0xe3170801
+       .word   0x1a00002d
+       .word   0xea000003
+       .word   0xe2118101
+       .word   0x1a000003
+       .word   0xe3170801
+       .word   0x1a000085
+       .word   0xe3877001
+       .word   0xe3811101
+       .word   0xe31b0702
+       .word   0x1a000010
+       .word   0xe31b0080
+       .word   0x1a000006
+       .word   0xe2000103
+       .word   0xe380007f
+       .word   0xe3800901
+       .word   0xe3a02000
+       .word   0xe3c110ff
+       .word   0xe3811102
+       .word   0xe1a0f00e
+       .word   0xe2000103
+       .word   0xe38000ff
+       .word   0xe3800c43
+       .word   0xe1a025a2
+       .word   0xe1a02582
+       .word   0xe3811102
+       .word   0xe1300000
+       .word   0xe1a0f00e
+       .word   0xe31b0c02
+       .word   0x1a000005
+       .word   0xe3c08103
+       .word   0xe3a090ff
+       .word   0xe3899c43
+       .word   0xe1580009
+       .word   0x33c22001
+       .word   0x03822001
+       .word   0xe2000103
+       .word   0xe38000ff
+       .word   0xe3800c7f
+       .word   0xe1300000
+       .word   0xe1a0f00e
+       .word   0xe3170801
+       .word   0x1a000004
+       .word   0xe3877001
+       .word   0xe28f0d0a
+       .word   0xe8900007
+       .word   0xe1811408
+       .word   0xe1a0f00e
+       .word   0xe92d4c30
+       .word   0xee207110
+       .word   0xe24dd00c
+       .word   0xe92d0007
+       .word   0xe28f8f9b
+       .word   0xe20b3010
+       .word   0xe7983123
+       .word   0xe31b0902
+       .word   0x11a03823
+       .word   0xe20b860f
+       .word   0xe1a08a28
+       .word   0xe1a03833
+       .word   0xe0033fa7
+       .word   0xe1c33527
+       .word   0xe0033cab
+       .word   0xe31b0702
+       .word   0x1a00002e
+       .word   0xe31b0080
+       .word   0x1a00001f
+       .word   0xeb000e1d
+       .word   0xe24dd010
+       .word   0xe1a08407
+       .word   0xe3888001
+       .word   0xe58d8000
+       .word   0xe10f8000
+       .word   0xe3888080
+       .word   0xe129f008
+       .word   0xe1a00000
+       .word   0xe28d8010
+       .word   0xed088203
+       .word   0xed980100
+       .word   0xea00002b
+       .word   0xe92d4c30
+       .word   0xee207110
+       .word   0xe24dd00c
+       .word   0xe92d0007
+       .word   0xe28f8f7b
+       .word   0xe20b3010
+       .word   0xe7983123
+       .word   0xe31b0902
+       .word   0x11a03823
+       .word   0xe20b860f
+       .word   0xe1a08a28
+       .word   0xe1a03833
+       .word   0xe0033fa7
+       .word   0xe1c33527
+       .word   0xe0033cab
+       .word   0xe31b0501
+       .word   0x1a00000e
+       .word   0xe31b0902
+       .word   0x0affffdf
+       .word   0xeb000dfd
+       .word   0xe24dd010
+       .word   0xe1a08407
+       .word   0xe3888001
+       .word   0xe58d8000
+       .word   0xe10f8000
+       .word   0xe3888080
+       .word   0xe129f008
+       .word   0xe1a00000
+       .word   0xe28d8010
+       .word   0xed088203
+       .word   0xed988100
+       .word   0xea00000b
+       .word   0xeb000df0
+       .word   0xe24dd010
+       .word   0xe1a08407
+       .word   0xe3888001
+       .word   0xe58d8000
+       .word   0xe10f8000
+       .word   0xe3888080
+       .word   0xe129f008
+       .word   0xe1a00000
+       .word   0xe28d8010
+       .word   0xed088203
+       .word   0xedd80100
+       .word   0xee307110
+       .word   0xe28d8010
+       .word   0xed888200
+       .word   0xe8980007
+       .word   0xed188203
+       .word   0xe28dd028
+       .word   0xe10f8000
+       .word   0xe3c88080
+       .word   0xe129f008
+       .word   0xe1a00000
+       .word   0xe2106101
+       .word   0x03c03103
+       .word   0x02000102
+       .word   0xe3b08001
+       .word   0xe8bd8c30
+       .word   0xe3170801
+       .word   0x0affff9d
+       .word   0xe92d4c30
+       .word   0xee207110
+       .word   0xe92d003f
+       .word   0xe28f80fc
+       .word   0xe20b3010
+       .word   0xe7983123
+       .word   0xe31b0902
+       .word   0x11a03823
+       .word   0xe20b860f
+       .word   0xe1a08a28
+       .word   0xe1a03833
+       .word   0xe0033fa7
+       .word   0xe1c33527
+       .word   0xe0033cab
+       .word   0xe31b0702
+       .word   0x1a000005
+       .word   0xe31b0080
+       .word   0x1a000001
+       .word   0xeb000dc1
+       .word   0xeaffffa2
+       .word   0xeb000dbf
+       .word   0xeaffffc0
+       .word   0xeb000dbd
+       .word   0xeaffffcb
+       .word   0xe3170801
+       .word   0x03877001
+       .word   0x01a0f00e
+       .word   0xe92d4c00
+       .word   0xee207110
+       .word   0xe24dd004
+       .word   0xe92d0007
+       .word   0xe3a03000
+       .word   0xeb000db3
+       .word   0xee307110
+       .word   0xe49d6010
+       .word   0xe8bd8c00
+       .word   0xe3170801
+       .word   0x03877001
+       .word   0x01a0f00e
+       .word   0xe92d4c00
+       .word   0xee207110
+       .word   0xe92d003f
+       .word   0xe3a03000
+       .word   0xeb000da8
+       .word   0xee307110
+       .word   0xe49d6018
+       .word   0xe8bd8c00
+       .word   0xe92d4c00
+       .word   0xee207110
+       .word   0xe24dd004
+       .word   0xe92d0007
+       .word   0xe3a03000
+       .word   0xe3170b02
+       .word   0x1a000003
+       .word   0xeb000d9d
+       .word   0xe8bd0007
+       .word   0xe28dd004
+       .word   0xea000001
+       .word   0xeb000d99
+       .word   0xe8bd0047
+       .word   0xee307110
+       .word   0xe8bd8c00
+       .word   0x40007fff
+       .word   0x00000000
+       .word   0x00000000
+       .word   0x40007fff
+       .word   0x40000000
+       .word   0x00000000
+       .word   0xc0070e3f
+       .word   0x00010001
+       .word   0xe3170802
+       .word   0x1a000004
+       .word   0xe3877002
+       .word   0xe24f0034
+       .word   0xe8900007
+       .word   0xe3800102
+       .word   0xe1a0f00e
+       .word   0xe92d4c30
+       .word   0xee207110
+       .word   0xe24dd00c
+       .word   0xe92d0007
+       .word   0xe24f803c
+       .word   0xe20b3010
+       .word   0xe7983123
+       .word   0xe31b0902
+       .word   0x11a03823
+       .word   0xe20b860f
+       .word   0xe1a08a28
+       .word   0xe1a03833
+       .word   0xe0033fa7
+       .word   0xe1c33527
+       .word   0xe0033cab
+       .word   0xe31b0702
+       .word   0x1a000005
+       .word   0xe31b0080
+       .word   0x1a000001
+       .word   0xeb000d75
+       .word   0xeaffff54
+       .word   0xeb000d73
+       .word   0xeaffff72
+       .word   0xeb000d71
+       .word   0xeaffff7d
+       .word   0xe3170802
+       .word   0x1a000006
+       .word   0xe3877002
+       .word   0xe0208003
+       .word   0xe2088102
+       .word   0xe24f00bc
+       .word   0xe8900007
+       .word   0xe1800008
+       .word   0xe1a0f00e
+       .word   0xe92d4c30
+       .word   0xee207110
+       .word   0xe92d003f
+       .word   0xe24f80c0
+       .word   0xe20b3010
+       .word   0xe7983123
+       .word   0xe31b0902
+       .word   0x11a03823
+       .word   0xe20b860f
+       .word   0xe1a08a28
+       .word   0xe1a03833
+       .word   0xe0033fa7
+       .word   0xe1c33527
+       .word   0xe0033cab
+       .word   0xe31b0702
+       .word   0x1a000005
+       .word   0xe31b0080
+       .word   0x1a000001
+       .word   0xeb000d54
+       .word   0xeaffff33
+       .word   0xeb000d52
+       .word   0xeaffff51
+       .word   0xeb000d50
+       .word   0xeaffff5c
+       .word   0xe2000102
+       .word   0xe3310000
+       .word   0x0a000017
+       .word   0xe3a08000
+       .word   0xe1b09821
+       .word   0x01a01801
+       .word   0x02888010
+       .word   0xe1b09c21
+       .word   0x01a01401
+       .word   0x02888008
+       .word   0xe1b09e21
+       .word   0x01a01201
+       .word   0x02888004
+       .word   0xe1b09f21
+       .word   0x01a01101
+       .word   0x02888002
+       .word   0xe1b09fa1
+       .word   0x01a01081
+       .word   0x02888001
+       .word   0xe05898a6
+       .word   0x81a01931
+       .word   0x81a088a6
+       .word   0xe2686020
+       .word   0xe1811632
+       .word   0xe1a02812
+       .word   0x30400009
+       .word   0xe1a0f00e
+       .word   0xe3560501
+       .word   0x3a000016
+       .word   0xe1b01002
+       .word   0x01a0f00e
+       .word   0xe3a02000
+       .word   0xe3a08020
+       .word   0xe1b09821
+       .word   0x01a01801
+       .word   0x02888010
+       .word   0xe1b09c21
+       .word   0x01a01401
+       .word   0x02888008
+       .word   0xe1b09e21
+       .word   0x01a01201
+       .word   0x02888004
+       .word   0xe1b09f21
+       .word   0x01a01101
+       .word   0x02888002
+       .word   0xe1b09fa1
+       .word   0x01a01081
+       .word   0x02888001
+       .word   0xe05898a6
+       .word   0x81a01931
+       .word   0x30400009
+       .word   0xe1a0f00e
+       .word   0xe1a088a6
+       .word   0xe2689020
+       .word   0xe1a01811
+       .word   0xe1811932
+       .word   0xe1a02812
+       .word   0xe1a0f00e
+       .word   0xe2033102
+       .word   0xe3340000
+       .word   0x0a000017
+       .word   0xe3a08000
+       .word   0xe1b09824
+       .word   0x01a04804
+       .word   0x02888010
+       .word   0xe1b09c24
+       .word   0x01a04404
+       .word   0x02888008
+       .word   0xe1b09e24
+       .word   0x01a04204
+       .word   0x02888004
+       .word   0xe1b09f24
+       .word   0x01a04104
+       .word   0x02888002
+       .word   0xe1b09fa4
+       .word   0x01a04084
+       .word   0x02888001
+       .word   0xe05898a6
+       .word   0x81a04934
+       .word   0x81a088a6
+       .word   0xe2686020
+       .word   0xe1844635
+       .word   0xe1a05815
+       .word   0x30433009
+       .word   0xe1a0f00e
+       .word   0xe3560501
+       .word   0x3a000016
+       .word   0xe1b04005
+       .word   0x01a0f00e
+       .word   0xe3a05000
+       .word   0xe3a08020
+       .word   0xe1b09824
+       .word   0x01a04804
+       .word   0x02888010
+       .word   0xe1b09c24
+       .word   0x01a04404
+       .word   0x02888008
+       .word   0xe1b09e24
+       .word   0x01a04204
+       .word   0x02888004
+       .word   0xe1b09f24
+       .word   0x01a04104
+       .word   0x02888002
+       .word   0xe1b09fa4
+       .word   0x01a04084
+       .word   0x02888001
+       .word   0xe05898a6
+       .word   0x81a04934
+       .word   0x30433009
+       .word   0xe1a0f00e
+       .word   0xe1a088a6
+       .word   0xe2689020
+       .word   0xe1a04814
+       .word   0xe1844935
+       .word   0xe1a05815
+       .word   0xe1a0f00e
+       .word   0xe3a02000
+       .word   0xe2160102
+       .word   0x12661000
+       .word   0x01b01006
+       .word   0x03a03000
+       .word   0x01a0f00e
+       .word   0xe3a03901
+       .word   0xe383301e
+       .word   0xe3a06000
+       .word   0xe3310000
+       .word   0x01a01002
+       .word   0x03a02000
+       .word   0x02433020
+       .word   0xe3a08000
+       .word   0xe1b09821
+       .word   0x01a01801
+       .word   0x02888010
+       .word   0xe1b09c21
+       .word   0x01a01401
+       .word   0x02888008
+       .word   0xe1b09e21
+       .word   0x01a01201
+       .word   0x02888004
+       .word   0xe1b09f21
+       .word   0x01a01101
+       .word   0x02888002
+       .word   0xe1b09fa1
+       .word   0x01a01081
+       .word   0x02888001
+       .word   0xe2789020
+       .word   0xe1811932
+       .word   0xe1a02812
+       .word   0xe0433008
+       .word   0xe1a0f00e
+       .word   0xe3340000
+       .word   0x01a04005
+       .word   0x03a05000
+       .word   0x02433020
+       .word   0xe3a08000
+       .word   0xe1b09824
+       .word   0x01a04804
+       .word   0x02888010
+       .word   0xe1b09c24
+       .word   0x01a04404
+       .word   0x02888008
+       .word   0xe1b09e24
+       .word   0x01a04204
+       .word   0x02888004
+       .word   0xe1b09f24
+       .word   0x01a04104
+       .word   0x02888002
+       .word   0xe1b09fa4
+       .word   0x01a04084
+       .word   0x02888001
+       .word   0xe2789020
+       .word   0xe1844935
+       .word   0xe1a05815
+       .word   0xe0433008
+       .word   0xe1a0f00e
+       .word   0xe3310000
+       .word   0x01a01002
+       .word   0x03a02000
+       .word   0x02833020
+       .word   0xe3a08000
+       .word   0xe1b09821
+       .word   0x01a01801
+       .word   0x02888010
+       .word   0xe1b09c21
+       .word   0x01a01401
+       .word   0x02888008
+       .word   0xe1b09e21
+       .word   0x01a01201
+       .word   0x02888004
+       .word   0xe1b09f21
+       .word   0x01a01101
+       .word   0x02888002
+       .word   0xe1b09fa1
+       .word   0x01a01081
+       .word   0x02888001
+       .word   0xe2789020
+       .word   0xe1811932
+       .word   0xe1a02812
+       .word   0xe0833008
+       .word   0xe1a0f00e
+       .word   0xe3100101
+       .word   0x03130101
+       .word   0x1a0003c1
+       .word   0xe92d4000
+       .word   0xe31b0602
+       .word   0x12233102
+       .word   0xe31b0601
+       .word   0x12233102
+       .word   0x12200102
+       .word   0xe1a06880
+       .word   0xe0568883
+       .word   0xe020e003
+       .word   0xe2000102
+       .word   0xe1a038a6
+       .word   0x8a00001a
+       .word   0x01a09008
+       .word   0x0a00002e
+       .word   0xe2686000
+       .word   0xe1a068a6
+       .word   0xe0833006
+       .word   0xe1a092a6
+       .word   0xe1c66289
+       .word   0xe3590002
+       .word   0x33390000
+       .word   0xe2669020
+       .word   0xe1a08912
+       .word   0xe1a02632
+       .word   0xe1822911
+       .word   0xe1a01631
+       .word   0x0a000003
+       .word   0x11888108
+       .word   0x11828128
+       .word   0x11a02001
+       .word   0x13a01000
+       .word   0x3a000004
+       .word   0x21888002
+       .word   0x21888108
+       .word   0x21818128
+       .word   0x23a02000
+       .word   0x23a01000
+       .word   0xe3a09000
+       .word   0xea000015
+       .word   0xe1a068a8
+       .word   0xe1a082a6
+       .word   0xe1c66288
+       .word   0xe3580002
+       .word   0x33380000
+       .word   0xe2668020
+       .word   0xe1a09815
+       .word   0xe1a05635
+       .word   0xe1855814
+       .word   0xe1a04634
+       .word   0x0a000003
+       .word   0x11899109
+       .word   0x11859129
+       .word   0x11a05004
+       .word   0x13a04000
+       .word   0x3a000004
+       .word   0x21899005
+       .word   0x21899109
+       .word   0x21849129
+       .word   0x23a05000
+       .word   0x23a04000
+       .word   0xe3a08000
+       .word   0xe31e0102
+       .word   0x1a000009
+       .word   0xe0986009
+       .word   0xe0b22005
+       .word   0xe0b11004
+       .word   0x38bd8000
+       .word   0xe2833001
+       .word   0xe1b01061
+       .word   0xe1b02062
+       .word   0xe1866086
+       .word   0xe1a06066
+       .word   0xe8bd8000
+       .word   0xe0586009
+       .word   0xe0d22005
+       .word   0xe0d11004
+       .word   0x2a000003
+       .word   0xe2200102
+       .word   0xe2766000
+       .word   0xe2f22000
+       .word   0xe2e11000
+       .word   0xe3110102
+       .word   0x18bd8000
+       .word   0xe0966006
+       .word   0xe0b22002
+       .word   0xe0a11001
+       .word   0xe2433001
+       .word   0xe3110102
+       .word   0x18bd8000
+       .word   0xe191e002
+       .word   0x1bffff56
+       .word   0x18bd8000
+       .word   0xe20b8060
+       .word   0xe3380040
+       .word   0x03a00102
+       .word   0x13a00000
+       .word   0xe3a03000
+       .word   0xe8bd8000
+       .word   0xe3100101
+       .word   0x03130101
+       .word   0x1a000395
+       .word   0xe0118004
+       .word   0x5a0003b5
+       .word   0xe3c08103
+       .word   0xe3c39103
+       .word   0xe0200003
+       .word   0xe2000102
+       .word   0xe0883009
+       .word   0xe2433c3f
+       .word   0xe24330fe
+       .word   0xe31b0502
+       .word   0x1a00007f
+       .word   0xe3320000
+       .word   0x0a00005d
+       .word   0xe3350000
+       .word   0x0a00003d
+       .word   0xe92d4881
+       .word   0xe1a00821
+       .word   0xe1c17800
+       .word   0xe1a06824
+       .word   0xe1c48806
+       .word   0xe0090690
+       .word   0xe0060697
+       .word   0xe0070798
+       .word   0xe0977806
+       .word   0xe0a99826
+       .word   0xe0080890
+       .word   0xe0977808
+       .word   0xe0a90828
+       .word   0xe1a0b822
+       .word   0xe1c2e80b
+       .word   0xe1a06825
+       .word   0xe1c58806
+       .word   0xe009069b
+       .word   0xe006069e
+       .word   0xe00e0e98
+       .word   0xe09ee806
+       .word   0xe0a99826
+       .word   0xe008089b
+       .word   0xe09ee808
+       .word   0xe0a9b828
+       .word   0xe097700b
+       .word   0xe2a00000
+       .word   0xe097b00e
+       .word   0xe0b77000
+       .word   0xe2a00000
+       .word   0xe0518002
+       .word   0xe3a01000
+       .word   0xe3a06000
+       .word   0x31e01001
+       .word   0x30446005
+       .word   0x10559004
+       .word   0x03a01000
+       .word   0x31e01001
+       .word   0x30466008
+       .word   0xe1a04828
+       .word   0xe1c85804
+       .word   0xe1a08829
+       .word   0xe1c99808
+       .word   0xe0226894
+       .word   0xe0080895
+       .word   0xe0060599
+       .word   0xe0966808
+       .word   0xe0a22828
+       .word   0xe0090994
+       .word   0xe0966809
+       .word   0xe0a22829
+       .word   0xe09b6006
+       .word   0xe0b72002
+       .word   0xe0b01001
+       .word   0xe18ee10e
+       .word   0xe186612e
+       .word   0x48bd8881
+       .word   0xe0966006
+       .word   0xe0b22002
+       .word   0xe0a11001
+       .word   0xe2433001
+       .word   0xe8bd8881
+       .word   0xe1a05824
+       .word   0xe1c46805
+       .word   0xe1a08821
+       .word   0xe1c19808
+       .word   0xe0040895
+       .word   0xe0080896
+       .word   0xe0010699
+       .word   0xe0911808
+       .word   0xe0a44828
+       .word   0xe0090995
+       .word   0xe0911809
+       .word   0xe0a44829
+       .word   0xe1a08822
+       .word   0xe1c29808
+       .word   0xe0020895
+       .word   0xe0080896
+       .word   0xe0060699
+       .word   0xe0966808
+       .word   0xe0a22828
+       .word   0xe0090995
+       .word   0xe0966809
+       .word   0xe0a25829
+       .word   0xe0952001
+       .word   0xe2b41000
+       .word   0x41a0f00e
+       .word   0xe0966006
+       .word   0xe0b22002
+       .word   0xe0a11001
+       .word   0xe2433001
+       .word   0xe1a0f00e
+       .word   0xe3350000
+       .word   0x0a00001d
+       .word   0xe1a02821
+       .word   0xe1c16802
+       .word   0xe1a08824
+       .word   0xe1c49808
+       .word   0xe0010892
+       .word   0xe0080896
+       .word   0xe0040699
+       .word   0xe0944808
+       .word   0xe0a11828
+       .word   0xe0090992
+       .word   0xe0944809
+       .word   0xe0a11829
+       .word   0xe1a08825
+       .word   0xe1c59808
+       .word   0xe0050892
+       .word   0xe0080896
+       .word   0xe0060699
+       .word   0xe0966808
+       .word   0xe0a55828
+       .word   0xe0090992
+       .word   0xe0966809
+       .word   0xe0a52829
+       .word   0xe0922004
+       .word   0xe2b11000
+       .word   0x41a0f00e
+       .word   0xe0966006
+       .word   0xe0b22002
+       .word   0xe0a11001
+       .word   0xe2433001
+       .word   0xe1a0f00e
+       .word   0xe1a05824
+       .word   0xe1c46805
+       .word   0xe1a08821
+       .word   0xe1c19808
+       .word   0xe0010895
+       .word   0xe0080896
+       .word   0xe0020699
+       .word   0xe0922808
+       .word   0xe0a11828
+       .word   0xe0090995
+       .word   0xe0922809
+       .word   0xe0b11829
+       .word   0xe3a06000
+       .word   0x41a0f00e
+       .word   0xe0922002
+       .word   0xe0a11001
+       .word   0xe2433001
+       .word   0xe1a0f00e
+       .word   0xe3100101
+       .word   0x03130101
+       .word   0x1a000336
+       .word   0xe0118004
+       .word   0x5a000361
+       .word   0xe31b0601
+       .word   0x1a000008
+       .word   0xe1a08000
+       .word   0xe1a00003
+       .word   0xe1a03008
+       .word   0xe1a08001
+       .word   0xe1a01004
+       .word   0xe1a04008
+       .word   0xe1a08002
+       .word   0xe1a02005
+       .word   0xe1a05008
+       .word   0xe3c08103
+       .word   0xe3c39103
+       .word   0xe0200003
+       .word   0xe2000102
+       .word   0xe0493008
+       .word   0xe2833c3f
+       .word   0xe28330ff
+       .word   0xe92d4889
+       .word   0xe1a00821
+       .word   0xe1c17800
+       .word   0xe1a0b822
+       .word   0xe1c2e80b
+       .word   0xe28f6fd9
+       .word   0xe7d66420
+       .word   0xe0286690
+       .word   0xe2688502
+       .word   0xe0060698
+       .word   0xe1a069a6
+       .word   0xe2866002
+       .word   0xe1a086a1
+       .word   0xe0296698
+       .word   0xe2699202
+       .word   0xe1a08829
+       .word   0xe1c99808
+       .word   0xe0020699
+       .word   0xe0010698
+       .word   0xe0816822
+       .word   0xe1a06326
+       .word   0xe1b040a4
+       .word   0xe1b05065
+       .word   0x33a03000
+       .word   0x23a03102
+       .word   0xe1a087a4
+       .word   0xe0090896
+       .word   0xe1a09829
+       .word   0xe0080b99
+       .word   0xe0555008
+       .word   0xe0080990
+       .word   0xe0c44008
+       .word   0xe0080e99
+       .word   0xe0533808
+       .word   0xe0d55828
+       .word   0xe0080799
+       .word   0x30455808
+       .word   0x20555808
+       .word   0xe0c44828
+       .word   0xe1a01809
+       .word   0xe1a08124
+       .word   0xe0090896
+       .word   0xe1a09829
+       .word   0xe0080b99
+       .word   0xe0533988
+       .word   0xe0d556a8
+       .word   0xe0080990
+       .word   0x30455988
+       .word   0x20555988
+       .word   0xe0c446a8
+       .word   0xe0080e99
+       .word   0xe0533188
+       .word   0xe0d55ea8
+       .word   0xe0080799
+       .word   0x30455188
+       .word   0x20555188
+       .word   0xe0c44ea8
+       .word   0xe1a04d04
+       .word   0xe1844325
+       .word   0xe1a05d05
+       .word   0xe1855323
+       .word   0xe1a03d03
+       .word   0xe0811189
+       .word   0xe59d800c
+       .word   0xe3180702
+       .word   0x03180080
+       .word   0x0a000094
+       .word   0xe1a087a4
+       .word   0xe0090896
+       .word   0xe1a09829
+       .word   0xe0080b99
+       .word   0xe0555008
+       .word   0xe0080990
+       .word   0xe0c44008
+       .word   0xe0080e99
+       .word   0xe0533808
+       .word   0xe0d55828
+       .word   0xe0080799
+       .word   0x30455808
+       .word   0x20555808
+       .word   0xe0c44828
+       .word   0xe1a02b09
+       .word   0xe0811529
+       .word   0xe1a08124
+       .word   0xe0090896
+       .word   0xe1a09829
+       .word   0xe0080b99
+       .word   0xe0533988
+       .word   0xe0d556a8
+       .word   0xe0080990
+       .word   0x30455988
+       .word   0x20555988
+       .word   0xe0c446a8
+       .word   0xe0080e99
+       .word   0xe0533188
+       .word   0xe0d55ea8
+       .word   0xe0080799
+       .word   0x30455188
+       .word   0x20555188
+       .word   0xe0c44ea8
+       .word   0xe1a04d04
+       .word   0xe1844325
+       .word   0xe1a05d05
+       .word   0xe1855323
+       .word   0xe1a03d03
+       .word   0xe0922489
+       .word   0xe2a11000
+       .word   0xe59d800c
+       .word   0xe3180702
+       .word   0x0a00003f
+       .word   0xe1a087a4
+       .word   0xe0090896
+       .word   0xe1a09829
+       .word   0xe0080b99
+       .word   0xe0555008
+       .word   0xe0080990
+       .word   0xe0c44008
+       .word   0xe0080e99
+       .word   0xe0533808
+       .word   0xe0d55828
+       .word   0xe0080799
+       .word   0x30455808
+       .word   0x20555808
+       .word   0xe0c44828
+       .word   0xe1a04704
+       .word   0xe1844925
+       .word   0xe1a05705
+       .word   0xe1855923
+       .word   0xe1a03703
+       .word   0xe1a06e09
+       .word   0xe0922229
+       .word   0xe2a11000
+       .word   0xe1870800
+       .word   0xe18e780b
+       .word   0xe3a0e000
+       .word   0xe0559007
+       .word   0xe0d48000
+       .word   0x21a05009
+       .word   0x21a04008
+       .word   0xe0aee00e
+       .word   0xe3a0b000
+       .word   0xe0933003
+       .word   0xe0b55005
+       .word   0xe0b44004
+       .word   0xe0abb00b
+       .word   0xe0559007
+       .word   0xe0d48000
+       .word   0xe2dbb000
+       .word   0x21a05009
+       .word   0x21a04008
+       .word   0xe0aee00e
+       .word   0xe3a0b000
+       .word   0xe0933003
+       .word   0xe0b55005
+       .word   0xe0b44004
+       .word   0xe0abb00b
+       .word   0xe0559007
+       .word   0xe0d48000
+       .word   0xe2dbb000
+       .word   0x21a05009
+       .word   0x21a04008
+       .word   0xe0aee00e
+       .word   0xe1948005
+       .word   0x13866001
+       .word   0xe0966e0e
+       .word   0xe2b22000
+       .word   0xe2b11000
+       .word   0x48bd8889
+       .word   0xe8bd4889
+       .word   0xe0966006
+       .word   0xe0b22002
+       .word   0xe0a11001
+       .word   0xe2433001
+       .word   0xe1a0f00e
+       .word   0xe1870800
+       .word   0xe18e780b
+       .word   0xe3a0e000
+       .word   0xe0933003
+       .word   0xe0b55005
+       .word   0xe0a44004
+       .word   0xe0559007
+       .word   0xe0d48000
+       .word   0x21a05009
+       .word   0x21a04008
+       .word   0xe0aee00e
+       .word   0xe3a0b000
+       .word   0xe0933003
+       .word   0xe0b55005
+       .word   0xe0b44004
+       .word   0xe0abb00b
+       .word   0xe0559007
+       .word   0xe0d48000
+       .word   0xe2dbb000
+       .word   0x21a05009
+       .word   0x21a04008
+       .word   0xe0aee00e
+       .word   0xe3a0b000
+       .word   0xe0933003
+       .word   0xe0b55005
+       .word   0xe0b44004
+       .word   0xe0abb00b
+       .word   0xe0559007
+       .word   0xe0d48000
+       .word   0xe2dbb000
+       .word   0x21a05009
+       .word   0x21a04008
+       .word   0xe0aee00e
+       .word   0xe1846005
+       .word   0xe092248e
+       .word   0xe2b11000
+       .word   0x48bd8889
+       .word   0xe8bd4889
+       .word   0xe0922002
+       .word   0xe0a11001
+       .word   0xe2433001
+       .word   0xe1a0f00e
+       .word   0xe1870800
+       .word   0xe18e780b
+       .word   0xe0933003
+       .word   0xe0b55005
+       .word   0xe0a44004
+       .word   0xe0559007
+       .word   0xe0d48000
+       .word   0x21a05009
+       .word   0x21a04008
+       .word   0x22811020
+       .word   0xe3a0b000
+       .word   0xe0933003
+       .word   0xe0b55005
+       .word   0xe0b44004
+       .word   0xe0abb00b
+       .word   0xe0559007
+       .word   0xe0d48000
+       .word   0xe2dbb000
+       .word   0x21a05009
+       .word   0x21a04008
+       .word   0x22811010
+       .word   0xe3a0b000
+       .word   0xe0933003
+       .word   0xe0b55005
+       .word   0xe0b44004
+       .word   0xe0abb00b
+       .word   0xe0559007
+       .word   0xe0d48000
+       .word   0xe2dbb000
+       .word   0x21a05009
+       .word   0x21a04008
+       .word   0x22811008
+       .word   0xe1846005
+       .word   0xe3a02000
+       .word   0xe3310000
+       .word   0x48bd8889
+       .word   0xe8bd4889
+       .word   0xe1a01081
+       .word   0xe2433001
+       .word   0xe1a0f00e
+       .word   0x7e7f8080
+       .word   0x7a7b7c7d
+       .word   0x76777879
+       .word   0x73747576
+       .word   0x70717172
+       .word   0x6d6e6e6f
+       .word   0x6a6b6c6c
+       .word   0x6868696a
+       .word   0x65666667
+       .word   0x63636464
+       .word   0x60616162
+       .word   0x5e5f5f60
+       .word   0x5c5d5d5e
+       .word   0x5a5b5b5c
+       .word   0x5859595a
+       .word   0x56575758
+       .word   0x55555556
+       .word   0x53535454
+       .word   0x51525252
+       .word   0x50505051
+       .word   0x4e4f4f4f
+       .word   0x4d4d4d4e
+       .word   0x4b4c4c4c
+       .word   0x4a4a4b4b
+       .word   0x4949494a
+       .word   0x47484848
+       .word   0x46474747
+       .word   0x45454646
+       .word   0x44444445
+       .word   0x43434344
+       .word   0x42424243
+       .word   0x41414142
+       .word   0xe3100101
+       .word   0x03130101
+       .word   0x1a00025f
+       .word   0xe1946005
+       .word   0x03a0800a
+       .word   0x0afffc6c
+       .word   0xe1916002
+       .word   0x0a000297
+       .word   0xe92d4000
+       .word   0xe3c33103
+       .word   0xe2433001
+       .word   0xe3c06103
+       .word   0xe0566003
+       .word   0xe2000102
+       .word   0xb0863003
+       .word   0xb3a06000
+       .word   0xb1a0f00e
+       .word   0xe1a000c0
+       .word   0xe3a0e000
+       .word   0xea000002
+       .word   0xe1a0efa1
+       .word   0xe0922002
+       .word   0xe0a11001
+       .word   0xe0728005
+       .word   0xe0f19004
+       .word   0xe2fee000
+       .word   0x2a000002
+       .word   0xe0982005
+       .word   0xe0a91004
+       .word   0xe2200102
+       .word   0xe2566001
+       .word   0xaafffff3
+       .word   0xe3a06000
+       .word   0xe1918002
+       .word   0x01a00080
+       .word   0x03a03000
+       .word   0x12000102
+       .word   0x1bfffd52
+       .word   0xe8bd8000
+       .word   0xe3100101
+       .word   0x1a00027f
+       .word   0xe3110102
+       .word   0x0a000293
+       .word   0xe3c03103
+       .word   0xe2100102
+       .word   0x13a0800b
+       .word   0x1afffbe1
+       .word   0xe2833c3f
+       .word   0xe28330ff
+       .word   0xe1b030a3
+       .word   0x32414102
+       .word   0x22414101
+       .word   0xe1a05002
+       .word   0xe3a08202
+       .word   0xe3a01102
+       .word   0xe3a02000
+       .word   0xe3a0928b
+       .word   0xe1a069ab
+       .word   0xe3160001
+       .word   0x03a0926b
+       .word   0x031b0080
+       .word   0x03a09103
+       .word   0x3a000005
+       .word   0xe0955005
+       .word   0xe0b44004
+       .word   0xe1816008
+       .word   0x31540006
+       .word   0x20444006
+       .word   0x21811088
+       .word   0xe0955005
+       .word   0xe0b44004
+       .word   0xe18160a8
+       .word   0x31540006
+       .word   0x20444006
+       .word   0x21811008
+       .word   0xe0955005
+       .word   0xe0b44004
+       .word   0xe1816128
+       .word   0x31540006
+       .word   0x20444006
+       .word   0x218110a8
+       .word   0xe0955005
+       .word   0xe0b44004
+       .word   0xe18161a8
+       .word   0x31540006
+       .word   0x20444006
+       .word   0x21811128
+       .word   0xe0955005
+       .word   0xe0b44004
+       .word   0xe1816228
+       .word   0x31540006
+       .word   0x20444006
+       .word   0x218111a8
+       .word   0xe0955005
+       .word   0xe0b44004
+       .word   0xe18162a8
+       .word   0x31540006
+       .word   0x20444006
+       .word   0x21811228
+       .word   0xe2999201
+       .word   0xe1a08368
+       .word   0xbaffffd8
+       .word   0xe1946005
+       .word   0x13580020
+       .word   0x01a0f00e
+       .word   0xe92d4880
+       .word   0xe0955005
+       .word   0xe0b44004
+       .word   0xe0aee00e
+       .word   0xe1826008
+       .word   0xe055b006
+       .word   0xe0d47001
+       .word   0x31b0e0ae
+       .word   0x21a0500b
+       .word   0x21a04007
+       .word   0x21822088
+       .word   0x21811fa8
+       .word   0xe0955005
+       .word   0xe0b44004
+       .word   0xe0aee00e
+       .word   0xe18260a8
+       .word   0xe055b006
+       .word   0xe0d47001
+       .word   0x31b0e0ae
+       .word   0x21a0500b
+       .word   0x21a04007
+       .word   0x21822008
+       .word   0xe0955005
+       .word   0xe0b44004
+       .word   0xe0aee00e
+       .word   0xe1826128
+       .word   0xe055b006
+       .word   0xe0d47001
+       .word   0x31b0e0ae
+       .word   0x21a0500b
+       .word   0x21a04007
+       .word   0x218220a8
+       .word   0xe0955005
+       .word   0xe0b44004
+       .word   0xe0aee00e
+       .word   0xe18261a8
+       .word   0xe055b006
+       .word   0xe0d47001
+       .word   0x31b0e0ae
+       .word   0x21a0500b
+       .word   0x21a04007
+       .word   0x21822128
+       .word   0xe2599001
+       .word   0xe1a08268
+       .word   0x1affffd3
+       .word   0xe1946005
+       .word   0x13580080
+       .word   0x08bd8880
+       .word   0xe0955005
+       .word   0xe0b44004
+       .word   0xe0aee00e
+       .word   0xe2788000
+       .word   0xe0f2b005
+       .word   0xe0f17004
+       .word   0x31b0e0ae
+       .word   0x21a0500b
+       .word   0x21a04007
+       .word   0x33a08000
+       .word   0x23822001
+       .word   0xe3a06106
+       .word   0xe0988008
+       .word   0xe0b55005
+       .word   0xe0b44004
+       .word   0x28bd8880
+       .word   0xe0d5b002
+       .word   0xe0d4b001
+       .word   0x33a06001
+       .word   0xe8bd8880
+       .word   0xe3100101
+       .word   0x1a00021a
+       .word   0xe3c03103
+       .word   0xe2000102
+       .word   0xe3a06000
+       .word   0xe31b0601
+       .word   0x12200102
+       .word   0xe31b0602
+       .word   0x13c00102
+       .word   0xe1a0f00e
+       .word   0xe3100101
+       .word   0x1a000236
+       .word   0xe3c03103
+       .word   0xe3110102
+       .word   0x1a000008
+       .word   0xe1918002
+       .word   0x03a03000
+       .word   0x0a000005
+       .word   0xe92d4000
+       .word   0xe0116080
+       .word   0x43c11102
+       .word   0x42833001
+       .word   0xebfffcb4
+       .word   0xe8bd4000
+       .word   0xe2000102
+       .word   0xe3a06000
+       .word   0xe1a0f00e
+       .word   0xe3100101
+       .word   0x1a000232
+       .word   0xe3c06103
+       .word   0xe2000102
+       .word   0xe3a03016
+       .word   0xe31b0080
+       .word   0x13a03033
+       .word   0xe31b0702
+       .word   0x13a0303e
+       .word   0xe3833901
+       .word   0xe0538006
+       .word   0x9a000014
+       .word   0xe1a092a8
+       .word   0xe1c88289
+       .word   0xe3590002
+       .word   0x33390000
+       .word   0xe2689020
+       .word   0xe1a06912
+       .word   0xe1a02832
+       .word   0xe1822911
+       .word   0xe1a01831
+       .word   0x0a000003
+       .word   0x11866106
+       .word   0x11826126
+       .word   0x11a02001
+       .word   0x13a01000
+       .word   0x3a000004
+       .word   0x21866002
+       .word   0x21866106
+       .word   0x21816126
+       .word   0x23a02000
+       .word   0x23a01000
+       .word   0xe1a0f00e
+       .word   0xe1a03006
+       .word   0xe3a06000
+       .word   0xe1a0f00e
+       .word   0xe3100101
+       .word   0x1a000219
+       .word   0xe3c03103
+       .word   0xe2000102
+       .word   0xe3110102
+       .word   0x0a000049
+       .word   0x13a0603e
+       .word   0xe3866901
+       .word   0xe0568003
+       .word   0xda000045
+       .word   0xe2789020
+       .word   0xba000017
+       .word   0xe1b08912
+       .word   0x0a000041
+       .word   0xe1b08080
+       .word   0x231b0020
+       .word   0x331b0040
+       .word   0x1a000007
+       .word   0xe31b0060
+       .word   0x1a00000a
+       .word   0xe2898001
+       .word   0xe1b08812
+       .word   0x1a000001
+       .word   0xe1b080a1
+       .word   0xe1b08912
+       .word   0x2a000004
+       .word   0xe2699020
+       .word   0xe1a02932
+       .word   0xe1a02912
+       .word   0xe3a06101
+       .word   0xe1a0f00e
+       .word   0xe2699020
+       .word   0xe1e02932
+       .word   0xe1e02912
+       .word   0xe3a06103
+       .word   0xe1a0f00e
+       .word   0xe2789040
+       .word   0xba00001a
+       .word   0xe1928911
+       .word   0x0a000027
+       .word   0xe1b08080
+       .word   0x231b0020
+       .word   0x331b0040
+       .word   0x1a000007
+       .word   0xe31b0060
+       .word   0x1a00000c
+       .word   0xe2898001
+       .word   0xe1928811
+       .word   0x1a000001
+       .word   0xe3590001
+       .word   0x21b08911
+       .word   0x2a000006
+       .word   0xe2699020
+       .word   0xe1a01931
+       .word   0xe1b01911
+       .word   0xe3a02000
+       .word   0x03a03000
+       .word   0xe3a06101
+       .word   0xe1a0f00e
+       .word   0xe2699020
+       .word   0xe1e01931
+       .word   0xe1e01911
+       .word   0xe3e02000
+       .word   0xe3a06103
+       .word   0xe1a0f00e
+       .word   0xe0208d0b
+       .word   0xe0209c8b
+       .word   0xe1d88009
+       .word   0x4a000004
+       .word   0xe3a01000
+       .word   0xe3a02000
+       .word   0xe3a03000
+       .word   0xe3a06101
+       .word   0xe1a0f00e
+       .word   0xe3e01000
+       .word   0xe3e02000
+       .word   0xe3a03c3f
+       .word   0xe38330fe
+       .word   0xe3a06103
+       .word   0xe1a0f00e
+       .word   0xe3a06000
+       .word   0xe1a0f00e
+       .word   0xe3100101
+       .word   0x03130101
+       .word   0x1a0001d7
+       .word   0xe31b0602
+       .word   0x02233102
+       .word   0xe1a08880
+       .word   0xe1580883
+       .word   0x01510004
+       .word   0x01520005
+       .word   0x0a000004
+       .word   0x23300000
+       .word   0x33330000
+       .word   0x53a06202
+       .word   0x43a06102
+       .word   0xe1a0f00e
+       .word   0xe0309003
+       .word   0xe3a06206
+       .word   0x41a0f00e
+       .word   0xe1888001
+       .word   0xe1988002
+       .word   0x01a0f00e
+       .word   0xe3100102
+       .word   0x03a06202
+       .word   0x13a06102
+       .word   0xe1a0f00e
+       .word   0xe3100101
+       .word   0x1a0001f9
+       .word   0xe3c06103
+       .word   0xe2000102
+       .word   0xe92d4000
+       .word   0xe3a03901
+       .word   0xe383303e
+       .word   0xe0538006
+       .word   0x9a000023
+       .word   0xe1a092a8
+       .word   0xe1c88289
+       .word   0xe3590002
+       .word   0x33390000
+       .word   0xe2689020
+       .word   0xe1a06912
+       .word   0xe1a02832
+       .word   0xe1822911
+       .word   0xe1a01831
+       .word   0x0a000003
+       .word   0x11866106
+       .word   0x11826126
+       .word   0x11a02001
+       .word   0x13a01000
+       .word   0x3a000004
+       .word   0x21866002
+       .word   0x21866106
+       .word   0x21816126
+       .word   0x23a02000
+       .word   0x23a01000
+       .word   0xe20b5060
+       .word   0xe3855c01
+       .word   0xe3a04000
+       .word   0xebfff86d
+       .word   0xe1b08080
+       .word   0x21e01001
+       .word   0x22722000
+       .word   0x22811001
+       .word   0xe1310fc2
+       .word   0x1a000005
+       .word   0xe1a06002
+       .word   0xe3540000
+       .word   0x11b08aa7
+       .word   0x33877010
+       .word   0x8bfff9fe
+       .word   0xe8bd8000
+       .word   0xe8bd4000
+       .word   0xe3e06102
+       .word   0xe0266fc0
+       .word   0xe3a0800e
+       .word   0xeafffb03
+       .word   0xe1a09883
+       .word   0xe3790802
+       .word   0x30099004
+       .word   0xe0199083
+       .word   0xe1a08880
+       .word   0xe3780802
+       .word   0x30088001
+       .word   0xe0188080
+       .word   0x4a000014
+       .word   0xe3190102
+       .word   0x1a000022
+       .word   0xe92d4000
+       .word   0xe0116080
+       .word   0x43c11102
+       .word   0x42800001
+       .word   0xe0146083
+       .word   0x43c44102
+       .word   0x42833001
+       .word   0xe3100101
+       .word   0x11b06880
+       .word   0x1bfffb5d
+       .word   0xe3130101
+       .word   0x11b06883
+       .word   0x1bfffb94
+       .word   0xebfffc24
+       .word   0xe3110102
+       .word   0x18bd8000
+       .word   0xe191e002
+       .word   0x1bfffbd2
+       .word   0xe8bd8000
+       .word   0xe3190102
+       .word   0x0a000009
+       .word   0xe1828081
+       .word   0xe1888005
+       .word   0xe1988084
+       .word   0x1afffa1f
+       .word   0xe023850b
+       .word   0xe0388000
+       .word   0x52008102
+       .word   0x5a00000a
+       .word   0xe3a08004
+       .word   0xeafffabf
+       .word   0xe1928081
+       .word   0x1afffa35
+       .word   0xe2008102
+       .word   0xea000004
+       .word   0xe1958084
+       .word   0x1afffa1b
+       .word   0xe2038102
+       .word   0xe31b0602
+       .word   0x12288102
+       .word   0xe31b0601
+       .word   0x12288102
+       .word   0xe28f0fe6
+       .word   0xe8900007
+       .word   0xe1800008
+       .word   0xe1a0f00e
+       .word   0xe1a09883
+       .word   0xe3790802
+       .word   0x30099004
+       .word   0xe0199083
+       .word   0xe1a08880
+       .word   0xe3780802
+       .word   0x30088001
+       .word   0xe0188080
+       .word   0x4a00001f
+       .word   0xe3190102
+       .word   0x1a00002f
+       .word   0xe1918002
+       .word   0x11948005
+       .word   0x0a000013
+       .word   0xe0116080
+       .word   0x43c11102
+       .word   0x42800001
+       .word   0xe0146083
+       .word   0x43c44102
+       .word   0x42833001
+       .word   0xe3c08103
+       .word   0xe3c39103
+       .word   0xe0200003
+       .word   0xe2000102
+       .word   0xe0883009
+       .word   0xe2433c3f
+       .word   0xe24330fe
+       .word   0xe92d4000
+       .word   0xe3110102
+       .word   0x0bfffb98
+       .word   0xe3140102
+       .word   0x0bfffbaf
+       .word   0xe8bd4000
+       .word   0xeafffc50
+       .word   0xe0200003
+       .word   0xe2000102
+       .word   0xe3a01000
+       .word   0xe3a02000
+       .word   0xe3a03000
+       .word   0xe3a06000
+       .word   0xe1a0f00e
+       .word   0xe3190102
+       .word   0x0a000009
+       .word   0xe1828081
+       .word   0xe1888005
+       .word   0xe1988084
+       .word   0x1afff9db
+       .word   0xe0208003
+       .word   0xe2088102
+       .word   0xe28f0fb1
+       .word   0xe8900007
+       .word   0xe1800008
+       .word   0xe1a0f00e
+       .word   0xe1928081
+       .word   0x1afff9f1
+       .word   0xe1948005
+       .word   0x1afffff5
+       .word   0xe3a08005
+       .word   0xeafffa75
+       .word   0xe1958084
+       .word   0x1afff9d5
+       .word   0xe1918002
+       .word   0x1affffef
+       .word   0xe3a08006
+       .word   0xeafffa6f
+       .word   0xe1a09883
+       .word   0xe3790802
+       .word   0x30099004
+       .word   0xe0199083
+       .word   0xe1a08880
+       .word   0xe3780802
+       .word   0x30088001
+       .word   0xe0188080
+       .word   0x4a000036
+       .word   0xe3190102
+       .word   0x1a000048
+       .word   0xe1918002
+       .word   0x11948005
+       .word   0x0a00001e
+       .word   0xe31b0601
+       .word   0x1a000008
+       .word   0xe1a08000
+       .word   0xe1a00003
+       .word   0xe1a03008
+       .word   0xe1a08001
+       .word   0xe1a01004
+       .word   0xe1a04008
+       .word   0xe1a08002
+       .word   0xe1a02005
+       .word   0xe1a05008
+       .word   0xe0116080
+       .word   0x43c11102
+       .word   0x42800001
+       .word   0xe0146083
+       .word   0x43c44102
+       .word   0x42833001
+       .word   0xe3c08103
+       .word   0xe3c39103
+       .word   0xe0200003
+       .word   0xe2000102
+       .word   0xe0493008
+       .word   0xe2833c3f
+       .word   0xe28330ff
+       .word   0xe92d4000
+       .word   0xe3110102
+       .word   0x0bfffb7e
+       .word   0xe3140102
+       .word   0x0bfffb63
+       .word   0xe8bd4000
+       .word   0xeafffcaf
+       .word   0xe3a08007
+       .word   0xe31b0601
+       .word   0x1a00000a
+       .word   0xe1919002
+       .word   0x1afffaa5
+       .word   0xe1949005
+       .word   0x0afffa3b
+       .word   0xe0200003
+       .word   0xe2000102
+       .word   0xe3a01000
+       .word   0xe3a02000
+       .word   0xe3a03000
+       .word   0xe3a06000
+       .word   0xe1a0f00e
+       .word   0xe1919002
+       .word   0x1afffff6
+       .word   0xe1949005
+       .word   0x1afffa98
+       .word   0xeafffa2f
+       .word   0xe3190102
+       .word   0x0a000005
+       .word   0xe1828081
+       .word   0xe1888005
+       .word   0xe1988084
+       .word   0x1afff983
+       .word   0xe3a08008
+       .word   0xeafffa27
+       .word   0xe1928081
+       .word   0x1afff99d
+       .word   0xe0208003
+       .word   0xe2088102
+       .word   0xe31b0601
+       .word   0x028f0e15
+       .word   0x128f0d05
+       .word   0xe8900007
+       .word   0xe1800008
+       .word   0xe3a03000
+       .word   0xe3a06000
+       .word   0xe1a0f00e
+       .word   0xe1958084
+       .word   0x1afff97b
+       .word   0xe0208003
+       .word   0xe2088102
+       .word   0xe31b0601
+       .word   0x128f0e12
+       .word   0x028f0e11
+       .word   0xe8900007
+       .word   0xe1800008
+       .word   0xe3a03000
+       .word   0xe3a06000
+       .word   0xe1a0f00e
+       .word   0xe1a09883
+       .word   0xe3790802
+       .word   0x30099004
+       .word   0xe0199083
+       .word   0xe1a08880
+       .word   0xe3780802
+       .word   0x30088001
+       .word   0xe0188080
+       .word   0x4a000017
+       .word   0xe3190102
+       .word   0x1a000021
+       .word   0xe1948005
+       .word   0x03a0800a
+       .word   0x0afffa01
+       .word   0xe1916002
+       .word   0x0a00002c
+       .word   0xe0116080
+       .word   0x43c11102
+       .word   0x42800001
+       .word   0xe0146083
+       .word   0x43c44102
+       .word   0x42833001
+       .word   0xe92d4000
+       .word   0xe3c33103
+       .word   0xe3140102
+       .word   0x0bfffb14
+       .word   0xe2439001
+       .word   0xe3c03103
+       .word   0xe3140102
+       .word   0x0bfffaf7
+       .word   0xe0536009
+       .word   0xe1a03009
+       .word   0xeafffd88
+       .word   0xe3190102
+       .word   0x0a000005
+       .word   0xe1828081
+       .word   0xe1888005
+       .word   0xe1988084
+       .word   0x1afff942
+       .word   0xe3a08009
+       .word   0xeafff9e6
+       .word   0xe1928081
+       .word   0x1afff95c
+       .word   0xe3a08009
+       .word   0xeafff9e2
+       .word   0xe1958084
+       .word   0x1afff942
+       .word   0xe3100101
+       .word   0x03c03103
+       .word   0x02000102
+       .word   0x03a06000
+       .word   0x01a0f00e
+       .word   0xe1916002
+       .word   0x0a000006
+       .word   0xe3c03103
+       .word   0xe2000102
+       .word   0xe3110102
+       .word   0x13c11102
+       .word   0x12833001
+       .word   0xe3a06000
+       .word   0xeafffad8
+       .word   0xe2000102
+       .word   0xe3a03000
+       .word   0xe1a0f00e
+       .word   0x00000000
+       .word   0x00000000
+       .word   0x00000000
+       .word   0x40007fff
+       .word   0x00000000
+       .word   0x00000000
+       .word   0xe1a08880
+       .word   0xe3780802
+       .word   0x30088001
+       .word   0xe0188080
+       .word   0x4a000013
+       .word   0xe1918002
+       .word   0x02000102
+       .word   0x0a00000d
+       .word   0xe3c03103
+       .word   0xe2100102
+       .word   0x13a0800b
+       .word   0x1afff95b
+       .word   0xe92d4000
+       .word   0xe3110102
+       .word   0x13c11102
+       .word   0x12833001
+       .word   0xebfffabe
+       .word   0xe2833c3f
+       .word   0xe28330ff
+       .word   0xe1b030a3
+       .word   0xe8bd4000
+       .word   0xeafffd72
+       .word   0xe3a03000
+       .word   0xe3a06000
+       .word   0xe1a0f00e
+       .word   0xe1928081
+       .word   0x1afff921
+       .word   0xe3100102
+       .word   0x13a0800b
+       .word   0x1afff949
+       .word   0xe24f008c
+       .word   0xe8900007
+       .word   0xe1a0f00e
+       .word   0xe1a08880
+       .word   0xe3780802
+       .word   0x30088001
+       .word   0xe0188080
+       .word   0x4a00000a
+       .word   0xe1918002
+       .word   0x03a03000
+       .word   0x0afffddd
+       .word   0xe3c03103
+       .word   0xe92d4000
+       .word   0xe0116080
+       .word   0x43c11102
+       .word   0x42833001
+       .word   0xebfffaa0
+       .word   0xe8bd4000
+       .word   0xeafffdd5
+       .word   0xe1928081
+       .word   0x1a000008
+       .word   0xe2008102
+       .word   0xe31b0601
+       .word   0x12288102
+       .word   0xe31b0602
+       .word   0x13c88102
+       .word   0xe24f00f4
+       .word   0xe8900007
+       .word   0xe1800008
+       .word   0xe1a0f00e
+       .word   0xe92d4000
+       .word   0xebfff8d2
+       .word   0xe3360000
+       .word   0x4a000001
+       .word   0xebfff8fa
+       .word   0x18bd8000
+       .word   0xe31b0601
+       .word   0x12200102
+       .word   0xe31b0602
+       .word   0x13c00102
+       .word   0xe8bd8000
+       .word   0xe1a08880
+       .word   0xe3780802
+       .word   0x30088001
+       .word   0xe0188080
+       .word   0x53c03103
+       .word   0x5afffdc5
+       .word   0xe1928081
+       .word   0x1afff8ed
+       .word   0xe2008102
+       .word   0xe24f0f55
+       .word   0xe8900007
+       .word   0xe1800008
+       .word   0xe1a0f00e
+       .word   0xe1a08880
+       .word   0xe3780802
+       .word   0x30088001
+       .word   0xe0188080
+       .word   0x4afffff3
+       .word   0xe3c06103
+       .word   0xe2000102
+       .word   0xe3110102
+       .word   0x13c11102
+       .word   0x12866001
+       .word   0xeafffdc3
+       .word   0xe1a08880
+       .word   0xe3780802
+       .word   0x30088001
+       .word   0xe0188080
+       .word   0x4affffe8
+       .word   0xe1913002
+       .word   0x02000102
+       .word   0x0afffe2b
+       .word   0xe3c03103
+       .word   0xe2000102
+       .word   0xe92d4000
+       .word   0xe3110102
+       .word   0x13c11102
+       .word   0x12833001
+       .word   0xebfffa61
+       .word   0xe8bd4000
+       .word   0xeafffdd8
+       .word   0xe1a08880
+       .word   0xe3780802
+       .word   0x30088001
+       .word   0xe0188080
+       .word   0xe1a09883
+       .word   0xe3790802
+       .word   0x30099004
+       .word   0xe0199083
+       .word   0xe3180102
+       .word   0x11926081
+       .word   0x1a00001b
+       .word   0xe3190102
+       .word   0x11956084
+       .word   0x1a000018
+       .word   0xe92d4000
+       .word   0xe3180102
+       .word   0x12000102
+       .word   0x138000ff
+       .word   0x13800c7f
+       .word   0x13c11102
+       .word   0xe3190102
+       .word   0x12033102
+       .word   0x138330ff
+       .word   0x13833c7f
+       .word   0x13c44102
+       .word   0xe0116080
+       .word   0x43c11102
+       .word   0x42800001
+       .word   0xe0146083
+       .word   0x43c44102
+       .word   0x42833001
+       .word   0xe3100101
+       .word   0x11b06880
+       .word   0x1bfff9c0
+       .word   0xe3130101
+       .word   0x11b06883
+       .word   0x1bfff9f7
+       .word   0xe8bd4000
+       .word   0xeafffe00
+       .word   0xe3170a01
+       .word   0x03a06201
+       .word   0x13a06203
+       .word   0xe3180102
+       .word   0x11928081
+       .word   0x0a000004
+       .word   0xe2118101
+       .word   0x0afff950
+       .word   0xe3190102
+       .word   0x11958084
+       .word   0x0a000001
+       .word   0xe2148101
+       .word   0x0afff94b
+       .word   0xe31b0501
+       .word   0x01a0f00e
+       .word   0xe3a0800f
+       .word   0xeafff947
+       .word   0xe3100101
+       .word   0x0afffe05
+       .word   0xe1a08880
+       .word   0xe3780802
+       .word   0x30088001
+       .word   0xe0188080
+       .word   0x4a000005
+       .word   0xe3c06103
+       .word   0xe2000102
+       .word   0xe3110102
+       .word   0x13c11102
+       .word   0x12866001
+       .word   0xeafffdfc
+       .word   0xe3110101
+       .word   0x03a08000
+       .word   0x13a0800c
+       .word   0xe1926081
+       .word   0x03a0800d
+       .word   0xe3a06102
+       .word   0xeafff927
+       .word   0xedd8a200
+       .word   0xee181102
+       .word   0xee106111
+       .word   0xee308110
+       .word   0xe3180005
+       .word   0x0e016110
+       .word   0x0e192103
+       .word   0x0e280102
+       .word   0x0e192104
+       .word   0x0e280102
+       .word   0xe1a0f009
+       .word   0xecb8a203
+       .word   0xe2466001
+       .word   0xecb8b203
+       .word   0xee1a2101
+       .word   0xee0a2103
+       .word   0xe2566001
+       .word   0x1afffffa
+       .word   0xee1a2101
+       .word   0xe1a0f009
+       .word   0xecb8b203
+       .word   0xee094103
+       .word   0xe2566001
+       .word   0x01a0f009
+       .word   0xecb8b203
+       .word   0xee1c4101
+       .word   0xee0c4103
+       .word   0xe2566001
+       .word   0x1afffffa
+       .word   0xe1a0f009
+       .word   0xee08a109
+       .word   0xee108111
+       .word   0xe0389048
+       .word   0xe2a99000
+       .word   0xe3a06902
+       .word   0xe1190006
+       .word   0x01a060a6
+       .word   0x0afffffc
+       .word   0xe3580000
+       .word   0xba00000e
+       .word   0xea000002
+       .word   0xee1a2102
+       .word   0xe1190086
+       .word   0x1e1a2100
+       .word   0xe1b060a6
+       .word   0x1afffffa
+       .word   0xee1a3102
+       .word   0xe3190001
+       .word   0x0e1a2162
+       .word   0x1e1b2160
+       .word   0x1e1b3100
+       .word   0xea000009
+       .word   0xee1a2102
+       .word   0xe1190086
+       .word   0x1e4a2100
+       .word   0xe1b060a6
+       .word   0x1afffffa
+       .word   0xee1a3102
+       .word   0xe3190001
+       .word   0x0e1a2162
+       .word   0x1e4b2160
+       .word   0x1e4b3100
+       .word   0xee308110
+       .word   0xe318000c
+       .word   0x1a0001b7
+       .word   0xee92f113
+       .word   0x03a06101
+       .word   0x13a06103
+       .word   0xe3180010
+       .word   0x03a06000
+       .word   0xee088102
+       .word   0xea00010c
+       .word   0x80003ffe
+       .word   0xca20ad9a
+       .word   0xb5e946e9
+       .word   0x00004003
+       .word   0x83125100
+       .word   0xb57f6509
+       .word   0x80004005
+       .word   0x803ff895
+       .word   0x9dacd228
+       .word   0x80004004
+       .word   0x8eac025b
+       .word   0x3e7076bb
+       .word   0x00004007
+       .word   0x9c041fd0
+       .word   0xa933ef60
+       .word   0x80004008
+       .word   0xc05ff4e0
+       .word   0x6c83bb96
+       .word   0x00003ffe
+       .word   0xb17217f7
+       .word   0xd1cf0000
+       .word   0x00003fcd
+       .word   0xf35793c0
+       .word   0x00000000
+       .word   0x00003ffe
+       .word   0xb504f333
+       .word   0xf9de6484
+       .word   0x00003ffd
+       .word   0xde5bd8a9
+       .word   0x37287195
+       .word   0xe3100101
+       .word   0x1a000079
+       .word   0xe1918002
+       .word   0x0afff8eb
+       .word   0xe3100102
+       .word   0x13a08018
+       .word   0x1afff83e
+       .word   0xe3c03103
+       .word   0xe3a00c3f
+       .word   0xe38000fe
+       .word   0xe0433000
+       .word   0xe92d4000
+       .word   0xe24dd04c
+       .word   0xe1a09407
+       .word   0xe389901f
+       .word   0xe58d9000
+       .word   0xe10f9000
+       .word   0xe3899080
+       .word   0xe129f009
+       .word   0xe1a00000
+       .word   0xe3c7981f
+       .word   0xe3c9901f
+       .word   0xee209110
+       .word   0xe28d9040
+       .word   0xed09020f
+       .word   0xed09c203
+       .word   0xe8890007
+       .word   0xed998200
+       .word   0xe31b0601
+       .word   0x0a000011
+       .word   0xe2838001
+       .word   0xe0889108
+       .word   0xe0689109
+       .word   0xe1a09349
+       .word   0xe359001c
+       .word   0x2a000010
+       .word   0xe24f8b0b
+       .word   0xe2488feb
+       .word   0xe0888209
+       .word   0xe8980130
+       .word   0xe1320008
+       .word   0x01310005
+       .word   0x00444003
+       .word   0x01300004
+       .word   0x1a000007
+       .word   0xe3a06000
+       .word   0xee019110
+       .word   0xea00003e
+       .word   0xe3530001
+       .word   0x0e90f11e
+       .word   0x03a06000
+       .word   0x0e089108
+       .word   0x0a000039
+       .word   0xed5f113d
+       .word   0xee90f111
+       .word   0xd2433001
+       .word   0xde28010e
+       .word   0xee18110e
+       .word   0xee09110e
+       .word   0xce280109
+       .word   0xee480101
+       .word   0xee181100
+       .word   0xe24f8f5e
+       .word   0xe3a06003
+       .word   0xe1a0900f
+       .word   0xeaffff62
+       .word   0xe24f8f59
+       .word   0xe3a06003
+       .word   0xe1a0900f
+       .word   0xeaffff67
+       .word   0xee4a2104
+       .word   0xee1a1100
+       .word   0xee091100
+       .word   0xe3330000
+       .word   0x1a000008
+       .word   0xe31b0601
+       .word   0x1a000017
+       .word   0xee1a2160
+       .word   0xee0a0160
+       .word   0xee91f110
+       .word   0x03a06101
+       .word   0x13a06103
+       .word   0x1e089100
+       .word   0xea00001a
+       .word   0xee083110
+       .word   0xed5f2263
+       .word   0xee1a2100
+       .word   0xee1b3100
+       .word   0xee090102
+       .word   0xee282102
+       .word   0xee2a2101
+       .word   0xee0a2103
+       .word   0xee081102
+       .word   0xe31b0601
+       .word   0x1a000005
+       .word   0xee080162
+       .word   0xee91f110
+       .word   0x03a06101
+       .word   0x13a06103
+       .word   0x1e089100
+       .word   0xea000009
+       .word   0xee08a101
+       .word   0xed5f016b
+       .word   0xee181162
+       .word   0xe3a06101
+       .word   0xe31b00e0
+       .word   0x1a000003
+       .word   0xe31b0702
+       .word   0x1e180102
+       .word   0x1e90f111
+       .word   0x13a06103
+       .word   0xe28d9040
+       .word   0xed899200
+       .word   0xe8990007
+       .word   0xed19020f
+       .word   0xed19c203
+       .word   0xe28dd04c
+       .word   0xe10f9000
+       .word   0xe3c99080
+       .word   0xe129f009
+       .word   0xe1a00000
+       .word   0xe3c03103
+       .word   0xe2000102
+       .word   0xe8bd8000
+       .word   0xe1a08880
+       .word   0xe3780802
+       .word   0x30088001
+       .word   0xe0188080
+       .word   0x4a00000c
+       .word   0xe1918002
+       .word   0x0afff86c
+       .word   0xe3c03103
+       .word   0xe3100102
+       .word   0x13a08018
+       .word   0x1afff7be
+       .word   0xe92d4000
+       .word   0xe3110102
+       .word   0x13c11102
+       .word   0x12833001
+       .word   0xebfff921
+       .word   0xe8bd4000
+       .word   0xeaffff79
+       .word   0xe1928081
+       .word   0x1afff78a
+       .word   0xe3100102
+       .word   0x13a08018
+       .word   0x1afff7b2
+       .word   0xe24f0b01
+       .word   0xe2400fba
+       .word   0xe8900007
+       .word   0xe1a0f00e
+       .word   0x00003fff
+       .word   0xb8aa3b29
+       .word   0x5c17f0bc
+       .word   0x00003ffe
+       .word   0xb1800000
+       .word   0x00000000
+       .word   0x80003ff2
+       .word   0xde8082e3
+       .word   0x08654362
+       .word   0x00003ff1
+       .word   0x845a2157
+       .word   0x3490f106
+       .word   0x00003ff8
+       .word   0xf83a5f91
+       .word   0x50952c99
+       .word   0x00003feb
+       .word   0xc99b1867
+       .word   0x2822a93e
+       .word   0x00003ff5
+       .word   0xa57862e1
+       .word   0x46a6fb39
+       .word   0x00003ffb
+       .word   0xe8b9428e
+       .word   0xfecff592
+       .word   0x00003fbd
+       .word   0x80000000
+       .word   0x00000000
+       .word   0x00003ffd
+       .word   0xffffffff
+       .word   0xffffffff
+       .word   0xe3100101
+       .word   0x1a00005f
+       .word   0xe1916002
+       .word   0x0a00005a
+       .word   0xe1a05000
+       .word   0xe92d4000
+       .word   0xe24dd04c
+       .word   0xe1a09407
+       .word   0xe389901f
+       .word   0xe58d9000
+       .word   0xe10f9000
+       .word   0xe3899080
+       .word   0xe129f009
+       .word   0xe1a00000
+       .word   0xe3c7981f
+       .word   0xe3c9901f
+       .word   0xee209110
+       .word   0xe28d9040
+       .word   0xed09020f
+       .word   0xed09c203
+       .word   0xe8890007
+       .word   0xed998200
+       .word   0xe3a04000
+       .word   0xe24f80dc
+       .word   0xe1a0900f
+       .word   0xeafffeca
+       .word   0x02868801
+       .word   0x01b088a8
+       .word   0x1a000030
+       .word   0xe2866001
+       .word   0xe1844086
+       .word   0xed5f1127
+       .word   0xee28a100
+       .word   0xee92f111
+       .word   0xba000024
+       .word   0xee181100
+       .word   0xe24f80d4
+       .word   0xe3a06003
+       .word   0xe1a0900f
+       .word   0xeafffec7
+       .word   0xee0a4109
+       .word   0xe24f8c01
+       .word   0xe3a06002
+       .word   0xe1a0900f
+       .word   0xeafffec2
+       .word   0xee0a210e
+       .word   0xee1a2100
+       .word   0xee2c4102
+       .word   0xee4a1104
+       .word   0xee09016e
+       .word   0xe3a06101
+       .word   0xe31b00e0
+       .word   0x1a000004
+       .word   0xe31b0702
+       .word   0x0a000002
+       .word   0xee09110e
+       .word   0xee90f111
+       .word   0x13a06103
+       .word   0xe28d9040
+       .word   0xed898200
+       .word   0xe8990007
+       .word   0xed19020f
+       .word   0xed19c203
+       .word   0xe28dd04c
+       .word   0xe10f9000
+       .word   0xe3c99080
+       .word   0xe129f009
+       .word   0xe1a00000
+       .word   0xe3c03103
+       .word   0xe08330c4
+       .word   0xe1a00f84
+       .word   0xe8bd8000
+       .word   0xee90f118
+       .word   0xae08810e
+       .word   0xa3a06101
+       .word   0xbd5f0150
+       .word   0xb3a06103
+       .word   0xeaffffeb
+       .word   0xe28d9040
+       .word   0xed19020f
+       .word   0xed19c203
+       .word   0xe28dd04c
+       .word   0xe10f9000
+       .word   0xe3c99080
+       .word   0xe129f009
+       .word   0xe1a00000
+       .word   0xe28f0b01
+       .word   0xe2800f05
+       .word   0xe8900007
+       .word   0xe1800f84
+       .word   0xe3a03601
+       .word   0xe3150102
+       .word   0x12633000
+       .word   0xe3a06101
+       .word   0xe8bd8000
+       .word   0xe28f0e3f
+       .word   0xe890000f
+       .word   0xe1a0f00e
+       .word   0xe1a08880
+       .word   0xe3780802
+       .word   0x30088001
+       .word   0xe0188080
+       .word   0x5affff9a
+       .word   0xe1928081
+       .word   0x1afff6fc
+       .word   0xe3a04000
+       .word   0xe3100102
+       .word   0x024f0b02
+       .word   0x02400f47
+       .word   0x08900007
+       .word   0x13a00000
+       .word   0x13a01000
+       .word   0x13a03000
+       .word   0x13a06000
+       .word   0xe1800f84
+       .word   0xe1a0f00e
+       .word   0xe92d4000
+       .word   0xe24dd04c
+       .word   0xe1a09407
+       .word   0xe389901f
+       .word   0xe58d9000
+       .word   0xe10f9000
+       .word   0xe3899080
+       .word   0xe129f009
+       .word   0xe1a00000
+       .word   0xe3c7981f
+       .word   0xe3c9901f
+       .word   0xee209110
+       .word   0xe28d9040
+       .word   0xed09020f
+       .word   0xed09c203
+       .word   0xe31b0601
+       .word   0xe8890007
+       .word   0x0d998200
+       .word   0x1d999200
+       .word   0xe8890038
+       .word   0x0d999200
+       .word   0x1d998200
+       .word   0xe3100101
+       .word   0x03130101
+       .word   0x1a000096
+       .word   0xeee8a101
+       .word   0xeef8a102
+       .word   0xee91f112
+       .word   0x1a000044
+       .word   0xe31b0601
+       .word   0x01a08fa0
+       .word   0x11a08fa3
+       .word   0xe3180001
+       .word   0x1e19210e
+       .word   0x1ee8b102
+       .word   0x1ef8b103
+       .word   0x1e92f113
+       .word   0x03a08000
+       .word   0xee91f118
+       .word   0xca000002
+       .word   0x0a000069
+       .word   0xee90f118
+       .word   0x0a000026
+       .word   0xee90f118
+       .word   0xbe188100
+       .word   0x0a000015
+       .word   0xee90f119
+       .word   0x0a000006
+       .word   0xe1a04008
+       .word   0xe28f9fbd
+       .word   0xedd92100
+       .word   0xee92f111
+       .word   0xceb2f111
+       .word   0xcafffe58
+       .word   0xea000032
+       .word   0xe28d9040
+       .word   0xed19020f
+       .word   0xed19c203
+       .word   0xe28dd04c
+       .word   0xe10f9000
+       .word   0xe3c99080
+       .word   0xe129f009
+       .word   0xe1a00000
+       .word   0xe28f0e2a
+       .word   0xe890000f
+       .word   0xe1800f88
+       .word   0xe3a06000
+       .word   0xe8bd8000
+       .word   0xe28d9040
+       .word   0xed19020f
+       .word   0xed19c203
+       .word   0xe28dd04c
+       .word   0xe10f9000
+       .word   0xe3c99080
+       .word   0xe129f009
+       .word   0xe1a00000
+       .word   0xe1a00f88
+       .word   0xe3a01000
+       .word   0xe3a02000
+       .word   0xe3a03000
+       .word   0xe3a06000
+       .word   0xe8bd8000
+       .word   0xe28d9040
+       .word   0xed19020f
+       .word   0xed19c203
+       .word   0xe28dd04c
+       .word   0xe10f9000
+       .word   0xe3c99080
+       .word   0xe129f009
+       .word   0xe1a00000
+       .word   0xe3170802
+       .word   0x1afff793
+       .word   0xe3877002
+       .word   0xe24f0b02
+       .word   0xe2400fad
+       .word   0xe8900007
+       .word   0xe1800f88
+       .word   0xe8bd8000
+       .word   0xee90f118
+       .word   0xb3a08019
+       .word   0xba000107
+       .word   0x0a000038
+       .word   0xee90f119
+       .word   0x1e91f118
+       .word   0x0a000021
+       .word   0xe3a04000
+       .word   0xee688100
+       .word   0xee180101
+       .word   0xe28d8040
+       .word   0xed888200
+       .word   0xe5985000
+       .word   0xee309110
+       .word   0xe3190004
+       .word   0x1affff67
+       .word   0xee90f118
+       .word   0x0a000010
+       .word   0xe24f8b02
+       .word   0xe2488e31
+       .word   0xedd81100
+       .word   0xee90f111
+       .word   0x1eb0f111
+       .word   0x1affff28
+       .word   0xe28d9040
+       .word   0xed19020f
+       .word   0xed19c203
+       .word   0xe28dd04c
+       .word   0xe10f9000
+       .word   0xe3c99080
+       .word   0xe129f009
+       .word   0xe1a00000
+       .word   0xe8bd4000
+       .word   0xe1a00005
+       .word   0xeaffff70
+       .word   0xe3150102
+       .word   0x0e088109
+       .word   0x03a06101
+       .word   0x1ddf0163
+       .word   0x13a06103
+       .word   0xeaffff3a
+       .word   0xe24f8b02
+       .word   0xe2488fdb
+       .word   0xedd82100
+       .word   0xee90f112
+       .word   0x1e91f112
+       .word   0x1eb1f112
+       .word   0x03a0801b
+       .word   0x0a0000d9
+       .word   0xe28d9040
+       .word   0xed19020f
+       .word   0xed19c203
+       .word   0xe28dd04c
+       .word   0xe10f9000
+       .word   0xe3c99080
+       .word   0xe129f009
+       .word   0xe1a00000
+       .word   0xe28f0e13
+       .word   0xe890000f
+       .word   0xe3a06000
+       .word   0xe8bd8000
+       .word   0xee91f118
+       .word   0xd3a0801a
+       .word   0xda0000ca
+       .word   0xe28d9040
+       .word   0xed898200
+       .word   0xe8990007
+       .word   0xed19020f
+       .word   0xed19c203
+       .word   0xe28dd04c
+       .word   0xe10f9000
+       .word   0xe3c99080
+       .word   0xe129f009
+       .word   0xe1a00000
+       .word   0xe2000102
+       .word   0xe3a03000
+       .word   0xe3a06000
+       .word   0xe8bd8000
+       .word   0xe1a09883
+       .word   0xe3790802
+       .word   0x30099004
+       .word   0xe0199083
+       .word   0xe1a08880
+       .word   0xe3780802
+       .word   0x30088001
+       .word   0xe0188080
+       .word   0x4a000010
+       .word   0xe3190102
+       .word   0x0affff5d
+       .word   0xe1958084
+       .word   0x1a000002
+       .word   0xe31b0601
+       .word   0x0affffa2
+       .word   0xeaffff58
+       .word   0xe28d9040
+       .word   0xed19020f
+       .word   0xed19c203
+       .word   0xe28dd04c
+       .word   0xe10f9000
+       .word   0xe3c99080
+       .word   0xe129f009
+       .word   0xe1a00000
+       .word   0xe8bd4000
+       .word   0xeafff616
+       .word   0xe3190102
+       .word   0x0a00000d
+       .word   0xe1828081
+       .word   0xe1888005
+       .word   0xe1988084
+       .word   0x0affff91
+       .word   0xe28d9040
+       .word   0xed19020f
+       .word   0xed19c203
+       .word   0xe28dd04c
+       .word   0xe10f9000
+       .word   0xe3c99080
+       .word   0xe129f009
+       .word   0xe1a00000
+       .word   0xe8bd4000
+       .word   0xeafff5fe
+       .word   0xe1928081
+       .word   0x1a000002
+       .word   0xe31b0601
+       .word   0x1affff83
+       .word   0xeaffff39
+       .word   0xe28d9040
+       .word   0xed19020f
+       .word   0xed19c203
+       .word   0xe28dd04c
+       .word   0xe10f9000
+       .word   0xe3c99080
+       .word   0xe129f009
+       .word   0xe1a00000
+       .word   0xe8bd4000
+       .word   0xeafff60d
+       .word   0x00000000
+       .word   0x80000000
+       .word   0x00000000
+       .word   0x00003fff
+       .word   0x00003ffe
+       .word   0xffffffff
+       .word   0xffffffff
+       .word   0x0000400f
+       .word   0x80000000
+       .word   0x00000000
+       .word   0x00003ffd
+       .word   0xa2f9836e
+       .word   0x4e44152a
+       .word   0x00004000
+       .word   0xc9100000
+       .word   0x00000000
+       .word   0x80003fee
+       .word   0x95777a5c
+       .word   0xf72cece6
+       .word   0x00003fce
+       .word   0xc407fb4c
+       .word   0x9efca5fe
+       .word   0x80003fd6
+       .word   0xd72106e0
+       .word   0x424cdf56
+       .word   0x00003fde
+       .word   0xb091e343
+       .word   0x56a17fa8
+       .word   0x80003fe5
+       .word   0xd7322a5a
+       .word   0xee055b44
+       .word   0x00003fec
+       .word   0xb8ef1d29
+       .word   0x27831824
+       .word   0x80003ff2
+       .word   0xd00d00d0
+       .word   0x09f0d114
+       .word   0x00003ff8
+       .word   0x88888888
+       .word   0x88858061
+       .word   0x80003ffc
+       .word   0xaaaaaaaa
+       .word   0xaaaaa603
+       .word   0xe3100101
+       .word   0x1a00004d
+       .word   0xe1916002
+       .word   0x0a000043
+       .word   0xe92d4000
+       .word   0xe24dd04c
+       .word   0xe1a09407
+       .word   0xe389901f
+       .word   0xe58d9000
+       .word   0xe10f9000
+       .word   0xe3899080
+       .word   0xe129f009
+       .word   0xe1a00000
+       .word   0xe3c7981f
+       .word   0xe3c9901f
+       .word   0xee209110
+       .word   0xe28d9040
+       .word   0xed09020f
+       .word   0xed09c203
+       .word   0xe8890007
+       .word   0xed998200
+       .word   0xee90f118
+       .word   0xe0a44004
+       .word   0xbe188100
+       .word   0xe31b0601
+       .word   0x1ddf1172
+       .word   0x1e080101
+       .word   0x13a04001
+       .word   0xe24f80fc
+       .word   0xe1a0900f
+       .word   0xeafffd3d
+       .word   0x13a08010
+       .word   0x1a000037
+       .word   0xe0244006
+       .word   0xee90f118
+       .word   0xbe188100
+       .word   0xa2244001
+       .word   0xeddf1169
+       .word   0xee90f111
+       .word   0xba00001b
+       .word   0xee181100
+       .word   0xe24f8f43
+       .word   0xe3a06008
+       .word   0xe1a0900f
+       .word   0xeafffd3a
+       .word   0xee1a1140
+       .word   0xee091140
+       .word   0xe3a06101
+       .word   0xe31b00e0
+       .word   0x1a000004
+       .word   0xe31b0702
+       .word   0x1e1a2100
+       .word   0x1e0a0100
+       .word   0x1e90f111
+       .word   0x13a06103
+       .word   0xe28d9040
+       .word   0xed899200
+       .word   0xe8990007
+       .word   0xed19020f
+       .word   0xed19c203
+       .word   0xe28dd04c
+       .word   0xe10f9000
+       .word   0xe3c99080
+       .word   0xe129f009
+       .word   0xe1a00000
+       .word   0xe1a03000
+       .word   0xe1a00f84
+       .word   0xe8bd8000
+       .word   0xed5f116d
+       .word   0xee181161
+       .word   0xe3a06103
+       .word   0xeaffffee
+       .word   0xe31b0601
+       .word   0x1a000002
+       .word   0xe2000102
+       .word   0xe3a03000
+       .word   0xe1a0f00e
+       .word   0xe24f0f7a
+       .word   0xe890000f
+       .word   0xe1a0f00e
+       .word   0xe1a08880
+       .word   0xe3780802
+       .word   0x30088001
+       .word   0xe0188080
+       .word   0x5affffac
+       .word   0xe1928081
+       .word   0x1afff586
+       .word   0xe3a08011
+       .word   0xeafff5af
+       .word   0xe28d9040
+       .word   0xed19020f
+       .word   0xed19c203
+       .word   0xe28dd04c
+       .word   0xe10f9000
+       .word   0xe3c99080
+       .word   0xe129f009
+       .word   0xe1a00000
+       .word   0xe8bd4000
+       .word   0xeafff5a5
+       .word   0x80003ffe
+       .word   0xb25dedaf
+       .word   0x30f3242c
+       .word   0x00004002
+       .word   0xa270bb27
+       .word   0x61c93957
+       .word   0x80004004
+       .word   0x9ec1654d
+       .word   0x36d4f820
+       .word   0x00004004
+       .word   0xe4d539b0
+       .word   0x56a451ad
+       .word   0x80004003
+       .word   0xdaf2ad41
+       .word   0xd05311c4
+       .word   0x80004003
+       .word   0xbe974377
+       .word   0xcc30f9e6
+       .word   0x00004006
+       .word   0x96f3e4b2
+       .word   0xc8e37cbc
+       .word   0x80004007
+       .word   0xbeee77e2
+       .word   0xb5423cf3
+       .word   0x00004007
+       .word   0xd0927880
+       .word   0xf5c2170b
+       .word   0x80004006
+       .word   0xa43601f1
+       .word   0x5c3e6196
+       .word   0x00003fff
+       .word   0xc90fdaa2
+       .word   0x2168c234
+       .word   0x00003fbf
+       .word   0xc4c68000
+       .word   0x00000000
+       .word   0x00004000
+       .word   0xc90fdaa2
+       .word   0x2168c234
+       .word   0x00003fc0
+       .word   0xc4c68000
+       .word   0x00000000
+       .word   0x00003fff
+       .word   0xc90fdaa2
+       .word   0x2168c235
+       .word   0x00003fdf
+       .word   0x80000000
+       .word   0x00000000
+       .word   0xe3100101
+       .word   0x1a000075
+       .word   0xe31b0501
+       .word   0x01916002
+       .word   0x0a00006f
+       .word   0xe92d4000
+       .word   0xe24dd04c
+       .word   0xe1a09407
+       .word   0xe389901f
+       .word   0xe58d9000
+       .word   0xe10f9000
+       .word   0xe3899080
+       .word   0xe129f009
+       .word   0xe1a00000
+       .word   0xe3c7981f
+       .word   0xe3c9901f
+       .word   0xee209110
+       .word   0xe28d9040
+       .word   0xed09020f
+       .word   0xed09c203
+       .word   0xe8890007
+       .word   0xed998200
+       .word   0xee90f118
+       .word   0xe0a44004
+       .word   0xbe188100
+       .word   0xee90f11e
+       .word   0xba000044
+       .word   0xee90f119
+       .word   0xba000004
+       .word   0xc3a08014
+       .word   0xcaffffa6
+       .word   0xe31b0501
+       .word   0x13140001
+       .word   0x1a00004f
+       .word   0xe3a0520d
+       .word   0xe3140001
+       .word   0x13a05103
+       .word   0xe31b0501
+       .word   0x13a0520e
+       .word   0x13140001
+       .word   0x13a05000
+       .word   0xee381109
+       .word   0xee19110e
+       .word   0xee488101
+       .word   0xee080100
+       .word   0xe24f8f5f
+       .word   0xe3a06005
+       .word   0xe1a0900f
+       .word   0xeafffca3
+       .word   0xe24f8e15
+       .word   0xe3a06005
+       .word   0xe1a0900f
+       .word   0xeafffca8
+       .word   0xee4a2104
+       .word   0xe3150102
+       .word   0x1e188100
+       .word   0xee1a1100
+       .word   0xee091100
+       .word   0xe1b04105
+       .word   0x2a000006
+       .word   0xee1a2160
+       .word   0xee0a0160
+       .word   0xee91f110
+       .word   0x03a06101
+       .word   0x13a06103
+       .word   0x1e089100
+       .word   0xea00000d
+       .word   0x5d5f2257
+       .word   0x4d5f2252
+       .word   0xee090102
+       .word   0xee282102
+       .word   0xee2a2101
+       .word   0xee0a2103
+       .word   0xee081162
+       .word   0xe3a06101
+       .word   0xe31b00e0
+       .word   0x1a000003
+       .word   0xe31b0702
+       .word   0x1e080102
+       .word   0x1e90f111
+       .word   0x13a06103
+       .word   0xe3150201
+       .word   0x1e189101
+       .word   0xe28d9040
+       .word   0xed899200
+       .word   0xe8990007
+       .word   0xed19020f
+       .word   0xed19c203
+       .word   0xe28dd04c
+       .word   0xe10f9000
+       .word   0xe3c99080
+       .word   0xe129f009
+       .word   0xe1a00000
+       .word   0xe3c03103
+       .word   0xe2000102
+       .word   0xe8bd8000
+       .word   0xe3a05201
+       .word   0xe3140001
+       .word   0x13a05000
+       .word   0xe31b0501
+       .word   0x13a05101
+       .word   0x13140001
+       .word   0x13a05103
+       .word   0xed5f116c
+       .word   0xee90f111
+       .word   0xae181100
+       .word   0xaaffffc1
+       .word   0xe3150102
+       .word   0x1e188100
+       .word   0xee089100
+       .word   0xe1b04105
+       .word   0x2affffd2
+       .word   0xe3a06101
+       .word   0xeaffffde
+       .word   0xee089108
+       .word   0xe3a06000
+       .word   0xeaffffdd
+       .word   0xe2000102
+       .word   0xe3a03000
+       .word   0xe1a0f00e
+       .word   0xe1a08880
+       .word   0xe3780802
+       .word   0x30088001
+       .word   0xe0188080
+       .word   0x5affff84
+       .word   0xe1928081
+       .word   0x1afff4cb
+       .word   0xe3a08015
+       .word   0xeafff4f4
+       .word   0x00003ffe
+       .word   0xa2f9836e
+       .word   0x4e44152a
+       .word   0x00003fff
+       .word   0xc9100000
+       .word   0x00000000
+       .word   0x80003fed
+       .word   0x95777a5c
+       .word   0xf72cece6
+       .word   0x80003fef
+       .word   0x95d5b975
+       .word   0x16391da8
+       .word   0x00003ff6
+       .word   0xe0741531
+       .word   0xdd56f650
+       .word   0x80003ffc
+       .word   0x8895af2a
+       .word   0x6847fcd5
+       .word   0x00003fea
+       .word   0x85bba783
+       .word   0xb3c748a9
+       .word   0x80003ff3
+       .word   0xa37b24c8
+       .word   0x4a42092e
+       .word   0x00003ff9
+       .word   0xd23cf50b
+       .word   0xf10aca84
+       .word   0x80003ffd
+       .word   0xeef5823f
+       .word   0xdecea969
+       .word   0x00000000
+       .word   0x80000000
+       .word   0x00000000
+       .word   0x00003ffe
+       .word   0xffffffff
+       .word   0xffffffff
+       .word   0x00005fff
+       .word   0x80000000
+       .word   0x00000000
+       .word   0xe3100101
+       .word   0x1a00005c
+       .word   0xe1916002
+       .word   0x0a000057
+       .word   0xe92d4000
+       .word   0xe24dd04c
+       .word   0xe1a09407
+       .word   0xe389901f
+       .word   0xe58d9000
+       .word   0xe10f9000
+       .word   0xe3899080
+       .word   0xe129f009
+       .word   0xe1a00000
+       .word   0xe3c7981f
+       .word   0xe3c9901f
+       .word   0xee209110
+       .word   0xe28d9040
+       .word   0xed09020f
+       .word   0xed09c203
+       .word   0xe8890007
+       .word   0xed998200
+       .word   0xe24f80f8
+       .word   0xe1a0900f
+       .word   0xeafffc09
+       .word   0x13a08012
+       .word   0x1affff03
+       .word   0xe1a04006
+       .word   0xeddf1163
+       .word   0xee28a100
+       .word   0xee92f111
+       .word   0xba000028
+       .word   0xee181100
+       .word   0xe24f8c01
+       .word   0xe3a06003
+       .word   0xe1a0900f
+       .word   0xeafffc08
+       .word   0xee0a2109
+       .word   0xee184102
+       .word   0xe24f80f4
+       .word   0xe3a06004
+       .word   0xe1a0900f
+       .word   0xeafffc02
+       .word   0xee0a2109
+       .word   0xe3140001
+       .word   0x0e4c0142
+       .word   0x1e18c104
+       .word   0x1e4a0144
+       .word   0xe3a06101
+       .word   0xe31b00e0
+       .word   0x1a000006
+       .word   0xe31b0702
+       .word   0x0a000004
+       .word   0xe3140001
+       .word   0x0e4c1102
+       .word   0x1e4a1104
+       .word   0xee90f111
+       .word   0x13a06103
+       .word   0xe3a04000
+       .word   0xe28d9040
+       .word   0xed898200
+       .word   0xe8990007
+       .word   0xed19020f
+       .word   0xed19c203
+       .word   0xe28dd04c
+       .word   0xe10f9000
+       .word   0xe3c99080
+       .word   0xe129f009
+       .word   0xe1a00000
+       .word   0xe3c03103
+       .word   0xe0833004
+       .word   0xe2000102
+       .word   0xe8bd8000
+       .word   0xed5fa253
+       .word   0xee289100
+       .word   0xe3140001
+       .word   0x1a000006
+       .word   0xe3a06101
+       .word   0xee91f112
+       .word   0xaaffffe9
+       .word   0xee180104
+       .word   0xe3a04a02
+       .word   0xe2644000
+       .word   0xeaffffe6
+       .word   0xe3a06103
+       .word   0xee91f112
+       .word   0xbe180104
+       .word   0xee188100
+       .word   0xee580109
+       .word   0xee180163
+       .word   0xaaffffde
+       .word   0xe3a04a02
+       .word   0xeaffffdd
+       .word   0xe2000102
+       .word   0xe3a03000
+       .word   0xe1a0f00e
+       .word   0xe1a08880
+       .word   0xe3780802
+       .word   0x30088001
+       .word   0xe0188080
+       .word   0x5affff9d
+       .word   0xe1928081
+       .word   0x1afff43c
+       .word   0xe3a08013
+       .word   0xeafff465
+       .word   0x80003ffe
+       .word   0xd66bd6cd
+       .word   0x8c3de934
+       .word   0x80004002
+       .word   0x87e9fae4
+       .word   0x6b531a29
+       .word   0x80004003
+       .word   0xa40bfdcf
+       .word   0x15e65691
+       .word   0x80004002
+       .word   0xdb053288
+       .word   0x30e70eb4
+       .word   0x00004002
+       .word   0xf0624f0a
+       .word   0x56388310
+       .word   0x00004004
+       .word   0xee505190
+       .word   0x6d1eb4e8
+       .word   0x00004005
+       .word   0xac509020
+       .word   0x5b6d243b
+       .word   0x00004004
+       .word   0xa443e5e6
+       .word   0x24ad4b90
+       .word   0x00003fdf
+       .word   0x80000000
+       .word   0x00000000
+       .word   0x00003ffe
+       .word   0xffffffff
+       .word   0xffffffff
+       .word   0x00003ffd
+       .word   0x8930a2f4
+       .word   0xf66ab18a
+       .word   0x00003ffe
+       .word   0x860a91c1
+       .word   0x6b9b2c23
+       .word   0x00003fbc
+       .word   0xb766aaaa
+       .word   0xaaaaaaab
+       .word   0x00003fff
+       .word   0x860a91c1
+       .word   0x6b9b2c23
+       .word   0x00003fbd
+       .word   0xb766aaaa
+       .word   0xaaaaaaab
+       .word   0x00003fff
+       .word   0xc90fdaa2
+       .word   0x2168c234
+       .word   0x00003fbf
+       .word   0xc4c68000
+       .word   0x00000000
+       .word   0x00003fff
+       .word   0xc90fdaa2
+       .word   0x2168c234
+       .word   0x00003fbf
+       .word   0xc4c68000
+       .word   0x00000000
+       .word   0x00004000
+       .word   0x860a91c1
+       .word   0x6b9b2c23
+       .word   0x00003fbe
+       .word   0xb766aaaa
+       .word   0xaaaaaaab
+       .word   0x00004000
+       .word   0xa78d3631
+       .word   0xc681f72b
+       .word   0x00003fc0
+       .word   0xd6ecd555
+       .word   0x55555555
+       .word   0x00004000
+       .word   0xc90fdaa2
+       .word   0x2168c234
+       .word   0x00003fc0
+       .word   0xc4c68000
+       .word   0x00000000
+       .word   0xe3100101
+       .word   0x03130101
+       .word   0x1a00008b
+       .word   0xe1946005
+       .word   0x1a000005
+       .word   0xe1918002
+       .word   0x03a08016
+       .word   0x0afff474
+       .word   0xe3100102
+       .word   0x01a00003
+       .word   0x0a00007e
+       .word   0xe2036102
+       .word   0xe3100102
+       .word   0x12266007
+       .word   0xe3c00102
+       .word   0xe3c33102
+       .word   0xe92d4000
+       .word   0xe24dd058
+       .word   0xe1a09407
+       .word   0xe389901f
+       .word   0xe58d9000
+       .word   0xe10f9000
+       .word   0xe3899080
+       .word   0xe129f009
+       .word   0xe1a00000
+       .word   0xe3c7981f
+       .word   0xe3c9901f
+       .word   0xee209110
+       .word   0xe28d9040
+       .word   0xed09020f
+       .word   0xed09c203
+       .word   0xe889003f
+       .word   0xedd90200
+       .word   0xe1a05006
+       .word   0xee490100
+       .word   0xea000016
+       .word   0xe3100101
+       .word   0x1a000083
+       .word   0xe1916002
+       .word   0x0a000061
+       .word   0xe2005102
+       .word   0xe3c00102
+       .word   0xe92d4000
+       .word   0xe24dd058
+       .word   0xe1a09407
+       .word   0xe389901f
+       .word   0xe58d9000
+       .word   0xe10f9000
+       .word   0xe3899080
+       .word   0xe129f009
+       .word   0xe1a00000
+       .word   0xe3c7981f
+       .word   0xe3c9901f
+       .word   0xee209110
+       .word   0xe28d9040
+       .word   0xed09020f
+       .word   0xed09c203
+       .word   0xe8890007
+       .word   0xed998200
+       .word   0xee90f119
+       .word   0xce580109
+       .word   0xc2255003
+       .word   0xed5f116d
+       .word   0xee90f111
+       .word   0xda000007
+       .word   0xee393109
+       .word   0xee182103
+       .word   0xee2a2109
+       .word   0xee0a2100
+       .word   0xee39110a
+       .word   0xee091100
+       .word   0xee4a0101
+       .word   0xe2255001
+       .word   0xed5f217e
+       .word   0xee289100
+       .word   0xeed1f112
+       .word   0xba000035
+       .word   0xee181100
+       .word   0xe24f8f9b
+       .word   0xe3a06004
+       .word   0xe1a0900f
+       .word   0xeafffb27
+       .word   0xe24f8f93
+       .word   0xe3a06004
+       .word   0xe1a0900f
+       .word   0xeafffb2c
+       .word   0xee4a2104
+       .word   0xee1a1100
+       .word   0xee091100
+       .word   0xe3150002
+       .word   0x1e189101
+       .word   0xe3150007
+       .word   0x1a000006
+       .word   0xee1a2160
+       .word   0xee0a0160
+       .word   0xee91f110
+       .word   0x03a06101
+       .word   0x13a06103
+       .word   0x1e089100
+       .word   0xea00000f
+       .word   0xe24f8f96
+       .word   0xe0859085
+       .word   0xe0888189
+       .word   0xedd82200
+       .word   0xee090102
+       .word   0xee282102
+       .word   0xee2a2101
+       .word   0xee0a2103
+       .word   0xee081162
+       .word   0xe3a06101
+       .word   0xe31b00e0
+       .word   0x1a000003
+       .word   0xe31b0702
+       .word   0x1e080102
+       .word   0x1e90f111
+       .word   0x13a06103
+       .word   0xe3150102
+       .word   0x1e189101
+       .word   0xe28d9040
+       .word   0xed899200
+       .word   0xe8990007
+       .word   0xed19020f
+       .word   0xed19c203
+       .word   0xe28dd058
+       .word   0xe10f9000
+       .word   0xe3c99080
+       .word   0xe129f009
+       .word   0xe1a00000
+       .word   0xe3c03103
+       .word   0xe2000102
+       .word   0xe8bd8000
+       .word   0xe3150007
+       .word   0x1e089100
+       .word   0x1affffd2
+       .word   0xed5f11b8
+       .word   0xee191160
+       .word   0xe3a06103
+       .word   0xeaffffe9
+       .word   0xe3a01000
+       .word   0xe3a02000
+       .word   0xe2000102
+       .word   0xe3a03000
+       .word   0xe1a0f00e
+       .word   0xe1a09883
+       .word   0xe3790802
+       .word   0x30099004
+       .word   0xe0199083
+       .word   0xe1a08880
+       .word   0xe3780802
+       .word   0x30088001
+       .word   0xe0188080
+       .word   0x4a000005
+       .word   0xe3190102
+       .word   0x0affff68
+       .word   0xe1958084
+       .word   0x1afff342
+       .word   0xe3a04102
+       .word   0xeaffff64
+       .word   0xe3190102
+       .word   0x0a000005
+       .word   0xe1828081
+       .word   0xe1888005
+       .word   0xe1988084
+       .word   0x1afff332
+       .word   0xe3a08017
+       .word   0xeafff3d6
+       .word   0xe1928081
+       .word   0x1afff34c
+       .word   0xe3a01102
+       .word   0xeaffff58
+       .word   0xe1a08880
+       .word   0xe3780802
+       .word   0x30088001
+       .word   0xe0188080
+       .word   0x5affff76
+       .word   0xe1928081
+       .word   0x1afff33e
+       .word   0xe3a01102
+       .word   0xeaffff72
+       .word   0x00000000
+       .word   0x00000000
+       .word   0x00000000
+       .word   0x00000000
+       .word   0x00000000
+       .word   0x00000000
+       .word   0xe59a2080
+       .word   0xe3320000
+       .word   0x5a00002b
+       .word   0xe92d4000
+       .word   0xeb00017d
+       .word   0xe8bd0004
+       .word   0xe8bd4000
+       .word   0xe5922000
+       .word   0xe132000a
+       .word   0x0e502110
+       .word   0xe59a2084
+       .word   0xe3c22b01
+       .word   0xe58a2084
+       .word   0xe24f2b1b
+       .word   0xe2422f2a
+       .word   0xe24f3d01
+       .word   0xe2433f05
+       .word   0xe1510002
+       .word   0xa1530001
+       .word   0xb1a0f00e
+       .word   0xe590103c
+       .word   0xe1510002
+       .word   0xa1530001
+       .word   0xb1a0f00e
+       .word   0xe2804044
+       .word   0xe5145004
+       .word   0xe3150001
+       .word   0x1cb48203
+       .word   0xe3150002
+       .word   0x1cb49203
+       .word   0xe3150004
+       .word   0x1cb4a203
+       .word   0xe3150008
+       .word   0x1cb4b203
+       .word   0xe3150010
+       .word   0x1cb4c203
+       .word   0xe3150020
+       .word   0x1cb4d203
+       .word   0xe3150040
+       .word   0x1cb4e203
+       .word   0xe3150080
+       .word   0x1cb4f203
+       .word   0xe1a052a5
+       .word   0xe3855481
+       .word   0xee205110
+       .word   0xe5900030
+       .word   0xeaffffe4
+       .word   0xe24f2a06
+       .word   0xe2422ed3
+       .word   0xe24f3d03
+       .word   0xe2433f07
+       .word   0xe1510002
+       .word   0xa1530001
+       .word   0xb1a0f00e
+       .word   0xe590103c
+       .word   0xe1510002
+       .word   0xa1530001
+       .word   0xb1a0f00e
+       .word   0xe28a3000
+       .word   0xe2804044
+       .word   0xe5145004
+       .word   0xe3150001
+       .word   0x18b400c2
+       .word   0x188300c2
+       .word   0xe2833010
+       .word   0xe3150002
+       .word   0x18b400c2
+       .word   0x188300c2
+       .word   0xe2833010
+       .word   0xe3150004
+       .word   0x18b400c2
+       .word   0x188300c2
+       .word   0xe2833010
+       .word   0xe3150008
+       .word   0x18b400c2
+       .word   0x188300c2
+       .word   0xe2833010
+       .word   0xe3150010
+       .word   0x18b400c2
+       .word   0x188300c2
+       .word   0xe2833010
+       .word   0xe3150020
+       .word   0x18b400c2
+       .word   0x188300c2
+       .word   0xe2833010
+       .word   0xe3150040
+       .word   0x18b400c2
+       .word   0x188300c2
+       .word   0xe2833010
+       .word   0xe3150080
+       .word   0x18b400c2
+       .word   0x188300c2
+       .word   0xe24f3c01
+       .word   0xe2433f22
+       .word   0xe1a052a5
+       .word   0xe3855401
+       .word   0xe58a5080
+       .word   0xe5900030
+       .word   0xeaffffd2
+       .word   0xe3e00000
+       .word   0xe1b0f00e
+       .word   0xe92d401e
+       .word   0xe58a1004
+       .word   0xe3a0e000
+       .word   0xe58ae000
+       .word   0xe10f3000
+       .word   0xe3830080
+       .word   0xe129f000
+       .word   0xe24f102c
+       .word   0xeb00011c
+       .word   0xe3a00000
+       .word   0xee504110
+       .word   0xe3300000
+       .word   0x158a0008
+       .word   0x1a000008
+       .word   0xe3a02102
+       .word   0xee302110
+       .word   0xe1a00c22
+       .word   0xe58a0008
+       .word   0xe3300081
+       .word   0x03a04c0d
+       .word   0x0e008109
+       .word   0x0e100100
+       .word   0xee404110
+       .word   0xeb000112
+       .word   0xe129f003
+       .word   0xe8bd801e
+       .word   0xe92d400f
+       .word   0xe3a00000
+       .word   0xe58a0084
+       .word   0xe92d4000
+       .word   0xeb0000fe
+       .word   0xe8bd0001
+       .word   0xe8bd4000
+       .word   0xe5900008
+       .word   0xe3300081
+       .word   0x1a00000d
+       .word   0xe24f0f8e
+       .word   0xe890000e
+       .word   0xe28a0000
+       .word   0xe8a0000e
+       .word   0xe8a0000e
+       .word   0xe8a0000e
+       .word   0xe8a0000e
+       .word   0xe8a0000e
+       .word   0xe8a0000e
+       .word   0xe8a0000e
+       .word   0xe8a0000e
+       .word   0xe59f003c
+       .word   0xe58a0080
+       .word   0xe8bd800f
+       .word   0xe24f0e27
+       .word   0xe890000e
+       .word   0xe28a0000
+       .word   0xe8a0001e
+       .word   0xe8a0001e
+       .word   0xe8a0001e
+       .word   0xe8a0001e
+       .word   0xe8a0001e
+       .word   0xe8a0001e
+       .word   0xe8a0001e
+       .word   0xe8a0001e
+       .word   0xe59f0008
+       .word   0xe58a0080
+       .word   0xe8bd800f
+       .word   0x81070000
+       .word   0x01070000
+       .word   0xe92d4007
+       .word   0xe28fe074
+       .word   0xe92d4000
+       .word   0xeb0000d7
+       .word   0xe8bd0001
+       .word   0xe8bd4000
+       .word   0xe5900000
+       .word   0xe3300000
+       .word   0x01a0f00e
+       .word   0xe5901080
+       .word   0xe3310000
+       .word   0x5a00000e
+       .word   0xe92d4002
+       .word   0xee501110
+       .word   0xe3110c01
+       .word   0x01a0e001
+       .word   0x1590e084
+       .word   0xe3ceec0d
+       .word   0xe3110b01
+       .word   0x138eec05
+       .word   0xe580e084
+       .word   0xee301110
+       .word   0xe5801080
+       .word   0xed800200
+       .word   0xed80420c
+       .word   0xee40e110
+       .word   0xe8bd8002
+       .word   0xe92d4000
+       .word   0xe3a0e000
+       .word   0xe580e084
+       .word   0xe8bd8000
+       .word   0xe92d4007
+       .word   0xe92d4000
+       .word   0xeb0000b9
+       .word   0xe8bd0001
+       .word   0xe8bd4000
+       .word   0xe580a000
+       .word   0xe5900008
+       .word   0xe3300081
+       .word   0x0e501110
+       .word   0xe33a0000
+       .word   0x0a000014
+       .word   0xe3300081
+       .word   0x1a00000b
+       .word   0xe59a1080
+       .word   0xee201110
+       .word   0xed9a0200
+       .word   0xed9a420c
+       .word   0xe24f1a06
+       .word   0xe2411efd
+       .word   0xeb0000b0
+       .word   0xe59a1084
+       .word   0xe3110b01
+       .word   0x13a01c05
+       .word   0x1e401110
+       .word   0xe8bd8007
+       .word   0xe3300081
+       .word   0x03a01c0d
+       .word   0x0e401110
+       .word   0xe24f1b19
+       .word   0xe2411f1e
+       .word   0xeb0000a5
+       .word   0xe8bd8007
+       .word   0xe3300081
+       .word   0x03a01c0d
+       .word   0x0e401110
+       .word   0xe8bd4007
+       .word   0xea0000a4
+       .word   0xe92d4400
+       .word   0xe3a0a000
+       .word   0xebffffd7
+       .word   0xe8bd8400
+       .word   0xe92d4000
+       .word   0xeb000091
+       .word   0xe8bd0001
+       .word   0xe8bd4000
+       .word   0xe5900000
+       .word   0xe3300000
+       .word   0x01a0f00e
+       .word   0xe5901080
+       .word   0xe3310000
+       .word   0x5a000007
+       .word   0xee501110
+       .word   0xe3110c01
+       .word   0x01a02001
+       .word   0x15902084
+       .word   0xe3822c09
+       .word   0xe5802084
+       .word   0xee402110
+       .word   0xe1a0f00e
+       .word   0xe3a01001
+       .word   0xe5801084
+       .word   0xe1a0f00e
+       .word   0xe92d4000
+       .word   0xeb00007c
+       .word   0xe8bd0001
+       .word   0xe8bd4000
+       .word   0xe5900000
+       .word   0xe3300000
+       .word   0x01a0f00e
+       .word   0xe5901080
+       .word   0xe3310000
+       .word   0x5a00000e
+       .word   0xee501110
+       .word   0xe3110b01
+       .word   0x01a0f00e
+       .word   0xe3110c01
+       .word   0x01a02001
+       .word   0x15902084
+       .word   0xe3822c01
+       .word   0xe3c22b02
+       .word   0xe5802084
+       .word   0xee301110
+       .word   0xe5801080
+       .word   0xed800200
+       .word   0xed80420c
+       .word   0xee402110
+       .word   0xe1a0f00e
+       .word   0xe3a01000
+       .word   0xe5801084
+       .word   0xe1a0f00e
+       .word   0xe92d40fe
+       .word   0xe59a2080
+       .word   0xe3320000
+       .word   0x5a000010
+       .word   0xe3a0700c
+       .word   0xe92d4000
+       .word   0xeb00005b
+       .word   0xe8bd0004
+       .word   0xe8bd4000
+       .word   0xe5922000
+       .word   0xe132000a
+       .word   0x159a6084
+       .word   0x1a000005
+       .word   0xee506110
+       .word   0xee302110
+       .word   0xe58a2080
+       .word   0xed8a0200
+       .word   0xed8a420c
+       .word   0xee406110
+       .word   0xe2066b01
+       .word   0xea000001
+       .word   0xe3a07010
+       .word   0xe3a06000
+       .word   0xe59a2080
+       .word   0xe4802004
+       .word   0xe3a02008
+       .word   0xe89a0038
+       .word   0xe08aa007
+       .word   0xe3130101
+       .word   0x0a000009
+       .word   0xe3c33101
+       .word   0xe3140102
+       .word   0x0a000008
+       .word   0xe3c44102
+       .word   0xe3130901
+       .word   0x02833001
+       .word   0x0a000004
+       .word   0xe38330ff
+       .word   0xe3833c7f
+       .word   0xea000006
+       .word   0xe3140102
+       .word   0x1a000004
+       .word   0xe92d0340
+       .word   0xe1a06883
+       .word   0xe2968802
+       .word   0x1bfff338
+       .word   0xe8bd0340
+       .word   0xe8a00038
+       .word   0xe2522001
+       .word   0x1affffe7
+       .word   0xe24f2a07
+       .word   0xe2422f6f
+       .word   0xe24f3b01
+       .word   0xe2433f5a
+       .word   0xe1510002
+       .word   0xa1530001
+       .word   0xa3a00001
+       .word   0xb1a00006
+       .word   0xe8bd80fe
+       .word   0xe92d40ff
+       .word   0xe59a1080
+       .word   0xe3310000
+       .word   0x53a07010
+       .word   0x43a0700c
+       .word   0xe4902004
+       .word   0xe3c224ff
+       .word   0x53822401
+       .word   0x43822481
+       .word   0xe58a2080
+       .word   0xe3a02008
+       .word   0xe8b00038
+       .word   0xe1846005
+       .word   0xe1966083
+       .word   0x0a000003
+       .word   0xe1a06883
+       .word   0xe2966802
+       .word   0x13140102
+       .word   0x03833101
+       .word   0xe88a0038
+       .word   0xe08aa007
+       .word   0xe2522001
+       .word   0x1afffff3
+       .word   0xe04aa187
+       .word   0xe3310000
+       .word   0x58bd80ff
+       .word   0xe92d4000
+       .word   0xeb00000b
+       .word   0xe8bd0004
+       .word   0xe8bd4000
+       .word   0xe5922000
+       .word   0xe132000a
+       .word   0x18bd80ff
+       .word   0xee506110
+       .word   0xe59a2080
+       .word   0xee202110
+       .word   0xed9a0200
+       .word   0xed9a420c
+       .word   0xee406110
+       .word   0xe8bd80ff
+       .word   0xe24dd008
+       .word   0xe58d0000
+       .word   0xe59f0008
+       .word   0xe58d0004
+       .word   0xe49d0004
+       .word   0xe1a0f00e
+       .word   0x00000000
+       .word   0x00000000
+       .word   0xe92d4003
+       .word   0xe59f0004
+       .word   0xe5801000
+       .word   0xe8bd8003
+       .word   0x00000000
+       .word   0xe92d4007
+       .word   0xe51f0010
+       .word   0xe59f1004
+       .word   0xe5801000
+       .word   0xe8bd8007
+       .word   0x00000000
+       .word   0xe1a0d00c
+       .word   0xe8dd7fff
+       .word   0xe0000000
+       .word   0xe28dd03c
+       .word   0xe8bd8000
+       .word   0xe3a00000
+       .word   0xea000009
+       .word   0xe3a00001
+       .word   0xea000007
+       .word   0xe3a00002
+       .word   0xea000005
+       .word   0xe3a00003
+       .word   0xea000003
+       .word   0xe3a00004
+       .word   0xea000001
+       .word   0xe3e00000
+       .word   0xeaffffff
+       .word   0xe59f1000
+       .word   0xe1a0f001
+       .word   0x00000000
+       .word   0xe3a00005
+       .word   0xeafffffa
+       .word   0xe1a00000
+       .word   0xe59f1030
+       .word   0xe24fb010
+       .word   0xe05b1001
+       .word   0x01a0f00e
+       .word   0xe59fb024
+       .word   0xe08bb001
+       .word   0xe28f2020
+       .word   0xe4920004
+       .word   0xe3700001
+       .word   0xd1a0f00e
+       .word   0xe79b3000
+       .word   0xe0833001
+       .word   0xe78b3000
+       .word   0xeafffff8
+       .word   0x0000f370
+       .word   0x00008000
+       .word   0x000073ac
+       .word   0x000073b0
+       .word   0xffffffff
+
diff --git a/sys/arch/arm32/fpe-arm/armfpe_glue.S b/sys/arch/arm32/fpe-arm/armfpe_glue.S
new file mode 100644 (file)
index 0000000..bd824f7
--- /dev/null
@@ -0,0 +1,411 @@
+/* $NetBSD: armfpe_glue.S,v 1.6 1996/03/18 19:54:59 mark Exp $ */
+
+/*
+ * Copyright (c) 1996 Mark Brinicombe
+ * 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 Mark Brinicombe.
+ * 4. The name of the company nor the name of the author may 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 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.
+ *
+ * RiscBSD kernel project
+ *
+ * arm_fpe_glue.S
+ *
+ * Glue code for calling the ARM FPE core code
+ *
+ * Created      : 21/12/95
+ */
+
+#include "assym.h"
+#include <machine/cpu.h>
+
+sp     .req    r13
+lr     .req    r14
+pc     .req    r15
+
+/* Offsets into fpe core for function addresses */
+
+#define ARM_FPE_CORE_ABORT              0
+#define ARM_FPE_CORE_INITWS             4
+#define ARM_FPE_CORE_INITCONTEXT        8
+#define ARM_FPE_CORE_CHANGECONTEXT     12
+#define ARM_FPE_CORE_SHUTDOWN          16
+#define ARM_FPE_CORE_ACTIVATECONTEXT   20
+#define ARM_FPE_CORE_DEACTIVATECONTEXT 24
+#define ARM_FPE_CORE_SAVECONTEXT       28
+#define ARM_FPE_CORE_LOADCONTEXT       32
+#define        ARM_FPE_CORE_DISABLE            36
+#define        ARM_FPE_CORE_ENABLE             40
+
+/*
+ * Ok Lots of little stubs for calling the fpe core
+ * routines from C
+ */
+
+       .text
+       .align
+
+arm_fpe_header:
+       .word   _arm_fpe_mod
+
+       .global _arm_fpe_core_disable
+_arm_fpe_core_disable:
+       stmfd   sp!, {r0-r7, lr}
+       ldr     r0, [pc, #arm_fpe_header - . - 8]
+       ldr     r0, [r0, #ARM_FPE_CORE_DISABLE]
+
+       add     lr, pc, #L1 - . - 8
+       mov     pc, r0
+L1:
+       ldmfd   sp!, {r0-r7, pc}
+
+
+       .global _arm_fpe_core_enable
+_arm_fpe_core_enable:
+       stmfd   sp!, {r0-r7, lr}
+       ldr     r0, [pc, #arm_fpe_header - . - 8]
+       ldr     r0, [r0, #ARM_FPE_CORE_ENABLE]
+
+       add     lr, pc, #L2 - . - 8
+       mov     pc, r0
+L2:
+       ldmfd   sp!, {r0-r7, pc}
+
+
+       .global _arm_fpe_core_initws
+_arm_fpe_core_initws:
+       stmfd   sp!, {r10, lr}
+       mov     r10, r0
+       ldr     r3, [pc, #arm_fpe_header - . - 8]
+       ldr     r3, [r3, #ARM_FPE_CORE_INITWS]
+
+       add     lr, pc, #L3 - . - 8
+       mov     pc, r3
+L3:
+       ldmfd   sp!, {r10, pc}
+
+
+       .global _arm_fpe_core_abort
+_arm_fpe_core_abort:
+       stmfd   sp!, {r1-r7, r10, lr}
+       mov     r10, r0
+       mov     r0, r1
+       mov     r1, r2
+       ldr     r3, [pc, #arm_fpe_header - . - 8]
+       ldr     r3, [r3, #ARM_FPE_CORE_ABORT]
+
+       add     lr, pc, #L4 - . - 8
+       mov     pc, r3
+L4:
+       ldmfd   sp!, {r1-r7, r10, pc}
+
+
+/* Only needs to preserve r10 */
+
+       .global _arm_fpe_core_initcontext
+_arm_fpe_core_initcontext:
+       stmfd   sp!, {r0-r7, r10, lr}
+       mov     r10, r0
+       ldr     r3, [pc, #arm_fpe_header - . - 8]
+       ldr     r3, [r3, #ARM_FPE_CORE_INITCONTEXT]
+
+       add     lr, pc, #L5 - . - 8
+       mov     pc, r3
+L5:
+       ldmfd   sp!, {r0-r7, r10, pc}
+
+
+/* Only needs to preserve r10 */
+
+       .global _arm_fpe_core_changecontext
+_arm_fpe_core_changecontext:
+       stmfd   sp!, {r1-r7, r10, lr}
+       mov     r10, r0
+       ldr     r3, [pc, #arm_fpe_header - . - 8]
+       ldr     r3, [r3, #ARM_FPE_CORE_CHANGECONTEXT]
+
+       add     lr, pc, #L6 - . - 8
+       mov     pc, r3
+L6:
+       ldmfd   sp!, {r1-r7, r10, pc}
+
+
+/* All regs preerved */
+
+       .global _arm_fpe_core_shutdown
+_arm_fpe_core_shutdown:
+       stmfd   sp!, {r0-r7, r10, lr}
+       ldr     r3, [pc, #arm_fpe_header - . - 8]
+       ldr     r3, [r3, #ARM_FPE_CORE_SHUTDOWN]
+
+       add     lr, pc, #L7 - . - 8
+       mov     pc, r3
+L7:
+       ldmfd   sp!, {r0-r7, r10, pc}
+
+
+/* Preserve r10 */
+       .global _arm_fpe_core_savecontext
+_arm_fpe_core_savecontext:
+       stmfd   sp!, {r1-r7, r10, lr}
+       mov     r10, r0
+       mov     r0, r1
+       mov     r1, r2
+       ldr     r3, [pc, #arm_fpe_header - . - 8]
+       ldr     r3, [r3, #ARM_FPE_CORE_SAVECONTEXT]
+
+       add     lr, pc, #L8 - . - 8
+       mov     pc, r3
+L8:
+       ldmfd   sp!, {r1-r7, r10, pc}
+
+
+/* Preserve r10 */
+
+       .global _arm_fpe_core_loadcontext
+_arm_fpe_core_loadcontext:
+       stmfd   sp!, {r0-r7, r10, lr}
+       mov     r10, r0
+       mov     r0, r1
+       ldr     r3, [pc, #arm_fpe_header - . - 8]
+       ldr     r3, [r3, #ARM_FPE_CORE_LOADCONTEXT]
+
+       add     lr, pc, #L9 - . - 8
+       mov     pc, r3
+L9:
+       ldmfd   sp!, {r0-r7, r10, pc}
+
+
+/* Only needs to preserve r10 */
+
+       .global _arm_fpe_core_activatecontext
+_arm_fpe_core_activatecontext:
+       stmfd   sp!, {r0-r7, r10, lr}
+       mov     r10, r0
+       ldr     r3, [pc, #arm_fpe_header - . - 8]
+       ldr     r3, [r3, #ARM_FPE_CORE_ACTIVATECONTEXT]
+
+       add     lr, pc, #L10 - . - 8
+       mov     pc, r3
+L10:
+       ldmfd   sp!, {r0-r7, r10, pc}
+
+
+/* Only needs to preserve r10 */
+
+       .global _arm_fpe_core_deactivatecontext
+_arm_fpe_core_deactivatecontext:
+       stmfd   sp!, {r1-r7, r10, lr}
+       ldr     r3, [pc, #arm_fpe_header - . - 8]
+       ldr     r3, [r3, #ARM_FPE_CORE_DEACTIVATECONTEXT]
+
+       add     lr, pc, #L11 - . - 8
+       mov     pc, r3
+L11:
+       ldmfd   sp!, {r1-r7, r10, pc}
+
+
+/* Simple call back function that panics */
+
+       .global _arm_fpe_panic
+_arm_fpe_panic:
+       adr     r0, fpe_panic_text
+       b       _panic
+
+fpe_panic_text:
+       .asciz  "armfpe: we are panicing"
+       .align  0
+
+
+/*
+ * Call back routine from FPE on completion of an instruction
+ */
+
+       .global _arm_fpe_post_proc_glue
+_arm_fpe_post_proc_glue:
+       stmfd   sp!, {r0-r6, r10-r12, lr}
+
+/* This could be optimised as we are going from UND32->SVC32 mode */
+
+        mrs     r4, cpsr_all
+       bic     r3, r4, #(PSR_MODE)
+        orr     r3, r3, #(PSR_SVC32_MODE)
+        msr     cpsr_all, r3
+
+       mov     r0, r12
+
+/* Reserve a trapframe on the SVC stack */
+
+       sub     sp, sp, #(TRAPFRAMESIZE)
+       mov     r1, sp
+
+       ldr     r2, [r0, #-0x0008]      /* Copy spsr */
+       str     r2, [r1, #0x0000]
+
+       ldr     r2, [r0, #0x0000]       /* Copy r0 */
+       str     r2, [r1, #0x0004]
+       ldr     r2, [r0, #0x0004]
+       str     r2, [r1, #0x0008]
+       ldr     r2, [r0, #0x0008]
+       str     r2, [r1, #0x000c]
+       ldr     r2, [r0, #0x000c]
+       str     r2, [r1, #0x0010]
+       ldr     r2, [r0, #0x0010]
+       str     r2, [r1, #0x0014]
+       ldr     r2, [r0, #0x0014]
+       str     r2, [r1, #0x0018]
+       ldr     r2, [r0, #0x0018]
+       str     r2, [r1, #0x001c]
+       ldr     r2, [r0, #0x001c]
+       str     r2, [r1, #0x0020]
+       ldr     r2, [r0, #0x0020]
+       str     r2, [r1, #0x0024]
+       ldr     r2, [r0, #0x0024]
+       str     r2, [r1, #0x0028]
+       ldr     r2, [r0, #0x0028]
+       str     r2, [r1, #0x002c]
+       ldr     r2, [r0, #0x002c]
+       str     r2, [r1, #0x0030]
+       ldr     r2, [r0, #0x0030]       /* Copy r12 */
+       str     r2, [r1, #0x0034]
+       ldr     r2, [r0, #0x0034]       /* Copy usr r13 */
+       str     r2, [r1, #0x0038]
+       ldr     r2, [r0, #0x0038]       /* Copy usr r14 */
+       str     r2, [r1, #0x003c]
+       ldr     r2, [r0, #0x003c]       /* Copy old pc */
+       str     r2, [r1, #0x0044]
+
+       str     r14, [r1, #0x0040]      /* SVC r14 */
+
+/*
+ * OK Question Time ...
+ *
+ * Do I need to save SVC r14 ? 
+ * It only needs saving if this routine can interrupt something already
+ * running in SVC mode. Since FP is only valid from USR32 mode this
+ * should not happen.
+ */
+
+       mov     r5, r14
+       mov     r6, r12
+
+/* More optimisation ... Need to code a assembly version of userret() */
+
+       bl      _arm_fpe_postproc
+
+/* Release the trapframe on the SVC stack */
+
+       ldr     r2, [sp, #0x0000]       /* Copy spsr */
+       str     r2, [r6, #-0x0008]
+
+       ldr     r2, [sp, #0x0004]       /* Copy r0 */
+       str     r2, [r6, #0x0000]
+       ldr     r2, [sp, #0x0008]       /* Copy r1 */
+       str     r2, [r6, #0x0004]
+       ldr     r2, [sp, #0x000c]       /* Copy r2 */
+       str     r2, [r6, #0x0008]
+       ldr     r2, [sp, #0x0010]       /* Copy r3 */
+       str     r2, [r6, #0x000c]
+       ldr     r2, [sp, #0x0014]       /* Copy r4 */
+       str     r2, [r6, #0x0010]
+       ldr     r2, [sp, #0x0018]       /* Copy r5 */
+       str     r2, [r6, #0x0014]
+       ldr     r2, [sp, #0x001c]       /* Copy r6 */
+       str     r2, [r6, #0x0018]
+       ldr     r2, [sp, #0x0020]       /* Copy r7 */
+       str     r2, [r6, #0x001c]
+       ldr     r2, [sp, #0x0024]       /* Copy r8 */
+       str     r2, [r6, #0x0020]
+       ldr     r2, [sp, #0x0028]       /* Copy r9 */
+       str     r2, [r6, #0x0024]
+       ldr     r2, [sp, #0x002c]       /* Copy r10 */
+       str     r2, [r6, #0x0028]
+       ldr     r2, [sp, #0x0030]       /* Copy r11 */
+       str     r2, [r6, #0x002c]
+       ldr     r2, [sp, #0x0034]       /* Copy r12 */
+       str     r2, [r6, #0x0030]
+       ldr     r2, [sp, #0x0038]       /* Copy usr r13 */
+       str     r2, [r6, #0x0034]
+       ldr     r2, [sp, #0x003c]       /* Copy usr r14 */
+       str     r2, [r6, #0x0038]
+       ldr     r2, [sp, #0x0044]       /* Copy pc */
+       str     r2, [r6, #0x003c]
+
+       add     sp, sp, #(TRAPFRAMESIZE)
+
+       mov     r14, r5
+
+       msr     cpsr_all, r4
+
+       ldmfd   sp!, {r0-r6, r10-r12, pc}
+
+
+/*
+ * Call back routine from FPE when the an exception occurs
+ */
+
+       .global _arm_fpe_exception_glue
+_arm_fpe_exception_glue:
+       stmfd   sp!, {r0-r5, r10-r12, lr}
+
+/* This could be optimised as we are going from UND32->SVC32 mode */
+
+        mrs     r4, cpsr_all
+       bic     r3, r4, #(PSR_MODE)
+        orr     r3, r3, #(PSR_SVC32_MODE)
+        msr     cpsr_all, r3
+
+       ldr     r1, [r12, #15*4]
+       mov     r2, r12
+
+       mov     r5, r14
+
+       bl      _arm_fpe_exception
+
+       mov     r14, r5
+
+       msr     cpsr_all, r4
+
+       ldmfd   sp!, {r0-r5, r10-r12, lr}
+
+/* Now pull the original trapframe that the FPE pushed off the stack */
+
+       ldmdb   r12, {r0, r1}
+
+       msr     cpsr_all, r1
+       msr     spsr_all, r0
+
+       mov     sp, r12
+
+       ldmia   sp, {r0-r14}^
+       mov     r0, r0
+       add     sp, sp, #15*4
+       ldmfd   sp!, {pc}^
+
+       .global _fpe_nexthandler
+_fpe_nexthandler:
+       .word   _undefinedinstruction_bounce
diff --git a/sys/arch/arm32/fpe-arm/armfpe_init.c b/sys/arch/arm32/fpe-arm/armfpe_init.c
new file mode 100644 (file)
index 0000000..05990d5
--- /dev/null
@@ -0,0 +1,332 @@
+/* $NetBSD: armfpe_init.c,v 1.6 1996/03/18 19:55:01 mark Exp $ */
+
+/*
+ * Copyright (C) 1996 Mark Brinicombe
+ * Copyright (C) 1995 Neil A Carson.
+ * 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 Brini.
+ * 4. The name of the company nor the name of the author may 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 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.
+ *
+ * RiscBSD kernel project
+ *
+ * arm_fpe.c
+ *
+ * Stuff needed to interface the ARM floating point emulator module to RiscBSD.
+ *
+ * Created      : 22/10/95
+ */
+
+/*#define DEBUG*/
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/proc.h>
+#include <sys/user.h>
+#include <sys/malloc.h>
+#include <sys/device.h>
+#include <sys/acct.h>
+#include <vm/vm.h>
+#include <vm/vm_kern.h>
+#include <vm/vm_param.h>
+
+#include <machine/cpu.h>
+#include <machine/cpus.h>
+#include <machine/katelib.h>
+#include <machine/frame.h>
+
+#include "armfpe.h"            /* Prototypes for things */
+
+extern int want_resched;
+extern u_int fpe_nexthandler;
+
+void undefinedinstruction_bounce __P(());
+void arm_fpe_exception_glue __P((int exception));
+void arm_fpe_panic __P(());
+void undefined_entry __P(());
+void arm_fpe_post_proc_glue __P(());
+
+/*
+ * A module header, pointing into the module
+ */
+
+extern u_int arm_fpe_mod[]; 
+extern u_int undefined_handler_address;
+
+/*
+ * Error messages for the various exceptions, numbered 0-5
+ */
+static char *exception_errors[] = {
+       "Floating point invalid operation",
+       "Floating point division by zero (0)",
+       "Floating point overflow",
+       "Floating point underflow",
+       "Floating point operation inexact",
+       "Floating point major faliure... core fault trapped... not good!"
+};
+
+/*
+ * Relocate the FPE.
+ */
+
+void
+arm_fpe_mod_reloc(void)
+{
+       int cnt;
+       arm_fpe_mod_hdr_t *arm_fpe_mod_hdr = (arm_fpe_mod_hdr_t *)arm_fpe_mod;
+
+       /* Go through the module header, and convert all offsets into absolute
+        * addresses. Careful here - the last two fields of the header do _NOT_
+        * want to be relocated!
+        */
+
+       for (cnt = 0; cnt < (sizeof(arm_fpe_mod_hdr_t) >> 2) - 2; cnt ++) {
+#ifdef DEBUG
+               printf("FPE: entry %02x = %08x ", cnt, arm_fpe_mod[cnt]);
+#endif
+               arm_fpe_mod[cnt] += (u_int) arm_fpe_mod;
+#ifdef DEBUG
+               printf(" reloc=%08x\n", arm_fpe_mod[cnt]);
+#endif
+       }
+       /* Print a startup message, and a couple of variables needed, these may need
+        * checking to make *sure* they are OK!
+        */
+
+#ifdef DEBUG
+       printf("FPE: global workspace size = %d bytes, context size = %d bytes\n",
+           arm_fpe_mod_hdr->WorkspaceLength, arm_fpe_mod_hdr->ContextLength);
+       printf("FPE: base=%08x\n", (u_int)arm_fpe_mod);
+#endif
+}
+
+/*
+ * Initialisation point. The kernel calls this during the configuration of the cpu
+ * in order to install the FPE.
+ * The FPE specification needs to be filled in the specified cpu_t structure
+ * and the FPE needs to be installed on the CPU undefined instruction vector.
+ */
+
+int
+initialise_arm_fpe(cpu)
+       cpu_t *cpu;
+{
+       int error;
+
+       cpu->fpu_class = FPU_CLASS_FPE;
+       cpu->fpu_type = FPU_TYPE_ARMLTD_FPE;
+       strcpy(cpu->fpu_model, "Advanced RISC Machines floating point emulator");
+       error = arm_fpe_boot();
+       if (error != 0) {
+               strcat(cpu->fpu_model, " - boot failed");
+               return(1);
+       }
+
+/* Return with start failure so the old FPE is installed */
+
+/*     strcat(cpu->fpu_model, " - boot aborted");*/
+
+       return(0);
+}
+
+/*
+ * The actual FPE boot routine.
+ * This has to do a number of things :
+ * 1. Relocate the FPE - Note this requires write access to the kernel text area
+ * 2. Allocated memory for the FPE
+ * 3. Initialise the FPE
+ */
+
+int
+arm_fpe_boot(void)
+{
+       u_int workspace;
+       int id;
+       arm_fpe_mod_hdr_t *arm_fpe_mod_hdr = (arm_fpe_mod_hdr_t *)arm_fpe_mod;
+       
+       /* First things first ... Relocate the FPE pointers */
+
+       arm_fpe_mod_reloc();
+
+       /* Now we must do some memory allocation */
+
+       workspace = (u_int)malloc(arm_fpe_mod_hdr->WorkspaceLength, M_DEVBUF, M_NOWAIT);
+#ifdef DEBUG
+       printf("Gloabl workspace at 0x%08x\n", workspace);
+#endif
+
+       if (!workspace)
+               return(ENOMEM);
+
+       *arm_fpe_mod_hdr->main_ws_ptr_addr = workspace;
+
+       *arm_fpe_mod_hdr->local_handler_ptr_addr = (u_int)&undefined_handler_address;
+       *arm_fpe_mod_hdr->old_handler_ptr_addr = undefined_handler_address;
+
+       /* Initialise out gloable workspace */
+
+#ifdef DEBUG
+       printf("Initing workspace ");
+#endif
+
+       id = arm_fpe_core_initws(workspace, (u_int)&fpe_nexthandler, (u_int)&fpe_nexthandler);
+
+#ifdef DEBUG
+       printf("id=%08x\n", id);
+#endif
+
+       /* Set up an exception handler */
+
+       *arm_fpe_mod_hdr->exc_handler_ptr_addr = (u_int)arm_fpe_exception_glue;
+
+       /* Set up post instruction handler */
+#if defined(CPU_ARM6) || defined(CPU_ARM7)
+       *arm_fpe_mod_hdr->fp_post_proc_addr = (((((u_int)arm_fpe_post_proc_glue -
+           (u_int)arm_fpe_mod_hdr->fp_post_proc_addr - 8)>>2) & 0x00ffffff) | 0xea000000);
+#ifdef DEBUG
+       printf("arm_fpe_mod_hdr->fp_post_proc_addr = %08x (%08x)",
+           arm_fpe_mod_hdr->fp_post_proc_addr,
+           *arm_fpe_mod_hdr->fp_post_proc_addr);
+#endif
+#else
+#error ARMFPE currently only supports ARM6 and ARM7
+#endif
+
+#ifdef DEBUG
+       printf("Initialising proc0 FPE context\n");
+#endif
+
+       /* Initialise proc0's FPE context */
+
+       arm_fpe_core_initcontext(FP_CONTEXT(&proc0));
+       arm_fpe_core_changecontext(FP_CONTEXT(&proc0));
+
+       return(0);
+}
+
+
+/*
+ * Callback routine from the FPE when instruction emulation completes
+ */
+
+void
+arm_fpe_postproc(fpframe, frame)
+       u_int fpframe;
+       struct trapframe *frame;
+{
+       register u_int s;
+       register int sig;
+       register struct proc *p;
+
+       p = curproc;
+       p->p_md.md_regs = frame;
+
+/* take pending signals */
+
+       while ((sig = (CURSIG(p))) != 0) {
+               postsig(sig);
+       }
+
+       p->p_priority = p->p_usrpri;
+
+       if (want_resched) {
+        /*
+         * Since we are curproc, a clock interrupt could
+         * change our priority without changing run queues
+         * (the running process is not kept on a run queue).
+         * If this happened after we setrunqueue ourselves but
+         * before we switch()'ed, we might not be on the queue
+         * indicated by our priority
+         */
+       
+               s = splstatclock();
+               setrunqueue(p);
+               p->p_stats->p_ru.ru_nivcsw++;
+
+               mi_switch();
+
+               (void)splx(s);
+               while ((sig = (CURSIG(p))) != 0) {
+                       postsig(sig);
+               }
+       }
+
+/* Profiling. */
+
+       if (p->p_flag & P_PROFIL) {
+               extern int psratio;
+               u_int pc;
+
+               pc = ReadWord(fpframe + 15*4);
+
+               if (pc <0x1000 || pc > 0xefc00000)
+                       printf("armfpe_postproc: pc=%08x\n", pc);
+
+/*             addupc_task(p, pc, (int)(p->p_sticks - sticks) * psratio);*/
+               addupc_task(p, pc, (int)(p->p_sticks - p->p_sticks) * psratio);
+       }
+
+       curpriority = p->p_priority;
+}
+
+
+/*
+ * Callback routine from the FPE when an exception occurs.
+ */
+
+void
+arm_fpe_exception(exception, pc, fpframe)
+       int exception;
+       u_int pc;
+       u_int fpframe;
+{
+       if (exception >= 0 && exception < 6)
+               printf("fpe exception: %d - %s\n", exception, exception_errors[exception]);
+       else
+               printf("fpe exception: %d - unknown\n", exception);
+
+       trapsignal(curproc, SIGFPE, exception);
+
+       printf("PC=%08x\n", ReadWord(fpframe + 60));
+
+       userret(curproc, pc, curproc->p_sticks);
+}
+
+
+void
+arm_fpe_copycontext(c1, c2)
+       u_int c1;
+       u_int c2;
+{
+       fp_context_frame_t fpcontext;
+
+       arm_fpe_core_savecontext(c1, (int *)&fpcontext, 0);
+       arm_fpe_core_loadcontext(c2, (int *)&fpcontext);
+}
+
+/* End of armfpe_init.c */
diff --git a/sys/arch/arm32/fpe-sp/fpe.c b/sys/arch/arm32/fpe-sp/fpe.c
new file mode 100644 (file)
index 0000000..84b79dc
--- /dev/null
@@ -0,0 +1,1321 @@
+/* $NetBSD: fpe.c,v 1.2 1996/03/18 19:58:09 mark Exp $ */
+
+/*
+ * Copyright (c) 1995 Mark Brinicombe.
+ * Copyright (c) 1995 Neil Carson.
+ * All rights reserved.
+ *
+ * This code is derived from software written for Brini by Mark Brinicombe
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided 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 RiscBSD kernel team.
+ * 4. The name of the company nor the name of the author may be used to
+ *    endorse or promote products derived from this software without specific
+ *    prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHORS 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.
+ *
+ * RiscBSD kernel project
+ *
+ * fpe.c
+ *
+ * Floating Point Emulator
+ *
+ * Currently calculations are only performed to single precision
+ *
+ * Created      : 11/02/95
+ */
+
+/* FPE Compile options
+ *
+ * FPE_SPEEDUPS        - use assembly speedups in place of C routines
+ * FPE_NODEBUG - don't compile in the debugging code
+ * FPE_PROF    - compile in FPE profiling code
+ * FPE_INLINE  - define this as inline to inline some functions
+ */
+
+#define FPE_SPEEDUPS
+#define FPE_NODEBUG
+/*#define FPE_PROF*/
+#define FPE_INLINE __inline
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/proc.h>
+#include <sys/user.h>
+#include <sys/kernel.h>
+#include <sys/device.h>
+#include <sys/syslog.h>
+
+#include <machine/cpu.h>
+#include <machine/cpus.h>
+#include <machine/katelib.h>
+#include <machine/frame.h>
+#include <machine/undefined.h>
+#include <machine/fp.h>
+
+typedef struct {
+       int opcode;
+       int precision;
+       int rounding;
+       int fpregm;
+       int fpregn;
+       int fpregd;
+       int regd;
+} fp_op_data_t;
+
+/* Types and stuctures used to hold floating point numbers */
+
+typedef struct {
+       u_int32_t exponent;
+       u_int32_t mantissa_hi;
+       u_int32_t mantissa_lo;
+} fpe_reg_t;
+
+typedef struct {
+       u_int   mantissa:23;
+       u_int   exponent:8;
+       u_int   sign:1;
+} fpe_sprec_t;
+
+typedef struct {
+       u_int   mantissa_hi:20;
+       u_int   exponent:11;
+       u_int   sign:1;
+       u_int32_t       mantissa_lo;
+} fpe_dprec_t;
+
+typedef struct {
+       u_int32_t exponent;
+       u_int32_t mantissa_hi;
+       u_int32_t mantissa_lo;
+} fpe_eprec_t;
+
+typedef struct {
+       u_int32_t word1;
+       u_int32_t word2;
+       u_int32_t word3;
+} fpe_pprec_t;
+
+typedef struct {
+       u_int32_t exponent;
+       u_int64_t mantissa;
+} fpe_qreg_t;
+
+/* FPE status and control registers */
+
+u_int  fpe_status  = 0x02000000;
+u_int  fpe_control = 0x00000000;
+
+#define FPE_STATUS_MASK                0x001f1f1f
+#define FPE_CONTROL_MASK       0x9cffffff
+
+/* Array containing the emulated registers */
+
+fpe_reg_t fpe_registers[16] = {
+       { 0, 0, 0 }, /* f0 */
+       { 0, 0, 0 }, /* f1 */
+       { 0, 0, 0 }, /* f2 */
+       { 0, 0, 0 }, /* f3 */
+       { 0, 0, 0 }, /* f4 */
+       { 0, 0, 0 }, /* f5 */
+       { 0, 0, 0 }, /* f6 */
+       { 0, 0, 0 }, /* f7 */
+       { 0x0000, 0x00000000, 0x00000000 }, /* 0.0 */
+       { 0x3fff, 0x80000000, 0x00000000 }, /* 1.0 */
+       { 0x4000, 0x80000000, 0x00000000 }, /* 2.0 */
+       { 0x4000, 0xc0000000, 0x00000000 }, /* 3.0 */
+       { 0x4001, 0x80000000, 0x00000000 }, /* 4.0 */
+       { 0x4001, 0xa0000000, 0x00000000 }, /* 5.0 */
+       { 0x3ffe, 0x80000000, 0x00000000 }, /* 0.5 */
+       { 0x4002, 0xa0000000, 0x00000000 }, /* 10.0 */
+};
+
+fpe_reg_t *fpregs;
+
+/* Prototypes for instruction emulation functions */ 
+
+typedef int (*fpe_handler_t) __P((unsigned int, trapframe_t *));
+typedef int (*fpe_dop_handler_t) __P((fp_op_data_t *, trapframe_t *));
+
+int fpe_mvf __P((fp_op_data_t *, trapframe_t *));
+int fpe_mnf __P((fp_op_data_t *, trapframe_t *));
+int fpe_adf __P((fp_op_data_t *, trapframe_t *));
+int fpe_muf __P((fp_op_data_t *, trapframe_t *));
+int fpe_suf __P((fp_op_data_t *, trapframe_t *));
+int fpe_dvf __P((fp_op_data_t *, trapframe_t *));
+int fpe_muf __P((fp_op_data_t *, trapframe_t *));
+int fpe_rdf __P((fp_op_data_t *, trapframe_t *));
+int fpe_rsf __P((fp_op_data_t *, trapframe_t *));
+int fpe_abs __P((fp_op_data_t *, trapframe_t *));
+
+/* Table of handler functions for register to registers operations */
+
+fpe_dop_handler_t fpe_dops[32] = {
+       fpe_adf, /* 00000 ADF Add */
+       fpe_mvf, /* 00001 MVF Move */
+       fpe_muf, /* 00010 MUL Multiply */
+       fpe_mnf, /* 00011 MNF Move negated */
+       fpe_suf, /* 00100 SUF Subtract */
+       fpe_abs, /* 00101 ABS Absolute value */
+       fpe_rsf, /* 00110 RSF Reverse subtract */
+       NULL,    /* 00111 RND Round to integer */
+       fpe_dvf, /* 01000 DVF Divide */
+       NULL,    /* 01001 SQT Square root */
+       fpe_rdf, /* 01010 RDF Reverse divide */
+       NULL,    /* 01011 LOG Logarithm to base 10 */
+       NULL,    /* 01100 POW Power */
+       NULL,    /* 01101 LGN Logarithm to base e */
+       NULL,    /* 01110 RPW Reverse power */
+       NULL,    /* 01111 EXP Exponent */
+       NULL,    /* 10000 RMF Remainder */
+       NULL,    /* 10001 SIN Sine */
+       fpe_muf, /* 10010 FML Fast multiply */
+       NULL,    /* 10011 COS Cosine */
+       fpe_dvf, /* 10100 FDV Fast divide */
+       NULL,    /* 10101 TAN Tangent */
+       fpe_rdf, /* 10110 FRD Fast reverse divide */
+       NULL,    /* 10111 ASN Arc sine */
+       NULL,    /* 11000 ROL Rolar angle */
+       NULL,    /* 11001 ACS Arc cosine */
+       NULL,    /* 11010 undefined */
+       NULL,    /* 11011 ATN Arc tangent */
+       NULL,    /* 11100 undefined */
+       NULL,    /* 11101 undefined */
+       NULL,    /* 11110 undefined */
+       NULL,    /* 11111 undefined */
+};
+
+/* Prototypes for instruction emulation functions */ 
+
+int fpe_flt __P((fp_op_data_t *, trapframe_t *));
+int fpe_fix __P((fp_op_data_t *, trapframe_t *));
+int fpe_wfs __P((fp_op_data_t *, trapframe_t *));
+int fpe_rfs __P((fp_op_data_t *, trapframe_t *));
+int fpe_wfc __P((fp_op_data_t *, trapframe_t *));
+int fpe_rfc __P((fp_op_data_t *, trapframe_t *));
+int fpe_cmf __P((fp_op_data_t *, trapframe_t *));
+int fpe_cnf __P((fp_op_data_t *, trapframe_t *));
+
+/* Table of handler functions for fp register transfer operations */ 
+
+fpe_dop_handler_t fpe_regtrans[16] = {
+       fpe_flt, /* 0000 FLT Integer to FP */
+       fpe_fix, /* 0001 FIX FP to Integer */
+       fpe_wfs, /* 0010 Write FP status */
+       fpe_rfs, /* 0011 Read FP status */
+       fpe_wfc, /* 0100 Write FP control */
+       fpe_rfc, /* 0101 Read FP control */
+       NULL,    /* 0110 undefined */
+       NULL,    /* 0111 undefined */
+       NULL,    /* 1000 undefined */
+       fpe_cmf, /* 1001 Compare FP */
+       NULL,    /* 1010 undefined */
+       fpe_cnf, /* 1011 Compare negated FP */
+       NULL,    /* 1100 undefined */
+       fpe_cmf, /* 1101 Compare FP with exception */
+       NULL,    /* 1110 undefined */
+       fpe_cnf, /* 1111 Compare negated FP with exception */
+};
+
+/* Prototypes for instruction emulation functions */ 
+
+int fpe_ldfstf __P((unsigned int address, trapframe_t *));
+
+FPE_INLINE int stofpe __P((u_int32_t */*address*/, fpe_reg_t */*fpreg*/));
+int dtofpe __P((u_int32_t *, fpe_reg_t *));
+int etofpe __P((u_int32_t *, fpe_reg_t *));
+int ptofpe __P((u_int32_t *, fpe_reg_t *));
+FPE_INLINE int fpetos __P((u_int32_t *, fpe_reg_t *));
+int fpetod __P((u_int32_t *, fpe_reg_t *));
+int fpetoe __P((u_int32_t *, fpe_reg_t *));
+int fpetop __P((u_int32_t *, fpe_reg_t *));
+
+int fpe_dump(void);
+
+int coproc1_handler __P((unsigned int, unsigned int, trapframe_t *));
+int coproc2_handler __P((unsigned int, unsigned int, trapframe_t *));
+
+/* Prototypes for assembly functions */
+
+u_int32_t nc_fp_add __P((u_int32_t, u_int32_t));
+u_int32_t nc_fp_sub __P((u_int32_t, u_int32_t));
+u_int32_t nc_fp_mul __P((u_int32_t, u_int32_t));
+u_int32_t nc_fp_div __P((u_int32_t, u_int32_t));
+u_int32_t nc_fp_fix __P((u_int32_t));
+u_int32_t nc_fp_cmp __P((u_int32_t, u_int32_t));
+
+#define FPP_ADD                0
+#define FPP_SUB                1
+#define FPP_MUL                2
+#define FPP_DIV                3
+#define FPP_CMF                4
+#define FPP_CNF                5
+#define FPP_FIX                6
+#define FPP_FLT                7
+#define FPP_ABS                8
+#define FPP_MOV                9
+#define FPP_MVN                10
+#define FPP_RDV                11
+#define FPP_RSB                12
+#define FPP_STRS       13
+#define FPP_STRD       14
+#define FPP_STRE       15
+#define FPP_STRP       16
+#define FPP_LDRS       17
+#define FPP_LDRD       18
+#define FPP_LDRE       19
+#define FPP_LDRP       20
+#define FPP_MAX        21
+
+#ifdef FPE_PROF
+u_int fp_profile[FPP_MAX];
+
+#define FPP_INC(x)     ++fp_profile[x]
+#else
+#define FPP_INC(x)
+#endif
+
+/*
+* If FPE is defined then we are being built into the kernel.
+* If not then we are being built as a standalone loadable module.
+*/
+
+#ifdef FPE
+#define PRINTF(x)      ;
+#define FPE_DUMP()     ;
+#else
+#define PRINTF(x) (*printf_store)(x)
+#define FPE_DUMP()     fpe_dump()
+
+void (*printf_store)();
+void (*install_coproc_store)();
+
+#ifdef NOTEXT
+void
+fpe_printf(char *a, ...)
+{
+}
+#endif
+
+/* Standalone initialisation point */
+
+int
+init_fpe(printf_handler, coproc_handler)
+       void (*printf_handler)();
+       void (*coproc_handler)();
+{
+       int loop;
+
+       printf_store = printf_handler;
+       install_coproc_store = coproc_handler;
+#ifdef NOTEXT
+       printf_store = fpe_printf;
+#endif
+       (*install_coproc_store)(FP_COPROC, coproc1_handler);
+       (*install_coproc_store)(FP_COPROC2, coproc2_handler);
+
+#ifdef FPE_PROF
+       for (loop = 0; loop < FPP_MAX; ++loop)
+               fp_profile[loop] = 0;
+#endif
+
+       PRINTF(("FPE installed\n"));
+       return(0);
+}
+#endif
+
+
+/*
+ * Main entry point after an undefined instruction.
+ * The instruction has been identified as a co-proc 2 instruction.
+ * We get the address of the instruction, the instruction itself and
+ * and pointer to the trap frame.
+ * Currently we do support this (LFM/SFM) so its gallows time
+ */
+
+int
+coproc2_handler(address, instruction, frame)
+       unsigned int address;
+       unsigned int instruction;
+       trapframe_t *frame;
+{
+       log(LOG_ERR, "Coprocessor 2 FP instruction 0x%08x not supported yet.", instruction);
+       return(1);
+}
+
+
+void
+init_fpe_state(p)
+       struct proc *p;
+{
+       struct fp_state *fpstate;
+       int loop;
+
+       fpstate = &p->p_addr->u_pcb.pcb_fpstate;
+       fpstate->fp_flags |= 1;
+
+       for (loop = 8; loop < 16; ++loop)
+               fpstate->fp_registers[loop] = *((fp_reg_t *)&fpe_registers[loop]);
+}
+
+
+int
+initialise_fpe(cpu)
+       cpu_t *cpu;
+{
+       cpu->fpu_class = FPU_CLASS_FPE;
+       cpu->fpu_type = FPU_TYPE_SP_FPE;
+       strcpy(cpu->fpu_model, "Single precision floating point emulator");
+       install_coproc_handler(FP_COPROC, coproc1_handler);
+       install_coproc_handler(FP_COPROC2, coproc2_handler);
+       init_fpe_state(curproc);
+       return(0);
+}
+
+
+/*
+ * Main entry point after an undefined instruction.
+ * The instruction has been identified as a co-proc 1 instruction.
+ * We get the address of the instruction, the instruction itself and
+ * and pointer to the trap frame.
+ */
+
+int
+coproc1_handler(address, instruction, frame)
+       unsigned int address;
+       unsigned int instruction;
+       trapframe_t *frame;
+{
+       struct fp_state *fpstate;
+       PRINTF(("FPE instruction 0x%08x -> 0x%08x\n",
+               address, instruction));
+
+/* Get the fp registers pointer */
+
+       fpstate = &curproc->p_addr->u_pcb.pcb_fpstate;
+
+       fpstate->fp_flags |= 2; /* so statclock can tell if we are spending time in the fpe */
+       
+       if (fpstate->fp_flags & 1)
+               fpregs = (fpe_reg_t *) &fpstate->fp_registers;
+       else
+               fpregs = fpe_registers;
+
+/* Test for a FP data transfer operation */
+
+       if ((instruction & (1 << 25)) == 0) {
+               int err;
+
+               PRINTF(("FP data transfer\n"));
+               err = fpe_ldfstf(instruction, frame);
+               FPE_DUMP();
+               fpstate->fp_flags &= ~2;
+               return(err);
+       }
+
+/* Test for a FP data operation */
+
+       else if ((instruction & (1 << 4)) == 0) {
+               fp_op_data_t op_data;
+
+               op_data.opcode = (instruction >> 19) & 0x1e;
+               if (instruction & 0x00008000)
+                       op_data.opcode |= 0x01;
+
+               op_data.precision = ((instruction & (1<<19)) ? 2 : 0)
+                                       | ((instruction & (1<<7)) ? 1 : 0);
+               op_data.rounding = (instruction >> 5) & 3;
+               op_data.fpregm = (instruction) & 15;
+               op_data.fpregn = (instruction >> 16) & 7;
+               op_data.fpregd = (instruction >> 12) & 7;
+
+               PRINTF(("FP data op = %d\n", op_data.opcode));
+               if (fpe_dops[op_data.opcode]) {
+                       int err;
+                       err = (*fpe_dops[op_data.opcode])(&op_data, frame);
+#ifndef FPE_NODEBUG
+                       if (err == 0)
+                               FPE_DUMP();
+#endif
+                       fpstate->fp_flags &= ~2;
+                       return(err);
+               }
+               else {
+                       fpstate->fp_flags &= ~2;
+                       return(1);
+               }
+       }
+
+/* Test for a FP register transfer operation */
+       
+       else {
+               fp_op_data_t op_data;
+
+               op_data.opcode = (instruction >> 20) & 0x0f;
+
+               op_data.precision = ((instruction & (1<<19)) ? 2 : 0)
+                                       | ((instruction & (1<<7)) ? 1 : 0);
+               op_data.rounding = (instruction >> 5) & 3;
+               op_data.fpregm = (instruction) & 15;
+               op_data.fpregn = (instruction >> 16) & 7;
+               op_data.regd = (instruction >> 12) & 15;
+
+               PRINTF(("FP reg trans = %d\n", op_data.opcode));
+               if (fpe_regtrans[op_data.opcode]) {
+                       int err;
+
+                       PRINTF(("FP reg trans op = %d\n", op_data.opcode));
+                       err = (*fpe_regtrans[op_data.opcode])(&op_data, frame);
+#ifndef FPE_NODEBUG
+                       if (err == 0 && (op_data.opcode == 0 || op_data.opcode == 2
+                               || op_data.opcode == 4))
+                               FPE_DUMP();
+#endif
+                       fpstate->fp_flags &= ~2;
+                       return(err);
+               }
+               else {
+                       fpstate->fp_flags &= ~2;
+                       return(1);
+               }
+       }
+
+/* Well if it gets here then it was not a decodable FP instruction */
+
+       fpstate->fp_flags &= ~2;
+       return(1);
+}
+
+
+/* Precision convertion routines */
+
+FPE_INLINE int
+stofpe(address, fpreg)
+       u_int32_t *address;
+       fpe_reg_t *fpreg;
+{
+       fpe_sprec_t real;
+       u_int32_t *words = (u_int32_t *)&real;
+
+       if ((address[0] & ~(1<<31)) == 0) {
+               PRINTF(("single=0\n"));
+
+               fpreg->mantissa_hi = 0;
+               fpreg->mantissa_lo = 0;
+               fpreg->exponent = address[0] & (1<<31);
+               return(0);
+       }
+
+       words[0] = address[0];
+       PRINTF(("word=%08x\n", address[0]));
+
+       PRINTF(("sign = %d exponent=%08x mantissa=%08x\n", real.sign,
+       real.exponent, real.mantissa));
+       fpreg->mantissa_hi = real.mantissa << 8;
+       fpreg->mantissa_lo = 0;
+       fpreg->exponent = ((int)real.exponent - 0x80) + 0x4000;
+       fpreg->exponent |= (real.sign << 31);
+       return(0);
+}
+
+
+int
+dtofpe(address, fpreg)
+       u_int32_t *address;
+       fpe_reg_t *fpreg;
+{
+       fpe_dprec_t real;
+
+       if ((address[0] & ~(1<<31)) == 0 && address[1] == 0) {
+               PRINTF(("double=0\n"));
+
+               fpreg->mantissa_hi = 0;
+               fpreg->mantissa_lo = 0;
+               fpreg->exponent = address[0] & (1<<31);
+               return(0);
+       }
+
+       real = *(fpe_dprec_t *)address;
+       PRINTF(("sign = %d exponent=%08x mantissa=%08x %08x\n", real.sign,
+       real.exponent, real.mantissa_lo, real.mantissa_hi));
+       fpreg->mantissa_hi = real.mantissa_hi << 11;
+       fpreg->mantissa_hi |= real.mantissa_lo >> 21;
+       fpreg->mantissa_lo = real.mantissa_lo << 11;
+       fpreg->exponent = (real.exponent - 0x400) + 0x4000;
+       fpreg->exponent |= (real.sign << 31);
+
+       return(0);
+}
+
+
+#ifndef FPE_SPEEDUPS
+int
+etofpe(address, fpreg)
+       u_int32_t *address;
+       fpe_reg_t *fpreg;
+{
+       bcopy((char *)address, (char *)fpreg, 12);
+       return(0);
+}
+#endif
+
+
+int
+ptofpe(address, fpreg)
+       u_int32_t *address;
+       fpe_reg_t *fpreg;
+{
+       fpe_pprec_t real;
+
+       real = *(fpe_pprec_t *)address;
+       return(1);
+}
+
+
+FPE_INLINE int
+fpetos(address, fpreg)
+       u_int32_t *address;
+       fpe_reg_t *fpreg;
+{
+       fpe_sprec_t real;
+       int exp;
+
+       if (fpreg->mantissa_hi == 0 && fpreg->mantissa_lo == 0
+           && (fpreg->exponent & ~(1<<31)) == 0) {
+               PRINTF(("single=0\n"));
+
+               address[0] = fpreg->exponent & (1<<31);
+               return(0);
+       }
+
+       real.sign = (fpreg->exponent >> 31) & 1;
+       real.mantissa = (fpreg->mantissa_hi >> 8);
+       exp = ((int)(fpreg->exponent & 0x7fff) - 0x4000) + 0x80;
+
+       if (exp < 0 || exp > 0xff) {
+               PRINTF(("ermm exponent out of range !\n"));
+               exp = 0x80;
+       }
+
+       real.exponent = exp;
+
+       PRINTF(("single=%08x\n", *((unsigned int *)&real)));
+
+       *(fpe_sprec_t *)address = real;
+       if (real.sign == 1 && real.mantissa == 0 && real.exponent == 0)
+               printf("single result = %08x", *address);
+       return(0);
+}
+
+
+int
+fpetod(address, fpreg)
+       u_int32_t *address;
+       fpe_reg_t *fpreg;
+{
+       fpe_dprec_t real;
+       u_int32_t *words = (u_int32_t *)&real;
+       int exp;
+
+       if (fpreg->mantissa_lo == 0 && (fpreg->exponent & ~(1<<31)) == 0) {
+               PRINTF(("double=0\n"));
+
+               address[0] = fpreg->exponent & (1<<31);
+               address[1] = 0;
+               return(0);
+       }
+
+       real.sign = (fpreg->exponent >> 31) & 1;
+       real.mantissa_hi = (fpreg->mantissa_hi >> 11);
+       real.mantissa_lo = (fpreg->mantissa_hi << 21) | (fpreg->mantissa_lo >> 11);
+       exp = ((int)(fpreg->exponent & 0x7fff) - 0x4000) + 0x400;
+
+       if (exp < 0 || exp > 0x7ff) {
+               PRINTF(("ermm exponent out of range !\n"));
+               exp = 0x400;
+       }
+
+       real.exponent = exp;
+
+       PRINTF(("double=%08x%08x\n", words[0], words[1]));
+
+       address[0] = words[0];
+       address[1] = words[1];
+       return(0);
+}
+
+#ifndef FPE_SPEEDUPS
+int
+fpetoe(address, fpreg)
+       u_int32_t *address;
+       fpe_reg_t *fpreg;
+{
+       bcopy((char *)fpreg, (char *)address, 12);
+       return(0);
+}
+#endif
+
+
+int
+fpetop(address, fpreg)
+       u_int32_t *address;
+       fpe_reg_t *fpreg;
+{
+       return(1);
+}
+
+
+/* Unary fp data operations */
+
+/*
+ * int fpe_mvf(fp_op_data_t *op, trapframe_t *frame)
+ *
+ * MVF - Move FP register to FP register
+ */
+
+int
+fpe_mvf(op, frame)
+       fp_op_data_t *op;
+       trapframe_t *frame;
+{
+       FPP_INC(FPP_MOV);
+       PRINTF(("MVF prec=%d rnd=%d fd=%d fn=%d fm=%d\n",
+               op->precision, op->rounding, op->fpregd, op->fpregn, op->fpregm));
+       fpregs[op->fpregd] = fpregs[op->fpregm];
+       return(0);
+}
+
+
+/*
+* int fpe_mnf(fp_op_data_t *op, trapframe_t *frame)
+*
+* MNF - Move FP register to FP register negated
+*/
+
+int
+fpe_mnf(op, frame)
+       fp_op_data_t *op;
+       trapframe_t *frame;
+{
+       fpe_qreg_t real1 = *(fpe_qreg_t *)&fpregs[8];
+       fpe_qreg_t real2 = *(fpe_qreg_t *)&fpregs[op->fpregm];
+       fpe_qreg_t result;
+       u_int32_t single_a, single_b, single_result;
+
+       FPP_INC(FPP_MVN);
+       PRINTF(("MNF prec=%d rnd=%d fd=%d fn=%d fm=%d\n",
+               op->precision, op->rounding, op->fpregd, op->fpregn, op->fpregm));
+
+       fpetos(&single_a, (fpe_reg_t *) &real1);
+       fpetos(&single_b, (fpe_reg_t *) &real2);
+       single_result = nc_fp_sub(single_a, single_b);
+       stofpe(&single_result, (fpe_reg_t *) &result);
+
+       fpregs[op->fpregd] = *(fpe_reg_t *) &result;
+       return(0);
+}
+
+
+/*
+* int fpe_abs(fp_op_data_t *op, trapframe_t *frame)
+*
+* ABS - Absolute value of a FP register
+*/
+
+int
+fpe_abs(op, frame)
+       fp_op_data_t *op;
+       trapframe_t *frame;
+{
+       fpe_qreg_t real1 = *(fpe_qreg_t *)&fpregs[8];
+       fpe_qreg_t real2 = *(fpe_qreg_t *)&fpregs[op->fpregm];
+       fpe_qreg_t result;
+       u_int32_t single_a, single_b, single_result;
+
+       FPP_INC(FPP_ABS);
+       PRINTF(("ABS prec=%d rnd=%d fd=%d fn=%d fm=%d\n",
+               op->precision, op->rounding, op->fpregd, op->fpregn, op->fpregm));
+
+       fpetos(&single_a, (fpe_reg_t *) &real2);
+       fpetos(&single_b, (fpe_reg_t *) &real1);
+       single_result = nc_fp_cmp(single_a, single_b);
+       if (single_result & 0x80000000) {
+               fpetos(&single_a, (fpe_reg_t *) &real1);
+               fpetos(&single_b, (fpe_reg_t *) &real2);
+               single_result = nc_fp_sub(single_a, single_b);
+               stofpe(&single_result, (fpe_reg_t *) &result);
+
+               fpregs[op->fpregd] = *(fpe_reg_t *) &result;
+       } else {
+               fpregs[op->fpregd] = fpregs[op->fpregm];
+       }
+
+       return(0);
+}
+
+
+/* Binary fp data operations */
+
+/*
+ * int fpe_adf(fp_op_data_t *op, trapframe_t *frame)
+ *
+ * ADF - Floating point add
+ */
+
+int
+fpe_adf(op, frame)
+       fp_op_data_t *op;
+       trapframe_t *frame;
+{
+       fpe_qreg_t real1 = *(fpe_qreg_t *)&fpregs[op->fpregn];
+       fpe_qreg_t real2 = *(fpe_qreg_t *)&fpregs[op->fpregm];
+       fpe_qreg_t result;
+       u_int32_t single_a, single_b, single_result;
+
+       FPP_INC(FPP_ADD);
+       PRINTF(("ADF prec=%d rnd=%d fd=%d fn=%d fm=%d\n",
+               op->precision, op->rounding, op->fpregd, op->fpregn, op->fpregm));
+
+       fpetos(&single_a, (fpe_reg_t *) &real1);
+       fpetos(&single_b, (fpe_reg_t *) &real2);
+       single_result = nc_fp_add(single_a, single_b);
+       stofpe(&single_result, (fpe_reg_t *) &result);
+       fpregs[op->fpregd] = *(fpe_reg_t *) &result;
+       return(0);
+}
+
+
+/*
+ * int fpe_suf(fp_op_data_t *op, trapframe_t *frame)
+ *
+ * SUF - Floating point subtract
+ */
+
+int
+fpe_suf(op, frame)
+       fp_op_data_t *op;
+       trapframe_t *frame;
+{
+       fpe_qreg_t real1 = *(fpe_qreg_t *)&fpregs[op->fpregn];
+       fpe_qreg_t real2 = *(fpe_qreg_t *)&fpregs[op->fpregm];
+       fpe_qreg_t result;
+       u_int32_t single_a, single_b, single_result;
+
+       FPP_INC(FPP_SUB);
+       PRINTF(("SUF prec=%d rnd=%d fd=%d fn=%d fm=%d\n",
+               op->precision, op->rounding, op->fpregd, op->fpregn, op->fpregm));
+
+       fpetos(&single_a, (fpe_reg_t *) &real1);
+       fpetos(&single_b, (fpe_reg_t *) &real2);
+       single_result = nc_fp_sub(single_a, single_b);
+       stofpe(&single_result, (fpe_reg_t *) &result);
+       fpregs[op->fpregd] = *(fpe_reg_t *) &result;
+       return(0);
+}
+
+
+/*
+ * int fpe_muf(fp_op_data_t *op, trapframe_t *frame)
+ *
+ * MUF - Floating point multiply
+ */
+
+int
+fpe_muf(op, frame)
+       fp_op_data_t *op;
+       trapframe_t *frame;
+{
+       fpe_qreg_t real1 = *(fpe_qreg_t *)&fpregs[op->fpregn];
+       fpe_qreg_t real2 = *(fpe_qreg_t *)&fpregs[op->fpregm];
+       fpe_qreg_t result;
+       u_int32_t single_a, single_b, single_result;
+
+       FPP_INC(FPP_MUL);
+       PRINTF(("MUF prec=%d rnd=%d fd=%d fn=%d fm=%d\n",
+               op->precision, op->rounding, op->fpregd, op->fpregn, op->fpregm));
+
+       fpetos(&single_a, (fpe_reg_t *) &real1);
+       fpetos(&single_b, (fpe_reg_t *) &real2);
+       single_result = nc_fp_mul(single_a, single_b);
+       stofpe(&single_result, (fpe_reg_t *) &result);
+               fpregs[op->fpregd] = *(fpe_reg_t *) &result;
+       return(0);
+}
+
+
+/*
+ * int fpe_dvf(fp_op_data_t *op, trapframe_t *frame)
+ *
+ * DVF - Floating point divide
+ */
+
+int fpe_dvf(fp_op_data_t *op, trapframe_t *frame)
+{
+       fpe_qreg_t real1 = *(fpe_qreg_t *)&fpregs[op->fpregn];
+       fpe_qreg_t real2 = *(fpe_qreg_t *)&fpregs[op->fpregm];
+       fpe_qreg_t result;
+       u_int32_t single_a, single_b, single_result;
+
+       FPP_INC(FPP_DIV);
+       PRINTF(("DVF prec=%d rnd=%d fd=%d fn=%d fm=%d\n", op->precision, op->rounding, op->fpregd, op->fpregn, op->fpregm));
+
+       fpetos(&single_a, (fpe_reg_t *) &real1);
+       fpetos(&single_b, (fpe_reg_t *) &real2);
+       single_result = nc_fp_div(single_a, single_b);
+       stofpe(&single_result, (fpe_reg_t *) &result);
+       fpregs[op->fpregd] = *(fpe_reg_t *) &result;
+       return(0);
+}
+
+
+/*
+ * int fpe_rdf(fp_op_data_t *op, trapframe_t *frame)
+ *
+ * RDF - Floating point reverse divide
+ */
+
+int
+fpe_rdf(op, frame)
+       fp_op_data_t *op;
+       trapframe_t *frame;
+{
+       fpe_qreg_t real1 = *(fpe_qreg_t *)&fpregs[op->fpregm];
+       fpe_qreg_t real2 = *(fpe_qreg_t *)&fpregs[op->fpregn];
+       fpe_qreg_t result;
+       u_int32_t single_a, single_b, single_result;
+
+       FPP_INC(FPP_RDV);
+       PRINTF(("RDF prec=%d rnd=%d fd=%d fn=%d fm=%d\n",
+               op->precision, op->rounding, op->fpregd, op->fpregn, op->fpregm));
+
+       fpetos(&single_a, (fpe_reg_t *) &real1);
+       fpetos(&single_b, (fpe_reg_t *) &real2);
+       single_result = nc_fp_div(single_a, single_b);
+       stofpe(&single_result, (fpe_reg_t *) &result);
+       fpregs[op->fpregd] = *(fpe_reg_t *) &result;
+       return(0);
+}
+
+
+/*
+ * int fpe_rsf(fp_op_data_t *op, trapframe_t *frame)
+ *
+ * RSF - Floating point reverse subtract
+ */
+
+int
+fpe_rsf(op, frame)
+       fp_op_data_t *op;
+       trapframe_t *frame;
+{
+       fpe_qreg_t real1 = *(fpe_qreg_t *)&fpregs[op->fpregm];
+       fpe_qreg_t real2 = *(fpe_qreg_t *)&fpregs[op->fpregn];
+       fpe_qreg_t result;
+       u_int32_t single_a, single_b, single_result;
+
+       FPP_INC(FPP_RSB);
+       PRINTF(("RSF prec=%d rnd=%d fd=%d fn=%d fm=%d\n",
+               op->precision, op->rounding, op->fpregd, op->fpregn, op->fpregm));
+
+       fpetos(&single_a, (fpe_reg_t *) &real1);
+       fpetos(&single_b, (fpe_reg_t *) &real2);
+       single_result = nc_fp_sub(single_a, single_b);
+       stofpe(&single_result, (fpe_reg_t *) &result);
+       fpregs[op->fpregd] = *(fpe_reg_t *) &result;
+       return(0);
+}
+
+
+/* FPE Register transfer instructions */
+
+/*
+* int fpe_flt(fp_op_data_t *op, trapframe_t *frame)
+*
+* FLT - Integer register to float register
+*/
+
+int
+fpe_flt(op, frame)
+       fp_op_data_t *op;
+       trapframe_t *frame;
+{
+       int regd;
+       fpe_reg_t real;
+       int *regs = &frame->tf_r0;
+
+       FPP_INC(FPP_FLT);
+       PRINTF(("FLT prec=%d rnd=%d rd=%d fn=%d fm=%d\n",
+               op->precision, op->rounding, op->regd, op->fpregn, op->fpregm));
+
+       regd = regs[op->regd];
+
+       if (regd > 0)
+               real.mantissa_lo = regd;
+       else
+               real.mantissa_lo = -regd;
+       real.mantissa_hi = 0;
+
+       if (regd == 0)
+               real.exponent = 0;
+       else {
+               real.exponent = 16383 + 63;
+
+               while ((real.mantissa_hi & (1 << 31)) == 0) {
+                       --real.exponent;
+                       real.mantissa_hi = real.mantissa_hi << 1;
+                       if (real.mantissa_lo & (1 << 31))
+                               real.mantissa_hi |= 1;
+                       real.mantissa_lo = real.mantissa_lo << 1;
+               }
+       }
+
+       if (regd < 0)
+               real.exponent |= (1 <<31);
+
+       fpregs[op->fpregn] = real;
+
+       return(0);
+}
+
+
+/*
+ * int fpe_fix(fp_op_data_t *op, trapframe_t *frame)
+ *
+ * FIX - Float register to integer register
+ */
+
+int
+fpe_fix(op, frame)
+       fp_op_data_t *op;
+       trapframe_t *frame;
+{
+       fpe_qreg_t src = *(fpe_qreg_t *) &fpregs[op->fpregm];
+       u_int32_t single_argument;
+       unsigned int *regs = &frame->tf_r0;
+
+       FPP_INC(FPP_FIX);
+       PRINTF(("FIX prec=%d rnd=%d rd=%d fn=%d fm=%d\n",
+               op->precision, op->rounding, op->regd, op->fpregn, op->fpregm));
+
+       fpetos(&single_argument, (fpe_reg_t *) &src);
+
+/*
+ * Call the assembler (32-bit) code for now
+ */
+       regs[op->regd] = nc_fp_fix(single_argument);
+       return(0);
+}
+
+
+/*
+ * int fpe_wfs(fp_op_data_t *op, trapframe_t *frame)
+ *
+ * WFS - Write FP status register
+ */
+
+int fpe_wfs(op, frame)
+       fp_op_data_t *op;
+       trapframe_t *frame;
+{
+       unsigned int *regs = &frame->tf_r0;
+
+       PRINTF(("WFS rd=%d\n", op->regd));
+
+       fpe_status = (fpe_status & ~FPE_STATUS_MASK)
+                       | (regs[op->regd] & FPE_STATUS_MASK);
+
+       return(0);
+}
+
+
+/*
+* int fpe_rfs(fp_op_data_t *op, trapframe_t *frame)
+*
+* RFS - Read FP status register
+*/
+
+int
+fpe_rfs(op, frame)
+       fp_op_data_t *op;
+       trapframe_t *frame;
+{
+       unsigned int *regs = &frame->tf_r0;
+
+       PRINTF(("RFS rd=%d\n", op->regd));
+
+       regs[op->regd] = fpe_status;
+
+       return(0);
+}
+
+
+/*
+ * int fpe_wfc(fp_op_data_t *op, trapframe_t *frame)
+ *
+ * WFC - Write FP control register
+ */
+
+int
+fpe_wfc(op, frame)
+       fp_op_data_t *op;
+       trapframe_t *frame;
+{
+       unsigned int *regs = &frame->tf_r0;
+
+       PRINTF(("WFC rd=%d\n", op->regd));
+
+       fpe_control = (fpe_control & ~FPE_CONTROL_MASK)
+                       | (regs[op->regd] & FPE_CONTROL_MASK);
+
+       return(0);
+}
+
+
+/*
+ * int fpe_rfc(fp_op_data_t *op, trapframe_t *frame)
+ *
+ * RFC - Read FP control register
+ */
+
+int
+fpe_rfc(op, frame)
+       fp_op_data_t *op;
+       trapframe_t *frame;
+{
+       unsigned int *regs = &frame->tf_r0;
+
+       PRINTF(("RFC rd=%d\n", op->regd));
+
+       regs[op->regd] = fpe_control;
+
+       return(0);
+}
+
+
+/*
+ * int fpe_cmf(fp_op_data_t *op, trapframe_t *frame)
+ *
+ * CMF - FP compare
+ */
+
+int
+fpe_cmf(op, frame)
+       fp_op_data_t *op;
+       trapframe_t *frame;
+{
+       fpe_qreg_t real1 = *(fpe_qreg_t *)&fpregs[op->fpregn];
+       fpe_qreg_t real2 = *(fpe_qreg_t *)&fpregs[op->fpregm];
+       u_int32_t single_a, single_b, single_result;
+
+       FPP_INC(FPP_CMF);
+       PRINTF(("CMF prec=%d rnd=%d rd=%d fn=%d fm=%d\n",
+               op->precision, op->rounding, op->regd, op->fpregn, op->fpregm));
+
+       fpetos(&single_a, (fpe_reg_t *) &real1);
+       fpetos(&single_b, (fpe_reg_t *) &real2);
+       single_result = nc_fp_cmp(single_a, single_b);
+       frame->tf_spsr = (frame->tf_spsr & ~0xf0000000) | (single_result & 0xf0000000);
+       return(0);
+}
+
+
+/*
+ * int fpe_cnf(fp_op_data_t *op, trapframe_t *frame)
+ *
+ * CNF - FP compare negated
+ */
+
+int
+fpe_cnf(op, frame)
+       fp_op_data_t *op;
+       trapframe_t *frame;
+{
+       fpe_qreg_t real0 = *(fpe_qreg_t *)&fpregs[8];
+       fpe_qreg_t real1 = *(fpe_qreg_t *)&fpregs[op->fpregn];
+       fpe_qreg_t real2 = *(fpe_qreg_t *)&fpregs[op->fpregm];
+       u_int32_t single_a, single_b, single_result;
+
+       FPP_INC(FPP_CNF);
+       PRINTF(("CNF prec=%d rnd=%d rd=%d fn=%d fm=%d\n",
+               op->precision, op->rounding, op->regd, op->fpregn, op->fpregm));
+
+       fpetos(&single_a, (fpe_reg_t *) &real0);
+       fpetos(&single_b, (fpe_reg_t *) &real2);
+       single_b = nc_fp_sub(single_a, single_b);
+
+       fpetos(&single_a, (fpe_reg_t *) &real1);
+       single_result = nc_fp_cmp(single_a, single_b);
+       frame->tf_spsr = (frame->tf_spsr & ~0xf0000000) | (single_result & 0xf0000000);
+       return(0);
+}
+
+
+/*
+ * int fpe_ldfstf(unsigned in instruction, trapframe_t *frame)
+ *
+ * LDF/STF - Load / store FP registers to / from memory
+ */
+
+
+int
+fpe_ldfstf(instruction, frame)
+       unsigned int instruction;
+       trapframe_t *frame;
+{
+       unsigned int *regs = &frame->tf_r0;
+       int offset;
+       int fpreg;
+       int reg;
+       u_int32_t address;
+       int precision;
+       int error = 0;
+
+       offset = (instruction & 0xff) << 2;
+
+       fpreg = (instruction >> 12) & 0x07;
+       reg = (instruction >> 16) & 0x0f;
+       precision = ((instruction & (1<<22)) ? 2 : 0)
+                       | ((instruction & (1<<15)) ? 1 : 0);
+
+       if (!(instruction & (1<<23)))
+               offset = -offset;
+
+       if (reg == 15)
+               printf("WARNING: LDF/STF using r15\n");
+
+       address = regs[reg];
+
+       if ((instruction & (1<<24)))
+               address += offset;
+
+       if (!(instruction & (1 << 20))) {
+               PRINTF(("STF rd=%d fd=%d prec=%d offset=%d address = %08x\n",
+                       reg, fpreg, precision, offset, address));
+
+               switch(precision) {
+               case 0 :
+                       FPP_INC(FPP_STRS);
+                       error = fpetos((u_int32_t *)address, &fpregs[fpreg]);
+                       break;
+               case 1 :
+                       FPP_INC(FPP_STRD);
+                       error = fpetod((u_int32_t *)address, &fpregs[fpreg]);
+                       break;
+               case 2 :
+                       FPP_INC(FPP_STRE);
+                       error = fpetoe((u_int32_t *)address, &fpregs[fpreg]);
+                       break;
+               case 3 :
+                       FPP_INC(FPP_STRP);
+                       error = fpetop((u_int32_t *)address, &fpregs[fpreg]);
+                       break;
+               }
+       } else {
+               PRINTF(("LDF rd=%d fd=%d prec=%d offset=%d address = %08x\n",
+                       reg, fpreg, precision, offset, address));
+
+               switch(precision) {
+               case 0 :
+                       FPP_INC(FPP_LDRS);
+                       error = stofpe((u_int32_t *)address, &fpregs[fpreg]);
+                       break;
+               case 1 :
+                       FPP_INC(FPP_LDRD);
+                       error = dtofpe((u_int32_t *)address, &fpregs[fpreg]);
+                       break;
+               case 2 :
+                       FPP_INC(FPP_LDRE);
+                       error = etofpe((u_int32_t *)address, &fpregs[fpreg]);
+                       break;
+               case 3 :
+                       FPP_INC(FPP_LDRP);
+                       error = ptofpe((u_int32_t *)address, &fpregs[fpreg]);
+                       break;
+               }
+       }
+
+       if (!(instruction & (1<<24)))
+               address += offset;
+
+       if ((instruction & (1<<21)))
+               regs[reg] = address;
+
+       return(error);
+}
+
+
+/* Debugging functions */
+
+int
+fpe_dump()
+{
+       int loop;
+
+       for (loop = 0; loop < 8; loop+=2) {
+               PRINTF(("f%2d : %08x %08x %08x   f%2d : %08x %08x %08x\n",
+                       loop, fpregs[loop].mantissa_hi,
+               fpregs[loop].mantissa_lo, fpregs[loop].exponent,
+                       loop+1, fpregs[loop+1].mantissa_hi,
+               fpregs[loop+1].mantissa_lo, fpregs[loop+1].exponent));
+       }
+       PRINTF(("\x1b[0mFPSR=%08x FPCR=%08x\n", fpe_status, fpe_control));
+       return(0);
+}
+
+
+#ifdef FPE_PROF
+void
+fpe_dump_prof()
+{
+       printf("adf : %6d\n", fp_profile[FPP_ADD]);
+       printf("suf : %6d\n", fp_profile[FPP_SUB]);
+       printf("muf : %6d\n", fp_profile[FPP_MUL]);
+       printf("dvf : %6d\n", fp_profile[FPP_DIV]);
+       printf("cmf : %6d\n", fp_profile[FPP_CMF]);
+       printf("cnf : %6d\n", fp_profile[FPP_CNF]);
+       printf("fix : %6d\n", fp_profile[FPP_FIX]);
+       printf("flt : %6d\n", fp_profile[FPP_FLT]);
+       printf("abs : %6d\n", fp_profile[FPP_ABS]);
+       printf("mvf : %6d\n", fp_profile[FPP_MOV]);
+       printf("mnf : %6d\n", fp_profile[FPP_MVN]);
+       printf("rdf : %6d\n", fp_profile[FPP_RDV]);
+       printf("rsf : %6d\n", fp_profile[FPP_RSB]);
+       printf("strs: %6d\n", fp_profile[FPP_STRS]);
+       printf("strd: %6d\n", fp_profile[FPP_STRD]);
+       printf("stre: %6d\n", fp_profile[FPP_STRE]);
+       printf("strp: %6d\n", fp_profile[FPP_STRP]);
+       printf("ldrs: %6d\n", fp_profile[FPP_LDRS]);
+       printf("ldrd: %6d\n", fp_profile[FPP_LDRD]);
+       printf("ldre: %6d\n", fp_profile[FPP_LDRE]);
+       printf("ldrp: %6d\n", fp_profile[FPP_LDRP]);
+}
+#else
+void
+fpe_dump_prof()
+{
+       printf("kernel not compiled with FPE profiling\n");
+}
+#endif
+
+/* End of fpe.c */
diff --git a/sys/arch/arm32/fpe-sp/fpeadd.S b/sys/arch/arm32/fpe-sp/fpeadd.S
new file mode 100644 (file)
index 0000000..395c441
--- /dev/null
@@ -0,0 +1,121 @@
+/* $NetBSD: fpeadd.S,v 1.2 1996/03/18 19:58:12 mark Exp $ */
+
+/*
+ * Copyright (c) 1995 Mark Brinicombe.
+ * Copyright (c) 1995 Neil Carson.
+ * 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 RiscBSD kernel team.
+ * 4. The name of the company nor the name of the author may be used to
+ *    endorse or promote products derived from this software without specific
+ *    prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHORS 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.
+ *
+ * RiscBSD kernel project
+ *
+ * fpeadd.S
+ *
+ * FP addition
+ *
+ * Created      : 11/02/95
+ */
+
+/* std. registers
+ */
+sp     .req    r13
+lr     .req    r14
+pc     .req    r15
+
+
+.global _nc_fp_add
+
+mant1  .req    r2
+xp1    .req    r3
+mant2  .req    r4
+xp2    .req    r5
+wrk1   .req    r14
+
+_nc_fp_add:
+    stmfd r13!,{r2-r5,r14}
+    mov xp1,r0,lsr #23                         /* get exponent+sign */
+    bic mant1,r0,xp1,lsl #23                   /* get mantissa */
+    cmp r0,#0
+    orrne mant1,mant1,#1<<23                   /* set on bit to left of point */
+    and xp1,xp1,#255                           /* remove sign */
+
+    mov xp2,r1,lsr #23                         /* get exponent+sign */
+    bic mant2,r1,xp2,lsl #23                   /* get mantissa */
+    cmp r1,#0
+    orrne mant2,mant2,#1<<23                   /* set on bit to left of point */
+    and xp2,xp2,#255                           /* remove sign */
+
+    eors wrk1,r0,r1                            /* both +ve/-ve? */
+    bmi fp_add_neg                             /* no, unequal signs */
+
+    subs wrk1,xp1,xp2                          /* exp. difference */
+    addpl mant1,mant1,mant2,lsr wrk1           /* xp1>exp2, round mant2 down */
+    rsbmi wrk1,wrk1,#0                         /* as +ve difference */
+    addmi mant1,mant2,mant1,lsr wrk1           /* xp1<exp2, round mant1 down */
+    movmi xp1,xp2                              /* exponent of result */
+    and   r0,r0,#1<<31                         /* set sign of result */
+    /* normalise mantissa & exponent */
+fp_add_rounddown:
+    cmp mant1,#1<<24
+    blt fp_add_normexit
+    add xp1,xp1,#1
+    mov mant1,mant1,lsr #1
+    b fp_add_rounddown
+
+    /* r0 or r1 is -ve */
+fp_add_neg:
+    subs wrk1,xp1,xp2                          /* exp. difference */
+    movpl mant2,mant2,lsr wrk1                 /* exp1>xp2, round mant2 */
+    rsbmi wrk1,wrk1,#0                         /* as +ve difference */
+    movmi mant1,mant1,lsr wrk1                 /* exp1<exp2, round mant1 */
+    movmi xp1,xp2                              /* exponent of result */
+
+    tst r0,#1<<31                              /* r0 -ve? */
+    subeq mant1,mant1,mant2                    /* no, r0=r0-r1 */
+    subne mant1,mant2,mant1                    /* yes, r0=r1-r0 */
+    cmp mant1,#0
+    rsbmi mant1,mant1,#0                       /* +ve mantissa */
+    movmi r0,#1<<31                            /* -ve result */
+    movpl r0,#0                                /* +ve result */
+    /* normalise result - adjust mantissa & exponent */
+    cmp mant1,#0                               /* check for 0 - special case */
+    moveq r0,#0
+    beq fp_add_exit
+fp_add_roundup:
+    tst mant1,#1<<23
+    bne fp_add_normexit
+    sub xp1,xp1,#1
+    mov mant1,mant1,lsl #1
+    b fp_add_roundup
+    /* combine result */
+fp_add_normexit:
+    orr r0,r0,xp1,lsl #23                      /* set exponent */
+    bic mant1,mant1,#1<<23                     /* clear hi-order */
+    orr r0,r0,mant1                            /* full result */
+fp_add_exit:
+    ldmfd r13!,{r2-r5,pc}
diff --git a/sys/arch/arm32/fpe-sp/fpecmf.S b/sys/arch/arm32/fpe-sp/fpecmf.S
new file mode 100644 (file)
index 0000000..088c5b2
--- /dev/null
@@ -0,0 +1,67 @@
+/* $NetBSD: fpecmf.S,v 1.2 1996/03/18 19:58:13 mark Exp $ */
+
+/*
+ * Copyright (c) 1995 Mark Brinicombe.
+ * Copyright (c) 1995 Neil Carson.
+ * 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 RiscBSD kernel team.
+ * 4. The name of the company nor the name of the author may be used to
+ *    endorse or promote products derived from this software without specific
+ *    prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHORS 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.
+ *
+ * RiscBSD kernel project
+ *
+ * fpecmf.S
+ *
+ * FP compare
+ *
+ * Created      : 11/02/95
+ */
+
+pc     .req    r15
+
+/* compare r0 with r1. sets status bits (in arm!) for result.*/
+
+       .global _nc_fp_cmp
+
+_nc_fp_cmp:
+    cmp r1,#0                                  /* r1 -ve? */
+    bmi fp_cmp_r0
+    cmp r0,r1                                  /* no - do normal cmp */
+    mrs        r0, cpsr_all
+    mov pc, r14
+fp_cmp_r0:
+    cmp r0,#0                                  /* r0 -ve? */ 
+    bmi fp_cmp_neg                             /* r0 & r1 -ve */
+    cmp r0,r1
+    mrs        r0, cpsr_all
+    mov pc, r14
+fp_cmp_neg:
+    cmp r1,r0                                  /* opposite compare */
+
+    mrs        r0, cpsr_all
+    mov pc, r14
+
diff --git a/sys/arch/arm32/fpe-sp/fpediv.S b/sys/arch/arm32/fpe-sp/fpediv.S
new file mode 100644 (file)
index 0000000..330d47f
--- /dev/null
@@ -0,0 +1,99 @@
+/* $NetBSD: fpediv.S,v 1.2 1996/03/18 19:58:14 mark Exp $ */
+
+/*
+ * Copyright (c) 1995 Mark Brinicombe.
+ * Copyright (c) 1995 Neil Carson.
+ * 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 RiscBSD kernel team.
+ * 4. The name of the company nor the name of the author may be used to
+ *    endorse or promote products derived from this software without specific
+ *    prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHORS 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.
+ *
+ * RiscBSD kernel project
+ *
+ * fpediv.S
+ *
+ * FP divide
+ *
+ * Created      : 11/02/95
+ */
+
+.global _nc_fp_div
+
+pc     .req    r15
+
+mant1  .req    r2
+xp1    .req    r3
+mant2  .req    r4
+xp2    .req    r14
+q      .req    r1
+p      .req    r14
+
+_nc_fp_div:
+    stmfd r13!,{r2-r4,r14}
+    /* check for null result */
+    cmp r0,#0
+    cmpne r1,#0
+    moveq r0,#0
+    beq fp_div_exit
+
+    mov xp1,r0,lsr #23                         /* get exponent+sign */
+    bic mant1,r0,xp1,lsl #23                   /* get mantissa */
+    orr mant1,mant1,#1<<23                     /* set on bit to left of point */
+    and xp1,xp1,#255                           /* remove sign */
+
+    mov xp2,r1,lsr #23                         /* get exponent+sign */
+    bic mant2,r1,xp2,lsl #23                   /* get mantissa */
+    orr mant2,mant2,#1<<23                     /* set on bit to left of point */
+    and xp2,xp2,#255                           /* remove sign */
+
+    sub xp1,xp1,xp2
+    adds xp1,xp1,#127                          /* exponent result */
+    movmi r0,#0                                /* underflow */
+    bmi fp_div_exit
+    eor r0,r0,r1                               /* sign of result */
+    and r0,r0,#1<<31                           /* clear rest of result */
+    /* do the divide to full precision */
+    mov q,#0                                   /* quotient */
+    mov p,#1<<23                               /* number binary places to do */
+fp_divloop:                                    /* do binary places */
+    cmp mant1,mant2                            /* number>divisor? */
+    orrcs q,q,p                                /* yes - set bit in binary place */
+    subcs mant1,mant1,mant2                    /* discard accounted value */
+    movs mant1,mant1,lsl #1                    /* shift up remainder, if any */
+    movnes p,p,lsr#1                           /* next binary place, if remainder */
+    bne fp_divloop                             /* next place if any */
+
+    cmp q,#1<<23                               /* normalise? */
+    sublt xp1,xp1,#1                           /* yes, adjust exponent */
+    movlt q,q,lsl #1                           /* & mantissa */
+    /* combine result */
+    orr r0,r0,xp1,lsl #23                      /* set exponent */
+    bic q,q,#1<<23                             /* clear hi-order */
+    orr r0,r0,q                                /* result */
+fp_div_exit:
+    ldmfd r13!,{r2-r4,pc}
+
diff --git a/sys/arch/arm32/fpe-sp/fpefix.S b/sys/arch/arm32/fpe-sp/fpefix.S
new file mode 100644 (file)
index 0000000..95c7c20
--- /dev/null
@@ -0,0 +1,72 @@
+/* $NetBSD: fpefix.S,v 1.2 1996/03/18 19:58:15 mark Exp $ */
+
+/*
+ * Copyright (c) 1995 Mark Brinicombe.
+ * Copyright (c) 1995 Neil Carson.
+ * 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 RiscBSD kernel team.
+ * 4. The name of the company nor the name of the author may be used to
+ *    endorse or promote products derived from this software without specific
+ *    prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHORS 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.
+ *
+ * RiscBSD kernel project
+ *
+ * fpefix.S
+ *
+ * FP register to integer
+ *
+ * Created      : 11/02/95
+ */
+
+/* std. registers
+ */
+sp     .req    r13
+lr     .req    r14
+pc     .req    r15
+
+
+mant1  .req    r0
+xp1    .req    r1
+
+    .global _nc_fp_fix
+
+_nc_fp_fix:
+    cmp r0,#0
+    moveq pc,r14
+    mov xp1,r0,lsr #23
+    bic mant1,r0,xp1,lsl #23
+    orr mant1,mant1,#1<<23
+    tst xp1,#1<<8
+    rsbne mant1,mant1,#0
+    bic xp1,xp1,#1<<8
+    subs xp1,xp1,#127
+    movmi r0,#0
+    movmi pc,r14
+    rsbs xp1,xp1,#23
+    movpl mant1,mant1,asr xp1
+    rsbmi xp1,xp1,#0
+    movmi mant1,mant1,asl xp1
+    mov pc,r14
diff --git a/sys/arch/arm32/fpe-sp/fpemul.S b/sys/arch/arm32/fpe-sp/fpemul.S
new file mode 100644 (file)
index 0000000..43c4f23
--- /dev/null
@@ -0,0 +1,99 @@
+/* $NetBSD: fpemul.S,v 1.2 1996/03/18 19:58:16 mark Exp $ */
+
+/*
+ * Copyright (c) 1995 Mark Brinicombe.
+ * Copyright (c) 1995 Neil Carson.
+ * 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 RiscBSD kernel team.
+ * 4. The name of the company nor the name of the author may be used to
+ *    endorse or promote products derived from this software without specific
+ *    prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHORS 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.
+ *
+ * RiscBSD kernel project
+ *
+ * fpemul.S
+ *
+ * FP multiply
+ *
+ * Created      : 11/02/95
+ */
+
+.global _nc_fp_mul
+
+pc     .req    r15
+
+mant1  .req    r2
+xp1    .req    r3
+mant2  .req    r1
+xp2    .req    r4
+wrk1   .req    r14
+reshigh        .req    r4
+
+_nc_fp_mul:
+    stmfd r13!,{r2-r4,r14}
+    /* check for null result - bloody lucky but you never know... */
+    cmp r0,#0
+    cmpne r1,#0
+    moveq r0,#0
+    beq fp_mul_exit
+
+    mov xp1,r0,lsr #23                         /* get exponent+sign */
+    bic mant1,r0,xp1,lsl #23                   /* get mantissa */
+    orr mant1,mant1,#1<<23                     /* set on bit to left of point */
+    and xp1,xp1,#255                           /* remove sign */
+
+    eor r0,r0,r1                               /* sign of result */
+    and r0,r0,#1<<31                           /* clear rest of result */
+
+    mov xp2,r1,lsr #23                         /* get exponent+sign */
+    bic mant2,r1,xp2,lsl #23                   /* get mantissa */
+    orr mant2,mant2,#1<<23                     /* set on bit to left of point */
+    and xp2,xp2,#255                           /* remove sign */
+
+    add xp1,xp1,xp2
+    subs xp1,xp1,#127                          /* exponent result */
+    movmi r0,#0                                /* underflow */
+    bmi fp_mul_exit
+    /* do the multiply to 30 bits precision */
+    mov wrk1,mant1,lsr#9                       /* top 15 bits */
+    mov reshigh,mant2,lsr#9                    /* top 15 bits */
+    bic mant1,mant1,wrk1,lsl#9                 /* low  9 bits */
+    bic mant2,mant2,reshigh,lsl#9              /* low  9 bits */
+    mul mant2,wrk1,mant2                       /* top*low */
+    mul mant1,reshigh,mant1                    /* low*top */
+    mul reshigh,wrk1,reshigh                   /* top*top */
+    add reshigh,reshigh,mant1,lsr#9            /* top + middle bit1 */
+    add reshigh,reshigh,mant2,lsr#9            /* top + middle bit2 */
+    /* adjust for carry */
+    tst reshigh,#1<<29
+    addne xp1,xp1,#1                           /* adjust exponent */
+    movne reshigh,reshigh,lsr#1                /* shift result right */
+    /* combine result */
+    orr r0,r0,xp1,lsl #23                      /* set exponent */
+    bic reshigh,reshigh,#1<<28                 /* clear hi-order */
+    orr r0,r0,reshigh,lsr #5                   /* top 23 bits */
+fp_mul_exit:
+    ldmfd r13!,{r2-r4,pc}
diff --git a/sys/arch/arm32/fpe-sp/fpesub.S b/sys/arch/arm32/fpe-sp/fpesub.S
new file mode 100644 (file)
index 0000000..c1f62b0
--- /dev/null
@@ -0,0 +1,113 @@
+/* $NetBSD: fpesub.S,v 1.2 1996/03/18 19:58:18 mark Exp $ */
+
+/*
+ * Copyright (c) 1995 Mark Brinicombe.
+ * Copyright (c) 1995 Neil Carson.
+ * 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 RiscBSD kernel team.
+ * 4. The name of the company nor the name of the author may be used to
+ *    endorse or promote products derived from this software without specific
+ *    prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHORS 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.
+ *
+ * RiscBSD kernel project
+ *
+ * fpesub.S
+ *
+ * FP subtract
+ *
+ * Created      : 11/02/95
+ */
+
+.global _nc_fp_sub
+
+pc     .req    r15
+
+mant1  .req    r2
+xp1    .req    r3
+mant2  .req    r4
+xp2    .req    r5
+wrk1   .req    r14
+
+_nc_fp_sub:
+    stmfd r13!,{r2-r5,r14}
+    mov xp1,r0,lsr #23                         /* get exponent+sign */
+    bic mant1,r0,xp1,lsl #23                   /* get mantissa */
+    cmp r0,#0
+    orrne mant1,mant1,#1<<23                   /* set on bit to left of point */
+    and xp1,xp1,#255                           /* remove sign */
+
+    mov xp2,r1,lsr #23                         /* get exponent+sign */
+    bic mant2,r1,xp2,lsl #23                   /* get mantissa */
+    cmp r1,#0
+    orrne mant2,mant2,#1<<23                   /* set on bit to left of point */
+    and xp2,xp2,#255                           /* remove sign */
+
+    eors wrk1,r0,r1                            /* both +ve/-ve? */
+    bmi fp_sub_unequal                         /* no - special case */
+
+    subs wrk1,xp1,xp2                          /* exp. difference */
+    subpl mant1,mant1,mant2,lsr wrk1           /* exp1>exp2, round mant2 & subtract */
+    rsbmi wrk1,wrk1,#0                         /* as +ve difference */
+    rsbmi mant1,mant2,mant1,lsr wrk1           /* exp1<exp2, round mant1 & subtract */
+    movmi xp1,xp2                              /* exponent of result */
+    and r0,r0,#1<<31                           /* default sign of result */
+    cmp mant1,#0                               /* flip sign? */
+    rsbmi mant1,mant1,#0                       /* yes - flip mantissa */
+    eormi r0,r0,#1<<31                         /* and final sign */
+    /* normalise result - adjust mantissa & exponent */
+    cmp mant1,#0                               /* check for 0 - special case */
+    moveq r0,#0
+    beq fp_sub_exit
+fp_sub_roundup:
+    tst mant1,#1<<23
+    bne fp_sub_normexit
+    sub xp1,xp1,#1
+    mov mant1,mant1,lsl #1
+    b fp_sub_roundup
+
+    /* r0 & r1 have different signs - add */
+fp_sub_unequal:
+    subs wrk1,xp1,xp2                          /* exp. difference */
+    addpl mant1,mant1,mant2,lsr wrk1      /* exp1>exp2, round mant2 & add */
+    rsbmi wrk1,wrk1,#0                         /* as +ve difference */
+    addmi mant1,mant2,mant1,lsr wrk1      /* exp1<exp2, round mant1 & add */
+    movmi xp1,xp2                              /* exponent of result */
+    and r0,r0,#1<<31                           /* sign of result */
+    /* normalise result - adjust mantissa & exponent */
+fp_sub_rounddown:
+    cmp mant1,#1<<24
+    blt fp_sub_normexit
+    add xp1,xp1,#1
+    mov mant1,mant1,lsr #1
+    b fp_sub_rounddown
+    /* combine result */
+fp_sub_normexit:
+    orr r0,r0,xp1,lsl #23                      /* set exponent */
+    bic mant1,mant1,#1<<23                     /* clear hi-order */
+    orr r0,r0,mant1                            /* full result */
+fp_sub_exit:
+    ldmfd r13!,{r2-r5,pc}
+
diff --git a/sys/arch/arm32/fpe-sp/fpetoe.S b/sys/arch/arm32/fpe-sp/fpetoe.S
new file mode 100644 (file)
index 0000000..ba5ca1e
--- /dev/null
@@ -0,0 +1,62 @@
+/* $NetBSD: fpetoe.S,v 1.2 1996/03/18 19:58:19 mark Exp $ */
+
+/*
+ * Copyright (c) 1995 Mark Brinicombe.
+ * Copyright (c) 1995 Neil Carson.
+ * 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 RiscBSD kernel team.
+ * 4. The name of the company nor the name of the author may be used to
+ *    endorse or promote products derived from this software without specific
+ *    prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHORS 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.
+ *
+ * RiscBSD kernel project
+ *
+ * fpetoe.S
+ *
+ * optimised functions for coping extended precision registers
+ *
+ * Created      : 11/02/95
+ */
+
+lr     .req    r14
+pc     .req    r15
+
+       .text
+       .align  0
+       .global _etofpe
+_etofpe:
+       ldmia   r0, {r0, r2-r3}
+       stmia   r1, {r0, r2-r3}
+       mov     r0, #0
+       mov     pc, r14
+
+       .align  0
+       .global _fpetoe
+_fpetoe:
+       ldmia   r1, {r1, r2-r3}
+       stmia   r0, {r1, r2-r3}
+       mov     r0, #0
+       mov     pc, r14
diff --git a/sys/arch/arm32/include/ansi.h b/sys/arch/arm32/include/ansi.h
new file mode 100644 (file)
index 0000000..5743081
--- /dev/null
@@ -0,0 +1,75 @@
+/* $NetBSD: ansi.h,v 1.3 1996/03/16 01:31:48 jtc 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.
+ *
+ *     from: @(#)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_WINT_T_   int                     /* wint_t */
+#define        _BSD_RUNE_T_    int                     /* rune_t */
+
+#endif /* _ANSI_H_ */
diff --git a/sys/arch/arm32/include/asm.h b/sys/arch/arm32/include/asm.h
new file mode 100644 (file)
index 0000000..fab79a2
--- /dev/null
@@ -0,0 +1,73 @@
+/* $NetBSD: asm.h,v 1.2 1996/03/14 23:11:03 mark 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.
+ *
+ *     from: @(#)asm.h 5.5 (Berkeley) 5/7/91
+ */
+
+#ifndef _ARM32_ASM_H_
+#define _ARM32_ASM_H_
+
+#ifdef PROF
+/*
+ * XXX assumes that arguments are not passed in %eax
+ */
+# define _BEGIN_ENTRY  /*.data; 1:; .long 0;*/ .text; .align 0
+# define _END_ENTRY    /*movl $1b,%eax; call PIC_PLT(mcount)*/
+#else
+# define _BEGIN_ENTRY  .text; .align 0
+# define _END_ENTRY
+#endif
+
+#ifdef __STDC__
+# define _C_FUNC(x)    _ ## x
+#else
+# define _C_FUNC(x)    _/**/x
+#endif
+#define        _ASM_FUNC(x)    x
+
+#define _ENTRY(x)      .globl x; /*.type x,@function;*/ x:
+
+#define        ENTRY(y)        _BEGIN_ENTRY; _ENTRY(_C_FUNC(y)); _END_ENTRY
+#define        TWOENTRY(y,z)   _BEGIN_ENTRY; _ENTRY(_C_FUNC(y)); _ENTRY(_C_FUNC(z)); \
+                       _END_ENTRY
+#define        ASENTRY(y)      _BEGIN_ENTRY; _ENTRY(_ASM_FUNC(y)); _END_ENTRY
+
+#define        ASMSTR          .asciz
+
+#define RCSID(x)       .text; .asciz x
+
+#endif /* !_ARM_ASM_H_ */
diff --git a/sys/arch/arm32/include/beep.h b/sys/arch/arm32/include/beep.h
new file mode 100644 (file)
index 0000000..64fcd37
--- /dev/null
@@ -0,0 +1,43 @@
+/* $NetBSD: beep.h,v 1.2 1996/03/14 23:11:04 mark Exp $ */
+
+/*
+ * Copyright (c) Mark Brinicombe 1995 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 RiscBSD team.
+ * 4. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/types.h>
+
+struct wavebuffer {
+       caddr_t addr;
+       int size;
+};
+
+#define BEEP_GENERATE  _IO ( 'B', 100)
+#define BEEP_SETRATE   _IO ( 'B', 101)
+#define BEEP_SET       _IOW ( 'B', 102, struct wavebuffer )
+
+/* End of beep.h */
diff --git a/sys/arch/arm32/include/bootconfig.h b/sys/arch/arm32/include/bootconfig.h
new file mode 100644 (file)
index 0000000..d7acfdd
--- /dev/null
@@ -0,0 +1,89 @@
+/* $NetBSD: bootconfig.h,v 1.2 1996/03/14 23:11:06 mark Exp $ */
+
+/*
+ * Copyright (c) 1994 Mark Brinicombe.
+ * Copyright (c) 1994 Brini.
+ * All rights reserved.
+ *
+ * This code is derived from software written for Brini by Mark Brinicombe
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided 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 Brini.
+ * 4. The name of the company nor the name of the author may be used to
+ *    endorse or promote products derived from this software without specific
+ *    prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BRINI ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL BRINI 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.
+ *
+ * RiscBSD kernel project
+ *
+ * bootconfig.h
+ *
+ * boot configuration structure
+ *
+ * Created      : 12/09/94
+ *
+ * Based on kate/boot/bootconfig.h
+ */
+
+typedef struct _PhysMem {
+       u_int address;
+       u_int pages;
+} PhysMem;
+
+typedef struct _BootConfig {
+       u_int kernvirtualbase;
+       u_int kernphysicalbase;
+       u_int kernsize;
+       u_int argvirtualbase;
+       u_int argphysicalbase;
+       u_int argsize;
+       u_int scratchvirtualbase;
+       u_int scratchphysicalbase;
+       u_int scratchsize;
+
+       u_int display_start;
+       u_int display_size;
+       u_int width;
+       u_int height;
+       u_int bitsperpixel;
+
+       PhysMem dram[4];
+       PhysMem vram[1];
+
+       u_int dramblocks;
+       u_int vramblocks;
+       u_int pagesize;
+       u_int drampages;
+       u_int vrampages;
+
+       char kernelname[80];
+
+       u_int framerate;
+       u_char machine_id[4];
+} BootConfig;
+
+#ifdef _KERNEL
+extern BootConfig bootconfig;
+#endif
+
+/* End of bootconfig.h */
diff --git a/sys/arch/arm32/include/cdefs.h b/sys/arch/arm32/include/cdefs.h
new file mode 100644 (file)
index 0000000..36ffac6
--- /dev/null
@@ -0,0 +1,35 @@
+/* $NetBSD: cdefs.h,v 1.1 1996/01/31 23:21:36 mark 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 __weak_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 __weak_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/arm32/include/cpu.h b/sys/arch/arm32/include/cpu.h
new file mode 100644 (file)
index 0000000..3d79f4d
--- /dev/null
@@ -0,0 +1,204 @@
+/* $NetBSD: cpu.h,v 1.6 1996/04/02 21:45:25 mark Exp $ */
+
+/*
+ * Copyright (c) 1994-1996 Mark Brinicombe.
+ * Copyright (c) 1994 Brini.
+ * All rights reserved.
+ *
+ * This code is derived from software written for Brini by Mark Brinicombe
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided 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 Brini.
+ * 4. The name of the company nor the name of the author may be used to
+ *    endorse or promote products derived from this software without specific
+ *    prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BRINI ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL BRINI 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.
+ *
+ * RiscBSD kernel project
+ *
+ * cpu.h
+ *
+ * CPU specific symbols
+ *
+ * Created      : 18/09/94
+ *
+ * Based on kate/katelib/arm6.h
+ */
+
+#ifndef _ARM32_CPU_H_
+#define _ARM32_CPU_H_
+
+#ifndef _LOCORE
+#include <machine/frame.h>
+#endif
+#include <machine/psl.h>
+
+/*
+ * If we are not an ARM6 then we MUST use late aborts as only the ARM6
+ * supports early aborts.
+ * For the ARM6 we will use early abort unless otherwise configured
+ * This reduces the overheads of LDR/STR aborts and no correction is required.
+ */
+
+#ifndef CPU_ARM6
+#define CPU_LATE_ABORTS
+#endif
+
+#define COPY_SIGCODE    /* copy sigcode above user stack in exec */
+/*
+ * ARM Process Status Register
+ *
+ * The picture in the ARM manuals looks like this:
+ *       3 3 2 2 2                              
+ *       1 0 9 8 7                                     8 7 6 5 4       0
+ *      +-------+---------------------------------------+-+-+-+---------+
+ *      | flags |                  reserved             |I|F| |M M M M M|
+ *      |n z c v|                                       | | | |4 3 2 1 0|
+ *      +-------+---------------------------------------+-+-+-+---------+
+ */
+
+#define        PSR_FLAGS 0xf0000000    /* flags */
+#define PSR_N_bit (1 << 31)    /* negative */
+#define PSR_Z_bit (1 << 30)    /* zero */
+#define PSR_C_bit (1 << 29)    /* carry */
+#define PSR_V_bit (1 << 28)    /* overflow */
+
+#define I32_bit (1 << 7)
+#define F32_bit (1 << 6)
+
+#define PSR_MODE       0x0000001f
+#define PSR_USR32_MODE 0x00000010
+#define PSR_FIQ32_MODE 0x00000011
+#define PSR_IRQ32_MODE 0x00000012
+#define PSR_SVC32_MODE 0x00000013
+#define PSR_ABT32_MODE 0x00000017
+#define PSR_UND32_MODE 0x0000001b
+
+#define CPU_ID_DESIGNER_MASK   0xff000000
+#define CPU_ID_ARM_LTD         0x41000000
+#define CPU_ID_DEC             0x44000000
+#define CPU_ID_MAKER_MASK      0x00ff0000
+#define CPU_ID_GPS             0x00560000
+#define CPU_ID_VLSI            0x00000000
+#define CPU_ID_CPU_MASK                0x0000fff0
+#define ID_ARM610              0x00000610
+#define ID_ARM700              0x00007000
+#define ID_ARM710              0x00007100
+#define ID_SARM110             0x0000a100
+#define CPU_ID_REVISION_MASK   0x0000000f
+
+#define CPU_CONTROL_MMU_ENABLE 0x0001
+#define CPU_CONTROL_AFLT_ENABLE        0x0002
+#define CPU_CONTROL_DC_ENABLE  0x0004
+#define CPU_CONTROL_WBUF_ENABLE 0x0008
+#define CPU_CONTROL_32BP_ENABLE 0x0010
+#define CPU_CONTROL_32BD_ENABLE 0x0020
+#define CPU_CONTROL_LABT_ENABLE 0x0040
+#define CPU_CONTROL_BEND_ENABLE 0x0080
+#define CPU_CONTROL_SYST_ENABLE 0x0100
+#define CPU_CONTROL_ROM_ENABLE 0x0200
+#define CPU_CONTROL_CPCLK      0x0400
+#define CPU_CONTROL_IC_ENABLE   0x1000
+
+/* StrongARM has separate instruction and data caches */
+
+#ifdef CPU_SA
+#define CPU_CONTROL_IDC_ENABLE (CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE)
+#else
+#define CPU_CONTROL_IDC_ENABLE CPU_CONTROL_DC_ENABLE
+#endif
+
+#define FAULT_TYPE_MASK 0x0f
+#define FAULT_USER      0x10
+
+#define FAULT_WRTBUF_0  0x00
+#define FAULT_WRTBUF_1  0x02
+#define FAULT_BUSERR_0  0x04
+#define FAULT_BUSERR_1  0x06
+#define FAULT_BUSERR_2  0x08
+#define FAULT_BUSERR_3  0x0a
+#define FAULT_ALIGN_0   0x01 
+#define FAULT_ALIGN_1   0x03 
+#define FAULT_BUSTRNL1  0x0c
+#define FAULT_BUSTRNL2  0x0e
+#define FAULT_TRANS_S   0x05
+#define FAULT_TRANS_P   0x07
+#define FAULT_DOMAIN_S  0x09
+#define FAULT_DOMAIN_P  0x0b
+#define FAULT_PERM_S    0x0d
+#define FAULT_PERM_P    0x0f
+
+#ifdef _LOCORE
+#define IRQdisable \
+       stmfd   sp!, {r0} ; \
+       mrs     r0, cpsr_all ; \
+       orr     r0, r0, #(I32_bit | F32_bit) ; \
+       msr     cpsr_all, r0 ; \
+       ldmfd   sp!, {r0}
+
+#define IRQenable \
+       stmfd   sp!, {r0} ; \
+       mrs     r0, cpsr_all ; \
+       bic     r0, r0, #(I32_bit | F32_bit) ; \
+       msr     cpsr_all, r0 ; \
+       ldmfd   sp!, {r0}               
+
+#else
+#define IRQdisable SetCPSR(I32_bit | F32_bit, I32_bit | F32_bit);
+#define IRQenable SetCPSR(I32_bit | F32_bit, 0);
+#endif /* _LOCORE */
+
+/*
+ * Return TRUE/FALSE (1/0) depending on whether the frame came from USR
+ * mode or not.
+ */
+#define CLKF_USERMODE(frame) ((frame->if_spsr & PSR_MODE) == PSR_USR32_MODE)
+
+#define CLKF_BASEPRI(frame) (1)
+
+#define CLKF_PC(frame) (frame->if_pc)
+
+/*#define CLKF_INTR(frame) ((frame->if_spsr & PSR_MODE) == PSR_IRQ32_MODE)*/
+
+/* Hack to treat FPE time as interrupt time so we can measure it */
+#define CLKF_INTR(frame) ((frame->if_spsr & PSR_MODE) == PSR_UND32_MODE)
+
+/*
+ * definitions of cpu-dependent requirements
+ * referenced in generic code
+ */
+
+#define cpu_wait(p)    /* nothing */
+
+/*
+ * Notify the current process (p) that it has a signal pending,
+ * process as soon as possible.
+ */
+
+#define signotify(p)            setsoftast()
+    
+#endif /* _ARM32_CPU_H_ */
+
+/* End of cpu.h */
diff --git a/sys/arch/arm32/include/cpus.h b/sys/arch/arm32/include/cpus.h
new file mode 100644 (file)
index 0000000..26ca72c
--- /dev/null
@@ -0,0 +1,160 @@
+/* $NetBSD: cpus.h,v 1.3 1996/03/14 23:11:08 mark Exp $ */
+
+/*
+ * Copyright (c) 1995 Mark Brinicombe.
+ * Copyright (c) 1995 Brini.
+ * 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 Brini.
+ * 4. The name of the company nor the name of the author may be used to
+ *    endorse or promote products derived from this software without specific
+ *    prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BRINI ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL BRINI 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.
+ *
+ * RiscBSD kernel project
+ *
+ * cpus.h
+ *
+ * cpu device header file
+ *
+ * Created      : 26/12/95
+ */
+
+#ifndef _LOCORE
+#include <sys/param.h>
+#endif
+
+/* If hydra is defined then we take into consideration the slave CPU's available */
+
+#ifdef HYDRA
+#define MAX_CPUS               6
+#define MAX_SLAVE_CPUS         4
+#define MAX_FOREIGN_CPUS       1
+#else
+#define MAX_CPUS               2
+#define MAX_SLAVE_CPUS         0
+#define MAX_FOREIGN_CPUS       1
+#endif
+
+#define CPU_MASTER     0
+#define CPU_486                1
+#define CPU_SLAVE      2
+
+#define CPU_CLASS_NONE 0       /* No CPU */
+#define CPU_CLASS_ARM  1       /* ARM 6/7/8 */
+#define CPU_CLASS_SARM 2       /* Guess */
+#define CPU_CLASS_I486 3       /* 486/586 */
+
+#define CPU_HOST_NONE          0       /* No host */
+#define CPU_HOST_MAINBUS       1       /* Hosted via motherboard */
+#define CPU_HOST_HYDRA         2       /* Hosted via hydra multiprocessor board */
+
+#define CPU_FLAG_PRESENT       0x01
+#define CPU_FLAG_HALTED                0x02
+
+#define FPU_CLASS_NONE         0       /* no Floating point support */
+#define FPU_CLASS_FPE          1       /* Floating point emulator installed */
+#define FPU_CLASS_FPA          2       /* Floating point accelerator installed */
+#define FPU_CLASS_FPU          3       /* Floating point unit installed */
+
+#define FPU_TYPE_SP_FPE                1       /* Single precision FPE */
+#define FPU_TYPE_ARMLTD_FPE    2       /* ARM Ltd FPE */
+#define FPU_TYPE_FPA11         0x81    /* ID of FPA11 */
+
+#ifndef _LOCORE
+
+/* Define the structure used to describe a cpu */
+
+typedef struct cpu_arm {
+       u_int cpu_id;           /* The CPU id */
+       u_int cpu_ctrl;         /* The CPU control register */
+
+       u_int cpu_svc_r13;      /* local data */
+       u_int cpu_und_r13;      /* local data */
+       u_int cpu_abt_r13;      /* local data */
+       u_int cpu_irq_r13;      /* local data */
+} cpu_arm_t;
+
+typedef struct cpu_sarm {
+       u_int cpu_id;           /* The CPU id */
+       u_int cpu_ctrl;         /* The CPU control register */
+} cpu_sarm_t;
+
+typedef struct cpu_i486 {
+       u_int cpu_id;           /* The CPU id */
+       u_int cpu_ctrl;         /* The CPU control register */
+} cpu_i486_t;
+
+
+typedef struct _cpu {
+/* These are generic CPU variables */
+
+       u_int   cpu_class;      /* The CPU class */
+       u_int   cpu_type;       /* The CPU type */
+       u_int   cpu_host;       /* The CPU host interface */
+       u_int   cpu_flags;      /* The CPU flags */
+       char    cpu_model[256]; /* Text description of CPU */
+
+/* These are generic FPU variables */
+
+       u_int   fpu_class;      /* The FPU class */
+       u_int   fpu_type;       /* The FPU type */
+       u_int   fpu_flags;      /* The FPU flags */
+       char    fpu_model[256]; /* Text description of FPU */
+
+/* These are ARM specific variables */
+
+       u_int cpu_id;           /* The CPU id */
+       u_int cpu_ctrl;         /* The CPU control register */
+
+       u_int cpu_svc_r13;      /* local data */
+       u_int cpu_und_r13;      /* local data */
+       u_int cpu_abt_r13;      /* local data */
+       u_int cpu_irq_r13;      /* local data */
+
+/* Not used yet */
+
+       union {
+               cpu_arm_t       cpu_arm;
+               cpu_sarm_t      cpu_sarm;
+               cpu_i486_t      cpu_i486;
+       } cpu_local;
+} cpu_t;
+
+
+struct cpu_softc {
+       struct  device sc_device;
+       int     sc_open;
+};
+
+#ifdef _KERNEL
+
+/* Array of cpu structures, one per possible cpu */
+
+extern cpu_t cpus[MAX_CPUS];
+
+#endif /* _KERNEL */
+#endif /* _LOCORE */
+
+/* End of hydra.h */
diff --git a/sys/arch/arm32/include/db_machdep.h b/sys/arch/arm32/include/db_machdep.h
new file mode 100644 (file)
index 0000000..2000290
--- /dev/null
@@ -0,0 +1,85 @@
+/* $NetBSD: db_machdep.h,v 1.2 1996/03/06 23:16:54 mark Exp $ */
+
+/*
+ * Copyright (c) 1996 Scott K Stevens
+ * 
+ * Mach Operating System
+ * Copyright (c) 1991,1990 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 "AS IS"
+ * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ * 
+ * Carnegie Mellon requests users of this software to return to
+ * 
+ *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
+ *  School of Computer Science
+ *  Carnegie Mellon University
+ *  Pittsburgh PA 15213-3890
+ * 
+ * any improvements or extensions that they make and grant Carnegie Mellon
+ * the rights to redistribute these changes.
+ */
+
+#ifndef        _ARM32_DB_MACHDEP_H_
+#define        _ARM32_DB_MACHDEP_H_
+
+/*
+ * Machine-dependent defines for new kernel debugger.
+ */
+
+
+#include <vm/vm.h>
+#include <machine/frame.h>
+#include <machine/psl.h>
+#include <machine/reg.h>
+
+/* end of mangling */
+
+typedef        vm_offset_t     db_addr_t;      /* address - unsigned */
+typedef        int             db_expr_t;      /* expression - signed */
+
+typedef struct {
+       trapframe_t     ddb_tf;
+} db_regs_t;
+
+db_regs_t              ddb_regs;       /* register state */
+#define        DDB_REGS        (&ddb_regs)
+#define        DDB_TF          (&ddb_regs.ddb_tf)
+
+#define        PC_REGS(regs)   ((db_addr_t)(regs)->ddb_tf.tf_pc)
+
+#define        BKPT_INST       (0xe7ffffff)    /* breakpoint instruction */
+#define        BKPT_SIZE       (4)             /* size of breakpoint inst */
+#define        BKPT_SET(inst)  (BKPT_INST)
+
+/*#define      db_clear_single_step(regs)      (0)
+#define        db_set_single_step(regs)        (0)*/
+
+#define T_BREAKPOINT                   (1)
+
+#define        IS_BREAKPOINT_TRAP(type, code)  ((type) == T_BREAKPOINT)
+#define IS_WATCHPOINT_TRAP(type, code) (0)
+
+#define        inst_trap_return(ins)   ((ins)&0)
+#define        inst_return(ins)        ((ins)&0)
+#define        inst_call(ins)          (((ins) & 0x0f000000) == 0x0b000000)
+#define        inst_branch(ins)        (((ins) & 0x0f000000) == 0x0a000000)
+#define inst_load(ins)         0
+#define inst_store(ins)                0
+
+#define getreg_val             (0)
+#define next_instr_address(pc, bd)     (pc + 4)
+
+#define DB_MACHINE_COMMANDS
+
+#define SOFTWARE_SSTEP
+
+#endif /* _ARM32_DB_MACHDEP_H_ */
diff --git a/sys/arch/arm32/include/disklabel.h b/sys/arch/arm32/include/disklabel.h
new file mode 100644 (file)
index 0000000..5178925
--- /dev/null
@@ -0,0 +1,134 @@
+/* $NetBSD: disklabel.h,v 1.2 1996/03/06 23:17:51 mark Exp $ */
+
+/*
+ * Copyright (c) 1994 Mark Brinicombe.
+ * Copyright (c) 1994 Brini.
+ * All rights reserved.
+ *
+ * This code is derived from software written for Brini by Mark Brinicombe
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided 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 Brini.
+ * 4. The name of the company nor the name of the author may be used to
+ *    endorse or promote products derived from this software without specific
+ *    prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BRINI ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL BRINI 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.
+ *
+ * RiscBSD kernel project
+ *
+ * disklabel.h
+ *
+ * machine specific disk label info
+ *
+ * Created      : 04/10/94
+ */
+
+#ifndef _ARM32_DISKLABEL_H_
+#define _ARM32_DISKLABEL_H_
+
+#define LABELSECTOR    1               /* sector containing label */
+#define LABELOFFSET    0               /* offset of label in sector */
+#define MAXPARTITIONS  8               /* number of partitions */
+#define RAW_PART       2               /* raw partition: XX?c */
+
+#define NRISCBSD_PARTITIONS MAXPARTITIONS
+
+#define PARTITION_TYPE_UNUSED  0
+#define PARTITION_TYPE_ADFS    1
+#define PARTITION_TYPE_RISCIX  2
+
+#define PARTITION_FORMAT_RISCIX  2
+#define PARTITION_FORMAT_RISCBSD 0x42
+
+#define FILECORE_BOOT_SECTOR 6
+
+/* Stuff to deal with RISCiX partitions */
+
+#define NRISCIX_PARTITIONS 8
+#define RISCIX_PARTITION_OFFSET 8
+
+struct riscix_partition {
+       u_int rp_start;
+       u_int rp_length;
+       u_int rp_type;
+       char rp_name[16];
+};
+
+struct riscix_partition_table {
+       u_int pad0;
+       u_int pad1;
+       struct riscix_partition partitions[NRISCIX_PARTITIONS];
+};
+
+  
+#include <sys/dkbad.h>
+
+struct riscbsd_partition {
+       u_int rp_start;
+       u_int rp_length;
+       u_int rp_type;
+       char rp_name[16];
+};
+
+struct cpu_disklabel {
+       u_int pad0;
+       u_int pad1;
+       struct riscbsd_partition partitions[NRISCBSD_PARTITIONS];
+       struct dkbad bad;
+};
+
+struct filecore_bootblock {
+       u_char  padding0[0x1c0];
+       u_char  log2secsize;
+       u_char  secspertrack;
+       u_char  heads;
+       u_char  density;
+       u_char  idlen;
+       u_char  log2bpmb;
+       u_char  skew;
+       u_char  bootoption;
+       u_char  lowsector;
+       u_char  nzones;
+       u_short zone_spare;
+       u_int   root;
+       u_int   disc_size;
+       u_short disc_id;
+       u_char  disc_name[10];
+       u_int   disc_type;
+
+       u_char  padding1[24];
+
+       u_char partition_type;
+       u_char partition_cyl_low;
+       u_char partition_cyl_high;
+       u_char checksum;
+};
+
+#ifdef _KERNEL
+struct disklabel;
+int    bounds_check_with_label __P((struct buf *, struct disklabel *, int));
+#endif /* _KERNEL */
+
+#endif /* _ARM32_DISKLABEL_H_ */
+
+/* End of disklabel.h */
diff --git a/sys/arch/arm32/include/endian.h b/sys/arch/arm32/include/endian.h
new file mode 100644 (file)
index 0000000..a7eb2a4
--- /dev/null
@@ -0,0 +1,78 @@
+/* $NetBSD: endian.h,v 1.2 1996/03/14 23:11:10 mark 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.
+ *
+ *     from: @(#)endian.h      7.8 (Berkeley) 4/3/91
+ */
+
+#ifndef _MACHINE_ENDIAN_H_
+#define _MACHINE_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 */
+#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
+
+/*
+ * Macros for network/external number representation conversion.
+ */
+#define        NTOHL(x)        (x) = ntohl((unsigned long)(x))
+#define        NTOHS(x)        (x) = ntohs((unsigned short)(x))
+#define        HTONL(x)        (x) = htonl((unsigned long)(x))
+#define        HTONS(x)        (x) = htons((unsigned short)(x))
+
+#endif /* _POSIX_SOURCE */
+
+#endif /* _MACHINE_ENDIAN_H_ */
diff --git a/sys/arch/arm32/include/exec.h b/sys/arch/arm32/include/exec.h
new file mode 100644 (file)
index 0000000..00cab9c
--- /dev/null
@@ -0,0 +1,59 @@
+/* $NetBSD: exec.h,v 1.2 1996/03/14 23:11:12 mark Exp $ */
+
+/*
+ * Copyright (c) 1994 Mark Brinicombe.
+ * 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 RiscBSD team.
+ * 4. The name "RiscBSD" nor the name of the author may be used to
+ *    endorse or promote products derived from this software without specific
+ *    prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY RISCBSD ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL RISCBSD 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.
+ */
+
+#ifndef        _ARM32_EXEC_H_
+#define        _ARM32_EXEC_H_
+
+#define        __LDPGSZ        4096
+
+/* Relocation format. */
+
+struct relocation_info_arm6 {
+        int r_address;                  /* offset in text or data segment */
+        unsigned int r_symbolnum : 24,  /* ordinal number of add symbol */
+        r_pcrel :  1,  /* 1 if value should be pc-relative */
+        r_length :  2,  /* log base 2 of value's width */
+        r_extern :  1,  /* 1 if need to add symbol to value */
+        r_baserel :  1,  /* linkage table relative */
+        r_jmptable :  1,  /* relocate to jump table */
+        r_relative :  1,  /* load address relative */
+        r_copy :  1;  /* run time copy */
+};
+
+#define relocation_info relocation_info_arm6
+                                                                                                                                                                                       
+/* No special executable format */
+#define        cpu_exec_aout_makecmds(a, b)    ENOEXEC
+
+#endif /* _ARM_EXEC_H_ */
diff --git a/sys/arch/arm32/include/float.h b/sys/arch/arm32/include/float.h
new file mode 100644 (file)
index 0000000..c9fe666
--- /dev/null
@@ -0,0 +1,71 @@
+/* $NetBSD: float.h,v 1.2 1996/03/14 23:11:13 mark 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
+ */
+
+/*extern int __flt_rounds();*/
+#define FLT_RADIX      2               /* b */
+/*#define FLT_ROUNDS   __flt_rounds()*/
+#define FLT_ROUNDS     1
+
+#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
diff --git a/sys/arch/arm32/include/fp.h b/sys/arch/arm32/include/fp.h
new file mode 100644 (file)
index 0000000..c32c923
--- /dev/null
@@ -0,0 +1,64 @@
+/* $NetBSD: fp.h,v 1.2 1996/03/14 23:11:15 mark Exp $ */
+
+/*
+ * Copyright (c) 1995 Mark Brinicombe.
+ * Copyright (c) 1995 Brini.
+ * All rights reserved.
+ *
+ * This code is derived from software written for Brini by Mark Brinicombe
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided 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 Brini.
+ * 4. The name of the company nor the name of the author may be used to
+ *    endorse or promote products derived from this software without specific
+ *    prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BRINI ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL BRINI 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.
+ *
+ * RiscBSD kernel project
+ *
+ * fp.h
+ *
+ * FP info
+ *
+ * Created      : 10/10/95
+ */
+
+#ifndef __ARM32_FP_H
+#define __ARM32_FP_H
+
+typedef struct {
+       u_int32_t fp_exp;
+       u_int32_t fp_man_hi;
+       u_int32_t fp_man_lo;
+} fp_reg_t;
+
+struct fp_state {
+       unsigned int fp_flags;
+       unsigned int fp_sr;
+       unsigned int fp_cr;
+       fp_reg_t fp_registers[16];
+};
+
+#endif
+
+/* End of fp.h */
diff --git a/sys/arch/arm32/include/frame.h b/sys/arch/arm32/include/frame.h
new file mode 100644 (file)
index 0000000..60b06de
--- /dev/null
@@ -0,0 +1,140 @@
+/* $NetBSD: frame.h,v 1.3 1996/03/13 21:06:34 mark Exp $ */
+
+/*
+ * Copyright (c) 1994-1996 Mark Brinicombe.
+ * Copyright (c) 1994 Brini.
+ * All rights reserved.
+ *
+ * This code is derived from software written for Brini by Mark Brinicombe
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided 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 Brini.
+ * 4. The name of the company nor the name of the author may be used to
+ *    endorse or promote products derived from this software without specific
+ *    prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BRINI ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL BRINI 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.
+ *
+ * RiscBSD kernel project
+ *
+ * frame.h
+ *
+ * Stack frames structures
+ *
+ * Created      : 30/09/94
+ */
+
+#ifndef _ARM32_FRAME_H_
+#define _ARM32_FRAME_H_
+
+#include <sys/signal.h>
+
+/*
+ * System stack frames.
+ */
+
+typedef struct irqframe {
+       unsigned int if_spsr;
+       unsigned int if_r0;
+       unsigned int if_r1;
+       unsigned int if_r2;
+       unsigned int if_r3;
+       unsigned int if_r4;
+       unsigned int if_r5;
+       unsigned int if_r6;
+       unsigned int if_r7;
+       unsigned int if_r8;
+       unsigned int if_r9;
+       unsigned int if_r10;
+       unsigned int if_r11;
+       unsigned int if_r12;
+       unsigned int if_usr_sp;
+       unsigned int if_usr_lr;
+       unsigned int if_svc_lr;
+       unsigned int if_pc;
+} irqframe_t;
+
+#define clockframe irqframe
+
+typedef struct trapframe {
+       unsigned int tf_spsr;
+       unsigned int tf_r0;
+       unsigned int tf_r1;
+       unsigned int tf_r2;
+       unsigned int tf_r3;
+       unsigned int tf_r4;
+       unsigned int tf_r5;
+       unsigned int tf_r6;
+       unsigned int tf_r7;
+       unsigned int tf_r8;
+       unsigned int tf_r9;
+       unsigned int tf_r10;
+       unsigned int tf_r11;
+       unsigned int tf_r12;
+       unsigned int tf_usr_sp;
+       unsigned int tf_usr_lr;
+       unsigned int tf_svc_lr;
+       unsigned int tf_pc;
+} trapframe_t;
+
+/*
+ * Signal frame
+ */
+
+struct sigframe {
+       int             sf_signum;
+       int             sf_code;
+       struct  sigcontext *sf_scp;
+       sig_t   sf_handler;
+       struct  sigcontext sf_sc;
+};
+
+/*
+ * Switch frame
+ */
+
+struct switchframe {
+       int     sf_spl;
+       u_int   sf_r4;
+       u_int   sf_r5;
+       u_int   sf_r6;
+       u_int   sf_r7;
+       u_int   sf_pc;
+};
+/*
+ * Stack frame. Used during stack traces (db_trace.c)
+ */
+struct frame {
+       u_int   fr_fp;
+       u_int   fr_sp;
+       u_int   fr_lr;
+       u_int   fr_pc;
+};
+
+#ifdef _KERNEL
+void validate_trapframe __P((trapframe_t *, int));
+#endif /* _KERNEL */
+
+#endif /* _ARM32_FRAME_H_ */
+  
+/* End of frame.h */
diff --git a/sys/arch/arm32/include/iic.h b/sys/arch/arm32/include/iic.h
new file mode 100644 (file)
index 0000000..837576f
--- /dev/null
@@ -0,0 +1,71 @@
+/* $NetBSD: iic.h,v 1.1 1996/04/19 19:52:46 mark Exp $ */
+
+/*
+ * Copyright (c) 1996 Mark Brinicombe.
+ * 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 Brini.
+ * 4. The name of the company nor the name of the author may be used to
+ *    endorse or promote products derived from this software without specific
+ *    prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BRINI ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL BRINI 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.
+ *
+ * RiscBSD kernel project
+ *
+ * iic.h
+ *
+ * header file for IIC
+ *
+ * Created      : 15/04/96
+ */
+
+/*
+ * IIC bus driver attach arguments
+ */
+
+#ifdef _KERNEL
+
+struct iicbus_attach_args {
+       u_int   ib_addr;        /* i/o address */
+       void    *ib_aux;        /* driver specific */
+};
+
+#define iic_bitdelay 10
+
+#define IIC_WRITE      0x00
+#define IIC_READ       0x01
+
+/* Prototypes for assembly functions */
+
+void iic_set_state             __P((int data, int clock));
+void iic_set_state_and_ack     __P((int data, int clock));
+void iic_delay                 __P((int delay));
+
+/* Prototype for kernel interface to IIC bus */
+
+int iic_control __P((u_char address, u_char *buffer, int count));
+
+#endif /* _KERNEL */
+
+/* End of iic.h */
diff --git a/sys/arch/arm32/include/io.h b/sys/arch/arm32/include/io.h
new file mode 100644 (file)
index 0000000..6b8ed7c
--- /dev/null
@@ -0,0 +1,120 @@
+/* $NetBSD: io.h,v 1.3 1996/03/28 21:28:21 mark Exp $ */
+
+/*
+ * Copyright (c) 1994 Mark Brinicombe.
+ * Copyright (c) 1994 Brini.
+ * All rights reserved.
+ *
+ * This code is derived from software written for Brini by Mark Brinicombe
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided 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 Brini.
+ * 4. The name of the company nor the name of the author may be used to
+ *    endorse or promote products derived from this software without specific
+ *    prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BRINI ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL BRINI 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.
+ *
+ * RiscBSD kernel project
+ *
+ * io.h
+ *
+ * IO registers
+ *
+ * Created      : 10/10/94
+ */
+
+/* Some of these addresses are frightening and need cleaning up */
+
+/*
+ * The podule addresses should be removed and localised for the podules.
+ * This is difficuly as the podule addresses are interleaved with the
+ * other IO devices thus making it difficult to separate them.
+ */
+#define IO_CONF_BASE                   0xf6000000
+
+#define IO_HW_BASE                     0x03000000
+
+#define IO_BASE                                0xf6200000
+
+#define COMBO_BASE                     0xf6210000
+
+#define IDE_CONTROLLER_BASE            0xf62107c0
+
+#define FLOPPY_CONTROLLER_BASE         0xf6210fc0
+
+#define FLOPPY_DACK                    0x00002000
+
+#define SERIAL0_CONTROLLER_BASE                0xf6210fe0
+
+#define SERIAL1_CONTROLLER_BASE                0xf6210be0
+
+#define PARALLEL_CONTROLLER_BASE       0xf62109e0
+
+#define IO_MOUSE_BUTTONS               0xf6010000
+
+#ifdef RC7500
+
+#define IDE_CONTROLLER_BASE2           0xf622B000
+
+/*
+ * a bit low turns attached LED on
+ */
+#define LEDPORT        (IO_BASE + 0x0002B060)
+#define LED0   0x01
+#define LED1   0x02
+#define LED2   0x04
+#define LED3   0x08
+#define LED4   0x10
+#define LED5   0x20
+#define LED6   0x40
+#define LED7   0x80
+#define LEDOFF 0x00
+#define LEDALL 0xFF
+#endif
+
+
+#define EASI_HW_BASE           0x08000000
+#define EASI_BASE              0xf8000000
+#define EASI_SIZE              0x01000000
+
+#define SIMPLE_PODULE_SIZE     0x00004000
+
+#define MOD_PODULE_BASE                0xf6200000
+#define SYNC_PODULE_BASE       0xf63c0000
+#define SYNC_PODULE_HW_BASE    0x033c0000
+#define FAST_PODULE_BASE       0xf6340000
+#define MEDIUM_PODULE_BASE     0xf60c0000
+#define SLOW_PODULE_BASE       0xf6040000
+
+#define PODULE_GAP             0x00020000
+#define MAX_PODULES            8
+
+#define NETSLOT_BASE           0xf622b000
+#define MAX_NETSLOTS           1
+
+#define MOUSE_BUTTON_RIGHT     0x10
+#define MOUSE_BUTTON_MIDDLE    0x20
+#define MOUSE_BUTTON_LEFT      0x40
+
+/* End of io.h */
diff --git a/sys/arch/arm32/include/iomd.h b/sys/arch/arm32/include/iomd.h
new file mode 100644 (file)
index 0000000..876c6df
--- /dev/null
@@ -0,0 +1,159 @@
+/* $NetBSD: iomd.h,v 1.3 1996/03/28 21:26:05 mark Exp $ */
+
+/*
+ * Copyright (c) 1994 Mark Brinicombe.
+ * Copyright (c) 1994 Brini.
+ * All rights reserved.
+ *
+ * This code is derived from software written for Brini by Mark Brinicombe
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided 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 Brini.
+ * 4. The name of the company nor the name of the author may be used to
+ *    endorse or promote products derived from this software without specific
+ *    prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BRINI ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL BRINI 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.
+ *
+ * RiscBSD kernel project
+ *
+ * iomd.h
+ *
+ * IOMD registers
+ *
+ * Created      : 18/09/94
+ *
+ * Based on kate/display/iomd.h
+ */
+
+#define IOMD_HW_BASE   0x03200000
+
+#define IOMD_BASE      0xf6000000
+
+#define IOMD_IOCR      (IOMD_BASE + 0x00000000)
+#define IOMD_KBDDAT    (IOMD_BASE + 0x00000004)
+#define IOMD_KBDCR     (IOMD_BASE + 0x00000008)
+
+#define IOMD_IRQSTA    (IOMD_BASE + 0x00000010)
+#define IOMD_IRQRQA    (IOMD_BASE + 0x00000014)
+#define IOMD_IRQMSKA   (IOMD_BASE + 0x00000018)
+#define IOMD_SUSPEND   (IOMD_BASE + 0x0000001C) /* ARM7500 */
+
+#define IOMD_IRQSTB    (IOMD_BASE + 0x00000020)
+#define IOMD_IRQRQB    (IOMD_BASE + 0x00000024)
+#define IOMD_IRQMSKB   (IOMD_BASE + 0x00000028)
+
+#define IOMD_FIQST     (IOMD_BASE + 0x00000030)
+#define IOMD_FIQRQ     (IOMD_BASE + 0x00000034)
+#define IOMD_FIQMSK    (IOMD_BASE + 0x00000038)
+
+#define IOMD_T0LOW     (IOMD_BASE + 0x00000040)
+#define IOMD_T0HIGH    (IOMD_BASE + 0x00000044)
+#define IOMD_T0GO      (IOMD_BASE + 0x00000048)
+#define IOMD_T0LATCH   (IOMD_BASE + 0x0000004c)
+
+#define IOMD_T1LOW     (IOMD_BASE + 0x00000050)
+#define IOMD_T1HIGH    (IOMD_BASE + 0x00000054)
+#define IOMD_T1GO      (IOMD_BASE + 0x00000058)
+#define IOMD_T1LATCH   (IOMD_BASE + 0x0000005c)
+
+/*
+ * For RC7500, it's not really a IOMD device.
+ */
+#define IOMD_IRQSTC    (IOMD_BASE + 0x00000060)        /* ARM7500 */
+#define IOMD_IRQRQC    (IOMD_BASE + 0x00000064)        /* ARM7500 */
+#define IOMD_IRQMSKC   (IOMD_BASE + 0x00000068)        /* ARM7500 */
+#define IOMD_VIDMUX    (IOMD_BASE + 0x0000006C)        /* ARM7500 */
+#define IOMD_IRQSTD    (IOMD_BASE + 0x00000070)        /* ARM7500 */
+#define IOMD_IRQRQD    (IOMD_BASE + 0x00000074)        /* ARM7500 */
+#define IOMD_IRQMSKD   (IOMD_BASE + 0x00000078)        /* ARM7500 */
+
+#define IOMD_ROMCR0    (IOMD_BASE + 0x00000080)
+#define IOMD_ROMCR1    (IOMD_BASE + 0x00000084)
+#define IOMD_DRAMCR    (IOMD_BASE + 0x00000088)
+#define IOMD_VREFCR    (IOMD_BASE + 0x0000008c)
+#define IOMD_FSIZE     (IOMD_BASE + 0x00000090)
+#define IOMD_ID0       (IOMD_BASE + 0x00000094)
+#define IOMD_ID1       (IOMD_BASE + 0x00000098)
+#define IOMD_VERSION   (IOMD_BASE + 0x0000009c)
+
+#define IOMD_MOUSEX    (IOMD_BASE + 0x000000a0)
+#define IOMD_MOUSEY    (IOMD_BASE + 0x000000a4)
+
+#define IOMD_MSDATA    (IOMD_BASE + 0x000000a8)        /* ARM7500 */
+#define IOMD_MSCR      (IOMD_BASE + 0x000000ac)        /* ARM7500 */
+
+#define IOMD_IOTCR     (IOMD_BASE + 0x000000C4)        /* ARM7500 */
+#define IOMD_ECTCR     (IOMD_BASE + 0x000000C8)        /* ARM7500 */
+#define IOMD_ASTCR     (IOMD_BASE + 0x000000CC)        /* ARM7500 */
+
+#define IOMD_DRAMWID   (IOMD_BASE + 0x000000D0)        /* ARM7500 */
+#define IOMD_SELFREF   (IOMD_BASE + 0x000000D4)        /* ARM7500 */
+
+#define IOMD_ATODICR   (IOMD_BASE + 0x000000E0)        /* ARM7500 */
+#define IOMD_ATODSR    (IOMD_BASE + 0x000000E4)        /* ARM7500 */
+#define IOMD_ATODCR    (IOMD_BASE + 0x000000E8)        /* ARM7500 */
+#define IOMD_ATODCNT1  (IOMD_BASE + 0x000000EC)        /* ARM7500 */
+#define IOMD_ATODCNT2  (IOMD_BASE + 0x000000F0)        /* ARM7500 */
+#define IOMD_ATODCNT3  (IOMD_BASE + 0x000000F4)        /* ARM7500 */
+#define IOMD_ATODCNT4  (IOMD_BASE + 0x000000F8)        /* ARM7500 */
+
+#define IOMD_SD0CURA   (IOMD_BASE + 0x00000180)
+#define IOMD_SD0ENDA   (IOMD_BASE + 0x00000184)
+#define IOMD_SD0CURB   (IOMD_BASE + 0x00000188)
+#define IOMD_SD0ENDB   (IOMD_BASE + 0x0000018c)
+#define IOMD_SD0CR     (IOMD_BASE + 0x00000190)
+#define IOMD_SD0ST     (IOMD_BASE + 0x00000194)
+
+#define IOMD_SD1CURA   (IOMD_BASE + 0x000001a0)
+#define IOMD_SD1ENDA   (IOMD_BASE + 0x000001a4)
+#define IOMD_SD1CURB   (IOMD_BASE + 0x000001a8)
+#define IOMD_SD1ENDB   (IOMD_BASE + 0x000001ac)
+#define IOMD_SD1CR     (IOMD_BASE + 0x000001b0)
+#define IOMD_SD1ST     (IOMD_BASE + 0x000001b4)
+
+#define IOMD_CURSCUR   (IOMD_BASE + 0x000001c0)
+#define IOMD_CURSINIT  (IOMD_BASE + 0x000001c4)
+
+#define IOMD_VIDCUR    (IOMD_BASE + 0x000001d0)
+#define IOMD_VIDEND    (IOMD_BASE + 0x000001d4)
+#define IOMD_VIDSTART  (IOMD_BASE + 0x000001d8)
+#define IOMD_VIDINIT   (IOMD_BASE + 0x000001dc)
+#define IOMD_VIDCR     (IOMD_BASE + 0x000001e0)
+
+#define IOMD_DMAST     (IOMD_BASE + 0x000001f0)
+#define IOMD_DMARQ     (IOMD_BASE + 0x000001f4)
+#define IOMD_DMAMSK    (IOMD_BASE + 0x000001f8)
+
+#define IO_MOUSE_BUTTONS 0xf6010000
+
+#define MOUSE_BUTTON_RIGHT  0x10
+#define MOUSE_BUTTON_MIDDLE 0x20
+#define MOUSE_BUTTON_LEFT   0x40
+
+#define RPC600_IOMD_ID 0xd4e7
+#define RC7500_IOC_ID  0x5B98
+
+#define FREQCON        (IOMD_BASE + 0x40000)
+
+/* End of iomd.h */
diff --git a/sys/arch/arm32/include/irqhandler.h b/sys/arch/arm32/include/irqhandler.h
new file mode 100644 (file)
index 0000000..3b506c9
--- /dev/null
@@ -0,0 +1,212 @@
+/* $NetBSD: irqhandler.h,v 1.4 1996/03/28 21:29:32 mark Exp $ */
+
+/*
+ * Copyright (c) 1994-1996 Mark Brinicombe.
+ * Copyright (c) 1994 Brini.
+ * All rights reserved.
+ *
+ * This code is derived from software written for Brini by Mark Brinicombe
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided 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 Brini.
+ * 4. The name of the company nor the name of the author may be used to
+ *    endorse or promote products derived from this software without specific
+ *    prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BRINI ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL BRINI 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.
+ *
+ * RiscBSD kernel project
+ *
+ * irq.h
+ *
+ * IRQ related stuff
+ *
+ * Created      : 30/09/94
+ */
+
+#include <sys/types.h>
+
+typedef struct irqhandler {
+       int (*ih_func)();               /* handler function */
+       void *ih_arg;                   /* Argument to handler */
+       int ih_level;                   /* Interrupt level */
+       int ih_num;                     /* Interrupt number (for accounting) */
+       char *ih_name;                  /* Name of interrupt (for vmstat -i) */
+       unsigned int ih_flags;          /* Interrupt flags */
+       unsigned int *ih_irqmask;       /* mask location for expansion cards */
+       unsigned int ih_irqbit;         /* interrupt bit for expansion cards */
+       struct irqhandler *ih_next;     /* next handler */
+} irqhandler_t;
+
+#define IRQ_FLAG_ACTIVE 0x00000001     /* This is the active handler in list */
+
+/* Define the IRQ bits */
+
+
+
+#ifdef RC7500
+
+/*#define IRQ_PRINTER  0x00*/
+#define IRQ_RESERVED0  0x01
+#define IRQ_BUTTON     0x02
+#define IRQ_FLYBACK    0x03
+#define IRQ_POR                0x04
+#define IRQ_TIMER0     0x05
+#define IRQ_TIMER1     0x06
+#define IRQ_FIQDOWN    0x07
+
+#define IRQ_DREQ3      0x08
+/*#define IRQ_HD1              0x09*/
+/*#define IRQ_HD               IRQ_HD1*/
+#define IRQ_DREQ2      0x0A
+#define IRQ_ETHERNET   0x0B
+/*#define IRQ_FLOPPY   0x0C*/
+/*#define IRQ_SERIAL   0x0D*/
+#define IRQ_KBDTX      0x0E
+#define IRQ_KBDRX      0x0F
+
+#define IRQ_IRQ3       0x10
+#define IRQ_IRQ4       0x11
+#define IRQ_IRQ5       0x12
+#define IRQ_IRQ6       0x13
+#define IRQ_IRQ7       0x14
+#define IRQ_IRQ9       0x15
+#define IRQ_IRQ10      0x16
+#define IRQ_HD2                0x17
+
+#define IRQ_MSDRX      0x18
+#define IRQ_MSDTX      0x19
+#define IRQ_ATOD       0x1A
+#define IRQ_CLOCK      0x1B
+#define IRQ_PANIC      0x1C
+#define IRQ_RESERVED2  0x1D
+#define IRQ_RESERVED3  0x1E
+#define IRQ_RESERVED1  IRQ_RESERVED2
+
+/*
+ * Note that Sound DMA IRQ is on the 31st vector.
+ * It's not part of the IRQD.
+ */
+#define IRQ_SDMA       0x1F
+
+#else /* RC7500 */
+
+
+
+
+/*#define IRQ_PRINTER  0x00*/
+#define IRQ_RESERVED0  0x01
+/*#define IRQ_FLOPPYIDX        0x02*/
+#define IRQ_FLYBACK    0x03
+#define IRQ_POR                0x04
+#define IRQ_TIMER0     0x05
+#define IRQ_TIMER1     0x06
+#define IRQ_RESERVED1  0x07
+
+#define IRQ_RESERVED2  0x08
+/*#define IRQ_HD               0x09*/
+/*#define IRQ_SERIAL   0x0A*/
+#define IRQ_EXTENDED   0x0B
+/*#define IRQ_FLOPPY   0x0C*/
+#define IRQ_PODULE     0x0D
+#define IRQ_KBDTX      0x0E
+#define IRQ_KBDRX      0x0F
+
+#define IRQ_DMACH0     0x10
+#define IRQ_DMACH1     0x11
+#define IRQ_DMACH2     0x12
+#define IRQ_DMACH3     0x13
+#define IRQ_DMASCH0    0x14
+#define IRQ_DMASCH1    0x15
+#define IRQ_RESERVED3  0x16
+#define IRQ_RESERVED4  0x17
+
+#define IRQ_EXPCARD0   0x18
+#define IRQ_EXPCARD1   0x19
+#define IRQ_EXPCARD2   0x1A
+#define IRQ_EXPCARD3   0x1B
+#define IRQ_EXPCARD4   0x1C
+#define IRQ_EXPCARD5   0x1D
+#define IRQ_EXPCARD6   0x1E
+#define IRQ_EXPCARD7   0x1F
+
+#endif /* RC7500 */
+
+#define IRQ_VSYNC      IRQ_FLYBACK     /* Aliased */
+#define IRQ_NETSLOT    IRQ_EXTENDED
+
+#define IRQ_SOFTNET    IRQ_RESERVED0   /* Emulated */
+#define IRQMASK_SOFTNET        (1 << IRQ_SOFTNET)
+#define IRQ_SOFTCLOCK  IRQ_RESERVED1   /* Emulated */
+#define IRQMASK_SOFTCLOCK      (1 << IRQ_SOFTCLOCK)
+
+#define IRQ_INSTRUCT   -1
+#define NIRQS          0x20
+
+/* Define the various Interrupt Priority Levels */
+
+/* Interrupt Priority Levels are not mutually exclusive. */
+
+#define IPL_NONE      -1
+#define IPL_BIO        0       /* block I/O */
+#define IPL_NET        1       /* network */
+#define IPL_TTY        2       /* terminal */
+#define IPL_CLOCK      3       /* clock */
+#define IPL_IMP        4       /* memory allocation */
+
+#define IRQ_LEVELS     5
+
+#ifdef _KERNEL
+extern u_int irqmasks[IRQ_LEVELS];
+
+void irq_init __P(());
+int irq_claim __P((int, irqhandler_t *));
+int irq_release __P((int, irqhandler_t *));
+void irq_setmasks __P((void));
+void disable_irq __P((int));
+void enable_irq __P((int));
+u_int enable_interrupts __P((u_int));
+u_int disable_interrupts __P((u_int));
+u_int restore_interrupts __P((u_int));
+#endif
+
+typedef struct fiqhandler {
+       void (*fh_func)();      /* handler function */
+       u_int fh_size;          /* Size of handler function */
+       u_int fh_mask;          /* FIQ mask */
+       u_int fh_r8;            /* FIQ mode r8 */
+       u_int fh_r9;            /* FIQ mode r9 */
+       u_int fh_r10;           /* FIQ mode r10 */
+       u_int fh_r11;           /* FIQ mode r11 */
+       u_int fh_r12;           /* FIQ mode r12 */
+       u_int fh_r13;           /* FIQ mode r13 */
+} fiqhandler_t;
+
+#ifdef RC7500
+int fiq_claim __P((int, fiqhandler_t *));
+int fiq_release __P((int, fiqhandler_t *));
+#else
+int fiq_claim __P((fiqhandler_t *));
+int fiq_release __P((fiqhandler_t *));
+#endif
+
+/* End of irqhandler.h */
diff --git a/sys/arch/arm32/include/katelib.h b/sys/arch/arm32/include/katelib.h
new file mode 100644 (file)
index 0000000..3fe6f06
--- /dev/null
@@ -0,0 +1,132 @@
+/* $NetBSD: katelib.h,v 1.5 1996/03/28 21:35:51 mark Exp $ */
+
+/*
+ * Copyright (c) 1994,1995 Mark Brinicombe.
+ * Copyright (c) 1994 Brini.
+ * All rights reserved.
+ *
+ * This code is derived from software written for Brini by Mark Brinicombe
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided 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 Brini.
+ * 4. The name of the company nor the name of the author may be used to
+ *    endorse or promote products derived from this software without specific
+ *    prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BRINI ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL BRINI 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.
+ *
+ * RiscBSD kernel project
+ *
+ * katelib.h
+ *
+ * Prototypes for machine specific functions. Most of these
+ * could be inlined.
+ *
+ * This should not really be a separate header file. Eventually I will merge
+ * this into other header files once I have decided where the declarations
+ * should go. 
+ *
+ * Created      : 18/09/94
+ *
+ * Based on kate/katelib/prototypes.h
+ */
+
+#include <sys/types.h>
+
+#ifdef _KERNEL
+
+/* Assembly modules */
+
+/* In setcpsr.S */
+
+u_int SetCPSR __P((u_int, u_int));
+u_int GetCPSR __P((void));
+
+/* In coproc15.S */
+
+void tlbflush __P((void));
+void tlbpurge __P((u_int));
+void idcflush __P((void));
+void cpu_control __P((u_int));
+void cpu_domains __P((u_int));
+void setttb __P((u_int));
+
+u_int cpu_id __P((void));
+u_int cpu_faultstatus __P((void));
+u_int cpu_faultaddress __P((void));
+
+/* In setstack.S */
+
+void set_stackptr __P((u_int, u_int));
+u_int get_stackptr __P((u_int));
+
+/* In blockio.S */
+
+void insw __P((u_int /*io*/, u_int /*dest*/, u_int /*size*/));
+void outsw __P((u_int /*io*/, u_int /*src*/, u_int /*size*/));
+void insw16 __P((u_int /*io*/, u_int /*dest*/, u_int /*size*/));
+void outsw16 __P((u_int /*io*/, u_int /*src*/, u_int /*size*/));
+
+/* Macros for reading and writing words, shorts, bytes */
+
+#define WriteWord(a, b) \
+*((volatile unsigned int *)(a)) = (b)
+
+#define ReadWord(a) \
+(*((volatile unsigned int *)(a)))
+
+#define WriteShort(a, b) \
+*((volatile unsigned int *)(a)) = ((b) | ((b) << 16))
+
+#define ReadShort(a) \
+((*((volatile unsigned int *)(a))) & 0xffff)
+
+#define WriteByte(a, b) \
+*((volatile unsigned char *)(a)) = (b)
+
+#define ReadByte(a) \
+(*((volatile unsigned char *)(a)))
+
+/* Define in/out macros */
+
+#define inb(port)              ReadByte((port))
+#define outb(port, byte)       WriteByte((port), (byte))
+#define inw(port)              ReadShort((port))
+#define outw(port, word)       WriteShort((port), (word))
+#define inl(port)              ReadWord((port))
+#define outl(port, lword)      WriteWord((port), (lword))
+
+/* Prototypes that are wandering the streets */
+
+#ifdef _ARM32_FRAME_H
+void postmortem __P((trapframe_t */*frame*/));
+#endif
+u_int traceback __P(());
+u_int simpletraceback __P(());
+u_int irqtraceback __P((u_int, u_int));
+int shell __P(());
+void kstack_stuff __P((struct proc */*p*/));
+void boot0 __P(());
+void bootsync __P((void));
+#endif
+
+/* End of katelib.h */
diff --git a/sys/arch/arm32/include/kbd.h b/sys/arch/arm32/include/kbd.h
new file mode 100644 (file)
index 0000000..a202308
--- /dev/null
@@ -0,0 +1,66 @@
+/* $NetBSD: kbd.h,v 1.2 1996/03/14 23:11:21 mark Exp $ */
+
+/*
+ * Copyright (c) 1995 Mark Brinicombe.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided 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 Mark Brinicombe.
+ * 4. The name of the company nor the name of the author may 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 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.
+ *
+ * RiscBSD kernel project
+ *
+ * kbd.h
+ *
+ * Keyboard ioctls
+ *
+ * Created      : 21/07/95
+ */
+
+struct kbd_data {
+       int keycode;
+       struct timeval event_time;
+};
+
+struct kbd_autorepeat {
+       int ka_delay;
+       int ka_rate;
+};
+
+#define KBD_GETAUTOREPEAT      _IOR( 'k', 100, struct kbd_autorepeat)
+#define KBD_SETAUTOREPEAT      _IOW( 'k', 101, struct kbd_autorepeat)
+#define KBD_SETLEDS            _IOW( 'k', 102, int)
+#define KBD_XXX                        _IOW( 'k', 103, int)
+
+#define KBD_LED_SCROLL_LOCK    0x01
+#define KBD_LED_NUM_LOCK       0x02
+#define KBD_LED_CAPS_LOCK      0x04
+
+#ifdef _KERNEL
+void   kbdsetstate __P((int /*state*/));
+int    kbdgetstate __P(());
+#endif
+
+/* End of kbd.h */
diff --git a/sys/arch/arm32/include/kgdb.h b/sys/arch/arm32/include/kgdb.h
new file mode 100644 (file)
index 0000000..3f875e7
--- /dev/null
@@ -0,0 +1,45 @@
+/* $NetBSD: kgdb.h,v 1.2 1996/03/14 23:11:23 mark Exp $ */
+
+/*
+ * Copyright (C) 1993, 1994 Wolfgang Solfrank.
+ * Copyright (C) 1993, 1994 TooLs GmbH.
+ * 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 TooLs GmbH.
+ * 4. The name of TooLs GmbH may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/* define certain registers */
+#define        SP              13
+#define        LR              14
+#define        PC              15
+#define        PSR             16
+#define        SPSR            17
+#define        NREG            18
+
+extern int kgdbregs[NREG];
+
+extern int *kgdb_find_stack();
+extern void kgdb_free_stack __P((int *));
diff --git a/sys/arch/arm32/include/limits.h b/sys/arch/arm32/include/limits.h
new file mode 100644 (file)
index 0000000..0eb9808
--- /dev/null
@@ -0,0 +1,75 @@
+/* $NetBSD: limits.h,v 1.2 1996/03/14 23:11:25 mark 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.
+ *
+ *     from: @(#)limits.h      7.2 (Berkeley) 6/28/90
+ */
+
+#ifndef        _ARM32_LIMITS_H_
+#define        _ARM32_LIMITS_H_
+
+#define        CHAR_BIT        8               /* number of bits in a char */
+#define        MB_LEN_MAX      1               /* no multibyte characters */
+
+#define SCHAR_MIN      (-0x7f-1)       /* max value for a signed char */
+#define        SCHAR_MAX       0x7f            /* min 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       0xffffffff      /* 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)
+#define        SIZE_T_MAX      UINT_MAX        /* max value for a size_t */
+
+#define        UQUAD_MAX       0xffffffffffffffffLL            /* max unsigned quad */
+#define        QUAD_MAX        0x7fffffffffffffffLL            /* max signed quad */
+#define        QUAD_MIN        (-0x7fffffffffffffffLL-1)       /* min signed quad */
+
+#endif /* !_POSIX_SOURCE */
+#endif /* !_ANSI_SOURCE */
+#endif /* _ARM_LIMITS_H_ */
diff --git a/sys/arch/arm32/include/mouse.h b/sys/arch/arm32/include/mouse.h
new file mode 100644 (file)
index 0000000..1187aff
--- /dev/null
@@ -0,0 +1,111 @@
+/* $NetBSD: mouse.h,v 1.1 1996/03/27 20:57:18 mark Exp $ */
+
+/*
+ * Copyright (c) Mark Brinicombe 1996 All rights reserved
+ * Copyright (c) Scott Stevens 1995 All rights reserved
+ * Copyright (c) Melvin Tang-Richardson 1995 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 RiscBSD team.
+ * 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.
+ */
+
+/*
+#define MOUSE_BUTTON_RIGHT  0x10
+#define MOUSE_BUTTON_MIDDLE 0x20
+#define MOUSE_BUTTON_LEFT   0x40
+*/
+
+/* Used in pms.c */
+
+#define BUTSTATMASK    0x07    /* Any mouse button down if any bit set */
+#define BUTCHNGMASK    0x38    /* Any mouse button changed if any bit set */
+
+#define BUT3STAT       0x01    /* Button 3 down if set */
+#define BUT2STAT       0x02    /* Button 2 down if set */
+#define BUT1STAT       0x04    /* Button 1 down if set */
+#define BUT3CHNG       0x08    /* Button 3 changed if set */
+#define BUT2CHNG       0x10    /* Button 2 changed if set */
+#define BUT1CHNG       0x20    /* Button 1 changed if set */
+#define MOVEMENT       0x40    /* Mouse movement detected */
+
+/* Define user visible mouse structures */
+
+struct mouseinfo {
+       u_int status;
+       int xmotion, ymotion;
+};
+
+struct mousebufrec {
+       int status;
+       int x,y;
+       struct timeval event_time;
+};
+
+struct mouse_state {
+       signed short x, y;
+       int buttons;
+};
+
+struct mouse_boundingbox {
+       int x, y, a, b;
+};
+
+struct mouse_origin {
+       int x, y;
+};
+
+/* Define mouse ioctls */
+
+#define MOUSEIOC_WRITEX                _IO ( 'M', 100 )
+#define MOUSEIOC_WRITEY                _IO ( 'M', 101 )
+
+#define MOUSEIOC_SETSTATE      _IOW ( 'M', 102, struct mouse_state )
+#define MOUSEIOC_SETBOUNDS     _IOW ( 'M', 103, struct mouse_boundingbox )
+#define MOUSEIOC_SETORIGIN     _IOW ( 'M', 104, struct mouse_origin )
+
+#define MOUSEIOC_GETSTATE      _IOR ( 'M', 105, struct mouse_state )
+#define MOUSEIOC_READ          MOUSEIOC_GETSTATE
+#define MOUSEIOC_GETBOUNDS     _IOR ( 'M', 106, struct mouse_boundingbox )
+#define MOUSEIOC_GETORIGIN     _IOR ( 'M', 107, struct mouse_origin )
+
+/*
+ * For backwards compatibility with the current Xserver.
+ * Eventually these will be removed.
+ */
+
+#define QUADMOUSE_WRITEX       MOUSEIOC_WRITEX
+#define QUADMOUSE_WRITEY       MOUSEIOC_WRITEY
+
+#define QUADMOUSE_SETSTATE     MOUSEIOC_SETSTATE
+#define QUADMOUSE_SETBOUNDS    MOUSEIOC_SETBOUNDS
+#define QUADMOUSE_SETORIGIN    MOUSEIOC_SETORIGIN
+
+#define QUADMOUSE_GETSTATE     MOUSEIOC_GETSTATE
+#define QUADMOUSE_GETBOUNDS    MOUSEIOC_GETBOUNDS
+#define QUADMOUSE_GETORIGIN    MOUSEIOC_GETORIGIN
+
+#define QUADMOUSE_SETFORMAT    _IOW ( 'M', 108, char[20] )
+
+/* End of mouse.h */
diff --git a/sys/arch/arm32/include/param.h b/sys/arch/arm32/include/param.h
new file mode 100644 (file)
index 0000000..5b737d6
--- /dev/null
@@ -0,0 +1,184 @@
+/* $NetBSD: param.h,v 1.6 1996/03/14 23:11:27 mark Exp $ */
+
+/*
+ * Copyright (c) 1994,1995 Mark Brinicombe.
+ * 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 RiscBSD team.
+ * 4. The name "RiscBSD" nor the name of the author may be used to
+ *    endorse or promote products derived from this software without specific
+ *    prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY RISCBSD ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL RISCBSD 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.
+ */
+
+#ifndef        _ARM32_PARAM_H_
+#define        _ARM32_PARAM_H_
+
+#ifdef _KERNEL
+#  include <machine/cpu.h>
+#endif
+
+/*
+ * Machine dependent constants for ARM6+ processors
+ */
+/*#define      ovbcopy bcopy   */      /* XXX should probably have long gone by now */
+
+#define        _MACHINE        arm32
+#define        MACHINE         "arm32"
+#define        _MACHINE_ARCH   arm32
+#define        MACHINE_ARCH    "arm32"
+#define        MID_MACHINE     MID_ARM6
+
+/*
+ * Round p (pointer or byte index) up to a correctly-aligned value
+ * for all data types (int, long, ...).   The result is u_int and
+ * must be cast to any desired pointer type.
+ */
+#define ALIGNBYTES     (sizeof(int) - 1)
+#define ALIGN(p)       (((u_int)(p) + ALIGNBYTES) &~ ALIGNBYTES)
+
+#define        PGSHIFT         12              /* LOG2(NBPG) */
+#define        NBPG            (1 << PGSHIFT)  /* bytes/page */
+#define        PGOFSET         (NBPG-1)        /* byte offset into page */
+#define        NPTEPG          (NBPG/(sizeof (pt_entry_t)))
+
+
+#define        DEV_BSHIFT      9               /* log2(DEV_BSIZE) */
+#define        DEV_BSIZE       (1 << DEV_BSHIFT)
+#define        BLKDEV_IOSIZE   2048
+#define        MAXPHYS         (64 * 1024)     /* max raw I/O transfer size */
+
+#define        CLSIZELOG2      0
+#define        CLSIZE          (1 << CLSIZELOG2)
+
+/* NOTE: SSIZE, SINCR and UPAGES must be multiples of CLSIZE */
+#define SSIZE           1               /* initial stack size/NBPG */
+#define SINCR           1               /* increment of stack/NBPG */
+#define UPAGES          2               /* pages of u-area */
+#define USPACE          (UPAGES * NBPG) /* total size of u-area */
+
+/*
+ * Constants related to network buffer management.
+ * MCLBYTES must be no larger than CLBYTES (the software page size), and,
+ * on machines that exchange pages of input or output buffers with mbuf
+ * clusters (MAPPED_MBUFS), MCLBYTES must also be an integral multiple
+ * of the hardware page size.
+ */
+#define        MSIZE           128             /* size of an mbuf */
+#define        MCLSHIFT        11              /* convert bytes to m_buf clusters */
+#define        MCLBYTES        (1 << MCLSHIFT) /* size of a m_buf cluster */
+#define        MCLOFSET        (MCLBYTES - 1)  /* offset within a m_buf cluster */
+
+#ifndef NMBCLUSTERS
+#ifdef GATEWAY
+#define        NMBCLUSTERS     512             /* map size, max cluster allocation */
+#else
+#define        NMBCLUSTERS     256             /* map size, max cluster allocation */
+#endif
+#endif
+
+/*
+ * Size of kernel malloc arena in CLBYTES-sized logical pages
+ */ 
+#ifndef NKMEMCLUSTERS
+#define        NKMEMCLUSTERS   (6 * 1024 * 1024 / CLBYTES)
+#endif
+
+/* pages ("clicks") (4096 bytes) to disk blocks */
+#define        ctod(x) ((x) << (PGSHIFT - DEV_BSHIFT))
+#define        dtoc(x) ((x) >> (PGSHIFT - DEV_BSHIFT))
+/*#define      dtob(x) ((x) << DEV_BSHIFT)*/
+
+#define        ctob(x) ((x) << PGSHIFT)
+
+/* bytes to pages */
+#define        btoc(x) (((unsigned)(x) + PGOFSET) >> PGSHIFT)
+
+#define        btodb(bytes)                    /* calculates (bytes / DEV_BSIZE) */ \
+       ((unsigned)(bytes) >> DEV_BSHIFT)
+#define        dbtob(db)                       /* calculates (db * DEV_BSIZE) */ \
+       ((unsigned)(db) << DEV_BSHIFT)
+
+/*
+ * Map a ``block device block'' to a file system block.
+ * This should be device dependent, and should use the bsize
+ * field from the disk label.
+ * For now though just use DEV_BSIZE.
+ */
+#define        bdbtofsb(bn)    ((bn) / (BLKDEV_IOSIZE / DEV_BSIZE))
+
+/* Define various base addresses */
+
+#define KERNEL_BASE            0xf0000000
+#define KERNEL_VM_BASE         0xf1000000
+#define PAGE_DIRS_BASE         0xf3000000
+#define ALT_PAGE_TBLS_BASE     0xf3c00000
+#define CURRENT_PAGEDIR_BASE   0xeffd4000
+#define PROCESS_PAGE_TBLS_BASE 0xefc00000
+
+#define KERNBASE       KERNEL_BASE
+
+/* Constants used to divide the USPACE area */
+
+/*
+ * The USPACE area contains :
+ * 1. the user structure for the process
+ * 2. the fp context for FP emulation
+ * 3. the kernel (svc) stack
+ * 4. the undefined instruction stack
+ *
+ * The layout of the area looks like this
+ *
+ * | user area | FP context | undefined stack | kernel stack |
+ *
+ * The size of the user area is known.
+ * The size of the FP context is variable depending of the FP emulator
+ * in use and whether there is hardware FP support. However we can put
+ * an upper limit on it.
+ * The undefined stack needs to be at least 512 bytes. This is a requirement
+ * if the FP emulators
+ * The kernel stack should be at least 4K is size.
+ *
+ * The stack top addresses are used to set the stack pointers. The stack bottom
+ * addresses at the addresses monitored by the diagnostic code for stack overflows
+ *
+ */
+
+#define FPCONTEXTSIZE                  (0x100)
+#define USPACE_SVC_STACK_TOP           (USPACE)
+#define USPACE_SVC_STACK_BOTTOM                (USPACE_SVC_STACK_TOP - 0x1000)
+#define        USPACE_UNDEF_STACK_TOP          (USPACE_SVC_STACK_BOTTOM - 0x10)
+#define USPACE_UNDEF_STACK_BOTTOM      (sizeof(struct user) + FPCONTEXTSIZE + 10)
+
+#define arm_byte_to_page(x) (x >> PGSHIFT)
+#define arm_page_to_byte(x) (x << PGSHIFT)
+
+#ifdef _KERNEL
+#ifndef _LOCORE
+void   delay __P((unsigned));
+#define DELAY(x)       delay(x)
+#endif
+#endif
+
+#endif /* _ARM_PARAM_H_ */
diff --git a/sys/arch/arm32/include/pcb.h b/sys/arch/arm32/include/pcb.h
new file mode 100644 (file)
index 0000000..00c04a8
--- /dev/null
@@ -0,0 +1,79 @@
+/* $NetBSD: pcb.h,v 1.2 1996/03/13 21:08:36 mark Exp $ */
+
+/*
+ * Copyright (c) 1994 Mark Brinicombe.
+ * 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 RiscBSD team.
+ * 4. The name "RiscBSD" nor the name of the author may be used to
+ *    endorse or promote products derived from this software without specific
+ *    prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY RISCBSD ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL RISCBSD 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.
+ */
+
+#ifndef        _ARM32_PCB_H_
+#define        _ARM32_PCB_H_
+
+#include <machine/pte.h>
+#include <machine/fp.h>
+
+struct pcb {
+       pd_entry_t      *pcb_pagedir;           /* PT hooks */
+       u_int   pcb_flags;                      /* Flags */
+       u_int   pcb_spsr;
+       u_int   pcb_r0;                         /* Space for register dump */
+       u_int   pcb_r1;
+       u_int   pcb_r2;
+       u_int   pcb_r3;
+       u_int   pcb_r4;
+       u_int   pcb_r5;
+       u_int   pcb_r6;
+       u_int   pcb_r7;
+       u_int   pcb_r8;                         /* used */
+       u_int   pcb_r9;                         /* used */
+       u_int   pcb_r10;                        /* used */
+       u_int   pcb_r11;                        /* used */
+       u_int   pcb_r12;                        /* used */
+       u_int   pcb_sp;                         /* used */
+       u_int   pcb_lr;
+       u_int   pcb_pc;
+       u_int   pcb_und_sp;
+       caddr_t pcb_onfault;                    /* On fault handler */
+       struct  fp_state pcb_fpstate;           /* Floating Point state */
+};
+
+/*
+ * No additional data for core dumps.
+ */
+struct md_coredump {
+       int     md_empty;
+};
+
+#ifdef _KERNEL
+extern struct pcb *curpcb;
+#endif /* _KERNEL */
+
+#endif /* _ARM32_PCB_H_ */
+
+/* End of pcb.h */
diff --git a/sys/arch/arm32/include/pmap.h b/sys/arch/arm32/include/pmap.h
new file mode 100644 (file)
index 0000000..888c7a2
--- /dev/null
@@ -0,0 +1,132 @@
+/* $NetBSD: pmap.h,v 1.3 1996/03/14 23:11:29 mark Exp $ */
+
+/*
+ * Copyright (c) 1994,1995 Mark Brinicombe.
+ * 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 RiscBSD team.
+ * 4. The name "RiscBSD" nor the name of the author may be used to
+ *    endorse or promote products derived from this software without specific
+ *    prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY RISCBSD ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL RISCBSD 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.
+ */
+
+#ifndef        _ARM32_PMAP_H_
+#define        _ARM32_PMAP_H_
+
+#include <machine/pte.h>
+
+/*
+ * virtual address to page table entry and
+ * to physical address.
+ */
+
+#define vtopte(va) \
+       ((pt_entry_t *)(PROCESS_PAGE_TBLS_BASE + (arm_byte_to_page((unsigned int)(va)) << 2)))
+        
+        
+#define vtophys(va) \
+       ((*vtopte(va) & PG_FRAME) | ((unsigned int)(va) & ~PG_FRAME))
+
+/*
+ * Pmap stuff
+ */
+struct pmap {
+       pd_entry_t              *pm_pdir;       /* KVA of page directory */
+       vm_offset_t             pm_pptpt;       /* PA of pt's page table */
+       vm_offset_t             pm_vptpt;       /* VA of pt's page table */
+       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 */
+};
+
+typedef struct pmap *pmap_t;
+
+/*
+ * For speed we store the both the virtual address and the page table
+ * entry address for each page hook.
+ */
+typedef struct {
+       vm_offset_t va;
+       pt_entry_t *pte;
+} pagehook_t;
+             
+/*
+ * For each vm_page_t, there is a list of all currently valid virtual
+ * mappings of that page.  An entry is a pv_entry_t, the list is pv_table.
+ */
+
+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;
+
+struct pv_page;
+
+struct pv_page_info {
+       TAILQ_ENTRY(pv_page) pgi_list;
+       struct pv_entry *pgi_freelist;
+       int pgi_nfree;
+};
+
+/*
+ * This is basically:
+ * ((NBPG - sizeof(struct pv_page_info)) / sizeof(struct pv_entry))
+ */
+#define NPVPPG ((NBPG - sizeof(struct pv_page_info)) / sizeof(struct pv_entry))
+
+struct pv_page {
+       struct pv_page_info pvp_pgi;
+       struct pv_entry pvp_pv[NPVPPG];
+};
+
+#ifdef  _KERNEL
+pv_entry_t      pv_table;               /* array of entries, one per page */
+extern pmap_t  kernel_pmap;
+extern struct pmap     kernel_pmap_store;
+
+#define pmap_kernel()  (&kernel_pmap_store)
+#define pmap_update()  tlbflush()
+#define        pmap_resident_count(pmap)       ((pmap)->pm_stats.resident_count)
+
+boolean_t pmap_testbit __P((vm_offset_t, int));
+void pmap_changebit __P((vm_offset_t, int, int));
+
+static __inline vm_offset_t
+pmap_phys_address(int ppn)
+{
+        return(arm_page_to_byte(ppn));
+}
+
+#endif
+
+#endif
+
+/* End of pmap.h */
diff --git a/sys/arch/arm32/include/podule.h b/sys/arch/arm32/include/podule.h
new file mode 100644 (file)
index 0000000..5561d45
--- /dev/null
@@ -0,0 +1,88 @@
+/*     $NetBSD: podule.h,v 1.2 1996/03/14 23:11:31 mark Exp $  */
+
+/*
+ * Copyright (C) 1994 Wolfgang Solfrank.
+ * Copyright (C) 1994 TooLs GmbH.
+ * 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 TooLs GmbH.
+ * 4. The name of TooLs GmbH may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (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        _ARM32_PODULE_H_
+#define        _ARM32_PODULE_H_
+
+/*
+ * Generic defines for Acorn Podules
+ */
+#define        IO_SPACE_PHYS   0x03000000              /* physical I/O space location */
+#define        IO_SPACE_VIRT   0xf8000000              /* virtual I/O space location */
+#define        IO_SPACE_SIZE   0x01000000              /* size of I/O space */
+
+#define        PODULE_SLOW_MEM ((volatile void *)(IO_SPACE_VIRT + 0x240000))
+#define        PODULE_MED_MEM  ((volatile void *)(IO_SPACE_VIRT + 0x2c0000))
+#define        PODULE_FAST_MEM ((volatile void *)(IO_SPACE_VIRT + 0x340000))
+#define        PODULE_SYNC_MEM ((volatile void *)(IO_SPACE_VIRT + 0x3c0000))
+
+#define        PODULE_SLOT2MEM(slot,mem)       ((slot)*0x4000 + (mem))
+
+/*
+ * Access 8 bit wide memory on podule
+ */
+#define        PODULE_GET_BYTE(sp,off)         (((volatile u_char *)(sp))[(off) * 4])
+#define        PODULE_SET_BYTE(sp,off,byte)    (((volatile u_int *)(sp))[(off)] \
+                                        = ((u_char)(byte) << 24) \
+                                          | ((u_char)(byte) << 16) \
+                                          | ((u_char)(byte) << 8) \
+                                          | (u_char)(byte))
+/*
+ * Access 16 bit wide memory on podule
+ */
+#define        PODULE_GET_SHORT(sp,off)        (((volatile u_short *)(sp))[(off)])
+#define        PODULE_SET_SHORT(sp,off,word)   (((volatile u_int *)(sp))[(off) / 2] \
+                                        = ((u_short)(word) << 16) \
+                                          | (u_short)(word))
+
+/*
+ * Known offsets in any podule
+ */
+#define        PODULE_IRQ_BYTE         0
+#define        PODULE_IRQ_PEND         1
+#define        PODULE_FIQ_PEND         2
+
+#define        PODULE_ID_BYTE          3
+#define        PODULE_ID_SCSI          2
+#define        PODULE_ID_ETHER         3
+
+extern void podule_get_bytes __P((volatile void *sp, void *dp, int cnt));
+extern void podule_set_bytes __P((void *sp, volatile void *dp, int cnt));
+
+extern void podule_get_shorts __P((volatile void *sp, void *dp, int cnt));
+extern void podule_set_shorts __P((void *sp, volatile void *dp, int cnt));
+
+/* XXX Shouldn't this be somewhere else? */
+#define        offsetof(type, member)  ((size_t)&((type *)0)->member)
+
+#endif /* _ARM_PODULE_H_ */
diff --git a/sys/arch/arm32/include/proc.h b/sys/arch/arm32/include/proc.h
new file mode 100644 (file)
index 0000000..ff2531b
--- /dev/null
@@ -0,0 +1,45 @@
+/* $NetBSD: proc.h,v 1.2 1996/03/14 23:11:33 mark Exp $ */
+
+/*
+ * Copyright (c) 1994 Mark Brinicombe.
+ * 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 RiscBSD team.
+ * 4. The name "RiscBSD" nor the name of the author may be used to
+ *    endorse or promote products derived from this software without specific
+ *    prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY RISCBSD ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL RISCBSD 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.
+ */
+
+#ifndef        _ARM32_PROC_H_
+#define        _ARM32_PROC_H_
+
+/*
+ * Machine-dependent part of the proc structure for arm.
+ */
+struct mdproc {
+       struct trapframe *md_regs;      /* registers on current frame */
+       int     __spare;
+};
+#endif
diff --git a/sys/arch/arm32/include/profile.h b/sys/arch/arm32/include/profile.h
new file mode 100644 (file)
index 0000000..9d6a132
--- /dev/null
@@ -0,0 +1,65 @@
+/* $NetBSD: profile.h,v 1.3 1996/03/14 23:11:34 mark Exp $ */
+
+/*
+ * Copyright (c) 1995-1996 Mark Brinicombe
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided 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 Mark Brinicombe.
+ * 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.
+ */
+
+#define        _MCOUNT_DECL static inline void _mcount
+
+/* Cannot implement mcount in C as GCC uses the ip register to pass the
+ * frompcindex variable. GCC also uses ip during the register pushing
+ * at the beginning of any C function.
+ */
+#define        MCOUNT \
+extern void mcount() asm("mcount");                                    \
+void                                                                   \
+mcount()                                                               \
+{                                                                      \
+       register int selfpc, frompcindex;                                       \
+       /*                                                              \
+        * find the return address for mcount,                          \
+        * and the return address for mcount's caller.                  \
+        *                                                              \
+        * selfpc = pc pushed by mcount call                            \
+        */                                                             \
+       asm("mov %0, lr" : "=r" (selfpc));                              \
+       /*                                                              \
+        * frompcindex = pc pushed by call into self.                   \
+        */                                                             \
+       asm("mov %0, ip" : "=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/arm32/include/psl.h b/sys/arch/arm32/include/psl.h
new file mode 100644 (file)
index 0000000..b7ffcf1
--- /dev/null
@@ -0,0 +1,84 @@
+/* $NetBSD: psl.h,v 1.2 1996/03/08 16:35:17 mark Exp $ */
+
+/*
+ * Copyright (c) 1995 Mark Brinicombe.
+ * 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 Mark Brinicombe.
+ * 4. The name of the company nor the name of the author may 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 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.
+ *
+ * RiscBSD kernel project
+ *
+ * psl.h
+ *
+ * spl prototypes.
+ * Eventually this will become a set of defines.
+ *
+ * Created      : 21/07/95
+ */
+
+/*
+ * These are the different SPL states
+ *
+ * Each state has an interrupt mask associated with it which
+ * indicate which interrupts are allowed.
+ */
+
+#define SPL_0          0
+#define SPL_SOFT       1
+#define SPL_BIO                2
+#define SPL_NET                3
+#define SPL_TTY                4
+#define SPL_CLOCK      5
+#define SPL_IMP                6
+#define SPL_HIGH       7
+#define SPL_LEVELS     8
+
+#define spl0()         splx(SPL_0)
+#define splhigh()      splx(SPL_HIGH)
+#define splbio()       raisespl(SPL_BIO)
+#define splnet()       raisespl(SPL_NET)
+#define spltty()       raisespl(SPL_TTY)
+#define splimp()       raisespl(SPL_IMP)
+#define splclock()     raisespl(SPL_CLOCK)
+#define splstatclock() raisespl(SPL_CLOCK)
+#define splsoftnet()   raisespl(SPL_SOFT)
+
+#ifndef _LOCORE
+int raisespl __P((int));
+int lowerspl __P((int));
+int splx __P((int));
+int splsoftclock __P(());
+
+#ifdef _KERNEL
+extern int current_spl_level;
+
+extern u_int spl_masks[SPL_LEVELS];
+#endif /* _KERNEL */
+#endif /* _LOCORE */
+
+/* End of psl.h */
diff --git a/sys/arch/arm32/include/pte.h b/sys/arch/arm32/include/pte.h
new file mode 100644 (file)
index 0000000..73a0873
--- /dev/null
@@ -0,0 +1,107 @@
+/* $NetBSD: pte.h,v 1.3 1996/03/14 23:11:36 mark Exp $ */
+
+/*
+ * Copyright (c) 1994 Mark Brinicombe.
+ * 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 RiscBSD team.
+ * 4. The name "RiscBSD" nor the name of the author may be used to
+ *    endorse or promote products derived from this software without specific
+ *    prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY RISCBSD ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL RISCBSD 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.
+ */
+
+#ifndef _ARM32_PTE_H_
+#define _ARM32_PTE_H_
+
+#define PDSHIFT        20                      /* LOG2(NBPDR) */
+#define NBPD           (1 << PDSHIFT)  /* bytes/page dir */
+/*# define PDOFSET     (NBPD-1)*/      /* byte offset into page dir */
+#define NPTEPD         (NBPD / NBPG)
+
+#ifndef _LOCORE
+typedef        int     pd_entry_t;             /* page directory entry */
+typedef        int     pt_entry_t;             /* page table entry */
+#endif
+
+#define PD_MASK        0xfff00000              /* page directory address bits */
+#define PT_MASK        0x000ff000              /* page table address bits */
+
+#define PG_FRAME       0xfffff000
+
+/* The PT_SIZE definition is misleading... A page table is only 0x400
+ * bytes long. But since VM mapping can only be done to 0x1000 a single
+ * 1KB blocks cannot be steered to a va by itself. Therefore the
+ * pages tables are allocated in blocks of 4. i.e. if a 1 KB block
+ * was allocated for a PT then the other 3KB would also get mapped
+ * whenever the 1KB was mapped.
+ */
+#define PT_SIZE                0x1000
+#define PD_SIZE                0x4000
+
+#define AP_KR          0x00
+#define AP_KRW         0x01
+#define AP_KRWUR       0x02
+#define AP_KRWURW      0x03
+
+#define AP_W           0x01
+#define AP_U           0x02
+
+#define PT_B           0x04    /* Phys - Buffered (write) */
+#define PT_C           0x08    /* Phys - Cacheable */
+#define PT_U           0x10    /* Phys - Updateable */
+
+#define PT_M           0x01    /* Virt - Modified */
+#define PT_H           0x02    /* Virt - Handled (Used) */
+#define PT_W           0x40    /* Virt - Wired */
+#define PT_Wr          0x10    /* Virt / Phys Write */
+#define PT_Us          0x20    /* Virt / Phys User */
+
+#define PT_AP(x)       ((x << 10) | (x << 8) | (x << 6)  | (x << 4))
+
+#define AP_SECTION_SHIFT       10
+
+#define L1_PAGE                0x01
+#define L1_SECTION     0x02
+#define L2_LPAGE       0x01
+#define L2_SPAGE       0x02
+#define L2_MASK                0x03
+#define L2_INVAL       0x00
+
+#define L2_PTE(p, a) ((p) | PT_AP(a) | L2_SPAGE | PT_C | PT_B)
+#define L2_PTE_NC(p, a) ((p) | PT_AP(a) | L2_SPAGE | PT_B)
+
+#define L1_PTE(p) ((p) | 0x00 | PT_U | L1_PAGE)
+
+#define L1_SEC(p) ((p) | (AP_KRW << AP_SECTION_SHIFT) | PT_U | L1_SECTION)
+
+#define DOMAIN_FAULT           0x00
+#define DOMAIN_CLIENT          0x01
+#define DOMAIN_RESERVED                0x02
+#define DOMAIN_MANAGER         0x03
+
+#endif
+
+/* End of pte.h */
diff --git a/sys/arch/arm32/include/ptrace.h b/sys/arch/arm32/include/ptrace.h
new file mode 100644 (file)
index 0000000..8eb446a
--- /dev/null
@@ -0,0 +1,41 @@
+/* $NetBSD: ptrace.h,v 1.2 1996/03/14 23:11:38 mark Exp $ */
+
+/*
+ * Copyright (c) 1995 Frank Lancaster
+ * Copyright (c) 1995 Tools GmbH
+ * 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 TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * arm-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/arm32/include/qmouse.h b/sys/arch/arm32/include/qmouse.h
new file mode 100644 (file)
index 0000000..1d776a5
--- /dev/null
@@ -0,0 +1,75 @@
+/* $NetBSD: qmouse.h,v 1.2 1996/03/14 23:11:40 mark Exp $ */
+
+/*
+ * Copyright (c) Scott Stevens 1995 All rights reserved
+ * Copyright (c) Melvin Tang-Richardson 1995 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 RiscBSD team.
+ * 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.
+ */
+
+#define MOVEEVENT      0x40
+#define B1TRANS                0x20
+#define B2TRANS                0x10
+#define B3TRANS                0x08
+#define BTRANSMASK     0x38
+#define B1VAL          0x04
+#define B2VAL          0x02
+#define B3VAL          0x01
+#define BVALMASK       0x07
+
+struct mousebufrec {
+       int status;
+       int x,y;
+       struct timeval event_time;
+};
+
+struct mouse_state {
+       signed short x, y;
+       int buttons;
+};
+
+struct mouse_boundingbox {
+       int x, y, a, b;
+};
+
+struct mouse_origin {
+       int x, y;
+};
+
+#define QUADMOUSE_WRITEX       _IO ( 'M', 100 )
+#define QUADMOUSE_WRITEY       _IO ( 'M', 101 )
+
+#define QUADMOUSE_SETSTATE     _IOW ( 'M', 102, struct mouse_state )
+#define QUADMOUSE_SETBOUNDS    _IOW ( 'M', 103, struct mouse_boundingbox )
+#define QUADMOUSE_SETORIGIN    _IOW ( 'M', 104, struct mouse_origin )
+
+#define QUADMOUSE_GETSTATE     _IOR ( 'M', 105, struct mouse_state )
+#define QUADMOUSE_GETBOUNDS    _IOR ( 'M', 106, struct mouse_boundingbox )
+#define QUADMOUSE_GETORIGIN    _IOR ( 'M', 107, struct mouse_origin )
+
+#define QUADMOUSE_SETFORMAT    _IOW ( 'M', 108, char[20] )
+
+/* End of qmouse.h */
diff --git a/sys/arch/arm32/include/reg.h b/sys/arch/arm32/include/reg.h
new file mode 100644 (file)
index 0000000..840a9d6
--- /dev/null
@@ -0,0 +1,58 @@
+/* $NetBSD: reg.h,v 1.2 1996/03/14 23:11:41 mark Exp $ */
+
+/*
+ * Copyright (C) 1994, 1995 Frank Lancaster
+ * Copyright (C) 1994, 1995 TooLs GmbH.
+ * 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 TooLs GmbH.
+ * 4. The name of TooLs GmbH may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (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
+ */
+
+#ifndef _ARM32_REG_H_
+#define _ARM32_REG_H_
+
+#include <machine/fp.h>
+
+struct reg {
+  unsigned int r[13];
+  unsigned int r_sp;
+  unsigned int r_lr;
+  unsigned int r_pc;
+  unsigned int r_cpsr;
+};
+
+/* this is identical to fp_state */
+struct fpreg {
+  unsigned int fpr_flags;
+  unsigned int fpr_sr;
+  unsigned int fpr_cr;
+  fp_reg_t fpr[16];
+};
+
+#endif /* !_ARM32_REG_H_ */
+
diff --git a/sys/arch/arm32/include/rtc.h b/sys/arch/arm32/include/rtc.h
new file mode 100644 (file)
index 0000000..7f9e689
--- /dev/null
@@ -0,0 +1,83 @@
+/* $NetBSD: rtc.h,v 1.3 1996/04/19 19:51:48 mark Exp $ */
+
+/*
+ * Copyright (c) 1994 Mark Brinicombe.
+ * Copyright (c) 1994 Brini.
+ * All rights reserved.
+ *
+ * This code is derived from software written for Brini by Mark Brinicombe
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided 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 Brini.
+ * 4. The name of the company nor the name of the author may be used to
+ *    endorse or promote products derived from this software without specific
+ *    prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BRINI ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL BRINI 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.
+ *
+ * RiscBSD kernel project
+ *
+ * rtc.h
+ *
+ * Header file for RTC / CMOS stuff
+ *
+ * Created      : 13/10/94
+ *
+ * Based of kate/display/iiccontrol.c
+ */
+
+/*
+ * IIC addresses for RTC chip
+ * Two PCF8583 chips are supported on the IIC bus
+ */
+
+#define IIC_PCF8583_MASK 0xfc
+#define IIC_PCF8583_ADDR 0xa0
+
+#define RTC_Write (IIC_PCF8583_ADDR | IIC_WRITE)
+#define RTC_Read  (IIC_PCF8583_ADDR | IIC_READ)
+
+typedef struct {
+       u_char rtc_micro;
+       u_char rtc_centi;
+       u_char rtc_sec;
+       u_char rtc_min;
+       u_char rtc_hour;
+       u_char rtc_day;
+       u_char rtc_mon;
+       u_char rtc_year;
+       u_char rtc_cen;
+} rtc_t;
+
+#define RTC_ADDR_BOOTOPTS      0x90
+#define RTC_ADDR_REBOOTCNT     0x91
+#define RTC_ADDR_YEAR          0xc0
+#define RTC_ADDR_CENT          0xc1
+
+#ifdef _KERNEL
+int cmos_read __P((int));
+int cmos_write __P((int, int));
+int rtc_read __P((rtc_t *));
+int rtc_write __P((rtc_t *));
+#endif /* _KERNEL */
+
+/* End of rtc.h */
diff --git a/sys/arch/arm32/include/setjmp.h b/sys/arch/arm32/include/setjmp.h
new file mode 100644 (file)
index 0000000..bac9859
--- /dev/null
@@ -0,0 +1,7 @@
+/* $NetBSD: setjmp.h,v 1.2 1996/03/14 23:11:45 mark Exp $ */
+
+/*
+ * machine/setjmp.h: machine dependent setjmp-related information.
+ */
+
+#define        _JBLEN  26              /* size, in longs, of a jmp_buf */
diff --git a/sys/arch/arm32/include/signal.h b/sys/arch/arm32/include/signal.h
new file mode 100644 (file)
index 0000000..2cae693
--- /dev/null
@@ -0,0 +1,89 @@
+/* $NetBSD: signal.h,v 1.3 1996/03/14 23:11:47 mark Exp $ */
+
+/*
+ * Copyright (c) 1994-1996 Mark Brinicombe.
+ * Copyright (c) 1994 Brini.
+ * All rights reserved.
+ *
+ * This code is derived from software written for Brini by Mark Brinicombe
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided 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 Brini.
+ * 4. The name of the company nor the name of the author may be used to
+ *    endorse or promote products derived from this software without specific
+ *    prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BRINI ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL BRINI 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.
+ *
+ * RiscBSD kernel project
+ *
+ * signal.h
+ *
+ * Architecture dependant signal types and structures
+ *
+ * Created      : 30/09/94
+ */
+
+#ifndef _ARM32_SIGNAL_H_
+#define _ARM32_SIGNAL_H_
+
+#ifndef _LOCORE
+
+typedef int sig_atomic_t;
+
+/*
+ * 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 */
+
+       unsigned int sc_spsr;
+       unsigned int sc_r0;
+       unsigned int sc_r1;
+       unsigned int sc_r2;
+       unsigned int sc_r3;
+       unsigned int sc_r4;
+       unsigned int sc_r5;
+       unsigned int sc_r6;
+       unsigned int sc_r7;
+       unsigned int sc_r8;
+       unsigned int sc_r9;
+       unsigned int sc_r10;
+       unsigned int sc_r11;
+       unsigned int sc_r12;
+       unsigned int sc_usr_sp;
+       unsigned int sc_usr_lr;
+       unsigned int sc_svc_lr;
+       unsigned int sc_pc;
+};
+
+#endif
+
+#endif /* _ARM_SIGNAL_H_ */
+
+/* End of signal.h */
diff --git a/sys/arch/arm32/include/stdarg.h b/sys/arch/arm32/include/stdarg.h
new file mode 100644 (file)
index 0000000..b0c4350
--- /dev/null
@@ -0,0 +1,60 @@
+/* $NetBSD: stdarg.h,v 1.2 1996/03/14 23:11:49 mark 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.
+ *
+ *     from: @(#)stdarg.h      8.1 (Berkeley) 6/10/93
+ */
+
+#ifndef _STDARG_H_
+#define        _STDARG_H_
+
+typedef char *va_list;
+
+#define        __va_promote(type) \
+       (((sizeof(type) + sizeof(int) - 1) / sizeof(int)) * sizeof(int))
+
+#define        va_start(ap, last) \
+       (ap = ((char *)&(last) + __va_promote(last)))
+
+#ifdef _KERNEL
+#define        va_arg(ap, type) \
+       ((type *)(ap += sizeof(type)))[-1]
+#else
+#define        va_arg(ap, type) \
+       ((type *)(ap += sizeof(type) < sizeof(int) ? \
+               (abort(), 0) : sizeof(type)))[-1]
+#endif
+
+#define        va_end(ap)
+
+#endif /* !_STDARG_H_ */
diff --git a/sys/arch/arm32/include/types.h b/sys/arch/arm32/include/types.h
new file mode 100644 (file)
index 0000000..4e841da
--- /dev/null
@@ -0,0 +1,70 @@
+/* $NetBSD: types.h,v 1.2 1996/03/06 23:04:04 mark 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.
+ *
+ *     from: @(#)types.h       7.5 (Berkeley) 3/9/91
+ */
+
+#ifndef        _ARM32_TYPES_H_
+#define        _ARM32_TYPES_H_
+
+#include <sys/cdefs.h>
+
+typedef struct _physadr {
+       int r[1];
+} *physadr;
+
+typedef struct label_t {       /* Used by setjmp & longjmp */
+        int val[11];
+} label_t;
+         
+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;
+
+#endif /* _ARM32_TYPES_H_ */
diff --git a/sys/arch/arm32/include/undefined.h b/sys/arch/arm32/include/undefined.h
new file mode 100644 (file)
index 0000000..c27b4c1
--- /dev/null
@@ -0,0 +1,63 @@
+/* $NetBSD: undefined.h,v 1.2 1996/03/14 23:11:51 mark Exp $ */
+
+/*
+ * Copyright (c) 1995-1996 Mark Brinicombe.
+ * Copyright (c) 1995 Brini.
+ * All rights reserved.
+ *
+ * This code is derived from software written for Brini by Mark Brinicombe
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided 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 Brini.
+ * 4. The name of the company nor the name of the author may be used to
+ *    endorse or promote products derived from this software without specific
+ *    prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BRINI ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL BRINI 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.
+ *
+ * RiscBSD kernel project
+ *
+ * undefined.h
+ *
+ * Undefined instruction types, symbols and prototypes
+ *
+ * Created      : 08/02/95
+ */
+
+#ifdef _KERNEL
+
+typedef int (*undef_handler_t) __P((unsigned int, unsigned int, trapframe_t *));
+
+#define FP_COPROC      1
+#define FP_COPROC2     2
+#define MAX_COPROCS    16
+
+extern undef_handler_t undefined_handlers[MAX_COPROCS];
+
+/* Prototypes for undefined.c */
+
+int install_coproc_handler __P((int, undef_handler_t));
+void undefined_init __P((void));
+
+#endif
+
+/* End of undefined.h */
diff --git a/sys/arch/arm32/include/varargs.h b/sys/arch/arm32/include/varargs.h
new file mode 100644 (file)
index 0000000..7f0c6bc
--- /dev/null
@@ -0,0 +1,64 @@
+/* $NetBSD: varargs.h,v 1.2 1996/03/14 23:11:53 mark 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.
+ *
+ *     from: @(#)varargs.h     8.2 (Berkeley) 3/22/94
+ */
+
+#ifndef _MACHINE_VARARGS_H_
+#define        _MACHINE_VARARGS_H_
+
+typedef char *va_list;
+
+#define        va_dcl  int va_alist; ...
+
+#define        va_start(ap) \
+       ap = (char *)&va_alist
+
+#ifdef _KERNEL
+#define        va_arg(ap, type) \
+       ((type *)(ap += sizeof(type)))[-1]
+#else
+#define        va_arg(ap, type) \
+       ((type *)(ap += sizeof(type) < sizeof(int) ? \
+               (abort(), 0) : sizeof(type)))[-1]
+#endif
+
+#define        va_end(ap)
+
+#endif /* !_MACHINE_VARARGS_H_ */
diff --git a/sys/arch/arm32/include/vconsole.h b/sys/arch/arm32/include/vconsole.h
new file mode 100644 (file)
index 0000000..fd8dd37
--- /dev/null
@@ -0,0 +1,294 @@
+/* $NetBSD: vconsole.h,v 1.1 1996/01/31 23:23:29 mark Exp $ */
+
+/*
+ * Copyright (c) 1994,1995 Melvyn Tang-Richardson
+ * All rights reserved.
+ *
+ * This code is derived from software written for Brini by Mark Brinicombe
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided 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 RiscBSD team
+ * 4. The name of the company nor the name of the author may be used to
+ *    endorse or promote products derived from this software without specific
+ *    prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHORS 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.
+ *
+ * RiscBSD kernel project
+ *
+ * vconsole.h
+ *
+ * Virtual console header
+ *
+ * Created      : 18/09/94
+ * Last updated : 10/01/96
+ *
+ *    $Id: vconsole.h,v 1.1.1.1 1996/04/24 11:08:46 deraadt Exp $
+ */
+
+#ifdef _KERNEL
+#define LOSSY           1
+#define FIXEDRES        2
+
+#define BOLD           (1<<15)
+#define UNDERLINE      (1<<16)
+#define REVERSE                (1<<17)
+#define BLINKING       (1<<18)
+
+#include <machine/vidc.h>
+
+struct vconsole;
+
+/*
+ * Render routines and terminal drivers which conform to version 1.00
+ * of the spec should always be present.  This is the lowest common
+ * denominator, which enables the driver to always find something that
+ * will work.
+ *
+ * Prefered drivers can be added required in the tables.
+ */
+
+struct render_engine {
+       char * name;
+        int  ( *init           ) __P(( struct vconsole *vc ));
+        void ( *putchar                ) __P(( dev_t dev, char c, struct vconsole *vc ));
+        int  ( *spawn          ) __P(( struct vconsole *vc ));
+        int  ( *swapin         ) __P(( struct vconsole *vc ));
+        int  ( *mmap           ) __P(( struct vconsole *vc, int offset, int nprot ));
+       void ( *render          ) __P(( struct vconsole *vc, char c));
+       void ( *scrollup        ) __P(( struct vconsole *vc, int low, int high ));
+       void ( *scrolldown      ) __P(( struct vconsole *vc, int low, int high ));
+       void ( *cls             ) __P(( struct vconsole *vc ));
+       void ( *update          ) __P(( struct vconsole *vc ));
+       int ( *scrollback       ) __P(( struct vconsole *vc ));
+       int ( *scrollforward    ) __P(( struct vconsole *vc ));
+       int ( *scrollbackend    ) __P(( struct vconsole *vc ));
+       int ( *clreos           ) __P(( struct vconsole *vc, int code ));
+       int ( *debugprint       ) __P(( struct vconsole *vc ));
+       int ( *cursorupdate     ) __P(( struct vconsole *vc ));
+       int ( *cursorflashrate  ) __P(( struct vconsole *vc, int rate ));
+       int ( *setfgcol         ) __P(( struct vconsole *vc, int col ));
+       int ( *setbgcol         ) __P(( struct vconsole *vc, int col ));
+       int ( *textpalette      ) __P(( struct vconsole *vc ));
+       int ( *sgr              ) __P(( struct vconsole *vc, int type ));
+       int ( *blank            ) __P(( struct vconsole *vc, int type ));
+        int ( *ioctl           ) __P(( struct vconsole *vc, dev_t dev, int cmd,
+                                   caddr_t data, int flag, struct proc *p));
+        int ( *redraw          ) __P(( struct vconsole *vc, int x, int y, int a, int b ));
+       int ( *attach           ) __P(( struct vconsole *vc, struct device *dev, struct device *dev1, void * arg));
+       int ( *flash            ) __P(( struct vconsole *vc, int flash ));
+       int ( *cursor_flash     ) __P(( struct vconsole *vc, int flash ));
+};
+
+/* Blank types.  VESA defined */
+
+/* Blank type 3 is suported by default */
+
+#define BLANK_NONE     0       /* Not really blanked */
+#define BLANK_IDLE     1       /* Vsync dropped for fast reactivation */ 
+#define BLANK_UNUSED   2       /* Hsync dropped for semi fast reactivation */
+#define BLANK_OFF      3       /* All signals removed slowest reactivation */
+
+#define R_NAME         render_engine->name
+#define        SPAWN           render_engine->spawn
+#define SCROLLUP       render_engine->scrollup
+#define SCROLLDOWN     render_engine->scrolldown
+#define RENDER         render_engine->render
+#define R_SWAPIN       render_engine->swapin
+#define CLS            render_engine->cls
+#define R_INIT         render_engine->init
+#define PUTCHAR                render_engine->putchar
+#define R_SWAPIN       render_engine->swapin
+#define MMAP           render_engine->mmap
+#define R_SCROLLBACK   render_engine->scrollback
+#define R_SCROLLFORWARD        render_engine->scrollforward
+#define R_SCROLLBACKEND        render_engine->scrollbackend
+#define R_CLREOS       render_engine->clreos
+#define R_DEBUGPRINT   render_engine->debugprint
+#define CURSORUPDATE   render_engine->cursorupdate
+#define CURSORFLASHRATE        render_engine->cursorflashrate
+#define SETFGCOL       render_engine->setfgcol
+#define SETBGCOL       render_engine->setbgcol
+#define        TEXTPALETTE     render_engine->textpalette
+#define        SGR             render_engine->sgr
+#define BLANK          render_engine->blank
+#define IOCTL          render_engine->ioctl
+#define REDRAW         render_engine->redraw
+#define R_ATTACH       render_engine->attach
+#define FLASH          render_engine->flash
+#define CURSOR_FLASH   render_engine->cursor_flash
+
+/*
+ * The terminal emulator's scroll back is only used as a last resort for
+ * cases when a render engine can't scrollback.  In most cases though, the
+ * terminal emulator won't allocate enough chapmap to perform scrollback.
+ */
+
+struct terminal_emulator {
+       char *name;
+       /* Terminal emulation routines */
+       int (*term_init)        __P((struct vconsole *vc));
+        int (*putstring)       __P((char *string, int length, struct vconsole *vc));
+        int (*swapin)          __P((struct vconsole *vc));
+       int (*swapout)          __P((struct vconsole *vc));
+       int (*sleep)            __P((struct vconsole *vc));
+       int (*wake)             __P((struct vconsole *vc));
+       int ( *scrollback)      __P(( struct vconsole *vc ));
+       int ( *scrollforward)   __P(( struct vconsole *vc ));
+       int ( *scrollbackend)   __P(( struct vconsole *vc ));
+       int ( *debugprint)      __P(( struct vconsole *vc ));
+       int ( *modechange)      __P(( struct vconsole *vc ));
+       int ( *attach )         __P(( struct vconsole *vc, struct device *dev, struct device *dev1, void *arg ));
+};
+
+#define T_NAME         terminal_emulator->name
+#define TERM_INIT      terminal_emulator->term_init
+#define T_SWAPIN       terminal_emulator->swapin
+#define PUTSTRING      terminal_emulator->putstring
+#define SLEEP          terminal_emulator->sleep
+#define WAKE           terminal_emulator->wake
+#define T_SCROLLBACK   terminal_emulator->scrollback
+#define T_SCROLLFORWARD        terminal_emulator->scrollforward
+#define T_SCROLLBACKEND        terminal_emulator->scrollbackend
+#define T_DEBUGPRINT   terminal_emulator->debugprint
+#define MODECHANGE     terminal_emulator->modechange
+#define T_ATTACH       terminal_emulator->attach
+
+struct vconsole {
+        /* Management of consoles */
+
+        struct vconsole *next;
+        int number;
+        int opened;
+        struct tty *tp;
+       struct proc *proc;
+        int flags;
+
+        /* Data structures */
+        char *data;
+       char *r_data;
+
+        /* Structures required for the generic character map */
+        int xchars, ychars;
+        int *charmap;
+       int xcur, ycur;
+
+       /* This is the end of the old stuff */
+
+       struct render_engine *render_engine;
+       struct terminal_emulator *terminal_emulator;
+
+       int t_scrolledback;
+       int r_scrolledback;
+
+       int blanked;
+
+       int vtty;
+};
+
+extern int vconsole_pending;
+extern int vconsole_blankinit;
+extern int vconsole_blankcounter;
+
+extern struct vconsole *vconsole_current;
+
+extern struct render_engine *render_engine_tab[];
+extern struct terminal_emulator *terminal_emulator_tab[];
+
+#endif
+
+/* ioctls for switching between vconsoles */
+
+#define CONSOLE_SWITCHUP       _IO( 'n',  0 )
+#define CONSOLE_SWITCHDOWN     _IO( 'n',  1 )
+#define CONSOLE_SWITCHTO       _IOW( 'n', 2, int )
+#define CONSOLE_SWITCHPREV     _IO( 'n',  3 )
+
+/* ioctls for creating new virtual consoles */
+
+#define CONSOLE_CREATE         _IOW( 'n', 10, int )
+#define CONSOLE_RENDERTYPE     _IOR( 'n', 11, 20 )
+#define CONSOLE_TERMTYPE       _IOR( 'n', 12, 20 )
+
+/* ioctls for locking in the current console.  Kinky eh ? */
+
+#define CONSOLE_LOCK           _IO( 'n', 20 )
+#define CONSOLE_UNLOCK         _IO( 'n', 21 )
+
+/* ioctls for animation, multimedia and games */
+
+#define CONSOLE_SWOP           _IO( 'n', 30 ) /* Screen Banking */
+
+#ifdef CONSOLEGFX
+struct console_line {
+       int len;
+       char data[128];
+};
+
+struct console_coords {
+       int x, y;
+};
+
+#define CONSOLE_DRAWGFX                _IOW( 'n', 31, struct console_line ) /* Screen Banking */
+#define CONSOLE_MOVE           _IOW( 'n', 32, struct console_coords )
+#endif
+
+/* ioctls for configuration and control */
+
+#define CONSOLE_CURSORFLASHRATE        _IOW ( 'n', 40, int )
+#define CONSOLE_MODE           _IOW ( 'n', 41, struct vidc_mode )
+#define CONSOLE_MODE_ALL       _IOW ( 'n', 42, struct vidc_mode )
+
+#define CONSOLE_BLANKTIME      _IOW ( 'n', 44, int )
+
+/* ioctls for developers *DO NOT USE * */
+
+#define CONSOLE_SPAWN_VIDC     _IOW( 'n', 100, int )
+#define CONSOLE_DEBUGPRINT     _IOW( 'n', 101, int )
+
+
+/* structures and ioctls added by mark for the Xserver development */
+
+struct console_info {
+       videomemory_t videomemory;
+       int width;
+       int height;
+       int bpp;
+};
+
+struct console_palette {
+       int entry;
+       int red;
+       int green;
+       int blue;
+};
+
+#define CONSOLE_RESETSCREEN    _IO( 'n', 102)
+#define CONSOLE_RESTORESCREEN  _IO( 'n', 103)
+#define CONSOLE_GETINFO                _IOR( 'n', 104, struct console_info )
+#define CONSOLE_PALETTE                _IOW( 'n', 105, struct console_palette )
+#define CONSOLE_GETVC          _IOR( 'n', 106, int )
+
+#define CONSOLE_IOCTL_COMPAT_N _IO( 'n', 107 )
+#define CONSOLE_IOCTL_COMPAT_T _IO( 't', 107 )
+
+/* End of vconsole.h */
diff --git a/sys/arch/arm32/include/vidc.h b/sys/arch/arm32/include/vidc.h
new file mode 100644 (file)
index 0000000..4c28277
--- /dev/null
@@ -0,0 +1,269 @@
+/* $NetBSD: vidc.h,v 1.2 1996/03/28 21:22:24 mark Exp $ */
+
+/*
+ * Copyright (c) 1994,1995 Mark Brinicombe.
+ * Copyright (c) 1994,1995 Brini.
+ * All rights reserved.
+ *
+ * This code is derived from software written for Brini by Mark Brinicombe
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided 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 Brini.
+ * 4. The name of the company nor the name of the author may be used to
+ *    endorse or promote products derived from this software without specific
+ *    prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BRINI ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL BRINI 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.
+ *
+ * RiscBSD kernel project
+ *
+ * vidc.h
+ *
+ * VIDC20 registers
+ *
+ * Created      : 18/09/94
+ * Last updated : 08/03/95
+ *
+ * Based on kate/display/vidc.h
+ *
+ *    $Id: vidc.h,v 1.1.1.1 1996/04/24 11:08:46 deraadt Exp $
+ */
+
+#ifndef __vidc_h
+#define __vidc_h
+
+/* VIDC20 Base addresses */
+
+#define VIDC_HW_BASE 0x03400000
+
+#define VIDC_BASE    0xf6100000
+
+/* Video registers */
+
+#define VIDC_PALETTE 0x00000000
+#define VIDC_PALREG  0x10000000
+
+#define VIDC_BCOL    0x40000000
+#define VIDC_CP0     0x40000000
+#define VIDC_CP1     0x50000000
+#define VIDC_CP2     0x60000000
+#define VIDC_CP3     0x70000000
+
+#define VIDC_HCR     0x80000000
+#define VIDC_HSWR    0x81000000
+#define VIDC_HBSR    0x82000000
+#define VIDC_HDSR    0x83000000
+#define VIDC_HDER    0x84000000
+#define VIDC_HBER    0x85000000
+#define VIDC_HCSR    0x86000000
+#define VIDC_HIR     0x87000000
+
+#define VIDC_VCR     0x90000000
+#define VIDC_VSWR    0x91000000
+#define VIDC_VBSR    0x92000000
+#define VIDC_VDSR    0x93000000
+#define VIDC_VDER    0x94000000
+#define VIDC_VBER    0x95000000
+#define VIDC_VCSR    0x96000000
+#define VIDC_VCER    0x97000000
+
+#define VIDC_EREG    0xc0000000
+#define VIDC_FSYNREG 0xd0000000
+#define VIDC_CONREG  0xe0000000
+#define VIDC_DCTL    0xf0000000
+
+/* VIDC palette macros */
+
+#define VIDC_RED(r)   (r)
+#define VIDC_GREEN(g) (g << 8)
+#define VIDC_BLUE(b)  (b << 16)
+#define VIDC_COL(r, g, b) (VIDC_RED(r) | VIDC_GREEN(g) | VIDC_BLUE(b))
+
+#ifdef RC7500
+/*
+ * Video frequency definitions
+ */
+#define VIDFREQ_25_18  0x00
+#define VIDFREQ_28_32  0x01
+#define VIDFREQ_40_00  0x02
+#define VIDFREQ_72_00  0x03
+#define VIDFREQ_50_00  0x04
+#define VIDFREQ_77_00  0x05
+#define VIDFREQ_36_00  0x06
+#define VIDFREQ_44_90  0x07
+#define VIDFREQ_130_0  0x08
+#define VIDFREQ_120_0  0x09
+#define VIDFREQ_80_00  0x0A
+#define VIDFREQ_31_50  0x0B
+#define VIDFREQ_110_0  0x0C
+#define VIDFREQ_65_00  0x0D
+#define VIDFREQ_75_00  0x0E
+#define VIDFREQ_94_50  0x0F
+#endif
+
+
+/* Sound registers */
+
+#define VIDC_SIR0    0xa0000000
+#define VIDC_SIR1    0xa1000000
+#define VIDC_SIR2    0xa2000000
+#define VIDC_SIR3    0xa3000000
+#define VIDC_SIR4    0xa4000000
+#define VIDC_SIR5    0xa5000000
+#define VIDC_SIR6    0xa6000000
+#define VIDC_SIR7    0xa7000000
+
+#define VIDC_SFR     0xb0000000
+#define VIDC_SCR     0xb1000000
+
+#define SIR_LEFT_100  0x01
+#define SIR_LEFT_83   0x02
+#define SIR_LEFT_67   0x03
+#define SIR_CENTRE    0x04
+#define SIR_RIGHT_67  0x05
+#define SIR_RIGHT_83  0x06
+#define SIR_RIGHT_100 0x07
+
+/* Video display addresses */
+
+/* Where the display memory is mapped */
+
+#define VMEM_VBASE 0xf4000000
+
+/* Where the VRAM will be found */
+
+#define VRAM_BASE 0x02000000
+
+/* Video memory descriptor */
+
+typedef struct
+  {
+    u_int vidm_vbase;  /* virtual base of video memory */
+    u_int vidm_pbase;  /* physical base of video memory */
+    u_int vidm_size;   /* video memory size */
+    int   vidm_type;   /* video memory type */
+  } videomemory_t;
+
+#define VIDEOMEM_TYPE_VRAM 0x01
+#define VIDEOMEM_TYPE_DRAM 0x02
+
+/* Structures and prototypes for vidc handling functions */
+
+struct vidc_state {
+       int palette[256];
+       int palreg;
+       int bcol;
+       int cp1;
+       int cp2;
+       int cp3;
+       int hcr, hswr, hbsr, hdsr, hder, hber, hcsr; 
+       int hir;
+       int vcr, vswr, vbsr, vdsr, vder, vber, vcsr, vcer;      
+       int ereg;
+       int fsynreg;
+       int conreg;
+       int dctl;
+};
+
+#define VIDC_FREF      24000000
+
+#ifdef _KERNEL
+extern int  vidc_write         __P((u_int /*reg*/, int /*value*/));
+extern void vidc_setstate      __P((struct vidc_state */*vidc*/));
+extern void vidc_setpalette    __P((struct vidc_state */*vidc*/));
+extern void vidc_stdpalette    __P(());
+extern int  vidc_col           __P((int /*red*/, int /*green*/, int /*blue*/));
+extern struct vidc_state vidc_current[];
+#endif
+
+struct vidc_mode {
+    int pixel_rate;
+    int hswr, hbsr, hdsr, hder, hber, hcr;
+    int vswr, vbsr, vdsr, vder, vber, vcr;
+    int bitsperpixel;
+    int sync_pol;
+    int frame_rate;
+};
+
+typedef struct
+  {
+    int chars;                 /* Number of characters defined in font */
+    int width;                 /* Defined width of characters in bytes */
+    int height;                /* Defined height of characters in lines */
+    int pixel_width;           /* Width of characters in pixels */
+    int pixel_height;          /* Height of characters in pixels */
+    int x_spacing;             /* Spacing in pixels between chars */
+    int y_spacing;             /* Spacing in pixels between lines */
+    int data_size;             /* Allocated data size */
+    unsigned char *data;       /* Font data */
+  } font_struct;
+
+#define XRES mode.hder
+#define YRES mode.vder
+#define BITSPERPIXEL mode.bitsperpixel
+
+struct vidc_info
+  {
+    struct vidc_mode mode;
+    struct vidc_state vidc;
+    font_struct *font;         /* pointer to current font_struct */
+    font_struct *normalfont;   /* pointer to normal font struct */
+    font_struct *italicfont;   /* pointer to italic font struct */
+    font_struct *boldfont;     /* pointer to bold font struct */
+    int xfontsize, yfontsize;
+    int text_width, text_height;
+    int bytes_per_line;
+    int bytes_per_scroll;
+    int pixelsperbyte;
+    int screensize;
+    int fast_render;
+    int forecolour, forefillcolour;
+    int backcolour, backfillcolour;
+    int text_colours;
+    int frontporch;
+    int topporch;      /* ;) */
+    int bold;
+    int reverse;
+    int n_forecolour;
+    int n_backcolour;
+    int blanked;
+    int scrollback_end;
+    int flash;
+    int cursor_flash;
+  };
+
+#define COLOUR_BLACK_1 0x00
+#define COLOUR_WHITE_1 0x01
+
+#define COLOUR_BLACK_2 0x00
+#define COLOUR_WHITE_2 0x03
+
+#define COLOUR_BLACK_4 0x00
+#define COLOUR_WHITE_4 0x07
+
+#define COLOUR_BLACK_8 0x00
+#define COLOUR_WHITE_8 0x07
+
+#endif
+
+/* End of vidc.h */
+
diff --git a/sys/arch/arm32/include/vmparam.h b/sys/arch/arm32/include/vmparam.h
new file mode 100644 (file)
index 0000000..d86654c
--- /dev/null
@@ -0,0 +1,116 @@
+/* $NetBSD: vmparam.h,v 1.1 1996/01/31 23:23:37 mark 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.
+ *
+ *     $Id: vmparam.h,v 1.1.1.1 1996/04/24 11:08:46 deraadt Exp $
+ */
+
+#ifndef        _ARM32_VMPARAM_H_
+#define        _ARM32_VMPARAM_H_
+
+#define        USRTEXT         VM_MIN_ADDRESS
+#define        USRSTACK        VM_MAXUSER_ADDRESS
+
+/*
+ * Note that MAXTSIZ mustn't be greater than 32M. Otherwise you'd have
+ * to change the compiler to not generate bl instructions
+ */
+#define        MAXTSIZ         (8*1024*1024)           /* max text size */
+#ifndef        DFLDSIZ
+#define        DFLDSIZ         (16*1024*1024)          /* initial data size limit */
+#endif
+#ifndef        MAXDSIZ
+#define        MAXDSIZ         (256*1024*1024)         /* max data size */
+#endif
+#ifndef        DFLSSIZ
+#define        DFLSSIZ         (512*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 */
+
+/*
+ * Size of shared memory map
+ */
+#ifndef SHMMAXPGS
+#define SHMMAXPGS       1024
+#endif
+
+/*
+ * 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
+
+/*
+ * Mach derived constants
+ */
+   
+/*#define      VM_MIN_ADDRESS          ((vm_offset_t)0x00400000)*/
+#define        VM_MIN_ADDRESS          ((vm_offset_t)0x00001000)
+#define        VM_MAXUSER_ADDRESS      ((vm_offset_t)0xefc00000 - UPAGES * NBPG)
+#define        VM_MAX_ADDRESS          ((vm_offset_t)0xeffc0000)
+
+#define        VM_MIN_KERNEL_ADDRESS   ((vm_offset_t)0xf0000000)
+#define        VM_MAX_KERNEL_ADDRESS   ((vm_offset_t)0xffffffff)
+
+/*
+ * Size of User Raw I/O map
+ */
+
+#define USRIOSIZE       300
+
+/* 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)
+#endif
+
+/* End of vmparam.h */
+                                            
diff --git a/sys/arch/arm32/kshell/dumphex.c b/sys/arch/arm32/kshell/dumphex.c
new file mode 100644 (file)
index 0000000..d45947b
--- /dev/null
@@ -0,0 +1,133 @@
+/* $NetBSD: dumphex.c,v 1.2 1996/03/18 20:32:31 mark Exp $ */
+
+/*
+ * Copyright (c) 1994 Mark Brinicombe.
+ * Copyright (c) 1994 Brini.
+ * All rights reserved.
+ *
+ * This code is derived from software written for Brini by Mark Brinicombe
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided 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 Brini.
+ * 4. The name of the company nor the name of the author may be used to
+ *    endorse or promote products derived from this software without specific
+ *    prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BRINI ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL BRINI 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.
+ *
+ * RiscBSD kernel project
+ *
+ * dumphex.c
+ *
+ * Hex memory dump routines
+ *
+ * Created      : 17/09/94
+ */
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/systm.h>
+
+/* dumpb - dumps memory in bytes*/
+
+void
+dumpb(addr, count)
+       u_char *addr;
+       int count;
+{
+       u_int byte;
+       int loop;
+
+       for (; count > 0; count -= 16) {
+               printf("%08x: ", (int)addr);
+
+               for (loop = 0; loop < 16; ++loop) {
+                       byte = addr[loop];
+                       printf("%02x ", byte);
+               }
+
+               printf(" ");
+
+               for (loop = 0; loop < 16; ++loop) {
+                       byte = addr[loop];
+                       if (byte < 0x20)
+                               printf("\x1b[31m%c\x1b[0m", byte + '@');
+                       else if (byte == 0x7f)
+                               printf("\x1b[31m?\x1b[0m");
+                       else if (byte < 0x80)
+                               printf("%c", byte);
+                       else if (byte < 0xa0)
+                               printf("\x1b[32m%c\x1b[0m", byte - '@');
+                       else if (byte == 0xff)
+                               printf("\x1b[32m?\x1b[0m");
+                       else
+                               printf("%c", byte & 0x7f);
+               }
+
+               printf("\r\n");
+               addr += 16;
+       }
+}
+
+
+/* dumpw - dumps memory in bytes*/
+
+void 
+dumpw(addr, count)
+       u_char *addr;
+       int count;
+{
+       u_int byte;
+       int loop;
+
+       for (; count > 0; count -= 32) {
+               printf("%08x: ", (int)addr);
+
+               for (loop = 0; loop < 8; ++loop) {
+                       byte = ((u_int *)addr)[loop];
+                       printf("%08x ", byte);
+               }
+
+               printf(" ");
+
+               for (loop = 0; loop < 32; ++loop) {
+                       byte = addr[loop];
+                       if (byte < 0x20)
+                               printf("\x1b[31m%c\x1b[0m", byte + '@');
+                       else if (byte == 0x7f)
+                               printf("\x1b[31m?\x1b[0m");
+                       else if (byte < 0x80)
+                               printf("%c", byte);
+                       else if (byte < 0xa0)
+                               printf("\x1b[32m%c\x1b[0m", byte - '@');
+                       else if (byte == 0xff)
+                               printf("\x1b[32m?\x1b[0m");
+                       else
+                               printf("%c", byte & 0x7f);
+               }
+
+               printf("\r\n");
+               addr += 32;
+       }
+}
+
+/* End of dumphex.c */
diff --git a/sys/arch/arm32/kshell/shell_disassem.c b/sys/arch/arm32/kshell/shell_disassem.c
new file mode 100644 (file)
index 0000000..6de632e
--- /dev/null
@@ -0,0 +1,186 @@
+/* $NetBSD: shell_disassem.c,v 1.2 1996/03/06 23:52:15 mark Exp $ */
+
+/*
+ * Copyright (c) 1994 Mark Brinicombe.
+ * Copyright (c) 1994 Brini.
+ * All rights reserved.
+ *
+ * This code is derived from software written for Brini by Mark Brinicombe
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided 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 Brini.
+ * 4. The name of the company nor the name of the author may be used to
+ *    endorse or promote products derived from this software without specific
+ *    prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BRINI ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL BRINI 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.
+ *
+ * RiscBSD kernel project
+ *
+ * shell_disassem.c
+ *
+ * Debug / Monitor shell disassembler
+ *
+ * Created      : 09/10/94
+ */
+
+/* Include standard header files */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+
+/* Local header files */
+
+#include <machine/katelib.h>
+
+/* Declare external variables */
+
+/* Local function prototypes */
+
+u_int disassemble __P((u_char *));
+u_int do_disassemble __P((u_char *));
+
+/* Now for the main code */
+
+/* dis - disassembles memory */
+
+void
+shell_disassem(argc, argv)
+       int argc;
+       char *argv[];
+{
+       u_char *addr;
+
+       if (argc < 2) {
+               printf("Syntax: dis <addr>\n\r");
+               return;
+       }
+
+/* Decode the one argument */
+
+       addr = (u_char *)readhex(argv[1]);
+
+       printf("Interactive disassembly\n\r");
+
+       do_disassemble(addr);
+}
+
+
+u_int
+do_disassemble(addr)
+       u_char *addr;
+{
+       u_int result;
+       int quit = 0;
+       int key;
+       int count = 1;
+
+       do {
+               result = disassemble(addr);
+
+               --count;
+
+               if (count == 0) {
+                       count = 1;
+
+                       key = cngetc();
+
+                       switch (key) {
+                       case 'Q' :
+                       case 'q' :
+                       case 0x1b :
+                       case 0x03 :
+                       case 0x04 :
+                       case 0x10b :
+                               quit = 1;
+                               break;
+                       case 0x09 :
+                       case 'r' :
+                       case 'R' :
+                       case 0x103 :
+                               count = 16;
+                               addr += 4;
+                               break;
+
+                       case 0x102 :
+                               count = 16;
+                               addr -= 124;
+                               break;
+
+                       case 0x0d :
+                       case 0x101 :
+                               addr = addr + 4;
+                               break;
+
+                       case 'B' :
+                       case 'b' :
+                       case 0x100:
+                               addr = addr - 4;
+                               break;
+
+                       case '+' :
+                       case '=' :
+                       case 0x104 :
+                               addr = addr + 0x80;
+                               break;
+
+                       case '-' :
+                       case '_' :
+                       case 0x105 :
+                               addr = addr - 0x80;
+                               break;
+
+                       case ' ' :
+                               quit = do_disassemble((u_char *)result);
+                               break;
+
+                       case 'J' :
+                       case 'j' :
+                               addr = (u_char *)result;
+                               break;
+
+                       case '/' :
+                       case '?' :
+                               printf("\'\xe3\'  - Backwards 1 word\n\r");
+                               printf("\'\xe4\'  - Forwards 1 word\n\r");
+                               printf("\'\xe5\'  - Backwords 16 words\n\r");
+                               printf("\'\xe6\'  - Forwards 16 words\n\r");
+                               printf("\'Q\'  - Quit\n\r");
+                               printf("\'B\'  - Back a word\n\r");
+                               printf("\'R\'  - Disassemble 16 words\n\r");
+                               printf("\'J\'  - Jump to address\n\r");
+                               printf("\' \'  - Branch to address\n\r");
+                               printf("<BS> - Return from branch\n\r");
+                               printf("\'-\'  - Skip backwards 128 words\n\r");
+                               printf("\'+\'  - Skip forwards 128 words\n\r");
+                               break;
+
+                       }
+               } else {
+                       addr += 4;
+               }
+       } while (!quit && key != 0x08);
+
+       return(quit);
+}
+
+/* End of shell_disassem.c */
diff --git a/sys/arch/arm32/kshell/shell_input.c b/sys/arch/arm32/kshell/shell_input.c
new file mode 100644 (file)
index 0000000..07cbd57
--- /dev/null
@@ -0,0 +1,297 @@
+/* $NetBSD: shell_input.c,v 1.2 1996/03/06 23:44:07 mark Exp $ */
+
+/*
+ * Copyright (c) 1994 Mark Brinicombe.
+ * Copyright (c) 1994 Brini.
+ * All rights reserved.
+ *
+ * This code is derived from software written for Brini by Mark Brinicombe
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided 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 Brini.
+ * 4. The name of the company nor the name of the author may be used to
+ *    endorse or promote products derived from this software without specific
+ *    prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BRINI ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL BRINI 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.
+ *
+ * RiscBSD kernel project
+ *
+ * shell_input.c
+ *
+ * string input functions
+ *
+ * Created      : 09/10/94
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/malloc.h>
+
+/*#define SOFT_CURSOR*/
+
+/* Declare global variables */
+
+/* Prototype declarations */
+
+char    *strchr __P((const char *, int));
+
+void deleteline __P((int, int));
+
+/*
+ * Reads a line from the keyboard into an input buffer allowing
+ * cursor editing and input history.
+ */
+
+int
+readstring(string, length, valid_string, insert)
+       char *string;
+       int length;
+       char *valid_string;
+       char *insert;
+{
+       int key;
+       int loop;
+       int entered;
+       int insert_mode = 1;
+
+/*
+ * If we have text to preinsert into the buffer enter it and echo it
+ * to the display.
+ */
+
+       if (insert && insert[0] != 0) {
+               strcpy(string, insert);
+               loop = strlen(insert);
+               printf("%s", insert);
+       } else
+               loop = 0;
+
+       entered = loop;
+
+/*
+ * The main loop.
+ * Keep looping until return or CTRL-D is pressed.
+ */
+
+       do {
+#ifdef SOFT_CURSOR
+/*
+ * Display the cursor depending on what mode we are in
+ */
+               if (!insert_mode)
+                       printf("\xe2");
+               else
+                       printf("\xe1");
+#endif
+
+/*
+ * Read the keyboard
+ */
+
+               key = cngetc();
+
+#ifdef SOFT_CURSOR
+/*
+ * Remove the cursor, restoring the text under it if necessary.
+ */
+
+               if (loop == entered || entered == 0)
+                       printf("\x7f");
+               else
+                       printf("\x08%c\x08", string[loop]);
+#endif
+
+/*
+ * Decode the key
+ */
+
+               switch (key) {
+/*
+ * DELETE
+ */
+
+               case 0x109 :
+               case 0x7f :
+               {
+                       int loop1;
+
+                       if (loop == entered) break;
+                       for (loop1 = loop; loop1 < (entered - 1); ++loop1) {
+                               string[loop1] = string[loop1+1];
+                       }
+                       --entered;
+                       string[entered] = 0;
+/*                     printf("\x1b[s%s \x1b[u", &string[loop]);*/
+                       printf("\r%s \r", string);
+                       for (loop1 = 0; loop1 <= loop; ++loop1)
+                               printf("\x09");
+               }
+               break;
+
+/*
+ * BACKSPACE
+ */
+
+               case 0x08 :
+               {
+                       int loop1;
+
+                       if (loop == 0) {
+                               printf("\x07");
+                               break;
+                       }
+                       for (loop1 = loop-1; loop1 < (entered - 1); ++loop1) {
+                               string[loop1] = string[loop1+1];
+                       }
+                       --loop;
+                       --entered;
+                       string[entered] = 0;
+/*                     printf("\x1b[D\x1b[s%s \x1b[u", &string[loop]);*/
+                       printf("\r%s \r", string);
+                       for (loop1 = 0; loop1 < loop; ++loop1)
+                               printf("\x09");
+               }
+               break;
+
+/*
+ * CTRL-U
+ */
+               case 0x15 :
+                       deleteline(loop, entered);
+                       loop = 0;
+                       entered = 0;
+                       break;
+
+/*
+ * CTRL-A
+ */
+               case 0x01 :
+                       insert_mode = !insert_mode;
+                       break;
+
+/*
+ * CTRL-D
+ */
+               case 0x04 :
+                       return(-1);
+                       break;
+
+/*
+ * CURSOR LEFT
+ */
+
+               case 0x102 :
+                       --loop;
+                       if (loop < 0)
+                               loop = 0;
+                       else
+                               printf("\x1b[D");
+                       break;
+
+/*
+ * CURSOR RIGHT
+ */
+
+               case 0x103 :
+                       ++loop;
+                       if (loop > entered)
+                               loop = entered;
+                       else
+                               printf("\x1b[C");
+                       break;
+
+/*
+ * RETURN
+ */
+
+               case 0x0d :
+               case 0x0a :
+                       break;
+
+/*
+ * Another key
+ */
+
+               default :
+
+/*
+ * Check for a valid key to enter
+ */
+
+                       if (key < 0x100 && key > 0x1f
+                           && (valid_string == NULL || strchr(valid_string, key))) {
+                               if (!insert_mode && loop < length) {
+                                       string[loop] = key;
+                                       printf("%c", key);
+                                       ++loop;
+                                       if (loop > entered) entered = loop;
+                               }
+                               else if (entered < length) {
+                                       int loop1;
+
+                                       for (loop1 = entered; loop1 >= loop; --loop1) {
+                                               string[loop1+1] = string[loop1];
+                                       }
+                                       string[loop] = key;
+                                       ++loop;
+                                       ++entered;
+                                       string[entered] = 0;
+                                       if (loop != entered) printf("\x1b[s");
+                                       printf("%s", &string[loop-1]);
+                                       if (loop != entered) printf("\x1b[u\x1b[C");
+                               } else {
+                                       printf("\x07");
+                               }
+                       }
+                       break;
+               }
+       } while (key != 0x0d && key != 0x0a);
+
+       printf("\n\r");
+
+       string[entered] = 0;
+
+       return(entered);
+}
+
+
+/* This erases a line of text */
+
+void
+deleteline(loop, entered)
+       int loop;
+       int entered;
+{
+       while (loop < entered) {
+               ++loop;
+               printf("\x1b[C");
+       }
+
+       while (loop > 0) {
+               --loop;
+               --entered;
+               printf("\x7f");
+       }
+}
+
+/* End of shell_input.c */
diff --git a/sys/arch/arm32/kshell/shell_shell.c b/sys/arch/arm32/kshell/shell_shell.c
new file mode 100644 (file)
index 0000000..870e4a1
--- /dev/null
@@ -0,0 +1,662 @@
+/* $NetBSD: shell_shell.c,v 1.5 1996/04/19 20:15:36 mark Exp $ */
+
+/*
+ * Copyright (c) 1994-1996 Mark Brinicombe.
+ * Copyright (c) 1994 Brini.
+ * All rights reserved.
+ *
+ * This code is derived from software written for Brini by Mark Brinicombe
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided 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 Brini.
+ * 4. The name of the company nor the name of the author may be used to
+ *    endorse or promote products derived from this software without specific
+ *    prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BRINI ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL BRINI 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.
+ *
+ * RiscBSD kernel project
+ *
+ * shell_shell.c
+ *
+ * Debug / Monitor shell entry and commands
+ *
+ * Created      : 09/10/94
+ */
+
+/* Include standard header files */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/buf.h>
+#include <sys/proc.h>
+#include <sys/device.h>
+#include <sys/vnode.h>
+#include <vm/vm.h>
+
+/* Local header files */
+
+#include <machine/pmap.h>
+#include <machine/katelib.h>
+#include <machine/vidc.h>
+#include <machine/rtc.h>
+
+/* Declare global variables */
+
+/* Local function prototypes */
+
+char   *strchr __P((const char *, int));
+
+void dumpb __P((u_char */*addr*/, int /*count*/));
+void dumpw __P((u_char */*addr*/, int /*count*/));
+
+int readstring __P((char *, int, char *, char *));
+
+void debug_show_q_details __P((void));
+void shell_disassem    __P((int argc, char *argv[]));
+void shell_devices     __P((int argc, char *argv[]));
+void shell_vmmap       __P((int argc, char *argv[]));
+void shell_flush       __P((int argc, char *argv[]));
+void shell_pextract    __P((int argc, char *argv[]));
+void shell_vnode       __P((int argc, char *argv[]));
+void debug_show_all_procs __P((int argc, char *argv[]));
+void debug_show_callout        __P((int argc, char *argv[]));
+void debug_show_fs     __P((int argc, char *argv[]));
+void debug_show_vm_map __P((vm_map_t map, char *text));
+void debug_show_pmap   __P((pmap_t pmap));
+void pmap_dump_pvs     __P((void));
+void bootsync          __P((void));
+
+/* Now for the main code */
+
+/* readhex
+ *
+ * This routine interprets the input string as a sequence of hex characters
+ * and returns it as an integer.
+ */
+
+int
+readhex(buf)
+       char *buf;
+{
+       int value;
+       int nibble;
+
+       if (buf == NULL)
+               return(0);
+
+/* skip any spaces */
+
+       while (*buf == ' ')
+               ++buf;
+
+/* return 0 if a zero length string is passed */
+
+       if (*buf == 0)
+               return(0);
+
+/* Convert the characters */
+
+       value = 0;
+
+       while (*buf != 0 && strchr("0123456789abcdefABCDEF", *buf) != 0) {
+               nibble = (*buf - '0');
+               if (nibble > 9) nibble -= 7;
+               if (nibble > 15) nibble -= 32;
+               value = (value << 4) | nibble;
+               ++buf;
+       }
+
+       return(value);
+}
+
+
+/* poke - writes a byte/word to memory */
+
+void
+shell_poke(argc, argv)
+       int argc;
+       char *argv[];   
+{
+       u_int addr;
+       u_int data;
+
+       if (argc < 3) {
+               printf("Syntax: poke[bw] <addr> <data>\n\r");
+               return;
+       }
+
+/* Decode the two arguments */
+
+       addr = readhex(argv[1]);
+       data = readhex(argv[2]);
+
+       if (argv[0][4] == 'b')
+               WriteByte(addr, data);
+       if (argv[0][4] == 'w')
+               WriteWord(addr, data);
+}
+
+
+/* peek - reads a byte/word from memory*/
+
+void
+shell_peek(argc, argv)
+       int argc;
+       char *argv[];   
+{
+       u_int addr;
+       u_int data;
+
+       if (argc < 2) {
+               printf("Syntax: peek[bw] <addr>\n\r");
+               return;
+       }
+
+/* Decode the one argument */
+
+       addr = readhex(argv[1]);
+
+       if (argv[0][4] == 'b')
+               data = ReadByte(addr);
+       if (argv[0][4] == 'w')
+               data = ReadWord(addr);
+
+       printf("%08x : %08x\n\r", addr, data);
+}
+
+
+/* dumpb - dumps memory in bytes*/
+
+void
+shell_dumpb(argc, argv)
+       int argc;
+       char *argv[];   
+{
+       u_char *addr;
+       int count;
+
+       if (argc < 2) {
+               printf("Syntax: dumpb <addr> [<bytes>]\n\r");
+               return;
+       }
+
+/* Decode the one argument */
+
+       addr = (u_char *)readhex(argv[1]);
+
+       if (argc > 2)
+               count = readhex(argv[2]);
+       else
+               count = 0x80;
+
+       dumpb(addr, count);
+}
+
+
+/* dumpw - dumps memory in bytes*/
+
+void
+shell_dumpw(argc, argv)
+       int argc;
+       char *argv[];   
+{
+       u_char *addr;
+       int count;
+
+       if (argc < 2) {
+               printf("Syntax: dumpw <addr> [<bytes>]\n\r");
+               return;
+       }
+
+/* Decode the one argument */
+
+       addr = (u_char *)readhex(argv[1]);
+
+       if (argc > 2)
+               count = readhex(argv[2]);
+       else
+               count = 0x80;
+
+       dumpw(addr, count); 
+}
+
+  
+/* vmmap - dumps the vmmap */
+
+void
+shell_vmmap(argc, argv)
+       int argc;
+       char *argv[];   
+{
+       u_char *addr;
+
+       if (argc < 2) {
+               printf("Syntax: vmmap <map addr>\n\r");
+               return;
+       }
+
+/* Decode the one argument */
+
+       addr = (u_char *)readhex(argv[1]);
+
+       debug_show_vm_map((vm_map_t)addr, argv[1]);
+}
+
+
+/* pmap - dumps the pmap */
+
+void
+shell_pmap(argc, argv)
+       int argc;
+       char *argv[];   
+{
+       u_char *addr;
+
+       if (argc < 2) {
+               printf("Syntax: pmap <pmap addr>\n\r");
+               return;
+       }
+
+/* Decode the one argument */
+
+       addr = (u_char *)readhex(argv[1]);
+
+       debug_show_pmap((pmap_t)addr);
+}
+
+
+/*
+ * void shell_devices(int argc, char *argv[])
+ *
+ * Display all the devices
+ */
+
+extern struct cfdata cfdata[];
+void
+shell_devices(argc, argv)
+       int argc;
+       char *argv[];   
+{
+       struct cfdata *cf;
+       struct cfdriver *cd;
+       struct device *dv;
+       int loop;
+       char *state;
+
+       printf(" driver  unit state     name\n");
+       for (cf = cfdata; cf->cf_driver; ++cf) {
+               cd = cf->cf_driver;
+               if (cf->cf_fstate & FSTATE_FOUND)
+                       state = "FOUND    ";
+               else
+                       state = "NOT FOUND";
+
+               printf("%08x  %2d  %s %s\n", (u_int)cd, (u_int)cf->cf_unit,
+                   state, cd->cd_name);
+
+               if (cf->cf_fstate & FSTATE_FOUND) {
+                       for (loop = 0; loop < cd->cd_ndevs; ++loop) {
+                               dv = (struct device *)cd->cd_devs[loop];
+                               if (dv != 0)
+                                       printf("                        %s (%08x)\n",
+                                           dv->dv_xname, (u_int) dv);
+                       }
+               }
+               printf("\n");
+       } 
+}
+
+
+void
+shell_reboot(argc, argv)
+       int argc;
+       char *argv[];   
+{
+       printf("Running shutdown hooks ...\n");
+       doshutdownhooks();
+
+       IRQdisable;
+       boot0();
+}
+
+void
+forceboot(argc, argv)
+       int argc;
+       char *argv[];   
+{
+       cmos_write(0x90, cmos_read(0x90) | 0x02);
+       shell_reboot(0, NULL);
+}
+
+
+void
+shell_flush(argc, argv)
+       int argc;
+       char *argv[];   
+{
+       idcflush();
+       tlbflush();
+}
+
+
+void
+shell_vmstat(argc, argv)
+       int argc;
+       char *argv[];   
+{
+       struct vmmeter sum;
+    
+       sum = cnt;
+       (void)printf("%9u cpu context switches\n", sum.v_swtch);
+       (void)printf("%9u device interrupts\n", sum.v_intr);
+       (void)printf("%9u software interrupts\n", sum.v_soft);
+       (void)printf("%9u traps\n", sum.v_trap);
+       (void)printf("%9u system calls\n", sum.v_syscall);
+       (void)printf("%9u total faults taken\n", sum.v_faults);
+       (void)printf("%9u swap ins\n", sum.v_swpin);
+       (void)printf("%9u swap outs\n", sum.v_swpout);
+       (void)printf("%9u pages swapped in\n", sum.v_pswpin / CLSIZE);
+       (void)printf("%9u pages swapped out\n", sum.v_pswpout / CLSIZE);
+       (void)printf("%9u page ins\n", sum.v_pageins);
+       (void)printf("%9u page outs\n", sum.v_pageouts);
+       (void)printf("%9u pages paged in\n", sum.v_pgpgin);
+       (void)printf("%9u pages paged out\n", sum.v_pgpgout);
+       (void)printf("%9u pages reactivated\n", sum.v_reactivated);
+       (void)printf("%9u intransit blocking page faults\n", sum.v_intrans);
+       (void)printf("%9u zero fill pages created\n", sum.v_nzfod / CLSIZE);
+       (void)printf("%9u zero fill page faults\n", sum.v_zfod / CLSIZE);
+       (void)printf("%9u pages examined by the clock daemon\n", sum.v_scan);
+       (void)printf("%9u revolutions of the clock hand\n", sum.v_rev);
+       (void)printf("%9u VM object cache lookups\n", sum.v_lookups);
+       (void)printf("%9u VM object hits\n", sum.v_hits);
+       (void)printf("%9u total VM faults taken\n", sum.v_vm_faults);
+       (void)printf("%9u copy-on-write faults\n", sum.v_cow_faults);
+       (void)printf("%9u pages freed by daemon\n", sum.v_dfree);
+       (void)printf("%9u pages freed by exiting processes\n", sum.v_pfree);
+       (void)printf("%9u pages free\n", sum.v_free_count);
+       (void)printf("%9u pages wired down\n", sum.v_wire_count);
+       (void)printf("%9u pages active\n", sum.v_active_count);
+       (void)printf("%9u pages inactive\n", sum.v_inactive_count);
+       (void)printf("%9u bytes per page\n", sum.v_page_size);
+}
+
+
+void
+shell_pextract(argc, argv)
+       int argc;
+       char *argv[];   
+{
+       u_char *addr;
+       vm_offset_t pa;
+       int pind;
+
+       if (argc < 2) {
+               printf("Syntax: pextract <addr>\n\r");
+               return;
+       }
+
+/* Decode the one argument */
+
+       addr = (u_char *)readhex(argv[1]);
+
+       pa = pmap_extract(kernel_pmap, (vm_offset_t)addr);
+       pind = pmap_page_index(pa);
+
+       printf("va=%08x pa=%08x pind=%d\n", (u_int)addr, (u_int)pa, pind);
+}
+
+
+void
+shell_vnode(argc, argv)
+       int argc;
+       char *argv[];   
+{
+       struct vnode *vp;
+
+       if (argc < 2) {
+               printf("Syntax: vnode <vp>\n\r");
+               return;
+       }
+
+/* Decode the one argument */
+
+       vp = (struct vnode *)readhex(argv[1]);
+
+       printf("vp = %08x\n", (u_int)vp);
+       printf("vp->v_type = %d\n", vp->v_type);
+       printf("vp->v_flag = %ld\n", vp->v_flag);
+       printf("vp->v_usecount = %d\n", vp->v_usecount);
+       printf("vp->v_writecount = %d\n", vp->v_writecount);
+       printf("vp->v_numoutput = %ld\n", vp->v_numoutput);
+
+       vprint("vnode:", vp);
+}
+
+#if 0
+void
+shell_vndbuf(argc, argv)
+       int argc;
+       char *argv[];   
+{
+       struct vnode *vp;
+
+       if (argc < 2) {
+               printf("Syntax: vndbuf <vp>\n\r");
+               return;
+       }
+
+/* Decode the one argument */
+
+       vp = (struct vnode *)readhex(argv[1]);
+
+       dumpvndbuf(vp);
+}
+
+
+void
+shell_vncbuf(argc, argv)
+       int argc;
+       char *argv[];   
+{
+       struct vnode *vp;
+
+       if (argc < 2) {
+               printf("Syntax: vndbuf <vp>\n\r");
+               return;
+       }
+
+/* Decode the one argument */
+
+       vp = (struct vnode *)readhex(argv[1]);
+
+       dumpvncbuf(vp);
+}
+#endif
+
+/* shell - a crude shell */
+
+int
+shell()
+{
+       int quit = 0;
+       char buffer[200];
+       char *ptr;
+       char *ptr1;
+       int args;
+       char *argv[20];
+
+       printf("\nRiscBSD debug/monitor shell\n");
+       printf("CTRL-D, exit or reboot to terminate\n\n");
+
+       do {
+/* print prompt */
+
+               printf("kshell> ");
+
+/* Read line from keyboard */
+
+               if (readstring(buffer, 200, NULL, NULL) == -1)
+                       return(0);
+
+               ptr = buffer;
+
+/* Slice leading spaces */
+
+               while (*ptr == ' ')
+                       ++ptr;
+
+/* Loop back if zero length string */
+
+               if (*ptr == 0)
+                       continue;
+
+/* Count the number of space separated args */
+
+               args = 0;
+               ptr1 = ptr;
+
+               while (*ptr1 != 0) {
+                       if (*ptr1 == ' ') {
+                               ++args;
+                               while (*ptr1 == ' ')
+                                       ++ptr1;
+                       } else
+                               ++ptr1;
+               }
+
+/*
+ * Construct the array of pointers to the args and terminate
+ * each argument with 0x00
+ */
+
+               args = 0;
+               ptr1 = ptr;
+
+               while (*ptr1 != 0) {
+                       argv[args] = ptr1;
+                       ++args;
+                       while (*ptr1 != ' ' && *ptr1 != 0)
+                               ++ptr1;
+
+                       while (*ptr1 == ' ') {
+                               *ptr1 = 0;
+                               ++ptr1;
+                       }
+               }
+
+               argv[args] = NULL;
+
+/* Interpret commands */
+
+               if (strcmp(argv[0], "exit") == 0)
+                       quit = 1;
+#ifdef DDB
+               else if (strcmp(argv[0], "deb") == 0)
+                       Debugger();
+#endif
+               else if (strcmp(argv[0], "peekb") == 0)
+                       shell_peek(args, argv);
+               else if (strcmp(argv[0], "pokeb") == 0)
+                       shell_poke(args, argv);
+               else if (strcmp(argv[0], "peekw") == 0)
+                       shell_peek(args, argv);
+               else if (strcmp(argv[0], "pokew") == 0)
+                       shell_poke(args, argv);
+               else if (strcmp(argv[0], "dumpb") == 0)
+                       shell_dumpb(args, argv);
+               else if (strcmp(argv[0], "reboot") == 0)
+                       shell_reboot(args, argv);
+               else if (strcmp(argv[0], "dumpw") == 0)
+                       shell_dumpw(args, argv);
+               else if (strcmp(argv[0], "dump") == 0)
+                       shell_dumpw(args, argv);
+               else if (strcmp(argv[0], "dis") == 0)
+                       shell_disassem(args, argv);
+               else if (strcmp(argv[0], "qs") == 0)
+                       debug_show_q_details();
+               else if (strcmp(argv[0], "ps") == 0)
+                       debug_show_all_procs(args, argv);
+               else if (strcmp(argv[0], "callouts") == 0)
+                       debug_show_callout(args, argv);
+               else if (strcmp(argv[0], "devices") == 0)
+                       shell_devices(args, argv);
+               else if (strcmp(argv[0], "listfs") == 0)
+                       debug_show_fs(args, argv);
+               else if (strcmp(argv[0], "vmmap") == 0)
+                       shell_vmmap(args, argv);
+               else if (strcmp(argv[0], "pmap") == 0)
+                       shell_pmap(args, argv);
+               else if (strcmp(argv[0], "flush") == 0)
+                       shell_flush(args, argv);
+               else if (strcmp(argv[0], "vmstat") == 0)
+                       shell_vmstat(args, argv);
+               else if (strcmp(argv[0], "pdstat") == 0)
+                       pmap_pagedir_dump();
+               else if (strcmp(argv[0], "traceback") == 0)
+                       traceback();
+               else if (strcmp(argv[0], "forceboot") == 0)
+                       forceboot(args, argv);
+               else if (strcmp(argv[0], "dumppvs") == 0)
+                       pmap_dump_pvs();
+               else if (strcmp(argv[0], "pextract") == 0)
+                       shell_pextract(args, argv);
+               else if (strcmp(argv[0], "vnode") == 0)
+                       shell_vnode(args, argv);
+               else if (strcmp(argv[0], "ascdump") == 0)
+                       asc_dump();
+               else if (strcmp(argv[0], "help") == 0
+                   || strcmp(argv[0], "?") == 0) {
+                       printf("peekb <hexaddr>\r\n");
+                       printf("pokeb <hexaddr> <data>\r\n");
+                       printf("peekw <hexaddr>\r\n");
+                       printf("pokew <hexaddr <data>\r\n");
+                       printf("dis <hexaddr>\r\n");
+                       printf("dumpb <hexaddr> [length]\r\n");
+                       printf("dumpw <hexaddr> [length]\r\n");
+                       printf("dump <hexaddr> [length]\r\n");
+                       printf("reboot\r\n");
+                       printf("qs\r\n");
+                       printf("ps [m]\r\n");
+                       printf("vmstat\n");
+                       printf("listfs\n");
+                       printf("devices\n");
+                       printf("callouts\n");
+                       printf("prompt\r\n");
+                       printf("vmmap <vmmap addr>\r\n");
+                       printf("pmap <pmap addr>\r\n");
+                       printf("pdstat\r\n");
+                       printf("flush\r\n");
+                       printf("exit\r\n");
+                       printf("forceboot\r\n");
+                       printf("dumppvs\r\n");
+                       printf("pextract <phys addr>\r\n");
+                       printf("vnode <vp>\r\n");
+                       printf("ascdump\r\n");
+               }
+       } while (!quit);
+
+       return(0);
+}
+
+/* End of shell_shell.c */
diff --git a/sys/arch/arm32/kshell/strchr.c b/sys/arch/arm32/kshell/strchr.c
new file mode 100644 (file)
index 0000000..8caae13
--- /dev/null
@@ -0,0 +1,49 @@
+/* $NetBSD: strchr.c,v 1.2 1996/03/18 20:32:34 mark Exp $ */
+
+/*
+ * Copyright (c) 1994 Mark Brinicombe.
+ * 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 RiscBSD kernel team.
+ * 4. The name of the company nor the name of the author may 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 OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+#include <sys/param.h>
+
+char *
+strchr(s, c)
+       register char *s;
+       int c;
+{
+       do {
+               if (*s == c) {
+                       return (s);
+               }
+       } while (*s++);
+       return (0);
+}
+
+/* End of strchr.c */
diff --git a/sys/arch/arm32/mainbus/beep.c b/sys/arch/arm32/mainbus/beep.c
new file mode 100644 (file)
index 0000000..7628303
--- /dev/null
@@ -0,0 +1,369 @@
+/* $NetBSD: beep.c,v 1.4 1996/03/27 22:08:36 mark Exp $ */
+
+/*
+ * Copyright (c) 1995 Mark Brinicombe
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided 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 RiscBSD team.
+ * 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.
+ */
+
+/*
+ * Simple beep sounds using VIDC
+ */
+
+/*
+ * To use the driver, open /dev/beep and write lines. 
+ * Each write will generate a beep  
+ *
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/conf.h>
+#include <sys/ioctl.h>
+#include <sys/tty.h>
+#include <sys/kernel.h>
+#include <sys/types.h>
+#include <sys/device.h>
+#include <sys/proc.h>
+#include <sys/time.h>
+#include <sys/errno.h>
+#include <dev/cons.h>
+#include <vm/vm.h>
+#include <vm/vm_kern.h>
+
+#include <machine/irqhandler.h>
+#include <machine/katelib.h>
+#include <machine/iomd.h>
+#include <machine/vidc.h>
+#include <machine/pmap.h>
+#include <machine/beep.h>
+#include <arm32/mainbus/mainbus.h>
+#include <arm32/mainbus/waveform.h>
+
+#include "beep.h"
+
+struct beep_softc {
+       struct device sc_device;
+       irqhandler_t sc_ih;
+       int sc_iobase;
+       int sc_open;
+       int sc_count;
+       u_int sc_sound_cur0; 
+       u_int sc_sound_end0; 
+       u_int sc_sound_cur1; 
+       u_int sc_sound_end1; 
+       vm_offset_t sc_buffer0;
+       vm_offset_t sc_buffer1;
+};
+
+int    beepprobe       __P((struct device *parent, void *match, void *aux));
+void   beepattach      __P((struct device *parent, struct device *self, void *aux));
+int    beepopen        __P((dev_t, int, int, struct proc *));
+int    beepclose       __P((dev_t, int, int, struct proc *));
+int    beepintr        __P((struct beep_softc *sc));
+void   beepdma         __P((struct beep_softc *sc, int buf));
+
+struct cfattach beep_ca = {
+       sizeof(struct beep_softc), beepprobe, beepattach
+};
+
+struct cfdriver        beep_cd = {
+       NULL, "beep", DV_TTY
+};
+
+
+int
+beepprobe(parent, match, aux)
+       struct device *parent;
+       void *match;
+       void *aux;
+{
+/*     struct mainbus_attach_args *mb = aux;*/
+       int id;
+
+/* Make sure we have an IOMD we understand */
+
+       id = ReadByte(IOMD_ID0) | (ReadByte(IOMD_ID1) << 8);
+
+/* So far I only know about this IOMD */
+
+       switch (id) {
+       case RPC600_IOMD_ID:
+               return(1);
+               break;
+       default:
+               printf("beep: Unknown IOMD id=%04x", id);
+               break;
+       }
+       return(0);
+}
+
+
+void
+beepattach(parent, self, aux)
+       struct device *parent;
+       struct device *self;
+       void *aux;
+{
+       struct beep_softc *sc = (void *)self;
+       struct mainbus_attach_args *mb = aux;
+    
+       sc->sc_iobase = mb->mb_iobase;
+       sc->sc_open = 0;
+       sc->sc_count = 0;
+    
+       sc->sc_buffer0 = kmem_alloc(kernel_map, NBPG);
+       if (sc->sc_buffer0 == 0) 
+               panic("beep: Cannot allocate buffer memory\n");
+       if ((sc->sc_buffer0 & (NBPG -1)) != 0)
+               panic("beep: Cannot allocate page aligned buffer\n");
+       sc->sc_buffer1 = sc->sc_buffer0;
+
+       sc->sc_sound_cur0 = pmap_extract(kernel_pmap,
+           (vm_offset_t)sc->sc_buffer0 & PG_FRAME);
+       sc->sc_sound_end0 = (sc->sc_sound_cur0 + NBPG - 16) | 0x00000000;
+       sc->sc_sound_cur1 = pmap_extract(kernel_pmap,
+           (vm_offset_t)sc->sc_buffer1 & PG_FRAME);
+       sc->sc_sound_end1 = (sc->sc_sound_cur1 + NBPG - 16) | 0x00000000;
+
+       bcopy(beep_waveform, (void *)sc->sc_buffer0, sizeof(beep_waveform));
+
+/* Reset the sound DMA channel */
+
+       WriteWord(IOMD_SD0CURA, sc->sc_sound_cur0);
+       WriteWord(IOMD_SD0ENDA, sc->sc_sound_end0 | 0xc0000000);
+       WriteWord(IOMD_SD0CURB, sc->sc_sound_cur1);
+       WriteWord(IOMD_SD0ENDB, sc->sc_sound_end1 | 0xc0000000);
+    
+       WriteByte(IOMD_SD0CR, 0x90);
+
+/* Install an IRQ handler */
+
+       sc->sc_ih.ih_func = beepintr;
+       sc->sc_ih.ih_arg = sc;
+       sc->sc_ih.ih_level = IPL_NONE;
+       sc->sc_ih.ih_name = "dma snd ch 0";
+
+       if (irq_claim(IRQ_DMASCH0, &sc->sc_ih))
+               panic("Cannot claim DMASCH0 IRQ for beep%d\n", parent->dv_unit);
+
+       disable_irq(IRQ_DMASCH0);
+
+/*
+       printf(" [ buf0=%08x:%08x->%08x buf1=%08x:%08x->%08x ]",
+           (u_int)sc->sc_buffer0, sc->sc_sound_cur0, sc->sc_sound_end0,
+           (u_int)sc->sc_buffer1, sc->sc_sound_cur1, sc->sc_sound_end1);
+*/
+       printf("\n");
+
+/* Set sample rate to 32us */
+
+       WriteWord(VIDC_BASE, VIDC_SFR | 32);
+
+/* Set the stereo postions to centred for all channels */
+
+       WriteWord(VIDC_BASE, VIDC_SIR0 | SIR_CENTRE);
+       WriteWord(VIDC_BASE, VIDC_SIR1 | SIR_CENTRE);
+       WriteWord(VIDC_BASE, VIDC_SIR2 | SIR_CENTRE);
+       WriteWord(VIDC_BASE, VIDC_SIR3 | SIR_CENTRE);
+       WriteWord(VIDC_BASE, VIDC_SIR4 | SIR_CENTRE);
+       WriteWord(VIDC_BASE, VIDC_SIR5 | SIR_CENTRE);
+       WriteWord(VIDC_BASE, VIDC_SIR6 | SIR_CENTRE);
+       WriteWord(VIDC_BASE, VIDC_SIR7 | SIR_CENTRE);
+}
+
+
+int
+beepopen(dev, flag, mode, p)
+       dev_t dev;
+       int flag;
+       int mode;
+       struct proc *p;
+{
+       struct beep_softc *sc;
+       int unit = minor(dev);
+       int s;
+    
+       if (unit >= beep_cd.cd_ndevs)
+               return(ENXIO);
+
+       sc = beep_cd.cd_devs[unit];
+       if (!sc) return(ENXIO);
+
+/* HACK hack hack */
+
+       s = splhigh();
+       if (sc->sc_open) {
+               (void)splx(s);
+               return(EBUSY);
+       }
+
+       ++sc->sc_open;   
+       (void)splx(s); 
+
+       return(0);
+}
+
+
+int
+beepclose(dev, flag, mode, p)
+       dev_t dev;
+       int flag;
+       int mode;
+       struct proc *p;
+{
+       int unit = minor(dev);
+       struct beep_softc *sc = beep_cd.cd_devs[unit];
+       int s;
+
+       if (sc->sc_open == 0) return(ENXIO);
+    
+/* HACK hack hack */
+
+       s = splhigh();
+       --sc->sc_open;
+       (void)splx(s);
+      
+       return(0);
+}
+
+
+void
+beep_generate(void)
+{
+       struct beep_softc *sc = beep_cd.cd_devs[0];
+/*     int status;*/
+
+       if (sc->sc_count > 0) {
+/*             printf("beep: active\n");*/
+               return;
+       }
+/*     printf("beep: generate ");*/
+       ++sc->sc_count;
+    
+/*     status = ReadByte(IOMD_SD0ST);
+       printf("st=%02x\n", status);*/
+       WriteByte(IOMD_SD0CR, 0x90);
+       WriteByte(IOMD_SD0CR, 0x30);
+       beepdma(sc, 0);
+}
+
+
+int
+beepioctl(dev, cmd, data, flag, p)
+       dev_t dev;
+       int cmd;
+       caddr_t data;
+       int flag;
+       struct proc *p;
+{
+       struct beep_softc *sc = beep_cd.cd_devs[minor(dev)];
+       int rate;
+       struct wavebuffer *wave = (struct wavebuffer *)data;
+
+       switch (cmd) {
+       case BEEP_GENERATE:
+               beep_generate();
+               break;
+
+       case BEEP_SETRATE:
+               rate = *(int *)data;
+           
+               if (rate < 3 || rate > 255)
+                       return(EINVAL);
+
+               WriteWord(VIDC_BASE, VIDC_SFR | rate);
+               break;
+
+       case BEEP_SET:
+               printf("set %08x\n", (u_int)data);
+               printf("set %08x %08x\n", (u_int)wave->addr, wave->size);
+               if (wave->size < 16 || wave->size > NBPG)
+                       return(ENXIO);
+               copyin(wave->addr, (char *)sc->sc_buffer0, wave->size);
+               sc->sc_sound_end0 = (sc->sc_sound_cur0 + wave->size - 16);
+               sc->sc_sound_end1 = (sc->sc_sound_cur1 + wave->size - 16);
+               break;
+
+       default:
+               return(ENXIO);
+               break;
+       }   
+
+       return(0);
+}
+
+
+int
+beepintr(sc)
+       struct beep_softc *sc;
+{
+/*     printf("beepintr: %02x,%02x,%02x,%d\n", ReadByte(IOMD_DMARQ),
+           ReadByte(IOMD_SD0CR), ReadByte(IOMD_SD0ST), sc->sc_count);*/
+       WriteByte(IOMD_DMARQ, 0x10);
+       --sc->sc_count;
+       if (sc->sc_count <= 0) {
+               WriteWord(IOMD_SD0CURB, sc->sc_sound_cur1);
+               WriteWord(IOMD_SD0ENDB, sc->sc_sound_end1 | (1 << 30));
+               disable_irq(IRQ_DMASCH0);
+/*             printf("stop:st=%02x\n", ReadByte(IOMD_SD0ST));*/
+               return(1);
+       }
+
+       beepdma(sc, sc->sc_count & 1);
+       return(1);
+}
+
+
+void
+beepdma(sc, buf)
+       struct beep_softc *sc;
+       int buf;
+{
+       int status;
+/*     printf("beep:dma %d", buf);    */
+       status = ReadByte(IOMD_SD0ST);
+/*     printf("st=%02x\n", status);*/
+
+       if (buf == 0) {
+               WriteWord(IOMD_SD0CURA, sc->sc_sound_cur0);
+               WriteWord(IOMD_SD0ENDA, sc->sc_sound_end0);
+               WriteWord(IOMD_SD0CURB, sc->sc_sound_cur1);
+               WriteWord(IOMD_SD0ENDB, sc->sc_sound_end1 | (1 << 30));
+       }
+
+       if (buf == 1) {
+               WriteWord(IOMD_SD0CURB, sc->sc_sound_cur1);
+               WriteWord(IOMD_SD0ENDB, sc->sc_sound_end1 | (1 << 30));
+       }
+
+/*     status = ReadByte(IOMD_SD0ST);
+       printf("st=%02x\n", status);*/
+
+       enable_irq(IRQ_DMASCH0);
+}
+
+/* End of beep.c */
diff --git a/sys/arch/arm32/mainbus/com.c b/sys/arch/arm32/mainbus/com.c
new file mode 100644 (file)
index 0000000..ee9b812
--- /dev/null
@@ -0,0 +1,1034 @@
+/*     $NetBSD: com.c,v 1.5 1996/03/28 21:52:32 mark Exp $     */
+
+/*-
+ * Copyright (c) 1993, 1994, 1995 Charles M. Hannum.  All rights reserved.
+ * Copyright (c) 1991 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     @(#)com.c       7.5 (Berkeley) 5/16/91
+ */
+
+/*
+ * COM driver, based on HP dca driver
+ * uses National Semiconductor NS16450/NS16550AF UART
+ */
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/ioctl.h>
+#include <sys/select.h>
+#include <sys/tty.h>
+#include <sys/proc.h>
+#include <sys/user.h>
+#include <sys/conf.h>
+#include <sys/file.h>
+#include <sys/uio.h>
+#include <sys/kernel.h>
+#include <sys/syslog.h>
+#include <sys/types.h>
+#include <sys/device.h>
+
+#include <machine/cpu.h>
+#include <machine/katelib.h>
+#include <machine/irqhandler.h>
+#include <machine/io.h>
+#include <arm32/mainbus/comreg.h>
+#include <arm32/mainbus/mainbus.h>
+
+#define        com_lcr com_cfcr
+
+#define        COM_IBUFSIZE    (2 * 256)
+#define        COM_IHIGHWATER  ((3 * COM_IBUFSIZE) / 4)
+
+struct com_softc {
+       struct device sc_dev;
+       irqhandler_t sc_ih;
+       struct tty *sc_tty;
+
+       int sc_overflows;
+       int sc_floods;
+       int sc_errors;
+
+       int sc_iobase;
+       u_char sc_hwflags;
+#define        COM_HW_NOIEN    0x01
+#define        COM_HW_FIFO     0x02
+#define        COM_HW_CONSOLE  0x40
+       u_char sc_swflags;
+#define        COM_SW_SOFTCAR  0x01
+#define        COM_SW_CLOCAL   0x02
+#define        COM_SW_CRTSCTS  0x04
+#define        COM_SW_MDMBUF   0x08
+       u_char sc_msr, sc_mcr, sc_lcr;
+       u_char sc_dtr;
+
+       u_char *sc_ibuf, *sc_ibufp, *sc_ibufhigh, *sc_ibufend;
+       u_char sc_ibufs[2][COM_IBUFSIZE];
+};
+
+int comprobe __P((struct device *, void *, void *));
+void comattach __P((struct device *, struct device *, void *));
+int comopen __P((dev_t, int, int, struct proc *));
+int comclose __P((dev_t, int, int, struct proc *));
+void comdiag __P((void *));
+int comintr __P((void *));
+void compoll __P((void *));
+int comparam __P((struct tty *, struct termios *));
+void comstart __P((struct tty *));
+
+struct cfattach com_ca = {
+       sizeof(struct com_softc), comprobe, comattach
+};
+
+struct cfdriver com_cd = {
+       NULL, "com", DV_TTY
+};
+
+int    comdefaultrate = TTYDEF_SPEED;
+#ifdef COMCONSOLE
+int    comconsole = COMCONSOLE;
+#else
+int    comconsole = -1;
+#endif
+int    comconsinit;
+int    commajor;
+int    comsopen = 0;
+int    comevents = 0;
+
+#ifdef KGDB
+#include <machine/remote-sl.h>
+extern int kgdb_dev;
+extern int kgdb_rate;
+extern int kgdb_debug_init;
+#endif
+
+#define        COMUNIT(x)      (minor(x))
+
+/* Macros to clear/set/test flags. */
+#define        SET(t, f)       (t) |= (f)
+#define        CLR(t, f)       (t) &= ~(f)
+#define        ISSET(t, f)     ((t) & (f))
+
+int
+comspeed(speed)
+       long speed;
+{
+#define        divrnd(n, q)    (((n)*2/(q)+1)/2)       /* divide and round off */
+
+       int x, err;
+
+       if (speed == 0)
+               return 0;
+       if (speed < 0)
+               return -1;
+       x = divrnd((COM_FREQ / 16), speed);
+       if (x <= 0)
+               return -1;
+       err = divrnd((COM_FREQ / 16) * 1000, speed * x) - 1000;
+       if (err < 0)
+               err = -err;
+       if (err > COM_TOLERANCE)
+               return -1;
+       return x;
+
+#undef divrnd(n, q)
+}
+
+int
+comprobe1(iobase)
+       int iobase;
+{
+
+       /* force access to id reg */
+       outb(iobase + com_lcr, 0);
+       outb(iobase + com_iir, 0);
+       if (inb(iobase + com_iir) & 0x38)
+               return 0;
+
+       return 1;
+}
+
+int
+comprobe(parent, match, aux)
+       struct device *parent;
+       void *match, *aux;
+{
+       struct mainbus_attach_args *mb = aux;
+       int iobase = mb->mb_iobase;
+
+       if (!comprobe1(iobase))
+               return 0;
+
+       mb->mb_iosize = COM_NPORTS;
+       return 1;
+}
+
+void
+comattach(parent, self, aux)
+       struct device *parent, *self;
+       void *aux;
+{
+       struct com_softc *sc = (void *)self;
+       struct mainbus_attach_args *mb = aux;
+       struct cfdata *cf = sc->sc_dev.dv_cfdata;
+       int iobase = mb->mb_iobase;
+       struct tty *tp;
+
+       sc->sc_iobase = iobase;
+       sc->sc_hwflags = ISSET(cf->cf_flags, COM_HW_NOIEN);
+       sc->sc_swflags = 0;
+
+       if (sc->sc_dev.dv_unit == comconsole)
+               delay(1000);
+
+       /* look for a NS 16550AF UART with FIFOs */
+       outb(iobase + com_fifo,
+           FIFO_ENABLE | FIFO_RCV_RST | FIFO_XMT_RST | FIFO_TRIGGER_14);
+       delay(100);
+       if (ISSET(inb(iobase + com_iir), IIR_FIFO_MASK) == IIR_FIFO_MASK)
+               if (ISSET(inb(iobase + com_fifo), FIFO_TRIGGER_14) == FIFO_TRIGGER_14) {
+                       SET(sc->sc_hwflags, COM_HW_FIFO);
+                       printf(": ns16550a, working fifo\n");
+               } else
+                       printf(": ns16550, broken fifo\n");
+       else
+               printf(": ns8250 or ns16450, no fifo\n");
+       outb(iobase + com_fifo, 0);
+
+       /* disable interrupts */
+       outb(iobase + com_ier, 0);
+       outb(iobase + com_mcr, 0);
+
+       sc->sc_ih.ih_func = comintr;
+       sc->sc_ih.ih_arg = sc;
+       sc->sc_ih.ih_level = IPL_TTY;
+       sc->sc_ih.ih_name = "serial";
+       if (mb->mb_irq != IRQUNK)
+               if (irq_claim(mb->mb_irq, &sc->sc_ih))
+                       panic("Cannot claim IRQ %d for com%d\n", mb->mb_irq, sc->sc_dev.dv_unit);
+
+#ifdef KGDB
+       if (kgdb_dev == makedev(commajor, unit)) {
+               if (comconsole == unit)
+                       kgdb_dev = -1;  /* can't debug over console port */
+               else {
+                       (void) cominit(unit, kgdb_rate);
+                       if (kgdb_debug_init) {
+                               /*
+                                * Print prefix of device name,
+                                * let kgdb_connect print the rest.
+                                */
+                               printf("%s: ", sc->sc_dev.dv_xname);
+                               kgdb_connect(1);
+                       } else
+                               printf("%s: kgdb enabled\n",
+                                   sc->sc_dev.dv_xname);
+               }
+       }
+#endif
+
+       if (sc->sc_dev.dv_unit == comconsole) {
+               /*
+                * Need to reset baud rate, etc. of next print so reset
+                * comconsinit.  Also make sure console is always "hardwired".
+                */
+               comconsinit = 0;
+               SET(sc->sc_hwflags, COM_HW_CONSOLE);
+               SET(sc->sc_swflags, COM_SW_SOFTCAR);
+       }
+}
+
+int
+comopen(dev, flag, mode, p)
+       dev_t dev;
+       int flag, mode;
+       struct proc *p;
+{
+       int unit = COMUNIT(dev);
+       struct com_softc *sc;
+       int iobase;
+       struct tty *tp;
+       int s;
+       int error = 0;
+       if (unit >= com_cd.cd_ndevs)
+               return ENXIO;
+       sc = com_cd.cd_devs[unit];
+       if (!sc)
+               return ENXIO;
+
+       if (!sc->sc_tty)
+               tp = sc->sc_tty = ttymalloc();
+       else
+               tp = sc->sc_tty;
+
+       tp->t_oproc = comstart;
+       tp->t_param = comparam;
+       tp->t_dev = dev;
+       if (!ISSET(tp->t_state, TS_ISOPEN)) {
+               SET(tp->t_state, TS_WOPEN);
+               ttychars(tp);
+               tp->t_iflag = TTYDEF_IFLAG;
+               tp->t_oflag = TTYDEF_OFLAG;
+               tp->t_cflag = TTYDEF_CFLAG;
+               if (ISSET(sc->sc_swflags, COM_SW_CLOCAL))
+                       SET(tp->t_cflag, CLOCAL);
+               if (ISSET(sc->sc_swflags, COM_SW_CRTSCTS))
+                       SET(tp->t_cflag, CRTSCTS);
+               if (ISSET(sc->sc_swflags, COM_SW_MDMBUF))
+                       SET(tp->t_cflag, MDMBUF);
+               tp->t_lflag = TTYDEF_LFLAG;
+               tp->t_ispeed = tp->t_ospeed = comdefaultrate;
+
+               s = spltty();
+
+               comparam(tp, &tp->t_termios);
+               ttsetwater(tp);
+
+               if (comsopen++ == 0)
+                       timeout(compoll, NULL, 1);
+
+               sc->sc_ibufp = sc->sc_ibuf = sc->sc_ibufs[0];
+               sc->sc_ibufhigh = sc->sc_ibuf + COM_IHIGHWATER;
+               sc->sc_ibufend = sc->sc_ibuf + COM_IBUFSIZE;
+
+               iobase = sc->sc_iobase;
+               /* Set the FIFO threshold based on the receive speed. */
+               if (ISSET(sc->sc_hwflags, COM_HW_FIFO))
+                       outb(iobase + com_fifo,
+                           FIFO_ENABLE | FIFO_RCV_RST | FIFO_XMT_RST |
+                           (tp->t_ispeed <= 1200 ? FIFO_TRIGGER_1 : FIFO_TRIGGER_8));
+               /* flush any pending I/O */
+               while (ISSET(inb(iobase + com_lsr), LSR_RXRDY))
+                       (void) inb(iobase + com_data);
+               /* you turn me on, baby */
+               sc->sc_mcr = MCR_DTR | MCR_RTS;
+               if (!ISSET(sc->sc_hwflags, COM_HW_NOIEN))
+                       SET(sc->sc_mcr, MCR_IENABLE);
+               outb(iobase + com_mcr, sc->sc_mcr);
+               outb(iobase + com_ier,
+                   IER_ERXRDY | IER_ETXRDY | IER_ERLS | IER_EMSC);
+
+               sc->sc_msr = inb(iobase + com_msr);
+               if (ISSET(sc->sc_swflags, COM_SW_SOFTCAR) ||
+                   ISSET(sc->sc_msr, MSR_DCD) || ISSET(tp->t_cflag, MDMBUF))
+                       SET(tp->t_state, TS_CARR_ON);
+               else
+                       CLR(tp->t_state, TS_CARR_ON);
+       } else if (ISSET(tp->t_state, TS_XCLUDE) && p->p_ucred->cr_uid != 0)
+               return EBUSY;
+       else
+               s = spltty();
+
+       /* wait for carrier if necessary */
+       if (!ISSET(flag, O_NONBLOCK))
+               while (!ISSET(tp->t_cflag, CLOCAL) &&
+                   !ISSET(tp->t_state, TS_CARR_ON)) {
+                       SET(tp->t_state, TS_WOPEN);
+                       error = ttysleep(tp, &tp->t_rawq, TTIPRI | PCATCH,
+                           ttopen, 0);
+                       if (error) {
+                               /* XXX should turn off chip if we're the
+                                  only waiter */
+                               splx(s);
+                               return error;
+                       }
+               }
+       splx(s);
+
+       return (*linesw[tp->t_line].l_open)(dev, tp);
+}
+int
+comclose(dev, flag, mode, p)
+       dev_t dev;
+       int flag, mode;
+       struct proc *p;
+{
+       int unit = COMUNIT(dev);
+       struct com_softc *sc = com_cd.cd_devs[unit];
+       struct tty *tp = sc->sc_tty;
+       int iobase = sc->sc_iobase;
+       int s;
+
+       /* XXX This is for cons.c. */
+       if (!ISSET(tp->t_state, TS_ISOPEN))
+               return 0;
+
+       (*linesw[tp->t_line].l_close)(tp, flag);
+       s = spltty();
+       CLR(sc->sc_lcr, LCR_SBREAK);
+       outb(iobase + com_lcr, sc->sc_lcr);
+       outb(iobase + com_ier, 0);
+       if (ISSET(tp->t_cflag, HUPCL) &&
+           !ISSET(sc->sc_swflags, COM_SW_SOFTCAR)) {
+               /* XXX perhaps only clear DTR */
+               outb(iobase + com_mcr, 0);
+       }
+       CLR(tp->t_state, TS_BUSY | TS_FLUSH);
+       if (--comsopen == 0)
+               untimeout(compoll, NULL);
+       splx(s);
+       ttyclose(tp);
+#ifdef notyet /* XXXX */
+       if (unit != comconsole) {
+               ttyfree(tp);
+               sc->sc_tty = 0;
+       }
+#endif
+       return 0;
+}
+int
+comread(dev, uio, flag)
+       dev_t dev;
+       struct uio *uio;
+       int flag;
+{
+       struct com_softc *sc = com_cd.cd_devs[COMUNIT(dev)];
+       struct tty *tp = sc->sc_tty;
+       return ((*linesw[tp->t_line].l_read)(tp, uio, flag));
+}
+int
+comwrite(dev, uio, flag)
+       dev_t dev;
+       struct uio *uio;
+       int flag;
+{
+       struct com_softc *sc = com_cd.cd_devs[COMUNIT(dev)];
+       struct tty *tp = sc->sc_tty;
+       return ((*linesw[tp->t_line].l_write)(tp, uio, flag));
+}
+
+struct tty *
+comtty(dev)
+       dev_t dev;
+{
+       struct com_softc *sc = com_cd.cd_devs[COMUNIT(dev)];
+       struct tty *tp = sc->sc_tty;
+
+       return (tp);
+}
+static u_char
+tiocm_xxx2mcr(data)
+       int data;
+{
+       u_char m = 0;
+
+       if (ISSET(data, TIOCM_DTR))
+               SET(m, MCR_DTR);
+       if (ISSET(data, TIOCM_RTS))
+               SET(m, MCR_RTS);
+       return m;
+}
+
+int
+comioctl(dev, cmd, data, flag, p)
+       dev_t dev;
+       u_long cmd;
+       caddr_t data;
+       int flag;
+       struct proc *p;
+{
+       int unit = COMUNIT(dev);
+       struct com_softc *sc = com_cd.cd_devs[unit];
+       struct tty *tp = sc->sc_tty;
+       int iobase = sc->sc_iobase;
+       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:
+               SET(sc->sc_lcr, LCR_SBREAK);
+               outb(iobase + com_lcr, sc->sc_lcr);
+               break;
+       case TIOCCBRK:
+               CLR(sc->sc_lcr, LCR_SBREAK);
+               outb(iobase + com_lcr, sc->sc_lcr);
+               break;
+       case TIOCSDTR:
+               SET(sc->sc_mcr, sc->sc_dtr);
+               outb(iobase + com_mcr, sc->sc_mcr);
+               break;
+       case TIOCCDTR:
+               CLR(sc->sc_mcr, sc->sc_dtr);
+               outb(iobase + com_mcr, sc->sc_mcr);
+               break;
+       case TIOCMSET:
+               CLR(sc->sc_mcr, MCR_DTR | MCR_RTS);
+       case TIOCMBIS:
+               SET(sc->sc_mcr, tiocm_xxx2mcr(*(int *)data));
+               outb(iobase + com_mcr, sc->sc_mcr);
+               break;
+       case TIOCMBIC:
+               CLR(sc->sc_mcr, tiocm_xxx2mcr(*(int *)data));
+               outb(iobase + com_mcr, sc->sc_mcr);
+               break;
+       case TIOCMGET: {
+               u_char m;
+               int bits = 0;
+
+               m = sc->sc_mcr;
+               if (ISSET(m, MCR_DTR))
+                       SET(bits, TIOCM_DTR);
+               if (ISSET(m, MCR_RTS))
+                       SET(bits, TIOCM_RTS);
+               m = sc->sc_msr;
+               if (ISSET(m, MSR_DCD))
+                       SET(bits, TIOCM_CD);
+               if (ISSET(m, MSR_CTS))
+                       SET(bits, TIOCM_CTS);
+               if (ISSET(m, MSR_DSR))
+                       SET(bits, TIOCM_DSR);
+               if (ISSET(m, MSR_RI | MSR_TERI))
+                       SET(bits, TIOCM_RI);
+               if (inb(iobase + com_ier))
+                       SET(bits, TIOCM_LE);
+               *(int *)data = bits;
+               break;
+       }
+       case TIOCGFLAGS: {
+               int driverbits, userbits = 0;
+
+               driverbits = sc->sc_swflags;
+               if (ISSET(driverbits, COM_SW_SOFTCAR))
+                       SET(userbits, TIOCFLAG_SOFTCAR);
+               if (ISSET(driverbits, COM_SW_CLOCAL))
+                       SET(userbits, TIOCFLAG_CLOCAL);
+               if (ISSET(driverbits, COM_SW_CRTSCTS))
+                       SET(userbits, TIOCFLAG_CRTSCTS);
+               if (ISSET(driverbits, COM_SW_MDMBUF))
+                       SET(userbits, TIOCFLAG_MDMBUF);
+
+               *(int *)data = userbits;
+               break;
+       }
+       case TIOCSFLAGS: {
+               int userbits, driverbits = 0;
+
+               error = suser(p->p_ucred, &p->p_acflag); 
+               if (error != 0)
+                       return(EPERM); 
+
+               userbits = *(int *)data;
+               if (ISSET(userbits, TIOCFLAG_SOFTCAR) ||
+                   ISSET(sc->sc_hwflags, COM_HW_CONSOLE))
+                       SET(driverbits, COM_SW_SOFTCAR);
+               if (ISSET(userbits, TIOCFLAG_CLOCAL))
+                       SET(driverbits, COM_SW_CLOCAL);
+               if (ISSET(userbits, TIOCFLAG_CRTSCTS))
+                       SET(driverbits, COM_SW_CRTSCTS);
+               if (ISSET(userbits, TIOCFLAG_MDMBUF))
+                       SET(driverbits, COM_SW_MDMBUF);
+
+               sc->sc_swflags = driverbits;
+               break;
+       }
+       default:
+               return ENOTTY;
+       }
+
+       return 0;
+}
+
+int
+comparam(tp, t)
+       struct tty *tp;
+       struct termios *t;
+{
+       struct com_softc *sc = com_cd.cd_devs[COMUNIT(tp->t_dev)];
+       int iobase = sc->sc_iobase;
+       int ospeed = comspeed(t->c_ospeed);
+       u_char lcr;
+       tcflag_t oldcflag;
+       int s;
+
+       /* check requested parameters */
+       if (ospeed < 0 || (t->c_ispeed && t->c_ispeed != t->c_ospeed))
+               return EINVAL;
+
+       lcr = sc->sc_lcr & LCR_SBREAK;
+
+       switch (ISSET(t->c_cflag, CSIZE)) {
+       case CS5:
+               SET(lcr, LCR_5BITS);
+               break;
+       case CS6:
+               SET(lcr, LCR_6BITS);
+               break;
+       case CS7:
+               SET(lcr, LCR_7BITS);
+               break;
+       case CS8:
+               SET(lcr, LCR_8BITS);
+               break;
+       }
+       if (ISSET(t->c_cflag, PARENB)) {
+               SET(lcr, LCR_PENAB);
+               if (!ISSET(t->c_cflag, PARODD))
+                       SET(lcr, LCR_PEVEN);
+       }
+       if (ISSET(t->c_cflag, CSTOPB))
+               SET(lcr, LCR_STOPB);
+
+       sc->sc_lcr = lcr;
+
+       s = spltty();
+
+       if (ospeed == 0) {
+               CLR(sc->sc_mcr, MCR_DTR);
+               outb(iobase + com_mcr, sc->sc_mcr);
+       }
+
+       /*
+        * Set the FIFO threshold based on the receive speed, if we are
+        * changing it.
+        */
+       if (tp->t_ispeed != t->c_ispeed) {
+               if (ISSET(sc->sc_hwflags, COM_HW_FIFO))
+                       outb(iobase + com_fifo,
+                           FIFO_ENABLE |
+                           (t->c_ispeed <= 1200 ? FIFO_TRIGGER_1 : FIFO_TRIGGER_8));
+       }
+
+       if (ospeed != 0) {
+               outb(iobase + com_lcr, lcr | LCR_DLAB);
+               outb(iobase + com_dlbl, ospeed);
+               outb(iobase + com_dlbh, ospeed >> 8);
+               outb(iobase + com_lcr, lcr);
+               SET(sc->sc_mcr, MCR_DTR);
+               outb(iobase + com_mcr, sc->sc_mcr);
+       } else
+               outb(iobase + com_lcr, lcr);
+
+       /* When not using CRTSCTS, RTS follows DTR. */
+       if (!ISSET(t->c_cflag, CRTSCTS)) {
+               if (ISSET(sc->sc_mcr, MCR_DTR)) {
+                       if (!ISSET(sc->sc_mcr, MCR_RTS)) {
+                               SET(sc->sc_mcr, MCR_RTS);
+                               outb(iobase + com_mcr, sc->sc_mcr);
+                       }
+               } else {
+                       if (ISSET(sc->sc_mcr, MCR_RTS)) {
+                               CLR(sc->sc_mcr, MCR_RTS);
+                               outb(iobase + com_mcr, sc->sc_mcr);
+                       }
+               }
+               sc->sc_dtr = MCR_DTR | MCR_RTS;
+       } else
+               sc->sc_dtr = MCR_DTR;
+
+       /* and copy to tty */
+       tp->t_ispeed = t->c_ispeed;
+       tp->t_ospeed = t->c_ospeed;
+       oldcflag = tp->t_cflag;
+       tp->t_cflag = t->c_cflag;
+
+       /*
+        * If DCD is off and MDMBUF is changed, ask the tty layer if we should
+        * stop the device.
+        */
+       if (!ISSET(sc->sc_msr, MSR_DCD) &&
+           !ISSET(sc->sc_swflags, COM_SW_SOFTCAR) &&
+           ISSET(oldcflag, MDMBUF) != ISSET(tp->t_cflag, MDMBUF) &&
+           (*linesw[tp->t_line].l_modem)(tp, 0) == 0) {
+               CLR(sc->sc_mcr, sc->sc_dtr);
+               outb(iobase + com_mcr, sc->sc_mcr);
+       }
+
+       splx(s);
+       return 0;
+}
+
+void
+comstart(tp)
+       struct tty *tp;
+{
+       struct com_softc *sc = com_cd.cd_devs[COMUNIT(tp->t_dev)];
+       int iobase = sc->sc_iobase;
+       int s;
+
+       s = spltty();
+       if (ISSET(tp->t_state, TS_TTSTOP | TS_BUSY))
+               goto out;
+       if (ISSET(tp->t_cflag, CRTSCTS) && !ISSET(sc->sc_msr, MSR_CTS))
+               goto out;
+       if (tp->t_outq.c_cc <= tp->t_lowat) {
+               if (ISSET(tp->t_state, TS_ASLEEP)) {
+                       CLR(tp->t_state, TS_ASLEEP);
+                       wakeup(&tp->t_outq);
+               }
+               if (tp->t_outq.c_cc == 0)
+                       goto out;
+               selwakeup(&tp->t_wsel);
+       }
+       SET(tp->t_state, TS_BUSY);
+       if (ISSET(sc->sc_hwflags, COM_HW_FIFO)) {
+               u_char buffer[16], *cp = buffer;
+               int n = q_to_b(&tp->t_outq, cp, sizeof buffer);
+               do {
+                       outb(iobase + com_data, *cp++);
+               } while (--n);
+       } else
+               outb(iobase + com_data, getc(&tp->t_outq));
+out:
+       splx(s);
+}
+
+/*
+ * Stop output on a line.
+ */
+void
+comstop(tp, flag)
+       struct tty *tp;
+{
+       int s;
+
+       s = spltty();
+       if (ISSET(tp->t_state, TS_BUSY))
+               if (!ISSET(tp->t_state, TS_TTSTOP))
+                       SET(tp->t_state, TS_FLUSH);
+       splx(s);
+}
+
+void
+comdiag(arg)
+       void *arg;
+{
+       struct com_softc *sc = arg;
+       int overflows, floods;
+       int s;
+
+       s = spltty();
+       sc->sc_errors = 0;
+       overflows = sc->sc_overflows;
+       sc->sc_overflows = 0;
+       floods = sc->sc_floods;
+       sc->sc_floods = 0;
+       splx(s);
+
+       log(LOG_WARNING, "%s: %d silo overflow%s, %d ibuf overflow%s\n",
+           sc->sc_dev.dv_xname,
+           overflows, overflows == 1 ? "" : "s",
+           floods, floods == 1 ? "" : "s");
+}
+
+void
+compoll(arg)
+       void *arg;
+{
+       int unit;
+       struct com_softc *sc;
+       struct tty *tp;
+       register u_char *ibufp;
+       u_char *ibufend;
+       register int c;
+       int s;
+       static int lsrmap[8] = {
+               0,      TTY_PE,
+               TTY_FE, TTY_PE|TTY_FE,
+               TTY_FE, TTY_PE|TTY_FE,
+               TTY_FE, TTY_PE|TTY_FE
+       };
+
+       s = spltty();
+       if (comevents == 0) {
+               splx(s);
+               goto out;
+       }
+       comevents = 0;
+       splx(s);
+
+       for (unit = 0; unit < com_cd.cd_ndevs; unit++) {
+               sc = com_cd.cd_devs[unit];
+               if (sc == 0 || sc->sc_ibufp == sc->sc_ibuf)
+                       continue;
+
+               tp = sc->sc_tty;
+
+               s = spltty();
+
+               ibufp = sc->sc_ibuf;
+               ibufend = sc->sc_ibufp;
+
+               if (ibufp == ibufend) {
+                       splx(s);
+                       continue;
+               }
+
+               sc->sc_ibufp = sc->sc_ibuf = (ibufp == sc->sc_ibufs[0]) ?
+                                            sc->sc_ibufs[1] : sc->sc_ibufs[0];
+               sc->sc_ibufhigh = sc->sc_ibuf + COM_IHIGHWATER;
+               sc->sc_ibufend = sc->sc_ibuf + COM_IBUFSIZE;
+
+               if (tp == 0 || !ISSET(tp->t_state, TS_ISOPEN)) {
+                       splx(s);
+                       continue;
+               }
+
+               if (ISSET(tp->t_cflag, CRTSCTS) &&
+                   !ISSET(sc->sc_mcr, MCR_RTS)) {
+                       /* XXX */
+                       SET(sc->sc_mcr, MCR_RTS);
+                       outb(sc->sc_iobase + com_mcr, sc->sc_mcr);
+               }
+
+               splx(s);
+
+               while (ibufp < ibufend) {
+                       c = *ibufp++;
+                       if (*ibufp & LSR_OE) {
+                               sc->sc_overflows++;
+                               if (sc->sc_errors++ == 0)
+                                       timeout(comdiag, sc, 60 * hz);
+                       }
+                       /* This is ugly, but fast. */
+                       c |= lsrmap[(*ibufp++ & (LSR_BI|LSR_FE|LSR_PE)) >> 2];
+                       (*linesw[tp->t_line].l_rint)(c, tp);
+               }
+       }
+
+out:
+       timeout(compoll, NULL, 1);
+}
+
+int
+comintr(arg)
+       void *arg;
+{
+       struct com_softc *sc = arg;
+       int iobase = sc->sc_iobase;
+       struct tty *tp;
+       u_char lsr, data, msr, delta;
+
+       if (ISSET(inb(iobase + com_iir), IIR_NOPEND))
+               return (0);
+
+       tp = sc->sc_tty;
+
+       for (;;) {
+               lsr = inb(iobase + com_lsr);
+
+               if (ISSET(lsr, LSR_RCV_MASK)) {
+                       register u_char *p = sc->sc_ibufp;
+
+                       comevents = 1;
+                       do {
+                               data = ISSET(lsr, LSR_RXRDY) ?
+                                   inb(iobase + com_data) : 0;
+                               if (ISSET(lsr, LSR_BI)) {
+#ifdef DDB
+                                       if (sc->sc_dev.dv_unit == comconsole) {
+                                               Debugger();
+                                               goto next;
+                                       }
+#endif
+                                       data = '\0';
+                               }
+                               if (p >= sc->sc_ibufend) {
+                                       sc->sc_floods++;
+                                       if (sc->sc_errors++ == 0)
+                                               timeout(comdiag, sc, 60 * hz);
+                               } else {
+                                       *p++ = data;
+                                       *p++ = lsr;
+                                       if (p == sc->sc_ibufhigh &&
+                                           ISSET(tp->t_cflag, CRTSCTS)) {
+                                               /* XXX */
+                                               CLR(sc->sc_mcr, MCR_RTS);
+                                               outb(iobase + com_mcr,
+                                                    sc->sc_mcr);
+                                       }
+                               }
+                       next:
+                               lsr = inb(iobase + com_lsr);
+                       } while (ISSET(lsr, LSR_RCV_MASK));
+
+                       sc->sc_ibufp = p;
+               }
+#if 0
+               else if (ISSET(lsr, LSR_BI|LSR_FE|LSR_PE|LSR_OE))
+                       printf("weird lsr %02x\n", lsr);
+#endif
+
+               msr = inb(iobase + com_msr);
+
+               if (msr != sc->sc_msr) {
+                       delta = msr ^ sc->sc_msr;
+                       sc->sc_msr = msr;
+                       if (ISSET(delta, MSR_DCD) &&
+                           !ISSET(sc->sc_swflags, COM_SW_SOFTCAR) &&
+                           (*linesw[tp->t_line].l_modem)(tp, ISSET(msr, MSR_DCD)) == 0) {
+                               CLR(sc->sc_mcr, sc->sc_dtr);
+                               outb(iobase + com_mcr, sc->sc_mcr);
+                       }
+                       if (ISSET(delta & msr, MSR_CTS) &&
+                           ISSET(tp->t_cflag, CRTSCTS)) {
+                               /* the line is up and we want to do rts/cts flow control */
+                               (*linesw[tp->t_line].l_start)(tp);
+                       }
+               }
+
+               if (ISSET(lsr, LSR_TXRDY) && ISSET(tp->t_state, TS_BUSY)) {
+                       CLR(tp->t_state, TS_BUSY);
+                       if (ISSET(tp->t_state, TS_FLUSH))
+                               CLR(tp->t_state, TS_FLUSH);
+                       else
+                               (*linesw[tp->t_line].l_start)(tp);
+               }
+
+               if (ISSET(inb(iobase + com_iir), IIR_NOPEND))
+                       return (1);
+       }
+}
+
+/*
+ * Following are all routines needed for COM to act as console
+ */
+#include <dev/cons.h>
+
+void
+comcnprobe(cp)
+       struct consdev *cp;
+{
+
+       if (!comprobe1(CONADDR)) {
+               cp->cn_pri = CN_DEAD;
+               return;
+       }
+
+       /* locate the major number */
+       for (commajor = 0; commajor < nchrdev; commajor++)
+               if (cdevsw[commajor].d_open == comopen)
+                       break;
+
+       /* initialize required fields */
+       cp->cn_dev = makedev(commajor, CONUNIT);
+#ifdef COMCONSOLE
+       cp->cn_pri = CN_REMOTE;         /* Force a serial port console */
+#else
+       cp->cn_pri = CN_NORMAL;
+#endif
+}
+
+void
+comcninit(cp)
+       struct consdev *cp;
+{
+
+       cominit(CONUNIT, comdefaultrate);
+       comconsole = CONUNIT;
+       comconsinit = 0;
+}
+
+cominit(unit, rate)
+       int unit, rate;
+{
+       int s = splhigh();
+       int iobase = CONADDR;
+       u_char stat;
+
+       outb(iobase + com_lcr, LCR_DLAB);
+       rate = comspeed(comdefaultrate);
+       outb(iobase + com_dlbl, rate);
+       outb(iobase + com_dlbh, rate >> 8);
+       outb(iobase + com_lcr, LCR_8BITS);
+       outb(iobase + com_ier, IER_ERXRDY | IER_ETXRDY);
+       outb(iobase + com_fifo, FIFO_ENABLE | FIFO_RCV_RST | FIFO_XMT_RST | FIFO_TRIGGER_4);
+       stat = inb(iobase + com_iir);
+       splx(s);
+}
+
+comcngetc(dev)
+       dev_t dev;
+{
+       int s = splhigh();
+       int iobase = CONADDR;
+       u_char stat, c;
+
+       while (!ISSET(stat = inb(iobase + com_lsr), LSR_RXRDY))
+               ;
+       c = inb(iobase + com_data);
+       stat = inb(iobase + com_iir);
+       splx(s);
+       return c;
+}
+
+/*
+ * Console kernel output character routine.
+ */
+void
+comcnputc(dev, c)
+       dev_t dev;
+       int c;
+{
+       int s = splhigh();
+       int iobase = CONADDR;
+       u_char stat;
+       register int timo;
+
+#ifdef KGDB
+       if (dev != kgdb_dev)
+#endif
+       if (comconsinit == 0) {
+               (void) cominit(COMUNIT(dev), comdefaultrate);
+               comconsinit = 1;
+       }
+       /* wait for any pending transmission to finish */
+       timo = 50000;
+       while (!ISSET(stat = inb(iobase + com_lsr), LSR_TXRDY) && --timo)
+               ;
+       outb(iobase + com_data, c);
+       /* wait for this transmission to complete */
+       timo = 1500000;
+       while (!ISSET(stat = inb(iobase + com_lsr), LSR_TXRDY) && --timo)
+               ;
+       /* clear any interrupts generated by this transmission */
+       stat = inb(iobase + com_iir);
+       splx(s);
+}
+
+void
+comcnpollc(dev, on)
+       dev_t dev;
+       int on;
+{
+
+}
diff --git a/sys/arch/arm32/mainbus/comreg.h b/sys/arch/arm32/mainbus/comreg.h
new file mode 100644 (file)
index 0000000..7b1464d
--- /dev/null
@@ -0,0 +1,133 @@
+/*     $NetBSD: comreg.h,v 1.1 1996/01/31 23:24:29 mark 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.
+ *
+ *     @(#)comreg.h    7.2 (Berkeley) 5/9/91
+ */
+
+/*
+ * NS16550 UART registers
+ */
+
+#define com_data       0       /* data register (R/W) */
+#define com_dlbl       0       /* divisor latch low (W) */
+#define com_dlbh       4       /* divisor latch high (W) */
+#define com_ier                4       /* interrupt enable (W) */
+#define com_iir                8       /* interrupt identification (R) */
+#define com_fifo       8       /* FIFO control (W) */
+#define com_lctl       12      /* line control register (R/W) */
+#define com_cfcr       12      /* line control register (R/W) */
+#define com_mcr                16      /* modem control register (R/W) */
+#define com_lsr                20      /* line status register (R/W) */
+#define com_msr                24      /* modem status register (R/W) */
+#define com_scratch    28      /* scratch register (R/W) */
+
+#define        COM_FREQ        1843200 /* 16-bit baud rate divisor */
+#define        COM_TOLERANCE   30      /* baud rate tolerance, in 0.1% units */
+
+/* interrupt enable register */
+#define        IER_ERXRDY      0x1
+#define        IER_ETXRDY      0x2
+#define        IER_ERLS        0x4
+#define        IER_EMSC        0x8
+
+/* interrupt identification register */
+#define        IIR_IMASK       0xf
+#define        IIR_RXTOUT      0xc
+#define        IIR_RLS         0x6
+#define        IIR_RXRDY       0x4
+#define        IIR_TXRDY       0x2
+#define        IIR_NOPEND      0x1
+#define        IIR_MLSC        0x0
+#define        IIR_FIFO_MASK   0xc0    /* set if FIFOs are enabled */
+
+/* fifo control register */
+#define        FIFO_ENABLE     0x01
+#define        FIFO_RCV_RST    0x02
+#define        FIFO_XMT_RST    0x04
+#define        FIFO_DMA_MODE   0x08
+#define        FIFO_TRIGGER_1  0x00
+#define        FIFO_TRIGGER_4  0x40
+#define        FIFO_TRIGGER_8  0x80
+#define        FIFO_TRIGGER_14 0xc0
+
+/* line control register */
+#define        LCR_DLAB        0x80
+#define        LCR_SBREAK      0x40
+#define        LCR_PZERO       0x30
+#define        LCR_PONE        0x20
+#define        LCR_PEVEN       0x10
+#define        LCR_PODD        0x00
+#define        LCR_PENAB       0x08
+#define        LCR_STOPB       0x04
+#define        LCR_8BITS       0x03
+#define        LCR_7BITS       0x02
+#define        LCR_6BITS       0x01
+#define        LCR_5BITS       0x00
+
+/* modem control register */
+#define        MCR_LOOPBACK    0x10
+#define        MCR_IENABLE     0x08
+#define        MCR_DRS         0x04
+#define        MCR_RTS         0x02
+#define        MCR_DTR         0x01
+
+/* line status register */
+#define        LSR_RCV_FIFO    0x80
+#define        LSR_TSRE        0x40
+#define        LSR_TXRDY       0x20
+#define        LSR_BI          0x10
+#define        LSR_FE          0x08
+#define        LSR_PE          0x04
+#define        LSR_OE          0x02
+#define        LSR_RXRDY       0x01
+#define        LSR_RCV_MASK    0x1f
+
+/* modem status register */
+#define        MSR_DCD         0x80
+#define        MSR_RI          0x40
+#define        MSR_DSR         0x20
+#define        MSR_CTS         0x10
+#define        MSR_DDCD        0x08
+#define        MSR_TERI        0x04
+#define        MSR_DDSR        0x02
+#define        MSR_DCTS        0x01
+
+#define        COM_NPORTS      32
+
+/*
+ * WARNING: Serial console is assumed to be at COM1 address
+ * and CONUNIT must be 0.
+ */
+#define        CONADDR (SERIAL0_CONTROLLER_BASE)
+#define        CONUNIT (0)
diff --git a/sys/arch/arm32/mainbus/cpu.c b/sys/arch/arm32/mainbus/cpu.c
new file mode 100644 (file)
index 0000000..b5b8551
--- /dev/null
@@ -0,0 +1,500 @@
+/* $NetBSD: cpu.c,v 1.4 1996/03/18 20:50:00 mark Exp $ */
+
+/*
+ * Copyright (c) 1995 Mark Brinicombe.
+ * Copyright (c) 1995 Brini.
+ * 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 Brini.
+ * 4. The name of the company nor the name of the author may be used to
+ *    endorse or promote products derived from this software without specific
+ *    prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BRINI ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL BRINI 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.
+ *
+ * RiscBSD kernel project
+ *
+ * cpu.c
+ *
+ * Probing and configuration for the master cpu
+ *
+ * Created      : 10/10/95
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/conf.h>
+#include <sys/malloc.h>
+#include <sys/device.h>
+#include <sys/proc.h>
+#include <sys/user.h>
+#include <vm/vm_kern.h>
+#include <machine/io.h>
+#include <machine/katelib.h>
+#include <machine/cpu.h>
+#include <machine/pte.h>
+#include <machine/undefined.h>
+#include <machine/cpus.h>
+
+#include "cpu.h"
+#if NCPU < 1
+#error Need at least 1 CPU configured
+#endif
+
+/* Array of cpu structures, one per possible cpu */
+
+cpu_t cpus[MAX_CPUS];
+
+char cpu_model[48];
+extern int cpu_ctrl;           /* Control bits for boot CPU */
+volatile int undefined_test;   /* Used for FPA test */
+
+extern char *boot_args;
+
+/* Declare prototypes */
+
+/* Prototypes */
+
+void identify_master_cpu __P((int /*cpu_number*/));
+void identify_arm_cpu  __P((int /*cpu_number*/));
+void identify_arm_fpu  __P((int /*cpu_number*/));
+char *strstr           __P((char */*s1*/, char */*s2*/));
+
+
+/*
+ * int cpumatch(struct device *parent, void *match, void *aux)
+ *
+ * Probe for the main cpu. Currently all this does is return 1 to
+ * indicate that the cpu was found.
+ */ 
+int
+cpumatch(parent, match, aux)
+       struct device *parent;
+       void *match;
+       void *aux;
+{
+       struct device *dev = match;
+
+       if (dev->dv_unit == 0)
+               return(1);
+       return(0);
+}
+
+
+/*
+ * void cpusattach(struct device *parent, struct device *dev, void *aux)
+ *
+ * Attach the main cpu
+ */
+  
+void
+cpuattach(parent, self, aux)
+       struct device *parent;
+       struct device *self;
+       void *aux;
+{
+       int loop;
+
+       for (loop = 0; loop < MAX_CPUS; ++loop)
+               bzero(&cpus[loop], sizeof(cpu_t));
+
+       identify_master_cpu(CPU_MASTER);
+}
+
+struct cfattach cpu_ca = {
+       sizeof(struct cpu_softc), cpumatch, cpuattach
+};
+
+struct cfdriver cpu_cd = {
+       NULL, "cpu", DV_DULL, 1
+};
+
+
+/*
+ * Used to test for an FPA. The following function is installed as a coproc1 handler
+ * on the undefined instruction vector and then we issue a FPA instruction.
+ * If undefined_test is non zero then the FPA did not handle the instruction so
+ * must be absent.
+ */
+
+int
+fpa_test(address, instruction, frame)
+       u_int address;
+       u_int instruction;
+       trapframe_t *frame;
+{
+       ++undefined_test;
+       return(0);
+}
+
+/*
+ * If an FPA was found then this function is installed as the coproc1 handler
+ * on the undefined instruction vector. Currently we don't support FPA's
+ * so this just triggers an exception.
+ */
+
+int
+fpa_handler(address, instruction, frame)
+       u_int address;
+       u_int instruction;
+       trapframe_t *frame;
+{
+       u_int fpsr;
+    
+       __asm __volatile("stmfd sp!, {r0}; .word 0xee300110; mov %0, r0; ldmfd sp!, {r0}" : "=r" (fpsr));
+
+       printf("FPA exception: fpsr = %08x\n", fpsr);
+
+       return(1);
+}
+
+
+/*
+ * Identify the master (boot) CPU
+ * This also probes for an FPU and will install an FPE if necessary
+ */
+void
+identify_master_cpu(cpu_number)
+       int cpu_number;
+{
+       u_int fpsr;
+
+       cpus[cpu_number].cpu_class = CPU_CLASS_ARM;
+       cpus[cpu_number].cpu_host = CPU_HOST_MAINBUS;
+       cpus[cpu_number].cpu_flags = CPU_FLAG_PRESENT;
+       cpus[cpu_number].cpu_ctrl = cpu_ctrl;
+
+/* Get the cpu ID from coprocessor 15 */
+
+       cpus[cpu_number].cpu_id = cpu_id();
+
+       identify_arm_cpu(cpu_number);
+       strcpy(cpu_model, cpus[cpu_number].cpu_model);
+
+/*
+ * Ok now we test for an FPA
+ * At this point no floating point emulator has been installed.
+ * This means any FP instruction will cause undefined exception.
+ * We install a temporay coproc 1 handler which will modify undefined_test
+ * if it is called.
+ * We then try to read the FP status register. If undefined_test has been
+ * decremented then the instruction was not handled by an FPA so we know
+ * the FPA is missing. If undefined_test is still 1 then we know the
+ * instruction was handled by an FPA.
+ * We then remove our test handler and look at the
+ * FP status register for identification.
+ */
+       install_coproc_handler(FP_COPROC, fpa_test);
+
+       undefined_test = 0;
+
+       __asm __volatile("stmfd sp!, {r0}; .word 0xee300110; mov %0, r0; ldmfd sp!, {r0}" : "=r" (fpsr));
+
+       if (undefined_test == 0) {
+               cpus[cpu_number].fpu_type = (fpsr >> 24);
+               switch (fpsr >> 24) {
+               case 0x81 :
+                       cpus[cpu_number].fpu_class = FPU_CLASS_FPA;
+
+#if 0
+/* Experimental stuff used when playing with an ARM700+FPA11 */
+                       printf("FPA11: FPSR=%08x\n", fpsr);
+                       fpsr=0x00070400;
+                       __asm __volatile("wfs %0" : "=r" (fpsr));
+                       __asm __volatile("rfc %0" : "=r" (fpsr));
+                       printf("FPA11: FPCR=%08x", fpsr);
+                       __asm __volatile("stmfd sp!, {r0}; mov r0, #0x00000e00 ; wfc r0; ldmfd sp!, {r0}");
+                       __asm __volatile("rfc %0" : "=r" (fpsr));
+                       printf("FPA11: FPCR=%08x", fpsr);
+#endif
+                       break;
+
+               default :
+                       cpus[cpu_number].fpu_class = FPU_CLASS_FPU;
+                       break;
+               }
+               cpus[cpu_number].fpu_flags = 0;
+               install_coproc_handler(FP_COPROC, fpa_handler);
+       } else {
+               cpus[cpu_number].fpu_class = FPU_CLASS_NONE;
+               cpus[cpu_number].fpu_flags = 0;
+
+/* Ok if ARMFPE is defined and the boot options request the ARM FPE then it will
+ * be installed as the FPE. If the installation fails the existing FPE is used as
+ * a fall back.
+ * If either ARMFPE is not defined or the boot args did not request it the old FPE
+ * is installed.
+ * This is just while I work on integrating the new FPE.
+ * It means the new FPE gets installed if compiled int (ARMFPE defined)
+ * and also gives me a on/off option when I boot in case the new FPE is
+ * causing panics.
+ * In all cases it falls back on the existing FPE is the ARMFPE was not successfully
+ * installed.
+ */
+
+#ifdef ARMFPE
+        if (boot_args) {
+               char *ptr;
+       
+               ptr = strstr(boot_args, "noarmfpe");
+               if (!ptr) {
+                       if (initialise_arm_fpe(&cpus[cpu_number]) != 0) {
+                               identify_arm_fpu(cpu_number);
+#ifdef FPE
+                               initialise_fpe(&cpus[cpu_number]);
+#endif
+                       }
+#ifdef FPE
+               } else
+                       initialise_fpe(&cpus[cpu_number]);
+
+       } else
+               initialise_fpe(&cpus[cpu_number]);
+#else
+               }
+       }
+#endif
+
+#else
+#ifdef FPE
+               initialise_fpe(&cpus[cpu_number]);
+#else
+#error No FPE built in
+#endif
+#endif
+       }
+
+       identify_arm_fpu(cpu_number);
+}
+
+
+
+/*
+ * Report the type of the specifed arm processor. This uses the generic and arm specific
+ * information in the cpu structure to identify the processor. The remaining fields
+ * in the cpu structure are filled in appropriately.
+ */
+
+void
+identify_arm_cpu(cpu_number)
+       int cpu_number;
+{
+       cpu_t *cpu;
+       u_int cpuid;
+
+       cpu = &cpus[cpu_number];
+       if (cpu->cpu_host == CPU_HOST_NONE || cpu->cpu_class == CPU_CLASS_NONE) {
+               printf("No installed processor\n");
+               return;
+       }
+       if (cpu->cpu_class != CPU_CLASS_ARM) {
+               printf("identify_arm_cpu: Can only identify ARM CPU's\n");
+               return;
+       }
+       cpuid = cpu->cpu_id;
+
+       if (cpuid == 0) {
+               printf("Processor failed probe - no CPU ID\n");
+               return;
+       }
+
+       if ((cpuid & CPU_ID_DESIGNER_MASK) != CPU_ID_ARM_LTD)
+               printf("Unrecognised designer ID = %08x\n", cpuid);
+
+       switch (cpuid & CPU_ID_CPU_MASK) {
+        case ID_ARM610:
+               cpu->cpu_type = cpuid & CPU_ID_CPU_MASK;
+               break;
+          
+       case ID_ARM710 :
+       case ID_ARM700 :
+               cpu->cpu_type = (cpuid & CPU_ID_CPU_MASK) >> 4;
+               break;
+
+       default :
+               printf("Unrecognised processor ID = %08x\n", cpuid);
+               cpu->cpu_type = cpuid & CPU_ID_CPU_MASK;
+               break;
+       }
+
+       sprintf(cpu->cpu_model, "ARM%x rev %d", cpu->cpu_type, cpuid & CPU_ID_REVISION_MASK);
+
+       if ((cpu->cpu_ctrl & CPU_CONTROL_IDC_ENABLE) == 0)
+               strcat(cpu->cpu_model, " IDC disabled");
+       else
+               strcat(cpu->cpu_model, " IDC enabled");
+
+       if ((cpu->cpu_ctrl & CPU_CONTROL_WBUF_ENABLE) == 0)
+               strcat(cpu->cpu_model, " WB disabled");
+       else
+               strcat(cpu->cpu_model, " WB enabled");
+
+       if (cpu->cpu_ctrl & CPU_CONTROL_LABT_ENABLE)
+               strcat(cpu->cpu_model, " LABT");
+       else
+               strcat(cpu->cpu_model, " EABT");
+
+/* Print the info */
+
+       printf(": %s\n", cpu->cpu_model);
+}
+
+
+/*
+ * Report the type of the specifed arm fpu. This uses the generic and arm specific
+ * information in the cpu structure to identify the fpu. The remaining fields
+ * in the cpu structure are filled in appropriately.
+ */
+
+void
+identify_arm_fpu(cpu_number)
+       int cpu_number;
+{
+       cpu_t *cpu;
+
+       cpu = &cpus[cpu_number];
+       if (cpu->cpu_host == CPU_HOST_NONE || cpu->cpu_class == CPU_CLASS_NONE) {
+               printf("No installed processor\n");
+               return;
+       }
+
+       if (cpu->cpu_class != CPU_CLASS_ARM) {
+               printf("identify_arm_cpu: Can only identify ARM FPU's\n");
+               return;
+       }
+
+/* Now for the FP info */
+
+       switch (cpu->fpu_class) {
+       case FPU_CLASS_NONE :
+               strcpy(cpu->fpu_model, "None");
+               break;
+       case FPU_CLASS_FPE :
+               printf("fpe%d at cpu%d: %s\n", cpu_number, cpu_number, cpu->fpu_model);
+               printf("fpe%d: no hardware found\n", cpu_number);
+               break;
+       case FPU_CLASS_FPA :
+               printf("fpe%d at cpu%d: %s\n", cpu_number, cpu_number, cpu->fpu_model);
+               if (cpu->fpu_type == FPU_TYPE_FPA11) {
+                       strcpy(cpu->fpu_model, "FPA11");
+                       printf("fpe%d: fpa11 found\n", cpu_number);
+               } else {
+                       strcpy(cpu->fpu_model, "FPA");
+                       printf("fpe%d: fpa10 found\n", cpu_number);
+               }
+               if ((cpu->fpu_flags & 4) == 0)
+                       strcat(cpu->fpu_model, "");
+               else
+                       strcat(cpu->fpu_model, " clk/2");
+               break;
+       case FPU_CLASS_FPU :
+               sprintf(cpu->fpu_model, "Unknown FPU (ID=%02x)\n", cpu->fpu_type);
+               printf("fpu%d at cpu%d: %s\n", cpu_number, cpu_number, cpu->fpu_model);
+               break;
+       }
+}
+
+
+int
+cpuopen(dev, flag, mode, p)
+       dev_t dev;
+       int flag;
+       int mode;
+       struct proc *p;
+{
+       struct cpu_softc *sc;
+       int unit;
+       int s;
+    
+       unit = minor(dev);
+       if (unit >= cpu_cd.cd_ndevs)
+               return(ENXIO);
+
+       sc = cpu_cd.cd_devs[unit];
+       if (!sc) return(ENXIO);
+
+       s = splhigh();
+       if (sc->sc_open) {
+               (void)splx(s);
+               return(EBUSY);
+       }
+
+       ++sc->sc_open;   
+       (void)splx(s);
+
+       return(0);
+}
+
+
+int
+cpuclose(dev, flag, mode, p)
+       dev_t dev;
+       int flag;
+       int mode;
+       struct proc *p;
+{
+       struct cpu_softc *sc;
+       int unit;
+       int s;
+
+       unit = minor(dev);
+       sc = cpu_cd.cd_devs[unit];
+
+       if (sc->sc_open == 0) return(ENXIO);
+    
+       s = splhigh();
+       --sc->sc_open;
+       (void)splx(s);
+      
+       return(0);
+}
+
+
+int
+cpuioctl(dev, cmd, data, flag, p)
+       dev_t dev;
+       int cmd;
+       caddr_t data;
+       int flag;
+       struct proc *p;
+{
+       struct cpu_softc *sc;
+       int unit;
+
+       unit = minor(dev);
+       sc = cpu_cd.cd_devs[unit];
+
+       switch (cmd) {
+       default:
+               return(ENXIO);
+               break;
+       }   
+
+       return(0);
+}
+
+/* End of cpu.c */
diff --git a/sys/arch/arm32/mainbus/fd.c b/sys/arch/arm32/mainbus/fd.c
new file mode 100644 (file)
index 0000000..d12e73d
--- /dev/null
@@ -0,0 +1,1339 @@
+/*     $NetBSD: fd.c,v 1.5 1996/03/28 21:52:41 mark Exp $      */
+
+/*-
+ * Copyright (c) 1993, 1994, 1995 Charles Hannum.
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * 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.
+ *
+ *     @(#)fd.c        7.4 (Berkeley) 5/25/91
+ */
+
+/* The new config stuff do no use to use and need to be pulled out */
+
+#undef NEWCONFIG
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/conf.h>
+#include <sys/file.h>
+#include <sys/ioctl.h>
+#include <sys/device.h>
+#include <sys/disklabel.h>
+#include <sys/dkstat.h>
+#include <sys/disk.h>
+#include <sys/buf.h>
+#include <sys/uio.h>
+#include <sys/syslog.h>
+#include <sys/queue.h>
+
+
+#include <machine/cpu.h>
+#include <machine/irqhandler.h>
+#include <machine/iomd.h>
+#include <machine/io.h>
+#include <machine/katelib.h>
+
+#include <arm32/mainbus/mainbus.h>
+#include <arm32/mainbus/fdreg.h>
+
+#define FDUNIT(dev)    (minor(dev) / 8)
+#define FDTYPE(dev)    (minor(dev) % 8)
+
+#define b_cylin b_resid
+
+enum fdc_state {
+       DEVIDLE = 0,
+       MOTORWAIT,
+       DOSEEK,
+       SEEKWAIT,
+       SEEKTIMEDOUT,
+       SEEKCOMPLETE,
+       DOIO,
+       IOCOMPLETE,
+       IOTIMEDOUT,
+       DORESET,
+       RESETCOMPLETE,
+       RESETTIMEDOUT,
+       DORECAL,
+       RECALWAIT,
+       RECALTIMEDOUT,
+       RECALCOMPLETE,
+};
+
+/* software state, per controller */
+struct fdc_softc {
+       struct device sc_dev;           /* boilerplate */
+       irqhandler_t sc_ih;
+
+       int sc_iobase;
+       int sc_drq;
+
+       struct fd_softc *sc_fd[4];      /* pointers to children */
+       TAILQ_HEAD(drivehead, fd_softc) sc_drives;
+       enum fdc_state sc_state;
+       int sc_errors;                  /* number of retries so far */
+       u_char sc_status[7];            /* copy of registers */
+};
+
+/* controller driver configuration */
+int fdcprobe __P((struct device *, void *, void *));
+#ifdef NEWCONFIG
+void fdcforceintr __P((void *));
+#endif
+void fdcattach __P((struct device *, struct device *, void *));
+
+static fiqhandler_t fiqhandler;
+
+void floppy_read_fiq __P((void));
+void floppy_write_fiq __P((void));
+
+struct cfattach fdc_ca = {
+       sizeof(struct fdc_softc), fdcprobe, fdcattach
+};
+
+struct cfdriver fdc_cd = {
+       NULL, "fdc", DV_DULL
+};
+
+/*
+ * Floppies come in various flavors, e.g., 1.2MB vs 1.44MB; here is how
+ * we tell them apart.
+ */
+struct fd_type {
+       int     sectrac;        /* sectors per track */
+       int     heads;          /* number of heads */
+       int     seccyl;         /* sectors per cylinder */
+       int     secsize;        /* size code for sectors */
+       int     datalen;        /* data len when secsize = 0 */
+       int     steprate;       /* step rate and head unload time */
+       int     gap1;           /* gap len between sectors */
+       int     gap2;           /* formatting gap */
+       int     tracks;         /* total num of tracks */
+       int     size;           /* size of disk in sectors */
+       int     step;           /* steps per cylinder */
+       int     rate;           /* transfer speed code */
+       char    *name;
+};
+
+/* The order of entries in the following table is important -- BEWARE! */
+struct fd_type fd_types[] = {
+        { 18,2,36,2,0xff,0xcf,0x1b,0x6c,80,2880,1,FDC_500KBPS,"1.44MB"    }, /* 1.44MB diskette */
+        { 15,2,30,2,0xff,0xdf,0x1b,0x54,80,2400,1,FDC_500KBPS, "1.2MB"    }, /* 1.2 MB AT-diskettes */
+        {  9,2,18,2,0xff,0xdf,0x23,0x50,40, 720,2,FDC_300KBPS, "360KB/AT" }, /* 360kB in 1.2MB drive */
+        {  9,2,18,2,0xff,0xdf,0x2a,0x50,40, 720,1,FDC_250KBPS, "360KB/PC" }, /* 360kB PC diskettes */
+        {  9,2,18,2,0xff,0xdf,0x2a,0x50,80,1440,1,FDC_250KBPS, "720KB"    }, /* 3.5" 720kB diskette */
+        {  9,2,18,2,0xff,0xdf,0x23,0x50,80,1440,1,FDC_300KBPS, "720KB/x"  }, /* 720kB in 1.2MB drive */
+        {  9,2,18,2,0xff,0xdf,0x2a,0x50,40, 720,2,FDC_250KBPS, "360KB/x"  }, /* 360kB in 720kB drive */
+};
+
+/* software state, per disk (with up to 4 disks per ctlr) */
+struct fd_softc {
+       struct device sc_dev;
+       struct disk sc_dk;
+
+       struct fd_type *sc_deftype;     /* default type descriptor */
+       struct fd_type *sc_type;        /* current type descriptor */
+
+       daddr_t sc_blkno;       /* starting block number */
+       int sc_bcount;          /* byte count left */
+       int sc_skip;            /* bytes already transferred */
+       int sc_nblks;           /* number of blocks currently tranferring */
+       int sc_nbytes;          /* number of bytes currently tranferring */
+
+       int sc_drive;           /* physical unit number */
+       int sc_flags;
+#define        FD_OPEN         0x01            /* it's open */
+#define        FD_MOTOR        0x02            /* motor should be on */
+#define        FD_MOTOR_WAIT   0x04            /* motor coming up */
+       int sc_cylin;           /* where we think the head is */
+
+       void *sc_sdhook;        /* saved shutdown hook for drive. */
+
+       TAILQ_ENTRY(fd_softc) sc_drivechain;
+       int sc_ops;             /* I/O ops since last switch */
+       struct buf sc_q;        /* head of buf chain */
+};
+
+/* floppy driver configuration */
+int fdprobe __P((struct device *, void *, void *));
+void fdattach __P((struct device *, struct device *, void *));
+
+struct cfattach fd_ca = {
+       sizeof(struct fd_softc), fdprobe, fdattach
+};
+
+struct cfdriver fd_cd = {
+       NULL, "fd", DV_DISK
+};
+
+void fdgetdisklabel __P((struct fd_softc *));
+int fd_get_parms __P((struct fd_softc *));
+void fdstrategy __P((struct buf *));
+void fdstart __P((struct fd_softc *));
+
+struct dkdriver fddkdriver = { fdstrategy };
+
+struct fd_type *fd_nvtotype __P((char *, int, int));
+void fd_set_motor __P((struct fdc_softc *fdc, int reset));
+void fd_motor_off __P((void *arg));
+void fd_motor_on __P((void *arg));
+int fdcresult __P((struct fdc_softc *fdc));
+int out_fdc __P((int iobase, u_char x));
+void fdcstart __P((struct fdc_softc *fdc));
+void fdcstatus __P((struct device *dv, int n, char *s));
+void fdctimeout __P((void *arg));
+void fdcpseudointr __P((void *arg));
+int fdcintr __P((void *));
+void fdcretry __P((struct fdc_softc *fdc));
+void fdfinish __P((struct fd_softc *fd, struct buf *bp));
+
+int
+fdcprobe(parent, match, aux)
+       struct device *parent;
+       void *match, *aux;
+{
+       register struct mainbus_attach_args *mb = aux;
+       int iobase = mb->mb_iobase;
+
+       /* reset */
+       outb(iobase + fdout, 0);
+       delay(100);
+       outb(iobase + fdout, FDO_FRST);
+
+       /* see if it can handle a command */
+       if (out_fdc(iobase, NE7CMD_SPECIFY) < 0)
+               return 0;
+       out_fdc(iobase, 0xdf);
+       out_fdc(iobase, 6/*2*/);        /* Don't remember why - mark */
+
+#ifdef NEWCONFIG
+       if (iobase == IOBASEUNK || ia->ia_drq == DRQUNK)
+               return 0;
+
+       if (ia->ia_irq == IRQUNK) {
+               ia->ia_irq = isa_discoverintr(fdcforceintr, aux);
+               if (ia->ia_irq == IRQNONE)
+                       return 0;
+
+               /* reset it again */
+               outb(iobase + fdout, 0);
+               delay(100);
+               outb(iobase + fdout, FDO_FRST);
+       }
+#endif
+
+       mb->mb_iosize = FDC_NPORT;
+       return 1;
+}
+
+#ifdef NEWCONFIG
+void
+fdcforceintr(aux)
+       void *aux;
+{
+       struct mainbus_attach_args *mb = aux;
+       int iobase = mb->mb_iobase;
+
+       /* the motor is off; this should generate an error with or
+          without a disk drive present */
+       out_fdc(iobase, NE7CMD_SEEK);
+       out_fdc(iobase, 0);
+       out_fdc(iobase, 0);
+}
+#endif
+
+/*
+ * Arguments passed between fdcattach and fdprobe.
+ */
+struct fdc_attach_args {
+       int fa_drive;
+       struct fd_type *fa_deftype;
+};
+
+/*
+ * Print the location of a disk drive (called just before attaching the
+ * the drive).  If `fdc' is not NULL, the drive was found but was not
+ * in the system config file; print the drive name as well.
+ * Return QUIET (config_find ignores this if the device was configured) to
+ * avoid printing `fdN not configured' messages.
+ */
+int
+fdprint(aux, fdc)
+       void *aux;
+       char *fdc;
+{
+       register struct fdc_attach_args *fa = aux;
+
+       if (!fdc)
+               printf(" drive %d", fa->fa_drive);
+       return QUIET;
+}
+
+void
+fdcattach(parent, self, aux)
+       struct device *parent, *self;
+       void *aux;
+{
+       struct fdc_softc *fdc = (void *)self;
+       struct mainbus_attach_args *mb = aux;
+       struct fdc_attach_args fa;
+       int type;
+
+       fdc->sc_iobase = mb->mb_iobase;
+       fdc->sc_drq = mb->mb_iobase + mb->mb_drq;
+       fdc->sc_state = DEVIDLE;
+       TAILQ_INIT(&fdc->sc_drives);
+
+       printf("\n");
+
+/*#ifdef NEWCONFIG
+       at_setup_dmachan(fdc->sc_drq, FDC_MAXIOSIZE);
+       isa_establish(&fdc->sc_id, &fdc->sc_dev);
+#endif*/
+
+       fdc->sc_ih.ih_func = fdcintr;
+       fdc->sc_ih.ih_arg = fdc;
+       fdc->sc_ih.ih_level = IPL_BIO;
+       fdc->sc_ih.ih_name = "fdc";
+       if (irq_claim(mb->mb_irq, &fdc->sc_ih))
+               panic("Cannot claim IRQ %d for fdc%d\n", mb->mb_irq, parent->dv_unit);
+
+       /*
+        * The NVRAM info only tells us about the first two disks on the
+        * `primary' floppy controller.
+        */
+/*     if (fdc->sc_dev.dv_unit == 0)
+               type = mc146818_read(NULL, NVRAM_DISKETTE);
+       else
+               type = -1;*/
+
+       type = 0x10;
+
+       /* physical limit: four drives per controller. */
+       for (fa.fa_drive = 0; fa.fa_drive < 4; fa.fa_drive++) {
+               if (type >= 0 && fa.fa_drive < 2)
+                       fa.fa_deftype = fd_nvtotype(fdc->sc_dev.dv_xname,
+                           type, fa.fa_drive);
+               else
+                       fa.fa_deftype = NULL;           /* unknown */
+               (void)config_found(self, (void *)&fa, fdprint);
+       }
+}
+
+int
+fdprobe(parent, match, aux)
+       struct device *parent;
+       void *match, *aux;
+{
+       struct fdc_softc *fdc = (void *)parent;
+       struct cfdata *cf = match;
+       struct fdc_attach_args *fa = aux;
+       int drive = fa->fa_drive;
+       int iobase = fdc->sc_iobase;
+       int n;
+
+       if (cf->cf_loc[0] != -1 && cf->cf_loc[0] != drive)
+               return 0;
+       /*
+        * XXX
+        * This is to work around some odd interactions between this driver
+        * and SMC Ethernet cards.
+        */
+
+       /* Don't need this for arm32 port but leave for the time being (it won't hurt) */
+
+       if (cf->cf_loc[0] == -1 && drive >= 2)
+               return 0;
+
+       /* select drive and turn on motor */
+       outb(iobase + fdout, drive | FDO_FRST | FDO_MOEN(drive));
+       /* wait for motor to spin up */
+       delay(250000);
+       out_fdc(iobase, NE7CMD_RECAL);
+       out_fdc(iobase, drive);
+       /* wait for recalibrate */
+       delay(2000000);
+       out_fdc(iobase, NE7CMD_SENSEI);
+       n = fdcresult(fdc);
+#ifdef FD_DEBUG
+       {
+               int i;
+               printf("fdprobe: status");
+               for (i = 0; i < n; i++)
+                       printf(" %x", fdc->sc_status[i]);
+               printf("\n");
+       }
+#endif
+       if (n != 2 || (fdc->sc_status[0] & 0xf8) != 0x20)
+               return 0;
+       /* turn off motor */
+       outb(iobase + fdout, FDO_FRST);
+
+       return 1;
+}
+
+/*
+ * Controller is working, and drive responded.  Attach it.
+ */
+void
+fdattach(parent, self, aux)
+       struct device *parent, *self;
+       void *aux;
+{
+       struct fdc_softc *fdc = (void *)parent;
+       struct fd_softc *fd = (void *)self;
+       struct fdc_attach_args *fa = aux;
+       struct fd_type *type = fa->fa_deftype;
+       int drive = fa->fa_drive;
+
+       /* XXX Allow `flags' to override device type? */
+
+       if (type)
+               printf(": %s %d cyl, %d head, %d sec\n", type->name,
+                   type->tracks, type->heads, type->sectrac);
+       else
+               printf(": density unknown\n");
+
+       fd->sc_cylin = -1;
+       fd->sc_drive = drive;
+       fd->sc_deftype = type;
+       fdc->sc_fd[drive] = fd;
+
+       /*
+        * Initialize and attach the disk structure.
+        */
+       fd->sc_dk.dk_name = fd->sc_dev.dv_xname;
+       fd->sc_dk.dk_driver = &fddkdriver;
+       disk_attach(&fd->sc_dk);
+
+#ifdef NEWCONFIG
+       /* XXX Need to do some more fiddling with sc_dk. */
+       dk_establish(&fd->sc_dk, &fd->sc_dev);
+#endif
+       /* Needed to power off if the motor is on when we halt. */
+       fd->sc_sdhook = shutdownhook_establish(fd_motor_off, fd);
+}
+
+/*
+ * Translate nvram type into internal data structure.  Return NULL for
+ * none/unknown/unusable.
+ */
+struct fd_type *
+fd_nvtotype(fdc, nvraminfo, drive)
+       char *fdc;
+       int nvraminfo, drive;
+{
+       int type;
+
+       type = (drive == 0 ? nvraminfo : nvraminfo << 4) & 0xf0;
+       switch (type) {
+/*     case 0x00 :
+               return NULL;*/
+       case 0x10 :
+               return &fd_types[0];
+       default:
+               printf("%s: drive %d: unknown device type 0x%x\n",
+                   fdc, drive, type);
+               return NULL;
+       }
+}
+
+inline struct fd_type *
+fd_dev_to_type(fd, dev)
+       struct fd_softc *fd;
+       dev_t dev;
+{
+       int type = FDTYPE(dev);
+
+       if (type > (sizeof(fd_types) / sizeof(fd_types[0])))
+               return NULL;
+       return type ? &fd_types[type - 1] : fd->sc_deftype;
+}
+
+void
+fdstrategy(bp)
+       register struct buf *bp;        /* IO operation to perform */
+{
+       struct fd_softc *fd;
+       int unit = FDUNIT(bp->b_dev);
+       int sz;
+       int s;
+
+/*     printf("fdstrategy: bp=%08x\n", bp);*/
+
+       /* Valid unit, controller, and request? */
+       if (unit >= fd_cd.cd_ndevs ||
+           (fd = fd_cd.cd_devs[unit]) == 0 ||
+           bp->b_blkno < 0 ||
+           (bp->b_bcount % FDC_BSIZE) != 0) {
+               bp->b_error = EINVAL;
+               goto bad;
+       }
+
+       /* If it's a null transfer, return immediately. */
+       if (bp->b_bcount == 0)
+               goto done;
+
+       sz = howmany(bp->b_bcount, FDC_BSIZE);
+
+       if (bp->b_blkno + sz > fd->sc_type->size) {
+               sz = fd->sc_type->size - bp->b_blkno;
+               if (sz == 0) {
+                       /* If exactly at end of disk, return EOF. */
+                       bp->b_resid = bp->b_bcount;
+                       goto done;
+               }
+               if (sz < 0) {
+                       /* If past end of disk, return EINVAL. */
+                       bp->b_error = EINVAL;
+                       goto bad;
+               }
+               /* Otherwise, truncate request. */
+               bp->b_bcount = sz << DEV_BSHIFT;
+       }
+
+       bp->b_cylin = bp->b_blkno / (FDC_BSIZE / DEV_BSIZE) / fd->sc_type->seccyl;
+
+#ifdef FD_DEBUG
+       printf("fdstrategy: b_blkno %d b_bcount %d blkno %d cylin %d sz %d\n",
+           bp->b_blkno, bp->b_bcount, fd->sc_blkno, bp->b_cylin, sz);
+#endif
+
+       /* Queue transfer on drive, activate drive and controller if idle. */
+       s = splbio();
+       disksort(&fd->sc_q, bp);
+       untimeout(fd_motor_off, fd); /* a good idea */
+       /* Instrumentation. */
+       disk_busy(&fd->sc_dk);
+       if (!fd->sc_q.b_active)
+               fdstart(fd);
+#ifdef DIAGNOSTIC
+       else {
+               struct fdc_softc *fdc = (void *)fd->sc_dev.dv_parent;
+               if (fdc->sc_state == DEVIDLE) {
+                       printf("fdstrategy: controller inactive\n");
+                       fdcstart(fdc);
+               }
+       }
+#endif
+       splx(s);
+       return;
+
+bad:
+       bp->b_flags |= B_ERROR;
+done:
+       /* Toss transfer; we're done early. */
+       biodone(bp);
+}
+
+void
+fdstart(fd)
+       struct fd_softc *fd;
+{
+       struct fdc_softc *fdc = (void *)fd->sc_dev.dv_parent;
+       int active = fdc->sc_drives.tqh_first != 0;
+
+/*     printf("fdstart:\n");*/
+
+       /* Link into controller queue. */
+       fd->sc_q.b_active = 1;
+       TAILQ_INSERT_TAIL(&fdc->sc_drives, fd, sc_drivechain);
+
+       /* Instrumentation. */
+/*     disk_busy(&fd->sc_dk);*/
+
+       /* If controller not already active, start it. */
+       if (!active)
+               fdcstart(fdc);
+}
+
+void
+fdfinish(fd, bp)
+       struct fd_softc *fd;
+       struct buf *bp;
+{
+       struct fdc_softc *fdc = (void *)fd->sc_dev.dv_parent;
+
+       /*
+        * Move this drive to the end of the queue to give others a `fair'
+        * chance.  We only force a switch if N operations are completed while
+        * another drive is waiting to be serviced, since there is a long motor
+        * startup delay whenever we switch.
+        */
+       if (fd->sc_drivechain.tqe_next && ++fd->sc_ops >= 8) {
+               fd->sc_ops = 0;
+               TAILQ_REMOVE(&fdc->sc_drives, fd, sc_drivechain);
+               if (bp->b_actf) {
+                       TAILQ_INSERT_TAIL(&fdc->sc_drives, fd, sc_drivechain);
+               } else
+                       fd->sc_q.b_active = 0;
+       }
+       bp->b_resid = fd->sc_bcount;
+       fd->sc_skip = 0;
+       fd->sc_q.b_actf = bp->b_actf;
+
+/*     printf("fdfinish: fd=%08x buf=%08x busy=%d\n", (u_int)fd, (u_int)bp, fd->sc_dk.dk_busy);*/
+
+       disk_unbusy(&fd->sc_dk, (bp->b_bcount - bp->b_resid));
+
+       biodone(bp);
+       /* turn off motor 5s from now */
+       timeout(fd_motor_off, fd, 5 * hz);
+       fdc->sc_state = DEVIDLE;
+}
+
+int
+fdread(dev, uio)
+       dev_t dev;
+       struct uio *uio;
+{
+
+       return (physio(fdstrategy, NULL, dev, B_READ, minphys, uio));
+}
+
+int
+fdwrite(dev, uio)
+       dev_t dev;
+       struct uio *uio;
+{
+
+       return (physio(fdstrategy, NULL, dev, B_WRITE, minphys, uio));
+}
+
+void
+fd_set_motor(fdc, reset)
+       struct fdc_softc *fdc;
+       int reset;
+{
+       struct fd_softc *fd;
+       u_char status;
+       int n;
+
+       if (fd = fdc->sc_drives.tqh_first)
+               status = fd->sc_drive;
+       else
+               status = 0;
+       if (!reset)
+               status |= FDO_FRST | FDO_FDMAEN;
+       for (n = 0; n < 4; n++)
+               if ((fd = fdc->sc_fd[n]) && (fd->sc_flags & FD_MOTOR))
+                       status |= FDO_MOEN(n);
+       outb(fdc->sc_iobase + fdout, status);
+}
+
+void
+fd_motor_off(arg)
+       void *arg;
+{
+       struct fd_softc *fd = arg;
+       int s;
+
+       s = splbio();
+       fd->sc_flags &= ~(FD_MOTOR | FD_MOTOR_WAIT);
+       fd_set_motor((struct fdc_softc *)fd->sc_dev.dv_parent, 0);
+       splx(s);
+}
+
+void
+fd_motor_on(arg)
+       void *arg;
+{
+       struct fd_softc *fd = arg;
+       struct fdc_softc *fdc = (void *)fd->sc_dev.dv_parent;
+       int s;
+
+       s = splbio();
+       fd->sc_flags &= ~FD_MOTOR_WAIT;
+       if ((fdc->sc_drives.tqh_first == fd) && (fdc->sc_state == MOTORWAIT))
+               (void) fdcintr(fdc);
+       splx(s);
+}
+
+int
+fdcresult(fdc)
+       struct fdc_softc *fdc;
+{
+       int iobase = fdc->sc_iobase;
+       u_char i;
+       int j = 100000,
+           n = 0;
+
+       for (; j; j--) {
+               i = inb(iobase + fdsts) & (NE7_DIO | NE7_RQM | NE7_CB);
+               if (i == NE7_RQM)
+                       return n;
+               if (i == (NE7_DIO | NE7_RQM | NE7_CB)) {
+                       if (n >= sizeof(fdc->sc_status)) {
+                               log(LOG_ERR, "fdcresult: overrun\n");
+                               return -1;
+                       }
+                       fdc->sc_status[n++] = inb(iobase + fddata);
+               }
+       }
+       log(LOG_ERR, "fdcresult: timeout\n");
+       return -1;
+}
+
+int
+out_fdc(iobase, x)
+       int iobase;
+       u_char x;
+{
+       int i = 100000;
+
+       while ((inb(iobase + fdsts) & NE7_DIO) && i-- > 0);
+       if (i <= 0)
+               return -1;
+       while ((inb(iobase + fdsts) & NE7_RQM) == 0 && i-- > 0);
+       if (i <= 0)
+               return -1;
+       outb(iobase + fddata, x);
+       return 0;
+}
+
+int
+fdopen(dev, flags)
+       dev_t dev;
+       int flags;
+{
+       int unit;
+       struct fd_softc *fd;
+       struct fd_type *type;
+
+       unit = FDUNIT(dev);
+       if (unit >= fd_cd.cd_ndevs)
+               return ENXIO;
+       fd = fd_cd.cd_devs[unit];
+       if (fd == 0)
+               return ENXIO;
+       type = fd_dev_to_type(fd, dev);
+       if (type == NULL)
+               return ENXIO;
+
+       if ((fd->sc_flags & FD_OPEN) != 0 &&
+           fd->sc_type != type)
+               return EBUSY;
+
+       fd->sc_type = type;
+       fd->sc_cylin = -1;
+       fd->sc_flags |= FD_OPEN;
+
+       return 0;
+}
+
+int
+fdclose(dev, flags)
+       dev_t dev;
+       int flags;
+{
+       struct fd_softc *fd = fd_cd.cd_devs[FDUNIT(dev)];
+
+       fd->sc_flags &= ~FD_OPEN;
+       return 0;
+}
+
+void
+fdcstart(fdc)
+       struct fdc_softc *fdc;
+{
+
+#ifdef DIAGNOSTIC
+       /* only got here if controller's drive queue was inactive; should
+          be in idle state */
+       if (fdc->sc_state != DEVIDLE) {
+               printf("fdcstart: not idle\n");
+               return;
+       }
+#endif
+       (void) fdcintr(fdc);
+}
+
+void
+fdcstatus(dv, n, s)
+       struct device *dv;
+       int n;
+       char *s;
+{
+       struct fdc_softc *fdc = (void *)dv->dv_parent;
+       int iobase = fdc->sc_iobase;
+
+       if (n == 0) {
+               out_fdc(fdc->sc_iobase, NE7CMD_SENSEI);
+               (void) fdcresult(fdc);
+               n = 2;
+       }
+
+       printf("%s: %s", dv->dv_xname, s);
+
+       switch (n) {
+       case 0:
+               printf("\n");
+               break;
+       case 2:
+               printf(" (st0 %b cyl %d)\n",
+                   fdc->sc_status[0], NE7_ST0BITS,
+                   fdc->sc_status[1]);
+               break;
+       case 7:
+               printf(" (st0 %b st1 %b st2 %b cyl %d head %d sec %d)\n",
+                   fdc->sc_status[0], NE7_ST0BITS,
+                   fdc->sc_status[1], NE7_ST1BITS,
+                   fdc->sc_status[2], NE7_ST2BITS,
+                   fdc->sc_status[3], fdc->sc_status[4], fdc->sc_status[5]);
+               break;
+#ifdef DIAGNOSTIC
+       default:
+               printf("\nfdcstatus: weird size");
+               break;
+#endif
+       }
+}
+
+void
+fdctimeout(arg)
+       void *arg;
+{
+       struct fdc_softc *fdc = arg;
+       struct fd_softc *fd = fdc->sc_drives.tqh_first;
+       int s;
+
+       s = splbio();
+       fdcstatus(&fd->sc_dev, 0, "timeout");
+
+       if (fd->sc_q.b_actf)
+               fdc->sc_state++;
+       else
+               fdc->sc_state = DEVIDLE;
+
+       (void) fdcintr(fdc);
+       splx(s);
+}
+
+void
+fdcpseudointr(arg)
+       void *arg;
+{
+       int s;
+
+       /* Just ensure it has the right spl. */
+       s = splbio();
+       (void) fdcintr(arg);
+       splx(s);
+}
+
+int
+fdcintr(arg)
+       void *arg;
+{
+       struct fdc_softc *fdc = arg;
+#define        st0     fdc->sc_status[0]
+#define        cyl     fdc->sc_status[1]
+       struct fd_softc *fd;
+       struct buf *bp;
+       int iobase = fdc->sc_iobase;
+       int read, head, trac, sec, i, s, nblks;
+       struct fd_type *type;
+
+loop:
+       /* Is there a drive for the controller to do a transfer with? */
+       fd = fdc->sc_drives.tqh_first;
+       if (fd == NULL) {
+               fdc->sc_state = DEVIDLE;
+               return 1;
+       }
+
+       /* Is there a transfer to this drive?  If not, deactivate drive. */
+       bp = fd->sc_q.b_actf;
+       if (bp == NULL) {
+               fd->sc_ops = 0;
+               TAILQ_REMOVE(&fdc->sc_drives, fd, sc_drivechain);
+               fd->sc_q.b_active = 0;
+               goto loop;
+       }
+
+       switch (fdc->sc_state) {
+       case DEVIDLE:
+               fdc->sc_errors = 0;
+               fd->sc_skip = 0;
+               fd->sc_bcount = bp->b_bcount;
+               fd->sc_blkno = bp->b_blkno / (FDC_BSIZE / DEV_BSIZE);
+               untimeout(fd_motor_off, fd);
+               if ((fd->sc_flags & FD_MOTOR_WAIT) != 0) {
+                       fdc->sc_state = MOTORWAIT;
+                       return 1;
+               }
+               if ((fd->sc_flags & FD_MOTOR) == 0) {
+                       /* Turn on the motor, being careful about pairing. */
+                       struct fd_softc *ofd = fdc->sc_fd[fd->sc_drive ^ 1];
+                       if (ofd && ofd->sc_flags & FD_MOTOR) {
+                               untimeout(fd_motor_off, ofd);
+                               ofd->sc_flags &= ~(FD_MOTOR | FD_MOTOR_WAIT);
+                       }
+                       fd->sc_flags |= FD_MOTOR | FD_MOTOR_WAIT;
+                       fd_set_motor(fdc, 0);
+                       fdc->sc_state = MOTORWAIT;
+                       /* Allow .25s for motor to stabilize. */
+                       timeout(fd_motor_on, fd, hz / 4);
+                       return 1;
+               }
+               /* Make sure the right drive is selected. */
+               fd_set_motor(fdc, 0);
+
+               /* fall through */
+       case DOSEEK:
+       doseek:
+               if (fd->sc_cylin == bp->b_cylin)
+                       goto doio;
+
+               out_fdc(iobase, NE7CMD_CONFIGURE);/* configure command */
+               out_fdc(iobase, 0);
+               out_fdc(iobase, 0x1a);
+               out_fdc(iobase, 0);
+
+               out_fdc(iobase, NE7CMD_SPECIFY);/* specify command */
+               out_fdc(iobase, fd->sc_type->steprate);
+               out_fdc(iobase, 6);             /* XXX head load time == 6ms */
+
+               out_fdc(iobase, NE7CMD_SEEK);   /* seek function */
+               out_fdc(iobase, fd->sc_drive);  /* drive number */
+               out_fdc(iobase, bp->b_cylin * fd->sc_type->step);
+
+               fd->sc_cylin = -1;
+               fdc->sc_state = SEEKWAIT;
+               timeout(fdctimeout, fdc, 4 * hz);
+               return 1;
+
+       case DOIO:
+       doio:
+               type = fd->sc_type;
+               sec = fd->sc_blkno % type->seccyl;
+               nblks = type->seccyl - sec;
+               nblks = min(nblks, fd->sc_bcount / FDC_BSIZE);
+               nblks = min(nblks, FDC_MAXIOSIZE / FDC_BSIZE);
+               fd->sc_nblks = nblks;
+               fd->sc_nbytes = nblks * FDC_BSIZE;
+               head = sec / type->sectrac;
+               sec -= head * type->sectrac;
+#ifdef DIAGNOSTIC
+               {int block;
+                block = (fd->sc_cylin * type->heads + head) * type->sectrac + sec;
+                if (block != fd->sc_blkno) {
+                        printf("fdcintr: block %d != blkno %d\n", block, fd->sc_blkno);
+#ifdef DDB
+                        Debugger();
+#endif
+                }}
+#endif
+               read = bp->b_flags & B_READ;
+/*#ifdef NEWCONFIG
+               at_dma(read, bp->b_data + fd->sc_skip, fd->sc_nbytes,
+                   fdc->sc_drq);
+#else
+               isa_dmastart(read, bp->b_data + fd->sc_skip, fd->sc_nbytes,
+                   fdc->sc_drq);
+#endif*/
+               if (read)
+                       fiqhandler.fh_func = floppy_read_fiq;
+               else
+                       fiqhandler.fh_func = floppy_write_fiq;
+               fiqhandler.fh_r11 = nblks * FDC_BSIZE;
+               fiqhandler.fh_r12 = (int)bp->b_data + (int)fd->sc_skip;
+               fiqhandler.fh_r13 = fdc->sc_drq;
+               fiqhandler.fh_mask = 0x01;
+               if (fiq_claim(&fiqhandler) == -1)
+                       panic("Cannot claim FIQ vector\n");
+
+               outb(iobase + fdctl, type->rate);
+#ifdef FD_DEBUG
+               printf("fdcintr: %s drive %d track %d head %d sec %d nblks %d\n",
+                   read ? "read" : "write", fd->sc_drive, fd->sc_cylin, head,
+                   sec, nblks);
+#endif
+               if (read)
+                       out_fdc(iobase, NE7CMD_READ);   /* READ */
+               else
+                       out_fdc(iobase, NE7CMD_WRITE);  /* WRITE */
+               out_fdc(iobase, (head << 2) | fd->sc_drive);
+               out_fdc(iobase, fd->sc_cylin);          /* track */
+               out_fdc(iobase, head);
+               out_fdc(iobase, sec + 1);               /* sector +1 */
+               out_fdc(iobase, type->secsize);         /* sector size */
+               out_fdc(iobase, type->sectrac);         /* sectors/track */
+               out_fdc(iobase, type->gap1);            /* gap1 size */
+               out_fdc(iobase, type->datalen);         /* data length */
+               fdc->sc_state = IOCOMPLETE;
+               /* allow 2 seconds for operation */
+               timeout(fdctimeout, fdc, 2 * hz);
+               return 1;                               /* will return later */
+
+       case SEEKWAIT:
+               untimeout(fdctimeout, fdc);
+               fdc->sc_state = SEEKCOMPLETE;
+               /* allow 1/50 second for heads to settle */
+/*             timeout(fdcpseudointr, fdc, hz / 50);*/
+               return 1;
+
+       case SEEKCOMPLETE:
+               /* Make sure seek really happened. */
+               out_fdc(iobase, NE7CMD_SENSEI);
+               if (fdcresult(fdc) != 2 || (st0 & 0xf8) != 0x20 ||
+                   cyl != bp->b_cylin * fd->sc_type->step) {
+#ifdef FD_DEBUG
+                       fdcstatus(&fd->sc_dev, 2, "seek failed");
+#endif
+                       fdcretry(fdc);
+                       goto loop;
+               }
+               fd->sc_cylin = bp->b_cylin;
+               goto doio;
+
+       case IOTIMEDOUT:
+/*#ifdef NEWCONFIG
+               at_dma_abort(fdc->sc_drq);
+#else
+               isa_dmaabort(fdc->sc_drq);
+#endif*/
+               if (fiq_release(&fiqhandler) == -1)
+                       panic("Cannot release FIQ vector\n");
+       case SEEKTIMEDOUT:
+       case RECALTIMEDOUT:
+       case RESETTIMEDOUT:
+               fdcretry(fdc);
+               goto loop;
+
+       case IOCOMPLETE: /* IO DONE, post-analyze */
+               untimeout(fdctimeout, fdc);
+               if (fdcresult(fdc) != 7 || (st0 & 0xf8) != 0) {
+/*#ifdef NEWCONFIG
+                       at_dma_abort(fdc->sc_drq);
+#else
+                       isa_dmaabort(fdc->sc_drq);
+#endif*/
+               if (fiq_release(&fiqhandler) == -1)
+                       panic("Cannot release FIQ vector\n");
+#ifdef FD_DEBUG
+                       fdcstatus(&fd->sc_dev, 7, bp->b_flags & B_READ ?
+                           "read failed" : "write failed");
+                       printf("blkno %d nblks %d\n",
+                           fd->sc_blkno, fd->sc_nblks);
+#endif
+                       fdcretry(fdc);
+                       goto loop;
+               }
+/*#ifdef NEWCONFIG
+               at_dma_terminate(fdc->sc_drq);
+#else
+               read = bp->b_flags & B_READ;
+               isa_dmadone(read, bp->b_data + fd->sc_skip, fd->sc_nbytes,
+                   fdc->sc_drq);
+#endif*/
+               if (fiq_release(&fiqhandler) == -1)
+                       panic("Cannot release FIQ vector\n");
+
+               if (fdc->sc_errors) {
+/*                     diskerr(bp, "fd", "soft error", LOG_PRINTF,
+                           fd->sc_skip / FDC_BSIZE, (struct disklabel *)NULL);
+                       printf("\n");*/
+                       fdc->sc_errors = 0;
+               }
+               fd->sc_blkno += fd->sc_nblks;
+               fd->sc_skip += fd->sc_nbytes;
+               fd->sc_bcount -= fd->sc_nbytes;
+               if (fd->sc_bcount > 0) {
+                       bp->b_cylin = fd->sc_blkno / fd->sc_type->seccyl;
+                       goto doseek;
+               }
+/*             printf("IOCOMPLETE:calling fdfinish fd=%08x bp=%08x blkno=%d\n", (u_int)fd, (u_int)bp, fd->sc_blkno);*/
+               fdfinish(fd, bp);
+               goto loop;
+
+       case DORESET:
+               /* try a reset, keep motor on */
+               fd_set_motor(fdc, 1);
+               delay(100);
+               fd_set_motor(fdc, 0);
+               fdc->sc_state = RESETCOMPLETE;
+               timeout(fdctimeout, fdc, hz / 2);
+               return 1;                       /* will return later */
+
+       case RESETCOMPLETE:
+               untimeout(fdctimeout, fdc);
+               /* clear the controller output buffer */
+               for (i = 0; i < 4; i++) {
+                       out_fdc(iobase, NE7CMD_SENSEI);
+                       (void) fdcresult(fdc);
+               }
+
+               /* fall through */
+       case DORECAL:
+               out_fdc(iobase, NE7CMD_RECAL);  /* recalibrate function */
+               out_fdc(iobase, fd->sc_drive);
+               fdc->sc_state = RECALWAIT;
+               timeout(fdctimeout, fdc, 5 * hz);
+               return 1;                       /* will return later */
+
+       case RECALWAIT:
+               untimeout(fdctimeout, fdc);
+               fdc->sc_state = RECALCOMPLETE;
+               /* allow 1/30 second for heads to settle */
+/*             timeout(fdcpseudointr, fdc, hz / 30);*/
+               return 1;                       /* will return later */
+
+       case RECALCOMPLETE:
+               out_fdc(iobase, NE7CMD_SENSEI);
+               if (fdcresult(fdc) != 2 || (st0 & 0xf8) != 0x20 || cyl != 0) {
+#ifdef FD_DEBUG
+                       fdcstatus(&fd->sc_dev, 2, "recalibrate failed");
+#endif
+                       fdcretry(fdc);
+                       goto loop;
+               }
+               fd->sc_cylin = 0;
+               goto doseek;
+
+       case MOTORWAIT:
+               if (fd->sc_flags & FD_MOTOR_WAIT)
+                       return 1;               /* time's not up yet */
+               goto doseek;
+
+       default:
+               fdcstatus(&fd->sc_dev, 0, "stray interrupt");
+               return 1;
+       }
+#ifdef DIAGNOSTIC
+       panic("fdcintr: impossible");
+#endif
+#undef st0
+#undef cyl
+}
+
+void
+fdcretry(fdc)
+       struct fdc_softc *fdc;
+{
+       struct fd_softc *fd;
+       struct buf *bp;
+
+       fd = fdc->sc_drives.tqh_first;
+       bp = fd->sc_q.b_actf;
+
+       switch (fdc->sc_errors) {
+       case 0:
+               /* try again */
+/*             fdc->sc_state = SEEKCOMPLETE;*/
+               fdc->sc_state = DOSEEK;
+               break;
+
+       case 1: case 2: case 3:
+               /* didn't work; try recalibrating */
+               fdc->sc_state = DORECAL;
+               break;
+
+       case 4:
+               /* still no go; reset the bastard */
+               fdc->sc_state = DORESET;
+               break;
+
+       default:
+               diskerr(bp, "fd", "hard error", LOG_PRINTF,
+                   fd->sc_skip / FDC_BSIZE, (struct disklabel *)NULL);
+               printf(" (st0 %b st1 %b st2 %b cyl %d head %d sec %d)\n",
+                   fdc->sc_status[0], NE7_ST0BITS,
+                   fdc->sc_status[1], NE7_ST1BITS,
+                   fdc->sc_status[2], NE7_ST2BITS,
+                   fdc->sc_status[3], fdc->sc_status[4], fdc->sc_status[5]);
+
+               bp->b_flags |= B_ERROR;
+               bp->b_error = EIO;
+               fdfinish(fd, bp);
+       }
+       fdc->sc_errors++;
+}
+
+int
+fdsize(dev)
+       dev_t dev;
+{
+
+       /* Swapping to floppies would not make sense. */
+       return -1;
+}
+
+int
+fddump(dev, blkno, va, size)
+       dev_t dev;
+       daddr_t blkno;
+       caddr_t va;
+       size_t size;
+{
+
+       /* Not implemented. */
+       return ENXIO;
+}
+
+int
+fdioctl(dev, cmd, addr, flag)
+       dev_t dev;
+       u_long cmd;
+       caddr_t addr;
+       int flag;
+{
+       struct fd_softc *fd = fd_cd.cd_devs[FDUNIT(dev)];
+       struct disklabel buffer;
+       int error;
+
+       switch (cmd) {
+       case DIOCGDINFO:
+               bzero(&buffer, sizeof(buffer));
+
+               buffer.d_secpercyl = fd->sc_type->seccyl;
+               buffer.d_type = DTYPE_FLOPPY;
+               buffer.d_secsize = FDC_BSIZE;
+
+               if (readdisklabel(dev, fdstrategy, &buffer, NULL) != NULL)
+                       return EINVAL;
+
+               *(struct disklabel *)addr = buffer;
+               return 0;
+
+       case DIOCWLABEL:
+               if ((flag & FWRITE) == 0)
+                       return EBADF;
+               /* XXX do something */
+               return 0;
+
+       case DIOCWDINFO:
+               if ((flag & FWRITE) == 0)
+                       return EBADF;
+
+               error = setdisklabel(&buffer, (struct disklabel *)addr, 0, NULL);
+               if (error)
+                       return error;
+
+               error = writedisklabel(dev, fdstrategy, &buffer, NULL);
+               return error;
+
+       default:
+               return ENOTTY;
+       }
+
+#ifdef DIAGNOSTIC
+       panic("fdioctl: impossible");
+#endif
+}
+
+
+#include "rd.h"
+#if NRD > 0
+
+#include <dev/ramdisk.h>
+
+int
+load_ramdisc_from_floppy(rd, dev)
+       struct rd_conf *rd;
+       dev_t dev;
+{
+       struct buf *bp;
+       int loop;
+       int s;
+       int type;
+       int floppysize;
+
+       if (major(dev) != 17)
+               return(EINVAL);
+
+       if (rd->rd_type == RD_UNCONFIGURED || rd->rd_addr == 0)
+               return(EBUSY);
+
+       type = FDTYPE(dev) - 1;
+       if (type < 0) type = 0;
+       floppysize = fd_types[type].size << (fd_types[type].secsize + 7);
+        
+       if (rd->rd_size < floppysize) {
+               printf("Ramdisc not big enough for floppy image\n");
+               return(EINVAL);
+       }
+
+/* We have the ramdisk ! */
+
+       printf("Loading ramdisc : %4dK ", 0);
+
+/* obtain a buffer */
+
+       bp = geteblk(fd_types[type].sectrac * DEV_BSIZE);
+    
+/* request no partition relocation by driver on I/O operations */
+
+       bp->b_dev = dev;
+
+       s = spl0();
+
+       if (fdopen(bp->b_dev, 0) != 0) {
+               brelse(bp);             
+               printf("Cannot open floppy device\n");
+                       return(EINVAL);
+       }
+
+       for (loop = 0;
+           loop < (floppysize / DEV_BSIZE / fd_types[type].sectrac);
+           ++loop) {
+               printf("\x08\x08\x08\x08\x08\x08%4dK ",
+                   loop * fd_types[type].sectrac * DEV_BSIZE / 1024);
+               bp->b_blkno = loop * fd_types[type].sectrac;
+               bp->b_bcount = fd_types[type].sectrac * DEV_BSIZE;
+               bp->b_flags = B_BUSY | B_READ;
+               bp->b_error = 0;
+               bp->b_resid = 0;
+               fdstrategy(bp);
+
+               if (biowait(bp))
+                       panic("Cannot load floppy image\n");
+                                                 
+               bcopy((caddr_t)bp->b_data, (caddr_t)rd->rd_addr
+                   + loop * fd_types[type].sectrac * DEV_BSIZE,
+                   fd_types[type].sectrac * DEV_BSIZE);
+       }
+       printf("\x08\x08\x08\x08\x08\x08%4dK done\n",
+           loop * fd_types[type].sectrac * DEV_BSIZE / 1024);
+        
+       fdclose(bp->b_dev, 0);
+
+       brelse(bp);
+
+       splx(s);
+       return(0);
+}
+
+#endif
diff --git a/sys/arch/arm32/mainbus/fdreg.h b/sys/arch/arm32/mainbus/fdreg.h
new file mode 100644 (file)
index 0000000..bdfd8fe
--- /dev/null
@@ -0,0 +1,102 @@
+/*     $NetBSD: fdreg.h,v 1.2 1996/03/18 20:50:02 mark 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.
+ *
+ *     @(#)fdreg.h     7.1 (Berkeley) 5/9/91
+ */
+
+/*
+ * AT floppy controller registers and bitfields
+ */
+
+
+/*
+ * Nec 765 floppy disc controller definitions
+ */
+  
+/* Main status register */
+#define NE7_DAB        0x01    /* Diskette drive A is seeking, thus busy */
+#define NE7_DBB        0x02    /* Diskette drive B is seeking, thus busy */
+#define NE7_CB 0x10    /* Diskette Controller Busy */
+#define NE7_NDM        0x20    /* Diskette Controller in Non Dma Mode */
+#define NE7_DIO        0x40    /* Diskette Controller Data register I/O */
+#define NE7_RQM        0x80    /* Diskette Controller ReQuest for Master */
+
+/* Status register ST0 */
+#define NE7_ST0BITS    "\020\010invld\007abnrml\006seek_cmplt\005drv_chck\004drive_rdy\003top_head"
+
+/* Status register ST1 */
+#define NE7_ST1BITS    "\020\010end_of_cyl\006bad_crc\005data_overrun\003sec_not_fnd\002write_protect\001no_am"
+
+/* Status register ST2 */
+#define NE7_ST2BITS    "\020\007ctrl_mrk\006bad_crc\005wrong_cyl\004scn_eq\003scn_not_fnd\002bad_cyl\001no_dam"
+
+/* Status register ST3 */
+#define NE7_ST3BITS    "\020\010fault\007write_protect\006drdy\005tk0\004two_side\003side_sel\002"
+
+/* Commands */
+#define NE7CMD_SPECIFY 3       /*  specify drive parameters - requires unit
+                                       parameters byte */
+#define NE7CMD_SENSED  4       /*  sense drive - requires unit select byte */
+#define NE7CMD_WRITE   0xc5    /*  write - requires eight additional bytes */
+#define NE7CMD_READ    0xe6    /*  read - requires eight additional bytes */
+#define NE7CMD_FORMAT  0x4c    /*  format - requires five additional bytes */
+#define NE7CMD_RECAL   7       /*  recalibrate drive - requires
+                                       unit select byte */
+#define NE7CMD_SENSEI  8       /*  sense controller interrupt status */
+#define NE7CMD_SEEK    15      /*  seek drive - requires unit select byte
+                                       and new cyl byte */
+#define NE7CMD_CONFIGURE 0x13
+
+/* registers */
+#define        fdout   8       /* Digital Output Register (W) */
+#define        FDO_FDSEL       0x03    /*  floppy device select */
+#define        FDO_FRST        0x04    /*  floppy controller reset */
+#define        FDO_FDMAEN      0x08    /*  enable floppy DMA and Interrupt */
+#define        FDO_MOEN(n)     ((1 << n) * 0x10)       /* motor enable */
+
+#define        fdsts   16      /* NEC 765 Main Status Register (R) */
+#define        fddata  20      /* NEC 765 Data Register (R/W) */
+
+#define        fdctl   28      /* Control Register (W) */
+#define        FDC_500KBPS     0x00    /* 500KBPS MFM drive transfer rate */
+#define        FDC_300KBPS     0x01    /* 300KBPS MFM drive transfer rate */
+#define        FDC_250KBPS     0x02    /* 250KBPS MFM drive transfer rate */
+#define        FDC_125KBPS     0x03    /* 125KBPS FM drive transfer rate */
+
+#define        fdin    28      /* Digital Input Register (R) */
+#define        FDI_DCHG        0x80    /* diskette has been changed */
+
+#define        FDC_BSIZE       512
+#define        FDC_NPORT       32
+#define        FDC_MAXIOSIZE   NBPG    /* XXX should be MAXBSIZE */
diff --git a/sys/arch/arm32/mainbus/iic.c b/sys/arch/arm32/mainbus/iic.c
new file mode 100644 (file)
index 0000000..334b603
--- /dev/null
@@ -0,0 +1,403 @@
+/* $NetBSD: iic.c,v 1.1 1996/04/19 19:49:03 mark Exp $ */
+
+/*
+ * Copyright (c) 1994-1996 Mark Brinicombe.
+ * Copyright (c) 1994 Brini.
+ * All rights reserved.
+ *
+ * This code is derived from software written for Brini by Mark Brinicombe
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided 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 Mark Brinicombe.
+ * 4. The name of the company nor the name of the author may be used to
+ *    endorse or promote products derived from this software without specific
+ *    prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BRINI ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL BRINI 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.
+ *
+ * RiscBSD kernel project
+ *
+ * iic.c
+ *
+ * Routines to communicate with IIC devices
+ *
+ * Created      : 13/10/94
+ *
+ * Based of kate/display/iiccontrol.c
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/conf.h>
+#include <sys/malloc.h>
+#include <sys/device.h>
+
+#include <machine/io.h>
+#include <machine/iomd.h>
+#include <machine/katelib.h>
+#include <machine/cpu.h>
+#include <machine/irqhandler.h>
+#include <machine/iic.h>
+#include <arm32/mainbus/mainbus.h>
+
+/* Local function prototypes */
+
+static int iic_getack          __P((void));
+static void iic_write_bit      __P((int bit));
+static int iic_write_byte      __P((u_char value));
+static u_char iic_read_byte    __P((void));
+static void iic_start_bit      __P((void));
+static void iic_stop_bit       __P((void));
+
+struct iic_softc {
+       struct device   sc_dev;
+       int             sc_flags;
+#define IIC_BROKEN     1
+#define IIC_OPEN       2
+#define IIC_BUSY       4
+};
+
+void iicattach __P((struct device *parent, struct device *self, void *aux));
+int iicmatch __P((struct device *parent, void *match, void *aux));
+
+/*
+ * Main entry to IIC driver.
+ */
+
+int
+iic_control(address, buffer, count)
+       u_char address;
+       u_char *buffer;
+       int count;
+{
+       int loop;
+
+/* Send the start bit */
+
+       iic_start_bit();
+
+/* Send the address */
+
+       if (!iic_write_byte(address)) {
+               iic_stop_bit();
+               return(-1);
+       }
+
+/* Read or write the data as required */
+
+       if ((address & 1) == 0) {
+/* Write bytes */
+               for (loop = 0; loop < count; ++loop) {
+                       if (!iic_write_byte(buffer[loop])) {
+                               iic_stop_bit();
+                               return(-1);
+                       }
+               }
+       }
+       else {
+/* Read bytes */
+               for (loop = 0; loop < count; ++loop) {
+                       buffer[loop] = iic_read_byte();
+
+/* Send final acknowledge */
+
+                       if (loop == (count - 1))
+                               iic_write_bit(1);
+                       else
+                               iic_write_bit(0);
+               }
+       }
+
+/* Send stop bit */
+
+       iic_stop_bit();
+
+       return(0);
+}
+
+
+static int
+iic_getack()
+{
+       u_int oldirqstate;
+       int ack;
+
+       iic_set_state(1, 0);
+       oldirqstate = disable_interrupts(I32_bit);
+       iic_set_state_and_ack(1, 1);
+       ack = ReadByte(IOMD_IOCR);
+       iic_set_state(1, 0);
+       restore_interrupts(oldirqstate);
+
+       return((ack & 1) == 0);
+}
+
+
+static void
+iic_write_bit(bit)
+       int bit;
+{
+       u_int oldirqstate;
+
+       iic_set_state(bit, 0);
+       oldirqstate = disable_interrupts(I32_bit);
+       iic_set_state_and_ack(bit, 1);
+       iic_set_state(bit, 0);
+       restore_interrupts(oldirqstate);
+}
+
+
+static int
+iic_write_byte(value)
+       u_char value;
+{
+       int loop;
+       int bit;
+
+       for (loop = 0x80; loop != 0; loop = loop >> 1) {
+               bit = ((value & loop) != 0);
+               iic_write_bit(bit);
+       }
+
+       return(iic_getack());
+}
+
+
+static u_char
+iic_read_byte()
+{
+       int loop;
+       u_char byte;
+       u_int oldirqstate;
+
+       iic_set_state(1,0);
+
+       byte = 0;
+
+       for (loop = 0; loop < 8; ++loop) {
+               oldirqstate = disable_interrupts(I32_bit);
+               iic_set_state_and_ack(1, 1);
+               byte = (byte << 1) + (ReadByte(IOMD_IOCR) & 1);
+               iic_set_state(1, 0);
+               restore_interrupts(oldirqstate);
+       }
+
+       return(byte);
+}
+
+
+static void
+iic_start_bit()
+{
+       iic_set_state(1, 1);
+       iic_set_state(0, 1);
+       iic_delay(10);
+       iic_set_state(0, 0);
+}
+
+
+static void
+iic_stop_bit()
+{
+       iic_set_state(0, 1);
+       iic_set_state(1, 1);
+}
+
+
+struct cfattach iic_ca = {
+       sizeof(struct iic_softc), iicmatch, iicattach
+};
+
+struct cfdriver iic_cd = {
+       NULL, "iic", DV_DULL, 0
+};
+
+int
+iicmatch(parent, match, aux)
+       struct device *parent;
+       void *match;
+       void *aux;
+{
+       int id;
+
+/* Make sure we have an IOMD we understand */
+    
+       id = ReadByte(IOMD_ID0) | (ReadByte(IOMD_ID1) << 8);
+
+/* So far I only know about this IOMD */
+
+       switch (id) {
+       case RPC600_IOMD_ID:
+       case RC7500_IOC_ID:
+               return(1);
+               break;
+       default:
+               printf("iic: Unknown IOMD id=%04x", id);
+               break;
+       }
+
+       return(0);
+}
+
+int
+iicprint(aux, name)
+       void *aux;
+       char *name;
+{
+       struct iicbus_attach_args *ib = aux;
+
+       if (!name) {
+               if (ib->ib_addr)
+                       printf(" addr 0x%02x", ib->ib_addr);
+       }
+
+/* XXXX print flags */
+       return (QUIET);
+}
+
+
+int
+iicsubmatch(parent, match, aux)
+       struct device *parent;
+       void *match;
+       void *aux;
+{
+       struct cfdata *cf = match;
+       struct iicbus_attach_args *ib = aux;
+
+       if (cf->cf_fstate == FSTATE_STAR)
+               panic("eekkk, I'm stuffed");
+
+       ib->ib_addr = cf->cf_loc[0];
+
+       if (ib->ib_addr == -1)
+               return(0);
+
+       return((*cf->cf_attach->ca_match)(parent, match, aux));
+}
+
+void
+iicattach(parent, self, aux)
+       struct device *parent;
+       struct device *self;
+       void *aux;
+{
+       struct iicbus_attach_args iaa;
+
+       printf("\n");
+
+       while (config_found_sm(self, &iaa, iicprint, iicsubmatch));
+}
+
+
+int
+iicopen(dev, flag, mode, p)
+       dev_t dev;
+       int flag;
+       int mode;
+       struct proc *p;
+{
+       struct iic_softc *sc;
+       int unit = minor(dev);
+    
+       if (unit >= iic_cd.cd_ndevs)
+               return(ENXIO);
+
+       sc = iic_cd.cd_devs[unit];
+    
+       if (!sc) return(ENXIO);
+
+       if (sc->sc_flags & IIC_OPEN) return(EBUSY);
+
+       sc->sc_flags |= IIC_OPEN;
+
+       return(0);
+}
+
+
+int
+iicclose(dev, flag, mode, p)
+       dev_t dev;
+       int flag;
+       int mode;
+       struct proc *p;
+{
+       int unit = minor(dev);
+       struct iic_softc *sc = iic_cd.cd_devs[unit];
+    
+       sc->sc_flags &= ~IIC_OPEN;
+
+       return(0);
+}
+
+
+int
+iicread(dev, uio, flag)
+       dev_t dev;
+       struct uio *uio;
+       int flag;
+{
+       int unit = minor(dev);
+       struct iic_softc *sc = iic_cd.cd_devs[unit];
+
+       return(ENXIO);
+}
+
+
+int
+iicwrite(dev, uio, flag)
+       dev_t dev;
+       struct uio *uio;
+       int flag;
+{
+       int unit = minor(dev);
+       struct iic_softc *sc = iic_cd.cd_devs[unit];
+
+       return(ENXIO);
+}
+
+
+int
+iicioctl(dev, cmd, data, flag, p)
+       dev_t dev;
+       int cmd;
+       caddr_t data;
+       int flag;
+       struct proc *p;
+{
+       struct iic_softc *sc = iic_cd.cd_devs[minor(dev)];
+
+/*
+       switch (cmd) {
+       case IICIOC_CONTROL:
+               if (iiccontrol() != 0) {
+                       return(EIO);
+               }
+               return(0);
+       }
+*/
+
+       return(EINVAL);
+}
+
+/* End of iic.c */
diff --git a/sys/arch/arm32/mainbus/iic_asm.S b/sys/arch/arm32/mainbus/iic_asm.S
new file mode 100644 (file)
index 0000000..10ceb8a
--- /dev/null
@@ -0,0 +1,239 @@
+/* $NetBSD: iic_asm.S,v 1.1 1996/04/19 19:49:04 mark Exp $ */
+
+/*
+ * Copyright (c) 1994-1996 Mark Brinicombe.
+ * Copyright (c) 1994 Brini.
+ * All rights reserved.
+ *
+ * This code is derived from software written for Brini by Mark Brinicombe
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided 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 Mark Brinicombe.
+ * 4. The name of the company nor the name of the author may be used to
+ *    endorse or promote products derived from this software without specific
+ *    prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BRINI ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL BRINI 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.
+ *
+ * RiscBSD kernel project
+ *
+ * iic.s
+ *
+ * Low level routines to with IIC devices
+ *
+ * Created      : 13/10/94
+ *
+ * Based of kate/display/iic.s
+ */
+
+#include <machine/cpu.h>
+#include <machine/iomd.h>
+
+#define IIC_BITDELAY 10
+
+sp     .req    r13
+lr     .req    r14
+pc     .req    r15
+
+.text
+
+       .global _iic_set_state
+
+_iic_set_state:
+/*
+ * Parameters
+ *   r0 - IIC data bit
+ *   r1 - IIC clock bit
+ */
+
+/* Store temporary register */
+/*     stmfd   sp!, {r4}*/
+
+/*
+ * Mask the data and clock bits
+ * Since these routines are only called from iiccontrol.c this is not
+ * really needed
+ */
+       and     r0, r0, #0x00000001
+       and     r1, r1, #0x00000001
+
+/* Get address of IOMD control register */
+
+       mov     r2, #(IOMD_BASE)
+
+/* Get the current CPSR */
+/*     mrs     r4, cpsr_all
+       orr     r3, r4, #(I32_bit | F32_bit)
+       msr     cpsr_all, r3
+*/
+
+       IRQdisable
+/* Get current value of control register */
+
+       ldrb    r3, [r2, #(IOMD_IOCR - IOMD_BASE)]
+
+/* Preserve non-IIC bits */
+
+       bic     r3, r3, #0x00000003
+       orr     r3, r3, #0x000000c0
+
+/* Set the IIC clock and data bits */
+
+       orr     r3, r3, r0
+       orr     r3, r3, r1, lsl #1
+
+/* Store the new value of control register */
+
+       strb    r3, [r2, #(IOMD_IOCR - IOMD_BASE)]
+
+/* Restore CPSR state */
+/*     msr     cpsr_all, r4 */
+
+       IRQenable
+
+/* Restore temporary register */
+/*     ldmfd   sp!, {r4} */
+
+/* Pause a bit */
+
+       mov     r0, #(IIC_BITDELAY)
+
+/* Exit via iic_delay routine */
+       b       _iic_delay
+
+
+       .global _iic_set_state_and_ack
+
+_iic_set_state_and_ack:
+/*
+ * Parameters
+ *  r0 - IIC data bit
+ *  r1 - IIC clock bit
+ */
+/* Store temporary register */
+/*     stmfd   sp!, {r4} */
+
+/*
+ * Mask the data and clock bits
+ * Since these routines are only called from iiccontrol.c this is not
+ * really needed
+ */
+
+       and     r0, r0, #0x00000001
+       and     r1, r1, #0x00000001
+
+/* Get address of IOMD control register */
+
+       mov     r2, #(IOMD_BASE)
+
+/* Get the current CPSR */
+/*     mrs     r4, cpsr_all
+       orr     r3, r4, #(I32_bit | F32_bit)
+       msr     cpsr_all, r3
+*/
+       IRQdisable
+
+/* Get current value of control register */
+
+       ldrb    r3, [r2, #(IOMD_IOCR - IOMD_BASE)]
+
+/* Preserve non-IIC bits */
+
+       bic     r3, r3, #0x00000003
+       orr     r3, r3, #0x000000c0
+
+/* Set the IIC clock and data bits */
+
+       orr     r3, r3, r0
+       orr     r3, r3, r1, lsl #1
+
+/* Store the new value of control register */
+
+       strb    r3, [r2, #(IOMD_IOCR - IOMD_BASE)]
+
+iic_set_state_and_ack_loop:
+       ldrb    r3, [r2, #(IOMD_IOCR - IOMD_BASE)]
+       tst     r3, #0x00000002
+       beq     iic_set_state_and_ack_loop
+
+/* Restore CPSR state */
+/*     msr     cpsr_all, r4 */
+
+       IRQenable
+
+/* Restore temporary register */
+/*     ldmfd   sp!, {r4} */
+
+/* Pause a bit */
+
+       mov     r0, #(IIC_BITDELAY)
+
+/* Exit via iic_delay routine */
+       b       _iic_delay
+
+
+       .global _iic_delay
+
+_iic_delay:
+/*
+ * Parameters
+ *   r0 - time to wait
+ */
+
+/* Load address of IOMD */
+
+       mov     r2, #(IOMD_BASE)
+
+/* Latch current value of timer 1 */
+
+       strb    r2, [r2, #(IOMD_T0LATCH - IOMD_BASE)]
+
+/* Get the latched value */
+
+       ldrb    r1, [r2, #(IOMD_T0LOW - IOMD_BASE)]
+
+/* Loop until timer reaches end value */
+
+iic_delay_loop:
+
+/* Latch the current value of timer1 */
+
+       strb    r2, [r2, #(IOMD_T0LATCH - IOMD_BASE)]
+
+/* Get the latched value */
+
+       ldrb    r3, [r2, #(IOMD_T0LOW - IOMD_BASE)]
+
+/*  Loop until timer reached expected value */
+
+       teq     r3, r1
+       movne   r1, r3
+       beq     iic_delay_loop
+
+       subs    r0, r0, #0x00000001
+       bne     iic_delay_loop
+
+/* Exit */
+       mov     pc, lr
+
+/* End of iic_asm.S */
diff --git a/sys/arch/arm32/mainbus/kbd.c b/sys/arch/arm32/mainbus/kbd.c
new file mode 100644 (file)
index 0000000..3b85bdb
--- /dev/null
@@ -0,0 +1,1357 @@
+/* $NetBSD: kbd.c,v 1.7 1996/03/28 21:55:15 mark Exp $ */
+
+/*
+ * Copyright (c) 1994 Mark Brinicombe.
+ * Copyright (c) 1994 Brini.
+ * All rights reserved.
+ *
+ * This code is derived from software written for Brini by Mark Brinicombe
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided 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 Brini.
+ * 4. The name of the company nor the name of the author may be used to
+ *    endorse or promote products derived from this software without specific
+ *    prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BRINI ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL BRINI 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.
+ *
+ * RiscBSD kernel project
+ *
+ * kbd.c
+ *
+ * Keyboard driver functions
+ *
+ * Created      : 09/10/94
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/conf.h>
+#include <sys/proc.h>
+#include <sys/reboot.h>
+#include <sys/device.h>
+#include <sys/ioctl.h>
+#include <sys/malloc.h>
+#include <sys/tty.h>
+#include <sys/vnode.h>
+#include <sys/select.h>
+#include <sys/fcntl.h>
+#include <sys/signalvar.h>
+#include <sys/time.h>
+
+#include <machine/irqhandler.h>
+#include <machine/iomd.h>
+#include <machine/vidc.h>
+#include <machine/katelib.h>
+#include <machine/kbd.h>
+#include <arm32/mainbus/mainbus.h>
+#include "vt.h"
+#include "kbd.h"
+
+/* Declare global variables */
+
+/* Declare external variables */
+
+/* Local function prototypes */
+
+/* Now for the main code */
+
+/* Define the key_struct structure */
+
+typedef struct {
+       int base_code;  /* Base ASCII code */
+       int shift_code; /* Shifted ASCII code */
+       int ctrl_code;  /* CTRL code */
+       int alt_code;   /* Alt code */
+       int flags;      /* Flags field */
+} key_struct;
+
+/* Define mappings for each possible code */
+
+key_struct keys[256] = {
+/* 0x00 - 0x0f */
+    { 0x00, 0x00, 0x00, 0x00, 0x80 },
+    { 0x89, 0x99, 0x00, 0x489, 0x00 },
+    { 0x8a, 0x9a, 0x00, 0x00, 0x00 },
+    { 0x85, 0x95, 0x00, 0x485, 0x00 },
+    { 0x83, 0x93, 0x00, 0x483, 0x00 },
+    { 0x81, 0x91, 0x00, 0x481, 0x00 },
+    { 0x82, 0x92, 0x00, 0x482, 0x00 },
+    { 0x8c, 0x9c, 0x00, 0x48c, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x88, 0x98, 0x00, 0x488, 0x00 },
+    { 0x86, 0x96, 0x00, 0x486, 0x00 },
+    { 0x84, 0x94, 0x00, 0x484, 0x00 },
+    { 0x09, 0x09, 0x09, 0x09, 0x00 },
+    { 0x60, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+
+/* 0x10 - 0x1f */
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x84 },
+    { 0x00, 0x00, 0x00, 0x00, 0x82 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x81 },
+    { 0x71, 0x51, 0x11, 0x00, 0x40 },
+    { 0x31, 0x21, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x7a, 0x5a, 0x1a, 0x00, 0x40 },
+    { 0x73, 0x53, 0x13, 0x00, 0x40 },
+    { 0x61, 0x41, 0x01, 0x00, 0x40 },
+    { 0x77, 0x57, 0x17, 0x00, 0x40 },
+    { 0x32, 0x22, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+
+/* 0x20 - 0x2f */
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x63, 0x43, 0x03, 0x00, 0x40 },
+    { 0x78, 0x58, 0x18, 0x00, 0x40 },
+    { 0x64, 0x44, 0x04, 0x00, 0x40 },
+    { 0x65, 0x45, 0x05, 0x00, 0x40 },
+    { 0x34, 0x24, 0x00, 0x00, 0x00 },
+    { 0x33, 0x23, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x20, 0x20, 0x20, 0x20, 0x00 },
+    { 0x76, 0x56, 0x16, 0x00, 0x40 },
+    { 0x66, 0x46, 0x06, 0x00, 0x40 },
+    { 0x74, 0x54, 0x14, 0x00, 0x40 },
+    { 0x72, 0x52, 0x12, 0x00, 0x40 },
+    { 0x35, 0x25, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+
+/* 0x30 - 0x3f */
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x6e, 0x4e, 0x0e, 0x00, 0x40 },
+    { 0x62, 0x42, 0x02, 0x00, 0x40 },
+    { 0x68, 0x48, 0x08, 0x00, 0x40 },
+    { 0x67, 0x47, 0x07, 0x00, 0x40 },
+    { 0x79, 0x59, 0x19, 0x00, 0x40 },
+    { 0x36, 0x5e, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x6d, 0x4d, 0x0d, 0x00, 0x40 },
+    { 0x6a, 0x4a, 0x0a, 0x00, 0x40 },
+    { 0x75, 0x55, 0x15, 0x00, 0x40 },
+    { 0x37, 0x26, 0x00, 0x00, 0x00 },
+    { 0x38, 0x2a, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+
+/* 0x40 - 0x4f */
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x2c, 0x3c, 0x00, 0x00, 0x00 },
+    { 0x6b, 0x4b, 0x0b, 0x00, 0x40 },
+    { 0x69, 0x49, 0x09, 0x00, 0x40 },
+    { 0x6f, 0x4f, 0x0f, 0x00, 0x40 },
+    { 0x30, 0x29, 0x00, 0x00, 0x00 },
+    { 0x39, 0x28, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x2e, 0x3e, 0x00, 0x00, 0x00 },
+    { 0x2f, 0x3f, 0x00, 0x00, 0x00 },
+    { 0x6c, 0x4c, 0x0c, 0x00, 0x40 },
+    { 0x3b, 0x3a, 0x00, 0x00, 0x00 },
+    { 0x70, 0x50, 0x10, 0x00, 0x40 },
+    { 0x2d, 0x5f, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+
+/* 0x50 - 0x5f */
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x27, 0x40, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x5b, 0x7b, 0x00, 0x00, 0x00 },
+    { 0x3d, 0x2b, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0xa0 },
+    { 0x00, 0x00, 0x00, 0x00, 0x82 },
+    { 0x0d, 0x0d, 0x0d, 0x00, 0x00 },
+    { 0x5d, 0x7d, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x23, 0x7e, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+
+/* 0x60 - 0x6f */
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x5c, 0x7c, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x08, 0x7f, 0x08, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x31, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x34, 0x00, 0x00, 0x00, 0x00 },
+    { 0x37, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+
+/* 0x70 - 0x7f */
+    { 0x30, 0x00, 0x00, 0x00, 0x00 },
+    { 0x2e, 0x00, 0x00, 0x00, 0x00 },
+    { 0x32, 0x00, 0x00, 0x00, 0x00 },
+    { 0x35, 0x00, 0x00, 0x00, 0x00 },
+    { 0x36, 0x00, 0x00, 0x00, 0x00 },
+    { 0x38, 0x00, 0x00, 0x00, 0x00 },
+    { 0x1b, 0x1b, 0x21b, 0x1b, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x90 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x2b, 0x00, 0x00, 0x22b, 0x00 },
+    { 0x33, 0x00, 0x00, 0x00, 0x00 },
+    { 0x2d, 0x00, 0x00, 0x22d, 0x00 },
+    { 0x2a, 0x00, 0x00, 0x00, 0x00 },
+    { 0x39, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x88 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+
+/* 0x80 - 0x8f */
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x87, 0x97, 0x00, 0x487, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+
+/* 0x90 - 0x9f */
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+
+/* 0xa0 - 0xaf */
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+
+/* 0xb0 - 0xbf */
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+
+/* 0xc0 - 0xcf */
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+
+/* 0xd0 - 0xdf */
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+
+/* 0xe0 - 0xef */
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+
+/* 0xf0 - 0xff */
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 }
+};
+
+/* Define mappings for each possible code */
+
+key_struct E0keys[128] = {
+
+/* 0x00 - 0x0f */
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+
+/* 0x10 - 0x1f */
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x84 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x81 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+
+/* 0x20 - 0x2f */
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+
+/* 0x30 - 0x3f */
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+
+/* 0x40 - 0x4f */
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x2f, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+
+/* 0x50 - 0x5f */
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x0d, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+
+/* 0x60 - 0x6f */
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x10b, 0x00, 0x00, 0x20b, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x102, 0x00, 0x00, 0x202, 0x00 },
+    { 0x10a, 0x00, 0x00, 0x20a, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+
+/* 0x70 - 0x7f */
+    { 0x108, 0x00, 0x00, 0x208, 0x00 },
+    { 0x109, 0x00, 0x00, 0x209, 0x00 },
+    { 0x101, 0x105, 0x00, 0x201, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x103, 0x00, 0x00, 0x203, 0x00 },
+    { 0x100, 0x104, 0x00, 0x200, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x104, 0x100, 0x00, 0x204, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x105, 0x101, 0x00, 0x205, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },
+};
+
+/* Special keycodes */
+
+#define KEYCODE_UP     0x100
+#define KEYCODE_DOWN   0x101
+#define KEYCODE_LEFT   0x102
+#define KEYCODE_RIGHT  0x103
+#define KEYCODE_PGUP   0x104
+#define KEYCODE_PGDN   0x105
+#define KEYCODE_INSERT 0x108
+#define KEYCODE_DELETE 0x109
+#define KEYCODE_HOME   0x10a
+#define KEYCODE_END    0x10b
+
+/* Key modifiers flags */
+
+#define MODIFIER_CTRL   0x01
+#define MODIFIER_SHIFT  0x02
+#define MODIFIER_ALT    0x04
+#define MODIFIER_MASK   0x07
+
+#define MODIFIER_CAPS   0x20
+#define MODIFIER_NUM    0x10
+#define MODIFIER_SCROLL 0x08
+#define MODIFIER_LOCK_MASK   0x38
+
+#define MODIFIER_CAPSLOCK 0x40
+#define MODIFIER_NORETURN 0x80
+
+/* Keyboard buffer variables */
+
+#define BUFFER_SIZE 32
+#define RAWKBD_BSIZE 128
+
+static int autorepeatkey = -1;
+static struct kbd_autorepeat kbdautorepeat = { 5, 20 };
+static int rawkbd_device = 0;
+int modifiers = 0;
+static int kbd_ack = 0;
+static int kbd_resend = 0;
+
+extern int pmap_debug_level;
+
+struct kbd_softc {
+       struct device   sc_device;
+       irqhandler_t    sc_ih;
+
+       int sc_state;
+#define RAWKBD_OPEN    0x01
+#define KBD_OPEN       0x02
+#define RAWKBD_ASLEEP  0x04
+       int             sc_iobase;
+       struct clist    sc_q;
+       struct selinfo  sc_rsel;
+       struct proc     *sc_proc;
+};
+
+#define KBDUNIT(u)     (minor(u) / 2)
+#define KBDFLAG(u)     (minor(u) % 2) 
+
+#define KBDFLAG_RAWUNIT        0
+#define KBDFLAG_CONUNIT        1
+
+int    kbdprobe __P((struct device *, void *, void *));
+void   kbdattach __P((struct device *, struct device *, void *));
+
+int    kbdopen __P((dev_t, int, int, struct proc *));
+int    kbdclose __P((dev_t, int, int, struct proc *));
+int    kbdread __P((dev_t, struct uio *, int));
+int    kbdselect __P((dev_t, int, struct proc *));
+int    kbdioctl __P((dev_t, int, caddr_t, int, struct proc *));
+
+void   kbdinit __P((struct kbd_softc *sc));
+void   kbdsetleds __P((int /*leds*/));
+
+int PollKeyboard __P((int));
+int kbddecodekey __P((struct kbd_softc *, int));
+int kbdintr __P((struct kbd_softc *));
+
+void autorepeatstart __P((void *));
+void autorepeat __P((void *));
+
+struct cfattach kbd_ca = {
+       sizeof(struct kbd_softc), kbdprobe, kbdattach
+};
+
+struct cfdriver        kbd_cd = {
+       NULL, "kbd", DV_TTY
+};
+
+
+int
+kbdprobe(parent, match, aux)
+       struct device *parent;
+       void *match;
+       void *aux;
+{
+/*     struct mainbus_attach_args *mb = aux;*/
+       int id;
+
+/* Make sure we have an IOMD we understand */
+    
+       id = ReadByte(IOMD_ID0) | (ReadByte(IOMD_ID1) << 8);
+
+/* So far I only know about this IOMD */
+
+       switch (id) {
+       case RPC600_IOMD_ID:
+       case RC7500_IOC_ID:
+               return(1);
+               break;
+       default:
+               printf("kbd: Unknown IOMD id=%04x", id);
+               break;
+       }
+
+       return(0);
+}
+
+
+void
+kbdattach(parent, self, aux)
+       struct device *parent;
+       struct device *self;
+       void *aux;
+{
+       struct kbd_softc *sc = (void *)self;
+       struct mainbus_attach_args *mb = aux;
+
+       sc->sc_iobase = mb->mb_iobase;
+
+       kbdinit(sc);
+    
+       printf("\n");
+}
+
+
+int
+kbdopen(dev, flag, mode, p)
+       dev_t dev;
+       int flag;
+       int mode;
+       struct proc *p;
+{
+       struct kbd_softc *sc;
+       int unit = KBDUNIT(dev);
+
+       if (unit >= kbd_cd.cd_ndevs)
+               return(ENXIO);
+
+       sc = kbd_cd.cd_devs[unit];
+
+       if (!sc) return(ENXIO);
+
+       switch (KBDFLAG(dev)) {
+       case KBDFLAG_RAWUNIT :
+               if (sc->sc_state & RAWKBD_OPEN)
+                       return(EBUSY);
+               sc->sc_state |= RAWKBD_OPEN;
+               if (clalloc(&sc->sc_q, RAWKBD_BSIZE, 0) == -1)
+                       return(ENOMEM);
+               sc->sc_proc = p;
+               rawkbd_device = 1;
+               break;
+       case KBDFLAG_CONUNIT :
+               if (sc->sc_state & KBD_OPEN)
+                       return(EBUSY);
+               sc->sc_state |= KBD_OPEN;
+               break;
+       }
+
+/* Kill any active autorepeat */
+
+       untimeout(autorepeatstart, &autorepeatkey);
+       untimeout(autorepeat, &autorepeatkey);
+
+       return(0);
+}
+
+
+int
+kbdclose(dev, flag, mode, p)
+       dev_t dev;
+       int flag;
+       int mode;
+       struct proc *p;
+{
+       int unit = KBDUNIT(dev);
+       struct kbd_softc *sc = kbd_cd.cd_devs[unit];
+
+       switch (KBDFLAG(dev)) {
+       case KBDFLAG_RAWUNIT :
+               if (!(sc->sc_state & RAWKBD_OPEN))
+                       return(EINVAL);
+               sc->sc_state &= ~RAWKBD_OPEN;
+               clfree(&sc->sc_q);
+               sc->sc_proc = NULL;
+               rawkbd_device = 0;
+               break;
+       case KBDFLAG_CONUNIT :
+               if (!(sc->sc_state & KBD_OPEN))
+                       return(EINVAL);
+               sc->sc_state &= ~KBD_OPEN;
+               break;
+       }
+
+       return(0);
+}
+
+
+int
+kbdread(dev, uio, flag)
+       dev_t dev;
+       struct uio *uio;
+       int flag;
+{
+       struct kbd_softc *sc = kbd_cd.cd_devs[KBDUNIT(dev)];
+       int s;
+       int error = 0;
+       size_t length;
+       u_char buffer[128];
+
+       if (KBDFLAG(dev) == KBDFLAG_CONUNIT)
+               return(ENXIO);
+
+       /* Block until keyboard activity occured. */
+
+       s = spltty();
+       while (sc->sc_q.c_cc == 0) {
+               if (flag & IO_NDELAY) {
+                       splx(s);
+                       return EWOULDBLOCK;
+               }
+               sc->sc_state |= RAWKBD_ASLEEP;
+               if ((error = tsleep((caddr_t)sc, PZERO | PCATCH, "kbdread", 0))) {
+                       sc->sc_state &= (~RAWKBD_ASLEEP);
+                       splx(s);
+                       return error;
+               }
+       }
+       splx(s);
+
+       /* Transfer as many chunks as possible. */
+
+       while (sc->sc_q.c_cc > 0 && uio->uio_resid > 0) {
+               length = min(sc->sc_q.c_cc, uio->uio_resid);
+               if (length > sizeof(buffer))
+                       length = sizeof(buffer);
+
+               /* Remove a small chunk from the input queue. */
+               (void) q_to_b(&sc->sc_q, buffer, length);
+
+               /* Copy the data to the user process. */
+               if ((error = (uiomove(buffer, length, uio))))
+                       break;
+       }
+       return error;
+}
+
+int
+kbdselect(dev, rw, p)
+       dev_t dev;
+       int rw;
+       struct proc *p;
+{
+       struct kbd_softc *sc = kbd_cd.cd_devs[KBDUNIT(dev)];
+       int s;
+       int ret;
+
+       if (KBDFLAG(dev) == KBDFLAG_CONUNIT)
+               return(ENXIO);
+
+       if (rw == FWRITE)
+               return 0;
+                        
+       s = spltty();
+       if (!sc->sc_q.c_cc) {
+               selrecord(p, &sc->sc_rsel);
+               ret = 0;
+       } else
+               ret = 1;
+       splx(s);
+       return ret;
+}
+
+
+int
+kbdioctl(dev, cmd, data, flag, p)
+       dev_t dev;
+       int cmd;
+       caddr_t data;
+       int flag;
+       struct proc *p;
+{
+/*     struct kbd_softc *sc = kbd_cd.cd_devs[KBDUNIT(dev)];*/
+       struct kbd_autorepeat *kbdar = (void *)data;
+       int *leds = (int *)data;
+       int s;
+
+       switch (cmd) {
+       case KBD_GETAUTOREPEAT:
+/*             if (KBDFLAG(dev) == KBDFLAG_RAWUNIT)
+                       return(EINVAL);*/
+
+               *kbdar = kbdautorepeat;
+               break;
+       case KBD_SETAUTOREPEAT:
+/*             if (KBDFLAG(dev) == KBDFLAG_RAWUNIT)
+                       return(EINVAL);*/
+               s = spltty();
+               kbdautorepeat = *kbdar;
+               if (kbdautorepeat.ka_rate < 1)
+                       kbdautorepeat.ka_rate = 1;
+               if (kbdautorepeat.ka_rate > 50)
+                       kbdautorepeat.ka_rate = 50;
+               if (kbdautorepeat.ka_delay > 50)
+                       kbdautorepeat.ka_delay = 50;
+               if (kbdautorepeat.ka_delay < 1)
+                       kbdautorepeat.ka_delay = 1;
+               (void)splx(s);
+               break;
+       case KBD_SETLEDS:
+               kbdsetleds(*leds);
+               break;
+       default:
+               return(ENXIO);
+       }
+       return(0);
+}
+
+
+void
+kbdsetleds(leds)
+       int leds;
+{
+       int loop;
+
+       if ((ReadByte(IOMD_KBDCR) & 0x80)) {
+               WriteByte(IOMD_KBDDAT, 0xed);
+               loop = 10000;
+               while ((ReadByte(IOMD_KBDCR) & 0x40) && loop > 0)
+                       --loop;
+               if ((ReadByte(IOMD_KBDCR) & 0x80)) {
+                       WriteByte(IOMD_KBDDAT, leds);
+                       loop = 10000;
+                       while ((ReadByte(IOMD_KBDCR) & 0x40) && loop > 0)
+                               --loop;
+               }
+       }
+}
+
+
+void
+kbdsetstate(state)
+       int state;
+{
+       modifiers = state & MODIFIER_LOCK_MASK;
+}
+
+
+int
+kdbgetstate()
+{
+       return(modifiers);
+}
+
+  
+void
+kbdinit(sc)
+       struct kbd_softc *sc;
+{
+       sc->sc_ih.ih_func = kbdintr;
+       sc->sc_ih.ih_arg = sc;
+       sc->sc_ih.ih_level = IPL_TTY;
+       sc->sc_ih.ih_name = "kbd rx";
+       if (irq_claim(IRQ_KBDRX, &sc->sc_ih))
+               panic("Cannot claim IRQ for kbd%d\n", sc->sc_device.dv_unit);
+
+       modifiers = 0;
+       kbdsetleds((modifiers >> 3) & 7);
+}
+
+
+int
+getkey_polled()
+{
+       int code;
+       int key;
+       int up;
+       key_struct *ks;
+       int s;
+       
+       s = splhigh();
+
+       key = 0;
+
+       do {
+               while ((ReadByte(IOMD_KBDCR) & (1<<5)) == 0) ;
+
+/* Read the IOMD keyboard register and process the key */
+
+               code = PollKeyboard(ReadByte(IOMD_KBDDAT));
+
+               if (code != 0) {
+                       up = (code & 0x100);
+                       key = code & 0xff;
+
+/*                     printf("code=%04x mod=%04x\n", code, modifiers);*/
+
+/* By default we use the main keycode lookup table */
+
+                       ks = keys;
+
+/* If we have an E0 or E1 sqeuence we use the extended table */
+
+                       if (code > 0x1ff)
+                               ks = E0keys;
+
+/* Is the key a temporary modifier ? */
+
+                       if (ks[key].flags & MODIFIER_MASK) {
+                               if (up)
+                                       modifiers &= ~ks[key].flags;
+                               else
+                                       modifiers |= ks[key].flags;
+                               key = 0;
+                               continue;
+                       }
+
+/* Is the key a locking modifier ? */
+
+                       if (ks[key].flags & MODIFIER_LOCK_MASK) {
+                               if (!up) {
+                                       modifiers ^= ks[key].flags;
+                                       kbdsetleds((modifiers >> 3) & 7);
+                               }
+                               key = 0;
+                               continue;
+                       }
+
+/* Lookup the correct key code */
+
+                       if (modifiers & 0x01)
+                               key = ks[key].ctrl_code;
+                       else if (modifiers & 0x02)
+                               key = ks[key].shift_code;
+                       else if (modifiers & 0x04)
+                               key = ks[key].alt_code;
+                       else
+                               key = ks[key].base_code;
+
+                       if (modifiers & MODIFIER_CAPS) {
+                               if ((key >= 'A' && key <= 'Z') || (key >= 'a' && key <= 'z'))
+                                       key ^= 0x20;
+                       }
+
+                       if (up)
+                               key = 0;
+                       if (!up && key >= 0x200) {
+
+#if (NVT > 0)
+                               if ((key & ~0x0f) == 0x480)
+                                       console_switch((key & 0x0f) - 1);
+                               else
+#endif
+                               switch (key) {
+#if (NVT > 0)
+                               case 0x201:
+                                       console_scrollforward();
+                                       break;
+                               case 0x200:
+                                       console_scrollback();
+                                       break;
+#endif
+                               default:
+                                       break;
+                               }
+                               key = 0;
+                       }
+               }
+       } while (key == 0);
+
+       if (key == '\r')
+               key = '\n';
+
+       splx(s);
+       return(key);
+}
+
+
+/* Keyboard IRQ handler */
+
+int
+kbdintr(sc)
+       struct kbd_softc *sc;
+{
+       int key;
+
+/* Read the IOMD keyboard register and process the key */
+
+       key = PollKeyboard(ReadByte(IOMD_KBDDAT));
+
+/* If we have a raw keycode convert it to an ASCII code */
+
+       if (key != 0)
+               kbddecodekey(sc, key);
+       return(1);
+}
+
+
+/* Flags used to decode the raw keys */
+
+#define FLAG_KEYUP     0x01
+#define FLAG_E0                0x02
+#define FLAG_E1                0x04
+
+static int flags = 0;
+
+/*
+ * This function is now misnamed.
+ * It processes the raw key codes from the keyboard and generates
+ * a unique code that can be decoded with the key translation array.
+ */
+
+int
+PollKeyboard(code)
+       int code;
+{
+/*     printf("%02x.", code);*/
+
+/*
+ * Set the keyup flag if this is the release code.
+ */
+
+       if (code == 0xf0) {
+               flags |= FLAG_KEYUP;
+               return(0);
+       }
+
+/* If it is a special code ignore it */
+
+       if (code == 0xff || code == 0x00) {
+               flags = 0;
+               return(0);
+       }
+
+/* If it is a resend code note it down */
+
+       if (code == 0xfe) {
+               printf("kbd:resend\n");
+               kbd_resend = 1;
+               return(0);
+       }
+
+/* If it is an ack code note it down */
+
+       if (code == 0xfa) {
+/*             printf("kbd:ack\n");*/
+               kbd_ack = 1;
+               return(0);
+       }
+
+/* Flag the start of an E0 sequence. */
+
+       if (code == 0xe0) {
+               flags |= FLAG_E0;
+               return(0);
+       }
+
+/* Flag the start of an E1 sequence. */
+
+       if (code == 0xe1) {
+               flags |= FLAG_E1;
+               return(0);
+       }
+
+/* Ignore any other invalid codes */
+
+       if (code > 0x8f) {
+               flags = 0;
+               return(0);
+       }
+
+/*     printf("%02x:%02x.", code, flags);*/
+
+/* Mark the code appropriately if it is part of an E0 sequence */
+
+       if (flags & FLAG_E0) {
+               flags &= ~FLAG_E0;
+               if (code == 0x12) {
+                       flags &= ~FLAG_KEYUP;
+                       return(0);
+               }
+               code |= 0x200;
+       }
+
+/* Mark the key if it is the upcode */
+
+       if (flags & FLAG_KEYUP) {
+               flags &= ~FLAG_KEYUP;
+               code |= 0x100;
+       }
+
+/* Mark the code appropriately if it is part of an E1 sequence */
+
+       if (flags & FLAG_E1) {
+               if ((code & 0xff) == 0x14) {
+                       return(0);
+               }
+               flags &= ~FLAG_E1;
+               code |= 0x400;
+               flags &= ~FLAG_KEYUP;
+       }
+
+       return(code);
+}
+
+
+/*
+ * This routine decodes the unique keycode and generates an ASCII code
+ * if necessary.
+ */
+
+int
+kbddecodekey(sc, code)
+       struct kbd_softc *sc;
+       int code;
+{
+       key_struct *ks;
+       int up;
+       int key;
+
+       console_unblank();
+
+/* Do we have the raw kbd device open ... */
+
+       if (rawkbd_device == 1 && code != 0) {
+               struct kbd_data buffer;
+               int s;
+  
+  /* Add this event to the queue. */
+               buffer.keycode = code;
+               microtime(&buffer.event_time);
+               s=spltty();
+               (void) b_to_q((char *)&buffer, sizeof(buffer), &sc->sc_q);
+               splx(s);
+               selwakeup(&sc->sc_rsel);
+
+               if (sc->sc_state & RAWKBD_ASLEEP) {
+                       sc->sc_state &= ~RAWKBD_ASLEEP;
+                       wakeup((caddr_t)sc);
+               }
+
+               psignal(sc->sc_proc, SIGIO);
+               return(1);
+       }
+
+       up = (code & 0x100);
+       key = code & 0xff;
+
+/* By default we use the main keycode lookup table */
+
+       ks = keys;
+
+/* If we have an E0 or E1 sqeuence we use the extended table */
+
+       if (code > 0x1ff)
+               ks = E0keys;
+
+/* Is the key a temporary modifier ? */
+
+       if (ks[key].flags & MODIFIER_MASK) {
+               if (up)
+                       modifiers &= ~ks[key].flags;
+               else
+                       modifiers |= ks[key].flags;
+               return(0);
+       }
+
+/* Is the key a locking modifier ? */
+
+       if (ks[key].flags & MODIFIER_LOCK_MASK) {
+               if (!up) {
+                       modifiers ^= ks[key].flags;
+                       kbdsetleds((modifiers >> 3) & 7);
+               }
+               return(0);
+       }
+
+/* Lookup the correct key code */
+
+       if (modifiers & 0x01)
+               key = ks[key].ctrl_code;
+       else if (modifiers & 0x02)
+               key = ks[key].shift_code;
+       else if (modifiers & 0x04)
+               key = ks[key].alt_code;
+       else
+               key = ks[key].base_code;
+
+       if (modifiers & MODIFIER_CAPS) {
+               if ((key >= 'A' && key <= 'Z') || (key >= 'a' && key <= 'z'))
+                       key ^= 0x20;
+       }
+
+/* If no valid code the key is not yet mapped so report error */
+
+#ifdef DEBUG_TERM
+/*     if (key == 0) {
+               char err[80];
+
+               sprintf(err, "\n\rUnknown keycode %04x\n\r", code);
+               dprintf(err);
+       }*/
+#endif
+
+/* If we have an ASCII code insert it into the keyboard buffer */
+
+       if (!up && key != 0) {
+               if (key >= 0x200) {
+
+                       untimeout(autorepeatstart, &autorepeatkey);
+                       untimeout(autorepeat, &autorepeatkey);
+                       autorepeatkey = -1;
+#if (NVT > 0)
+                       if ((key & ~0x0f) == 0x480)
+                               console_switch((key & 0x0f) - 1);
+                       else
+#endif
+                               switch (key) {
+                               case 0x22b:
+                                       pmap_debug(pmap_debug_level + 1);
+                                       break;
+                               case 0x22d:
+                                       pmap_debug(pmap_debug_level - 1);
+                                       break;
+#if (NVT > 0)
+                               case 0x201:
+                                       console_scrollforward();
+                                       break;
+                               case 0x200:
+                                       console_scrollback();
+                                       break;
+                               case 0x202:
+                                       console_switchdown();
+                                       break;
+                               case 0x203:
+                                       console_switchup();
+                                       break;
+#endif
+                               case 0x204:
+                                       --kbdautorepeat.ka_rate;
+                                       if (kbdautorepeat.ka_rate < 1)
+                                               kbdautorepeat.ka_rate = 1;
+                                       break;
+                               case 0x205:
+                                       ++kbdautorepeat.ka_rate;
+                                       if (kbdautorepeat.ka_rate > 50)
+                                               kbdautorepeat.ka_rate = 50;
+                                       break;
+                               case 0x20a:
+                                       ++kbdautorepeat.ka_delay;
+                                       if (kbdautorepeat.ka_delay > 50)
+                                               kbdautorepeat.ka_delay = 50;
+                                       break;
+                               case 0x20b:
+                                       --kbdautorepeat.ka_delay;
+                                       if (kbdautorepeat.ka_delay < 1)
+                                               kbdautorepeat.ka_delay = 1;
+                                       break;
+#ifdef DDB
+                               case 0x208:
+                                       Debugger();
+                                       break;
+#endif
+                               case 0x21b:
+                                       printf("Kernel interruption\n");
+                                       boot(RB_HALT);
+                                       break;
+                               case 0x209:
+                                       printf("Kernel interruption - nosync\n");
+                                       boot(RB_NOSYNC | RB_HALT);
+                                       break;
+       
+                               default:
+                                       printf("Special key %04x\n", key);
+                                       break;
+                               }
+               } else {
+                       if (physconkbd(key) == 0 && rawkbd_device == 0) {
+                               if (autorepeatkey != key) {
+                                       untimeout(autorepeatstart, &autorepeatkey);
+                                       untimeout(autorepeat, &autorepeatkey);
+                                       autorepeatkey = key;
+                                       timeout(autorepeatstart, &autorepeatkey, hz/kbdautorepeat.ka_delay);
+                               }
+                       }
+
+                       return(1);
+               }
+       } else {
+               untimeout(autorepeatstart, &autorepeatkey);
+               untimeout(autorepeat, &autorepeatkey);
+               autorepeatkey = -1;
+       }
+       return(0);
+}
+
+
+void
+autorepeatstart(key)
+       void    *key;
+{
+       physconkbd(*((int *)key));
+       timeout(autorepeat, key, hz/kbdautorepeat.ka_rate);
+}
+
+
+void
+autorepeat(key)
+       void    *key;
+{
+       physconkbd(*((int *)key));
+       timeout(autorepeat, key, hz/kbdautorepeat.ka_rate);
+}
+
+/* End of kbd.c */
diff --git a/sys/arch/arm32/mainbus/lpt.c b/sys/arch/arm32/mainbus/lpt.c
new file mode 100644 (file)
index 0000000..35ff77c
--- /dev/null
@@ -0,0 +1,1314 @@
+/* $NetBSD: lpt.c,v 1.6 1996/03/28 21:52:47 mark Exp $ */
+
+/*
+ * Copyright (c) 1995 Mark Brinicombe
+ * 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.
+ *
+ *     from:$NetBSD: lpt.c,v 1.6 1996/03/28 21:52:47 mark Exp $
+ */
+
+/*
+ * Device Driver for AT parallel printer port
+ */
+/*
+ * PLIP driver code added by Mark Brinicombe
+ */
+
+#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>
+
+#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>
+#include "bpfilter.h"
+#if NBPFILTER > 0
+#include <sys/time.h>
+#include <net/bpf.h>
+#endif
+#endif
+
+#include <machine/cpu.h>
+#include <machine/katelib.h>
+#include <machine/irqhandler.h>
+#include <machine/io.h>
+#include <arm32/mainbus/lptreg.h>
+#include <arm32/mainbus/mainbus.h>
+
+#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      100
+#endif
+#ifndef PLIPMXRETRY
+#define PLIPMXRETRY     10      /* Max number of retransmits */
+#endif
+#ifndef PLIPRETRY
+#define PLIPRETRY       hz/10   /* Time between retransmits */
+#endif
+#endif
+
+#if !defined(DEBUG) || !defined(notdef)
+#define lprintf
+#else
+#define lprintf                if (lptdebug) printf
+int lptdebug = 1;
+#endif
+
+struct lpt_softc {
+       struct device sc_dev;
+       irqhandler_t sc_ih;
+
+       size_t sc_count;
+       struct buf *sc_inbuf;
+       u_char *sc_cp;
+       int sc_spinmax;
+       int sc_iobase;
+       int sc_irq;
+       u_char sc_state;
+#define        LPT_OPEN        0x01    /* device is open */
+#define        LPT_OBUSY       0x02    /* printer is busy doing output */
+#define        LPT_INIT        0x04    /* waiting to initialize for open */
+#define LPT_PLIP       0x08    /* busy with PLIP */
+       u_char sc_flags;
+#define        LPT_AUTOLF      0x20    /* automatic LF on CR */
+#define        LPT_NOPRIME     0x40    /* don't prime on open */
+#define        LPT_NOINTR      0x80    /* do not use interrupt */
+       u_char sc_control;
+       u_char sc_laststatus;
+#if defined(INET) && defined(PLIP)
+       struct arpcom   sc_arpcom;
+       u_char          *sc_ifbuf;
+       int             sc_iferrs;
+       int             sc_ifretry;
+#if defined(COMPAT_PLIP10)
+       u_char          sc_adrcksum;
+#endif
+#endif
+};
+
+int lptprobe __P((struct device *, void *, void *));
+void lptattach __P((struct device *, struct device *, void *));
+int lptintr __P((void *));
+
+#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 plipstart(struct ifnet *);
+static int plipintr(struct lpt_softc *);
+#endif
+
+struct cfattach lpt_ca = {
+       sizeof(struct lpt_softc), lptprobe, lptattach
+};
+
+struct cfdriver lpt_cd = {
+       NULL, "lpt", DV_TTY
+};
+
+#define        LPTUNIT(s)      (minor(s) & 0x1f)
+#define        LPTFLAGS(s)     (minor(s) & 0xe0)
+
+#define        LPS_INVERT      (LPS_SELECT|LPS_NERR|LPS_NBSY|LPS_NACK)
+#define        LPS_MASK        (LPS_SELECT|LPS_NERR|LPS_NBSY|LPS_NACK|LPS_NOPAPER)
+#define        NOT_READY()     ((inb(iobase + lpt_status) ^ LPS_INVERT) & LPS_MASK)
+#define        NOT_READY_ERR() not_ready(inb(iobase + lpt_status), sc)
+static int not_ready __P((u_char, struct lpt_softc *));
+
+static void lptwakeup __P((void *arg));
+static int pushbytes __P((struct lpt_softc *));
+
+/*
+ * Internal routine to lptprobe to do port tests of one byte value.
+ */
+int
+lpt_port_test(port, data, mask)
+       int port;
+       u_char data, mask;
+{
+       int timeout;
+       u_char temp;
+
+       data &= mask;
+       outb(port, data);
+       timeout = 1000;
+       do {
+               delay(10);
+               temp = inb(port) & mask;
+       } while (temp != data && --timeout);
+       lprintf("lpt: port=0x%x out=0x%x in=0x%x timeout=%d\n", port, data,
+           temp, timeout);
+       return (temp == data);
+}
+
+/*
+ * Logic:
+ *     1) You should be able to write to and read back the same value
+ *        to the data port.  Do an alternating zeros, alternating ones,
+ *        walking zero, and walking one test to check for stuck bits.
+ *
+ *     2) You should be able to write to and read back the same value
+ *        to the control port lower 5 bits, the upper 3 bits are reserved
+ *        per the IBM PC technical reference manauls and different boards
+ *        do different things with them.  Do an alternating zeros, alternating
+ *        ones, walking zero, and walking one test to check for stuck bits.
+ *
+ *        Some printers drag the strobe line down when the are powered off
+ *        so this bit has been masked out of the control port test.
+ *
+ *        XXX Some printers may not like a fast pulse on init or strobe, I
+ *        don't know at this point, if that becomes a problem these bits
+ *        should be turned off in the mask byte for the control port test.
+ *
+ *     3) Set the data and control ports to a value of 0
+ */
+int
+lptprobe(parent, match, aux)
+       struct device *parent;
+       void *match, *aux;
+{
+       struct mainbus_attach_args *mb = aux;
+       int iobase = mb->mb_iobase;
+       int port;
+       u_char mask, data;
+       int i;
+
+#ifdef DEBUG
+#define        ABORT   do {printf("lptprobe: mask %x data %x failed\n", mask, data); \
+                   return 0;} while (0)
+#else
+#define        ABORT   return 0
+#endif
+
+       port = iobase + lpt_data;
+       mask = 0xff;
+
+       data = 0x55;                            /* Alternating zeros */
+       if (!lpt_port_test(port, data, mask))
+               ABORT;
+
+       data = 0xaa;                            /* Alternating ones */
+       if (!lpt_port_test(port, data, mask))
+               ABORT;
+
+       for (i = 0; i < CHAR_BIT; i++) {        /* Walking zero */
+               data = ~(1 << i);
+               if (!lpt_port_test(port, data, mask))
+                       ABORT;
+       }
+
+       for (i = 0; i < CHAR_BIT; i++) {        /* Walking one */
+               data = (1 << i);
+               if (!lpt_port_test(port, data, mask))
+                       ABORT;
+       }
+
+       outb(iobase + lpt_data, 0);
+       outb(iobase + lpt_control, 0);
+
+       mb->mb_iosize = LPT_NPORTS;
+       return 1;
+}
+
+void
+lptattach(parent, self, aux)
+       struct device *parent, *self;
+       void *aux;
+{
+       struct lpt_softc *sc = (void *)self;
+       struct mainbus_attach_args *mb = aux;
+       int iobase = mb->mb_iobase;
+
+       if (mb->mb_irq != IRQUNK)
+               printf("\n");
+       else
+               printf(": polled\n");
+
+       sc->sc_iobase = iobase;
+       sc->sc_irq = mb->mb_irq;
+       sc->sc_state = 0;
+       outb(iobase + lpt_control, LPC_NINIT);
+
+       if (mb->mb_irq != IRQUNK) {
+               sc->sc_ih.ih_func = lptintr;
+               sc->sc_ih.ih_arg = sc;
+#if defined(INET) && defined(PLIP)
+               sc->sc_ih.ih_level = IPL_NET;
+               sc->sc_ih.ih_name = "lpt/plip";
+               plipattach(sc, self->dv_unit);
+#else
+               sc->sc_ih.ih_level = IPL_NONE;
+               sc->sc_ih.ih_name = "lpt";
+#endif
+               if (irq_claim(mb->mb_irq, &sc->sc_ih))
+                       panic("Cannot claim IRQ %d for lpt%d\n", mb->mb_irq, sc->sc_dev.dv_unit);
+
+       }
+#if defined(INET) && defined(PLIP)
+       else {
+               printf("Warning PLIP device needs IRQ driven lpt driver\n");
+       }
+#endif
+}
+
+/*
+ * Reset the printer, then wait until it's selected and not busy.
+ */
+int
+lptopen(dev, flag)
+       dev_t dev;
+       int flag;
+{
+       int unit = LPTUNIT(dev);
+       u_char flags = LPTFLAGS(dev);
+       struct lpt_softc *sc;
+       int iobase;
+       u_char control;
+       int error;
+       int spin;
+
+       if (unit >= lpt_cd.cd_ndevs)
+               return ENXIO;
+       sc = lpt_cd.cd_devs[unit];
+       if (!sc)
+               return ENXIO;
+
+       if (sc->sc_irq == IRQUNK && (flags & LPT_NOINTR) == 0)
+               return ENXIO;
+
+#ifdef DIAGNOSTIC
+       if (sc->sc_state)
+               printf("%s: stat=0x%x not zero\n", sc->sc_dev.dv_xname,
+                   sc->sc_state);
+#endif
+
+       if (sc->sc_state)
+               return EBUSY;
+
+       sc->sc_state = LPT_INIT;
+       sc->sc_flags = flags;
+       lprintf("%s: open: flags=0x%x\n", sc->sc_dev.dv_xname, flags);
+       iobase = sc->sc_iobase;
+
+       if ((flags & LPT_NOPRIME) == 0) {
+               /* assert INIT for 100 usec to start up printer */
+               outb(iobase + lpt_control, LPC_SELECT);
+               delay(100);
+       }
+
+       control = LPC_SELECT | LPC_NINIT;
+       outb(iobase + lpt_control, control);
+
+       /* wait till ready (printer running diagnostics) */
+       for (spin = 0; NOT_READY_ERR(); 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;
+               }
+       }
+
+       if ((flags & LPT_NOINTR) == 0)
+               control |= LPC_IENABLE;
+       if (flags & LPT_AUTOLF)
+               control |= LPC_AUTOLF;
+       sc->sc_control = control;
+       outb(iobase + lpt_control, control);
+
+       sc->sc_inbuf = geteblk(LPT_BSIZE);
+       sc->sc_count = 0;
+       sc->sc_state = LPT_OPEN;
+
+       if ((sc->sc_flags & LPT_NOINTR) == 0)
+               lptwakeup(sc);
+
+       lprintf("%s: opened\n", sc->sc_dev.dv_xname);
+       return 0;
+}
+
+int
+not_ready(status, sc)
+       u_char status;
+       struct lpt_softc *sc;
+{
+       u_char new;
+
+       status = (status ^ LPS_INVERT) & LPS_MASK;
+       new = status & ~sc->sc_laststatus;
+       sc->sc_laststatus = status;
+
+       if (new & LPS_SELECT)
+               log(LOG_NOTICE, "%s: offline\n", sc->sc_dev.dv_xname);
+       else if (new & LPS_NOPAPER)
+               log(LOG_NOTICE, "%s: out of paper\n", sc->sc_dev.dv_xname);
+       else if (new & LPS_NERR)
+               log(LOG_NOTICE, "%s: output error\n", sc->sc_dev.dv_xname);
+
+       return status;
+}
+
+
+void
+lptwakeup(arg)
+       void *arg;
+{
+       struct lpt_softc *sc = arg;
+       int s;
+
+       s = spltty();
+       lptintr(sc);
+       splx(s);
+
+       timeout(lptwakeup, sc, STEP);
+}
+
+/*
+ * Close the device, and free the local line buffer.
+ */
+lptclose(dev, flag)
+       dev_t dev;
+       int flag;
+{
+       int unit = LPTUNIT(dev);
+       struct lpt_softc *sc = lpt_cd.cd_devs[unit];
+       int iobase = sc->sc_iobase;
+
+       if (sc->sc_count)
+               (void) pushbytes(sc);
+
+       if ((sc->sc_flags & LPT_NOINTR) == 0)
+               untimeout(lptwakeup, sc);
+
+       outb(iobase + lpt_control, LPC_NINIT);
+       sc->sc_state = 0;
+       outb(iobase + lpt_control, LPC_NINIT);
+       brelse(sc->sc_inbuf);
+
+       lprintf("%s: closed\n", sc->sc_dev.dv_xname);
+       return 0;
+}
+
+int
+pushbytes(sc)
+       struct lpt_softc *sc;
+{
+       int iobase = sc->sc_iobase;
+       int error;
+
+       if (sc->sc_flags & LPT_NOINTR) {
+               int spin, tic;
+               u_char control = sc->sc_control;
+
+               while (sc->sc_count > 0) {
+                       spin = 0;
+                       while (NOT_READY()) {
+                               if (++spin < sc->sc_spinmax)
+                                       continue;
+                               tic = 0;
+                               /* adapt busy-wait algorithm */
+                               sc->sc_spinmax++;
+                               while (NOT_READY_ERR()) {
+                                       /* exponential backoff */
+                                       tic = tic + tic + 1;
+                                       if (tic > TIMEOUT)
+                                               tic = TIMEOUT;
+                                       error = tsleep((caddr_t)sc,
+                                           LPTPRI | PCATCH, "lptpsh", tic);
+                                       if (error != EWOULDBLOCK)
+                                               return error;
+                               }
+                               break;
+                       }
+
+                       outb(iobase + lpt_data, *sc->sc_cp++);
+                       outb(iobase + lpt_control, control | LPC_STROBE);
+                       sc->sc_count--;
+                       outb(iobase + lpt_control, control);
+
+                       /* adapt busy-wait algorithm */
+                       if (spin*2 + 16 < sc->sc_spinmax)
+                               sc->sc_spinmax--;
+               }
+       } else {
+               int s;
+
+               while (sc->sc_count > 0) {
+                       /* if the printer is ready for a char, give it one */
+                       if ((sc->sc_state & LPT_OBUSY) == 0) {
+                               lprintf("%s: write %d\n", sc->sc_dev.dv_xname,
+                                   sc->sc_count);
+                               s = spltty();
+                               (void) lptintr(sc);
+                               splx(s);
+                       }
+                       if (error = tsleep((caddr_t)sc, LPTPRI | PCATCH,
+                           "lptwrite2", 0))
+                               return error;
+               }
+       }
+       return 0;
+}
+
+/* 
+ * Copy a line from user space to a local buffer, then call putc to get the
+ * chars moved to the output queue.
+ */
+lptwrite(dev, uio)
+       dev_t dev;
+       struct uio *uio;
+{
+       struct lpt_softc *sc = lpt_cd.cd_devs[LPTUNIT(dev)];
+       size_t n;
+       int error = 0;
+
+       while (n = min(LPT_BSIZE, uio->uio_resid)) {
+               uiomove(sc->sc_cp = sc->sc_inbuf->b_data, 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.
+ */
+int
+lptintr(arg)
+       void *arg;
+{
+       struct lpt_softc *sc = arg;
+       int iobase = sc->sc_iobase;
+
+/*printf("lptintr:\n");*/
+
+#if defined(INET) && defined(PLIP)
+       if (sc->sc_arpcom.ac_if.if_flags & IFF_UP) {
+               return(plipintr(sc));
+       }
+#endif
+
+#if 0
+       if ((sc->sc_state & LPT_OPEN) == 0)
+               return 0;
+#endif
+
+       /* is printer online and ready for output */
+       if (NOT_READY() && NOT_READY_ERR())
+               return 0;
+
+       if (sc->sc_count) {
+               u_char control = sc->sc_control;
+               /* send char */
+               outb(iobase + lpt_data, *sc->sc_cp++);
+               outb(iobase + lpt_control, control | LPC_STROBE);
+               sc->sc_count--;
+               outb(iobase + lpt_control, control);
+               sc->sc_state |= LPT_OBUSY;
+       } else
+               sc->sc_state &= ~LPT_OBUSY;
+
+       if (sc->sc_count == 0) {
+               /* none, wake up the top half to get more */
+               wakeup((caddr_t)sc);
+       }
+
+       return(1);
+}
+
+int
+lptioctl(dev, cmd, data, flag)
+       dev_t dev;
+       u_long cmd;
+       caddr_t data;
+       int flag;
+{
+       int error = 0;
+
+       switch (cmd) {
+       default:
+               error = ENODEV;
+       }
+
+       return error;
+}
+
+
+#if defined(INET) && defined(PLIP)
+
+#define PLIP_INTR_ENABLE       (LPC_NINIT | LPC_SELECT | LPC_IENABLE)
+#define PLIP_INTR_DISABLE      (LPC_NINIT | LPC_SELECT)
+#define PLIP_DATA              (iobase + lpt_data)
+#define PLIP_STATUS            (iobase + lpt_status)
+#define PLIP_CONTROL           (iobase + lpt_control)
+#define PLIP_REMOTE_TRIGGER    0x08
+#define PLIP_DELAY_UNIT                50
+#if PLIP_DELAY_UNIT > 0        
+#define PLIP_DELAY             DELAY(PLIP_DELAY_UNIT)
+#else
+#define PLIP_DELAY
+#endif
+#define PLIP_DEBUG_RX  0x01
+#define PLIP_DEBUG_TX  0x02
+#define PLIP_DEBUG_IF  0x04
+#define PLIP_DEBUG     0x07
+#if PLIP_DEBUG != 0
+static int plip_debug = PLIP_DEBUG;
+#endif
+
+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;
+
+       if_attach(ifp);
+       ether_ifattach(ifp);
+
+       printf("plip%d at lpt%d: mtu=%d,%d,%d", unit, unit, (int) ifp->if_mtu,
+           ifp->if_hdrlen, ifp->if_addrlen);
+       if (sizeof(struct ether_header) != 14)
+               printf(" ethhdr super kludge mode enabled\n");
+       else
+               printf("\n");
+
+#if NBPFILTER > 0
+       bpfattach(&ifp->if_bpf, ifp, DLT_EN10MB, sizeof(struct ether_header));
+#endif                 
+}
+
+/*
+ * 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 *) lpt_cd.cd_devs[ifp->if_unit];
+       unsigned int iobase = sc->sc_iobase;
+       struct ifaddr *ifa = (struct ifaddr *)data;
+       struct ifreq *ifr = (struct ifreq *)data; 
+       int s;
+       int error = 0;
+
+#if PLIP_DEBUG > 0
+       printf("plipioctl: cmd=%08x ifp=%08x data=%08x\n", cmd, ifp, data);
+       printf("plipioctl: ifp->flags=%08x\n", ifp->if_flags);
+#endif
+
+       switch (cmd) {
+
+       case SIOCSIFFLAGS:
+               if (((ifp->if_flags & IFF_UP) == 0) &&
+                   (ifp->if_flags & IFF_RUNNING)) {
+                       ifp->if_flags &= ~IFF_RUNNING;
+/* Deactive the parallel port */
+#if PLIP_DEBUG != 0
+                       if (plip_debug & PLIP_DEBUG_IF)
+                               printf("plip: Disabling lpt irqs\n");
+#endif
+                       outb(PLIP_DATA, 0x00);
+                       outb(PLIP_CONTROL, PLIP_INTR_DISABLE);
+                       sc->sc_state = 0;
+                                
+                       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 (!(ifp->if_flags & IFF_DEBUG))
+                               plip_debug = PLIP_DEBUG;
+                       else
+                               plip_debug = 0;*/
+                       sc->sc_state = LPT_OPEN | LPT_PLIP;
+                       if (!sc->sc_ifbuf)
+                               sc->sc_ifbuf =
+                                       malloc(ifp->if_mtu + ifp->if_hdrlen,
+                                              M_DEVBUF, M_WAITOK);
+                       ifp->if_flags |= IFF_RUNNING;
+/* This starts it running */
+/* Enable lpt interrupts */
+
+#if PLIP_DEBUG != 0
+                       if (plip_debug & PLIP_DEBUG_IF)
+                               printf("plip: Enabling lpt irqs\n");
+#endif
+                       outb(PLIP_CONTROL, PLIP_INTR_ENABLE);
+                       outb(PLIP_DATA, 0x00);
+               }
+               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
+/* Looks the same as the start condition above */
+/* Enable lpt interrupts */
+
+#if PLIP_DEBUG != 0
+                       if (plip_debug & PLIP_DEBUG_IF)
+                               printf("plip: Enabling lpt irqs\n");
+#endif
+                       outb(PLIP_CONTROL, PLIP_INTR_ENABLE);
+                       outb(PLIP_DATA, 0x00);
+
+                       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 int
+plipreceive(unsigned int iobase, u_char *buf, int len)
+{
+       int i;
+       u_char cksum = 0, c;
+       u_char c0, c1;
+
+#if PLIP_DEBUG != 0
+       if (plip_debug & PLIP_DEBUG_RX)
+               printf("Rx: ");
+#endif
+
+       while (len--) {
+               i = PLIPMXSPIN2;
+/* Receive a byte */
+
+/* Wait for a steady handshake */
+               while (1) {
+                       c0 = inb(PLIP_STATUS);
+                       if ((c0 & LPS_NBSY) == 0) {
+                               c1 = inb(PLIP_STATUS);
+                               if (c0 == c1) break;
+#if PLIP_DEBUG != 0
+                               if (plip_debug & PLIP_DEBUG_RX)
+                                       printf("rx: %02x-%02x ", c0, c1);
+#endif
+                       }
+                       --i;
+                       if (i < 0) {
+#if PLIP_DEBUG > 0
+                               printf("timeout rx lsn %02x\n", c0);
+#endif
+                               return(-1);
+                       }
+                       PLIP_DELAY;
+               }
+               c = (c0 >> 3) & 0x0f;
+
+/* Acknowledge */
+               outb(PLIP_DATA, 0x10);
+
+/* Another handshake */                
+               i = PLIPMXSPIN2;
+               while (1) {
+                       c0 = inb(PLIP_STATUS);
+                       if (c0 & LPS_NBSY) {
+                               c1 = inb(PLIP_STATUS);
+                               if (c0 == c1) break;
+#if PLIP_DEBUG != 0
+                               if (plip_debug & PLIP_DEBUG_RX)
+                                       printf("rx: %02x-%02x ", c0, c1);
+#endif
+                       }
+                       --i;
+                       if (i < 0) {
+#if PLIP_DEBUG > 0
+                               printf("timeout rx msn %02x\n", c0);
+#endif
+                               return(-1);
+                       }
+                       PLIP_DELAY;
+               }
+               c = c | ((c0 << 1) & 0xf0);
+/* Acknowledge */
+               outb(PLIP_DATA, 0x00);
+#if PLIP_DEBUG != 0
+               if (plip_debug & PLIP_DEBUG_RX)
+                       printf("%02x ", c);
+#endif
+
+               cksum += (*buf++ = c);
+       }
+#if PLIP_DEBUG != 0
+       if (plip_debug & PLIP_DEBUG_RX)
+               printf("\n");
+#endif
+       return(cksum);
+}
+
+static int
+plipintr(struct lpt_softc *sc)
+{
+       extern struct mbuf *m_devget(char *, int, int, struct ifnet *, void (*)());
+       struct ifnet *ifp = &sc->sc_arpcom.ac_if;
+       unsigned int iobase = sc->sc_iobase;
+       struct mbuf *m;
+       struct ether_header *eh;
+       u_char *p = sc->sc_ifbuf, minibuf[4];
+       int c, s, len, cksum;
+       u_char c0;
+
+printf("plipintr:\n");
+
+/* Get the status */
+
+       c0 = inb(PLIP_STATUS);
+#if PLIP_DEBUG > 0
+       if ((c0 & 0xf8) != 0xc0) {
+               printf("st5=%02x ", c0);
+       }
+#endif
+
+/* Don't want ints while receiving */
+
+       outb(PLIP_CONTROL, PLIP_INTR_DISABLE);
+
+       outb(PLIP_DATA, 0x01);   /* send ACK */ /* via NERR */
+                                              
+#if defined(COMPAT_PLIP10)
+       if (ifp->if_flags & IFF_LINK0) {
+               if (plipreceive(iobase, 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(iobase, p, 1)) < 0) goto err;
+                       p += 6;
+                       if ((c = plipreceive(iobase, 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(iobase, p, len)) < 0) goto err;
+                       break;
+               default:
+                       goto err;
+               }
+       } else
+#endif
+       {
+               if (plipreceive(iobase, 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 PLIP_DEBUG != 0
+               if (plip_debug & PLIP_DEBUG_RX)
+                       printf("len=%d ", len);
+#endif
+                       if (sizeof(struct ether_header) != 14) {
+                       if ((cksum = plipreceive(iobase, p, 14)) < 0) goto err;
+                       if ((c = plipreceive(iobase, p+16, len-14)) < 0) goto err;
+                       cksum += c;
+                       len += 2;
+               }
+               else
+                       if ((cksum = plipreceive(iobase, p, len)) < 0) goto err;
+       }
+       
+       if (plipreceive(iobase, minibuf, 1) < 0) goto err;
+       if ((cksum & 0xff) != minibuf[0]) {
+               printf("cksum=%d, %d, %d\n", cksum, c, minibuf[0]);
+               log(LOG_NOTICE, "plip%d: checksum error\n", ifp->if_unit);
+               goto err;
+       } 
+
+       outb(PLIP_DATA, 0x00);   /* clear ACK */ /* via NERR */
+#if PLIP_DEBUG != 0
+       if (plip_debug & PLIP_DEBUG_RX)
+               printf("done\n");
+#endif
+       s = splimp();
+       
+       eh = (struct ether_header *)sc->sc_ifbuf;
+
+       if ((m = m_devget(sc->sc_ifbuf + sizeof(struct ether_header), len - sizeof(struct ether_header), 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);*/
+/*             printf("m->m_data=%08x ifbuf=%08x eh=%08x\n", m->m_data, sc->sc_ifbuf, eh);*/
+
+#if NBPFILTER > 0
+/*
+ * Check if there's a BPF listener on this interface.
+ * If so, hand off the raw packet to bpf.
+ */
+               if (sc->sc_arpcom.ac_if.if_bpf) {
+                       bpf_mtap(sc->sc_arpcom.ac_if.if_bpf, m);
+               }
+#endif
+               ether_input(ifp, eh, m);
+       }
+       splx(s);
+       sc->sc_iferrs = 0;
+       ifp->if_ipackets++;
+
+/* Allow ints again */
+
+       outb(PLIP_CONTROL, PLIP_INTR_ENABLE);
+       return(1);
+
+err:
+       outb(PLIP_DATA, 0x00);   /* clear ACK */ /* via NERR */
+
+       ifp->if_ierrors++;
+       sc->sc_iferrs++;
+       if (sc->sc_iferrs > PLIPMXERRS
+           || (sc->sc_iferrs > 5 && (inb(iobase + lpt_status) & LPS_NBSY))) {
+               /* We are not able to send receive anything for now,
+                * so stop wasting our time and leave the interrupt
+                * disabled.
+                */
+               if (sc->sc_iferrs == PLIPMXERRS + 1)
+                       log(LOG_NOTICE, "plip%d: rx hard error\n", ifp->if_unit);
+/*     xxx     i8255->port_a |= LPA_ACTIVE;*/
+       } else
+;
+/*     xxx     i8255->port_a |= LPA_ACKENABLE | LPA_ACTIVE;*/
+
+/* Allow ints again */
+
+       outb(PLIP_CONTROL, PLIP_INTR_ENABLE);
+       return(1);
+}
+
+static int
+pliptransmit(unsigned int iobase, u_char *buf, int len)
+{
+       int i;
+       u_char cksum = 0, c;
+       u_char c0;
+#if PLIP_DEBUG != 0
+       if (plip_debug & PLIP_DEBUG_TX)
+               printf("tx: len=%d ", len);
+#endif
+
+       while (len--) {
+               i = PLIPMXSPIN2;
+               cksum += (c = *buf++);
+#if PLIP_DEBUG != 0
+               if (plip_debug & PLIP_DEBUG_TX)
+                       printf("%02x ", c);
+#endif
+/*     xxx     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;
+*/
+
+/* Send the nibble + handshake */
+
+               outb(PLIP_DATA, 0x00 | (c & 0x0f));
+               outb(PLIP_DATA, 0x10 | (c & 0x0f));
+
+               while (1) {
+                       c0 = inb(PLIP_STATUS);
+                       if ((c0 & LPS_NBSY) == 0)
+                               break;
+                       if (--i == 0) { /* time out */
+#if PLIP_DEBUG > 0
+                               printf("timeout tx lsn %02x ", c0);
+#endif
+                               return(-1);
+                       }
+                       PLIP_DELAY;
+               }
+
+               outb(PLIP_DATA, 0x10 | (c >> 4));
+               outb(PLIP_DATA, 0x00 | (c >> 4));
+               i = PLIPMXSPIN2;
+               while (1) {
+                       c0 = inb(PLIP_STATUS);
+                       if ((c0 & LPS_NBSY) != 0)
+                               break;
+                       if (--i == 0) { /* time out */
+#if PLIP_DEBUG > 0
+                               printf("timeout tx msn %02x ", c0);
+#endif
+                               return(-1);
+                       }
+                       PLIP_DELAY;
+               }
+       }
+#if PLIP_DEBUG != 0
+       if (plip_debug & PLIP_DEBUG_TX)
+               printf("done\n");
+#endif
+       return(cksum);
+}
+
+/*
+ * Setup output on interface.
+ */
+static void
+plipstart(struct ifnet *ifp)
+{
+       struct lpt_softc *sc = (struct lpt_softc *) lpt_cd.cd_devs[ifp->if_unit];
+       unsigned int iobase = sc->sc_iobase;
+       struct mbuf *m0, *m;
+       u_char minibuf[4], cksum;
+       int len, i, s;
+       u_char *p;
+
+#if PLIP_DEBUG != 0
+       if (plip_debug & PLIP_DEBUG_TX)
+               printf("plipstart: ");
+#endif
+       if (ifp->if_flags & IFF_OACTIVE)
+               return;
+       ifp->if_flags |= IFF_OACTIVE;
+
+       if (sc->sc_ifretry)
+               untimeout((void (*)(void *))plipstart, ifp);
+
+       for (;;) {
+               s = splimp();
+               IF_DEQUEUE(&ifp->if_snd, m0);
+               splx(s);
+               if (!m0)
+                       break;
+
+               for (len = 0, m = m0; m; m = m->m_next) {
+#if PLIP_DEBUG > 0
+                       if (plip_debug & PLIP_DEBUG_TX)
+                               printf("len=%d %d\n", m->m_len, len);
+#endif
+                       len += m->m_len;
+               }
+#if NBPFILTER > 0
+               p = sc->sc_ifbuf;
+               for (m = m0; m; m = m->m_next) {
+                       if (m->m_len == 0)
+                               continue;
+                       bcopy(mtod(m, u_char *), p, m->m_len);
+                       p += m->m_len;
+               }
+               if (sc->sc_arpcom.ac_if.if_bpf)
+                       bpf_tap(sc->sc_arpcom.ac_if.if_bpf, sc->sc_ifbuf, len);
+#endif
+                       if (sizeof(struct ether_header) != 14)
+                       len -= 2;
+#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;
+               }
+
+/*yyy          for (i = PLIPMXSPIN1; (inb(PLIP_STATUS) & LPS_NERR) != 0; i--)
+                       if (i < 0) goto retry;*/
+
+               /* Trigger remote interrupt */
+
+#if PLIP_DEBUG > 0
+               if (plip_debug & PLIP_DEBUG_TX)
+                       printf("st=%02x ", inb(PLIP_STATUS));
+#endif
+               if (inb(PLIP_STATUS) & LPS_NERR) {
+                       for (i = PLIPMXSPIN1; (inb(PLIP_STATUS) & LPS_NERR) != 0; i--)
+                               PLIP_DELAY;
+#if PLIP_DEBUG > 0
+                       if (plip_debug & PLIP_DEBUG_TX)
+                               printf("st1=%02x ", inb(PLIP_STATUS));
+#endif
+               }
+
+               outb(PLIP_DATA, PLIP_REMOTE_TRIGGER);
+               for (i = PLIPMXSPIN1; (inb(PLIP_STATUS) & LPS_NERR) == 0; i--) {
+                       if (i < 0 || (i > PLIPMXSPIN1/3
+                           && inb(PLIP_STATUS) & LPS_NACK)) {
+#if PLIP_DEBUG > 0
+                           printf("trigger ack timeout\n");
+#endif
+                               goto retry;
+                       }
+                       PLIP_DELAY;
+               }
+#if PLIP_DEBUG > 0
+               if (plip_debug & PLIP_DEBUG_TX)
+                       printf("st3=%02x ", inb(PLIP_STATUS));
+#endif
+
+/* Don't want ints while transmitting */
+
+               outb(PLIP_CONTROL, PLIP_INTR_DISABLE);
+
+               if (pliptransmit(iobase, minibuf + 1, minibuf[0]) < 0) goto retry;
+               for (cksum = 0, m = m0; m; m = m->m_next) {
+                       if (sizeof(struct ether_header) != 14 && m == m0) {
+                               i = pliptransmit(iobase, mtod(m, u_char *), 14);
+                               if (i < 0) goto retry;
+                               cksum += i;
+                               i = pliptransmit(iobase, mtod(m, u_char *)+16, m->m_len-16);
+                               if (i < 0) goto retry;
+                       }
+                       else                             
+                               i = pliptransmit(iobase, mtod(m, u_char *), m->m_len);
+                       if (i < 0) goto retry;
+                       cksum += i;
+               }
+               if (pliptransmit(iobase, &cksum, 1) < 0) goto retry;
+               i = PLIPMXSPIN2;
+               while ((inb(PLIP_STATUS) & LPS_NBSY) == 0)
+                       if (i-- < 0) goto retry;
+
+               outb(iobase + lpt_data, 0x00);
+/* Re-enable ints */
+
+               outb(PLIP_CONTROL, PLIP_INTR_ENABLE);
+
+               ifp->if_opackets++;
+               ifp->if_obytes += len + 4;
+               sc->sc_ifretry = 0;
+               s = splimp();
+               m_freem(m0);
+               splx(s);
+       }
+       ifp->if_flags &= ~IFF_OACTIVE;
+       return;
+
+retry:
+#if PLIP_DEBUG > 0
+       if (plip_debug & PLIP_DEBUG_TX)
+               printf("retry: %02x", inb(iobase + lpt_status));
+#endif
+       if (inb(PLIP_STATUS & LPS_NACK))
+               ifp->if_collisions++;
+       else
+               ifp->if_oerrors++;
+       if ((ifp->if_flags & (IFF_RUNNING | IFF_UP)) == (IFF_RUNNING | IFF_UP)
+           && sc->sc_ifretry < PLIPMXRETRY) {
+               sc->sc_ifretry++;
+               s = splimp();
+               IF_PREPEND(&ifp->if_snd, m0);
+               splx(s);
+               timeout((void (*)(void *))plipstart, ifp, PLIPRETRY);
+       } else {
+               if (sc->sc_ifretry == PLIPMXRETRY) {
+                       sc->sc_ifretry++;
+                       log(LOG_NOTICE, "plip%d: tx hard error\n", ifp->if_unit);
+               }
+               s = splimp();
+               m_freem(m0);
+               splx(s);
+       }
+       ifp->if_flags &= ~IFF_OACTIVE;
+               outb(PLIP_DATA, 0x00);
+
+/* Re-enable ints */
+
+               outb(PLIP_CONTROL, PLIP_INTR_ENABLE);
+/*xxx  if (sc->sc_iferrs > PLIPMXERRS)
+               i8255->port_a |= LPA_ACTIVE;
+       else
+               i8255->port_a |= LPA_ACKENABLE | LPA_ACTIVE;*/
+       return;
+}
+
+#endif
diff --git a/sys/arch/arm32/mainbus/lptreg.h b/sys/arch/arm32/mainbus/lptreg.h
new file mode 100644 (file)
index 0000000..f909794
--- /dev/null
@@ -0,0 +1,64 @@
+/* $NetBSD: lptreg.h,v 1.2 1996/03/18 20:50:03 mark 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.
+ *
+ *      @(#)lptreg.h   1.1 (Berkeley) 12/19/90
+ */
+
+/*
+ * AT Parallel Port (for lineprinter)
+ * Interface port and bit definitions
+ * Written by William Jolitz 12/18/90
+ * Copyright (C) William Jolitz 1990
+ */
+
+#define        lpt_data        0       /* Data to/from printer (R/W) */
+
+#define        lpt_status      4       /* Status of printer (R) */
+#define        LPS_NERR                0x08    /* printer no error */
+#define        LPS_SELECT              0x10    /* printer selected */
+#define        LPS_NOPAPER             0x20    /* printer out of paper */
+#define        LPS_NACK                0x40    /* printer no ack of data */
+#define        LPS_NBSY                0x80    /* printer no ack of data */
+
+#define        lpt_control     8       /* Control printer (R/W) */
+#define        LPC_STROBE              0x01    /* strobe data to printer */
+#define        LPC_AUTOLF              0x02    /* automatic linefeed */
+#define        LPC_NINIT               0x04    /* initialize printer */
+#define        LPC_SELECT              0x08    /* printer selected */
+#define        LPC_IENABLE             0x10    /* printer out of paper */
+
+#define        LPT_NPORTS      32
diff --git a/sys/arch/arm32/mainbus/mainbus.c b/sys/arch/arm32/mainbus/mainbus.c
new file mode 100644 (file)
index 0000000..7caade5
--- /dev/null
@@ -0,0 +1,136 @@
+/* $NetBSD: mainbus.c,v 1.3 1996/03/20 18:38:00 mark Exp $ */
+
+/*
+ * Copyright (c) 1994,1995 Mark Brinicombe.
+ * Copyright (c) 1994 Brini.
+ * 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 Brini.
+ * 4. The name of the company nor the name of the author may be used to
+ *    endorse or promote products derived from this software without specific
+ *    prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BRINI ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL BRINI 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.
+ *
+ * RiscBSD kernel project
+ *
+ * mainbus.c
+ *
+ * mainbus configuration
+ *
+ * Created      : 15/12/94
+ * Last updated : 03/07/95
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/conf.h>
+#include <sys/malloc.h>
+#include <sys/device.h>
+
+#include <arm32/mainbus/mainbus.h>
+#include <machine/io.h>
+
+int mainbusmatch __P((struct device *, void *, void *));
+void mainbusattach __P((struct device *, struct device *, void *));
+
+struct cfattach mainbus_ca = {
+       sizeof(struct device), mainbusmatch, mainbusattach
+};
+
+struct cfdriver mainbus_cd = {
+       NULL, "mainbus", DV_DULL, 1
+};
+
+int
+mainbusmatch(parent, match, aux)
+       struct device *parent;
+       void *match;
+       void *aux;
+{
+       return (1);
+}
+
+int
+mainbusprint(aux, mainbus)
+       void *aux;
+       char *mainbus;
+{
+       struct mainbus_attach_args *mb = aux;
+
+       if (mb->mb_iobase)
+               printf(" base 0x%x", mb->mb_iobase);
+       if (mb->mb_iosize > 1)
+               printf("-0x%x", mb->mb_iobase + mb->mb_iosize - 1);
+       if (mb->mb_irq != -1)
+               printf(" irq %d", mb->mb_irq);
+       if (mb->mb_drq != -1)
+               printf(" drq 0x%08x", mb->mb_drq);
+
+/* XXXX print flags */
+       return (QUIET);
+}
+
+
+void
+mainbusscan(parent, match)
+       struct device *parent;
+       void *match;
+{
+       struct device *dev = match;
+       struct cfdata *cf = dev->dv_cfdata;
+       struct mainbus_attach_args mb;
+
+       if (cf->cf_fstate == FSTATE_STAR)
+               panic("eekkk, I'm stuffed");
+
+       if (cf->cf_loc[0] == -1) {
+               mb.mb_iobase = 0;
+               mb.mb_iosize = 0;
+               mb.mb_drq = -1;
+               mb.mb_irq = -1;
+       } else {    
+               mb.mb_iobase = cf->cf_loc[0] + IO_CONF_BASE;
+               mb.mb_iosize = 0;
+               mb.mb_drq = cf->cf_loc[1];
+               mb.mb_irq = cf->cf_loc[2];
+       }
+       if ((*cf->cf_attach->ca_match)(parent, dev, &mb) > 0)
+               config_attach(parent, dev, &mb, mainbusprint);
+       else
+               free(dev, M_DEVBUF);
+}
+
+void
+mainbusattach(parent, self, aux)
+       struct device *parent;
+       struct device *self;
+       void *aux;
+{
+       printf("\n");
+
+       config_scan(mainbusscan, self);
+}
+
+/* End of mainbus.c */
diff --git a/sys/arch/arm32/mainbus/mainbus.h b/sys/arch/arm32/mainbus/mainbus.h
new file mode 100644 (file)
index 0000000..d0ae78e
--- /dev/null
@@ -0,0 +1,62 @@
+/* $NetBSD: mainbus.h,v 1.2 1996/03/18 20:50:05 mark Exp $ */
+
+/*
+ * Copyright (c) 1994,1995 Mark Brinicombe.
+ * Copyright (c) 1994 Brini.
+ * 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 Brini.
+ * 4. The name of the company nor the name of the author may be used to
+ *    endorse or promote products derived from this software without specific
+ *    prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BRINI ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL BRINI 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.
+ *
+ * RiscBSD kernel project
+ *
+ * mainbus.c
+ *
+ * mainbus configuration
+ *
+ * Created      : 15/12/94
+ */
+
+/*
+ * mainbus driver attach arguments
+ */
+
+struct mainbus_attach_args {
+       u_int   mb_iobase;              /* base i/o address */
+       int     mb_iosize;              /* span of ports used */
+       int     mb_irq;                 /* interrupt request */
+       int     mb_drq;                 /* DMA request */
+       void    *mb_aux;                /* driver specific */
+};
+
+#define DRQUNK -1
+#define INTUNK -1
+#define IRQUNK -1
+
+/* End of mainbus.h */
+
+
diff --git a/sys/arch/arm32/mainbus/pms.c b/sys/arch/arm32/mainbus/pms.c
new file mode 100644 (file)
index 0000000..8339e1a
--- /dev/null
@@ -0,0 +1,612 @@
+/* $NetBSD: pms.c,v 1.1 1996/03/28 21:50:19 mark Exp $ */
+
+/*-
+ * Copyright (c) 1996 D.C. Tsen
+ * Copyright (c) 1994 Charles Hannum.
+ * Copyright (c) 1992, 1993 Erik Forsberg.
+ * 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 RiscBSD team.
+ * 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 AUTHORS ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (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:pms.c,v 1.24 1995/12/24 02:30:28 mycroft Exp
+ */
+
+/*
+ * Ported from 386 version of PS/2 mouse driver.
+ * D.C. Tsen
+ */
+
+#include "pms.h"
+#if NPMS > 1
+#error Only one PS/2 style mouse may be configured into your system.
+#endif
+
+#include <sys/param.h>
+#include <sys/kernel.h>
+#include <sys/systm.h>
+#include <sys/buf.h>
+#include <sys/malloc.h>
+#include <sys/ioctl.h>
+#include <sys/tty.h>
+#include <sys/file.h>
+#include <sys/select.h>
+#include <sys/proc.h>
+#include <sys/signalvar.h>
+#include <sys/vnode.h>
+#include <sys/device.h>
+
+#include <machine/cpu.h>
+#include <machine/katelib.h>
+#include <machine/irqhandler.h>
+#include <machine/iomd.h>
+#include <machine/mouse.h>
+#include <arm32/mainbus/mainbus.h>
+
+/* mouse commands */
+#define        PMS_SET_SCALE11 0xe6    /* set scaling 1:1 */
+#define        PMS_SET_SCALE21 0xe7    /* set scaling 2:1 */
+#define        PMS_SET_RES     0xe8    /* set resolution */
+#define        PMS_GET_SCALE   0xe9    /* get scaling factor */
+#define        PMS_SET_STREAM  0xea    /* set streaming mode */
+#define        PMS_SET_SAMPLE  0xf3    /* set sampling rate */
+#define        PMS_DEV_ENABLE  0xf4    /* mouse on */
+#define        PMS_DEV_DISABLE 0xf5    /* mouse off */
+#define        PMS_RESET       0xff    /* reset */
+
+#define        PMS_CHUNK       128     /* chunk size for read */
+#define        PMS_BSIZE       (20*64) /* buffer size */
+
+struct pms_softc {             /* driver status information */
+       struct device sc_dev;
+       irqhandler_t sc_ih;
+
+       struct proc *proc;
+       struct clist sc_q;
+       struct selinfo sc_rsel;
+       u_int sc_state; /* mouse driver state */
+#define        PMS_OPEN        0x01    /* device is open */
+#define        PMS_ASLP        0x02    /* waiting for mouse data */
+       u_int sc_status;        /* mouse button status */
+       int sc_x, sc_y;         /* accumulated motion in the X,Y axis */
+       int boundx, boundy, bounda, boundb;     /* Bounding box.  x,y is bottom left */
+       int origx, origy;
+       int lastx, lasty, lastb;
+};
+
+int pmsprobe __P((struct device *, void *, void *));
+void pmsattach __P((struct device *, struct device *, void *));
+int pmsintr __P((void *));
+
+struct cfattach pms_ca = {
+       sizeof(struct pms_softc), pmsprobe, pmsattach
+};
+
+struct cfdriver        pms_cd = {
+       NULL, "pms", DV_DULL
+};
+
+#define        PMSUNIT(dev)    (minor(dev))
+
+static inline void
+pms_flush()
+{
+       while (inb(IOMD_MSCR) & 0x20) {
+               delay(6);
+               (void) inb(IOMD_MSDATA);
+               delay(6);
+               (void) inb(IOMD_MSDATA);
+               delay(6);
+               (void) inb(IOMD_MSDATA);
+       }
+}
+
+static void
+cmd_mouse(unsigned char cmd)
+{
+       unsigned char c;
+       int i = 0;
+       int retry = 10;
+
+       for (i = 0; i < 1000; i++) {
+               if (inb(IOMD_MSCR) & 0x80)
+                       break;
+               delay(2);
+       }
+       if (i == 1000)
+               printf("Mouse transmit not ready\n");
+
+resend:
+       outb(IOMD_MSDATA, cmd);
+       delay(2);
+       c = inb(IOMD_MSCR) & (unsigned char) 0xff;
+       while (!(c & (unsigned char) 0x20)) {
+               delay(1);
+               c = inb(IOMD_MSCR);
+       }
+
+       delay(10000);
+
+       c = inb(IOMD_MSDATA) & 0xff;
+       if ((c == 0xFA) || (c == 0xEE))
+               return;
+
+       if (--retry) {
+               pms_flush();
+               goto resend;
+       }
+
+       printf("Mouse cmd failed, cmd = %x, status = %x\n", cmd, c);
+       return;
+}
+
+int
+pmsprobe(parent, match, aux)
+       struct device *parent;
+       void *match, *aux;
+{
+       /*struct mainbus_attach_args *mb = aux;*/
+       int i, j;
+       int mid;
+       int id;
+
+/* Make sure we have an IOMD we understand */
+    
+       id = ReadByte(IOMD_ID0) | (ReadByte(IOMD_ID1) << 8);
+
+/* So far I only know about this IOMD */
+
+       switch (id) {
+       case RPC600_IOMD_ID:
+               return(0);
+               break;
+       case RC7500_IOC_ID:
+               break;
+       default:
+               printf("pms: Unknown IOMD id=%04x", id);
+               return(0);
+               break;
+       }
+
+       outb(IOMD_MSCR, 0x08);  /* enable the mouse */
+
+       i = 0;
+       while ((inb(IOMD_MSCR) & 0x03) != 0x03) {
+               if (i++ > 10) {
+                       printf("Mouse not found, status = <%x>.\n", inb(IOMD_MSCR));
+                       return(0);
+               }
+               pms_flush();
+               delay(2);
+               outb(IOMD_MSCR, 0x08);
+       }
+
+       pms_flush();
+
+       /*
+        * Disable, reset and enable the mouse.
+        */
+       cmd_mouse(PMS_DEV_DISABLE);
+       cmd_mouse(PMS_RESET);
+       delay(300000);
+       j = 10;
+       i = 0;
+       while ((mid = inb(IOMD_MSDATA)) != 0xAA) {
+               if (++i > 500) {
+                       if (--j < 0) {
+                               printf("Mouse Reset failed, status = <%x>.\n", mid);
+                               return(0);
+                       }
+                       pms_flush();
+                       cmd_mouse(PMS_RESET);
+                       i = 0;
+               }
+               delay(100000);
+       }
+       mid = inb(IOMD_MSDATA);
+#if 0
+       cmd_mouse(PMS_SET_RES);
+       cmd_mouse(3);           /* 8 counts/mm */
+       cmd_mouse(PMS_SET_SCALE21);
+       cmd_mouse(PMS_SET_SAMPLE);
+       cmd_mouse(100); /* 100 samples/sec */
+       cmd_mouse(PMS_SET_STREAM);
+#endif
+       cmd_mouse(PMS_DEV_ENABLE);
+       return 1;
+}
+
+void
+pmsattach(parent, self, aux)
+       struct device *parent, *self;
+       void *aux;
+{
+       struct pms_softc *sc = (void *)self;
+       struct mainbus_attach_args *mb = aux;
+
+       printf("\n");
+
+       /* Other initialization was done by pmsprobe. */
+       sc->sc_state = 0;
+       sc->origx = 0;
+       sc->origy = 0;
+       sc->boundx = -4095;
+       sc->boundy = -4095;
+       sc->bounda = 4096;
+       sc->boundb = 4096;
+
+       sc->sc_ih.ih_func = pmsintr;
+       sc->sc_ih.ih_arg = sc;
+       sc->sc_ih.ih_level = IPL_TTY;
+       sc->sc_ih.ih_name = "pms";
+       if (mb->mb_irq != IRQUNK)
+               sc->sc_ih.ih_num = mb->mb_irq;
+       else
+#ifdef RC7500
+               sc->sc_ih.ih_num = IRQ_MSDRX;
+#else
+               panic("pms: No IRQ specified for pms interrupt handler\n");
+#endif
+}
+
+int
+pmsopen(dev, flag, mode, p)
+       dev_t dev;
+       int flag;
+       int mode;
+       struct proc *p;
+{
+       int unit = PMSUNIT(dev);
+       struct pms_softc *sc;
+
+       if (unit >= pms_cd.cd_ndevs)
+               return ENXIO;
+       sc = pms_cd.cd_devs[unit];
+       if (!sc)
+               return ENXIO;
+
+       if (sc->sc_state & PMS_OPEN)
+               return EBUSY;
+
+       if (clalloc(&sc->sc_q, PMS_BSIZE, 0) == -1)
+               return ENOMEM;
+
+       sc->proc = p;
+       sc->sc_state |= PMS_OPEN;
+       sc->sc_status = 0;
+       sc->sc_x = sc->sc_y = 0;
+       sc->lastx = -1;
+       sc->lasty = -1;
+       sc->lastb = -1;
+
+       if (irq_claim(IRQ_INSTRUCT, &sc->sc_ih) == -1)
+               panic("Cannot claim MOUSE IRQ\n");
+
+       return 0;
+}
+
+int
+pmsclose(dev, flag, mode, p)
+       dev_t dev;
+       int flag;
+       int mode;
+       struct proc *p;
+{
+       struct pms_softc *sc = pms_cd.cd_devs[PMSUNIT(dev)];
+
+       if (irq_release(IRQ_INSTRUCT, &sc->sc_ih) != 0)
+               panic("Cannot release MOUSE IRQ\n");
+       sc->proc = NULL;
+       sc->sc_state &= ~PMS_OPEN;
+       sc->sc_x = sc->sc_y = 0;
+
+       clfree(&sc->sc_q);
+
+       return 0;
+}
+
+int
+pmsread(dev, uio, flag)
+       dev_t dev;
+       struct uio *uio;
+       int flag;
+{
+       struct pms_softc *sc = pms_cd.cd_devs[PMSUNIT(dev)];
+       int s;
+       int error = 0;
+       size_t length;
+       u_char buffer[PMS_CHUNK];
+
+       /* Block until mouse activity occured. */
+
+       s = spltty();
+       while (sc->sc_q.c_cc == 0) {
+               if (flag & IO_NDELAY) {
+                       splx(s);
+                       return EWOULDBLOCK;
+               }
+               sc->sc_state |= PMS_ASLP;
+               if (error = tsleep((caddr_t)sc, (PZERO | PCATCH), "pmsread", 0)) {
+                       sc->sc_state &= ~PMS_ASLP;
+                       splx(s);
+                       return error;
+               }
+       }
+
+       /* Transfer as many chunks as possible. */
+
+       while (sc->sc_q.c_cc > 0 && uio->uio_resid > 0) {
+               length = min(sc->sc_q.c_cc, uio->uio_resid);
+               if (length > sizeof(buffer))
+                       length = sizeof(buffer);
+
+               /* Remove a small chunk from the input queue. */
+               (void) q_to_b(&sc->sc_q, buffer, length);
+
+               /* Copy the data to the user process. */
+               if (error = uiomove(buffer, length, uio))
+                       break;
+       }
+       splx(s);
+
+       return error;
+}
+
+int
+pmsioctl(dev, cmd, addr, flag, p)
+       dev_t dev;
+       u_long cmd;
+       caddr_t addr;
+       int flag;
+       struct proc *p;
+{
+       struct pms_softc *sc = pms_cd.cd_devs[PMSUNIT(dev)];
+       struct mouseinfo info;
+       int s;
+       int error = 0;
+
+       s = spltty();
+
+       switch (cmd) {
+       case MOUSEIOC_SETSTATE:
+               printf("MOUSEIOC_SETSTATE called\n");
+               break;
+       case MOUSEIOC_WRITEX:
+               sc->sc_x = *(int *) addr;
+               break;
+       case MOUSEIOC_WRITEY:
+               sc->sc_y = *(int *) addr;
+               break;
+       case MOUSEIOC_SETBOUNDS:
+       {
+               register struct mouse_boundingbox *bo = (void *) addr;
+               sc->boundx = bo->x; sc->boundy = bo->y;
+               sc->bounda = bo->a; sc->boundb = bo->b;
+               break;
+       }
+       case MOUSEIOC_SETORIGIN:
+       {
+               register struct mouse_origin *oo = (void *) addr;
+               sc->origx = oo->x;
+               sc->origy = oo->y;
+               break;
+       }
+       case MOUSEIOC_GETBOUNDS:
+       {
+               register struct mouse_boundingbox *bo = (void *) addr;
+               bo->x = sc->boundx; bo->y = sc->boundy;
+               bo->a = sc->bounda; bo->b = sc->boundb;
+               break;
+       }
+       case MOUSEIOC_GETORIGIN:
+       {
+               register struct mouse_origin *oo = (void *) addr;
+               oo->x = sc->origx;
+               oo->y = sc->origy;
+               break;
+       }
+       case MOUSEIOC_GETSTATE:
+               printf("MOUSEIOC_GETSTATE called\n");
+               /*
+                * Fall through.
+                */
+/*     case MOUSEIOCREAD:*/
+
+               info.status = sc->sc_status;
+               if (sc->sc_x || sc->sc_y)
+                       info.status |= MOVEMENT;
+
+#if 1
+               info.xmotion = sc->sc_x;
+               info.ymotion = sc->sc_y;
+#else
+               if (sc->sc_x > sc->bounda)
+                       info.xmotion = sc->bounda;
+               else if (sc->sc_x < sc->boundx)
+                       info.xmotion = sc->boundx;
+               else
+                       info.xmotion = sc->sc_x;
+
+               if (sc->sc_y > sc->boundb)
+                       info.ymotion = sc->boundb;
+               else if (sc->sc_y < sc->boundy)
+                       info.ymotion = sc->boundy;
+               else
+                       info.ymotion = sc->sc_y;
+#endif
+
+               /* Reset historical information. */
+               sc->sc_x = sc->sc_y = 0;
+               sc->sc_status &= ~BUTCHNGMASK;
+               ndflush(&sc->sc_q, sc->sc_q.c_cc);
+
+               error = copyout(&info, addr, sizeof(struct mouseinfo));
+               break;
+
+       default:
+               error = EINVAL;
+               break;
+       }
+       splx(s);
+
+       return error;
+}
+
+/* Masks for the first byte of a packet */
+#define PS2LBUTMASK 0x01
+#define PS2RBUTMASK 0x02
+#define PS2MBUTMASK 0x04
+
+#define XNEG_MASK      0x10
+#define YNEG_MASK      0x20
+
+int
+pmsintr(arg)
+       void *arg;
+{
+       struct pms_softc *sc = arg;
+       static int state = 0;
+       static u_char buttons;
+       u_char changed;
+       static int dx, dy;
+       int dosignal = 0;
+       int s;
+       u_char b;
+       struct mousebufrec mbuffer;
+
+       if ((sc->sc_state & PMS_OPEN) == 0) {
+               /* Interrupts are not expected.  Discard the byte. */
+               pms_flush();
+               return(-1);
+       }
+
+       switch (state) {
+
+       case 0:
+               buttons = inb(IOMD_MSDATA);
+               if ((buttons & 0xc0) == 0)
+                       ++state;
+               break;
+
+       case 1:
+               dx = inb(IOMD_MSDATA);
+               dx = (buttons & XNEG_MASK) ? -dx : dx;
+               ++state;
+               break;
+
+       case 2:
+               dy = inb(IOMD_MSDATA);
+               dy = (buttons & YNEG_MASK) ? -dy : dy;
+               state = 0;
+
+               buttons = ((buttons & PS2LBUTMASK) << 2) |
+                         ((buttons & (PS2RBUTMASK | PS2MBUTMASK)) >> 1);
+               /*
+                * Ahhh, the Xarm server interrupt button bits reversed.
+                * If bit is set to 1, it means button is not pressed which is
+                * not what PS/2 mouse button bits said.  Since we are simulating
+                * the quadmouse, that's not too picky about it.
+                */
+               buttons ^= BUTSTATMASK;
+               changed = ((buttons ^ sc->sc_status) & BUTSTATMASK) << 3;
+               sc->sc_status = buttons | (sc->sc_status & ~BUTSTATMASK) | changed;
+
+               if (dx || dy || changed) {
+                       if (dx < 0)
+                               dx = -(256 + dx);
+                       if (dy < 0)
+                               dy = -(256 + dy);
+
+                       /* Update accumulated movements. */
+                       sc->sc_x += dx;
+                       sc->sc_y += dy;
+
+                       if (sc->sc_x > sc->bounda)
+                               sc->sc_x = sc->bounda;
+                       else if (sc->sc_x < sc->boundx)
+                               sc->sc_x = sc->boundx;
+
+                       if (sc->sc_y > sc->boundb)
+                               sc->sc_y = sc->boundb;
+                       else if (sc->sc_y < sc->boundy)
+                               sc->sc_y = sc->boundy;
+
+                       if (sc->sc_q.c_cc == 0) {
+                               dosignal = 1;
+                       }
+
+                       /* Add this event to the queue. */
+                       b = buttons & BUTSTATMASK;
+                       mbuffer.status = b | (b ^ sc->lastb) << 3
+                               | (((sc->sc_x==sc->lastx) && (sc->sc_y==sc->lasty))?0:0x40);
+                       mbuffer.x = sc->sc_x * 2;
+                       mbuffer.y = sc->sc_y * 2;
+                       microtime(&mbuffer.event_time);
+                       s = spltty();
+                       (void) b_to_q((char *)&mbuffer, sizeof(mbuffer), &sc->sc_q);
+                       (void) splx(s);
+                       sc->lastx = sc->sc_x;
+                       sc->lasty = sc->sc_y;
+                       sc->lastb = b;
+
+                       selwakeup(&sc->sc_rsel);
+                       if (sc->sc_state & PMS_ASLP) {
+                               sc->sc_state &= ~PMS_ASLP;
+                               wakeup((caddr_t)sc);
+                       }
+                       if (dosignal)
+                               psignal(sc->proc, SIGIO);
+               }
+
+               break;
+       }
+
+       return(0);
+}
+
+int
+pmsselect(dev, rw, p)
+       dev_t dev;
+       int rw;
+       struct proc *p;
+{
+       struct pms_softc *sc = pms_cd.cd_devs[PMSUNIT(dev)];
+       int s;
+       int ret;
+
+       if (rw == FWRITE)
+               return 0;
+
+       s = spltty();
+       if (!sc->sc_q.c_cc) {
+               selrecord(p, &sc->sc_rsel);
+               ret = 0;
+       } else
+               ret = 1;
+       splx(s);
+
+       return ret;
+}
diff --git a/sys/arch/arm32/mainbus/qmouse.c b/sys/arch/arm32/mainbus/qmouse.c
new file mode 100644 (file)
index 0000000..b2a6447
--- /dev/null
@@ -0,0 +1,440 @@
+/* $NetBSD: qmouse.c,v 1.5 1996/03/28 21:56:40 mark Exp $ */
+
+/*
+ * Copyright (c) Scott Stevens 1995 All rights reserved
+ * Copyright (c) Melvin Tang-Richardson 1995 All rights reserved
+ * Copyright (c) Mark Brinicombe 1995 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 RiscBSD team.
+ * 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.
+ */
+
+/*
+ * Quadrature mouse driver
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/conf.h>
+#include <sys/ioctl.h>
+#include <sys/tty.h>
+#include <sys/kernel.h>
+#include <sys/types.h>
+#include <sys/device.h>
+#include <sys/proc.h>
+#include <sys/time.h>
+#include <sys/errno.h>
+#include <dev/cons.h>
+#include <sys/fcntl.h>
+#include <sys/signalvar.h>
+#include <sys/vnode.h>
+#include <sys/time.h>
+
+#include <arm32/mainbus/mainbus.h>
+#include <machine/irqhandler.h>
+#include <machine/katelib.h>
+#include <machine/iomd.h>
+#include <machine/mouse.h>
+
+#include "quadmouse.h"
+
+#define TIMER1_COUNT 40000             /* 50Hz */
+
+#define QMOUSE_BSIZE 12*64
+
+struct quadmouse_softc {
+       struct device sc_device;
+       irqhandler_t sc_ih;
+       int sc_iobase;
+       struct selinfo sc_rsel;
+#define QMOUSE_OPEN 0x01
+#define QMOUSE_ASLEEP 0x02
+       int sc_state;
+       int boundx, boundy, bounda, boundb;     /* Bounding box.  x,y is bottom left */
+       int origx, origy;
+       int xmult, ymult;       /* Multipliers */
+       int lastx, lasty, lastb;
+       struct proc *proc;
+       struct clist buffer;
+};
+
+int    quadmouseprobe  __P((struct device *, void *, void *));
+void   quadmouseattach __P((struct device *, struct device *, void *));
+int    quadmouseopen   __P((dev_t, int, int, struct proc *));
+int    quadmouseclose  __P((dev_t, int, int, struct proc *));
+
+int        strncmp __P((const char *, const char *, size_t));
+
+int quadmouseintr      (struct quadmouse_softc *);
+
+struct cfattach quadmouse_ca = {
+       sizeof(struct quadmouse_softc), quadmouseprobe, quadmouseattach
+};
+
+struct cfdriver        quadmouse_cd = {
+       NULL, "quadmouse", DV_DULL
+};
+
+
+int
+quadmouseprobe(parent, match, aux)
+       struct device *parent;
+       void *match;
+       void *aux;
+{
+/*     struct mainbus_attach_args *mb = aux;*/
+       int id;
+
+/* Make sure we have an IOMD we understand */
+    
+       id = ReadByte(IOMD_ID0) | (ReadByte(IOMD_ID1) << 8);
+
+/* So far I only know about this IOMD */
+
+       switch (id) {
+       case RPC600_IOMD_ID:
+               return(1);
+               break;
+       default:
+               printf("quadmouse: Unknown IOMD id=%04x", id);
+               break;
+       }
+
+       return(0);
+}
+
+
+void
+quadmouseattach(parent, self, aux)
+       struct device *parent;
+       struct device *self;
+       void *aux;
+{
+       struct quadmouse_softc *sc = (void *)self;
+       struct mainbus_attach_args *mb = aux;
+    
+       sc->sc_iobase = mb->mb_iobase;
+    
+/* Check for a known IOMD chip */
+
+       sc->sc_ih.ih_func = quadmouseintr;
+       sc->sc_ih.ih_arg = sc;
+       sc->sc_ih.ih_level = IPL_TTY;
+       sc->sc_ih.ih_name = "T1 quadmouse";
+
+/* Set up origin and multipliers */
+
+       sc->origx = 0;
+       sc->origy = 0;
+       sc->xmult = 2;
+       sc->ymult = 2;
+
+/* Set up bounding box */
+
+       sc->boundx = -4095;
+       sc->boundy = -4095;
+       sc->bounda = 4096;
+       sc->boundb = 4096;
+
+       sc->sc_state = 0;
+
+       WriteWord(IOMD_MOUSEX, sc->origx);
+       WriteWord(IOMD_MOUSEY, sc->origy);
+    
+       printf("\n");
+}
+
+
+int
+quadmouseopen(dev, flag, mode, p)
+       dev_t dev;
+       int flag;
+       int mode;
+       struct proc *p;
+{
+       struct quadmouse_softc *sc;
+       int unit = minor(dev);
+    
+       if (unit >= quadmouse_cd.cd_ndevs)
+               return(ENXIO);
+
+       sc = quadmouse_cd.cd_devs[unit];
+    
+       if (!sc) return(ENXIO);
+
+       if (sc->sc_state & QMOUSE_OPEN) return(EBUSY);
+
+       sc->proc = p;
+    
+       sc->lastx = -1;
+       sc->lasty = -1;
+       sc->lastb = -1;
+
+       /* initialise buffer */
+       if (clalloc(&sc->buffer, QMOUSE_BSIZE, 0) == -1)
+               return(ENOMEM);
+
+       sc->sc_state |= QMOUSE_OPEN;
+
+       WriteByte(IOMD_T1LOW, (TIMER1_COUNT >> 0) & 0xff);
+       WriteByte(IOMD_T1HIGH, (TIMER1_COUNT >> 8) & 0xff);
+       WriteByte(IOMD_T1GO, 0);
+       
+       if (irq_claim(IRQ_TIMER1, &sc->sc_ih))
+               panic("Cannot claim TIMER1 IRQ for quadmouse%d\n", sc->sc_device.dv_unit);
+
+       return(0);
+}
+
+
+int
+quadmouseclose(dev, flag, mode, p)
+       dev_t dev;
+       int flag;
+       int mode;
+       struct proc *p;
+{
+       int unit = minor (dev);
+       struct quadmouse_softc *sc = quadmouse_cd.cd_devs[unit];
+    
+       if (irq_release(IRQ_TIMER1, &sc->sc_ih) != 0)
+               panic("Cannot release IRA\n");
+
+       sc->proc = NULL;
+       sc->sc_state = 0;
+
+       clfree(&sc->buffer);
+
+       return(0);
+}
+
+int
+quadmouseread(dev, uio, flag)
+       dev_t dev;
+       struct uio *uio;
+       int flag;
+{
+       int unit = minor(dev);
+       struct quadmouse_softc *sc = quadmouse_cd.cd_devs[unit];
+       int error;
+       int s;
+       int length;
+       u_char buffer[128];
+
+       s=spltty();
+       while(sc->buffer.c_cc==0) {
+               if(flag & IO_NDELAY) {
+                       (void)splx(s);
+                       return(EWOULDBLOCK);
+               }
+               sc->sc_state |= QMOUSE_ASLEEP;
+               if((error = tsleep((caddr_t)sc, PZERO | PCATCH, "quadmouseread", 0))) {
+                       sc->sc_state &= ~QMOUSE_ASLEEP;
+                       (void)splx(s);
+                       return(error);
+               }
+       }
+       
+       while(sc->buffer.c_cc>0 && uio->uio_resid>0) {
+               length=min(sc->buffer.c_cc, uio->uio_resid);
+               if(length>sizeof(buffer))
+                       length=sizeof(buffer);
+
+               (void) q_to_b(&sc->buffer, buffer, length);
+
+               if(error = (uiomove(buffer, length, uio)))
+                       break;
+       }
+       (void)splx(s);
+       return(error);
+}
+
+
+#define FMT_START      int x = ReadWord(IOMD_MOUSEX)&0xffff;           \
+                       int y = ReadWord(IOMD_MOUSEY)&0xffff;           \
+                       int b = ReadByte(IO_MOUSE_BUTTONS)&0x70;        \
+                       if(x&0x8000) x|=0xffff0000;                     \
+                       if(y&0x8000) y|=0xffff0000;                     \
+                       x = (x - sc->origx);                            \
+                       y = (y - sc->origy);                            \
+                       if (x<(sc->boundx)) x = sc->boundx;             \
+                               WriteWord(IOMD_MOUSEX, x + sc->origx);  \
+                       if (x>(sc->bounda)) x = sc->bounda;             \
+                               WriteWord(IOMD_MOUSEX, x + sc->origx);  \
+                       if (y<(sc->boundy)) y = sc->boundy;             \
+                               WriteWord(IOMD_MOUSEY, y + sc->origy);  \
+                       if (y>(sc->boundb)) y = sc->boundb;             \
+                               WriteWord(IOMD_MOUSEY, y + sc->origy);  \
+                       x=x*sc->xmult;                                  \
+                       y=y*sc->ymult;
+
+#define        FMT_END
+
+
+int
+quadmouseioctl(dev, cmd, data, flag, p)
+       dev_t dev;
+       int cmd;
+       caddr_t data;
+       int flag;
+       struct proc *p;
+{
+       struct quadmouse_softc *sc = quadmouse_cd.cd_devs[minor(dev)];
+
+       switch (cmd) {
+       case MOUSEIOC_WRITEX:
+               WriteWord(IOMD_MOUSEX, *(int *)data+sc->origx);
+               return 0;
+       case MOUSEIOC_WRITEY:
+               WriteWord(IOMD_MOUSEY, *(int *)data+sc->origy);
+               return 0;
+       case MOUSEIOC_SETSTATE:
+       {
+               register struct mouse_state *co = (void *)data;
+               WriteWord(IOMD_MOUSEX, co->x);
+               WriteWord(IOMD_MOUSEY, co->y);
+
+               /* Silly, but here for completeness, just incase */
+               /* the hardware supports it *giggle*             */
+
+/* This is not writable -- mark -- technically this should fault */
+
+/*             WriteWord ( IO_MOUSE_BUTTONS, co->buttons );*/
+               return 0;
+       }
+       case MOUSEIOC_SETBOUNDS:
+       {
+               register struct mouse_boundingbox *bo = (void *)data;
+               sc->boundx = bo->x; sc->boundy = bo->y;
+               sc->bounda = bo->a; sc->boundb = bo->b;
+               return 0;
+       }
+       case MOUSEIOC_SETORIGIN:
+       {
+               register struct mouse_origin *oo = (void *)data;
+/*             int oldx, oldy;*/
+               /* Need to fix up! */
+               sc->origx = oo->x;
+               sc->origy = oo->y;
+               return 0;
+       }
+       case MOUSEIOC_GETSTATE:
+       {
+               register struct mouse_state *co = (void *)data;
+               FMT_START
+               co->x = x;
+               co->y = y;
+               co->buttons = b ^ 0x70;
+               FMT_END
+               return 0;
+       }
+       case MOUSEIOC_GETBOUNDS:
+       {
+               register struct mouse_boundingbox *bo = (void *)data;
+               bo->x = sc->boundx; bo->y = sc->boundy;
+               bo->a = sc->bounda; bo->b = sc->boundb;
+               return 0;
+       }
+       case MOUSEIOC_GETORIGIN:
+       {
+               register struct mouse_origin *oo = (void *)data;
+               oo->x = sc->origx;
+               oo->y = sc->origy;
+               return 0;
+       }
+       }   
+
+       return (EINVAL);
+}
+
+
+int
+quadmouseintr(sc)
+       struct quadmouse_softc *sc;
+{
+       int s;
+       struct mousebufrec buffer;
+       int dosignal=0;
+
+       FMT_START
+
+       b &= 0x70;
+       b >>= 4;
+        if (x != sc->lastx || y != sc->lasty || b != sc->lastb) {
+               /* Mouse state changed */
+               buffer.status = b | ( b ^ sc->lastb) << 3 | (((x==sc->lastx) && (y==sc->lasty))?0:0x40);
+               buffer.x = x;
+               buffer.y = y;
+               microtime(&buffer.event_time);
+
+               if(sc->buffer.c_cc==0)
+                       dosignal=1;
+
+               s=spltty();
+               (void) b_to_q((char *)&buffer, sizeof(buffer), &sc->buffer);
+               (void)splx(s);
+               selwakeup(&sc->sc_rsel);
+
+               if(sc->sc_state & QMOUSE_ASLEEP) {
+                       sc->sc_state &= ~QMOUSE_ASLEEP;
+                       wakeup((caddr_t)sc);
+               }
+
+               if(dosignal)
+                       psignal(sc->proc, SIGIO);
+               
+               sc->lastx = x;
+               sc->lasty = y;
+               sc->lastb = b;
+       }
+
+       FMT_END
+       return(0);
+}
+
+int
+quadmouseselect(dev, rw, p)
+       dev_t dev;
+       int rw;
+       struct proc *p;
+{
+       int unit = minor(dev);
+       struct quadmouse_softc *sc = quadmouse_cd.cd_devs[unit];
+       int s;
+
+       if(rw == FWRITE)
+               return 0;
+
+       s=spltty();
+       if(sc->buffer.c_cc > 0) {
+               selrecord(p, &sc->sc_rsel);
+               (void)splx(s);
+               return 0;
+       }
+       (void)splx(s);
+       return 1;
+}
+
+/* End of quadmouse.c */
diff --git a/sys/arch/arm32/mainbus/rtc.c b/sys/arch/arm32/mainbus/rtc.c
new file mode 100644 (file)
index 0000000..d759294
--- /dev/null
@@ -0,0 +1,384 @@
+/* $NetBSD: rtc.c,v 1.1 1996/04/19 19:49:06 mark Exp $ */
+
+/*
+ * Copyright (c) 1994-1996 Mark Brinicombe.
+ * Copyright (c) 1994 Brini.
+ * All rights reserved.
+ *
+ * This code is derived from software written for Brini by Mark Brinicombe
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided 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 Brini.
+ * 4. The name of the company nor the name of the author may be used to
+ *    endorse or promote products derived from this software without specific
+ *    prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BRINI ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL BRINI 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.
+ *
+ * RiscBSD kernel project
+ *
+ * rtc.c
+ *
+ * Routines to read and write the RTC and CMOS RAM
+ *
+ * Created      : 13/10/94
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/conf.h>
+#include <sys/malloc.h>
+#include <sys/device.h>
+#include <machine/iic.h>
+#include <machine/rtc.h>
+
+struct rtc_softc {
+       struct device   sc_dev;
+       int             sc_flags;
+#define RTC_BROKEN     1
+#define RTC_OPEN       2
+};
+
+void rtcattach __P((struct device *parent, struct device *self, void *aux));
+int rtcmatch __P((struct device *parent, void *match, void *aux));
+
+/* Read a byte from CMOS RAM */
+
+int
+cmos_read(location)
+       int location;
+{
+       u_char buff;
+
+/*
+ * This commented code dates from when I was translating CMOS address
+ * from the RISCOS addresses. Now all addresses are specifed as
+ * actual addresses in the CMOS RAM
+ */
+
+/* 
+       if (location > 0xF0)
+               return(-1);
+
+       if (location < 0xC0)
+               buff = location + 0x40;
+       else
+               buff = location - 0xB0;
+*/
+       buff = location;
+
+       if (iic_control(RTC_Write, &buff, 1))
+               return(-1);
+       if (iic_control(RTC_Read, &buff, 1))
+               return(-1);
+
+       return(buff);
+}
+
+
+/* Write a byte to CMOS RAM */
+
+int
+cmos_write(location, value)
+       int location;
+       int value;
+{
+       u_char buff[2];
+
+/*
+ * This commented code dates from when I was translating CMOS address
+ * from the RISCOS addresses. Now all addresses are specifed as
+ * actual addresses in the CMOS RAM
+ */
+
+/*     if (location > 0xF0)
+               return(-1);
+
+       if (location < 0xC0)
+               buff = location + 0x40;
+       else
+               buff = location - 0xB0;
+*/
+       buff[0] = location;
+       buff[1] = value;
+
+       if (iic_control(RTC_Write, buff, 2))
+               return(-1);
+
+       return(0);
+}
+
+
+/* Hex to BCD and BCD to hex conversion routines */
+
+static inline int
+hexdectodec(n)
+       u_char n;
+{
+       return(((n >> 4) & 0x0F) * 10 + (n & 0x0F));
+}
+
+static inline int
+dectohexdec(n)
+       u_char n;
+{
+       return(((n / 10) << 4) + (n % 10));
+}
+
+
+/* Write the RTC data from an 8 byte buffer */
+
+int
+rtc_write(rtc)
+       rtc_t *rtc;
+{
+       u_char buff[8];
+
+       buff[0] = 1;
+
+       buff[1] = dectohexdec(rtc->rtc_centi);
+       buff[2] = dectohexdec(rtc->rtc_sec);
+       buff[3] = dectohexdec(rtc->rtc_min);
+       buff[4] = dectohexdec(rtc->rtc_hour) & 0x3f;
+       buff[5] = dectohexdec(rtc->rtc_day);
+       buff[6] = dectohexdec(rtc->rtc_mon);
+
+       if (iic_control(RTC_Write, buff, 7))
+               return(0);
+
+       cmos_write(RTC_ADDR_YEAR, rtc->rtc_year);
+       cmos_write(RTC_ADDR_CENT, rtc->rtc_cen);
+
+       return(1);
+}
+
+
+/* Read the RTC data into a 8 byte buffer */
+
+int
+rtc_read(rtc)
+       rtc_t *rtc;
+{
+       u_char buff[8];
+       int byte;
+    
+       buff[0] = 0;
+
+       if (iic_control(RTC_Write, buff, 1))
+               return(0);
+
+       if (iic_control(RTC_Read, buff, 8))
+               return(0);
+
+       rtc->rtc_micro = 0;
+       rtc->rtc_centi = hexdectodec(buff[1] & 0xff);
+       rtc->rtc_sec   = hexdectodec(buff[2] & 0x7f);
+       rtc->rtc_min   = hexdectodec(buff[3] & 0x7f);
+       rtc->rtc_hour  = hexdectodec(buff[4] & 0x3f);
+
+       /* If in 12 hour mode need to look at the AM/PM flag */
+       
+       if (buff[4] & 0x80)
+               rtc->rtc_hour += (buff[4] & 0x40) ? 12 : 0;
+
+       rtc->rtc_day   = hexdectodec(buff[5] & 0x3f);
+       rtc->rtc_mon   = hexdectodec(buff[6] & 0x1f);
+
+       byte = cmos_read(RTC_ADDR_YEAR);
+       if (byte == -1)
+               return(0);
+       rtc->rtc_year = byte; 
+
+       byte = cmos_read(RTC_ADDR_CENT);
+       if (byte == -1)
+               return(0);
+       rtc->rtc_cen = byte; 
+
+       return(1);
+}
+
+
+struct cfattach rtc_ca = {
+       sizeof(struct rtc_softc), rtcmatch, rtcattach
+};
+
+struct cfdriver rtc_cd = {
+       NULL, "rtc", DV_DULL, 0
+};
+
+int
+rtcmatch(parent, match, aux)
+       struct device *parent;
+       void *match;
+       void *aux;
+{
+/*     struct iicbus_attach_args *ib = aux;*/
+
+       return(1);
+}
+
+
+void
+rtcattach(parent, self, aux)
+       struct device *parent;
+       struct device *self;
+       void *aux;
+{
+       struct rtc_softc *sc = (struct rtc_softc *)self;
+       struct iicbus_attach_args *ib = aux;
+       u_char buff[1];
+
+       sc->sc_flags |= RTC_BROKEN;
+       if ((ib->ib_addr & IIC_PCF8583_MASK) == IIC_PCF8583_ADDR) {
+               printf(": PCF8583");
+
+               buff[0] = 0;
+
+               if (iic_control(RTC_Write, buff, 1))
+                       return;
+
+               if (iic_control(RTC_Read, buff, 1))
+                       return;
+
+               printf(" clock base ");
+               switch (buff[0] & 0x30) {
+               case 0x00:
+                       printf("32.768KHz");
+                       break;
+               case 0x10:
+                       printf("50Hz");
+                       break;
+               case 0x20:
+                       printf("event");
+                       break;
+               case 0x30:
+                       printf("test mode");
+                       break;
+               }
+
+               if (buff[0] & 0x80)
+                       printf(" stopped");
+               if (buff[0] & 0x04)
+                       printf(" alarm enabled");
+               sc->sc_flags &= ~RTC_BROKEN;
+       }
+
+
+/*
+ * Initialise the time of day register.
+ * This is normally left to the filing system to do but not all
+ * filing systems call it e.g. cd9660
+ */
+
+       inittodr(0);
+
+       printf("\n");
+}
+
+
+int
+rtcopen(dev, flag, mode, p)
+       dev_t dev;
+       int flag;
+       int mode;
+       struct proc *p;
+{
+       struct rtc_softc *sc;
+       int unit = minor(dev);
+    
+       if (unit >= rtc_cd.cd_ndevs)
+               return(ENXIO);
+
+       sc = rtc_cd.cd_devs[unit];
+    
+       if (!sc) return(ENXIO);
+
+       if (sc->sc_flags & RTC_OPEN) return(EBUSY);
+
+       sc->sc_flags |= RTC_OPEN;
+
+       return(0);
+}
+
+
+int
+rtcclose(dev, flag, mode, p)
+       dev_t dev;
+       int flag;
+       int mode;
+       struct proc *p;
+{
+       int unit = minor(dev);
+       struct rtc_softc *sc = rtc_cd.cd_devs[unit];
+    
+       sc->sc_flags &= ~RTC_OPEN;
+
+       return(0);
+}
+
+
+int
+rtcread(dev, uio, flag)
+       dev_t dev;
+       struct uio *uio;
+       int flag;
+{
+       int unit = minor(dev);
+       struct rtc_softc *sc = rtc_cd.cd_devs[unit];
+
+       return(ENXIO);
+}
+
+
+int
+rtcwrite(dev, uio, flag)
+       dev_t dev;
+       struct uio *uio;
+       int flag;
+{
+       int unit = minor(dev);
+       struct rtc_softc *sc = rtc_cd.cd_devs[unit];
+
+       return(ENXIO);
+}
+
+
+int
+rtcioctl(dev, cmd, data, flag, p)
+       dev_t dev;
+       int cmd;
+       caddr_t data;
+       int flag;
+       struct proc *p;
+{
+       struct rtc_softc *sc = rtc_cd.cd_devs[minor(dev)];
+
+/*     switch (cmd) {
+       case RTCIOC_READ:
+               return(0);
+       }   */
+
+       return(EINVAL);
+}
+
+/* End of rtc.c */
diff --git a/sys/arch/arm32/mainbus/vidcaudio.c b/sys/arch/arm32/mainbus/vidcaudio.c
new file mode 100644 (file)
index 0000000..0529519
--- /dev/null
@@ -0,0 +1,870 @@
+/* $NetBSD: vidcaudio.c,v 1.3 1996/03/17 01:24:37 thorpej Exp $ */
+
+/*
+ * Copyright (c) 1995 Melvin Tang-Richardson
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided 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 RiscBSD team.
+ * 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.
+ */
+
+/*
+ * Yikes just had a look at this and realised that it does not conform
+ * to Kernel Normal Form at all. I have fixed the first few functions
+ * but there are a lot more still to do - mark
+ */
+
+/*
+ * vidcaudio driver for RiscBSD by Melvin Tang-Richardson (c) 1995
+ *
+ * Interfaces with the NetBSD generic audio driver to provide SUN
+ * /dev/audio (partial) compatibility.
+ *
+ * Do not include me in conf.c.  My interface is done by the generic
+ * audio driver.  Put me in config file and files.arm32.  Do not put
+ * the audio.c generic driver in them.  I do the autoconfig for it.
+ *
+ * The following files need to be altered
+ *
+ * [files.arm32]
+ * device  vidcaudio at mainbus :audio
+ * file    arch/arm32/mainbus/vidcaudio.c      vidcaudio needs-flag
+ * major { audio=36 }
+ *
+ * [conf.c]
+ * #include "audio.h"
+ * cdev_decl(audio)
+ *
+ * cdev_audio_init(NAUDIO,audio)       /* 36: generic audio I/O */
+ *
+ * [GENERIC]
+ * vidcaudio0  at mainbus? base 0x00000000
+ *
+ */
+
+#include <sys/param.h> /* proc.h */
+#include <sys/types.h>  /* dunno  */
+#include <sys/conf.h>   /* autoconfig functions */
+#include <sys/device.h> /* device calls */
+#include <sys/proc.h>  /* device calls */
+#include <sys/audioio.h>
+#include <sys/errno.h>
+#include <sys/systm.h>
+
+#include <vm/vm.h>
+#include <vm/vm_kern.h>
+
+#include <dev/audio_if.h>
+
+#include <machine/irqhandler.h>
+#include <machine/iomd.h>
+#include <machine/vidc.h>
+#include <machine/katelib.h> /* ReadByte etc. */
+
+#include <arm32/mainbus/mainbus.h>
+#include "waveform.h"
+#include "vidcaudio.h"
+
+#undef DEBUG
+
+struct audio_general {
+       int in_sr;
+       int out_sr;
+       vm_offset_t silence;
+       irqhandler_t ih;
+
+       void (*intr) ();
+       void *arg;
+
+       vm_offset_t next_cur;
+       vm_offset_t next_end;
+       void (*next_intr) ();
+       void *next_arg;
+
+       int buffer;
+       int in_progress;
+
+       int open;
+} ag;
+
+struct vidcaudio_softc {
+       struct device device;
+       int iobase;
+
+       int open;
+
+       u_int encoding;
+       int inport;
+       int outport;
+};
+
+int  vidcaudio_probe   __P((struct device *parent, struct device *match, void *aux));
+void vidcaudio_attach  __P((struct device *parent, struct device *self, void *aux));
+int  vidcaudio_open    __P((dev_t dev, int flags));
+void vidcaudio_close   __P((void *addr));
+
+int vidcaudio_intr     __P((void *arg));
+int vidcaudio_dma_program      __P((vm_offset_t cur, vm_offset_t end, void (*intr)(), void *arg));
+void vidcaudio_dummy_routine   __P((void *arg));
+int vidcaudio_stereo   __P((int channel, int position));
+int vidcaudio_rate     __P((int rate));
+void vidcaudio_shutdown        __P((void));
+int vidcaudio_hw_attach        __P((struct vidcaudio_softc *sc));
+
+struct cfattach vidcaudio_ca = {
+       sizeof(struct vidcaudio_softc), vidcaudio_probe, vidcaudio_attach
+};
+
+struct cfdriver vidcaudio_cd = {
+       NULL, "vidcaudio", DV_DULL
+};
+
+
+void
+vidcaudio_beep_generate()
+{
+       vidcaudio_dma_program ( ag.silence, ag.silence+sizeof(beep_waveform)-16,
+           vidcaudio_dummy_routine, NULL );
+}
+
+
+int
+vidcaudio_probe(parent, match, aux)
+       struct device *parent;
+       struct device *match;
+       void *aux;
+{
+       int id;
+
+       id = ReadByte(IOMD_ID0) | ReadByte(IOMD_ID1) << 8;
+
+/* So far I only know about this IOMD */
+
+       switch (id) {
+       case RPC600_IOMD_ID:
+               return(1);
+               break;
+       default:
+               printf("vidcaudio: Unknown IOMD id=%04x", id);
+               break;
+       }
+
+       return (0);
+}
+
+
+void
+vidcaudio_attach(parent, self, aux)
+       struct device *parent;
+       struct device *self;
+       void *aux;
+{
+       struct mainbus_attach_args *mb = aux;
+       struct vidcaudio_softc *sc = (void *)self;
+
+       sc->iobase = mb->mb_iobase;
+
+       sc->open = 0;
+       sc->encoding = 0;
+       sc->inport = 0;
+       sc->outport = 0;
+       ag.in_sr = 24*1024;
+       ag.out_sr = 24*1024;
+       ag.in_progress = 0;
+
+       ag.next_cur = 0;
+       ag.next_end = 0;
+       ag.next_intr = NULL;
+       ag.next_arg = NULL;
+
+       vidcaudio_rate(32);
+
+/* Program the silence buffer and reset the DMA channel */
+
+       ag.silence = kmem_alloc(kernel_map, NBPG);
+       if (ag.silence == NULL)
+               panic("vidcaudio: Cannot allocate memory\n");
+
+       bzero((char *)ag.silence, NBPG);
+       bcopy((char *)beep_waveform, (char *)ag.silence, sizeof(beep_waveform));
+
+       ag.buffer = 0;
+
+       /* Install the irq handler for the DMA interrupt */
+       ag.ih.ih_func = vidcaudio_intr;
+       ag.ih.ih_arg = NULL;
+       ag.ih.ih_level = IPL_NONE;
+
+       ag.intr = NULL;
+       ag.nextintr = NULL;
+
+       disable_irq(IRQ_DMASCH0);
+
+       if (irq_claim(IRQ_DMASCH0, &(ag.ih)))
+               panic("vidcaudio: couldn't claim IRQ_DMASCH0");
+
+       disable_irq(IRQ_DMASCH0);
+
+       vidcaudio_dma_program(ag.silence, ag.silence+NBPG-16,
+           vidcaudio_dummy_routine, NULL);
+
+       vidcaudio_hw_attach(sc);
+
+#ifdef DEBUG
+       printf(" UNDER DEVELOPMENT (nuts)\n");
+#endif
+}
+
+int
+vidcaudio_open(dev, flags)
+       dev_t dev;
+       int flags;
+{
+       struct vidcaudio_softc *sc;
+       int unit = AUDIOUNIT (dev);
+       int s;
+
+#ifdef DEBUG
+       printf("DEBUG: vidcaudio_open called\n");
+#endif
+
+       if (unit >= vidcaudio_cd.cd_ndevs)
+               return ENODEV;
+
+       sc = vidcaudio_cd.cd_devs[unit];
+
+       if (!sc)
+               return ENXIO;
+
+       s = splhigh();
+
+       if (sc->open != 0) {
+               (void)splx(s);
+               return EBUSY;
+       }
+
+       sc->open=1;
+       ag.open=1;
+
+       (void)splx(s);
+       return 0;
+}
+void
+vidcaudio_close(addr)
+       void *addr;
+{
+       struct vidcaudio_softc *sc = addr;
+
+       vidcaudio_shutdown ();
+
+#ifdef DEBUG
+       printf("DEBUG: vidcaudio_close called\n");
+#endif
+
+       sc->open = 0;
+       ag.open = 0;
+}
+
+/* ************************************************************************* * 
+ | Interface to the generic audio driver                                     |
+ * ************************************************************************* */
+
+int    vidcaudio_set_in_sr       __P((void *, u_long));
+u_long vidcaudio_get_in_sr       __P((void *));
+int    vidcaudio_set_out_sr      __P((void *, u_long));
+u_long vidcaudio_get_out_sr      __P((void *));
+int    vidcaudio_query_encoding  __P((void *, struct audio_encoding *));
+int    vidcaudio_set_encoding   __P((void *, u_int));
+int    vidcaudio_get_encoding   __P((void *));
+int    vidcaudio_set_precision  __P((void *, u_int));
+int    vidcaudio_getprecision   __P((void *));
+int    vidcaudio_set_channels   __P((void *, int));
+int    vidcaudio_get_channels   __P((void *));
+int    vidcaudio_round_blocksize __P((void *, int));
+int    vidcaudio_set_out_port   __P((void *, int));
+int    vidcaudio_get_out_port   __P((void *));
+int    vidcaudio_set_in_port    __P((void *, int));
+int    vidcaudio_get_in_port    __P((void *));
+int    vidcaudio_commit_settings __P((void *));
+u_int  vidcaudio_get_silence    __P((int));
+void   vidcaudio_sw_encode      __P((int, u_char *, int));
+void   vidcaudio_sw_decode      __P((int, u_char *, int));
+int    vidcaudio_start_output   __P((void *, void *, int, void (*)(), void *));
+int    vidcaudio_start_input    __P((void *, void *, int, void (*)(), void *));
+int    vidcaudio_halt_output    __P((void *));
+int    vidcaudio_halt_input     __P((void *));
+int    vidcaudio_cont_output    __P((void *));
+int    vidcaudio_cont_input     __P((void *));
+int    vidcaudio_speaker_ctl    __P((void *, int));
+int    vidcaudio_getdev                 __P((void *, struct audio_device *));
+int    vidcaudio_setfd          __P((void *, int));
+int    vidcaudio_set_port       __P((void *, mixer_ctrl_t *));
+int    vidcaudio_get_port       __P((void *, mixer_ctrl_t *));
+int    vidcaudio_query_devinfo  __P((void *, mixer_devinfo_t *));
+
+struct audio_device vidcaudio_device = {
+       "VidcAudio 8-bit",
+       "x",
+       "vidcaudio"
+};
+
+int
+vidcaudio_set_in_sr(addr, sr)
+       void *addr;
+       u_long sr;
+{
+       ag.in_sr = sr;
+       return 0;
+}
+
+u_long
+vidcaudio_get_in_sr(addr)
+       void *addr;
+{
+       return ag.in_sr;
+}
+
+int
+vidcaudio_set_out_sr(addr, sr)
+       void *addr;
+       u_long sr;
+{
+       ag.out_sr = sr;
+       return 0;
+}
+
+u_long
+vidcaudio_get_out_sr(addr)
+       void *addr;
+{
+       return(ag.out_sr);
+}
+
+int vidcaudio_query_encoding ( void *addr, struct audio_encoding *fp )
+{
+    switch ( fp->index )
+    {
+        case 0:
+           strcpy (fp->name, "vidc" );
+            fp->format_id = AUDIO_ENCODING_ULAW;
+            break;
+
+       default:
+           return (EINVAL);
+    }
+    return 0;
+}
+
+int vidcaudio_set_encoding ( void *addr, u_int enc )
+{
+    struct vidcaudio_softc *sc = addr;
+
+    switch (enc)
+    {
+       case AUDIO_ENCODING_ULAW:
+#ifdef DEBUG
+           printf ( "DEBUG: Set ulaw encoding\n" );
+#endif
+            sc->encoding = enc;
+           break;
+
+        default:
+           return (EINVAL);
+    }
+    return 0;
+}
+
+int vidcaudio_get_encoding ( void *addr )
+{
+    struct vidcaudio_softc *sc = addr;
+    return sc->encoding;
+}
+
+int vidcaudio_set_precision ( void *addr, u_int prec )
+{
+    if (prec != 8)
+       return EINVAL;
+    return 0;
+}
+
+int vidcaudio_get_precision ( void *addr )
+{
+    return (8);
+}
+
+int vidcaudio_set_channels ( void *addr, int chans )
+{
+    if ( chans!=1 )
+       return EINVAL;
+
+    return 0;
+}
+
+int vidcaudio_get_channels ( void *addr )
+{
+    return 1;
+}
+
+int vidcaudio_round_blocksize ( void *addr, int blk )
+{
+    if (blk>NBPG) blk=NBPG;
+    return blk;
+}
+
+int vidcaudio_set_out_port ( void *addr, int port )
+{
+    struct vidcaudio_softc *sc = addr;
+    sc->outport = port;
+    return 0;
+}
+
+int vidcaudio_get_out_port ( void *addr )
+{
+    struct vidcaudio_softc *sc = addr;
+    return sc->outport;
+}
+
+int vidcaudio_set_in_port ( void *addr, int port )
+{
+    struct vidcaudio_softc *sc = addr;
+    sc->inport = port;
+    return 0;
+}
+
+int vidcaudio_get_in_port ( void *addr )
+{
+    struct vidcaudio_softc *sc = addr;
+    return sc->inport;
+}
+
+int vidcaudio_commit_settings ( void *addr )
+{
+#ifdef DEBUG
+printf ( "DEBUG: committ_settings\n" );
+#endif
+    return 0;
+}
+
+u_int vidcaudio_get_silence ( int enc )
+{
+    switch (enc)
+    {
+       case AUDIO_ENCODING_ULAW:
+           return 0x7f;
+
+        default:
+           return 0;
+    }
+    return 0;
+}
+
+void vidcaudio_sw_encode ( int e, u_char *p, int cc )
+{
+#ifdef DEBUG
+    printf ( "DEBUG: sw_encode\n" );    
+#endif
+    return;
+}
+
+void vidcaudio_sw_decode ( int e, u_char *p, int cc )
+{
+#ifdef DEBUG
+    printf ( "DEBUG: sw_decode\n" );    
+#endif
+}
+
+#define ROUND(s)  ( ((int)s) & (~(NBPG-1)) )
+
+int vidcaudio_start_output ( void *addr, void *p, int cc,
+                             void (*intr)(), void *arg )
+{
+    /* I can only DMA inside 1 page */
+
+#ifdef DEBUG
+    printf ( "vidcaudio_start_output (%d) %08x %08x\n", cc, intr, arg );
+#endif
+
+    if ( ROUND(p) != ROUND(p+cc) )
+    {
+        /* If it's over a page I can fix it up by copying it into my buffer */
+
+#ifdef DEBUG
+        printf ( "vidcaudio: DMA over page boundary requested.  Fixing up\n" );
+#endif
+        bcopy ( (char *)ag.silence, p, cc>NBPG ? NBPG : cc );
+        p=(void *)ag.silence;
+
+       /* I can't DMA any more than that, but it is possible to fix it up  */
+        /* by handling multiple buffers and only interrupting the audio     */
+        /* driver after sending out all the stuff it gave me.  That it more */
+        /* than I can be bothered to do right now and it probablly wont     */
+        /* happen so I'll just truncate the buffer and tell the user        */
+
+       if ( cc>NBPG )
+       {
+           printf ( "vidcaudio: DMA buffer truncated. I could fix this up\n" );
+           cc=NBPG;
+       }
+    }
+    vidcaudio_dma_program ( (vm_offset_t)p, (vm_offset_t)(p+cc), intr, arg );
+    return 0;
+}
+
+int vidcaudio_start_input ( void *addr, void *p, int cc,
+                            void (*intr)(), void *arg )
+{
+    return EIO;
+}
+
+int vidcaudio_halt_output ( void *addr )
+{
+#ifdef DEBUG
+    printf ( "DEBUG: vidcaudio_halt_output\n" );
+#endif
+    return EIO;
+}
+
+int vidcaudio_halt_input ( void *addr )
+{
+#ifdef DEBUG
+    printf ( "DEBUG: vidcaudio_halt_output\n" );
+#endif
+    return EIO;
+}
+
+int vidcaudio_cont_output ( void *addr )
+{
+#ifdef DEBUG
+    printf ( "DEBUG: vidcaudio_halt_output\n" );
+#endif
+    return EIO;
+}
+
+int vidcaudio_cont_input ( void *addr )
+{
+#ifdef DEBUG
+    printf ( "DEBUG: vidcaudio_halt_output\n" );
+#endif
+    return EIO;
+}
+
+int vidcaudio_speaker_ctl ( void *addr, int newstate )
+{
+#ifdef DEBUG
+    printf ( "DEBUG: vidcaudio_speaker_ctl\n" );
+#endif
+    return 0;
+}
+
+int vidcaudio_getdev ( void *addr, struct audio_device *retp )
+{
+    *retp = vidcaudio_device;
+    return 0;
+}
+
+
+int vidcaudio_setfd ( void *addr, int flag )
+{
+    return ENOTTY;
+}
+
+int vidcaudio_set_port ( void *addr, mixer_ctrl_t *cp )
+{
+    return EINVAL;
+}
+
+int vidcaudio_get_port ( void *addr, mixer_ctrl_t *cp )
+{
+    return EINVAL;
+}
+
+int vidcaudio_query_devinfo ( void *addr, mixer_devinfo_t *dip )
+{
+    return 0;
+}
+
+struct audio_hw_if vidcaudio_hw_if = {
+    vidcaudio_open,
+    vidcaudio_close,
+    NULL,
+    vidcaudio_set_in_sr,
+    vidcaudio_get_in_sr,
+    vidcaudio_set_out_sr,
+    vidcaudio_get_out_sr,
+    vidcaudio_query_encoding,
+    vidcaudio_set_encoding,
+    vidcaudio_get_encoding,
+    vidcaudio_set_precision,
+    vidcaudio_get_precision,
+    vidcaudio_set_channels,
+    vidcaudio_get_channels,
+    vidcaudio_round_blocksize,
+    vidcaudio_set_out_port,
+    vidcaudio_get_out_port,
+    vidcaudio_set_in_port,
+    vidcaudio_get_in_port,
+    vidcaudio_commit_settings,
+    vidcaudio_get_silence,
+    vidcaudio_sw_encode,
+    vidcaudio_sw_decode,
+    vidcaudio_start_output,
+    vidcaudio_start_input,
+    vidcaudio_halt_output,
+    vidcaudio_halt_input,
+    vidcaudio_cont_output,
+    vidcaudio_cont_input,
+    vidcaudio_speaker_ctl,
+    vidcaudio_getdev,
+    vidcaudio_setfd,
+    vidcaudio_set_port,
+    vidcaudio_get_port,
+    vidcaudio_query_devinfo,
+    0, /* not full duplex */
+    0
+};
+
+void vidcaudio_dummy_routine ( void *arg )
+{
+#ifdef DEBUG
+    printf ( "vidcaudio_dummy_routine\n" );
+#endif
+}
+
+int vidcaudio_hw_attach ( struct vidcaudio_softc *sc )
+{
+    return ( audio_hardware_attach ( &vidcaudio_hw_if, sc ) );
+}
+
+int vidcaudio_rate ( int rate )
+{
+    WriteWord ( VIDC_BASE, VIDC_SFR | rate );
+    return 0;
+}
+
+int vidcaudio_stereo ( int channel, int position )
+{
+    if ( channel<0 ) return EINVAL;
+    if ( channel>7 ) return EINVAL;
+    channel = channel<<24 | VIDC_SIR0;
+    WriteWord ( VIDC_BASE, channel|position );
+    return 0;
+}
+
+#define PHYS(x) (pmap_extract( kernel_pmap, ((x)&PG_FRAME) ))
+
+/*
+ * Program the next buffer to be used
+ * This function must be re-entrant, maximum re-entrancy of 2
+ */
+
+#define FLAGS (0)
+
+int vidcaudio_dma_program ( vm_offset_t cur, vm_offset_t end,
+                           void (*intr)(), void *arg )
+{
+    /* If there isn't a transfer in progress then start a new one */
+    if ( ag.in_progress==0 )
+    {
+       ag.buffer = 0;
+        WriteWord ( IOMD_SD0CR, 0x90 );        /* Reset State Machine */
+        WriteWord ( IOMD_SD0CR, 0x30 );        /* Reset State Machine */
+
+       WriteWord ( IOMD_SD0CURB, PHYS(cur) );
+        WriteWord ( IOMD_SD0ENDB, PHYS(end-16)|FLAGS );
+       WriteWord ( IOMD_SD0CURA, PHYS(cur) );
+        WriteWord ( IOMD_SD0ENDA, PHYS(end-16)|FLAGS );
+
+        ag.in_progress = 1;
+
+       ag.next_cur = ag.next_end = 0;
+        ag.next_intr = ag.next_arg = 0; 
+
+       ag.intr = intr;
+        ag.arg = arg;
+
+        /* The driver 'clicks' between buffer swaps, leading me to think */
+        /* that the fifo is much small than on other sound cards.  So    */
+        /* so I'm going to have to do some tricks here                   */
+
+        (*ag.intr)(ag.arg);                    /* Schedule the next buffer */
+       ag.intr = vidcaudio_dummy_routine;      /* Already done this        */
+       ag.arg = NULL;
+
+#ifdef PRINT
+printf ( "vidcaudio: start output\n" );
+#endif
+#ifdef DEBUG
+       printf ( "SE" );
+#endif
+        enable_irq ( IRQ_DMASCH0 );
+    }
+    else
+    {
+        /* Otherwise schedule the next one */
+       if ( ag.next_cur!=0 )
+       {
+           /* If there's one scheduled then complain */
+           printf ( "vidcaudio: Buffer already Q'ed\n" );
+           return EIO;
+       }
+       else
+       {
+           /* We're OK to schedule it now */
+            ag.buffer = (++ag.buffer) & 1;
+            ag.next_cur = PHYS(cur);
+            ag.next_end = PHYS(end-16);
+            ag.next_intr = intr;
+            ag.next_arg = arg;
+#ifdef DEBUG
+printf ( "s" );
+#endif
+       }
+    }
+    return 0;
+}
+
+void vidcaudio_shutdown ( void )
+{
+    /* Shut down the channel */
+    ag.intr = NULL;
+    ag.in_progress = 0;
+#ifdef PRINT
+printf ( "vidcaudio: stop output\n" );
+#endif
+    WriteWord ( IOMD_SD0CURB, ag.silence );
+    WriteWord ( IOMD_SD0ENDB, (ag.silence + NBPG - 16) | (1<<30) );
+    disable_irq ( IRQ_DMASCH0 );
+}
+
+int vidcaudio_intr ( void *arg )
+{
+    int status = ReadByte(IOMD_SD0ST);
+    void (*nintr)();
+    void *narg;
+    void (*xintr)();
+    void *xarg;
+    int xcur, xend;
+    WriteWord ( IOMD_DMARQ, 0x10 );
+
+#ifdef PRINT
+    printf ( "I" );
+#endif
+
+    if ( ag.open==0 )
+    {
+       vidcaudio_shutdown ();
+       return 0;
+    }
+
+    /* Have I got the generic audio device attached */
+
+#ifdef DEBUG
+    printf ( "[B%01x]", status );
+#endif
+
+    nintr=ag.intr;
+    narg=ag.arg;
+    ag.intr = NULL;
+
+    xintr=ag.next_intr;
+    xarg=ag.next_arg;
+    xcur=ag.next_cur;
+    xend=ag.next_end;
+       ag.next_cur = 0;
+        ag.intr = xintr;
+       ag.arg = xarg;
+
+    if ( nintr )
+    {
+#ifdef DEBUG
+       printf ( "i" );
+#endif
+       (*nintr)(narg);
+    }
+
+    if ( xcur==0 )
+    {
+       vidcaudio_shutdown ();
+    }
+    else
+    {
+#define OVERRUN        (0x04)
+#define INTERRUPT      (0x02)
+#define BANK_A         (0x00)
+#define BANK_B         (0x01)
+       switch ( status&0x7 )
+       {
+           case (INTERRUPT|BANK_A):
+#ifdef PRINT
+printf( "B" );
+#endif
+               WriteWord ( IOMD_SD0CURB, xcur );
+               WriteWord ( IOMD_SD0ENDB, xend|FLAGS );
+               break;
+
+           case (INTERRUPT|BANK_B):
+#ifdef PRINT
+printf( "A" );
+#endif
+               WriteWord ( IOMD_SD0CURA, xcur );
+               WriteWord ( IOMD_SD0ENDA, xend|FLAGS );
+               break;
+
+           case (OVERRUN|INTERRUPT|BANK_A):
+#ifdef PRINT
+printf( "A" );
+#endif
+               WriteWord ( IOMD_SD0CURA, xcur );
+               WriteWord ( IOMD_SD0ENDA, xend|FLAGS );
+               break;
+                
+           case (OVERRUN|INTERRUPT|BANK_B):
+#ifdef PRINT
+printf( "B" );
+#endif
+               WriteWord ( IOMD_SD0CURB, xcur );
+               WriteWord ( IOMD_SD0ENDB, xend|FLAGS );
+               break;
+       }
+/*
+       ag.next_cur = 0;
+        ag.intr = xintr;
+       ag.arg = xarg;
+*/
+    }
+#ifdef PRINT
+printf ( "i" );
+#endif
+
+    if ( ag.next_cur==0 )
+    {
+        (*ag.intr)(ag.arg);                    /* Schedule the next buffer */
+       ag.intr = vidcaudio_dummy_routine;      /* Already done this        */
+       ag.arg = NULL;
+    }
+    return 0;
+}
+
+
diff --git a/sys/arch/arm32/mainbus/waveform.h b/sys/arch/arm32/mainbus/waveform.h
new file mode 100644 (file)
index 0000000..1508a71
--- /dev/null
@@ -0,0 +1,551 @@
+/* $NetBSD: waveform.h,v 1.2 1996/03/18 20:50:06 mark Exp $ */
+
+/*
+ * Copyright (c) 1994,1995 Mark Brinicombe.
+ * Copyright (c) 1994 Brini.
+ * 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 Brini.
+ * 4. The name of the company nor the name of the author may be used to
+ *    endorse or promote products derived from this software without specific
+ *    prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BRINI ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL BRINI 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.
+ */
+
+static unsigned char beep_waveform[] = {
+    0x00, 0x06, 0x18, 0x2a, 0x3e, 0x4a, 0x54, 0x60,
+    0x64, 0x68, 0x6a, 0x6a, 0x66, 0x62, 0x54, 0x3e,
+    0x00, 0x45, 0x61, 0x6f, 0x7f, 0x87, 0x8d, 0x91,
+    0x93, 0x95, 0x93, 0x91, 0x8b, 0x85, 0x73, 0x59,
+    0x00, 0x5c, 0x78, 0x8a, 0x96, 0xa0, 0xa6, 0xa8,
+    0xaa, 0xaa, 0xa8, 0xa6, 0xa2, 0x94, 0x86, 0x6a,
+    0x00, 0x6b, 0x8b, 0x9d, 0xa7, 0xaf, 0xb5, 0xb9,
+    0xbb, 0xbb, 0xb9, 0xb3, 0xad, 0xa5, 0x93, 0x77,
+    0x00, 0x78, 0x96, 0xa8, 0xb2, 0xbc, 0xc2, 0xc4,
+    0xc6, 0xc6, 0xc4, 0xc0, 0xb8, 0xac, 0x9e, 0x82,
+    0x00, 0x83, 0xa3, 0xb1, 0xbf, 0xc5, 0xcb, 0xcd,
+    0xcf, 0xcf, 0xcd, 0xc9, 0xc3, 0xb7, 0xa7, 0x89,
+    0x00, 0x88, 0xa8, 0xb8, 0xc4, 0xcc, 0xd0, 0xd4,
+    0xd6, 0xd4, 0xd2, 0xce, 0xc8, 0xbe, 0xac, 0x8e,
+    0x00, 0x8f, 0xaf, 0xc3, 0xcb, 0xd3, 0xd9, 0xdd,
+    0xdf, 0xdd, 0xdb, 0xd5, 0xcf, 0xc5, 0xb3, 0x95,
+    0x00, 0x96, 0xb4, 0xc6, 0xd0, 0xd8, 0xe0, 0xe2,
+    0xe4, 0xe2, 0xe2, 0xdc, 0xd2, 0xc8, 0xb8, 0x9a,
+    0x00, 0x9d, 0xbb, 0xcb, 0xd7, 0xe1, 0xe5, 0xe7,
+    0xe9, 0xe7, 0xe5, 0xe3, 0xd9, 0xcf, 0xbf, 0xa1,
+    0x00, 0xa2, 0xc0, 0xce, 0xdc, 0xe4, 0xe8, 0xea,
+    0xec, 0xea, 0xe8, 0xe4, 0xde, 0xd2, 0xc2, 0xa4,
+    0x00, 0xa5, 0xc5, 0xd5, 0xe3, 0xe7, 0xed, 0xef,
+    0xf1, 0xef, 0xed, 0xe9, 0xe3, 0xd7, 0xc7, 0xa9,
+    0x00, 0xa8, 0xc6, 0xd8, 0xe4, 0xea, 0xee, 0xf2,
+    0xf4, 0xf2, 0xf0, 0xec, 0xe6, 0xda, 0xc8, 0xaa,
+    0x00, 0xab, 0xcb, 0xdd, 0xe7, 0xef, 0xf3, 0xf7,
+    0xf9, 0xf7, 0xf5, 0xef, 0xe9, 0xdf, 0xcd, 0xaf,
+    0x00, 0xae, 0xcc, 0xe0, 0xea, 0xf0, 0xf6, 0xfa,
+    0xfc, 0xfa, 0xf8, 0xf2, 0xea, 0xe2, 0xd0, 0xb0,
+    0x00, 0xb1, 0xd1, 0xe3, 0xed, 0xf5, 0xfb, 0xff,
+    0xff, 0xff, 0xfb, 0xf7, 0xef, 0xe5, 0xd3, 0xb5,
+    0x00, 0xb4, 0xd2, 0xe4, 0xee, 0xf6, 0xfc, 0xfe,
+    0xfe, 0xfe, 0xfc, 0xf6, 0xee, 0xe4, 0xd2, 0xb4,
+    0x00, 0xb5, 0xd3, 0xe5, 0xef, 0xf7, 0xfd, 0xff,
+    0xff, 0xff, 0xfd, 0xf7, 0xef, 0xe5, 0xd3, 0xb5,
+    0x00, 0xb4, 0xd2, 0xe4, 0xee, 0xf6, 0xfc, 0xfe,
+    0xfe, 0xfe, 0xfc, 0xf6, 0xee, 0xe4, 0xd2, 0xb4,
+    0x00, 0xb5, 0xd3, 0xe5, 0xef, 0xf7, 0xfd, 0xff,
+    0xff, 0xff, 0xfd, 0xf7, 0xef, 0xe5, 0xd3, 0xb5,
+    0x00, 0xb4, 0xd2, 0xe4, 0xee, 0xf6, 0xfc, 0xfe,
+    0xfe, 0xfe, 0xfc, 0xf6, 0xee, 0xe4, 0xd2, 0xb4,
+    0x00, 0xb5, 0xd3, 0xe5, 0xef, 0xf7, 0xfd, 0xff,
+    0xff, 0xff, 0xfd, 0xf7, 0xef, 0xe5, 0xd3, 0xb5,
+    0x00, 0xb4, 0xd2, 0xe4, 0xee, 0xf6, 0xfc, 0xfe,
+    0xfe, 0xfe, 0xfc, 0xf6, 0xee, 0xe4, 0xd2, 0xb4,
+    0x00, 0xb5, 0xd3, 0xe5, 0xef, 0xf7, 0xfd, 0xff,
+    0xff, 0xff, 0xfd, 0xf7, 0xef, 0xe5, 0xd3, 0xb5,
+    0x00, 0xb4, 0xd2, 0xe4, 0xee, 0xf6, 0xfc, 0xfe,
+    0xfe, 0xfe, 0xfc, 0xf6, 0xee, 0xe4, 0xd2, 0xb4,
+    0x00, 0xb5, 0xd3, 0xe5, 0xef, 0xf7, 0xfd, 0xff,
+    0xff, 0xff, 0xfd, 0xf7, 0xef, 0xe5, 0xd3, 0xb5,
+    0x00, 0xb4, 0xd2, 0xe4, 0xee, 0xf6, 0xfc, 0xfe,
+    0xfe, 0xfe, 0xfc, 0xf6, 0xee, 0xe4, 0xd2, 0xb4,
+    0x00, 0xb5, 0xd3, 0xe5, 0xef, 0xf7, 0xfd, 0xff,
+    0xff, 0xff, 0xfd, 0xf7, 0xef, 0xe5, 0xd3, 0xb5,
+    0x00, 0xb4, 0xd2, 0xe4, 0xee, 0xf6, 0xfc, 0xfe,
+    0xfe, 0xfe, 0xfc, 0xf6, 0xee, 0xe4, 0xd2, 0xb4,
+    0x00, 0xb5, 0xd3, 0xe5, 0xef, 0xf7, 0xfd, 0xff,
+    0xff, 0xff, 0xfd, 0xf7, 0xef, 0xe5, 0xd3, 0xb5,
+    0x00, 0xb4, 0xd2, 0xe4, 0xee, 0xf6, 0xfc, 0xfe,
+    0xfe, 0xfe, 0xfc, 0xf6, 0xee, 0xe4, 0xd2, 0xb4,
+    0x00, 0xb5, 0xd3, 0xe5, 0xef, 0xf7, 0xfd, 0xff,
+    0xff, 0xff, 0xfd, 0xf7, 0xef, 0xe5, 0xd3, 0xb5,
+    0x00, 0xb4, 0xd2, 0xe4, 0xee, 0xf6, 0xfc, 0xfe,
+    0xfe, 0xfe, 0xfc, 0xf6, 0xee, 0xe4, 0xd2, 0xb4,
+    0x00, 0xb5, 0xd3, 0xe5, 0xef, 0xf7, 0xfd, 0xff,
+    0xff, 0xff, 0xfd, 0xf7, 0xef, 0xe5, 0xd3, 0xb5,
+    0x00, 0xb4, 0xd2, 0xe4, 0xee, 0xf6, 0xfc, 0xfe,
+    0xfe, 0xfe, 0xfc, 0xf6, 0xee, 0xe4, 0xd2, 0xb4,
+    0x00, 0xb5, 0xd3, 0xe5, 0xef, 0xf7, 0xfd, 0xff,
+    0xff, 0xff, 0xfd, 0xf7, 0xef, 0xe5, 0xd3, 0xb5,
+    0x00, 0xb4, 0xd2, 0xe4, 0xee, 0xf6, 0xfc, 0xfe,
+    0xfe, 0xfe, 0xfc, 0xf6, 0xee, 0xe4, 0xd2, 0xb4,
+    0x00, 0xb5, 0xd3, 0xe5, 0xef, 0xf7, 0xfd, 0xff,
+    0xff, 0xff, 0xfd, 0xf7, 0xef, 0xe5, 0xd3, 0xb5,
+    0x00, 0xb4, 0xd2, 0xe4, 0xee, 0xf6, 0xfc, 0xfe,
+    0xfe, 0xfe, 0xfc, 0xf6, 0xee, 0xe4, 0xd2, 0xb4,
+    0x00, 0xb5, 0xd3, 0xe5, 0xef, 0xf7, 0xfd, 0xff,
+    0xff, 0xff, 0xfd, 0xf7, 0xef, 0xe5, 0xd3, 0xb5,
+    0x00, 0xb4, 0xd2, 0xe4, 0xee, 0xf6, 0xfc, 0xfe,
+    0xfe, 0xfe, 0xfc, 0xf6, 0xee, 0xe4, 0xd2, 0xb4,
+    0x00, 0xb5, 0xd3, 0xe5, 0xef, 0xf7, 0xfd, 0xff,
+    0xff, 0xff, 0xfd, 0xf7, 0xef, 0xe5, 0xd3, 0xb5,
+    0x00, 0xb4, 0xd2, 0xe4, 0xee, 0xf6, 0xfc, 0xfe,
+    0xfe, 0xfe, 0xfc, 0xf6, 0xee, 0xe4, 0xd2, 0xb4,
+    0x00, 0xb5, 0xd3, 0xe5, 0xef, 0xf7, 0xfd, 0xff,
+    0xff, 0xff, 0xfd, 0xf7, 0xef, 0xe5, 0xd3, 0xb5,
+    0x00, 0xb4, 0xd2, 0xe4, 0xee, 0xf6, 0xfc, 0xfe,
+    0xfe, 0xfe, 0xfc, 0xf6, 0xee, 0xe4, 0xd2, 0xb4,
+    0x00, 0xb5, 0xd3, 0xe5, 0xef, 0xf7, 0xfd, 0xff,
+    0xff, 0xff, 0xfd, 0xf7, 0xef, 0xe5, 0xd3, 0xb5,
+    0x00, 0xb4, 0xd2, 0xe4, 0xee, 0xf6, 0xfc, 0xfe,
+    0xfe, 0xfe, 0xfc, 0xf6, 0xee, 0xe4, 0xd2, 0xb4,
+    0x00, 0xb5, 0xd3, 0xe5, 0xef, 0xf7, 0xfd, 0xff,
+    0xff, 0xff, 0xfd, 0xf7, 0xef, 0xe5, 0xd3, 0xb5,
+    0x00, 0xb4, 0xd2, 0xe4, 0xee, 0xf6, 0xfc, 0xfe,
+    0xfe, 0xfe, 0xfc, 0xf6, 0xee, 0xe4, 0xd2, 0xb4,
+    0x00, 0xb5, 0xd3, 0xe5, 0xef, 0xf7, 0xfd, 0xff,
+    0xff, 0xff, 0xfd, 0xf7, 0xef, 0xe5, 0xd3, 0xb5,
+    0x00, 0xb4, 0xd2, 0xe4, 0xee, 0xf6, 0xfc, 0xfe,
+    0xfe, 0xfe, 0xfc, 0xf6, 0xee, 0xe4, 0xd2, 0xb4,
+    0x00, 0xb5, 0xd3, 0xe5, 0xef, 0xf7, 0xfd, 0xff,
+    0xff, 0xff, 0xfd, 0xf7, 0xef, 0xe5, 0xd3, 0xb5,
+    0x00, 0xb4, 0xd2, 0xe4, 0xee, 0xf6, 0xfc, 0xfe,
+    0xfe, 0xfe, 0xfc, 0xf6, 0xee, 0xe4, 0xd2, 0xb4,
+    0x00, 0xb5, 0xd3, 0xe5, 0xef, 0xf7, 0xfd, 0xff,
+    0xff, 0xff, 0xfd, 0xf7, 0xef, 0xe5, 0xd3, 0xb5,
+    0x00, 0xb4, 0xd2, 0xe4, 0xee, 0xf6, 0xfc, 0xfe,
+    0xfe, 0xfe, 0xfc, 0xf6, 0xee, 0xe4, 0xd2, 0xb4,
+    0x00, 0xb5, 0xd3, 0xe5, 0xef, 0xf7, 0xfd, 0xff,
+    0xff, 0xff, 0xfd, 0xf7, 0xef, 0xe5, 0xd3, 0xb5,
+    0x00, 0xb4, 0xd2, 0xe4, 0xee, 0xf6, 0xfc, 0xfe,
+    0xfe, 0xfe, 0xfc, 0xf6, 0xee, 0xe4, 0xd2, 0xb4,
+    0x00, 0xb5, 0xd3, 0xe5, 0xef, 0xf7, 0xfd, 0xff,
+    0xff, 0xff, 0xfd, 0xf7, 0xef, 0xe5, 0xd3, 0xb5,
+    0x00, 0xb4, 0xd2, 0xe4, 0xee, 0xf6, 0xfc, 0xfe,
+    0xfe, 0xfe, 0xfc, 0xf6, 0xee, 0xe4, 0xd2, 0xb4,
+    0x00, 0xb5, 0xd3, 0xe5, 0xef, 0xf7, 0xfd, 0xff,
+    0xff, 0xff, 0xfd, 0xf7, 0xef, 0xe5, 0xd3, 0xb5,
+    0x00, 0xb4, 0xd2, 0xe4, 0xee, 0xf6, 0xfc, 0xfe,
+    0xfe, 0xfe, 0xfc, 0xf6, 0xee, 0xe4, 0xd2, 0xb4,
+    0x00, 0xb5, 0xd3, 0xe5, 0xef, 0xf7, 0xfd, 0xff,
+    0xff, 0xff, 0xfd, 0xf7, 0xef, 0xe5, 0xd3, 0xb5,
+    0x00, 0xb4, 0xd2, 0xe4, 0xee, 0xf6, 0xfc, 0xfe,
+    0xfe, 0xfe, 0xfc, 0xf6, 0xee, 0xe4, 0xd2, 0xb4,
+    0x00, 0xb5, 0xd3, 0xe5, 0xef, 0xf7, 0xfd, 0xff,
+    0xff, 0xff, 0xfd, 0xf7, 0xef, 0xe5, 0xd3, 0xb5,
+    0x00, 0xb4, 0xd2, 0xe4, 0xee, 0xf6, 0xfc, 0xfe,
+    0xfe, 0xfe, 0xfc, 0xf6, 0xee, 0xe4, 0xd2, 0xb4,
+    0x00, 0xb5, 0xd3, 0xe5, 0xef, 0xf7, 0xfd, 0xff,
+    0xff, 0xff, 0xfd, 0xf7, 0xef, 0xe5, 0xd3, 0xb5,
+    0x00, 0xb4, 0xd2, 0xe4, 0xee, 0xf6, 0xfc, 0xfe,
+    0xfe, 0xfe, 0xfc, 0xf6, 0xee, 0xe4, 0xd2, 0xb4,
+    0x00, 0xb5, 0xd3, 0xe5, 0xef, 0xf7, 0xfd, 0xff,
+    0xff, 0xff, 0xfd, 0xf7, 0xef, 0xe5, 0xd3, 0xb5,
+    0x00, 0xb4, 0xd2, 0xe4, 0xee, 0xf6, 0xfc, 0xfe,
+    0xfe, 0xfe, 0xfc, 0xf6, 0xee, 0xe4, 0xd2, 0xb4,
+    0x00, 0xb5, 0xd3, 0xe5, 0xef, 0xf7, 0xfd, 0xff,
+    0xff, 0xff, 0xfd, 0xf7, 0xef, 0xe5, 0xd3, 0xb5,
+    0x00, 0xb4, 0xd2, 0xe4, 0xee, 0xf6, 0xfc, 0xfe,
+    0xfe, 0xfe, 0xfc, 0xf6, 0xee, 0xe4, 0xd2, 0xb4,
+    0x00, 0xb5, 0xd3, 0xe5, 0xef, 0xf7, 0xfd, 0xff,
+    0xff, 0xff, 0xfd, 0xf7, 0xef, 0xe5, 0xd3, 0xb5,
+    0x00, 0xb4, 0xd2, 0xe4, 0xee, 0xf6, 0xfc, 0xfe,
+    0xfe, 0xfe, 0xfc, 0xf6, 0xee, 0xe4, 0xd2, 0xb4,
+    0x00, 0xb5, 0xd3, 0xe5, 0xef, 0xf7, 0xfd, 0xff,
+    0xff, 0xff, 0xfd, 0xf7, 0xef, 0xe5, 0xd3, 0xb5,
+    0x00, 0xb4, 0xd2, 0xe4, 0xee, 0xf6, 0xfc, 0xfe,
+    0xfe, 0xfe, 0xfc, 0xf6, 0xee, 0xe4, 0xd2, 0xb4,
+    0x00, 0xb5, 0xd3, 0xe5, 0xef, 0xf7, 0xfd, 0xff,
+    0xff, 0xff, 0xfd, 0xf7, 0xef, 0xe5, 0xd3, 0xb5,
+    0x00, 0xb4, 0xd2, 0xe4, 0xee, 0xf6, 0xfc, 0xfe,
+    0xfe, 0xfe, 0xfc, 0xf6, 0xee, 0xe4, 0xd2, 0xb4,
+    0x00, 0xb5, 0xd3, 0xe5, 0xef, 0xf7, 0xfd, 0xff,
+    0xff, 0xff, 0xfd, 0xf7, 0xef, 0xe5, 0xd3, 0xb5,
+    0x00, 0xb4, 0xd2, 0xe4, 0xee, 0xf6, 0xfc, 0xfe,
+    0xfe, 0xfe, 0xfc, 0xf6, 0xee, 0xe4, 0xd2, 0xb4,
+    0x00, 0xb5, 0xd3, 0xe5, 0xef, 0xf7, 0xfd, 0xff,
+    0xff, 0xff, 0xfd, 0xf7, 0xef, 0xe5, 0xd3, 0xb5,
+    0x00, 0xb4, 0xd2, 0xe4, 0xee, 0xf6, 0xfc, 0xfe,
+    0xfe, 0xfe, 0xfc, 0xf6, 0xee, 0xe4, 0xd2, 0xb4,
+    0x00, 0xb5, 0xd3, 0xe5, 0xef, 0xf7, 0xfd, 0xff,
+    0xff, 0xff, 0xfd, 0xf7, 0xef, 0xe5, 0xd3, 0xb5,
+    0x00, 0xb4, 0xd2, 0xe4, 0xee, 0xf6, 0xfc, 0xfe,
+    0xfe, 0xfe, 0xfc, 0xf6, 0xee, 0xe4, 0xd2, 0xb4,
+    0x00, 0xb5, 0xd3, 0xe5, 0xef, 0xf7, 0xfd, 0xff,
+    0xff, 0xff, 0xfd, 0xf7, 0xef, 0xe5, 0xd3, 0xb5,
+    0x00, 0xb4, 0xd2, 0xe4, 0xee, 0xf6, 0xfc, 0xfe,
+    0xfe, 0xfe, 0xfc, 0xf6, 0xee, 0xe4, 0xd2, 0xb4,
+    0x00, 0xb5, 0xd3, 0xe5, 0xef, 0xf7, 0xfd, 0xff,
+    0xff, 0xff, 0xfd, 0xf7, 0xef, 0xe5, 0xd3, 0xb5,
+    0x00, 0xb4, 0xd2, 0xe4, 0xee, 0xf6, 0xfc, 0xfe,
+    0xfe, 0xfe, 0xfc, 0xf6, 0xee, 0xe4, 0xd2, 0xb4,
+    0x00, 0xb5, 0xd3, 0xe5, 0xef, 0xf7, 0xfd, 0xff,
+    0xff, 0xff, 0xfd, 0xf7, 0xef, 0xe5, 0xd3, 0xb5,
+    0x00, 0xb4, 0xd2, 0xe4, 0xee, 0xf6, 0xfc, 0xfe,
+    0xfe, 0xfe, 0xfc, 0xf6, 0xee, 0xe4, 0xd2, 0xb4,
+    0x00, 0xb5, 0xd3, 0xe5, 0xef, 0xf7, 0xfd, 0xff,
+    0xff, 0xff, 0xfd, 0xf7, 0xef, 0xe5, 0xd3, 0xb5,
+    0x00, 0xb4, 0xd2, 0xe4, 0xee, 0xf6, 0xfc, 0xfe,
+    0xfe, 0xfe, 0xfc, 0xf6, 0xee, 0xe4, 0xd2, 0xb4,
+    0x00, 0xb5, 0xd3, 0xe5, 0xef, 0xf7, 0xfd, 0xff,
+    0xff, 0xff, 0xfd, 0xf7, 0xef, 0xe5, 0xd3, 0xb5,
+    0x00, 0xb4, 0xd2, 0xe4, 0xee, 0xf6, 0xfc, 0xfe,
+    0xfe, 0xfe, 0xfc, 0xf6, 0xee, 0xe4, 0xd2, 0xb4,
+    0x00, 0xb5, 0xd3, 0xe5, 0xef, 0xf7, 0xfd, 0xff,
+    0xff, 0xff, 0xfd, 0xf7, 0xef, 0xe5, 0xd3, 0xb5,
+    0x00, 0xb4, 0xd2, 0xe4, 0xee, 0xf6, 0xfc, 0xfe,
+    0xfe, 0xfe, 0xfc, 0xf6, 0xee, 0xe4, 0xd2, 0xb4,
+    0x00, 0xb5, 0xd3, 0xe5, 0xef, 0xf7, 0xfd, 0xff,
+    0xff, 0xff, 0xfd, 0xf7, 0xef, 0xe5, 0xd3, 0xb5,
+    0x00, 0xb4, 0xd2, 0xe4, 0xee, 0xf6, 0xfc, 0xfe,
+    0xfe, 0xfe, 0xfc, 0xf6, 0xee, 0xe4, 0xd2, 0xb4,
+    0x00, 0xb5, 0xd3, 0xe5, 0xef, 0xf7, 0xfd, 0xff,
+    0xff, 0xff, 0xfd, 0xf7, 0xef, 0xe5, 0xd3, 0xb5,
+    0x00, 0xb4, 0xd2, 0xe4, 0xee, 0xf6, 0xfc, 0xfe,
+    0xfe, 0xfe, 0xfc, 0xf6, 0xee, 0xe4, 0xd2, 0xb4,
+    0x00, 0xb5, 0xd3, 0xe5, 0xef, 0xf7, 0xfd, 0xff,
+    0xff, 0xff, 0xfd, 0xf7, 0xef, 0xe5, 0xd3, 0xb5,
+    0x00, 0xb4, 0xd2, 0xe4, 0xee, 0xf6, 0xfc, 0xfe,
+    0xfe, 0xfe, 0xfc, 0xf6, 0xee, 0xe4, 0xd2, 0xb4,
+    0x00, 0xb5, 0xd3, 0xe5, 0xef, 0xf7, 0xfd, 0xff,
+    0xff, 0xff, 0xfd, 0xf7, 0xef, 0xe5, 0xd3, 0xb5,
+    0x00, 0xb4, 0xd2, 0xe4, 0xee, 0xf6, 0xfc, 0xfe,
+    0xfe, 0xfe, 0xfc, 0xf6, 0xee, 0xe4, 0xd2, 0xb4,
+    0x00, 0xb5, 0xd3, 0xe5, 0xef, 0xf7, 0xfd, 0xff,
+    0xff, 0xff, 0xfd, 0xf7, 0xef, 0xe5, 0xd3, 0xb5,
+    0x00, 0xb4, 0xd2, 0xe4, 0xee, 0xf6, 0xfc, 0xfe,
+    0xfe, 0xfe, 0xfc, 0xf6, 0xee, 0xe4, 0xd2, 0xb4,
+    0x00, 0xb5, 0xd3, 0xe5, 0xef, 0xf7, 0xfd, 0xff,
+    0xff, 0xff, 0xfd, 0xf7, 0xef, 0xe5, 0xd3, 0xb5,
+    0x00, 0xb4, 0xd2, 0xe4, 0xee, 0xf6, 0xfc, 0xfe,
+    0xfe, 0xfe, 0xfc, 0xf6, 0xee, 0xe4, 0xd2, 0xb4,
+    0x00, 0xb5, 0xd3, 0xe5, 0xef, 0xf7, 0xfd, 0xff,
+    0xff, 0xff, 0xfd, 0xf7, 0xef, 0xe5, 0xd3, 0xb5,
+    0x00, 0xb4, 0xd2, 0xe4, 0xee, 0xf6, 0xfc, 0xfe,
+    0xfe, 0xfe, 0xfc, 0xf6, 0xee, 0xe4, 0xd2, 0xb4,
+    0x00, 0xb5, 0xd3, 0xe5, 0xef, 0xf7, 0xfd, 0xff,
+    0xff, 0xff, 0xfd, 0xf7, 0xef, 0xe5, 0xd3, 0xb5,
+    0x00, 0xb4, 0xd2, 0xe4, 0xee, 0xf6, 0xfc, 0xfe,
+    0xfe, 0xfe, 0xfc, 0xf6, 0xee, 0xe4, 0xd2, 0xb4,
+    0x00, 0xb5, 0xd3, 0xe5, 0xef, 0xf7, 0xfd, 0xff,
+    0xff, 0xff, 0xfd, 0xf7, 0xef, 0xe5, 0xd3, 0xb5,
+    0x00, 0xb4, 0xd2, 0xe4, 0xee, 0xf6, 0xfc, 0xfe,
+    0xfe, 0xfe, 0xfc, 0xf6, 0xee, 0xe4, 0xd2, 0xb4,
+    0x00, 0xb5, 0xd3, 0xe5, 0xef, 0xf7, 0xfd, 0xff,
+    0xff, 0xff, 0xfd, 0xf7, 0xef, 0xe5, 0xd3, 0xb5,
+    0x00, 0xb4, 0xd2, 0xe4, 0xee, 0xf6, 0xfc, 0xfe,
+    0xfe, 0xfe, 0xfc, 0xf6, 0xee, 0xe4, 0xd2, 0xb4,
+    0x00, 0xb5, 0xd3, 0xe5, 0xef, 0xf7, 0xfd, 0xff,
+    0xff, 0xff, 0xfd, 0xf7, 0xef, 0xe5, 0xd3, 0xb5,
+    0x00, 0xb4, 0xd2, 0xe4, 0xee, 0xf6, 0xfc, 0xfe,
+    0xfe, 0xfe, 0xfc, 0xf6, 0xee, 0xe4, 0xd2, 0xb4,
+    0x00, 0xb5, 0xd3, 0xe5, 0xef, 0xf7, 0xfd, 0xff,
+    0xff, 0xff, 0xfd, 0xf7, 0xef, 0xe5, 0xd3, 0xb5,
+    0x00, 0xb4, 0xd2, 0xe4, 0xee, 0xf6, 0xfc, 0xfe,
+    0xfe, 0xfe, 0xfc, 0xf6, 0xee, 0xe4, 0xd2, 0xb4,
+    0x00, 0xb5, 0xd3, 0xe5, 0xef, 0xf7, 0xfd, 0xff,
+    0xff, 0xff, 0xfd, 0xf7, 0xef, 0xe5, 0xd3, 0xb5,
+    0x00, 0xb4, 0xd2, 0xe4, 0xee, 0xf6, 0xfc, 0xfe,
+    0xfe, 0xfe, 0xfc, 0xf6, 0xee, 0xe4, 0xd2, 0xb4,
+    0x00, 0xb5, 0xd3, 0xe5, 0xef, 0xf7, 0xfd, 0xff,
+    0xff, 0xff, 0xfd, 0xf7, 0xef, 0xe5, 0xd3, 0xb5,
+    0x00, 0xb4, 0xd2, 0xe4, 0xee, 0xf6, 0xfc, 0xfe,
+    0xfe, 0xfe, 0xfc, 0xf6, 0xee, 0xe4, 0xd2, 0xb4,
+    0x00, 0xb5, 0xd3, 0xe5, 0xef, 0xf7, 0xfd, 0xff,
+    0xff, 0xff, 0xfd, 0xf7, 0xef, 0xe5, 0xd3, 0xb5,
+    0x00, 0xb4, 0xd2, 0xe4, 0xee, 0xf6, 0xfc, 0xfe,
+    0xfe, 0xfe, 0xfc, 0xf6, 0xee, 0xe4, 0xd2, 0xb4,
+    0x00, 0xb5, 0xd3, 0xe5, 0xef, 0xf7, 0xfd, 0xff,
+    0xff, 0xff, 0xfd, 0xf7, 0xef, 0xe5, 0xd3, 0xb5,
+    0x00, 0xb4, 0xd2, 0xe4, 0xee, 0xf6, 0xfc, 0xfe,
+    0xfe, 0xfe, 0xfc, 0xf6, 0xee, 0xe4, 0xd2, 0xb4,
+    0x00, 0xb5, 0xd3, 0xe5, 0xef, 0xf7, 0xfd, 0xff,
+    0xff, 0xff, 0xfd, 0xf7, 0xef, 0xe5, 0xd3, 0xb5,
+    0x00, 0xb4, 0xd2, 0xe4, 0xee, 0xf6, 0xfc, 0xfe,
+    0xfe, 0xfe, 0xfc, 0xf6, 0xee, 0xe4, 0xd2, 0xb4,
+    0x00, 0xb5, 0xd3, 0xe5, 0xef, 0xf7, 0xfd, 0xff,
+    0xff, 0xff, 0xfd, 0xf7, 0xef, 0xe5, 0xd3, 0xb5,
+    0x00, 0xb4, 0xd2, 0xe4, 0xee, 0xf6, 0xfc, 0xfe,
+    0xfe, 0xfe, 0xfc, 0xf6, 0xee, 0xe4, 0xd2, 0xb2,
+    0x00, 0xb3, 0xd3, 0xe5, 0xef, 0xf7, 0xfb, 0xff,
+    0xff, 0xff, 0xfb, 0xf5, 0xef, 0xe5, 0xd1, 0xb3,
+    0x00, 0xb2, 0xd0, 0xe4, 0xec, 0xf4, 0xfa, 0xfe,
+    0xfe, 0xfe, 0xfa, 0xf4, 0xec, 0xe4, 0xd0, 0xb2,
+    0x00, 0xb3, 0xd1, 0xe5, 0xed, 0xf5, 0xfb, 0xff,
+    0xff, 0xff, 0xfb, 0xf5, 0xed, 0xe5, 0xd1, 0xb3,
+    0x00, 0xb2, 0xd0, 0xe4, 0xec, 0xf4, 0xfa, 0xfc,
+    0xfe, 0xfc, 0xfa, 0xf4, 0xec, 0xe2, 0xd0, 0xb2,
+    0x00, 0xb3, 0xd1, 0xe3, 0xed, 0xf5, 0xf9, 0xfd,
+    0xff, 0xfd, 0xf9, 0xf5, 0xed, 0xe3, 0xd1, 0xb1,
+    0x00, 0xb0, 0xd0, 0xe2, 0xec, 0xf2, 0xf8, 0xfc,
+    0xfc, 0xfc, 0xf8, 0xf2, 0xec, 0xe2, 0xd0, 0xb0,
+    0x00, 0xb1, 0xcf, 0xe3, 0xed, 0xf3, 0xf9, 0xfd,
+    0xfd, 0xfd, 0xf9, 0xf3, 0xed, 0xe3, 0xcf, 0xb1,
+    0x00, 0xb0, 0xce, 0xe2, 0xea, 0xf2, 0xf8, 0xfa,
+    0xfc, 0xfa, 0xf8, 0xf2, 0xea, 0xe2, 0xce, 0xb0,
+    0x00, 0xb1, 0xcf, 0xe3, 0xeb, 0xf3, 0xf9, 0xfb,
+    0xfd, 0xfb, 0xf7, 0xf3, 0xeb, 0xe3, 0xcf, 0xb1,
+    0x00, 0xb0, 0xce, 0xe2, 0xea, 0xf2, 0xf6, 0xfa,
+    0xfa, 0xfa, 0xf6, 0xf2, 0xea, 0xe2, 0xce, 0xae,
+    0x00, 0xaf, 0xcf, 0xe3, 0xeb, 0xf1, 0xf7, 0xfb,
+    0xfb, 0xfb, 0xf7, 0xf1, 0xeb, 0xe1, 0xcf, 0xaf,
+    0x00, 0xae, 0xce, 0xe0, 0xea, 0xf0, 0xf6, 0xf8,
+    0xfa, 0xf8, 0xf6, 0xf0, 0xea, 0xe0, 0xcc, 0xae,
+    0x00, 0xaf, 0xcd, 0xe1, 0xeb, 0xf1, 0xf7, 0xf9,
+    0xfb, 0xf9, 0xf7, 0xf1, 0xe9, 0xe1, 0xcd, 0xaf,
+    0x00, 0xae, 0xcc, 0xe0, 0xe8, 0xf0, 0xf4, 0xf8,
+    0xf8, 0xf8, 0xf4, 0xf0, 0xe8, 0xe0, 0xcc, 0xae,
+    0x00, 0xaf, 0xcd, 0xe1, 0xe9, 0xf1, 0xf5, 0xf9,
+    0xf9, 0xf9, 0xf5, 0xf1, 0xe9, 0xdf, 0xcd, 0xad,
+    0x00, 0xac, 0xcc, 0xde, 0xe8, 0xee, 0xf4, 0xf6,
+    0xf8, 0xf6, 0xf4, 0xee, 0xe8, 0xde, 0xcc, 0xac,
+    0x00, 0xad, 0xcd, 0xdf, 0xe9, 0xef, 0xf5, 0xf7,
+    0xf9, 0xf7, 0xf5, 0xef, 0xe9, 0xdf, 0xcb, 0xad,
+    0x00, 0xac, 0xca, 0xde, 0xe8, 0xee, 0xf2, 0xf6,
+    0xf6, 0xf6, 0xf2, 0xee, 0xe8, 0xde, 0xca, 0xac,
+    0x00, 0xad, 0xcb, 0xdd, 0xe7, 0xef, 0xf3, 0xf7,
+    0xf7, 0xf7, 0xf3, 0xef, 0xe7, 0xdd, 0xcb, 0xad,
+    0x00, 0xac, 0xca, 0xdc, 0xe6, 0xee, 0xf2, 0xf4,
+    0xf6, 0xf4, 0xf2, 0xee, 0xe6, 0xdc, 0xca, 0xaa,
+    0x00, 0xab, 0xcb, 0xdd, 0xe7, 0xed, 0xf3, 0xf5,
+    0xf7, 0xf5, 0xf3, 0xed, 0xe7, 0xdd, 0xcb, 0xab,
+    0x00, 0xaa, 0xca, 0xdc, 0xe6, 0xec, 0xf2, 0xf4,
+    0xf4, 0xf4, 0xf0, 0xec, 0xe6, 0xda, 0xc8, 0xaa,
+    0x00, 0xab, 0xc9, 0xdb, 0xe7, 0xed, 0xf1, 0xf5,
+    0xf5, 0xf5, 0xf1, 0xed, 0xe7, 0xdb, 0xc9, 0xab,
+    0x00, 0xaa, 0xc8, 0xda, 0xe6, 0xec, 0xf0, 0xf4,
+    0xf4, 0xf2, 0xf0, 0xec, 0xe6, 0xda, 0xc8, 0xaa,
+    0x00, 0xab, 0xc9, 0xdb, 0xe5, 0xed, 0xf1, 0xf3,
+    0xf5, 0xf3, 0xf1, 0xeb, 0xe5, 0xdb, 0xc9, 0xa9,
+    0x00, 0xa8, 0xc8, 0xd8, 0xe4, 0xea, 0xf0, 0xf2,
+    0xf2, 0xf2, 0xf0, 0xea, 0xe4, 0xd8, 0xc8, 0xa8,
+    0x00, 0xa9, 0xc9, 0xd9, 0xe5, 0xeb, 0xef, 0xf3,
+    0xf3, 0xf3, 0xef, 0xeb, 0xe5, 0xd9, 0xc9, 0xa9,
+    0x00, 0xa8, 0xc6, 0xd8, 0xe4, 0xea, 0xee, 0xf2,
+    0xf2, 0xf2, 0xee, 0xea, 0xe4, 0xd8, 0xc6, 0xa8,
+    0x00, 0xa9, 0xc7, 0xd9, 0xe5, 0xeb, 0xef, 0xf1,
+    0xf3, 0xf1, 0xef, 0xeb, 0xe5, 0xd7, 0xc7, 0xa9,
+    0x00, 0xa8, 0xc6, 0xd6, 0xe4, 0xea, 0xee, 0xf0,
+    0xf0, 0xf0, 0xee, 0xe8, 0xe2, 0xd6, 0xc6, 0xa8,
+    0x00, 0xa7, 0xc7, 0xd7, 0xe3, 0xe9, 0xed, 0xf1,
+    0xf1, 0xf1, 0xed, 0xe9, 0xe3, 0xd7, 0xc7, 0xa7,
+    0x00, 0xa6, 0xc6, 0xd6, 0xe2, 0xe8, 0xec, 0xf0,
+    0xf0, 0xf0, 0xec, 0xe8, 0xe2, 0xd6, 0xc6, 0xa6,
+    0x00, 0xa7, 0xc5, 0xd7, 0xe3, 0xe9, 0xed, 0xef,
+    0xf1, 0xef, 0xed, 0xe9, 0xe3, 0xd5, 0xc5, 0xa7,
+    0x00, 0xa6, 0xc4, 0xd4, 0xe2, 0xe8, 0xec, 0xee,
+    0xee, 0xee, 0xec, 0xe8, 0xe2, 0xd4, 0xc4, 0xa6,
+    0x00, 0xa7, 0xc5, 0xd5, 0xe3, 0xe7, 0xed, 0xef,
+    0xef, 0xef, 0xeb, 0xe7, 0xe3, 0xd5, 0xc5, 0xa7,
+    0x00, 0xa6, 0xc4, 0xd4, 0xe0, 0xe6, 0xea, 0xee,
+    0xee, 0xee, 0xea, 0xe6, 0xe0, 0xd4, 0xc4, 0xa4,
+    0x00, 0xa5, 0xc5, 0xd3, 0xe1, 0xe7, 0xeb, 0xed,
+    0xef, 0xed, 0xeb, 0xe7, 0xe1, 0xd3, 0xc5, 0xa5,
+    0x00, 0xa4, 0xc4, 0xd2, 0xe0, 0xe6, 0xea, 0xec,
+    0xec, 0xec, 0xea, 0xe6, 0xe0, 0xd2, 0xc2, 0xa4,
+    0x00, 0xa5, 0xc3, 0xd3, 0xdf, 0xe7, 0xeb, 0xed,
+    0xed, 0xed, 0xeb, 0xe7, 0xdf, 0xd3, 0xc3, 0xa5,
+    0x00, 0xa4, 0xc2, 0xd2, 0xde, 0xe4, 0xe8, 0xec,
+    0xec, 0xec, 0xe8, 0xe4, 0xde, 0xd0, 0xc2, 0xa4,
+    0x00, 0xa5, 0xc3, 0xd1, 0xdf, 0xe5, 0xe9, 0xeb,
+    0xed, 0xeb, 0xe9, 0xe5, 0xdf, 0xd1, 0xc3, 0xa3,
+    0x00, 0xa2, 0xc2, 0xd0, 0xdc, 0xe4, 0xe8, 0xea,
+    0xea, 0xea, 0xe8, 0xe4, 0xdc, 0xd0, 0xc2, 0xa2,
+    0x00, 0xa3, 0xc3, 0xd1, 0xdd, 0xe5, 0xe9, 0xeb,
+    0xeb, 0xeb, 0xe9, 0xe5, 0xdd, 0xd1, 0xc1, 0xa3,
+    0x00, 0xa2, 0xc0, 0xce, 0xdc, 0xe4, 0xe6, 0xea,
+    0xea, 0xea, 0xe6, 0xe4, 0xda, 0xce, 0xc0, 0xa2,
+    0x00, 0xa3, 0xc1, 0xcf, 0xdb, 0xe3, 0xe7, 0xe9,
+    0xeb, 0xe9, 0xe7, 0xe3, 0xdb, 0xcf, 0xc1, 0xa3,
+    0x00, 0xa2, 0xc0, 0xce, 0xda, 0xe2, 0xe6, 0xe8,
+    0xe8, 0xe8, 0xe6, 0xe2, 0xda, 0xce, 0xbe, 0xa0,
+    0x00, 0xa1, 0xbf, 0xcf, 0xdb, 0xe3, 0xe7, 0xe9,
+    0xe9, 0xe9, 0xe7, 0xe3, 0xd9, 0xcd, 0xbf, 0xa1,
+    0x00, 0xa0, 0xbe, 0xcc, 0xd8, 0xe2, 0xe6, 0xe8,
+    0xe8, 0xe8, 0xe4, 0xe2, 0xd8, 0xcc, 0xbc, 0x9e,
+    0x00, 0x9f, 0xbd, 0xcd, 0xd9, 0xe3, 0xe5, 0xe7,
+    0xe9, 0xe7, 0xe5, 0xe1, 0xd9, 0xcd, 0xbd, 0x9f,
+    0x00, 0x9e, 0xbc, 0xcc, 0xd8, 0xe0, 0xe4, 0xe6,
+    0xe6, 0xe6, 0xe4, 0xe0, 0xd6, 0xcc, 0xbc, 0x9e,
+    0x00, 0x9f, 0xbd, 0xcd, 0xd7, 0xe1, 0xe5, 0xe7,
+    0xe7, 0xe7, 0xe5, 0xe1, 0xd7, 0xcb, 0xbb, 0x9d,
+    0x00, 0x9c, 0xba, 0xca, 0xd6, 0xde, 0xe4, 0xe6,
+    0xe6, 0xe6, 0xe4, 0xde, 0xd6, 0xca, 0xba, 0x9c,
+    0x00, 0x9d, 0xbb, 0xcb, 0xd5, 0xdf, 0xe3, 0xe5,
+    0xe7, 0xe5, 0xe3, 0xdf, 0xd5, 0xcb, 0xbb, 0x9d,
+    0x00, 0x9a, 0xb8, 0xca, 0xd4, 0xde, 0xe2, 0xe4,
+    0xe4, 0xe4, 0xe2, 0xdc, 0xd4, 0xca, 0xb8, 0x9a,
+    0x00, 0x9b, 0xb9, 0xc9, 0xd5, 0xdd, 0xe3, 0xe5,
+    0xe5, 0xe5, 0xe3, 0xdd, 0xd5, 0xc9, 0xb9, 0x9b,
+    0x00, 0x9a, 0xb8, 0xc8, 0xd2, 0xdc, 0xe2, 0xe4,
+    0xe4, 0xe4, 0xe2, 0xdc, 0xd2, 0xc8, 0xb6, 0x98,
+    0x00, 0x99, 0xb7, 0xc9, 0xd3, 0xdb, 0xe1, 0xe3,
+    0xe5, 0xe3, 0xe1, 0xdb, 0xd3, 0xc9, 0xb7, 0x99,
+    0x00, 0x98, 0xb6, 0xc8, 0xd2, 0xda, 0xe0, 0xe2,
+    0xe2, 0xe2, 0xe0, 0xda, 0xd2, 0xc6, 0xb6, 0x98,
+    0x00, 0x99, 0xb7, 0xc7, 0xd1, 0xd9, 0xdf, 0xe3,
+    0xe3, 0xe3, 0xdf, 0xd9, 0xd1, 0xc7, 0xb5, 0x97,
+    0x00, 0x96, 0xb4, 0xc6, 0xd0, 0xd8, 0xde, 0xe2,
+    0xe2, 0xe2, 0xde, 0xd8, 0xd0, 0xc6, 0xb4, 0x96,
+    0x00, 0x97, 0xb5, 0xc7, 0xd1, 0xd9, 0xdf, 0xe1,
+    0xe3, 0xe1, 0xdd, 0xd7, 0xcf, 0xc7, 0xb3, 0x95,
+    0x00, 0x94, 0xb2, 0xc4, 0xce, 0xd6, 0xdc, 0xe0,
+    0xe0, 0xe0, 0xdc, 0xd6, 0xce, 0xc4, 0xb2, 0x94,
+    0x00, 0x95, 0xb3, 0xc5, 0xcf, 0xd7, 0xdd, 0xdf,
+    0xe1, 0xdf, 0xdd, 0xd7, 0xcf, 0xc5, 0xb3, 0x95,
+    0x00, 0x94, 0xb2, 0xc4, 0xce, 0xd4, 0xda, 0xde,
+    0xde, 0xde, 0xda, 0xd4, 0xcc, 0xc4, 0xb0, 0x92,
+    0x00, 0x93, 0xb1, 0xc5, 0xcd, 0xd5, 0xdb, 0xdd,
+    0xdf, 0xdd, 0xdb, 0xd5, 0xcd, 0xc3, 0xb1, 0x93,
+    0x00, 0x92, 0xb0, 0xc2, 0xcc, 0xd4, 0xd8, 0xdc,
+    0xdc, 0xdc, 0xd8, 0xd2, 0xcc, 0xc2, 0xb0, 0x90,
+    0x00, 0x91, 0xaf, 0xc3, 0xcb, 0xd3, 0xd9, 0xdb,
+    0xdd, 0xdb, 0xd9, 0xd3, 0xcb, 0xc3, 0xaf, 0x91,
+    0x00, 0x90, 0xae, 0xc2, 0xca, 0xd2, 0xd6, 0xda,
+    0xda, 0xda, 0xd6, 0xd2, 0xca, 0xc2, 0xae, 0x90,
+    0x00, 0x91, 0xaf, 0xc3, 0xcb, 0xd1, 0xd7, 0xd9,
+    0xdb, 0xd9, 0xd7, 0xd1, 0xcb, 0xc1, 0xad, 0x8f,
+    0x00, 0x8e, 0xac, 0xc0, 0xc8, 0xd0, 0xd4, 0xd8,
+    0xd8, 0xd8, 0xd4, 0xd0, 0xc8, 0xc0, 0xac, 0x8e,
+    0x00, 0x8f, 0xad, 0xbf, 0xc9, 0xcf, 0xd5, 0xd7,
+    0xd9, 0xd7, 0xd5, 0xcf, 0xc9, 0xbf, 0xad, 0x8f,
+    0x00, 0x8c, 0xac, 0xbe, 0xc8, 0xce, 0xd2, 0xd6,
+    0xd6, 0xd6, 0xd2, 0xce, 0xc8, 0xbe, 0xaa, 0x8c,
+    0x00, 0x8d, 0xab, 0xbd, 0xc7, 0xcf, 0xd3, 0xd5,
+    0xd7, 0xd5, 0xd3, 0xcd, 0xc7, 0xbd, 0xab, 0x8d,
+    0x00, 0x8c, 0xaa, 0xbc, 0xc6, 0xcc, 0xd2, 0xd4,
+    0xd4, 0xd4, 0xd0, 0xcc, 0xc6, 0xba, 0xaa, 0x8a,
+    0x00, 0x8b, 0xa9, 0xbb, 0xc7, 0xcd, 0xd1, 0xd5,
+    0xd5, 0xd3, 0xd1, 0xcd, 0xc5, 0xbb, 0xa9, 0x8b,
+    0x00, 0x8a, 0xa8, 0xba, 0xc4, 0xca, 0xd0, 0xd2,
+    0xd2, 0xd2, 0xd0, 0xca, 0xc4, 0xb8, 0xa8, 0x8a,
+    0x00, 0x8b, 0xa9, 0xb9, 0xc5, 0xcb, 0xcf, 0xd3,
+    0xd3, 0xd1, 0xcf, 0xcb, 0xc5, 0xb9, 0xa7, 0x89,
+    0x00, 0x88, 0xa6, 0xb8, 0xc4, 0xca, 0xce, 0xd0,
+    0xd0, 0xd0, 0xce, 0xc8, 0xc2, 0xb6, 0xa6, 0x88,
+    0x00, 0x89, 0xa7, 0xb7, 0xc3, 0xc9, 0xcd, 0xd1,
+    0xd1, 0xcf, 0xcd, 0xc9, 0xc3, 0xb7, 0xa7, 0x87,
+    0x00, 0x86, 0xa6, 0xb4, 0xc2, 0xc8, 0xcc, 0xce,
+    0xce, 0xce, 0xcc, 0xc8, 0xc2, 0xb4, 0xa4, 0x86,
+    0x00, 0x87, 0xa5, 0xb5, 0xc3, 0xc7, 0xcb, 0xcf,
+    0xcf, 0xcf, 0xcb, 0xc7, 0xc1, 0xb5, 0xa5, 0x87,
+    0x00, 0x86, 0xa4, 0xb2, 0xc0, 0xc6, 0xca, 0xcc,
+    0xcc, 0xcc, 0xca, 0xc6, 0xc0, 0xb2, 0xa2, 0x84,
+    0x00, 0x85, 0xa3, 0xb3, 0xbf, 0xc5, 0xc9, 0xcd,
+    0xcd, 0xcd, 0xc9, 0xc5, 0xbf, 0xb1, 0xa3, 0x85,
+    0x00, 0x84, 0xa2, 0xb0, 0xbc, 0xc4, 0xc8, 0xca,
+    0xca, 0xca, 0xc8, 0xc4, 0xbc, 0xb0, 0xa2, 0x82,
+    0x00, 0x83, 0xa3, 0xb1, 0xbd, 0xc5, 0xc7, 0xcb,
+    0xcb, 0xcb, 0xc7, 0xc3, 0xbb, 0xaf, 0xa1, 0x83,
+    0x00, 0x82, 0xa0, 0xae, 0xba, 0xc2, 0xc6, 0xc8,
+    0xc8, 0xc8, 0xc6, 0xc2, 0xba, 0xae, 0x9e, 0x82,
+    0x00, 0x83, 0x9f, 0xaf, 0xb9, 0xc3, 0xc7, 0xc9,
+    0xc9, 0xc9, 0xc5, 0xc3, 0xb9, 0xad, 0x9f, 0x81,
+    0x00, 0x80, 0x9c, 0xac, 0xb8, 0xc0, 0xc4, 0xc6,
+    0xc6, 0xc6, 0xc4, 0xc0, 0xb6, 0xac, 0x9c, 0x7e,
+    0x00, 0x7f, 0x9d, 0xab, 0xb7, 0xbf, 0xc5, 0xc7,
+    0xc7, 0xc7, 0xc5, 0xbf, 0xb7, 0xab, 0x9b, 0x7d,
+    0x00, 0x7c, 0x9a, 0xaa, 0xb4, 0xbe, 0xc2, 0xc4,
+    0xc4, 0xc4, 0xc2, 0xbc, 0xb4, 0xaa, 0x98, 0x7c,
+    0x00, 0x7d, 0x99, 0xa9, 0xb5, 0xbd, 0xc3, 0xc5,
+    0xc5, 0xc5, 0xc3, 0xbb, 0xb3, 0xa9, 0x99, 0x7b,
+    0x00, 0x7a, 0x96, 0xa8, 0xb2, 0xba, 0xc0, 0xc2,
+    0xc2, 0xc2, 0xc0, 0xba, 0xb0, 0xa6, 0x96, 0x78,
+    0x00, 0x79, 0x97, 0xa7, 0xb1, 0xb9, 0xbf, 0xc3,
+    0xc3, 0xc3, 0xbf, 0xb9, 0xb1, 0xa7, 0x95, 0x77,
+    0x00, 0x76, 0x94, 0xa6, 0xae, 0xb6, 0xbc, 0xc0,
+    0xc0, 0xc0, 0xbc, 0xb6, 0xae, 0xa4, 0x92, 0x76,
+    0x00, 0x75, 0x93, 0xa5, 0xaf, 0xb5, 0xbb, 0xbf,
+    0xbf, 0xbf, 0xbb, 0xb5, 0xad, 0xa5, 0x91, 0x75,
+    0x00, 0x74, 0x90, 0xa4, 0xac, 0xb4, 0xb8, 0xbc,
+    0xbc, 0xbc, 0xb8, 0xb2, 0xac, 0xa2, 0x90, 0x72,
+    0x00, 0x73, 0x91, 0xa3, 0xab, 0xb3, 0xb7, 0xbb,
+    0xbb, 0xbb, 0xb7, 0xb1, 0xab, 0xa3, 0x8f, 0x71,
+    0x00, 0x70, 0x8e, 0xa0, 0xaa, 0xb0, 0xb4, 0xb8,
+    0xb8, 0xb8, 0xb4, 0xb0, 0xa8, 0xa0, 0x8c, 0x6e,
+    0x00, 0x6f, 0x8d, 0x9f, 0xa9, 0xaf, 0xb5, 0xb7,
+    0xb7, 0xb7, 0xb3, 0xaf, 0xa9, 0x9f, 0x8b, 0x6f,
+    0x00, 0x6e, 0x8a, 0x9c, 0xa6, 0xac, 0xb2, 0xb4,
+    0xb4, 0xb4, 0xb0, 0xac, 0xa6, 0x9a, 0x8a, 0x6c,
+    0x00, 0x6d, 0x89, 0x9b, 0xa5, 0xab, 0xb1, 0xb3,
+    0xb3, 0xb3, 0xaf, 0xab, 0xa5, 0x99, 0x89, 0x6b,
+    0x00, 0x6a, 0x88, 0x98, 0xa4, 0xaa, 0xae, 0xb0,
+    0xb0, 0xb0, 0xae, 0xa8, 0xa2, 0x96, 0x86, 0x68,
+    0x00, 0x69, 0x87, 0x97, 0xa3, 0xa9, 0xad, 0xaf,
+    0xaf, 0xaf, 0xad, 0xa7, 0xa3, 0x95, 0x85, 0x69,
+    0x00, 0x66, 0x84, 0x94, 0xa0, 0xa6, 0xaa, 0xac,
+    0xac, 0xac, 0xaa, 0xa6, 0x9e, 0x92, 0x84, 0x66,
+    0x00, 0x67, 0x83, 0x93, 0x9f, 0xa5, 0xa9, 0xab,
+    0xab, 0xab, 0xa9, 0xa5, 0x9d, 0x91, 0x83, 0x65,
+    0x00, 0x64, 0x82, 0x8e, 0x9a, 0xa2, 0xa6, 0xa8,
+    0xa8, 0xa8, 0xa6, 0xa2, 0x9a, 0x8e, 0x80, 0x62,
+    0x00, 0x63, 0x7f, 0x8d, 0x99, 0xa1, 0xa5, 0xa7,
+    0xa7, 0xa7, 0xa5, 0xa1, 0x97, 0x8d, 0x7d, 0x61,
+    0x00, 0x60, 0x7c, 0x8a, 0x94, 0x9e, 0xa2, 0xa4,
+    0xa4, 0xa4, 0xa2, 0x9c, 0x94, 0x8a, 0x7a, 0x5e,
+    0x00, 0x5f, 0x79, 0x89, 0x93, 0x9b, 0xa1, 0xa3,
+    0xa3, 0xa3, 0xa1, 0x9b, 0x91, 0x87, 0x77, 0x5b,
+    0x00, 0x5a, 0x76, 0x86, 0x90, 0x96, 0x9c, 0xa0,
+    0xa0, 0xa0, 0x9c, 0x96, 0x8e, 0x84, 0x72, 0x58,
+    0x00, 0x59, 0x73, 0x85, 0x8d, 0x95, 0x99, 0x9d,
+    0x9d, 0x9d, 0x99, 0x93, 0x8d, 0x83, 0x71, 0x55,
+    0x00, 0x54, 0x70, 0x82, 0x8a, 0x90, 0x96, 0x98,
+    0x98, 0x98, 0x94, 0x90, 0x88, 0x80, 0x6c, 0x52,
+    0x00, 0x51, 0x6d, 0x7f, 0x87, 0x8d, 0x93, 0x95,
+    0x95, 0x95, 0x91, 0x8d, 0x87, 0x7b, 0x6b, 0x4f,
+    0x00, 0x4e, 0x6a, 0x7a, 0x84, 0x8a, 0x8e, 0x90,
+    0x90, 0x90, 0x8c, 0x88, 0x82, 0x76, 0x66, 0x4a,
+    0x00, 0x4b, 0x67, 0x75, 0x83, 0x87, 0x8b, 0x8d,
+    0x8d, 0x8d, 0x8b, 0x87, 0x7f, 0x73, 0x65, 0x49,
+    0x00, 0x48, 0x62, 0x70, 0x7c, 0x82, 0x86, 0x88,
+    0x88, 0x88, 0x86, 0x82, 0x78, 0x6e, 0x60, 0x44,
+    0x00, 0x45, 0x5f, 0x6d, 0x77, 0x7f, 0x83, 0x85,
+    0x85, 0x85, 0x83, 0x7d, 0x75, 0x6b, 0x5b, 0x43,
+    0x00, 0x42, 0x58, 0x68, 0x70, 0x78, 0x7c, 0x80,
+    0x80, 0x7e, 0x7c, 0x76, 0x6e, 0x64, 0x54, 0x3c,
+    0x00, 0x3d, 0x53, 0x63, 0x6b, 0x73, 0x77, 0x79,
+    0x79, 0x79, 0x75, 0x6f, 0x69, 0x61, 0x4f, 0x37,
+    0x00, 0x34, 0x4c, 0x5c, 0x66, 0x6a, 0x6e, 0x70,
+    0x70, 0x70, 0x6c, 0x68, 0x62, 0x56, 0x48, 0x30,
+    0x00, 0x2f, 0x47, 0x55, 0x5f, 0x65, 0x67, 0x69,
+    0x69, 0x69, 0x65, 0x63, 0x59, 0x4f, 0x43, 0x2b,
+    0x00, 0x28, 0x40, 0x4a, 0x52, 0x5a, 0x5e, 0x60,
+    0x60, 0x5e, 0x5a, 0x54, 0x4c, 0x44, 0x36, 0x22,
+    0x00, 0x23, 0x33, 0x43, 0x49, 0x4d, 0x4f, 0x51,
+    0x51, 0x4f, 0x4d, 0x47, 0x43, 0x37, 0x2b, 0x19,
+    0x00, 0x16, 0x26, 0x30, 0x36, 0x3c, 0x40, 0x40,
+    0x40, 0x3c, 0x38, 0x32, 0x2c, 0x24, 0x1a, 0x0c,
+    0x00, 0x0b, 0x15, 0x1b, 0x21, 0x23, 0x23, 0x21,
+    0x1f, 0x19, 0x15, 0x0f, 0x09, 0x05, 0x03, 0x00,
+};
+
+/* End of waveform.h */
diff --git a/sys/arch/arm32/mainbus/wd.c b/sys/arch/arm32/mainbus/wd.c
new file mode 100644 (file)
index 0000000..e54e2e2
--- /dev/null
@@ -0,0 +1,1764 @@
+/*     $NetBSD: wd.c,v 1.6 1996/03/28 21:52:52 mark Exp $      */
+
+/*
+ * Copyright (c) 1994, 1995 Charles M. Hannum.  All rights reserved.
+ *
+ * DMA and multi-sector PIO handling are derived from code contributed by
+ * Onno van der Linden.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by Charles M. Hannum.
+ * 4. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/conf.h>
+#include <sys/file.h>
+#include <sys/stat.h>
+#include <sys/ioctl.h>
+#include <sys/buf.h>
+#include <sys/uio.h>
+#include <sys/malloc.h>
+#include <sys/device.h>
+#include <sys/disklabel.h>
+#include <sys/disk.h>
+#include <sys/syslog.h>
+
+#include <vm/vm.h>
+
+#include <machine/cpu.h>
+
+#include <arm32/mainbus/wdreg.h>
+#include <arm32/mainbus/mainbus.h>
+#include <machine/irqhandler.h>
+#include <machine/io.h>
+#include <machine/katelib.h>
+
+extern int wdresethack;
+
+#define        WAITTIME        (4 * hz)        /* time to wait for a completion */
+#define        RECOVERYTIME    (hz / 2)        /* time to recover from an error */
+
+#define WDCDELAY       100
+#define WDCNDELAY      100000          /* delay = 100us; so 10s for a controller state change */
+#if 0
+/* If you enable this, it will report any delays more than 100us * N long. */
+#define WDCNDELAY_DEBUG        10
+#endif
+
+#define        WDIORETRIES     5               /* number of retries before giving up */
+
+#define        WDUNIT(dev)                     DISKUNIT(dev)
+#define        WDPART(dev)                     DISKPART(dev)
+#define        MAKEWDDEV(maj, unit, part)      MAKEDISKDEV(maj, unit, part)
+
+#define        WDLABELDEV(dev) (MAKEWDDEV(major(dev), WDUNIT(dev), RAW_PART))
+
+struct wd_softc {
+       struct device sc_dev;
+       struct disk sc_dk;
+
+       /* Information about the current transfer: */
+       daddr_t sc_blkno;       /* starting block number */
+       int sc_bcount;          /* byte count left */
+       int sc_skip;            /* bytes already transferred */
+       int sc_nblks;           /* number of blocks currently transferring */
+       int sc_nbytes;          /* number of bytes currently transferring */
+
+       /* Long-term state: */
+       int sc_drive;                   /* physical unit number */
+       int sc_state;                   /* control state */
+#define        RECAL           0               /* recalibrate */
+#define        RECAL_WAIT      1               /* done recalibrating */
+#define        GEOMETRY        2               /* upload geometry */
+#define        GEOMETRY_WAIT   3               /* done uploading geometry */
+#define        MULTIMODE       4               /* set multiple mode */
+#define        MULTIMODE_WAIT  5               /* done setting multiple mode */
+#define        OPEN            6               /* done with open */
+       int sc_mode;                    /* transfer mode */
+#define        WDM_PIOSINGLE   0               /* single-sector PIO */
+#define        WDM_PIOMULTI    1               /* multi-sector PIO */
+#define        WDM_DMA         2               /* DMA */
+       int sc_multiple;                /* multiple for WDM_PIOMULTI */
+       int sc_flags;                   /* drive characteistics found */
+#define        WDF_LOCKED      0x01
+#define        WDF_WANTED      0x02
+#define        WDF_WLABEL      0x04            /* label is writable */
+#define        WDF_LABELLING   0x08            /* writing label */
+/* XXX Nothing resets this yet, but disk change sensing will when ATAPI is
+   implemented. */
+#define        WDF_LOADED      0x10            /* parameters loaded */
+#define        WDF_32BIT       0x20            /* can do 32-bit transfer */
+
+       struct wdparams sc_params;      /* ESDI/ATA drive parameters */
+       daddr_t sc_badsect[127];        /* 126 plus trailing -1 marker */
+
+       TAILQ_ENTRY(wd_softc) sc_drivechain;
+       struct buf sc_q;
+};
+
+struct wdc_softc {
+       struct device sc_dev;
+       irqhandler_t sc_ih;
+
+       int sc_iobase;                  /* I/O port base */
+       int sc_drq;                     /* DMA channel */
+
+       TAILQ_HEAD(drivehead, wd_softc) sc_drives;
+       int sc_flags;
+#define        WDCF_ACTIVE     0x01            /* controller is active */
+#define        WDCF_SINGLE     0x02            /* sector at a time mode */
+#define        WDCF_ERROR      0x04            /* processing a disk error */
+#define        WDCF_WANTED     0x08            /* XXX locking for wd_get_parms() */
+       int sc_errors;                  /* errors during current transfer */
+       u_char sc_status;               /* copy of status register */
+       u_char sc_error;                /* copy of error register */
+};
+
+int wdcprobe __P((struct device *, void *, void *));
+void wdcattach __P((struct device *, struct device *, void *));
+
+struct cfattach wdc_ca = {
+       sizeof(struct wdc_softc), wdcprobe, wdcattach
+};
+
+struct cfdriver wdc_cd = {
+       NULL, "wdc", DV_DULL
+};
+
+int wdprobe __P((struct device *, void *, void *));
+void wdattach __P((struct device *, struct device *, void *));
+
+struct cfattach wd_ca = {
+       sizeof(struct wd_softc), wdprobe, wdattach
+};
+
+struct cfdriver wd_cd = {
+       NULL, "wd", DV_DISK
+};
+
+void wdgetdisklabel __P((struct wd_softc *));
+int wd_get_parms __P((struct wd_softc *));
+void wdstrategy __P((struct buf *));
+void wdstart __P((struct wd_softc *));
+
+struct dkdriver wddkdriver = { wdstrategy };
+
+void wdfinish __P((struct wd_softc *, struct buf *));
+int wdcintr __P((void *));
+void wdcstart __P((struct wdc_softc *));
+int wdcommand __P((struct wd_softc *, int, int, int, int, int));
+int wdcommandshort __P((struct wdc_softc *, int, int));
+int wdcontrol __P((struct wd_softc *));
+int wdsetctlr __P((struct wd_softc *));
+static void bad144intern __P((struct wd_softc *));
+int wdcreset __P((struct wdc_softc *));
+void wdcrestart __P((void *arg));
+void wdcunwedge __P((struct wdc_softc *));
+void wdctimeout __P((void *arg));
+void wderror __P((void *, struct buf *, char *));
+int wdcwait __P((struct wdc_softc *, int));
+/* ST506 spec says that if READY or SEEKCMPLT go off, then the read or write
+   command is aborted. */
+#define        wait_for_drq(d)         wdcwait(d, WDCS_DRDY | WDCS_DSC | WDCS_DRQ)
+#define        wait_for_ready(d)       wdcwait(d, WDCS_DRDY | WDCS_DSC)
+#define        wait_for_unbusy(d)      wdcwait(d, 0)
+
+int
+wdcprobe(parent, match, aux)
+       struct device *parent;
+       void *match, *aux;
+{
+       struct wdc_softc *wdc = match;
+       struct mainbus_attach_args *mb = aux;
+       int iobase;
+
+       wdc->sc_iobase = iobase = mb->mb_iobase;
+
+       /* Check if we have registers that work. */
+       outb(iobase+wd_error, 0x5a);    /* Error register not writable, */
+       outb(iobase+wd_cyl_lo, 0xa5);   /* but all of cyllo are. */
+       if (inb(iobase+wd_error) == 0x5a || inb(iobase+wd_cyl_lo) != 0xa5)
+               return 0;
+
+       if (wdcreset(wdc) != 0) {
+               delay(500000);
+               if (wdcreset(wdc) != 0)
+                       return 0;
+       }
+
+       /* Select drive 0. */
+       outb(iobase+wd_sdh, WDSD_IBM | 0);
+
+       /* Wait for controller to become ready. */
+       if (wait_for_unbusy(wdc) < 0)
+               return 0;
+    
+       /* Start drive diagnostics. */
+       outb(iobase+wd_command, WDCC_DIAGNOSE);
+
+       /* Wait for command to complete. */
+       if (wait_for_unbusy(wdc) < 0)
+               return 0;
+
+       mb->mb_iosize = 32;
+       return 1;
+}
+
+struct wdc_attach_args {
+       int wa_drive;
+};
+
+int
+wdprint(aux, wdc)
+       void *aux;
+       char *wdc;
+{
+       struct wdc_attach_args *wa = aux;
+
+       if (!wdc)
+               printf(" drive %d", wa->wa_drive);
+       return QUIET;
+}
+
+void
+wdcattach(parent, self, aux)
+       struct device *parent, *self;
+       void *aux;
+{
+       struct wdc_softc *wdc = (void *)self;
+       struct mainbus_attach_args *mb = aux;
+       struct wdc_attach_args wa;
+
+       TAILQ_INIT(&wdc->sc_drives);
+       wdc->sc_drq = mb->mb_drq;
+
+       printf("\n");
+
+       wdc->sc_ih.ih_func = wdcintr;
+       wdc->sc_ih.ih_arg = wdc;
+       wdc->sc_ih.ih_level = IPL_BIO;
+       wdc->sc_ih.ih_name = "wdc";
+       if (irq_claim(mb->mb_irq, &wdc->sc_ih))
+               panic("Cannot claim IRQ %d for wdc%d\n", mb->mb_irq, parent->dv_unit);
+
+       for (wa.wa_drive = 0; wa.wa_drive < 2; wa.wa_drive++)
+               (void)config_found(self, (void *)&wa, wdprint);
+}
+
+int
+wdprobe(parent, match, aux)
+       struct device *parent;
+       void *match, *aux;
+{
+       struct wdc_softc *wdc = (void *)parent;
+       struct cfdata *cf = match;
+       struct wdc_attach_args *wa = aux;
+       int drive = wa->wa_drive;
+
+       if (cf->cf_loc[0] != -1 && cf->cf_loc[0] != drive)
+               return 0;
+       
+       if (wdcommandshort(wdc, drive, WDCC_RECAL) != 0 ||
+           wait_for_ready(wdc) != 0)
+               return 0;
+
+       return 1;
+}
+
+void
+wdattach(parent, self, aux)
+       struct device *parent, *self;
+       void *aux;
+{
+       struct wd_softc *wd = (void *)self;
+       struct wdc_softc *wdc = (void *)parent;
+       struct wdc_attach_args *wa = aux;
+       int i, blank;
+       char buf[41], c, *p, *q;
+
+       wd->sc_drive = wa->wa_drive;
+
+       /*
+        * Initialize and attach the disk structure.
+        */
+       wd->sc_dk.dk_driver = &wddkdriver;
+       wd->sc_dk.dk_name = wd->sc_dev.dv_xname;
+       disk_attach(&wd->sc_dk);
+
+       wd_get_parms(wd);
+       for (blank = 0, p = wd->sc_params.wdp_model, q = buf, i = 0;
+            i < sizeof(wd->sc_params.wdp_model); i++) {
+               c = *p++;
+               if (c == '\0')
+                       break;
+               if (c != ' ') {
+                       if (blank) {
+                               *q++ = ' ';
+                               blank = 0;
+                       }
+                       *q++ = c;
+               } else
+                       blank = 1;
+       }
+       *q++ = '\0';
+
+       printf(": %dMB, %d cyl, %d head, %d sec, %d bytes/sec <%s>\n",
+           wd->sc_params.wdp_cylinders *
+           (wd->sc_params.wdp_heads * wd->sc_params.wdp_sectors) /
+           (1048576 / DEV_BSIZE),
+           wd->sc_params.wdp_cylinders,
+           wd->sc_params.wdp_heads,
+           wd->sc_params.wdp_sectors,
+           DEV_BSIZE,
+           buf);
+
+       if ((wd->sc_params.wdp_capabilities & WD_CAP_DMA) != 0 &&
+           wdc->sc_drq != DRQUNK) {
+               wd->sc_mode = WDM_DMA;
+       } else if (wd->sc_params.wdp_maxmulti > 1) {
+               wd->sc_mode = WDM_PIOMULTI;
+               wd->sc_multiple = min(wd->sc_params.wdp_maxmulti, 16);
+       } else {
+               wd->sc_mode = WDM_PIOSINGLE;
+               wd->sc_multiple = 1;
+       }
+
+       printf("%s: using", wd->sc_dev.dv_xname);
+       if (wd->sc_mode == WDM_DMA)
+               printf(" dma transfers,");
+       else
+               printf(" %d-sector %d-bit pio transfers,",
+                   wd->sc_multiple, (wd->sc_flags & WDF_32BIT) == 0 ? 16 : 32);
+       if ((wd->sc_params.wdp_capabilities & WD_CAP_LBA) != 0)
+               printf(" lba addressing\n");
+       else
+               printf(" chs addressing\n");
+}
+
+/*
+ * Read/write routine for a buffer.  Validates the arguments and schedules the
+ * transfer.  Does not wait for the transfer to complete.
+ */
+void
+wdstrategy(bp)
+       struct buf *bp;
+{
+       struct wd_softc *wd = wd_cd.cd_devs[WDUNIT(bp->b_dev)];
+       int s;
+    
+       /* Valid request?  */
+       if (bp->b_blkno < 0 ||
+           (bp->b_bcount % wd->sc_dk.dk_label->d_secsize) != 0 ||
+           (bp->b_bcount / wd->sc_dk.dk_label->d_secsize) >= (1 << NBBY)) {
+               bp->b_error = EINVAL;
+               goto bad;
+       }
+    
+       /* If device invalidated (e.g. media change, door open), error. */
+       if ((wd->sc_flags & WDF_LOADED) == 0) {
+               bp->b_error = EIO;
+               goto bad;
+       }
+
+       /* If it's a null transfer, return immediately. */
+       if (bp->b_bcount == 0)
+               goto done;
+
+       /*
+        * Do bounds checking, adjust transfer. if error, process.
+        * If end of partition, just return.
+        */
+       if (WDPART(bp->b_dev) != RAW_PART &&
+           bounds_check_with_label(bp, wd->sc_dk.dk_label,
+           (wd->sc_flags & (WDF_WLABEL|WDF_LABELLING)) != 0) <= 0)
+               goto done;
+    
+       /* Queue transfer on drive, activate drive and controller if idle. */
+       s = splbio();
+       disksort(&wd->sc_q, bp);
+       if (!wd->sc_q.b_active)
+               wdstart(wd);
+#if 0
+       else {
+               struct wdc_softc *wdc = (void *)wd->sc_dev.dv_parent;
+               if ((wdc->sc_flags & (WDCF_ACTIVE|WDCF_ERROR)) == 0) {
+                       printf("wdstrategy: controller inactive\n");
+                       wdcstart(wdc);
+               }
+       }
+#endif
+       splx(s);
+       return;
+    
+bad:
+       bp->b_flags |= B_ERROR;
+done:
+       /* Toss transfer; we're done early. */
+       bp->b_resid = bp->b_bcount;
+       biodone(bp);
+}
+
+/*
+ * Queue a drive for I/O.
+ */
+void
+wdstart(wd)
+       struct wd_softc *wd;
+{
+       struct wdc_softc *wdc = (void *)wd->sc_dev.dv_parent;
+       int active = wdc->sc_drives.tqh_first != 0;
+
+       /* Link onto controller queue. */
+       wd->sc_q.b_active = 1;
+       TAILQ_INSERT_TAIL(&wdc->sc_drives, wd, sc_drivechain);
+
+       disk_busy(&wd->sc_dk);
+    
+       /* If controller not already active, start it. */
+       if (!active)
+               wdcstart(wdc);
+}
+
+/*
+ * Finish an I/O operation.  Clean up the drive and controller state, set the
+ * residual count, and inform the upper layers that the operation is complete.
+ */
+void
+wdfinish(wd, bp)
+       struct wd_softc *wd;
+       struct buf *bp;
+{
+       struct wdc_softc *wdc = (void *)wd->sc_dev.dv_parent;
+
+       wdc->sc_flags &= ~(WDCF_SINGLE | WDCF_ERROR);
+       wdc->sc_errors = 0;
+       /*
+        * Move this drive to the end of the queue to give others a `fair'
+        * chance.
+        */
+       if (wd->sc_drivechain.tqe_next) {
+               TAILQ_REMOVE(&wdc->sc_drives, wd, sc_drivechain);
+               if (bp->b_actf) {
+                       TAILQ_INSERT_TAIL(&wdc->sc_drives, wd, sc_drivechain);
+               } else
+                       wd->sc_q.b_active = 0;
+       }
+       bp->b_resid = wd->sc_bcount;
+       wd->sc_skip = 0;
+       wd->sc_q.b_actf = bp->b_actf;
+
+       disk_unbusy(&wd->sc_dk, (bp->b_bcount - bp->b_resid));
+
+       if (!wd->sc_q.b_actf) {
+               TAILQ_REMOVE(&wdc->sc_drives, wd, sc_drivechain);
+               wd->sc_q.b_active = 0;
+       } else
+               disk_busy(&wd->sc_dk);
+
+       biodone(bp);
+}
+
+int
+wdread(dev, uio)
+       dev_t dev;
+       struct uio *uio;
+{
+
+       return (physio(wdstrategy, NULL, dev, B_READ, minphys, uio));
+}
+
+int
+wdwrite(dev, uio)
+       dev_t dev;
+       struct uio *uio;
+{
+
+       return (physio(wdstrategy, NULL, dev, B_WRITE, minphys, uio));
+}
+
+/*
+ * Start I/O on a controller.  This does the calculation, and starts a read or
+ * write operation.  Called to from wdstart() to start a transfer, from
+ * wdcintr() to continue a multi-sector transfer or start the next transfer, or
+ * wdcrestart() after recovering from an error.
+ */
+void
+wdcstart(wdc)
+       struct wdc_softc *wdc;
+{
+       struct wd_softc *wd;
+       struct buf *bp;
+       struct disklabel *lp;
+       int nblks;
+
+#ifdef DIAGNOSTIC
+       if ((wdc->sc_flags & WDCF_ACTIVE) != 0)
+               panic("wdcstart: controller still active");
+#endif
+
+       /*
+        * XXX
+        * This is a kluge.  See comments in wd_get_parms().
+        */
+       if ((wdc->sc_flags & WDCF_WANTED) != 0) {
+               wdc->sc_flags &= ~WDCF_WANTED;
+               wakeup(wdc);
+               return;
+       }
+
+loop:
+       /* Is there a drive for the controller to do a transfer with? */
+       wd = wdc->sc_drives.tqh_first;
+       if (wd == NULL)
+               return;
+    
+       /* Is there a transfer to this drive?  If not, deactivate drive. */
+       bp = wd->sc_q.b_actf;
+    
+       if (wdc->sc_errors >= WDIORETRIES) {
+               wderror(wd, bp, "hard error");
+               bp->b_error = EIO;
+               bp->b_flags |= B_ERROR;
+               wdfinish(wd, bp);
+               goto loop;
+       }
+
+       /* Do control operations specially. */
+       if (wd->sc_state < OPEN) {
+               /*
+                * Actually, we want to be careful not to mess with the control
+                * state if the device is currently busy, but we can assume
+                * that we never get to this point if that's the case.
+                */
+               if (wdcontrol(wd) == 0) {
+                       /* The drive is busy.  Wait. */
+                       return;
+               }
+       }
+
+       /*
+        * WDCF_ERROR is set by wdcunwedge() and wdcintr() when an error is
+        * encountered.  If we are in multi-sector mode, then we switch to
+        * single-sector mode and retry the operation from the start.
+        */
+       if (wdc->sc_flags & WDCF_ERROR) {
+               wdc->sc_flags &= ~WDCF_ERROR;
+               if ((wdc->sc_flags & WDCF_SINGLE) == 0) {
+                       wdc->sc_flags |= WDCF_SINGLE;
+                       wd->sc_skip = 0;
+               }
+       }
+
+       lp = wd->sc_dk.dk_label;
+
+       /* When starting a transfer... */
+       if (wd->sc_skip == 0) {
+               int part = WDPART(bp->b_dev);
+               daddr_t blkno;
+
+#ifdef WDDEBUG
+               printf("\n%s: wdcstart %s %d@%d; map ", wd->sc_dev.dv_xname,
+                   (bp->b_flags & B_READ) ? "read" : "write", bp->b_bcount,
+                   bp->b_blkno);
+#endif
+               wd->sc_bcount = bp->b_bcount;
+               blkno = bp->b_blkno;
+               if (part != RAW_PART)
+                       blkno += lp->d_partitions[part].p_offset;
+               wd->sc_blkno = blkno / (lp->d_secsize / DEV_BSIZE);
+       } else {
+#ifdef WDDEBUG
+               printf(" %d)%x", wd->sc_skip, inb(wd->sc_iobase+wd_altsts));
+#endif
+       }
+
+       /* When starting a multi-sector transfer, or doing single-sector
+           transfers... */
+       if (wd->sc_skip == 0 || (wdc->sc_flags & WDCF_SINGLE) != 0 ||
+           wd->sc_mode == WDM_DMA) {
+               daddr_t blkno = wd->sc_blkno;
+               long cylin, head, sector;
+               int command;
+
+               if ((wdc->sc_flags & WDCF_SINGLE) != 0)
+                       nblks = 1;
+               else if (wd->sc_mode != WDM_DMA)
+                       nblks = wd->sc_bcount / lp->d_secsize;
+               else
+                       nblks = min(wd->sc_bcount / lp->d_secsize, 8);
+
+               /* Check for bad sectors and adjust transfer, if necessary. */
+               if ((lp->d_flags & D_BADSECT) != 0
+#ifdef B_FORMAT
+                   && (bp->b_flags & B_FORMAT) == 0
+#endif
+                   ) {
+                       long blkdiff;
+                       int i;
+
+                       for (i = 0; (blkdiff = wd->sc_badsect[i]) != -1; i++) {
+                               blkdiff -= blkno;
+                               if (blkdiff < 0)
+                                       continue;
+                               if (blkdiff == 0) {
+                                       /* Replace current block of transfer. */
+                                       blkno =
+                                           lp->d_secperunit - lp->d_nsectors - i - 1;
+                               }
+                               if (blkdiff < nblks) {
+                                       /* Bad block inside transfer. */
+                                       wdc->sc_flags |= WDCF_SINGLE;
+                                       nblks = 1;
+                               }
+                               break;
+                       }
+                       /* Tranfer is okay now. */
+               }
+
+               if ((wd->sc_params.wdp_capabilities & WD_CAP_LBA) != 0) {
+                       sector = (blkno >> 0) & 0xff;
+                       cylin = (blkno >> 8) & 0xffff;
+                       head = (blkno >> 24) & 0xf;
+                       head |= WDSD_LBA;
+               } else {
+                       sector = blkno % lp->d_nsectors;
+                       sector++;       /* Sectors begin with 1, not 0. */
+                       blkno /= lp->d_nsectors;
+                       head = blkno % lp->d_ntracks;
+                       blkno /= lp->d_ntracks;
+                       cylin = blkno;
+                       head |= WDSD_CHS;
+               }
+
+               if (wd->sc_mode == WDM_PIOSINGLE ||
+                   (wdc->sc_flags & WDCF_SINGLE) != 0)
+                       wd->sc_nblks = 1;
+               else if (wd->sc_mode == WDM_PIOMULTI)
+                       wd->sc_nblks = min(nblks, wd->sc_multiple);
+               else
+                       wd->sc_nblks = nblks;
+               wd->sc_nbytes = wd->sc_nblks * lp->d_secsize;
+    
+#ifdef B_FORMAT
+               if (bp->b_flags & B_FORMAT) {
+                       sector = lp->d_gap3;
+                       nblks = lp->d_nsectors;
+                       command = WDCC_FORMAT;
+               } else
+#endif
+               switch (wd->sc_mode) {
+               case WDM_DMA:
+                       command = (bp->b_flags & B_READ) ?
+                           WDCC_READDMA : WDCC_WRITEDMA;
+                       /* Start the DMA channel and bounce the buffer if
+                          necessary. */
+/*                     isa_dmastart(bp->b_flags & B_READ,
+                           bp->b_data + wd->sc_skip,
+                           wd->sc_nbytes, wdc->sc_drq);*/
+                       panic("wd cannot do DMA yet\n");
+                       break;
+               case WDM_PIOMULTI:
+                       command = (bp->b_flags & B_READ) ?
+                           WDCC_READMULTI : WDCC_WRITEMULTI;
+                       break;
+               case WDM_PIOSINGLE:
+                       command = (bp->b_flags & B_READ) ?
+                           WDCC_READ : WDCC_WRITE;
+                       break;
+               }
+       
+               /* Initiate command! */
+               if (wdcommand(wd, command, cylin, head, sector, nblks) != 0) {
+                       wderror(wd, NULL,
+                           "wdcstart: timeout waiting for unbusy");
+                       wdcunwedge(wdc);
+                       return;
+               }
+
+#ifdef WDDEBUG
+               printf("sector %d cylin %d head %d addr %x sts %x\n", sector,
+                   cylin, head, bp->b_data, 0/*inb(wd->sc_iobase+wd_altsts)*/);
+#endif
+       } else if (wd->sc_nblks > 1) {
+               /* The number of blocks in the last stretch may be smaller. */
+               nblks = wd->sc_bcount / lp->d_secsize;
+               if (wd->sc_nblks > nblks) {
+                       wd->sc_nblks = nblks;
+                       wd->sc_nbytes = wd->sc_bcount;
+               }
+       }
+
+       /* If this was a write and not using DMA, push the data. */
+       if (wd->sc_mode != WDM_DMA &&
+           (bp->b_flags & (B_READ|B_WRITE)) == B_WRITE) {
+               if (wait_for_drq(wdc) < 0) {
+                       wderror(wd, NULL, "wdcstart: timeout waiting for drq");
+                       wdcunwedge(wdc);
+                       return;
+               }
+
+               /* Push out data. */
+               if ((wd->sc_flags & WDF_32BIT) == 0)
+                       outsw(wdc->sc_iobase+wd_data, (u_int) bp->b_data + wd->sc_skip,
+                           wd->sc_nbytes >> 1);
+               else
+                       panic("wd cannot do 32 bit transfers\n");
+/*                     outsl(wdc->sc_iobase+wd_data, bp->b_data + wd->sc_skip,
+                           wd->sc_nbytes >> 2);*/
+       }
+
+       wdc->sc_flags |= WDCF_ACTIVE;
+       timeout(wdctimeout, wdc, WAITTIME);
+}
+
+/*
+ * Interrupt routine for the controller.  Acknowledge the interrupt, check for
+ * errors on the current operation, mark it done if necessary, and start the
+ * next request.  Also check for a partially done transfer, and continue with
+ * the next chunk if so.
+ */
+int
+wdcintr(arg)
+       void *arg;
+{
+       struct wdc_softc *wdc = arg;
+       struct wd_softc *wd;
+       struct buf *bp;
+
+       if ((wdc->sc_flags & WDCF_ACTIVE) == 0) {
+               /* Clear the pending interrupt and abort. */
+               (void) inb(wdc->sc_iobase+wd_status);
+               return 0;
+       }
+
+       wdc->sc_flags &= ~WDCF_ACTIVE;
+       untimeout(wdctimeout, wdc);
+
+       wd = wdc->sc_drives.tqh_first;
+       bp = wd->sc_q.b_actf;
+
+#ifdef WDDEBUG
+       printf("I%d ", ctrlr);
+#endif
+
+       if (wait_for_unbusy(wdc) < 0) {
+               wderror(wd, NULL, "wdcintr: timeout waiting for unbusy");
+               wdc->sc_status |= WDCS_ERR;     /* XXX */
+       }
+    
+       /* Is it not a transfer, but a control operation? */
+       if (wd->sc_state < OPEN) {
+               if (wdcontrol(wd) == 0) {
+                       /* The drive is busy.  Wait. */
+                       return 1;
+               }
+               wdcstart(wdc);
+               return 1;
+       }
+
+       /* Turn off the DMA channel and unbounce the buffer. */
+       if (wd->sc_mode == WDM_DMA)
+               panic("wd cannot do DMA\n");
+/*             isa_dmadone(bp->b_flags & B_READ, bp->b_data + wd->sc_skip,
+                   wd->sc_nbytes, wdc->sc_drq);*/
+
+       /* Have we an error? */
+       if (wdc->sc_status & WDCS_ERR) {
+       lose:
+#ifdef WDDEBUG
+               wderror(wd, NULL, "wdcintr");
+#endif
+               if ((wdc->sc_flags & WDCF_SINGLE) == 0) {
+                       wdc->sc_flags |= WDCF_ERROR;
+                       goto restart;
+               }
+
+#ifdef B_FORMAT
+               if (bp->b_flags & B_FORMAT)
+                       goto bad;
+#endif
+       
+               if (++wdc->sc_errors < WDIORETRIES)
+                       goto restart;
+               wderror(wd, bp, "hard error");
+
+       bad:
+               bp->b_error = EIO;
+               bp->b_flags |= B_ERROR;
+               goto done;
+       }
+
+       /* If this was a read and not using DMA, fetch the data. */
+       if (wd->sc_mode != WDM_DMA &&
+           (bp->b_flags & (B_READ|B_WRITE)) == B_READ) {
+               if ((wdc->sc_status & (WDCS_DRDY | WDCS_DSC | WDCS_DRQ))
+                   != (WDCS_DRDY | WDCS_DSC | WDCS_DRQ)) {
+                       wderror(wd, NULL, "wdcintr: read intr before drq");
+                       wdcunwedge(wdc);
+                       return 1;
+               }
+
+               /* Pull in data. */
+               if ((wd->sc_flags & WDF_32BIT) == 0)
+                       insw(wdc->sc_iobase+wd_data, (u_int) bp->b_data + wd->sc_skip, 
+                           wd->sc_nbytes >> 1);
+               else
+                       panic("wd cannot do 32 bit transfers\n");
+/*                     insl(wdc->sc_iobase+wd_data, bp->b_data + wd->sc_skip, 
+                           wd->sc_nbytes >> 2);*/
+       }
+    
+       /* If we encountered any abnormalities, flag it as a soft error. */
+       if (wdc->sc_errors > 0 ||
+           (wdc->sc_status & WDCS_CORR) != 0) {
+               wderror(wd, bp, "soft error (corrected)");
+               wdc->sc_errors = 0;
+       }
+    
+       /* Adjust pointers for the next block, if any. */
+       wd->sc_blkno += wd->sc_nblks;
+       wd->sc_skip += wd->sc_nbytes;
+       wd->sc_bcount -= wd->sc_nbytes;
+
+       /* See if this transfer is complete. */
+       if (wd->sc_bcount > 0)
+               goto restart;
+
+done:
+       /* Done with this transfer, with or without error. */
+       wdfinish(wd, bp);
+
+restart:
+       /* Start the next operation, if any. */
+       wdcstart(wdc);
+
+       return 1;
+}
+
+/*
+ * Wait interruptibly for an exclusive lock.
+ *
+ * XXX
+ * Several drivers do this; it should be abstracted and made MP-safe.
+ */
+int
+wdlock(wd)
+       struct wd_softc *wd;
+{
+       int error;
+
+       while ((wd->sc_flags & WDF_LOCKED) != 0) {
+               wd->sc_flags |= WDF_WANTED;
+               if ((error = tsleep(wd, PRIBIO | PCATCH, "wdlck", 0)) != 0)
+                       return error;
+       }
+       wd->sc_flags |= WDF_LOCKED;
+       return 0;
+}
+
+/*
+ * Unlock and wake up any waiters.
+ */
+void
+wdunlock(wd)
+       struct wd_softc *wd;
+{
+
+       wd->sc_flags &= ~WDF_LOCKED;
+       if ((wd->sc_flags & WDF_WANTED) != 0) {
+               wd->sc_flags &= ~WDF_WANTED;
+               wakeup(wd);
+       }
+}
+
+int
+wdopen(dev, flag, fmt)
+       dev_t dev;
+       int flag, fmt;
+{
+       struct wd_softc *wd;
+       int unit, part;
+       int error;
+    
+       unit = WDUNIT(dev);
+       if (unit >= wd_cd.cd_ndevs)
+               return ENXIO;
+       wd = wd_cd.cd_devs[unit];
+       if (wd == 0)
+               return ENXIO;
+    
+       if (error = wdlock(wd))
+               return error;
+
+       if (wd->sc_dk.dk_openmask != 0) {
+               /*
+                * If any partition is open, but the disk has been invalidated,
+                * disallow further opens.
+                */
+               if ((wd->sc_flags & WDF_LOADED) == 0) {
+                       error = EIO;
+                       goto bad3;
+               }
+       } else {
+               if ((wd->sc_flags & WDF_LOADED) == 0) {
+                       wd->sc_flags |= WDF_LOADED;
+
+                       /* Load the physical device parameters. */
+                       if (wd_get_parms(wd) != 0) {
+                               error = ENXIO;
+                               goto bad2;
+                       }
+
+                       /* Load the partition info if not already loaded. */
+                       wdgetdisklabel(wd);
+               }
+       }
+
+       part = WDPART(dev);
+
+       /* Check that the partition exists. */
+       if (part != RAW_PART &&
+           (part >= wd->sc_dk.dk_label->d_npartitions ||
+            wd->sc_dk.dk_label->d_partitions[part].p_fstype == FS_UNUSED)) {
+               error = ENXIO;
+               goto bad;
+       }
+    
+       /* Insure only one open at a time. */
+       switch (fmt) {
+       case S_IFCHR:
+               wd->sc_dk.dk_copenmask |= (1 << part);
+               break;
+       case S_IFBLK:
+               wd->sc_dk.dk_bopenmask |= (1 << part);
+               break;
+       }
+       wd->sc_dk.dk_openmask = wd->sc_dk.dk_copenmask | wd->sc_dk.dk_bopenmask;
+
+       wdunlock(wd);
+       return 0;
+
+bad2:
+       wd->sc_flags &= ~WDF_LOADED;
+
+bad:
+       if (wd->sc_dk.dk_openmask == 0) {
+       }
+
+bad3:
+       wdunlock(wd);
+       return error;
+}
+
+int
+wdclose(dev, flag, fmt)
+       dev_t dev;
+       int flag, fmt;
+{
+       struct wd_softc *wd = wd_cd.cd_devs[WDUNIT(dev)];
+       int part = WDPART(dev);
+       int error;
+    
+       if (error = wdlock(wd))
+               return error;
+
+       switch (fmt) {
+       case S_IFCHR:
+               wd->sc_dk.dk_copenmask &= ~(1 << part);
+               break;
+       case S_IFBLK:
+               wd->sc_dk.dk_bopenmask &= ~(1 << part);
+               break;
+       }
+       wd->sc_dk.dk_openmask = wd->sc_dk.dk_copenmask | wd->sc_dk.dk_bopenmask;
+
+       if (wd->sc_dk.dk_openmask == 0) {
+               /* XXXX Must wait for I/O to complete! */
+       }
+
+       wdunlock(wd);
+       return 0;
+}
+
+/*
+ * Fabricate a default disk label, and try to read the correct one.
+ */
+void
+wdgetdisklabel(wd)
+       struct wd_softc *wd;
+{
+       struct disklabel *lp = wd->sc_dk.dk_label;
+       char *errstring;
+
+       bzero(lp, sizeof(struct disklabel));
+       bzero(wd->sc_dk.dk_cpulabel, sizeof(struct cpu_disklabel));
+
+       lp->d_secsize = DEV_BSIZE;
+       lp->d_ntracks = wd->sc_params.wdp_heads;
+       lp->d_nsectors = wd->sc_params.wdp_sectors;
+       lp->d_ncylinders = wd->sc_params.wdp_cylinders;
+       lp->d_secpercyl = lp->d_ntracks * lp->d_nsectors;
+
+#if 0
+       strncpy(lp->d_typename, "ST506 disk", 16);
+       lp->d_type = DTYPE_ST506;
+#endif
+       strncpy(lp->d_packname, wd->sc_params.wdp_model, 16);
+       lp->d_secperunit = lp->d_secpercyl * lp->d_ncylinders;
+       lp->d_rpm = 3600;
+       lp->d_interleave = 1;
+       lp->d_flags = 0;
+
+       lp->d_partitions[RAW_PART].p_offset = 0;
+       lp->d_partitions[RAW_PART].p_size =
+           lp->d_secperunit * (lp->d_secsize / DEV_BSIZE);
+       lp->d_partitions[RAW_PART].p_fstype = FS_UNUSED;
+       lp->d_npartitions = RAW_PART + 1;
+
+       lp->d_magic = DISKMAGIC;
+       lp->d_magic2 = DISKMAGIC;
+       lp->d_checksum = dkcksum(lp);
+
+       wd->sc_badsect[0] = -1;
+
+       if (wd->sc_state > RECAL)
+               wd->sc_state = RECAL;
+       errstring = readdisklabel(MAKEWDDEV(0, wd->sc_dev.dv_unit, RAW_PART),
+           wdstrategy, lp, wd->sc_dk.dk_cpulabel);
+       if (errstring) {
+               /*
+                * This probably happened because the drive's default
+                * geometry doesn't match the DOS geometry.  We
+                * assume the DOS geometry is now in the label and try
+                * again.  XXX This is a kluge.
+                */
+               if (wd->sc_state > GEOMETRY)
+                       wd->sc_state = GEOMETRY;
+               errstring = readdisklabel(MAKEWDDEV(0, wd->sc_dev.dv_unit, RAW_PART),
+                   wdstrategy, lp, wd->sc_dk.dk_cpulabel);
+       }
+       if (errstring) {
+               printf("%s: %s\n", wd->sc_dev.dv_xname, errstring);
+               return;
+       }
+
+       if (wd->sc_state > GEOMETRY)
+               wd->sc_state = GEOMETRY;
+       if ((lp->d_flags & D_BADSECT) != 0)
+               bad144intern(wd);
+}
+
+/*
+ * Implement operations needed before read/write.
+ * Returns 0 if operation still in progress, 1 if completed.
+ */
+int
+wdcontrol(wd)
+       struct wd_softc *wd;
+{
+       struct wdc_softc *wdc = (void *)wd->sc_dev.dv_parent;
+    
+       switch (wd->sc_state) {
+       case RECAL:                     /* Set SDH, step rate, do recal. */
+               if (wdcommandshort(wdc, wd->sc_drive, WDCC_RECAL) != 0) {
+                       wderror(wd, NULL, "wdcontrol: recal failed (1)");
+                       goto bad;
+               }
+               wd->sc_state = RECAL_WAIT;
+               break;
+
+       case RECAL_WAIT:
+               if (wdc->sc_status & WDCS_ERR) {
+                       wderror(wd, NULL, "wdcontrol: recal failed (2)");
+                       goto bad;
+               }
+               /* fall through */
+       case GEOMETRY:
+               if ((wd->sc_params.wdp_capabilities & WD_CAP_LBA) != 0)
+                       goto multimode;
+               if (wdsetctlr(wd) != 0) {
+                       /* Already printed a message. */
+                       goto bad;
+               }
+               wd->sc_state = GEOMETRY_WAIT;
+               break;
+
+       case GEOMETRY_WAIT:
+               if (wdc->sc_status & WDCS_ERR) {
+                       wderror(wd, NULL, "wdcontrol: geometry failed");
+                       goto bad;
+               }
+               /* fall through */
+       case MULTIMODE:
+       multimode:
+               if (wd->sc_mode != WDM_PIOMULTI)
+                       goto open;
+               outb(wdc->sc_iobase+wd_seccnt, wd->sc_multiple);
+               if (wdcommandshort(wdc, wd->sc_drive, WDCC_SETMULTI) != 0) {
+                       wderror(wd, NULL, "wdcontrol: setmulti failed (1)");
+                       goto bad;
+               }
+               wd->sc_state = MULTIMODE_WAIT;
+               break;
+
+       case MULTIMODE_WAIT:
+               if (wdc->sc_status & WDCS_ERR) {
+                       wderror(wd, NULL, "wdcontrol: setmulti failed (2)");
+                       goto bad;
+               }
+               /* fall through */
+       case OPEN:
+       open:
+               wdc->sc_errors = 0;
+               wd->sc_state = OPEN;
+               /*
+                * The rest of the initialization can be done by normal means.
+                */
+               return 1;
+
+       bad:
+               wdcunwedge(wdc);
+               return 0;
+       }
+
+       wdc->sc_flags |= WDCF_ACTIVE;
+       timeout(wdctimeout, wdc, WAITTIME);
+       return 0;
+}
+
+/*
+ * Wait for the drive to become ready and send a command.
+ * Return -1 if busy for too long or 0 otherwise.
+ * Assumes interrupts are blocked.
+ */
+int
+wdcommand(wd, command, cylin, head, sector, count)
+       struct wd_softc *wd;
+       int command;
+       int cylin, head, sector, count;
+{
+       struct wdc_softc *wdc = (void *)wd->sc_dev.dv_parent;
+       int iobase = wdc->sc_iobase;
+       int stat;
+    
+       /* Select drive, head, and addressing mode. */
+       outb(iobase+wd_sdh, WDSD_IBM | (wd->sc_drive << 4) | head);
+
+       /* Wait for it to become ready to accept a command. */
+       if (command == WDCC_IDP)
+               stat = wait_for_unbusy(wdc);
+       else
+               stat = wdcwait(wdc, WDCS_DRDY);
+       if (stat < 0)
+               return -1;
+    
+       /* Load parameters. */
+       if (wd->sc_dk.dk_label->d_type == DTYPE_ST506)
+               outb(iobase+wd_precomp, wd->sc_dk.dk_label->d_precompcyl / 4);
+       else
+               outb(iobase+wd_features, 0);
+       outb(iobase+wd_cyl_lo, cylin);
+       outb(iobase+wd_cyl_hi, cylin >> 8);
+       outb(iobase+wd_sector, sector);
+       outb(iobase+wd_seccnt, count);
+
+       /* Send command. */
+       outb(iobase+wd_command, command);
+
+       return 0;
+}
+
+/*
+ * Simplified version of wdcommand().
+ */
+int
+wdcommandshort(wdc, drive, command)
+       struct wdc_softc *wdc;
+       int drive;
+       int command;
+{
+       int iobase = wdc->sc_iobase;
+
+       /* Select drive. */
+       outb(iobase+wd_sdh, WDSD_IBM | (drive << 4));
+
+       if (wdcwait(wdc, WDCS_DRDY) < 0)
+               return -1;
+
+       outb(iobase+wd_command, command);
+
+       return 0;
+}
+
+/*
+ * Tell the drive what geometry to use.
+ */
+int
+wdsetctlr(wd)
+       struct wd_softc *wd;
+{
+       struct wdc_softc *wdc = (void *)wd->sc_dev.dv_parent;
+
+#ifdef WDDEBUG
+       printf("wd(%d,%d) C%dH%dS%d\n", wd->sc_dev.dv_unit, wd->sc_drive,
+           wd->sc_dk.dk_label->d_ncylinders, wd->sc_dk.dk_label->d_ntracks,
+           wd->sc_dk.dk_label->d_nsectors);
+#endif
+    
+       if (wdcommand(wd, WDCC_IDP, wd->sc_dk.dk_label->d_ncylinders,
+           wd->sc_dk.dk_label->d_ntracks - 1, 0,
+           wd->sc_dk.dk_label->d_nsectors) != 0) {
+               wderror(wd, NULL, "wdsetctlr: geometry upload failed");
+               return -1;
+       }
+
+       return 0;
+}
+
+/*
+ * Get the drive parameters, if ESDI or ATA, or create fake ones for ST506.
+ */
+int
+wd_get_parms(wd)
+       struct wd_softc *wd;
+{
+       struct wdc_softc *wdc = (void *)wd->sc_dev.dv_parent;
+       int i;
+       char tb[DEV_BSIZE];
+       int s, error;
+
+       /*
+        * XXX
+        * The locking done here, and the length of time this may keep the rest
+        * of the system suspended, is a kluge.  This should be rewritten to
+        * set up a transfer and queue it through wdstart(), but it's called
+        * infrequently enough that this isn't a pressing matter.
+        */
+
+       s = splbio();
+
+       while ((wdc->sc_flags & WDCF_ACTIVE) != 0) {
+               wdc->sc_flags |= WDCF_WANTED;
+               if ((error = tsleep(wdc, PRIBIO | PCATCH, "wdprm", 0)) != 0) {
+                       splx(s);
+                       return error;
+               }
+       }
+
+       if (wdcommandshort(wdc, wd->sc_drive, WDCC_IDENTIFY) != 0 ||
+           wait_for_drq(wdc) != 0) {
+               /*
+                * We `know' there's a drive here; just assume it's old.
+                * This geometry is only used to read the MBR and print a
+                * (false) attach message.
+                */
+               strncpy(wd->sc_dk.dk_label->d_typename, "ST506",
+                   sizeof wd->sc_dk.dk_label->d_typename);
+               wd->sc_dk.dk_label->d_type = DTYPE_ST506;
+
+               strncpy(wd->sc_params.wdp_model, "unknown",
+                   sizeof wd->sc_params.wdp_model);
+               wd->sc_params.wdp_config = WD_CFG_FIXED;
+               wd->sc_params.wdp_cylinders = 1024;
+               wd->sc_params.wdp_heads = 8;
+               wd->sc_params.wdp_sectors = 17;
+               wd->sc_params.wdp_maxmulti = 0;
+               wd->sc_params.wdp_usedmovsd = 0;
+               wd->sc_params.wdp_capabilities = 0;
+       } else {
+               strncpy(wd->sc_dk.dk_label->d_typename, "ESDI/IDE",
+                   sizeof wd->sc_dk.dk_label->d_typename);
+               wd->sc_dk.dk_label->d_type = DTYPE_ESDI;
+
+               /* Read in parameter block. */
+               insw(wdc->sc_iobase+wd_data, (u_int)tb, sizeof(tb) / sizeof(short));
+               bcopy(tb, &wd->sc_params, sizeof(struct wdparams));
+
+               /* Shuffle string byte order. */
+               for (i = 0; i < sizeof(wd->sc_params.wdp_model); i += 2) {
+                       u_short *p;
+                       p = (u_short *)(wd->sc_params.wdp_model + i);
+                       *p = ntohs(*p);
+               }
+       }
+
+       /* Clear any leftover interrupt. */
+       (void) inb(wdc->sc_iobase+wd_status);
+
+       /* Restart the queue. */
+       wdcstart(wdc);
+
+       splx(s);
+       return 0;
+}
+
+int
+wdioctl(dev, cmd, addr, flag, p)
+       dev_t dev;
+       u_long cmd;
+       caddr_t addr;
+       int flag;
+       struct proc *p;
+{
+       struct wd_softc *wd = wd_cd.cd_devs[WDUNIT(dev)];
+       int error;
+    
+       if ((wd->sc_flags & WDF_LOADED) == 0)
+               return EIO;
+
+       switch (cmd) {
+       case DIOCSBAD:
+               if ((flag & FWRITE) == 0)
+                       return EBADF;
+               wd->sc_dk.dk_cpulabel->bad = *(struct dkbad *)addr;
+               wd->sc_dk.dk_label->d_flags |= D_BADSECT;
+               bad144intern(wd);
+               return 0;
+
+       case DIOCGDINFO:
+               *(struct disklabel *)addr = *(wd->sc_dk.dk_label);
+               return 0;
+       
+       case DIOCGPART:
+               ((struct partinfo *)addr)->disklab = wd->sc_dk.dk_label;
+               ((struct partinfo *)addr)->part =
+                   &wd->sc_dk.dk_label->d_partitions[WDPART(dev)];
+               return 0;
+       
+       case DIOCWDINFO:
+       case DIOCSDINFO:
+               if ((flag & FWRITE) == 0)
+                       return EBADF;
+
+               if (error = wdlock(wd))
+                       return error;
+               wd->sc_flags |= WDF_LABELLING;
+
+               error = setdisklabel(wd->sc_dk.dk_label,
+                   (struct disklabel *)addr, /*wd->sc_dk.dk_openmask : */0,
+                   wd->sc_dk.dk_cpulabel);
+               if (error == 0) {
+                       if (wd->sc_state > GEOMETRY)
+                               wd->sc_state = GEOMETRY;
+                       if (cmd == DIOCWDINFO)
+                               error = writedisklabel(WDLABELDEV(dev),
+                                   wdstrategy, wd->sc_dk.dk_label,
+                                   wd->sc_dk.dk_cpulabel);
+               }
+
+               wd->sc_flags &= ~WDF_LABELLING;
+               wdunlock(wd);
+               return error;
+       
+       case DIOCWLABEL:
+               if ((flag & FWRITE) == 0)
+                       return EBADF;
+               if (*(int *)addr)
+                       wd->sc_flags |= WDF_WLABEL;
+               else
+                       wd->sc_flags &= ~WDF_WLABEL;
+               return 0;
+       
+#ifdef notyet
+       case DIOCWFORMAT:
+               if ((flag & FWRITE) == 0)
+                       return EBADF;
+       {
+               register struct format_op *fop;
+               struct iovec aiov;
+               struct uio auio;
+           
+               fop = (struct format_op *)addr;
+               aiov.iov_base = fop->df_buf;
+               aiov.iov_len = fop->df_count;
+               auio.uio_iov = &aiov;
+               auio.uio_iovcnt = 1;
+               auio.uio_resid = fop->df_count;
+               auio.uio_segflg = 0;
+               auio.uio_offset =
+                   fop->df_startblk * wd->sc_dk.dk_label->d_secsize;
+               auio.uio_procp = p;
+               error = physio(wdformat, NULL, dev, B_WRITE, minphys,
+                   &auio);
+               fop->df_count -= auio.uio_resid;
+               fop->df_reg[0] = wdc->sc_status;
+               fop->df_reg[1] = wdc->sc_error;
+               return error;
+       }
+#endif
+
+       default:
+               return ENOTTY;
+       }
+
+#ifdef DIAGNOSTIC
+       panic("wdioctl: impossible");
+#endif
+}
+
+#ifdef B_FORMAT
+int
+wdformat(struct buf *bp)
+{
+
+       bp->b_flags |= B_FORMAT;
+       return wdstrategy(bp);
+}
+#endif
+
+int
+wdsize(dev)
+       dev_t dev;
+{
+       struct wd_softc *wd;
+       int part;
+       int size;
+    
+       if (wdopen(dev, 0, S_IFBLK) != 0)
+               return -1;
+       wd = wd_cd.cd_devs[WDUNIT(dev)];
+       part = WDPART(dev);
+       if (wd->sc_dk.dk_label->d_partitions[part].p_fstype != FS_SWAP)
+               size = -1;
+       else
+               size = wd->sc_dk.dk_label->d_partitions[part].p_size;
+       if (wdclose(dev, 0, S_IFBLK) != 0)
+               return -1;
+       return size;
+}
+
+
+#ifndef __BDEVSW_DUMP_OLD_TYPE
+/* #define WD_DUMP_NOT_TRUSTED if you just want to watch */
+static int wddoingadump;
+static int wddumprecalibrated;
+
+/*
+ * Dump core after a system crash.
+ */
+int
+wddump(dev, blkno, va, size)
+        dev_t dev;
+        daddr_t blkno;
+        caddr_t va;
+        size_t size;
+{
+       struct wd_softc *wd;    /* disk unit to do the I/O */
+       struct wdc_softc *wdc;  /* disk controller to do the I/O */
+       struct disklabel *lp;   /* disk's disklabel */
+       int     unit, part;
+       int     nblks;          /* total number of sectors left to write */
+
+       /* Check if recursive dump; if so, punt. */
+       if (wddoingadump)
+               return EFAULT;
+       wddoingadump = 1;
+
+       unit = WDUNIT(dev);
+       if (unit >= wd_cd.cd_ndevs)
+               return ENXIO;
+       wd = wd_cd.cd_devs[unit];
+       if (wd == 0)
+               return ENXIO;
+
+       part = WDPART(dev);
+
+       /* Make sure it was initialized. */
+       if (wd->sc_state < OPEN)
+               return ENXIO;
+
+       wdc = (void *)wd->sc_dev.dv_parent;
+
+        /* Convert to disk sectors.  Request must be a multiple of size. */
+       lp = wd->sc_dk.dk_label;
+       if ((size % lp->d_secsize) != 0)
+               return EFAULT;
+       nblks = size / lp->d_secsize;
+       blkno = blkno / (lp->d_secsize / DEV_BSIZE);
+
+       /* Check transfer bounds against partition size. */
+       if ((blkno < 0) || ((blkno + nblks) > lp->d_partitions[part].p_size))
+               return EINVAL;  
+
+       /* Offset block number to start of partition. */
+       blkno += lp->d_partitions[part].p_offset;
+
+       /* Recalibrate, if first dump transfer. */
+       if (wddumprecalibrated == 0) {
+               wddumprecalibrated = 1;
+               if (wdcommandshort(wdc, wd->sc_drive, WDCC_RECAL) != 0 ||
+                   wait_for_ready(wdc) != 0 || wdsetctlr(wd) != 0 ||
+                   wait_for_ready(wdc) != 0) {
+                       wderror(wd, NULL, "wddump: recal failed");
+                       return EIO;
+               }
+       }
+   
+       while (nblks > 0) {
+               daddr_t xlt_blkno = blkno;
+               long cylin, head, sector;
+
+               if ((lp->d_flags & D_BADSECT) != 0) {
+                       long blkdiff;
+                       int i;
+
+                       for (i = 0; (blkdiff = wd->sc_badsect[i]) != -1; i++) {
+                               blkdiff -= xlt_blkno;
+                               if (blkdiff < 0)
+                                       continue;
+                               if (blkdiff == 0) {
+                                       /* Replace current block of transfer. */
+                                       xlt_blkno = lp->d_secperunit -
+                                           lp->d_nsectors - i - 1;
+                               }
+                               break;
+                       }
+                       /* Tranfer is okay now. */
+               }
+
+               if ((wd->sc_params.wdp_capabilities & WD_CAP_LBA) != 0) {
+                       sector = (xlt_blkno >> 0) & 0xff;
+                       cylin = (xlt_blkno >> 8) & 0xffff;
+                       head = (xlt_blkno >> 24) & 0xf;
+                       head |= WDSD_LBA;
+               } else {
+                       sector = xlt_blkno % lp->d_nsectors;
+                       sector++;       /* Sectors begin with 1, not 0. */
+                       xlt_blkno /= lp->d_nsectors;
+                       head = xlt_blkno % lp->d_ntracks;
+                       xlt_blkno /= lp->d_ntracks;
+                       cylin = xlt_blkno;
+                       head |= WDSD_CHS;
+               }
+
+#ifndef WD_DUMP_NOT_TRUSTED
+               if (wdcommand(wd, WDCC_WRITE, cylin, head, sector, 1) != 0 ||
+                   wait_for_drq(wdc) != 0) {
+                       wderror(wd, NULL, "wddump: write failed");
+                       return EIO;
+               }
+       
+               outsw(wdc->sc_iobase+wd_data, (u_int)va, lp->d_secsize >> 1);
+       
+               /* Check data request (should be done). */
+               if (wait_for_ready(wdc) != 0) {
+                       wderror(wd, NULL, "wddump: timeout waiting for ready");
+                       return EIO;
+               }
+#else  /* WD_DUMP_NOT_TRUSTED */
+               /* Let's just talk about this first... */
+               printf("wd%d: dump addr 0x%x, cylin %d, head %d, sector %d\n",
+                   unit, va, cylin, head, sector);
+               delay(500 * 1000);      /* half a second */
+#endif
+
+               /* update block count */
+               nblks -= 1;
+               blkno += 1;
+               va += lp->d_secsize;
+       }
+
+       wddoingadump = 0;
+       return 0;
+}
+#else /* __BDEVSW_DUMP_NEW_TYPE */
+int
+wddump(dev, blkno, va, size)
+        dev_t dev;
+        daddr_t blkno;
+        caddr_t va;
+        size_t size;
+{
+
+       /* Not implemented. */
+       return ENXIO;
+}
+#endif /* __BDEVSW_DUMP_NEW_TYPE */
+
+/*
+ * Internalize the bad sector table.
+ */
+void
+bad144intern(wd)
+       struct wd_softc *wd;
+{
+       struct dkbad *bt = &wd->sc_dk.dk_cpulabel->bad;
+       struct disklabel *lp = wd->sc_dk.dk_label;
+       int i = 0;
+
+       for (; i < 126; i++) {
+               if (bt->bt_bad[i].bt_cyl == 0xffff)
+                       break;
+               wd->sc_badsect[i] =
+                   bt->bt_bad[i].bt_cyl * lp->d_secpercyl +
+                   (bt->bt_bad[i].bt_trksec >> 8) * lp->d_nsectors +
+                   (bt->bt_bad[i].bt_trksec & 0xff);
+       }
+       for (; i < 127; i++)
+               wd->sc_badsect[i] = -1;
+}
+
+int
+wdcreset(wdc)
+       struct wdc_softc *wdc;
+{
+       int iobase = wdc->sc_iobase;
+
+       /* Reset the device. */
+       if (wdresethack) {
+               outb(iobase+wd_ctlr, WDCTL_RST | WDCTL_IDS);
+               delay(1000);
+               outb(iobase+wd_ctlr, WDCTL_IDS);
+               delay(1000);
+               (void) inb(iobase+wd_error);
+               outb(iobase+wd_ctlr, WDCTL_4BIT);
+       }
+
+       if (wait_for_unbusy(wdc) < 0) {
+               printf("%s: reset failed\n", wdc->sc_dev.dv_xname);
+               return 1;
+       }
+
+       return 0;
+}
+
+void
+wdcrestart(arg)
+       void *arg;
+{
+       struct wdc_softc *wdc = arg;
+       int s;
+
+       s = splbio();
+       wdcstart(wdc);
+       splx(s);
+}
+
+/*
+ * Unwedge the controller after an unexpected error.  We do this by resetting
+ * it, marking all drives for recalibration, and stalling the queue for a short
+ * period to give the reset time to finish.
+ * NOTE: We use a timeout here, so this routine must not be called during
+ * autoconfig or dump.
+ */
+void
+wdcunwedge(wdc)
+       struct wdc_softc *wdc;
+{
+       int unit;
+
+       untimeout(wdctimeout, wdc);
+       (void) wdcreset(wdc);
+
+       /* Schedule recalibrate for all drives on this controller. */
+       for (unit = 0; unit < wd_cd.cd_ndevs; unit++) {
+               struct wd_softc *wd = wd_cd.cd_devs[unit];
+               if (!wd || (void *)wd->sc_dev.dv_parent != wdc)
+                       continue;
+               if (wd->sc_state > RECAL)
+                       wd->sc_state = RECAL;
+       }
+
+       wdc->sc_flags |= WDCF_ERROR;
+       ++wdc->sc_errors;
+
+       /* Wake up in a little bit and restart the operation. */
+       timeout(wdcrestart, wdc, RECOVERYTIME);
+}
+
+int
+wdcwait(wdc, mask)
+       struct wdc_softc *wdc;
+       int mask;
+{
+       int iobase = wdc->sc_iobase;
+       int timeout = 0;
+       u_char status;
+       extern int cold;
+
+       for (;;) {
+               wdc->sc_status = status = inb(iobase+wd_status);
+               if ((status & WDCS_BSY) == 0 && (status & mask) == mask)
+                       break;
+               if (++timeout > WDCNDELAY)
+                       return -1;
+               delay(WDCDELAY);
+       }
+       if (status & WDCS_ERR) {
+               wdc->sc_error = inb(iobase+wd_error);
+               return WDCS_ERR;
+       }
+#ifdef WDCNDELAY_DEBUG
+       /* After autoconfig, there should be no long delays. */
+       if (!cold && timeout > WDCNDELAY_DEBUG)
+               printf("%s: warning: busy-wait took %dus\n",
+                   wdc->sc_dev.dv_xname, WDCDELAY * timeout);
+#endif
+       return 0;
+}
+
+void
+wdctimeout(arg)
+       void *arg;
+{
+       struct wdc_softc *wdc = (struct wdc_softc *)arg;
+       int s;
+
+       s = splbio();
+       if ((wdc->sc_flags & WDCF_ACTIVE) != 0) {
+               struct wd_softc *wd = wdc->sc_drives.tqh_first;
+               struct buf *bp = wd->sc_q.b_actf;
+
+               wdc->sc_flags &= ~WDCF_ACTIVE;
+               wderror(wdc, NULL, "lost interrupt");
+               printf("%s: lost interrupt: %sing %d@%s:%d\n",
+                   wdc->sc_dev.dv_xname,
+                   (bp->b_flags & B_READ) ? "read" : "writ",
+                   wd->sc_nblks, wd->sc_dev.dv_xname, wd->sc_blkno);
+               wdcunwedge(wdc);
+       } else
+               wderror(wdc, NULL, "missing untimeout");
+       splx(s);
+}
+
+void
+wderror(dev, bp, msg)
+       void *dev;
+       struct buf *bp;
+       char *msg;
+{
+       struct wd_softc *wd = dev;
+       struct wdc_softc *wdc = dev;
+
+       if (bp) {
+               diskerr(bp, "wd", msg, LOG_PRINTF, wd->sc_skip / DEV_BSIZE,
+                   wd->sc_dk.dk_label);
+               printf("\n");
+       } else
+               printf("%s: %s: status %b error %b\n", wdc->sc_dev.dv_xname,
+                   msg, wdc->sc_status, WDCS_BITS, wdc->sc_error, WDERR_BITS);
+}
diff --git a/sys/arch/arm32/mainbus/wdreg.h b/sys/arch/arm32/mainbus/wdreg.h
new file mode 100644 (file)
index 0000000..12311b7
--- /dev/null
@@ -0,0 +1,161 @@
+/*     $NetBSD: wdreg.h,v 1.1 1996/01/31 23:25:18 mark Exp $   */
+
+/*-
+ * Copyright (c) 1991 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.
+ *
+ *     @(#)wdreg.h     7.1 (Berkeley) 5/9/91
+ */
+
+/*
+ * Disk Controller register definitions.
+ */
+#define        wd_data         0x000   /* data register (R/W - 16 bits) */
+#define wd_error       0x004   /* error register (R) */
+#define        wd_precomp      0x004   /* write precompensation (W) */
+#define        wd_features     0x004   /* features (W) */
+#define        wd_seccnt       0x008   /* sector count (R/W) */
+#define        wd_sector       0x00c   /* first sector number (R/W) */
+#define        wd_cyl_lo       0x010   /* cylinder address, low byte (R/W) */
+#define        wd_cyl_hi       0x014   /* cylinder address, high byte (R/W) */
+#define        wd_sdh          0x018   /* sector size/drive/head (R/W) */
+#define        wd_command      0x01c   /* command register (W) */
+#define        wd_status       0x01c   /* immediate status (R) */
+
+#define        wd_altsts       0x818   /* alternate fixed disk status (via 1015) (R) */
+#define        wd_ctlr         0x818   /* fixed disk controller control (via 1015) (W) */
+#define  WDCTL_4BIT     0x08   /* use four head bits (wd1003) */
+#define  WDCTL_RST      0x04   /* reset the controller */
+#define  WDCTL_IDS      0x02   /* disable controller interrupts */
+#define        wd_digin        0x81c   /* disk controller input (via 1015) (R) */
+
+/*
+ * Status bits.
+ */
+#define        WDCS_BSY        0x80    /* busy */
+#define        WDCS_DRDY       0x40    /* drive ready */
+#define        WDCS_DWF        0x20    /* drive write fault */
+#define        WDCS_DSC        0x10    /* drive seek complete */
+#define        WDCS_DRQ        0x08    /* data request */
+#define        WDCS_CORR       0x04    /* corrected data */
+#define        WDCS_IDX        0x02    /* index */
+#define        WDCS_ERR        0x01    /* error */
+#define WDCS_BITS      "\020\010bsy\007drdy\006dwf\005dsc\004drq\003corr\002idx\001err"
+
+/*
+ * Error bits.
+ */
+#define        WDCE_BBK        0x80    /* bad block detected */
+#define        WDCE_UNC        0x40    /* uncorrectable data error */
+#define        WDCE_MC         0x20    /* media changed */
+#define        WDCE_IDNF       0x10    /* id not found */
+#define        WDCE_ABRT       0x08    /* aborted command */
+#define        WDCE_MCR        0x04    /* media change requested */
+#define        WDCE_TK0NF      0x02    /* track 0 not found */
+#define        WDCE_AMNF       0x01    /* address mark not found */
+#define WDERR_BITS     "\020\010bbk\007unc\006mc\005idnf\004mcr\003abrt\002tk0nf\001amnf"
+
+/*
+ * Commands for Disk Controller.
+ */
+#define        WDCC_RECAL      0x10    /* disk restore code -- resets cntlr */
+
+#define        WDCC_READ       0x20    /* disk read code */
+#define        WDCC_WRITE      0x30    /* disk write code */
+#define         WDCC__LONG      0x02    /* modifier -- access ecc bytes */
+#define         WDCC__NORETRY   0x01    /* modifier -- no retrys */
+
+#define        WDCC_FORMAT     0x50    /* disk format code */
+#define        WDCC_DIAGNOSE   0x90    /* controller diagnostic */
+#define        WDCC_IDP        0x91    /* initialize drive parameters */
+
+#define        WDCC_READMULTI  0xc4    /* read multiple */
+#define        WDCC_WRITEMULTI 0xc5    /* write multiple */
+#define        WDCC_SETMULTI   0xc6    /* set multiple mode */
+
+#define        WDCC_READDMA    0xc8    /* read with DMA */
+#define        WDCC_WRITEDMA   0xca    /* write with DMA */
+
+#define        WDCC_ACKMC      0xdb    /* acknowledge media change */
+#define        WDCC_LOCK       0xde    /* lock drawer */
+#define        WDCC_UNLOCK     0xdf    /* unlock drawer */
+
+#define        WDCC_IDENTIFY   0xec    /* read parameters from controller */
+#define        WDCC_CACHEC     0xef    /* cache control */
+
+#define        WDSD_IBM        0xa0    /* forced to 512 byte sector, ecc */
+#define        WDSD_CHS        0x00    /* cylinder/head/sector addressing */
+#define        WDSD_LBA        0x40    /* logical block addressing */
+
+
+#ifdef _KERNEL
+/*
+ * read parameters command returns this:
+ */
+struct wdparams {
+       /* drive info */
+       short   wdp_config;             /* general configuration */
+#define        WD_CFG_REMOVABLE        0x0080
+#define        WD_CFG_FIXED            0x0040
+       short   wdp_cylinders;          /* number of non-removable cylinders */
+       char    __reserved1[2];
+       short   wdp_heads;              /* number of heads */
+       short   wdp_unfbytespertrk;     /* number of unformatted bytes/track */
+       short   wdp_unfbytespersec;     /* number of unformatted bytes/sector */
+       short   wdp_sectors;            /* number of sectors */
+       char    wdp_vendor1[6];
+       /* controller info */
+       char    wdp_serial[20];         /* serial number */
+       short   wdp_buftype;            /* buffer type */
+#define        WD_BUF_SINGLEPORTSECTOR 1        /* single port, single sector buffer */
+#define        WD_BUF_DUALPORTMULTI    2        /* dual port, multiple sector buffer */
+#define        WD_BUF_DUALPORTMULTICACHE 3      /* above plus track cache */
+       short   wdp_bufsize;            /* buffer size, in 512-byte units */
+       short   wdp_eccbytes;           /* ecc bytes appended */
+       char    wdp_revision[8];        /* firmware revision */
+       char    wdp_model[40];          /* model name */
+       u_char  wdp_maxmulti;           /* maximum sectors per interrupt */
+       char    wdp_vendor2[1];
+       short   wdp_usedmovsd;          /* can use double word read/write? */
+       char    wdp_vendor3[1];
+       char    wdp_capabilities;       /* capability flags */
+#define        WD_CAP_LBA      0x02
+#define        WD_CAP_DMA      0x01
+       char    __reserved2[2];
+       char    wdp_vendor4[1];         
+       char    wdp_piotiming;          /* PIO timing mode */
+       char    wdp_vendor5[1];
+       char    wdp_dmatiming;          /* DMA timing mode */
+};
+#endif /* _KERNEL */
diff --git a/sys/arch/arm32/podulebus/asc.c b/sys/arch/arm32/podulebus/asc.c
new file mode 100644 (file)
index 0000000..80f64e3
--- /dev/null
@@ -0,0 +1,483 @@
+/* $NetBSD: asc.c,v 1.5 1996/04/19 20:13:56 mark Exp $ */
+
+/*
+ * Copyright (c) 1996 Mark Brinicombe
+ * Copyright (c) 1982, 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     from:ahsc.c
+ */
+
+/*
+ * Ok this driver is not wonderful yet. It only supports POLLING mode
+ * The Acorn SCSI card (or any WD3393 based card) does not support
+ * DMA so the DMA section of this driver and the sbic driver needs
+ * to be rewritten.
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/device.h>
+#include <scsi/scsi_all.h>
+#include <scsi/scsiconf.h>
+#include <machine/io.h>
+#include <machine/irqhandler.h>
+#include <machine/katelib.h>
+#include <arm32/podulebus/podulebus.h>
+#include <arm32/podulebus/sbicreg.h>
+#include <arm32/podulebus/sbicvar.h>
+#include <arm32/podulebus/ascreg.h>
+#include <arm32/podulebus/ascvar.h>
+
+int ascprint __P((void *auxp, char *));
+void ascattach __P((struct device *, struct device *, void *));
+int ascmatch __P((struct device *, void *, void *));
+
+void asc_enintr __P((struct sbic_softc *));
+void asc_dmastop __P((struct sbic_softc *));
+int asc_dmanext __P((struct sbic_softc *));
+int asc_dmaintr __P((struct sbic_softc *));
+int asc_dmago __P((struct sbic_softc *, char *, int, int));
+int asc_scsicmd __P((struct scsi_xfer *xs));
+int asc_intr __P((struct asc_softc *));
+
+char *strstr           __P((char */*s1*/, char */*s2*/));
+
+struct scsi_adapter asc_scsiswitch = {
+       asc_scsicmd,
+       sbic_minphys,
+       0,                      /* no lun support */
+       0,                      /* no lun support */
+};
+
+struct scsi_device asc_scsidev = {
+       NULL,           /* use default error handler */
+       NULL,           /* do not have a start functio */
+       NULL,           /* have no async handler */
+       NULL,           /* Use default done routine */
+};
+
+
+#ifdef DEBUG
+int    asc_dmadebug = 0;
+#endif
+
+struct cfattach asc_ca = {
+       sizeof(struct asc_softc), ascmatch, ascattach
+};
+
+struct cfdriver asc_cd = {
+       NULL, "asc", DV_DULL, NULL, 0
+};
+
+u_long scsi_nosync;
+int shift_nosync;
+
+#if ASC_POLL > 0
+int asc_poll = 1;
+
+extern char *boot_args;
+#endif
+
+int
+ascmatch(pdp, match, auxp)
+       struct device *pdp;
+       void *match, *auxp;
+{
+       struct podule_attach_args *pa = (struct podule_attach_args *)auxp;
+       int podule;
+
+       podule = findpodule(0x00, 0x02, pa->pa_podule_number);
+
+       if (podule == -1)
+         return(0);
+
+       pa->pa_podule_number = podule;
+       pa->pa_podule = &podules[podule];
+
+       return(1);
+}
+
+void
+ascattach(pdp, dp, auxp)
+       struct device *pdp, *dp;
+       void *auxp;
+{
+       volatile struct sdmac *rp;
+       struct asc_softc *sc;
+       struct sbic_softc *sbic;
+       struct podule_attach_args *pa;
+
+       sc = (struct asc_softc *)dp;
+
+       pa = (struct podule_attach_args *)auxp;
+       sc->sc_podule_number = pa->pa_podule_number;
+       if (sc->sc_podule_number == -1)
+               panic("Podule has disappeared !");
+
+       sc->sc_podule = &podules[sc->sc_podule_number];
+       podules[sc->sc_podule_number].attached = 1;
+
+#if ASC_POLL > 0
+        if (boot_args) {
+               char *ptr;
+       
+               ptr = strstr(boot_args, "noascpoll");
+               if (ptr)
+                       asc_poll = 0;
+       }
+
+       if (asc_poll)
+               printf(" polling");
+       else
+               printf(" using interrupts");
+#endif
+       printf("\n");
+
+       sbic = &sc->sc_softc;
+
+       sbic->sc_enintr = asc_enintr;
+       sbic->sc_dmago = asc_dmago;
+       sbic->sc_dmanext = asc_dmanext;
+       sbic->sc_dmastop = asc_dmastop;
+       sbic->sc_dmacmd = 0;
+
+       /*
+        * eveything is a valid dma address
+        */
+       sbic->sc_dmamask = 0;
+       sbic->sc_sbicp = (sbic_regmap_p) (sc->sc_podule->mod_base + ASC_SBIC);
+       sbic->sc_clkfreq = sbic_clock_override ? sbic_clock_override : 143;
+       
+       sbic->sc_link.adapter_softc = sbic;
+       sbic->sc_link.adapter_target = 7;
+       sbic->sc_link.adapter = &asc_scsiswitch;
+       sbic->sc_link.device = &asc_scsidev;
+       sbic->sc_link.openings = 1;     /* was 2 */
+
+       sc->sc_pagereg = sc->sc_podule->fast_base + ASC_PAGEREG;
+        sc->sc_intstat = sc->sc_podule->fast_base + ASC_INTSTATUS;
+
+       /* Reset the card */
+
+       WriteByte(sc->sc_pagereg, 0x80);
+       DELAY(500000);
+       WriteByte(sc->sc_pagereg, 0x00);
+       DELAY(250000);
+
+       sbicinit(sbic);
+
+/* If we are polling only then we don't need a interrupt handler */
+
+       sc->sc_ih.ih_func = asc_intr;
+       sc->sc_ih.ih_arg = sc;
+       sc->sc_ih.ih_level = IPL_BIO;
+       sc->sc_ih.ih_name = "asc";
+
+#ifdef ASC_POLL
+       if (!asc_poll)
+#endif
+       if (irq_claim(IRQ_PODULE, &sc->sc_ih))
+               panic("asc: Cannot claim podule IRQ\n");
+
+       /*
+        * attach all scsi units on us
+        */
+       config_found(dp, &sbic->sc_link, ascprint);
+}
+
+/*
+ * print diag if pnp is NULL else just extra
+ */
+int
+ascprint(auxp, pnp)
+       void *auxp;
+       char *pnp;
+{
+       if (pnp == NULL)
+               return(UNCONF);
+       return(QUIET);
+}
+
+
+void
+asc_enintr(sbicsc)
+       struct sbic_softc *sbicsc;
+{
+       struct asc_softc *sc = (struct asc_softc *)sbicsc;
+/*     printf("asc_enintr\n");*/
+/*
+       volatile struct sdmac *sdp;
+
+       sdp = dev->sc_cregs;
+
+       dev->sc_flags |= SBICF_INTR;
+       sdp->CNTR = CNTR_PDMD | CNTR_INTEN;
+*/
+       sbicsc->sc_flags |= SBICF_INTR;
+       WriteByte(sc->sc_pagereg, 0x40);
+}
+
+
+int
+asc_dmago(dev, addr, count, flags)
+       struct sbic_softc *dev;
+       char *addr;
+       int count, flags;
+{
+       printf("asc_dmago\n");
+#ifdef DDB
+       Debugger();
+#else
+       panic("Hit a brick wall\n");
+#endif
+#if 0
+       volatile struct sdmac *sdp;
+
+       sdp = dev->sc_cregs;
+       /*
+        * Set up the command word based on flags
+        */
+       dev->sc_dmacmd = CNTR_PDMD | CNTR_INTEN;
+       if ((flags & DMAGO_READ) == 0)
+               dev->sc_dmacmd |= CNTR_DDIR;
+#ifdef DEBUG
+       if (ahsc_dmadebug & DDB_IO)
+               printf("ahsc_dmago: cmd %x\n", dev->sc_dmacmd);
+#endif
+
+       dev->sc_flags |= SBICF_INTR;
+       sdp->CNTR = dev->sc_dmacmd;
+       sdp->ACR = (u_int) dev->sc_cur->dc_addr;
+       sdp->ST_DMA = 1;
+
+       return(dev->sc_tcnt);
+#endif
+}
+
+void
+asc_dmastop(dev)
+       struct sbic_softc *dev;
+{
+/*     printf("asc_dmastop\n");*/
+#if 0
+       volatile struct sdmac *sdp;
+       int s;
+
+       sdp = dev->sc_cregs;
+
+#ifdef DEBUG
+       if (ahsc_dmadebug & DDB_FOLLOW)
+               printf("ahsc_dmastop()\n");
+#endif
+       if (dev->sc_dmacmd) {
+               s = splbio();
+               if ((dev->sc_dmacmd & (CNTR_TCEN | CNTR_DDIR)) == 0) {
+                       /*
+                        * only FLUSH if terminal count not enabled,
+                        * and reading from peripheral
+                        */
+                       sdp->FLUSH = 1;
+                       while ((sdp->ISTR & ISTR_FE_FLG) == 0)
+                               ;
+               }
+               /* 
+                * clear possible interrupt and stop dma
+                */
+               sdp->CINT = 1;
+               sdp->SP_DMA = 1;
+               dev->sc_dmacmd = 0;
+               splx(s);
+       }
+#endif
+}
+
+int
+asc_dmaintr(dev)
+       struct sbic_softc *dev;
+{
+       panic("asc_dmaintr");
+#if 0
+       volatile struct sdmac *sdp;
+       int stat, found;
+
+       sdp = dev->sc_cregs;
+       stat = sdp->ISTR;
+
+       if ((stat & (ISTR_INT_F|ISTR_INT_P)) == 0)
+               return (0);
+
+#ifdef DEBUG
+       if (ahsc_dmadebug & DDB_FOLLOW)
+               printf("%s: dmaintr 0x%x\n", dev->sc_dev.dv_xname, stat);
+#endif
+
+       /*
+        * both, SCSI and DMA interrupts arrive here. I chose
+        * arbitrarily that DMA interrupts should have higher
+        * precedence than SCSI interrupts.
+        */
+       found = 0;
+       if (stat & ISTR_E_INT) {
+               ++found;
+
+               sdp->CINT = 1;  /* clear possible interrupt */
+
+               /*
+                * check for SCSI ints in the same go and 
+                * eventually save an interrupt
+                */
+       }
+
+       if (dev->sc_flags & SBICF_INTR && stat & ISTR_INTS)
+               found += sbicintr(dev);
+       return(found);
+#endif
+}
+
+
+int
+asc_dmanext(dev)
+       struct sbic_softc *dev;
+{
+       printf("asc_dmanext\n");
+#ifdef DDB
+       Debugger();
+#else
+       panic("Hit a brick wall\n");
+#endif
+#if 0
+       volatile struct sdmac *sdp;
+       int i, stat;
+
+       sdp = dev->sc_cregs;
+
+       if (dev->sc_cur > dev->sc_last) {
+               /* shouldn't happen !! */
+               printf("ahsc_dmanext at end !!!\n");
+               asc_dmastop(dev);
+               return(0);
+       }
+       if ((dev->sc_dmacmd & (CNTR_TCEN | CNTR_DDIR)) == 0) {
+                 /* 
+                  * only FLUSH if terminal count not enabled,
+                  * and reading from peripheral
+                  */
+               sdp->FLUSH = 1;
+               while ((sdp->ISTR & ISTR_FE_FLG) == 0)
+                       ;
+        }
+       /* 
+        * clear possible interrupt and stop dma
+        */
+       sdp->CINT = 1;  /* clear possible interrupt */
+       sdp->SP_DMA = 1;        /* stop dma */
+       sdp->CNTR = dev->sc_dmacmd;
+       sdp->ACR = (u_int)dev->sc_cur->dc_addr;
+       sdp->ST_DMA = 1;
+
+       dev->sc_tcnt = dev->sc_cur->dc_count << 1;
+       return(dev->sc_tcnt);
+#endif
+}
+
+void
+asc_dump()
+{
+       int i;
+
+       for (i = 0; i < asc_cd.cd_ndevs; ++i)
+               if (asc_cd.cd_devs[i])
+                       sbic_dump(asc_cd.cd_devs[i]);
+}
+
+int
+asc_scsicmd(xs)
+       struct scsi_xfer *xs;
+{
+       struct scsi_link *sc_link = xs->sc_link;
+
+       /* ensure command is polling for the moment */
+#if ASC_POLL > 0
+       if (asc_poll)
+               xs->flags |= SCSI_POLL;
+#endif
+
+/*     printf("id=%d lun=%dcmdlen=%d datalen=%d opcode=%02x flags=%08x status=%02x blk=%02x %02x\n",
+           sc_link->target, sc_link->lun, xs->cmdlen, xs->datalen, xs->cmd->opcode,
+           xs->flags, xs->status, xs->cmd->bytes[0], xs->cmd->bytes[1]);*/
+
+       return(sbic_scsicmd(xs));
+}
+
+
+int
+asc_intr(sc)
+       struct asc_softc *sc;
+{
+       int intr;
+       
+/*     printf("ascintr:");*/
+               intr = ReadByte(sc->sc_intstat);
+/*             printf("%02x\n", intr);*/
+
+       if (intr & IS_SBIC_IRQ)
+               sbicintr((struct sbic_softc *)sc);
+       return(0);
+}
+
+
+int kvtop()
+{
+       printf("kvtop\n");
+#ifdef DDB
+       Debugger();
+#else
+       panic("Hit a brick wall\n");
+#endif
+       return(0);
+}
+
+void alloc_z2mem()
+{
+       panic("allocz2mem");
+}
+
+void isztwomem()
+{
+       panic("isz2mem");
+}
+
+void PREP_DMA_MEM()
+{
+       panic("PREP_DMA_MEM");
+}
diff --git a/sys/arch/arm32/podulebus/ascreg.h b/sys/arch/arm32/podulebus/ascreg.h
new file mode 100644 (file)
index 0000000..dba455e
--- /dev/null
@@ -0,0 +1,279 @@
+/* $NetBSD: ascreg.h,v 1.4 1996/03/07 23:54:29 mark Exp $ */
+
+/*
+ * Copyright (c) 1996 Mark Brinicombe
+ * Copyright (c) 1994 Christian E. Hopps
+ * Copyright (c) 1982, 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     from:ahscreg.h,v 1.2 1994/10/26 02:02:46
+ */
+
+#ifndef _ASCREG_H_
+#define _ASCREG_H_
+
+/*
+ * Hardware layout of the A3000 SDMAC. This also contains the
+ * registers for the sbic chip, but in favor of separating DMA and
+ * scsi, the scsi-driver doesn't make use of this dependency
+ */
+
+#define v_char         volatile char
+#define        v_int           volatile int
+#define vu_char                volatile u_char
+#define vu_short       volatile u_short
+#define vu_int         volatile u_int
+
+struct sdmac {
+       short           pad0;
+       vu_short DAWR;          /* DACK Width Register WO */
+       vu_int   WTC;           /* Word Transfer Count Register RW */
+       short           pad1;
+       vu_short CNTR;          /* Control Register RW */
+       vu_int   ACR;           /* Address Count Register RW */
+       short           pad2;
+       vu_short ST_DMA;        /* Start DMA Transfers RW-Strobe */
+       short           pad3;
+       vu_short FLUSH;         /* Flush FIFO RW-Strobe */
+       short           pad4;
+       vu_short CINT;          /* Clear Interrupts RW-Strobe */
+       short           pad5;
+       vu_short ISTR;          /* Interrupt Status Register RO */
+       int             pad6[7];
+       short           pad7;
+       vu_short SP_DMA;        /* Stop DMA Transfers RW-Strobe */
+       char            pad8;
+       vu_char  SASR;          /* sbic asr */
+       char            pad9;
+       vu_char  SCMD;          /* sbic data */
+};
+
+/*
+ * value to go into DAWR
+ */
+#define DAWR_AHSC      3       /* according to A3000T service-manual */
+
+/*
+ * bits defined for CNTR
+ */
+#define CNTR_TCEN      (1<<5)  /* Terminal Count Enable */
+#define CNTR_PREST     (1<<4)  /* Perp Reset (not implemented :-((( ) */
+#define CNTR_PDMD      (1<<3)  /* Perp Device Mode Select (1=SCSI,0=XT/AT) */
+#define CNTR_INTEN     (1<<2)  /* Interrupt Enable */
+#define CNTR_DDIR      (1<<1)  /* Device Direction. 1==rd host, wr perp */
+#define CNTR_IO_DX     (1<<0)  /* IORDY & CSX1 Polarity Select */
+
+/*
+ * bits defined for ISTR
+ */
+#define ISTR_INTX      (1<<8)  /* XT/AT Interrupt pending */
+#define ISTR_INT_F     (1<<7)  /* Interrupt Follow */
+#define ISTR_INTS      (1<<6)  /* SCSI Peripheral Interrupt */
+#define ISTR_E_INT     (1<<5)  /* End-Of-Process Interrupt */
+#define ISTR_INT_P     (1<<4)  /* Interrupt Pending */
+#define ISTR_UE_INT    (1<<3)  /* Under-Run FIFO Error Interrupt */
+#define ISTR_OE_INT    (1<<2)  /* Over-Run FIFO Error Interrupt */
+#define ISTR_FF_FLG    (1<<1)  /* FIFO-Full Flag */
+#define ISTR_FE_FLG    (1<<0)  /* FIFO-Empty Flag */
+
+#define DMAGO_READ 0x01
+
+
+/* Addresses relative to podule base */
+
+#define ASC_INTSTATUS  0x2000
+#define ASC_CLRINT     0x2000
+#define ASC_PAGEREG    0x3000
+
+/* Addresses relative to module base */
+
+#define ASC_DMAC               0x3000
+#define ASC_SBIC               0x2000
+#define ASC_SRAM               0x0000
+
+#define ASC_SRAM_BLKSIZE       0x1000
+
+#define IS_IRQREQ              0x01
+#define IS_DMAC_IRQ            0x02
+#define IS_SBIC_IRQ            0x08
+
+#if 0
+/* SBIC Commands */
+
+#define SBIC_CMD_Reset         0x00    /* Reset the SBIC */
+#define SBIC_Abort             0x01    /* Abort command */
+#define SBIC_Sel_tx_wATN       0x08    /* Select and Transfer with ATN */
+#define SBIC_Sel_tx_woATN      0x09    /* Select and Transfer without ATN */
+
+/* SBIC status codes */
+
+#define SBIC_ResetOk   0x00
+#define SBIC_ResetAFOk 0x01
+
+/* SBIC registers                    bit7 bit6 bit5 bit4 bit3 bit2 bit1 bit0 */
+
+#define SBIC_OWNID     0x00    /* RW  FS1  FS0    0  EHP  EAF  ID2  ID1  ID0 */
+#define SBIC_CONTROL   0x01    /* RW  DM2  DM1  DM0  HHP  EDI  IDI   HA  HSP */
+#define SBIC_TIMEREG   0x02    /* RW timeout period  value = Tper*Ficlk/80d  */
+#define SBIC_CDB1TSECT 0x03    /* RW CDB byte 1 & Total sectors per track    */
+#define SBIC_CDB2THEAD 0x04    /* RW CDB byte 2 & Total number of heads      */
+#define SBIC_CDB3TCYL1 0x05    /* RW CDB byte 3 & Total no. of cylinders MSB */
+#define SBIC_CDB4TCYL2 0x06    /* RW CDB byte 4 & Total no. of cylinders LSB */
+#define SBIC_CDB5LADR1 0x07    /* RW CDB byte 5 & Logical addr to translate  */
+#define SBIC_CBD6LADR2 0x08    /* RW CDB byte 6 & Logical addr to translate  */
+#define SBIC_CDB7LADR3 0x09    /* RW CDB byte 7 & Logical addr to translate  */
+#define SBIC_CDB8LADR4 0x0A    /* RW CDB byte 8 & Logical addr to translate  */
+#define SBIC_CDB9SECT  0x0B    /* RW CDB byte 9 & Translation sector result  */
+#define SBIC_CDB10HEAD 0x0C    /* RW CDB byte 10 & Translation head result   */
+#define SBIC_CDB11CYL1 0x0D    /* RW CDB byte 11 & Translation cyl result MSB*/
+#define SBIC_CDB12CYL2 0x0E    /* RW CDB byte 12 & Translation cyl result LSB*/
+#define SBIC_TARGETLUN 0x0F    /* RW  TLV  DOK    0    0    0  TL2  TL1  TL0 */
+#define SBIC_COMPHASE  0x10    /* RW Command Phase Register for multi-phase  */
+#define SBIC_SYNCTX    0x11    /* RW    0  TP2  TP1  TP0  OF3  OF2  OF1  OF0 */
+#define SBIC_TXCOUNT1  0x12    /* RW Transfer count MSB                      */
+#define SBIC_TXCOUNT2  0x13    /* RW Transfer count                          */
+#define SBIC_TXCOUNT3  0x14    /* RW Transfer count LSB                      */
+#define SBIC_DESTID    0x15    /* RW  SCC  DPD    0    0    0  DI2  DI1  DI0 */
+#define SBIC_SOURCEID  0x16    /* RW   ER   ES  DSP    0  SIV  SI2  SI1  SI0 */
+#define SBIC_SCSISTAT  0x17    /* RO **Interrupt type***  **Int. qualifier** */
+#define SBIC_COMMAND   0x18    /* RW  SBT *********Command code************* */
+#define SBIC_DATA      0x19    /* RW Access to data i/o FIFO for polled use  */
+
+#define SBIC_ADDRREG   0x00
+#define SBIC_DATAREG   0x04
+#define SBIC_AUX_STATUS        0x00
+
+/*
+ * My ID register, and/or CDB Size
+ */
+  
+#define SBIC_ID_FS_8_10                0x00    /* Input clock is  8-10 Mhz */
+                                       /* 11 Mhz is invalid */
+#define SBIC_ID_FS_12_15       0x40    /* Input clock is 12-15 Mhz */
+#define SBIC_ID_FS_16_20       0x80    /* Input clock is 16-20 Mhz */
+#define SBIC_ID_EHP            0x10    /* Enable host parity */
+#define SBIC_ID_EAF            0x08    /* Enable Advanced Features */
+#define SBIC_ID_MASK           0x07
+#define SBIC_ID_CBDSIZE_MASK   0x0f    /* if unk SCSI cmd group */
+
+/*
+ * Control register
+*/
+  
+#define SBIC_CTL_DMA           0x80    /* Single byte dma */
+#define SBIC_CTL_DBA_DMA       0x40    /* direct buffer acces (bus master)*/
+#define SBIC_CTL_BURST_DMA     0x20    /* continuous mode (8237) */
+#define SBIC_CTL_NO_DMA                0x00    /* Programmed I/O */
+#define SBIC_CTL_HHP           0x10    /* Halt on host parity error */
+#define SBIC_CTL_EDI           0x08    /* Ending disconnect interrupt */
+#define SBIC_CTL_IDI           0x04    /* Intermediate disconnect interrupt*/
+#define SBIC_CTL_HA            0x02    /* Halt on ATN */
+#define SBIC_CTL_HSP           0x01    /* Halt on SCSI parity error */
+
+/*
+ * Destination ID register
+ */
+
+#define SBIC_DID_DPD           0x40    /* Data Phase Direction */
+
+/*
+ * Auxiliary Status Register
+ */
+  
+#define SBIC_ASR_INT           0x80    /* Interrupt pending */
+#define SBIC_ASR_LCI           0x40    /* Last command ignored */
+#define SBIC_ASR_BSY           0x20    /* Busy, only cmd/data/asr readable */
+#define SBIC_ASR_CIP           0x10    /* Busy, cmd unavail also */
+#define SBIC_ASR_xxx           0x0c
+#define SBIC_ASR_PE            0x02    /* Parity error (even) */
+#define SBIC_ASR_DBR           0x01    /* Data Buffer Ready */
+   
+/* DMAC constants */
+
+#define DMAC_Bits              0x01
+#define DMAC_Ctrl1             0x60
+#define DMAC_Ctrl2             0x01
+#define DMAC_CLEAR_MASK                0x0E
+#define DMAC_SET_MASK          0x0F
+#define DMAC_DMA_RD_MODE       0x04
+#define DMAC_DMA_WR_MODE       0x08
+
+/* DMAC registers */
+
+#define DMAC_INITIALISE        0x0000  /* WO ---- ---- ---- ---- ---- ----  16B  RES */
+#define DMAC_CHANNEL   0x0200  /* R  ---- ---- ---- BASE SEL3 SEL2 SEL1 SEL0 */
+                               /* W  ---- ---- ---- ---- ---- BASE *SELECT** */
+#define DMAC_TXCNTLO   0x0004  /* RW   C7   C6   C5   C4   C3   C2   C1   C0 */
+#define DMAC_TXCNTHI   0x0204  /* RW  C15  C14  C13  C12  C11  C10   C9   C8 */
+#define DMAC_TXADRLO   0x0008  /* RW   A7   A6   A5   A4   A3   A2   A1   A0 */
+#define DMAC_TXADRMD   0x0208  /* RW  A15  A14  A13  A12  A11  A10   A9   A8 */
+#define DMAC_TXADRHI   0x000C  /* RW  A23  A22  A21  A20  A19  A18  A17  A16 */
+#define DMAC_DEVCON1   0x0010  /* RW  AKL  RQL  EXW  ROT  CMP DDMA AHLD  MTM */
+#define DMAC_DEVCON2   0x0210  /* RW ---- ---- ---- ---- ---- ----  WEV BHLD */
+#define DMAC_MODECON   0x0014  /* RW **TMODE** ADIR AUTI **TDIR*** ---- WORD */
+#define DMAC_STATUS    0x0214  /* RO  RQ3  RQ2  RQ1  RQ0  TC3  TC2  TC1  TC0 */
+#if 0
+templo  = dmac + 0x0018;/*    RO   T7   T6   T5   T4   T3   T2   T1   T0 */
+temphi  = dmac + 0x0218;/*    RO  T15  T14  T13  T12  T11  T10   T9   T8 */
+#endif
+#define DMAC_REQREG    0x001C  /* RW ---- ---- ---- ---- SRQ3 SRQ2 SRQ1 SRQ0 */
+#define DMAC_MASKREG   0x021C  /* RW ---- ---- ---- ----   M3   M2   M1   M0 */
+
+#ifndef _LOCORE
+#define WriteSBIC(a, d) \
+       WriteByte(sbic_base + SBIC_ADDRREG, a); \
+       WriteByte(sbic_base + SBIC_DATAREG, d);
+
+/*
+#define ReadSBIC(a) \
+       (WriteByte(sbic_base, a), ReadWord(sbic_base + 4) & 0xff)
+*/
+#define ReadSBIC(a) \
+       ReadSBIC1(sbic_base, a)
+
+
+static inline int
+ReadSBIC1(sbic_base, a)
+       u_int sbic_base;
+       int a;
+{
+       WriteByte(sbic_base + SBIC_ADDRREG, a);
+       return(ReadByte(sbic_base + SBIC_DATAREG));
+}
+
+
+#define WriteDMAC(a, d) WriteByte(dmac_base + a, d)
+#define ReadDMAC(a) ReadByte(dmac_base + a)
+#endif
+
+
+#endif
+#endif /* _ASCREG_H_ */
diff --git a/sys/arch/arm32/podulebus/ascvar.h b/sys/arch/arm32/podulebus/ascvar.h
new file mode 100644 (file)
index 0000000..a722f2f
--- /dev/null
@@ -0,0 +1,52 @@
+/* $NetBSD: ascvar.h,v 1.1 1996/03/07 23:54:31 mark Exp $ */
+
+/*
+ * Copyright (c) 1996 Mark Brinicombe
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided 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 Mark Brinicombe
+ *      for the NetBSD Project.
+ * 4. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _ASCVAR_H_
+#define _ASCVAR_H_
+
+#include <arm32/podulebus/sbicvar.h>
+#include <arm32/podulebus/ascreg.h>
+
+#define ASC_POLL 1
+
+struct asc_softc {
+       struct sbic_softc       sc_softc;
+
+       podule_t                *sc_podule;
+       int                     sc_podule_number;
+       irqhandler_t            sc_ih;
+
+       vu_int                  sc_pagereg;
+       vu_int                  sc_intstat;
+       };
+
+#endif /* _ASCVAR_H_ */
diff --git a/sys/arch/arm32/podulebus/if_ea.c b/sys/arch/arm32/podulebus/if_ea.c
new file mode 100644 (file)
index 0000000..1104d51
--- /dev/null
@@ -0,0 +1,1557 @@
+/* $NetBSD: if_ea.c,v 1.4 1996/03/27 21:49:26 mark Exp $ */
+
+/*
+ * Copyright (c) 1995 Mark Brinicombe
+ * 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 Mark Brinicombe.
+ * 4. The name of the company nor the name of the author may 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 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.
+ *
+ * RiscBSD kernel project
+ *
+ * if_ea.c
+ *
+ * Ether3 device driver
+ *
+ * Created      : 08/07/95
+ */
+
+/*
+ * SEEQ 8005 device driver
+ */
+
+/*
+ * Bugs/possible improvements:
+ *     - Does not currently support DMA
+ *     - Does not currently support multicasts
+ *     - Does not transmit multiple packets in one go
+ */
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/errno.h>
+#include <sys/ioctl.h>
+#include <sys/mbuf.h>
+#include <sys/socket.h>
+#include <sys/syslog.h>
+#include <sys/device.h>
+
+#include <net/if.h>
+#include <net/if_dl.h>
+#include <net/if_types.h>
+
+#ifdef INET
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/in_var.h>
+#include <netinet/ip.h>
+#include <netinet/if_ether.h>
+#endif
+
+#ifdef NS
+#include <netns/ns.h>
+#include <netns/ns_if.h>
+#endif
+
+#include "bpfilter.h"
+#if NBPFILTER > 0
+#include <net/bpf.h>
+#include <net/bpfdesc.h>
+#endif
+
+#include <machine/cpu.h>
+#include <machine/katelib.h>
+#include <machine/io.h>
+#include <machine/irqhandler.h>
+
+#include <arm32/podulebus/if_eareg.h>
+#include <arm32/podulebus/podulebus.h>
+
+#define ETHER_MIN_LEN  64
+#define ETHER_MAX_LEN  1514
+#define ETHER_ADDR_LEN 6
+
+#ifndef EA_TIMEOUT
+#define EA_TIMEOUT     60
+#endif
+
+/*#define EA_TX_DEBUG*/
+/*#define EA_RX_DEBUG*/
+/*#define EA_DEBUG*/
+/*#define EA_PACKET_DEBUG*/
+
+/* for debugging convenience */
+#ifdef EA_DEBUG
+#define dprintf(x) printf x
+#else
+#define dprintf(x)
+#endif
+
+#define MY_MANUFACTURER 0x11
+#define MY_PODULE       0xa4
+
+/*
+ * per-line info and status
+ */
+
+struct ea_softc {
+       struct device sc_dev;
+       irqhandler_t sc_ih;
+       int sc_irq;                     /* IRQ number */
+       podule_t *sc_podule;            /* Our podule */
+       int sc_podule_number;           /* Our podule number */
+       u_int sc_iobase;                /* base I/O addr */
+       struct arpcom sc_arpcom;        /* ethernet common */
+       char sc_pktbuf[EA_BUFSIZ];      /* frame buffer */
+       int sc_config1;                 /* Current config1 bits */
+       int sc_config2;                 /* Current config2 bits */
+       int sc_command;                 /* Current command bits */
+       int sc_irqclaimed;              /* Whether we have an IRQ claimed */
+       int sc_rx_ptr;                  /* Receive buffer pointer */
+       int sc_tx_ptr;                  /* Transmit buffer pointer */
+};
+
+/*
+ * prototypes
+ */
+
+static int eaintr __P((void *));
+static int ea_init __P((struct ea_softc *));
+static int ea_ioctl __P((struct ifnet *, u_long, caddr_t));
+static void ea_start __P((struct ifnet *));
+static void ea_watchdog __P((int));
+static void ea_reinit __P((struct ea_softc *));
+static void ea_chipreset __P((struct ea_softc *));
+static void ea_ramtest __P((struct ea_softc *));
+static int ea_stoptx __P((struct ea_softc *));
+static int ea_stoprx __P((struct ea_softc *));
+static void ea_stop __P((struct ea_softc *));
+static void ea_writebuf __P((struct ea_softc *, u_char *, int, int));
+static void ea_readbuf __P((struct ea_softc *, u_char *, int, int));
+static void earead __P((struct ea_softc *, caddr_t, int));
+static struct mbuf *eaget __P((caddr_t, int, struct ifnet *));
+static void ea_hardreset __P((struct ea_softc *));
+static void eagetpackets __P((struct ea_softc *));
+static void eatxpacket __P((struct ea_softc *));
+
+int eaprobe __P((struct device *, void *, void *));
+void eaattach __P((struct device *, struct device *, void *));
+
+/* driver structure for autoconf */
+
+struct cfattach ea_ca = {
+       sizeof(struct ea_softc), eaprobe, eaattach
+};
+
+struct cfdriver ea_cd = {
+       NULL, "ea", DV_IFNET
+};
+
+#if 0
+
+/*
+ * Dump the chip registers
+ */
+
+void
+eadump(iobase)
+       u_int iobase;
+{
+       dprintf(("%08x: %04x %04x %04x %04x %04x %04x %04x %04x\n", iobase,
+           ReadShort(iobase + 0x00), ReadShort(iobase + 0x40),
+           ReadShort(iobase + 0x80), ReadShort(iobase + 0xc0),
+           ReadShort(iobase + 0x100), ReadShort(iobase + 0x140),
+           ReadShort(iobase + 0x180), ReadShort(iobase + 0x1c0)));
+}
+#endif
+
+/*
+ * Dump the interface buffer
+ */
+
+void
+ea_dump_buffer(sc, offset)
+       struct ea_softc *sc;
+       int offset;
+{
+#ifdef EA_PACKET_DEBUG
+       u_int iobase = sc->sc_iobase;
+       int addr;
+       int loop;
+       int size;
+       int ctrl;
+       int ptr;
+       
+       addr = offset;
+
+       do {
+               WriteShort(sc->sc_iobase + EA_8005_COMMAND, sc->sc_command | EA_CMD_FIFO_READ);
+               WriteShort(iobase + EA_8005_CONFIG1, sc->sc_config1 | EA_BUFCODE_LOCAL_MEM);
+               WriteShort(iobase + EA_8005_DMA_ADDR, addr);
+
+               ptr = ReadShort(iobase + EA_8005_BUFWIN);
+               ctrl = ReadShort(iobase + EA_8005_BUFWIN);
+               ptr = ((ptr & 0xff) << 8) | ((ptr >> 8) & 0xff);
+
+               if (ptr == 0) break;
+               size = ptr - addr;
+
+               printf("addr=%04x size=%04x ", addr, size);
+               printf("cmd=%02x st=%02x\n", ctrl & 0xff, ctrl >> 8);
+
+               for (loop = 0; loop < size - 4; loop += 2)
+                       printf("%04x ", ReadShort(iobase + EA_8005_BUFWIN));
+               printf("\n");
+               addr = ptr;
+       } while (size != 0);
+#endif
+}
+
+/*
+ * Probe routine.
+ */
+
+/*
+ * int eaprobe(struct device *parent, void *match, void *aux)
+ *
+ * Probe for the ether3 podule.
+ */
+
+int
+eaprobe(parent, match, aux)
+       struct device *parent;
+       void *match;
+       void *aux;
+{
+       struct podule_attach_args *pa = (void *)aux;
+       int podule;
+       u_int iobase;
+       
+/*     dprintf(("Probing for SEEQ 8005... \n"));*/
+
+/* Look for a network slot interface */
+
+       podule = findpodule(MY_MANUFACTURER, MY_PODULE, pa->pa_podule_number);
+
+/* Fail if we did not find it */
+
+       if (podule == -1)
+               return(0);
+
+       iobase = podules[podule].mod_base + EA_8005_BASE;
+
+/* Reset it  - Why here ? */
+
+       WriteShort(iobase + EA_8005_CONFIG2, EA_CFG2_RESET);
+       delay(100);
+
+/* We found it */
+
+       pa->pa_podule_number = podule;
+       pa->pa_podule = &podules[podule];
+
+       return(1);
+}
+
+
+/*
+ * void eaattach(struct device *parent, struct device *dev, void *aux)
+ *
+ * Attach podule.
+ */
+
+void
+eaattach(parent, self, aux)
+       struct device *parent;
+       struct device *self;
+       void *aux;
+{
+       struct ea_softc *sc = (void *)self;
+       struct podule_attach_args *pa = (void *)aux;
+       struct ifnet *ifp = &sc->sc_arpcom.ac_if;
+       int loop;
+       int sum;
+
+/*     dprintf(("Attaching %s...\n", sc->sc_dev.dv_xname));*/
+
+/* Note the podule number and validate */
+
+       sc->sc_podule_number = pa->pa_podule_number;
+       if (sc->sc_podule_number == -1)
+               panic("Podule has disappeared !");
+
+       sc->sc_podule = &podules[sc->sc_podule_number];
+       podules[sc->sc_podule_number].attached = 1;
+
+/* Set the address of the controller for easy access */
+       
+       sc->sc_iobase = sc->sc_podule->mod_base + EA_8005_BASE;
+
+       sc->sc_irqclaimed = 0;
+
+/* Set up the interrupt structure */
+
+       sc->sc_ih.ih_func = eaintr;
+       sc->sc_ih.ih_arg = sc;
+       sc->sc_ih.ih_level = IPL_NET;
+       sc->sc_ih.ih_name = "net: ea";
+
+/* Claim either a network slot interrupt or a podule interrupt */
+
+       if (sc->sc_podule_number >= MAX_PODULES)
+               sc->sc_irq = IRQ_NETSLOT;
+       else
+               sc->sc_irq = IRQ_PODULE /*+ sc->sc_podule_number*/;
+
+       /* Stop the board. */
+
+       ea_chipreset(sc);
+       ea_stoptx(sc);
+       ea_stoprx(sc);
+
+       /* Initialise ifnet structure. */
+
+       ifp->if_unit = sc->sc_dev.dv_unit;
+       ifp->if_name = ea_cd.cd_name;
+       ifp->if_start = ea_start;
+       ifp->if_ioctl = ea_ioctl;
+       ifp->if_watchdog = ea_watchdog;
+       ifp->if_flags = IFF_BROADCAST | IFF_NOTRAILERS;
+
+       /* Now we can attach the interface. */
+
+/*     dprintf(("Attaching interface...\n"));*/
+       if_attach(ifp);
+       ether_ifattach(ifp);
+
+/* Read the station address - the receiver must be off */
+
+       WriteShort(sc->sc_iobase + EA_8005_CONFIG1, EA_BUFCODE_STATION_ADDR0);
+       
+       for (sum = 0, loop = 0; loop < ETHER_ADDR_LEN; ++loop) {
+               sc->sc_arpcom.ac_enaddr[loop] =
+                   ReadByte(sc->sc_iobase + EA_8005_BUFWIN);
+               sum += sc->sc_arpcom.ac_enaddr[loop];
+       }
+
+/*
+ * Hard code the ether address if we don't have one.
+ * Need to work out how I get the real address
+ */
+
+       if (sum == 0) {
+               sc->sc_arpcom.ac_enaddr[0] = 0x00;
+               sc->sc_arpcom.ac_enaddr[1] = 0x00;
+               sc->sc_arpcom.ac_enaddr[2] = 0xa4;
+               sc->sc_arpcom.ac_enaddr[3] = 0x10;
+               sc->sc_arpcom.ac_enaddr[4] = 0x02;
+               sc->sc_arpcom.ac_enaddr[5] = 0x87;
+       }
+
+       /* Print out some information for the user. */
+
+       printf(" SEEQ8005 address %s", ether_sprintf(sc->sc_arpcom.ac_enaddr));
+
+       /* Finally, attach to bpf filter if it is present. */
+
+#if NBPFILTER > 0
+/*     dprintf(("Attaching to BPF...\n"));*/
+       bpfattach(&ifp->if_bpf, ifp, DLT_EN10MB, sizeof(struct ether_header));
+#endif
+
+       /* Should test the RAM */
+
+       ea_ramtest(sc);
+       
+/*     dprintf(("eaattach() finished.\n"));*/
+}
+
+
+/*
+ * Test the RAM on the ethernet card. This does not work yet
+ */
+
+void
+ea_ramtest(sc)
+       struct ea_softc *sc;
+{
+       register u_int iobase = sc->sc_iobase;
+       register int loop;
+       register u_int sum = 0;
+
+/*     dprintf(("ea_ramtest()\n"));*/
+
+       /*
+        * Test the buffer memory on the board.
+        * Write simple pattens to it and read them back.
+        */
+
+       /* Set up the whole buffer RAM for writing */
+
+       WriteShort(iobase + EA_8005_CONFIG1, EA_BUFCODE_TX_EAP);
+       WriteShort(iobase + EA_8005_BUFWIN, ((EA_BUFFER_SIZE >> 8) - 1));
+       WriteShort(iobase + EA_8005_TX_PTR, 0x0000);
+       WriteShort(iobase + EA_8005_RX_PTR, EA_BUFFER_SIZE - 2);
+
+       /* Set the write start address and write a pattern */
+
+       ea_writebuf(sc, NULL, 0x0000, 0);
+
+       for (loop = 0; loop < EA_BUFFER_SIZE; loop += 2)
+               WriteShort(iobase + EA_8005_BUFWIN, loop);
+
+       /* Set the read start address and verify the pattern */
+       
+       ea_readbuf(sc, NULL, 0x0000, 0);
+
+       for (loop = 0; loop < EA_BUFFER_SIZE; loop += 2)
+               if (ReadShort(iobase + EA_8005_BUFWIN) != loop)
+                       ++sum;
+
+       if (sum != 0)
+               dprintf(("sum=%d\n", sum));
+
+       /* Set the write start address and write a pattern */
+
+       ea_writebuf(sc, NULL, 0x0000, 0);
+
+       for (loop = 0; loop < EA_BUFFER_SIZE; loop += 2)
+               WriteShort(iobase + EA_8005_BUFWIN, loop ^ (EA_BUFFER_SIZE - 1));
+
+       /* Set the read start address and verify the pattern */
+
+       ea_readbuf(sc, NULL, 0x0000, 0);
+
+       for (loop = 0; loop < EA_BUFFER_SIZE; loop += 2)
+               if (ReadShort(iobase + EA_8005_BUFWIN) != (loop ^ (EA_BUFFER_SIZE - 1)))
+                       ++sum;
+
+       if (sum != 0)
+               dprintf(("sum=%d\n", sum));
+
+       /* Set the write start address and write a pattern */
+
+       ea_writebuf(sc, NULL, 0x0000, 0);
+
+       for (loop = 0; loop < EA_BUFFER_SIZE; loop += 2)
+               WriteShort(iobase + EA_8005_BUFWIN, 0xaa55);
+
+       /* Set the read start address and verify the pattern */
+
+       ea_readbuf(sc, NULL, 0x0000, 0);
+
+       for (loop = 0; loop < EA_BUFFER_SIZE; loop += 2)
+               if (ReadShort(iobase + EA_8005_BUFWIN) != 0xaa55)
+                       ++sum;
+
+       if (sum != 0)
+               dprintf(("sum=%d\n", sum));
+
+       /* Set the write start address and write a pattern */
+
+       ea_writebuf(sc, NULL, 0x0000, 0);
+
+       for (loop = 0; loop < EA_BUFFER_SIZE; loop += 2)
+               WriteShort(iobase + EA_8005_BUFWIN, 0x55aa);
+
+       /* Set the read start address and verify the pattern */
+
+       ea_readbuf(sc, NULL, 0x0000, 0);
+
+       for (loop = 0; loop < EA_BUFFER_SIZE; loop += 2)
+               if (ReadShort(iobase + EA_8005_BUFWIN) != 0x55aa)
+                       ++sum;
+
+       if (sum != 0)
+               dprintf(("sum=%d\n", sum));
+
+       /* Report */
+
+       if (sum == 0)
+               printf(" %dK buffer RAM\n", EA_BUFFER_SIZE / 1024);
+       else
+               printf(" buffer RAM failed self test, %d faults\n", sum);
+}
+
+
+/* Claim an irq for the board */
+
+void
+ea_claimirq(sc)
+       struct ea_softc *sc;
+{
+/* Have we claimed one already ? */
+
+       if (sc->sc_irqclaimed) return;
+
+/* Claim it */
+
+       dprintf(("ea_claimirq(%d)\n", sc->sc_irq));
+       if (irq_claim(sc->sc_irq, &sc->sc_ih))
+               panic("Cannot install IRQ handler for IRQ %d\n", sc->sc_irq);
+
+       sc->sc_irqclaimed = 1;
+}
+
+
+/* Release an irq */
+
+void
+ea_releaseirq(sc)
+       struct ea_softc *sc;
+{
+/* Have we claimed one ? */
+
+       if (!sc->sc_irqclaimed) return;
+
+       dprintf(("ea_releaseirq(%d)\n", sc->sc_irq));
+       if (irq_release(sc->sc_irq, &sc->sc_ih))
+               panic("Cannot release IRQ handler for IRQ %d\n", sc->sc_irq);
+
+       sc->sc_irqclaimed = 0;
+}
+
+
+/*
+ * Stop and reinitialise the interface.
+ */
+
+static void
+ea_reinit(sc)
+       struct ea_softc *sc;
+{
+       int s;
+
+       dprintf(("eareinit()\n"));
+
+/* Stop and reinitialise the interface */
+
+       s = splimp();
+       ea_stop(sc);
+       ea_init(sc);
+       (void)splx(s);
+}
+
+
+/*
+ * Stop the tx interface.
+ *
+ * Returns 0 if the tx was already stopped or 1 if it was active
+ */
+
+static int
+ea_stoptx(sc)
+       struct ea_softc *sc;
+{
+       u_int iobase = sc->sc_iobase;
+       int timeout;
+       int status;
+
+       dprintf(("ea_stoptx()\n"));
+
+       status = ReadShort(iobase + EA_8005_STATUS);
+       if (!(status & EA_STATUS_TX_ON))
+               return(0);
+
+/* Stop any tx and wait for confirmation */
+
+       WriteShort(iobase + EA_8005_COMMAND, sc->sc_command | EA_CMD_TX_OFF);
+
+       timeout = 20000;
+       do {
+               status = ReadShort(iobase + EA_8005_STATUS);
+       } while ((status & EA_STATUS_TX_ON) && --timeout > 0);
+       if (timeout == 0)
+               dprintf(("ea_stoptx: timeout waiting for tx termination\n"));
+
+/* Clear any pending tx interrupt */
+
+       WriteShort(iobase + EA_8005_COMMAND, sc->sc_command | EA_CMD_TX_INTACK);
+       return(1);
+}
+
+
+/*
+ * Stop the rx interface.
+ *
+ * Returns 0 if the tx was already stopped or 1 if it was active
+ */
+
+static int
+ea_stoprx(sc)
+       struct ea_softc *sc;
+{
+       u_int iobase = sc->sc_iobase;
+       int timeout;
+       int status;
+
+       dprintf(("ea_stoprx()\n"));
+
+       status = ReadShort(iobase + EA_8005_STATUS);
+       if (!(status & EA_STATUS_RX_ON))
+               return(0);
+
+/* Stop any rx and wait for confirmation */
+
+       WriteShort(iobase + EA_8005_COMMAND, sc->sc_command | EA_CMD_RX_OFF);
+
+       timeout = 20000;
+       do {
+               status = ReadShort(iobase + EA_8005_STATUS);
+       } while ((status & EA_STATUS_RX_ON) && --timeout > 0);
+       if (timeout == 0)
+               dprintf(("ea_stoprx: timeout waiting for rx termination\n"));
+
+/* Clear any pending rx interrupt */
+
+       WriteShort(iobase + EA_8005_COMMAND, sc->sc_command | EA_CMD_RX_INTACK);
+       return(1);
+}
+
+
+/*
+ * Stop interface.
+ * Stop all IO and shut the interface down
+ */
+
+static void
+ea_stop(sc)
+       struct ea_softc *sc;
+{
+       u_int iobase = sc->sc_iobase;
+
+       dprintf(("ea_stop()\n"));
+
+/* Stop all IO */
+
+       ea_stoptx(sc);
+       ea_stoprx(sc);
+
+/* Disable rx and tx interrupts */
+
+       sc->sc_command &= (EA_CMD_RX_INTEN | EA_CMD_TX_INTEN);
+
+/* Clear any pending interrupts */
+
+       WriteShort(iobase + EA_8005_COMMAND, sc->sc_command
+           | EA_CMD_RX_INTACK | EA_CMD_TX_INTACK | EA_CMD_DMA_INTACK
+           | EA_CMD_BW_INTACK);
+       dprintf(("st=%08x", ReadShort(iobase + EA_8005_STATUS)));
+
+/* Release the irq */
+
+       ea_releaseirq(sc);
+
+       /* Cancel any watchdog timer */
+       
+       sc->sc_arpcom.ac_if.if_timer = 0;
+}
+
+
+/*
+ * Reset the chip
+ * Following this the software registers are reset
+ */
+
+static void
+ea_chipreset(sc)
+       struct ea_softc *sc;
+{
+       u_int iobase = sc->sc_iobase;
+
+       dprintf(("ea_chipreset()\n"));
+
+/* Reset the controller. Min of 4us delay here */
+
+       WriteShort(iobase + EA_8005_CONFIG2, EA_CFG2_RESET);
+       delay(100);
+
+       sc->sc_command = 0;
+       sc->sc_config1 = 0;
+       sc->sc_config2 = 0;
+}
+
+
+/*
+ * Do a hardware reset of the board, and upload the ethernet address again in
+ * case the board forgets.
+ */
+
+static void
+ea_hardreset(sc)
+       struct ea_softc *sc;
+{
+       u_int iobase = sc->sc_iobase;
+       int loop;
+
+       dprintf(("ea_hardreset()\n"));
+
+/* Stop any activity */
+
+       ea_stoptx(sc);
+       ea_stoprx(sc);
+
+       ea_chipreset(sc);
+
+/* Set up defaults for the registers */
+
+       sc->sc_config2 = 0;
+       WriteShort(iobase + EA_8005_CONFIG2, sc->sc_config2);
+       sc->sc_command = 0x00;
+       sc->sc_config1 = EA_CFG1_STATION_ADDR0 | EA_CFG1_DMA_BSIZE_1 | EA_CFG1_DMA_BURST_CONT;
+       WriteShort(iobase + EA_8005_CONFIG1, sc->sc_config1);
+       WriteShort(iobase + EA_8005_COMMAND, sc->sc_command);
+
+       WriteShort(iobase + EA_8005_CONFIG1, EA_BUFCODE_TX_EAP);
+       WriteShort(iobase + EA_8005_BUFWIN, ((EA_TX_BUFFER_SIZE >> 8) - 1));
+
+/* Write the station address - the receiver must be off */
+
+       WriteShort(sc->sc_iobase + EA_8005_CONFIG1,
+           sc->sc_config1 | EA_BUFCODE_STATION_ADDR0);
+       for (loop = 0; loop < ETHER_ADDR_LEN; ++loop) {
+               WriteByte(sc->sc_iobase + EA_8005_BUFWIN, sc->sc_arpcom.ac_enaddr[loop]);
+       }
+}
+
+
+/*
+ * write to the buffer memory on the interface
+ *
+ * If addr is within range for the interface buffer then the buffer
+ * address is set to addr.
+ * If len != 0 then data is copied from the address starting at buf
+ * to the interface buffer.
+ */
+
+static void
+ea_writebuf(sc, buf, addr, len)
+       struct ea_softc *sc;
+       u_char *buf;
+       int addr;
+       int len;
+{
+       u_int iobase = sc->sc_iobase;
+       int loop;
+       int timeout;
+
+       dprintf(("writebuf: st=%04x\n", ReadShort(iobase + EA_8005_STATUS)));
+
+/* If we have a valid buffer address set the buffer pointer and direction */
+
+       if (addr >= 0 && addr < EA_BUFFER_SIZE) {
+               WriteShort(iobase + EA_8005_CONFIG1, sc->sc_config1 | EA_BUFCODE_LOCAL_MEM);
+               WriteShort(iobase + EA_8005_COMMAND, sc->sc_command | EA_CMD_FIFO_WRITE);
+
+               /* Should wait here of FIFO empty flag */
+
+               timeout = 20000;
+               while ((ReadShort(iobase + EA_8005_STATUS) & EA_STATUS_FIFO_EMPTY) == 0 && --timeout > 0);
+
+
+               WriteShort(iobase + EA_8005_DMA_ADDR, addr);
+       }
+
+       for (loop = 0; loop < len; loop += 2)
+               WriteShort(iobase + EA_8005_BUFWIN, buf[loop] | buf[loop + 1] << 8);
+
+/*     if (len > 0)
+               outsw(iobase + EA_8005_BUFWIN, buf, len / 2);*/
+}
+
+
+/*
+ * read from the buffer memory on the interface
+ *
+ * If addr is within range for the interface buffer then the buffer
+ * address is set to addr.
+ * If len != 0 then data is copied from the interface buffer to the
+ * address starting at buf.
+ */
+
+static void
+ea_readbuf(sc, buf, addr, len)
+       struct ea_softc *sc;
+       u_char *buf;
+       int addr;
+       int len;
+{
+       u_int iobase = sc->sc_iobase;
+       int loop;
+       int word;
+       int timeout;
+
+       dprintf(("readbuf: st=%04x addr=%04x len=%d\n", ReadShort(iobase + EA_8005_STATUS), addr, len));
+
+/* If we have a valid buffer address set the buffer pointer and direction */
+
+       if (addr >= 0 && addr < EA_BUFFER_SIZE) {
+               if ((ReadShort(iobase + EA_8005_STATUS) & EA_STATUS_FIFO_DIR) == 0) {
+                       /* Should wait here of FIFO empty flag */
+
+                       timeout = 20000;
+                       while ((ReadShort(iobase + EA_8005_STATUS) & EA_STATUS_FIFO_EMPTY) == 0 && --timeout > 0);
+               }
+               WriteShort(iobase + EA_8005_CONFIG1, sc->sc_config1 | EA_BUFCODE_LOCAL_MEM);
+               WriteShort(iobase + EA_8005_COMMAND, sc->sc_command | EA_CMD_FIFO_WRITE);
+
+               /* Should wait here of FIFO empty flag */
+
+               timeout = 20000;
+               while ((ReadShort(iobase + EA_8005_STATUS) & EA_STATUS_FIFO_EMPTY) == 0 && --timeout > 0);
+
+               WriteShort(iobase + EA_8005_DMA_ADDR, addr);
+               WriteShort(iobase + EA_8005_COMMAND, sc->sc_command | EA_CMD_FIFO_READ);
+
+               /* Should wait here of FIFO full flag */
+
+               timeout = 20000;
+               while ((ReadShort(iobase + EA_8005_STATUS) & EA_STATUS_FIFO_FULL) == 0 && --timeout > 0);
+
+
+       }
+
+       for (loop = 0; loop < len; loop += 2) {
+               word = ReadShort(iobase + EA_8005_BUFWIN);
+               buf[loop] = word & 0xff;
+               buf[loop + 1] = word >> 8;
+       }
+}
+
+
+/*
+ * Initialize interface.
+ *
+ * This should leave the interface in a state for packet reception and transmission
+ */
+
+static int
+ea_init(sc)
+       struct ea_softc *sc;
+{
+       struct ifnet *ifp = &sc->sc_arpcom.ac_if;
+       u_int iobase = sc->sc_iobase;
+       int s;
+
+       dprintf(("ea_init()\n"));
+
+       s = splimp();
+
+/* Grab an irq */
+
+       ea_claimirq(sc);
+
+       /* First, reset the board. */
+
+       ea_hardreset(sc);
+
+/* Configure rx. */
+
+       dprintf(("Configuring rx...\n"));
+       if (ifp->if_flags & IFF_PROMISC)
+               sc->sc_config1 = EA_CFG1_PROMISCUOUS;
+       else
+               sc->sc_config1 = EA_CFG1_BROADCAST;
+
+       sc->sc_config1 |= EA_CFG1_DMA_BSIZE_8 | EA_CFG1_STATION_ADDR0 | EA_CFG1_DMA_BURST_CONT;
+       WriteShort(iobase + EA_8005_CONFIG1, sc->sc_config1);
+
+/* Configure TX. */
+
+       dprintf(("Configuring tx...\n"));
+
+       WriteShort(iobase + EA_8005_CONFIG1, sc->sc_config1 | EA_BUFCODE_TX_EAP);
+       WriteShort(iobase + EA_8005_BUFWIN, ((EA_TX_BUFFER_SIZE >> 8) - 1));
+       WriteShort(iobase + EA_8005_TX_PTR, 0x0000);
+
+       sc->sc_config2 |= EA_CFG2_OUTPUT;
+       WriteShort(iobase + EA_8005_CONFIG2, sc->sc_config2);
+
+/* Place a NULL header at the beginning of the transmit area */
+
+       ea_writebuf(sc, NULL, 0x0000, 0);
+               
+       WriteShort(iobase + EA_8005_BUFWIN, 0x0000);
+       WriteShort(iobase + EA_8005_BUFWIN, 0x0000);
+
+       sc->sc_command |= EA_CMD_TX_INTEN;
+       WriteShort(iobase + EA_8005_COMMAND, sc->sc_command);
+
+/* Setup the Rx pointers */
+
+       sc->sc_rx_ptr = EA_TX_BUFFER_SIZE;
+
+       WriteShort(iobase + EA_8005_RX_PTR, sc->sc_rx_ptr);
+       WriteShort(iobase + EA_8005_RX_END, (sc->sc_rx_ptr >> 8));
+
+/* Place a NULL header at the beginning of the receive area */
+
+       ea_writebuf(sc, NULL, sc->sc_rx_ptr, 0);
+               
+       WriteShort(iobase + EA_8005_BUFWIN, 0x0000);
+       WriteShort(iobase + EA_8005_BUFWIN, 0x0000);
+
+/* Turn on Rx */
+
+       sc->sc_command |= EA_CMD_RX_INTEN;
+       WriteShort(iobase + EA_8005_COMMAND, sc->sc_command | EA_CMD_RX_ON);
+
+       /* Set flags appropriately. */
+       ifp->if_flags |= IFF_RUNNING;
+       ifp->if_flags &= ~IFF_OACTIVE;
+
+       dprintf(("init: st=%04x\n", ReadShort(iobase + EA_8005_STATUS)));
+
+       /* And start output. */
+       ea_start(ifp);
+
+       (void)splx(s);
+       return(0);
+}
+
+
+/*
+ * Start output on interface. Get datagrams from the queue and output them,
+ * giving the receiver a chance between datagrams. Call only from splimp or
+ * interrupt level!
+ */
+
+static void
+ea_start(ifp)
+       struct ifnet *ifp;
+{
+       struct ea_softc *sc = ea_cd.cd_devs[ifp->if_unit];
+       int s;
+
+       s = splimp();
+#ifdef EA_TX_DEBUG
+       dprintf(("ea_start()...\n"));
+#endif
+
+       /* Don't do anything if output is active. */
+
+       if (sc->sc_arpcom.ac_if.if_flags & IFF_OACTIVE)
+               return;
+
+       /* Mark interface as output active */
+       
+       sc->sc_arpcom.ac_if.if_flags |= IFF_OACTIVE;
+
+       /* tx packets */
+
+       eatxpacket(sc);
+       (void)splx(s);
+}
+
+
+/*
+ * Transfer a packet to the interface buffer and start transmission
+ *
+ * Called at splimp()
+ */
+void
+eatxpacket(sc)
+       struct ea_softc *sc;
+{
+       u_int iobase = sc->sc_iobase;
+       struct mbuf *m, *m0;
+       int len;
+
+/* Dequeue the next datagram. */
+
+       IF_DEQUEUE(&sc->sc_arpcom.ac_if.if_snd, m0);
+
+/* If there's nothing to send, return. */
+
+       if (!m0) {
+               sc->sc_arpcom.ac_if.if_flags &= ~IFF_OACTIVE;
+               sc->sc_config2 |= EA_CFG2_OUTPUT;
+               WriteShort(iobase + EA_8005_CONFIG2, sc->sc_config2);
+#ifdef EA_TX_DEBUG
+               dprintf(("tx finished\n"));
+#endif
+               return;
+       }
+
+       /* Give the packet to the bpf, if any. */
+#if NBPFILTER > 0
+       if (sc->sc_arpcom.ac_if.if_bpf)
+               bpf_mtap(sc->sc_arpcom.ac_if.if_bpf, m0);
+#endif
+
+#ifdef EA_TX_DEBUG
+       dprintf(("Tx new packet\n"));
+#endif
+
+/*
+ * Copy the datagram to the temporary buffer.
+ *
+ * Eventually we may as well just copy straight into the interface buffer
+ */
+
+       len = 0;
+       for (m = m0; m; m = m->m_next) {
+               if (m->m_len == 0)
+                       continue;
+               bcopy(mtod(m, caddr_t), sc->sc_pktbuf + len, m->m_len);
+               len += m->m_len;
+       }
+       m_freem(m0);
+
+/* If packet size is odd round up to the next 16 bit boundry */
+
+       if (len % 2)
+               ++len;
+
+       len = max(len, ETHER_MIN_LEN);
+       
+       if (len > ETHER_MAX_LEN)
+               log(LOG_WARNING, "ea: oversize packet = %d bytes\n", len);
+
+/* Ok we now have a packet len bytes long in our packet buffer */
+
+/* Transfer datagram to board. */
+
+#ifdef EA_TX_DEBUG
+       dprintf(("ea: xfr pkt length=%d...\n", len));
+
+       dprintf(("%s-->", ether_sprintf(sc->sc_pktbuf+6)));
+       dprintf(("%s\n", ether_sprintf(sc->sc_pktbuf)));
+#endif
+
+       sc->sc_config2 &= ~EA_CFG2_OUTPUT;
+       WriteShort(iobase + EA_8005_CONFIG2, sc->sc_config2);
+
+/*     dprintf(("st=%04x\n", ReadShort(iobase + EA_8005_STATUS)));*/
+
+/* Write the packet to the interface buffer, skipping the packet header */
+
+       ea_writebuf(sc, sc->sc_pktbuf, 0x0004, len);
+
+/* Follow it with a NULL packet header */
+
+       WriteShort(iobase + EA_8005_BUFWIN, 0x00);
+       WriteShort(iobase + EA_8005_BUFWIN, 0x00);
+
+/* Write the packet header */
+
+       ea_writebuf(sc, NULL, 0x0000, 0);
+
+       WriteShort(iobase + EA_8005_BUFWIN, (((len+4) & 0xff00) >> 8) | (((len+4) & 0xff) << 8));
+       WriteShort(iobase + EA_8005_BUFWIN, 0x00aa);
+
+       WriteShort(iobase + EA_8005_TX_PTR, 0x0000);
+
+/*     dprintf(("st=%04x\n", ReadShort(iobase + EA_8005_STATUS)));*/
+
+#ifdef EA_DEBUG
+       ea_dump_buffer(sc, 0);
+#endif
+
+/* Now transmit the datagram. */
+
+/*     dprintf(("st=%04x\n", ReadShort(iobase + EA_8005_STATUS)));*/
+       WriteShort(iobase + EA_8005_COMMAND, sc->sc_command | EA_CMD_TX_ON);
+#ifdef EA_TX_DEBUG
+       dprintf(("st=%04x\n", ReadShort(iobase + EA_8005_STATUS)));
+       dprintf(("tx: queued\n"));
+#endif
+}
+
+
+/*
+ * Ethernet controller interrupt.
+ */
+
+int
+eaintr(arg)
+       void *arg;
+{
+       register struct ea_softc *sc = arg;
+       u_int iobase = sc->sc_iobase;
+       int status, s;
+       u_int txstatus;
+
+       dprintf(("eaintr: "));
+
+/* Get the controller status */
+
+       status = ReadShort(iobase + EA_8005_STATUS);
+        dprintf(("st=%04x ", status)); 
+
+/* Tx interrupt ? */
+
+       if (status & EA_STATUS_TX_INT) {
+               dprintf(("txint "));
+
+/* Acknowledge the interrupt */
+
+               WriteShort(iobase + EA_8005_COMMAND, sc->sc_command
+                   | EA_CMD_TX_INTACK);
+
+               ea_readbuf(sc, (u_char *)&txstatus, 0x0000, 4);
+
+#ifdef EA_TX_DEBUG             
+               dprintf(("txstatus=%08x\n", txstatus));
+#endif
+               txstatus = (txstatus >> 24) & 0xff;
+
+/*
+ * Did it succeed ? Did we collide ?
+ *
+ * The exact proceedure here is not clear. We should get
+ * an interrupt on a sucessfull tx or on a collision.
+ * The done flag is set after successfull tx or 16 collisions
+ * We should thus get a interrupt for each of collision
+ * and the done bit should not be set. However it does appear
+ * to be set at the same time as the collision bit ...
+ *
+ * So we will count collisions and output errors and will assume
+ * that if the done bit is set the packet was transmitted.
+ * Stats may be wrong if 16 collisions occur on a packet
+ * as the done flag should be set but the packet may not have been
+ * transmitted. so the output count might not require incrementing
+ * if the 16 collisions flags is set. I don;t know abou this until
+ * it happens.
+ */
+
+               if (txstatus & EA_TXHDR_COLLISION) {
+                       sc->sc_arpcom.ac_if.if_collisions++;
+               } else if (txstatus & EA_TXHDR_ERROR_MASK) {
+                       sc->sc_arpcom.ac_if.if_oerrors++;
+               }
+
+/*             if (txstatus & EA_TXHDR_ERROR_MASK) {
+                       log(LOG_WARNING, "tx packet error =%02x\n", txstatus);
+               }*/
+
+               if (txstatus & EA_PKTHDR_DONE) {
+                       sc->sc_arpcom.ac_if.if_opackets++;
+
+                       /* Tx next packet */
+
+                       s = splimp();
+                       eatxpacket(sc);
+                       (void)splx(s);
+               }
+       }
+
+/* Rx interrupt ? */
+
+       if (status & EA_STATUS_RX_INT) {
+               dprintf(("rxint "));
+
+/* Acknowledge the interrupt */
+
+               WriteShort(iobase + EA_8005_COMMAND, sc->sc_command
+                   | EA_CMD_RX_INTACK);
+
+/* Install a watchdog timer needed atm to fixed rx lockups */
+
+               sc->sc_arpcom.ac_if.if_timer = EA_TIMEOUT;
+
+/* Processes the received packets */
+               eagetpackets(sc);
+
+/* Make sure the receiver is on */
+
+/*             if ((status & EA_STATUS_RX_ON) == 0) {
+                       WriteShort(iobase + EA_8005_COMMAND, sc->sc_command
+                           | EA_CMD_RX_ON);
+                       printf("rxintr: rx is off st=%04x\n",status);
+               }*/
+       }
+
+#ifdef EA_DEBUG
+       status = ReadShort(iobase + EA_8005_STATUS);
+        dprintf(("st=%04x\n", status));
+#endif
+       return(0);
+}
+
+void
+eagetpackets(sc)
+       struct ea_softc *sc;
+{
+       u_int iobase = sc->sc_iobase;
+       int addr;
+       int len;
+       int ctrl;
+       int ptr;
+       int pack;
+       int status;
+       u_int rxstatus;
+
+/* We start from the last rx pointer position */
+
+       addr = sc->sc_rx_ptr;
+       sc->sc_config2 &= ~EA_CFG2_OUTPUT;
+       WriteShort(iobase + EA_8005_CONFIG2, sc->sc_config2);
+
+       do {
+/* Read rx header */
+
+               ea_readbuf(sc, (u_char *)&rxstatus, addr, 4);
+               
+/* Split the packet header */
+
+               ptr = ((rxstatus & 0xff) << 8) | ((rxstatus >> 8) & 0xff);
+               ctrl = (rxstatus >> 16) & 0xff;
+               status = (rxstatus >> 24) & 0xff;
+
+#ifdef EA_RX_DEBUG
+               dprintf(("addr=%04x ptr=%04x ctrl=%02x status=%02x\n", addr, ptr, ctrl, status));
+#endif
+
+/* Zero packet ptr ? then must be null header so exit */
+
+               if (ptr == 0) break;
+
+/* Get packet length */
+       
+               len = (ptr - addr) - 4;
+
+               if (len < 0) {
+                       len += EA_RX_BUFFER_SIZE;
+               }
+
+#ifdef EA_RX_DEBUG
+               dprintf(("len=%04x\n", len));
+#endif
+
+/* Has the packet rx completed ? if not then exit */
+
+               if ((status & EA_PKTHDR_DONE) == 0)
+                       break;
+
+/* Did we have any errors ? then note error and go to next packet */
+
+               if (status & 0x0f) {
+                       ++sc->sc_arpcom.ac_if.if_ierrors;
+                       printf("rx packet error (%02x) - dropping packet\n", status & 0x0f);
+/*                     sc->sc_config2 |= EA_CFG2_OUTPUT;
+                       WriteShort(iobase + EA_8005_CONFIG2, sc->sc_config2);
+                       ea_reinit(sc);
+                       return; */
+                       addr = ptr;
+                       continue;
+               }
+
+/* Is the packet too big ? - this will probably be trapped above as a receive error */
+
+               if (len > ETHER_MAX_LEN) {
+                       ++sc->sc_arpcom.ac_if.if_ierrors;
+                       printf("rx packet size error len=%d\n", len);
+/*                     sc->sc_config2 |= EA_CFG2_OUTPUT;
+                       WriteShort(iobase + EA_8005_CONFIG2, sc->sc_config2);
+                       ea_reinit(sc);
+                       return;*/
+                       addr = ptr;
+                       continue;
+               }
+
+               ea_readbuf(sc, sc->sc_pktbuf, addr + 4, len);
+
+#ifdef EA_RX_DEBUG
+               dprintf(("%s-->", ether_sprintf(sc->sc_pktbuf+6)));
+               dprintf(("%s\n", ether_sprintf(sc->sc_pktbuf)));
+#endif
+               sc->sc_arpcom.ac_if.if_ipackets++;
+               /* Pass data up to upper levels. */
+               earead(sc, (caddr_t)sc->sc_pktbuf, len);
+
+               addr = ptr;
+               ++pack;
+       } while (len != 0);
+
+       sc->sc_config2 |= EA_CFG2_OUTPUT;
+       WriteShort(iobase + EA_8005_CONFIG2, sc->sc_config2);
+
+#ifdef EA_RX_DEBUG
+       dprintf(("new rx ptr=%04x\n", addr));
+#endif
+
+/* Store new rx pointer */
+
+       sc->sc_rx_ptr = addr;
+       WriteShort(iobase + EA_8005_RX_END, (sc->sc_rx_ptr >> 8));
+
+/* Make sure the receiver is on */
+
+       WriteShort(iobase + EA_8005_COMMAND, sc->sc_command
+           | EA_CMD_RX_ON);
+
+}
+
+
+/*
+ * Pass a packet up to the higher levels.
+ */
+
+static void
+earead(sc, buf, len)
+       struct ea_softc *sc;
+       caddr_t buf;
+       int len;
+{
+       register struct ether_header *eh;
+       struct mbuf *m;
+
+       eh = (struct ether_header *)buf;
+       len -= sizeof(struct ether_header);
+       if (len <= 0)
+               return;
+
+       /* Pull packet off interface. */
+       m = eaget(buf, len, &sc->sc_arpcom.ac_if);
+       if (m == 0)
+               return;
+
+#if NBPFILTER > 0
+       /*
+        * Check if there's a BPF listener on this interface.
+        * If so, hand off the raw packet to bpf.
+        */
+       if (sc->sc_arpcom.ac_if.if_bpf) {
+               bpf_tap(sc->sc_arpcom.ac_if.if_bpf, buf, len + sizeof(struct ether_header));
+/*             bpf_mtap(sc->sc_arpcom.ac_if.if_bpf, m);*/
+
+               /*
+                * Note that the interface cannot be in promiscuous mode if
+                * there are no BPF listeners.  And if we are in promiscuous
+                * mode, we have to check if this packet is really ours.
+                */
+               if ((sc->sc_arpcom.ac_if.if_flags & IFF_PROMISC) &&
+                   (eh->ether_dhost[0] & 1) == 0 && /* !mcast and !bcast */
+                   bcmp(eh->ether_dhost, sc->sc_arpcom.ac_enaddr,
+                           sizeof(eh->ether_dhost)) != 0) {
+                       m_freem(m);
+                       return;
+               }
+       }
+#endif
+
+       ether_input(&sc->sc_arpcom.ac_if, eh, m);
+}
+
+/*
+ * Pull read data off a interface.  Len is length of data, with local net
+ * header stripped.  We copy the data into mbufs.  When full cluster sized
+ * units are present we copy into clusters.
+ */
+
+struct mbuf *
+eaget(buf, totlen, ifp)
+        caddr_t buf;
+        int totlen;
+        struct ifnet *ifp;
+{
+        struct mbuf *top, **mp, *m;
+        int len;
+        register caddr_t cp = buf;
+        char *epkt;
+
+        buf += sizeof(struct ether_header);
+        cp = buf;
+        epkt = cp + totlen;
+
+        MGETHDR(m, M_DONTWAIT, MT_DATA);
+        if (m == 0)
+                return 0;
+        m->m_pkthdr.rcvif = ifp;
+        m->m_pkthdr.len = totlen;
+        m->m_len = MHLEN;
+        top = 0;
+        mp = &top;
+
+        while (totlen > 0) {
+                if (top) {
+                        MGET(m, M_DONTWAIT, MT_DATA);
+                        if (m == 0) {
+                                m_freem(top);
+                                return 0;
+                        }
+                        m->m_len = MLEN;
+                }
+                len = min(totlen, epkt - cp);
+                if (len >= MINCLSIZE) {
+                        MCLGET(m, M_DONTWAIT);
+                        if (m->m_flags & M_EXT)
+                                m->m_len = len = min(len, MCLBYTES);
+                        else
+                                len = m->m_len;
+                } else {
+                        /*
+                         * Place initial small packet/header at end of mbuf.
+                         */
+                        if (len < m->m_len) {
+                                if (top == 0 && len + max_linkhdr <= m->m_len)
+                                        m->m_data += max_linkhdr;
+                                m->m_len = len;
+                        } else
+                                len = m->m_len;
+                }
+                bcopy(cp, mtod(m, caddr_t), (unsigned)len);
+                cp += len;
+                *mp = m;
+                mp = &m->m_next;
+                totlen -= len;
+                if (cp == epkt)
+                        cp = buf;
+        }
+
+        return top;
+}
+
+/*
+ * Process an ioctl request. This code needs some work - it looks pretty ugly.
+ */
+static int
+ea_ioctl(ifp, cmd, data)
+       register struct ifnet *ifp;
+       u_long cmd;
+       caddr_t data;
+{
+       struct ea_softc *sc = ea_cd.cd_devs[ifp->if_unit];
+       struct ifaddr *ifa = (struct ifaddr *)data;
+/*     struct ifreq *ifr = (struct ifreq *)data;*/
+       int s, error = 0;
+
+       s = splimp();
+
+       switch (cmd) {
+
+       case SIOCSIFADDR:
+               ifp->if_flags |= IFF_UP;
+               dprintf(("if_flags=%08x\n", ifp->if_flags));
+
+               switch (ifa->ifa_addr->sa_family) {
+#ifdef INET
+               case AF_INET:
+                       arp_ifinit(&sc->sc_arpcom, ifa);
+                       dprintf(("Interface ea is coming up (AF_INET)\n"));
+                       ea_init(sc);
+                       break;
+#endif
+#ifdef NS
+               /* XXX - This code is probably wrong. */
+               case AF_NS:
+                   {
+                       register struct ns_addr *ina = &IA_SNS(ifa)->sns_addr;
+
+                       if (ns_nullhost(*ina))
+                               ina->x_host =
+                                   *(union ns_host *)(sc->sc_arpcom.ac_enaddr);
+                       else
+                               bcopy(ina->x_host.c_host,
+                                   sc->sc_arpcom.ac_enaddr,
+                                   sizeof(sc->sc_arpcom.ac_enaddr));
+                       /* Set new address. */
+                       dprintf(("Interface ea is coming up (AF_NS)\n"));
+                       ea_init(sc);
+                       break;
+                   }
+#endif
+               default:
+                       dprintf(("Interface ea is coming up (default)\n"));
+                       ea_init(sc);
+                       break;
+               }
+               break;
+
+       case SIOCSIFFLAGS:
+               dprintf(("if_flags=%08x\n", ifp->if_flags));
+               if ((ifp->if_flags & IFF_UP) == 0 &&
+                   (ifp->if_flags & IFF_RUNNING) != 0) {
+                       /*
+                        * If interface is marked down and it is running, then
+                        * stop it.
+                        */
+                       dprintf(("Interface ea is stopping\n"));
+                       ea_stop(sc);
+                       ifp->if_flags &= ~IFF_RUNNING;
+               } else if ((ifp->if_flags & IFF_UP) != 0 &&
+                          (ifp->if_flags & IFF_RUNNING) == 0) {
+                       /*
+                        * If interface is marked up and it is stopped, then
+                        * start it.
+                        */
+                       dprintf(("Interface ea is restarting(1)\n"));
+                       ea_init(sc);
+               } else {
+                       /*
+                        * Some other important flag might have changed, so
+                        * reset.
+                        */
+                       dprintf(("Interface ea is reinitialising\n"));
+                       ea_reinit(sc);
+               }
+               break;
+
+       default:
+               error = EINVAL;
+               break;
+       }
+
+       (void)splx(s);
+       return error;
+}
+
+/*
+ * Device timeout routine.
+ *
+ * Ok I am not sure exactly how the device timeout should work....
+ * Currently what will happens is that that the device timeout is only
+ * set when a packet it received. This indicates we are on an active
+ * network and thus we should expect more packets. If non arrive in
+ * in the timeout period then we reinitialise as we may have jammed.
+ * We zero the timeout at this point so that we don't end up with
+ * an endless stream of timeouts if the network goes down.
+ */
+
+static void
+ea_watchdog(unit)
+       int unit;
+{
+       struct ea_softc *sc = ea_cd.cd_devs[unit];
+
+       log(LOG_ERR, "%s: device timeout\n", sc->sc_dev.dv_xname);
+       sc->sc_arpcom.ac_if.if_oerrors++;
+       dprintf(("ea_watchdog: "));
+       dprintf(("st=%04x\n", ReadShort(sc->sc_iobase + EA_8005_STATUS)));
+
+       /* Kick the interface */
+
+       ea_reinit(sc);
+
+/*     sc->sc_arpcom.ac_if.if_timer = EA_TIMEOUT;*/
+       sc->sc_arpcom.ac_if.if_timer = 0;
+}
+
+/* End of if_ea.c */
diff --git a/sys/arch/arm32/podulebus/if_eareg.h b/sys/arch/arm32/podulebus/if_eareg.h
new file mode 100644 (file)
index 0000000..7d069da
--- /dev/null
@@ -0,0 +1,168 @@
+/* $NetBSD: if_eareg.h,v 1.2 1996/03/18 21:23:09 mark Exp $ */
+
+/*
+ * Copyright (c) 1995 Mark Brinicombe
+ * 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 Mark Brinicombe.
+ * 4. The name of the company nor the name of the author may 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 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.
+ *
+ * RiscBSD kernel project
+ *
+ * if_eareg.h
+ *
+ * Ether3 device driver
+ *
+ * Created      : 08/07/95
+ */
+
+/*
+ * SEEQ 8005 Register Definitions
+ */
+
+#define EA_8005_BASE   0x000
+
+/*
+ * SEEQ 8005 registers
+ */
+
+
+#define EA_8005_COMMAND                0x000
+#define EA_8005_STATUS         0x000
+#define EA_8005_CONFIG1                0x040
+#define EA_8005_CONFIG2                0x080
+#define EA_8005_RX_END         0x0c0
+#define EA_8005_BUFWIN         0x100
+#define EA_8005_RX_PTR         0x140
+#define EA_8005_TX_PTR         0x180
+#define EA_8005_DMA_ADDR       0x1c0
+
+/*  */
+
+#define EA_CMD_DMA_INTEN       (1 << 0)
+#define EA_CMD_RX_INTEN                (1 << 1)
+#define EA_CMD_TX_INTEN                (1 << 2)
+#define EA_CMD_BW_INTEN                (1 << 3)
+#define EA_CMD_DMA_INTACK      (1 << 4)
+#define EA_CMD_RX_INTACK       (1 << 5)
+#define EA_CMD_TX_INTACK       (1 << 6)
+#define EA_CMD_BW_INTACK       (1 << 7)
+#define EA_CMD_DMA_ON          (1 << 8)
+#define EA_CMD_RX_ON           (1 << 9)
+#define EA_CMD_TX_ON           (1 << 10)
+#define EA_CMD_DMA_OFF         (1 << 11)
+#define EA_CMD_RX_OFF          (1 << 12)
+#define EA_CMD_TX_OFF          (1 << 13)
+#define EA_CMD_FIFO_READ       (1 << 14)
+#define EA_CMD_FIFO_WRITE      (1 << 15)
+
+#define EA_STATUS_DMA_INT      (1 << 4)
+#define EA_STATUS_RX_INT       (1 << 5)
+#define EA_STATUS_TX_INT       (1 << 6)
+#define EA_STATUS_RX_ON                (1 << 9)
+#define EA_STATUS_TX_ON                (1 << 10)
+#define EA_STATUS_FIFO_FULL    (1 << 13)
+#define EA_STATUS_FIFO_EMPTY   (1 << 14)
+#define EA_STATUS_FIFO_DIR     (1 << 15)
+#define EA_STATUS_FIFO_READ    (1 << 15)
+
+#define EA_CFG1_DMA_BURST_CONT 0x00
+#define EA_CFG1_DMA_BURST_800  0x10
+#define EA_CFG1_DMA_BURST_1600 0x20
+#define EA_CFG1_DMA_BURST_3200 0x30
+#define EA_CFG1_DMA_BSIZE_1    0x00
+#define EA_CFG1_DMA_BSIZE_4    0x40
+#define EA_CFG1_DMA_BSIZE_8    0x80
+#define EA_CFG1_DMA_BSIZE_16   0xc0
+
+#define EA_CFG1_STATION_ADDR0  (1 << 8)
+#define EA_CFG1_STATION_ADDR1  (1 << 9)
+#define EA_CFG1_STATION_ADDR2  (1 << 10)
+#define EA_CFG1_STATION_ADDR3  (1 << 11)
+#define EA_CFG1_STATION_ADDR4  (1 << 12)
+#define EA_CFG1_STATION_ADDR5  (1 << 13)
+#define EA_CFG1_SPECIFIC       ((0 << 15) | (0 << 14))
+#define EA_CFG1_BROADCAST      ((0 << 15) | (1 << 14))
+#define EA_CFG1_MULTICAST      ((1 << 15) | (0 << 14))
+#define EA_CFG1_PROMISCUOUS    ((1 << 15) | (1 << 14))
+
+#define EA_CFG2_BYTESWAP       (1 << 0)
+#define EA_CFG2_CRC_ERR_ENABLE (1 << 3)
+#define EA_CFG2_DRIB_ERR_ENABLE (1 << 4)
+#define EA_CFG2_PASS_SHORT     (1 << 5)
+#define EA_CFG2_SLOT_SELECT    (1 << 6)
+#define EA_CFG2_PREAM_SELECT   (1 << 7)
+#define EA_CFG2_ADDR_LENGTH    (1 << 8)
+#define EA_CFG2_RX_CRC         (1 << 9)
+#define EA_CFG2_NO_TX_CRC      (1 << 10)
+#define EA_CFG2_LOOPBACK       (1 << 11)
+#define EA_CFG2_OUTPUT         (1 << 12)
+#define EA_CFG2_RESET          (1 << 15)
+
+#define EA_BUFCODE_STATION_ADDR0       0x00
+#define EA_BUFCODE_STATION_ADDR1       0x01
+#define EA_BUFCODE_STATION_ADDR2       0x02
+#define EA_BUFCODE_STATION_ADDR3       0x03
+#define EA_BUFCODE_STATION_ADDR4       0x04
+#define EA_BUFCODE_STATION_ADDR5       0x05
+#define EA_BUFCODE_ADDRESS_PROM                0x06
+#define EA_BUFCODE_TX_EAP              0x07
+#define EA_BUFCODE_LOCAL_MEM           0x08
+#define EA_BUFCODE_INT_VECTOR          0x09
+/*#define EA_BUFCODE_MULTICAST         0x0f*/
+
+#define EA_PKTHDR_TX           (1 << 7)
+#define EA_PKTHDR_RX           (0 << 7)
+#define EA_PKTHDR_CHAIN_CONT   (1 << 6)
+#define EA_PKTHDR_DATA_FOLLOWS (1 << 5)
+
+#define EA_PKTHDR_DONE         (1 << 7)
+
+#define EA_TXHDR_BABBLE                (1 << 0)
+#define EA_TXHDR_COLLISION     (1 << 1)
+#define EA_TXHDR_COLLISION16   (1 << 2)
+
+#define EA_TXHDR_BABBLE_INT    (1 << 0)
+#define EA_TXHDR_COLLISION_INT (1 << 1)
+#define EA_TXHDR_COLLISION16_INT       (1 << 2)
+#define EA_TXHDR_XMIT_SUCCESS_INT      (1 << 3)
+#define EA_TXHDR_ERROR_MASK    (0x07)
+
+#define EA_RXHDR_OVERSIZE      (1 << 0)
+#define EA_RXHDR_CRC_ERROR     (1 << 1)
+#define EA_RXHDR_DRIBBLE_ERROR (1 << 2)
+#define EA_RXHDR_SHORT_FRAME   (1 << 3)
+
+#define EA_BUFFER_SIZE         0x10000
+#define EA_TX_BUFFER_SIZE      0x4000
+#define EA_RX_BUFFER_SIZE      0xC000
+
+/* Packet buffer size */
+
+#define        EA_BUFSIZ       2048
+
+/* End of if_eareg.h */
diff --git a/sys/arch/arm32/podulebus/if_eb.c b/sys/arch/arm32/podulebus/if_eb.c
new file mode 100644 (file)
index 0000000..a433d38
--- /dev/null
@@ -0,0 +1,1575 @@
+/* $NetBSD: if_eb.c,v 1.4 1996/03/27 21:49:31 mark Exp $ */
+
+/*
+ * Copyright (c) 1995 Mark Brinicombe
+ * 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 Mark Brinicombe.
+ * 4. The name of the company nor the name of the author may 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 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.
+ *
+ * RiscBSD kernel project
+ *
+ * if_eb.c
+ *
+ * EtherB device driver
+ *
+ * Created      : 08/07/95
+ */
+
+/*
+ * SEEQ 80C04 device driver
+ */
+
+/*
+ * Bugs/possible improvements:
+ *     - Does not currently support DMA
+ *     - Does not currently support multicasts
+ *     - Does not transmit multiple packets in one go
+ */
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/errno.h>
+#include <sys/ioctl.h>
+#include <sys/mbuf.h>
+#include <sys/socket.h>
+#include <sys/syslog.h>
+#include <sys/device.h>
+
+#include <net/if.h>
+#include <net/if_dl.h>
+#include <net/if_types.h>
+
+#ifdef INET
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/in_var.h>
+#include <netinet/ip.h>
+#include <netinet/if_ether.h>
+#endif
+
+#ifdef NS
+#include <netns/ns.h>
+#include <netns/ns_if.h>
+#endif
+
+#include "bpfilter.h"
+#if NBPFILTER > 0
+#include <net/bpf.h>
+#include <net/bpfdesc.h>
+#endif
+
+#include <machine/cpu.h>
+#include <machine/katelib.h>
+#include <machine/io.h>
+#include <machine/irqhandler.h>
+#include <machine/bootconfig.h>
+
+#include <arm32/podulebus/if_ebreg.h>
+#include <arm32/podulebus/podulebus.h>
+
+#define ETHER_MIN_LEN  64
+#define ETHER_MAX_LEN  1514
+#define ETHER_ADDR_LEN 6
+
+#ifndef EB_TIMEOUT
+#define EB_TIMEOUT     60
+#endif
+
+/*#define EB_TX_DEBUG*/
+/*#define EB_RX_DEBUG*/
+/*#define EB_DEBUG*/
+/*#define EB_PACKET_DEBUG*/
+
+/* for debugging convenience */
+#ifdef EB_DEBUG
+#define dprintf(x) printf x
+#else
+#define dprintf(x)
+#endif
+
+#define MY_MANUFACTURER 0x53
+#define MY_PODULE       0xe4
+
+/*
+ * per-line info and status
+ */
+
+struct eb_softc {
+       struct device sc_dev;
+       irqhandler_t sc_ih;
+       int sc_irq;                     /* IRQ number */
+       podule_t *sc_podule;            /* Our podule */
+       int sc_podule_number;           /* Our podule number */
+       u_int sc_iobase;                /* base I/O addr */
+       struct arpcom sc_arpcom;        /* ethernet common */
+       char sc_pktbuf[EB_BUFSIZ];      /* frame buffer */
+       int sc_config1;                 /* Current config1 bits */
+       int sc_config2;                 /* Current config2 bits */
+       int sc_command;                 /* Current command bits */
+       int sc_irqclaimed;              /* Whether we have an IRQ claimed */
+       int sc_rx_ptr;                  /* Receive buffer pointer */
+       int sc_tx_ptr;                  /* Transmit buffer pointer */
+};
+
+/*
+ * prototypes
+ */
+
+static int ebintr __P((void *));
+static int eb_init __P((struct eb_softc *));
+static int eb_ioctl __P((struct ifnet *, u_long, caddr_t));
+static void eb_start __P((struct ifnet *));
+static void eb_watchdog __P((int));
+static void eb_reinit __P((struct eb_softc *));
+static void eb_chipreset __P((struct eb_softc *));
+static void eb_ramtest __P((struct eb_softc *));
+static int eb_stoptx __P((struct eb_softc *));
+static int eb_stoprx __P((struct eb_softc *));
+static void eb_stop __P((struct eb_softc *));
+static void eb_writebuf __P((struct eb_softc *, u_char *, int, int));
+static void eb_readbuf __P((struct eb_softc *, u_char *, int, int));
+static void ebread __P((struct eb_softc *, caddr_t, int));
+static struct mbuf *ebget __P((caddr_t, int, struct ifnet *));
+static void eb_hardreset __P((struct eb_softc *));
+static void ebgetpackets __P((struct eb_softc *));
+static void ebtxpacket __P((struct eb_softc *));
+
+int ebprobe __P((struct device *, void *, void *));
+void ebattach __P((struct device *, struct device *, void *));
+
+/* driver structure for autoconf */
+
+struct cfattach eb_ca = {
+       sizeof(struct eb_softc), ebprobe, ebattach
+};
+
+struct cfdriver eb_cd = {
+       NULL, "eb", DV_IFNET
+};
+
+#if 0
+
+/*
+ * Dump the chip registers
+ */
+
+void
+ebdump(iobase)
+       u_int iobase;
+{
+       dprintf(("%08x: %04x %04x %04x %04x %04x %04x %04x %04x\n", iobase,
+           ReadShort(iobase + 0x00), ReadShort(iobase + 0x40),
+           ReadShort(iobase + 0x80), ReadShort(iobase + 0xc0),
+           ReadShort(iobase + 0x100), ReadShort(iobase + 0x140),
+           ReadShort(iobase + 0x180), ReadShort(iobase + 0x1c0)));
+}
+#endif
+
+/*
+ * Dump the interface buffer
+ */
+
+void
+eb_dump_buffer(sc, offset)
+       struct eb_softc *sc;
+       int offset;
+{
+#ifdef EB_PACKET_DEBUG
+       u_int iobase = sc->sc_iobase;
+       int addr;
+       int loop;
+       int size;
+       int ctrl;
+       int ptr;
+       
+       addr = offset;
+
+       do {
+               WriteShort(sc->sc_iobase + EB_8004_COMMAND, sc->sc_command | EB_CMD_FIFO_READ);
+               WriteShort(iobase + EB_8004_CONFIG1, sc->sc_config1 | EB_BUFCODE_LOCAL_MEM);
+               WriteShort(iobase + EB_8004_DMA_ADDR, addr);
+
+               ptr = ReadShort(iobase + EB_8004_BUFWIN);
+               ctrl = ReadShort(iobase + EB_8004_BUFWIN);
+               ptr = ((ptr & 0xff) << 8) | ((ptr >> 8) & 0xff);
+
+               if (ptr == 0) break;
+               size = ptr - addr;
+
+               printf("addr=%04x size=%04x ", addr, size);
+               printf("cmd=%02x st=%02x\n", ctrl & 0xff, ctrl >> 8);
+
+               for (loop = 0; loop < size - 4; loop += 2)
+                       printf("%04x ", ReadShort(iobase + EB_8004_BUFWIN));
+               printf("\n");
+               addr = ptr;
+       } while (size != 0);
+#endif
+}
+
+/*
+ * Probe routine.
+ */
+
+/*
+ * int ebprobe(struct device *parent, void *match, void *aux)
+ *
+ * Probe for the ether3 podule.
+ */
+
+int
+ebprobe(parent, match, aux)
+       struct device *parent;
+       void *match;
+       void *aux;
+{
+       struct podule_attach_args *pa = (void *)aux;
+       int podule;
+       u_int iobase;
+       
+/*     dprintf(("Probing for SEEQ 8004... \n"));*/
+
+/* Look for a network slot interface */
+
+       podule = findpodule(MY_MANUFACTURER, MY_PODULE, pa->pa_podule_number);
+
+/* Fail if we did not find it */
+
+       if (podule == -1)
+               return(0);
+
+       iobase = podules[podule].mod_base + EB_8004_BASE;
+
+/* Reset it  - Why here ? */
+
+       WriteShort(iobase + EB_8004_CONFIG2, EB_CFG2_RESET);
+       delay(100);
+
+/* We found it */
+
+       pa->pa_podule_number = podule;
+       pa->pa_podule = &podules[podule];
+
+       return(1);
+}
+
+
+/*
+ * void ebattach(struct device *parent, struct device *dev, void *aux)
+ *
+ * Attach podule.
+ */
+
+void
+ebattach(parent, self, aux)
+       struct device *parent;
+       struct device *self;
+       void *aux;
+{
+       struct eb_softc *sc = (void *)self;
+       struct podule_attach_args *pa = (void *)aux;
+       struct ifnet *ifp = &sc->sc_arpcom.ac_if;
+       int loop;
+       int sum;
+       int id;
+
+/*     dprintf(("Attaching %s...\n", sc->sc_dev.dv_xname));*/
+
+/* Note the podule number and validate */
+
+       sc->sc_podule_number = pa->pa_podule_number;
+       if (sc->sc_podule_number == -1)
+               panic("Podule has disappeared !");
+
+       sc->sc_podule = &podules[sc->sc_podule_number];
+       podules[sc->sc_podule_number].attached = 1;
+
+/* Set the address of the controller for easy access */
+       
+       sc->sc_iobase = sc->sc_podule->mod_base + EB_8004_BASE;
+
+       sc->sc_irqclaimed = 0;
+
+/* Set up the interrupt structure */
+
+       sc->sc_ih.ih_func = ebintr;
+       sc->sc_ih.ih_arg = sc;
+       sc->sc_ih.ih_level = IPL_NET;
+       sc->sc_ih.ih_name = "net: eb";
+
+/* Claim either a network slot interrupt or a podule interrupt */
+
+       if (sc->sc_podule_number >= MAX_PODULES)
+               sc->sc_irq = IRQ_NETSLOT;
+       else
+               sc->sc_irq = IRQ_PODULE /*+ sc->sc_podule_number*/;
+
+       /* Stop the board. */
+
+       eb_chipreset(sc);
+       eb_stoptx(sc);
+       eb_stoprx(sc);
+
+       /* Initialise ifnet structure. */
+
+       ifp->if_unit = sc->sc_dev.dv_unit;
+       ifp->if_name = eb_cd.cd_name;
+       ifp->if_start = eb_start;
+       ifp->if_ioctl = eb_ioctl;
+       ifp->if_watchdog = eb_watchdog;
+       ifp->if_flags = IFF_BROADCAST | IFF_NOTRAILERS;
+
+       /* Now we can attach the interface. */
+
+/*     dprintf(("Attaching interface...\n"));*/
+       if_attach(ifp);
+       ether_ifattach(ifp);
+
+/* Read the station address - the receiver must be off */
+
+       WriteShort(sc->sc_iobase + EB_8004_CONFIG1, EB_BUFCODE_STATION_ADDR);
+       
+       for (sum = 0, loop = 0; loop < ETHER_ADDR_LEN; ++loop) {
+               sc->sc_arpcom.ac_enaddr[loop] =
+                   ReadByte(sc->sc_iobase + EB_8004_BUFWIN);
+               sum += sc->sc_arpcom.ac_enaddr[loop];
+       }
+
+/*
+ * Hard code the ether address if we don't have one.
+ * Build the address from the machine id.
+ */
+
+       if (sum == 0) {
+               sc->sc_arpcom.ac_enaddr[0] = 0x00;
+               sc->sc_arpcom.ac_enaddr[1] = 0x00;
+               sc->sc_arpcom.ac_enaddr[2] = bootconfig.machine_id[3];
+               sc->sc_arpcom.ac_enaddr[3] = bootconfig.machine_id[2];
+               sc->sc_arpcom.ac_enaddr[4] = bootconfig.machine_id[1];
+               sc->sc_arpcom.ac_enaddr[5] = bootconfig.machine_id[0];
+       }
+
+       /* Get the product ID */
+       
+       WriteShort(sc->sc_iobase + EB_8004_CONFIG1, EB_BUFCODE_PRODUCTID);
+       id = ReadByte(sc->sc_iobase + EB_8004_BUFWIN);
+
+       /* Print out some information for the user. */
+
+       if ((id & 0xf0) == 0xa0)
+               printf(" SEEQ80C04 rev %x address %s", id & 0x0f, ether_sprintf(sc->sc_arpcom.ac_enaddr));
+       else
+               printf(" SEEQ???? rev %02x address %s", id, ether_sprintf(sc->sc_arpcom.ac_enaddr));
+
+       /* Finally, attach to bpf filter if it is present. */
+
+#if NBPFILTER > 0
+/*     dprintf(("Attaching to BPF...\n"));*/
+       bpfattach(&ifp->if_bpf, ifp, DLT_EN10MB, sizeof(struct ether_header));
+#endif
+
+       /* Should test the RAM */
+
+       eb_ramtest(sc);
+       
+/*     dprintf(("ebattach() finished.\n"));*/
+}
+
+
+/*
+ * Test the RAM on the ethernet card. This does not work yet
+ */
+
+void
+eb_ramtest(sc)
+       struct eb_softc *sc;
+{
+       register u_int iobase = sc->sc_iobase;
+       register int loop;
+       register u_int sum = 0;
+
+/*     dprintf(("eb_ramtest()\n"));*/
+
+       /*
+        * Test the buffer memory on the board.
+        * Write simple pattens to it and read them back.
+        */
+
+       /* Set up the whole buffer RAM for writing */
+
+       WriteShort(iobase + EB_8004_CONFIG1, EB_BUFCODE_TX_EAP);
+       WriteShort(iobase + EB_8004_BUFWIN, ((EB_BUFFER_SIZE >> 8) - 1));
+       WriteShort(iobase + EB_8004_TX_PTR, 0x0000);
+       WriteShort(iobase + EB_8004_RX_PTR, EB_BUFFER_SIZE - 2);
+
+       /* Set the write start address and write a pattern */
+
+       eb_writebuf(sc, NULL, 0x0000, 0);
+
+       for (loop = 0; loop < EB_BUFFER_SIZE; loop += 2)
+               WriteShort(iobase + EB_8004_BUFWIN, loop);
+
+       /* Set the read start address and verify the pattern */
+       
+       eb_readbuf(sc, NULL, 0x0000, 0);
+
+       for (loop = 0; loop < EB_BUFFER_SIZE; loop += 2)
+               if (ReadShort(iobase + EB_8004_BUFWIN) != loop)
+                       ++sum;
+
+       if (sum != 0)
+               dprintf(("sum=%d\n", sum));
+
+       /* Set the write start address and write a pattern */
+
+       eb_writebuf(sc, NULL, 0x0000, 0);
+
+       for (loop = 0; loop < EB_BUFFER_SIZE; loop += 2)
+               WriteShort(iobase + EB_8004_BUFWIN, loop ^ (EB_BUFFER_SIZE - 1));
+
+       /* Set the read start address and verify the pattern */
+
+       eb_readbuf(sc, NULL, 0x0000, 0);
+
+       for (loop = 0; loop < EB_BUFFER_SIZE; loop += 2)
+               if (ReadShort(iobase + EB_8004_BUFWIN) != (loop ^ (EB_BUFFER_SIZE - 1)))
+                       ++sum;
+
+       if (sum != 0)
+               dprintf(("sum=%d\n", sum));
+
+       /* Set the write start address and write a pattern */
+
+       eb_writebuf(sc, NULL, 0x0000, 0);
+
+       for (loop = 0; loop < EB_BUFFER_SIZE; loop += 2)
+               WriteShort(iobase + EB_8004_BUFWIN, 0xaa55);
+
+       /* Set the read start address and verify the pattern */
+
+       eb_readbuf(sc, NULL, 0x0000, 0);
+
+       for (loop = 0; loop < EB_BUFFER_SIZE; loop += 2)
+               if (ReadShort(iobase + EB_8004_BUFWIN) != 0xaa55)
+                       ++sum;
+
+       if (sum != 0)
+               dprintf(("sum=%d\n", sum));
+
+       /* Set the write start address and write a pattern */
+
+       eb_writebuf(sc, NULL, 0x0000, 0);
+
+       for (loop = 0; loop < EB_BUFFER_SIZE; loop += 2)
+               WriteShort(iobase + EB_8004_BUFWIN, 0x55aa);
+
+       /* Set the read start address and verify the pattern */
+
+       eb_readbuf(sc, NULL, 0x0000, 0);
+
+       for (loop = 0; loop < EB_BUFFER_SIZE; loop += 2)
+               if (ReadShort(iobase + EB_8004_BUFWIN) != 0x55aa)
+                       ++sum;
+
+       if (sum != 0)
+               dprintf(("sum=%d\n", sum));
+
+       /* Report */
+
+       if (sum == 0)
+               printf(" %dK buffer RAM\n", EB_BUFFER_SIZE / 1024);
+       else
+               printf(" buffer RAM failed self test, %d faults\n", sum);
+}
+
+
+/* Claim an irq for the board */
+
+void
+eb_claimirq(sc)
+       struct eb_softc *sc;
+{
+/* Have we claimed one already ? */
+
+       if (sc->sc_irqclaimed) return;
+
+/* Claim it */
+
+       dprintf(("eb_claimirq(%d)\n", sc->sc_irq));
+       if (irq_claim(sc->sc_irq, &sc->sc_ih))
+               panic("Cannot install IRQ handler for IRQ %d\n", sc->sc_irq);
+
+       sc->sc_irqclaimed = 1;
+}
+
+
+/* Release an irq */
+
+void
+eb_releaseirq(sc)
+       struct eb_softc *sc;
+{
+/* Have we claimed one ? */
+
+       if (!sc->sc_irqclaimed) return;
+
+       dprintf(("eb_releaseirq(%d)\n", sc->sc_irq));
+       if (irq_release(sc->sc_irq, &sc->sc_ih))
+               panic("Cannot release IRQ handler for IRQ %d\n", sc->sc_irq);
+
+       sc->sc_irqclaimed = 0;
+}
+
+
+/*
+ * Stop and reinitialise the interface.
+ */
+
+static void
+eb_reinit(sc)
+       struct eb_softc *sc;
+{
+       int s;
+
+       dprintf(("eb_reinit()\n"));
+
+/* Stop and reinitialise the interface */
+
+       s = splimp();
+       eb_stop(sc);
+       eb_init(sc);
+       (void)splx(s);
+}
+
+
+/*
+ * Stop the tx interface.
+ *
+ * Returns 0 if the tx was already stopped or 1 if it was active
+ */
+
+static int
+eb_stoptx(sc)
+       struct eb_softc *sc;
+{
+       u_int iobase = sc->sc_iobase;
+       int timeout;
+       int status;
+
+       dprintf(("eb_stoptx()\n"));
+
+       status = ReadShort(iobase + EB_8004_STATUS);
+       if (!(status & EB_STATUS_TX_ON))
+               return(0);
+
+/* Stop any tx and wait for confirmation */
+
+       WriteShort(iobase + EB_8004_COMMAND, sc->sc_command | EB_CMD_TX_OFF);
+
+       timeout = 20000;
+       do {
+               status = ReadShort(iobase + EB_8004_STATUS);
+       } while ((status & EB_STATUS_TX_ON) && --timeout > 0);
+       if (timeout == 0)
+               dprintf(("eb_stoptx: timeout waiting for tx termination\n"));
+
+/* Clear any pending tx interrupt */
+
+       WriteShort(iobase + EB_8004_COMMAND, sc->sc_command | EB_CMD_TX_INTACK);
+       return(1);
+}
+
+
+/*
+ * Stop the rx interface.
+ *
+ * Returns 0 if the tx was already stopped or 1 if it was active
+ */
+
+static int
+eb_stoprx(sc)
+       struct eb_softc *sc;
+{
+       u_int iobase = sc->sc_iobase;
+       int timeout;
+       int status;
+
+       dprintf(("eb_stoprx()\n"));
+
+       status = ReadShort(iobase + EB_8004_STATUS);
+       if (!(status & EB_STATUS_RX_ON))
+               return(0);
+
+/* Stop any rx and wait for confirmation */
+
+       WriteShort(iobase + EB_8004_COMMAND, sc->sc_command | EB_CMD_RX_OFF);
+
+       timeout = 20000;
+       do {
+               status = ReadShort(iobase + EB_8004_STATUS);
+       } while ((status & EB_STATUS_RX_ON) && --timeout > 0);
+       if (timeout == 0)
+               dprintf(("eb_stoprx: timeout waiting for rx termination\n"));
+
+/* Clear any pending rx interrupt */
+
+       WriteShort(iobase + EB_8004_COMMAND, sc->sc_command | EB_CMD_RX_INTACK);
+       return(1);
+}
+
+
+/*
+ * Stop interface.
+ * Stop all IO and shut the interface down
+ */
+
+static void
+eb_stop(sc)
+       struct eb_softc *sc;
+{
+       u_int iobase = sc->sc_iobase;
+
+       dprintf(("eb_stop()\n"));
+
+/* Stop all IO */
+
+       eb_stoptx(sc);
+       eb_stoprx(sc);
+
+       /* Disable rx and tx interrupts */
+
+       sc->sc_command &= (EB_CMD_RX_INTEN | EB_CMD_TX_INTEN);
+
+       /* Clear any pending interrupts */
+
+       WriteShort(iobase + EB_8004_COMMAND, sc->sc_command
+           | EB_CMD_RX_INTACK | EB_CMD_TX_INTACK | EB_CMD_TEST_INTACK
+           | EB_CMD_BW_INTACK);
+       dprintf(("st=%08x", ReadShort(iobase + EB_8004_STATUS)));
+
+       /* Release the irq */
+
+       eb_releaseirq(sc);
+
+       /* Put the chip to sleep */
+
+       WriteShort(iobase + EB_8004_CONFIG1, EB_BUFCODE_CONFIG3);
+       WriteShort(iobase + EB_8004_BUFWIN, EB_CFG3_SLEEP);
+
+       /* Cancel any watchdog timer */
+       
+       sc->sc_arpcom.ac_if.if_timer = 0;
+}
+
+
+/*
+ * Reset the chip
+ * Following this the software registers are reset
+ */
+
+static void
+eb_chipreset(sc)
+       struct eb_softc *sc;
+{
+       u_int iobase = sc->sc_iobase;
+
+       dprintf(("eb_chipreset()\n"));
+
+/* Reset the controller. Min of 4us delay here */
+
+       WriteShort(iobase + EB_8004_CONFIG2, EB_CFG2_RESET);
+       delay(100);
+
+       sc->sc_command = 0;
+       sc->sc_config1 = 0;
+       sc->sc_config2 = 0;
+}
+
+
+/*
+ * Do a hardware reset of the board, and upload the ethernet address again in
+ * case the board forgets.
+ */
+
+static void
+eb_hardreset(sc)
+       struct eb_softc *sc;
+{
+       u_int iobase = sc->sc_iobase;
+       int loop;
+
+       dprintf(("eb_hardreset()\n"));
+
+/* Stop any activity */
+
+       eb_stoptx(sc);
+       eb_stoprx(sc);
+
+       eb_chipreset(sc);
+
+/* Set up defaults for the registers */
+
+       sc->sc_config2 = 0;
+       WriteShort(iobase + EB_8004_CONFIG2, sc->sc_config2);
+       sc->sc_command = 0x00;
+       sc->sc_config1 = 0;
+       WriteShort(iobase + EB_8004_CONFIG1, sc->sc_config1);
+       WriteShort(iobase + EB_8004_COMMAND, sc->sc_command);
+
+       WriteShort(iobase + EB_8004_CONFIG1, EB_BUFCODE_TX_EAP);
+       WriteShort(iobase + EB_8004_BUFWIN, ((EB_TX_BUFFER_SIZE >> 8) - 1));
+
+/* Write the station address - the receiver must be off */
+
+       WriteShort(sc->sc_iobase + EB_8004_CONFIG1,
+           sc->sc_config1 | EB_BUFCODE_STATION_ADDR);
+       for (loop = 0; loop < ETHER_ADDR_LEN; ++loop) {
+               WriteByte(sc->sc_iobase + EB_8004_BUFWIN, sc->sc_arpcom.ac_enaddr[loop]);
+       }
+}
+
+
+/*
+ * write to the buffer memory on the interface
+ *
+ * If addr is within range for the interface buffer then the buffer
+ * address is set to addr.
+ * If len != 0 then data is copied from the address starting at buf
+ * to the interface buffer.
+ */
+
+static void
+eb_writebuf(sc, buf, addr, len)
+       struct eb_softc *sc;
+       u_char *buf;
+       int addr;
+       int len;
+{
+       u_int iobase = sc->sc_iobase;
+       int loop;
+       int timeout;
+
+       dprintf(("writebuf: st=%04x\n", ReadShort(iobase + EB_8004_STATUS)));
+
+/* If we have a valid buffer address set the buffer pointer and direction */
+
+       if (addr >= 0 && addr < EB_BUFFER_SIZE) {
+               WriteShort(iobase + EB_8004_CONFIG1, sc->sc_config1 | EB_BUFCODE_LOCAL_MEM);
+               WriteShort(iobase + EB_8004_COMMAND, sc->sc_command | EB_CMD_FIFO_WRITE);
+
+               /* Should wait here of FIFO empty flag */
+
+               timeout = 20000;
+               while ((ReadShort(iobase + EB_8004_STATUS) & EB_STATUS_FIFO_EMPTY) == 0 && --timeout > 0);
+
+
+               WriteShort(iobase + EB_8004_DMA_ADDR, addr);
+       }
+
+       for (loop = 0; loop < len; loop += 2)
+               WriteShort(iobase + EB_8004_BUFWIN, buf[loop] | buf[loop + 1] << 8);
+
+
+/*     if (len > 0)
+               outsw(iobase + EB_8004_BUFWIN, buf, len / 2);*/
+}
+
+
+/*
+ * read from the buffer memory on the interface
+ *
+ * If addr is within range for the interface buffer then the buffer
+ * address is set to addr.
+ * If len != 0 then data is copied from the interface buffer to the
+ * address starting at buf.
+ */
+
+static void
+eb_readbuf(sc, buf, addr, len)
+       struct eb_softc *sc;
+       u_char *buf;
+       int addr;
+       int len;
+{
+       u_int iobase = sc->sc_iobase;
+       int loop;
+       int word;
+       int timeout;
+
+       dprintf(("readbuf: st=%04x addr=%04x len=%d\n", ReadShort(iobase + EB_8004_STATUS), addr, len));
+
+/* If we have a valid buffer address set the buffer pointer and direction */
+
+       if (addr >= 0 && addr < EB_BUFFER_SIZE) {
+               if ((ReadShort(iobase + EB_8004_STATUS) & EB_STATUS_FIFO_DIR) == 0) {
+                       /* Should wait here of FIFO empty flag */
+
+                       timeout = 20000;
+                       while ((ReadShort(iobase + EB_8004_STATUS) & EB_STATUS_FIFO_EMPTY) == 0 && --timeout > 0);
+               }
+               WriteShort(iobase + EB_8004_CONFIG1, sc->sc_config1 | EB_BUFCODE_LOCAL_MEM);
+               WriteShort(iobase + EB_8004_COMMAND, sc->sc_command | EB_CMD_FIFO_WRITE);
+
+               /* Should wait here of FIFO empty flag */
+
+               timeout = 20000;
+               while ((ReadShort(iobase + EB_8004_STATUS) & EB_STATUS_FIFO_EMPTY) == 0 && --timeout > 0);
+
+               WriteShort(iobase + EB_8004_DMA_ADDR, addr);
+               WriteShort(iobase + EB_8004_COMMAND, sc->sc_command | EB_CMD_FIFO_READ);
+
+               /* Should wait here of FIFO full flag */
+
+               timeout = 20000;
+               while ((ReadShort(iobase + EB_8004_STATUS) & EB_STATUS_FIFO_FULL) == 0 && --timeout > 0);
+
+
+       }
+
+       for (loop = 0; loop < len; loop += 2) {
+               word = ReadShort(iobase + EB_8004_BUFWIN);
+               buf[loop] = word & 0xff;
+               buf[loop + 1] = word >> 8;
+       }
+
+/*     if (len > 0)
+               insw(iobase + EB_8004_BUFWIN, buf, len / 2);*/
+}
+
+
+/*
+ * Initialize interface.
+ *
+ * This should leave the interface in a state for packet reception and transmission
+ */
+
+static int
+eb_init(sc)
+       struct eb_softc *sc;
+{
+       struct ifnet *ifp = &sc->sc_arpcom.ac_if;
+       u_int iobase = sc->sc_iobase;
+       int s;
+
+       dprintf(("eb_init()\n"));
+
+       s = splimp();
+
+/* Grab an irq */
+
+       eb_claimirq(sc);
+
+       /* First, reset the board. */
+
+       eb_hardreset(sc);
+
+/* Configure rx. */
+
+       dprintf(("Configuring rx...\n"));
+       if (ifp->if_flags & IFF_PROMISC)
+               sc->sc_config1 = EB_CFG1_PROMISCUOUS;
+       else
+               sc->sc_config1 = EB_CFG1_BROADCAST;
+
+       sc->sc_config1 |= 0;
+       WriteShort(iobase + EB_8004_CONFIG1, sc->sc_config1);
+
+/* Configure TX. */
+
+       dprintf(("Configuring tx...\n"));
+
+       WriteShort(iobase + EB_8004_CONFIG1, sc->sc_config1 | EB_BUFCODE_TX_EAP);
+       WriteShort(iobase + EB_8004_BUFWIN, ((EB_TX_BUFFER_SIZE >> 8) - 1));
+       WriteShort(iobase + EB_8004_TX_PTR, 0x0000);
+
+       sc->sc_config2 |= (EB_CFG2_OUTPUT | EB_CFG2_RX_TX_DISABLE);
+       WriteShort(iobase + EB_8004_CONFIG2, sc->sc_config2);
+
+/* Place a NULL header at the beginning of the transmit area */
+
+       eb_writebuf(sc, NULL, 0x0000, 0);
+               
+       WriteShort(iobase + EB_8004_BUFWIN, 0x0000);
+       WriteShort(iobase + EB_8004_BUFWIN, 0x0000);
+
+       sc->sc_command |= EB_CMD_TX_INTEN;
+       WriteShort(iobase + EB_8004_COMMAND, sc->sc_command);
+
+/* Setup the Rx pointers */
+
+       sc->sc_rx_ptr = EB_TX_BUFFER_SIZE;
+
+       WriteShort(iobase + EB_8004_RX_PTR, sc->sc_rx_ptr);
+       WriteShort(iobase + EB_8004_RX_END, (sc->sc_rx_ptr >> 8));
+
+/* Place a NULL header at the beginning of the receive area */
+
+       eb_writebuf(sc, NULL, sc->sc_rx_ptr, 0);
+               
+       WriteShort(iobase + EB_8004_BUFWIN, 0x0000);
+       WriteShort(iobase + EB_8004_BUFWIN, 0x0000);
+
+/* Turn on Rx */
+
+       sc->sc_command |= EB_CMD_RX_INTEN;
+       WriteShort(iobase + EB_8004_COMMAND, sc->sc_command | EB_CMD_RX_ON);
+
+       /* Set flags appropriately. */
+       ifp->if_flags |= IFF_RUNNING;
+       ifp->if_flags &= ~IFF_OACTIVE;
+
+       dprintf(("init: st=%04x\n", ReadShort(iobase + EB_8004_STATUS)));
+
+       /* And start output. */
+       eb_start(ifp);
+
+       (void)splx(s);
+       return(0);
+}
+
+
+/*
+ * Start output on interface. Get datagrams from the queue and output them,
+ * giving the receiver a chance between datagrams. Call only from splimp or
+ * interrupt level!
+ */
+
+static void
+eb_start(ifp)
+       struct ifnet *ifp;
+{
+       struct eb_softc *sc = eb_cd.cd_devs[ifp->if_unit];
+       int s;
+
+       s = splimp();
+#ifdef EB_TX_DEBUG
+       dprintf(("eb_start()...\n"));
+#endif
+
+       /* Don't do anything if output is active. */
+
+       if (sc->sc_arpcom.ac_if.if_flags & IFF_OACTIVE)
+               return;
+
+       /* Mark interface as output active */
+       
+       sc->sc_arpcom.ac_if.if_flags |= IFF_OACTIVE;
+
+       /* tx packets */
+
+       ebtxpacket(sc);
+       (void)splx(s);
+}
+
+
+/*
+ * Transfer a packet to the interface buffer and start transmission
+ *
+ * Called at splimp()
+ */
+void
+ebtxpacket(sc)
+       struct eb_softc *sc;
+{
+       u_int iobase = sc->sc_iobase;
+       struct mbuf *m, *m0;
+       int len;
+
+/* Dequeue the next datagram. */
+
+       IF_DEQUEUE(&sc->sc_arpcom.ac_if.if_snd, m0);
+
+/* If there's nothing to send, return. */
+
+       if (!m0) {
+               sc->sc_arpcom.ac_if.if_flags &= ~IFF_OACTIVE;
+               sc->sc_config2 |= EB_CFG2_OUTPUT;
+               WriteShort(iobase + EB_8004_CONFIG2, sc->sc_config2);
+#ifdef EB_TX_DEBUG
+               dprintf(("tx finished\n"));
+#endif
+               return;
+       }
+
+       /* Give the packet to the bpf, if any. */
+#if NBPFILTER > 0
+       if (sc->sc_arpcom.ac_if.if_bpf)
+               bpf_mtap(sc->sc_arpcom.ac_if.if_bpf, m0);
+#endif
+
+#ifdef EB_TX_DEBUG
+       dprintf(("Tx new packet\n"));
+#endif
+
+/*
+ * Copy the datagram to the temporary buffer.
+ *
+ * Eventually we may as well just copy straight into the interface buffer
+ */
+
+       len = 0;
+       for (m = m0; m; m = m->m_next) {
+               if (m->m_len == 0)
+                       continue;
+               bcopy(mtod(m, caddr_t), sc->sc_pktbuf + len, m->m_len);
+               len += m->m_len;
+       }
+       m_freem(m0);
+
+/* If packet size is odd round up to the next 16 bit boundry */
+
+       if (len % 2)
+               ++len;
+
+       len = max(len, ETHER_MIN_LEN);
+       
+       if (len > ETHER_MAX_LEN)
+               log(LOG_WARNING, "ea: oversize packet = %d bytes\n", len);
+
+/* Ok we now have a packet len bytes long in our packet buffer */
+
+/* Transfer datagram to board. */
+
+#ifdef EB_TX_DEBUG
+       dprintf(("eb: xfr pkt length=%d...\n", len));
+
+       dprintf(("%s-->", ether_sprintf(sc->sc_pktbuf+6)));
+       dprintf(("%s\n", ether_sprintf(sc->sc_pktbuf)));
+#endif
+
+       sc->sc_config2 &= ~EB_CFG2_OUTPUT;
+       WriteShort(iobase + EB_8004_CONFIG2, sc->sc_config2);
+
+/*     dprintf(("st=%04x\n", ReadShort(iobase + EB_8004_STATUS)));*/
+
+/* Write the packet to the interface buffer, skipping the packet header */
+
+       eb_writebuf(sc, sc->sc_pktbuf, 0x0004, len);
+
+/* Follow it with a NULL packet header */
+
+       WriteShort(iobase + EB_8004_BUFWIN, 0x00);
+       WriteShort(iobase + EB_8004_BUFWIN, 0x00);
+
+/* Write the packet header */
+
+       eb_writebuf(sc, NULL, 0x0000, 0);
+
+       WriteShort(iobase + EB_8004_BUFWIN, (((len+4) & 0xff00) >> 8) | (((len+4) & 0xff) << 8));
+       WriteShort(iobase + EB_8004_BUFWIN, 0x00aa);
+
+       WriteShort(iobase + EB_8004_TX_PTR, 0x0000);
+
+/*     dprintf(("st=%04x\n", ReadShort(iobase + EB_8004_STATUS)));*/
+
+#ifdef EB_DEBUG
+       eb_dump_buffer(sc, 0);
+#endif
+
+/* Now transmit the datagram. */
+
+/*     dprintf(("st=%04x\n", ReadShort(iobase + EB_8004_STATUS)));*/
+       WriteShort(iobase + EB_8004_COMMAND, sc->sc_command | EB_CMD_TX_ON);
+#ifdef EB_TX_DEBUG
+       dprintf(("st=%04x\n", ReadShort(iobase + EB_8004_STATUS)));
+       dprintf(("tx: queued\n"));
+#endif
+}
+
+
+/*
+ * Ethernet controller interrupt.
+ */
+
+int
+ebintr(arg)
+       void *arg;
+{
+       register struct eb_softc *sc = arg;
+       u_int iobase = sc->sc_iobase;
+       int status, s;
+       u_int txstatus;
+
+       dprintf(("ebintr: "));
+
+/* Get the controller status */
+
+       status = ReadShort(iobase + EB_8004_STATUS);
+        dprintf(("st=%04x ", status)); 
+
+/* Tx interrupt ? */
+
+       if (status & EB_STATUS_TX_INT) {
+               dprintf(("txint "));
+
+/* Acknowledge the interrupt */
+
+               WriteShort(iobase + EB_8004_COMMAND, sc->sc_command
+                   | EB_CMD_TX_INTACK);
+
+               eb_readbuf(sc, (u_char *)&txstatus, 0x0000, 4);
+
+#ifdef EB_TX_DEBUG             
+               dprintf(("txstatus=%08x\n", txstatus));
+#endif
+               txstatus = (txstatus >> 24) & 0xff;
+
+/*
+ * Did it succeed ? Did we collide ?
+ *
+ * The exact proceedure here is not clear. We should get
+ * an interrupt on a sucessfull tx or on a collision.
+ * The done flag is set after successfull tx or 16 collisions
+ * We should thus get a interrupt for each of collision
+ * and the done bit should not be set. However it does appear
+ * to be set at the same time as the collision bit ...
+ *
+ * So we will count collisions and output errors and will assume
+ * that if the done bit is set the packet was transmitted.
+ * Stats may be wrong if 16 collisions occur on a packet
+ * as the done flag should be set but the packet may not have been
+ * transmitted. so the output count might not require incrementing
+ * if the 16 collisions flags is set. I don;t know abou this until
+ * it happens.
+ */
+
+               if (txstatus & EB_TXHDR_COLLISION) {
+                       sc->sc_arpcom.ac_if.if_collisions++;
+               } else if (txstatus & EB_TXHDR_ERROR_MASK) {
+                       sc->sc_arpcom.ac_if.if_oerrors++;
+               }
+
+/*             if (txstatus & EB_TXHDR_ERROR_MASK) {
+                       log(LOG_WARNING, "tx packet error =%02x\n", txstatus);
+               }*/
+
+               if (txstatus & EB_PKTHDR_DONE) {
+                       sc->sc_arpcom.ac_if.if_opackets++;
+
+                       /* Tx next packet */
+
+                       s = splimp();
+                       ebtxpacket(sc);
+                       (void)splx(s);
+               }
+       }
+
+/* Rx interrupt ? */
+
+       if (status & EB_STATUS_RX_INT) {
+               dprintf(("rxint "));
+
+/* Acknowledge the interrupt */
+
+               WriteShort(iobase + EB_8004_COMMAND, sc->sc_command
+                   | EB_CMD_RX_INTACK);
+
+/* Install a watchdog timer needed atm to fixed rx lockups */
+
+               sc->sc_arpcom.ac_if.if_timer = EB_TIMEOUT;
+
+/* Processes the received packets */
+               ebgetpackets(sc);
+
+/* Make sure the receiver is on */
+
+/*             if ((status & EB_STATUS_RX_ON) == 0) {
+                       WriteShort(iobase + EB_8004_COMMAND, sc->sc_command
+                           | EB_CMD_RX_ON);
+                       printf("rxintr: rx is off st=%04x\n",status);
+               }*/
+       }
+
+#ifdef EB_DEBUG
+       status = ReadShort(iobase + EB_8004_STATUS);
+        dprintf(("st=%04x\n", status));
+#endif
+       return(0);
+}
+
+void
+ebgetpackets(sc)
+       struct eb_softc *sc;
+{
+       u_int iobase = sc->sc_iobase;
+       int addr;
+       int len;
+       int ctrl;
+       int ptr;
+       int pack;
+       int status;
+       u_int rxstatus;
+
+/* We start from the last rx pointer position */
+
+       addr = sc->sc_rx_ptr;
+       sc->sc_config2 &= ~EB_CFG2_OUTPUT;
+       WriteShort(iobase + EB_8004_CONFIG2, sc->sc_config2);
+
+       do {
+/* Read rx header */
+
+               eb_readbuf(sc, (u_char *)&rxstatus, addr, 4);
+               
+/* Split the packet header */
+
+               ptr = ((rxstatus & 0xff) << 8) | ((rxstatus >> 8) & 0xff);
+               ctrl = (rxstatus >> 16) & 0xff;
+               status = (rxstatus >> 24) & 0xff;
+
+#ifdef EB_RX_DEBUG
+               dprintf(("addr=%04x ptr=%04x ctrl=%02x status=%02x\n", addr, ptr, ctrl, status));
+#endif
+
+/* Zero packet ptr ? then must be null header so exit */
+
+               if (ptr == 0) break;
+
+/* Get packet length */
+       
+               len = (ptr - addr) - 4;
+
+               if (len < 0) {
+                       len += EB_RX_BUFFER_SIZE;
+               }
+
+#ifdef EB_RX_DEBUG
+               dprintf(("len=%04x\n", len));
+#endif
+
+/* Has the packet rx completed ? if not then exit */
+
+               if ((status & EB_PKTHDR_DONE) == 0)
+                       break;
+
+/* Did we have any errors ? then note error and go to next packet */
+
+               if (status & 0x0f) {
+                       ++sc->sc_arpcom.ac_if.if_ierrors;
+                       printf("rx packet error (%02x) - dropping packet\n", status & 0x0f);
+/*                     sc->sc_config2 |= EB_CFG2_OUTPUT;
+                       WriteShort(iobase + EB_8004_CONFIG2, sc->sc_config2);
+                       eb_reinit(sc);
+                       return; */
+                       addr = ptr;
+                       continue;
+               }
+
+/* Is the packet too big ? - this will probably be trapped above as a receive error */
+
+               if (len > ETHER_MAX_LEN) {
+                       ++sc->sc_arpcom.ac_if.if_ierrors;
+                       printf("rx packet size error len=%d\n", len);
+/*                     sc->sc_config2 |= EB_CFG2_OUTPUT;
+                       WriteShort(iobase + EB_8004_CONFIG2, sc->sc_config2);
+                       eb_reinit(sc);
+                       return;*/
+                       addr = ptr;
+                       continue;
+               }
+
+               eb_readbuf(sc, sc->sc_pktbuf, addr + 4, len);
+
+#ifdef EB_RX_DEBUG
+               dprintf(("%s-->", ether_sprintf(sc->sc_pktbuf+6)));
+               dprintf(("%s\n", ether_sprintf(sc->sc_pktbuf)));
+#endif
+               sc->sc_arpcom.ac_if.if_ipackets++;
+               /* Pass data up to upper levels. */
+               ebread(sc, (caddr_t)sc->sc_pktbuf, len);
+
+               addr = ptr;
+               ++pack;
+       } while (len != 0);
+
+       sc->sc_config2 |= EB_CFG2_OUTPUT;
+       WriteShort(iobase + EB_8004_CONFIG2, sc->sc_config2);
+
+#ifdef EB_RX_DEBUG
+       dprintf(("new rx ptr=%04x\n", addr));
+#endif
+
+/* Store new rx pointer */
+
+       sc->sc_rx_ptr = addr;
+       WriteShort(iobase + EB_8004_RX_END, (sc->sc_rx_ptr >> 8));
+
+/* Make sure the receiver is on */
+
+       WriteShort(iobase + EB_8004_COMMAND, sc->sc_command
+           | EB_CMD_RX_ON);
+
+}
+
+
+/*
+ * Pass a packet up to the higher levels.
+ */
+
+static void
+ebread(sc, buf, len)
+       struct eb_softc *sc;
+       caddr_t buf;
+       int len;
+{
+       register struct ether_header *eh;
+       struct mbuf *m;
+
+       eh = (struct ether_header *)buf;
+       len -= sizeof(struct ether_header);
+       if (len <= 0)
+               return;
+
+       /* Pull packet off interface. */
+       m = ebget(buf, len, &sc->sc_arpcom.ac_if);
+       if (m == 0)
+               return;
+
+#if NBPFILTER > 0
+       /*
+        * Check if there's a BPF listener on this interface.
+        * If so, hand off the raw packet to bpf.
+        */
+       if (sc->sc_arpcom.ac_if.if_bpf) {
+               bpf_tap(sc->sc_arpcom.ac_if.if_bpf, buf, len + sizeof(struct ether_header));
+/*             bpf_mtap(sc->sc_arpcom.ac_if.if_bpf, m);*/
+
+               /*
+                * Note that the interface cannot be in promiscuous mode if
+                * there are no BPF listeners.  And if we are in promiscuous
+                * mode, we have to check if this packet is really ours.
+                */
+               if ((sc->sc_arpcom.ac_if.if_flags & IFF_PROMISC) &&
+                   (eh->ether_dhost[0] & 1) == 0 && /* !mcast and !bcast */
+                   bcmp(eh->ether_dhost, sc->sc_arpcom.ac_enaddr,
+                           sizeof(eh->ether_dhost)) != 0) {
+                       m_freem(m);
+                       return;
+               }
+       }
+#endif
+
+       ether_input(&sc->sc_arpcom.ac_if, eh, m);
+}
+
+/*
+ * Pull read data off a interface.  Len is length of data, with local net
+ * header stripped.  We copy the data into mbufs.  When full cluster sized
+ * units are present we copy into clusters.
+ */
+
+struct mbuf *
+ebget(buf, totlen, ifp)
+        caddr_t buf;
+        int totlen;
+        struct ifnet *ifp;
+{
+        struct mbuf *top, **mp, *m;
+        int len;
+        register caddr_t cp = buf;
+        char *epkt;
+
+        buf += sizeof(struct ether_header);
+        cp = buf;
+        epkt = cp + totlen;
+
+        MGETHDR(m, M_DONTWAIT, MT_DATA);
+        if (m == 0)
+                return 0;
+        m->m_pkthdr.rcvif = ifp;
+        m->m_pkthdr.len = totlen;
+        m->m_len = MHLEN;
+        top = 0;
+        mp = &top;
+
+        while (totlen > 0) {
+                if (top) {
+                        MGET(m, M_DONTWAIT, MT_DATA);
+                        if (m == 0) {
+                                m_freem(top);
+                                return 0;
+                        }
+                        m->m_len = MLEN;
+                }
+                len = min(totlen, epkt - cp);
+                if (len >= MINCLSIZE) {
+                        MCLGET(m, M_DONTWAIT);
+                        if (m->m_flags & M_EXT)
+                                m->m_len = len = min(len, MCLBYTES);
+                        else
+                                len = m->m_len;
+                } else {
+                        /*
+                         * Place initial small packet/header at end of mbuf.
+                         */
+                        if (len < m->m_len) {
+                                if (top == 0 && len + max_linkhdr <= m->m_len)
+                                        m->m_data += max_linkhdr;
+                                m->m_len = len;
+                        } else
+                                len = m->m_len;
+                }
+                bcopy(cp, mtod(m, caddr_t), (unsigned)len);
+                cp += len;
+                *mp = m;
+                mp = &m->m_next;
+                totlen -= len;
+                if (cp == epkt)
+                        cp = buf;
+        }
+
+        return top;
+}
+
+/*
+ * Process an ioctl request. This code needs some work - it looks pretty ugly.
+ */
+static int
+eb_ioctl(ifp, cmd, data)
+       register struct ifnet *ifp;
+       u_long cmd;
+       caddr_t data;
+{
+       struct eb_softc *sc = eb_cd.cd_devs[ifp->if_unit];
+       struct ifaddr *ifa = (struct ifaddr *)data;
+/*     struct ifreq *ifr = (struct ifreq *)data;*/
+       int s, error = 0;
+
+       s = splimp();
+
+       switch (cmd) {
+
+       case SIOCSIFADDR:
+               ifp->if_flags |= IFF_UP;
+               dprintf(("if_flags=%08x\n", ifp->if_flags));
+
+               switch (ifa->ifa_addr->sa_family) {
+#ifdef INET
+               case AF_INET:
+                       arp_ifinit(&sc->sc_arpcom, ifa);
+                       dprintf(("Interface eb is coming up (AF_INET)\n"));
+                       eb_init(sc);
+                       break;
+#endif
+#ifdef NS
+               /* XXX - This code is probably wrong. */
+               case AF_NS:
+                   {
+                       register struct ns_addr *ina = &IA_SNS(ifa)->sns_addr;
+
+                       if (ns_nullhost(*ina))
+                               ina->x_host =
+                                   *(union ns_host *)(sc->sc_arpcom.ac_enaddr);
+                       else
+                               bcopy(ina->x_host.c_host,
+                                   sc->sc_arpcom.ac_enaddr,
+                                   sizeof(sc->sc_arpcom.ac_enaddr));
+                       /* Set new address. */
+                       dprintf(("Interface eb is coming up (AF_NS)\n"));
+                       eb_init(sc);
+                       break;
+                   }
+#endif
+               default:
+                       dprintf(("Interface eb is coming up (default)\n"));
+                       eb_init(sc);
+                       break;
+               }
+               break;
+
+       case SIOCSIFFLAGS:
+               dprintf(("if_flags=%08x\n", ifp->if_flags));
+               if ((ifp->if_flags & IFF_UP) == 0 &&
+                   (ifp->if_flags & IFF_RUNNING) != 0) {
+                       /*
+                        * If interface is marked down and it is running, then
+                        * stop it.
+                        */
+                       dprintf(("Interface ea is stopping\n"));
+                       eb_stop(sc);
+                       ifp->if_flags &= ~IFF_RUNNING;
+               } else if ((ifp->if_flags & IFF_UP) != 0 &&
+                          (ifp->if_flags & IFF_RUNNING) == 0) {
+                       /*
+                        * If interface is marked up and it is stopped, then
+                        * start it.
+                        */
+                       dprintf(("Interface eb is restarting(1)\n"));
+                       eb_init(sc);
+               } else {
+                       /*
+                        * Some other important flag might have changed, so
+                        * reset.
+                        */
+                       dprintf(("Interface eb is reinitialising\n"));
+                       eb_reinit(sc);
+               }
+               break;
+
+       default:
+               error = EINVAL;
+               break;
+       }
+
+       (void)splx(s);
+       return error;
+}
+
+/*
+ * Device timeout routine.
+ *
+ * Ok I am not sure exactly how the device timeout should work....
+ * Currently what will happens is that that the device timeout is only
+ * set when a packet it received. This indicates we are on an active
+ * network and thus we should expect more packets. If non arrive in
+ * in the timeout period then we reinitialise as we may have jammed.
+ * We zero the timeout at this point so that we don't end up with
+ * an endless stream of timeouts if the network goes down.
+ */
+
+static void
+eb_watchdog(unit)
+       int unit;
+{
+       struct eb_softc *sc = eb_cd.cd_devs[unit];
+
+       log(LOG_ERR, "%s: device timeout\n", sc->sc_dev.dv_xname);
+       sc->sc_arpcom.ac_if.if_oerrors++;
+       dprintf(("eb_watchdog: "));
+       dprintf(("st=%04x\n", ReadShort(sc->sc_iobase + EB_8004_STATUS)));
+
+       /* Kick the interface */
+
+       eb_reinit(sc);
+
+       sc->sc_arpcom.ac_if.if_timer = 0;
+}
+
+/* End of if_ea.c */
diff --git a/sys/arch/arm32/podulebus/if_ebreg.h b/sys/arch/arm32/podulebus/if_ebreg.h
new file mode 100644 (file)
index 0000000..b14bea7
--- /dev/null
@@ -0,0 +1,154 @@
+/* $NetBSD: if_ebreg.h,v 1.2 1996/03/18 21:23:12 mark Exp $ */
+
+/*
+ * Copyright (c) 1995 Mark Brinicombe
+ * 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 Mark Brinicombe.
+ * 4. The name of the company nor the name of the author may 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 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.
+ *
+ * RiscBSD kernel project
+ *
+ * if_ebreg.h
+ *
+ * EtherB device driver
+ *
+ * Created      : 08/07/95
+ */
+
+/*
+ * SEEQ 80C04 Register Definitions
+ */
+
+#define EB_8004_BASE   0x800
+
+/*
+ * SEEQ 80C04 registers
+ */
+
+#define EB_8004_COMMAND                0x000
+#define EB_8004_STATUS         0x000
+#define EB_8004_CONFIG1                0x040
+#define EB_8004_CONFIG2                0x080
+#define EB_8004_RX_END         0x0c0
+#define EB_8004_BUFWIN         0x100
+#define EB_8004_RX_PTR         0x140
+#define EB_8004_TX_PTR         0x180
+#define EB_8004_DMA_ADDR       0x1c0
+
+/*  */
+
+#define EB_CMD_TEST_INTEN      (1 << 0)
+#define EB_CMD_RX_INTEN                (1 << 1)
+#define EB_CMD_TX_INTEN                (1 << 2)
+#define EB_CMD_TEST_INTACK     (1 << 4)
+#define EB_CMD_RX_INTACK       (1 << 5)
+#define EB_CMD_TX_INTACK       (1 << 6)
+#define EB_CMD_BW_INTACK       (1 << 7)
+#define EB_CMD_TEST_INT1       (1 << 8)
+#define EB_CMD_RX_ON           (1 << 9)
+#define EB_CMD_TX_ON           (1 << 10)
+#define EB_CMD_TEST_INT2       (1 << 11)
+#define EB_CMD_RX_OFF          (1 << 12)
+#define EB_CMD_TX_OFF          (1 << 13)
+#define EB_CMD_FIFO_READ       (1 << 14)
+#define EB_CMD_FIFO_WRITE      (1 << 15)
+
+#define EB_STATUS_TEST_INT     (1 << 4)
+#define EB_STATUS_RX_INT       (1 << 5)
+#define EB_STATUS_TX_INT       (1 << 6)
+#define EB_STATUS_RX_ON                (1 << 9)
+#define EB_STATUS_TX_ON                (1 << 10)
+#define EB_STATUS_TX_NOFAIL    (1 << 12)
+#define EB_STATUS_FIFO_FULL    (1 << 13)
+#define EB_STATUS_FIFO_EMPTY   (1 << 14)
+#define EB_STATUS_FIFO_DIR     (1 << 15)
+#define EB_STATUS_FIFO_READ    (1 << 15)
+
+#define EB_CFG1_SPECIFIC       ((0 << 15) | (0 << 14))
+#define EB_CFG1_BROADCAST      ((0 << 15) | (1 << 14))
+#define EB_CFG1_MULTICAST      ((1 << 15) | (0 << 14))
+#define EB_CFG1_PROMISCUOUS    ((1 << 15) | (1 << 14))
+
+#define EB_CFG2_BYTESWAP       (1 << 0)
+#define EB_CFG2_REA_AUTOUPDATE (1 << 1)
+#define EB_CFG2_RX_TX_DISABLE  (1 << 2)
+#define EB_CFG2_CRC_ERR_ENABLE (1 << 3)
+#define EB_CFG2_DRIB_ERR_ENABLE (1 << 4)
+#define EB_CFG2_PASS_LONGSHORT (1 << 5)
+#define EB_CFG2_PREAM_SELECT   (1 << 7)
+#define EB_CFG2_RX_CRC         (1 << 9)
+#define EB_CFG2_NO_TX_CRC      (1 << 10)
+#define EB_CFG2_LOOPBACK       (1 << 11)
+#define EB_CFG2_OUTPUT         (1 << 12)
+#define EB_CFG2_RESET          (1 << 15)
+
+#define EB_CFG3_SLEEP          (1 << 3)
+
+#define EB_BUFCODE_STATION_ADDR        0x00
+#define EB_BUFCODE_ADDRESS_PROM 0x06
+#define EB_BUFCODE_TX_EAP      0x07
+#define EB_BUFCODE_LOCAL_MEM   0x08
+#define EB_BUFCODE_TX_COLLS    0x0b
+#define EB_BUFCODE_CONFIG3     0x0c
+#define EB_BUFCODE_PRODUCTID   0x0d
+#define EB_BUFCODE_TESTENABLE   0x0e
+#define EB_BUFCODE_MULTICAST   0x0f
+
+#define EB_PKTHDR_TX           (1 << 7)
+#define EB_PKTHDR_RX           (0 << 7)
+#define EB_PKTHDR_CHAIN_CONT   (1 << 6)
+#define EB_PKTHDR_DATA_FOLLOWS (1 << 5)
+
+#define EB_PKTHDR_DONE         (1 << 7)
+
+#define EB_TXHDR_BABBLE                (1 << 0)
+#define EB_TXHDR_COLLISION     (1 << 1)
+#define EB_TXHDR_COLLISION16   (1 << 2)
+#define EB_TXHDR_COLLISIONMASK (0x78)
+#define EB_TXHDR_ERROR_MASK    (0x07)
+
+#define EB_TXHDR_BABBLE_INT    (1 << 0)
+#define EB_TXHDR_COLLISION_INT (1 << 1)
+#define EB_TXHDR_COLLISION16_INT       (1 << 2)
+#define EB_TXHDR_XMIT_SUCCESS_INT      (1 << 3)
+#define EB_TXHDR_SQET_TEST_INT (1 << 3)
+
+#define EB_RXHDR_OVERSIZE      (1 << 0)
+#define EB_RXHDR_CRC_ERROR     (1 << 1)
+#define EB_RXHDR_DRIBBLE_ERROR (1 << 2)
+#define EB_RXHDR_SHORT_FRAME   (1 << 3)
+
+#define EB_BUFFER_SIZE         0x10000
+#define EB_TX_BUFFER_SIZE      0x4000
+#define EB_RX_BUFFER_SIZE      0xC000
+
+/* Packet buffer size */
+
+#define        EB_BUFSIZ       2048
+
+/* End of if_ebreg.h */
diff --git a/sys/arch/arm32/podulebus/if_eh.c b/sys/arch/arm32/podulebus/if_eh.c
new file mode 100644 (file)
index 0000000..ab47663
--- /dev/null
@@ -0,0 +1,1213 @@
+/* $NetBSD: if_eh.c,v 1.6 1996/03/27 21:49:34 mark Exp $ */
+
+/*
+ * Copyright (c) 1995 Melvin Tang-Richardson.
+ * All rights reserved.
+ *
+ * Essential things to do
+ *  - BPF and multicast support
+ *  - Testing
+ *  - 16-bit dma's
+ *  - Buffer overflow handling (This must be done a certain way) [Nuts]
+ *  - Enabling card interrupts (Need i cubed info)
+ *
+ * Other things to do
+ *  - Pipelined transmitts
+ *  - Dynamic buffer allocation
+ *  - Shared RAM if I cubed give me info
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided 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 RiscBSD.
+ * 4. The name of the company nor the name of the author may be used to
+ *    endorse or promote products derived from this software without specific
+ *    prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY RISCBSD ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL RISCBSD OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * if_eh.c
+ *
+ * Ether H driver.
+ */
+
+/* Some system includes *****************************************************/
+
+#include <sys/types.h>
+#include <sys/cdefs.h>
+#include <sys/time.h>
+#include <sys/systm.h>
+#include <sys/param.h>
+#include <sys/kernel.h>
+#include <sys/malloc.h>
+#include <sys/syslog.h>
+#include <sys/device.h>
+#include <machine/bootconfig.h>
+
+/* Hardware related include chip/card/bus ***********************************/
+
+#include <machine/io.h>
+#include <machine/irqhandler.h>
+#include <machine/katelib.h>
+#include <arm32/podulebus/podulebus.h>
+#include <arm32/podulebus/if_ehreg.h>
+
+/* Includes for interfacing with the network subsystem **********************/
+
+#include <sys/socket.h>
+#include <sys/ioctl.h>
+#include <sys/mbuf.h>
+
+#include <net/if.h>
+#include <net/if_types.h>
+#include <net/if_dl.h>
+#include <net/netisr.h>
+#include <net/route.h>
+
+#ifdef INET
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/in_var.h>
+#include <netinet/ip.h>
+#include <netinet/if_ether.h>
+#endif
+
+#ifdef NS
+#include <netns/ns.h>
+#include <netns/ns_if.h>
+#endif
+
+/****************************************************************************/
+/* Some useful definitions **************************************************/
+/****************************************************************************/
+
+#define MY_MANUFACTURER        (0x46)
+#define MY_PODULE      (0xec)
+
+#define TXBUF_SIZE     (1522)
+#define NTXBUF         (1)
+
+#define RXBUF_SIZE     (256)
+#define NRXBUF         (26)
+
+#define ETHER_MIN_LEN   (64)
+#define ETHER_MAX_LEN   (1522)
+
+#define PRINTF printf
+
+/****************************************************************************/
+/* Prototype internal data structures ***************************************/
+/****************************************************************************/
+
+struct eh_softc {
+       /* Kernel interface variables */
+       struct device   sc_dev;
+       int             sc_podule_number;
+       podule_t        *sc_podule;
+       irqhandler_t    sc_ih;
+
+       /* Network subsystem interface */
+       struct arpcom   sc_arpcom;
+       int             promisc;
+
+       /* Driver defined state variables */
+       int             sc_flags;
+
+       /* Hardware defined state */
+       int             sc_base;
+       int             sc_reg;
+       int             sc_nxtpkt;
+
+       /* Card memory map */
+       int             sc_physstart;
+       int             sc_physend;
+       int             sc_tbs[NTXBUF];  /* Transmit buffer start */
+       int             sc_rbs;
+       int             sc_rbd;
+
+       /* Txrx parameters */
+       int             sc_txcur;        /* Fill this buffer next */
+       int             sc_txlst;        /* Buffer in use         */
+};
+
+/* sc_flags */
+
+#define MODE_MASK      (3)
+#define MODE_DEAD      (0)
+#define        MODE_PIO        (1)
+#define MODE_SHRAM     (2)
+
+/****************************************************************************/
+/* Function and data prototypes *********************************************/
+/****************************************************************************/
+
+int  ehprobe           __P((struct device *parent, void *match, void *aux));
+void ehattach          __P((struct device *parent, struct device *self, void *aux));
+void ehstart           __P((struct ifnet *ifp));
+int  ehioctl           __P((struct ifnet *ifp, u_long cmd, caddr_t data));
+void ehwatchdog                __P((int unit));
+void eh_stop_controller  __P((struct eh_softc *sc));
+void eh_start_controller __P((struct eh_softc *sc));
+void eh_transmit_command __P((struct eh_softc *sc));
+int  eh_copyin         __P((struct eh_softc *sc, int src, char *dest, int len));
+int  eh_copyout                __P((struct eh_softc *sc, char *src, int dest, int len));
+void ehinit            __P((struct eh_softc *sc));
+int  ehstop            __P((struct eh_softc *sc));
+int  ehintr            __P((void *arg));
+void eh_shutdown       __P((void *arg));
+
+struct cfattach eh_ca = {
+       sizeof(struct eh_softc), ehprobe, ehattach
+};
+
+struct cfdriver eh_cd = {
+       NULL, "eh", DV_DULL, NULL, 0
+};
+
+/****************************************************************************/
+/* Some useful macros *******************************************************/
+/****************************************************************************/
+
+#define SetReg(r,v)    WriteWord ( sc->sc_reg+(r), (v)|((v)<<16) )
+
+#define GetReg(r)      ReadByte ( sc->sc_reg+(r) )
+
+#define        PAGE(n) SetReg ( EH_COMMAND,    \
+               ((GetReg(EH_COMMAND)&COM_MASK_PAGE)|(n<<6)) )
+
+/* When initiating a remote dma, reset the TXP bit.  This Does Not abort */
+/* the transmit, but allows us overlap this remote dma                  */
+
+#define        REMOTE_DMA(n)   SetReg ( EH_COMMAND,    \
+               ((GetReg(EH_COMMAND)&(COM_MASK_DMA))|n) )
+
+extern char *boot_args;
+char *strstr           __P((char */*s1*/, char */*s2*/));
+
+/****************************************************************************/
+/* Bus attachment code ******************************************************/
+/****************************************************************************/
+
+int
+ehprobe(parent, match, aux)
+       struct device *parent;
+       void *match;
+       void *aux;
+{
+       struct eh_softc *sc = (void *) match;
+       struct podule_attach_args *pa = (void *) aux;
+       int counter;
+       int temp;
+       int podule;
+
+       podule = findpodule(MY_MANUFACTURER, MY_PODULE, pa->pa_podule_number);
+
+       if (podule == -1)
+               return 0;
+
+       /* Start to fill in the softc with the trivial variables */
+
+       sc->sc_flags = MODE_PIO;        /* Select pio mode until I get info from i^3 */
+       sc->sc_base = podules[podule].fast_base;
+       sc->sc_reg = sc->sc_base + 0x800;
+
+       /* The probe could be tidied up a little */
+
+       /* Reset the card */
+       SetReg(EH_RESET, 0xff);
+       delay(10000);
+
+       /* Explicitly abort remote DMA, mainly to set a legal state */
+       PAGE(0);
+       eh_stop_controller(sc);
+       SetReg(EH_COMMAND, 0x20);            /* This is wrong */
+
+       SetReg(EH_ISR, 0xf );                /* Clear any previous work */
+
+       temp = GetReg(EH_CONFIGA);
+       temp = GetReg(EH_CONFIGA);
+       temp &= ~0x38;
+       SetReg(EH_CONFIGA, temp | 3<<3);
+
+       temp = GetReg(EH_CONFIGA);
+       temp = GetReg(EH_CONFIGA);
+
+       /* Make the thing interrupt and test it */
+
+       eh_start_controller(sc);
+
+       /* Temporary initialisation, to allow a transmit test */
+
+       SetReg(EH_PSTART, 16384 >> 8);
+       SetReg(EH_PSTOP,  16896 >> 8);
+       SetReg(EH_BNRY,   16384 >> 8);
+
+       SetReg(EH_TCR, TCR_NORMALLOOP); /* Erk!! No, put us in loopback */
+       SetReg(EH_DCR, DCR_WTS|DCR_LS|DCR_LAS);
+       SetReg(EH_RCR, 0);
+
+       /* Transmit some garbage into the loopback */
+
+       SetReg(EH_TPSR, 0x5000);
+       SetReg(EH_TBCR0, 0);
+       SetReg(EH_TBCR1, 3);
+
+       eh_transmit_command(sc);
+
+       /* The card shouldn't be this quick, so use it as a test */
+
+       if ((GetReg(EH_TSR)&TSR_DONE) != 0)
+               PRINTF("eh: Card responded rather quickly %02x\n", GetReg(EH_TSR));
+
+       for (counter=500; counter>0; counter--) {
+               if ((GetReg(EH_TSR)&TSR_DONE) != 0)
+                       break;
+
+               delay(500);
+       }
+
+       if (counter == 0) {
+               PRINTF("eh: card did not respond\n");
+               return 0;
+       }
+
+       /* Let it sleep since we're not doing anything with it for now */
+
+       SetReg(EH_ISR, 0);
+       SetReg(EH_DCR, DCR_WTS|DCR_LS|DCR_LAS);
+
+
+       /* Test the board ram.  This code will change */
+
+       /*
+        * Due to problems with some ether H cards the boot option ehbug
+        * can be used to skip this test.
+        * If you system hangs during the eh probe try this option.
+        */
+
+       #define NLEN (0x2000)
+       #define NBASE (0x4000)
+
+        if (boot_args) {
+               char *ptr;
+       
+               ptr = strstr(boot_args, "ehbug");
+               if (!ptr) {
+                       char *test_data;
+                       char *read_buffer;
+                       MALLOC(test_data, char *, NLEN, M_TEMP, M_NOWAIT);
+                       if (test_data == NULL)
+                               panic("Cannot allocate temporary memory for buffer test (1)\n");
+                       MALLOC(read_buffer, char *, NLEN, M_TEMP, M_NOWAIT);
+                       if (read_buffer == NULL)
+                               panic("Cannot allocate temporary memory for buffer test (1)\n");
+
+                       printf("1.");
+
+               /* Fill the test_data block */
+
+                       for (counter=0; counter<NLEN; counter++) {
+                               test_data[counter] = (char)(counter&0xff);
+                               if (test_data[counter] == 0)
+                                       test_data[counter]=0x23;
+                       }
+
+                       printf("2.");
+       
+                       eh_copyout(sc, test_data, NBASE, NLEN);
+                       printf("3.");
+                       delay(10000);
+                       eh_copyin(sc, NBASE, read_buffer, NLEN);
+                       printf("4.");
+       
+                       if (bcmp(test_data, read_buffer, NLEN))
+                               PRINTF("Block test failed\n");
+                       printf("5.");
+                       FREE(test_data, M_TEMP);
+                       FREE(read_buffer, M_TEMP);
+               }
+       }
+       /* This is always true for our ether h */
+
+       sc->sc_physstart = 0x4000;
+       sc->sc_physend   = 0x6000;
+
+       /* Get out ethernet address */
+       sc->sc_arpcom.ac_enaddr[0] = 0x00;
+       sc->sc_arpcom.ac_enaddr[1] = 0x00;
+       sc->sc_arpcom.ac_enaddr[2] = 0xc0;
+       sc->sc_arpcom.ac_enaddr[3] = 0x41;
+       sc->sc_arpcom.ac_enaddr[4] = bootconfig.machine_id[1];
+       sc->sc_arpcom.ac_enaddr[5] = bootconfig.machine_id[0];
+
+       /* Copy the ether addr cards filter */
+
+       PAGE(1);
+       for (counter=0; counter<6; counter++)
+               SetReg(((counter+1)<<2), sc->sc_arpcom.ac_enaddr[counter]);
+       PAGE(0);
+
+       /* Tell the podule system about our successful probe */
+       pa->pa_podule_number = podule;
+       pa->pa_podule = &podules[podule];
+
+       return 1;
+}
+
+void
+ehattach(parent, self, aux)
+       struct device *parent;
+       struct device *self;
+       void *aux;
+{
+       struct eh_softc *sc = (void *) self;
+       struct podule_attach_args *pa = (void *)aux;
+       struct ifnet *ifp = &sc->sc_arpcom.ac_if;
+       int irq;
+       int temp;
+
+       /* Check a few things about the attach args */
+       sc->sc_podule_number = pa->pa_podule_number;
+       if (sc->sc_podule_number == -1)
+               panic("Podule has disappeared !");
+
+       sc->sc_podule = &podules[sc->sc_podule_number];
+       podules[sc->sc_podule_number].attached = 1;
+
+       /* Fill in my application form to attach to the networking system */
+
+       ifp->if_unit = sc->sc_dev.dv_unit;
+       ifp->if_name = eh_cd.cd_name;
+       ifp->if_start = ehstart;
+       ifp->if_ioctl = ehioctl;
+       ifp->if_watchdog = ehwatchdog;
+       ifp->if_flags = IFF_BROADCAST | IFF_NOTRAILERS;
+
+       /* Signed, dated then sent */
+
+       if_attach(ifp);
+       ether_ifattach(ifp);
+
+       /* Not print some stuff for the attach line, starting with the address */
+
+       PRINTF(" address %s", ether_sprintf(sc->sc_arpcom.ac_enaddr));
+
+       /* Now the transfer mode we're operating in */
+
+       switch (sc->sc_flags & MODE_MASK) {
+               case MODE_PIO:
+                       PRINTF(" pio mode");
+                       break;
+               case MODE_SHRAM:
+                       PRINTF(" ram mode");
+                       break;
+               default:
+                       panic("Ether H probe set an unknown mode");
+       }
+
+       /* Get an irq handler installed */
+
+       SetReg(EH_IMR, 0);
+       SetReg(EH_ISR, 0xff);
+
+       sc->sc_ih.ih_func  = ehintr;
+       sc->sc_ih.ih_arg   = sc;
+       sc->sc_ih.ih_level = IPL_NET;
+       sc->sc_ih.ih_name = "net: eh";
+       
+       irq = (sc->sc_podule_number>=MAX_PODULES) ? IRQ_NETSLOT : IRQ_PODULE;
+
+       if (irq_claim(irq, &sc->sc_ih))
+               panic("Cannot install IRQ handler");
+
+    /* This loopbacks the card on reset, and stops riscos locking */
+
+       if (shutdownhook_establish(eh_shutdown, (void *)sc)==NULL)
+               panic("Cannot install shutdown handler");
+
+    /* Reprogram CONFIGA.  I dont think we should do this any more */
+
+       temp = GetReg(EH_CONFIGA);
+       temp = GetReg(EH_CONFIGA);
+       temp &= ~0x38;
+       SetReg(EH_CONFIGA, temp | (3<<3));
+
+       /* And that's it */
+
+       PRINTF("\n");
+}
+
+/****************************************************************************/
+/* Net subsystem interface **************************************************/
+/****************************************************************************/
+
+#define NEXT_TXBUF (((sc->sc_txcur+1)>=NTXBUF) ? 0 : (sc->sc_txcur+1))
+
+void
+ehstart(ifp)
+       struct ifnet *ifp;
+{
+       struct eh_softc *sc = eh_cd.cd_devs[ifp->if_unit];
+       int cur;
+       struct mbuf *m0, *m;
+       int nextbuf;
+       char *buffer;
+       char txbuf[TXBUF_SIZE];
+       int len = 0;
+
+       PAGE(0);
+
+       if ((ifp->if_flags & IFF_OACTIVE) != 0)
+               return;
+
+/* This is for pipelined transmit.  At present just use 1 buffer */
+
+       for (;;) {
+
+/* The #ifdef PIPELINE_TRANSMIT code is total screwed */
+
+#ifdef PIPELINE_TRANSMIT
+               nextbuf = NEXT_TXBUF;
+               if ( nextbuf == sc->sc_txlst )
+                       ifp->if_flags |= IFF_OACTIVE;
+               break;
+       }
+#else
+               nextbuf = 0;
+#endif
+
+               /*** Speed up - In future, copy the bufs direct to the card ***/
+
+               /* Copy a frame out of the mbufs */
+
+               IF_DEQUEUE(&sc->sc_arpcom.ac_if.if_snd, m);
+               if ( !m )
+                       break;
+
+               buffer = txbuf;
+
+               len = 0;
+               for ( m0=m; m && (len + m->m_len) < TXBUF_SIZE; m=m->m_next ) {
+                       bcopy(mtod(m,caddr_t), buffer, m->m_len);
+                       buffer+=m->m_len;
+                       len+=m->m_len;
+               }
+           
+               m_freem(m0);
+               len = max ( len, ETHER_MIN_LEN );
+
+               /* And blat it to the card */
+
+               eh_copyout ( sc, txbuf, sc->sc_tbs[nextbuf], len );
+
+#ifdef PIPELINE_TRANSMIT
+               sc->sc_txlst = nextbuf;
+#endif
+               PAGE(0);
+
+               SetReg ( EH_TPSR, sc->sc_tbs[nextbuf]>>8 );
+               SetReg ( EH_TBCR0, len&0xff );
+               SetReg ( EH_TBCR1, (len>>8) & 0xff );
+
+               cur = GetReg(EH_COMMAND);
+
+               eh_transmit_command (sc );
+
+               ifp->if_flags |= IFF_OACTIVE;
+               ifp->if_timer = 30;
+
+#ifndef PIPELINE_TRANSMIT
+               break;
+#endif
+       }
+}
+
+#define IZSET(a,b) ((a->if_flags&b)!=0)
+#define IZCLR(a,b) ((a->if_flags&b)==0)
+#define DOSET(a,b) (a->if_flags|=b)
+#define DOCLR(a,b) (a->if_flags&=~b)
+
+int
+ehioctl(ifp, cmd, data)
+       struct ifnet *ifp;
+       u_long cmd;
+       caddr_t data;
+{
+       struct eh_softc *sc = eh_cd.cd_devs[ifp->if_unit];
+       struct ifaddr *ifa = (struct ifaddr *)data;
+       int s = splimp ();
+       int error = 0;
+
+       switch (cmd) {
+       case SIOCSIFADDR:
+               ifp->if_flags |= IFF_UP;
+               switch ( ifa->ifa_addr->sa_family ) {
+#ifdef INET
+               case AF_INET:
+                       ehinit(sc);
+                       arp_ifinit(&sc->sc_arpcom, ifa);
+                       break;
+#endif
+               default:
+                       ehinit(sc);
+                       break;
+               }
+               break;
+
+       case SIOCSIFFLAGS:
+               sc->promisc = ifp->if_flags & ( IFF_PROMISC | IFF_ALLMULTI );
+
+               if ( IZCLR(ifp,IFF_UP) && IZSET(ifp,IFF_RUNNING) ) {
+                       /* Interface marked down, but still running */
+                       ehstop(sc);
+                       DOCLR(ifp,IFF_RUNNING); 
+               } else if ( IZSET(ifp,IFF_UP) && IZCLR(ifp,IFF_RUNNING) ) {
+                       /* Just marked up, not running yet */
+                       ehinit(sc);
+               } else {
+                       /* Reset to invoke changes in other registers */
+                       ehstop(sc);
+                       ehinit(sc);
+               }
+
+       default:
+               error = EINVAL;
+       }
+
+       splx (s);
+       return error;
+}
+
+void
+ehwatchdog(unit)
+       int unit;
+{
+       struct eh_softc *sc = eh_cd.cd_devs[unit];
+
+       log (LOG_ERR, "%s: device timeout\n", sc->sc_dev.dv_xname );
+       sc->sc_arpcom.ac_if.if_oerrors++;
+
+       ehinit (sc);
+}
+
+/*
+ * void eh_stop_controller ( struct eh_softc *sc )
+ *
+ * Software reset command, takes the controller offline, no packets will be
+ * received or transmitted.  Any reception or transmission inprogres will
+ * continue to completion before entering the reset state.
+ */
+
+void
+eh_stop_controller(sc)
+       struct eh_softc *sc;
+{
+       SetReg ( EH_COMMAND, ((GetReg(EH_COMMAND)&0xfc)|1) );
+       delay ( 10000 );        /* Change this to wait on the ISR bit */
+}
+
+/*
+ * void eh_start_controller ( struct eh_softc *sc )
+ *
+ * Activte the NIC core after either power up or when the NIC Core has
+ * been placed in a reset mode by eh_stop_controller or an error.
+ */
+
+void
+eh_start_controller(sc)
+       struct eh_softc *sc;
+{
+       int temp = GetReg(EH_COMMAND);
+       SetReg ( EH_COMMAND, ( (temp&0xfc)|2) );
+}
+
+void
+eh_transmit_command(sc)
+       struct eh_softc *sc;
+{
+       /* Explicit set here.  There is no other reasonable combination */
+       SetReg ( EH_COMMAND, COM_ABORT|COM_STA|COM_TXP);
+}
+
+/****************************************************************************/
+/* Remote DMA handling ******************************************************/
+/****************************************************************************/
+
+/* Remote DMA handling is going to undergo a major overhaul real soon now */
+
+/* We musn't fail */
+
+inline void
+eh_ensure_dma_ok(sc)
+       struct eh_softc *sc;
+{
+       register int isr = GetReg ( EH_ISR );
+       register int status = GetReg ( EH_COMMAND );
+       int dummy;
+
+       if ((status&COM_ABORT)==0) {
+               SetReg ( EH_COMMAND, status|COM_ABORT );
+               while ((isr&ISR_RDC)==0) {
+                       dummy = GetReg ( EH_DATA_PORT );
+                       delay(50);
+               }
+       }
+
+       /* Reset the COM_TXP bit.  This does not abort transmission */
+
+       SetReg(EH_COMMAND, 0x22);
+}
+
+inline int
+eh_ensure_dma_competed(sc, type)
+       struct eh_softc *sc;
+       int type;
+{
+       register int status = GetReg ( EH_COMMAND );
+
+       if ( (status&COM_ABORT)==0 ) {
+               int dummy=0;
+               printf ( "EHDEBUG: Remote %d wasn't finished\n", type );
+               SetReg ( EH_COMMAND, status|COM_ABORT );
+               switch ( type ) {
+               case COM_READ:
+                       dummy = GetReg ( EH_DATA_PORT );
+                       break;
+               case COM_WRITE:
+                       SetReg ( EH_DATA_PORT, dummy );
+                       break;
+               }
+               ehinit (sc);
+               return 1;
+       }
+       return 0;
+}
+
+/* Do an eh_copyin, but take into consideration ring wrap */
+
+int
+eh_copyring(sc, src, dest, len)
+       struct eh_softc *sc;
+       int src;
+       char *dest;
+       int len;
+{
+       if ( (src+len)>sc->sc_rbd ) {
+               register int in = sc->sc_rbd - src;
+               if ( eh_copyin ( sc, src, dest, in )==0 ) {
+                       printf ( "copyring failed pass 1\n" );
+                       return 0;
+               }
+               if ( eh_copyin ( sc, sc->sc_rbs, dest+in, len-in )==0 ) {
+                       printf ( "copyring failed pass 2\n" );
+                       return 0;
+               }
+       } else {
+               if ( eh_copyin ( sc, src, dest, len )==0 ) {
+                       printf ( "copyring faild on 1 pass copy\n" );
+                       return 0;
+               }
+       }
+       return len;
+}
+
+int
+eh_copyin(sc, src, dest, len)
+       struct eh_softc *sc;
+       int src;
+       char *dest;
+       int len;
+{
+       int counter;
+       int s;
+       short *dst = (short *)dest;
+
+       s = splhigh();          /* Erm, maybe not needed now */
+
+       if (len & 1)
+               len++;
+       if (src & 1) {
+               printf ( "EHDEBUG: Copying from odd address\n" );
+               src++;
+       }
+
+       /* Remote DMA to the DP83905 must be done with care.  If we dont */
+       /* do it exactly right, it punishes us by locking the bus.           */
+
+       eh_ensure_dma_ok (sc);
+
+       /* Set up the DMA */
+
+       SetReg ( EH_RSAR0, src & 0xff );
+       SetReg ( EH_RSAR1, (src>>8) & 0xff );
+       SetReg ( EH_RBCR0, len & 0xff );
+       SetReg ( EH_RBCR1, (len>>8) & 0xff );
+
+       /* Set the DMA running */
+       /* REMOTE_DMA ( COM_READ ); */ /* SetReg ( EH_COMMAND, 0x0a ); */
+       SetReg ( EH_COMMAND, COM_READ|COM_STA );
+
+       for ( counter=0; counter<len; counter+=2 )
+               *(dst++)=ReadShort ( sc->sc_reg + EH_DATA_PORT );
+
+       splx(s);
+
+       if ( eh_ensure_dma_competed ( sc, COM_READ ) )
+               return 0;
+
+       return len;
+}
+
+int
+eh_copyout(sc, src, dest, len)
+       struct eh_softc *sc;
+       char *src;
+       int dest;
+       int len;
+{
+       int counter;
+       int s;
+       short *sr = (short *)src;
+
+       if (len & 1)
+               len++;
+       if (dest & 1) {
+               printf ( "EHDEBUG: Copying to odd address\n" );
+               dest++;
+       }
+
+       s = splhigh();          /* Erm, maybe not needed now */
+
+       /* Remote DMA to the DP83905 must be done with care.  If we dont */
+       /* do it exactly right, it punishes us by locking the bus.           */
+
+       eh_ensure_dma_ok (sc);
+
+       /* Set up the DMA */
+
+       SetReg ( EH_RSAR0, dest & 0xff );
+       SetReg ( EH_RSAR1, (dest>>8) & 0xff );
+       SetReg ( EH_RBCR0, len & 0xff );
+       SetReg ( EH_RBCR1, (len>>8) & 0xff );
+
+       /* Set the DMA running */
+       /*REMOTE_DMA ( COM_WRITE );*/ /* SetReg ( EH_COMMAND, 0x0a ); */
+       SetReg ( EH_COMMAND, COM_WRITE|COM_STA );
+
+       for ( counter=0; counter<len; counter+=2 ) {
+               WriteShort ( sc->sc_reg + EH_DATA_PORT, *(sr) );
+               sr++;
+       }
+
+       splx(s);
+
+       if ( eh_ensure_dma_competed ( sc, COM_WRITE ) )
+               return 0;
+
+       return len;
+}
+
+#define ALLOCBLK(v,s)  (v)=card_freestart;     \
+                       card_freestart+=((s)+0xff)&(~0xff)
+
+void
+ehinit(sc)
+       struct eh_softc *sc;
+{
+       int card_freestart;
+       int counter;
+
+       PAGE(0);
+
+       /* Lay out the cards ram */
+       card_freestart = sc->sc_physstart;
+
+       /* Allocate receive buffers */
+
+       ALLOCBLK ( sc->sc_rbs, (RXBUF_SIZE*NRXBUF) );
+       sc->sc_rbd = card_freestart;
+       sc->sc_nxtpkt = sc->sc_rbs + 0x100;
+
+       /* Allocate transmit buffers */
+       for ( counter=0; counter<NTXBUF; counter++ ) {
+               ALLOCBLK ( sc->sc_tbs[counter], TXBUF_SIZE );
+       }
+
+       if ( card_freestart > sc->sc_physend ) {
+               printf ( "eh: card short of ram %02x required %02x present\n",
+                   card_freestart, sc->sc_physstart );
+               sc->sc_arpcom.ac_if.if_flags &= ~IFF_RUNNING;
+               sc->sc_arpcom.ac_if.if_flags |= IFF_OACTIVE;
+               return;
+       }
+
+       /*
+        * Bring the controller up
+        *
+        * The ordering here is critical.  Dont change unless you know what
+        * you're doing
+        */
+
+       /* Reset the card */
+
+       SetReg ( EH_RESET, 0xff );
+       delay (50000);
+       SetReg ( EH_RESET, 0x00 );
+       delay (50000);
+
+       /* 1. Program the command register for page 0 */
+
+       SetReg ( EH_COMMAND, 0x21 );
+
+       /* 2. Initialize the Data configuration register */
+
+       SetReg ( EH_DCR, DCR_WTS|DCR_LS|(0<<5) );
+
+       /* 3. Clear RBCR if using remote DMA */
+
+       SetReg ( EH_RBCR0, 0 );
+       SetReg ( EH_RBCR1, 0 );
+
+       /* 4. Initialise RCR */
+
+       SetReg ( EH_RCR, 0x04 );
+
+       /* 5. Place the controller in loopback mode 1 or 2  TCR=02H or 04H */
+
+       SetReg ( EH_TCR, 0x02 );
+
+       /* 6. Initiliase Receive ring buffer BNDRY PSTART PSTOP */
+
+       SetReg ( EH_BNRY,   sc->sc_rbs >> 8 );
+       SetReg ( EH_PSTART, sc->sc_rbs >> 8 );
+       SetReg ( EH_PSTOP,  sc->sc_rbd >> 8 );
+
+       /* 7. Clear ISR */
+
+       SetReg ( EH_ISR, 0xff );
+
+       /* 8. Initialise IMR */
+
+       SetReg ( EH_IMR, ISR_PRX|ISR_PTX|ISR_RXE|ISR_TXE|ISR_OVW|ISR_CNT );
+
+       /* 9. Program command register for page 1 COM=0x61      */
+       /*    Initialise PAR MAR and CURR                       */
+
+       PAGE(1);
+
+       SetReg ( EH_CURR,   sc->sc_nxtpkt >> 8 );
+
+       for ( counter=0; counter<6; counter++ )
+               SetReg ( ((counter+1)<<2), sc->sc_arpcom.ac_enaddr[counter] );
+
+       /* Put controller into start mode COM = 0x22 */
+
+       SetReg ( EH_COMMAND, 0x22 );
+
+       /* Initialise the TCR */
+
+       SetReg ( EH_TCR, TCR_NORMALLOOP );
+
+       /* Interface is up */
+
+       sc->sc_arpcom.ac_if.if_flags |= IFF_RUNNING;
+       sc->sc_arpcom.ac_if.if_flags &= ~IFF_OACTIVE;
+
+       ehstart(&sc->sc_arpcom.ac_if);
+}
+
+int
+ehstop(sc)
+       struct eh_softc *sc;
+{
+       int s = splimp();
+       eh_stop_controller(sc);
+       SetReg(EH_DCR, DCR_LS|DCR_LAS);
+       splx(s);
+       return 0;
+}
+
+#define INTR_ACK(s) SetReg ( EH_ISR, s )
+
+/* In need of tidying */
+
+#undef MYTEST
+
+void
+eh_rint(sc)
+       struct eh_softc *sc;
+{
+       struct ifnet *ifp = &sc->sc_arpcom.ac_if;
+       struct mbuf *top, **mp, *m;
+       struct ether_header eh;
+       struct eh_rxhdr hdr;
+       int status = GetReg(EH_RSR);
+       int rxstatus=0;
+       int totlen, len;
+       int ptr;
+       int rbend;
+       int thispacket;
+       int bnry;
+
+#ifdef MYTEST
+       int old;
+#endif
+
+       /* Get the end of the ring buffer */
+
+       PAGE(1);
+       rbend = GetReg ( EH_CURR ) << 8;
+       PAGE(0);
+
+       /* If we have something to receive then receive it */
+
+       if ( status&RSR_PRX ) {
+               /* Remove all the packets from the ring buffer */
+               for ( ptr=sc->sc_nxtpkt; ptr!=rbend ; ptr = sc->sc_nxtpkt ) {
+
+                       thispacket = ptr;
+                       /* Copy the ether h receive header */
+
+                       if ( eh_copyring ( sc, ptr, (char *)&hdr, 4 ) != 4 ) {
+                               printf ( "eh: Failed copying in header\n" );
+                               printf ( "eh: thispacket %02x\n", thispacket );
+                               ehinit (sc);
+                               return;
+                       }
+
+                       rxstatus = hdr.rx_status;
+                       totlen = (hdr.rx_rbc1<<8) + hdr.rx_rbc0;
+
+                       ptr+=4;
+
+                       /* Check the packet's status */
+                       if ( hdr.rx_status&(RSR_CRC|RSR_FAE|RSR_FO|RSR_MPA) ) {
+                               printf ( "eh: intact packet is corrupt %02x %04x\n",
+                                   hdr.rx_status, ptr );
+                       }
+
+                       if (((hdr.rx_nxtpkt<<8)>sc->sc_rbd) || ((hdr.rx_nxtpkt<<8)<sc->sc_rbs)) {
+                               printf ( "eh: ring buffer empty %04x %04x\n",
+                                   hdr.rx_nxtpkt, ptr );
+                               ehinit (sc);
+                               return;
+                       }
+
+                       if (0)
+                               printf ( "pulling packet at %08x, next at %08x\n", thispacket, sc->sc_nxtpkt );
+
+                       if ( totlen>ETHER_MAX_LEN ) {
+                               printf ( "eh: giant packet received %04x\n", totlen );
+                               totlen = ETHER_MAX_LEN;
+                       }
+
+                       /* Copy the ether header */
+
+                       if ((eh_copyring ( sc, ptr, (char *)&eh, sizeof (eh)))!=sizeof(eh))  {
+                               printf ( "eh: Failed copying in ethenet header\n" );
+                               return;
+                       }
+                       ptr+=sizeof(eh);
+                       totlen-=sizeof(eh);
+
+                       /* Copy the packet into mbufs */
+
+                       MGETHDR(m, M_DONTWAIT, MT_DATA);
+                       if ( m==0 )
+                               return;
+                       m->m_pkthdr.rcvif = ifp;
+                       m->m_pkthdr.len   = totlen;
+                       len = MHLEN;
+                       top = 0;
+                       mp = &top;
+
+                       while ( totlen > 0 ) {
+                               if (top) {
+                                       MGET(m, M_DONTWAIT, MT_DATA);
+                                       if ( m==0 ) {
+                                               m_freem(top);
+                                               goto skip;
+                                       }
+                                       len = MLEN;
+                               }
+                               if ( totlen >= MINCLSIZE ) {
+                                       MCLGET(m, M_DONTWAIT);
+                                       if (m->m_flags & M_EXT)
+                                       len = MCLBYTES;
+                               }
+                               m->m_len = len = min ( totlen, len );
+
+                               if ((eh_copyring ( sc, ptr, mtod(m, caddr_t), len))!=len)
+                                       printf ( "eh: failed copying in buffer %d\n", len );
+
+                               ptr += len;
+                               totlen -= len;
+                               *mp = m;
+                               mp = &m->m_next;
+                       }
+
+                       m = top;
+                       ifp->if_ipackets++;
+                       ether_input(ifp, &eh, m );
+skip:
+
+                       /* Ok, I'm done with this packet */
+
+                       sc->sc_nxtpkt = hdr.rx_nxtpkt << 8;
+
+                       /* Set the boundary pointer on the ring buffer */
+
+                       bnry = (sc->sc_nxtpkt>>8)-1;
+                       if ( bnry < (sc->sc_rbs>>8) )
+                               bnry = (sc->sc_rbd>>8)-1;
+                       SetReg ( EH_BNRY, bnry );
+       
+                       PAGE(1);
+                       rbend = GetReg ( EH_CURR ) << 8;
+                       PAGE(0);
+               }
+       }
+}
+
+int
+ehintr(arg)
+       void *arg;
+{
+       struct eh_softc *sc = arg;
+       register int isr = GetReg ( EH_ISR );   /* Is char of int faster ? */
+       register int times = 0;
+
+       PAGE(0);
+
+       if ( isr & ISR_RXE ) {
+               int status = GetReg ( EH_RSR );
+               PRINTF ( "eh: Receive Error:" );
+               if ( status&RSR_PRX )
+                       PRINTF ( " packet received intact (this should happen)" );
+               if ( status&RSR_CRC )
+                       PRINTF ( " crc error" );
+               if ( status&RSR_FAE )
+                       PRINTF ( " frame alignment error" );
+               if ( status&RSR_FO )
+                       PRINTF ( " fifo overrun" );
+               if ( status&RSR_MPA )
+                       PRINTF ( " missed packet" );
+               if ( status&RSR_DIS )
+                       PRINTF ( " receiver disabled" );
+               printf ( "\n" );
+               INTR_ACK ( ISR_RXE );
+               ehinit (sc);
+               return 0;
+       }
+
+       if ( isr & ISR_PRX ) {
+               eh_rint (sc);
+               INTR_ACK ( ISR_PRX );
+       }
+
+       if ( isr & ISR_PTX ) {
+               struct ifnet *ifp = &sc->sc_arpcom.ac_if;
+               int status;
+               INTR_ACK ( ISR_PTX );
+               ifp->if_timer=0;
+               ifp->if_flags &= ~IFF_OACTIVE;
+
+               status = GetReg ( EH_TSR );
+
+               if ( status&TSR_PTX )
+                       ifp->if_opackets++;
+
+               if ( status&TSR_COL )
+                       ifp->if_collisions+=GetReg(EH_NCR);
+
+               if ( status&TSR_ABT )
+                       PRINTF ( "eh: too many collisions\n" );
+
+               if ( status&TSR_CRS )
+                       PRINTF ( "eh: no carrier\n" );
+
+               if ( status&TSR_CDH )
+                       PRINTF ( "eh: tranceiver failure, no heartbeat \n" );
+
+               if ( status&TSR_OWC )
+                       PRINTF ( "eh: out of window \n" );
+
+               if ( status&(TSR_ABT|TSR_CRS|TSR_FU|TSR_CDH|TSR_OWC) )
+                       ifp->if_oerrors++;
+
+               ehstart(ifp);   
+       }
+
+       if ( isr & ISR_TXE ) {
+               INTR_ACK ( ISR_TXE );
+               PRINTF ( "ehintr: Transmit error\n" );
+       }
+
+       if ( isr & ISR_OVW ) {
+               INTR_ACK ( ISR_OVW );
+               PRINTF ( "ehintr: Counter overflow\n" );
+       }
+
+       if ( isr & ISR_RST ) {
+               INTR_ACK ( ISR_RST );
+               PRINTF ( "ehintr: Reset status\n" );
+       }
+
+       if ((times++)>16) {
+               PRINTF ( "eh: possible interrupt jammed on." );
+               SetReg ( EH_IMR, 0x0 );
+       }
+
+       /* Dont do this for the mo until I'm sure.
+
+       isr = GetReg ( EH_ISR );
+
+       if ( (isr&GetReg(EH_IMR))!=0 )
+               goto more;
+       */
+
+       if ( (isr&GetReg(EH_IMR))!=0 )
+               printf ( "eh: Interrupt not serviced\n" );
+
+       return 0;
+}
+
+/****************************************************************************/
+/* Auxilary routines ********************************************************/
+/****************************************************************************/
+
+void
+eh_shutdown(arg)
+       void *arg;
+{
+       struct eh_softc *sc = (struct eh_softc *)arg;
+
+       /* On shutdown put us in loopback */
+
+       SetReg(EH_DCR, DCR_LAS);
+       SetReg(EH_TCR, TCR_NICMOD);
+
+       /* and program remote dma so riscos doesnt lock */
+
+       SetReg(EH_RSAR0, 0);
+       SetReg(EH_RSAR1, 1);
+       SetReg(EH_RBCR0, 0);
+       SetReg(EH_RBCR1, 1);
+}
diff --git a/sys/arch/arm32/podulebus/if_ehreg.h b/sys/arch/arm32/podulebus/if_ehreg.h
new file mode 100644 (file)
index 0000000..8fbb18e
--- /dev/null
@@ -0,0 +1,151 @@
+/* $NetBSD: if_ehreg.h,v 1.2 1996/03/08 16:24:51 mark Exp $ */
+
+/*
+ * Copyright (c) 1995 Melvin Tang-Richardson.
+ * 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 RiscBSD.
+ * 4. The name of the company nor the name of the author may be used to
+ *    endorse or promote products derived from this software without specific
+ *    prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY RISCBSD ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL RISCBSD OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * if_ehreg.h
+ *
+ * Ether H register definitions.
+ */
+
+#define EH_RESET       (0x18<<2)
+
+#define EH_DATA_PORT   (0x10<<2)
+
+/* Special registers */
+
+#define EH_CONFIGA     (0x0a<<2)
+
+/* Page 0 read registers */
+
+#define EH_COMMAND     (0x00<<2)
+#define EH_CLAD0       (0x01<<2)
+#define EH_CLDA1       (0x02<<2)
+#define EH_BNRY                (0x03<<2)
+#define EH_TSR         (0x04<<2)
+#define EH_NCR         (0x05<<2)
+#define EH_FIFO                (0x06<<2)
+#define EH_ISR         (0x07<<2)
+#define EH_CRDA0       (0x08<<2)
+#define EH_CRDA1       (0x09<<2)
+#define EH_RSR         (0x0c<<2)
+
+/* Page 0 write registers */
+
+#define EH_PSTART      (0x01<<2)
+#define EH_PSTOP       (0x02<<2)
+#define EH_TPSR                (0x04<<2)
+#define EH_TBCR0       (0x05<<2)
+#define EH_TBCR1       (0x06<<2)
+#define EH_RSAR0       (0x08<<2)
+#define EH_RSAR1       (0x09<<2)
+#define EH_RBCR0       (0x0a<<2)
+#define EH_RBCR1       (0x0b<<2)
+#define EH_RCR         (0x0c<<2)
+#define EH_TCR         (0x0d<<2)
+#define EH_DCR         (0x0e<<2)
+#define EH_IMR         (0x0f<<2)
+
+/* Page 1 write registers */
+
+#define EH_CURR                (0x07<<2)
+
+/* Command bits */
+
+#define COM_STP                (0x01)
+#define COM_STA                (0x02)
+#define COM_TXP                (0x04)
+#define COM_MASK_PAGE  (0x3f)
+#define COM_READ       (0x08)
+#define COM_WRITE      (0x10)
+#define COM_SEND       (0x18)
+#define COM_ABORT      (0x20)
+#define COM_MASK_DMA   (0xc7)
+#define COM_DMA_MASK   (0x38)
+
+/* DCR bits */
+
+#define DCR_WTS                (0x01)
+#define DCR_BOS                (0x02)
+#define DCR_LAS                (0x04)
+#define DCR_LS         (0x08)
+#define DCR_ARM                (0x10)
+
+/* TSR bits */
+
+#define TSR_PTX                (0x01)
+#define TSR_COL                (0x04)
+#define TSR_ABT                (0x08)
+#define TSR_CRS                (0x10)
+#define TSR_FU         (0x20)
+#define TSR_CDH                (0x40)
+#define TSR_OWC                (0x80)
+#define TSR_DONE       ((TSR_PTX)|(TSR_ABT))
+
+/* TCR bits */
+
+#define TCR_CRC                (0x01)
+#define TCR_NORMALLOOP (0x00)
+#define TCR_NICMOD     (0x02)
+#define TCR_ENDECMOD   (0x04)
+#define TCR_EXTLOOP    (0x06)
+#define TCR_ATD                (0x08)
+#define TCR_OFST       (0x10)
+
+/* ISR bits */
+
+#define ISR_PRX                (0x01)
+#define ISR_PTX                (0x02)
+#define ISR_RXE                (0x04)
+#define ISR_TXE                (0x08)
+#define ISR_OVW                (0x10)
+#define ISR_CNT                (0x20)
+#define ISR_RDC                (0x40)
+#define ISR_RST                (0x80)
+
+/* RSR bits */
+
+#define RSR_PRX                (0x01)
+#define RSR_CRC                (0x02)
+#define RSR_FAE                (0x04)
+#define RSR_FO         (0x08)
+#define RSR_MPA                (0x10)
+#define RSR_PHY                (0x20)
+#define RSR_DIS                (0x40)
+#define RSR_DFR                (0x80)
+
+struct eh_rxhdr {
+       char rx_status;
+       char rx_nxtpkt;
+       char rx_rbc0;
+       char rx_rbc1;
+};
+
diff --git a/sys/arch/arm32/podulebus/if_ie.c b/sys/arch/arm32/podulebus/if_ie.c
new file mode 100644 (file)
index 0000000..ecc8269
--- /dev/null
@@ -0,0 +1,1524 @@
+/* $NetBSD: if_ie.c,v 1.5 1996/03/27 21:49:36 mark Exp $ */
+
+/*
+ * Copyright (c) 1995 Melvin Tang-Richardson.
+ * All rights reserved.
+ *
+ * This driver is a major hash up of src/sys/dev/isa/if_ie.c and
+ * src/sys/arch/arm32/podule/kgdb_ie.c  Please refer to copyright
+ * notices from them too.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided 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 RiscBSD.
+ * 4. The name of the company nor the name of the author may be used to
+ *    endorse or promote products derived from this software without specific
+ *    prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY RISCBSD ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL RISCBSD 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.
+ *
+ * RiscBSD kernel project
+ *
+ * if_ie.c
+ *
+ * Ether 1 podule driver
+ *
+ * Created      : 26/06/95
+ */
+
+/*
+ *     This driver is at it's last beta release.  It should not cause
+ *     any problems (Touch wood)
+ *
+ *     If it passes field tests again.  This will constitute the realse
+ *     version.
+ */
+
+#define IGNORE_ETHER1_IDROM_CHECKSUM
+
+/* Standard podule includes */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/conf.h>
+#include <sys/malloc.h>
+#include <sys/device.h>
+#include <machine/io.h>
+#include <machine/irqhandler.h>
+#include <machine/katelib.h>
+#include <arm32/podulebus/podulebus.h>
+
+/* Include for interface to the net and ethernet subsystems */
+
+#include <sys/socket.h>
+#include <sys/syslog.h>
+#include <sys/ioctl.h>
+#include <sys/mbuf.h>
+
+#include <net/if.h>
+#include <net/if_types.h>
+#include <net/if_dl.h>
+#include <net/netisr.h>
+#include <net/route.h>
+
+#ifdef INET
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/in_var.h>
+#include <netinet/ip.h>
+#include <netinet/if_ether.h>
+#endif
+
+#ifdef NS
+#include <netns/ns.h>
+#include <netns/ns_if.h>
+#endif
+
+/* Import our data structres */
+
+#include "if_iereg.h"
+
+/* BPF support */
+
+#include "bpfilter.h"
+#if NBPFILTER > 0
+#include <net/bpf.h>
+#include <net/bpfdesc.h>
+#endif
+
+/* Some useful defines and macros */
+
+#define MY_MANUFACTURER 0x00
+#define MY_PODULE       0x03
+#define PODULE_IRQ_PENDING (1)
+#define NFRAMES        (16)            /* number of frame to allow for receive */
+#define NRXBUF (48)            /* number of receive buffers to allocate */
+#define IE_RXBUF_SIZE (256)    /* receive buf size */
+#define NTXBUF  (2)            /* number of transmit buffers to allocate */
+#define IE_TXBUF_SIZE (1522)   /* size of tx buffer */
+
+#define ETHER_MIN_LEN  (64)
+#define ETHER_MAX_LEN  (1518)
+
+#define PWriteShort(a,b)       WriteWord(a,(b)<<16|(b))
+
+#define offsetof(type, member)  (((size_t)&((type *)0)->member)<<1)
+
+/* Some data structres local to this file */
+
+struct ie_softc {
+       struct device   sc_dev;
+       int             sc_podule_number;
+       podule_t        *sc_podule;
+       irqhandler_t    sc_ih;
+       int             sc_iobase;
+       int             sc_fastbase;
+       int             sc_rom;
+       int             sc_ram;
+       int             sc_control;
+       struct arpcom   sc_arpcom;
+       int             promisc;
+       int             sc_irqmode;
+
+       u_long  rframes[NFRAMES];
+       u_long  rbuffs[NRXBUF];
+       u_long  cbuffs[NRXBUF];
+       int     rfhead, rftail, rbhead, rbtail;
+
+       u_long  xmit_cmds[NTXBUF];
+       u_long  xmit_buffs[NTXBUF];
+       u_long  xmit_cbuffs[NTXBUF];
+       int     xmit_count;
+       int     xmit_free;
+       int     xchead;
+       int     xctail;
+};
+
+/* Function and data prototypes */
+
+static void host2ie  ( struct ie_softc *sc, void *src, u_long dest, int size );
+static void ie2host  ( struct ie_softc *sc, u_long src, void *dest, int size );
+static void iezero   ( struct ie_softc *sc, u_long p, int size );
+void        iereset  ( struct ie_softc *sc );
+void        iewatchdog ( int unit );
+int         ieioctl  ( struct ifnet *ifp, u_long cmd, caddr_t data );
+void        iestart  ( struct ifnet *ifp );
+int        iestop   ( struct ie_softc *sc );
+int         ieinit   ( struct ie_softc *sc );
+int        ieintr   ( void *arg );
+void       ietint   ( struct ie_softc *sc );
+
+/* A whopper of a function */
+static int command_and_wait ( struct ie_softc *sc, u_short cmd,
+                             struct ie_sys_ctl_block *pscb,
+                             void *pcmd, int ocmd, int scmd, int mask );
+
+struct cfattach ie_ca;
+
+struct cfdriver ie_cd;
+
+/* Let's go! */
+
+/*
+ * Clear all pending interrupts from the i82586 chip
+ */
+
+static __inline void ie_cli ( struct ie_softc *sc )
+{
+    WriteByte ( sc->sc_fastbase + (IE_CONTROL<<2), IE_CONT_CLI );
+}
+
+/*
+ * Cool down the i82586, like its namesake, it gets very hot
+ */
+
+static __inline void ie_cooldown ( int temperature )
+{
+}
+
+/* 
+ * Wake the i82586 chip up and get it to do something
+ */
+
+static __inline void ieattn ( struct ie_softc *sc )
+{
+    WriteByte ( sc->sc_control + (IE_CONTROL<<2), IE_CONT_ATTN );
+}
+
+/*
+ * Set the podule page register to bring a given address into view
+ */
+
+static __inline void setpage ( struct ie_softc *sc, u_long off )
+{
+    WriteByte ( sc->sc_control + (IE_PAGE<<2), IE_COFF2PAGE(off) );
+}
+
+/*
+ * Ack the i82586
+ */
+
+static void ie_ack ( struct ie_softc *sc, u_short mask )
+{
+    u_short stat;
+    int i;
+    setpage(sc, IE_IBASE + IE_SCB_OFF );
+
+    stat = ReadShort ( sc->sc_ram + IE_COFF2POFF(IE_IBASE+IE_SCB_OFF) +
+               (offsetof(struct ie_sys_ctl_block, ie_status)) );
+
+    PWriteShort ( sc->sc_ram + IE_COFF2POFF(IE_IBASE+IE_SCB_OFF) +
+               (offsetof(struct ie_sys_ctl_block, ie_command)),
+               stat & mask );
+
+    ieattn(sc);
+
+    for ( i=4000; --i>=0; ) {
+        if ( !ReadShort(sc->sc_ram + IE_COFF2POFF(IE_IBASE+IE_SCB_OFF) +
+           (offsetof(struct ie_sys_ctl_block, ie_command))) )
+               break;
+           delay(100);
+    }
+
+    if ( i<=0 )
+    {
+       printf ( "ie: command timed out\n" );
+    }
+    ie_cli(sc);
+}
+
+/*
+ * This routine does the checksumming for the idrom
+ */
+
+static u_long crc32(u_char *p, int l)
+{
+    u_long crc=-1;
+    int i, b;
+    while ( --l >= 0 ) {
+       b = *p++;
+       for ( i=8; --i >= 0; b>>=1 )
+           if ((b&1)^(crc>>31))
+               crc=(crc<<1)^0x4c11db7;
+           else
+               crc<<=1;
+    }
+    return crc;
+}
+
+/*
+ * Probe for the ether1 card.  return 1 on success 0 on failure
+ */
+
+int ieprobe ( struct device *parent, void *match, void *aux )
+{
+       struct ie_softc *sc = (void *)match;
+       struct podule_attach_args *pa = (void *)aux;
+       int podule, i;
+       char idrom[32];
+       u_char *hwaddr = sc->sc_arpcom.ac_enaddr;
+
+       /* Get the nice podulebus podule to find my podule in its table */
+       podule = findpodule(MY_MANUFACTURER, MY_PODULE, pa->pa_podule_number);
+
+       if (podule == -1)
+               return(0);
+
+       /* Index some podule areas */
+       sc->sc_iobase   = podules[podule].sync_base;    /* OBSOLETE */
+       sc->sc_fastbase = podules[podule].fast_base;    /* OBSOLETE */
+       sc->sc_rom      = podules[podule].sync_base;
+       sc->sc_control  = podules[podule].fast_base;
+       sc->sc_ram      = podules[podule].fast_base + IE_MEMOFF;
+
+       /* Set the page mask to something know and neutral */
+       setpage(sc, IE_SCB_OFF);
+
+       /* Fetch the first part of the idrom */
+       for ( i=0; i<16; i++ ) {
+           idrom[i] = ReadByte ( sc->sc_rom + (i<<2) );
+       };
+
+       /* Verify the podulebus probe incase RiscOS lied */
+        if ( ReadByte ( sc->sc_rom + (3<<2) ) != 0x03 ) {
+           panic ( "ie: Ether1 ROM probablly broken.  ECID corrupt" );
+           return 0;
+       }
+
+       /* Reset the 82586 */
+       WriteByte ( sc->sc_fastbase + (IE_CONTROL<<2), IE_CONT_RESET );
+       delay(1000);
+       WriteByte ( sc->sc_fastbase + (IE_CONTROL<<2), 0 );
+       delay(10000);
+
+       /* Clear pending interrupts */
+       ie_cli (sc);
+
+       /* Setup SCP */
+       {
+           struct ie_sys_conf_ptr scp;
+           bzero (&scp, sizeof(scp) );
+           scp.ie_iscp_ptr = (caddr_t)IE_ISCP_ADDR;
+           host2ie(sc, &scp, IE_SCP_ADDR, sizeof (scp) );
+       }
+
+       /* Setup ISCP */
+       {
+           struct ie_int_sys_conf_ptr iscp;
+           bzero ( &iscp, sizeof(iscp) );
+           iscp.ie_busy = 1;
+           iscp.ie_base = (caddr_t)IE_IBASE;
+           iscp.ie_scb_offset = IE_SCB_OFF;
+           host2ie(sc, &iscp, IE_ISCP_ADDR, sizeof(iscp) );
+       }
+
+       /* Initialise the control block */
+       iezero ( sc, IE_IBASE + IE_SCB_OFF, sizeof(struct ie_sys_ctl_block) );
+       ieattn(sc);
+
+       /* Wait for not busy */
+       setpage ( sc, IE_ISCP_ADDR );
+       for ( i=10000; --i>=0; ) {
+           if ( !ReadShort( sc->sc_ram + IE_COFF2POFF(IE_ISCP_ADDR) +
+                 ( offsetof(struct ie_int_sys_conf_ptr, ie_busy)) ) )
+               break;
+           delay (10);
+       }
+
+       /* If the busy didn't go low, the i82586 is broken or too slow */
+        if ( i<=0 )
+       {
+          printf ( "ie: ether1 chipset didn't respond\n" );
+          return 0;
+       }
+
+       /* Ensure that the podule sends interrupts */
+        for ( i=1000; --i>=0 ; ) {
+           if ( ReadByte(sc->sc_rom + 0) & PODULE_IRQ_PENDING )
+               break;
+           delay (10);
+       }
+
+       /* If we didn't see the interrupt then the IRQ line is broken */
+       if ( i<=0 )
+       {
+           printf ( "ie: interrupt from chipset didn't reach host\n" );
+           return 0;
+       }
+
+       /* Ack our little test operation */
+       ie_ack(sc,IE_ST_WHENCE);
+        ie_cli (sc);
+
+       /* Get second part of idrom */
+       for ( i=16; i<32; i++ ) {
+           idrom[i] = ReadByte ( sc->sc_rom + (i<<2) );
+       };
+
+       /* This checksum always fails.  For some reason the first 16 */
+       /* bytes are duplicated in the second 16 bytes, the checksum */
+       /* should be at location 28 it is clearly not                */
+
+       /* It is possible that this ether1 card is buggered          */
+
+#ifndef IGNORE_ETHER1_IDROM_CHECKSUM
+       if ( crc32(idrom,28) != *(u_long *)(idrom+28) )
+       {
+           printf ( "ie: ether1 idrom failed checksum %08x!=%08x\n",
+                                       crc32(idrom,28), *(u_long *)(idrom+28));
+            for ( i=0; i<32; i+=8 ) {
+               printf ( "IDROM: %02x %02x %02x %02x %02x %02x %02x %02x\n",
+                   idrom[0+i], idrom[1+i], idrom[2+i], idrom[3+i], 
+                   idrom[4+i], idrom[5+i], idrom[6+i], idrom[7+i] );
+           }
+           printf ( "ie: I'll ignore this fact for now!\n" );
+       }
+#endif
+
+       /* Get our ethernet address.  Do explicit copy */
+       for ( i=0; i<ETHER_ADDR_LEN; i++ )
+           hwaddr[i] = idrom[9+i];
+
+       /* Tell the podule system about our successful probe */
+       pa->pa_podule_number = podule;
+       pa->pa_podule = &podules[podule];
+
+       return(1);
+}
+
+/*
+ * Attach our driver to the interfaces it uses
+ */
+  
+void ieattach ( struct device *parent, struct device *self, void *aux )
+{
+       struct ie_softc *sc = (void *)self;
+       struct podule_attach_args *pa = (void *)aux;
+       struct ifnet *ifp = &sc->sc_arpcom.ac_if;
+
+       /* Check a few things about the attach args */
+       sc->sc_podule_number = pa->pa_podule_number;
+       if (sc->sc_podule_number == -1)
+               panic("Podule has disappeared !");
+
+       sc->sc_podule = &podules[sc->sc_podule_number];
+       podules[sc->sc_podule_number].attached = 1;
+
+       /* Fill in my application form to attach to the inet system */
+
+       ifp->if_unit = sc->sc_dev.dv_unit;
+       ifp->if_name = ie_cd.cd_name;
+       ifp->if_start = iestart;
+       ifp->if_ioctl = ieioctl;
+       ifp->if_watchdog = iewatchdog;
+       ifp->if_flags = IFF_BROADCAST | IFF_NOTRAILERS;
+       
+       /* Signed, dated then sent */
+        if_attach (ifp);
+       ether_ifattach(ifp);
+
+       /* "Hmm," said nuts, "what if the attach fails" */
+    
+       /* Write some pretty things on the annoucement line */
+       printf ( " %s using %dk card ram",
+           ether_sprintf(sc->sc_arpcom.ac_enaddr),
+           ((NRXBUF*IE_RXBUF_SIZE)+(NTXBUF*IE_TXBUF_SIZE))/1024 );
+
+#if NBPFILTER > 0
+       printf ( " BPF" );
+       bpfattach ( &ifp->if_bpf, ifp, DLT_EN10MB, sizeof(struct ether_header));
+#endif
+
+       sc->sc_ih.ih_func = ieintr;
+       sc->sc_ih.ih_arg = sc;
+       sc->sc_ih.ih_level = IPL_NET;
+       sc->sc_ih.ih_name = "net: ie";
+
+       if (irq_claim(IRQ_PODULE, &sc->sc_ih))
+       {
+           sc->sc_irqmode = 0;
+           printf ( " POLLED" );
+           panic("Cannot install IRQ handler\n");
+       }
+       else
+       {
+           sc->sc_irqmode = 1;
+           printf ( " IRQ" );
+       }
+
+       printf ( "\n" );
+}
+  
+                  
+/*
+ * Our cfdriver structure for the autoconfig system to chew on
+ */
+
+struct cfattach ie_ca = {
+       sizeof(struct ie_softc), ieprobe, ieattach
+};
+
+struct cfdriver ie_cd = {
+       NULL, "ie", DV_IFNET
+};
+
+/*
+ * Oh no!! Where's my shorts!!! I'm sure I put them on this morning
+ */
+
+void PWriteShorts ( char *src, char *dest, int cnt )
+{
+    for ( cnt/=2; --cnt>=0; ) {
+       PWriteShort ( dest, *(u_short *)src );
+       src+=2;
+       dest+=4;
+    }
+}
+
+void ReadShorts ( char *src, char *dest, int cnt )
+{
+    for ( cnt/=2; --cnt>=0; ) {
+       *(u_short *)dest = ReadShort ( src );
+       src+=4;
+       dest+=2;
+    }
+}
+
+/*
+ * A bcopy or memcpy to adapter ram.  It handles the page register for you
+ * so you dont have to worry about the ram windowing
+ */
+
+static void host2ie ( struct ie_softc *sc, void *src, u_long dest, int size )
+{
+    int cnt;
+
+    if (size&1)
+       panic ( "host2ie" );
+
+    while ( size>0 ) {
+       cnt = IE_PAGESIZE - dest % IE_PAGESIZE;
+       if ( cnt > size )
+           cnt = size;
+       setpage ( sc, dest );
+       PWriteShorts ( src, (char *)sc->sc_ram + IE_COFF2POFF(dest), cnt );
+       src+=cnt;
+       dest+=cnt;
+       size-=cnt;
+    }
+}
+
+static void ie2host ( struct ie_softc *sc, u_long src, void *dest, int size )
+{
+    int cnt;
+
+    if (size&1)
+       panic ( "ie2host" );
+
+    while ( size>0 ) {
+       cnt = IE_PAGESIZE - src % IE_PAGESIZE;
+       if ( cnt > size )
+           cnt = size;
+       setpage ( sc, src );
+       ReadShorts ( (char *)sc->sc_ram + IE_COFF2POFF(src), dest, cnt );
+       src+=cnt;
+       dest+=cnt;
+       size-=cnt;
+    }
+}
+
+/*
+ * Like a bzero or memset 0 for adapter memory.  It handles the page
+ * register so you dont have to worry about it
+ */
+
+static void iezero ( struct ie_softc *sc, u_long p, int size )
+{
+    int cnt;
+    while ( size > 0 ) {
+       cnt = IE_PAGESIZE - p % IE_PAGESIZE;
+       if ( cnt>size )
+           cnt=size;
+       setpage(sc, p);
+       bzero((char *)sc->sc_ram + IE_COFF2POFF(p), 2*cnt );
+       p += cnt;
+       size -= cnt;
+    }
+}
+
+/*
+ * I/O Control interface to the kernel, entry point here
+ */
+
+int ieioctl ( struct ifnet *ifp, u_long cmd, caddr_t data )
+{
+    struct ie_softc *sc = ie_cd.cd_devs[ifp->if_unit];
+    struct ifaddr *ifa = (struct ifaddr *)data;
+/*    struct ifreq *ifr = (struct ifreq *)data;*/
+    int s;
+    int error=0;
+
+    s=splimp();
+
+    switch ( cmd )
+    {
+       case SIOCSIFADDR:
+           ifp->if_flags |= IFF_UP;
+           switch ( ifa->ifa_addr->sa_family ) {
+#ifdef INET
+               case AF_INET:
+                   ieinit(sc);
+                   arp_ifinit(&sc->sc_arpcom, ifa );
+                   break;
+#endif
+               default:
+                   ieinit(sc);
+                   break;
+           }
+           break;
+
+#define IZSET(a,b) ((a->if_flags&b)!=0)
+#define IZCLR(a,b) ((a->if_flags&b)==0)
+#define DOSET(a,b) (a->if_flags|=b)
+#define DOCLR(a,b) (a->if_flags&=~b)
+
+       case SIOCSIFFLAGS:
+           sc->promisc = ifp->if_flags & ( IFF_PROMISC | IFF_ALLMULTI );
+
+           if ( IZCLR(ifp,IFF_UP) && IZSET(ifp,IFF_RUNNING) )
+           {
+               /* Interface was marked down and its running so stop it */
+               iestop(sc);
+               DOCLR(ifp,IFF_RUNNING);
+           }
+           else if ( IZSET(ifp,IFF_UP) && IZCLR(ifp,IFF_RUNNING) )
+           {
+               /* Just marked up and we're not running so start it */
+               ieinit(sc);
+           }
+           else
+           {
+               /* else reset to invoke changes in other registers */
+               iestop(sc);
+               ieinit(sc);
+            }
+
+       default:
+           error = EINVAL;
+    }
+    (void)splx(s);
+    return error;
+}
+
+/*
+ * Reset the card.  Completely.
+ */
+
+void iereset( struct ie_softc *sc )
+{
+    struct ie_sys_ctl_block scb;
+    int s = splimp();
+
+    iestop(sc);
+
+    ie2host ( sc, IE_IBASE + IE_SCB_OFF, &scb, sizeof scb );
+
+    if ( command_and_wait(sc, IE_RU_ABORT|IE_CU_ABORT, 0, 0, 0, 0, 0) )
+        printf ( "ie0: abort commands timed out\n" );
+
+    if ( command_and_wait(sc, IE_RU_DISABLE|IE_CU_STOP, 0, 0, 0, 0, 0) )
+        printf ( "ie0: abort commands timed out\n" );
+
+    ieinit(sc);
+
+    (void)splx(s);
+}
+
+/*
+ * Watchdog entry point.  This is the entry for the kernel to call us
+ */
+
+void iewatchdog ( int unit )
+{
+    struct ie_softc *sc = ie_cd.cd_devs[unit];
+
+    /* WOOF WOOF */
+    log(LOG_ERR, "%s: device timeout\n", sc->sc_dev.dv_xname );
+    ++sc->sc_arpcom.ac_if.if_oerrors;
+    iereset(sc);
+}
+
+/* 
+ * Start the time-domain-refloctometer running
+ */
+
+static void run_tdr ( struct ie_softc *sc )
+{
+    struct ie_sys_ctl_block scb;
+    u_long ptr = IE_IBASE + IE_SCB_OFF + sizeof scb;
+    struct ie_tdr_cmd cmd;
+    int result;
+
+    bzero ( &scb, sizeof(scb) );
+    bzero ( &cmd, sizeof(cmd) );
+
+    cmd.com.ie_cmd_status = 0;
+    cmd.com.ie_cmd_cmd = IE_CMD_TDR | IE_CMD_LAST;
+    cmd.com.ie_cmd_link = 0xffff;
+    cmd.ie_tdr_time = 0;
+
+    scb.ie_command_list = (u_short)ptr;
+
+    result=0;
+    if ( command_and_wait(sc, IE_CU_START, &scb, &cmd, ptr, sizeof cmd,
+       IE_STAT_COMPL) )
+    {
+           result = 0x10000;
+    }
+    else if ( !(cmd.com.ie_cmd_status & IE_STAT_OK) )
+    {
+       result = 0x10000;
+    }
+
+    if ( result==0 )
+       result = cmd.ie_tdr_time;
+
+    ie_ack ( sc, IE_ST_WHENCE );
+
+    if (result & IE_TDR_SUCCESS )
+       return;
+
+    /* Very messy.  I'll tidy it later */
+
+    if ( result & 0x10000 )
+    {
+       printf ( "ie: TDR command failed\n" );
+    }
+    else if ( result & IE_TDR_XCVR )
+    {
+       printf ( "ie: tranceiver problem. Is it plugged in?\n" );
+    }
+    else if ( result & IE_TDR_OPEN )
+    {
+       if ((result & IE_TDR_TIME)>0)
+           printf ( "ie: TDR detected an open %d clocks away.\n",
+                       result & IE_TDR_TIME );
+    }
+    else if ( result & IE_TDR_SHORT )
+    {
+       if ((result & IE_TDR_TIME)>0)
+           printf ( "ie: TDR detected a short %d clock away.\n",
+                       result & IE_TDR_TIME );
+    }
+    else
+    {
+       printf ( "ie: TDR returned unknown status %x\n", result );
+    }
+}
+
+u_long setup_rfa ( struct ie_softc *sc, u_long ptr )
+{
+    int i;
+    {
+       /* Receive frame descriptors */
+        struct ie_recv_frame_desc rfd;
+       bzero( &rfd, sizeof rfd );
+       for ( i=0; i<NFRAMES; i++ )
+       {
+           sc->rframes[i] = ptr;
+           rfd.ie_fd_next = ptr + sizeof rfd;
+           host2ie(sc, (char *)&rfd, ptr, sizeof rfd);
+           ptr += sizeof rfd;
+       }
+       rfd.ie_fd_next = sc->rframes[0];
+       rfd.ie_fd_last |= IE_FD_LAST;
+       host2ie(sc, (char *)&rfd, sc->rframes[NFRAMES-1], sizeof rfd );
+
+       ie2host(sc, sc->rframes[0], (char *)&rfd, sizeof rfd );
+       rfd.ie_fd_buf_desc = (u_short) ptr;
+       host2ie(sc, (char *)&rfd, sc->rframes[0], sizeof rfd );
+    }
+
+    {
+       /* Receive frame descriptors */
+       struct ie_recv_buf_desc rbd;
+       bzero(&rbd, sizeof rbd);
+       for ( i=0; i<NRXBUF; i++ )
+       {
+           sc->rbuffs[i] = ptr;
+           rbd.ie_rbd_length = IE_RXBUF_SIZE;
+           rbd.ie_rbd_buffer = (caddr_t)(ptr + sizeof rbd);
+           rbd.ie_rbd_next = (u_short)(ptr + sizeof rbd + IE_RXBUF_SIZE);
+           host2ie(sc, &rbd, ptr, sizeof rbd);
+           ptr+=sizeof rbd;
+
+           sc->cbuffs[i] = ptr;        
+           ptr+=IE_RXBUF_SIZE;
+       }
+       rbd.ie_rbd_next = sc->rbuffs[0];
+       rbd.ie_rbd_length |= IE_RBD_LAST;
+       host2ie(sc, &rbd, sc->rbuffs[NRXBUF-1], sizeof rbd);
+    }
+
+    sc->rfhead = 0;
+    sc->rftail = NFRAMES-1;
+    sc->rbhead = 0;
+    sc->rbtail = NRXBUF-1;
+
+    {
+       struct ie_sys_ctl_block scb;
+       bzero ( &scb, sizeof scb );
+       scb.ie_recv_list = (u_short)sc->rframes[0];
+       host2ie(sc, (char *)&scb, (IE_IBASE + IE_SCB_OFF), sizeof scb );
+    }
+    return ptr;
+}
+
+static void start_receiver ( struct ie_softc *sc )
+{
+    struct ie_sys_ctl_block scb;
+    ie2host ( sc, IE_IBASE + IE_SCB_OFF, &scb, sizeof scb );
+    scb.ie_recv_list = (u_short)sc->rframes[0];
+    command_and_wait(sc, IE_RU_START, &scb, 0, 0, 0, 0);
+    ie_ack(sc, IE_ST_WHENCE );
+}
+
+/*
+ * Take our configuration and update all the other data structures that
+ * require information from the driver.
+ *
+ * CALL AT SPLIMP OR HIGHER
+ */
+
+int ieinit ( struct ie_softc *sc )
+{
+    struct ie_sys_ctl_block scb;
+    struct ie_config_cmd cmd;
+    struct ie_iasetup_cmd iasetup_cmd;
+    u_long ptr = IE_IBASE + IE_SCB_OFF + sizeof scb;
+    int n;
+
+    bzero ( &scb, sizeof(scb) );
+
+    /* Send the configure command */
+
+    cmd.com.ie_cmd_status = 0;
+    cmd.com.ie_cmd_cmd = IE_CMD_CONFIG | IE_CMD_LAST;
+    cmd.com.ie_cmd_link = 0xffff;
+
+    cmd.ie_config_count = 0x0c;
+    cmd.ie_fifo = 8;
+    cmd.ie_save_bad = 0x40;
+    cmd.ie_addr_len = 0x2e;
+    cmd.ie_priority = 0;
+    cmd.ie_ifs = 0x60;
+    cmd.ie_slot_low = 0;
+    cmd.ie_slot_high = 0xf2;
+    cmd.ie_promisc = 0;                /* Hey nuts, look at this! */
+    cmd.ie_crs_cdt = 0;
+    cmd.ie_min_len = 64;
+    cmd.ie_junk = 0xff;
+
+    scb.ie_command_list = (u_short)ptr;
+
+    if ( command_and_wait(sc, IE_CU_START, &scb, &cmd, ptr, sizeof cmd,
+       IE_STAT_COMPL) )
+    {
+       printf ( "%s: command failed: timeout\n", sc->sc_dev.dv_xname );
+       return 0;
+    }
+
+    if ( !(cmd.com.ie_cmd_status & IE_STAT_OK) )
+    {
+       printf ( "%s: command failed: !IE_STAT_OK\n", sc->sc_dev.dv_xname );
+       return 0;
+    }
+
+    /* Individual address setup command */
+
+    iasetup_cmd.com.ie_cmd_status = 0;
+    iasetup_cmd.com.ie_cmd_cmd = IE_CMD_IASETUP | IE_CMD_LAST;
+    iasetup_cmd.com.ie_cmd_link = 0xffff;
+
+    bcopy ( sc->sc_arpcom.ac_enaddr, (caddr_t) &iasetup_cmd.ie_address,
+               sizeof (iasetup_cmd.ie_address) );
+
+    if ( command_and_wait(sc, IE_CU_START, &scb, &iasetup_cmd, ptr, sizeof cmd,
+       IE_STAT_COMPL) )
+    {
+       printf ( "%s: iasetup failed : timeout\n", sc->sc_dev.dv_xname );
+       return 0;
+    }
+
+    if ( !(cmd.com.ie_cmd_status & IE_STAT_OK) )
+    {
+       printf ( "%s: iasetup failed : !IE_STAT_OK\n", sc->sc_dev.dv_xname );
+       return 0;
+    }
+
+    ie_ack ( sc, IE_ST_WHENCE );
+
+    /* Run the time-domain refloctometer */
+    run_tdr ( sc );
+
+    ie_ack ( sc, IE_ST_WHENCE );
+
+    /* meminit */
+    ptr = setup_rfa(sc, ptr);
+
+    sc->sc_arpcom.ac_if.if_flags |= IFF_RUNNING;
+    sc->sc_arpcom.ac_if.if_flags &= ~IFF_OACTIVE;
+
+    /* Setup transmit buffers */
+
+    for ( n=0; n<NTXBUF; n++ ) {
+       sc->xmit_cmds[n] = ptr;
+       iezero(sc, ptr, sizeof(struct ie_xmit_cmd) );
+       ptr += sizeof(struct ie_xmit_cmd);
+
+       sc->xmit_buffs[n] = ptr;
+       iezero(sc, ptr, sizeof(struct ie_xmit_buf));
+       ptr += sizeof(struct ie_xmit_buf);
+    }
+
+    for ( n=0; n<NTXBUF; n++ ) {
+       sc->xmit_cbuffs[n] = ptr;
+       ptr += IE_TXBUF_SIZE;
+    }
+
+    sc->xmit_free = NTXBUF;
+    sc->xchead = sc->xctail = 0;
+
+    {
+       struct ie_xmit_cmd xmcmd;
+       bzero ( &xmcmd, sizeof xmcmd );
+       xmcmd.ie_xmit_status = IE_STAT_COMPL;
+       host2ie(sc, &xmcmd, sc->xmit_cmds[0], sizeof xmcmd);
+    }
+
+    start_receiver (sc);
+
+    return 0;
+}
+
+int iestop ( struct ie_softc *sc )
+{
+    struct ie_sys_ctl_block scb;
+    int s = splimp();
+
+    ie2host ( sc, IE_IBASE + IE_SCB_OFF, &scb, sizeof scb );
+
+    if ( command_and_wait(sc, IE_RU_DISABLE, &scb, 0, 0, 0, 0) )
+        printf ( "ie0: abort commands timed out\n" );
+
+    (void)splx(s);
+    return(0);
+}
+
+/*
+ * Send a command to the card and awaits it's completion.
+ * Timeout if it's taking too long
+ */
+
+/*CAW*/
+
+static int command_and_wait ( struct ie_softc *sc, u_short cmd,
+                             struct ie_sys_ctl_block *pscb,
+                             void *pcmd, int ocmd, int scmd, int mask )
+{
+    int i=0;
+
+    /* Copy the command to the card */
+
+    if ( pcmd )
+       host2ie(sc, pcmd, ocmd, scmd); /* transfer the command to the card */
+
+    /* Copy the scb to the card */
+
+    if ( pscb ) {
+       pscb->ie_command = cmd;
+       host2ie(sc, pscb, IE_IBASE + IE_SCB_OFF, sizeof *pscb);
+    }
+    else
+    {
+       setpage ( sc, IE_IBASE + IE_SCB_OFF );
+       PWriteShort ( sc->sc_ram + IE_COFF2POFF(IE_IBASE+IE_SCB_OFF) +
+               (offsetof(struct ie_sys_ctl_block, ie_command)), cmd );
+    }
+
+    /* Prod the card to act on the newly loaded command */
+    ieattn(sc);
+
+    /* Wait for the command to complete */
+    if ( IE_ACTION_COMMAND(cmd) && pcmd )
+    {
+       setpage(sc,ocmd);
+       for ( i=4000; --i>=0; ) {
+           if ( ReadShort(sc->sc_ram + IE_COFF2POFF(ocmd) +
+               (offsetof(struct ie_config_cmd, ie_config_status))) & mask)
+               break;
+           delay(100);
+       }
+    }
+    else
+    {
+       for ( i=4000; --i>=0; ) {
+           if ( !ReadShort(sc->sc_ram + IE_COFF2POFF(IE_IBASE+IE_SCB_OFF) +
+               (offsetof(struct ie_sys_ctl_block, ie_command))) )
+               break;
+           delay(100);
+       }
+    }
+
+    /* Update the host structures to reflect the state on the card */
+    if ( pscb )
+       ie2host(sc, IE_IBASE + IE_SCB_OFF, pscb, sizeof *pscb );
+    if ( pcmd )
+       ie2host(sc, ocmd, pcmd, scmd);
+
+    return i < 0;
+}
+
+#define READ_MEMBER(sc,type,member,ptr,dest)                   \
+       setpage(sc, ptr);                                       \
+       dest = ReadShort(sc->sc_ram + IE_COFF2POFF(ptr) +       \
+              (offsetof(type, member)) );
+
+#define WRITE_MEMBER(sc,type,member,ptr,dest)                  \
+       setpage(sc, ptr);                                       \
+       PWriteShort(sc->sc_ram + IE_COFF2POFF(ptr) +    \
+              (offsetof(type, member)), dest );
+
+static inline int ie_buflen ( struct ie_softc *sc, int head )
+{
+   int actual;
+   READ_MEMBER(sc,struct ie_recv_buf_desc, ie_rbd_actual,
+               sc->rbuffs[head], actual );
+
+   return ( actual & ( IE_RXBUF_SIZE | ( IE_RXBUF_SIZE-1 ) ) ) ;
+}
+
+static inline int ie_packet_len ( struct ie_softc *sc )
+{
+    int i;
+    int actual;
+    int head = sc->rbhead;
+    int acc=0;
+
+    do {
+       READ_MEMBER(sc,struct ie_recv_buf_desc, ie_rbd_actual,
+                       sc->rbuffs[sc->rbhead], actual );
+       if (!(actual&IE_RBD_USED))
+       {
+           return (-1);
+       }
+
+       READ_MEMBER(sc,struct ie_recv_buf_desc, ie_rbd_actual,
+                       sc->rbuffs[head], i );
+        i = i & IE_RBD_LAST;
+
+       acc += ie_buflen(sc, head);
+       head = (head+1) % NRXBUF;
+    } while (!i);
+
+    return acc;
+}
+
+struct mbuf *ieget(struct ie_softc *sc, struct ether_header *ehp, int *to_bpf )
+{
+    struct mbuf *top, **mp, *m;
+    int head;
+    int resid, totlen, thisrboff, thismboff;
+    int len;
+
+    totlen = ie_packet_len(sc);
+
+    if ( totlen > ETHER_MAX_LEN )
+    {
+       printf ( "ie: Gosh that packet was s-o-o-o big.\n" );
+       return 0;
+    }
+
+    if ( totlen<=0 )
+       return 0;
+
+    head = sc->rbhead;
+
+    /* Read the ethernet header */
+    ie2host ( sc, sc->cbuffs[head], (caddr_t)ehp, sizeof *ehp );
+
+    /* Check if the packet is for us */
+
+    resid = totlen -= (thisrboff = sizeof *ehp);
+
+    MGETHDR ( m, M_DONTWAIT, MT_DATA );
+    if ( m==0 )
+       return 0;
+
+    m->m_pkthdr.rcvif = &sc->sc_arpcom.ac_if;
+    m->m_pkthdr.len = totlen;
+    len = MHLEN;
+    top = 0;
+    mp = &top;
+
+    /*
+     * This loop goes through and allocates mbufs for all the data we will
+     * be copying in.  It does not actually do the copying yet.
+     */
+    while (totlen > 0) {
+       if (top) {
+           MGET(m, M_DONTWAIT, MT_DATA);
+           if (m == 0) {
+               m_freem(top);
+               return 0;
+           }
+           len = MLEN;
+       }
+       if (totlen >= MINCLSIZE) {
+           MCLGET(m, M_DONTWAIT);
+           if (m->m_flags & M_EXT)
+               len = MCLBYTES;
+       }
+        m->m_len = len = min(totlen, len);
+        totlen -= len;
+        *mp = m;
+        mp = &m->m_next;
+    }
+
+    m = top;
+    thismboff = 0;
+
+    /*
+     * Now we take the mbuf chain (hopefully only one mbuf most of the
+     * time) and stuff the data into it.  There are no possible failures at
+     * or after this point.
+     */
+    while (resid > 0) {
+       int thisrblen = ie_buflen(sc, head) - thisrboff,
+           thismblen = m->m_len - thismboff;
+       len = min(thisrblen, thismblen);
+
+/*      bcopy((caddr_t)(sc->cbuffs[head] + thisrboff),
+           mtod(m, caddr_t) + thismboff, (u_int)len);   */
+
+
+       if ( len&1 )
+       {
+           ie2host(sc, sc->cbuffs[head]+thisrboff,
+               mtod(m, caddr_t) + thismboff, (u_int)len+1);
+       }
+       else
+       {
+           ie2host(sc, sc->cbuffs[head]+thisrboff,
+               mtod(m, caddr_t) + thismboff, (u_int)len);
+       }
+
+       resid -= len;
+
+       if (len == thismblen) {
+               m = m->m_next;
+               thismboff = 0;
+       } else
+               thismboff += len;
+
+       if (len == thisrblen) {
+               head = (head + 1) % NRXBUF;
+               thisrboff = 0;
+       } else
+               thisrboff += len;
+    }
+
+
+    return top;
+}
+
+void ie_drop_packet_buffer ( struct ie_softc *sc )
+{
+    int i, actual, last;
+
+    do {
+       READ_MEMBER(sc,struct ie_recv_buf_desc, ie_rbd_actual,
+                       sc->rbuffs[sc->rbhead], actual );
+       if (!(actual&IE_RBD_USED))
+       {
+           iereset(sc);
+           return;
+       }
+
+       i = actual & IE_RBD_LAST;
+
+        READ_MEMBER(sc,struct ie_recv_buf_desc,ie_rbd_length,
+                       sc->rbuffs[sc->rbhead], last );
+        last |= IE_RBD_LAST;
+        WRITE_MEMBER(sc,struct ie_recv_buf_desc,ie_rbd_length,
+                       sc->rbuffs[sc->rbhead], last );
+
+        WRITE_MEMBER(sc,struct ie_recv_buf_desc,ie_rbd_actual,
+                       sc->rbuffs[sc->rbhead], 0 );
+
+       sc->rbhead = ( sc->rbhead + 1 ) % NRXBUF;
+
+        READ_MEMBER(sc,struct ie_recv_buf_desc,ie_rbd_length,
+                       sc->rbuffs[sc->rbtail], last );
+        last &= ~IE_RBD_LAST;
+        WRITE_MEMBER(sc,struct ie_recv_buf_desc,ie_rbd_length,
+                       sc->rbuffs[sc->rbtail], last );
+
+       sc->rbtail = ( sc->rbtail + 1 ) % NRXBUF;
+    } while (!i);
+}
+
+void ie_read_frame ( struct ie_softc *sc, int num )
+{
+    int status;
+    struct ie_recv_frame_desc rfd;
+    struct mbuf *m=0;
+    struct ether_header eh;
+    int last;
+
+    ie2host(sc, sc->rframes[num], &rfd, sizeof rfd );
+    status = rfd.ie_fd_status;
+
+    /* Advance the RFD list, since we're done with this descriptor */
+
+    WRITE_MEMBER(sc,struct ie_recv_frame_desc,ie_fd_status,
+                       sc->rframes[num], 0 );
+
+    READ_MEMBER(sc,struct ie_recv_frame_desc,ie_fd_last,
+                       sc->rframes[num], last );
+    last |= IE_FD_LAST;
+    WRITE_MEMBER(sc,struct ie_recv_frame_desc,ie_fd_last,
+                       sc->rframes[num], last );
+
+    READ_MEMBER(sc,struct ie_recv_frame_desc,ie_fd_last,
+                       sc->rframes[sc->rftail], last );
+    last &= ~IE_FD_LAST;
+    WRITE_MEMBER(sc,struct ie_recv_frame_desc,ie_fd_last,
+                       sc->rframes[sc->rftail], last );
+
+    sc->rftail = ( sc->rftail + 1 ) % NFRAMES;
+    sc->rfhead = ( sc->rfhead + 1 ) % NFRAMES;
+
+    if ( status & IE_FD_OK ) {
+       m = ieget(sc, &eh, 0);
+       ie_drop_packet_buffer(sc);
+    }
+
+    if ( m==0 ) {
+       sc->sc_arpcom.ac_if.if_ierrors++;
+       return;
+    }
+
+/*
+    printf ( "%s: frame from ether %s type %x\n", sc->sc_dev.dv_xname,
+               ether_sprintf(eh.ether_shost), (u_int)eh.ether_type );
+*/
+
+#if NBFILTER > 0
+    if ( sc->sc_arpcom.ac_if.if_bpf ) {
+       bpf_mtap(sc->sc_arpcom.ac_if.if_bpf, m );
+    };
+#endif
+
+    ether_input ( &sc->sc_arpcom.ac_if, &eh, m );
+    sc->sc_arpcom.ac_if.if_ipackets++;
+}
+
+void ierint ( struct ie_softc *sc )
+{
+    int i;
+    int times_thru = 1024;
+    struct ie_sys_ctl_block scb;
+    int status;
+    int saftey_catch = 0;
+
+    i = sc->rfhead;
+    for (;;) {
+
+       if ( (saftey_catch++)>100 )
+       {
+           printf ( "ie: ierint saftey catch tripped\n" );
+           iereset(sc);
+           return;
+       }
+
+       READ_MEMBER(sc,struct ie_recv_frame_desc,ie_fd_status,
+                               sc->rframes[i],status);
+
+       if ((status&IE_FD_COMPLETE)&&(status&IE_FD_OK)) {
+           if ( !--times_thru ) {
+               printf ( "IERINT: Uh oh. Nuts, look at this bit!!!\n" );
+               ie2host ( sc, IE_IBASE + IE_SCB_OFF, &scb, sizeof scb );
+               sc->sc_arpcom.ac_if.if_ierrors += scb.ie_err_crc +
+                                                 scb.ie_err_align +
+                                                 scb.ie_err_resource +
+                                                 scb.ie_err_overrun;
+               scb.ie_err_crc      = scb.ie_err_align   = 0;
+               scb.ie_err_resource = scb.ie_err_overrun = 0;
+               host2ie(sc, &scb, IE_SCP_ADDR, sizeof (scb) );
+           }
+           ie_read_frame(sc, i);
+       } else {
+           ie2host ( sc, IE_IBASE + IE_SCB_OFF, &scb, sizeof scb );
+
+           if ( ((status&IE_FD_RNR)!=0) && ((scb.ie_status&IE_RU_READY)==0) )
+           {
+               WRITE_MEMBER(sc,struct ie_recv_frame_desc, ie_fd_buf_desc,
+                               sc->rframes[0], sc->rbuffs[0] );
+
+               scb.ie_recv_list = sc->rframes[0];
+               host2ie(sc, (char *)&scb, IE_IBASE + IE_SCB_OFF, sizeof (scb) );
+               command_and_wait(sc, IE_RU_START, &scb, 0, 0, 0, 0);
+           }
+           break;
+       }
+       i = (i + 1) % NFRAMES;
+    }
+}
+
+static int in_intr = 0;
+
+int ieintr ( void *arg )
+{
+    struct ie_softc *sc = arg;
+    u_short status;
+    int saftey_catch = 0;
+    static saftey_net = 0;
+
+    if ( in_intr==1 )
+    {
+       panic ( "ie: INTERRUPT REENTERED\n" );
+    }
+
+    /* Clear the interrrupt */
+    ie_cli (sc);
+
+    setpage(sc, IE_IBASE + IE_SCB_OFF );
+    status = ReadShort ( sc->sc_ram + IE_COFF2POFF(IE_IBASE+IE_SCB_OFF) +
+               (offsetof(struct ie_sys_ctl_block, ie_status)) );
+
+    status = status & IE_ST_WHENCE;
+
+    if ( status==0 )
+    {
+       in_intr = 0;
+       return 0;
+    }
+
+loop:
+
+    ie_ack(sc, status);
+
+    if (status & (IE_ST_FR | IE_ST_RNR)) {
+       ierint(sc);
+    }
+
+    if (status & IE_ST_CX) {
+       ietint(sc);
+    }
+
+    if (status & IE_ST_RNR) {
+       printf ( "ie: receiver not ready\n" );
+       sc->sc_arpcom.ac_if.if_ierrors++;
+       iereset(sc);
+    }
+
+    setpage(sc, IE_IBASE + IE_SCB_OFF );
+    status = ReadShort ( sc->sc_ram + IE_COFF2POFF(IE_IBASE+IE_SCB_OFF) +
+               (offsetof(struct ie_sys_ctl_block, ie_status)) );
+    status = status & IE_ST_WHENCE;
+
+    ie_cli(sc);
+
+    if ( status==0 )
+    {
+       in_intr = 0;
+       return 1;
+    }
+
+    /* This is prehaps a little over cautious */
+    if ( saftey_catch++ > 10 )
+    {
+       printf ( "ie: Interrupt couldn't be cleared\n" );
+       delay ( 1000 );
+       ie_cli(sc);
+       if ( saftey_net++ > 50 )
+       {
+           printf ( "ie: saftey net catches driver, shutting down\n" );
+           disable_irq ( IRQ_PODULE );
+       }
+       in_intr = 0;
+       return 1;
+    }
+
+    goto loop;
+}
+
+void iexmit ( struct ie_softc *sc )
+{
+/*    int actual;*/
+    struct ie_sys_ctl_block scb;
+
+    struct ie_xmit_cmd xc;
+    struct ie_xmit_buf xb;
+    
+    ie2host(sc, sc->xmit_buffs[sc->xctail], (char *)&xb, sizeof xb );
+    xb.ie_xmit_flags |= IE_XMIT_LAST;
+    xb.ie_xmit_next = 0xffff;
+    xb.ie_xmit_buf = (caddr_t)sc->xmit_cbuffs[sc->xctail];
+    host2ie(sc, &xb, sc->xmit_buffs[sc->xctail], sizeof xb );
+
+    bzero ( &xc, sizeof xc );
+    xc.com.ie_cmd_link = 0xffff;
+    xc.com.ie_cmd_cmd = IE_CMD_XMIT | IE_CMD_INTR | IE_CMD_LAST;
+    xc.ie_xmit_status = 0x0000;
+    xc.ie_xmit_desc = sc->xmit_buffs[sc->xctail];
+    host2ie(sc, (char *)&xc, sc->xmit_cmds[sc->xctail], sizeof xc );
+
+    ie2host ( sc, IE_IBASE + IE_SCB_OFF, &scb, sizeof scb );
+    scb.ie_command_list = sc->xmit_cmds[sc->xctail];
+    host2ie(sc, (char *)&scb, (IE_IBASE + IE_SCB_OFF), sizeof scb );
+
+    command_and_wait(sc, IE_CU_START, &scb, &xc, sc->xmit_cmds[sc->xctail]
+                       , sizeof xc, IE_STAT_COMPL);
+
+    sc->sc_arpcom.ac_if.if_timer = 5;
+}
+/*
+ * Start sending all the queued buffers.
+ */
+
+void iestart( struct ifnet *ifp )
+{
+       struct ie_softc *sc = ie_cd.cd_devs[ifp->if_unit];
+       struct mbuf *m0, *m;
+       u_char *buffer;
+       u_short len;
+       char txbuf[IE_TXBUF_SIZE];
+       int saftey_catch = 0;
+
+       if ((ifp->if_flags & IFF_OACTIVE) != 0)
+               return;
+
+       for (;;) {
+               if ( (saftey_catch++)>100 )
+               {
+                   printf ( "ie: iestart saftey catch tripped\n" );
+                   iereset(sc);
+                   return;
+               }
+               if (sc->xmit_free == 0) {
+                       ifp->if_flags |= IFF_OACTIVE;
+                       break;
+               }
+
+               IF_DEQUEUE(&sc->sc_arpcom.ac_if.if_snd, m);
+               if (!m)
+                       break;
+
+               /* TODO: Write directly to the card */
+               len = 0;
+               /* buffer = sc->xmit_cbuffs[sc->xchead]; */
+               buffer = txbuf;
+
+               for (m0 = m; m && (len + m->m_len) < IE_TXBUF_SIZE;
+                    m = m->m_next) {
+                       bcopy(mtod(m, caddr_t), buffer, m->m_len);
+                       buffer += m->m_len;
+                       len += m->m_len;
+               }
+
+               m_freem(m0);
+               len = max(len, ETHER_MIN_LEN);
+
+#if NBPFILTER > 0
+               if ( sc->sc_arpcom.ac_if.if_bpf )
+                   bpf_tap(sc->sc_arpcom.ac_if.if_bpf, txbuf, len);
+#endif
+
+               /* When we write directly to the card we dont need this */
+               if (len&1)
+                   host2ie(sc, txbuf, sc->xmit_cbuffs[sc->xchead], len+1 );
+               else
+                   host2ie(sc, txbuf, sc->xmit_cbuffs[sc->xchead], len );
+
+               /* sc->xmit_buffs[sc->xchead]->ie_xmit_flags = len; */
+               
+               WRITE_MEMBER(sc,struct ie_xmit_buf, ie_xmit_flags,
+                               sc->xmit_buffs[sc->xchead], len)
+
+               /* Start the first packet transmitting. */
+               if (sc->xmit_free == NTXBUF)
+                       iexmit(sc);
+
+               sc->xchead = (sc->xchead + 1) % NTXBUF;
+               sc->xmit_free--;
+       }
+}
+
+void ietint ( struct ie_softc *sc )
+{
+    struct ifnet *ifp = &sc->sc_arpcom.ac_if;
+
+    int status;
+
+    ifp->if_timer=0;
+    ifp->if_flags &= ~IFF_OACTIVE;
+    READ_MEMBER(sc,struct ie_xmit_cmd, ie_xmit_status,
+       sc->xmit_cmds[sc->xctail], status );
+
+    if (!(status&IE_STAT_COMPL) || (status & IE_STAT_BUSY) )
+       printf ( "ietint: command still busy!\n" );
+    
+    if ( status & IE_STAT_OK ) {
+       ifp->if_opackets++;
+       ifp->if_collisions += status & IE_XS_MAXCOLL;
+    } else {
+       ifp->if_oerrors++;      
+       if ( status & IE_STAT_ABORT )
+           printf ( "ie: send aborted\n" );
+       if ( status & IE_XS_LATECOLL )
+           printf ( "ie: late collision\n" );
+       if ( status & IE_XS_NOCARRIER )
+           printf ( "ie: no carrier\n" );
+       if ( status & IE_XS_LOSTCTS )
+           printf ( "ie: lost CTS\n" );
+       if ( status & IE_XS_UNDERRUN )
+           printf ( "ie: DMA underrun\n" );
+       if ( status & IE_XS_EXCMAX )
+           printf ( "ie: too many collisions\n" );
+       ifp->if_collisions+=16;
+    }
+    /* Done with the buffer */
+    sc->xmit_free++;
+    sc->xctail = (sc->xctail + 1 ) % NTXBUF;
+    /* Start the next packet transmitting, if any */
+    if ( sc->xmit_free<NTXBUF )
+       iexmit(sc);
+
+    iestart(ifp);
+}
+
+
+/* End of if_ie.c */
diff --git a/sys/arch/arm32/podulebus/if_iereg.h b/sys/arch/arm32/podulebus/if_iereg.h
new file mode 100644 (file)
index 0000000..cf3ad61
--- /dev/null
@@ -0,0 +1,53 @@
+/* $NetBSD: if_iereg.h,v 1.2 1996/03/18 21:23:16 mark Exp $ */
+
+/*
+ * Copyright (C) 1994 Wolfgang Solfrank.
+ * Copyright (C) 1994 TooLs GmbH.
+ * 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 TooLs GmbH.
+ * 4. The name of TooLs GmbH may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#define        IE_PAGE         0
+
+#define        IE_CONTROL      1
+#define        IE_CONT_RESET   1
+#define        IE_CONT_LOOP    2
+#define        IE_CONT_ATTN    4
+#define        IE_CONT_CLI     8
+
+#define        IE_MEMSIZE      65536
+#define        IE_PAGESIZE     4096
+#define        IE_MEMOFF       0x2000
+#define        IE_COFF2POFF(off)       ((off) % IE_PAGESIZE * 2)
+#define        IE_COFF2PAGE(off)       (((off) % IE_MEMSIZE) / IE_PAGESIZE)
+
+#define        IE_ISCP_ADDR    (IE_SCP_ADDR - sizeof(struct ie_int_sys_conf_ptr))
+#define        IE_IBASE        (0x1000000 - IE_MEMSIZE)
+#define        IE_SCB_OFF      0
+
+/* Steal most defines from PC driver: */
+#include <dev/ic/i82586reg.h>
diff --git a/sys/arch/arm32/podulebus/ncr5380reg.h b/sys/arch/arm32/podulebus/ncr5380reg.h
new file mode 100644 (file)
index 0000000..04b181d
--- /dev/null
@@ -0,0 +1,160 @@
+/*     $NetBSD: ncr5380reg.h,v 1.1 1996/01/31 23:26:04 mark Exp $      */
+
+/* 
+ * Mach Operating System
+ * Copyright (c) 1991,1990,1989 Carnegie Mellon University
+ * All Rights Reserved.
+ * 
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ * 
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS 
+ * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ * 
+ * Carnegie Mellon requests users of this software to return to
+ * 
+ *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
+ *  School of Computer Science
+ *  Carnegie Mellon University
+ *  Pittsburgh PA 15213-3890
+ * 
+ * any improvements or extensions that they make and grant Carnegie the
+ * rights to redistribute these changes.
+ */
+/*
+ * HISTORY (mach3)
+ * Revision 2.3  91/08/24  12:25:10  af
+ *     Moved padding of regmap in impl file.
+ *     [91/08/02  04:22:39  af]
+ * 
+ * Revision 2.2  91/06/19  16:28:35  rvb
+ *     From the NCR data sheets
+ *     "NCR 5380 Family, SCSI Protocol Controller Data Manual"
+ *     NCR Microelectronics Division, Colorado Spring, 6/98 T01891L
+ *     [91/04/21            af]
+ * 
+ */
+
+/*
+ *     File: scsi_5380.h
+ *     Author: Alessandro Forin, Carnegie Mellon University
+ *     Date:   5/91
+ *
+ *     Defines for the NCR 5380 (SCSI chip), aka Am5380
+ */
+
+/*
+ * Register map:  Note not declared here anymore!
+ * All the 5380 registers are accessed through individual
+ * pointers initialized by MD code.  This allows the 5380
+ * MI functions to be shared between MD drivers that have
+ * different padding between the registers (i.e. amiga).
+ */
+#if 0  /* example only */
+struct ncr5380regs {
+       volatile u_char sci_r0;
+       volatile u_char sci_r1;
+       volatile u_char sci_r2;
+       volatile u_char sci_r3;
+       volatile u_char sci_r4;
+       volatile u_char sci_r5;
+       volatile u_char sci_r6;
+       volatile u_char sci_r7;
+};
+#endif
+
+/*
+ * Machine-independent code uses these names:
+ */
+#define        sci_data        sci_r0  /* r:  Current data */
+#define        sci_odata       sci_r0  /* w:  Out data */
+
+#define        sci_icmd        sci_r1  /* rw: Initiator command */
+#define        sci_mode        sci_r2  /* rw: Mode */
+#define        sci_tcmd        sci_r3  /* rw: Target command */
+
+#define        sci_bus_csr     sci_r4  /* r:  Bus Status */
+#define sci_sel_enb sci_r4     /* w:  Select enable */
+
+#define        sci_csr          sci_r5 /* r:  Status */
+#define sci_dma_send sci_r5    /* w:  Start dma send data */
+
+#define        sci_idata       sci_r6  /* r:  Input data */
+#define        sci_trecv       sci_r6  /* w:  Start dma receive, target */
+
+#define        sci_iack        sci_r7  /* r:  Interrupt Acknowledge  */
+#define sci_irecv      sci_r7  /* w:  Start dma receive, initiator */
+
+
+/*
+ * R1: 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 */
+/* Bits to keep when doing read/modify/write (leave out RST) */
+#define SCI_ICMD_RMASK         0x1F
+
+
+/*
+ * R2: 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 */
+
+
+/*
+ * R3: 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_TCMD_PHASE(x)               ((x) & 0x7)
+
+/*
+ * R4: Current (SCSI) Bus status (.sci_bus_csr)
+ */
+#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_BUS_PHASE(x)        (((x) >> 2) & 7)
+
+/*
+ * R5: Bus and Status register (.sci_csr)
+ */
+#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 */
diff --git a/sys/arch/arm32/podulebus/ncr5380sbc.c b/sys/arch/arm32/podulebus/ncr5380sbc.c
new file mode 100644 (file)
index 0000000..9758419
--- /dev/null
@@ -0,0 +1,2591 @@
+/*     $NetBSD: ncr5380sbc.c,v 1.2 1996/03/27 22:05:19 mark Exp $      */
+
+/*
+ * Copyright (c) 1996 Melvin Tang-Richardson (Modified for weird regs)
+ * Copyright (c) 1995 David Jones, Gordon W. Ross
+ * Copyright (c) 1994 Jarle Greipsland
+ * 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 authors may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ * 4. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *      This product includes software developed by
+ *      David Jones and Gordon Ross
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#undef DIAGNOSTIC
+
+/*
+ * This is a machine-independent driver for the NCR5380
+ * SCSI Bus Controller (SBC), also known as the Am5380.
+ *
+ * This code should work with any memory-mapped 5380,
+ * and can be shared by multiple adapters that address
+ * the 5380 with different register offset spacings.
+ * (This can happen on the atari, for example.)
+ * For porting/design info. see: ncr5380.doc
+ *
+ * Credits, history:
+ *
+ * David Jones is the author of most of the code that now
+ * appears in this file, and was the architect of the
+ * current overall structure (MI/MD code separation, etc.)
+ *
+ * Gordon Ross integrated the message phase code, added lots of
+ * comments about what happens when and why (re. SCSI spec.),
+ * debugged some reentrance problems, and added several new
+ * "hooks" needed for the Sun3 "si" adapters.
+ *
+ * The message in/out code was taken nearly verbatim from
+ * the aic6360 driver by Jarle Greipsland.
+ *
+ * Several other NCR5380 drivers were used for reference
+ * while developing this driver, including work by:
+ *   The Alice Group (mac68k port) namely:
+ *       Allen K. Briggs, Chris P. Caputo, Michael L. Finch,
+ *       Bradley A. Grantham, and Lawrence A. Kesteloot
+ *   Michael L. Hitch (amiga drivers: sci.c)
+ *   Leo Weppelman (atari driver: ncr5380.c)
+ * There are others too.  Thanks, everyone.
+ */
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/errno.h>
+#include <sys/device.h>
+#include <sys/buf.h>
+#include <sys/proc.h>
+#include <sys/user.h>
+
+#include <scsi/scsi_all.h>
+#include <scsi/scsi_debug.h>
+#include <scsi/scsi_message.h>
+#include <scsi/scsiconf.h>
+
+#define DEBUG XXX
+
+#define SetReg(l,d) *((volatile unsigned int *)((void *)l))=((d)|(((d)<<16)))
+
+#if 0  /* XXX - not yet... */
+#include <dev/ic/ncr5380reg.h>
+#include <dev/ic/ncr5380var.h>
+#else
+#include "ncr5380reg.h"
+#include "ncr5380var.h"
+#endif
+
+static int     ncr5380_wait_req __P((struct ncr5380_softc *));
+static int     ncr5380_wait_not_req __P((struct ncr5380_softc *));
+
+static void    ncr5380_sched __P((struct ncr5380_softc *));
+static void    ncr5380_done __P((struct ncr5380_softc *));
+
+static int     ncr5380_select
+       __P((struct ncr5380_softc *, struct sci_req *));
+static void    ncr5380_reselect __P((struct ncr5380_softc *));
+
+static int     ncr5380_msg_in __P((struct ncr5380_softc *));
+static int     ncr5380_msg_out __P((struct ncr5380_softc *));
+static int     ncr5380_data_xfer __P((struct ncr5380_softc *, int));
+static int     ncr5380_command __P((struct ncr5380_softc *));
+static int     ncr5380_status __P((struct ncr5380_softc *));
+static void    ncr5380_machine __P((struct ncr5380_softc *));
+
+/*
+ * Action flags returned by the info_tranfer functions:
+ * (These determine what happens next.)
+ */
+#define ACT_CONTINUE   0x00    /* No flags: expect another phase */
+#define ACT_DISCONNECT 0x01    /* Target is disconnecting */
+#define ACT_CMD_DONE   0x02    /* Need to call scsi_done() */
+#define ACT_RESET_BUS  0x04    /* Need bus reset (cmd timeout) */
+#define ACT_WAIT_DMA   0x10    /* Wait for DMA to complete */
+
+/*****************************************************************
+ * Debugging stuff
+ *****************************************************************/
+
+#ifndef DDB
+/* This is used only in recoverable places. */
+#define Debugger() printf("Debug: ncr5380.c:%d\n", __LINE__)
+#endif
+
+#ifdef DEBUG
+
+#define        NCR_DBG_BREAK   1
+#define        NCR_DBG_CMDS    2
+int ncr5380_debug = NCR_DBG_BREAK;
+#define        NCR_BREAK() \
+       do { if (ncr5380_debug & NCR_DBG_BREAK) Debugger(); } while (0)
+static void ncr5380_show_scsi_cmd __P((struct scsi_xfer *));
+static void ncr5380_show_sense __P((struct scsi_xfer *));
+#else  /* DEBUG */
+#define        NCR_BREAK()             /* nada */
+#define ncr5380_show_scsi_cmd(xs) /* nada */
+#define ncr5380_show_sense(xs) /* nada */
+#endif /* DEBUG */
+
+static char *
+phase_names[8] = {
+       "DATA_OUT",
+       "DATA_IN",
+       "COMMAND",
+       "STATUS",
+       "UNSPEC1",
+       "UNSPEC2",
+       "MSG_OUT",
+       "MSG_IN",
+};
+
+/*****************************************************************
+ * Actual chip control
+ *****************************************************************/
+
+/*
+ * XXX: These timeouts might need to be tuned...
+ */
+
+/* This one is used when waiting for a phase change. (X100uS.) */
+int ncr5380_wait_phase_timo = 1000 * 10 * 300; /* 5 min. */
+
+/* These are used in the following inline functions. */
+int ncr5380_wait_req_timo = 1000 * 50; /* X2 = 100 mS. */
+int ncr5380_wait_nrq_timo = 1000 * 25; /* X2 =  50 mS. */
+
+/* Return zero on success. */
+static __inline__ int ncr5380_wait_req(sc)
+       struct ncr5380_softc *sc;
+{
+       register int timo = ncr5380_wait_req_timo;
+       for (;;) {
+               if (*sc->sci_bus_csr & SCI_BUS_REQ) {
+                       timo = 0;       /* return 0 */
+                       break;
+               }
+               if (--timo < 0)
+                       break;  /* return -1 */
+               delay(2);
+       }
+       return (timo);
+}
+
+/* Return zero on success. */
+static __inline__ int ncr5380_wait_not_req(sc)
+       struct ncr5380_softc *sc;
+{
+       register int timo = ncr5380_wait_nrq_timo;
+       for (;;) {
+               if ((*sc->sci_bus_csr & SCI_BUS_REQ) == 0) {
+                       timo = 0;       /* return 0 */
+                       break;
+               }
+               if (--timo < 0)
+                       break;  /* return -1 */
+               delay(2);
+       }
+       return (timo);
+}
+
+/* Ask the target for a MSG_OUT phase. */
+static __inline__ void
+ncr_sched_msgout(sc, msg_code)
+       struct ncr5380_softc *sc;
+       int msg_code;
+{
+       /* First time, raise ATN line. */
+       if (sc->sc_msgpriq == 0) {
+               register u_char icmd;
+               icmd = *sc->sci_icmd & SCI_ICMD_RMASK;
+               SetReg ( sc->sci_icmd, icmd | SCI_ICMD_ATN );
+/*             *sc->sci_icmd = icmd | SCI_ICMD_ATN; */
+               delay(2);
+       }
+       sc->sc_msgpriq |= msg_code;
+}
+
+
+int
+ncr5380_pio_out(sc, phase, count, data)
+       struct ncr5380_softc *sc;
+       int phase, count;
+       unsigned char           *data;
+{
+       register u_char         icmd;
+       register int            resid;
+       register int            error;
+
+       icmd = *(sc->sci_icmd) & SCI_ICMD_RMASK;
+
+       icmd |= SCI_ICMD_DATA;
+       SetReg ( sc->sci_icmd, icmd );
+/*     *sc->sci_icmd = icmd; */
+
+       resid = count;
+       while (resid > 0) {
+               if (!SCI_BUSY(sc)) {
+                       NCR_TRACE("pio_out: lost BSY, resid=%d\n", resid);
+                       break;
+               }
+               if (ncr5380_wait_req(sc)) {
+                       NCR_TRACE("pio_out: no REQ, resid=%d\n", resid);
+                       break;
+               }
+               if (SCI_BUS_PHASE(*sc->sci_bus_csr) != phase)
+                       break;
+
+               /* Put the data on the bus. */
+               SetReg ( sc->sci_odata, *data ); data++;
+/*             *sc->sci_odata = *data++; */
+
+               /* Tell the target it's there. */
+               icmd |= SCI_ICMD_ACK;
+               SetReg ( sc->sci_icmd, icmd );
+/*             *sc->sci_icmd = icmd; */
+
+               /* Wait for target to get it. */
+               error = ncr5380_wait_not_req(sc);
+
+               /* OK, it's got it (or we gave up waiting). */
+               icmd &= ~SCI_ICMD_ACK;
+               SetReg ( sc->sci_icmd, icmd );
+/*             *sc->sci_icmd = icmd; */
+
+               if (error) {
+                       NCR_TRACE("pio_out: stuck REQ, resid=%d\n", resid);
+                       break;
+               }
+
+               --resid;
+       }
+
+       /* Stop driving the data bus. */
+       icmd &= ~SCI_ICMD_DATA;
+       SetReg ( sc->sci_icmd, icmd );
+/*     *sc->sci_icmd = icmd; */
+
+       return (count - resid);
+}
+
+
+int
+ncr5380_pio_in(sc, phase, count, data)
+       struct ncr5380_softc *sc;
+       int phase, count;
+       unsigned char                   *data;
+{
+       register u_char         icmd;
+       register int            resid;
+       register int            error;
+
+       icmd = *(sc->sci_icmd) & SCI_ICMD_RMASK;
+
+       resid = count;
+       while (resid > 0) {
+               if (!SCI_BUSY(sc)) {
+                       NCR_TRACE("pio_in: lost BSY, resid=%d\n", resid);
+                       break;
+               }
+               if (ncr5380_wait_req(sc)) {
+                       NCR_TRACE("pio_in: no REQ, resid=%d\n", resid);
+                       break;
+               }
+               /* A phase change is not valid until AFTER REQ rises! */
+               if (SCI_BUS_PHASE(*sc->sci_bus_csr) != phase)
+                       break;
+
+               /* Read the data bus. */
+               *data++ = *sc->sci_data;
+
+               /* Tell target we got it. */
+               icmd |= SCI_ICMD_ACK;
+               SetReg ( sc->sci_icmd, icmd );
+/*             *sc->sci_icmd = icmd; */
+
+               /* Wait for target to drop REQ... */
+               error = ncr5380_wait_not_req(sc);
+
+               /* OK, we can drop ACK. */
+               icmd &= ~SCI_ICMD_ACK;
+               SetReg ( sc->sci_icmd, icmd );
+/*             *sc->sci_icmd = icmd; */
+
+               if (error) {
+                       NCR_TRACE("pio_in: stuck REQ, resid=%d\n", resid);
+                       break;
+               }
+
+               --resid;
+       }
+
+       return (count - resid);
+}
+
+
+void
+ncr5380_init(sc)
+       struct ncr5380_softc *sc;
+{
+       int i, j;
+
+#ifdef DEBUG
+       ncr5380_debug_sc = sc;
+#endif
+
+       for (i = 0; i < SCI_OPENINGS; i++)
+               sc->sc_ring[i].sr_xs = NULL;
+       for (i = 0; i < 8; i++)
+               for (j = 0; j < 8; j++)
+                       sc->sc_matrix[i][j] = NULL;
+
+       sc->sc_link.openings = 2;       /* XXX - Not SCI_OPENINGS */
+       sc->sc_prevphase = PHASE_INVALID;
+       sc->sc_state = NCR_IDLE;
+
+       SetReg ( sc->sci_tcmd, PHASE_INVALID );
+       SetReg ( sc->sci_icmd, 0 );
+       SetReg ( sc->sci_mode, 0 );
+       SetReg ( sc->sci_sel_enb, 0 );
+
+/*     *sc->sci_tcmd = PHASE_INVALID;
+       *sc->sci_icmd = 0;
+       *sc->sci_mode = 0;
+       *sc->sci_sel_enb = 0; */
+       SCI_CLR_INTR(sc);
+
+       /* XXX: Enable reselect interrupts... */
+       SetReg ( sc->sci_sel_enb, 0x80 );
+/*     *sc->sci_sel_enb = 0x80; */
+
+       /* Another hack (Er.. hook!) for the sun3 si: */
+       if (sc->sc_intr_on) {
+               NCR_TRACE("init: intr ON\n", 0);
+               sc->sc_intr_on(sc);
+       }
+}
+
+
+void
+ncr5380_reset_scsibus(sc)
+       struct ncr5380_softc *sc;
+{
+
+       NCR_TRACE("reset_scsibus, cur=0x%x\n",
+                         (long) sc->sc_current);
+
+       SetReg ( sc->sci_icmd, SCI_ICMD_RST );
+/*     *sc->sci_icmd = SCI_ICMD_RST; */
+       delay(500);
+       SetReg ( sc->sci_icmd, 0 );
+/*     *sc->sci_icmd = 0; */
+
+       SetReg ( sc->sci_mode, 0 );
+       SetReg ( sc->sci_tcmd, PHASE_INVALID );
+
+/*     *sc->sci_mode = 0;
+       *sc->sci_tcmd = PHASE_INVALID; */
+
+       SCI_CLR_INTR(sc);
+       /* XXX - Need long delay here! */
+       delay(100000);
+
+       /* XXX - Need to cancel disconnected requests. */
+}
+
+
+/*
+ * Interrupt handler for the SCSI Bus Controller (SBC)
+ * This may also called for a DMA timeout (at splbio).
+ */
+int
+ncr5380_intr(sc)
+       struct ncr5380_softc *sc;
+{
+       int claimed = 0;
+
+       /*
+        * Do not touch SBC regs here unless sc_current == NULL
+        * or it will complain about "register conflict" errors.
+        * Instead, just let ncr5380_machine() deal with it.
+        */
+       NCR_TRACE("intr: top, state=%d\n", sc->sc_state);
+
+       if (sc->sc_state == NCR_IDLE) {
+               /*
+                * Might be reselect.  ncr5380_reselect() will check,
+                * and set up the connection if so.  This will verify
+                * that sc_current == NULL at the beginning...
+                */
+
+               /* Another hack (Er.. hook!) for the sun3 si: */
+               if (sc->sc_intr_off) {
+                       NCR_TRACE("intr: for reselect, intr off\n", 0);
+                   sc->sc_intr_off(sc);
+               }
+
+               ncr5380_reselect(sc);
+       }
+
+       /*
+        * The remaining documented interrupt causes are phase mismatch and
+        * disconnect.  In addition, the sunsi controller may produce a state
+        * where SCI_CSR_DONE is false, yet DMA is complete.
+        *
+        * The procedure in all these cases is to let ncr5380_machine()
+        * figure out what to do next.
+        */
+       if (sc->sc_state & NCR_WORKING) {
+               NCR_TRACE("intr: call machine, cur=0x%x\n",
+                                 (long) sc->sc_current);
+               /* This will usually free-up the nexus. */
+               ncr5380_machine(sc);
+               NCR_TRACE("intr: machine done, cur=0x%x\n",
+                                 (long) sc->sc_current);
+               claimed = 1;
+       }
+
+       /* Maybe we can run some commands now... */
+       if (sc->sc_state == NCR_IDLE) {
+               NCR_TRACE("intr: call sched, cur=0x%x\n",
+                                 (long) sc->sc_current);
+               ncr5380_sched(sc);
+               NCR_TRACE("intr: sched done, cur=0x%x\n",
+                                 (long) sc->sc_current);
+       }
+
+       return claimed;
+}
+
+
+/*
+ * Abort the current command (i.e. due to timeout)
+ */
+void
+ncr5380_abort(sc)
+       struct ncr5380_softc *sc;
+{
+
+       /*
+        * Finish it now.  If DMA is in progress, we
+        * can not call ncr_sched_msgout() because
+        * that hits the SBC (avoid DMA conflict).
+        */
+
+       /* Another hack (Er.. hook!) for the sun3 si: */
+       if (sc->sc_intr_off) {
+               NCR_TRACE("abort: intr off\n", 0);
+               sc->sc_intr_off(sc);
+       }
+
+       sc->sc_state |= NCR_ABORTING;
+       if ((sc->sc_state & NCR_DOINGDMA) == 0) {
+               ncr_sched_msgout(sc, SEND_ABORT);
+       }
+       NCR_TRACE("abort: call machine, cur=0x%x\n",
+                         (long) sc->sc_current);
+       ncr5380_machine(sc);
+       NCR_TRACE("abort: machine done, cur=0x%x\n",
+                         (long) sc->sc_current);
+
+       /* Another hack (Er.. hook!) for the sun3 si: */
+       if (sc->sc_intr_on) {
+               NCR_TRACE("abort: intr ON\n", 0);
+           sc->sc_intr_on(sc);
+       }
+}
+
+/*
+ * Timeout handler, scheduled for each SCSI command.
+ */
+void
+ncr5380_cmd_timeout(arg)
+       void *arg;
+{
+       struct sci_req *sr = arg;
+       struct scsi_xfer *xs;
+       struct scsi_link *sc_link;
+       struct ncr5380_softc *sc;
+       int s;
+
+       s = splbio();
+
+       /* Get all our variables... */
+       xs = sr->sr_xs;
+       if (xs == NULL) {
+               printf("ncr5380_cmd_timeout: no scsi_xfer\n");
+               goto out;
+       }
+       sc_link = xs->sc_link;
+       sc = sc_link->adapter_softc;
+
+       printf("%s: cmd timeout, targ=%d, lun=%d\n",
+                  sc->sc_dev.dv_xname,
+                  sr->sr_target, sr->sr_lun);
+
+       /*
+        * Mark the overdue job as failed, and arrange for
+        * ncr5380_machine to terminate it.  If the victim
+        * is the current job, call ncr5380_machine() now.
+        * Otherwise arrange for ncr5380_sched() to do it.
+        */
+       sr->sr_flags |= SR_OVERDUE;
+       if (sc->sc_current == sr) {
+               NCR_TRACE("cmd_tmo: call abort, sr=0x%x\n", (long) sr);
+               ncr5380_abort(sc);
+       } else {
+               /*
+                * The driver may be idle, or busy with another job.
+                * Arrange for ncr5380_sched() to do the deed.
+                */
+               NCR_TRACE("cmd_tmo: clear matrix, t/l=0x%02x\n",
+                                 (sr->sr_target << 4) | sr->sr_lun);
+               sc->sc_matrix[sr->sr_target][sr->sr_lun] = NULL;
+       }
+
+       /*
+        * We may have aborted the current job, or may have
+        * already been idle. In either case, we should now
+        * be idle, so try to start another job.
+        */
+       if (sc->sc_state == NCR_IDLE) {
+               NCR_TRACE("cmd_tmo: call sched, cur=0x%x\n",
+                                 (long) sc->sc_current);
+               ncr5380_sched(sc);
+               NCR_TRACE("cmd_tmo: sched done, cur=0x%x\n",
+                                 (long) sc->sc_current);
+       }
+
+out:
+       splx(s);
+}
+
+
+/*****************************************************************
+ * Interface to higher level
+ *****************************************************************/
+
+
+/*
+ * Enter a new SCSI command into the "issue" queue, and
+ * if there is work to do, start it going.
+ *
+ * WARNING:  This can be called recursively!
+ * (see comment in ncr5380_done)
+ */
+int
+ncr5380_scsi_cmd(xs)
+       struct scsi_xfer *xs;
+{
+       struct  ncr5380_softc *sc;
+       struct sci_req  *sr;
+       int s, rv, i, flags;
+       extern int cold;                /* XXX */
+
+       sc = xs->sc_link->adapter_softc;
+
+       flags = xs->flags;
+       /*
+        * XXX: Hack: During autoconfig, force polling mode.
+        * Needed as long as sdsize() can be called while cold,
+        * otherwise timeouts will never call back (grumble).
+        */
+       if (cold)
+               flags |= SCSI_POLL;
+
+       if (sc->sc_flags & NCR5380_FORCE_POLLING)
+               flags |= SCSI_POLL;
+
+       if (flags & SCSI_DATA_UIO)
+               panic("ncr5380: scsi data uio requested");
+
+       s = splbio();
+
+       if (flags & SCSI_POLL) {
+               /* Terminate any current command. */
+               sr = sc->sc_current;
+               if (sr) {
+                       printf("%s: polled request aborting %d/%d\n",
+                                  sc->sc_dev.dv_xname,
+                                  sr->sr_target, sr->sr_lun);
+                       ncr5380_abort(sc);
+               }
+               if (sc->sc_state != NCR_IDLE) {
+                       panic("ncr5380_scsi_cmd: polled request, abort failed");
+               }
+       }
+
+       /*
+        * Find lowest empty slot in ring buffer.
+        * XXX: What about "fairness" and cmd order?
+        */
+       for (i = 0; i < SCI_OPENINGS; i++)
+               if (sc->sc_ring[i].sr_xs == NULL)
+                       goto new;
+
+       rv = TRY_AGAIN_LATER;
+       NCR_TRACE("scsi_cmd: no openings, rv=%d\n", rv);
+       goto out;
+
+new:
+       /* Create queue entry */
+       sr = &sc->sc_ring[i];
+       sr->sr_xs = xs;
+       sr->sr_target = xs->sc_link->target;
+       sr->sr_lun = xs->sc_link->lun;
+       sr->sr_dma_hand = NULL;
+       sr->sr_dataptr = xs->data;
+       sr->sr_datalen = xs->datalen;
+       sr->sr_flags = (flags & SCSI_POLL) ? SR_IMMED : 0;
+       sr->sr_status = -1;     /* no value */
+       sc->sc_ncmds++;
+       rv = SUCCESSFULLY_QUEUED;
+
+       NCR_TRACE("scsi_cmd: new sr=0x%x\n", (long)sr);
+
+       if (flags & SCSI_POLL) {
+               /* Force this new command to be next. */
+               sc->sc_rr = i;
+       }
+
+       /*
+        * If we were idle, run some commands...
+        */
+       if (sc->sc_state == NCR_IDLE) {
+               NCR_TRACE("scsi_cmd: call sched, cur=0x%x\n",
+                                 (long) sc->sc_current);
+               ncr5380_sched(sc);
+               NCR_TRACE("scsi_cmd: sched done, cur=0x%x\n",
+                                 (long) sc->sc_current);
+       }
+
+       if (flags & SCSI_POLL) {
+               /* Make sure ncr5380_sched() finished it. */
+               if ((xs->flags & ITSDONE) == 0)
+                       panic("ncr5380_scsi_cmd: poll didn't finish");
+               rv = COMPLETE;
+       }
+
+out:
+       splx(s);
+       return (rv);
+}
+
+
+/*
+ * POST PROCESSING OF SCSI_CMD (usually current)
+ * Called by ncr5380_sched(), ncr5380_machine()
+ */
+static void
+ncr5380_done(sc)
+       struct ncr5380_softc *sc;
+{
+       struct  sci_req *sr;
+       struct  scsi_xfer *xs;
+
+#ifdef DIAGNOSTIC
+       if ((getsr() & PSL_IPL) < PSL_IPL2)
+               panic("ncr5380_done: bad spl");
+       if (sc->sc_state == NCR_IDLE)
+               panic("ncr5380_done: state=idle");
+       if (sc->sc_current == NULL)
+               panic("ncr5380_done: current=0");
+#endif
+
+       sr = sc->sc_current;
+       xs = sr->sr_xs;
+
+       NCR_TRACE("done: top, cur=0x%x\n", (long) sc->sc_current);
+
+       /*
+        * Clean up DMA resources for this command.
+        */
+       if (sr->sr_dma_hand) {
+               NCR_TRACE("done: dma_free, dh=0x%x\n",
+                                 (long) sr->sr_dma_hand);
+               (*sc->sc_dma_free)(sc);
+       }
+#ifdef DIAGNOSTIC
+       if (sr->sr_dma_hand)
+               panic("ncr5380_done: dma free did not");
+#endif
+
+       if (sc->sc_state & NCR_ABORTING) {
+               NCR_TRACE("done: aborting, error=%d\n", xs->error);
+               if (xs->error == XS_NOERROR)
+                       xs->error = XS_TIMEOUT;
+       }
+
+       NCR_TRACE("done: check error=%d\n", (long) xs->error);
+
+       /* If error is already set, ignore sr_status value. */
+       if (xs->error != XS_NOERROR)
+               goto finish;
+
+       NCR_TRACE("done: check status=%d\n", sr->sr_status);
+
+       switch (sr->sr_status) {
+       case SCSI_OK:   /* 0 */
+               if (sr->sr_flags & SR_SENSE) {
+                       if (ncr5380_debug & NCR_DBG_CMDS) {
+                               ncr5380_show_sense(xs);
+                       }
+                       xs->error = XS_SENSE;
+               }
+               break;
+
+       case SCSI_CHECK:
+               if (sr->sr_flags & SR_SENSE) {
+                       /* Sense command also asked for sense? */
+                       printf("ncr5380_done: sense asked for sense\n");
+                       NCR_BREAK();
+                       xs->error = XS_DRIVER_STUFFUP;
+                       break;
+               }
+               sr->sr_flags |= SR_SENSE;
+               NCR_TRACE("done: get sense, sr=0x%x\n", (long) sr);
+               /*
+                * Leave queued, but clear sc_current so we start over
+                * with selection.  Guaranteed to get the same request.
+                */
+               sc->sc_state = NCR_IDLE;
+               sc->sc_current = NULL;
+               sc->sc_matrix[sr->sr_target][sr->sr_lun] = NULL;
+               return;         /* XXX */
+
+       case SCSI_BUSY:
+               xs->error = XS_BUSY;
+               break;
+
+       case -1:
+               /* This is our "impossible" initial value. */
+               /* fallthrough */
+       default:
+               printf("%s: target %d, bad status=%d\n",
+                       sc->sc_dev.dv_xname, sr->sr_target, sr->sr_status);
+               xs->error = XS_DRIVER_STUFFUP;
+               break;
+       }
+
+finish:
+
+       NCR_TRACE("done: finish, error=%d\n", xs->error);
+
+       /*
+        * Dequeue the finished command, but don't clear sc_state until
+        * after the call to scsi_done(), because that may call back to
+        * ncr5380_scsi_cmd() - unwanted recursion!
+        *
+        * Keeping sc->sc_state != idle terminates the recursion.
+        */
+#ifdef DIAGNOSTIC
+       if ((sc->sc_state & NCR_WORKING) == 0)
+               panic("ncr5380_done: bad state");
+#endif
+
+       /* Clear our pointers to the request. */
+       sc->sc_current = NULL;
+       sc->sc_matrix[sr->sr_target][sr->sr_lun] = NULL;
+       untimeout(ncr5380_cmd_timeout, sr);
+
+       /* Make the request free. */
+       sr->sr_xs = NULL;
+       sc->sc_ncmds--;
+
+       /* Tell common SCSI code it is done. */
+       xs->flags |= ITSDONE;
+       scsi_done(xs);
+
+       sc->sc_state = NCR_IDLE;
+       /* Now ncr5380_sched() may be called again. */
+}
+
+
+/*
+ * Schedule a SCSI operation.  This routine should return
+ * only after it achieves one of the following conditions:
+ *     Busy (sc->sc_state != NCR_IDLE)
+ *     No more work can be started.
+ */
+static void
+ncr5380_sched(sc)
+       struct  ncr5380_softc *sc;
+{
+       struct sci_req  *sr;
+       struct scsi_xfer *xs;
+       int     target, lun;
+       int     error, i;
+
+#ifdef DIAGNOSTIC
+       if ((getsr() & PSL_IPL) < PSL_IPL2)
+               panic("ncr5380_sched: bad spl");
+#endif
+
+       /* Another hack (Er.. hook!) for the sun3 si: */
+       if (sc->sc_intr_off) {
+               NCR_TRACE("sched: top, intr off\n", 0);
+           sc->sc_intr_off(sc);
+       }
+
+next_job:
+       /*
+        * Grab the next job from queue.  Must be idle.
+        */
+#ifdef DIAGNOSTIC
+       if (sc->sc_state != NCR_IDLE)
+               panic("ncr5380_sched: not idle");
+       if (sc->sc_current)
+               panic("ncr5380_sched: current set");
+#endif
+
+       /*
+        * Always start the search where we last looked.
+        * The REQUEST_SENSE logic depends on this to
+        * choose the same job as was last picked, so it
+        * can just clear sc_current and reschedule.
+        * (Avoids loss of "contingent allegiance".)
+        */
+       i = sc->sc_rr;
+       sr = NULL;
+       do {
+               if (sc->sc_ring[i].sr_xs) {
+                       target = sc->sc_ring[i].sr_target;
+                       lun = sc->sc_ring[i].sr_lun;
+                       if (sc->sc_matrix[target][lun] == NULL) {
+                           sc->sc_matrix[target][lun] =
+                                       sr = &sc->sc_ring[i];
+                           sc->sc_rr = i;
+                           break;
+                       }
+               }
+               i++;
+               if (i == SCI_OPENINGS)
+                       i = 0;
+       } while (i != sc->sc_rr);
+
+       if (sr == NULL) {
+               NCR_TRACE("sched: no work, cur=0x%x\n",
+                                 (long) sc->sc_current);
+
+               /* Another hack (Er.. hook!) for the sun3 si: */
+               if (sc->sc_intr_on) {
+                       NCR_TRACE("sched: ret, intr ON\n", 0);
+                   sc->sc_intr_on(sc);
+               }
+
+               return;         /* No more work to do. */
+       }
+
+       NCR_TRACE("sched: select for t/l=0x%02x\n",
+                         (sr->sr_target << 4) | sr->sr_lun);
+
+       sc->sc_state = NCR_WORKING;
+       error = ncr5380_select(sc, sr);
+       if (sc->sc_current) {
+               /* Lost the race!  reselected out from under us! */
+               /* Work with the reselected job. */
+               if (sr->sr_flags & SR_IMMED) {
+                       printf("%s: reselected while polling (abort)\n",
+                                  sc->sc_dev.dv_xname);
+                       /* Abort the reselected job. */
+                       sc->sc_state |= NCR_ABORTING;
+                       sc->sc_msgpriq |= SEND_ABORT;
+               }
+               sr = sc->sc_current;
+               xs = sr->sr_xs;
+               NCR_TRACE("sched: reselect, new sr=0x%x\n", (long)sr);
+               goto have_nexus;
+       }
+
+       /* Normal selection result */
+       sc->sc_current = sr;    /* connected */
+       xs = sr->sr_xs;
+
+       /*
+        * Initialize pointers, etc. for this job
+        */
+       sc->sc_dataptr  = sr->sr_dataptr;
+       sc->sc_datalen  = sr->sr_datalen;
+       sc->sc_prevphase = PHASE_INVALID;
+       sc->sc_msgpriq = SEND_IDENTIFY;
+       sc->sc_msgoutq = 0;
+       sc->sc_msgout  = 0;
+
+       NCR_TRACE("sched: select rv=%d\n", error);
+
+       switch (error) {
+       case XS_NOERROR:
+               break;
+
+       case XS_BUSY:
+               /* XXX - Reset and try again. */
+               printf("%s: SCSI bus busy, resetting...\n",
+                          sc->sc_dev.dv_xname);
+               ncr5380_reset_scsibus(sc);
+               /* fallthrough */
+       case XS_SELTIMEOUT:
+       default:
+               xs->error = error;      /* from select */
+               NCR_TRACE("sched: call done, sr=0x%x\n", (long)sr);
+               ncr5380_done(sc);
+
+               /* Paranoia: clear everything. */
+               sc->sc_dataptr = NULL;
+               sc->sc_datalen = 0;
+               sc->sc_prevphase = PHASE_INVALID;
+               sc->sc_msgpriq = 0;
+               sc->sc_msgoutq = 0;
+               sc->sc_msgout  = 0;
+
+               goto next_job;
+       }
+
+       /*
+        * Selection was successful.  Normally, this means
+        * we are starting a new command.  However, this
+        * might be the termination of an overdue job.
+        */
+       if (sr->sr_flags & SR_OVERDUE) {
+               NCR_TRACE("sched: overdue, sr=0x%x\n", (long)sr);
+               sc->sc_state |= NCR_ABORTING;
+               sc->sc_msgpriq |= SEND_ABORT;
+               goto have_nexus;
+       }
+
+       /*
+        * This may be the continuation of some job that
+        * completed with a "check condition" code.
+        */
+       if (sr->sr_flags & SR_SENSE) {
+               NCR_TRACE("sched: get sense, sr=0x%x\n", (long)sr);
+               /* Do not allocate DMA, nor set timeout. */
+               goto have_nexus;
+       }
+
+       /*
+        * OK, we are starting a new command.
+        * Initialize and allocate resources for the new command.
+        * Device reset is special (only uses MSG_OUT phase).
+        * Normal commands start in MSG_OUT phase where we will
+        * send and IDENDIFY message, and then expect CMD phase.
+        */
+       if (ncr5380_debug & NCR_DBG_CMDS) {
+               printf("ncr5380_sched: begin, target=%d, LUN=%d\n",
+                          xs->sc_link->target, xs->sc_link->lun);
+               ncr5380_show_scsi_cmd(xs);
+       }
+       if (xs->flags & SCSI_RESET) {
+               NCR_TRACE("sched: cmd=reset, sr=0x%x\n", (long)sr);
+               /* Not an error, so do not set NCR_ABORTING */
+               sc->sc_msgpriq |= SEND_DEV_RESET;
+               goto have_nexus;
+       }
+
+#ifdef DIAGNOSTIC
+       if ((xs->flags & (SCSI_DATA_IN | SCSI_DATA_OUT)) == 0) {
+               if (sc->sc_dataptr) {
+                       printf("%s: ptr but no data in/out flags?\n");
+                       NCR_BREAK();
+                       sc->sc_dataptr = NULL;
+               }
+       }
+#endif
+
+       /* Allocate DMA space (maybe) */
+       if (sc->sc_dataptr && sc->sc_dma_alloc &&
+               (sc->sc_datalen >= sc->sc_min_dma_len))
+       {
+               NCR_TRACE("sched: dma_alloc, len=%d\n", sc->sc_datalen);
+               (*sc->sc_dma_alloc)(sc);
+       }
+
+       /*
+        * Initialization hook called just after select,
+        * at the beginning of COMMAND phase.
+        * (but AFTER the DMA allocation is done)
+        *
+        * The evil Sun "si" adapter (OBIO variant) needs some
+        * setup done to the DMA engine BEFORE the target puts
+        * the SCSI bus into any DATA phase.
+        */
+       if (sr->sr_dma_hand && sc->sc_dma_setup) {
+               NCR_TRACE("sched: dma_setup, dh=0x%x\n",
+                                 (long) sr->sr_dma_hand);
+           sc->sc_dma_setup(sc);
+       }
+
+       /*
+        * Schedule a timeout for the job we are starting.
+        */
+       if ((sr->sr_flags & SR_IMMED) == 0) {
+               i = (xs->timeout * hz) / 1000;
+               NCR_TRACE("sched: set timeout=%d\n", i);
+               timeout(ncr5380_cmd_timeout, sr, i);
+       }
+
+have_nexus:
+       NCR_TRACE("sched: call machine, cur=0x%x\n",
+                         (long) sc->sc_current);
+       ncr5380_machine(sc);
+       NCR_TRACE("sched: machine done, cur=0x%x\n",
+                         (long) sc->sc_current);
+
+       /*
+        * What state did ncr5380_machine() leave us in?
+        * Hopefully it sometimes completes a job...
+        */
+       if (sc->sc_state == NCR_IDLE)
+               goto next_job;
+
+       return;         /* Have work in progress. */
+}
+
+
+/*
+ *  Reselect handler: checks for reselection, and if we are being
+ *     reselected, it sets up sc->sc_current.
+ *
+ *  We are reselected when:
+ *     SEL is TRUE
+ *     IO  is TRUE
+ *     BSY is FALSE
+ */
+void
+ncr5380_reselect(sc)
+       struct ncr5380_softc *sc;
+{
+       struct sci_req *sr;
+       int target, lun, phase, timo;
+       u_char bus, data, icmd, msg;
+
+#ifdef DIAGNOSTIC
+       /*
+        * Note: sc_state will be "idle" when ncr5380_intr()
+        * calls, or "working" when ncr5380_select() calls.
+        * (So don't test that in this DIAGNOSTIC)
+        */
+       if (sc->sc_current)
+               panic("ncr5380_reselect: current set");
+#endif
+
+       /*
+        * First, check the select line.
+        * (That has to be set first.)
+        */
+       bus = *(sc->sci_bus_csr);
+       if ((bus & SCI_BUS_SEL) == 0) {
+               /* Not a selection or reselection. */
+               return;
+       }
+
+       /*
+        * The target will assert BSY first (for bus arbitration),
+        * then raise SEL, and finally drop BSY.  Only then is the
+        * data bus required to have valid selection ID bits set.
+        * Wait for: SEL==1, BSY==0 before reading the data bus.
+        */
+       timo = ncr5380_wait_nrq_timo;
+       for (;;) {
+               if ((bus & SCI_BUS_BSY) == 0)
+                       break;
+               /* Probably never get here... */
+               if (--timo <= 0) {
+                       printf("%s: reselect, BSY stuck, bus=0x%x\n",
+                               sc->sc_dev.dv_xname, bus);
+                       /* Not much we can do. Reset the bus. */
+                       ncr5380_reset_scsibus(sc);
+                       return;
+               }
+               delay(10);
+               bus = *(sc->sci_bus_csr);
+               /* If SEL went away, forget it. */
+               if ((bus & SCI_BUS_SEL) == 0)
+                       return;
+               /* Still have SEL, check BSY. */
+       }
+       NCR_TRACE("reselect, valid data after %d loops\n",
+                         ncr5380_wait_nrq_timo - timo);
+
+       /*
+        * Good.  We have SEL=1 and BSY=0.  Now wait for a
+        * "bus settle delay" before we sample the data bus
+        */
+       delay(2);
+       data = *(sc->sci_data) & 0xFF;
+       /* XXX - Should check parity... */
+
+       /*
+        * Is this a reselect (I/O == 1) or have we been
+        * selected as a target? (I/O == 0)
+        */
+       if ((bus & SCI_BUS_IO) == 0) {
+               printf("%s: selected as target, data=0x%x\n",
+                       sc->sc_dev.dv_xname, data);
+               /* Not much we can do. Reset the bus. */
+               ncr5380_reset_scsibus(sc);
+               return;
+       }
+
+       /*
+        * OK, this is a reselection.
+        */
+       for (target = 0; target < 7; target++)
+               if (data & (1 << target))
+                       break;
+
+       if ((data & 0x7F) != (1 << target)) {
+               /* No selecting ID? or >2 IDs on bus? */
+               printf("%s: bad reselect, data=0x%x\n",
+                       sc->sc_dev.dv_xname, data);
+               return;
+       }
+
+       NCR_TRACE("reselect: target=0x%x\n", target);
+
+       /* Raise BSY to acknowledge target reselection. */
+       SetReg ( sc->sci_icmd, SCI_ICMD_BSY );
+/*     *(sc->sci_icmd) = SCI_ICMD_BSY; */
+
+       /* Wait for target to drop SEL. */
+       timo = ncr5380_wait_nrq_timo;
+       for (;;) {
+               bus = *(sc->sci_bus_csr);
+               if ((bus & SCI_BUS_SEL) == 0)
+                       break;  /* success */
+               if (--timo <= 0) {
+                       printf("%s: reselect, SEL stuck, bus=0x%x\n",
+                               sc->sc_dev.dv_xname, bus);
+                       NCR_BREAK();
+                       /* assume connected (fail later if not) */
+                       break;
+               }
+               delay(2);
+       }
+
+       /* Now we drop BSY, and we are connected. */
+       SetReg ( sc->sci_icmd, 0 );
+       SetReg ( sc->sci_sel_enb, 0 );
+/*     *(sc->sci_icmd) = 0;
+       *sc->sci_sel_enb = 0; */
+       SCI_CLR_INTR(sc);
+
+       /*
+        * At this point the target should send an IDENTIFY message,
+        * which will permit us to determine the reselecting LUN.
+        * If not, we assume LUN 0.
+        */
+       lun = 0;
+       /* Wait for REQ before reading bus phase. */
+       if (ncr5380_wait_req(sc)) {
+               printf("%s: reselect, no REQ\n",
+                          sc->sc_dev.dv_xname);
+               /* Try to send an ABORT message. */
+               goto abort;
+       }
+       phase = SCI_BUS_PHASE(*sc->sci_bus_csr);
+       if (phase != PHASE_MSG_IN) {
+               printf("%s: reselect, phase=%d\n",
+                          sc->sc_dev.dv_xname, phase);
+               goto abort;
+       }
+
+       /* Ack. the change to PHASE_MSG_IN */
+       SetReg ( sc->sci_tcmd, PHASE_MSG_IN );
+/*     *(sc->sci_tcmd) = PHASE_MSG_IN; */
+
+       /* Peek at the message byte without consuming it! */
+       msg = *(sc->sci_data);
+       if ((msg & 0x80) == 0) {
+               printf("%s: reselect, not identify, msg=%d\n",
+                          sc->sc_dev.dv_xname, msg);
+               goto abort;
+       }
+       lun = msg & 7;
+       
+       /* We now know target/LUN.  Do we have the request? */
+       sr = sc->sc_matrix[target][lun];
+       if (sr) {
+               /* We now have a nexus. */
+               sc->sc_state |= NCR_WORKING;
+               sc->sc_current = sr;
+               NCR_TRACE("reselect: resume sr=0x%x\n", (long)sr);
+
+               /* Implicit restore pointers message */
+               sc->sc_dataptr = sr->sr_dataptr;
+               sc->sc_datalen = sr->sr_datalen;
+
+               sc->sc_prevphase = PHASE_INVALID;
+               sc->sc_msgpriq = 0;
+               sc->sc_msgoutq = 0;
+               sc->sc_msgout  = 0;
+
+               /*
+                * Another hack for the Sun3 "si", which needs
+                * some setup done to its DMA engine before the
+                * target puts the SCSI bus into any DATA phase.
+                */
+               if (sr->sr_dma_hand && sc->sc_dma_setup) {
+                       NCR_TRACE("reselect: call DMA setup, dh=0x%x\n",
+                                         (long) sr->sr_dma_hand);
+                   sc->sc_dma_setup(sc);
+               }
+
+               /* Now consume the IDENTIFY message. */
+               ncr5380_pio_in(sc, PHASE_MSG_IN, 1, &msg);
+               return;
+       }
+
+       printf("%s: phantom reselect: target=%d, LUN=%d\n",
+                  sc->sc_dev.dv_xname, target, lun);
+abort:
+       /*
+        * Try to send an ABORT message.  This makes us
+        * temporarily busy, but no current command...
+        */
+       sc->sc_state |= NCR_ABORTING;
+
+       /* Raise ATN, delay, raise ACK... */
+       icmd = SCI_ICMD_ATN;
+       SetReg ( sc->sci_icmd, icmd );
+/*     *sc->sci_icmd = icmd; */
+       delay(2);
+
+       /* Now consume the IDENTIFY message. */
+       ncr5380_pio_in(sc, PHASE_MSG_IN, 1, &msg);
+
+       /* Finally try to send the ABORT. */
+       sc->sc_prevphase = PHASE_INVALID;
+       sc->sc_msgpriq = SEND_ABORT;
+       ncr5380_msg_out(sc);
+
+       SetReg ( sc->sci_tcmd, PHASE_INVALID );
+       SetReg ( sc->sci_sel_enb, 0 );
+/*     *(sc->sci_tcmd) = PHASE_INVALID;
+       *sc->sci_sel_enb = 0; */
+       SCI_CLR_INTR(sc);
+       SetReg ( sc->sci_sel_enb, 0x80 );
+/*     *sc->sci_sel_enb = 0x80; */
+
+       sc->sc_state &= ~NCR_ABORTING;
+}
+
+
+/*
+ *  Select target: xs is the transfer that we are selecting for.
+ *  sc->sc_current should be NULL.
+ *
+ *  Returns:
+ *     sc->sc_current != NULL  ==> we were reselected (race!)
+ *     XS_NOERROR              ==> selection worked
+ *     XS_BUSY                 ==> lost arbitration
+ *     XS_SELTIMEOUT           ==> no response to selection
+ */
+static int
+ncr5380_select(sc, sr)
+       struct ncr5380_softc *sc;
+       struct sci_req *sr;
+{
+       int timo;
+       u_char bus, data, icmd;
+
+       /* Check for reselect */
+       ncr5380_reselect(sc);
+       if (sc->sc_current) {
+               NCR_TRACE("select: reselect, cur=0x%x\n",
+                                 (long) sc->sc_current);
+               return XS_BUSY; /* reselected */
+       }
+
+       /*
+        * Set phase bits to 0, otherwise the 5380 won't drive the bus during
+        * selection.
+        */
+
+       SetReg ( sc->sci_tcmd, PHASE_DATA_OUT );
+       SetReg ( sc->sci_icmd, 0 );
+       SetReg ( sc->sci_mode, 0 );
+
+/*     *sc->sci_tcmd = PHASE_DATA_OUT;
+       *sc->sci_icmd = icmd = 0;
+       *sc->sci_mode = 0; */
+
+       /*
+        * Arbitrate for the bus.  The 5380 takes care of the
+        * time-critical bus interactions.  We set our ID bit
+        * in the output data register and set MODE_ARB.  The
+        * 5380 watches for the required "bus free" period.
+        * If and when the "bus free" period is detected, the
+        * 5380 then drives BSY, drives the data bus, and sets
+        * the "arbitration in progress" (AIP) bit to let us
+        * know arbitration has started.  We then wait for one
+        * arbitration delay (2.2uS) and check the ICMD_LST bit,
+        * which will be set if someone else drives SEL.
+        */
+
+       SetReg ( sc->sci_odata, 0x80 );
+       SetReg ( sc->sci_mode, SCI_MODE_ARB );
+
+/*     *(sc->sci_odata) = 0x80; */     /* OUR_ID */
+/*     *(sc->sci_mode) = SCI_MODE_ARB; */
+
+       /* Wait for ICMD_AIP. */
+       timo = ncr5380_wait_req_timo;
+       for (;;) {
+               if (*(sc->sci_icmd) & SCI_ICMD_AIP)
+                       break;
+               if (--timo <= 0) {
+                       /* Did not see any "bus free" period. */
+                       SetReg ( sc->sci_mode, 0 );
+/*                     *sc->sci_mode = 0; */
+                       NCR_TRACE("select: bus busy, rc=%d\n", XS_BUSY);
+                       return XS_BUSY;
+               }
+               delay(2);
+       }
+       NCR_TRACE("select: have AIP after %d loops\n",
+                         ncr5380_wait_req_timo - timo);
+
+       /* Got AIP.  Wait one arbitration delay (2.2 uS.) */
+       delay(3);
+
+       /* Check for ICMD_LST */
+       if (*(sc->sci_icmd) & SCI_ICMD_LST) {
+               /* Some other target asserted SEL. */
+               SetReg ( sc->sci_mode, 0 );
+/*             *sc->sci_mode = 0; */
+               NCR_TRACE("select: lost one, rc=%d\n", XS_BUSY);
+               ncr5380_reselect(sc);   /* XXX */
+               return XS_BUSY;
+       }
+
+       /*
+        * No other device has declared itself the winner.
+        * The spec. says to check for higher IDs, but we
+        * are always the highest (ID=7) so don't bother.
+        * We can now declare victory by asserting SEL.
+        *
+        * Note that the 5380 is asserting BSY because we
+        * asked it to do arbitration.  We will now hold
+        * BSY directly so we can turn off ARB mode.
+        */
+       icmd = (SCI_ICMD_BSY | SCI_ICMD_SEL);
+       SetReg ( sc->sci_icmd, icmd );
+/*     *sc->sci_icmd = icmd; */
+
+       /*
+        * "The SCSI device that wins arbitration shall wait
+        *  at least a bus clear delay plus a bus settle delay
+        *  after asserting the SEL signal before changing
+        *  any [other] signal."  (1.2uS. total)
+        */
+       delay(2);
+
+#if 1
+       /*
+        * XXX: Check one last time to see if we really
+        * XXX: did win arbitration.  (too paranoid?)
+        */
+       if (*(sc->sci_icmd) & SCI_ICMD_LST) {
+       SetReg ( sc->sci_icmd, 0 );
+       SetReg ( sc->sci_mode, 0 );
+/*             *sc->sci_icmd = 0;
+               *sc->sci_mode = 0; */
+               NCR_TRACE("select: lost two, rc=%d\n", XS_BUSY);
+               return XS_BUSY;
+       }
+#endif
+       /* Leave ARB mode Now that we drive BSY+SEL */
+       SetReg ( sc->sci_mode, 0 );
+       SetReg ( sc->sci_sel_enb, 0 );
+/*     *sc->sci_mode = 0;
+       *sc->sci_sel_enb = 0; */
+
+       /*
+        * Arbitration is complete.  Now do selection:
+        * Drive the data bus with the ID bits for both
+        * the host and target.  Also set ATN now, to
+        * ask the target for a messgae out phase.
+        */
+       data = 0x80 | (1 << sr->sr_target);
+       SetReg ( sc->sci_odata, data );
+/*     *(sc->sci_odata) = data; */
+       icmd |= (SCI_ICMD_DATA | SCI_ICMD_ATN);
+       SetReg ( sc->sci_icmd, icmd );
+       *(sc->sci_icmd) = icmd;
+       delay(2);       /* two deskew delays. */
+
+       /* De-assert BSY (targets sample the data now). */
+       icmd &= ~SCI_ICMD_BSY;
+       SetReg ( sc->sci_icmd, icmd );
+/*     *(sc->sci_icmd) = icmd; */
+       delay(3);       /* Bus settle delay. */
+
+       /*
+        * Wait for the target to assert BSY.
+        * SCSI spec. says wait for 250 mS.
+        */
+       for (timo = 25000;;) {
+               if (*sc->sci_bus_csr & SCI_BUS_BSY)
+                       goto success;
+               if (--timo <= 0)
+                       break;
+               delay(10);
+       }
+
+       /*
+        * There is no reaction from the target.  Start the selection
+        * timeout procedure. We release the databus but keep SEL+ATN
+        * 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.
+        */
+       icmd &= ~SCI_ICMD_DATA;
+       SetReg ( sc->sci_icmd, icmd );
+/*     *(sc->sci_icmd) = icmd; */
+       delay(201);
+       if ((*sc->sci_bus_csr & SCI_BUS_BSY) == 0) {
+               /* Really no device on bus */
+               SetReg ( sc->sci_tcmd, PHASE_INVALID );
+               SetReg ( sc->sci_icmd, 0 );
+               SetReg ( sc->sci_mode, 0 );
+               SetReg ( sc->sci_sel_enb, 0 );
+/*             *sc->sci_tcmd = PHASE_INVALID;
+               *sc->sci_icmd = 0;
+               *sc->sci_mode = 0;
+               *sc->sci_sel_enb = 0; */
+               SCI_CLR_INTR(sc);
+               SetReg ( sc->sci_sel_enb, 0x80 );
+               *sc->sci_sel_enb = 0x80;
+               NCR_TRACE("select: device down, rc=%d\n", XS_SELTIMEOUT);
+               return XS_SELTIMEOUT;
+       }
+
+success:
+       /*
+        * The target is now driving BSY, so we can stop
+        * driving SEL and the data bus (keep ATN true).
+        * Configure the ncr5380 to monitor BSY, parity.
+        */
+       icmd &= ~(SCI_ICMD_DATA | SCI_ICMD_SEL);
+       SetReg ( sc->sci_icmd, icmd );
+/*     *sc->sci_icmd = icmd; */
+
+       /* XXX - Make parity checking optional? */
+       SetReg ( sc->sci_mode, (SCI_MODE_MONBSY) );
+/*     SetReg ( sc->sci_mode, (SCI_MODE_MONBSY | SCI_MODE_PAR_CHK) ); */
+/*     *sc->sci_mode = (SCI_MODE_MONBSY | SCI_MODE_PAR_CHK); */
+
+       return XS_NOERROR;
+}
+
+
+/*****************************************************************
+ * Functions to handle each info. transfer phase:
+ *****************************************************************/
+
+/*
+ * The message system:
+ *
+ * This is a revamped message system that now should easier accomodate
+ * new messages, if necessary.
+ *
+ * Currently we accept these messages:
+ * IDENTIFY (when reselecting)
+ * COMMAND COMPLETE # (expect bus free after messages marked #)
+ * NOOP
+ * MESSAGE REJECT
+ * SYNCHRONOUS DATA TRANSFER REQUEST
+ * SAVE DATA POINTER
+ * RESTORE POINTERS
+ * DISCONNECT #
+ *
+ * We may send these messages in prioritized order:
+ * BUS DEVICE RESET #          if SCSI_RESET & xs->flags (or in weird sits.)
+ * MESSAGE PARITY ERROR                par. err. during MSGI
+ * MESSAGE REJECT              If we get a message we don't know how to handle
+ * ABORT #                     send on errors
+ * INITIATOR DETECTED ERROR    also on errors (SCSI2) (during info xfer)
+ * IDENTIFY                    At the start of each transfer
+ * SYNCHRONOUS DATA TRANSFER REQUEST   if appropriate
+ * NOOP                                if nothing else fits the bill ...
+ */
+
+#define IS1BYTEMSG(m) (((m) != 0x01 && (m) < 0x20) || (m) >= 0x80)
+#define IS2BYTEMSG(m) (((m) & 0xf0) == 0x20)
+#define ISEXTMSG(m) ((m) == 0x01)
+
+/*
+ * Precondition:
+ * The SCSI bus is already in the MSGI phase and there is a message byte
+ * on the bus, along with an asserted REQ signal.
+ *
+ * Our return value determines whether our caller, ncr5380_machine()
+ * will expect to see another REQ (and possibly phase change).
+ */
+static int
+ncr5380_msg_in(sc)
+       register struct ncr5380_softc *sc;
+{
+       struct sci_req *sr = sc->sc_current;
+       int n, phase, timo;
+       int act_flags;
+       register u_char icmd;
+
+       /* acknowledge phase change */
+       SetReg ( sc->sci_tcmd, PHASE_MSG_IN );
+/*     *sc->sci_tcmd = PHASE_MSG_IN; */
+
+       act_flags = ACT_CONTINUE;
+       icmd = *sc->sci_icmd & SCI_ICMD_RMASK;
+
+       if (sc->sc_prevphase == PHASE_MSG_IN) {
+               /* This is a continuation of the previous message. */
+               n = sc->sc_imp - sc->sc_imess;
+               NCR_TRACE("msg_in: continuation, n=%d\n", n);
+               goto nextbyte;
+       }
+
+       /* This is a new MESSAGE IN phase.  Clean up our state. */
+       sc->sc_state &= ~NCR_DROP_MSGIN;
+
+nextmsg:
+       n = 0;
+       sc->sc_imp = &sc->sc_imess[n];
+
+nextbyte:
+       /*
+        * Read a whole message, but don't ack the last byte.  If we reject the
+        * message, we have to assert ATN during the message transfer phase
+        * itself.
+        */
+       for (;;) {
+               /*
+                * Read a message byte.
+                * First, check BSY, REQ, phase...
+                */
+               if (!SCI_BUSY(sc)) {
+                       NCR_TRACE("msg_in: lost BSY, n=%d\n", n);
+                       /* XXX - Assume the command completed? */
+                       act_flags |= (ACT_DISCONNECT | ACT_CMD_DONE);
+                       return (act_flags);
+               }
+               if (ncr5380_wait_req(sc)) {
+                       NCR_TRACE("msg_in: BSY but no REQ, n=%d\n", n);
+                       /* Just let ncr5380_machine() handle it... */
+                       return (act_flags);
+               }
+               phase = SCI_BUS_PHASE(*sc->sci_bus_csr);
+               if (phase != PHASE_MSG_IN) {
+                       /*
+                        * Target left MESSAGE IN, probably because it
+                        * a) noticed our ATN signal, or
+                        * b) ran out of messages.
+                        */
+                       return (act_flags);
+               }
+               /* Still in MESSAGE IN phase, and REQ is asserted. */
+               if (*sc->sci_csr & SCI_CSR_PERR) {
+                       ncr_sched_msgout(sc, SEND_PARITY_ERROR);
+                       sc->sc_state |= NCR_DROP_MSGIN;
+               }
+
+               /* Gather incoming message bytes if needed. */
+               if ((sc->sc_state & NCR_DROP_MSGIN) == 0) {
+                       if (n >= NCR_MAX_MSG_LEN) {
+                               ncr_sched_msgout(sc, SEND_REJECT);
+                               sc->sc_state |= NCR_DROP_MSGIN;
+                       } else {
+                               *sc->sc_imp++ = *sc->sci_data;
+                               n++;
+                               /*
+                                * This testing is suboptimal, but most
+                                * messages will be of the one byte variety, so
+                                * it should not affect performance
+                                * significantly.
+                                */
+                               if (n == 1 && IS1BYTEMSG(sc->sc_imess[0]))
+                                       goto have_msg;
+                               if (n == 2 && IS2BYTEMSG(sc->sc_imess[0]))
+                                       goto have_msg;
+                               if (n >= 3 && ISEXTMSG(sc->sc_imess[0]) &&
+                                       n == sc->sc_imess[1] + 2)
+                                       goto have_msg;
+                       }
+               }
+
+               /*
+                * If we reach this spot we're either:
+                * a) in the middle of a multi-byte message, or
+                * b) dropping bytes.
+                */
+
+               /* Ack the last byte read. */
+               icmd |= SCI_ICMD_ACK;
+               SetReg ( sc->sci_icmd, icmd );
+/*             *sc->sci_icmd = icmd; */
+
+               if (ncr5380_wait_not_req(sc)) {
+                       NCR_TRACE("msg_in: drop, stuck REQ, n=%d\n", n);
+                       act_flags |= ACT_RESET_BUS;
+               }
+
+               icmd &= ~SCI_ICMD_ACK;
+               SetReg ( sc->sci_icmd, icmd );
+/*             *sc->sci_icmd = icmd; */
+
+               if (act_flags != ACT_CONTINUE)
+                       return (act_flags);
+
+               /* back to nextbyte */
+       }
+
+have_msg:
+       /* We now have a complete message.  Parse it. */
+
+       switch (sc->sc_imess[0]) {
+       case MSG_CMDCOMPLETE:
+               NCR_TRACE("msg_in: CMDCOMPLETE\n", 0);
+               /* Target is about to disconnect. */
+               act_flags |= (ACT_DISCONNECT | ACT_CMD_DONE);
+               break;
+
+       case MSG_DISCONNECT:
+               NCR_TRACE("msg_in: DISCONNECT\n", 0);
+               /* Target is about to disconnect. */
+               act_flags |= ACT_DISCONNECT;
+               break;
+
+       case MSG_PARITY_ERROR:
+               NCR_TRACE("msg_in: PARITY_ERROR\n", 0);
+               /* Resend the last message. */
+               ncr_sched_msgout(sc, sc->sc_msgout);
+               break;
+
+       case MSG_MESSAGE_REJECT:
+               /* The target rejects the last message we sent. */
+               NCR_TRACE("msg_in: got reject for 0x%x\n", sc->sc_msgout);
+               switch (sc->sc_msgout) {
+               case SEND_IDENTIFY:
+                       /* Really old target controller? */
+                       /* XXX ... */
+                       break;
+               case SEND_INIT_DET_ERR:
+                       goto abort;
+               }
+               break;
+
+       case MSG_NOOP:
+               NCR_TRACE("msg_in: NOOP\n", 0);
+               break;
+
+       case MSG_SAVEDATAPOINTER:
+               NCR_TRACE("msg_in: SAVE_PTRS\n", 0);
+               sr->sr_dataptr = sc->sc_dataptr;
+               sr->sr_datalen = sc->sc_datalen;
+               break;
+
+       case MSG_RESTOREPOINTERS:
+               NCR_TRACE("msg_in: RESTORE_PTRS\n", 0);
+               sc->sc_dataptr = sr->sr_dataptr;
+               sc->sc_datalen = sr->sr_datalen;
+               break;
+
+       case MSG_EXTENDED:
+               switch (sc->sc_imess[2]) {
+               case MSG_EXT_SDTR:
+               case MSG_EXT_WDTR:
+                       /* The ncr5380 can not do synchronous mode. */
+                       goto reject;
+               default:
+                       printf("%s: unrecognized MESSAGE EXTENDED; sending REJECT\n",
+                                  sc->sc_dev.dv_xname);
+                       NCR_BREAK();
+                       goto reject;
+               }
+               break;
+
+       default:
+               NCR_TRACE("msg_in: eh? imsg=0x%x\n", sc->sc_imess[0]);
+               printf("%s: unrecognized MESSAGE; sending REJECT\n",
+                          sc->sc_dev.dv_xname);
+               NCR_BREAK();
+               /* fallthrough */
+       reject:
+               ncr_sched_msgout(sc, SEND_REJECT);
+               break;
+
+       abort:
+               sc->sc_state |= NCR_ABORTING;
+               ncr_sched_msgout(sc, SEND_ABORT);
+               break;
+       }
+
+       /* Ack the last byte read. */
+       icmd |= SCI_ICMD_ACK;
+       SetReg ( sc->sci_icmd, icmd );
+/*     *sc->sci_icmd = icmd; */
+
+       if (ncr5380_wait_not_req(sc)) {
+               NCR_TRACE("msg_in: last, stuck REQ, n=%d\n", n);
+               act_flags |= ACT_RESET_BUS;
+       }
+
+       icmd &= ~SCI_ICMD_ACK;
+       SetReg ( sc->sci_icmd, icmd );
+/*     *sc->sci_icmd = icmd; */
+
+       /* Go get the next message, if any. */
+       if (act_flags == ACT_CONTINUE)
+               goto nextmsg;
+
+       return (act_flags);
+}
+
+
+/*
+ * The message out (and in) stuff is a bit complicated:
+ * If the target requests another message (sequence) without
+ * having changed phase in between it really asks for a
+ * retransmit, probably due to parity error(s).
+ * The following messages can be sent:
+ * IDENTIFY       @ These 4 stem from SCSI command activity
+ * SDTR                   @
+ * WDTR                   @
+ * DEV_RESET      @
+ * REJECT if MSGI doesn't make sense
+ * PARITY_ERROR if parity error while in MSGI
+ * INIT_DET_ERR if parity error while not in MSGI
+ * ABORT if INIT_DET_ERR rejected
+ * NOOP if asked for a message and there's nothing to send
+ *
+ * Note that we call this one with (sc_current == NULL)
+ * when sending ABORT for unwanted reselections.
+ */
+static int
+ncr5380_msg_out(sc)
+       register struct ncr5380_softc *sc;
+{
+       struct sci_req *sr = sc->sc_current;
+       int n, phase, resel;
+       int progress, act_flags;
+       register u_char icmd;
+
+       /* acknowledge phase change */
+       SetReg ( sc->sci_tcmd, PHASE_MSG_OUT );
+/*     *sc->sci_tcmd = PHASE_MSG_OUT; */
+
+       progress = 0;   /* did we send any messages? */
+       act_flags = ACT_CONTINUE;
+
+       /*
+        * Set ATN.  If we're just sending a trivial 1-byte message,
+        * we'll clear ATN later on anyway.  Also drive the data bus.
+        */
+       icmd = *sc->sci_icmd & SCI_ICMD_RMASK;
+       icmd |= (SCI_ICMD_ATN | SCI_ICMD_DATA);
+       SetReg ( sc->sci_icmd, icmd );
+/*     *sc->sci_icmd = icmd; */
+
+       if (sc->sc_prevphase == PHASE_MSG_OUT) {
+               if (sc->sc_omp == sc->sc_omess) {
+                       /*
+                        * This is a retransmission.
+                        *
+                        * We get here if the target stayed in MESSAGE OUT
+                        * phase.  Section 5.1.9.2 of the SCSI 2 spec indicates
+                        * that all of the previously transmitted messages must
+                        * be sent again, in the same order.  Therefore, we
+                        * requeue all the previously transmitted messages, and
+                        * start again from the top.  Our simple priority
+                        * scheme keeps the messages in the right order.
+                        */
+                       sc->sc_msgpriq |= sc->sc_msgoutq;
+                       NCR_TRACE("msg_out: retrans priq=0x%x\n", sc->sc_msgpriq);
+               } else {
+                       /* This is a continuation of the previous message. */
+                       n = sc->sc_omp - sc->sc_omess;
+                       NCR_TRACE("msg_out: continuation, n=%d\n", n);
+                       goto nextbyte;
+               }
+       }
+
+       /* No messages transmitted so far. */
+       sc->sc_msgoutq = 0;
+
+nextmsg:
+       /* Pick up highest priority message. */
+       sc->sc_msgout = sc->sc_msgpriq & -sc->sc_msgpriq;
+       sc->sc_msgpriq &= ~sc->sc_msgout;
+       sc->sc_msgoutq |= sc->sc_msgout;
+
+       /* Build the outgoing message data. */
+       switch (sc->sc_msgout) {
+       case SEND_IDENTIFY:
+               NCR_TRACE("msg_out: SEND_IDENTIFY\n", 0);
+               if (sr == NULL) {
+                       printf("%s: SEND_IDENTIFY while not connected; sending NOOP\n",
+                               sc->sc_dev.dv_xname);
+                       NCR_BREAK();
+                       goto noop;
+               }
+               resel = (sc->sc_flags & NCR5380_PERMIT_RESELECT) ? 1 : 0;
+               resel &= (sr->sr_flags & (SR_IMMED | SR_SENSE)) ? 0 : 1;
+               sc->sc_omess[0] = MSG_IDENTIFY(sr->sr_lun, resel);
+               n = 1;
+               break;
+
+       case SEND_DEV_RESET:
+               NCR_TRACE("msg_out: SEND_DEV_RESET\n", 0);
+               /* Expect disconnect after this! */
+               /* XXX: Kill jobs for this target? */
+               act_flags |= (ACT_DISCONNECT | ACT_CMD_DONE);
+               sc->sc_omess[0] = MSG_BUS_DEV_RESET;
+               n = 1;
+               break;
+
+       case SEND_REJECT:
+               NCR_TRACE("msg_out: SEND_REJECT\n", 0);
+               sc->sc_omess[0] = MSG_MESSAGE_REJECT;
+               n = 1;
+               break;
+
+       case SEND_PARITY_ERROR:
+               NCR_TRACE("msg_out: SEND_PARITY_ERROR\n", 0);
+               sc->sc_omess[0] = MSG_PARITY_ERROR;
+               n = 1;
+               break;
+
+       case SEND_INIT_DET_ERR:
+               NCR_TRACE("msg_out: SEND_INIT_DET_ERR\n", 0);
+               sc->sc_omess[0] = MSG_INITIATOR_DET_ERR;
+               n = 1;
+               break;
+
+       case SEND_ABORT:
+               NCR_TRACE("msg_out: SEND_ABORT\n", 0);
+               /* Expect disconnect after this! */
+               /* XXX: Set error flag? */
+               act_flags |= (ACT_DISCONNECT | ACT_CMD_DONE);
+               sc->sc_omess[0] = MSG_ABORT;
+               n = 1;
+               break;
+
+       case 0:
+               printf("%s: unexpected MESSAGE OUT; sending NOOP\n",
+                       sc->sc_dev.dv_xname);
+               NCR_BREAK();
+       noop:
+               NCR_TRACE("msg_out: send NOOP\n", 0);
+               sc->sc_omess[0] = MSG_NOOP;
+               n = 1;
+               break;
+
+       default:
+               printf("%s: weird MESSAGE OUT; sending NOOP\n",
+                       sc->sc_dev.dv_xname);
+               NCR_BREAK();
+               goto noop;
+       }
+       sc->sc_omp = &sc->sc_omess[n];
+
+nextbyte:
+       /* Send message bytes. */
+       while (n > 0) {
+               /*
+                * Send a message byte.
+                * First check BSY, REQ, phase...
+                */
+               if (!SCI_BUSY(sc)) {
+                       NCR_TRACE("msg_out: lost BSY, n=%d\n", n);
+                       goto out;
+               }
+               if (ncr5380_wait_req(sc)) {
+                       NCR_TRACE("msg_out: no REQ, n=%d\n", n);
+                       goto out;
+               }
+               phase = SCI_BUS_PHASE(*sc->sci_bus_csr);
+               if (phase != PHASE_MSG_OUT) {
+                       /*
+                        * Target left MESSAGE OUT, possibly to reject
+                        * our message.
+                        */
+                       NCR_TRACE("msg_out: new phase=%d\n", phase);
+                       goto out;
+               }
+
+               /* Yes, we can send this message byte. */
+               --n;
+
+               /* Clear ATN before last byte if this is the last message. */
+               if (n == 0 && sc->sc_msgpriq == 0) {
+                       icmd &= ~SCI_ICMD_ATN;
+                       SetReg ( sc->sci_icmd, icmd );
+/*                     *sc->sci_icmd = icmd; */
+                       /* 2 deskew delays */
+                       delay(2);       /* XXX */
+               }
+
+               /* Put data on the bus. */
+               sc->sc_omp--;
+               SetReg ( sc->sci_odata, *sc->sc_omp );
+/*             *sc->sci_odata = *--sc->sc_omp; */
+
+               /* Raise ACK to tell target data is on the bus. */
+               icmd |= SCI_ICMD_ACK;
+               SetReg ( sc->sci_icmd, icmd );
+/*             *sc->sci_icmd = icmd; */
+
+               /* Wait for REQ to be negated. */
+               if (ncr5380_wait_not_req(sc)) {
+                       NCR_TRACE("msg_out: stuck REQ, n=%d\n", n);
+                       act_flags |= ACT_RESET_BUS;
+               }
+
+               /* Finally, drop ACK. */
+               icmd &= ~SCI_ICMD_ACK;
+               SetReg ( sc->sci_icmd, icmd );
+/*             *sc->sci_icmd = icmd; */
+
+               /* Stuck bus or something... */
+               if (act_flags & ACT_RESET_BUS)
+                       goto out;
+
+       }
+       progress++;
+
+       /* We get here only if the entire message has been transmitted. */
+       if (sc->sc_msgpriq != 0) {
+               /* There are more outgoing messages. */
+               goto nextmsg;
+       }
+
+       /*
+        * The last message has been transmitted.  We need to remember the last
+        * message transmitted (in case the target switches to MESSAGE IN phase
+        * and sends a MESSAGE REJECT), and the list of messages transmitted
+        * this time around (in case the target stays in MESSAGE OUT phase to
+        * request a retransmit).
+        */
+
+out:
+       /* Stop driving the data bus. */
+       icmd &= ~SCI_ICMD_DATA;
+       SetReg ( sc->sci_icmd, icmd );
+/*     *sc->sci_icmd = icmd; */
+
+       if (!progress)
+               act_flags |= ACT_RESET_BUS;
+
+       return (act_flags);
+}
+
+
+/*
+ * Handle command phase.
+ */
+static int
+ncr5380_command(sc)
+       struct ncr5380_softc *sc;
+{
+       struct sci_req *sr = sc->sc_current;
+       struct scsi_xfer *xs = sr->sr_xs;
+       struct scsi_sense rqs;
+       int len;
+
+       /* acknowledge phase change */
+       SetReg ( sc->sci_tcmd, PHASE_COMMAND );
+/*     *sc->sci_tcmd = PHASE_COMMAND; */
+
+       if (sr->sr_flags & SR_SENSE) {
+               rqs.opcode = REQUEST_SENSE;
+               rqs.byte2 = xs->sc_link->lun << 5;
+               rqs.length = sizeof(xs->sense);
+
+               rqs.unused[0] = rqs.unused[1] = rqs.control = 0;
+               len = ncr5380_pio_out(sc, PHASE_COMMAND, sizeof(rqs),
+                       (u_char *)&rqs);
+       }
+       else {
+               /* Assume command can be sent in one go. */
+               /* XXX: Do this using DMA, and get a phase change intr? */
+               len = ncr5380_pio_out(sc, PHASE_COMMAND, xs->cmdlen,
+                       (u_char *)xs->cmd);
+       }
+
+       if (len != xs->cmdlen) {
+#ifdef DEBUG
+               printf("ncr5380_command: short transfer: wanted %d got %d.\n",
+                          xs->cmdlen, len);
+               ncr5380_show_scsi_cmd(xs);
+               NCR_BREAK();
+#endif
+               if (len < 6) {
+                       xs->error = XS_DRIVER_STUFFUP;
+                       sc->sc_state |= NCR_ABORTING;
+                       ncr_sched_msgout(sc, SEND_ABORT);
+               }
+
+       }
+
+       return ACT_CONTINUE;
+}
+
+
+/*
+ * Handle either data_in or data_out
+ */
+static int
+ncr5380_data_xfer(sc, phase)
+       struct ncr5380_softc *sc;
+       int phase;
+{
+       struct sci_req *sr = sc->sc_current;
+       struct scsi_xfer *xs = sr->sr_xs;
+       int expected_phase;
+       int i, len;
+
+       if (sr->sr_flags & SR_SENSE) {
+               NCR_TRACE("data_xfer: get sense, sr=0x%x\n", (long)sr);
+               if (phase != PHASE_DATA_IN) {
+                       printf("%s: sense phase error\n", sc->sc_dev.dv_xname);
+                       goto abort;
+               }
+               /* acknowledge phase change */
+               SetReg ( sc->sci_tcmd, PHASE_DATA_IN );
+/*             *sc->sci_tcmd = PHASE_DATA_IN; */
+               len = ncr5380_pio_in(sc, phase, sizeof(xs->sense),
+                               (u_char *)&xs->sense);
+               return ACT_CONTINUE;
+       }
+
+       /*
+        * When aborting a command, disallow any data phase.
+        */
+       if (sc->sc_state & NCR_ABORTING) {
+               printf("%s: aborting, but phase=%s (reset)\n",
+                      sc->sc_dev.dv_xname,
+                          phase_names[phase & 7]);
+               return ACT_RESET_BUS;   /* XXX */
+       }
+
+       /* Validate expected phase (data_in or data_out) */
+       expected_phase = (xs->flags & SCSI_DATA_OUT) ?
+               PHASE_DATA_OUT : PHASE_DATA_IN;
+       if (phase != expected_phase) {
+               printf("%s: data phase error\n",
+                          sc->sc_dev.dv_xname);
+               goto abort;
+       }
+
+       /* Make sure we have some data to move. */
+       if (sc->sc_datalen <= 0) {
+               printf("%s: can not transfer more data\n",
+                          sc->sc_dev.dv_xname);
+               goto abort;
+       }
+
+       /*
+        * Attempt DMA only if dma_alloc gave us a DMA handle AND
+        * there is enough left to transfer so DMA is worth while.
+        */
+       if (sr->sr_dma_hand &&
+               (sc->sc_datalen >= sc->sc_min_dma_len))
+       {
+               /*
+                * OK, really start DMA.  Note, the MI start function
+                * is responsible for setting the TCMD register, etc.
+                * (Acknowledge the phase change there, not here.)
+                */
+               NCR_TRACE("data_xfer: dma_start, dh=0x%x\n",
+                         (long) sr->sr_dma_hand);
+               (*sc->sc_dma_start)(sc);
+               return ACT_WAIT_DMA;
+       }
+
+       NCR_TRACE("data_xfer: doing PIO, len=%d\n", sc->sc_datalen);
+
+       /* acknowledge phase change */
+       SetReg ( sc->sci_tcmd, phase );
+/*     *sc->sci_tcmd = phase; */
+       if (phase == PHASE_DATA_OUT) {
+               len = ncr5380_pio_out(sc, phase, sc->sc_datalen, sc->sc_dataptr);
+       } else {
+               len = ncr5380_pio_in (sc, phase, sc->sc_datalen, sc->sc_dataptr);
+       }
+       sc->sc_dataptr += len;
+       sc->sc_datalen -= len;
+
+       NCR_TRACE("data_xfer: did PIO, resid=%d\n", sc->sc_datalen);
+       return (ACT_CONTINUE);
+
+abort:
+       sc->sc_state |= NCR_ABORTING;
+       ncr_sched_msgout(sc, SEND_ABORT);
+       return (ACT_CONTINUE);
+}
+
+
+static int
+ncr5380_status(sc)
+       struct ncr5380_softc *sc;
+{
+       int len;
+       u_char status;
+       struct sci_req *sr = sc->sc_current;
+       struct scsi_xfer *xs = sr->sr_xs;
+
+       /* acknowledge phase change */
+       SetReg ( sc->sci_tcmd, PHASE_STATUS );
+/*     *sc->sci_tcmd = PHASE_STATUS; */
+
+       len = ncr5380_pio_in(sc, PHASE_STATUS, 1, &status);
+       if (len) {
+               sr->sr_status = status;
+       } else {
+               printf("ncr5380_status: none?\n");
+       }
+
+       return ACT_CONTINUE;
+}
+
+
+/*
+ * This is the big state machine that follows SCSI phase changes.
+ * This is somewhat like a co-routine.  It will do a SCSI command,
+ * and exit if the command is complete, or if it must wait, i.e.
+ * for DMA to complete or for reselect to resume the job.
+ *
+ * The bus must be selected, and we need to know which command is
+ * being undertaken.
+ */
+static void
+ncr5380_machine(sc)
+       struct ncr5380_softc *sc;
+{
+       struct sci_req *sr;
+       struct scsi_xfer *xs;
+       int act_flags, phase, timo;
+
+#ifdef DIAGNOSTIC
+       if ((getsr() & PSL_IPL) < PSL_IPL2)
+               panic("ncr5380_machine: bad spl");
+       if (sc->sc_state == NCR_IDLE)
+               panic("ncr5380_machine: state=idle");
+       if (sc->sc_current == NULL)
+               panic("ncr5380_machine: no current cmd");
+#endif
+
+       sr = sc->sc_current;
+       xs = sr->sr_xs;
+       act_flags = ACT_CONTINUE;
+
+       /*
+        * This will be called by ncr5380_intr() when DMA is
+        * complete.  Must stop DMA before touching the 5380 or
+        * there will be "register conflict" errors.
+        */
+       if (sc->sc_state & NCR_DOINGDMA) {
+               /* Pick-up where where we left off... */
+               goto dma_done;
+       }
+
+next_phase:
+
+       if (!SCI_BUSY(sc)) {
+               /* Unexpected disconnect */
+               printf("ncr5380_machine: unexpected disconnect.\n");
+               xs->error = XS_DRIVER_STUFFUP;
+               act_flags |= (ACT_DISCONNECT | ACT_CMD_DONE);
+               goto do_actions;
+       }
+
+       /*
+        * Wait for REQ before reading the phase.
+        * Need to wait longer than usual here, because
+        * some devices are just plain slow...
+        */
+       timo = ncr5380_wait_phase_timo;
+       for (;;) {
+               if (*sc->sci_bus_csr & SCI_BUS_REQ)
+                       break;
+               if (--timo <= 0) {
+                       if (sc->sc_state & NCR_ABORTING) {
+                               printf("%s: no REQ while aborting, reset\n",
+                                      sc->sc_dev.dv_xname);
+                               act_flags |= ACT_RESET_BUS;
+                               goto do_actions;
+                       }
+                       printf("%s: no REQ for next phase, abort\n",
+                              sc->sc_dev.dv_xname);
+                       sc->sc_state |= NCR_ABORTING;
+                       ncr_sched_msgout(sc, SEND_ABORT);
+                       goto next_phase;
+               }
+               delay(100);
+       }
+
+       phase = SCI_BUS_PHASE(*sc->sci_bus_csr);
+       NCR_TRACE("machine: phase=%s\n",
+                         (long) phase_names[phase & 7]);
+
+       /*
+        * We assume that the device knows what it's doing,
+        * so any phase is good.
+        */
+
+#if 0
+       /*
+        * XXX: Do not ACK the phase yet! do it later...
+        * XXX: ... each phase routine does that itself.
+        * In particular, DMA needs it done LATER.
+        */
+       SetReg ( sc->sci_tcmd, phase );
+/*     *sc->sci_tcmd = phase; */       /* acknowledge phase change */
+#endif
+
+       switch (phase) {
+
+       case PHASE_DATA_OUT:
+       case PHASE_DATA_IN:
+               act_flags = ncr5380_data_xfer(sc, phase);
+               break;
+
+       case PHASE_COMMAND:
+               act_flags = ncr5380_command(sc);
+               break;
+
+       case PHASE_STATUS:
+               act_flags = ncr5380_status(sc);
+               break;
+
+       case PHASE_MSG_OUT:
+               act_flags = ncr5380_msg_out(sc);
+               break;
+
+       case PHASE_MSG_IN:
+               act_flags = ncr5380_msg_in(sc);
+               break;
+
+       default:
+               printf("ncr5380_machine: Unexpected phase 0x%x\n", phase);
+               sc->sc_state |= NCR_ABORTING;
+               ncr_sched_msgout(sc, SEND_ABORT);
+               goto next_phase;
+
+       } /* switch */
+       sc->sc_prevphase = phase;
+
+do_actions:
+       __asm("_ncr5380_actions:");
+
+       if (act_flags & ACT_WAIT_DMA) {
+               act_flags &= ~ACT_WAIT_DMA;
+               /* Wait for DMA to complete (polling, or interrupt). */
+               if ((sr->sr_flags & SR_IMMED) == 0) {
+                       NCR_TRACE("machine: wait for DMA intr.\n", 0);
+                       return;         /* will resume at dma_done */
+               }
+               /* Busy-wait for it to finish. */
+               NCR_TRACE("machine: dma_poll, dh=0x%x\n",
+                                 (long) sr->sr_dma_hand);
+               (*sc->sc_dma_poll)(sc);
+       dma_done:
+               /* Return here after interrupt. */
+               if (sr->sr_flags & SR_OVERDUE)
+                       sc->sc_state |= NCR_ABORTING;
+               NCR_TRACE("machine: dma_stop, dh=0x%x\n",
+                                 (long) sr->sr_dma_hand);
+               (*sc->sc_dma_stop)(sc);
+               SCI_CLR_INTR(sc);       /* XXX */
+               /*
+                * While DMA is running we can not touch the SBC,
+                * so various places just set NCR_ABORTING and
+                * expect us the "kick it" when DMA is done.
+                */
+               if (sc->sc_state & NCR_ABORTING) {
+                       ncr_sched_msgout(sc, SEND_ABORT);
+               }
+       }
+
+       /*
+        * Check for parity error.
+        * XXX - better place to check?
+        */
+       if (*(sc->sci_csr) & SCI_CSR_PERR) {
+               printf("%s: parity error csr = %02x!\n",
+                          sc->sc_dev.dv_xname, *(sc->sci_csr) );
+               /* XXX: sc->sc_state |= NCR_ABORTING; */
+               ncr_sched_msgout(sc, SEND_PARITY_ERROR);
+       }
+
+       if (act_flags == ACT_CONTINUE)
+               goto next_phase;
+       /* All other actions "break" from the loop. */
+
+       NCR_TRACE("machine: act_flags=0x%x\n", act_flags);
+
+       if (act_flags & ACT_RESET_BUS) {
+               act_flags |= ACT_CMD_DONE;
+               /*
+                * Reset the SCSI bus, usually due to a timeout.
+                * The error code XS_TIMEOUT allows retries.
+                */
+               sc->sc_state |= NCR_ABORTING;
+               printf("%s: reset SCSI bus for TID=%d LUN=%d\n",
+                          sc->sc_dev.dv_xname,
+                          sr->sr_target, sr->sr_lun);
+               ncr5380_reset_scsibus(sc);
+       }
+
+       if (act_flags & ACT_CMD_DONE) {
+               act_flags |= ACT_DISCONNECT;
+               /* Need to call scsi_done() */
+               /* XXX: from the aic6360 driver, but why? */
+               if (sc->sc_datalen < 0) {
+                       printf("%s: %d extra bytes from %d:%d\n",
+                                  sc->sc_dev.dv_xname, -sc->sc_datalen,
+                                  sr->sr_target, sr->sr_lun);
+                       sc->sc_datalen = 0;
+               }
+               xs->resid = sc->sc_datalen;
+               /* Note: this will clear sc_current */
+               NCR_TRACE("machine: call done, cur=0x%x\n", (long)sr);
+               ncr5380_done(sc);
+       }
+
+       if (act_flags & ACT_DISCONNECT) {
+               /*
+                * The device has dropped BSY (or will soon).
+                * Return and let ncr5380_sched() do its thing.
+                */
+               SetReg ( sc->sci_icmd, 0 );
+               SetReg ( sc->sci_mode, 0 );
+               SetReg ( sc->sci_tcmd, PHASE_INVALID );
+               SetReg ( sc->sci_sel_enb, 0 );
+
+/*             *sc->sci_icmd = 0;
+               *sc->sci_mode = 0;
+               *sc->sci_tcmd = PHASE_INVALID;
+               *sc->sci_sel_enb = 0; */
+
+               SCI_CLR_INTR(sc);
+               SetReg ( sc->sci_sel_enb, 0x80 );
+               *sc->sci_sel_enb = 0x80;
+
+               if ((act_flags & ACT_CMD_DONE) == 0) {
+                       __asm("_ncr5380_disconnected:");
+                       NCR_TRACE("machine: discon, cur=0x%x\n", (long)sr);
+               }
+
+               /*
+                * We may be here due to a disconnect message,
+                * in which case we did NOT call ncr5380_done,
+                * and we need to clear sc_current.
+                */
+               sc->sc_state = NCR_IDLE;
+               sc->sc_current = NULL;
+
+               /* Paranoia: clear everything. */
+               sc->sc_dataptr = NULL;
+               sc->sc_datalen = 0;
+               sc->sc_prevphase = PHASE_INVALID;
+               sc->sc_msgpriq = 0;
+               sc->sc_msgoutq = 0;
+               sc->sc_msgout  = 0;
+
+               /* Our caller will re-enable interrupts. */
+       }
+}
+
+
+#ifdef DEBUG
+
+static void
+ncr5380_show_scsi_cmd(xs)
+       struct scsi_xfer *xs;
+{
+       u_char  *b = (u_char *) xs->cmd;
+       int     i  = 0;
+
+       if ( ! ( xs->flags & SCSI_RESET ) ) {
+               printf("si(%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("si(%d:%d:%d)-RESET-\n",
+                          xs->sc_link->scsibus,
+                          xs->sc_link->target,
+                          xs->sc_link->lun);
+       }
+}
+
+
+static void
+ncr5380_show_sense(xs)
+       struct scsi_xfer *xs;
+{
+       u_char  *b = (u_char *)&xs->sense;
+       int     i;
+
+       printf("sense:");
+       for (i = 0; i < sizeof(xs->sense); i++)
+               printf(" %02x", b[i]);
+       printf("\n");
+}
+
+int ncr5380_traceidx = 0;
+
+#define        TRACE_MAX       1024
+struct trace_ent {
+       char *msg;
+       long  val;
+} ncr5380_tracebuf[TRACE_MAX];
+
+void
+ncr5380_trace(msg, val)
+       char *msg;
+       long  val;
+{
+       register struct trace_ent *tr;
+       register int s;
+
+       s = splhigh();
+
+       tr = &ncr5380_tracebuf[ncr5380_traceidx];
+
+       ncr5380_traceidx++;
+       if (ncr5380_traceidx >= TRACE_MAX)
+               ncr5380_traceidx = 0;
+
+       tr->msg = msg;
+       tr->val = val;
+
+       splx(s);
+}
+
+#ifdef DDB
+void
+ncr5380_clear_trace()
+{
+       ncr5380_traceidx = 0;
+       bzero((char*) ncr5380_tracebuf, sizeof(ncr5380_tracebuf));
+}
+
+void
+ncr5380_show_trace()
+{
+       struct trace_ent *tr;
+       int idx;
+
+       idx = ncr5380_traceidx;
+       do {
+               tr = &ncr5380_tracebuf[idx];
+               idx++;
+               if (idx >= TRACE_MAX)
+                       idx = 0;
+               if (tr->msg)
+                       db_printf(tr->msg, tr->val);
+       } while (idx != ncr5380_traceidx);
+}
+
+void
+ncr5380_show_req(sr)
+       struct sci_req *sr;
+{
+       struct scsi_xfer *xs = sr->sr_xs;
+
+       db_printf("TID=%d ",    sr->sr_target);
+       db_printf("LUN=%d ",    sr->sr_lun);
+       db_printf("dh=0x%x ",   sr->sr_dma_hand);
+       db_printf("dptr=0x%x ", sr->sr_dataptr);
+       db_printf("dlen=0x%x ", sr->sr_datalen);
+       db_printf("flags=%d ",  sr->sr_flags);
+       db_printf("stat=%d ",   sr->sr_status);
+
+       if (xs == NULL) {
+               db_printf("(xs=NULL)\n");
+               return;
+       }
+       db_printf("\n");
+#ifdef SCSIDEBUG
+       show_scsi_xs(xs);
+#else
+       db_printf("xs=0x%x\n", xs);
+#endif
+}
+
+void
+ncr5380_show_state()
+{
+       struct ncr5380_softc *sc;
+       struct sci_req *sr;
+       int i, j, k;
+
+       sc = ncr5380_debug_sc;
+
+       if (sc == NULL) {
+               db_printf("ncr5380_debug_sc == NULL\n");
+               return;
+       }
+
+       db_printf("sc_ncmds=%d\n",      sc->sc_ncmds);
+       k = -1; /* which is current? */
+       for (i = 0; i < SCI_OPENINGS; i++) {
+               sr = &sc->sc_ring[i];
+               if (sr->sr_xs) {
+                       if (sr == sc->sc_current)
+                               k = i;
+                       db_printf("req %d: (sr=0x%x)", i, (long)sr);
+                       ncr5380_show_req(sr);
+               }
+       }
+       db_printf("sc_rr=%d, current=%d\n", sc->sc_rr, k);
+
+       db_printf("Active request matrix:\n");
+       for(i = 0; i < 8; i++) {                /* targets */
+               for (j = 0; j < 8; j++) {       /* LUN */
+                       sr = sc->sc_matrix[i][j];
+                       if (sr) {
+                               db_printf("TID=%d LUN=%d sr=0x%x\n", i, j, (long)sr);
+                       }
+               }
+       }
+
+       db_printf("sc_state=0x%x\n",    sc->sc_state);
+       db_printf("sc_current=0x%x\n",  sc->sc_current);
+       db_printf("sc_dataptr=0x%x\n",  sc->sc_dataptr);
+       db_printf("sc_datalen=0x%x\n",  sc->sc_datalen);
+
+       db_printf("sc_prevphase=%d\n",  sc->sc_prevphase);
+       db_printf("sc_msgpriq=0x%x\n",  sc->sc_msgpriq);
+}
+
+#endif /* DDB */
+#endif /* DEBUG */
diff --git a/sys/arch/arm32/podulebus/ncr5380var.h b/sys/arch/arm32/podulebus/ncr5380var.h
new file mode 100644 (file)
index 0000000..0ad0637
--- /dev/null
@@ -0,0 +1,178 @@
+/*     $NetBSD: ncr5380var.h,v 1.1 1996/01/31 23:26:12 mark Exp $      */
+
+/*
+ * Copyright (c) 1995 David Jones, Gordon W. Ross
+ * Copyright (c) 1994 Jarle Greipsland
+ * 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 authors may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ * 4. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *      This product includes software developed by
+ *      David Jones and Gordon Ross
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * This file defines the interface between the machine-dependent
+ * module and the machine-indepenedent ncr5380sbc.c module.
+ */
+
+#define SCI_CLR_INTR(sc)       (*(sc)->sci_iack)
+#define        SCI_BUSY(sc)            (*sc->sci_bus_csr & SCI_BUS_BSY)
+
+/* These are NOT artibtrary, but map to bits in sci_tcmd */
+#define PHASE_DATA_OUT 0x0
+#define PHASE_DATA_IN  0x1
+#define PHASE_COMMAND  0x2
+#define PHASE_STATUS   0x3
+#define PHASE_UNSPEC1  0x4
+#define PHASE_UNSPEC2  0x5
+#define PHASE_MSG_OUT  0x6
+#define PHASE_MSG_IN   0x7
+
+/*
+ * This illegal phase is used to prevent the 5380 from having
+ * a phase-match condition when we don't want one, such as
+ * when setting up the DMA engine or whatever...
+ */
+#define PHASE_INVALID  PHASE_UNSPEC1
+
+
+/* Per-request state.  This is required in order to support reselection. */
+struct sci_req {
+       struct          scsi_xfer *sr_xs;       /* Pointer to xfer struct, NULL=unused */
+       int             sr_target, sr_lun;      /* For fast access */
+       void            *sr_dma_hand;           /* Current DMA hnadle */
+       u_char          *sr_dataptr;            /* Saved data pointer */
+       int             sr_datalen;
+       int             sr_flags;               /* Internal error code */
+#define        SR_IMMED                        1       /* Immediate command */
+#define        SR_SENSE                        2       /* We are getting sense */
+#define        SR_OVERDUE                      4       /* Timeout while not current */
+#define        SR_ERROR                        8       /* Error occurred */
+       int             sr_status;              /* Status code from last cmd */
+};
+#define        SCI_OPENINGS    16              /* How many commands we can enqueue. */
+
+
+struct ncr5380_softc {
+       struct device   sc_dev;
+       struct          scsi_link sc_link;
+
+       /* Pointers to 5380 registers.  See ncr5380reg.h */
+       volatile u_char *sci_r0;
+       volatile u_char *sci_r1;
+       volatile u_char *sci_r2;
+       volatile u_char *sci_r3;
+       volatile u_char *sci_r4;
+       volatile u_char *sci_r5;
+       volatile u_char *sci_r6;
+       volatile u_char *sci_r7;
+
+       /* Functions set from MD code */
+       int             (*sc_pio_out) __P((struct ncr5380_softc *,
+                                          int, int, u_char *));
+       int             (*sc_pio_in) __P((struct ncr5380_softc *,
+                                         int, int, u_char *));
+       void            (*sc_dma_alloc) __P((struct ncr5380_softc *));
+       void            (*sc_dma_free) __P((struct ncr5380_softc *));
+
+       void            (*sc_dma_setup) __P((struct ncr5380_softc *));
+       void            (*sc_dma_start) __P((struct ncr5380_softc *));
+       void            (*sc_dma_poll) __P((struct ncr5380_softc *));
+       void            (*sc_dma_eop) __P((struct ncr5380_softc *));
+       void            (*sc_dma_stop) __P((struct ncr5380_softc *));
+
+       void            (*sc_intr_on) __P((struct ncr5380_softc *));
+       void            (*sc_intr_off) __P((struct ncr5380_softc *));
+
+       int             sc_flags;       /* Misc. flags and capabilities */
+#define        NCR5380_PERMIT_RESELECT         1  /* Allow disconnect/reselect */
+#define        NCR5380_FORCE_POLLING           2  /* Do not use interrupts. */
+
+       int     sc_min_dma_len; /* Smaller than this is done with PIO */
+
+       /* Begin MI shared data */
+
+       int             sc_state;
+#define        NCR_IDLE                   0    /* Ready for new work. */
+#define NCR_WORKING    0x01    /* Some command is in progress. */
+#define        NCR_ABORTING    0x02    /* Bailing out */
+#define NCR_DOINGDMA   0x04    /* The FIFO data path is active! */
+#define NCR_DROP_MSGIN 0x10    /* Discard all msgs (parity err detected) */
+
+       /* The request that has the bus now. */
+       struct          sci_req *sc_current;
+
+       /* Active data pointer for current SCSI command. */
+       u_char          *sc_dataptr;
+       int             sc_datalen;
+
+       /* Begin MI private data */
+
+       /* The number of operations in progress on the bus */
+       volatile int    sc_ncmds;
+
+       /* Ring buffer of pending/active requests */
+       struct          sci_req sc_ring[SCI_OPENINGS];
+       int             sc_rr;          /* Round-robin scan pointer */
+
+       /* Active requests, by target/LUN */
+       struct          sci_req *sc_matrix[8][8];
+
+       /* Message stuff */
+       int     sc_prevphase;
+
+       u_int   sc_msgpriq;     /* Messages we want to send */
+       u_int   sc_msgoutq;     /* Messages sent during last MESSAGE OUT */
+       u_int   sc_msgout;      /* Message last transmitted */
+#define SEND_DEV_RESET         0x01
+#define SEND_PARITY_ERROR      0x02
+#define SEND_ABORT             0x04
+#define SEND_REJECT            0x08
+#define SEND_INIT_DET_ERR      0x10
+#define SEND_IDENTIFY                  0x20
+#define SEND_SDTR              0x40
+#define        SEND_WDTR               0x80
+#define NCR_MAX_MSG_LEN 8
+       u_char  sc_omess[NCR_MAX_MSG_LEN];
+       u_char  *sc_omp;                /* Outgoing message pointer */
+       u_char  sc_imess[NCR_MAX_MSG_LEN];
+       u_char  *sc_imp;                /* Incoming message pointer */
+
+};
+
+void   ncr5380_init __P((struct ncr5380_softc *));
+void   ncr5380_reset_scsibus __P((struct ncr5380_softc *));
+int    ncr5380_intr __P((struct ncr5380_softc *));
+int    ncr5380_scsi_cmd __P((struct scsi_xfer *));
+int    ncr5380_pio_in __P((struct ncr5380_softc *, int, int, u_char *));
+int    ncr5380_pio_out __P((struct ncr5380_softc *, int, int, u_char *));
+
+#ifdef DEBUG
+struct ncr5380_softc *ncr5380_debug_sc;
+void ncr5380_trace __P((char *msg, long val));
+#define        NCR_TRACE(msg, val) ncr5380_trace(msg, val)
+#else
+#define        NCR_TRACE(msg, val)     /* nada */
+#endif
diff --git a/sys/arch/arm32/podulebus/oak.c b/sys/arch/arm32/podulebus/oak.c
new file mode 100644 (file)
index 0000000..48922d6
--- /dev/null
@@ -0,0 +1,381 @@
+/* $NetBSD: oak.c,v 1.3 1996/03/17 01:24:51 thorpej Exp $ */
+
+/*
+ * Copyright (c) 1995 Melvin Tang-Richardson 1996.
+ * 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 RiscBSD.
+ * 4. The name of the company nor the name of the author may be used to
+ *    endorse or promote products derived from this software without specific
+ *    prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY RISCBSD ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL RISCBSD 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.
+ *
+ * oak.c
+ *
+ * Oak SCSI Driver.
+ */
+
+#undef USE_OWN_PIO_ROUTINES
+
+/* Some system includes *****************************************************/
+
+#include <sys/types.h>
+#include <sys/cdefs.h>
+#include <sys/time.h>
+#include <sys/systm.h>
+#include <sys/param.h>
+#include <sys/kernel.h>
+#include <sys/malloc.h>
+#include <sys/syslog.h>
+#include <sys/device.h>
+#include <sys/buf.h>
+/*#include <machine/bootconfig.h>*/
+
+/* SCSI bus includes */
+
+#include <scsi/scsi_all.h>
+#include <scsi/scsiconf.h>
+
+/* Hardware related include chip/card/bus ***********************************/
+
+#include <machine/io.h>
+#include <machine/irqhandler.h>
+#include <machine/katelib.h>
+#include <arm32/podulebus/podulebus.h>
+#include <arm32/podulebus/ncr5380reg.h>
+#include <arm32/podulebus/ncr5380var.h>
+
+/****************************************************************************/
+/* Some useful definitions **************************************************/
+/****************************************************************************/
+
+#define MY_MANUFACTURER        (0x21)
+#define MY_PODULE      (0x58)
+#define MAX_DMA_LEN    (0xe000)
+
+/****************************************************************************/
+/* Prototype internal data structures ***************************************/
+/****************************************************************************/
+
+struct oak_softc {
+       struct ncr5380_softc ncr_sc;
+       int sc_podule;
+       int sc_base;
+};
+
+/****************************************************************************/
+/* Function and data prototypes *********************************************/
+/****************************************************************************/
+
+int  oakprobe  __P(( struct device *, void *, void * ));
+void oakattach         __P(( struct device *, struct device *, void * ));
+int  oakprint   __P(( void *, char * ));
+void oakminphys __P(( struct buf * ));
+
+#ifdef USE_OWN_PIO_ROUTINES
+int oak_pio_in  __P(( struct ncr5380_softc *, int, int, unsigned char * ));
+int oak_pio_out __P(( struct ncr5380_softc *, int, int, unsigned char * ));
+#endif
+
+struct scsi_adapter oak_adapter = {
+       ncr5380_scsi_cmd,
+       oakminphys,
+       NULL,
+       NULL,
+};
+
+struct scsi_device oak_device = {
+       NULL,
+       NULL,
+       NULL,
+       NULL,
+};
+
+int
+oakprobe(parent, match, aux)
+       struct device *parent;
+       void *match;
+       void *aux;
+{
+       struct oak_softc *sc = (void *) match;
+       struct podule_attach_args *pa = (void *) aux;
+       int podule;
+
+       podule = findpodule(MY_MANUFACTURER, MY_PODULE, pa->pa_podule_number);
+
+       if (podule == -1)
+               return 0;
+
+       sc->sc_podule = podule;
+       sc->sc_base = podules[podule].mod_base;
+
+       return 1;
+}
+
+void
+oakattach(parent, self, aux)
+       struct device *parent;
+       struct device *self;
+       void *aux;
+{
+       struct oak_softc *sc = (void *) self;
+       struct ncr5380_softc *ncr_sc = (struct ncr5380_softc *)sc;
+       struct podule_attach_args *pa = (void *)aux;
+
+       printf(" 16-bit");
+
+       ncr_sc->sc_link.adapter_softc = sc;
+       ncr_sc->sc_link.adapter_target = 7;
+       ncr_sc->sc_link.adapter = &oak_adapter;
+       ncr_sc->sc_link.device = &oak_device;
+
+       ncr_sc->sci_r0 = (volatile u_char *)sc->sc_base + 0x00;
+       ncr_sc->sci_r1 = (volatile u_char *)sc->sc_base + 0x04;
+       ncr_sc->sci_r2 = (volatile u_char *)sc->sc_base + 0x08;
+       ncr_sc->sci_r3 = (volatile u_char *)sc->sc_base + 0x0c;
+       ncr_sc->sci_r4 = (volatile u_char *)sc->sc_base + 0x10;
+       ncr_sc->sci_r5 = (volatile u_char *)sc->sc_base + 0x14;
+       ncr_sc->sci_r6 = (volatile u_char *)sc->sc_base + 0x18;
+       ncr_sc->sci_r7 = (volatile u_char *)sc->sc_base + 0x1c;
+
+#ifdef USE_OWN_PIO_ROUTINES
+       printf ( ", my pio" );
+       ncr_sc->sc_pio_out = oak_pio_out;
+       ncr_sc->sc_pio_in  = oak_pio_in;
+#else
+       printf ( ", normal pio" );
+       ncr_sc->sc_pio_out = ncr5380_pio_out;
+       ncr_sc->sc_pio_in  = ncr5380_pio_in;
+#endif
+
+       ncr_sc->sc_dma_alloc = NULL;
+       ncr_sc->sc_dma_free  = NULL;
+       ncr_sc->sc_dma_poll  = NULL;
+       ncr_sc->sc_dma_setup  = NULL;
+       ncr_sc->sc_dma_start  = NULL;
+       ncr_sc->sc_dma_eop  = NULL;
+       ncr_sc->sc_dma_stop  = NULL;
+
+       printf(", polling");
+       ncr_sc->sc_intr_on   = NULL;
+       ncr_sc->sc_intr_off  = NULL;
+
+       ncr_sc->sc_flags  = NCR5380_FORCE_POLLING;
+
+       ncr5380_init(ncr_sc);
+       ncr5380_reset_scsibus(ncr_sc);
+
+       printf(" UNDER DEVELOPMENT\n");
+
+       config_found(self, &(ncr_sc->sc_link), oakprint);
+}
+
+int
+oakprint(aux, name)
+       void *aux;
+       char *name;
+{
+       if (name != NULL)
+               printf("%s: scsibus ", name);
+       return UNCONF;
+}
+
+void
+oakminphys(bp)
+       struct buf *bp;
+{
+       if (bp->b_bcount > MAX_DMA_LEN) {
+               printf("oak: DEBUG reducing dma length\n");
+               bp->b_bcount = MAX_DMA_LEN;
+       }
+       return (minphys(bp));
+}
+
+struct cfattach oak_ca = {
+       sizeof(struct oak_softc), oakprobe, oakattach
+};
+
+struct cfdriver oak_cd = {
+       NULL, "oak", DV_DISK, NULL, 0,
+};
+
+#ifdef USE_OWN_PIO_ROUTINES
+
+/****************************************************************************/
+/* Copyright (c) 1996 Melvin Tang-Richardson                               */
+/* Copyright (c) 1995 David Jones, Gordon W. Rose                          */
+/* Copyright (c) 1994 Jarle Greipsland                                     */
+/****************************************************************************/
+
+static ncr5380_wait_req_timo = 1000 * 50;      /* X2 = 100 mS */
+static ncr5380_wait_nrq_timo = 1000 * 25;      /* X2 =  50 mS */
+
+/* Return zero on success. */
+static __inline__ int ncr5380_wait_req(sc)
+       struct ncr5380_softc *sc;
+{
+       register int timo = ncr5380_wait_req_timo;
+       for (;;) {
+               if (*sc->sci_bus_csr & SCI_BUS_REQ) {
+                       timo = 0;       /* return 0 */
+                       break;
+               }
+               if (--timo < 0)
+                       break;  /* return -1 */
+               delay(2);
+       }
+       return (timo);
+}
+
+/* Return zero on success. */
+static __inline__ int ncr5380_wait_not_req(sc)
+       struct ncr5380_softc *sc;
+{
+       register int timo = ncr5380_wait_nrq_timo;
+       for (;;) {
+               if ((*sc->sci_bus_csr & SCI_BUS_REQ) == 0) {
+                       timo = 0;       /* return 0 */
+                       break;
+               }
+               if (--timo < 0)
+                       break;  /* return -1 */
+               delay(2);
+       }
+       return (timo);
+}
+
+int
+oak_pio_out(sc, phase, count, data)
+       struct ncr5380_softc *sc;
+       int phase, count;
+       unsigned char           *data;
+{
+       register u_char         icmd;
+       register int            resid;
+       register int            error;
+
+       printf("oak: pio_out %d %d\n", phase, count);
+
+       icmd = *(sc->sci_icmd) & SCI_ICMD_RMASK;
+
+       icmd |= SCI_ICMD_DATA;
+       *sc->sci_icmd = icmd;
+
+       resid = count;
+       while (resid > 0) {
+               if (!SCI_BUSY(sc)) {
+                       NCR_TRACE("pio_out: lost BSY, resid=%d\n", resid);
+                       break;
+               }
+               if (ncr5380_wait_req(sc)) {
+                       NCR_TRACE("pio_out: no REQ, resid=%d\n", resid);
+                       break;
+               }
+               if (SCI_BUS_PHASE(*sc->sci_bus_csr) != phase)
+                       break;
+
+               /* Put the data on the bus. */
+               *sc->sci_odata = *data++;
+
+               /* Tell the target it's there. */
+               icmd |= SCI_ICMD_ACK;
+               *sc->sci_icmd = icmd;
+
+               /* Wait for target to get it. */
+               error = ncr5380_wait_not_req(sc);
+
+               /* OK, it's got it (or we gave up waiting). */
+               icmd &= ~SCI_ICMD_ACK;
+               *sc->sci_icmd = icmd;
+
+               if (error) {
+                       NCR_TRACE("pio_out: stuck REQ, resid=%d\n", resid);
+                       break;
+               }
+
+               --resid;
+       }
+
+       /* Stop driving the data bus. */
+       icmd &= ~SCI_ICMD_DATA;
+       *sc->sci_icmd = icmd;
+
+       return (count - resid);
+}
+
+int
+oak_pio_in(sc, phase, count, data)
+       struct ncr5380_softc *sc;
+       int phase, count;
+       unsigned char   *data;
+{
+       register u_char         icmd;
+       register int            resid;
+       register int            error;
+
+       printf("oak: pio_in %d %d\n", phase, count);
+
+       icmd = *(sc->sci_icmd) & SCI_ICMD_RMASK;
+
+       resid = count;
+       while (resid > 0) {
+               if (!SCI_BUSY(sc)) {
+                       NCR_TRACE("pio_in: lost BSY, resid=%d\n", resid);
+                       break;
+               }
+               if (ncr5380_wait_req(sc)) {
+                       NCR_TRACE("pio_in: no REQ, resid=%d\n", resid);
+                       break;
+               }
+               /* A phase change is not valid until AFTER REQ rises! */
+               if (SCI_BUS_PHASE(*sc->sci_bus_csr) != phase)
+                       break;
+
+               /* Read the data bus. */
+               *data++ = *sc->sci_data;
+
+               /* Tell target we got it. */
+               icmd |= SCI_ICMD_ACK;
+               *sc->sci_icmd = icmd;
+
+               /* Wait for target to drop REQ... */
+               error = ncr5380_wait_not_req(sc);
+
+               /* OK, we can drop ACK. */
+               icmd &= ~SCI_ICMD_ACK;
+               *sc->sci_icmd = icmd;
+
+               if (error) {
+                       NCR_TRACE("pio_in: stuck REQ, resid=%d\n", resid);
+                       break;
+               }
+
+               --resid;
+       }
+
+       return (count - resid);
+}
+
+#endif /* USE_OWN_PIO_ROUTINES */
+
diff --git a/sys/arch/arm32/podulebus/podulebus.c b/sys/arch/arm32/podulebus/podulebus.c
new file mode 100644 (file)
index 0000000..4ca0e18
--- /dev/null
@@ -0,0 +1,627 @@
+/* $NetBSD: podulebus.c,v 1.5 1996/03/27 22:07:26 mark Exp $ */
+
+/*
+ * Copyright (c) 1994,1995 Mark Brinicombe.
+ * Copyright (c) 1994 Brini.
+ * 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 Brini.
+ * 4. The name of the company nor the name of the author may be used to
+ *    endorse or promote products derived from this software without specific
+ *    prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BRINI ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL BRINI 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.
+ *
+ * RiscBSD kernel project
+ *
+ * podulebus.c
+ *
+ * Podule probe and configuration routines
+ *
+ * Created      : 07/11/94
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/conf.h>
+#include <sys/malloc.h>
+#include <sys/device.h>
+#include <machine/io.h>
+#include <machine/katelib.h>
+#include <machine/irqhandler.h>
+#include <arm32/podulebus/podulebus.h>
+
+/*
+ * Now construct the table of know podules.
+ * A podule description array is setup for each manufacturer id
+ */
+struct podule_description podules_0000[] = {
+       { 0x02, "SCSI interface" },
+       { 0x03, "ether 1 interface" },
+       { 0x61, "ether 2 interface" },
+       { 0x00, NULL },
+};
+
+struct podule_description podules_0004[] = {
+       { 0x14, "laser direct (Canon LBP-4)" },
+       { 0x00, NULL },
+};
+
+struct podule_description podules_0009[] = {
+       { 0x52, "hawk V9 mark2" },
+       { 0xcb, "scanlight Video256" },
+       { 0xcc, "eagle M2" },
+       { 0xce, "lark A16" },
+       { 0x200, "MIDI max" },
+       { 0x00, NULL },
+};
+
+struct podule_description podules_0011[] = {
+       { 0xa4, "ether 3 interface" },
+       { 0x00, NULL },
+};
+
+struct podule_description podules_001a[] = {
+       { 0x95, "16 bit SCSI interface" },
+       { 0x00, NULL },
+};
+
+struct podule_description podules_0021[] = {
+       { 0x58, "16 bit SCSI interface" },
+       { 0x00, NULL },
+};
+
+struct podule_description podules_002b[] = {
+       { 0x67, "SCSI interface" },
+       { 0x00, NULL },
+};
+
+struct podule_description podules_003a[] = {
+       { 0x3a, "SCSI II interface" },
+       { 0xdd, "CDFS & SLCD expansion card" },
+       { 0x00, NULL },
+};
+
+struct podule_description podules_0041[] = {
+       { 0x41, "16 bit SCSI interface" },
+       { 0x00, NULL },
+};
+  
+struct podule_description podules_0042[] = {
+       { 0xea, "PC card" },
+       { 0x00, NULL },
+};
+  
+struct podule_description podules_0046[] = {
+       { 0xec, "etherlan 600 network slot interface" },
+       { 0x00, NULL },
+};
+
+struct podule_description podules_0050[] = {
+       { 0x00, "BriniPort intelligent I/O interface" },
+       { 0xdf, "BriniLink transputer link adapter" },
+       { 0x00, NULL },
+};
+
+struct podule_description podules_0053[] = {
+       { 0xe4, "ether B network slot interface" },
+       { 0x00, NULL },
+};
+
+struct podule_description podules_005b[] = {
+       { 0x107, "SCSI 1 / SCSI 2 host adapter" },
+       { 0x00, NULL },
+};
+
+/* A podule list if setup for all the manufacturers */
+  
+struct podule_list known_podules[] = {
+       { 0x00, "Acorn",        podules_0000 },
+       { 0x04, "CConcepts",    podules_0004 }, /* Two codes ??? */
+       { 0x09, "CConcepts",    podules_0009 },
+       { 0x11, "Atomwide",     podules_0011 },
+       { 0x1a, "Lingenuity",   podules_001a },
+       { 0x21, "Oak",          podules_0021 },
+       { 0x2b, "Morley",       podules_002b },
+       { 0x3a, "Cumana",       podules_003a },
+       { 0x41, "ARXE",         podules_0041 },
+       { 0x42, "Aleph1",       podules_0042 },
+       { 0x46, "I-Cubed",      podules_0046 },
+       { 0x50, "Brini",        podules_0050 },
+       { 0x53, "ANT",          podules_0053 },
+       { 0x5b, "Power-tec",    podules_005b },
+};
+
+/* Array of podule structures, one per possible podule */
+
+podule_t podules[MAX_PODULES + MAX_NETSLOTS];
+irqhandler_t poduleirq;
+extern u_int actual_mask;
+extern irqhandler_t *irqhandlers[NIRQS];
+
+/* Declare prototypes */
+
+void map_section __P((vm_offset_t, vm_offset_t, vm_offset_t));
+int poduleirqhandler __P((void));
+u_int poduleread __P((u_int /*address*/, int /*offset*/, int /*slottype*/));
+
+
+/*
+ * int podulebusmatch(struct device *parent, void *match, void *aux)
+ *
+ * Probe for the podule bus. Currently all this does is return 1 to
+ * indicate that the podule bus was found.
+ */
+int
+podulebusmatch(parent, match, aux)
+       struct device *parent;
+       void *match;
+       void *aux;
+{
+       return (1);
+}
+
+
+int
+podulebusprint(aux, podulebus)
+       void *aux;
+       char *podulebus;
+{
+       struct podule_attach_args *pa = aux;
+
+       if (pa->pa_podule != NULL) {
+               if (pa->pa_podule->slottype == SLOT_POD)
+                       printf(" [ podule %d ]:", pa->pa_podule_number);
+               else if (pa->pa_podule->slottype == SLOT_NET)
+                       printf(" [ netslot %d ]:", pa->pa_podule_number - MAX_PODULES);
+               else
+                       panic("Invalid slot type\n");
+       }
+
+/* XXXX print flags */
+       return (QUIET);
+}
+
+
+void
+podulebusscan(parent, match)
+       struct device *parent;
+       void *match;
+{
+       struct device *dev = match;
+       struct cfdata *cf = dev->dv_cfdata;
+       struct podule_attach_args pa;
+
+       if (cf->cf_fstate == FSTATE_STAR)
+               panic("nope cannot handle this");
+
+       pa.pa_podule = NULL;
+       pa.pa_podule_number = -1;
+
+       if (cf->cf_loc[0] != -1) {
+               pa.pa_podule_number = cf->cf_loc[0];
+       }
+
+       if ((*cf->cf_attach->ca_match)(parent, dev, &pa) > 0)
+               config_attach(parent, dev, &pa, podulebusprint);
+       else
+               free(dev, M_DEVBUF);
+}
+
+
+void
+dump_podule(podule)
+       podule_t *podule;
+{
+       printf("podule%d: ", podule->podulenum);
+       printf("flags0=%02x ", podule->flags0);
+       printf("flags1=%02x ", podule->flags1);
+       printf("reserved=%02x ", podule->reserved);
+       printf("product=%02x ", podule->product);
+       printf("manufacturer=%02x ", podule->manufacturer);
+       printf("country=%02x ", podule->country);
+       printf("irq_addr=%08x ", podule->irq_addr);
+       printf("irq_mask=%02x ", podule->irq_mask);
+       printf("fiq_addr=%08x ", podule->fiq_addr);
+       printf("fiq_mask=%02x ", podule->fiq_mask);
+       printf("fast_base=%08x ", podule->fast_base);
+       printf("medium_base=%08x ", podule->medium_base);
+       printf("slow_base=%08x ", podule->slow_base);
+       printf("sync_base=%08x ", podule->sync_base);
+       printf("mod_base=%08x ", podule->mod_base);
+       printf("easi_base=%08x ", podule->easi_base);
+       printf("attached=%d ", podule->attached);
+       printf("slottype=%d ", podule->slottype);
+       printf("podulenum=%d ", podule->podulenum);
+       printf("\n");
+}
+
+
+void
+podulechunkdirectory(podule)
+       podule_t *podule;
+{
+       u_int address;
+       u_int id;
+       u_int size;
+       u_int addr;
+       int loop;
+       
+       address = 0x40;
+
+       do {
+               id = poduleread(podule->slow_base, address, podule->slottype);
+               size = poduleread(podule->slow_base, address + 4, podule->slottype);
+               size |= (poduleread(podule->slow_base, address + 8, podule->slottype) << 8);
+               size |= (poduleread(podule->slow_base, address + 12, podule->slottype) << 16);
+               if (id == 0xf5) {
+                       addr = poduleread(podule->slow_base, address + 16, podule->slottype);
+                       addr |= (poduleread(podule->slow_base, address + 20, podule->slottype) << 8);
+                       addr |= (poduleread(podule->slow_base, address + 24, podule->slottype) << 16);
+                       addr |= (poduleread(podule->slow_base, address + 28, podule->slottype) << 24);
+                       if (addr < 0x800) {
+                               for (loop = 0; loop < size; ++loop)
+                                       printf("%c", poduleread(podule->slow_base, (addr + loop)*4, podule->slottype));
+                               printf("\n");
+                       }
+               }
+               address += 32;
+       } while (id != 0 && address < 0x800);
+}
+
+
+void
+poduleexamine(podule, dev, slottype)
+       podule_t *podule;
+       struct device *dev;
+       int slottype;
+{
+       struct podule_list *pod_list;
+       struct podule_description *pod_desc;
+
+/* Test to see if the podule is present */
+
+       if ((podule->flags0 & 0x02) == 0x00) {
+               podule->slottype = slottype;
+               if (slottype == SLOT_NET)
+                       printf("netslot%d at %s : ", podule->podulenum - MAX_PODULES,
+                           dev->dv_xname);
+               else
+                       printf("podule%d  at %s : ", podule->podulenum,
+                           dev->dv_xname);
+
+/* Is it Acorn conformant ? */
+
+               if (podule->flags0 & 0x80)
+                       printf("Non-Acorn conformant expansion card\n");
+               else {
+                       int id;
+
+/* Is it a simple podule ? */
+
+                       id = (podule->flags0 >> 3) & 0x0f;
+                       if (id != 0)
+                               printf("Simple expansion card <%x>\n", id);
+                       else {
+/* Do we know this manufacturer ? */
+                               pod_list = known_podules;
+                               while (pod_list->description) {
+                                       if (pod_list->manufacturer_id == podule->manufacturer)
+                                               break;
+                                       ++pod_list;
+                               }
+                               if (!pod_list->description)
+                                       printf("man=%04x   : ", podule->manufacturer);
+                               else
+                                       printf("%10s : ", pod_list->description);
+
+/* Do we know this product ? */
+
+                               pod_desc = pod_list->products;
+                               while (pod_desc->description) {
+                                       if (pod_desc->product_id == podule->product)
+                                               break;
+                                       ++pod_desc;
+                               }
+                               if (!pod_desc->description)
+                                       printf("prod=%04x\n", podule->product);
+                               else
+                                       printf("%s\n", pod_desc->description);
+
+                               if (pod_desc->description == NULL
+                                   && podule->flags1 & PODULE_FLAGS_CD)
+                                       podulechunkdirectory(podule);
+                       }
+               }
+       }
+}
+
+
+u_int
+poduleread(address, offset, slottype)
+       u_int address;
+       int offset;
+       int slottype;
+{
+       static u_int netslotoffset;
+
+       if (slottype == SLOT_NET) {
+               offset = offset >> 2;
+               if (offset < netslotoffset) {
+                       WriteWord(address, 0);
+                       netslotoffset = 0;
+               }
+               while (netslotoffset < offset) {
+                       slottype = ReadWord(address);
+                       ++netslotoffset;
+               }
+               ++netslotoffset;
+               return(ReadByte(address));
+       }
+       return(ReadByte(address + offset));
+}
+
+
+void
+podulescan(dev)
+       struct device *dev;
+{
+       int loop;
+       podule_t *podule;
+       u_char *address;
+       u_int offset = 0;
+
+/* Loop round all the podules */
+
+       for (loop = 0; loop < MAX_PODULES; ++loop, offset += SIMPLE_PODULE_SIZE) {
+               if (loop == 4) offset += PODULE_GAP;
+               address = ((u_char *)SLOW_PODULE_BASE) + offset;
+        
+               podule = &podules[loop];
+
+/* Get information from the podule header */
+
+               podule->flags0 = address[0];
+               podule->flags1 = address[4];
+               podule->reserved = address[8];
+               podule->product = address[12] + (address[16] << 8);
+               podule->manufacturer = address[20] + (address[24] << 8);
+               podule->country = address[28];
+               if (podule->flags1 & PODULE_FLAGS_IS) {
+                       podule->irq_addr = address[52] + (address[56] << 8) + (address[60] << 16);
+                       podule->irq_mask = address[48];
+                       podule->fiq_addr = address[36] + (address[40] << 8) + (address[44] << 16);
+                       podule->fiq_mask = address[32];
+               } else {
+                       podule->irq_addr = 0;
+                       podule->irq_mask = 0;
+                       podule->fiq_addr = 0;
+                       podule->fiq_mask = 0;
+               }
+               podule->fast_base = FAST_PODULE_BASE + offset;
+               podule->medium_base = MEDIUM_PODULE_BASE + offset;
+               podule->slow_base = SLOW_PODULE_BASE + offset;
+               podule->sync_base = SYNC_PODULE_BASE + offset;
+               podule->mod_base = MOD_PODULE_BASE + offset;
+               podule->easi_base = EASI_BASE + loop * EASI_SIZE;
+               podule->attached = 0;
+               podule->slottype = SLOT_NONE;
+               podule->podulenum = loop;
+
+               poduleexamine(podule, dev, SLOT_POD);
+       }
+}
+
+
+void
+netslotscan(dev)
+       struct device *dev;
+{
+       podule_t *podule;
+       volatile u_char *address;
+
+/* Only one netslot atm */
+
+/* Reset the address counter */
+
+       WriteByte(NETSLOT_BASE, 0x00);
+
+       address = (u_char *)NETSLOT_BASE;
+
+       podule = &podules[MAX_PODULES];
+
+/* Get information from the podule header */
+
+       podule->flags0 = *address;
+       podule->flags1 = *address;
+       podule->reserved = *address;
+       podule->product = *address + (*address << 8);
+       podule->manufacturer = *address + (*address << 8);
+       podule->country = *address;
+       if (podule->flags1 & PODULE_FLAGS_IS) {
+               podule->irq_mask = *address;
+               podule->irq_addr = *address + (*address << 8) + (*address << 16);
+               podule->fiq_mask = *address;
+               podule->fiq_addr = *address + (*address << 8) + (*address << 16);
+       } else {
+               podule->irq_addr = 0;
+               podule->irq_mask = 0;
+               podule->fiq_addr = 0;
+               podule->fiq_mask = 0;
+       }
+       podule->fast_base = NETSLOT_BASE;
+       podule->medium_base = NETSLOT_BASE;
+       podule->slow_base = NETSLOT_BASE;
+       podule->sync_base = NETSLOT_BASE;
+       podule->mod_base = NETSLOT_BASE;
+       podule->easi_base = 0;
+       podule->attached = 0;
+       podule->slottype = SLOT_NONE;
+       podule->podulenum = MAX_PODULES;
+
+       poduleexamine(podule, dev, SLOT_NET);
+}
+
+
+/*
+ * void podulebusattach(struct device *parent, struct device *dev, void *aux)
+ *
+ * Attach podulebus.
+ * This probes all the podules and sets up the podules array with
+ * information found in the podule headers.
+ * After identifing all the podules, all the children of the podulebus
+ * are probed and attached.
+ */
+  
+void
+podulebusattach(parent, self, aux)
+       struct device *parent;
+       struct device *self;
+       void *aux;
+{
+       int loop;
+    
+       printf("\n");
+
+/* Ok we need to map in the podulebus */
+
+/* Map the FAST and SYNC simple podules */
+
+       map_section(PAGE_DIRS_BASE, SYNC_PODULE_BASE & 0xfff00000,
+           SYNC_PODULE_HW_BASE & 0xfff00000);
+
+/* Now map the EASI space */
+
+       for (loop = 0; loop < MAX_PODULES; ++loop) {
+               int loop1;
+        
+               for (loop1 = loop * EASI_SIZE; loop1 < ((loop + 1) * EASI_SIZE); loop1 += (1 << 20))
+               map_section(PAGE_DIRS_BASE, EASI_BASE + loop1, EASI_HW_BASE + loop1);
+       }
+
+/*
+ * The MEDIUM and SLOW simple podules and the module space will have been
+ * mapped when the IOMD and COMBO we mapped in for the RPC
+ */
+
+/* Install an podule IRQ handler */
+
+       poduleirq.ih_func = poduleirqhandler;
+       poduleirq.ih_arg = NULL;
+       poduleirq.ih_level = IPL_NONE;
+       poduleirq.ih_name = "podulebus";
+
+       if (irq_claim(IRQ_PODULE, &poduleirq))
+               panic("Cannot claim IRQ for podulebus%d\n", IRQ_PODULE, parent->dv_unit);
+
+/* Find out what hardware is bolted on */
+
+       podulescan(self); 
+       netslotscan(self);
+
+/* Look for drivers */
+
+       config_scan(podulebusscan, self);
+}
+
+
+/*
+ * int podule_irqhandler(void *arg)
+ *
+ * text irq handler to service expansion card IRQ's
+ *
+ * There is currently a problem here.
+ * The spl_mask may mask out certain expansion card IRQ's e.g. SCSI
+ * but allow others e.g. Ethernet.
+ */
+
+int
+poduleirqhandler()
+{
+       int loop;
+       irqhandler_t *handler;
+
+       printf("eek ! Unknown podule IRQ received - Blocking all podule interrupts\n");
+       disable_irq(IRQ_PODULE);
+       return(1);
+
+/* Loop round the expansion card handlers */
+
+       for (loop = IRQ_EXPCARD0; loop <= IRQ_EXPCARD7; ++loop) {
+
+/* Is the IRQ currently allowable */
+
+               if (actual_mask & (1 << loop)) {
+                       handler = irqhandlers[loop];
+        
+                       if (handler && handler->ih_irqmask) {
+                               if ((*handler->ih_irqmask) & handler->ih_irqbit)
+                                       handler->ih_func(handler->ih_arg);
+                       }
+               }
+       }
+       return(1);      
+}
+
+struct cfattach podulebus_ca = {
+       sizeof(struct device), podulebusmatch, podulebusattach
+};
+
+struct cfdriver podulebus_cd = {
+       NULL, "podulebus", DV_DULL, 1
+};
+
+
+/* Useful functions that drivers may share */
+
+/*
+ * Search the podule list for the specified manufacturer and product.
+ * Return the podule number if the podule is not already attach and
+ * the podule was in the required slot.
+ * A required slot of -1 means any slot.
+ */
+
+int
+findpodule(manufacturer, product, required_slot)
+       int manufacturer;
+       int product;
+       int required_slot;
+{
+       int loop;
+
+       for (loop = 0; loop < MAX_PODULES+MAX_NETSLOTS; ++loop) {
+               if (podules[loop].slottype != SLOT_NONE
+                   && !podules[loop].attached
+                   && podules[loop].manufacturer == manufacturer
+                   && podules[loop].product == product
+                   && (required_slot == -1 || required_slot == loop))
+                       return(loop);
+       }
+      
+       return(-1);
+}
+
+/* End of podulebus.c */
diff --git a/sys/arch/arm32/podulebus/podulebus.h b/sys/arch/arm32/podulebus/podulebus.h
new file mode 100644 (file)
index 0000000..0b0c638
--- /dev/null
@@ -0,0 +1,114 @@
+/* $NetBSD: podulebus.h,v 1.2 1996/03/18 21:23:18 mark Exp $ */
+
+/*
+ * Copyright (c) 1995 Mark Brinicombe.
+ * Copyright (c) 1995 Brini.
+ * 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 Brini.
+ * 4. The name of the company nor the name of the author may be used to
+ *    endorse or promote products derived from this software without specific
+ *    prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BRINI ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL BRINI 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.
+ *
+ * RiscBSD kernel project
+ *
+ * podulebus.h
+ *
+ * Podule bus header file
+ *
+ * Created      : 26/04/95
+ */
+
+#include <sys/param.h>
+
+/* Define the structures used to describe the "known" podules */
+
+struct podule_description {
+       int product_id;
+       char *description;
+};
+
+struct podule_list {
+       int manufacturer_id;
+       char *description;
+       struct podule_description *products;
+};
+
+/* Define the structure used to describe a podule */
+
+typedef struct {
+/* The podule header, read from the on board ROM */
+
+       u_char flags0;
+       u_char flags1;
+       u_char reserved;
+       u_short product;
+       u_short manufacturer;
+       u_char country;
+       u_int irq_addr;
+       u_int irq_mask;
+       u_int fiq_addr;
+       u_int fiq_mask;
+
+/* The base addresses for this podule */
+
+       u_int fast_base;
+       u_int medium_base;
+       u_int slow_base;
+       u_int sync_base;
+       u_int mod_base;
+       u_int easi_base;
+
+/* Flags */
+
+       int podulenum; 
+       int slottype;
+       int attached;
+} podule_t;
+
+#define PODULE_FLAGS_CD        0x01
+#define PODULE_FLAGS_IS        0x02
+
+#define SLOT_NONE 0x00
+#define SLOT_POD  0x01
+#define SLOT_NET  0x02
+
+struct podule_attach_args {
+       podule_t *pa_podule;
+       int pa_podule_number;
+       int pa_slottype;
+};
+  
+#ifdef _KERNEL
+
+/* Array of podule structures, one per possible podule */
+
+extern podule_t podules[MAX_PODULES + MAX_NETSLOTS];
+
+int findpodule __P((int, int, int));
+
+#endif
+
+/* End of podulebus.h */
diff --git a/sys/arch/arm32/podulebus/ptsc.c b/sys/arch/arm32/podulebus/ptsc.c
new file mode 100644 (file)
index 0000000..f13c928
--- /dev/null
@@ -0,0 +1,485 @@
+/* $NetBSD: ptsc.c,v 1.2 1996/03/17 01:24:54 thorpej Exp $ */
+
+/*
+ * Copyright (c) 1995 Scott Stevens
+ * Copyright (c) 1995 Daniel Widenfalk
+ * Copyright (c) 1994 Christian E. Hopps
+ * Copyright (c) 1982, 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     @(#)ptsc.c
+ */
+/*
+ * Power-tec SCSI-2 driver
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/device.h>
+#include <scsi/scsi_all.h>
+#include <scsi/scsiconf.h>
+#include <vm/vm.h>
+#include <vm/vm_kern.h>
+#include <vm/vm_page.h>
+#include <machine/pmap.h>
+#include <machine/io.h>
+#include <machine/irqhandler.h>
+#include <arm32/podulebus/podulebus.h>
+#include <arm32/podulebus/sfasreg.h>
+#include <arm32/podulebus/sfasvar.h>
+#include <arm32/podulebus/ptscreg.h>
+#include <arm32/podulebus/ptscvar.h>
+
+int  ptscprint  __P((void *auxp, char *));
+void ptscattach __P((struct device *, struct device *, void *));
+int  ptscmatch  __P((struct device *, void *, void *));
+int ptsc_scsicmd __P((struct scsi_xfer *));
+
+struct scsi_adapter ptsc_scsiswitch = {
+       ptsc_scsicmd,
+       sfas_minphys,
+       0,                      /* no lun support */
+       0,                      /* no lun support */
+};
+
+struct scsi_device ptsc_scsidev = {
+       NULL,           /* use default error handler */
+       NULL,           /* do not have a start functio */
+       NULL,           /* have no async handler */
+       NULL,           /* Use default done routine */
+};
+
+struct cfattach ptsc_ca = {
+       sizeof(struct ptsc_softc), ptscmatch, ptscattach
+};
+
+struct cfdriver ptsc_cd = {
+       NULL, "ptsc", DV_DULL, NULL, 0
+};
+
+int ptsc_intr           __P((struct sfas_softc *dev));
+int ptsc_setup_dma      __P((struct sfas_softc *sc, void *ptr, int len,
+                             int mode));
+int ptsc_build_dma_chain __P((struct sfas_softc *sc,
+                             struct sfas_dma_chain *chain, void *p, int l));
+int ptsc_need_bump      __P((struct sfas_softc *sc, void *ptr, int len));
+void ptsc_led           __P((struct sfas_softc *sc, int mode));
+
+/*
+ * if we are a Power-tec SCSI-2 card
+ */
+int
+ptscmatch(pdp, match, auxp)
+       struct device   *pdp;
+       void            *match, *auxp;
+{
+       struct podule_attach_args *pa = (struct podule_attach_args *)auxp;
+       int podule;
+
+       podule = findpodule(0x5b, 0x107, pa->pa_podule_number);
+
+       if (podule == -1)
+         return(0);
+
+       pa->pa_podule_number = podule;
+       pa->pa_podule = &podules[podule];
+
+       return(1);
+}
+
+void
+ptscattach(pdp, dp, auxp)
+       struct device   *pdp;
+       struct device   *dp;
+       void            *auxp;
+{
+       struct ptsc_softc *sc = (struct ptsc_softc *)dp;
+       struct podule_attach_args  *pa;
+       ptsc_regmap_p      rp = &sc->sc_regmap;
+       vu_char           *fas;
+
+       pa = (struct podule_attach_args *)auxp;
+       sc->sc_specific.sc_podule_number = pa->pa_podule_number;
+       if (sc->sc_specific.sc_podule_number == -1)
+         panic("Podule has disappeared !");
+
+       sc->sc_specific.sc_podule = &podules[sc->sc_specific.sc_podule_number];
+       sc->sc_specific.sc_iobase =
+         (vu_char *)sc->sc_specific.sc_podule->fast_base;
+
+       rp->chipreset = &sc->sc_specific.sc_iobase[PTSC_CONTROL_CHIPRESET];
+       rp->inten = &sc->sc_specific.sc_iobase[PTSC_CONTROL_INTEN];
+       rp->status = &sc->sc_specific.sc_iobase[PTSC_STATUS];
+       rp->term = &sc->sc_specific.sc_iobase[PTSC_CONTROL_TERM];
+       rp->led = &sc->sc_specific.sc_iobase[PTSC_CONTROL_LED];
+       fas = &sc->sc_specific.sc_iobase[PTSC_FASOFFSET_BASE];
+
+       rp->FAS216.sfas_tc_low  = &fas[PTSC_FASOFFSET_TCL];
+       rp->FAS216.sfas_tc_mid  = &fas[PTSC_FASOFFSET_TCM];
+       rp->FAS216.sfas_fifo    = &fas[PTSC_FASOFFSET_FIFO];
+       rp->FAS216.sfas_command = &fas[PTSC_FASOFFSET_COMMAND];
+       rp->FAS216.sfas_dest_id = &fas[PTSC_FASOFFSET_DESTID];
+       rp->FAS216.sfas_timeout = &fas[PTSC_FASOFFSET_TIMEOUT];
+       rp->FAS216.sfas_syncper = &fas[PTSC_FASOFFSET_PERIOD];
+       rp->FAS216.sfas_syncoff = &fas[PTSC_FASOFFSET_OFFSET];
+       rp->FAS216.sfas_config1 = &fas[PTSC_FASOFFSET_CONFIG1];
+       rp->FAS216.sfas_clkconv = &fas[PTSC_FASOFFSET_CLOCKCONV];
+       rp->FAS216.sfas_test    = &fas[PTSC_FASOFFSET_TEST];
+       rp->FAS216.sfas_config2 = &fas[PTSC_FASOFFSET_CONFIG2];
+       rp->FAS216.sfas_config3 = &fas[PTSC_FASOFFSET_CONFIG3];
+       rp->FAS216.sfas_tc_high = &fas[PTSC_FASOFFSET_TCH];
+       rp->FAS216.sfas_fifo_bot = &fas[PTSC_FASOFFSET_FIFOBOTTOM];
+
+       sc->sc_softc.sc_fas     = (sfas_regmap_p)rp;
+       sc->sc_softc.sc_spec    = &sc->sc_specific;
+
+       sc->sc_softc.sc_led     = ptsc_led;
+
+       sc->sc_softc.sc_setup_dma       = ptsc_setup_dma;
+       sc->sc_softc.sc_build_dma_chain = ptsc_build_dma_chain;
+       sc->sc_softc.sc_need_bump       = ptsc_need_bump;
+
+       sc->sc_softc.sc_clock_freq   = 8;   /* Power-Tec runs at 8MHz */
+       sc->sc_softc.sc_timeout      = 250;  /* Set default timeout to 250ms */
+       sc->sc_softc.sc_config_flags = SFAS_NO_DMA /*| SFAS_NF_DEBUG*/;
+       sc->sc_softc.sc_host_id      = 7;    /* Should check the jumpers */
+
+       sc->sc_softc.sc_bump_sz = NBPG;
+       sc->sc_softc.sc_bump_pa = 0x0;
+
+       sfasinitialize((struct sfas_softc *)sc);
+
+       sc->sc_softc.sc_link.adapter_softc  = sc;
+       sc->sc_softc.sc_link.adapter_target = sc->sc_softc.sc_host_id;
+       sc->sc_softc.sc_link.adapter        = &ptsc_scsiswitch;
+       sc->sc_softc.sc_link.device         = &ptsc_scsidev;
+       sc->sc_softc.sc_link.openings       = 1;
+
+       sc->sc_softc.sc_ih.ih_func = ptsc_intr;
+       sc->sc_softc.sc_ih.ih_arg  = &sc->sc_softc;
+       sc->sc_softc.sc_ih.ih_level = IPL_BIO;
+
+/* initialise the card */
+       *rp->term = 0;
+       *rp->inten = (PTSC_POLL?0:1);
+       *rp->led = 0;
+
+#if PTSC_POLL == 0
+       if (irq_claim(IRQ_PODULE /*IRQ_EXPCARD0 + sc->sc_specific.sc_podule_number */,
+                     &sc->sc_softc.sc_ih))
+           panic("ptsc: Cannot install IRQ handler\n");
+#endif
+       
+       printf("\n");
+
+/* attach all scsi units on us */
+       config_found(dp, &sc->sc_softc.sc_link, ptscprint);
+}
+
+/* print diag if pnp is NULL else just extra */
+int
+ptscprint(auxp, pnp)
+       void *auxp;
+       char *pnp;
+{
+       if (pnp == NULL)
+               return(UNCONF);
+
+       return(QUIET);
+}
+
+int
+ptsc_intr(dev)
+       struct sfas_softc *dev;
+{
+       ptsc_regmap_p         rp;
+       int                   quickints;
+
+       rp = (ptsc_regmap_p)dev->sc_fas;
+
+       if (*rp->FAS216.sfas_status & SFAS_STAT_INTERRUPT_PENDING) {
+               quickints = 16;
+               do {
+                       dev->sc_status = *rp->FAS216.sfas_status;
+                       dev->sc_interrupt = *rp->FAS216.sfas_interrupt;
+         
+                       if (dev->sc_interrupt & SFAS_INT_RESELECTED) {
+                               dev->sc_resel[0] = *rp->FAS216.sfas_fifo;
+                               dev->sc_resel[1] = *rp->FAS216.sfas_fifo;
+                       }
+
+                       sfasintr(dev);
+
+               } while((*rp->FAS216.sfas_status & SFAS_STAT_INTERRUPT_PENDING)
+                       && --quickints);
+       }
+
+       return(1);
+}
+
+/* Load transfer address into dma register */
+void
+ptsc_set_dma_adr(sc, ptr)
+       struct sfas_softc *sc;
+       void             *ptr;
+{
+       ptsc_regmap_p   rp;
+       unsigned int   *p;
+       unsigned int    d;
+
+#if 0
+       printf("ptsc_set_dma_adr(sc = 0x%08x, ptr = 0x%08x)\n", (u_int)sc, (u_int)ptr);
+#endif
+       return;
+#if 0
+       rp = (ptsc_regmap_p)sc->sc_fas;
+
+       d = (unsigned int)ptr;
+       p = (unsigned int *)((d & 0xFFFFFF) + (int)rp->dmabase);
+
+       *rp->clear=0;
+       *p = d;
+#endif
+}
+
+/* Set DMA transfer counter */
+void
+ptsc_set_dma_tc(sc, len)
+       struct sfas_softc *sc;
+       unsigned int      len;
+{
+       printf("ptsc_set_dma_tc(sc, len = 0x%08x)", len);
+
+       *sc->sc_fas->sfas_tc_low  = len; len >>= 8;
+       *sc->sc_fas->sfas_tc_mid  = len; len >>= 8;
+       *sc->sc_fas->sfas_tc_high = len;
+}
+
+/* Set DMA mode */
+void
+ptsc_set_dma_mode(sc, mode)
+       struct sfas_softc *sc;
+       int               mode;
+{
+       struct csc_specific *spec;
+
+#if 0
+       spec = sc->sc_spec;
+
+       spec->portbits = (spec->portbits & ~FLSC_PB_DMA_BITS) | mode;
+       *((flsc_regmap_p)sc->sc_fas)->hardbits = spec->portbits;
+#endif
+}
+
+/* Initialize DMA for transfer */
+int
+ptsc_setup_dma(sc, ptr, len, mode)
+       struct sfas_softc *sc;
+       void             *ptr;
+       int               len;
+       int               mode;
+{
+       int     retval;
+
+       retval = 0;
+
+#if 0
+       printf("ptsc_setup_dma(sc, ptr = 0x%08x, len = 0x%08x, mode = 0x%08x)\n", (u_int)ptr, len, mode);
+#endif
+       return(0);
+
+#if 0
+       switch(mode) {
+       case SFAS_DMA_READ:
+       case SFAS_DMA_WRITE:
+               flsc_set_dma_adr(sc, ptr);
+               if (mode == SFAS_DMA_READ)
+                 flsc_set_dma_mode(sc,FLSC_PB_ENABLE_DMA | FLSC_PB_DMA_READ);
+               else
+                 flsc_set_dma_mode(sc,FLSC_PB_ENABLE_DMA | FLSC_PB_DMA_WRITE);
+
+               flsc_set_dma_tc(sc, len);
+               break;
+
+       case SFAS_DMA_CLEAR:
+       default:
+               flsc_set_dma_mode(sc, FLSC_PB_DISABLE_DMA);
+               flsc_set_dma_adr(sc, 0);
+
+               retval = (*sc->sc_fas->sfas_tc_high << 16) |
+                        (*sc->sc_fas->sfas_tc_mid  <<  8) |
+                         *sc->sc_fas->sfas_tc_low;
+
+               flsc_set_dma_tc(sc, 0);
+               break;
+       }
+
+       return(retval);
+#endif
+}
+
+/* Check if address and len is ok for DMA transfer */
+int
+ptsc_need_bump(sc, ptr, len)
+       struct sfas_softc *sc;
+       void             *ptr;
+       int               len;
+{
+       int     p;
+
+       p = (int)ptr & 0x03;
+
+       if (p) {
+               p = 4-p;
+           
+               if (len < 256)
+                       p = len;
+       }
+
+       return(p);
+}
+
+/* Interrupt driven routines */
+int
+ptsc_build_dma_chain(sc, chain, p, l)
+       struct sfas_softc       *sc;
+       struct sfas_dma_chain   *chain;
+       void                    *p;
+       int                      l;
+{
+       vm_offset_t  pa, lastpa;
+       char        *ptr;
+       int          len, prelen, postlen, max_t, n;
+
+#if 0
+       printf("ptsc_build_dma_chain()\n");
+#endif
+       return(0);
+
+#if 0
+       if (l == 0)
+               return(0);
+
+#define set_link(n, p, l, f)\
+do { chain[n].ptr = (p); chain[n].len = (l); chain[n++].flg = (f); } while(0)
+
+       n = 0;
+
+       if (l < 512)
+               set_link(n, (vm_offset_t)p, l, SFAS_CHAIN_BUMP);
+       else if ((p >= (void *)0xFF000000)
+#if M68040
+                && ((mmutype == MMU_68040) && (p >= (void *)0xFFFC0000))
+#endif
+                ) {
+               while(l != 0) {
+                       len = ((l > sc->sc_bump_sz) ? sc->sc_bump_sz : l);
+         
+                       set_link(n, (vm_offset_t)p, len, SFAS_CHAIN_BUMP);
+         
+                       p += len;
+                       l -= len;
+               }
+       } else {
+               ptr = p;
+               len = l;
+
+               pa = kvtop(ptr);
+               prelen = ((int)ptr & 0x03);
+
+               if (prelen) {
+                       prelen = 4-prelen;
+                       set_link(n, (vm_offset_t)ptr, prelen, SFAS_CHAIN_BUMP);
+                       ptr += prelen;
+                       len -= prelen;
+               }
+
+               lastpa = 0;
+               while(len > 3) {
+                       pa = kvtop(ptr);
+                       max_t = NBPG - (pa & PGOFSET);
+                       if (max_t > len)
+                         max_t = len;
+
+                       max_t &= ~3;
+
+                       if (lastpa == pa)
+                               sc->sc_chain[n-1].len += max_t;
+                       else
+                               set_link(n, pa, max_t, SFAS_CHAIN_DMA);
+         
+                       lastpa = pa+max_t;
+         
+                       ptr += max_t;
+                       len -= max_t;
+               }
+      
+               if (len)
+                       set_link(n, (vm_offset_t)ptr, len, SFAS_CHAIN_BUMP);
+       }
+
+       return(n);
+#endif
+}
+
+/* Turn on/off led */
+void
+ptsc_led(sc, mode)
+       struct sfas_softc *sc;
+       int               mode;
+{
+       ptsc_regmap_p           rp;
+
+       rp = (ptsc_regmap_p)sc->sc_fas;
+
+       if (mode) {
+               sc->sc_led_status++;
+       } else {
+               if (sc->sc_led_status)
+                       sc->sc_led_status--;
+       }
+       *rp->led = (sc->sc_led_status?1:0);
+}
+
+int
+ptsc_scsicmd(xs)
+       struct scsi_xfer *xs;
+{
+       /* ensure command is polling for the moment */
+#if PTSC_POLL > 0
+       xs->flags |= SCSI_POLL;
+#endif
+#if 0
+       printf("Opcode %d\n", (int)(xs->cmd->opcode));
+#endif
+       return(sfas_scsicmd(xs));
+}
diff --git a/sys/arch/arm32/podulebus/ptscreg.h b/sys/arch/arm32/podulebus/ptscreg.h
new file mode 100644 (file)
index 0000000..81f01b7
--- /dev/null
@@ -0,0 +1,77 @@
+/* $NetBSD: ptscreg.h,v 1.1 1996/01/31 23:26:35 mark Exp $ */
+
+/*
+ * Copyright (c) 1995 Scott Stevens
+ * Copyright (c) 1995 Daniel Widenfalk
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided 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 Daniel Widenfalk
+ *      for the NetBSD Project.
+ * 4. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/*
+ * Power-tec SCSI-2 with FAS216 SCSI interface hardware description.
+ */
+
+#ifndef _PTSCREG_H_
+#define _PTSCREG_H_
+
+#include <arm32/podulebus/sfasvar.h>
+
+typedef volatile unsigned short vu_short;
+
+typedef struct ptsc_regmap {
+       sfas_regmap_t   FAS216;
+       vu_char         *chipreset;
+       vu_char         *inten;
+       vu_char         *status;
+       vu_char         *term;
+       vu_char         *led;
+} ptsc_regmap_t;
+typedef ptsc_regmap_t *ptsc_regmap_p;
+
+/* NDA Information */
+#define PTSC_CONTROL_CHIPRESET         0x1018
+#define        PTSC_CONTROL_INTEN              0x101c
+#define PTSC_STATUS                    0x2000
+#define PTSC_CONTROL_TERM              0x2018
+#define PTSC_CONTROL_LED               0x201c
+#define PTSC_FASOFFSET_BASE            0x3000
+#define PTSC_FASOFFSET_TCL             0x0000
+#define PTSC_FASOFFSET_TCM             0x0040
+#define PTSC_FASOFFSET_FIFO            0x0080
+#define PTSC_FASOFFSET_COMMAND         0x00c0
+#define PTSC_FASOFFSET_DESTID          0x0100
+#define PTSC_FASOFFSET_TIMEOUT         0x0140
+#define PTSC_FASOFFSET_PERIOD          0x0180
+#define PTSC_FASOFFSET_OFFSET          0x01c0
+#define PTSC_FASOFFSET_CONFIG1         0x0200
+#define PTSC_FASOFFSET_CLOCKCONV       0x0240
+#define PTSC_FASOFFSET_TEST            0x0280
+#define PTSC_FASOFFSET_CONFIG2         0x02c0
+#define PTSC_FASOFFSET_CONFIG3         0x0300
+#define PTSC_FASOFFSET_TCH             0x0380
+#define PTSC_FASOFFSET_FIFOBOTTOM      0x03c0
+/* NDA Info end */
+#endif
diff --git a/sys/arch/arm32/podulebus/ptscvar.h b/sys/arch/arm32/podulebus/ptscvar.h
new file mode 100644 (file)
index 0000000..6608eaf
--- /dev/null
@@ -0,0 +1,52 @@
+/* $NetBSD: ptscvar.h,v 1.1 1996/01/31 23:26:38 mark Exp $ */
+
+/*
+ * Copyright (c) 1995 Scott Stevens
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided 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 Daniel Widenfalk
+ *      for the NetBSD Project.
+ * 4. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef _PTSCVAR_H_
+#define _PTSCVAR_H_
+
+#include <arm32/podulebus/sfasvar.h>
+#include <arm32/podulebus/ptscreg.h>
+
+#define PTSC_POLL 1
+
+struct ptsc_specific {
+    vu_char            *sc_iobase;
+    int                        sc_podule_number;
+    podule_t           *sc_podule;
+};
+
+struct ptsc_softc {
+       struct sfas_softc       sc_softc;
+       ptsc_regmap_t           sc_regmap;
+       struct ptsc_specific    sc_specific;
+};
+
+#endif /* _PTSCVAR_H_ */
diff --git a/sys/arch/arm32/podulebus/sbic.c b/sys/arch/arm32/podulebus/sbic.c
new file mode 100644 (file)
index 0000000..b4d5b09
--- /dev/null
@@ -0,0 +1,2947 @@
+/* $NetBSD: sbic.c,v 1.2 1996/04/19 20:09:50 mark Exp $ */
+
+/*
+ * Copyright (c) 1994 Christian E. Hopps
+ * Copyright (c) 1990 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.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided 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: sbic.c,v 1.21 1996/01/07 22:01:54
+ */
+#define DEBUG
+/*#define SBIC_DEBUG*/
+/*
+ * AMIGA AMD 33C93 scsi adaptor driver
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/device.h>
+#include <sys/kernel.h> /* For hz */
+#include <sys/disklabel.h>
+#include <sys/dkstat.h>
+#include <sys/buf.h>
+#include <scsi/scsi_all.h>
+#include <scsi/scsiconf.h>
+#include <vm/vm.h>
+#include <vm/vm_kern.h>
+#include <vm/vm_page.h>
+/*#include <machine/pmap.h>
+#include <machine/cpu.h>*/
+#include <machine/io.h>
+#include <machine/irqhandler.h>
+#include <arm32/podulebus/podulebus.h>
+#include <arm32/podulebus/sbicreg.h>
+#include <arm32/podulebus/sbicvar.h>
+#include <arm32/podulebus/ascreg.h>
+
+/* These are for bounce buffers */
+
+/*#include <vm/pmap.h>*/
+
+/* Since I can't find this in any other header files */
+#define SCSI_PHASE(reg)        (reg&0x07)
+
+/*
+ * SCSI delays
+ * In u-seconds, primarily for state changes on the SPC.
+ */
+#define        SBIC_CMD_WAIT   50000   /* wait per step of 'immediate' cmds */
+#define        SBIC_DATA_WAIT  50000   /* wait per data in/out step */
+#define        SBIC_INIT_WAIT  50000   /* wait per step (both) during init */
+
+#define        b_cylin         b_resid
+#define SBIC_WAIT(regs, until, timeo) sbicwait(regs, until, timeo, __LINE__)
+
+extern u_int kvtop();
+
+int  sbicicmd __P((struct sbic_softc *, int, int, void *, int, void *, int));
+int  sbicgo __P((struct sbic_softc *, struct scsi_xfer *));
+int  sbicdmaok __P((struct sbic_softc *, struct scsi_xfer *));
+int  sbicwait __P((sbic_regmap_p, char, int , int));
+int  sbiccheckdmap __P((void *, u_long, u_long));
+int  sbicselectbus __P((struct sbic_softc *, sbic_regmap_p, u_char, u_char, u_char));
+int  sbicxfstart __P((sbic_regmap_p, int, u_char, int));
+int  sbicxfout __P((sbic_regmap_p regs, int, void *, int));
+int  sbicfromscsiperiod __P((struct sbic_softc *, sbic_regmap_p, int));
+int  sbictoscsiperiod __P((struct sbic_softc *, sbic_regmap_p, int));
+int  sbicintr __P((struct sbic_softc *));
+int  sbicpoll __P((struct sbic_softc *));
+int  sbicnextstate __P((struct sbic_softc *, u_char, u_char));
+int  sbicmsgin __P((struct sbic_softc *));
+int  sbicxfin __P((sbic_regmap_p regs, int, void *));
+int  sbicabort __P((struct sbic_softc *, sbic_regmap_p, char *));
+void sbicxfdone __P((struct sbic_softc *, sbic_regmap_p, int));
+void sbicerror __P((struct sbic_softc *, sbic_regmap_p, u_char));
+void sbicstart __P((struct sbic_softc *));
+void sbicreset __P((struct sbic_softc *));
+void sbic_scsidone __P((struct sbic_acb *, int));
+void sbic_sched __P((struct sbic_softc *));
+void sbic_save_ptrs __P((struct sbic_softc *, sbic_regmap_p,int,int));
+void sbic_load_ptrs __P((struct sbic_softc *, sbic_regmap_p,int,int));
+
+/*
+ * Synch xfer parameters, and timing conversions
+ */
+int sbic_min_period = SBIC_SYN_MIN_PERIOD;  /* in cycles = f(ICLK,FSn) */
+int sbic_max_offset = SBIC_SYN_MAX_OFFSET;  /* pure number */
+
+int sbic_cmd_wait = SBIC_CMD_WAIT;
+int sbic_data_wait = SBIC_DATA_WAIT;
+int sbic_init_wait = SBIC_INIT_WAIT;
+
+/*
+ * was broken before.. now if you want this you get it for all drives
+ * on sbic controllers.
+ */
+u_char sbic_inhibit_sync[8];
+int sbic_enable_reselect = 1;
+int sbic_clock_override = 0;
+int sbic_no_dma = 1;   /* was 0 */
+int sbic_parallel_operations = 1;
+
+#ifdef DEBUG
+sbic_regmap_p debug_sbic_regs;
+int    sbicdma_ops = 0;        /* total DMA operations */
+int    sbicdma_bounces = 0;    /* number operations using bounce buffer */
+int    sbicdma_hits = 0;       /* number of DMA chains that were contiguous */
+int    sbicdma_misses = 0;     /* number of DMA chains that were not contiguous */
+int     sbicdma_saves = 0;
+#define QPRINTF(a) if (sbic_debug > 1) printf a
+int    sbic_debug = 0;
+int    sync_debug = 0;
+int    sbic_dma_debug = 0;
+int    reselect_debug = 0;
+int    report_sense = 0;
+int    data_pointer_debug = 0;
+u_char debug_asr, debug_csr, routine;
+void sbictimeout __P((struct sbic_softc *dev));
+void sbic_dump __P((struct sbic_softc *dev));
+
+#define CSR_TRACE_SIZE 32
+#if CSR_TRACE_SIZE
+#define CSR_TRACE(w,c,a,x) do { \
+       int s = splbio(); \
+       csr_trace[csr_traceptr].whr = (w); csr_trace[csr_traceptr].csr = (c); \
+       csr_trace[csr_traceptr].asr = (a); csr_trace[csr_traceptr].xtn = (x); \
+/*     dma_cachectl(&csr_trace[csr_traceptr], sizeof(csr_trace[0]));*/ \
+       csr_traceptr = (csr_traceptr + 1) & (CSR_TRACE_SIZE - 1); \
+/*     dma_cachectl(&csr_traceptr, sizeof(csr_traceptr));*/ \
+       splx(s); \
+} while (0)
+int csr_traceptr;
+int csr_tracesize = CSR_TRACE_SIZE;
+struct {
+       u_char whr;
+       u_char csr;
+       u_char asr;
+       u_char xtn;
+} csr_trace[CSR_TRACE_SIZE];
+#else
+#define CSR_TRACE
+#endif
+
+#define SBIC_TRACE_SIZE 0
+#if SBIC_TRACE_SIZE
+#define SBIC_TRACE(dev) do { \
+       int s = splbio(); \
+       sbic_trace[sbic_traceptr].sp = &s; \
+       sbic_trace[sbic_traceptr].line = __LINE__; \
+       sbic_trace[sbic_traceptr].sr = s; \
+       sbic_trace[sbic_traceptr].csr = csr_traceptr; \
+/*     dma_cachectl(&sbic_trace[sbic_traceptr], sizeof(sbic_trace[0]));*/ \
+       sbic_traceptr = (sbic_traceptr + 1) & (SBIC_TRACE_SIZE - 1); \
+/*     dma_cachectl(&sbic_traceptr, sizeof(sbic_traceptr));*/ \
+       if (dev) dma_cachectl(dev, sizeof(*dev)); \
+       splx(s); \
+} while (0)
+int sbic_traceptr;
+int sbic_tracesize = SBIC_TRACE_SIZE;
+struct {
+       void *sp;
+       u_short line;
+       u_short sr;
+       int csr;
+} sbic_trace[SBIC_TRACE_SIZE];
+#else
+#define SBIC_TRACE
+#endif
+
+#else
+#define QPRINTF
+#define CSR_TRACE
+#define SBIC_TRACE
+#endif
+
+/*
+ * default minphys routine for sbic based controllers
+ */
+void
+sbic_minphys(bp)
+       struct buf *bp;
+{
+
+       /*
+        * No max transfer at this level.
+        */
+       minphys(bp);
+}
+
+/*
+ * Save DMA pointers.  Take into account partial transfer. Shut down DMA.
+ */
+void
+sbic_save_ptrs(dev, regs, target, lun)
+       struct sbic_softc *dev;
+       sbic_regmap_p regs;
+       int target, lun;
+{
+       int count, asr, csr, s;
+       unsigned long ptr;
+       char *vptr;
+       struct sbic_acb* acb;
+
+       extern vm_offset_t vm_first_phys;
+
+       SBIC_TRACE(dev);
+       if( !dev->sc_cur ) return;
+       if( !(dev->sc_flags & SBICF_INDMA) ) return; /* DMA not active */
+
+       s = splbio();
+
+       acb = dev->sc_nexus;
+       count = -1;
+       do {
+               GET_SBIC_asr(regs, asr);
+               if( asr & SBIC_ASR_DBR ) {
+                       printf("sbic_save_ptrs: asr %02x canceled!\n", asr);
+                       splx(s);
+                       SBIC_TRACE(dev);
+                       return;
+               }
+       } while( asr & (SBIC_ASR_BSY|SBIC_ASR_CIP) );
+
+       /* Save important state */
+       /* must be done before dmastop */
+       acb->sc_dmacmd = dev->sc_dmacmd;
+       SBIC_TC_GET(regs, count);
+
+       /* Shut down DMA ====CAREFUL==== */
+       dev->sc_dmastop(dev);
+       dev->sc_flags &= ~SBICF_INDMA;
+       SBIC_TC_PUT(regs, 0);
+
+#ifdef DEBUG
+       if(!count && sbic_debug) printf("%dcount0",target);
+       if(data_pointer_debug == -1)
+               printf("SBIC saving target %d data pointers from (%x,%x)%xASR:%02x",
+                      target, dev->sc_cur->dc_addr, dev->sc_cur->dc_count,
+                      acb->sc_dmacmd, asr);
+#endif
+
+       /* Fixup partial xfers */
+       acb->sc_kv.dc_addr += (dev->sc_tcnt - count);
+       acb->sc_kv.dc_count -= (dev->sc_tcnt - count);
+       acb->sc_pa.dc_addr += (dev->sc_tcnt - count);
+       acb->sc_pa.dc_count -= ((dev->sc_tcnt - count)>>1);
+
+       acb->sc_tcnt = dev->sc_tcnt = count;
+#ifdef DEBUG
+       if(data_pointer_debug)
+               printf(" at (%x,%x):%x\n",
+                      dev->sc_cur->dc_addr, dev->sc_cur->dc_count,count);
+       sbicdma_saves++;
+#endif
+       splx(s);
+       SBIC_TRACE(dev);
+}
+
+
+/*
+ * DOES NOT RESTART DMA!!!
+ */
+void sbic_load_ptrs(dev, regs, target, lun)
+       struct sbic_softc *dev;
+       sbic_regmap_p regs;
+       int target, lun;
+{
+       int i, s, asr, count;
+       char* vaddr, * paddr;
+       struct sbic_acb *acb;
+
+       SBIC_TRACE(dev);
+       acb = dev->sc_nexus;
+       if( !acb->sc_kv.dc_count ) {
+               /* No data to xfer */
+               SBIC_TRACE(dev);
+               return;
+       }
+
+       s = splbio();
+
+       dev->sc_last = dev->sc_cur = &acb->sc_pa;
+       dev->sc_tcnt = acb->sc_tcnt;
+       dev->sc_dmacmd = acb->sc_dmacmd;
+
+#ifdef DEBUG
+       sbicdma_ops++;
+#endif
+       if( !dev->sc_tcnt ) {
+               /* sc_tcnt == 0 implies end of segment */
+
+               /* do kvm to pa mappings */
+#if 0 /* mark */
+               paddr = acb->sc_pa.dc_addr =
+                       (char *) kvtop(acb->sc_kv.dc_addr);
+#endif
+               vaddr = acb->sc_kv.dc_addr;
+               count = acb->sc_kv.dc_count;
+#if 0 /* mark */
+               for(count = (NBPG - ((int)vaddr & PGOFSET));
+                   count < acb->sc_kv.dc_count
+                   && (char*)kvtop(vaddr + count + 4) == paddr + count + 4;
+                   count += NBPG);
+#endif
+               /* If it's all contiguous... */
+               if(count > acb->sc_kv.dc_count ) {
+                       count = acb->sc_kv.dc_count;
+#ifdef DEBUG
+                       sbicdma_hits++;
+#endif
+               } else {
+#ifdef DEBUG
+                       sbicdma_misses++;
+#endif
+               }
+               acb->sc_tcnt = count;
+               acb->sc_pa.dc_count = count >> 1;
+
+#ifdef DEBUG
+               if(data_pointer_debug)
+                       printf("DMA recalc:kv(%x,%x)pa(%x,%x)\n",
+                              acb->sc_kv.dc_addr,
+                              acb->sc_kv.dc_count,
+                              acb->sc_pa.dc_addr,
+                              acb->sc_tcnt);
+#endif
+       }
+       splx(s);
+#ifdef DEBUG
+       if(data_pointer_debug)
+               printf("SBIC restoring target %d data pointers at (%x,%x)%x\n",
+                      target, dev->sc_cur->dc_addr, dev->sc_cur->dc_count,
+                      dev->sc_dmacmd);
+#endif
+       SBIC_TRACE(dev);
+}
+
+/*
+ * used by specific sbic controller
+ *
+ * it appears that the higher level code does nothing with LUN's
+ * so I will too.  I could plug it in, however so could they
+ * in scsi_scsi_cmd().
+ */
+int
+sbic_scsicmd(xs)
+       struct scsi_xfer *xs;
+{
+       struct sbic_acb *acb;
+       struct sbic_softc *dev;
+       struct scsi_link *slp;
+       int flags, s, stat;
+
+       slp = xs->sc_link;
+       dev = slp->adapter_softc;
+       SBIC_TRACE(dev);
+       flags = xs->flags;
+
+       if (flags & SCSI_DATA_UIO)
+               panic("sbic: scsi data uio requested");
+
+       if (dev->sc_nexus && flags & SCSI_POLL)
+               panic("sbic_scsicmd: busy");
+
+       if (slp->target == slp->adapter_target)
+               return ESCAPE_NOT_SUPPORTED;
+
+       s = splbio();
+       acb = dev->free_list.tqh_first;
+       if (acb)
+               TAILQ_REMOVE(&dev->free_list, acb, chain);
+       splx(s);
+
+       if (acb == NULL) {
+#ifdef DEBUG
+               printf("sbic_scsicmd: unable to queue request for target %d\n",
+                   slp->target);
+#ifdef DDB
+               Debugger();
+#endif
+#endif
+               xs->error = XS_DRIVER_STUFFUP;
+               SBIC_TRACE(dev);
+               return(TRY_AGAIN_LATER);
+       }
+
+       acb->flags = ACB_ACTIVE;
+       if (flags & SCSI_DATA_IN)
+               acb->flags |= ACB_DATAIN;
+       acb->xs = xs;
+       bcopy(xs->cmd, &acb->cmd, xs->cmdlen);
+       acb->clen = xs->cmdlen;
+       acb->sc_kv.dc_addr = xs->data;
+       acb->sc_kv.dc_count = xs->datalen;
+#if 0
+       acb->pa_addr = xs->data ? (char *)kvtop(xs->data) : 0;  /* XXXX check */
+#endif
+       if (flags & SCSI_POLL) {
+               s = splbio();
+               /*
+                * This has major side effects -- it locks up the machine
+                */
+
+               dev->sc_flags |= SBICF_ICMD;
+               do {
+                       while(dev->sc_nexus)
+                               sbicpoll(dev);
+                       dev->sc_nexus = acb;
+                       dev->sc_stat[0] = -1;
+                       dev->sc_xs = xs;
+                       dev->target = slp->target;
+                       dev->lun = slp->lun;
+                       stat = sbicicmd(dev, slp->target, slp->lun,
+                                       &acb->cmd, acb->clen,
+                                       acb->sc_kv.dc_addr, acb->sc_kv.dc_count);
+               } while (dev->sc_nexus != acb);
+               sbic_scsidone(acb, stat);
+
+               splx(s);
+               SBIC_TRACE(dev);
+               return(COMPLETE);
+       }
+
+       s = splbio();
+       TAILQ_INSERT_TAIL(&dev->ready_list, acb, chain);
+
+       if (dev->sc_nexus) {
+               splx(s);
+               SBIC_TRACE(dev);
+               return(SUCCESSFULLY_QUEUED);
+       }
+
+       /*
+        * nothing is active, try to start it now.
+        */
+       sbic_sched(dev);
+       splx(s);
+
+       SBIC_TRACE(dev);
+/* TODO:  add sbic_poll to do SCSI_POLL operations */
+#if 0
+       if (flags & SCSI_POLL)
+               return(COMPLETE);
+#endif
+       return(SUCCESSFULLY_QUEUED);
+}
+
+/*
+ * attempt to start the next available command
+ */
+void
+sbic_sched(dev)
+       struct sbic_softc *dev;
+{
+       struct scsi_xfer *xs;
+       struct scsi_link *slp;
+       struct sbic_acb *acb;
+       int flags, /*phase,*/ stat, i;
+
+       SBIC_TRACE(dev);
+       if (dev->sc_nexus)
+               return;                 /* a command is current active */
+
+       SBIC_TRACE(dev);
+       for (acb = dev->ready_list.tqh_first; acb; acb = acb->chain.tqe_next) {
+               slp = acb->xs->sc_link;
+               i = slp->target;
+               if (!(dev->sc_tinfo[i].lubusy & (1 << slp->lun))) {
+                       struct sbic_tinfo *ti = &dev->sc_tinfo[i];
+
+                       TAILQ_REMOVE(&dev->ready_list, acb, chain);
+                       dev->sc_nexus = acb;
+                       slp = acb->xs->sc_link;
+                       ti = &dev->sc_tinfo[slp->target];
+                       ti->lubusy |= (1 << slp->lun);
+                       acb->sc_pa.dc_addr = acb->pa_addr;      /* XXXX check */
+                       break;
+               }
+       }
+
+       SBIC_TRACE(dev);
+       if (acb == NULL)
+               return;                 /* did not find an available command */
+
+       dev->sc_xs = xs = acb->xs;
+       slp = xs->sc_link;
+       flags = xs->flags;
+
+       if (flags & SCSI_RESET)
+               sbicreset(dev);
+
+#ifdef DEBUG
+       if( data_pointer_debug > 1 )
+               printf("sbic_sched(%d,%d)\n",slp->target,slp->lun);
+#endif
+       dev->sc_stat[0] = -1;
+       dev->target = slp->target;
+       dev->lun = slp->lun;
+       if ( flags & SCSI_POLL || ( !sbic_parallel_operations
+                                  && (/*phase == STATUS_PHASE ||*/
+                                      sbicdmaok(dev, xs) == 0) ) )
+               stat = sbicicmd(dev, slp->target, slp->lun, &acb->cmd,
+                   acb->clen, acb->sc_kv.dc_addr, acb->sc_kv.dc_count);
+       else if (sbicgo(dev, xs) == 0) {
+               SBIC_TRACE(dev);
+               return;
+       } else
+               stat = dev->sc_stat[0];
+
+       sbic_scsidone(acb, stat);
+       SBIC_TRACE(dev);
+}
+
+void
+sbic_scsidone(acb, stat)
+       struct sbic_acb *acb;
+       int stat;
+{
+       struct scsi_xfer *xs;
+       struct scsi_link *slp;
+       struct sbic_softc *dev;
+       int s, dosched = 0;
+
+       xs = acb->xs;
+       slp = xs->sc_link;
+       dev = slp->adapter_softc;
+       SBIC_TRACE(dev);
+#ifdef DIAGNOSTIC
+       if (acb == NULL || xs == NULL) {
+               printf("sbic_scsidone -- (%d,%d) no scsi_xfer\n",
+                      dev->target, dev->lun);
+#ifdef DDB
+               Debugger();
+#endif
+               return;
+       }
+#endif
+       /*
+        * XXX Support old-style instrumentation for now.
+        * IS THIS REALLY THE RIGHT PLACE FOR THIS?  --thorpej
+        */
+       if (slp->device_softc &&
+           ((struct device *)(slp->device_softc))->dv_unit < dk_ndrive)
+               ++dk_xfer[((struct device *)(slp->device_softc))->dv_unit];
+       /*
+        * is this right?
+        */
+       xs->status = stat;
+
+#ifdef DEBUG
+       if( data_pointer_debug > 1 )
+               printf("scsidone: (%d,%d)->(%d,%d)%02x\n",
+                      slp->target, slp->lun,
+                      dev->target,  dev->lun,  stat);
+       if( xs->sc_link->target == dev->sc_link.adapter_target )
+               panic("target == hostid");
+#endif
+
+       if (xs->error == XS_NOERROR && !(acb->flags & ACB_CHKSENSE)) {
+               if (stat == SCSI_CHECK) {
+                       /* Schedule a REQUEST SENSE */
+                       struct scsi_sense *ss = (void *)&acb->cmd;
+#ifdef DEBUG
+                       if (report_sense)
+                               printf("sbic_scsidone: autosense %02x targ %d lun %d",
+                                   acb->cmd.opcode, slp->target, slp->lun);
+#endif
+                       bzero(ss, sizeof(*ss));
+                       ss->opcode = REQUEST_SENSE;
+                       ss->byte2 = slp->lun << 5;
+                       ss->length = sizeof(struct scsi_sense_data);
+                       acb->clen = sizeof(*ss);
+                       acb->sc_kv.dc_addr = (char *)&xs->sense;
+                       acb->sc_kv.dc_count = sizeof(struct scsi_sense_data);
+#if 0
+                       acb->pa_addr = (char *)kvtop(&xs->sense); /* XXX check */
+#endif
+                       acb->flags = ACB_ACTIVE | ACB_CHKSENSE | ACB_DATAIN;
+                       TAILQ_INSERT_HEAD(&dev->ready_list, acb, chain);
+                       dev->sc_tinfo[slp->target].lubusy &=
+                           ~(1 << slp->lun);
+                       dev->sc_tinfo[slp->target].senses++;
+                       if (dev->sc_nexus == acb) {
+                               dev->sc_nexus = NULL;
+                               dev->sc_xs = NULL;
+                               sbic_sched(dev);
+                       }
+                       SBIC_TRACE(dev);
+                       return;
+               }
+       }
+       if (xs->error == XS_NOERROR && (acb->flags & ACB_CHKSENSE)) {
+               xs->error = XS_SENSE;
+#ifdef DEBUG
+               if (report_sense)
+                       printf(" => %02x %02x\n", xs->sense.flags,
+                           xs->sense.extra_bytes[3]);
+#endif
+       } else {
+               xs->resid = 0;          /* XXXX */
+       }
+#if whataboutthisone
+               case SCSI_BUSY:
+                       xs->error = XS_BUSY;
+                       break;
+#endif
+       xs->flags |= ITSDONE;
+
+       /*
+        * Remove the ACB from whatever queue it's on.  We have to do a bit of
+        * a hack to figure out which queue it's on.  Note that it is *not*
+        * necessary to cdr down the ready queue, but we must cdr down the
+        * nexus queue and see if it's there, so we can mark the unit as no
+        * longer busy.  This code is sickening, but it works.
+        */
+       if (acb == dev->sc_nexus) {
+               dev->sc_nexus = NULL;
+               dev->sc_xs = NULL;
+               dev->sc_tinfo[slp->target].lubusy &= ~(1<<slp->lun);
+               if (dev->ready_list.tqh_first)
+                       dosched = 1;    /* start next command */
+       } else if (dev->ready_list.tqh_last == &acb->chain.tqe_next) {
+               TAILQ_REMOVE(&dev->ready_list, acb, chain);
+       } else {
+               register struct sbic_acb *acb2;
+               for (acb2 = dev->nexus_list.tqh_first; acb2;
+                   acb2 = acb2->chain.tqe_next) {
+                       if (acb2 == acb) {
+                               TAILQ_REMOVE(&dev->nexus_list, acb, chain);
+                               dev->sc_tinfo[slp->target].lubusy
+                                       &= ~(1<<slp->lun);
+                               break;
+                       }
+               }
+               if (acb2)
+                       ;
+               else if (acb->chain.tqe_next) {
+                       TAILQ_REMOVE(&dev->ready_list, acb, chain);
+               } else {
+                       printf("%s: can't find matching acb\n",
+                           dev->sc_dev.dv_xname);
+#ifdef DDB
+                       Debugger();
+#endif
+               }
+       }
+       /* Put it on the free list. */
+       acb->flags = ACB_FREE;
+       TAILQ_INSERT_HEAD(&dev->free_list, acb, chain);
+
+       dev->sc_tinfo[slp->target].cmds++;
+
+       scsi_done(xs);
+
+       if (dosched)
+               sbic_sched(dev);
+       SBIC_TRACE(dev);
+}
+
+int
+sbicdmaok(dev, xs)
+       struct sbic_softc *dev;
+       struct scsi_xfer *xs;
+{
+       if (sbic_no_dma || xs->datalen & 0x1 || (u_int)xs->data & 0x3)
+               return(0);
+       /*
+        * controller supports dma to any addresses?
+        */
+       else if ((dev->sc_flags & SBICF_BADDMA) == 0)
+               return(1);
+       /*
+        * this address is ok for dma?
+        */
+       else if (sbiccheckdmap(xs->data, xs->datalen, dev->sc_dmamask) == 0)
+               return(1);
+       /*
+        * we have a bounce buffer?
+        */
+       else if (dev->sc_tinfo[xs->sc_link->target].bounce)
+               return(1);
+       /*
+        * try to get one
+        */
+       else if (dev->sc_tinfo[xs->sc_link->target].bounce
+                = (char *)alloc_z2mem(MAXPHYS)) {
+               if (isztwomem(dev->sc_tinfo[xs->sc_link->target].bounce))
+                       printf("alloc ZII target %d bounce pa 0x%x\n",
+                              xs->sc_link->target,
+                              kvtop(dev->sc_tinfo[xs->sc_link->target].bounce));
+               else if (dev->sc_tinfo[xs->sc_link->target].bounce)
+                       printf("alloc CHIP target %d bounce pa 0x%x\n",
+                              xs->sc_link->target,
+                              PREP_DMA_MEM(dev->sc_tinfo[xs->sc_link->target].bounce));
+               return(1);
+       }
+
+       return(0);
+}
+
+
+int
+sbicwait(regs, until, timeo, line)
+       sbic_regmap_p regs;
+       char until;
+       int timeo;
+       int line;
+{
+       u_char val;
+       int csr;
+
+       SBIC_TRACE((struct sbic_softc *)0);
+       if (timeo == 0)
+               timeo = 1000000;        /* some large value.. */
+
+       GET_SBIC_asr(regs,val);
+       while ((val & until) == 0) {
+               if (timeo-- == 0) {
+                       GET_SBIC_csr(regs, csr);
+                       printf("sbicwait TIMEO @%d with asr=x%x csr=x%x\n",
+                           line, val, csr);
+#if defined(DDB) && defined(DEBUG)
+                       Debugger();
+#endif
+                       return(val); /* Maybe I should abort */
+                       break;
+               }
+               DELAY(1);
+               GET_SBIC_asr(regs,val);
+       }
+       SBIC_TRACE((struct sbic_softc *)0);
+       return(val);
+}
+
+int
+sbicabort(dev, regs, where)
+       struct sbic_softc *dev;
+       sbic_regmap_p regs;
+       char *where;
+{
+       u_char csr, asr;
+
+       GET_SBIC_asr(regs, asr);
+       GET_SBIC_csr(regs, csr);
+
+       printf ("%s: abort %s: csr = 0x%02x, asr = 0x%02x\n",
+           dev->sc_dev.dv_xname, where, csr, asr);
+
+
+#if 0
+       /* Clean up running command */
+       if (dev->sc_nexus != NULL) {
+               dev->sc_nexus->xs->error = XS_DRIVER_STUFFUP;
+               sbic_scsidone(dev->sc_nexus, dev->sc_stat[0]);
+       }
+       while (acb = dev->nexus_list.tqh_first) {
+               acb->xs->error = XS_DRIVER_STUFFUP;
+               sbic_scsidone(acb, -1 /*acb->stat[0]*/);
+       }
+#endif
+
+       /* Clean up chip itself */
+       if (dev->sc_flags & SBICF_SELECTED) {
+               while( asr & SBIC_ASR_DBR ) {
+                       /* sbic is jammed w/data. need to clear it */
+                       /* But we don't know what direction it needs to go */
+                       GET_SBIC_data(regs, asr);
+                       printf("%s: abort %s: clearing data buffer 0x%02x\n",
+                              dev->sc_dev.dv_xname, where, asr);
+                       GET_SBIC_asr(regs, asr);
+                       if( asr & SBIC_ASR_DBR ) /* Not the read direction, then */
+                               SET_SBIC_data(regs, asr);
+                       GET_SBIC_asr(regs, asr);
+               }
+               WAIT_CIP(regs);
+printf("%s: sbicabort - sending ABORT command\n", dev->sc_dev.dv_xname);
+               SET_SBIC_cmd(regs, SBIC_CMD_ABORT);
+               WAIT_CIP(regs);
+
+               GET_SBIC_asr(regs, asr);
+               if (asr & (SBIC_ASR_BSY|SBIC_ASR_LCI)) {
+                       /* ok, get more drastic.. */
+
+printf("%s: sbicabort - asr %x, trying to reset\n", dev->sc_dev.dv_xname, asr);
+                       sbicreset(dev);
+                       dev->sc_flags &= ~SBICF_SELECTED;
+                       return -1;
+               }
+printf("%s: sbicabort - sending DISC command\n", dev->sc_dev.dv_xname);
+               SET_SBIC_cmd(regs, SBIC_CMD_DISC);
+
+               do {
+                       asr = SBIC_WAIT (regs, SBIC_ASR_INT, 0);
+                       GET_SBIC_csr (regs, csr);
+                       CSR_TRACE('a',csr,asr,0);
+               } while ((csr != SBIC_CSR_DISC) && (csr != SBIC_CSR_DISC_1)
+                   && (csr != SBIC_CSR_CMD_INVALID));
+
+               /* lets just hope it worked.. */
+               dev->sc_flags &= ~SBICF_SELECTED;
+       }
+       return -1;
+}
+
+
+/*
+ * Initialize driver-private structures
+ */
+
+void
+sbicinit(dev)
+       struct sbic_softc *dev;
+{
+       sbic_regmap_p regs;
+       u_int my_id, i, s;
+       u_char csr;
+       struct sbic_acb *acb;
+       u_int inhibit_sync;
+
+       extern u_long scsi_nosync;
+       extern int shift_nosync;
+
+#ifdef SBIC_DEBUG
+       printf("sbicinit:\n");
+#endif
+
+       regs = dev->sc_sbicp;
+
+       if ((dev->sc_flags & SBICF_ALIVE) == 0) {
+               TAILQ_INIT(&dev->ready_list);
+               TAILQ_INIT(&dev->nexus_list);
+               TAILQ_INIT(&dev->free_list);
+               dev->sc_nexus = NULL;
+               dev->sc_xs = NULL;
+               acb = dev->sc_acb;
+               bzero(acb, sizeof(dev->sc_acb));
+#ifdef SBIC_DEBUG
+               printf("sbicinit: %d\n", __LINE__);
+#endif
+
+               for (i = 0; i < sizeof(dev->sc_acb) / sizeof(*acb); i++) {
+                       TAILQ_INSERT_TAIL(&dev->free_list, acb, chain);
+                       acb++;
+               }
+               bzero(dev->sc_tinfo, sizeof(dev->sc_tinfo));
+#ifdef DEBUG
+               /* make sure timeout is really not needed */
+               timeout((void *)sbictimeout, dev, 30 * hz);
+#endif
+
+       } else panic("sbic: reinitializing driver!");
+
+#ifdef SBIC_DEBUG
+       printf("sbicinit: %d\n", __LINE__);
+#endif
+
+       dev->sc_flags |= SBICF_ALIVE;
+       dev->sc_flags &= ~SBICF_SELECTED;
+
+       /* initialize inhibit array */
+       if (scsi_nosync) {
+#ifdef SBIC_DEBUG
+               printf("sbicinit: %d\n", __LINE__);
+#endif
+               inhibit_sync = (scsi_nosync >> shift_nosync) & 0xff;
+               shift_nosync += 8;
+#ifdef DEBUG
+               if (inhibit_sync)
+                       printf("%s: Inhibiting synchronous transfer %02x\n",
+                               dev->sc_dev.dv_xname, inhibit_sync);
+#endif
+               for (i = 0; i < 8; ++i)
+                       if (inhibit_sync & (1 << i))
+                               sbic_inhibit_sync[i] = 1;
+       }
+
+#ifdef SBIC_DEBUG
+       printf("sbicinit: %d\n", __LINE__);
+#endif
+
+       sbicreset(dev);
+}
+
+void
+sbicreset(dev)
+       struct sbic_softc *dev;
+{
+       sbic_regmap_p regs;
+       u_int my_id, i, s;
+       u_char csr;
+       struct sbic_acb *acb;
+
+#ifdef SBIC_DEBUG
+       printf("sbicreset: %d\n", __LINE__);
+#endif
+
+       regs = dev->sc_sbicp;
+
+#ifdef SBIC_DEBUG
+       printf("sbicreset: regs = %08x\n", regs);
+#endif
+#if 0
+       if (dev->sc_flags & SBICF_ALIVE) {
+               SET_SBIC_cmd(regs, SBIC_CMD_ABORT);
+               WAIT_CIP(regs);
+       }
+#else
+               SET_SBIC_cmd(regs, SBIC_CMD_ABORT);
+#ifdef SBIC_DEBUG
+               printf("sbicreset: %d\n", __LINE__);
+#endif
+               WAIT_CIP(regs);
+#ifdef SBIC_DEBUG
+               printf("sbicreset: %d\n", __LINE__);
+#endif
+#endif
+       s = splbio();
+       my_id = dev->sc_link.adapter_target & SBIC_ID_MASK;
+
+       /* Enable advanced mode */
+       my_id |= SBIC_ID_EAF /*| SBIC_ID_EHP*/ ;
+       SET_SBIC_myid(regs, my_id);
+#ifdef SBIC_DEBUG
+       printf("sbicreset: %d\n", __LINE__);
+#endif
+
+       /*
+        * Disable interrupts (in dmainit) then reset the chip
+        */
+       SET_SBIC_cmd(regs, SBIC_CMD_RESET);
+       DELAY(25);
+       SBIC_WAIT(regs, SBIC_ASR_INT, 0);
+       GET_SBIC_csr(regs, csr);       /* clears interrupt also */
+
+       if (dev->sc_clkfreq < 110)
+               my_id |= SBIC_ID_FS_8_10;
+       else if (dev->sc_clkfreq < 160)
+               my_id |= SBIC_ID_FS_12_15;
+       else if (dev->sc_clkfreq < 210)
+               my_id |= SBIC_ID_FS_16_20;
+
+       SET_SBIC_myid(regs, my_id);
+#ifdef SBIC_DEBUG
+       printf("sbicreset: %d\n", __LINE__);
+#endif
+
+       /*
+        * Set up various chip parameters
+        */
+       SET_SBIC_control(regs, SBIC_CTL_EDI | SBIC_CTL_IDI /* | SBIC_CTL_HSP */
+           | SBIC_MACHINE_DMA_MODE);
+       /*
+        * don't allow (re)selection (SBIC_RID_ES)
+        * until we can handle target mode!!
+        */
+       SET_SBIC_rselid(regs, SBIC_RID_ER);
+       SET_SBIC_syn(regs, 0);     /* asynch for now */
+
+       /*
+        * anything else was zeroed by reset
+        */
+       splx(s);
+
+#if 0
+       if ((dev->sc_flags & SBICF_ALIVE) == 0) {
+               TAILQ_INIT(&dev->ready_list);
+               TAILQ_INIT(&dev->nexus_list);
+               TAILQ_INIT(&dev->free_list);
+               dev->sc_nexus = NULL;
+               dev->sc_xs = NULL;
+               acb = dev->sc_acb;
+               bzero(acb, sizeof(dev->sc_acb));
+               for (i = 0; i < sizeof(dev->sc_acb) / sizeof(*acb); i++) {
+                       TAILQ_INSERT_TAIL(&dev->free_list, acb, chain);
+                       acb++;
+               }
+               bzero(dev->sc_tinfo, sizeof(dev->sc_tinfo));
+       } else {
+               if (dev->sc_nexus != NULL) {
+                       dev->sc_nexus->xs->error = XS_DRIVER_STUFFUP;
+                       sbic_scsidone(dev->sc_nexus, dev->sc_stat[0]);
+               }
+               while (acb = dev->nexus_list.tqh_first) {
+                       acb->xs->error = XS_DRIVER_STUFFUP;
+                       sbic_scsidone(acb, -1 /*acb->stat[0]*/);
+               }
+       }
+
+       dev->sc_flags |= SBICF_ALIVE;
+#endif
+       dev->sc_flags &= ~SBICF_SELECTED;
+}
+
+void
+sbicerror(dev, regs, csr)
+       struct sbic_softc *dev;
+       sbic_regmap_p regs;
+       u_char csr;
+{
+       struct scsi_xfer *xs;
+
+       xs = dev->sc_xs;
+
+#ifdef DIAGNOSTIC
+       if (xs == NULL)
+               panic("sbicerror");
+#endif
+       if (xs->flags & SCSI_SILENT)
+               return;
+
+       printf("%s: ", dev->sc_dev.dv_xname);
+       printf("csr == 0x%02x\n", csr); /* XXX */
+}
+
+/*
+ * select the bus, return when selected or error.
+ */
+int
+sbicselectbus(dev, regs, target, lun, our_addr)
+        struct sbic_softc *dev;
+       sbic_regmap_p regs;
+       u_char target, lun, our_addr;
+{
+       u_char asr, csr, id;
+
+       SBIC_TRACE(dev);
+       QPRINTF(("sbicselectbus %d\n", target));
+
+       /*
+        * if we're already selected, return (XXXX panic maybe?)
+        */
+       if (dev->sc_flags & SBICF_SELECTED) {
+               SBIC_TRACE(dev);
+               return(1);
+       }
+
+       /*
+        * issue select
+        */
+       SBIC_TC_PUT(regs, 0);
+       SET_SBIC_selid(regs, target);
+       SET_SBIC_timeo(regs, SBIC_TIMEOUT(250,dev->sc_clkfreq));
+
+       /*
+        * set sync or async
+        */
+       if (dev->sc_sync[target].state == SYNC_DONE)
+               SET_SBIC_syn(regs, SBIC_SYN (dev->sc_sync[target].offset,
+                   dev->sc_sync[target].period));
+       else
+               SET_SBIC_syn(regs, SBIC_SYN (0, sbic_min_period));
+
+       GET_SBIC_asr(regs, asr);
+       if( asr & (SBIC_ASR_INT|SBIC_ASR_BSY) ) {
+               /* This means we got ourselves reselected upon */
+/*             printf("sbicselectbus: INT/BSY asr %02x\n", asr);*/
+#ifdef DDB
+/*             Debugger();*/
+#endif
+               SBIC_TRACE(dev);
+               return 1;
+       }
+
+       SET_SBIC_cmd(regs, SBIC_CMD_SEL_ATN);
+
+       /*
+        * wait for select (merged from seperate function may need
+        * cleanup)
+        */
+       WAIT_CIP(regs);
+       do {
+               asr = SBIC_WAIT(regs, SBIC_ASR_INT | SBIC_ASR_LCI, 0);
+               if (asr & SBIC_ASR_LCI) {
+#ifdef DEBUG
+                       if (reselect_debug)
+                               printf("sbicselectbus: late LCI asr %02x\n", asr);
+#endif
+                       SBIC_TRACE(dev);
+                       return 1;
+               }
+               GET_SBIC_csr (regs, csr);
+               CSR_TRACE('s',csr,asr,target);
+               QPRINTF(("%02x ", csr));
+               if( csr == SBIC_CSR_RSLT_NI || csr == SBIC_CSR_RSLT_IFY) {
+#ifdef DEBUG
+                       if(reselect_debug)
+                               printf("sbicselectbus: reselected asr %02x\n", asr);
+#endif
+                       /* We need to handle this now so we don't lock up later */
+                       sbicnextstate(dev, csr, asr);
+                       SBIC_TRACE(dev);
+                       return 1;
+               }
+               if( csr == SBIC_CSR_SLT || csr == SBIC_CSR_SLT_ATN) {
+                       panic("sbicselectbus: target issued select!");
+                       return 1;
+               }
+       } while (csr != (SBIC_CSR_MIS_2|MESG_OUT_PHASE)
+           && csr != (SBIC_CSR_MIS_2|CMD_PHASE) && csr != SBIC_CSR_SEL_TIMEO);
+
+       /* Enable (or not) reselection */
+       if(!sbic_enable_reselect && dev->nexus_list.tqh_first == NULL)
+               SET_SBIC_rselid (regs, 0);
+       else
+               SET_SBIC_rselid (regs, SBIC_RID_ER);
+
+       if (csr == (SBIC_CSR_MIS_2|CMD_PHASE)) {
+               dev->sc_flags |= SBICF_SELECTED;        /* device ignored ATN */
+               GET_SBIC_selid(regs, id);
+               dev->target = id;
+               GET_SBIC_tlun(regs,dev->lun);
+               if( dev->lun & SBIC_TLUN_VALID )
+                       dev->lun &= SBIC_TLUN_MASK;
+               else
+                       dev->lun = lun;
+       } else if (csr == (SBIC_CSR_MIS_2|MESG_OUT_PHASE)) {
+               /*
+                * Send identify message
+                * (SCSI-2 requires an identify msg (?))
+                */
+               GET_SBIC_selid(regs, id);
+               dev->target = id;
+               GET_SBIC_tlun(regs,dev->lun);
+               if( dev->lun & SBIC_TLUN_VALID )
+                       dev->lun &= SBIC_TLUN_MASK;
+               else
+                       dev->lun = lun;
+               /*
+                * handle drives that don't want to be asked
+                * whether to go sync at all.
+                */
+               if (sbic_inhibit_sync[id]
+                   && dev->sc_sync[id].state == SYNC_START) {
+#ifdef DEBUG
+                       if (sync_debug)
+                               printf("Forcing target %d asynchronous.\n", id);
+#endif
+                       dev->sc_sync[id].offset = 0;
+                       dev->sc_sync[id].period = sbic_min_period;
+                       dev->sc_sync[id].state = SYNC_DONE;
+               }
+
+
+               if (dev->sc_sync[id].state != SYNC_START){
+                       if( dev->sc_xs->flags & SCSI_POLL
+                          || (dev->sc_flags & SBICF_ICMD)
+                          || !sbic_enable_reselect )
+                               SEND_BYTE (regs, MSG_IDENTIFY | lun);
+                       else
+                               SEND_BYTE (regs, MSG_IDENTIFY_DR | lun);
+               } else {
+                       /*
+                        * try to initiate a sync transfer.
+                        * So compose the sync message we're going
+                        * to send to the target
+                        */
+
+#ifdef DEBUG
+                       if (sync_debug)
+                               printf("Sending sync request to target %d ... ",
+                                   id);
+#endif
+                       /*
+                        * setup scsi message sync message request
+                        */
+                       dev->sc_msg[0] = MSG_IDENTIFY | lun;
+                       dev->sc_msg[1] = MSG_EXT_MESSAGE;
+                       dev->sc_msg[2] = 3;
+                       dev->sc_msg[3] = MSG_SYNC_REQ;
+                       dev->sc_msg[4] = sbictoscsiperiod(dev, regs,
+                           sbic_min_period);
+                       dev->sc_msg[5] = sbic_max_offset;
+
+                       if (sbicxfstart(regs, 6, MESG_OUT_PHASE, sbic_cmd_wait))
+                               sbicxfout(regs, 6, dev->sc_msg, MESG_OUT_PHASE);
+
+                       dev->sc_sync[id].state = SYNC_SENT;
+#ifdef DEBUG
+                       if (sync_debug)
+                               printf ("sent\n");
+#endif
+               }
+
+               asr = SBIC_WAIT (regs, SBIC_ASR_INT, 0);
+               GET_SBIC_csr (regs, csr);
+               CSR_TRACE('y',csr,asr,target);
+               QPRINTF(("[%02x]", csr));
+#ifdef DEBUG
+               if (sync_debug && dev->sc_sync[id].state == SYNC_SENT)
+                       printf("csr-result of last msgout: 0x%x\n", csr);
+#endif
+
+               if (csr != SBIC_CSR_SEL_TIMEO)
+                       dev->sc_flags |= SBICF_SELECTED;
+       }
+       if (csr == SBIC_CSR_SEL_TIMEO)
+               dev->sc_xs->error = XS_SELTIMEOUT;
+
+       QPRINTF(("\n"));
+
+       SBIC_TRACE(dev);
+       return(csr == SBIC_CSR_SEL_TIMEO);
+}
+
+int
+sbicxfstart(regs, len, phase, wait)
+       sbic_regmap_p regs;
+       int len, wait;
+       u_char phase;
+{
+       u_char id;
+
+       switch (phase) {
+       case DATA_IN_PHASE:
+       case MESG_IN_PHASE:
+               GET_SBIC_selid (regs, id);
+               id |= SBIC_SID_FROM_SCSI;
+               SET_SBIC_selid (regs, id);
+               SBIC_TC_PUT (regs, (unsigned)len);
+               break;
+       case DATA_OUT_PHASE:
+       case MESG_OUT_PHASE:
+       case CMD_PHASE:
+               GET_SBIC_selid (regs, id);
+               id &= ~SBIC_SID_FROM_SCSI;
+               SET_SBIC_selid (regs, id);
+               SBIC_TC_PUT (regs, (unsigned)len);
+               break;
+       default:
+               SBIC_TC_PUT (regs, 0);
+       }
+       QPRINTF(("sbicxfstart %d, %d, %d\n", len, phase, wait));
+
+       return(1);
+}
+
+int
+sbicxfout(regs, len, bp, phase)
+       sbic_regmap_p regs;
+       int len;
+       void *bp;
+       int phase;
+{
+       u_char orig_csr, csr, asr, *buf;
+       int wait;
+
+       buf = bp;
+       wait = sbic_data_wait;
+
+       QPRINTF(("sbicxfout {%d} %02x %02x %02x %02x %02x "
+           "%02x %02x %02x %02x %02x\n", len, buf[0], buf[1], buf[2],
+           buf[3], buf[4], buf[5], buf[6], buf[7], buf[8], buf[9]));
+
+       GET_SBIC_csr (regs, orig_csr);
+       CSR_TRACE('>',orig_csr,0,0);
+
+       /*
+        * sigh.. WD-PROTO strikes again.. sending the command in one go
+        * causes the chip to lock up if talking to certain (misbehaving?)
+        * targets. Anyway, this procedure should work for all targets, but
+        * it's slightly slower due to the overhead
+        */
+       WAIT_CIP (regs);
+       SET_SBIC_cmd (regs, SBIC_CMD_XFER_INFO);
+       for (;len > 0; len--) {
+               GET_SBIC_asr (regs, asr);
+               while ((asr & SBIC_ASR_DBR) == 0) {
+                       if ((asr & SBIC_ASR_INT) || --wait < 0) {
+#ifdef DEBUG
+                               if (sbic_debug)
+                                       printf("sbicxfout fail: l%d i%x w%d\n",
+                                           len, asr, wait);
+#endif
+                               return (len);
+                       }
+/*                     DELAY(1);*/
+                       GET_SBIC_asr (regs, asr);
+               }
+
+               SET_SBIC_data (regs, *buf);
+               buf++;
+       }
+       SBIC_TC_GET(regs, len);
+       QPRINTF(("sbicxfout done %d bytes\n", len));
+       /*
+        * this leaves with one csr to be read
+        */
+       return(0);
+}
+
+/* returns # bytes left to read */
+int
+sbicxfin(regs, len, bp)
+       sbic_regmap_p regs;
+       int len;
+       void *bp;
+{
+       int wait, read;
+       u_char *obp, *buf;
+       u_char orig_csr, csr, asr;
+
+       wait = sbic_data_wait;
+       obp = bp;
+       buf = bp;
+
+       GET_SBIC_csr (regs, orig_csr);
+       CSR_TRACE('<',orig_csr,0,0);
+
+       QPRINTF(("sbicxfin %d, csr=%02x\n", len, orig_csr));
+
+       WAIT_CIP (regs);
+       SET_SBIC_cmd (regs, SBIC_CMD_XFER_INFO);
+       for (;len > 0; len--) {
+               GET_SBIC_asr (regs, asr);
+               if((asr & SBIC_ASR_PE)) {
+#ifdef DEBUG
+                       printf("sbicxfin parity error: l%d i%x w%d\n",
+                              len, asr, wait);
+/*                     return ((unsigned long)buf - (unsigned long)bp); */
+#ifdef DDB
+                       Debugger();
+#endif
+#endif
+               }
+               while ((asr & SBIC_ASR_DBR) == 0) {
+                       if ((asr & SBIC_ASR_INT) || --wait < 0) {
+#ifdef DEBUG
+                               if (sbic_debug) {
+       QPRINTF(("sbicxfin fail:{%d} %02x %02x %02x %02x %02x %02x "
+           "%02x %02x %02x %02x\n", len, obp[0], obp[1], obp[2],
+           obp[3], obp[4], obp[5], obp[6], obp[7], obp[8], obp[9]));
+                                       printf("sbicxfin fail: l%d i%x w%d\n",
+                                           len, asr, wait);
+}
+#endif
+                               return len;
+                       }
+
+                       if( ! asr & SBIC_ASR_BSY ) {
+                               GET_SBIC_csr(regs, csr);
+                               CSR_TRACE('<',csr,asr,len);
+                               QPRINTF(("[CSR%02xASR%02x]", csr, asr));
+                       }
+
+/*                     DELAY(1);*/
+                       GET_SBIC_asr (regs, asr);
+               }
+
+               GET_SBIC_data (regs, *buf);
+/*             QPRINTF(("asr=%02x, csr=%02x, data=%02x\n", asr, csr, *buf));*/
+               buf++;
+       }
+
+       QPRINTF(("sbicxfin {%d} %02x %02x %02x %02x %02x %02x "
+           "%02x %02x %02x %02x\n", len, obp[0], obp[1], obp[2],
+           obp[3], obp[4], obp[5], obp[6], obp[7], obp[8], obp[9]));
+
+       /* this leaves with one csr to be read */
+       return len;
+}
+
+/*
+ * SCSI 'immediate' command:  issue a command to some SCSI device
+ * and get back an 'immediate' response (i.e., do programmed xfer
+ * to get the response data).  'cbuf' is a buffer containing a scsi
+ * command of length clen bytes.  'buf' is a buffer of length 'len'
+ * bytes for data.  The transfer direction is determined by the device
+ * (i.e., by the scsi bus data xfer phase).  If 'len' is zero, the
+ * command must supply no data.
+ */
+int
+sbicicmd(dev, target, lun, cbuf, clen, buf, len)
+       struct sbic_softc *dev;
+       void *cbuf, *buf;
+       int clen, len;
+{
+       sbic_regmap_p regs;
+       u_char phase, csr, asr;
+       int wait, newtarget, cmd_sent, parity_err;
+       struct sbic_acb *acb;
+
+       int discon;
+       int i;
+
+#define CSR_LOG_BUF_SIZE 0
+#if CSR_LOG_BUF_SIZE
+       int bufptr;
+       int csrbuf[CSR_LOG_BUF_SIZE];
+       bufptr=0;
+#endif
+
+       SBIC_TRACE(dev);
+       regs = dev->sc_sbicp;
+       acb = dev->sc_nexus;
+
+       /* Make sure pointers are OK */
+       dev->sc_last = dev->sc_cur = &acb->sc_pa;
+       dev->sc_tcnt = acb->sc_tcnt = 0;
+       acb->sc_pa.dc_count = 0; /* No DMA */
+       acb->sc_kv.dc_addr = buf;
+       acb->sc_kv.dc_count = len;
+
+#ifdef DEBUG
+       routine = 3;
+       debug_sbic_regs = regs; /* store this to allow debug calls */
+       if( data_pointer_debug > 1 )
+               printf("sbicicmd(%d,%d):%d\n", target, lun,
+                      acb->sc_kv.dc_count);
+#endif
+
+       /*
+        * set the sbic into non-DMA mode
+        */
+       SET_SBIC_control(regs, SBIC_CTL_EDI | SBIC_CTL_IDI /*| SBIC_CTL_HSP*/);
+
+       dev->sc_stat[0] = 0xff;
+       dev->sc_msg[0] = 0xff;
+       i = 1; /* pre-load */
+
+       /* We're stealing the SCSI bus */
+       dev->sc_flags |= SBICF_ICMD;
+
+       do {
+               /*
+                * select the SCSI bus (it's an error if bus isn't free)
+                */
+               if (!( dev->sc_flags & SBICF_SELECTED )
+                   && sbicselectbus(dev, regs, target, lun, dev->sc_scsiaddr)) {
+                       /*printf("sbicicmd trying to select busy bus!\n");*/
+                       dev->sc_flags &= ~SBICF_ICMD;
+                       return(-1);
+               }
+
+               /*
+                * Wait for a phase change (or error) then let the device sequence
+                * us through the various SCSI phases.
+                */
+
+               wait = sbic_cmd_wait;
+
+               asr = GET_SBIC_asr (regs, asr);
+               GET_SBIC_csr (regs, csr);
+               CSR_TRACE('I',csr,asr,target);
+               QPRINTF((">ASR:%02xCSR:%02x<", asr, csr));
+
+#if CSR_LOG_BUF_SIZE
+               csrbuf[bufptr++] = csr;
+#endif
+
+
+               switch (csr) {
+               case SBIC_CSR_S_XFERRED:
+               case SBIC_CSR_DISC:
+               case SBIC_CSR_DISC_1:
+                       dev->sc_flags &= ~SBICF_SELECTED;
+                       GET_SBIC_cmd_phase (regs, phase);
+                       if (phase == 0x60) {
+                               GET_SBIC_tlun (regs, dev->sc_stat[0]);
+                               i = 0; /* done */
+/*                             break; /* Bypass all the state gobldygook */
+                       } else {
+#ifdef DEBUG
+                               if(reselect_debug>1)
+                                       printf("sbicicmd: handling disconnect\n");
+#endif
+                               i = SBIC_STATE_DISCONNECT;
+                       }
+                       break;
+
+               case SBIC_CSR_XFERRED|CMD_PHASE:
+               case SBIC_CSR_MIS|CMD_PHASE:
+               case SBIC_CSR_MIS_1|CMD_PHASE:
+               case SBIC_CSR_MIS_2|CMD_PHASE:
+                       if (sbicxfstart(regs, clen, CMD_PHASE, sbic_cmd_wait))
+                               if (sbicxfout(regs, clen,
+                                             cbuf, CMD_PHASE))
+                                       i = sbicabort(dev, regs,"icmd sending cmd");
+#if 0
+                       GET_SBIC_csr(regs, csr); /* Lets us reload tcount */
+                       WAIT_CIP(regs);
+                       GET_SBIC_asr(regs, asr);
+                       CSR_TRACE('I',csr,asr,target);
+                       if( asr & (SBIC_ASR_BSY|SBIC_ASR_LCI|SBIC_ASR_CIP) )
+                               printf("next: cmd sent asr %02x, csr %02x\n",
+                                      asr, csr);
+#endif
+                       break;
+
+#if 0
+               case SBIC_CSR_XFERRED|DATA_OUT_PHASE:
+               case SBIC_CSR_XFERRED|DATA_IN_PHASE:
+               case SBIC_CSR_MIS|DATA_OUT_PHASE:
+               case SBIC_CSR_MIS|DATA_IN_PHASE:
+               case SBIC_CSR_MIS_1|DATA_OUT_PHASE:
+               case SBIC_CSR_MIS_1|DATA_IN_PHASE:
+               case SBIC_CSR_MIS_2|DATA_OUT_PHASE:
+               case SBIC_CSR_MIS_2|DATA_IN_PHASE:
+                       if (acb->sc_kv.dc_count <= 0)
+                               i = sbicabort(dev, regs, "icmd out of data");
+                       else {
+                         wait = sbic_data_wait;
+                         if (sbicxfstart(regs,
+                                         acb->sc_kv.dc_count,
+                                         SBIC_PHASE(csr), wait))
+                           if (csr & 0x01)
+                             /* data in? */
+                             i=sbicxfin(regs,
+                                        acb->sc_kv.dc_count,
+                                        acb->sc_kv.dc_addr);
+                           else
+                             i=sbicxfout(regs,
+                                         acb->sc_kv.dc_count,
+                                         acb->sc_kv.dc_addr,
+                                            SBIC_PHASE(csr));
+                         acb->sc_kv.dc_addr +=
+                                 (acb->sc_kv.dc_count - i);
+                         acb->sc_kv.dc_count = i;
+                         i = 1;
+                       }
+                       break;
+
+#endif
+               case SBIC_CSR_XFERRED|STATUS_PHASE:
+               case SBIC_CSR_MIS|STATUS_PHASE:
+               case SBIC_CSR_MIS_1|STATUS_PHASE:
+               case SBIC_CSR_MIS_2|STATUS_PHASE:
+                       /*
+                        * the sbic does the status/cmd-complete reading ok,
+                        * so do this with its hi-level commands.
+                        */
+#ifdef DEBUG
+                       if(sbic_debug)
+                               printf("SBICICMD status phase\n");
+#endif
+                       SBIC_TC_PUT(regs, 0);
+                       SET_SBIC_cmd_phase(regs, 0x46);
+                       SET_SBIC_cmd(regs, SBIC_CMD_SEL_ATN_XFER);
+                       break;
+
+#if THIS_IS_A_RESERVED_STATE
+               case BUS_FREE_PHASE:            /* This is not legal */
+                       if( dev->sc_stat[0] != 0xff )
+                               goto out;
+                       break;
+#endif
+
+               default:
+                       i = sbicnextstate(dev, csr, asr);
+               }
+
+               /*
+                * make sure the last command was taken,
+                * ie. we're not hunting after an ignored command..
+                */
+               GET_SBIC_asr(regs, asr);
+
+               /* tapes may take a loooong time.. */
+               while (asr & SBIC_ASR_BSY){
+                       if(asr & SBIC_ASR_DBR) {
+                               printf("sbicicmd: Waiting while sbic is jammed, CSR:%02x,ASR:%02x\n",
+                                      csr,asr);
+#ifdef DDB
+                               Debugger();
+#endif
+                               /* SBIC is jammed */
+                               /* DUNNO which direction */
+                               /* Try old direction */
+                               GET_SBIC_data(regs,i);
+                               GET_SBIC_asr(regs, asr);
+                               if( asr & SBIC_ASR_DBR) /* Wants us to write */
+                                       SET_SBIC_data(regs,i);
+                       }
+                       GET_SBIC_asr(regs, asr);
+               }
+
+               /*
+                * wait for last command to complete
+                */
+               if (asr & SBIC_ASR_LCI) {
+                       printf("sbicicmd: last command ignored\n");
+               }
+               else if( i == 1 ) /* Bsy */
+                       SBIC_WAIT (regs, SBIC_ASR_INT, wait);
+
+               /*
+                * do it again
+                */
+       } while ( i > 0 && dev->sc_stat[0] == 0xff);
+
+       /* Sometimes we need to do an extra read of the CSR */
+       GET_SBIC_csr(regs, csr);
+       CSR_TRACE('I',csr,asr,0xff);
+
+#if CSR_LOG_BUF_SIZE
+       if(reselect_debug>1)
+               for(i=0; i<bufptr; i++)
+                       printf("CSR:%02x", csrbuf[i]);
+#endif
+
+#ifdef DEBUG
+       if(data_pointer_debug > 1)
+               printf("sbicicmd done(%d,%d):%d =%d=\n",
+                      dev->target, lun,
+                      acb->sc_kv.dc_count,
+                      dev->sc_stat[0]);
+#endif
+
+       QPRINTF(("=STS:%02x=", dev->sc_stat[0]));
+       dev->sc_flags &= ~SBICF_ICMD;
+
+       SBIC_TRACE(dev);
+       return(dev->sc_stat[0]);
+}
+
+/*
+ * Finish SCSI xfer command:  After the completion interrupt from
+ * a read/write operation, sequence through the final phases in
+ * programmed i/o.  This routine is a lot like sbicicmd except we
+ * skip (and don't allow) the select, cmd out and data in/out phases.
+ */
+void
+sbicxfdone(dev, regs, target)
+       struct sbic_softc *dev;
+       sbic_regmap_p regs;
+       int target;
+{
+       u_char phase, asr, csr;
+       int s;
+
+       SBIC_TRACE(dev);
+       QPRINTF(("{"));
+       s = splbio();
+
+       /*
+        * have the sbic complete on its own
+        */
+       SBIC_TC_PUT(regs, 0);
+       SET_SBIC_cmd_phase(regs, 0x46);
+       SET_SBIC_cmd(regs, SBIC_CMD_SEL_ATN_XFER);
+
+       do {
+               asr = SBIC_WAIT (regs, SBIC_ASR_INT, 0);
+               GET_SBIC_csr (regs, csr);
+               CSR_TRACE('f',csr,asr,target);
+               QPRINTF(("%02x:", csr));
+       } while ((csr != SBIC_CSR_DISC) && (csr != SBIC_CSR_DISC_1)
+           && (csr != SBIC_CSR_S_XFERRED));
+
+       dev->sc_flags &= ~SBICF_SELECTED;
+
+       GET_SBIC_cmd_phase (regs, phase);
+       QPRINTF(("}%02x", phase));
+       if (phase == 0x60)
+               GET_SBIC_tlun(regs, dev->sc_stat[0]);
+       else
+               sbicerror(dev, regs, csr);
+
+       QPRINTF(("=STS:%02x=\n", dev->sc_stat[0]));
+       splx(s);
+       SBIC_TRACE(dev);
+}
+
+       /*
+        * No DMA chains
+        */
+
+int
+sbicgo(dev, xs)
+       struct sbic_softc *dev;
+       struct scsi_xfer *xs;
+{
+       int i, dmaflags, count, wait, usedma;
+       u_char csr, asr, cmd, *addr;
+       sbic_regmap_p regs;
+       struct sbic_acb *acb;
+
+       SBIC_TRACE(dev);
+       dev->target = xs->sc_link->target;
+       dev->lun = xs->sc_link->lun;
+       acb = dev->sc_nexus;
+       regs = dev->sc_sbicp;
+
+       usedma = sbicdmaok(dev, xs);
+#ifdef DEBUG
+       routine = 1;
+       debug_sbic_regs = regs; /* store this to allow debug calls */
+       if( data_pointer_debug > 1 )
+               printf("sbicgo(%d,%d)\n", dev->target, dev->lun);
+#endif
+
+       /*
+        * set the sbic into DMA mode
+        */
+       if( usedma )
+               SET_SBIC_control(regs, SBIC_CTL_EDI | SBIC_CTL_IDI |
+                                SBIC_MACHINE_DMA_MODE);
+       else
+               SET_SBIC_control(regs, SBIC_CTL_EDI | SBIC_CTL_IDI);
+
+
+       /*
+        * select the SCSI bus (it's an error if bus isn't free)
+        */
+       if (sbicselectbus(dev, regs, dev->target, dev->lun,
+           dev->sc_scsiaddr)) {
+/*             printf("sbicgo: Trying to select busy bus!\n"); */
+               SBIC_TRACE(dev);
+               return(0); /* Not done: needs to be rescheduled */
+       }
+       dev->sc_stat[0] = 0xff;
+
+       /*
+        * Calculate DMA chains now
+        */
+
+       dmaflags = 0;
+       if (acb->flags & ACB_DATAIN)
+               dmaflags |= DMAGO_READ;
+
+
+       /*
+        * Deal w/bounce buffers.
+        */
+
+       addr = acb->sc_kv.dc_addr;
+       count = acb->sc_kv.dc_count;
+#if 0 /* mark */
+       if (count && (char *)kvtop(addr) != acb->sc_pa.dc_addr) { /* XXXX check */
+               printf("sbic: DMA buffer mapping changed %x->%x\n",
+                   acb->sc_pa.dc_addr, kvtop(addr));
+#ifdef DDB
+               Debugger();
+#endif
+       }
+#endif
+
+#ifdef DEBUG
+       ++sbicdma_ops;                  /* count total DMA operations */
+#endif
+       if (count && usedma && dev->sc_flags & SBICF_BADDMA &&
+           sbiccheckdmap(addr, count, dev->sc_dmamask)) {
+               /*
+                * need to bounce the dma.
+                */
+               if (dmaflags & DMAGO_READ) {
+                       acb->flags |= ACB_BBUF;
+                       acb->sc_dmausrbuf = addr;
+                       acb->sc_dmausrlen = count;
+                       acb->sc_usrbufpa = (u_char *)kvtop(addr);
+                       if(!dev->sc_tinfo[dev->target].bounce) {
+                               printf("sbicgo: HELP! no bounce allocated for %d\n",
+                                      dev->target);
+                               printf("xfer: (%x->%x,%x)\n", acb->sc_dmausrbuf,
+                                      acb->sc_usrbufpa, acb->sc_dmausrlen);
+                               dev->sc_tinfo[xs->sc_link->target].bounce
+                                       = (char *)alloc_z2mem(MAXPHYS);
+                               if (isztwomem(dev->sc_tinfo[xs->sc_link->target].bounce))
+                                       printf("alloc ZII target %d bounce pa 0x%x\n",
+                                              xs->sc_link->target,
+                                              kvtop(dev->sc_tinfo[xs->sc_link->target].bounce));
+                               else if (dev->sc_tinfo[xs->sc_link->target].bounce)
+                                       printf("alloc CHIP target %d bounce pa 0x%x\n",
+                                              xs->sc_link->target,
+                                              PREP_DMA_MEM(dev->sc_tinfo[xs->sc_link->target].bounce));
+
+                               printf("Allocating %d bounce at %x\n",
+                                      dev->target,
+                                      kvtop(dev->sc_tinfo[dev->target].bounce));
+                       }
+               } else {        /* write: copy to dma buffer */
+#ifdef DEBUG
+                       if(data_pointer_debug)
+                       printf("sbicgo: copying %x bytes to target %d bounce %x\n",
+                              count, dev->target,
+                              kvtop(dev->sc_tinfo[dev->target].bounce));
+#endif
+                       bcopy (addr, dev->sc_tinfo[dev->target].bounce, count);
+               }
+               addr = dev->sc_tinfo[dev->target].bounce;/* and use dma buffer */
+               acb->sc_kv.dc_addr = addr;
+#ifdef DEBUG
+               ++sbicdma_bounces;              /* count number of bounced */
+#endif
+       }
+
+       /*
+        * Allocate the DMA chain
+        */
+
+       /* Set start KVM addresses */
+#if 0
+       acb->sc_kv.dc_addr = addr;
+       acb->sc_kv.dc_count = count;
+#endif
+
+       /* Mark end of segment */
+       acb->sc_tcnt = dev->sc_tcnt = 0;
+       acb->sc_pa.dc_count = 0;
+
+       sbic_load_ptrs(dev, regs, dev->target, dev->lun);
+       SBIC_TRACE(dev);
+       /* Enable interrupts but don't do any DMA */
+       dev->sc_enintr(dev);
+       if (usedma) {
+               dev->sc_tcnt = dev->sc_dmago(dev, acb->sc_pa.dc_addr,
+                   acb->sc_pa.dc_count,
+                   dmaflags);
+#ifdef DEBUG
+               dev->sc_dmatimo = dev->sc_tcnt ? 1 : 0;
+#endif
+        } else
+               dev->sc_dmacmd = 0; /* Don't use DMA */
+       dev->sc_flags |= SBICF_INDMA;
+/*     SBIC_TC_PUT(regs, dev->sc_tcnt); /* XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX */
+       SBIC_TRACE(dev);
+       sbic_save_ptrs(dev, regs, dev->target, dev->lun);
+
+       /*
+        * push the data cache ( I think this won't work (EH))
+        */
+#if defined(M68040)
+       if (mmutype == MMU_68040 && usedma && count) {
+               dma_cachectl(addr, count);
+               if (((u_int)addr & 0xF) || (((u_int)addr + count) & 0xF))
+                       dev->sc_flags |= SBICF_DCFLUSH;
+       }
+#endif
+
+       /*
+        * enintr() also enables interrupts for the sbic
+        */
+#ifdef DEBUG
+       if( data_pointer_debug > 1 )
+               printf("sbicgo dmago:%d(%x:%x)\n",
+                      dev->target,dev->sc_cur->dc_addr,dev->sc_tcnt);
+       debug_asr = asr;
+       debug_csr = csr;
+#endif
+
+       /*
+        * Lets cycle a while then let the interrupt handler take over
+        */
+
+       asr = GET_SBIC_asr(regs, asr);
+       do {
+               GET_SBIC_csr(regs, csr);
+               CSR_TRACE('g',csr,asr,dev->target);
+#ifdef DEBUG
+               debug_csr = csr;
+               routine = 1;
+#endif
+               QPRINTF(("go[0x%x]", csr));
+
+               i = sbicnextstate(dev, csr, asr);
+
+               WAIT_CIP(regs);
+               GET_SBIC_asr(regs, asr);
+#ifdef DEBUG
+               debug_asr = asr;
+#endif
+               if(asr & SBIC_ASR_LCI) printf("sbicgo: LCI asr:%02x csr:%02x\n",
+                                             asr,csr);
+       } while( i == SBIC_STATE_RUNNING
+               && asr & (SBIC_ASR_INT|SBIC_ASR_LCI) );
+
+       CSR_TRACE('g',csr,asr,i<<4);
+       SBIC_TRACE(dev);
+if (i == SBIC_STATE_DONE && dev->sc_stat[0] == 0xff) printf("sbicgo: done & stat = 0xff\n");
+       if (i == SBIC_STATE_DONE && dev->sc_stat[0] != 0xff) {
+/*     if( i == SBIC_STATE_DONE && dev->sc_stat[0] ) { */
+               /* Did we really finish that fast? */
+               return 1;
+       }
+       return 0;
+}
+
+
+int
+sbicintr(dev)
+       struct sbic_softc *dev;
+{
+       sbic_regmap_p regs;
+       struct dma_chain *df, *dl;
+       u_char asr, csr, *tmpaddr;
+       struct sbic_acb *acb;
+       int i, newtarget, newlun;
+       unsigned tcnt;
+
+       regs = dev->sc_sbicp;
+
+       /*
+        * pending interrupt?
+        */
+       GET_SBIC_asr (regs, asr);
+       if ((asr & SBIC_ASR_INT) == 0)
+               return(0);
+
+       SBIC_TRACE(dev);
+       do {
+               GET_SBIC_csr(regs, csr);
+               CSR_TRACE('i',csr,asr,dev->target);
+#ifdef DEBUG
+               debug_csr = csr;
+               routine = 2;
+#endif
+               QPRINTF(("intr[0x%x]", csr));
+
+               i = sbicnextstate(dev, csr, asr);
+
+               WAIT_CIP(regs);
+               GET_SBIC_asr(regs, asr);
+#ifdef DEBUG
+               debug_asr = asr;
+#endif
+#if 0
+               if(asr & SBIC_ASR_LCI) printf("sbicintr: LCI asr:%02x csr:%02x\n",
+                                             asr,csr);
+#endif
+       } while(i == SBIC_STATE_RUNNING &&
+               asr & (SBIC_ASR_INT|SBIC_ASR_LCI));
+       CSR_TRACE('i',csr,asr,i<<4);
+       SBIC_TRACE(dev);
+       return(1);
+}
+
+/*
+ * Run commands and wait for disconnect
+ */
+int
+sbicpoll(dev)
+       struct sbic_softc *dev;
+{
+       sbic_regmap_p regs;
+       u_char asr, csr;
+       struct sbic_pending* pendp;
+       int i;
+       unsigned tcnt;
+
+       SBIC_TRACE(dev);
+       regs = dev->sc_sbicp;
+
+       do {
+               GET_SBIC_asr (regs, asr);
+#ifdef DEBUG
+               debug_asr = asr;
+#endif
+               GET_SBIC_csr(regs, csr);
+               CSR_TRACE('p',csr,asr,dev->target);
+#ifdef DEBUG
+               debug_csr = csr;
+               routine = 2;
+#endif
+               QPRINTF(("poll[0x%x]", csr));
+
+               i = sbicnextstate(dev, csr, asr);
+
+               WAIT_CIP(regs);
+               GET_SBIC_asr(regs, asr);
+               /* tapes may take a loooong time.. */
+               while (asr & SBIC_ASR_BSY){
+                       if(asr & SBIC_ASR_DBR) {
+                               printf("sbipoll: Waiting while sbic is jammed, CSR:%02x,ASR:%02x\n",
+                                      csr,asr);
+#ifdef DDB
+                               Debugger();
+#endif
+                               /* SBIC is jammed */
+                               /* DUNNO which direction */
+                               /* Try old direction */
+                               GET_SBIC_data(regs,i);
+                               GET_SBIC_asr(regs, asr);
+                               if( asr & SBIC_ASR_DBR) /* Wants us to write */
+                                       SET_SBIC_data(regs,i);
+                       }
+                       GET_SBIC_asr(regs, asr);
+               }
+
+               if(asr & SBIC_ASR_LCI) printf("sbicpoll: LCI asr:%02x csr:%02x\n",
+                                             asr,csr);
+               else if( i == 1 ) /* BSY */
+                       SBIC_WAIT(regs, SBIC_ASR_INT, sbic_cmd_wait);
+       } while(i == SBIC_STATE_RUNNING);
+       CSR_TRACE('p',csr,asr,i<<4);
+       SBIC_TRACE(dev);
+       return(1);
+}
+
+/*
+ * Handle a single msgin
+ */
+
+int
+sbicmsgin(dev)
+       struct sbic_softc *dev;
+{
+       sbic_regmap_p regs;
+       int recvlen;
+       u_char asr, csr, *tmpaddr;
+
+       regs = dev->sc_sbicp;
+
+       dev->sc_msg[0] = 0xff;
+       dev->sc_msg[1] = 0xff;
+
+       GET_SBIC_asr(regs, asr);
+#ifdef DEBUG
+       if(reselect_debug>1)
+               printf("sbicmsgin asr=%02x\n", asr);
+#endif
+
+       sbic_save_ptrs(dev, regs, dev->target, dev->lun);
+
+       GET_SBIC_selid (regs, csr);
+       SET_SBIC_selid (regs, csr | SBIC_SID_FROM_SCSI);
+
+       SBIC_TC_PUT(regs, 0);
+       tmpaddr = dev->sc_msg;
+       recvlen = 1;
+       do {
+               while( recvlen-- ) {
+                       asr = GET_SBIC_asr(regs, asr);
+                       GET_SBIC_csr(regs, csr);
+                       QPRINTF(("sbicmsgin ready to go (csr,asr)=(%02x,%02x)\n",
+                                csr, asr));
+
+                       RECV_BYTE(regs, *tmpaddr);
+                       CSR_TRACE('m',csr,asr,*tmpaddr);
+#if 1
+                       /*
+                        * get the command completion interrupt, or we
+                        * can't send a new command (LCI)
+                        */
+                       SBIC_WAIT(regs, SBIC_ASR_INT, 0);
+                       GET_SBIC_csr(regs, csr);
+                       CSR_TRACE('X',csr,asr,dev->target);
+#else
+                       WAIT_CIP(regs);
+                       do {
+                               GET_SBIC_asr(regs, asr);
+                               csr = 0xff;
+                               GET_SBIC_csr(regs, csr);
+                               CSR_TRACE('X',csr,asr,dev->target);
+                               if( csr == 0xff )
+                                       printf("sbicmsgin waiting: csr %02x asr %02x\n", csr, asr);
+                       } while( csr == 0xff );
+#endif
+#ifdef DEBUG
+                       if(reselect_debug>1)
+                               printf("sbicmsgin: got %02x csr %02x asr %02x\n",
+                                      *tmpaddr, csr, asr);
+#endif
+#if do_parity_check
+                       if( asr & SBIC_ASR_PE ) {
+                               printf ("Parity error");
+                               /* This code simply does not work. */
+                               WAIT_CIP(regs);
+                               SET_SBIC_cmd(regs, SBIC_CMD_SET_ATN);
+                               WAIT_CIP(regs);
+                               GET_SBIC_asr(regs, asr);
+                               WAIT_CIP(regs);
+                               SET_SBIC_cmd(regs, SBIC_CMD_CLR_ACK);
+                               WAIT_CIP(regs);
+                               if( !(asr & SBIC_ASR_LCI) )
+                                       /* Target wants to send garbled msg*/
+                                       continue;
+                               printf("--fixing\n");
+                               /* loop until a msgout phase occurs on target */
+                               while(csr & 0x07 != MESG_OUT_PHASE) {
+                                       while( asr & SBIC_ASR_BSY &&
+                                             !(asr & SBIC_ASR_DBR|SBIC_ASR_INT) )
+                                               GET_SBIC_asr(regs, asr);
+                                       if( asr & SBIC_ASR_DBR )
+                                               panic("msgin: jammed again!\n");
+                                       GET_SBIC_csr(regs, csr);
+                                       CSR_TRACE('e',csr,asr,dev->target);
+                                       if( csr & 0x07 != MESG_OUT_PHASE ) {
+                                               sbicnextstate(dev, csr, asr);
+                                               sbic_save_ptrs(dev, regs,
+                                                              dev->target,
+                                                              dev->lun);
+                                       }
+                               }
+                               /* Should be msg out by now */
+                               SEND_BYTE(regs, MSG_PARITY_ERROR);
+                       }
+                       else
+#endif
+                               tmpaddr++;
+
+                       if(recvlen) {
+                               /* Clear ACK */
+                               WAIT_CIP(regs);
+                               GET_SBIC_asr(regs, asr);
+                               GET_SBIC_csr(regs, csr);
+                               CSR_TRACE('X',csr,asr,dev->target);
+                               QPRINTF(("sbicmsgin pre byte CLR_ACK (csr,asr)=(%02x,%02x)\n",
+                                        csr, asr));
+                               SET_SBIC_cmd(regs, SBIC_CMD_CLR_ACK);
+                               SBIC_WAIT(regs, SBIC_ASR_INT, 0);
+                       }
+
+               };
+
+               if(dev->sc_msg[0] == 0xff) {
+                       printf("sbicmsgin: sbic swallowed our message\n");
+                       break;
+               }
+#ifdef DEBUG
+               if (sync_debug)
+                       printf("msgin done csr 0x%x asr 0x%x msg 0x%x\n",
+                              csr, asr, dev->sc_msg[0]);
+#endif
+               /*
+                * test whether this is a reply to our sync
+                * request
+                */
+               if (MSG_ISIDENTIFY(dev->sc_msg[0])) {
+                       QPRINTF(("IFFY"));
+#if 0
+                       /* There is an implied load-ptrs here */
+                       sbic_load_ptrs(dev, regs, dev->target, dev->lun);
+#endif
+                       /* Got IFFY msg -- ack it */
+               } else if (dev->sc_msg[0] == MSG_REJECT
+                          && dev->sc_sync[dev->target].state == SYNC_SENT) {
+                       QPRINTF(("REJECT of SYN"));
+#ifdef DEBUG
+                       if (sync_debug)
+                               printf("target %d rejected sync, going async\n",
+                                      dev->target);
+#endif
+                       dev->sc_sync[dev->target].period = sbic_min_period;
+                       dev->sc_sync[dev->target].offset = 0;
+                       dev->sc_sync[dev->target].state = SYNC_DONE;
+                       SET_SBIC_syn(regs,
+                                    SBIC_SYN(dev->sc_sync[dev->target].offset,
+                                             dev->sc_sync[dev->target].period));
+               } else if ((dev->sc_msg[0] == MSG_REJECT)) {
+                       QPRINTF(("REJECT"));
+                       /*
+                        * we'll never REJECt a REJECT message..
+                        */
+               } else if ((dev->sc_msg[0] == MSG_SAVE_DATA_PTR)) {
+                       QPRINTF(("MSG_SAVE_DATA_PTR"));
+                       /*
+                        * don't reject this either.
+                        */
+               } else if ((dev->sc_msg[0] == MSG_DISCONNECT)) {
+                       QPRINTF(("DISCONNECT"));
+#ifdef DEBUG
+                       if( reselect_debug>1 && dev->sc_msg[0] == MSG_DISCONNECT )
+                               printf("sbicmsgin: got disconnect msg %s\n",
+                                      (dev->sc_flags & SBICF_ICMD)?"rejecting":"");
+#endif
+                       if( dev->sc_flags & SBICF_ICMD ) {
+                               /* We're in immediate mode. Prevent disconnects. */
+                               /* prepare to reject the message, NACK */
+                               SET_SBIC_cmd(regs, SBIC_CMD_SET_ATN);
+                               WAIT_CIP(regs);
+                       }
+               } else if (dev->sc_msg[0] == MSG_CMD_COMPLETE ) {
+                       QPRINTF(("CMD_COMPLETE"));
+                       /* !! KLUDGE ALERT !! quite a few drives don't seem to
+                        * really like the current way of sending the
+                        * sync-handshake together with the ident-message, and
+                        * they react by sending command-complete and
+                        * disconnecting right after returning the valid sync
+                        * handshake. So, all I can do is reselect the drive,
+                        * and hope it won't disconnect again. I don't think
+                        * this is valid behavior, but I can't help fixing a
+                        * problem that apparently exists.
+                        *
+                        * Note: we should not get here on `normal' command
+                        * completion, as that condition is handled by the
+                        * high-level sel&xfer resume command used to walk
+                        * thru status/cc-phase.
+                        */
+
+#ifdef DEBUG
+                       if (sync_debug)
+                               printf ("GOT MSG %d! target %d acting weird.."
+                                       " waiting for disconnect...\n",
+                                       dev->sc_msg[0], dev->target);
+#endif
+                       /* Check to see if sbic is handling this */
+                       GET_SBIC_asr(regs, asr);
+                       if(asr & SBIC_ASR_BSY)
+                               return SBIC_STATE_RUNNING;
+
+                       /* Let's try this: Assume it works and set status to 00 */
+                       dev->sc_stat[0] = 0;
+               } else if (dev->sc_msg[0] == MSG_EXT_MESSAGE
+                          && tmpaddr == &dev->sc_msg[1]) {
+                       QPRINTF(("ExtMSG\n"));
+                       /* Read in whole extended message */
+                       SET_SBIC_cmd(regs, SBIC_CMD_CLR_ACK);
+                       SBIC_WAIT(regs, SBIC_ASR_INT, 0);
+                       GET_SBIC_asr(regs, asr);
+                       GET_SBIC_csr(regs, csr);
+                       QPRINTF(("CLR ACK asr %02x, csr %02x\n", asr, csr));
+                       RECV_BYTE(regs, *tmpaddr);
+                       CSR_TRACE('x',csr,asr,*tmpaddr);
+                       /* Wait for command completion IRQ */
+                       SBIC_WAIT(regs, SBIC_ASR_INT, 0);
+                       recvlen = *tmpaddr++;
+                       QPRINTF(("Recving ext msg, asr %02x csr %02x len %02x\n",
+                              asr, csr, recvlen));
+               } else if (dev->sc_msg[0] == MSG_EXT_MESSAGE && dev->sc_msg[1] == 3
+                          && dev->sc_msg[2] == MSG_SYNC_REQ) {
+                       QPRINTF(("SYN"));
+                       dev->sc_sync[dev->target].period =
+                               sbicfromscsiperiod(dev,
+                                                  regs, dev->sc_msg[3]);
+                       dev->sc_sync[dev->target].offset = dev->sc_msg[4];
+                       dev->sc_sync[dev->target].state = SYNC_DONE;
+                       SET_SBIC_syn(regs,
+                                    SBIC_SYN(dev->sc_sync[dev->target].offset,
+                                             dev->sc_sync[dev->target].period));
+                       printf("%s: target %d now synchronous,"
+                              " period=%dns, offset=%d.\n",
+                              dev->sc_dev.dv_xname, dev->target,
+                              dev->sc_msg[3] * 4, dev->sc_msg[4]);
+               } else {
+#ifdef DEBUG
+                       if (sbic_debug || sync_debug)
+                               printf ("sbicmsgin: Rejecting message 0x%02x\n",
+                                       dev->sc_msg[0]);
+#endif
+                       /* prepare to reject the message, NACK */
+                       SET_SBIC_cmd(regs, SBIC_CMD_SET_ATN);
+                       WAIT_CIP(regs);
+               }
+               /* Clear ACK */
+               WAIT_CIP(regs);
+               GET_SBIC_asr(regs, asr);
+               GET_SBIC_csr(regs, csr);
+               CSR_TRACE('X',csr,asr,dev->target);
+               QPRINTF(("sbicmsgin pre CLR_ACK (csr,asr)=(%02x,%02x)%d\n",
+                        csr, asr, recvlen));
+               SET_SBIC_cmd(regs, SBIC_CMD_CLR_ACK);
+               SBIC_WAIT(regs, SBIC_ASR_INT, 0);
+       }
+#if 0
+       while((csr == SBIC_CSR_MSGIN_W_ACK)
+             || (SBIC_PHASE(csr) == MESG_IN_PHASE));
+#else
+       while (recvlen>0);
+#endif
+
+       QPRINTF(("sbicmsgin finished: csr %02x, asr %02x\n",csr, asr));
+
+       /* Should still have one CSR to read */
+       return SBIC_STATE_RUNNING;
+}
+
+
+/*
+ * sbicnextstate()
+ * return:
+ *             0  == done
+ *             1  == working
+ *             2  == disconnected
+ *             -1 == error
+ */
+int
+sbicnextstate(dev, csr, asr)
+       struct sbic_softc *dev;
+       u_char csr, asr;
+{
+       sbic_regmap_p regs;
+       struct dma_chain *df, *dl;
+       struct sbic_acb *acb;
+       int i, newtarget, newlun, wait;
+       unsigned tcnt;
+
+       SBIC_TRACE(dev);
+       regs = dev->sc_sbicp;
+       acb = dev->sc_nexus;
+
+       QPRINTF(("next[%02x,%02x]",asr,csr));
+
+       switch (csr) {
+       case SBIC_CSR_XFERRED|CMD_PHASE:
+       case SBIC_CSR_MIS|CMD_PHASE:
+       case SBIC_CSR_MIS_1|CMD_PHASE:
+       case SBIC_CSR_MIS_2|CMD_PHASE:
+               sbic_save_ptrs(dev, regs, dev->target, dev->lun);
+               if (sbicxfstart(regs, acb->clen, CMD_PHASE, sbic_cmd_wait))
+                       if (sbicxfout(regs, acb->clen,
+                                     &acb->cmd, CMD_PHASE))
+                               goto abort;
+               break;
+
+       case SBIC_CSR_XFERRED|STATUS_PHASE:
+       case SBIC_CSR_MIS|STATUS_PHASE:
+       case SBIC_CSR_MIS_1|STATUS_PHASE:
+       case SBIC_CSR_MIS_2|STATUS_PHASE:
+               /*
+                * this should be the normal i/o completion case.
+                * get the status & cmd complete msg then let the
+                * device driver look at what happened.
+                */
+               sbicxfdone(dev,regs,dev->target);
+               /*
+                * check for overlapping cache line, flush if so
+                */
+#ifdef M68040
+               if (dev->sc_flags & SBICF_DCFLUSH) {
+#if 0
+                       printf("sbic: 68040 DMA cache flush needs fixing? %x:%x\n",
+                           dev->sc_xs->data, dev->sc_xs->datalen);
+#endif
+               }
+#endif
+#ifdef DEBUG
+               if( data_pointer_debug > 1 )
+                       printf("next dmastop: %d(%x:%x)\n",
+                              dev->target,dev->sc_cur->dc_addr,dev->sc_tcnt);
+               dev->sc_dmatimo = 0;
+#endif
+               dev->sc_dmastop(dev); /* was dmafree */
+               if (acb->flags & ACB_BBUF) {
+                       if ((u_char *)kvtop(acb->sc_dmausrbuf) != acb->sc_usrbufpa)
+                               printf("%s: WARNING - buffer mapping changed %x->%x\n",
+                                   dev->sc_dev.dv_xname, acb->sc_usrbufpa,
+                                   kvtop(acb->sc_dmausrbuf));
+#ifdef DEBUG
+                       if(data_pointer_debug)
+                       printf("sbicgo:copying %x bytes from target %d bounce %x\n",
+                              acb->sc_dmausrlen,
+                              dev->target,
+                              kvtop(dev->sc_tinfo[dev->target].bounce));
+#endif
+                       bcopy(dev->sc_tinfo[dev->target].bounce,
+                             acb->sc_dmausrbuf,
+                             acb->sc_dmausrlen);
+               }
+               dev->sc_flags &= ~(SBICF_INDMA | SBICF_DCFLUSH);
+               sbic_scsidone(acb, dev->sc_stat[0]);
+               SBIC_TRACE(dev);
+               return SBIC_STATE_DONE;
+
+       case SBIC_CSR_XFERRED|DATA_OUT_PHASE:
+       case SBIC_CSR_XFERRED|DATA_IN_PHASE:
+       case SBIC_CSR_MIS|DATA_OUT_PHASE:
+       case SBIC_CSR_MIS|DATA_IN_PHASE:
+       case SBIC_CSR_MIS_1|DATA_OUT_PHASE:
+       case SBIC_CSR_MIS_1|DATA_IN_PHASE:
+       case SBIC_CSR_MIS_2|DATA_OUT_PHASE:
+       case SBIC_CSR_MIS_2|DATA_IN_PHASE:
+               if( dev->sc_xs->flags & SCSI_POLL || dev->sc_flags & SBICF_ICMD
+                  || acb->sc_dmacmd == 0 ) {
+                       /* Do PIO */
+                       SET_SBIC_control(regs, SBIC_CTL_EDI | SBIC_CTL_IDI);
+                       if (acb->sc_kv.dc_count <= 0) {
+                               printf("sbicnextstate:xfer count %d asr%x csr%x\n",
+                                      acb->sc_kv.dc_count, asr, csr);
+                               goto abort;
+                       }
+                       wait = sbic_data_wait;
+                       if( sbicxfstart(regs,
+                                       acb->sc_kv.dc_count,
+                                       SBIC_PHASE(csr), wait))
+                               if( SBIC_PHASE(csr) == DATA_IN_PHASE )
+                                       /* data in? */
+                                       i=sbicxfin(regs,
+                                                  acb->sc_kv.dc_count,
+                                                  acb->sc_kv.dc_addr);
+                               else
+                                       i=sbicxfout(regs,
+                                                   acb->sc_kv.dc_count,
+                                                   acb->sc_kv.dc_addr,
+                                                   SBIC_PHASE(csr));
+                       acb->sc_kv.dc_addr +=
+                               (acb->sc_kv.dc_count - i);
+                       acb->sc_kv.dc_count = i;
+               } else {
+                       if (acb->sc_kv.dc_count <= 0) {
+                               printf("sbicnextstate:xfer count %d asr%x csr%x\n",
+                                      acb->sc_kv.dc_count, asr, csr);
+                               goto abort;
+                       }
+                       /*
+                        * do scatter-gather dma
+                        * hacking the controller chip, ouch..
+                        */
+                       SET_SBIC_control(regs, SBIC_CTL_EDI | SBIC_CTL_IDI |
+                                        SBIC_MACHINE_DMA_MODE);
+                       /*
+                        * set next dma addr and dec count
+                        */
+#if 0
+                       SBIC_TC_GET(regs, tcnt);
+                       dev->sc_cur->dc_count -= ((dev->sc_tcnt - tcnt) >> 1);
+                       dev->sc_cur->dc_addr += (dev->sc_tcnt - tcnt);
+                       dev->sc_tcnt = acb->sc_tcnt = tcnt;
+#else
+                       sbic_save_ptrs(dev, regs, dev->target, dev->lun);
+                       sbic_load_ptrs(dev, regs, dev->target, dev->lun);
+#endif
+#ifdef DEBUG
+                       if( data_pointer_debug > 1 )
+                               printf("next dmanext: %d(%x:%x)\n",
+                                      dev->target,dev->sc_cur->dc_addr,
+                                      dev->sc_tcnt);
+                       dev->sc_dmatimo = 1;
+#endif
+                       dev->sc_tcnt = dev->sc_dmanext(dev);
+                       SBIC_TC_PUT(regs, (unsigned)dev->sc_tcnt);
+                       SET_SBIC_cmd(regs, SBIC_CMD_XFER_INFO);
+                       dev->sc_flags |= SBICF_INDMA;
+               }
+               break;
+
+       case SBIC_CSR_XFERRED|MESG_IN_PHASE:
+       case SBIC_CSR_MIS|MESG_IN_PHASE:
+       case SBIC_CSR_MIS_1|MESG_IN_PHASE:
+       case SBIC_CSR_MIS_2|MESG_IN_PHASE:
+               SBIC_TRACE(dev);
+               return sbicmsgin(dev);
+
+       case SBIC_CSR_MSGIN_W_ACK:
+               SET_SBIC_cmd(regs, SBIC_CMD_CLR_ACK); /* Dunno what I'm ACKing */
+               printf("Acking unknown msgin CSR:%02x",csr);
+               break;
+
+       case SBIC_CSR_XFERRED|MESG_OUT_PHASE:
+       case SBIC_CSR_MIS|MESG_OUT_PHASE:
+       case SBIC_CSR_MIS_1|MESG_OUT_PHASE:
+       case SBIC_CSR_MIS_2|MESG_OUT_PHASE:
+#ifdef DEBUG
+               if (sync_debug)
+                       printf ("sending REJECT msg to last msg.\n");
+#endif
+
+               sbic_save_ptrs(dev, regs, dev->target, dev->lun);
+               /*
+                * should only get here on reject,
+                * since it's always US that
+                * initiate a sync transfer
+                */
+               SEND_BYTE(regs, MSG_REJECT);
+               WAIT_CIP(regs);
+               if( asr & (SBIC_ASR_BSY|SBIC_ASR_LCI|SBIC_ASR_CIP) )
+                       printf("next: REJECT sent asr %02x\n", asr);
+               SBIC_TRACE(dev);
+               return SBIC_STATE_RUNNING;
+
+       case SBIC_CSR_DISC:
+       case SBIC_CSR_DISC_1:
+               dev->sc_flags &= ~(SBICF_INDMA|SBICF_SELECTED);
+
+               /* Try to schedule another target */
+#ifdef DEBUG
+               if(reselect_debug>1)
+                       printf("sbicnext target %d disconnected\n", dev->target);
+#endif
+               TAILQ_INSERT_HEAD(&dev->nexus_list, acb, chain);
+               ++dev->sc_tinfo[dev->target].dconns;
+               dev->sc_nexus = NULL;
+               dev->sc_xs = NULL;
+
+               if( acb->xs->flags & SCSI_POLL
+                  || (dev->sc_flags & SBICF_ICMD)
+                  || !sbic_parallel_operations ) {
+                       SBIC_TRACE(dev);
+                       return SBIC_STATE_DISCONNECT;
+               }
+               sbic_sched(dev);
+               SBIC_TRACE(dev);
+               return SBIC_STATE_DISCONNECT;
+
+       case SBIC_CSR_RSLT_NI:
+       case SBIC_CSR_RSLT_IFY:
+               GET_SBIC_rselid(regs, newtarget);
+               /* check SBIC_RID_SIV? */
+               newtarget &= SBIC_RID_MASK;
+               if (csr == SBIC_CSR_RSLT_IFY) {
+                       /* Read IFY msg to avoid lockup */
+                       GET_SBIC_data(regs, newlun);
+                       WAIT_CIP(regs);
+                       newlun &= SBIC_TLUN_MASK;
+                       CSR_TRACE('r',csr,asr,newtarget);
+               } else {
+                       /* Need to get IFY message */
+                       for (newlun = 256; newlun; --newlun) {
+                               GET_SBIC_asr(regs, asr);
+                               if (asr & SBIC_ASR_INT)
+                                       break;
+                               delay(1);
+                       }
+                       newlun = 0;     /* XXXX */
+                       if ((asr & SBIC_ASR_INT) == 0) {
+#ifdef DEBUG
+                               if (reselect_debug)
+                                       printf("RSLT_NI - no IFFY message? asr %x\n", asr);
+#endif
+                       } else {
+                               GET_SBIC_csr(regs,csr);
+                               CSR_TRACE('n',csr,asr,newtarget);
+                               if (csr == SBIC_CSR_MIS|MESG_IN_PHASE ||
+                                   csr == SBIC_CSR_MIS_1|MESG_IN_PHASE ||
+                                   csr == SBIC_CSR_MIS_2|MESG_IN_PHASE) {
+                                       sbicmsgin(dev);
+                                       newlun = dev->sc_msg[0] & 7;
+                               } else {
+                                       printf("RSLT_NI - not MESG_IN_PHASE %x\n",
+                                           csr);
+                               }
+                       }
+               }
+#ifdef DEBUG
+               if(reselect_debug>1 || (reselect_debug && csr==SBIC_CSR_RSLT_NI))
+                       printf("sbicnext: reselect %s from targ %d lun %d\n",
+                           csr == SBIC_CSR_RSLT_NI ? "NI" : "IFY",
+                           newtarget, newlun);
+#endif
+               if (dev->sc_nexus) {
+#ifdef DEBUG
+                       if (reselect_debug > 1)
+                               printf("%s: reselect %s with active command\n",
+                                   dev->sc_dev.dv_xname,
+                                   csr == SBIC_CSR_RSLT_NI ? "NI" : "IFY");
+#ifdef DDB
+/*                     Debugger();*/
+#endif
+#endif
+                       TAILQ_INSERT_HEAD(&dev->ready_list, dev->sc_nexus, chain);
+                       dev->sc_tinfo[dev->target].lubusy &= ~(1 << dev->lun);
+                       dev->sc_nexus = NULL;
+                       dev->sc_xs = NULL;
+               }
+               /* Reload sync values for this target */
+               if (dev->sc_sync[newtarget].state == SYNC_DONE)
+                       SET_SBIC_syn(regs, SBIC_SYN (dev->sc_sync[newtarget].offset,
+                           dev->sc_sync[newtarget].period));
+               else
+                       SET_SBIC_syn(regs, SBIC_SYN (0, sbic_min_period));
+               for (acb = dev->nexus_list.tqh_first; acb;
+                   acb = acb->chain.tqe_next) {
+                       if (acb->xs->sc_link->target != newtarget ||
+                           acb->xs->sc_link->lun != newlun)
+                               continue;
+                       TAILQ_REMOVE(&dev->nexus_list, acb, chain);
+                       dev->sc_nexus = acb;
+                       dev->sc_xs = acb->xs;
+                       dev->sc_flags |= SBICF_SELECTED;
+                       dev->target = newtarget;
+                       dev->lun = newlun;
+                       break;
+               }
+               if (acb == NULL) {
+                       printf("%s: reselect %s targ %d not in nexus_list %x\n",
+                           dev->sc_dev.dv_xname,
+                           csr == SBIC_CSR_RSLT_NI ? "NI" : "IFY", newtarget,
+                           &dev->nexus_list.tqh_first);
+                       panic("bad reselect in sbic");
+               }
+               if (csr == SBIC_CSR_RSLT_IFY)
+                       SET_SBIC_cmd(regs, SBIC_CMD_CLR_ACK);
+               break;
+
+       default:
+        abort:
+               /*
+                * Something unexpected happened -- deal with it.
+                */
+               printf("sbicnextstate: aborting csr %02x asr %02x\n", csr, asr);
+#ifdef DDB
+               Debugger();
+#endif
+#ifdef DEBUG
+               if( data_pointer_debug > 1 )
+                       printf("next dmastop: %d(%x:%x)\n",
+                              dev->target,dev->sc_cur->dc_addr,dev->sc_tcnt);
+               dev->sc_dmatimo = 0;
+#endif
+               dev->sc_dmastop(dev);
+               SET_SBIC_control(regs, SBIC_CTL_EDI | SBIC_CTL_IDI);
+               sbicerror(dev, regs, csr);
+               sbicabort(dev, regs, "next");
+               if (dev->sc_flags & SBICF_INDMA) {
+                       /*
+                        * check for overlapping cache line, flush if so
+                        */
+#ifdef M68040
+                       if (dev->sc_flags & SBICF_DCFLUSH) {
+#if 0
+                               printf("sibc: 68040 DMA cache flush needs fixing? %x:%x\n",
+                                   dev->sc_xs->data, dev->sc_xs->datalen);
+#endif
+                       }
+#endif
+                       dev->sc_flags &=
+                               ~(SBICF_INDMA | SBICF_DCFLUSH);
+#ifdef DEBUG
+                       if( data_pointer_debug > 1 )
+                               printf("next dmastop: %d(%x:%x)\n",
+                                   dev->target,dev->sc_cur->dc_addr,dev->sc_tcnt);
+                       dev->sc_dmatimo = 0;
+#endif
+                       dev->sc_dmastop(dev);
+                       sbic_scsidone(acb, -1);
+               }
+               SBIC_TRACE(dev);
+                return SBIC_STATE_ERROR;
+       }
+
+       SBIC_TRACE(dev);
+       return(SBIC_STATE_RUNNING);
+}
+
+
+/*
+ * Check if DMA can not be used with specified buffer
+ */
+
+int
+sbiccheckdmap(bp, len, mask)
+       void *bp;
+       u_long len, mask;
+{
+       u_char *buffer;
+       u_long phy_buf;
+       u_long phy_len;
+
+       buffer = bp;
+
+       if (len == 0)
+               return(0);
+
+       while (len) {
+               phy_buf = kvtop(buffer);
+               if (len < (phy_len = NBPG - ((int) buffer & PGOFSET)))
+                       phy_len = len;
+               if (phy_buf & mask)
+                       return(1);
+               buffer += phy_len;
+               len -= phy_len;
+       }
+       return(0);
+}
+
+int
+sbictoscsiperiod(dev, regs, a)
+       struct sbic_softc *dev;
+       sbic_regmap_p regs;
+       int a;
+{
+       unsigned int fs;
+
+       /*
+        * cycle = DIV / (2*CLK)
+        * DIV = FS+2
+        * best we can do is 200ns at 20Mhz, 2 cycles
+        */
+
+       GET_SBIC_myid(regs,fs);
+       fs = (fs >>6) + 2;              /* DIV */
+       fs = (fs * 10000) / (dev->sc_clkfreq<<1);       /* Cycle, in ns */
+       if (a < 2) a = 8;               /* map to Cycles */
+       return ((fs*a)>>2);             /* in 4 ns units */
+}
+
+int
+sbicfromscsiperiod(dev, regs, p)
+       struct sbic_softc *dev;
+       sbic_regmap_p regs;
+       int p;
+{
+       register unsigned int fs, ret;
+
+       /* Just the inverse of the above */
+
+       GET_SBIC_myid(regs,fs);
+       fs = (fs >>6) + 2;              /* DIV */
+       fs = (fs * 10000) / (dev->sc_clkfreq<<1);   /* Cycle, in ns */
+
+       ret = p << 2;                   /* in ns units */
+       ret = ret / fs;                 /* in Cycles */
+       if (ret < sbic_min_period)
+               return(sbic_min_period);
+
+       /* verify rounding */
+       if (sbictoscsiperiod(dev, regs, ret) < p)
+               ret++;
+       return (ret >= 8) ? 0 : ret;
+}
+
+#ifdef DEBUG
+
+void sbicdumpstate()
+{
+       u_char csr, asr;
+
+       GET_SBIC_asr(debug_sbic_regs,asr);
+       GET_SBIC_csr(debug_sbic_regs,csr);
+       printf("%s: asr:csr(%02x:%02x)->(%02x:%02x)\n",
+              (routine==1)?"sbicgo":
+              (routine==2)?"sbicintr":
+              (routine==3)?"sbicicmd":
+              (routine==4)?"sbicnext":"unknown",
+              debug_asr, debug_csr, asr, csr);
+
+}
+
+void sbictimeout(dev)
+       struct sbic_softc *dev;
+{
+       int s, asr;
+
+       s = splbio();
+       if (dev->sc_dmatimo) {
+               if (dev->sc_dmatimo > 1) {
+                       printf("%s: dma timeout #%d\n",
+                           dev->sc_dev.dv_xname, dev->sc_dmatimo - 1);
+                       GET_SBIC_asr(dev->sc_sbicp, asr);
+                       if( asr & SBIC_ASR_INT ) {
+                               /* We need to service a missed IRQ */
+                               printf("Servicing a missed int:(%02x,%02x)->(%02x,??)\n",
+                                   debug_asr, debug_csr, asr);
+                               sbicintr(dev);
+                       }
+                       sbicdumpstate();
+               }
+               dev->sc_dmatimo++;
+       }
+       splx(s);
+       timeout((void *)sbictimeout, dev, 30 * hz);
+}
+
+void
+sbic_dump_acb(acb)
+       struct sbic_acb *acb;
+{
+       u_char *b = (u_char *) &acb->cmd;
+       int i;
+
+       printf("acb@%x ", acb);
+       if (acb->xs == NULL) {
+               printf("<unused>\n");
+               return;
+       }
+       printf("(%d:%d) flags %2x clen %2d cmd ", acb->xs->sc_link->target,
+           acb->xs->sc_link->lun, acb->flags, acb->clen);
+       for (i = acb->clen; i; --i)
+               printf(" %02x", *b++);
+       printf("\n");
+       printf("  xs: %08x data %8x:%04x ", acb->xs, acb->xs->data,
+           acb->xs->datalen);
+       printf("va %8x:%04x ", acb->sc_kv.dc_addr, acb->sc_kv.dc_count);
+       printf("pa %8x:%04x tcnt %x\n", acb->sc_pa.dc_addr, acb->sc_pa.dc_count,
+           acb->sc_tcnt);
+}
+
+void
+sbic_dump(dev)
+       struct sbic_softc *dev;
+{
+       sbic_regmap_p regs;
+       u_char csr, asr;
+       struct sbic_acb *acb;
+       int s;
+       int i;
+
+       s = splbio();
+       regs = dev->sc_sbicp;
+#if CSR_TRACE_SIZE
+       printf("csr trace: ");
+       i = csr_traceptr;
+       do {
+               printf("%c%02x%02x%02x ", csr_trace[i].whr,
+                   csr_trace[i].csr, csr_trace[i].asr, csr_trace[i].xtn);
+               switch(csr_trace[i].whr) {
+               case 'g':
+                       printf("go "); break;
+               case 's':
+                       printf("select "); break;
+               case 'y':
+                       printf("select+ "); break;
+               case 'i':
+                       printf("intr "); break;
+               case 'f':
+                       printf("finish "); break;
+               case '>':
+                       printf("out "); break;
+               case '<':
+                       printf("in "); break;
+               case 'm':
+                       printf("msgin "); break;
+               case 'x':
+                       printf("msginx "); break;
+               case 'X':
+                       printf("msginX "); break;
+               case 'r':
+                       printf("reselect "); break;
+               case 'I':
+                       printf("icmd "); break;
+               case 'a':
+                       printf("abort "); break;
+               default:
+                       printf("? ");
+               }
+               switch(csr_trace[i].csr) {
+               case 0x11:
+                       printf("INITIATOR"); break;
+               case 0x16:
+                       printf("S_XFERRED"); break;
+               case 0x20:
+                       printf("MSGIN_ACK"); break;
+               case 0x41:
+                       printf("DISC"); break;
+               case 0x42:
+                       printf("SEL_TIMEO"); break;
+               case 0x80:
+                       printf("RSLT_NI"); break;
+               case 0x81:
+                       printf("RSLT_IFY"); break;
+               case 0x85:
+                       printf("DISC_1"); break;
+               case 0x18: case 0x19: case 0x1a:
+               case 0x1b: case 0x1e: case 0x1f:
+               case 0x28: case 0x29: case 0x2a:
+               case 0x2b: case 0x2e: case 0x2f:
+               case 0x48: case 0x49: case 0x4a:
+               case 0x4b: case 0x4e: case 0x4f:
+               case 0x88: case 0x89: case 0x8a:
+               case 0x8b: case 0x8e: case 0x8f:
+                       switch(csr_trace[i].csr & 0xf0) {
+                       case 0x10:
+                               printf("DONE_"); break;
+                       case 0x20:
+                               printf("STOP_"); break;
+                       case 0x40:
+                               printf("ERR_"); break;
+                       case 0x80:
+                               printf("REQ_"); break;
+                       }
+                       switch(csr_trace[i].csr & 7) {
+                       case 0:
+                               printf("DATA_OUT"); break;
+                       case 1:
+                               printf("DATA_IN"); break;
+                       case 2:
+                               printf("CMD"); break;
+                       case 3:
+                               printf("STATUS"); break;
+                       case 6:
+                               printf("MSG_OUT"); break;
+                       case 7:
+                               printf("MSG_IN"); break;
+                       default:
+                               printf("invld phs");
+                       }
+                       break;
+               default:    printf("****"); break;
+               }
+               if (csr_trace[i].asr & SBIC_ASR_INT)
+                       printf(" ASR_INT");
+               if (csr_trace[i].asr & SBIC_ASR_LCI)
+                       printf(" ASR_LCI");
+               if (csr_trace[i].asr & SBIC_ASR_BSY)
+                       printf(" ASR_BSY");
+               if (csr_trace[i].asr & SBIC_ASR_CIP)
+                       printf(" ASR_CIP");
+               printf("\n");
+               i = (i + 1) & (CSR_TRACE_SIZE - 1);
+       } while (i != csr_traceptr);
+#endif
+       GET_SBIC_asr(regs, asr);
+       if ((asr & SBIC_ASR_INT) == 0)
+               GET_SBIC_csr(regs, csr);
+       else
+               csr = 0;
+       printf("%s@%x regs %x asr %x csr %x\n", dev->sc_dev.dv_xname,
+           dev, regs, asr, csr);
+       if (acb = dev->free_list.tqh_first) {
+               printf("Free list:\n");
+               while (acb) {
+                       sbic_dump_acb(acb);
+                       acb = acb->chain.tqe_next;
+               }
+       }
+       if (acb = dev->ready_list.tqh_first) {
+               printf("Ready list:\n");
+               while (acb) {
+                       sbic_dump_acb(acb);
+                       acb = acb->chain.tqe_next;
+               }
+       }
+       if (acb = dev->nexus_list.tqh_first) {
+               printf("Nexus list:\n");
+               while (acb) {
+                       sbic_dump_acb(acb);
+                       acb = acb->chain.tqe_next;
+               }
+       }
+       if (dev->sc_nexus) {
+               printf("nexus:\n");
+               sbic_dump_acb(dev->sc_nexus);
+       }
+       printf("sc_xs %x targ %d lun %d flags %x tcnt %x dmacmd %x mask %x\n",
+           dev->sc_xs, dev->target, dev->lun, dev->sc_flags, dev->sc_tcnt,
+           dev->sc_dmacmd, dev->sc_dmamask);
+       for (i = 0; i < 8; ++i) {
+               if (dev->sc_tinfo[i].cmds > 2) {
+                       printf("tgt %d: cmds %d disc %d senses %d lubusy %x\n",
+                           i, dev->sc_tinfo[i].cmds,
+                           dev->sc_tinfo[i].dconns,
+                           dev->sc_tinfo[i].senses,
+                           dev->sc_tinfo[i].lubusy);
+               }
+       }
+       splx(s);
+}
+
+#endif
diff --git a/sys/arch/arm32/podulebus/sbicreg.h b/sys/arch/arm32/podulebus/sbicreg.h
new file mode 100644 (file)
index 0000000..0b43c60
--- /dev/null
@@ -0,0 +1,426 @@
+/* $NetBSD: sbicreg.h,v 1.1 1996/03/06 23:44:09 mark Exp $ */
+
+/*
+ * Copyright (c) 1990 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.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided 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.
+ *
+ *     @(#)scsireg.h   7.3 (Berkeley) 2/5/91
+ */
+
+/*
+ * AMD AM33C93A SCSI interface hardware description.
+ *
+ * Using parts of the Mach scsi driver for the 33C93
+ */
+
+#define        SBIC_myid       0
+#define        SBIC_cdbsize    0
+#define        SBIC_control    1
+#define        SBIC_timeo      2
+#define        SBIC_cdb1       3
+#define        SBIC_tsecs      3
+#define        SBIC_cdb2       4
+#define        SBIC_theads     4
+#define        SBIC_cdb3       5
+#define        SBIC_tcyl_hi    5
+#define        SBIC_cdb4       6
+#define        SBIC_tcyl_lo    6
+#define        SBIC_cdb5       7
+#define        SBIC_addr_hi    7
+#define        SBIC_cdb6       8
+#define        SBIC_addr_2     8
+#define        SBIC_cdb7       9
+#define        SBIC_addr_3     9
+#define        SBIC_cdb8       10
+#define        SBIC_addr_lo    10
+#define        SBIC_cdb9       11
+#define        SBIC_secno      11
+#define        SBIC_cdb10      12
+#define        SBIC_headno     12
+#define        SBIC_cdb11      13
+#define        SBIC_cylno_hi   13
+#define        SBIC_cdb12      14
+#define        SBIC_cylno_lo   14
+#define        SBIC_tlun       15
+#define        SBIC_cmd_phase  16
+#define        SBIC_syn        17
+#define        SBIC_count_hi   18
+#define        SBIC_count_med  19
+#define        SBIC_count_lo   20
+#define        SBIC_selid      21
+#define        SBIC_rselid     22
+#define        SBIC_csr        23
+#define        SBIC_cmd        24
+#define        SBIC_data       25
+/* sbic_asr is addressed directly */
+
+/*
+ *     Register defines
+ */
+
+/*
+ * Auxiliary Status Register
+ */
+
+#define SBIC_ASR_INT           0x80    /* Interrupt pending */
+#define SBIC_ASR_LCI           0x40    /* Last command ignored */
+#define SBIC_ASR_BSY           0x20    /* Busy, only cmd/data/asr readable */
+#define SBIC_ASR_CIP           0x10    /* Busy, cmd unavail also */
+#define SBIC_ASR_xxx           0x0c
+#define SBIC_ASR_PE            0x02    /* Parity error (even) */
+#define SBIC_ASR_DBR           0x01    /* Data Buffer Ready */
+
+/*
+ * My ID register, and/or CDB Size
+ */
+
+#define SBIC_ID_FS_8_10                0x00    /* Input clock is  8-10 Mhz */
+                                       /* 11 Mhz is invalid */
+#define SBIC_ID_FS_12_15       0x40    /* Input clock is 12-15 Mhz */
+#define SBIC_ID_FS_16_20       0x80    /* Input clock is 16-20 Mhz */
+#define SBIC_ID_EHP            0x10    /* Enable host parity */
+#define SBIC_ID_EAF            0x08    /* Enable Advanced Features */
+#define SBIC_ID_MASK           0x07
+#define SBIC_ID_CBDSIZE_MASK   0x0f    /* if unk SCSI cmd group */
+
+/*
+ * Control register
+ */
+
+#define SBIC_CTL_DMA           0x80    /* Single byte dma */
+#define SBIC_CTL_DBA_DMA       0x40    /* direct buffer acces (bus master)*/
+#define SBIC_CTL_BURST_DMA     0x20    /* continuous mode (8237) */
+#define SBIC_CTL_NO_DMA                0x00    /* Programmed I/O */
+#define SBIC_CTL_HHP           0x10    /* Halt on host parity error */
+#define SBIC_CTL_EDI           0x08    /* Ending disconnect interrupt */
+#define SBIC_CTL_IDI           0x04    /* Intermediate disconnect interrupt*/
+#define SBIC_CTL_HA            0x02    /* Halt on ATN */
+#define SBIC_CTL_HSP           0x01    /* Halt on SCSI parity error */
+
+/*
+ * Timeout period register
+ * [val in msecs, input clk in 0.1 Mhz]
+ */
+
+#define        SBIC_TIMEOUT(val,clk)   ((((val) * (clk)) / 800) + 1)
+
+/*
+ * CDBn registers, note that
+ *     cdb11 is used for status byte in target mode (send-status-and-cc)
+ *     cdb12 sez if linked command complete, and w/flag if so
+ */
+
+/*
+ * Target LUN register
+ * [holds target status when select-and-xfer]
+ */
+
+#define        SBIC_TLUN_VALID 0x80    /* did we receive an Identify msg */
+#define        SBIC_TLUN_DOK   0x40    /* Disconnect OK */
+#define        SBIC_TLUN_xxx   0x38
+#define        SBIC_TLUN_MASK  0x07
+
+/*
+ * Command Phase register
+ */
+
+#define        SBIC_CPH_MASK   0x7f    /* values/restarts are cmd specific */
+#define        SBIC_CPH(p)     ((p) & SBIC_CPH_MASK)
+
+/*
+ * FIFO register
+ */
+
+#define SBIC_FIFO_DEEP 12
+
+/*
+ * maximum possible size in TC registers. Since this is 24 bit, it's easy
+ */
+#define SBIC_TC_MAX    ((1 << 24) - 1)
+
+/*
+ * Synchronous xfer register
+ */
+
+#define        SBIC_SYN_OFF_MASK       0x0f
+#define        SBIC_SYN_MAX_OFFSET     SBIC_FIFO_DEEP
+#define        SBIC_SYN_PER_MASK       0x70
+#define        SBIC_SYN_MIN_PERIOD     2               /* upto 8, encoded as 0 */
+
+#define        SBIC_SYN(o,p) \
+    (((o) & SBIC_SYN_OFF_MASK) | (((p) << 4) & SBIC_SYN_PER_MASK))
+
+/*
+ * Transfer count register
+ * optimal access macros depend on addressing
+ */
+
+/*
+ * Destination ID (selid) register
+ */
+
+#define        SBIC_SID_SCC            0x80    /* Select command chaining (tgt) */
+#define        SBIC_SID_DPD            0x40    /* Data phase direction (inittor) */
+#define        SBIC_SID_FROM_SCSI      0x40
+#define        SBIC_SID_TO_SCSI        0x00
+#define        SBIC_SID_xxx            0x38
+#define        SBIC_SID_IDMASK         0x07
+
+/*
+ * Source ID (rselid) register
+ */
+
+#define        SBIC_RID_ER             0x80    /* Enable reselection */
+#define        SBIC_RID_ES             0x40    /* Enable selection */
+#define        SBIC_RID_DSP            0x20    /* Disable select parity */
+#define        SBIC_RID_SIV            0x08    /* Source ID valid */
+#define        SBIC_RID_MASK           0x07
+
+/*
+ * Status register
+ */
+
+#define        SBIC_CSR_CAUSE          0xf0
+#define        SBIC_CSR_RESET          0x00    /* chip was reset */
+#define        SBIC_CSR_CMD_DONE       0x10    /* cmd completed */
+#define        SBIC_CSR_CMD_STOPPED    0x20    /* interrupted or abrted*/
+#define        SBIC_CSR_CMD_ERR        0x40    /* end with error */
+#define        SBIC_CSR_BUS_SERVICE    0x80    /* REQ pending on the bus */
+
+
+#define        SBIC_CSR_QUALIFIER      0x0f
+/* Reset State Interrupts */
+#define        SBIC_CSR_RESET          0x00    /* reset w/advanced features*/
+#define        SBIC_CSR_RESET_AM       0x01    /* reset w/advanced features*/
+/* Successful Completion Interrupts */
+#define        SBIC_CSR_TARGET         0x10    /* reselect complete */
+#define        SBIC_CSR_INITIATOR      0x11    /* select complete */
+#define        SBIC_CSR_WO_ATN         0x13    /* tgt mode completion */
+#define        SBIC_CSR_W_ATN          0x14    /* ditto */
+#define        SBIC_CSR_XLATED         0x15    /* translate address cmd */
+#define        SBIC_CSR_S_XFERRED      0x16    /* initiator mode completion*/
+#define        SBIC_CSR_XFERRED        0x18    /* phase in low bits */
+/* Paused or Aborted Interrupts */
+#define        SBIC_CSR_MSGIN_W_ACK    0x20    /* (I) msgin, ACK asserted*/
+#define        SBIC_CSR_SDP            0x21    /* (I) SDP msg received */
+#define        SBIC_CSR_SEL_ABRT       0x22    /* sel/resel aborted */
+#define        SBIC_CSR_XFR_PAUSED     0x23    /* (T) no ATN */
+#define        SBIC_CSR_XFR_PAUSED_ATN 0x24    /* (T) ATN is asserted */
+#define        SBIC_CSR_RSLT_AM        0x27    /* (I) lost selection (AM) */
+#define        SBIC_CSR_MIS            0x28    /* (I) xfer aborted, ph mis */
+/* Terminated Interrupts */
+#define        SBIC_CSR_CMD_INVALID    0x40
+#define        SBIC_CSR_DISC           0x41    /* (I) tgt disconnected */
+#define        SBIC_CSR_SEL_TIMEO      0x42
+#define        SBIC_CSR_PE             0x43    /* parity error */
+#define        SBIC_CSR_PE_ATN         0x44    /* ditto, ATN is asserted */
+#define        SBIC_CSR_XLATE_TOOBIG   0x45
+#define        SBIC_CSR_RSLT_NOAM      0x46    /* (I) lost sel, no AM mode */
+#define        SBIC_CSR_BAD_STATUS     0x47    /* status byte was nok */
+#define        SBIC_CSR_MIS_1          0x48    /* ph mis, see low bits */
+/* Service Required Interrupts */
+#define        SBIC_CSR_RSLT_NI        0x80    /* reselected, no ify msg */
+#define        SBIC_CSR_RSLT_IFY       0x81    /* ditto, AM mode, got ify */
+#define        SBIC_CSR_SLT            0x82    /* selected, no ATN */
+#define        SBIC_CSR_SLT_ATN        0x83    /* selected with ATN */
+#define        SBIC_CSR_ATN            0x84    /* (T) ATN asserted */
+#define        SBIC_CSR_DISC_1         0x85    /* (I) bus is free */
+#define        SBIC_CSR_UNK_GROUP      0x87    /* strange CDB1 */
+#define        SBIC_CSR_MIS_2          0x88    /* (I) ph mis, see low bits */
+
+#define        SBIC_PHASE(csr)         SCSI_PHASE(csr)
+
+/*
+ * Command register (command codes)
+ */
+
+#define SBIC_CMD_SBT           0x80    /* Single byte xfer qualifier */
+#define        SBIC_CMD_MASK           0x7f
+
+                                       /* Miscellaneous */
+#define SBIC_CMD_RESET         0x00    /* (DTI) lev I */
+#define SBIC_CMD_ABORT         0x01    /* (DTI) lev I */
+#define SBIC_CMD_DISC          0x04    /* ( TI) lev I */
+#define SBIC_CMD_SSCC          0x0d    /* ( TI) lev I */
+#define SBIC_CMD_SET_IDI       0x0f    /* (DTI) lev I */
+#define SBIC_CMD_XLATE         0x18    /* (DT ) lev II */
+
+                                       /* Initiator state */
+#define SBIC_CMD_SET_ATN       0x02    /* (  I) lev I */
+#define SBIC_CMD_CLR_ACK       0x03    /* (  I) lev I */
+#define SBIC_CMD_XFER_PAD      0x19    /* (  I) lev II */
+#define SBIC_CMD_XFER_INFO     0x20    /* (  I) lev II */
+
+                                       /* Target state */
+#define SBIC_CMD_SND_DISC      0x0e    /* ( T ) lev II */
+#define SBIC_CMD_RCV_CMD       0x10    /* ( T ) lev II */
+#define SBIC_CMD_RCV_DATA      0x11    /* ( T ) lev II */
+#define SBIC_CMD_RCV_MSG_OUT   0x12    /* ( T ) lev II */
+#define SBIC_CMD_RCV           0x13    /* ( T ) lev II */
+#define SBIC_CMD_SND_STATUS    0x14    /* ( T ) lev II */
+#define SBIC_CMD_SND_DATA      0x15    /* ( T ) lev II */
+#define SBIC_CMD_SND_MSG_IN    0x16    /* ( T ) lev II */
+#define SBIC_CMD_SND           0x17    /* ( T ) lev II */
+
+                                       /* Disconnected state */
+#define SBIC_CMD_RESELECT      0x05    /* (D  ) lev II */
+#define SBIC_CMD_SEL_ATN       0x06    /* (D  ) lev II */
+#define SBIC_CMD_SEL           0x07    /* (D  ) lev II */
+#define SBIC_CMD_SEL_ATN_XFER  0x08    /* (D I) lev II */
+#define SBIC_CMD_SEL_XFER      0x09    /* (D I) lev II */
+#define SBIC_CMD_RESELECT_RECV 0x0a    /* (DT ) lev II */
+#define SBIC_CMD_RESELECT_SEND 0x0b    /* (DT ) lev II */
+#define SBIC_CMD_WAIT_SEL_RECV 0x0c    /* (DT ) lev II */
+
+/* approximate, but we won't do SBT on selects */
+#define        sbic_isa_select(cmd)    (((cmd) > 0x5) && ((cmd) < 0xa))
+
+#define PAD(n)         char n;
+#define SBIC_MACHINE_DMA_MODE  SBIC_CTL_DMA
+
+typedef struct {
+        volatile unsigned char  sbic_asr;      /* r : Aux Status Register */
+#define sbic_address sbic_asr                  /* w : desired register no */
+        PAD(pad1);
+        PAD(pad2);
+        PAD(pad3);
+        volatile unsigned char  sbic_value;    /* rw: register value */
+} sbic_padded_ind_regmap_t;
+typedef volatile sbic_padded_ind_regmap_t *sbic_regmap_p;
+
+#define        sbic_read_reg(regs,regno,val) do { \
+               (regs)->sbic_address = (regno); \
+               (val) = (regs)->sbic_value;     \
+       } while (0)
+
+#define        sbic_write_reg(regs,regno,val)  do { \
+               (regs)->sbic_address = (regno); \
+               (regs)->sbic_value = (val);     \
+       } while (0)
+
+#define SET_SBIC_myid(regs,val)         sbic_write_reg(regs,SBIC_myid,val)
+#define GET_SBIC_myid(regs,val)         sbic_read_reg(regs,SBIC_myid,val)
+#define SET_SBIC_cdbsize(regs,val)      sbic_write_reg(regs,SBIC_cdbsize,val)
+#define GET_SBIC_cdbsize(regs,val)      sbic_read_reg(regs,SBIC_cdbsize,val)
+#define SET_SBIC_control(regs,val)      sbic_write_reg(regs,SBIC_control,val)
+#define GET_SBIC_control(regs,val)      sbic_read_reg(regs,SBIC_control,val)
+#define SET_SBIC_timeo(regs,val)        sbic_write_reg(regs,SBIC_timeo,val)
+#define GET_SBIC_timeo(regs,val)        sbic_read_reg(regs,SBIC_timeo,val)
+#define SET_SBIC_cdb1(regs,val)         sbic_write_reg(regs,SBIC_cdb1,val)
+#define GET_SBIC_cdb1(regs,val)         sbic_read_reg(regs,SBIC_cdb1,val)
+#define SET_SBIC_cdb2(regs,val)         sbic_write_reg(regs,SBIC_cdb2,val)
+#define GET_SBIC_cdb2(regs,val)         sbic_read_reg(regs,SBIC_cdb2,val)
+#define SET_SBIC_cdb3(regs,val)         sbic_write_reg(regs,SBIC_cdb3,val)
+#define GET_SBIC_cdb3(regs,val)         sbic_read_reg(regs,SBIC_cdb3,val)
+#define SET_SBIC_cdb4(regs,val)         sbic_write_reg(regs,SBIC_cdb4,val)
+#define GET_SBIC_cdb4(regs,val)         sbic_read_reg(regs,SBIC_cdb4,val)
+#define SET_SBIC_cdb5(regs,val)         sbic_write_reg(regs,SBIC_cdb5,val)
+#define GET_SBIC_cdb5(regs,val)         sbic_read_reg(regs,SBIC_cdb5,val)
+#define SET_SBIC_cdb6(regs,val)         sbic_write_reg(regs,SBIC_cdb6,val)
+#define GET_SBIC_cdb6(regs,val)         sbic_read_reg(regs,SBIC_cdb6,val)
+#define SET_SBIC_cdb7(regs,val)         sbic_write_reg(regs,SBIC_cdb7,val)
+#define GET_SBIC_cdb7(regs,val)         sbic_read_reg(regs,SBIC_cdb7,val)
+#define SET_SBIC_cdb8(regs,val)         sbic_write_reg(regs,SBIC_cdb8,val)
+#define GET_SBIC_cdb8(regs,val)         sbic_read_reg(regs,SBIC_cdb8,val)
+#define SET_SBIC_cdb9(regs,val)         sbic_write_reg(regs,SBIC_cdb9,val)
+#define GET_SBIC_cdb9(regs,val)         sbic_read_reg(regs,SBIC_cdb9,val)
+#define SET_SBIC_cdb10(regs,val)        sbic_write_reg(regs,SBIC_cdb10,val)
+#define GET_SBIC_cdb10(regs,val)        sbic_read_reg(regs,SBIC_cdb10,val)
+#define SET_SBIC_cdb11(regs,val)        sbic_write_reg(regs,SBIC_cdb11,val)
+#define GET_SBIC_cdb11(regs,val)        sbic_read_reg(regs,SBIC_cdb11,val)
+#define SET_SBIC_cdb12(regs,val)        sbic_write_reg(regs,SBIC_cdb12,val)
+#define GET_SBIC_cdb12(regs,val)        sbic_read_reg(regs,SBIC_cdb12,val)
+#define SET_SBIC_tlun(regs,val)         sbic_write_reg(regs,SBIC_tlun,val)
+#define GET_SBIC_tlun(regs,val)         sbic_read_reg(regs,SBIC_tlun,val)
+#define SET_SBIC_cmd_phase(regs,val)    sbic_write_reg(regs,SBIC_cmd_phase,val)
+#define GET_SBIC_cmd_phase(regs,val)    sbic_read_reg(regs,SBIC_cmd_phase,val)
+#define SET_SBIC_syn(regs,val)          sbic_write_reg(regs,SBIC_syn,val)
+#define GET_SBIC_syn(regs,val)          sbic_read_reg(regs,SBIC_syn,val)
+#define SET_SBIC_count_hi(regs,val)     sbic_write_reg(regs,SBIC_count_hi,val)
+#define GET_SBIC_count_hi(regs,val)     sbic_read_reg(regs,SBIC_count_hi,val)
+#define SET_SBIC_count_med(regs,val)    sbic_write_reg(regs,SBIC_count_med,val)
+#define GET_SBIC_count_med(regs,val)    sbic_read_reg(regs,SBIC_count_med,val)
+#define SET_SBIC_count_lo(regs,val)     sbic_write_reg(regs,SBIC_count_lo,val)
+#define GET_SBIC_count_lo(regs,val)     sbic_read_reg(regs,SBIC_count_lo,val)
+#define SET_SBIC_selid(regs,val)        sbic_write_reg(regs,SBIC_selid,val)
+#define GET_SBIC_selid(regs,val)        sbic_read_reg(regs,SBIC_selid,val)
+#define SET_SBIC_rselid(regs,val)       sbic_write_reg(regs,SBIC_rselid,val)
+#define GET_SBIC_rselid(regs,val)       sbic_read_reg(regs,SBIC_rselid,val)
+#define SET_SBIC_csr(regs,val)          sbic_write_reg(regs,SBIC_csr,val)
+#define GET_SBIC_csr(regs,val)          sbic_read_reg(regs,SBIC_csr,val)
+#define SET_SBIC_cmd(regs,val)          sbic_write_reg(regs,SBIC_cmd,val)
+#define GET_SBIC_cmd(regs,val)          sbic_read_reg(regs,SBIC_cmd,val)
+#define SET_SBIC_data(regs,val)         sbic_write_reg(regs,SBIC_data,val)
+#define GET_SBIC_data(regs,val)         sbic_read_reg(regs,SBIC_data,val)
+
+#define SBIC_TC_PUT(regs,val) do { \
+       sbic_write_reg(regs,SBIC_count_hi,((val)>>16)); \
+       (regs)->sbic_value = (val)>>8; \
+       (regs)->sbic_value = (val); \
+} while (0)
+#define SBIC_TC_GET(regs,val) do { \
+       sbic_read_reg(regs,SBIC_count_hi,(val)); \
+       (val) = ((val)<<8) | (regs)->sbic_value; \
+       (val) = ((val)<<8) | (regs)->sbic_value; \
+} while (0)
+
+#define SBIC_LOAD_COMMAND(regs,cmd,cmdsize) do { \
+       int n=(cmdsize)-1; \
+       char *ptr = (char*)(cmd); \
+       sbic_write_reg(regs,SBIC_cdb1,*ptr++); \
+       while (n-- > 0) (regs)->sbic_value = *ptr++; \
+} while (0)
+
+#define GET_SBIC_asr(regs,val)          (val) = (regs)->sbic_asr
+
+#define WAIT_CIP(regs) do { \
+       while ((regs)->sbic_asr & SBIC_ASR_CIP) \
+               ; \
+} while (0)
+
+/* transmit a byte in programmed I/O mode */
+#define SEND_BYTE(regs, ch) do { \
+  WAIT_CIP(regs); \
+  SET_SBIC_cmd(regs, SBIC_CMD_SBT | SBIC_CMD_XFER_INFO); \
+  SBIC_WAIT(regs, SBIC_ASR_DBR, 0); \
+  SET_SBIC_data(regs, ch); \
+  } while (0)
+
+/* receive a byte in programmed I/O mode */
+#define RECV_BYTE(regs, ch) do { \
+  WAIT_CIP(regs); \
+  SET_SBIC_cmd(regs, SBIC_CMD_SBT | SBIC_CMD_XFER_INFO); \
+  SBIC_WAIT(regs, SBIC_ASR_DBR, 0); \
+  GET_SBIC_data(regs, ch); \
+  } while (0)
diff --git a/sys/arch/arm32/podulebus/sbicvar.h b/sys/arch/arm32/podulebus/sbicvar.h
new file mode 100644 (file)
index 0000000..3e17ecc
--- /dev/null
@@ -0,0 +1,230 @@
+/* $NetBSD: sbicvar.h,v 1.1 1996/03/06 23:44:10 mark Exp $ */
+
+/*
+ * Copyright (c) 1990 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.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided 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.
+ *
+ *     @(#)scsivar.h   7.1 (Berkeley) 5/8/90
+ */
+
+#ifndef _SBICVAR_H_
+#define _SBICVAR_H_
+#include <sys/malloc.h>
+
+/*
+ * The largest single request will be MAXPHYS bytes which will require
+ * at most MAXPHYS/NBPG+1 chain elements to describe, i.e. if none of
+ * the buffer pages are physically contiguous (MAXPHYS/NBPG) and the
+ * buffer is not page aligned (+1).
+ */
+#define        DMAMAXIO        (MAXPHYS/NBPG+1)
+
+struct dma_chain {
+       int     dc_count;
+       char    *dc_addr;
+};
+
+/*
+ * ACB. Holds additional information for each SCSI command Comments: We
+ * need a separate scsi command block because we may need to overwrite it
+ * with a request sense command.  Basicly, we refrain from fiddling with
+ * the scsi_xfer struct (except do the expected updating of return values).
+ * We'll generally update: xs->{flags,resid,error,sense,status} and
+ * occasionally xs->retries.
+ */
+struct sbic_acb {
+       TAILQ_ENTRY(sbic_acb) chain;
+       struct scsi_xfer *xs;           /* SCSI xfer ctrl block from above */
+       int             flags;          /* Status */
+#define ACB_FREE       0x00
+#define ACB_ACTIVE     0x01
+#define ACB_DONE       0x04
+#define ACB_CHKSENSE   0x08
+#define ACB_BBUF       0x10    /* DMA input needs to be copied from bounce */
+#define        ACB_DATAIN      0x20    /* DMA direction flag */
+       struct scsi_generic cmd;        /* SCSI command block */
+       int      clen;
+       struct  dma_chain sc_kv;        /* Virtual address of whole DMA */
+       struct  dma_chain sc_pa;        /* Physical address of DMA segment */
+       u_long  sc_tcnt;                /* number of bytes for this DMA */
+       u_char *sc_dmausrbuf;           /* user buffer kva - for bounce copy */
+       u_long  sc_dmausrlen;           /* length of bounce copy */
+       u_short sc_dmacmd;              /* Internal data for this DMA */
+       char *pa_addr;                  /* XXXX initial phys addr */
+       u_char *sc_usrbufpa;            /* user buffer phys addr */
+};
+
+/*
+ * Some info about each (possible) target on the SCSI bus.  This should
+ * probably have been a "per target+lunit" structure, but we'll leave it at
+ * this for now.  Is there a way to reliably hook it up to sc->fordriver??
+ */
+struct sbic_tinfo {
+       int     cmds;           /* #commands processed */
+       int     dconns;         /* #disconnects */
+       int     touts;          /* #timeouts */
+       int     perrs;          /* #parity errors */
+       int     senses;         /* #request sense commands sent */
+       u_char* bounce;         /* Bounce buffer for this device */
+       ushort  lubusy;         /* What local units/subr. are busy? */
+       u_char  flags;
+       u_char  period;         /* Period suggestion */
+       u_char  offset;         /* Offset suggestion */
+} tinfo_t;
+
+struct sbic_softc {
+       struct  device sc_dev;
+/*     struct  isr sc_isr;*/
+       struct  target_sync {
+               u_char  state;
+               u_char  period;
+               u_char  offset;
+       } sc_sync[8];
+       u_char  target;                 /* Currently active target */
+       u_char  lun;
+       struct  scsi_link sc_link;      /* proto for sub devices */
+       sbic_regmap_p   sc_sbicp;       /* the SBIC */
+       volatile void   *sc_cregs;      /* driver specific regs */
+
+       /* Lists of command blocks */
+       TAILQ_HEAD(acb_list, sbic_acb) free_list,
+                                      ready_list,
+                                      nexus_list;
+
+       struct sbic_acb *sc_nexus;      /* current command */
+       struct sbic_acb sc_acb[8];      /* the real command blocks */
+       struct sbic_tinfo sc_tinfo[8];
+
+       struct  scsi_xfer *sc_xs;       /* transfer from high level code */
+       u_char  sc_flags;
+       u_char  sc_scsiaddr;
+       u_char  sc_stat[2];
+       u_char  sc_msg[7];
+       u_long  sc_clkfreq;
+       u_long  sc_tcnt;                /* number of bytes transfered */
+       u_short sc_dmacmd;              /* used by dma drivers */
+       u_short sc_dmatimo;             /* dma timeout */
+       u_long  sc_dmamask;             /* dma valid mem mask */
+       struct  dma_chain *sc_cur;
+       struct  dma_chain *sc_last;
+       int  (*sc_dmago)        __P((struct sbic_softc *, char *, int, int));
+       int  (*sc_dmanext)      __P((struct sbic_softc *));
+       void (*sc_enintr)       __P((struct sbic_softc *));
+       void (*sc_dmastop)      __P((struct sbic_softc *));
+       u_short gtsc_bankmask;          /* GVP specific bank selected */
+};
+
+/* sc_flags */
+#define        SBICF_ALIVE     0x01    /* controller initialized */
+#define SBICF_DCFLUSH  0x02    /* need flush for overlap after dma finishes */
+#define SBICF_SELECTED 0x04    /* bus is in selected state. */
+#define SBICF_ICMD     0x08    /* Immediate command in execution */
+#define SBICF_BADDMA   0x10    /* controller can only DMA to ztwobus space */
+#define        SBICF_INTR      0x40    /* SBICF interrupt expected */
+#define        SBICF_INDMA     0x80    /* not used yet, DMA I/O in progress */
+
+/* sync states */
+#define SYNC_START     0       /* no sync handshake started */
+#define SYNC_SENT      1       /* we sent sync request, no answer yet */
+#define SYNC_DONE      2       /* target accepted our (or inferior) settings,
+                                  or it rejected the request and we stay async */
+#ifdef DEBUG
+#define        DDB_FOLLOW      0x04
+#define DDB_IO         0x08
+#endif
+extern u_char sbic_inhibit_sync[8];
+extern int sbic_no_dma;
+extern int sbic_clock_override;
+
+#define        PHASE           0x07            /* mask for psns/pctl phase */
+#define        DATA_OUT_PHASE  0x00
+#define        DATA_IN_PHASE   0x01
+#define        CMD_PHASE       0x02
+#define        STATUS_PHASE    0x03
+#define        BUS_FREE_PHASE  0x04
+#define        ARB_SEL_PHASE   0x05    /* Fuji chip combines arbitration with sel. */
+#define        MESG_OUT_PHASE  0x06
+#define        MESG_IN_PHASE   0x07
+
+#define        MSG_CMD_COMPLETE        0x00
+#define MSG_EXT_MESSAGE                0x01
+#define        MSG_SAVE_DATA_PTR       0x02
+#define        MSG_RESTORE_PTR         0x03
+#define        MSG_DISCONNECT          0x04
+#define        MSG_INIT_DETECT_ERROR   0x05
+#define        MSG_ABORT               0x06
+#define        MSG_REJECT              0x07
+#define        MSG_NOOP                0x08
+#define        MSG_PARITY_ERROR        0x09
+#define        MSG_BUS_DEVICE_RESET    0x0C
+#define        MSG_IDENTIFY            0x80
+#define        MSG_IDENTIFY_DR         0xc0    /* (disconnect/reconnect allowed) */
+#define        MSG_SYNC_REQ            0x01
+
+#define MSG_ISIDENTIFY(x) (x&MSG_IDENTIFY)
+#define IFY_TRN                0x20
+#define IFY_LUNTRN(x)  (x&0x07)
+#define IFY_LUN(x)     (!(x&0x20))
+
+/* Check if high bit set */
+
+#define        STS_CHECKCOND   0x02    /* Check Condition (ie., read sense) */
+#define        STS_CONDMET     0x04    /* Condition Met (ie., search worked) */
+#define        STS_BUSY        0x08
+#define        STS_INTERMED    0x10    /* Intermediate status sent */
+#define        STS_EXT         0x80    /* Extended status valid */
+
+
+/* States returned by our state machine */
+
+#define SBIC_STATE_ERROR       -1
+#define SBIC_STATE_DONE                0
+#define SBIC_STATE_RUNNING     1
+#define SBIC_STATE_DISCONNECT  2
+
+/*
+ * XXXX
+ */
+struct scsi_fmt_cdb {
+       int len;                /* cdb length (in bytes) */
+       u_char cdb[28];         /* cdb to use on next read/write */
+};
+
+struct buf;
+struct scsi_xfer;
+
+void sbic_minphys __P((struct buf *bp));
+int sbic_scsicmd __P((struct scsi_xfer *));
+
+#endif /* _SBICVAR_H_ */
diff --git a/sys/arch/arm32/podulebus/sfas.c b/sys/arch/arm32/podulebus/sfas.c
new file mode 100644 (file)
index 0000000..f605486
--- /dev/null
@@ -0,0 +1,1621 @@
+/* $NetBSD: sfas.c,v 1.4 1996/03/18 21:23:20 mark Exp $ */
+
+/*
+ * Copyright (c) 1995 Scott Stevens
+ * Copyright (c) 1995 Daniel Widenfalk
+ * Copyright (c) 1994 Christian E. Hopps
+ * Copyright (c) 1990 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.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided 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.
+ *
+ *     @(#)scsi.c      7.5 (Berkeley) 5/4/91
+ */
+
+/*
+ * Emulex FAS216 scsi adaptor driver
+ */
+
+/*
+ * Modified for NetBSD/arm32 by Scott Stevens
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/device.h>
+#include <sys/buf.h>
+#include <sys/proc.h>
+#include <scsi/scsi_all.h>
+#include <scsi/scsiconf.h>
+#include <vm/vm.h>
+#include <vm/vm_kern.h>
+#include <vm/vm_page.h>
+#include <machine/pmap.h>
+#include <machine/cpu.h>
+#include <machine/io.h>
+#include <machine/irqhandler.h>
+#include <machine/katelib.h>
+#include <arm32/podulebus/podulebus.h>
+#include <arm32/podulebus/sfasreg.h>
+#include <arm32/podulebus/sfasvar.h>
+
+/* Externs */
+extern pt_entry_t *pmap_pte __P((pmap_t, vm_offset_t));
+
+void sfasinitialize __P((struct sfas_softc *));
+void sfas_minphys   __P((struct buf *bp));
+int  sfas_scsicmd   __P((struct scsi_xfer *xs));
+void sfas_donextcmd __P((struct sfas_softc *dev, struct sfas_pending *pendp));
+void sfas_scsidone  __P((struct sfas_softc *dev, struct scsi_xfer *xs,
+                        int stat));
+void sfasintr      __P((struct sfas_softc *dev));
+void sfasiwait     __P((struct sfas_softc *dev));
+void sfasreset     __P((struct sfas_softc *dev, int how));
+int  sfasselect            __P((struct sfas_softc *dev, struct sfas_pending *pendp,
+                        unsigned char *cbuf, int clen,
+                        unsigned char *buf, int len, int mode));
+void sfasicmd      __P((struct sfas_softc *dev, struct sfas_pending *pendp));
+void sfasgo         __P((struct sfas_softc *dev, struct sfas_pending *pendp));
+
+/*
+ * Initialize these to make 'em patchable. Defaults to enable sync and discon.
+ */
+u_char sfas_inhibit_sync[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
+u_char sfas_inhibit_disc[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
+
+#define DEBUG
+#ifdef DEBUG
+#define QPRINTF(a) if (sfas_debug > 1) printf a
+int    sfas_debug = 2;
+#else
+#define QPRINTF
+#endif
+
+/*
+ * default minphys routine for sfas based controllers
+ */
+void
+sfas_minphys(bp)
+       struct buf *bp;
+{
+
+       /*
+        * No max transfer at this level.
+        */
+       minphys(bp);
+}
+
+/*
+ * Initialize the nexus structs.
+ */
+void
+sfas_init_nexus(dev, nexus)
+       struct sfas_softc *dev;
+       struct nexus      *nexus;
+{
+       bzero(nexus, sizeof(struct nexus));
+
+       nexus->state    = SFAS_NS_IDLE;
+       nexus->period   = 200;
+       nexus->offset   = 0;
+       nexus->syncper  = 5;
+       nexus->syncoff  = 0;
+       nexus->config3  = dev->sc_config3 & ~SFAS_CFG3_FASTSCSI;
+}
+
+void
+sfasinitialize(dev)
+       struct sfas_softc *dev;
+{
+       u_int           *pte;
+       int              i;
+
+       dev->sc_led_status = 0;
+
+       TAILQ_INIT(&dev->sc_xs_pending);
+       TAILQ_INIT(&dev->sc_xs_free);
+
+/*
+ * Initialize the sfas_pending structs and link them into the free list. We
+ * have to set vm_link_data.pages to 0 or the vm FIX won't work.
+ */
+       for(i=0; i<MAXPENDING; i++) {
+               TAILQ_INSERT_TAIL(&dev->sc_xs_free, &dev->sc_xs_store[i],
+                                 link);
+       }
+
+/*
+ * Calculate the correct clock conversion factor 2 <= factor <= 8, i.e. set
+ * the factor to clock_freq / 5 (int).
+ */
+       if (dev->sc_clock_freq <= 10)
+               dev->sc_clock_conv_fact = 2;
+       if (dev->sc_clock_freq <= 40)
+               dev->sc_clock_conv_fact = 2+((dev->sc_clock_freq-10)/5);
+       else
+               panic("sfasinitialize: Clock frequence too high");
+
+/* Setup and save the basic configuration registers */
+       dev->sc_config1 = (dev->sc_host_id & SFAS_CFG1_BUS_ID_MASK);
+       dev->sc_config2 = SFAS_CFG2_FEATURES_ENABLE;
+       dev->sc_config3 = (dev->sc_clock_freq > 25 ? SFAS_CFG3_FASTCLK : 0);
+
+/* Precalculate timeout value and clock period. */
+/* Ekkk ... floating point in the kernel !!!! */
+/*     dev->sc_timeout_val  = 1+dev->sc_timeout*dev->sc_clock_freq/
+                                (7.682*dev->sc_clock_conv_fact);*/
+       dev->sc_timeout_val  = 1+dev->sc_timeout*dev->sc_clock_freq/
+                                ((7682*dev->sc_clock_conv_fact)/1000);
+       dev->sc_clock_period = 1000/dev->sc_clock_freq;
+
+       sfasreset(dev, 1 | 2);  /* Reset Chip and Bus */
+
+       dev->sc_units_disconnected = 0;
+       dev->sc_msg_in_len = 0;
+       dev->sc_msg_out_len = 0;
+
+       dev->sc_flags = 0;
+
+       for(i=0; i<8; i++)
+               sfas_init_nexus(dev, &dev->sc_nexus[i]);
+
+/*
+ * Setup bump buffer.
+ */
+       dev->sc_bump_va = (u_char *)kmem_alloc(kernel_map, dev->sc_bump_sz);
+       dev->sc_bump_pa = pmap_extract(kernel_pmap, (vm_offset_t)dev->sc_bump_va);
+
+/*
+ * Setup pages to noncachable, that way we don't have to flush the cache
+ * every time we need "bumped" transfer.
+ */
+       pte = pmap_pte(kernel_pmap, (vm_offset_t)dev->sc_bump_va);
+       *pte &= ~PT_C;
+       tlbflush();
+
+       printf(" dmabuf V0x%08x P0x%08x", (u_int)dev->sc_bump_va, (u_int)dev->sc_bump_pa);
+}
+
+
+/*
+ * used by specific sfas controller
+ */
+int
+sfas_scsicmd(struct scsi_xfer *xs)
+{
+       struct sfas_softc       *dev;
+       struct scsi_link        *slp;
+       struct sfas_pending     *pendp;
+       int                      flags, s, target;
+
+       slp = xs->sc_link;
+       dev = slp->adapter_softc;
+       flags = xs->flags;
+       target = slp->target;
+
+       if (flags & SCSI_DATA_UIO)
+               panic("sfas: scsi data uio requested");
+
+       if ((flags & SCSI_POLL) && (dev->sc_flags & SFAS_ACTIVE))
+               panic("sfas_scsicmd: busy");
+
+/* Get hold of a sfas_pending block. */
+       s = splbio();
+       pendp = dev->sc_xs_free.tqh_first;
+       if (pendp == NULL) {
+               splx(s);
+               return(TRY_AGAIN_LATER);
+       }
+       TAILQ_REMOVE(&dev->sc_xs_free, pendp, link);
+       pendp->xs = xs;
+       splx(s);
+
+
+/* If the chip if busy OR the unit is busy, we have to wait for out turn. */
+       if ((dev->sc_flags & SFAS_ACTIVE) ||
+           (dev->sc_nexus[target].flags & SFAS_NF_UNIT_BUSY)) {
+               s = splbio();
+               TAILQ_INSERT_TAIL(&dev->sc_xs_pending, pendp, link);
+               splx(s);
+       } else
+               sfas_donextcmd(dev, pendp);
+
+       return((flags & SCSI_POLL) ? COMPLETE : SUCCESSFULLY_QUEUED);
+}
+
+/*
+ * Actually select the unit, whereby the whole scsi-process is started.
+ */
+void
+sfas_donextcmd(dev, pendp)
+       struct sfas_softc       *dev;
+       struct sfas_pending     *pendp;
+{
+       int     s;
+
+/*
+ * Special case for scsi unit reset. I think this is waterproof. We first
+ * select the unit during splbio. We then cycle through the generated
+ * interrupts until the interrupt routine signals that the unit has
+ * acknowledged the reset. After that we have to wait a reset to select
+ * delay before anything else can happend.
+ */
+       if (pendp->xs->flags & SCSI_RESET) {
+               struct nexus    *nexus;
+
+               s = splbio();
+               while(!sfasselect(dev, pendp, 0, 0, 0, 0, SFAS_SELECT_K)) {
+                       splx(s);
+                       delay(10);
+                       s = splbio();
+               }
+
+               nexus = dev->sc_cur_nexus;
+               while(nexus->flags & SFAS_NF_UNIT_BUSY) {
+                       sfasiwait(dev);
+                       sfasintr(dev);
+               }
+
+               nexus->flags |= SFAS_NF_UNIT_BUSY;
+               splx(s);
+
+               sfasreset(dev, 0);
+
+               s = splbio();
+               nexus->flags &= ~SFAS_NF_UNIT_BUSY;
+               splx(s);
+       }
+
+/*
+ * If we are polling, go to splbio and perform the command, else we poke
+ * the scsi-bus via sfasgo to get the interrupt machine going.
+ */
+       if (pendp->xs->flags & SCSI_POLL) {
+               s = splbio();
+               sfasicmd(dev, pendp);
+               TAILQ_INSERT_TAIL(&dev->sc_xs_free, pendp, link);
+               splx(s);
+       } else {
+               sfasgo(dev, pendp);
+       }
+}
+
+void
+sfas_scsidone(dev, xs, stat)
+       struct sfas_softc *dev;
+       struct scsi_xfer *xs;
+       int              stat;
+{
+       struct sfas_pending     *pendp;
+       int                      s;
+
+       xs->status = stat;
+
+       if (stat == 0)
+               xs->resid = 0;
+       else {
+               switch(stat) {
+               case SCSI_CHECK:
+               /* If we get here we have valid sense data. Faults during
+                * sense is handeled elsewhere and will generate a
+                * XS_DRIVER_STUFFUP. */
+                       xs->error = XS_SENSE;
+                       break;
+               case SCSI_BUSY:
+                       xs->error = XS_BUSY;
+                       break;
+               case -1:
+                       xs->error = XS_DRIVER_STUFFUP;
+                       QPRINTF(("sfas_scsicmd() bad %x\n", stat));
+                       break;
+               default:
+                       xs->error = XS_TIMEOUT;
+                       break;
+               }
+       }
+
+       xs->flags |= ITSDONE;
+
+/* Steal the next command from the queue so that one unit can't hog the bus. */
+       s = splbio();
+       pendp = dev->sc_xs_pending.tqh_first;
+       while(pendp) {
+               if (!(dev->sc_nexus[pendp->xs->sc_link->target].flags &
+                     SFAS_NF_UNIT_BUSY))
+                       break;
+               pendp = pendp->link.tqe_next;
+       }
+
+       if (pendp != NULL) {
+               TAILQ_REMOVE(&dev->sc_xs_pending, pendp, link);
+       }
+
+       splx(s);
+       scsi_done(xs);
+
+       if (pendp)
+               sfas_donextcmd(dev, pendp);
+}
+
+/*
+ * There are two kinds of reset:
+ *  1) CHIP-bus reset. This also implies a SCSI-bus reset.
+ *  2) SCSI-bus reset.
+ * After the appropriate resets have been performed we wait a reset to select
+ * delay time.
+ */
+void
+sfasreset(dev, how)
+       struct sfas_softc *dev;
+       int              how;
+{
+       sfas_regmap_p   rp;
+       int             i, s;
+
+       rp = dev->sc_fas;
+
+       if (how & 1) {
+               for(i=0; i<8; i++)
+                       sfas_init_nexus(dev, &dev->sc_nexus[i]);
+
+               *rp->sfas_command = SFAS_CMD_RESET_CHIP;
+               delay(1);
+               *rp->sfas_command = SFAS_CMD_NOP;
+
+               *rp->sfas_config1 = dev->sc_config1;
+               *rp->sfas_config2 = dev->sc_config2;
+               *rp->sfas_config3 = dev->sc_config3;
+               *rp->sfas_timeout = dev->sc_timeout_val;
+               *rp->sfas_clkconv = dev->sc_clock_conv_fact &
+                                       SFAS_CLOCK_CONVERSION_MASK;
+       }
+
+       if (how & 2) {
+               for(i=0; i<8; i++)
+                       sfas_init_nexus(dev, &dev->sc_nexus[i]);
+
+               s = splbio();
+
+               *rp->sfas_command = SFAS_CMD_RESET_SCSI_BUS;
+               delay(100);
+
+/* Skip interrupt generated by RESET_SCSI_BUS */
+               while(*rp->sfas_status & SFAS_STAT_INTERRUPT_PENDING) {
+                       dev->sc_status = *rp->sfas_status;
+                       dev->sc_interrupt = *rp->sfas_interrupt;
+
+                       delay(100);
+               }
+
+               dev->sc_status = *rp->sfas_status;
+               dev->sc_interrupt = *rp->sfas_interrupt;
+
+               splx(s);
+       }
+
+       if (dev->sc_config_flags & SFAS_SLOW_START)
+               delay(4*250000); /* RESET to SELECT DELAY*4 for slow devices */
+       else
+               delay(250000);   /* RESET to SELECT DELAY */
+}
+
+/*
+ * Save active data pointers to the nexus block currently active.
+ */
+void
+sfas_save_pointers(dev)
+       struct sfas_softc *dev;
+{
+       struct nexus    *nx;
+
+       nx = dev->sc_cur_nexus;
+       if (nx) {
+               nx->cur_link    = dev->sc_cur_link;
+               nx->max_link    = dev->sc_max_link;
+               nx->buf         = dev->sc_buf;
+               nx->len         = dev->sc_len;
+               nx->dma_len     = dev->sc_dma_len;
+               nx->dma_buf     = dev->sc_dma_buf;
+               nx->dma_blk_flg = dev->sc_dma_blk_flg;
+               nx->dma_blk_len = dev->sc_dma_blk_len;
+               nx->dma_blk_ptr = dev->sc_dma_blk_ptr;
+       }
+}
+
+/*
+ * Restore data pointers from the currently active nexus block.
+ */
+void
+sfas_restore_pointers(dev)
+       struct sfas_softc *dev;
+{
+       struct nexus    *nx;
+
+       nx = dev->sc_cur_nexus;
+       if (nx) {
+               dev->sc_cur_link    = nx->cur_link;
+               dev->sc_max_link    = nx->max_link;
+               dev->sc_buf         = nx->buf;
+               dev->sc_len         = nx->len;
+               dev->sc_dma_len     = nx->dma_len;
+               dev->sc_dma_buf     = nx->dma_buf;
+               dev->sc_dma_blk_flg = nx->dma_blk_flg;
+               dev->sc_dma_blk_len = nx->dma_blk_len;
+               dev->sc_dma_blk_ptr = nx->dma_blk_ptr;
+               dev->sc_chain       = nx->dma;
+               dev->sc_unit        = (nx->lun_unit & 0x0F);
+               dev->sc_lun         = (nx->lun_unit & 0xF0) >> 4;
+       }
+}
+
+/*
+ * sfasiwait is used during interrupt and polled IO to wait for an event from
+ * the FAS chip. This function MUST NOT BE CALLED without interrupt disabled.
+ */
+void
+sfasiwait(dev)
+       struct sfas_softc *dev;
+{
+       sfas_regmap_p   rp;
+
+/*
+ * If SFAS_DONT_WAIT is set, we have already grabbed the interrupt info
+ * elsewhere. So we don't have to wait for it.
+ */
+       if (dev->sc_flags & SFAS_DONT_WAIT) {
+               dev->sc_flags &= ~SFAS_DONT_WAIT;
+               return;
+       }
+
+       rp = dev->sc_fas;
+
+/* Wait for FAS chip to signal an interrupt. */
+       while(!(*rp->sfas_status & SFAS_STAT_INTERRUPT_PENDING))
+               delay(1);
+
+/* Grab interrupt info from chip. */
+       dev->sc_status = *rp->sfas_status;
+       dev->sc_interrupt = *rp->sfas_interrupt;
+       if (dev->sc_interrupt & SFAS_INT_RESELECTED) {
+               dev->sc_resel[0] = *rp->sfas_fifo;
+               dev->sc_resel[1] = *rp->sfas_fifo;
+       }
+}
+
+/*
+ * Transfer info to/from device. sfas_ixfer uses polled IO+sfasiwait so the
+ * rules that apply to sfasiwait also applies here.
+ */
+void
+sfas_ixfer(dev, polling)
+       struct sfas_softc *dev;
+       int polling;
+{
+       sfas_regmap_p    rp;
+       u_char          *buf;
+       int              len, mode, phase;
+
+       rp = dev->sc_fas;
+       buf = dev->sc_buf;
+       len = dev->sc_len;
+
+/*
+ * Decode the scsi phase to determine whether we are reading or writing.
+ * mode == 1 => READ, mode == 0 => WRITE
+ */
+       phase = dev->sc_status & SFAS_STAT_PHASE_MASK;
+       mode = (phase == SFAS_PHASE_DATA_IN);
+
+       while(len && ((dev->sc_status & SFAS_STAT_PHASE_MASK) == phase))
+               if (mode) {
+                       *rp->sfas_command = SFAS_CMD_TRANSFER_INFO;
+
+                       sfasiwait(dev);
+
+                       *buf++ = *rp->sfas_fifo;
+                       len--;
+               } else {
+                       len--;
+                       *rp->sfas_fifo = *buf++;
+                       *rp->sfas_command = SFAS_CMD_TRANSFER_INFO;
+
+                       sfasiwait(dev);
+               }
+
+/* Update buffer pointers to reflect the sent/recieved data. */
+       dev->sc_buf = buf;
+       dev->sc_len = len;
+
+/*
+ * Since the last sfasiwait will be a phase-change, we can't wait for it
+ * again later, so we have to signal that.
+ * Since this may be called from an interrupt initiated routine then we
+ * must call sfasintr again to avoid losing an interrupt. Phew!
+ */
+       if(polling)
+               dev->sc_flags |= SFAS_DONT_WAIT;
+       else
+               sfasintr(dev);
+}
+
+/*
+ * Build a Synchronous Data Transfer Request message
+ */
+void
+sfas_build_sdtrm(dev, period, offset)
+       struct sfas_softc *dev;
+       int               period;
+       int               offset;
+{
+       dev->sc_msg_out[0] = 0x01;
+       dev->sc_msg_out[1] = 0x03;
+       dev->sc_msg_out[2] = 0x01;
+       dev->sc_msg_out[3] = period/4;
+       dev->sc_msg_out[4] = offset;
+       dev->sc_msg_out_len= 5;
+}
+
+/*
+ * Arbitate the scsi bus and select the unit
+ */
+int
+sfas_select_unit(dev, target)
+       struct sfas_softc *dev;
+       short             target;
+{
+       sfas_regmap_p    rp;
+       struct nexus    *nexus;
+       int              s, retcode, i;
+       u_char           cmd;
+
+       s = splbio();   /* Do this at splbio so that we won't be disturbed. */
+
+       retcode = 0;
+
+       nexus = &dev->sc_nexus[target];
+
+/*
+ * Check if the chip is busy. If not the we mark it as so and hope that nobody
+ * reselects us until we have grabbed the bus.
+ */
+       if (!(dev->sc_flags & SFAS_ACTIVE) && !dev->sc_sel_nexus) {
+               dev->sc_flags |= SFAS_ACTIVE;
+
+               rp = dev->sc_fas;
+
+               *rp->sfas_syncper = nexus->syncper;
+               *rp->sfas_syncoff = nexus->syncoff;
+               *rp->sfas_config3 = nexus->config3;
+
+               *rp->sfas_config1 = dev->sc_config1;
+               *rp->sfas_timeout = dev->sc_timeout_val;
+               *rp->sfas_dest_id = target;
+
+/* If nobody has stolen the bus, we can send a select command to the chip. */
+               if (!(*rp->sfas_status & SFAS_STAT_INTERRUPT_PENDING)) {
+                       *rp->sfas_fifo = nexus->ID;
+                       if ((nexus->flags & (SFAS_NF_DO_SDTR | SFAS_NF_RESET))
+                           || (dev->sc_msg_out_len != 0))
+                               cmd = SFAS_CMD_SEL_ATN_STOP;
+                       else {
+                               for(i=0; i<nexus->clen; i++)
+                                       *rp->sfas_fifo = nexus->cbuf[i];
+
+                               cmd = SFAS_CMD_SEL_ATN;
+                       }
+
+                       dev->sc_sel_nexus = nexus;
+
+                       *rp->sfas_command = cmd;
+                       retcode = 1;
+               }
+       }
+
+       splx(s);
+       return(retcode);
+}
+
+/*
+ * Grab the nexus if available else return 0.
+ */
+struct nexus *
+sfas_arbitate_target(dev, target)
+       struct sfas_softc *dev;
+       int               target;
+{
+       struct nexus    *nexus;
+       int              s;
+
+/*
+ * This is realy simple. Raise interrupt level to splbio. Grab the nexus and
+ * leave.
+ */
+       nexus = &dev->sc_nexus[target];
+
+       s = splbio();
+
+       if (nexus->flags & SFAS_NF_UNIT_BUSY)
+               nexus = 0;
+       else
+               nexus->flags |= SFAS_NF_UNIT_BUSY;
+
+       splx(s);
+       return(nexus);
+}
+
+/*
+ * Setup a nexus for use. Initializes command, buffer pointers and dma chain.
+ */
+void
+sfas_setup_nexus(dev, nexus, pendp, cbuf, clen, buf, len, mode)
+       struct sfas_softc       *dev;
+       struct nexus            *nexus;
+       struct sfas_pending     *pendp;
+       unsigned char           *cbuf;
+       int                      clen;
+       unsigned char           *buf;
+       int                      len;
+       int                      mode;
+{
+       char    sync, target, lun;
+
+       target = pendp->xs->sc_link->target;
+       lun    = pendp->xs->sc_link->lun;
+
+/*
+ * Adopt mode to reflect the config flags.
+ * If we can't use DMA we can't use synch transfer. Also check the
+ * sfas_inhibit_xxx[target] flags.
+ */
+       if ((dev->sc_config_flags & (SFAS_NO_SYNCH | SFAS_NO_DMA)) ||
+           sfas_inhibit_sync[(int)target])
+               mode &= ~SFAS_SELECT_S;
+
+       if ((dev->sc_config_flags & SFAS_NO_RESELECT) ||
+           sfas_inhibit_disc[(int)target])
+               mode &= ~SFAS_SELECT_R;
+
+       nexus->xs               = pendp->xs;
+
+/* Setup the nexus struct. */
+       nexus->ID          = ((mode & SFAS_SELECT_R) ? 0xC0 : 0x80) | lun;
+       nexus->clen        = clen;
+       bcopy(cbuf, nexus->cbuf, nexus->clen);
+       nexus->cbuf[1] |= lun << 5;             /* Fix the lun bits */
+       nexus->cur_link    = 0;
+       nexus->dma_len     = 0;
+       nexus->dma_buf     = 0;
+       nexus->dma_blk_len = 0;
+       nexus->dma_blk_ptr = 0;
+       nexus->len         = len;
+       nexus->buf         = buf;
+       nexus->lun_unit    = (lun << 4) | target;
+       nexus->state       = SFAS_NS_SELECTED;
+
+/* We must keep these flags. All else must be zero. */
+       nexus->flags      &= SFAS_NF_UNIT_BUSY   | SFAS_NF_REQUEST_SENSE
+                          | SFAS_NF_SYNC_TESTED | SFAS_NF_SELECT_ME;
+
+/*
+ * If we are requesting sense, reflect that in the flags so that we can handle
+ * error in sense data correctly
+ */
+       if (nexus->flags & SFAS_NF_REQUEST_SENSE) {
+               nexus->flags &= ~SFAS_NF_REQUEST_SENSE;
+               nexus->flags |=  SFAS_NF_SENSING;
+       }
+
+       if (mode & SFAS_SELECT_I)
+               nexus->flags |= SFAS_NF_IMMEDIATE;
+       if (mode & SFAS_SELECT_K)
+               nexus->flags |= SFAS_NF_RESET;
+
+       sync  = ((mode & SFAS_SELECT_S) ? 1 : 0);
+
+/* We can't use sync during polled IO. */
+       if (sync && (mode & SFAS_SELECT_I))
+               sync = 0;
+
+       if (!sync &&
+           ((nexus->flags & SFAS_NF_SYNC_TESTED) && (nexus->offset != 0))) {
+               /*
+                * If the scsi unit is set to synch transfer and we don't want
+                * that, we have to renegotiate.
+                */
+
+               nexus->flags |= SFAS_NF_DO_SDTR;
+               nexus->period = 200;
+               nexus->offset = 0;
+       } else if (sync && !(nexus->flags & SFAS_NF_SYNC_TESTED)) {
+               /*
+                * If the scsi unit is not set to synch transfer and we want
+                * that, we have to negotiate. This should realy base the
+                * period on the clock frequence rather than just check if
+                * >25Mhz
+                */
+
+               nexus->flags |= SFAS_NF_DO_SDTR;
+               nexus->period = ((dev->sc_clock_freq>25) ? 100 : 200);
+               nexus->offset = 8;
+
+               /* If the user has a long cable, we want to limit the period */
+               if ((nexus->period == 100) &&
+                   (dev->sc_config_flags & SFAS_SLOW_CABLE))
+                       nexus->period = 200;
+       }
+
+/*
+ * Fake a dma-block for polled IO. This way we can use the same code to handle
+ * reselection. Much nicer this way.
+ */
+       if ((mode & SFAS_SELECT_I) || (dev->sc_config_flags & SFAS_NO_DMA)) {
+               nexus->dma[0].ptr = (vm_offset_t)buf;
+               nexus->dma[0].len = len;
+               nexus->dma[0].flg = SFAS_CHAIN_PRG;
+               nexus->max_link   = 1;
+       } else {
+               nexus->max_link = dev->sc_build_dma_chain(dev, nexus->dma,
+                                                         buf, len);
+       }
+
+/* Flush the caches. (If needed) */
+/* Do I need to ? */
+/*
+       if ((mmutype == MMU_68040) && len && !(mode & SFAS_SELECT_I))
+               dma_cachectl(buf, len);
+*/
+}
+
+int
+sfasselect(dev, pendp, cbuf, clen, buf, len, mode)
+       struct sfas_softc       *dev;
+       struct sfas_pending     *pendp;
+       unsigned char           *cbuf;
+       int                      clen;
+       unsigned char           *buf;
+       int                      len;
+       int                      mode;
+{
+       struct nexus    *nexus;
+
+/* Get the nexus struct. */
+       nexus = sfas_arbitate_target(dev, pendp->xs->sc_link->target);
+       if (nexus == NULL)
+               return(0);
+
+/* Setup the nexus struct. */
+       sfas_setup_nexus(dev, nexus, pendp, cbuf, clen, buf, len, mode);
+
+/* Post it to the interrupt machine. */
+       sfas_select_unit(dev, pendp->xs->sc_link->target);
+
+       return(1);
+}
+
+void
+sfas_request_sense(dev, nexus)
+       struct sfas_softc *dev;
+       struct nexus     *nexus;
+{
+       struct scsi_xfer        *xs;
+       struct sfas_pending      pend;
+       struct scsi_sense        rqs;
+       int                      mode;
+
+       xs = nexus->xs;
+
+/* Fake a sfas_pending structure. */
+       pend.xs                 = xs;
+
+       rqs.opcode = REQUEST_SENSE;
+       rqs.byte2 = xs->sc_link->lun << 5;
+#ifdef not_yet
+       rqs.length=xs->req_sense_length?xs->req_sense_length:sizeof(xs->sense);
+#else
+       rqs.length=sizeof(xs->sense);
+#endif
+
+       rqs.unused[0] = rqs.unused[1] = rqs.control = 0;
+
+/*
+ * If we are requesting sense during polled IO, we have to sense with polled
+ * IO too.
+ */
+       mode = SFAS_SELECT_RS;
+       if (nexus->flags & SFAS_NF_IMMEDIATE)
+               mode = SFAS_SELECT_I;
+
+/* Setup the nexus struct for sensing. */
+       sfas_setup_nexus(dev, nexus, &pend, (char *)&rqs, sizeof(rqs),
+                       (char *)&xs->sense, rqs.length, mode);
+
+/* Post it to the interrupt machine. */
+       sfas_select_unit(dev, xs->sc_link->target);
+}
+
+void
+sfasgo(dev, pendp)
+       struct sfas_softc   *dev;
+       struct sfas_pending *pendp;
+{
+       int      s;
+       char    *buf;
+
+       buf    = pendp->xs->data;
+
+       if (sfasselect(dev, pendp, (char *)pendp->xs->cmd, pendp->xs->cmdlen,
+                     buf, pendp->xs->datalen, SFAS_SELECT_RS)) {
+               /*
+                * We got the command going so the sfas_pending struct is now
+                * free to reuse.
+                */
+
+               s = splbio();
+               TAILQ_INSERT_TAIL(&dev->sc_xs_free, pendp, link);
+               splx(s);
+       } else {
+               /*
+                * We couldn't make the command fly so we have to wait. The
+                * struct MUST be inserted at the head to keep the order of
+                * the commands.
+                */
+
+               s = splbio();
+               TAILQ_INSERT_HEAD(&dev->sc_xs_pending, pendp, link);
+               splx(s);
+       }
+
+       return;
+}
+
+/*
+ * Part one of the interrupt machine. Error checks and reselection test.
+ * We don't know if we have an active nexus here!
+ */
+int
+sfas_pretests(dev, rp)
+       struct sfas_softc *dev;
+       sfas_regmap_p     rp;
+{
+       struct nexus    *nexus;
+       int              i, s;
+
+       if (dev->sc_interrupt & SFAS_INT_SCSI_RESET_DETECTED) {
+               /*
+                * Cleanup and notify user. Lets hope that this is all we
+                * have to do
+                */
+
+               for(i=0; i<8; i++) {
+                       if (dev->sc_nexus[i].xs)
+                               sfas_scsidone(dev, dev->sc_nexus[i].xs, -2);
+
+                       sfas_init_nexus(dev, &dev->sc_nexus[i]);
+               }
+               printf("sfasintr: SCSI-RESET detected!");
+               return(-1);
+       }
+
+       if (dev->sc_interrupt & SFAS_INT_ILLEGAL_COMMAND) {
+               /* Something went terrible wrong! Dump some data and panic! */
+
+               printf("FIFO:");
+               while(*rp->sfas_fifo_flags & SFAS_FIFO_COUNT_MASK)
+                       printf(" %x", *rp->sfas_fifo);
+               printf("\n");
+
+               printf("CMD: %x\n", *rp->sfas_command);
+               panic("sfasintr: ILLEGAL COMMAND!");
+       }
+
+       if (dev->sc_interrupt & SFAS_INT_RESELECTED) {
+               /* We were reselected. Set the chip as busy */
+
+               s = splbio();
+               dev->sc_flags |= SFAS_ACTIVE;
+               if (dev->sc_sel_nexus) {
+                       dev->sc_sel_nexus->flags |= SFAS_NF_SELECT_ME;
+                       dev->sc_sel_nexus = 0;
+               }
+               splx(s);
+
+               if (dev->sc_units_disconnected) {
+                       /* Find out who reselected us. */
+
+                       dev->sc_resel[0] &= ~(1<<dev->sc_host_id);
+
+                       for(i=0; i<8; i++)
+                               if (dev->sc_resel[0] & (1<<i))
+                                       break;
+
+                       if (i == 8)
+                               panic("Illegal reselection!");
+
+                       if (dev->sc_nexus[i].state == SFAS_NS_DISCONNECTED) {
+                               /*
+                                * This unit had disconnected, so we reconnect
+                                * it.
+                                */
+
+                               dev->sc_cur_nexus = &dev->sc_nexus[i];
+                               nexus = dev->sc_cur_nexus;
+
+                               *rp->sfas_syncper = nexus->syncper;
+                               *rp->sfas_syncoff = nexus->syncoff;
+                               *rp->sfas_config3 = nexus->config3;
+
+                               *rp->sfas_dest_id = i & 7;
+
+                               dev->sc_units_disconnected--;
+                               dev->sc_msg_in_len= 0;
+
+                               /* Restore active pointers. */
+                               sfas_restore_pointers(dev);
+
+                               nexus->state = SFAS_NS_RESELECTED;
+
+                               *rp->sfas_command = SFAS_CMD_MESSAGE_ACCEPTED;
+
+                               return(1);
+                       }
+               }
+
+               /* Somehow we got an illegal reselection. Dump and panic. */
+               printf("sfasintr: resel[0] %x resel[1] %x disconnected %d\n",
+                      dev->sc_resel[0], dev->sc_resel[1],
+                      dev->sc_units_disconnected);
+               panic("sfasintr: Unexpected reselection!");
+       }
+
+       return(0);
+}
+
+/*
+ * Part two of the interrupt machine. Handle disconnection and post command
+ * processing. We know that we have an active nexus here.
+ */
+int
+sfas_midaction(dev, rp, nexus)
+       struct sfas_softc *dev;
+       sfas_regmap_p     rp;
+       struct nexus     *nexus;
+{
+       int     i, left, len, s;
+       u_char  status, msg;
+
+       if (dev->sc_interrupt & SFAS_INT_DISCONNECT) {
+               s = splbio();
+               dev->sc_cur_nexus = 0;
+
+               /* Mark chip as busy and clean up the chip FIFO. */
+               dev->sc_flags &= ~SFAS_ACTIVE;
+               *rp->sfas_command = SFAS_CMD_FLUSH_FIFO;
+
+               /* Let the nexus state reflect what we have to do. */
+               switch(nexus->state) {
+               case SFAS_NS_SELECTED:
+                       dev->sc_sel_nexus = 0;
+                       nexus->flags &= ~SFAS_NF_SELECT_ME;
+
+                       /*
+                        * We were trying to select the unit. Probably no unit
+                        * at this ID.
+                        */
+                       nexus->xs->resid = dev->sc_len;
+
+                       nexus->status = -2;
+                       nexus->flags &= ~SFAS_NF_UNIT_BUSY;
+                       nexus->state = SFAS_NS_FINISHED;
+                       break;
+
+               case SFAS_NS_SENSE:
+                       /*
+                        * Oops! We have to request sense data from this unit.
+                        * Do so.
+                        */
+                       dev->sc_led(dev, 0);
+                       nexus->flags |= SFAS_NF_REQUEST_SENSE;
+                       sfas_request_sense(dev, nexus);
+                       break;
+
+               case SFAS_NS_DONE:
+                       /* All done. */
+                       nexus->xs->resid = dev->sc_len;
+
+                       nexus->flags &= ~SFAS_NF_UNIT_BUSY;
+                       nexus->state  = SFAS_NS_FINISHED;
+                       dev->sc_led(dev, 0);
+                       break;
+
+               case SFAS_NS_DISCONNECTING:
+                       /*
+                        * We have recieved a DISCONNECT message, so we are
+                        * doing a normal disconnection.
+                        */
+                       nexus->state = SFAS_NS_DISCONNECTED;
+
+                       dev->sc_units_disconnected++;
+                       break;
+
+               case SFAS_NS_RESET:
+                       /*
+                        * We were reseting this SCSI-unit. Clean up the
+                        * nexus struct.
+                        */
+                       dev->sc_led(dev, 0);
+                       sfas_init_nexus(dev, nexus);
+                       break;
+
+               default:
+                       /*
+                        * Unexpected disconnection! Cleanup and exit. This
+                        * shouldn't cause any problems.
+                        */
+                       printf("sfasintr: Unexpected disconnection\n");
+                       printf("sfasintr: u %x s %d p %d f %x c %x\n",
+                              nexus->lun_unit, nexus->state,
+                              dev->sc_status & SFAS_STAT_PHASE_MASK,
+                              nexus->flags, nexus->cbuf[0]);
+
+                       nexus->xs->resid = dev->sc_len;
+
+                       nexus->flags &= ~SFAS_NF_UNIT_BUSY;
+                       nexus->state = SFAS_NS_FINISHED;
+                       nexus->status = -3;
+
+                       dev->sc_led(dev, 0);
+                       break;
+               }
+
+               /*
+                * If we have disconnected units, we MUST enable reselection
+                * within 250ms.
+                */
+               if (dev->sc_units_disconnected &&
+                   !(dev->sc_flags & SFAS_ACTIVE))
+                       *rp->sfas_command = SFAS_CMD_ENABLE_RESEL;
+
+               splx(s);
+
+               /* Select the first pre-initialized nexus we find. */
+               for(i=0; i<8; i++)
+                       if (dev->sc_nexus[i].flags & SFAS_NF_SELECT_ME)
+                               if (sfas_select_unit(dev, i) == 2)
+                                       break;
+
+               /* Does any unit need sense data? */
+               for(i=0; i<8; i++)
+                       if (dev->sc_nexus[i].flags & SFAS_NF_REQUEST_SENSE) {
+                               sfas_request_sense(dev, &dev->sc_nexus[i]);
+                               break;
+                       }
+
+               /* We are done with this nexus! */
+               if (nexus->state == SFAS_NS_FINISHED)
+                       sfas_scsidone(dev, nexus->xs, nexus->status);
+
+               return(1);
+       }
+
+       switch(nexus->state) {
+       case SFAS_NS_SELECTED:
+               dev->sc_cur_nexus = nexus;
+               dev->sc_sel_nexus = 0;
+
+               nexus->flags &= ~SFAS_NF_SELECT_ME;
+
+               /*
+                * We have selected a unit. Setup chip, restore pointers and
+                * light the led.
+                */
+               *rp->sfas_syncper = nexus->syncper;
+               *rp->sfas_syncoff = nexus->syncoff;
+               *rp->sfas_config3 = nexus->config3;
+
+               sfas_restore_pointers(dev);
+
+               if (!(nexus->flags & SFAS_NF_SENSING))
+                       nexus->status   = 0xFF;
+               dev->sc_msg_in[0] = 0xFF;
+               dev->sc_msg_in_len= 0;
+
+               dev->sc_led(dev, 1);
+
+               break;
+
+       case SFAS_NS_DATA_IN:
+       case SFAS_NS_DATA_OUT:
+               /* We have transfered data. */
+               if (dev->sc_dma_len)
+                       if (dev->sc_cur_link < dev->sc_max_link) {
+                               /*
+                                * Clean up dma and at the same time get how
+                                * many bytes that were NOT transfered.
+                                */
+                         left = dev->sc_setup_dma(dev, 0, 0, SFAS_DMA_CLEAR);
+                         len  = dev->sc_dma_len;
+
+                         if (nexus->state == SFAS_NS_DATA_IN) {
+                           /*
+                            * If we were bumping we may have had an odd length
+                            * which means that there may be bytes left in the
+                            * fifo. We also need to move the data from the
+                            * bump buffer to the actual memory.
+                            */
+                           if (dev->sc_dma_buf == dev->sc_bump_pa)
+                           {
+                             while((*rp->sfas_fifo_flags&SFAS_FIFO_COUNT_MASK)
+                                   && left)
+                               dev->sc_bump_va[len-(left--)] = *rp->sfas_fifo;
+
+                             bcopy(dev->sc_bump_va, dev->sc_buf, len-left);
+                           }
+                         } else {
+                           /* Count any unsent bytes and flush them. */
+                           left+= *rp->sfas_fifo_flags & SFAS_FIFO_COUNT_MASK;
+                           *rp->sfas_command = SFAS_CMD_FLUSH_FIFO;
+                         }
+
+                         /*
+                          * Update pointers/length to reflect the transfered
+                          * data.
+                          */
+                         dev->sc_len -= len-left;
+                         dev->sc_buf += len-left;
+
+                         dev->sc_dma_buf += len-left;
+                         dev->sc_dma_len  = left;
+
+                         dev->sc_dma_blk_ptr += len-left;
+                         dev->sc_dma_blk_len -= len-left;
+
+                         /*
+                          * If it was the end of a dma block, we select the
+                          * next to begin with.
+                          */
+                         if (!dev->sc_dma_blk_len)
+                           dev->sc_cur_link++;
+                       }
+               break;
+
+       case SFAS_NS_STATUS:
+               /*
+                * If we were not sensing, grab the status byte. If we were
+                * sensing and we got a bad status, let the user know.
+                */
+
+               status = *rp->sfas_fifo;
+               msg = *rp->sfas_fifo;
+
+               if (!(nexus->flags & SFAS_NF_SENSING))
+                       nexus->status = status;
+               else if (status != 0)
+                       nexus->status = -1;
+
+               /*
+                * Preload the command complete message. Handeled in
+                * sfas_postaction.
+                */
+               dev->sc_msg_in[0] = msg;
+               dev->sc_msg_in_len = 1;
+               nexus->flags |= SFAS_NF_HAS_MSG;
+               break;
+
+       default:
+               break;
+       }
+
+       return(0);
+}
+
+/*
+ * Part three of the interrupt machine. Handle phase changes (and repeated
+ * phase passes). We know that we have an active nexus here.
+ */
+int
+sfas_postaction(dev, rp, nexus)
+       struct sfas_softc *dev;
+       sfas_regmap_p     rp;
+       struct nexus     *nexus;
+{
+       int     i, len;
+       u_char  cmd;
+       short   offset, period;
+
+       cmd = 0;
+
+       switch(dev->sc_status & SFAS_STAT_PHASE_MASK) {
+       case SFAS_PHASE_DATA_OUT:
+       case SFAS_PHASE_DATA_IN:
+               if ((dev->sc_status & SFAS_STAT_PHASE_MASK) ==
+                   SFAS_PHASE_DATA_OUT)
+                       nexus->state = SFAS_NS_DATA_OUT;
+               else
+                       nexus->state = SFAS_NS_DATA_IN;
+
+               /* Make DMA ready to accept new data. Load active pointers
+                * from the DMA block. */
+               dev->sc_setup_dma(dev, 0, 0, SFAS_DMA_CLEAR);
+               if (dev->sc_cur_link < dev->sc_max_link) {
+                 if (!dev->sc_dma_blk_len) {
+                   dev->sc_dma_blk_ptr = dev->sc_chain[dev->sc_cur_link].ptr;
+                   dev->sc_dma_blk_len = dev->sc_chain[dev->sc_cur_link].len;
+                   dev->sc_dma_blk_flg = dev->sc_chain[dev->sc_cur_link].flg;
+                 }
+
+                 /* We should use polled IO here. */
+                 if (dev->sc_dma_blk_flg == SFAS_CHAIN_PRG) {
+                       sfas_ixfer(dev, nexus->xs->flags & SCSI_POLL);
+                       dev->sc_cur_link++;
+                       dev->sc_dma_len = 0;
+                       break;
+                 }
+                 else if (dev->sc_dma_blk_flg == SFAS_CHAIN_BUMP)
+                       len = dev->sc_dma_blk_len;
+                 else
+                       len = dev->sc_need_bump(dev, dev->sc_dma_blk_ptr,
+                                               dev->sc_dma_blk_len);
+
+                 /*
+                  * If len != 0 we must bump the data, else we just DMA it
+                  * straight into memory.
+                  */
+                 if (len) {
+                       dev->sc_dma_buf = dev->sc_bump_pa;
+                       dev->sc_dma_len = len;
+
+                       if (nexus->state == SFAS_NS_DATA_OUT)
+                         bcopy(dev->sc_buf, dev->sc_bump_va, dev->sc_dma_len);
+                 } else {
+                       dev->sc_dma_buf = dev->sc_dma_blk_ptr;
+                       dev->sc_dma_len = dev->sc_dma_blk_len;
+                 }
+
+                 /* Load DMA with adress and length of transfer. */
+                 dev->sc_setup_dma(dev, dev->sc_dma_buf, dev->sc_dma_len,
+                                   ((nexus->state == SFAS_NS_DATA_OUT) ?
+                                    SFAS_DMA_WRITE : SFAS_DMA_READ));
+
+                 printf("Using DMA !!!!\n");
+                 cmd = SFAS_CMD_TRANSFER_INFO | SFAS_CMD_DMA;
+               } else {
+                       /*
+                        * Hmmm, the unit wants more info than we have or has
+                        * more than we want. Let the chip handle that.
+                        */
+
+                       *rp->sfas_tc_low = 0; /* was 256 but this does not make sense */
+                       *rp->sfas_tc_mid = 1;
+                       *rp->sfas_tc_high = 0;
+                       cmd = SFAS_CMD_TRANSFER_PAD;
+               }
+               break;
+
+       case SFAS_PHASE_COMMAND:
+               /* The scsi unit wants the command, send it. */
+               nexus->state = SFAS_NS_SVC;
+
+               *rp->sfas_command = SFAS_CMD_FLUSH_FIFO;
+               for(i=0; i<5; i++);
+
+               for(i=0; i<nexus->clen; i++)
+                       *rp->sfas_fifo = nexus->cbuf[i];
+               cmd = SFAS_CMD_TRANSFER_INFO;
+               break;
+
+       case SFAS_PHASE_STATUS:
+               /*
+                * We've got status phase. Request status and command
+                * complete message.
+                */
+               nexus->state = SFAS_NS_STATUS;
+               cmd = SFAS_CMD_COMMAND_COMPLETE;
+               break;
+
+       case SFAS_PHASE_MESSAGE_OUT:
+               /*
+                * Either the scsi unit wants us to send a message or we have
+                * asked for it by seting the ATN bit.
+                */
+               nexus->state = SFAS_NS_MSG_OUT;
+
+               *rp->sfas_command = SFAS_CMD_FLUSH_FIFO;
+
+               if (nexus->flags & SFAS_NF_DO_SDTR) {
+                       /* Send a Synchronous Data Transfer Request. */
+
+                       sfas_build_sdtrm(dev, nexus->period, nexus->offset);
+                       nexus->flags |= SFAS_NF_SDTR_SENT;
+                       nexus->flags &= ~SFAS_NF_DO_SDTR;
+               } else if (nexus->flags & SFAS_NF_RESET) {
+                       /* Send a reset scsi unit message. */
+
+                       dev->sc_msg_out[0] = 0x0C;
+                       dev->sc_msg_out_len = 1;
+                       nexus->state = SFAS_NS_RESET;
+                       nexus->flags &= ~SFAS_NF_RESET;
+               } else if (dev->sc_msg_out_len == 0) {
+                       /* Don't know what to send so we send a NOP message. */
+
+                       dev->sc_msg_out[0] = 0x08;
+                       dev->sc_msg_out_len = 1;
+               }
+
+               cmd = SFAS_CMD_TRANSFER_INFO;
+
+               for(i=0; i<dev->sc_msg_out_len; i++)
+                       *rp->sfas_fifo = dev->sc_msg_out[i];
+               dev->sc_msg_out_len = 0;
+
+               break;
+
+       case SFAS_PHASE_MESSAGE_IN:
+               /* Receive a message from the scsi unit. */
+               nexus->state = SFAS_NS_MSG_IN;
+
+               while(!(nexus->flags & SFAS_NF_HAS_MSG)) {
+                       *rp->sfas_command = SFAS_CMD_TRANSFER_INFO;
+                       sfasiwait(dev);
+
+                       dev->sc_msg_in[dev->sc_msg_in_len++] = *rp->sfas_fifo;
+
+                       /* Check if we got all the bytes in the message. */
+                       if (dev->sc_msg_in[0] >= 0x80)       ;
+                       else if (dev->sc_msg_in[0] >= 0x30)  ;
+                       else if (((dev->sc_msg_in[0] >= 0x20) &&
+                                 (dev->sc_msg_in_len == 2)) ||
+                                ((dev->sc_msg_in[0] != 0x01) &&
+                                 (dev->sc_msg_in_len == 1))) {
+                               nexus->flags |= SFAS_NF_HAS_MSG;
+                               break;
+                       } else {
+                         if (dev->sc_msg_in_len >= 2)
+                           if ((dev->sc_msg_in[1]+2) == dev->sc_msg_in_len) {
+                               nexus->flags |= SFAS_NF_HAS_MSG;
+                               break;
+                           }
+                       }
+
+                       *rp->sfas_command = SFAS_CMD_MESSAGE_ACCEPTED;
+                       sfasiwait(dev);
+
+                       if ((dev->sc_status & SFAS_STAT_PHASE_MASK) !=
+                           SFAS_PHASE_MESSAGE_IN)
+                               break;
+               }
+
+               cmd = SFAS_CMD_MESSAGE_ACCEPTED;
+               if (nexus->flags & SFAS_NF_HAS_MSG) {
+                       /* We have a message. Decode it. */
+
+                       switch(dev->sc_msg_in[0]) {
+                       case 0x00:      /* COMMAND COMPLETE */
+                               if ((nexus->status == SCSI_CHECK) &&
+                                   !(nexus->flags & SFAS_NF_SENSING))
+                                       nexus->state = SFAS_NS_SENSE;
+                               else
+                                       nexus->state = SFAS_NS_DONE;
+                               break;
+                       case 0x04:      /* DISCONNECT */
+                               nexus->state = SFAS_NS_DISCONNECTING;
+                               break;
+                       case 0x02:      /* SAVE DATA POINTER */
+                               sfas_save_pointers(dev);
+                               break;
+                       case 0x03:      /* RESTORE DATA POINTERS */
+                               sfas_restore_pointers(dev);
+                               break;
+                       case 0x07:      /* MESSAGE REJECT */
+                               /*
+                                * If we had sent a SDTR and we got a message
+                                * reject, the scsi docs say that we must go
+                                * to async transfer.
+                                */
+                               if (nexus->flags & SFAS_NF_SDTR_SENT) {
+                                       nexus->flags &= ~SFAS_NF_SDTR_SENT;
+
+                                       nexus->config3 &= ~SFAS_CFG3_FASTSCSI;
+                                       nexus->syncper = 5;
+                                       nexus->syncoff = 0;
+
+                                       *rp->sfas_syncper = nexus->syncper;
+                                       *rp->sfas_syncoff = nexus->syncoff;
+                                       *rp->sfas_config3 = nexus->config3;
+                               } else
+                               /*
+                                * Something was rejected but we don't know
+                                * what! PANIC!
+                                */
+                                 panic("sfasintr: Unknown message rejected!");
+                               break;
+                       case 0x08:      /* MO OPERATION */
+                               break;
+                       case 0x01:      /* EXTENDED MESSAGE */
+                               switch(dev->sc_msg_in[2]) {
+                               case 0x01:/* SYNC. DATA TRANSFER REQUEST */
+                                       /* Decode the SDTR message. */
+                                       period = 4*dev->sc_msg_in[3];
+                                       offset = dev->sc_msg_in[4];
+
+                                       /*
+                                        * Make sure that the specs are within
+                                        * chip limits. Note that if we
+                                        * initiated the negotiation the specs
+                                        * WILL be withing chip limits. If it
+                                        * was the scsi unit that initiated
+                                        * the negotiation, the specs may be
+                                        * to high.
+                                        */
+                                       if (offset > 16)
+                                               offset = 16;
+                                       if ((period < 200) &&
+                                           (dev->sc_clock_freq <= 25))
+                                               period = 200;
+
+                                       if (offset == 0)
+                                              period = 5*dev->sc_clock_period;
+
+                                       nexus->syncper = period/
+                                                         dev->sc_clock_period;
+                                       nexus->syncoff = offset;
+
+                                       if (period < 200)
+                                         nexus->config3 |= SFAS_CFG3_FASTSCSI;
+                                       else
+                                         nexus->config3 &=~SFAS_CFG3_FASTSCSI;
+
+                                       nexus->flags |= SFAS_NF_SYNC_TESTED;
+
+                                       *rp->sfas_syncper = nexus->syncper;
+                                       *rp->sfas_syncoff = nexus->syncoff;
+                                       *rp->sfas_config3 = nexus->config3;
+
+                                       /*
+                                        * Hmmm, it seems that the scsi unit
+                                        * initiated sync negotiation, so lets
+                                        * reply acording to scsi-2 standard.
+                                        */
+                                       if (!(nexus->flags& SFAS_NF_SDTR_SENT))
+                                       {
+                                         if ((dev->sc_config_flags &
+                                              SFAS_NO_SYNCH) ||
+                                             (dev->sc_config_flags &
+                                              SFAS_NO_DMA) ||
+                                             sfas_inhibit_sync[
+                                                       nexus->lun_unit & 7]) {
+                                                 period = 200;
+                                                 offset = 0;
+                                         }
+
+                                         nexus->offset = offset;
+                                         nexus->period = period;
+                                         nexus->flags |= SFAS_NF_DO_SDTR;
+                                         *rp->sfas_command = SFAS_CMD_SET_ATN;
+                                       }
+
+                                       nexus->flags &= ~SFAS_NF_SDTR_SENT;
+                                       break;
+
+                               case 0x00: /* MODIFY DATA POINTERS */
+                               case 0x02: /* EXTENDED IDENTIFY (SCSI-1) */
+                               case 0x03: /* WIDE DATA TRANSFER REQUEST */
+                               default:
+                                       /* Reject any unhandeled messages. */
+
+                                       dev->sc_msg_out[0] = 0x07;
+                                       dev->sc_msg_out_len = 1;
+                                       *rp->sfas_command = SFAS_CMD_SET_ATN;
+                                       cmd = SFAS_CMD_MESSAGE_ACCEPTED;
+                                       break;
+                               }
+                               break;
+
+                       default:
+                               /* Reject any unhandeled messages. */
+
+                               dev->sc_msg_out[0] = 0x07;
+                               dev->sc_msg_out_len = 1;
+                               *rp->sfas_command = SFAS_CMD_SET_ATN;
+                               cmd = SFAS_CMD_MESSAGE_ACCEPTED;
+                               break;
+                       }
+                       nexus->flags &= ~SFAS_NF_HAS_MSG;
+                       dev->sc_msg_in_len = 0;
+               }
+               break;
+       default:
+               printf("SFASINTR: UNKNOWN PHASE! phase: %d\n",
+                      dev->sc_status & SFAS_STAT_PHASE_MASK);
+               dev->sc_led(dev, 0);
+               sfas_scsidone(dev, nexus->xs, -4);
+
+               return(-1);
+       }
+
+       if (cmd)
+               *rp->sfas_command = cmd;
+
+       return(0);
+}
+
+/*
+ * Stub for interrupt machine.
+ */
+void
+sfasintr(dev)
+       struct sfas_softc *dev;
+{
+       sfas_regmap_p    rp;
+       struct nexus    *nexus;
+
+       rp = dev->sc_fas;
+
+       if (!sfas_pretests(dev, rp)) {
+
+               nexus = dev->sc_cur_nexus;
+               if (nexus == NULL)
+                       nexus = dev->sc_sel_nexus;
+
+               if (nexus)
+                       if (!sfas_midaction(dev, rp, nexus))
+                               sfas_postaction(dev, rp, nexus);
+       }
+}
+
+/*
+ * sfasicmd is used to perform IO when we can't use interrupts. sfasicmd
+ * emulates the normal environment by waiting for the chip and calling
+ * sfasintr.
+ */
+void
+sfasicmd(dev, pendp)
+       struct sfas_softc   *dev;
+       struct sfas_pending *pendp;
+{
+       sfas_regmap_p    rp;
+       struct nexus    *nexus;
+
+       nexus = &dev->sc_nexus[pendp->xs->sc_link->target];
+       rp = dev->sc_fas;
+
+       if (!sfasselect(dev, pendp, (char *)pendp->xs->cmd, pendp->xs->cmdlen,
+                       (char *)pendp->xs->data, pendp->xs->datalen,
+                       SFAS_SELECT_I))
+               panic("sfasicmd: Couldn't select unit");
+
+       while(nexus->state != SFAS_NS_FINISHED) {
+               sfasiwait(dev);
+               sfasintr(dev);
+       }
+
+       nexus->flags &= ~SFAS_NF_SYNC_TESTED;
+}
diff --git a/sys/arch/arm32/podulebus/sfasreg.h b/sys/arch/arm32/podulebus/sfasreg.h
new file mode 100644 (file)
index 0000000..9c4020a
--- /dev/null
@@ -0,0 +1,158 @@
+/* $NetBSD: sfasreg.h,v 1.1 1996/01/31 23:26:45 mark Exp $ */
+
+/*
+ * Copyright (c) 1995 Daniel Widenfalk
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided 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 Daniel Widenfalk
+ *      for the NetBSD Project.
+ * 4. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _SFASREG_H_
+#define _SFASREG_H_
+
+/*
+ * Emulex FAS216 SCSI interface hardware description.
+ */
+
+typedef volatile unsigned char vu_char;
+
+typedef struct {
+       vu_char         *sfas_tc_low;   /* rw: Transfer count low */
+       vu_char         *sfas_tc_mid;   /* rw: Transfer count mid */
+       vu_char         *sfas_fifo;     /* rw: Data FIFO */
+       vu_char         *sfas_command;  /* rw: Chip command reg */
+       vu_char         *sfas_dest_id;  /* w: (Re)select bus ID */
+#define sfas_status sfas_dest_id       /* r: Status */
+       vu_char         *sfas_timeout;  /* w: (Re)select timeout */
+#define sfas_interrupt sfas_timeout    /* r: Interrupt */
+       vu_char         *sfas_syncper;  /* w: Synch. transfer period */
+#define sfas_seqstep sfas_syncper      /* r: Sequence step */
+       vu_char         *sfas_syncoff;  /* w: Synch. transfer offset */
+#define sfas_fifo_flags sfas_syncoff   /* r: FIFO flags */
+       vu_char         *sfas_config1;  /* rw: Config register #1 */
+       vu_char         *sfas_clkconv;  /* w: Clock conv. factor */
+       vu_char         *sfas_test;     /* w: Test register */
+       vu_char         *sfas_config2;  /* rw: Config register #2 */
+       vu_char         *sfas_config3;  /* rw: Config register #3 */
+       vu_char         *sfas_tc_high;  /* rw: Transfer count high */
+       vu_char         *sfas_fifo_bot; /* w: FIFO bottom register */
+} sfas_regmap_t;
+typedef sfas_regmap_t *sfas_regmap_p;
+
+/* Commands for the FAS216 */
+#define SFAS_CMD_DMA                   0x80
+
+#define SFAS_CMD_SEL_NO_ATN            0x41
+#define SFAS_CMD_SEL_ATN               0x42
+#define SFAS_CMD_SEL_ATN3              0x46
+#define SFAS_CMD_SEL_ATN_STOP          0x43
+
+#define SFAS_CMD_ENABLE_RESEL          0x44
+#define SFAS_CMD_DISABLE_RESEL         0x45
+
+#define SFAS_CMD_TRANSFER_INFO         0x10
+#define SFAS_CMD_TRANSFER_PAD          0x98
+
+#define SFAS_CMD_COMMAND_COMPLETE      0x11
+#define SFAS_CMD_MESSAGE_ACCEPTED      0x12
+
+#define SFAS_CMD_SET_ATN               0x1A
+#define SFAS_CMD_RESET_ATN             0x1B
+
+#define SFAS_CMD_NOP                   0x00
+#define SFAS_CMD_FLUSH_FIFO            0x01
+#define SFAS_CMD_RESET_CHIP            0x02
+#define SFAS_CMD_RESET_SCSI_BUS                0x03
+
+#define SFAS_STAT_PHASE_MASK           0x07
+#define SFAS_STAT_PHASE_TRANS_CPLT     0x08
+#define SFAS_STAT_TRANSFER_COUNT_ZERO  0x10
+#define SFAS_STAT_PARITY_ERROR         0x20
+#define SFAS_STAT_GROSS_ERROR          0x40
+#define SFAS_STAT_INTERRUPT_PENDING    0x80
+
+#define SFAS_PHASE_DATA_OUT            0
+#define SFAS_PHASE_DATA_IN             1
+#define SFAS_PHASE_COMMAND             2
+#define SFAS_PHASE_STATUS              3
+#define SFAS_PHASE_MESSAGE_OUT         6
+#define SFAS_PHASE_MESSAGE_IN          7
+
+#define SFAS_DEST_ID_MASK              0x07
+
+#define SFAS_INT_SELECTED              0x01
+#define SFAS_INT_SELECTED_WITH_ATN     0x02
+#define SFAS_INT_RESELECTED            0x04
+#define SFAS_INT_FUNCTION_COMPLETE     0x08
+#define SFAS_INT_BUS_SERVICE           0x10
+#define SFAS_INT_DISCONNECT            0x20
+#define SFAS_INT_ILLEGAL_COMMAND       0x40
+#define SFAS_INT_SCSI_RESET_DETECTED   0x80
+
+#define SFAS_SYNCHRON_PERIOD_MASK      0x1F
+
+#define SFAS_FIFO_COUNT_MASK           0x1F
+#define SFAS_FIFO_SEQUENCE_STEP_MASK   0xE0
+#define SFAS_FIFO_SEQUENCE_SHIFT       5
+
+#define SFAS_SYNCHRON_OFFSET_MASK      0x0F
+#define SFAS_SYNC_ASSERT_MASK          0x30
+#define SFAS_SYNC_ASSERT_SHIFT         4
+#define SFAS_SYNC_DEASSERT_MASK                0x30
+#define SFAS_SYNC_DEASSERT_SHIFT       6
+
+#define SFAS_CFG1_BUS_ID_MASK          0x07
+#define SFAS_CFG1_CHIP_TEST_MODE       0x08
+#define SFAS_CFG1_SCSI_PARITY_ENABLE   0x10
+#define SFAS_CFG1_PARITY_TEST_MODE     0x20
+#define SFAS_CFG1_SCSI_RES_INT_DIS     0x40
+#define SFAS_CFG1_SLOW_CABLE_MODE      0x80
+
+#define SFAS_CLOCK_CONVERSION_MASK     0x07
+
+#define SFAS_TEST_TARGET_TEST_MODE     0x01
+#define SFAS_TEST_INITIATOR_TEST_MODE  0x02
+#define SFAS_TEST_TRISTATE_TEST_MODE   0x04
+
+#define SFAS_CFG2_DMA_PARITY_ENABLE    0x01
+#define SFAS_CFG2_REG_PARITY_ENABLE    0x02
+#define SFAS_CFG2_TARG_BAD_PARITY_ABORT        0x04
+#define SFAS_CFG2_SCSI_2_MODE          0x08
+#define SFAS_CFG2_TRISTATE_DMA_REQ     0x10
+#define SFAS_CFG2_BYTE_CONTROL_MODE    0x20
+#define SFAS_CFG2_FEATURES_ENABLE      0x40
+#define SFAS_CFG2_RESERVE_FIFO_BYTE    0x80
+
+#define SFAS_CFG3_THRESHOLD_8_MODE     0x01
+#define SFAS_CFG3_ALTERNATE_DMA_MODE   0x02
+#define SFAS_CFG3_SAVE_RESIDUAL_BYTE   0x04
+#define SFAS_CFG3_FASTCLK              0x08
+#define SFAS_CFG3_FASTSCSI             0x10
+#define SFAS_CFG3_CDB10                        0x20
+#define SFAS_CFG3_QENB                 0x40
+#define SFAS_CFG3_IDRESCHK             0x80
+
+#endif
diff --git a/sys/arch/arm32/podulebus/sfasvar.h b/sys/arch/arm32/podulebus/sfasvar.h
new file mode 100644 (file)
index 0000000..04dc68d
--- /dev/null
@@ -0,0 +1,263 @@
+/* $NetBSD: sfasvar.h,v 1.1 1996/01/31 23:26:49 mark Exp $ */
+
+/*
+ * Copyright (c) 1995 Daniel Widenfalk
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided 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 Daniel Widenfalk
+ *      for the NetBSD Project.
+ * 4. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _SFASVAR_H_
+#define _SFASVAR_H_
+
+#ifndef _SFASREG_H_
+#include <arm32/podulebus/sfasreg.h>
+#endif
+
+/*
+ * MAXCHAIN is the anticipated maximum number of chain blocks needed. This
+ * assumes that we are NEVER requested to transfer more than MAXPHYS bytes.
+ */
+#define MAXCHAIN       (MAXPHYS/NBPG+2)
+
+/*
+ * Maximum number of requests standing by. Could be anything, but I think 9
+ * looks nice :-) NOTE: This does NOT include requests already started!
+ */
+#define MAXPENDING     9       /* 7 IDs + 2 extra */
+
+/*
+ * DMA chain block. If flg == SFAS_CHAIN_PRG or flg == SFAS_CHAIN_BUMP then
+ * ptr is a VIRTUAL adress. If flg == SFAS_CHAIN_DMA then ptr is a PHYSICAL
+ * adress.
+ */
+struct sfas_dma_chain {
+       vm_offset_t     ptr;
+       u_short         len;
+       short           flg;
+};
+#define SFAS_CHAIN_DMA 0x00
+#define SFAS_CHAIN_BUMP        0x01
+#define SFAS_CHAIN_PRG 0x02
+
+
+/*
+ * This struct contains the necessary info for a pending request. Pointer to
+ * a scsi_xfer struct.
+ */
+struct sfas_pending {
+       TAILQ_ENTRY(sfas_pending) link;
+       struct scsi_xfer         *xs;
+};
+
+/*
+ * nexus contains all active data for one SCSI unit. Parts of the info in this
+ * struct survives between scsi commands.
+ */
+struct nexus {
+       struct  scsi_xfer       *xs;            /* Pointer to request */
+
+       u_char                   ID;            /* ID message to be sent */
+       u_char                   clen;          /* scsi command length + */
+       u_char                   cbuf[14];      /* the actual command bytes */
+
+       struct sfas_dma_chain    dma[MAXCHAIN]; /* DMA chain blocks */
+       short                    max_link;      /* Maximum used of above */
+       short                    cur_link;      /* Currently handled block */
+
+       u_char                  *buf;           /* Virtual adress of data */
+       int                      len;           /* Bytes left to transfer */
+
+       vm_offset_t              dma_buf;       /* Current DMA adress */
+       int                      dma_len;       /* Current DMA length */
+
+       vm_offset_t              dma_blk_ptr;   /* Current chain adress */
+       int                      dma_blk_len;   /* Current chain length */
+       u_char                   dma_blk_flg;   /* Current chain flags */
+
+       u_char                   state;         /* Nexus state, see below */
+       u_short                  flags;         /* Nexus flags, see below */
+
+       short                    period;        /* Sync period to request */
+       u_char                   offset;        /* Sync offset to request */
+
+       u_char                   syncper;       /* FAS216 variable storage */
+       u_char                   syncoff;       /* FAS216 variable storage */
+       u_char                   config3;       /* FAS216 variable storage */
+
+       u_char                   lun_unit;      /* (Lun<<4) | Unit of nexus */
+       u_char                   status;        /* Status byte from unit*/
+
+};
+
+/* SCSI nexus_states */
+#define SFAS_NS_IDLE           0       /* Nexus idle */
+#define SFAS_NS_SELECTED       1       /* Last command was a SELECT command */
+#define SFAS_NS_DATA_IN                2       /* Last command was a TRANSFER_INFO */
+                                       /* command during a data in phase */
+#define SFAS_NS_DATA_OUT       3       /* Last command was a TRANSFER_INFO */
+                                       /* command during a data out phase */
+#define SFAS_NS_STATUS         4       /* We have send a COMMAND_COMPLETE */
+                                       /* command and are awaiting status */
+#define SFAS_NS_MSG_IN         5       /* Last phase was MESSAGE IN */
+#define SFAS_NS_MSG_OUT                6       /* Last phase was MESSAGE OUT */
+#define SFAS_NS_SVC            7       /* We have sent the command */
+#define SFAS_NS_DISCONNECTING  8       /* We have recieved a disconnect msg */
+#define SFAS_NS_DISCONNECTED   9       /* We are disconnected */
+#define SFAS_NS_RESELECTED     10      /* We was reselected */
+#define SFAS_NS_DONE           11      /* Done. Prephsase to FINISHED */
+#define SFAS_NS_FINISHED       12      /* Realy done. Call scsi_done */
+#define SFAS_NS_SENSE          13      /* We are requesting sense */
+#define SFAS_NS_RESET          14      /* We are reseting this unit */
+
+/* SCSI nexus flags */
+#define SFAS_NF_UNIT_BUSY      0x0001  /* Unit is not available */
+
+#define SFAS_NF_SELECT_ME      0x0002  /* Nexus is set up, waiting for bus */
+
+#define SFAS_NF_REQUEST_SENSE  0x0004  /* We should request sense */
+#define SFAS_NF_SENSING                0x0008  /* We are sensing */
+
+#define SFAS_NF_HAS_MSG                0x0010  /* We have recieved a complete msg */
+
+#define SFAS_NF_DO_SDTR                0x0020  /* We should send a SDTR */
+#define SFAS_NF_SDTR_SENT      0x0040  /* We have sent a SDTR */
+#define SFAS_NF_SYNC_TESTED    0x0080  /* We have negotiated sync */
+
+#define SFAS_NF_RESET          0x0100  /* Reset this nexus */
+#define SFAS_NF_IMMEDIATE      0x0200  /* We are operating from sfasicmd */
+
+#define SFAS_NF_DEBUG          0x8000  /* As it says: DEBUG */
+
+struct sfas_softc {
+       struct  device           sc_dev;        /* System required struct */
+       struct  scsi_link        sc_link;       /* For sub devices */
+       irqhandler_t             sc_ih;         /* Interrupt chain struct */
+
+       TAILQ_HEAD(,sfas_pending) sc_xs_pending;
+       TAILQ_HEAD(,sfas_pending) sc_xs_free;
+       struct  sfas_pending     sc_xs_store[MAXPENDING];
+
+       sfas_regmap_p            sc_fas;        /* FAS216 Address */
+       void                    *sc_spec;       /* Board-specific data */
+
+       u_char                  *sc_bump_va;    /* Bumpbuf virtual adr */
+       vm_offset_t              sc_bump_pa;    /* Bumpbuf physical adr */
+       int                      sc_bump_sz;    /* Bumpbuf size */
+
+/* Configuration registers, must be set BEFORE sfasinitialize */
+       u_char                   sc_clock_freq;
+       u_short                  sc_timeout;
+       u_char                   sc_host_id;
+       u_char                   sc_config_flags;
+
+/* Generic DMA functions */
+       int                    (*sc_setup_dma)();
+       int                    (*sc_build_dma_chain)();
+       int                    (*sc_need_bump)();
+
+/* Generic Led data */
+       int                      sc_led_status;
+       void                   (*sc_led)();
+
+/* Nexus list */
+       struct nexus             sc_nexus[8];
+       struct nexus            *sc_cur_nexus;
+       struct nexus            *sc_sel_nexus;
+
+/* Current transfer data */
+       u_char                  *sc_buf;        /* va */
+       int                      sc_len;
+
+       vm_offset_t              sc_dma_buf;    /* pa */
+       int                      sc_dma_len;
+       vm_offset_t              sc_dma_blk_ptr;
+       int                      sc_dma_blk_len;
+       short                    sc_dma_blk_flg;
+
+       struct sfas_dma_chain   *sc_chain;      /* Current DMA chain */
+       short                    sc_max_link;
+       short                    sc_cur_link;
+
+/* Interrupt registers */
+       u_char                   sc_status;
+       u_char                   sc_interrupt;
+       u_char                   sc_resel[2];
+
+       u_char                   sc_units_disconnected;
+
+/* Storage for FAS216 config registers (current values) */
+       u_char                   sc_config1;
+       u_char                   sc_config2;
+       u_char                   sc_config3;
+       u_char                   sc_clock_conv_fact;
+       u_char                   sc_timeout_val;
+       u_char                   sc_clock_period;
+
+       u_char                   sc_msg_in[7];
+       u_char                   sc_msg_in_len;
+
+       u_char                   sc_msg_out[7];
+       u_char                   sc_msg_out_len;
+
+       u_char                   sc_unit;
+       u_char                   sc_lun;
+       u_char                   sc_flags;
+};
+
+#define SFAS_DMA_READ  0
+#define SFAS_DMA_WRITE 1
+#define SFAS_DMA_CLEAR 2
+
+/* sc_flags */
+#define SFAS_ACTIVE     0x01
+#define SFAS_DONT_WAIT  0x02
+
+/* SCSI Selection modes */
+#define SFAS_SELECT    0x00    /* Normal selection: No sync, no resel */
+#define SFAS_SELECT_R  0x01    /* Reselection allowed */
+#define SFAS_SELECT_S  0x02    /* Synchronous transfer allowed */
+#define SFAS_SELECT_I  0x04    /* Selection for sfasicmd */
+#define SFAS_SELECT_K  0x08    /* Send a BUS DEVICE RESET message (Kill) */
+
+/* Nice abbreviations of the above */
+#define SFAS_SELECT_RS (SFAS_SELECT_R|SFAS_SELECT_S)
+#define SFAS_SELECT_RI (SFAS_SELECT_R|SFAS_SELECT_I)
+#define SFAS_SELECT_SI (SFAS_SELECT_S|SFAS_SELECT_I)
+#define SFAS_SELECT_RSI        (SFAS_SELECT_R|SFAS_SELECT_S|SFAS_SELECT_I)
+
+/* sc_config_flags */
+#define SFAS_NO_SYNCH   0x01   /* Disable synchronous transfer */
+#define SFAS_NO_DMA     0x02   /* Do not use DMA! EVER! */
+#define SFAS_NO_RESELECT 0x04  /* Do not allow relesection */
+#define SFAS_SLOW_CABLE         0x08   /* Cable is "unsafe" for fast scsi-2 */
+#define SFAS_SLOW_START         0x10   /* There are slow starters on the bus */
+
+void   sfasinitialize __P((struct sfas_softc *sc));
+void   sfas_minphys   __P((struct buf *bp));
+int    sfas_scsicmd   __P((struct scsi_xfer *));
+
+#endif /* _SFASVAR_H_ */