summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorbjh21 <bjh21@NetBSD.org>2000-05-09 21:55:44 +0000
committerbjh21 <bjh21@NetBSD.org>2000-05-09 21:55:44 +0000
commit6c97e2bd7817f6eb36ea04f65488ea1e95cb158f (patch)
tree499bc6851619a39119e4f4e8919311cbb9b2948d /sys
parent6a36c27519360fbbcb9b0533b93429d400c5e315 (diff)
Initial commit of arm26 port
Diffstat (limited to 'sys')
-rw-r--r--sys/arch/arm26/Makefile33
-rw-r--r--sys/arch/arm26/arm26/Locore.c151
-rw-r--r--sys/arch/arm26/arm26/aout_machdep.c104
-rw-r--r--sys/arch/arm26/arm26/autoconf.c68
-rw-r--r--sys/arch/arm26/arm26/bus.c220
-rw-r--r--sys/arch/arm26/arm26/conf.c193
-rw-r--r--sys/arch/arm26/arm26/cons_machdep.c71
-rw-r--r--sys/arch/arm26/arm26/copyinout.S177
-rw-r--r--sys/arch/arm26/arm26/copyinoutstr.c108
-rw-r--r--sys/arch/arm26/arm26/cpu.c206
-rw-r--r--sys/arch/arm26/arm26/cpuvar.h42
-rw-r--r--sys/arch/arm26/arm26/db_disasm.c75
-rw-r--r--sys/arch/arm26/arm26/db_interface.c345
-rw-r--r--sys/arch/arm26/arm26/db_machdep.c227
-rw-r--r--sys/arch/arm26/arm26/db_trace.c150
-rw-r--r--sys/arch/arm26/arm26/disksubr.c447
-rw-r--r--sys/arch/arm26/arm26/disksubr_acorn.c359
-rw-r--r--sys/arch/arm26/arm26/disksubr_mbr.c278
-rw-r--r--sys/arch/arm26/arm26/except.c717
-rw-r--r--sys/arch/arm26/arm26/genassym.cf46
-rw-r--r--sys/arch/arm26/arm26/intrnames.S86
-rw-r--r--sys/arch/arm26/arm26/irq.c297
-rw-r--r--sys/arch/arm26/arm26/locore.S398
-rw-r--r--sys/arch/arm26/arm26/machdep.c205
-rw-r--r--sys/arch/arm26/arm26/md_root.c88
-rw-r--r--sys/arch/arm26/arm26/mem.c214
-rw-r--r--sys/arch/arm26/arm26/pmap.c930
-rw-r--r--sys/arch/arm26/arm26/rscons.c99
-rw-r--r--sys/arch/arm26/arm26/softintr.c175
-rw-r--r--sys/arch/arm26/arm26/start.c225
-rw-r--r--sys/arch/arm26/arm26/stubs.c205
-rw-r--r--sys/arch/arm26/arm26/vm_machdep.c330
-rw-r--r--sys/arch/arm26/arm26/zeropage.S100
-rw-r--r--sys/arch/arm26/boot/BBBB,fd1448
-rw-r--r--sys/arch/arm26/compile/.keep_me0
-rw-r--r--sys/arch/arm26/conf/GENERIC178
-rw-r--r--sys/arch/arm26/conf/Makefile.arm26190
-rw-r--r--sys/arch/arm26/conf/files.arm26236
-rw-r--r--sys/arch/arm26/conf/std.arm266
-rw-r--r--sys/arch/arm26/include/Makefile15
-rw-r--r--sys/arch/arm26/include/ansi.h81
-rw-r--r--sys/arch/arm26/include/aout_machdep.h37
-rw-r--r--sys/arch/arm26/include/armreg.h79
-rw-r--r--sys/arch/arm26/include/asm.h117
-rw-r--r--sys/arch/arm26/include/boot.h86
-rw-r--r--sys/arch/arm26/include/bswap.h9
-rw-r--r--sys/arch/arm26/include/bus.h128
-rw-r--r--sys/arch/arm26/include/cdefs.h3
-rw-r--r--sys/arch/arm26/include/cpu.h41
-rw-r--r--sys/arch/arm26/include/db_machdep.h90
-rw-r--r--sys/arch/arm26/include/disklabel.h84
-rw-r--r--sys/arch/arm26/include/disklabel_acorn.h121
-rw-r--r--sys/arch/arm26/include/elf_machdep.h44
-rw-r--r--sys/arch/arm26/include/endian.h3
-rw-r--r--sys/arch/arm26/include/endian_machdep.h3
-rw-r--r--sys/arch/arm26/include/float.h89
-rw-r--r--sys/arch/arm26/include/fp.h86
-rw-r--r--sys/arch/arm26/include/frame.h165
-rw-r--r--sys/arch/arm26/include/ieee.h150
-rw-r--r--sys/arch/arm26/include/ieeefp.h40
-rw-r--r--sys/arch/arm26/include/intr.h53
-rw-r--r--sys/arch/arm26/include/ipkdb.h43
-rw-r--r--sys/arch/arm26/include/irq.h46
-rw-r--r--sys/arch/arm26/include/limits.h97
-rw-r--r--sys/arch/arm26/include/lock.h51
-rw-r--r--sys/arch/arm26/include/machdep.h64
-rw-r--r--sys/arch/arm26/include/math.h11
-rw-r--r--sys/arch/arm26/include/memcreg.h226
-rw-r--r--sys/arch/arm26/include/param.h144
-rw-r--r--sys/arch/arm26/include/pcb.h52
-rw-r--r--sys/arch/arm26/include/pmap.h60
-rw-r--r--sys/arch/arm26/include/proc.h38
-rw-r--r--sys/arch/arm26/include/profile.h76
-rw-r--r--sys/arch/arm26/include/pte.h33
-rw-r--r--sys/arch/arm26/include/ptrace.h41
-rw-r--r--sys/arch/arm26/include/reg.h53
-rw-r--r--sys/arch/arm26/include/setjmp.h79
-rw-r--r--sys/arch/arm26/include/signal.h136
-rw-r--r--sys/arch/arm26/include/softintr.h40
-rw-r--r--sys/arch/arm26/include/spl.h93
-rw-r--r--sys/arch/arm26/include/stdarg.h60
-rw-r--r--sys/arch/arm26/include/trap.h58
-rw-r--r--sys/arch/arm26/include/types.h88
-rw-r--r--sys/arch/arm26/include/undefined.h63
-rw-r--r--sys/arch/arm26/include/varargs.h64
-rw-r--r--sys/arch/arm26/include/vmparam.h122
-rw-r--r--sys/arch/arm26/iobus/iobus.c116
-rw-r--r--sys/arch/arm26/iobus/iobusvar.h45
-rw-r--r--sys/arch/arm26/iobus/ioc.c529
-rw-r--r--sys/arch/arm26/iobus/iocreg.h153
-rw-r--r--sys/arch/arm26/iobus/iocvar.h72
-rw-r--r--sys/arch/arm26/ioc/arckbd.c740
-rw-r--r--sys/arch/arm26/ioc/arckbdmap.c238
-rw-r--r--sys/arch/arm26/ioc/arckbdreg.h94
-rw-r--r--sys/arch/arm26/ioc/arckbdvar.h45
-rw-r--r--sys/arch/arm26/ioc/iic.c351
-rw-r--r--sys/arch/arm26/ioc/iic.h64
-rw-r--r--sys/arch/arm26/ioc/ioeb.c73
-rw-r--r--sys/arch/arm26/ioc/ioebreg.h40
-rw-r--r--sys/arch/arm26/ioc/latchreg.h60
-rw-r--r--sys/arch/arm26/ioc/pcf8583reg.h81
-rw-r--r--sys/arch/arm26/ioc/rtc.c470
-rw-r--r--sys/arch/arm26/mainbus/mainbus.c104
-rw-r--r--sys/arch/arm26/podulebus/asc.c469
-rw-r--r--sys/arch/arm26/podulebus/ascreg.h279
-rw-r--r--sys/arch/arm26/podulebus/ascvar.h51
-rw-r--r--sys/arch/arm26/podulebus/dtide.c122
-rw-r--r--sys/arch/arm26/podulebus/dtidereg.h21
-rw-r--r--sys/arch/arm26/podulebus/if_ea.c1537
-rw-r--r--sys/arch/arm26/podulebus/if_eareg.h168
-rw-r--r--sys/arch/arm26/podulebus/if_ei.c371
-rw-r--r--sys/arch/arm26/podulebus/if_eireg.h62
-rw-r--r--sys/arch/arm26/podulebus/podulebus.c251
-rw-r--r--sys/arch/arm26/podulebus/podulebus.h98
-rw-r--r--sys/arch/arm26/podulebus/podulebusreg.h62
-rw-r--r--sys/arch/arm26/podulebus/sbic.c3011
-rw-r--r--sys/arch/arm26/podulebus/sbicreg.h426
-rw-r--r--sys/arch/arm26/podulebus/sbicvar.h236
-rw-r--r--sys/arch/arm26/podulebus/unixbp.c85
-rw-r--r--sys/arch/arm26/podulebus/unixbpreg.h15
-rw-r--r--sys/arch/arm26/vidc/arcvideo.c501
-rw-r--r--sys/arch/arm26/vidc/arcvideovar.h47
-rw-r--r--sys/arch/arm26/vidc/vidcreg.h131
-rw-r--r--sys/arch/arm26/vidc/vidmodes.c48
-rw-r--r--sys/arch/arm32/podulebus/podule_data.h8
-rw-r--r--sys/arch/arm32/podulebus/podules5
-rw-r--r--sys/arch/arm32/podulebus/podules.h5
-rw-r--r--sys/lib/libkern/arch/arm26/Makefile.inc9
-rw-r--r--sys/lib/libkern/arch/arm26/_memcpy.S463
-rw-r--r--sys/lib/libkern/arch/arm26/bcopy.S48
-rw-r--r--sys/lib/libkern/arch/arm26/byte_swap_2.S53
-rw-r--r--sys/lib/libkern/arch/arm26/byte_swap_4.S54
-rw-r--r--sys/lib/libkern/arch/arm26/bzero.S44
-rw-r--r--sys/lib/libkern/arch/arm26/divsi3.S398
-rw-r--r--sys/lib/libkern/arch/arm26/memcpy.S48
-rw-r--r--sys/lib/libkern/arch/arm26/memmove.S48
-rw-r--r--sys/lib/libkern/arch/arm26/memset.S134
137 files changed, 24369 insertions, 3 deletions
diff --git a/sys/arch/arm26/Makefile b/sys/arch/arm26/Makefile
new file mode 100644
index 00000000000..87c745ea262
--- /dev/null
+++ b/sys/arch/arm26/Makefile
@@ -0,0 +1,33 @@
+# $NetBSD: Makefile,v 1.1 2000/05/09 21:55:54 bjh21 Exp $
+
+# Makefile for arm26 tags file and boot blocks
+
+TARM26= ../arm26/tags
+SARM26= ../arm26/arm26/*.[ch] ../arm26/include/*.h \
+ ../arm26/iobus/*.[ch] ../arm26/ioc/*.[ch] ../arm32/mainbus/*.[ch] \
+ ../arm26/vidc/*.[ch]
+AARM26= ../arm26/arm26/*.S ../arm26/iobus/*.S
+
+# Directories in which to place tags links
+DARM26= arm26 include iobus ioc mainbus vidc
+
+.include "../../kern/Make.tags.inc"
+
+tags: TAGS
+ -ctags -wdtf ${TARM26} ${SARM26} ${COMM}
+ egrep "^ENTRY(.*)|^ALTENTRY(.*)" ${AARM26} | \
+ sed "s;\([^:]*\):\([^(]*\)(\([^, )]*\)\(.*\);\3 \1 /^\2(\3\4$$/;" \
+ >> ${TARM26}
+ sort -o ${TARM26} ${TARM26}
+
+TAGS:
+ etags ${SARM26} ${COMM} ${AARM26}
+
+links:
+ -for i in ${DARM26}; do \
+ cd $$i && rm -f tags; ln -s ../tags tags; done
+
+
+SUBDIR= include
+
+.include <bsd.subdir.mk>
diff --git a/sys/arch/arm26/arm26/Locore.c b/sys/arch/arm26/arm26/Locore.c
new file mode 100644
index 00000000000..05fb4577323
--- /dev/null
+++ b/sys/arch/arm26/arm26/Locore.c
@@ -0,0 +1,151 @@
+/* $NetBSD: Locore.c,v 1.1 2000/05/09 21:55:55 bjh21 Exp $ */
+
+/*
+ * Copyright (c) 2000 Ben Harris.
+ * Copyright (C) 1995, 1996 Wolfgang Solfrank.
+ * Copyright (C) 1995, 1996 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.
+ */
+
+/*
+ * Some additional routines that happened to be in locore.S traditionally,
+ * but have no need to be coded in assembly.
+ */
+
+#include <sys/param.h>
+
+__RCSID("$NetBSD: Locore.c,v 1.1 2000/05/09 21:55:55 bjh21 Exp $");
+
+#include <sys/proc.h>
+#include <sys/systm.h>
+#include <sys/user.h>
+
+#include <vm/vm.h>
+
+#include <machine/machdep.h>
+
+static void idle(void);
+
+volatile int whichqs;
+
+/*
+ * Put process p on the run queue indicated by its priority.
+ * Calls should be made at splstatclock(), and p->p_stat should be SRUN.
+ */
+void
+setrunqueue(struct proc *p)
+{
+ struct prochd *q;
+ struct proc *oldlast;
+ int which = p->p_priority >> 2;
+
+#ifdef DIAGNOSTIC
+ if (p->p_back)
+ panic("setrunqueue");
+#endif
+ q = &qs[which];
+ whichqs |= 1 << which;
+ p->p_forw = (struct proc *)q;
+ p->p_back = oldlast = q->ph_rlink;
+ q->ph_rlink = p;
+ oldlast->p_forw = p;
+}
+
+/*
+ * Remove process p from its run queue, which should be the one
+ * indicated by its priority.
+ * Calls should be made at splstatclock().
+ */
+void
+remrunqueue(struct proc *p)
+{
+ int which = p->p_priority >> 2;
+ struct prochd *q;
+
+#ifdef DIAGNOSTIC
+ if (!(whichqs & (1 << which)))
+ panic("remrunqueue");
+#endif
+ p->p_forw->p_back = p->p_back;
+ p->p_back->p_forw = p->p_forw;
+ p->p_back = NULL;
+ q = &qs[which];
+ if (q->ph_link == (struct proc *)q)
+ whichqs &= ~(1 << which);
+}
+
+/*
+ * Idle
+ */
+static void
+idle()
+{
+
+ spl0();
+ while (whichqs == 0)
+ continue;
+ splhigh();
+}
+
+extern int want_resched; /* XXX should be in <machine/cpu.h> */
+
+/*
+ * Find the highest-priority runnable process and switch to it.
+ */
+void
+cpu_switch(struct proc *p1)
+{
+ int which;
+ int s;
+ struct prochd *q;
+ struct proc *p2;
+
+#if 0
+ printf("cpu_switch: %p ->", p1);
+#endif
+ curproc = NULL;
+ s = splhigh();
+ while (whichqs == 0)
+ idle();
+ which = ffs(whichqs) - 1;
+ q = &qs[which];
+ p2 = q->ph_link;
+ remrunqueue(p2);
+ want_resched = 0;
+ curproc = p2;
+#if 0
+ printf(" %p\n", p2);
+#endif
+ if (p2 == p1)
+ return;
+ pmap_deactivate(p1);
+ pmap_activate(p2);
+ cpu_loswitch(&p1->p_addr->u_pcb.pcb_sf, p2->p_addr->u_pcb.pcb_sf);
+ /* We only get back here after the other process has run. */
+ splx(s);
+}
diff --git a/sys/arch/arm26/arm26/aout_machdep.c b/sys/arch/arm26/arm26/aout_machdep.c
new file mode 100644
index 00000000000..547b12cbc70
--- /dev/null
+++ b/sys/arch/arm26/arm26/aout_machdep.c
@@ -0,0 +1,104 @@
+/* $NetBSD: aout_machdep.c,v 1.1 2000/05/09 21:55:55 bjh21 Exp $ */
+
+/*
+ * Copyright (c) 2000 Ben Harris
+ * Copyright (c) 1993, 1994 Christopher G. Demetriou
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Christopher G. Demetriou.
+ * 4. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/* This file is part of NetBSD/arm26 -- a port of NetBSD to ARM2/3 machines. */
+/*
+ * aout_machdep.c - odd a.out executable formats
+ */
+
+#include <sys/param.h>
+
+__RCSID("$NetBSD: aout_machdep.c,v 1.1 2000/05/09 21:55:55 bjh21 Exp $");
+
+#include <sys/exec.h>
+#include <sys/exec_aout.h>
+#include <sys/systm.h>
+#include <sys/vnode.h>
+#include <machine/aout_machdep.h>
+#include <vm/vm.h>
+
+int cpu_exec_aout_prep_ozmagic(struct proc *, struct exec_package *);
+
+int
+cpu_exec_aout_makecmds(struct proc *p, struct exec_package *epp)
+{
+ struct exec *execp = epp->ep_hdr;
+
+ if (execp->a_midmag == ZMAGIC)
+ /* GNU binutils arm-acorn-aout format */
+ return cpu_exec_aout_prep_ozmagic(p, epp);
+ return ENOEXEC;
+}
+
+
+int cpu_exec_aout_prep_ozmagic(struct proc *p, struct exec_package *epp)
+{
+ struct exec *execp = epp->ep_hdr;
+
+ epp->ep_taddr = USRTEXT;
+ epp->ep_tsize = execp->a_text;
+ epp->ep_daddr = epp->ep_taddr + execp->a_text;
+ epp->ep_dsize = execp->a_data + execp->a_bss;
+ epp->ep_entry = execp->a_entry;
+
+ /*
+ * check if vnode is in open for writing, because we want to
+ * demand-page out of it. if it is, don't do it, for various
+ * reasons
+ */
+ if ((execp->a_text != 0 || execp->a_data != 0) &&
+ epp->ep_vp->v_writecount != 0) {
+#ifdef DIAGNOSTIC
+ if (epp->ep_vp->v_flag & VTEXT)
+ panic("exec: a VTEXT vnode has writecount != 0\n");
+#endif
+ return ETXTBSY;
+ }
+ epp->ep_vp->v_flag |= VTEXT;
+
+ /* set up command for text segment */
+ NEW_VMCMD(&epp->ep_vmcmds, vmcmd_map_pagedvn, execp->a_text,
+ epp->ep_taddr, epp->ep_vp, __LDPGSZ, VM_PROT_READ|VM_PROT_EXECUTE);
+
+ /* set up command for data segment */
+ NEW_VMCMD(&epp->ep_vmcmds, vmcmd_map_pagedvn, execp->a_data,
+ epp->ep_daddr, epp->ep_vp, __LDPGSZ + execp->a_text,
+ VM_PROT_READ|VM_PROT_WRITE|VM_PROT_EXECUTE);
+
+ /* set up command for bss segment */
+ NEW_VMCMD(&epp->ep_vmcmds, vmcmd_map_zero, execp->a_bss,
+ epp->ep_daddr + execp->a_data, NULLVP, 0,
+ VM_PROT_READ|VM_PROT_WRITE|VM_PROT_EXECUTE);
+
+ return exec_aout_setup_stack(p, epp);
+
+}
diff --git a/sys/arch/arm26/arm26/autoconf.c b/sys/arch/arm26/arm26/autoconf.c
new file mode 100644
index 00000000000..8ab3a0008a5
--- /dev/null
+++ b/sys/arch/arm26/arm26/autoconf.c
@@ -0,0 +1,68 @@
+/* $NetBSD: autoconf.c,v 1.1 2000/05/09 21:55:55 bjh21 Exp $ */
+/*-
+ * Copyright (c) 1998, 1999 Ben Harris
+ * 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.
+ */
+/* This file is part of NetBSD/arm26 -- a port of NetBSD to ARM2/3 machines. */
+/*
+ * autoconf.c - top level device-finding code
+ */
+
+#include <sys/param.h>
+
+__RCSID("$NetBSD: autoconf.c,v 1.1 2000/05/09 21:55:55 bjh21 Exp $");
+
+#include <sys/conf.h>
+#include <sys/device.h>
+#include <sys/systm.h>
+
+#include <machine/irq.h>
+#include <machine/machdep.h>
+
+void
+cpu_configure()
+{
+
+ irq_init();
+ config_rootfound("cpu", NULL);
+ config_rootfound("iobus", NULL);
+ config_rootfound("arcvideo", NULL);
+ spl0();
+}
+
+void
+cpu_rootconf()
+{
+
+ /* XXX This could actually do something */
+ setroot(NULL, 0);
+}
+
+void
+cpu_dumpconf()
+{
+
+ printf("cpu_dumpconf: Doing something here would be useful\n");
+}
diff --git a/sys/arch/arm26/arm26/bus.c b/sys/arch/arm26/arm26/bus.c
new file mode 100644
index 00000000000..fff776014c6
--- /dev/null
+++ b/sys/arch/arm26/arm26/bus.c
@@ -0,0 +1,220 @@
+/* $NetBSD: bus.c,v 1.1 2000/05/09 21:55:55 bjh21 Exp $ */
+/*-
+ * Copyright (c) 1999, 2000 Ben Harris
+ * 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.
+ */
+/* This file is part of NetBSD/arm26 -- a port of NetBSD to ARM2/3 machines. */
+/*
+ * bus.c - bus space functions for Archimedes I/O bus
+ */
+
+#include <sys/param.h>
+
+__RCSID("$NetBSD: bus.c,v 1.1 2000/05/09 21:55:55 bjh21 Exp $");
+
+#include <machine/bus.h>
+#include <machine/memcreg.h>
+
+int
+bus_space_map(bus_space_tag_t bst, bus_addr_t addr, bus_size_t size,
+ int flags, bus_space_handle_t *bshp)
+{
+
+ if (flags & BUS_SPACE_MAP_LINEAR)
+ return -1;
+ *bshp = (bus_space_handle_t)(MEMC_IO_BASE + addr);
+ return 0;
+}
+
+int
+bus_space_subregion(bus_space_tag_t bst, bus_space_handle_t bsh,
+ bus_size_t offset, bus_size_t size,
+ bus_space_handle_t *nbshp)
+{
+
+ *nbshp = bsh + (offset << bst);
+ return 0;
+}
+
+int
+bus_space_shift(bus_space_tag_t bst, bus_space_handle_t bsh, int shift,
+ bus_space_tag_t *nbstp, bus_space_handle_t *nbshp)
+{
+
+ *nbstp = shift;
+ *nbshp = bsh;
+ return 0;
+}
+
+void
+bus_space_read_multi_1(bus_space_tag_t bst, bus_space_handle_t bsh,
+ bus_size_t offset, u_int8_t *datap, bus_size_t count)
+{
+ int i;
+
+ for (i = 0; i < count; i++)
+ datap[i] = bus_space_read_1(bst, bsh, offset);
+}
+
+void
+bus_space_read_multi_2(bus_space_tag_t bst, bus_space_handle_t bsh,
+ bus_size_t offset, u_int16_t *datap, bus_size_t count)
+{
+ int i;
+
+ for (i = 0; i < count; i++)
+ datap[i] = bus_space_read_2(bst, bsh, offset);
+}
+
+void
+bus_space_write_multi_1(bus_space_tag_t bst, bus_space_handle_t bsh,
+ bus_size_t offset, u_int8_t const *datap,
+ bus_size_t count)
+{
+ int i;
+
+ for (i = 0; i < count; i++)
+ bus_space_write_1(bst, bsh, offset, datap[i]);
+}
+
+void
+bus_space_write_multi_2(bus_space_tag_t bst, bus_space_handle_t bsh,
+ bus_size_t offset, u_int16_t const *datap,
+ bus_size_t count)
+{
+ int i;
+
+ for (i = 0; i < count; i++)
+ bus_space_write_2(bst, bsh, offset, datap[i]);
+}
+
+void
+bus_space_set_multi_1(bus_space_tag_t bst, bus_space_handle_t bsh,
+ bus_size_t offset, u_int8_t value, bus_size_t count)
+{
+ int i;
+
+ for (i = 0; i < count; i++)
+ bus_space_write_1(bst, bsh, offset, value);
+}
+
+void
+bus_space_set_multi_2(bus_space_tag_t bst, bus_space_handle_t bsh,
+ bus_size_t offset, u_int16_t value, bus_size_t count)
+{
+ int i;
+
+ for (i = 0; i < count; i++)
+ bus_space_write_2(bst, bsh, offset, value);
+}
+
+void
+bus_space_read_region_1(bus_space_tag_t bst, bus_space_handle_t bsh,
+ bus_size_t offset, u_int8_t *datap, bus_size_t count)
+{
+ int i;
+
+ for (i = 0; i < count; i++)
+ datap[i] = bus_space_read_1(bst, bsh, offset + i);
+}
+
+void
+bus_space_read_region_2(bus_space_tag_t bst, bus_space_handle_t bsh,
+ bus_size_t offset, u_int16_t *datap, bus_size_t count)
+{
+ int i;
+
+ for (i = 0; i < count; i++)
+ datap[i] = bus_space_read_2(bst, bsh, offset + i);
+}
+
+void
+bus_space_write_region_1(bus_space_tag_t bst, bus_space_handle_t bsh,
+ bus_size_t offset, u_int8_t const *datap,
+ bus_size_t count)
+{
+ int i;
+
+ for (i = 0; i < count; i++)
+ bus_space_write_1(bst, bsh, offset + i, datap[i]);
+}
+
+void
+bus_space_write_region_2(bus_space_tag_t bst, bus_space_handle_t bsh,
+ bus_size_t offset, u_int16_t const *datap,
+ bus_size_t count)
+{
+ int i;
+
+ for (i = 0; i < count; i++)
+ bus_space_write_2(bst, bsh, offset + i, datap[i]);
+}
+
+void
+bus_space_set_region_1(bus_space_tag_t bst, bus_space_handle_t bsh,
+ bus_size_t offset, u_int8_t value, bus_size_t count)
+{
+ int i;
+
+ for (i = 0; i < count; i++)
+ bus_space_write_1(bst, bsh, offset + i, value);
+}
+
+void
+bus_space_set_region_2(bus_space_tag_t bst, bus_space_handle_t bsh,
+ bus_size_t offset, u_int16_t value, bus_size_t count)
+{
+ int i;
+
+ for (i = 0; i < count; i++)
+ bus_space_write_2(bst, bsh, offset + i, value);
+}
+
+void
+bus_space_copy_1(bus_space_tag_t bst,
+ bus_space_handle_t bsh1, bus_size_t offset1,
+ bus_space_handle_t bsh2, bus_size_t offset2, bus_size_t count)
+{
+ int i;
+
+ for (i = 0; i < count; i++)
+ bus_space_write_1(bst, bsh2, offset2 + 1,
+ bus_space_read_1(bst, bsh1, offset1 + i));
+}
+
+void
+bus_space_copy_2(bus_space_tag_t bst,
+ bus_space_handle_t bsh1, bus_size_t offset1,
+ bus_space_handle_t bsh2, bus_size_t offset2, bus_size_t count)
+{
+ int i;
+
+ for (i = 0; i < count; i++)
+ bus_space_write_2(bst, bsh2, offset2 + 1,
+ bus_space_read_1(bst, bsh1, offset1 + i));
+}
+
+
+
diff --git a/sys/arch/arm26/arm26/conf.c b/sys/arch/arm26/arm26/conf.c
new file mode 100644
index 00000000000..269b054e9ec
--- /dev/null
+++ b/sys/arch/arm26/arm26/conf.c
@@ -0,0 +1,193 @@
+/* $NetBSD: conf.c,v 1.1 2000/05/09 21:55:55 bjh21 Exp $ */
+/*-
+ * Copyright (c) 1998, 2000 Ben Harris
+ * 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.
+ */
+/* This file is part of NetBSD/arm26 -- a port of NetBSD to ARM2/3 machines. */
+/*
+ * conf.c -- Device switch tables and related gumf.
+ */
+
+#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>
+#include <dev/cons.h>
+
+#define mmread mmrw
+#define mmwrite mmrw
+cdev_decl(mm);
+bdev_decl(sw);
+cdev_decl(sw);
+#include "pty.h"
+#include "md.h"
+#include "vnd.h"
+#include "ccd.h"
+#include "wd.h"
+bdev_decl(wd);
+cdev_decl(wd);
+#include "sd.h"
+#include "cd.h"
+#include "bpfilter.h"
+#include "tun.h"
+#include "ipfilter.h"
+#include "rnd.h"
+#include "rs.h"
+#include "wsdisplay.h"
+cdev_decl(wsdisplay);
+#include "wskbd.h"
+cdev_decl(wskbd);
+#include "wsmouse.h"
+cdev_decl(wsmouse);
+#include "wsmux.h"
+cdev_decl(wsmux);
+
+cons_decl(rs);
+
+struct bdevsw bdevsw[] = {
+ bdev_swap_init(1, sw), /* 0: swap pseudo-device */
+ bdev_disk_init(NMD, md), /* 1: memory "disk" */
+ bdev_disk_init(NVND, vnd), /* 2: vnode "disk" */
+ bdev_disk_init(NCCD, ccd), /* 3: concatenated disks */
+ bdev_disk_init(NWD, wd), /* 4: IDE disks */
+ bdev_disk_init(NSD, sd), /* 5: SCSI disks */
+ bdev_disk_init(NCD, cd), /* 6: SCSI CD-ROMs */
+};
+
+int nblkdev = sizeof(bdevsw) / sizeof(bdevsw[0]);
+
+struct cdevsw cdevsw[] = {
+ /* First seven are standard across most ports */
+ cdev_cn_init(1, cn), /* 0: /dev/console */
+ cdev_ctty_init(1, ctty), /* 1: /dev/tty */
+ cdev_mm_init(1, mm), /* 2: /dev/{null,mem,kmem,zero} */
+ cdev_swap_init(1, sw), /* 3: /dev/drum */
+ cdev_tty_init(NPTY, pts), /* 4: pseudo-tty slave */
+ cdev_ptc_init(NPTY, ptc), /* 5: pseudo-tty master */
+ cdev_log_init(1, log), /* 6: /dev/klog */
+ cdev_fd_init(1, filedesc), /* 7: file descriptors */
+
+ cdev_disk_init(NMD, md), /* 8: memory "disk" */
+ cdev_disk_init(NVND, vnd), /* 9: vnode "disk" */
+ cdev_disk_init(NCCD, ccd), /* 10: concatenated disks */
+ cdev_mouse_init(NWSKBD, wskbd), /* 11: keyboards */
+ cdev_mouse_init(NWSMOUSE, wsmouse),
+ /* 12: mice */
+ cdev_mouse_init(NWSMUX, wsmux), /* 13: keyboard/mouse multiplexor */
+ cdev_wsdisplay_init(NWSDISPLAY, wsdisplay),
+ /* 14: console display */
+ cdev_disk_init(NWD, wd), /* 15: IDE disks */
+ cdev_disk_init(NSD, sd), /* 16: SCSI disks */
+ cdev_disk_init(NCD, cd), /* 17: SCSI CD-ROMs */
+};
+
+int nchrdev = sizeof(cdevsw) / sizeof(cdevsw[0]);
+
+
+int mem_no = 2; /* major device number of memory special file */
+
+/*
+ * Swapdev is a fake device implemented
+ * in sw.c used only internally to get to swstrategy.
+ * It cannot be provided to the users, because the
+ * swstrategy routine munches the b_dev and b_blkno entries
+ * before calling the appropriate driver. This would horribly
+ * confuse, e.g. the hashing routines. Instead, /dev/drum is
+ * provided as a character (raw) device.
+ */
+dev_t swapdev = makedev(1, 0);
+
+/*
+ * Returns true if dev is /dev/mem or /dev/kmem.
+ */
+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 */ NODEV,
+ /* 2 */ NODEV,
+ /* 3 */ NODEV,
+ /* 4 */ NODEV,
+ /* 5 */ NODEV,
+ /* 6 */ NODEV,
+ /* 7 */ NODEV,
+ /* 8 */ 1, /* md */
+ /* 9 */ 2, /* vnd */
+ /* 10 */ 3, /* ccd */
+ /* 11 */ NODEV,
+ /* 12 */ NODEV,
+ /* 13 */ NODEV,
+ /* 14 */ NODEV,
+ /* 15 */ 4, /* wd */
+ /* 16 */ 5, /* sd */
+ /* 17 */ 6, /* cd */
+};
+
+/*
+ * 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)));
+}
+
+struct consdev constab[] = {
+#if NRS > 0
+ cons_init(rs),
+#endif
+ { 0 }
+};
diff --git a/sys/arch/arm26/arm26/cons_machdep.c b/sys/arch/arm26/arm26/cons_machdep.c
new file mode 100644
index 00000000000..91e285c2ff9
--- /dev/null
+++ b/sys/arch/arm26/arm26/cons_machdep.c
@@ -0,0 +1,71 @@
+/* $NetBSD: cons_machdep.c,v 1.1 2000/05/09 21:55:55 bjh21 Exp $ */
+/*-
+ * Copyright (c) 1998 Ben Harris
+ * 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.
+ */
+/* This file is part of NetBSD/arm26 -- a port of NetBSD to ARM2/3 machines. */
+/*
+ * cons_machdep.c -- machine dependent console routines
+ */
+
+#include <sys/param.h>
+
+__RCSID("$NetBSD: cons_machdep.c,v 1.1 2000/05/09 21:55:55 bjh21 Exp $");
+
+#include <sys/syslog.h>
+#include <sys/systm.h>
+
+#include <dev/cons.h>
+
+#include "arcvideo.h"
+#include "opt_ddb.h"
+
+#ifdef DDB
+#include <machine/db_machdep.h>
+#include <ddb/db_extern.h>
+#include <ddb/db_interface.h>
+
+#include <machine/boot.h>
+#include <machine/memcreg.h>
+#endif
+
+extern void arccons_init __P((void));
+
+void
+consinit()
+{
+
+#if NARCVIDEO > 0
+ arccons_init();
+#endif
+/* cninit();*/
+
+#ifdef DDB
+ db_machine_init();
+ ddb_init(bootconfig.esym - bootconfig.ssym,
+ MEMC_PHYS_BASE + bootconfig.ssym,
+ MEMC_PHYS_BASE + bootconfig.esym);
+#endif /* DDB */
+}
diff --git a/sys/arch/arm26/arm26/copyinout.S b/sys/arch/arm26/arm26/copyinout.S
new file mode 100644
index 00000000000..69b6154da37
--- /dev/null
+++ b/sys/arch/arm26/arm26/copyinout.S
@@ -0,0 +1,177 @@
+/* $NetBSD: copyinout.S,v 1.1 2000/05/09 21:55:55 bjh21 Exp $ */
+
+/*-
+ * Copyright (c) 2000 Ben Harris
+ * 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.
+ */
+/* This file is part of NetBSD/arm26 -- a port of NetBSD to ARM2/3 machines. */
+/*
+ * copyinout.S - copy data between user and kernel space
+ */
+
+#include <machine/asm.h>
+
+RCSID("$NetBSD: copyinout.S,v 1.1 2000/05/09 21:55:55 bjh21 Exp $")
+
+#include <sys/errno.h>
+#include "assym.h"
+
+/*
+ * Note that most of these need special handling on data aborts. I
+ * haven't coded that bit yet.
+ */
+
+/*
+ * int copyin(const void *ua, void *ka, size_t len);
+ * int copyout(const void *ka, void *ua, size_t len);
+ * int kcopy(const void *src, void *dst, size_t len);
+ */
+
+/*
+ * memcpy isn't currently data-abort-safe (it uses R14). This is much
+ * slower, but safer.
+ */
+
+ENTRY(copyin)
+ mov ip, sp
+ stmfd sp!, {r4, fp, ip, lr, pc}
+ sub fp, ip, #4
+ adr r3, Lcopyfault
+ ldr r4, Lcurproc
+ ldr r4, [r4]
+ ldr r4, [r4, #P_ADDR]
+ str r3, [r4, #(U_PCB + PCB_ONFAULT)]
+Lcopyinloop:
+ ldrbt r3, [r0], #1
+ strb r3, [r1], #1
+ subs r2, r2, #1
+ bne Lcopyinloop
+ mov r0, #0
+ str r0, [r4, #(U_PCB + PCB_ONFAULT)]
+ ldmdb fp, {r4, fp, sp, pc}^
+
+ENTRY(copyout)
+ mov ip, sp
+ stmfd sp!, {r4, fp, ip, lr, pc}
+ sub fp, ip, #4
+ adr r3, Lcopyfault
+ ldr r4, Lcurproc
+ ldr r4, [r4]
+ ldr r4, [r4, #P_ADDR]
+ str r3, [r4, #(U_PCB + PCB_ONFAULT)]
+Lcopyoutloop:
+ ldrb r3, [r0], #1
+ strbt r3, [r1], #1
+ subs r2, r2, #1
+ bne Lcopyoutloop
+ mov r0, #0
+ str r0, [r4, #(U_PCB + PCB_ONFAULT)]
+ ldmdb fp, {r4, fp, sp, pc}^
+
+ENTRY(kcopy)
+ mov ip, sp
+ stmfd sp!, {r4, fp, ip, lr, pc}
+ sub fp, ip, #4
+ adr r3, Lcopyfault
+ ldr r4, Lcurproc
+ ldr r4, [r4]
+ ldr r4, [r4, #P_ADDR]
+ str r3, [r4, #(U_PCB + PCB_ONFAULT)]
+Lkcopyloop:
+ ldrb r3, [r0], #1
+ strb r3, [r1], #1
+ subs r2, r2, #1
+ bne Lkcopyloop
+ mov r0, #0
+ str r0, [r4, #(U_PCB + PCB_ONFAULT)]
+ ldmdb fp, {r4, fp, sp, pc}^
+
+Lcopyfault:
+ mov r0, #0
+ str r0, [r4, #(U_PCB + PCB_ONFAULT)]
+ mov r0, #EFAULT
+ ldmdb fp, {r4, fp, sp, pc}^
+
+/* int fubyte(void *base); */
+ENTRY(fubyte)
+ mov ip, lr /* data-abort safety */
+ adr r1, Lfusufault
+ ldr r2, Lcurproc
+ ldr r2, [r2]
+ ldr r2, [r2, #P_ADDR]
+ str r1, [r2, #(U_PCB + PCB_ONFAULT)]
+ ldrbt r0, [r0]
+ mov r1, #0
+ str r1, [r2, #(U_PCB + PCB_ONFAULT)]
+ movs pc, ip
+
+/* int fuword(void *base); */
+ENTRY(fuword)
+ mov ip, lr
+ adr r1, Lfusufault
+ ldr r2, Lcurproc
+ ldr r2, [r2]
+ ldr r2, [r2, #P_ADDR]
+ str r1, [r2, #(U_PCB + PCB_ONFAULT)]
+ ldrt r0, [r0]
+ mov r1, #0
+ str r1, [r2, #(U_PCB + PCB_ONFAULT)]
+ movs pc, lr
+
+/* int subyte(void *base, int c); */
+ENTRY(subyte)
+ mov ip, lr
+ adr r3, Lfusufault
+ ldr r2, Lcurproc
+ ldr r2, [r2]
+ ldr r2, [r2, #P_ADDR]
+ str r3, [r2, #(U_PCB + PCB_ONFAULT)]
+ strbt r1, [r0]
+ mov r0, #0
+ str r0, [r2, #(U_PCB + PCB_ONFAULT)]
+ movs pc, ip
+
+/* int suword(void *base, long c); */
+ENTRY(suword)
+ mov ip, lr
+ adr r3, Lfusufault
+ ldr r2, Lcurproc
+ ldr r2, [r2]
+ ldr r2, [r2, #P_ADDR]
+ str r3, [r2, #(U_PCB + PCB_ONFAULT)]
+ strt r1, [r0]
+ mov r0, #0
+ str r0, [r2, #(U_PCB + PCB_ONFAULT)]
+ movs pc, ip
+
+Lfusufault:
+ mov r0, #0
+ str r0, [r2, #(U_PCB + PCB_ONFAULT)]
+ mvn r0, #0
+ movs pc, ip
+
+Lcurproc:
+ .word _C_LABEL(curproc)
+
diff --git a/sys/arch/arm26/arm26/copyinoutstr.c b/sys/arch/arm26/arm26/copyinoutstr.c
new file mode 100644
index 00000000000..370db98d670
--- /dev/null
+++ b/sys/arch/arm26/arm26/copyinoutstr.c
@@ -0,0 +1,108 @@
+/* $NetBSD: copyinoutstr.c,v 1.1 2000/05/09 21:55:55 bjh21 Exp $ */
+
+/*-
+ * Copyright (c) 2000 Ben Harris
+ * 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.
+ */
+/* This file is part of NetBSD/arm26 -- a port of NetBSD to ARM2/3 machines. */
+/*
+ * copyinoutstr.c -- copy strings with sanity checking
+ */
+
+#include <sys/param.h>
+
+__RCSID("$NetBSD: copyinoutstr.c,v 1.1 2000/05/09 21:55:55 bjh21 Exp $");
+
+#include <sys/proc.h>
+#include <sys/systm.h>
+#include <sys/user.h>
+#include <machine/pcb.h>
+#include <vm/vm_param.h>
+
+/*
+ * FIXME: These are bogus. They should use LDRT and friends for user
+ * accesses.
+ */
+
+int copyinstr(const void *uaddr, void *kaddr, size_t len, size_t *done)
+{
+ int err;
+
+ /* Check if this is an easy case */
+ if (uaddr < (void *)VM_MIN_ADDRESS ||
+ uaddr >= (void *)VM_MAXUSER_ADDRESS)
+ return EFAULT;
+ if (uaddr + len < (void *)VM_MAXUSER_ADDRESS)
+ return copystr(uaddr, kaddr, len, done);
+ err = copystr(uaddr, kaddr, (void *)VM_MAXUSER_ADDRESS - uaddr, done);
+ if (err == ENAMETOOLONG)
+ return EFAULT;
+ return err;
+}
+
+int copyoutstr(const void *kaddr, void *uaddr, size_t len, size_t *done)
+{
+ int err;
+
+ /* Check if this is an easy case */
+ if (uaddr < (void *)VM_MIN_ADDRESS ||
+ uaddr > (void *)VM_MAXUSER_ADDRESS)
+ return EFAULT;
+ if (uaddr + len < (void *)VM_MAXUSER_ADDRESS)
+ return copystr(kaddr, uaddr, len, done);
+ err = copystr(kaddr, uaddr, (void *)VM_MAXUSER_ADDRESS - uaddr, done);
+ if (err == ENAMETOOLONG)
+ return EFAULT;
+ return err;
+}
+
+int copystr(const void *src, void *dest, size_t len, size_t *done)
+{
+ label_t here;
+ size_t count;
+ int c;
+ char const *s;
+ char *d;
+
+ if (setjmp(&here) == 0) {
+ s = src; d = dest;
+ curproc->p_addr->u_pcb.pcb_onfault = &here;
+ c = -1;
+ *done = count = 0;
+ while (count < len) {
+ c = d[count] = s[count];
+ *done = ++count;
+ if (c == 0)
+ break;
+ }
+ curproc->p_addr->u_pcb.pcb_onfault = NULL;
+ if (c == 0)
+ return 0;
+ return ENAMETOOLONG;
+ } else {
+ curproc->p_addr->u_pcb.pcb_onfault = NULL;
+ return EFAULT;
+ }
+}
diff --git a/sys/arch/arm26/arm26/cpu.c b/sys/arch/arm26/arm26/cpu.c
new file mode 100644
index 00000000000..a2db2bafd2c
--- /dev/null
+++ b/sys/arch/arm26/arm26/cpu.c
@@ -0,0 +1,206 @@
+/* $NetBSD: cpu.c,v 1.1 2000/05/09 21:55:55 bjh21 Exp $ */
+
+/*-
+ * Copyright (c) 2000 Ben Harris
+ * 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.
+ */
+/* This file is part of NetBSD/arm26 -- a port of NetBSD to ARM2/3 machines. */
+/*
+ * cpu.c - high-level CPU detection etc
+ */
+
+#include <sys/param.h>
+
+__KERNEL_RCSID(0, "$NetBSD: cpu.c,v 1.1 2000/05/09 21:55:55 bjh21 Exp $");
+
+#include <sys/device.h>
+#include <sys/proc.h>
+#include <sys/systm.h>
+#include <sys/time.h>
+#include <sys/user.h>
+#include <machine/armreg.h>
+#include <machine/machdep.h>
+#include <machine/pcb.h>
+
+#include <arch/arm26/arm26/cpuvar.h>
+
+#include "opt_cputypes.h"
+
+static int cpu_match(struct device *, struct cfdata *, void *);
+static void cpu_attach(struct device *, struct device *, void *);
+static register_t cpu_identify(void);
+#ifdef CPU_ARM3
+static void cpu_arm3_setup(struct device *);
+#endif
+static void cpu_delay_calibrate(struct device *);
+
+register_t cpu_type;
+
+struct cpu_softc {
+ struct device sc_dev;
+};
+
+struct cfattach cpu_ca = {
+ sizeof(struct cpu_softc), cpu_match, cpu_attach
+};
+
+static int
+cpu_match(struct device *parent, struct cfdata *cf, void *aux)
+{
+
+ if (cf->cf_unit == 0)
+ return 1;
+ return 0;
+}
+
+static void
+cpu_attach(struct device *parent, struct device *self, void *aux)
+{
+ int supported;
+
+ printf(": ");
+ cpu_type = cpu_identify();
+ supported = 0;
+ switch (cpu_type & CPU_ID_CPU_MASK) {
+ case CPU_ID_ARM2:
+ printf("ARM2");
+#ifdef CPU_ARM2
+ supported = 1;
+#endif
+ break;
+ case CPU_ID_ARM250:
+ printf("ARM250");
+#ifdef CPU_ARM250
+ supported = 1;
+#endif
+ break;
+ case CPU_ID_ARM3:
+ printf("ARM3 (rev. %d)", cpu_type & CPU_ID_REVISION_MASK);
+#ifdef CPU_ARM3
+ supported = 1;
+ cpu_arm3_setup(self);
+#endif
+ break;
+ default:
+ printf("Unknown type, ID=0x%08x", cpu_type);
+ break;
+ }
+ printf("\n");
+ if (!supported)
+ printf("%s: WARNING: CPU type not supported by kernel\n",
+ self->dv_xname);
+ config_interrupts(self, cpu_delay_calibrate);
+}
+
+static register_t
+cpu_identify()
+{
+ label_t here;
+ register_t dummy;
+ volatile register_t id;
+
+ if (setjmp(&here) == 0) {
+ curproc->p_addr->u_pcb.pcb_onundef_lj = &here;
+ id = CPU_ID_ARM2;
+ /* ARM250 and ARM3 support SWP. */
+ asm volatile ("swp r0, r0, [%0]" : : "r" (&dummy) : "r0");
+ id = CPU_ID_ARM250;
+ /* ARM3 has an internal coprocessor 15 with an ID register. */
+ asm volatile ("mrc 15, 0, %0, cr0, cr0" : "=r" (id));
+ }
+ curproc->p_addr->u_pcb.pcb_onundef_lj = NULL;
+ return id;
+}
+
+#ifdef CPU_ARM3
+
+#define ARM3_READ(reg, var) \
+ asm ("mrc 15, 0, %0, cr" __STRING(reg) ", cr0" : "=r" (var))
+#define ARM3_WRITE(reg, val) \
+ asm ("mcr 15, 0, %0, cr" __STRING(reg) ", cr0" : : "r" (val))
+
+static void
+cpu_arm3_setup(struct device *self)
+{
+ int oldctl;
+
+ /*
+ * We decide whether to enable the cache based on its current
+ * state. This is very dodgy, since the bootloader really
+ * _should_ disable it for us, but currently BBBB doesn't. In
+ * future, this should probably be a flag in the cpu
+ * attachment.
+ */
+ ARM3_READ(ARM3_CP15_CONTROL, oldctl);
+ if (oldctl & ARM3_CTL_CACHE_ON) {
+ /* Disable the cache while we set things up. */
+ ARM3_WRITE(ARM3_CP15_CONTROL, ARM3_CTL_SHARED);
+ /* All RAM and ROM is cacheable. */
+ ARM3_WRITE(ARM3_CP15_CACHEABLE, 0xfcffffff);
+ /* All RAM is updateable. */
+ ARM3_WRITE(ARM3_CP15_UPDATEABLE, 0x00ffffff);
+ /* Nothing is disruptive. We'll do cache flushing manually. */
+ ARM3_WRITE(ARM3_CP15_DISRUPTIVE, 0x00000000);
+ /* Flush the cache and turn it on. */
+ ARM3_WRITE(ARM3_CP15_FLUSH, 0);
+ ARM3_WRITE(ARM3_CP15_CONTROL,
+ ARM3_CTL_CACHE_ON | ARM3_CTL_SHARED);
+ printf(", cache enabled");
+ cpu_delay_factor = 8;
+ } else {
+ ARM3_WRITE(ARM3_CP15_CONTROL, ARM3_CTL_SHARED);
+ printf(", cache disabled");
+ }
+}
+#endif
+
+/* XXX This should be inlined. */
+void
+cpu_cache_flush(void)
+{
+
+#ifdef CPU_ARM3
+#if defined(CPU_ARM2) || defined(CPU_ARM250)
+ if ((cpu_type & CPU_ID_CPU_MASK) == CPU_ID_ARM3)
+#endif
+ ARM3_WRITE(ARM3_CP15_FLUSH, 0);
+#endif
+}
+
+int cpu_delay_factor = 1;
+
+static void
+cpu_delay_calibrate(struct device *self)
+{
+ struct timeval start, end, diff;
+
+ microtime(&start);
+ cpu_delayloop(10000);
+ microtime(&end);
+ timersub(&end, &start, &diff);
+ cpu_delay_factor = 10000 / diff.tv_usec + 1;
+ printf("%s: 10000 loops in %ld microseconds, delay factor = %d\n",
+ self->dv_xname, diff.tv_usec, cpu_delay_factor);
+}
diff --git a/sys/arch/arm26/arm26/cpuvar.h b/sys/arch/arm26/arm26/cpuvar.h
new file mode 100644
index 00000000000..96381a9b278
--- /dev/null
+++ b/sys/arch/arm26/arm26/cpuvar.h
@@ -0,0 +1,42 @@
+/* $NetBSD: cpuvar.h,v 1.1 2000/05/09 21:55:55 bjh21 Exp $ */
+/*-
+ * Copyright (c) 2000 Ben Harris
+ * 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.
+ */
+/* This file is part of NetBSD/arm26 -- a port of NetBSD to ARM2/3 machines. */
+
+#ifndef _ARM26_CPUVAR_H_
+#define _ARM26_CPUVAR_H_
+
+extern register_t cpu_type;
+extern int cpu_delay_factor;
+
+/* Fixed code sequence for reliability */
+#define cpu_delayloop(loops) \
+ asm volatile ("1:subs %0, %0, #1; bne 1b" : : "r" (loops) : "cc")
+
+extern void cpu_cache_flush(void);
+
+#endif
diff --git a/sys/arch/arm26/arm26/db_disasm.c b/sys/arch/arm26/arm26/db_disasm.c
new file mode 100644
index 00000000000..136cb6e4aa2
--- /dev/null
+++ b/sys/arch/arm26/arm26/db_disasm.c
@@ -0,0 +1,75 @@
+/* $NetBSD: db_disasm.c,v 1.1 2000/05/09 21:55:55 bjh21 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.
+ */
+
+#include <sys/param.h>
+#include <machine/db_machdep.h>
+#include <ddb/db_sym.h>
+#include <ddb/db_output.h>
+#include <ddb/db_access.h>
+
+#include <arm32/arm32/disassem.h>
+
+/* Glue code to interface db_disasm to the generic ARM disassembler */
+
+static u_int db_disasm_read_word(u_int);
+static void db_disasm_printaddr(u_int);
+
+static disasm_interface_t db_disasm_interface = {
+ db_disasm_read_word, db_disasm_printaddr, db_printf
+};
+
+static u_int
+db_disasm_read_word(u_int address)
+{
+
+ return db_get_value(address, 4, 0);
+}
+
+static void
+db_disasm_printaddr(u_int address)
+{
+
+ db_printsym((db_addr_t)address, DB_STGY_ANY);
+}
+
+vm_offset_t
+db_disasm(vm_offset_t loc, boolean_t altfmt)
+{
+
+ return disasm(&db_disasm_interface, loc, altfmt);
+}
+
+/* End of db_disasm.c */
diff --git a/sys/arch/arm26/arm26/db_interface.c b/sys/arch/arm26/arm26/db_interface.c
new file mode 100644
index 00000000000..5fa8bd94ad5
--- /dev/null
+++ b/sys/arch/arm26/arm26/db_interface.c
@@ -0,0 +1,345 @@
+/* $NetBSD: db_interface.c,v 1.1 2000/05/09 21:55:55 bjh21 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 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 "opt_ddb.h"
+
+#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 <ddb/db_access.h>
+#include <ddb/db_command.h>
+#include <ddb/db_output.h>
+#include <ddb/db_interface.h>
+#include <ddb/db_variables.h>
+#include <ddb/db_sym.h>
+#include <ddb/db_extern.h>
+#include <dev/cons.h>
+
+static int nil;
+
+int db_access_und_sp __P((struct db_variable *, db_expr_t *, int));
+int db_access_abt_sp __P((struct db_variable *, db_expr_t *, int));
+int db_access_irq_sp __P((struct db_variable *, db_expr_t *, int));
+u_int db_fetch_reg __P((int, db_regs_t *));
+
+static int db_validate_address __P((vm_offset_t));
+static void db_write_text __P((unsigned char *, int ch));
+
+struct db_variable db_regs[] = {
+ { "r0", (long *)&DDB_TF->tf_r0, FCN_NULL },
+ { "r1", (long *)&DDB_TF->tf_r1, FCN_NULL },
+ { "r2", (long *)&DDB_TF->tf_r2, FCN_NULL },
+ { "r3", (long *)&DDB_TF->tf_r3, FCN_NULL },
+ { "r4", (long *)&DDB_TF->tf_r4, FCN_NULL },
+ { "r5", (long *)&DDB_TF->tf_r5, FCN_NULL },
+ { "r6", (long *)&DDB_TF->tf_r6, FCN_NULL },
+ { "r7", (long *)&DDB_TF->tf_r7, FCN_NULL },
+ { "r8", (long *)&DDB_TF->tf_r8, FCN_NULL },
+ { "r9", (long *)&DDB_TF->tf_r9, FCN_NULL },
+ { "r10", (long *)&DDB_TF->tf_r10, FCN_NULL },
+ { "r11", (long *)&DDB_TF->tf_r11, FCN_NULL },
+ { "r12", (long *)&DDB_TF->tf_r12, FCN_NULL },
+ { "r13", (long *)&DDB_TF->tf_r13, FCN_NULL },
+ { "r14", (long *)&DDB_TF->tf_r14, FCN_NULL },
+ { "r15", (long *)&DDB_TF->tf_r15, 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;
+
+/*
+ * kdb_trap - field a TRACE or BPT trap
+ */
+int
+kdb_trap(type, regs)
+ int type;
+ db_regs_t *regs;
+{
+ int s;
+
+ switch (type) {
+ case T_BREAKPOINT: /* breakpoint */
+ case -1: /* keyboard interrupt */
+ break;
+ default:
+ if (db_recover != 0) {
+ db_error("Faulted in DDB; continuing...\n");
+ /*NOTREACHED*/
+ }
+ }
+
+ /* Should switch to kdb`s own stack here. */
+
+ ddb_regs = *regs;
+
+ s = splhigh();
+ db_active++;
+ cnpollc(TRUE);
+ db_trap(type, 0/*code*/);
+ cnpollc(FALSE);
+ db_active--;
+ splx(s);
+
+ *regs = ddb_regs;
+
+ return 1;
+}
+
+static int
+db_validate_address(addr)
+ vm_offset_t addr;
+{
+
+ /* FIXME */
+ return 0;
+}
+
+/*
+ * Read bytes from kernel address space for debugger.
+ */
+void
+db_read_bytes(addr, size, data)
+ vm_offset_t addr;
+ size_t size;
+ char *data;
+{
+ char *src;
+
+ src = (char *)addr;
+ for (; size > 0; size--) {
+ if (db_validate_address((u_int)src)) {
+ db_printf("address %p is invalid\n", src);
+ return;
+ }
+ *data++ = *src++;
+ }
+}
+
+static void
+db_write_text(dst, ch)
+ unsigned char *dst;
+ int ch;
+{
+
+ if (db_validate_address((u_int)dst)) {
+ db_printf(" address %p not a valid page\n", dst);
+ return;
+ }
+
+ *dst = (unsigned char)ch;
+}
+
+/*
+ * Write bytes to kernel address space for debugger.
+ */
+void
+db_write_bytes(addr, size, data)
+ vm_offset_t addr;
+ size_t size;
+ char *data;
+{
+#if 0
+ extern char _stext_[], _etext[];
+#endif
+ char *dst;
+ int loop;
+
+ dst = (char *)addr;
+ loop = size;
+ while (--loop >= 0) {
+#if 0 /* FIXME */
+ if ((dst >= _stext_) && (dst < _etext))
+#endif
+ db_write_text(dst, *data);
+#if 0
+ else {
+ if (db_validate_address((u_int)dst)) {
+ db_printf("address %p is invalid\n", dst);
+ return;
+ }
+ *dst = *data;
+ }
+#endif
+ dst++, data++;
+ }
+}
+
+void db_show_vmstat_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));
+void db_show_intrchain_cmd __P((db_expr_t addr, int have_addr, db_expr_t count, char *modif));
+void db_show_panic_cmd __P((db_expr_t addr, int have_addr, db_expr_t count, char *modif));
+void db_show_frame_cmd __P((db_expr_t addr, int have_addr, db_expr_t count, char *modif));
+
+struct db_command arm26_db_command_table[] = {
+ { "frame", db_show_frame_cmd, 0, NULL },
+#if 0
+ { "intrchain", db_show_intrchain_cmd, 0, NULL },
+#endif
+ { "panic", db_show_panic_cmd, 0, NULL },
+ { "vmstat", db_show_vmstat_cmd, 0, NULL },
+ { "vnode", db_show_vnode_cmd, 0, NULL },
+ { NULL, NULL, 0, NULL }
+};
+
+int
+db_trapper(addr, inst, frame, fault_code)
+ u_int addr;
+ u_int inst;
+ trapframe_t *frame;
+ int fault_code;
+{
+ if (fault_code == 0) {
+ if ((inst & ~0xf0000000) == (BKPT_INST & ~0xf0000000))
+ kdb_trap(T_BREAKPOINT, frame);
+ else
+ kdb_trap(-1, frame);
+ } else
+ return 1;
+ return 0;
+}
+
+extern u_int esym;
+extern u_int end;
+
+void
+db_machine_init()
+{
+
+ db_machine_commands_install(arm26_db_command_table);
+}
+
+u_int
+db_fetch_reg(reg, db_regs)
+ int reg;
+ db_regs_t *db_regs;
+{
+
+ switch (reg) {
+ case 0:
+ return (db_regs->ddb_tf.tf_r0);
+ case 1:
+ return (db_regs->ddb_tf.tf_r1);
+ case 2:
+ return (db_regs->ddb_tf.tf_r2);
+ case 3:
+ return (db_regs->ddb_tf.tf_r3);
+ case 4:
+ return (db_regs->ddb_tf.tf_r4);
+ case 5:
+ return (db_regs->ddb_tf.tf_r5);
+ case 6:
+ return (db_regs->ddb_tf.tf_r6);
+ case 7:
+ return (db_regs->ddb_tf.tf_r7);
+ case 8:
+ return (db_regs->ddb_tf.tf_r8);
+ case 9:
+ return (db_regs->ddb_tf.tf_r9);
+ case 10:
+ return (db_regs->ddb_tf.tf_r10);
+ case 11:
+ return (db_regs->ddb_tf.tf_r11);
+ case 12:
+ return (db_regs->ddb_tf.tf_r12);
+ case 13:
+ return (db_regs->ddb_tf.tf_r13);
+ case 14:
+ return (db_regs->ddb_tf.tf_r14);
+ case 15:
+ return (db_regs->ddb_tf.tf_r15);
+ default:
+ panic("db_fetch_reg: botch");
+ }
+}
+
+u_int
+branch_taken(insn, pc, db_regs)
+ u_int insn;
+ u_int pc;
+ db_regs_t *db_regs;
+{
+ u_int addr, nregs;
+
+ switch ((insn >> 24) & 0xf) {
+ case 0xa: /* b ... */
+ case 0xb: /* bl ... */
+ addr = ((insn << 2) & 0x03ffffff);
+ if (addr & 0x02000000)
+ addr |= 0xfc000000;
+ return (pc + 8 + addr);
+ case 0x7: /* ldr pc, [pc, reg, lsl #2] */
+ addr = db_fetch_reg(insn & 0xf, db_regs);
+ addr = pc + 8 + (addr << 2);
+ db_read_bytes(addr, 4, (char *)&addr);
+ return (addr);
+ case 0x1: /* mov pc, reg */
+ addr = db_fetch_reg(insn & 0xf, db_regs);
+ return (addr);
+ case 0x8: /* ldmxx reg, {..., pc} */
+ case 0x9:
+ addr = db_fetch_reg((insn >> 16) & 0xf, db_regs);
+ nregs = (insn & 0x5555) + ((insn >> 1) & 0x5555);
+ nregs = (nregs & 0x3333) + ((nregs >> 2) & 0x3333);
+ nregs = (nregs + (nregs >> 4)) & 0x0f0f;
+ nregs = (nregs + (nregs >> 8)) & 0x001f;
+ switch ((insn >> 23) & 0x3) {
+ case 0x0: /* ldmda */
+ addr = addr - 0;
+ break;
+ case 0x1: /* ldmia */
+ addr = addr + 0 + ((nregs - 1) << 2);
+ break;
+ case 0x2: /* ldmdb */
+ addr = addr - 4;
+ break;
+ case 0x3: /* ldmib */
+ addr = addr + 4 + ((nregs - 1) << 2);
+ break;
+ }
+ db_read_bytes(addr, 4, (char *)&addr);
+ return (addr);
+ default:
+ panic("branch_taken: botch");
+ }
+}
diff --git a/sys/arch/arm26/arm26/db_machdep.c b/sys/arch/arm26/arm26/db_machdep.c
new file mode 100644
index 00000000000..b9c90b40983
--- /dev/null
+++ b/sys/arch/arm26/arm26/db_machdep.c
@@ -0,0 +1,227 @@
+/* $NetBSD: db_machdep.c,v 1.1 2000/05/09 21:55:55 bjh21 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 "AS IS"
+ * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
+ * School of Computer Science
+ * Carnegie Mellon University
+ * Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie the
+ * rights to redistribute these changes.
+ */
+
+#include <sys/param.h>
+#include <sys/proc.h>
+#include <sys/vnode.h>
+#include <sys/systm.h>
+
+#include <machine/db_machdep.h>
+
+#include <ddb/db_access.h>
+#include <ddb/db_sym.h>
+#include <ddb/db_output.h>
+
+/*
+ * 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 %ld, writecount %ld, refcount %ld,",
+ 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", (u_int)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;
+{
+
+ db_printf("Current UVM status:\n");
+ db_printf(" pagesize=%d (0x%x), pagemask=0x%x, pageshift=%d\n",
+ uvmexp.pagesize, uvmexp.pagesize, uvmexp.pagemask,
+ uvmexp.pageshift);
+ db_printf(" %d VM pages: %d active, %d inactive, %d wired, %d free\n",
+ uvmexp.npages, uvmexp.active, uvmexp.inactive, uvmexp.wired,
+ uvmexp.free);
+ db_printf(" freemin=%d, free-target=%d, inactive-target=%d, "
+ "wired-max=%d\n", uvmexp.freemin, uvmexp.freetarg, uvmexp.inactarg,
+ uvmexp.wiredmax);
+ db_printf(" faults=%d, traps=%d, intrs=%d, ctxswitch=%d\n",
+ uvmexp.faults, uvmexp.traps, uvmexp.intrs, uvmexp.swtch);
+ db_printf(" softint=%d, syscalls=%d, swapins=%d, swapouts=%d\n",
+ uvmexp.softs, uvmexp.syscalls, uvmexp.swapins, uvmexp.swapouts);
+
+ db_printf(" fault counts:\n");
+ db_printf(" noram=%d, noanon=%d, pgwait=%d, pgrele=%d\n",
+ uvmexp.fltnoram, uvmexp.fltnoanon, uvmexp.fltpgwait,
+ uvmexp.fltpgrele);
+ db_printf(" ok relocks(total)=%d(%d), anget(retrys)=%d(%d), "
+ "amapcopy=%d\n", uvmexp.fltrelckok, uvmexp.fltrelck,
+ uvmexp.fltanget, uvmexp.fltanretry, uvmexp.fltamcopy);
+ db_printf(" neighbor anon/obj pg=%d/%d, gets(lock/unlock)=%d/%d\n",
+ uvmexp.fltnamap, uvmexp.fltnomap, uvmexp.fltlget, uvmexp.fltget);
+ db_printf(" cases: anon=%d, anoncow=%d, obj=%d, prcopy=%d, przero=%d\n",
+ uvmexp.flt_anon, uvmexp.flt_acow, uvmexp.flt_obj, uvmexp.flt_prcopy,
+ uvmexp.flt_przero);
+
+ db_printf(" daemon and swap counts:\n");
+ db_printf(" woke=%d, revs=%d, scans=%d, swout=%d\n", uvmexp.pdwoke,
+ uvmexp.pdrevs, uvmexp.pdscans, uvmexp.pdswout);
+ db_printf(" busy=%d, freed=%d, reactivate=%d, deactivate=%d\n",
+ uvmexp.pdbusy, uvmexp.pdfreed, uvmexp.pdreact, uvmexp.pddeact);
+ db_printf(" pageouts=%d, pending=%d, nswget=%d\n", uvmexp.pdpageouts,
+ uvmexp.pdpending, uvmexp.nswget);
+ db_printf(" nswapdev=%d, nanon=%d, nfreeanon=%d\n", uvmexp.nswapdev,
+ uvmexp.nanon, uvmexp.nfreeanon);
+
+ db_printf(" kernel pointers:\n");
+ db_printf(" objs(kmem/mb)=%p/%p\n", uvmexp.kmem_object,
+ uvmexp.mb_object);
+}
+
+#if 0
+void
+db_show_intrchain_cmd(addr, have_addr, count, modif)
+ db_expr_t addr;
+ int have_addr;
+ db_expr_t count;
+ char *modif;
+{
+ int loop;
+ irqhandler_t *ptr;
+ char *name;
+ db_expr_t offset;
+
+ for (loop = 0; loop < NIRQS; ++loop) {
+ ptr = irqhandlers[loop];
+ if (ptr) {
+ db_printf("IRQ %d\n", loop);
+
+ while (ptr) {
+ db_printf(" %-13s %d ", ptr->ih_name, ptr->ih_level);
+ db_find_sym_and_offset((u_int)ptr->ih_func, &name, &offset);
+ if (name == NULL)
+ name = "?";
+
+ db_printf("%s(", name);
+ db_printsym((u_int)ptr->ih_func, DB_STGY_PROC);
+ db_printf(") %08x\n", (u_int)ptr->ih_arg);
+ ptr = ptr->ih_next;
+ }
+ }
+ }
+}
+#endif
+
+void
+db_show_panic_cmd(addr, have_addr, count, modif)
+ db_expr_t addr;
+ int have_addr;
+ db_expr_t count;
+ char *modif;
+{
+ int s;
+
+ s = splhigh();
+
+ db_printf("Panic string: %s\n", panicstr);
+
+ (void)splx(s);
+}
+
+
+void
+db_show_frame_cmd(addr, have_addr, count, modif)
+ db_expr_t addr;
+ int have_addr;
+ db_expr_t count;
+ char *modif;
+{
+ struct trapframe *frame;
+
+ if (!have_addr) {
+ db_printf("frame address must be specified\n");
+ return;
+ }
+
+ frame = (struct trapframe *)addr;
+
+ db_printf("frame address = %08x ", (u_int)frame);
+ db_printf("r0 =%08x r1 =%08x r2 =%08x r3 =%08x\n",
+ frame->tf_r0, frame->tf_r1, frame->tf_r2, frame->tf_r3);
+ db_printf("r4 =%08x r5 =%08x r6 =%08x r7 =%08x\n",
+ frame->tf_r4, frame->tf_r5, frame->tf_r6, frame->tf_r7);
+ db_printf("r8 =%08x r9 =%08x r10=%08x r11=%08x\n",
+ frame->tf_r8, frame->tf_r9, frame->tf_r10, frame->tf_r11);
+ db_printf("r12=%08x r13=%08x r14=%08x r15=%08x\n",
+ frame->tf_r12, frame->tf_r13, frame->tf_r14, frame->tf_r15);
+}
diff --git a/sys/arch/arm26/arm26/db_trace.c b/sys/arch/arm26/arm26/db_trace.c
new file mode 100644
index 00000000000..1c31804dfb0
--- /dev/null
+++ b/sys/arch/arm26/arm26/db_trace.c
@@ -0,0 +1,150 @@
+/* $NetBSD: db_trace.c,v 1.1 2000/05/09 21:55:56 bjh21 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 the
+ * rights to redistribute these changes.
+ */
+
+#include <sys/param.h>
+#include <sys/proc.h>
+#include <sys/user.h>
+#include <machine/armreg.h>
+#include <machine/db_machdep.h>
+
+#include <ddb/db_access.h>
+#include <ddb/db_interface.h>
+#include <ddb/db_sym.h>
+#include <ddb/db_output.h>
+
+#define INKERNEL(va) (((vm_offset_t)(va)) >= VM_MIN_KERNEL_ADDRESS)
+
+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, *lastframe;
+ char c, *cp = modif;
+ boolean_t kernel_only = TRUE;
+ boolean_t trace_thread = FALSE;
+
+ while ((c = *cp++) != 0) {
+ if (c == 'u')
+ kernel_only = FALSE;
+ if (c == 't')
+ trace_thread = TRUE;
+ }
+
+ 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 {
+ if (trace_thread) {
+ struct proc *p;
+ struct user *u;
+ db_printf ("trace: pid %d ", (int)addr);
+ p = pfind(addr);
+ if (p == NULL) {
+ db_printf("not found\n");
+ return;
+ }
+ if (!(p->p_flag & P_INMEM)) {
+ db_printf("swapped out\n");
+ return;
+ }
+ u = p->p_addr;
+ frame = (struct frame *) (u->u_pcb.pcb_sf->sf_r11
+ - (sizeof(struct frame) - sizeof(u_int)));
+ db_printf("at %p\n", frame);
+ } else
+ frame = (struct frame *)(addr - (sizeof(struct frame)
+ - sizeof(u_int)));
+ }
+ lastframe = NULL;
+
+ while (count--) {
+ db_expr_t offset;
+ 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_r15);*/
+
+ pc = frame->fr_r15 & R15_PC;
+ if (!INKERNEL(pc))
+ break;
+
+ db_find_sym_and_offset(pc, &name, &offset);
+ if (name == NULL)
+ name = "?";
+
+ db_printf("%s(", name);
+ db_printsym(pc, DB_STGY_PROC);
+ db_printf(")");
+ db_printf("\n");
+
+ /*
+ * Switch to next frame up
+ */
+ if (frame->fr_fp == 0)
+ break; /* Top of stack */
+
+ lastframe = frame;
+ frame = (struct frame *)(frame->fr_fp - (sizeof(struct frame)
+ - sizeof(u_int)));
+
+ if (INKERNEL((int)frame)) {
+ /* staying in kernel */
+ if (frame <= lastframe) {
+ db_printf("Bad frame pointer: %p\n", frame);
+ break;
+ }
+ } else if (INKERNEL((int)lastframe)) {
+ /* switch from user to kernel */
+ if (kernel_only)
+ break; /* kernel stack only */
+ } else {
+ /* in user */
+ if (frame <= lastframe) {
+ db_printf("Bad user frame pointer: %p\n",
+ frame);
+ break;
+ }
+ }
+ }
+}
diff --git a/sys/arch/arm26/arm26/disksubr.c b/sys/arch/arm26/arm26/disksubr.c
new file mode 100644
index 00000000000..befc2509295
--- /dev/null
+++ b/sys/arch/arm26/arm26/disksubr.c
@@ -0,0 +1,447 @@
+/* $NetBSD: disksubr.c,v 1.1 2000/05/09 21:55:56 bjh21 Exp $ */
+
+/*
+ * Copyright (c) 1998 Christopher G. Demetriou. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Christopher G. Demetriou
+ * 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.
+ */
+
+/*
+ * 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>
+
+/*
+ * 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) __P((struct buf *));
+ struct disklabel *lp;
+ struct cpu_disklabel *osdep;
+{
+ struct buf *bp;
+ struct disklabel *dlp;
+ char *msg = NULL;
+ int cyl, netbsdpartoff, 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 netbsd partitions in the process of getting disklabel? */
+
+ netbsdpartoff = 0;
+ cyl = LABELSECTOR / lp->d_secpercyl;
+
+ if (osdep) {
+ if (filecore_label_read(dev, strat,lp, osdep, &msg, &cyl,
+ &netbsdpartoff) ||
+ mbr_label_read(dev, strat, lp, osdep, &msg, &cyl,
+ &netbsdpartoff)) {
+ if (msg != NULL)
+ goto done;
+ } else {
+ /*
+ * We didn't find anything we like; NetBSD native.
+ * netbsdpartoff and cyl should be unchanged.
+ */
+ KASSERT(netbsdpartoff == 0);
+ KASSERT(cyl == (LABELSECTOR / lp->d_secpercyl));
+ }
+ }
+
+ /* next, dig out disk label */
+
+/* printf("Reading disklabel addr=%08x\n", netbsdpartoff * DEV_BSIZE);*/
+
+ bp->b_blkno = netbsdpartoff + LABELSECTOR;
+ bp->b_cylinder = 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 (osdep && (lp->d_flags & D_BADSECT)) {
+ struct dkbad *bdp = &osdep->bad;
+ 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_cylinder = 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;
+{
+ int i;
+ 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 acorn/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) __P((struct buf *));
+ struct disklabel *lp;
+ struct cpu_disklabel *osdep;
+{
+ struct buf *bp;
+ struct disklabel *dlp;
+ int cyl, netbsdpartoff;
+ int error = 0, rv;
+
+ /* get a buffer and initialize it */
+
+ bp = geteblk((int)lp->d_secsize);
+ bp->b_dev = dev;
+
+ /* do netbsd partitions in the process of getting disklabel? */
+
+ netbsdpartoff = 0;
+ cyl = LABELSECTOR / lp->d_secpercyl;
+
+ if (osdep) {
+ if ((rv = filecore_label_locate(dev, strat,lp, osdep, &cyl,
+ &netbsdpartoff)) != 0||
+ (rv = mbr_label_locate(dev, strat, lp, osdep, &cyl,
+ &netbsdpartoff)) != 0) {
+ if (rv < 0) {
+ error = -rv;
+ goto done;
+ }
+ } else {
+ /*
+ * We didn't find anything we like; NetBSD native.
+ * netbsdpartoff and cyl should be unchanged.
+ */
+ KASSERT(netbsdpartoff == 0);
+ KASSERT(cyl == (LABELSECTOR / lp->d_secpercyl));
+ }
+ }
+
+/* writelabel: */
+
+/* printf("writedisklabel: Reading disklabel addr=%08x\n",
+ netbsdpartoff * DEV_BSIZE);*/
+
+ /* next, dig out disk label */
+
+ bp->b_blkno = netbsdpartoff + LABELSECTOR;
+ bp->b_cylinder = 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_cylinder = (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);
+}
+
+
+void
+dk_establish(dk, dev)
+ struct disk *dk;
+ struct device *dev;
+{
+ return;
+}
+
+/* End of disksubr.c */
diff --git a/sys/arch/arm26/arm26/disksubr_acorn.c b/sys/arch/arm26/arm26/disksubr_acorn.c
new file mode 100644
index 00000000000..db66b10f0e4
--- /dev/null
+++ b/sys/arch/arm26/arm26/disksubr_acorn.c
@@ -0,0 +1,359 @@
+/* $NetBSD: disksubr_acorn.c,v 1.1 2000/05/09 21:55:56 bjh21 Exp $ */
+
+/*
+ * Copyright (c) 1998 Christopher G. Demetriou. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Christopher G. Demetriou
+ * 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.
+ */
+
+/*
+ * 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/disklabel.h>
+
+static int filecore_checksum __P((u_char *));
+
+/*
+ * static int filecore_checksum(u_char *bootblock)
+ *
+ * Calculates the filecore boot block checksum. This is used to validate
+ * a filecore boot block on the disk. 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 disk is NetBSD.
+ *
+ * The basic algorithm is:
+ *
+ * for (each byte in block, excluding checksum) {
+ * sum += byte;
+ * if (sum > 255)
+ * sum -= 255;
+ * }
+ *
+ * That's equivalent to summing all of the bytes in the block
+ * (excluding the checksum byte, of course), then calculating the
+ * checksum as "cksum = sum - ((sum - 1) / 255) * 255)". That
+ * expression may or may not yield a faster checksum function,
+ * but it's easier to reason about.
+ *
+ * Note that if you have a block filled with bytes of a single
+ * value "X" (regardless of that value!) and calculate the cksum
+ * of the block (excluding the checksum byte), you will _always_
+ * end up with a checksum of X. (Do the math; that can be derived
+ * from the checksum calculation function!) That means that
+ * blocks which contain bytes which all have the same value will
+ * always checksum properly. That's a _very_ unlikely occurence
+ * (probably impossible, actually) for a valid filecore boot block,
+ * so we treat such blocks as invalid.
+ */
+static int
+filecore_checksum(bootblock)
+ u_char *bootblock;
+{
+ u_char byte0, accum_diff;
+ u_int sum;
+ int i;
+
+ sum = 0;
+ accum_diff = 0;
+ byte0 = bootblock[0];
+
+ /*
+ * Sum the contents of the block, keeping track of whether
+ * or not all bytes are the same. If 'accum_diff' ends up
+ * being zero, all of the bytes are, in fact, the same.
+ */
+ for (i = 0; i < 511; ++i) {
+ sum += bootblock[i];
+ accum_diff |= bootblock[i] ^ byte0;
+ }
+
+ /*
+ * Check to see if the checksum byte is the same as the
+ * rest of the bytes, too. (Note that if all of the bytes
+ * are the same except the checksum, a checksum compare
+ * won't succeed, but that's not our problem.)
+ */
+ accum_diff |= bootblock[i] ^ byte0;
+
+ /* All bytes in block are the same; call it invalid. */
+ if (accum_diff == 0)
+ return (-1);
+
+ return (sum - ((sum - 1) / 255) * 255);
+}
+
+
+int
+filecore_label_read(dev, strat, lp, osdep, msgp, cylp, netbsd_label_offp)
+ dev_t dev;
+ void (*strat) __P((struct buf *));
+ struct disklabel *lp;
+ struct cpu_disklabel *osdep;
+ char **msgp;
+ int *cylp, *netbsd_label_offp;
+{
+ struct filecore_bootblock *bb;
+ int heads;
+ int sectors;
+ int rv = 1;
+ int cyl, netbsdpartoff;
+ struct buf *bp;
+
+#ifdef __GNUC__
+ netbsdpartoff = 0; /* XXX -Wuninitialized */
+#endif
+
+ /* get a buffer and initialize it */
+ bp = geteblk((int)lp->d_secsize);
+ bp->b_dev = dev;
+
+ /* read the Acorn filecore boot block */
+
+ bp->b_blkno = FILECORE_BOOT_SECTOR;
+ bp->b_bcount = lp->d_secsize;
+ bp->b_flags = B_BUSY | B_READ;
+ bp->b_cylinder = bp->b_blkno / lp->d_secpercyl;
+ (*strat)(bp);
+
+ /*
+ * if successful, validate boot block and
+ * locate partition table
+ */
+
+ if (biowait(bp)) {
+ *msgp = "filecore boot block I/O error";
+ goto out;
+ }
+
+ 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 NetBSD
+ */
+ rv = 0;
+ goto out;
+ }
+
+ /* 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 NETBSD partition table ? */
+
+ if (bb->partition_type == PARTITION_FORMAT_RISCBSD) {
+/* printf("heads = %d nsectors = %d\n", heads, sectors);*/
+ netbsdpartoff = 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
+ *
+ * Read the RISCiX partition table and see if
+ * there is a NetBSD partition
+ */
+
+ bp->b_blkno = cyl * heads * sectors;
+/* printf("Found RiscIX partition table @ %08x\n",
+ bp->b_blkno);*/
+ bp->b_cylinder = 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)) {
+ *msgp = "disk label I/O error";
+ goto out;
+ }
+
+ 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 ||
+ strcmp(rpt->partitions[loop].rp_name,
+ "Empty:") == 0) {
+ netbsdpartoff =
+ rpt->partitions[loop].rp_start;
+ break;
+ }
+ }
+ if (loop == NRISCIX_PARTITIONS) {
+ *msgp = "NetBSD partition identifier string not found.";
+ goto out;
+ }
+ } else {
+ *msgp = "Invalid partition format";
+ goto out;
+ }
+
+ *cylp = cyl;
+ *netbsd_label_offp = netbsdpartoff;
+ *msgp = NULL;
+out:
+ bp->b_flags = B_INVAL | B_AGE | B_READ;
+ brelse(bp);
+ return (rv);
+}
+
+
+int
+filecore_label_locate(dev, strat, lp, osdep, cylp, netbsd_label_offp)
+ dev_t dev;
+ void (*strat) __P((struct buf *));
+ struct disklabel *lp;
+ struct cpu_disklabel *osdep;
+ int *cylp, *netbsd_label_offp;
+{
+ struct filecore_bootblock *bb;
+ int heads;
+ int sectors;
+ int rv;
+ int cyl, netbsdpartoff;
+ struct buf *bp;
+
+ /* get a buffer and initialize it */
+ bp = geteblk((int)lp->d_secsize);
+ bp->b_dev = dev;
+
+ /* 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_cylinder = bp->b_blkno / lp->d_secpercyl;
+ (*strat)(bp);
+
+ /*
+ * if successful, validate boot block and locate
+ * partition table
+ */
+
+ if ((rv = biowait(bp)) != 0) {
+ rv = -rv;
+ goto out;
+ }
+
+ bb = (struct filecore_bootblock *)bp->b_data;
+ rv = 1;
+
+ /* Validate boot block */
+
+ if (bb->checksum != filecore_checksum((u_char *)bb)) {
+ /*
+ * Invalid boot block so lets assume the
+ * entire disc is NetBSD
+ */
+
+/* printf("writedisklabel: Invalid filecore boot block (incorrect checksum)\n");*/
+ rv = 0;
+ goto out;
+ }
+
+ /* Do we have a NetBSD partition ? */
+
+ if (bb->partition_type != PARTITION_FORMAT_RISCBSD) {
+ printf("writedisklabel: Invalid partition format\n");
+ rv = -1;
+ goto out;
+ }
+
+ cyl = bb->partition_cyl_low + (bb->partition_cyl_high << 8);
+
+ heads = bb->heads;
+ sectors = bb->secspertrack;
+
+ /*printf("heads = %d nsectors = %d\n", heads, sectors);*/
+
+ netbsdpartoff = cyl * heads * sectors;
+
+ *cylp = cyl;
+ *netbsd_label_offp = netbsdpartoff;
+out:
+ bp->b_flags = B_INVAL | B_AGE | B_READ;
+ brelse(bp);
+ return (rv);
+}
diff --git a/sys/arch/arm26/arm26/disksubr_mbr.c b/sys/arch/arm26/arm26/disksubr_mbr.c
new file mode 100644
index 00000000000..9bdd1479681
--- /dev/null
+++ b/sys/arch/arm26/arm26/disksubr_mbr.c
@@ -0,0 +1,278 @@
+/* $NetBSD: disksubr_mbr.c,v 1.1 2000/05/09 21:55:56 bjh21 Exp $ */
+
+/*
+ * Copyright (c) 1998 Christopher G. Demetriou. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Christopher G. Demetriou
+ * 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.
+ */
+
+/*
+ * Copyright (c) 1982, 1986, 1988 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)ufs_disksubr.c 7.16 (Berkeley) 5/4/91
+ */
+
+/*
+ * From i386 disklabel.c rev 1.29, with cleanups and modifications to
+ * make it easier to use on the arm32 and to use as MI code (not quite
+ * clean enough, yet).
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/buf.h>
+#include <sys/disklabel.h>
+
+#include "opt_mbr.h"
+
+#define MBRSIGOFS 0x1fe
+static char mbrsig[2] = {0x55, 0xaa};
+
+int fat_types[] = {
+ MBR_PTYPE_FAT12, MBR_PTYPE_FAT16S,
+ MBR_PTYPE_FAT16B, MBR_PTYPE_FAT32,
+ MBR_PTYPE_FAT32L, MBR_PTYPE_FAT16L,
+ -1
+};
+
+int
+mbr_label_read(dev, strat, lp, osdep, msgp, cylp, netbsd_label_offp)
+ dev_t dev;
+ void (*strat) __P((struct buf *));
+ struct disklabel *lp;
+ struct cpu_disklabel *osdep;
+ char **msgp;
+ int *cylp, *netbsd_label_offp;
+{
+ struct mbr_partition *mbrp;
+ struct partition *pp;
+ int cyl, mbrpartoff, i, *ip;
+ struct buf *bp;
+ int rv = 1;
+
+ /* get a buffer and initialize it */
+ bp = geteblk((int)lp->d_secsize);
+ bp->b_dev = dev;
+
+ /* In case nothing sets them */
+ mbrpartoff = 0;
+ cyl = LABELSECTOR / lp->d_secpercyl;
+
+ mbrp = osdep->mbrparts;
+
+ /* read master boot record */
+ bp->b_blkno = MBR_BBSECTOR;
+ bp->b_bcount = lp->d_secsize;
+ bp->b_flags = B_BUSY | B_READ;
+ bp->b_cylinder = MBR_BBSECTOR / lp->d_secpercyl;
+ (*strat)(bp);
+
+ /* if successful, wander through dos partition table */
+ if (biowait(bp)) {
+ *msgp = "dos partition I/O error";
+ goto out;
+ } else {
+ struct mbr_partition *ourmbrp = NULL;
+
+ /* XXX "there has to be a better check than this." */
+ if (bcmp(bp->b_data + MBRSIGOFS, mbrsig, sizeof(mbrsig))) {
+ rv = 0;
+ goto out;
+ }
+
+ /* XXX how do we check veracity/bounds of this? */
+ bcopy(bp->b_data + MBR_PARTOFF, mbrp,
+ NMBRPART * sizeof(*mbrp));
+
+ /* look for NetBSD partition */
+ ourmbrp = NULL;
+ for (i = 0; !ourmbrp && i < NMBRPART; i++) {
+ if (mbrp[i].mbrp_typ == MBR_PTYPE_NETBSD)
+ ourmbrp = &mbrp[i];
+ }
+#ifdef COMPAT_386BSD_MBRPART
+ /* didn't find it -- look for 386BSD partition */
+ for (i = 0; !ourmbrp && i < NMBRPART; i++) {
+ if (mbrp[i].mbrp_typ == MBR_PTYPE_386BSD) {
+ printf("WARNING: old BSD partition ID!\n");
+ ourmbrp = &mbrp[i];
+ break;
+ }
+ }
+#endif
+ for (i = 0; i < NMBRPART; i++, mbrp++) {
+
+ strncpy(lp->d_packname, "fictitious-MBR",
+ sizeof lp->d_packname);
+
+ /* Install in partition e, f, g, or h. */
+ pp = &lp->d_partitions['e' - 'a' + i];
+ pp->p_offset = mbrp->mbrp_start;
+ pp->p_size = mbrp->mbrp_size;
+ for (ip = fat_types; *ip != -1; ip++) {
+ if (mbrp->mbrp_typ == *ip)
+ pp->p_fstype = FS_MSDOS;
+ }
+ if (mbrp->mbrp_typ == MBR_PTYPE_LNXEXT2)
+ pp->p_fstype = FS_EX2FS;
+
+ /* is this ours? */
+ if (mbrp == ourmbrp) {
+ /* need sector address for SCSI/IDE,
+ cylinder for ESDI/ST506/RLL */
+ mbrpartoff = mbrp->mbrp_start;
+ cyl = MBR_PCYL(mbrp->mbrp_scyl, mbrp->mbrp_ssect);
+
+#ifdef __i386__ /* XXX? */
+ /* update disklabel with details */
+ lp->d_partitions[2].p_size =
+ mbrp->mbrp_size;
+ lp->d_partitions[2].p_offset =
+ mbrp->mbrp_start;
+ lp->d_ntracks = mbrp->mbrp_ehd + 1;
+ lp->d_nsectors = MBR_PSECT(mbrp->mbrp_esect);
+ lp->d_secpercyl =
+ lp->d_ntracks * lp->d_nsectors;
+#endif
+ }
+ }
+ lp->d_npartitions = 'e' - 'a' + i;
+ }
+
+ *cylp = cyl;
+ *netbsd_label_offp = mbrpartoff;
+ *msgp = NULL;
+out:
+ bp->b_flags = B_INVAL | B_AGE | B_READ;
+ brelse(bp);
+ return (rv);
+}
+
+int
+mbr_label_locate(dev, strat, lp, osdep, cylp, netbsd_label_offp)
+ dev_t dev;
+ void (*strat) __P((struct buf *));
+ struct disklabel *lp;
+ struct cpu_disklabel *osdep;
+ int *cylp, *netbsd_label_offp;
+{
+ struct mbr_partition *mbrp;
+ int cyl, mbrpartoff, i;
+ struct mbr_partition *ourmbrp = NULL;
+ struct buf *bp;
+ int rv = 1;
+
+ /* get a buffer and initialize it */
+ bp = geteblk((int)lp->d_secsize);
+ bp->b_dev = dev;
+
+ /* do MBR partitions in the process of getting disklabel? */
+ mbrpartoff = 0;
+ cyl = LABELSECTOR / lp->d_secpercyl;
+
+ mbrp = osdep->mbrparts;
+
+ /* read master boot record */
+ bp->b_blkno = MBR_BBSECTOR;
+ bp->b_bcount = lp->d_secsize;
+ bp->b_flags = B_BUSY | B_READ;
+ bp->b_cylinder = MBR_BBSECTOR / lp->d_secpercyl;
+ (*strat)(bp);
+
+ if ((rv = biowait(bp)) != 0) {
+ rv = -rv;
+ goto out;
+ }
+
+ if (bcmp(bp->b_data + MBRSIGOFS, mbrsig, sizeof(mbrsig))) {
+ rv = 0;
+ goto out;
+ }
+
+ /* XXX how do we check veracity/bounds of this? */
+ bcopy(bp->b_data + MBR_PARTOFF, mbrp, NMBRPART * sizeof(*mbrp));
+
+ /* look for NetBSD partition */
+ ourmbrp = NULL;
+ for (i = 0; !ourmbrp && i < NMBRPART; i++) {
+ if (mbrp[i].mbrp_typ == MBR_PTYPE_NETBSD)
+ ourmbrp = &mbrp[i];
+ }
+#ifdef COMPAT_386BSD_MBRPART
+ /* didn't find it -- look for 386BSD partition */
+ for (i = 0; !ourmbrp && i < NMBRPART; i++) {
+ if (mbrp[i].mbrp_typ == MBR_PTYPE_386BSD) {
+ printf("WARNING: old BSD partition ID!\n");
+ ourmbrp = &mbrp[i];
+ }
+ }
+#endif
+ if (!ourmbrp) {
+ rv = 0; /* XXX allow easy clobber? */
+ goto out;
+ }
+
+ /* need sector address for SCSI/IDE, cylinder for ESDI/ST506/RLL */
+ mbrpartoff = ourmbrp->mbrp_start;
+ cyl = MBR_PCYL(ourmbrp->mbrp_scyl, ourmbrp->mbrp_ssect);
+
+ *cylp = cyl;
+ *netbsd_label_offp = mbrpartoff;
+out:
+ bp->b_flags = B_INVAL | B_AGE | B_READ;
+ brelse(bp);
+ return (rv);
+}
diff --git a/sys/arch/arm26/arm26/except.c b/sys/arch/arm26/arm26/except.c
new file mode 100644
index 00000000000..9f28e889e08
--- /dev/null
+++ b/sys/arch/arm26/arm26/except.c
@@ -0,0 +1,717 @@
+/* $NetBSD: except.c,v 1.1 2000/05/09 21:55:56 bjh21 Exp $ */
+/*-
+ * Copyright (c) 1998, 1999, 2000 Ben Harris
+ * 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.
+ */
+/* This file is part of NetBSD/arm26 -- a port of NetBSD to ARM2/3 machines. */
+/*
+ * except.c -- ARM exception handling.
+ */
+
+#include <sys/param.h>
+
+__KERNEL_RCSID(0, "$NetBSD: except.c,v 1.1 2000/05/09 21:55:56 bjh21 Exp $");
+
+#include <sys/syscall.h>
+#include <sys/syslog.h>
+#include <sys/systm.h>
+#include <sys/user.h>
+
+#include <vm/vm.h>
+#include <vm/vm_kern.h>
+
+#include <machine/armreg.h>
+#include <machine/machdep.h>
+#include <machine/pcb.h>
+
+#ifdef DEBUG
+#include <arm32/arm32/disassem.h>
+#endif
+
+#include "opt_cputypes.h"
+#include "opt_ddb.h"
+#include "opt_ktrace.h"
+
+#ifdef DDB
+#include <machine/db_machdep.h>
+#endif
+
+#ifdef KTRACE
+#include <sys/ktrace.h>
+#endif
+
+static void data_abort_fixup(struct trapframe *);
+static vaddr_t data_abort_address(struct trapframe *);
+static vm_prot_t data_abort_atype(struct trapframe *);
+#ifdef DEBUG
+static void printregs(struct trapframe *tf);
+#endif
+
+int want_resched;
+
+/*
+ * userret() is called just before any return to userland after a trap.
+ * It's all boilerplate stuff.
+ */
+
+static void
+userret(struct proc *p, vaddr_t pc, u_quad_t oticks)
+{
+ int sig;
+
+ /* take pending signals */
+ while ((sig = CURSIG(p)) != 0)
+ postsig(sig);
+ p->p_priority = p->p_usrpri;
+ if (want_resched) {
+ preempt(NULL);
+ while ((sig = CURSIG(p)) != 0)
+ postsig(sig);
+ }
+
+ /*
+ * If profiling, charge system time to the trapped pc.
+ */
+ if (p->p_flag & P_PROFIL) {
+ extern int psratio;
+
+ addupc_task(p, pc, (int)(p->p_sticks - oticks) * psratio);
+ }
+ curpriority = p->p_priority;
+#ifdef DIAGNOSTIC
+ /* Mark trapframe as invalid. */
+ p->p_addr->u_pcb.pcb_tf = (void *)-1;
+#endif
+}
+
+void
+undefined_handler(struct trapframe *tf)
+{
+ u_quad_t sticks;
+ struct proc *p;
+ u_int32_t insn;
+ vaddr_t pc;
+
+ pc = tf->tf_r15 & R15_PC;
+ insn = *(register_t *)pc;
+#ifdef CPU_ARM2
+ /*
+ * Check if the aborted instruction was a SWI (ARM2 bug --
+ * ARM3 data sheet p87) and call SWI handler if so.
+ */
+ if ((insn & 0x0f000000) == 0x0f000000) {
+ swi_handler(tf);
+ return;
+ }
+#endif
+ /* Enable interrupts if they were enabled before the trap. */
+ if ((tf->tf_r15 & R15_IRQ_DISABLE) == 0)
+ int_on();
+ uvmexp.traps++;
+ p = curproc;
+ if (p == NULL)
+ p = &proc0;
+ if (p->p_addr->u_pcb.pcb_onundef_lj != NULL)
+ longjmp(p->p_addr->u_pcb.pcb_onundef_lj);
+ if ((tf->tf_r15 & R15_MODE) != R15_MODE_USR) {
+#ifdef DDB
+ if (insn == 0xe7ffffff) {
+ kdb_trap(T_BREAKPOINT, (db_regs_t *)tf);
+ return;
+ }
+#endif
+#ifdef DEBUG
+ printf("Undefined instruction:\n");
+ printregs(tf);
+ printf("pc -> ");
+ disassemble(tf->tf_r15 & R15_PC);
+#endif
+ panic("undefined instruction in kernel mode");
+ } else {
+ p->p_addr->u_pcb.pcb_tf = tf;
+ sticks = p->p_sticks;
+ trapsignal(p, SIGILL, insn);
+ userret(p, pc, sticks);
+ }
+}
+
+void
+swi_handler(struct trapframe *tf)
+{
+ u_quad_t sticks;
+ struct proc *p;
+ vaddr_t pc;
+ int code, regparams, nextreg;
+ struct sysent *sy;
+ size_t argsize, regargsize, stkargsize;
+ char args[32]; /* XXX just enough for mmap... */
+ register_t rval[2], or15;
+ int error;
+
+ /* Enable interrupts if they were enabled before the trap. */
+ if ((tf->tf_r15 & R15_IRQ_DISABLE) == 0)
+ int_on();
+ uvmexp.traps++;
+ uvmexp.syscalls++;
+ p = curproc;
+ if (p == NULL)
+ p = &proc0;
+ sticks = p->p_sticks;
+ if ((tf->tf_r15 & R15_MODE) == R15_MODE_USR)
+ p->p_addr->u_pcb.pcb_tf = tf;
+
+ if ((tf->tf_r15 & R15_MODE) != R15_MODE_USR) {
+#ifdef DEBUG
+ printf("SWI:\n");
+ printregs(tf);
+ printf("pc -> ");
+ disassemble(tf->tf_r15 & R15_PC);
+#endif
+ panic("SWI in kernel mode");
+ }
+
+ pc = tf->tf_r15 & R15_PC;
+
+#ifdef DIAGNOSTIC
+ if ((*(u_int32_t *)pc & 0x0f000000) != 0x0f000000) {
+ disassemble(pc);
+ panic("SWI on non-SWI instruction");
+ }
+#endif
+
+ /* Look up the system call and see if it's magic. */
+ code = *(register_t *)pc & 0x00ffffff;
+ switch (code) {
+ case SYS_syscall: /* Indirect system call. First arg is new code */
+ code = tf->tf_r0;
+ regparams = 3; nextreg = 1;
+ break;
+ case SYS___syscall: /* As above, but quad_t arg */
+ if (p->p_emul->e_sysent == sysent) { /* NetBSD emulation */
+ code = tf->tf_r0; /* XXX assume little-endian */
+ regparams = 2; nextreg = 2;
+ break;
+ }
+ /* FALLTHROUGH */
+ default:
+ regparams = 4; nextreg = 0;
+ }
+ if (code > p->p_emul->e_nsysent)
+ sy = p->p_emul->e_sysent + p->p_emul->e_nosys;
+ else
+ sy = p->p_emul->e_sysent + code;
+
+ argsize = sy->sy_argsize;
+ if (argsize > (regparams * sizeof(int))) {
+ regargsize = regparams*sizeof(int);
+ stkargsize = argsize - regargsize;
+ } else {
+ regargsize = argsize;
+ stkargsize = 0;
+ }
+
+ if (regargsize)
+ bcopy((char *)tf + nextreg * sizeof(int), args, regargsize);
+
+ if (stkargsize) {
+ error = copyin((caddr_t)tf->tf_r13, args + regargsize,
+ stkargsize);
+ if (error) {
+#ifdef SYSCALL_DEBUG
+ scdebug_call(p, code, (register_t *)args);
+#endif
+ goto bad;
+ }
+ }
+
+#ifdef SYSCALL_DEBUG
+ scdebug_call(p, code, (register_t *)args);
+#endif
+#ifdef KTRACE
+ if (KTRPOINT(p, KTR_SYSCALL))
+ ktrsyscall(p->p_tracep, code, argsize, args);
+#endif
+
+ rval[0] = 0;
+ rval[1] = tf->tf_r1;
+
+ /* Set return address */
+ or15 = tf->tf_r15;
+ tf->tf_r15 += 4;
+
+ error = sy->sy_call(p, args, rval);
+
+ switch (error) {
+ case 0:
+ tf->tf_r0 = rval[0];
+ tf->tf_r1 = rval[1];
+ tf->tf_r15 &= ~R15_FLAG_C;
+ break;
+ case ERESTART:
+ tf->tf_r15 = or15;
+ break;
+ case EJUSTRETURN:
+ /* nothing to do */
+ break;
+ default:
+ bad:
+ tf->tf_r0 = rval[0] = error;
+ tf->tf_r15 |= R15_FLAG_C;
+ break;
+ }
+#ifdef SYSCALL_DEBUG
+ scdebug_ret(p, code, error, rval);
+#endif
+ userret(p, pc, sticks);
+#ifdef KTRACE
+ if (KTRPOINT(p, KTR_SYSRET))
+ ktrsysret(p->p_tracep, code, error, rval[0]);
+#endif
+}
+
+/*
+ * Return from fork(2) in the child. This is effectively the tail end of
+ * a normal successful syscall return.
+ */
+void
+child_return(void* ignore)
+{
+ struct proc *p;
+ struct trapframe *tf;
+
+ p = curproc;
+ tf = p->p_addr->u_pcb.pcb_tf;
+ tf->tf_r0 = 0;
+ tf->tf_r15 &= ~R15_FLAG_C;
+
+#ifdef SYSCALL_DEBUG
+ scdebug_ret(p, SYS_fork /* XXX */, 0, &tf->tf_r0);
+#endif
+ userret(p, tf->tf_r15 & R15_PC, 0);
+#ifdef KTRACE
+ if (KTRPOINT(p, KTR_SYSRET))
+ ktrsysret(p->p_tracep, SYS_fork /* XXX */, 0, &tf->tf_r0);
+#endif
+}
+
+void
+prefetch_abort_handler(struct trapframe *tf)
+{
+ u_quad_t sticks;
+ vaddr_t pc;
+ struct proc *p;
+ int ret;
+
+ /* Enable interrupts if they were enabled before the trap. */
+ if ((tf->tf_r15 & R15_IRQ_DISABLE) == 0)
+ int_on();
+
+ /*
+ * Check if the page being requested is already present. If
+ * so, call the undefined instruction handler instead (ARM3 ds
+ * p15).
+ */
+
+ uvmexp.traps++;
+ p = curproc;
+ if (p == NULL)
+ p = &proc0;
+ sticks = p->p_sticks;
+
+ if ((tf->tf_r15 & R15_MODE) == R15_MODE_USR)
+ p->p_addr->u_pcb.pcb_tf = tf;
+
+ if ((tf->tf_r15 & R15_MODE) != R15_MODE_USR) {
+#ifdef DEBUG
+ printf("Prefetch abort:\n");
+ printregs(tf);
+#endif
+ panic("prefetch abort in kernel mode");
+ }
+
+ /* User-mode prefetch abort */
+ pc = tf->tf_r15 & R15_PC;
+
+ if (pmap_fault(p->p_vmspace->vm_map.pmap, pc, VM_PROT_EXECUTE))
+ goto out;
+ ret = uvm_fault(&p->p_vmspace->vm_map, pc, 0, VM_PROT_EXECUTE);
+
+ if (ret != KERN_SUCCESS) {
+#ifdef DEBUG
+ printf("unhandled fault at %p (ret = %d)\n", (void *)pc, ret);
+ printf("Prefetch abort:\n");
+ printregs(tf);
+#endif
+ panic("prefetch_abort_handler: uvm_fault failed");
+ }
+out:
+ userret(p, pc, sticks);
+}
+
+void
+data_abort_handler(struct trapframe *tf)
+{
+ u_quad_t sticks;
+ vaddr_t pc, va;
+ int ret;
+ struct proc *p;
+ vm_prot_t atype;
+ vm_map_t map;
+ struct pcb *curpcb;
+
+ /*
+ * Data aborts in kernel mode are possible (copyout etc), so
+ * we hope the compiler (or programmer) has ensured that
+ * R14_svc gets saved.
+ *
+ * We may need to fix up an STM or LDM instruction. This
+ * involves seeing if the base was being written back, and if
+ * so resetting it (by counting the number of registers being
+ * transferred) before retrying (ARM 2 ds pp 10 & 33).
+ */
+
+ /* Enable interrupts if they were enabled before the trap. */
+ if ((tf->tf_r15 & R15_IRQ_DISABLE) == 0)
+ int_on();
+ uvmexp.traps++;
+ p = curproc;
+ if (p == NULL)
+ p = &proc0;
+ if ((tf->tf_r15 & R15_MODE) == R15_MODE_USR)
+ p->p_addr->u_pcb.pcb_tf = tf;
+ sticks = p->p_sticks;
+ pc = tf->tf_r15 & R15_PC;
+ data_abort_fixup(tf);
+ va = data_abort_address(tf);
+ atype = data_abort_atype(tf);
+ map = va >= VM_MIN_KERNEL_ADDRESS ? kernel_map : &p->p_vmspace->vm_map;
+ if (pmap_fault(map->pmap, va, atype))
+ goto out;
+ ret = uvm_fault(map, va, 0, atype);
+
+ if (ret != KERN_SUCCESS) {
+#ifdef DEBUG
+ printf("unhandled fault at %p (ret = %d)\n", (void *)va, ret);
+#endif
+ curpcb = &p->p_addr->u_pcb;
+ if (curpcb->pcb_onfault != NULL) {
+ tf->tf_r15 = (tf->tf_r15 & ~R15_PC) |
+ (register_t)curpcb->pcb_onfault;
+ return;
+ }
+ if (curpcb->pcb_onfault_lj != NULL)
+ longjmp(curpcb->pcb_onfault_lj);
+#ifdef DEBUG
+ printf("Data abort:\n");
+ printregs(tf);
+ printf("pc -> ");
+ disassemble(tf->tf_r15 & R15_PC);
+#endif
+ panic("data_abort_handler: uvm_fault failed");
+ }
+
+out:
+ if ((tf->tf_r15 & R15_MODE) == R15_MODE_USR)
+ userret(p, pc, sticks);
+}
+
+#define getreg(r) (((register_t *)tf)[r])
+
+/*
+ * Undo any effects of the aborted instruction that need to be undone
+ * in order for us to restart it. This is just a case of spotting
+ * aborted LDMs and STMs and reversing any base writeback. This code
+ * is derived loosely from the arm32 late-abort fixup.
+ */
+static void
+data_abort_fixup(struct trapframe *tf)
+{
+ register_t insn;
+ int rn, count, loop;
+
+ /* Get the faulting instruction */
+ insn = *(register_t *)(tf->tf_r15 & R15_PC);
+ if ((insn & 0x0e000000) == 0x08000000 &&
+ (insn & 1 << 21)) {
+ /* LDM/STM with writeback*/
+ rn = (insn >> 16) & 0x0f;
+ if (rn == 15)
+ return; /* No writeback on R15 */
+ /* Count registers transferred */
+ count = 0;
+ for (loop = 0; loop < 16; ++loop) {
+ if (insn & (1<<loop))
+ ++count;
+ }
+ if (insn & (1 << 23)) /* up/down bit -- we reverse it. */
+ getreg(rn) -= count * 4;
+ else
+ getreg(rn) += count * 4;
+ }
+}
+
+/*
+ * Work out where a data abort happened. This involves emulating the
+ * faulting instruction. Some of this code is derived from the arm32
+ * abort fixup stuff too.
+ */
+static vaddr_t
+data_abort_address(struct trapframe *tf)
+{
+ register_t insn;
+ int rn, rm, offset, shift, p, i, u;
+ vaddr_t base;
+
+ /* Get the faulting instruction */
+ insn = *(register_t *)(tf->tf_r15 & R15_PC);
+ if ((insn & 0x0c000000) == 0x04000000) {
+ /* Single data transfer */
+ rn = (insn & 0x000f0000) >> 16;
+ base = getreg(rn);
+ if (rn == 15)
+ base = (base & R15_PC) + 8;
+ p = insn & 1 << 24;
+ if (p == 0)
+ /* Post-indexed, so offset doesn't concern us */
+ return base;
+ u = insn & 1 << 23;
+ i = insn & 1 << 25;
+ if (i == 0) {
+ /* Immediate offset (str r0, [r1, #42]) */
+ offset = insn & 0x00000fff;
+ if (u == 0)
+ return base - offset;
+ else
+ return base + offset;
+ }
+ rm = insn & 0x0000000f;
+ offset = getreg(rm);
+ if (rm == 15)
+ offset += 8;
+ if ((insn & 1 << 4) == 0)
+ /* immediate shift */
+ shift = (insn & 0x00000f80) >> 7;
+ else
+ goto croak; /* register shifts can't happen in ARMv2 */
+ switch ((insn & 0x00000060) >> 5) {
+ 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 -- FIXME support this*/
+ default: /* help GCC */
+ goto croak;
+ }
+ if (u == 0)
+ return base - offset;
+ else
+ return base + offset;
+ } else if ((insn & 0x0e000000) == 0x08000000) {
+ vaddr_t sva, eva;
+ int loop, count;
+
+ /* LDM/STM */
+ rn = (insn >> 16) & 0x0f;
+ /* Need to find both ends of the range being transferred. */
+ p = insn & 1 << 24;
+ u = insn & 1 << 23;
+ if (p == 0)
+ sva = getreg(rn);
+ else
+ if (u == 0)
+ sva = getreg(rn) - 4;
+ else
+ sva = getreg(rn) + 4;
+ /*
+ * This is currently bogus. We should check the
+ * lowest address first. I doubt they'll notice.
+ */
+ if (pmap_confess(sva, data_abort_atype(tf)))
+ return sva;
+ /* Count registers transferred */
+ count = 0;
+ for (loop = 0; loop < 16; ++loop) {
+ if (insn & (1<<loop))
+ ++count;
+ }
+ if (u == 0) /* up/down bit */
+ eva = sva - count * 4;
+ else
+ eva = sva + count * 4;
+ return eva;
+#if defined(CPU_ARM250) || defined(CPU_ARM3)
+ } else if ((insn & 0x0fb00ff0) == 0x01000090) {
+ /* SWP */
+ rm = insn & 0x0000000f;
+ base = getreg(rm);
+ if (rm == 15)
+ return base + 8;
+ else
+ return base;
+#endif
+ }
+croak:
+#ifdef DEBUG
+ printf("Data abort:\n");
+ printregs(tf);
+ printf("pc -> ");
+ disassemble(tf->tf_r15 & R15_PC);
+#endif
+ panic("data_abort_address");
+}
+
+/*
+ * We need to know whether the page should be mapped as R or R/W. We
+ * need to disassemble the instruction responsible and determine if it
+ * was a read or write instruction. This code is based on the arm32
+ * version.
+ */
+static vm_prot_t
+data_abort_atype(struct trapframe *tf)
+{
+ register_t insn;
+
+ insn = *(register_t *)(tf->tf_r15 & R15_PC);
+ /* STR instruction ? */
+ if ((insn & 0x0c100000) == 0x04000000)
+ return VM_PROT_READ | VM_PROT_WRITE;
+ /* STM or CDT instruction ? */
+ else if ((insn & 0x0a100000) == 0x08000000)
+ return VM_PROT_READ | VM_PROT_WRITE;
+#if defined(CPU_ARM250) || defined(CPU_ARM3)
+ /* SWP instruction ? */
+ else if ((insn & 0x0fb00ff0) == 0x01000090)
+ return VM_PROT_READ | VM_PROT_WRITE;
+#endif
+ return VM_PROT_READ;
+}
+
+void
+address_exception_handler(struct trapframe *tf)
+{
+ u_quad_t sticks;
+ struct proc *p;
+ vaddr_t pc;
+
+ /* Enable interrupts if they were enabled before the trap. */
+ if ((tf->tf_r15 & R15_IRQ_DISABLE) == 0)
+ int_on();
+ uvmexp.traps++;
+ p = curproc;
+ if (p == NULL)
+ p = &proc0;
+ if ((tf->tf_r15 & R15_MODE) == R15_MODE_USR)
+ p->p_addr->u_pcb.pcb_tf = tf;
+
+/* if ((tf->tf_r15 & R15_MODE) != R15_MODE_USR) */{
+#ifdef DEBUG
+ printf("Address exception:\n");
+ printregs(tf);
+ printf("pc -> ");
+ disassemble(tf->tf_r15 & R15_PC);
+#endif
+ panic("address exception in kernel mode");
+ }
+
+ pc = tf->tf_r15 & R15_PC;
+ sticks = p->p_sticks;
+ trapsignal(p, SIGBUS, pc);
+ userret(p, pc, sticks);
+}
+
+/*
+ * An AST isn't a real hardware trap, but locore.S makes it look like one
+ * for consistency.
+ */
+int astpending;
+
+void
+ast_handler(struct trapframe *tf)
+{
+ u_quad_t sticks;
+ vaddr_t pc;
+ struct proc *p;
+
+ /* Enable interrupts if they were enabled before the trap. */
+ if ((tf->tf_r15 & R15_IRQ_DISABLE) == 0)
+ int_on();
+ astpending = 0;
+ p = curproc;
+ if (p == NULL)
+ p = &proc0;
+ sticks = p->p_sticks;
+ if ((tf->tf_r15 & R15_MODE) == R15_MODE_USR)
+ p->p_addr->u_pcb.pcb_tf = tf;
+ pc = tf->tf_r15 & R15_PC;
+
+ if (p->p_flag & P_OWEUPC) {
+ p->p_flag &= ~P_OWEUPC;
+ ADDUPROF(p);
+ }
+
+ userret(p, pc, sticks);
+}
+
+
+void
+setsoftast()
+{
+ astpending = 1;
+}
+
+extern int want_resched; /* XXX */
+
+void
+need_resched(void)
+{
+ want_resched = 1;
+ setsoftast();
+}
+
+
+#ifdef DEBUG
+static void
+printregs(struct trapframe *tf)
+{
+
+ printf("R0 = 0x%08x R1 = 0x%08x R2 = 0x%08x R3 = 0x%08x\n"
+ "R4 = 0x%08x R5 = 0x%08x R6 = 0x%08x R7 = 0x%08x\n"
+ "R8 = 0x%08x R9 = 0x%08x R10 = 0x%08x R11 = 0x%08x\n"
+ "R12 = 0x%08x R13 = 0x%08x R14 = 0x%08x R15 = 0x%08x\n",
+ tf->tf_r0, tf->tf_r1, tf->tf_r2, tf->tf_r3,
+ tf->tf_r4, tf->tf_r5, tf->tf_r6, tf->tf_r7,
+ tf->tf_r8, tf->tf_r9, tf->tf_r10, tf->tf_r11,
+ tf->tf_r12, tf->tf_r13, tf->tf_r14, tf->tf_r15);
+}
+#endif
+
+/* irq_handler is over in irq.c */
diff --git a/sys/arch/arm26/arm26/genassym.cf b/sys/arch/arm26/arm26/genassym.cf
new file mode 100644
index 00000000000..9e1a13c57db
--- /dev/null
+++ b/sys/arch/arm26/arm26/genassym.cf
@@ -0,0 +1,46 @@
+# $NetBSD: genassym.cf,v 1.1 2000/05/09 21:55:56 bjh21 Exp $
+#
+# Copyright (c) 1999 Ben Harris
+# 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.
+#
+# This file is part of NetBSD/arm26 -- a port of NetBSD to ARM2/3 machines.
+
+include <sys/param.h>
+
+include <sys/proc.h>
+include <sys/user.h>
+include <machine/pcb.h>
+
+define U_PCB offsetof(struct user, u_pcb)
+define PCB_ONFAULT offsetof(struct pcb, pcb_onfault)
+define P_ADDR offsetof(struct proc, p_addr)
+
+define TF_R15 offsetof(struct trapframe, tf_r15)
+define TF_SIZE sizeof(struct trapframe)
+
+define IF_R15 offsetof(struct irqframe, if_r15)
+define IF_SIZE sizeof(struct irqframe)
+
+define SF_SC offsetof(struct sigframe, sf_sc)
diff --git a/sys/arch/arm26/arm26/intrnames.S b/sys/arch/arm26/arm26/intrnames.S
new file mode 100644
index 00000000000..1a7ed4d6ceb
--- /dev/null
+++ b/sys/arch/arm26/arm26/intrnames.S
@@ -0,0 +1,86 @@
+/* $NetBSD: intrnames.S,v 1.1 2000/05/09 21:55:56 bjh21 Exp $ */
+/*-
+ * Copyright (c) 2000 Ben Harris
+ * 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.
+ */
+/* This file is part of NetBSD/arm26 -- a port of NetBSD to ARM2/3 machines. */
+/*
+ * intrnames.S -- interrupt names for systat etc.
+ */
+
+#include <machine/asm.h>
+
+RCSID("$NetBSD: intrnames.S,v 1.1 2000/05/09 21:55:56 bjh21 Exp $")
+
+ .text
+ .global _C_LABEL(intrnames)
+_C_LABEL(intrnames):
+.macro irqname irq
+Lirq\irq:
+ .asciz "IRQ \irq"
+.endm
+ irqname 0
+ irqname 1
+ irqname 2
+ irqname 3
+ irqname 4
+ irqname 5
+ irqname 6
+ irqname 7
+ irqname 8
+ irqname 9
+ irqname 10
+ irqname 11
+ irqname 12
+ irqname 13
+ irqname 14
+ irqname 15
+ .global _C_LABEL(eintrnames)
+_C_LABEL(eintrnames):
+ .global _C_LABEL(irqnames)
+_C_LABEL(irqnames):
+ .word Lirq0
+ .word Lirq1
+ .word Lirq2
+ .word Lirq3
+ .word Lirq4
+ .word Lirq5
+ .word Lirq6
+ .word Lirq7
+ .word Lirq8
+ .word Lirq9
+ .word Lirq10
+ .word Lirq11
+ .word Lirq12
+ .word Lirq13
+ .word Lirq14
+ .word Lirq15
+
+ .data
+ .global _C_LABEL(intrcnt)
+_C_LABEL(intrcnt):
+ .fill 16, 4
+ .global _C_LABEL(eintrcnt)
+_C_LABEL(eintrcnt):
diff --git a/sys/arch/arm26/arm26/irq.c b/sys/arch/arm26/arm26/irq.c
new file mode 100644
index 00000000000..8104d72de50
--- /dev/null
+++ b/sys/arch/arm26/arm26/irq.c
@@ -0,0 +1,297 @@
+/* $NetBSD: irq.c,v 1.1 2000/05/09 21:55:56 bjh21 Exp $ */
+
+/*-
+ * Copyright (c) 2000 Ben Harris
+ * 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.
+ */
+/* This file is part of NetBSD/arm26 -- a port of NetBSD to ARM2/3 machines. */
+/*
+ * irq.c - IOC IRQ handler.
+ */
+
+#include <sys/param.h>
+
+__RCSID("$NetBSD: irq.c,v 1.1 2000/05/09 21:55:56 bjh21 Exp $");
+
+#include <sys/device.h>
+#include <sys/kernel.h> /* for cold */
+#include <sys/malloc.h>
+#include <sys/queue.h>
+#include <sys/systm.h>
+
+#include <vm/vm.h>
+#include <uvm/uvm_extern.h>
+
+#include <machine/bus.h>
+#include <machine/frame.h>
+#include <machine/intr.h>
+#include <machine/irq.h>
+#include <machine/machdep.h>
+#include <machine/spl.h>
+
+#include <arch/arm26/iobus/iocreg.h>
+#include <arch/arm26/iobus/iocvar.h>
+
+extern struct cfdriver ioc_cd;
+
+#define NIRQ 16
+extern char *irqnames[];
+
+/*
+ * Interrupt masks are held in 32-bit integers. At present, the
+ * bottom eight bits are interrupt register A on the IOC, and the next
+ * eight are interrupt register B. FIQs and the Unix backplane should
+ * be represented eventually.
+ */
+
+static u_int32_t irqmask[NIPL];
+
+LIST_HEAD(irq_handler_head, irq_handler) irq_list_head =
+ LIST_HEAD_INITIALIZER(irq_list_head);
+
+struct irq_handler {
+ LIST_ENTRY(irq_handler) link;
+ int (*func) __P((void *));
+ void *arg;
+ u_int32_t mask;
+ int irqnum;
+ int ipl;
+ int enabled;
+};
+
+volatile static int current_spl = IPL_HIGH;
+
+void
+irq_init(void)
+{
+
+ irq_genmasks();
+ softintr_init();
+}
+
+/*
+ * This is optimised for speed rather than generality. It expects to
+ * be called an awful lot.
+ *
+ * On entry, IRQs are disabled on the CPU.
+ */
+
+void
+irq_handler(struct irqframe *irqf)
+{
+ int s, status, result, stray;
+ struct irq_handler *h;
+
+#ifdef DIAGNOSTIC
+ if (ioc_cd.cd_ndevs == 0 || ioc_cd.cd_devs == NULL ||
+ ioc_cd.cd_devs[0] == NULL)
+ panic("irq_handler: no ioc0");
+#endif
+ /* Get the current interrupt state */
+ status = ioc_irq_status_full(ioc_cd.cd_devs[0]);
+
+ /* Get interrupt-disabling back to the IOC */
+ s = splhigh();
+ int_on();
+
+#if 0
+ printf("*");
+#endif
+ uvmexp.intrs++;
+
+ stray = 1;
+ /* Find the highest-priority requested interrupt. */
+ for (h = irq_list_head.lh_first;
+ h != NULL && h->ipl > s;
+ h = h->link.le_next)
+ if (h->enabled && ((status & h->mask) != 0)) {
+ splx(h->ipl);
+#if 0
+ printf("IRQ %d...", h->irqnum);
+#endif
+ if (h->mask & IOC_IRQ_CLEARABLE_MASK)
+ ioc_irq_clear(ioc_cd.cd_devs[0], h->mask);
+ /* XXX IOEB support needed */
+ if (h->arg == NULL)
+ result = (h->func)(irqf);
+ else
+ result = (h->func)(h->arg);
+ if (result == IRQ_HANDLED) {
+ stray = 0;
+ break; /* XXX handle others? */
+ }
+ if (result == IRQ_MAYBE_HANDLED)
+ stray = 0;
+ }
+
+ if (stray) {
+ panic("Stray IRQ, status = 0x%x, spl = %d, mask = 0x%x",
+ status, s, irqmask[s]);
+ }
+#if 0
+ printf(" handled\n");
+#endif
+ dosoftints(s); /* May lower spl to s + 1, but no lower. */
+
+ int_off();
+ hardsplx(s);
+}
+
+struct irq_handler *
+irq_establish(int irqnum, int ipl, int (*func)(void *), void *arg)
+{
+ struct irq_handler *h, *new;
+
+#ifdef DIAGNOSTIC
+ if (irqnum >= NIRQ)
+ panic("irq_register: bad irq: %d", irqnum);
+#endif
+ MALLOC(new, struct irq_handler *, sizeof(struct irq_handler),
+ M_DEVBUF, M_WAITOK);
+ new->irqnum = irqnum;
+ new->mask = 1 << irqnum; /* XXX unix BP etc */
+ new->ipl = ipl;
+ new->func = func;
+ new->arg = arg;
+ new->enabled = 0;
+ if (irq_list_head.lh_first == NULL ||
+ irq_list_head.lh_first->ipl <= ipl)
+ /* XXX This shouldn't need to be a special case */
+ LIST_INSERT_HEAD(&irq_list_head, new, link);
+ else {
+ for (h = irq_list_head.lh_first;
+ h->link.le_next != NULL && h->link.le_next->ipl > ipl;
+ h = h->link.le_next);
+ LIST_INSERT_AFTER(h, new, link);
+ }
+ if (new->mask & IOC_IRQ_CLEARABLE_MASK)
+ ioc_irq_clear(ioc_cd.cd_devs[0], new->mask);
+ /* XXX IOEB support needed */
+ irq_genmasks();
+ return new;
+}
+
+char const *
+irq_string(struct irq_handler *h)
+{
+
+ return irqnames[h->irqnum];
+}
+
+void
+irq_disable(struct irq_handler *h)
+{
+ int s;
+
+ s = splhigh();
+ h->enabled = 0;
+ irq_genmasks();
+ splx(s);
+}
+
+void
+irq_enable(struct irq_handler *h)
+{
+ int s;
+
+ s = splhigh();
+ h->enabled = 1;
+ irq_genmasks();
+ splx(s);
+}
+
+
+void irq_genmasks()
+{
+ struct irq_handler *h;
+ int s, i;
+
+ /* Paranoia? */
+ s = splhigh();
+ /* Disable anything we don't understand */
+ for (i = 0; i < NIPL; i++)
+ irqmask[i] = 0;
+ /* Enable interrupts in levels lower than their own */
+ for (h = irq_list_head.lh_first; h != NULL; h = h->link.le_next)
+ if (h->enabled) {
+ if ((h->mask & irqmask[IPL_NONE]) == h->mask)
+ /* Shared interrupt -- use lowest priority. */
+ for (i = h->ipl; i < NIPL; i++)
+ irqmask[i] &= ~h->mask;
+ else
+ for (i = 0; i < h->ipl; i++)
+ irqmask[i] |= h->mask;
+ }
+ splx(s);
+}
+
+int
+raisespl(int s)
+{
+
+ if (s > current_spl)
+ return splx(s);
+ else
+ return current_spl;
+}
+
+int
+lowerspl(int s)
+{
+
+ if (s < current_spl)
+ return splx(s);
+ else
+ return current_spl;
+}
+
+int
+splx(int s)
+{
+
+ if (current_spl > s)
+ dosoftints(s);
+ return hardsplx(s);
+}
+
+int
+hardsplx(int s)
+{
+ int was;
+
+ int_off();
+ was = current_spl;
+ /* Don't try this till we've found the IOC */
+ /*
+ * XXX Note that second check should be redundant, but config_attach
+ * changes cd_ndevs before cd_devs, and can call up (via malloc) in
+ * the meantime.
+ */
+ if (ioc_cd.cd_ndevs > 0 && ioc_cd.cd_devs != NULL &&
+ ioc_cd.cd_devs[0] != NULL)
+ ioc_irq_setmask(ioc_cd.cd_devs[0], irqmask[s]);
+ current_spl = s;
+ return was; /* Restore interrupt state */
+}
diff --git a/sys/arch/arm26/arm26/locore.S b/sys/arch/arm26/arm26/locore.S
new file mode 100644
index 00000000000..2d8b2053f13
--- /dev/null
+++ b/sys/arch/arm26/arm26/locore.S
@@ -0,0 +1,398 @@
+/* $NetBSD: locore.S,v 1.1 2000/05/09 21:55:56 bjh21 Exp $ */
+/*
+ * Copyright (c) 1998, 2000 Ben Harris
+ * Copyright (C) 1994-1997 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.
+ */
+/* This file is part of NetBSD/arm26 -- a port of NetBSD to ARM2/3 machines. */
+/*
+ * locore.S - the (physical) start of the kernel and low-level handlers
+ */
+/* Note that the actual kernel startup is in start.c */
+
+#include <machine/asm.h>
+
+RCSID("$NetBSD: locore.S,v 1.1 2000/05/09 21:55:56 bjh21 Exp $")
+
+#include <sys/syscall.h>
+#include <machine/frame.h>
+#include <machine/cpu.h>
+#include <machine/armreg.h>
+#include "assym.h"
+
+#include "opt_cputypes.h"
+
+fp .req r11
+ip .req r12
+sp .req r13
+lr .req r14
+pc .req r15
+
+
+/*
+ * MODE_CHANGE_NOP should be inserted between a mode change and a
+ * banked register (R8--R15) access.
+ */
+#if defined(CPU_ARM2) || defined(CPU_ARM250)
+#define MODE_CHANGE_NOP mov r0, r0
+#else
+#define MODE_CHANGE_NOP /* Data sheet says ARM3 doesn't need it */
+#endif
+
+/*
+ * USR_LDM_NOP should be inserted between an LDM to the user bank
+ * and a read from a banked register. (ARM DS sec 6.6.4)
+ */
+#define USR_LDM_NOP mov r0, r0
+
+ .text
+ .balign 4
+
+/*
+ * This is for kvm_mkdb, and should be the address of the beginning
+ * of the kernel text segment (not necessarily the same as kernbase).
+ */
+
+ .global _C_LABEL(kernel_text)
+_C_LABEL(kernel_text):
+ b _C_LABEL(start) /* Just in case the linker loses it */
+
+/*
+ * Trap handlers
+ *
+ * These take an exception and get up into a state to enter the kernel
+ * proper. This currently involves fixing up the return address (to
+ * point to the faulting instruction in all cases), pushing a
+ * trapframe onto the stack, calling the C handler restoring the
+ * (possibly modified) trapframe and returning to userland.
+ */
+#define TRAP_REGS r0-r14
+ .macro HANDLER handler, lr_fixup
+ sub lr, lr, #\lr_fixup /* Compensate for prefetch */
+ sub sp, sp, #TF_SIZE /* Adjust SP */
+ str lr, [sp, #TF_R15] /* Push return address */
+ stmia sp, {TRAP_REGS}^ /* Push user mode registers */
+
+ mov r0, sp /* Supply handler with argument */
+ tst lr, #R15_MODE /* If the trap was from USR mode... */
+ moveq fp, #0 /* ... this is the end of the stack */
+ bl \handler
+
+/*
+ * AST handling stuff. We have to disable IRQs between loading the
+ * flag and returning to user mode, since otherwise an IRQ might
+ * happen in the interim and set the flag again. For simplicity, we
+ * just leave IRQs off throughout (ast_handler will re-enable them).
+ */
+ ldr lr, [sp, #TF_R15] /* Pull return address and PSR */
+ tst lr, #R15_MODE /* Was trap in USR mode? */
+ bne 3f /* If not, return */
+ ldr r4, Lastpending
+1:
+ ldr r1, [r4]
+ cmp r1, #0 /* AST pending? */
+ bne 2f /* If not, return */
+ mov r0, sp /* Reuse old trapframe */
+ bl _C_FUNC(ast_handler) /* Handle AST */
+ b 1b /* Try again */
+
+2:
+ ldr lr, [sp, #TF_R15] /* Pull return address */
+3: /* ... which we may have done above */
+ ldmia sp, {TRAP_REGS}^ /* Restore USR mode registers */
+ USR_LDM_NOP
+ add sp, sp, #TF_SIZE /* Adjust SP */
+ movs pc, lr
+ .endm
+
+Lastpending:
+ .word _C_LABEL(astpending)
+ .global reset_entry
+reset_entry:
+ adr r0, Lreset_panicmsg
+ bl _C_LABEL(panic)
+ /* NOTREACHED */
+Lreset_panicmsg:
+ .asciz "Reset handler called. Branch through zero?"
+ .balign 4
+
+ .global undefined_entry
+undefined_entry:
+ HANDLER _C_FUNC(undefined_handler), 4
+
+ .global swi_entry
+swi_entry:
+ HANDLER _C_FUNC(swi_handler), 4
+
+ .global prefetch_abort_entry
+prefetch_abort_entry:
+ HANDLER _C_FUNC(prefetch_abort_handler), 4
+
+ .global data_abort_entry
+data_abort_entry:
+ HANDLER _C_FUNC(data_abort_handler), 8
+
+ .global address_exception_entry
+address_exception_entry:
+ HANDLER _C_FUNC(address_exception_handler), 8
+
+/*
+ * The stack frame messing is different here since we're handling an
+ * irqframe, not a trapframe. IRQ handlers generally don't need to
+ * get at the contents of user registers (except R15), so we leave
+ * them to be saved by irq_handler's prologue. On the other hand,
+ * IRQs can happen in SVC mode, and we need to do a bit of juggling to
+ * save R14_svc before we enter the IRQ handler.
+ *
+ * The "R15" slot in the irqframe hols the value of R15 to return to.
+ * Conceptually, IRQs happen at the start of an instruction.
+ */
+
+#define IRQ_REGS_SVC r0-r3, r12, r14
+#define IRQ_REGS_USR r0-r3, r11-r12
+ .global irq_entry
+irq_entry:
+ sub r14, r14, #4 /* Fix up return address */
+ tst r14, #(R15_MODE)
+ beq Lirq_from_usr
+ teqp r15, #(R15_IRQ_DISABLE | R15_MODE_SVC)
+ MODE_CHANGE_NOP
+ sub sp, sp, #IF_SIZE /* mark space for irqframe */
+ stmia sp, {IRQ_REGS_SVC} /* save SVC mode regs */
+ mov r0, sp /* copy frame pointer */
+ teqp r15, #(R15_IRQ_DISABLE | R15_MODE_IRQ)
+ MODE_CHANGE_NOP
+ str lr, [r0, #IF_R15] /* Finally, save return addr */
+ teqp r15, #(R15_IRQ_DISABLE | R15_MODE_SVC)
+ MODE_CHANGE_NOP
+
+ mov r0, sp
+ bl _C_FUNC(irq_handler)
+
+ mov r0, sp
+ teqp r15, #(R15_IRQ_DISABLE | R15_MODE_IRQ)
+ MODE_CHANGE_NOP
+ ldr lr, [r0, #IF_R15] /* Retrieve return address */
+ teqp r15, #(R15_IRQ_DISABLE | R15_MODE_SVC)
+ MODE_CHANGE_NOP
+ ldmia sp, {IRQ_REGS_SVC} /* Restore SVC registers */
+ add sp, sp, #IF_SIZE /* Free irqframe */
+ teqp r15, #(R15_IRQ_DISABLE | R15_MODE_IRQ)
+ MODE_CHANGE_NOP
+ movs r15, lr /* and return. */
+
+Lirq_from_usr:
+ teqp r15, #(R15_IRQ_DISABLE | R15_MODE_SVC)
+ MODE_CHANGE_NOP
+ sub sp, sp, #IF_SIZE /* mark space for irqframe */
+ stmia sp, {IRQ_REGS_USR} /* save SVC/USR mode regs */
+ mov r0, sp /* copy frame pointer */
+ teqp r15, #(R15_IRQ_DISABLE | R15_MODE_IRQ)
+ MODE_CHANGE_NOP
+ str lr, [r0, #IF_R15] /* Finally, save return addr */
+ teqp r15, #(R15_IRQ_DISABLE | R15_MODE_SVC)
+ MODE_CHANGE_NOP
+
+ mov fp, #0 /* This is the top of the stack */
+ mov r0, sp
+ bl _C_FUNC(irq_handler)
+
+ ldr r0, Lastpending
+ ldr r0, [r0]
+ cmp r0, #0
+ bne Lirq_to_ast
+ mov r0, sp
+ teqp r15, #(R15_IRQ_DISABLE | R15_MODE_IRQ)
+ MODE_CHANGE_NOP
+ ldr lr, [r0, #IF_R15] /* Retrieve return address */
+ teqp r15, #(R15_IRQ_DISABLE | R15_MODE_SVC)
+ MODE_CHANGE_NOP
+ ldmia sp, {IRQ_REGS_USR} /* Restore SVC/USR registers */
+ add sp, sp, #IF_SIZE /* Free irqframe */
+ teqp r15, #(R15_IRQ_DISABLE | R15_MODE_IRQ)
+ MODE_CHANGE_NOP
+ movs r15, lr /* and return. */
+
+Lirq_to_ast:
+ ldmia sp, {IRQ_REGS_USR} /* Slurp up irqframe */
+ sub sp, sp, #(TF_SIZE - IF_SIZE)
+ stmia sp, {TRAP_REGS}^ /* Spit out trapframe */
+
+ mov fp, #0
+Last_again:
+ mov r0, sp
+ bl _C_FUNC(ast_handler)
+
+ teqp r15, #(R15_IRQ_DISABLE | R15_MODE_SVC)
+ ldr r0, Lastpending
+ ldr r0, [r0]
+ cmp r0, #0
+ bne Last_again
+ ldr lr, [sp, #TF_R15] /* Pull return address */
+ ldmia sp, {TRAP_REGS}^ /* Restore USR mode registers */
+ USR_LDM_NOP
+ add sp, sp, #TF_SIZE /* Adjust SP */
+ movs pc, lr
+
+ENTRY(atomic_set_bit)
+ /* disable interrupts */
+ /* Note that this is evil and only works due to prefetching */
+ mov r2, r15
+ orrs r15, r2, #(R15_IRQ_DISABLE | R15_FIQ_DISABLE)
+ ldr r2, [r0]
+ orr r2, r2, r1
+ str r2, [r0]
+ /* restore interrupt state and return */
+ movs pc, lr
+ENTRY(atomic_clear_bit)
+ /* disable interrupts */
+ /* Note that this is evil and only works due to prefetching */
+ mov r2, r15
+ orrs r15, r2, #(R15_IRQ_DISABLE | R15_FIQ_DISABLE)
+ ldr r2, [r0]
+ bic r2, r2, r1
+ str r2, [r0]
+ /* restore interrupt state and return */
+ movs pc, lr
+
+ENTRY(set_r13_irq)
+ /* register_t set_r13_irq(register_t r13_irq) */
+ /* XXX Is enabling FIQs OK? */
+ teqp r15, #(R15_IRQ_DISABLE | R15_MODE_IRQ)
+ mov r1, r0
+ mov r0, r13
+ mov r13, r1
+ teqp r15, #(R15_IRQ_DISABLE | R15_MODE_SVC)
+ MODE_CHANGE_NOP
+ movs r15, lr
+
+ /*
+ * These are grotty, and very non-APCS. The CPU interrupt status
+ * is part of the state that's restored on function exit, so the
+ * effect of these only persists until then.
+ */
+ENTRY(int_on)
+ bics r15, r14, #(R15_IRQ_DISABLE | R15_FIQ_DISABLE)
+ENTRY(int_off)
+ orrs r15, r14, #(R15_IRQ_DISABLE)
+
+ /*
+ * Low-level context-switch operation. cpu_switch() is in C -- this
+ * just handles the bits that can't be done in C.
+ *
+ * void cpu_loswitch(struct switchframe **fromp,
+ * struct switchframe *to)
+ *
+ * We leave a switchframe on the stack pointed to by fromp,
+ * and return to the context in to. This should be called in
+ * splhigh();
+ */
+ENTRY(cpu_loswitch)
+ mov r2, sp /* Temporary stack pointer */
+ stmfd r2!, {r4-r11, r13-r14} /* Save all relevant registers */
+ str r2, [r0] /* Save switchframe pointer */
+ ldmfd r1, {r4-r11, r13-r14} /* Restore from old switchframe */
+ movs pc, r14 /* and return */
+
+ /*
+ * This funny little routine implements starting a process.
+ * It's called by cpu_loswitch returning from a faked
+ * switchframe set up by cpu_fork() and cpu_set_kpc(), and gets
+ * the function it's meant to enter passed in R4 with its
+ * argument in R5. If that function's NULL, or if it returns,
+ * we hope there's a trapframe on the stack that'll take us
+ * back to userland.
+ */
+ENTRY(proc_trampoline)
+ mov fp, #0 /* Tie knot in top of stack */
+ mov r0, #0
+ bl _C_FUNC(splx) /* spl0() */
+ cmp r4, #0 /* Function to call? */
+ beq Lproc_trampoline_nofunc
+ mov r0, r5
+ mov r14, pc /* Save return address */
+ mov pc, r4 /* Call function */
+Lproc_trampoline_nofunc:
+ ldr lr, [sp, #TF_R15] /* Pull return address */
+ ldmia sp, {r0-r14}^ /* Restore USR mode registers */
+ USR_LDM_NOP
+ add sp, sp, #TF_SIZE /* Adjust SP */
+ movs pc, lr
+
+/* int setjmp(label_t *); */
+ENTRY(setjmp)
+ stmia r0, {r4-r11, r13-r14} /* Save relevant registers */
+ mov r0, #0 /* Return 0 */
+ movs pc, lr
+
+/* void longjmp(label_t *); */
+ENTRY(longjmp)
+ ldmia r0, {r4-r11, r13-r14} /* Restore registers */
+ mov r0, #1 /* Return 1 through longjmp */
+ movs pc, lr
+
+/* Enter DDB -- shove registers in a trapframe first */
+/* void cpu_Debugger(void); */
+ENTRY(cpu_Debugger)
+ stmfd r13!, {r14}
+ stmfd r13!, {r0-r15} /* Save all SVC-mode regs */
+ mov r1, r13
+ mov r0, #0
+ bl _C_FUNC(kdb_trap)
+ add r13, r13, #(4 * 16)
+ ldmfd r13!, {pc}^
+
+/*
+ * Signal trampoline; copied to top of user stack.
+ */
+
+ENTRY_NP(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, #SF_SC
+ swi SYS___sigreturn14
+
+/* Well if that failed we better exit quick ! */
+
+ swi SYS_exit
+ b . - 8
+
+ .align 0
+ .global _C_LABEL(esigcode)
+_C_LABEL(esigcode):
diff --git a/sys/arch/arm26/arm26/machdep.c b/sys/arch/arm26/arm26/machdep.c
new file mode 100644
index 00000000000..fc6ede31e2e
--- /dev/null
+++ b/sys/arch/arm26/arm26/machdep.c
@@ -0,0 +1,205 @@
+/* $NetBSD: machdep.c,v 1.1 2000/05/09 21:55:56 bjh21 Exp $ */
+
+/*-
+ * Copyright (c) 1998 Ben Harris
+ * 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.
+ */
+/* This file is part of NetBSD/arm26 -- a port of NetBSD to ARM2/3 machines. */
+/*
+ * machdep.c -- standard machine-dependent functions
+ */
+
+#include <sys/param.h>
+
+__KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.1 2000/05/09 21:55:56 bjh21 Exp $");
+
+#include <sys/buf.h>
+#include <sys/mbuf.h>
+#include <sys/reboot.h>
+#include <sys/systm.h>
+#include <vm/vm.h>
+#include <vm/vm_kern.h>
+
+#include <machine/memcreg.h>
+
+int physmem;
+char machine[] = MACHINE;
+char machine_arch[] = MACHINE_ARCH;
+char cpu_model[] = "Archimedes";
+
+vm_map_t exec_map = NULL;
+vm_map_t phys_map = NULL;
+vm_map_t mb_map = NULL; /* and ever more shall be so */
+
+void
+cpu_reboot(howto, b)
+ int howto;
+ char *b;
+{
+ /* FIXME This needs much more sophistication */
+ splhigh();
+ /* XXX Temporary measure */
+ howto |= RB_HALT;
+ if (howto & RB_HALT) {
+ printf("system halted\n");
+ for (;;);
+ } else {
+ printf("rebooting...");
+ /*
+ * On a real reset, the ROM is mapped into address
+ * zero. On RISC OS 3.11 at least, this can be faked
+ * by copying the first instruction in the ROM to
+ * address zero -- it immediately branches into the
+ * ROM at its usual address, and hence would remove
+ * the ROM mapped at zero anyway.
+ *
+ * In order to convince RISC OS to do a hard reset, we
+ * fake a *FX 200,2. Note that I don't know if this
+ * will work on RISC OS <3.10. This is slightly
+ * suboptimal as it causes RISC OS to zero the whole
+ * of RAM on startup (farewell, message buffer). If
+ * anyone can tell me how to fake a control-reset in
+ * software, I'd be most grateful.
+ */
+ *(volatile u_int8_t *)0x9c2 = 2; /* Zero page magic */
+ *(volatile u_int32_t *)0
+ = *(volatile u_int32_t *)MEMC_ROM_LOW_BASE;
+ asm volatile("movs pc, #3"); /* reboot in SVC mode */
+ }
+ panic("cpu_reboot failed");
+}
+
+/*
+ * This is provided because GCC seems to generate calls to it.
+ */
+void abort __P((void)) __attribute__((__noreturn__));
+
+void
+abort()
+{
+
+ panic("abort() called -- noreturn function returned?");
+}
+
+/*
+ * cpu_startup: allocate memory for variable-sized tables,
+ * initialize cpu, and do autoconfiguration.
+ */
+void
+cpu_startup()
+{
+ int i, base, residual;
+ vaddr_t minaddr, maxaddr;
+ vsize_t size;
+ char pbuf[9];
+
+ /* Stuff to do here: */
+ /* initmsgbuf() is called from start() */
+
+ printf("%s", version);
+ format_bytes(pbuf, sizeof(pbuf), ctob(physmem));
+ printf("total memory = %s\n", pbuf);
+
+ /* allocsys() is called from start() */
+
+ /* Various boilerplate memory allocations. */
+
+ /*
+ * Allocate virtual address space for file I/O buffers.
+ * Note they are different than the array of headers, 'buf',
+ * and usually occupy more virtual memory than physical.
+ */
+ size = MAXBSIZE * nbuf;
+ if (uvm_map(kernel_map, (vaddr_t *) &buffers, round_page(size),
+ NULL, UVM_UNKNOWN_OFFSET,
+ UVM_MAPFLAG(UVM_PROT_NONE, UVM_PROT_NONE, UVM_INH_NONE,
+ UVM_ADV_NORMAL, 0)) != KERN_SUCCESS)
+ panic("cpu_startup: cannot allocate VM for buffers");
+ base = bufpages / nbuf;
+ residual = bufpages % nbuf;
+ for (i = 0; i < nbuf; i++) {
+ vsize_t curbufsize;
+ vaddr_t curbuf;
+ struct vm_page *pg;
+
+ /*
+ * Each buffer has MAXBSIZE bytes of VM space allocated. Of
+ * that MAXBSIZE space, we allocate and map (base+1) pages
+ * for the first "residual" buffers, and then we allocate
+ * "base" pages for the rest.
+ */
+ curbuf = (vaddr_t) buffers + (i * MAXBSIZE);
+ curbufsize = NBPG * ((i < residual) ? (base+1) : base);
+
+ while (curbufsize) {
+ pg = uvm_pagealloc(NULL, 0, NULL, 0);
+ if (pg == NULL)
+ panic("cpu_startup: not enough memory for "
+ "buffer cache");
+ pmap_kenter_pgs(curbuf, &pg, 1);
+ curbuf += PAGE_SIZE;
+ curbufsize -= PAGE_SIZE;
+ }
+ }
+
+ /*
+ * Allocate a submap for exec arguments. This map effectively
+ * limits the number of processes exec'ing at any time.
+ */
+ minaddr = kernel_map->min_offset;
+ exec_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr,
+ NCARGS, VM_MAP_PAGEABLE, FALSE, NULL);
+
+ /*
+ * Allocate a submap for physio
+ */
+ phys_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr,
+ 512 * 1024, 0, FALSE, NULL);
+
+ /*
+ * No need to allocate an mbuf cluster submap. Mbuf clusters
+ * are allocated via the pool allocator, and we use direct-mapped
+ * pool pages.
+ */
+
+ format_bytes(pbuf, sizeof(pbuf), ptoa(uvmexp.free));
+ printf("avail memory = %s\n", pbuf);
+ format_bytes(pbuf, sizeof(pbuf), bufpages * NBPG);
+ printf("using %d buffers containing %s of memory\n", nbuf, pbuf);
+
+ /*
+ * Set up buffers, so they can be used to read disk labels.
+ */
+ bufinit();
+
+#if 0
+ /* Test exception handlers */
+ asm(".word 0x06000010"); /* undefined instruction */
+ asm("swi 0"); /* SWI */
+ (*(void (*)(void))(0x00008000))(); /* prefetch abort */
+ *(volatile int *)(0x00008000) = 0; /* data abort */
+ *(volatile int *)(0x10000000) = 0; /* address exception */
+#endif
+}
diff --git a/sys/arch/arm26/arm26/md_root.c b/sys/arch/arm26/arm26/md_root.c
new file mode 100644
index 00000000000..b3ef0712840
--- /dev/null
+++ b/sys/arch/arm26/arm26/md_root.c
@@ -0,0 +1,88 @@
+/* $NetBSD: md_root.c,v 1.1 2000/05/09 21:55:56 bjh21 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>
+
+__RCSID("$NetBSD: md_root.c,v 1.1 2000/05/09 21:55:56 bjh21 Exp $");
+
+#include <sys/systm.h>
+#include <sys/reboot.h>
+
+#include <dev/md.h>
+
+#include "opt_mdsize.h"
+
+extern int boothowto;
+
+#ifndef MINIROOTSIZE
+#define MINIROOTSIZE 512
+#endif
+
+#define ROOTBYTES (MINIROOTSIZE << DEV_BSHIFT)
+
+/*
+ * This array will be patched to contain a file-system image.
+ * See the program mdsetimage(8) for details.
+ */
+u_int32_t md_root_size = ROOTBYTES;
+char md_root_image[ROOTBYTES] = "|This is the root ramdisk!\n";
+
+/*
+ * This is called during autoconfig.
+ */
+void
+md_attach_hook(unit, md)
+ int unit;
+ struct md_conf *md;
+{
+ char pbuf[9];
+
+ if (unit == 0) {
+ /* Setup root ramdisk */
+ md->md_addr = (caddr_t)md_root_image;
+ md->md_size = (size_t)md_root_size;
+ md->md_type = MD_KMEM_FIXED;
+ format_bytes(pbuf, sizeof(pbuf), ROOTBYTES);
+ printf("md%d: internal %s image area\n", unit, pbuf);
+ }
+}
+
+/*
+ * This is called during open (i.e. mountroot)
+ */
+void
+md_open_hook(unit, md)
+ int unit;
+ struct md_conf *md;
+{
+ if (unit == 0) {
+ /* The root ramdisk only works single-user. */
+ boothowto |= RB_SINGLE;
+ }
+}
diff --git a/sys/arch/arm26/arm26/mem.c b/sys/arch/arm26/arm26/mem.c
new file mode 100644
index 00000000000..10f93e8049a
--- /dev/null
+++ b/sys/arch/arm26/arm26/mem.c
@@ -0,0 +1,214 @@
+/* $NetBSD: mem.c,v 1.1 2000/05/09 21:55:56 bjh21 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 <machine/memcreg.h>
+
+#include <vm/vm.h>
+#if defined(UVM)
+#include <uvm/uvm_extern.h>
+#endif
+
+caddr_t zeropage;
+int physlock;
+
+#define mmread mmrw
+#define mmwrite mmrw
+cdev_decl(mm);
+
+/*ARGSUSED*/
+int
+mmopen(dev, flag, mode, p)
+ dev_t dev;
+ int flag, mode;
+ struct proc *p;
+{
+ switch (minor(dev)) {
+ default:
+ break;
+ }
+ return (0);
+}
+
+/*ARGSUSED*/
+int
+mmclose(dev, flag, mode, p)
+ dev_t dev;
+ int flag, mode;
+ struct proc *p;
+{
+
+ return (0);
+}
+
+/*ARGSUSED*/
+int
+mmrw(dev, uio, flags)
+ dev_t dev;
+ struct uio *uio;
+ int flags;
+{
+ register vm_offset_t v;
+ register int c;
+ register struct iovec *iov;
+ int error = 0;
+
+ while (uio->uio_resid > 0 && error == 0) {
+ iov = uio->uio_iov;
+ if (iov->iov_len == 0) {
+ uio->uio_iov++;
+ uio->uio_iovcnt--;
+ if (uio->uio_iovcnt < 0)
+ panic("mmrw");
+ continue;
+ }
+ switch (minor(dev)) {
+
+ /* minor device 0 is physical memory */
+ case 0:
+ /*
+ * On arm26, there's no need to map in the
+ * relevant page, as we've got physical memory
+ * mapped in at another address and can just
+ * use that.
+ */
+ /* XXX Should use pmap_find(). */
+ if (v < 0 ||
+ (caddr_t)v + c > MEMC_PHYS_BASE + ptoa(physmem))
+ return EFAULT;
+ error = uiomove(MEMC_PHYS_BASE + uio->uio_offset,
+ uio->uio_resid, uio);
+ continue;
+
+ /* minor device 1 is kernel memory */
+ case 1:
+ v = uio->uio_offset;
+ c = min(iov->iov_len, MAXPHYS);
+ /* Allow reading from physically mapped space. */
+ if (((caddr_t)v >= MEMC_PHYS_BASE &&
+ (caddr_t)v + c <
+ MEMC_PHYS_BASE + ptoa(physmem)) ||
+ uvm_kernacc((caddr_t)v, c,
+ uio->uio_rw == UIO_READ ?
+ B_READ : B_WRITE))
+ error = uiomove((caddr_t)v, c, uio);
+ else
+ return (EFAULT);
+ 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(NBPG, M_TEMP, M_WAITOK);
+ bzero(zeropage, NBPG);
+ }
+ c = min(iov->iov_len, NBPG);
+ error = uiomove(zeropage, c, uio);
+ continue;
+
+ default:
+ return (ENXIO);
+ }
+ if (error)
+ break;
+ (caddr_t)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;
+{
+ int ppn;
+
+ /*
+ * /dev/mem is the only one that makes sense through this
+ * interface. For /dev/kmem any physaddr we return here
+ * could be transient and hence incorrect or invalid at
+ * a later time. /dev/null just doesn't make any sense
+ * and /dev/zero is a hack that is handled via the default
+ * pager in mmap().
+ */
+ if (minor(dev) != 0)
+ return (-1);
+
+ /* minor device 0 is physical memory */
+
+ /* XXX This may botch our cacheing assumptions. Do we care? */
+ ppn = atop(off);
+ if (ppn >= 0 && ppn < physmem )
+ return ppn;
+ return -1;
+}
diff --git a/sys/arch/arm26/arm26/pmap.c b/sys/arch/arm26/arm26/pmap.c
new file mode 100644
index 00000000000..b74603ee159
--- /dev/null
+++ b/sys/arch/arm26/arm26/pmap.c
@@ -0,0 +1,930 @@
+/* $NetBSD: pmap.c,v 1.1 2000/05/09 21:55:56 bjh21 Exp $ */
+/*-
+ * Copyright (c) 1997, 1998, 2000 Ben Harris
+ * 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.
+ */
+/* This file is part of NetBSD/arm26 -- a port of NetBSD to ARM2/3 machines. */
+
+/*
+ * pmap.c - Interfacing the MEMC to the BSD VM system.
+ */
+
+/*
+ * The MEMC has variable page sizes, and moreover it's necessary to
+ * change the page size depending on the amount of DRAM under the
+ * MEMC's control. This code currently only handles 32k pages.
+ *
+ * The bottom 32k of logically-mapped RAM is zero page, and is mapped
+ * in all address spaces (though it's not accessible in user mode).
+ * This contains interrupt vectors, and probably context-switching
+ * code. It doesn't appear in any pmap as it's never unmapped.
+ *
+ * Wired pages are an interesting proposition. We aren't allowed to
+ * let page faults on them reach the MI fault handler, and in general
+ * we shouldn't let them get dropped from the map in the MEMC at all.
+ * This is tricky when we have kernel and user space shared, as we
+ * have to ensure that no wired page in the kernel is mapped by any
+ * user process or vice versa.
+ */
+
+/*
+ * On an ARM3, the cache must be flushed whenever:
+ *
+ * 1 - We remove read access to a page, since we need to ensure reads
+ * will abort. Write access doesn't matter since the cache is
+ * write-through.
+ *
+ * 2 - We write to a page and need to be able to read it elsewhere.
+ * Since the MEMC can only map each page once, this only occurs
+ * without case one when one of the accesses is physical and the other
+ * logical, which I think only happens when doing odd things with
+ * /dev/mem. In all other cases, a physical page should only be
+ * accessed through one of its mappings (virtual if it has one,
+ * physical if it doesn't). pmap_find is useful for this.
+ */
+
+/*
+ * We assume the following rules apply:
+ *
+ * Accesses to memory managed by user pmaps will always be from USR
+ * mode, or from LDR/STR with the T bit set (which looks the same to
+ * the MEMC).
+ *
+ * Accesses to memory managed by the kernel pmap will always be from
+ * SVC mode.
+ *
+ * Breaking these rules (especially the first) is likely to upset
+ * referenced/modified emulation.
+ */
+
+#include "opt_cputypes.h"
+#include "opt_ddb.h"
+#include "arcvideo.h"
+
+#include <sys/param.h>
+
+__KERNEL_RCSID(0, "$NetBSD: pmap.c,v 1.1 2000/05/09 21:55:56 bjh21 Exp $");
+
+#include <sys/kernel.h> /* for cold */
+#include <sys/malloc.h>
+#define __POOL_EXPOSE /* We need to allocate one statically. */
+#include <sys/pool.h>
+#include <sys/systm.h>
+
+#include <vm/vm.h>
+#include <vm/pmap.h>
+#include <vm/vm_kern.h>
+
+#include <machine/machdep.h>
+#include <machine/memcreg.h>
+
+#include <arch/arm26/arm26/cpuvar.h>
+
+/*
+ * We store all the mapping information in the pv_table, and the pmaps
+ * just contain references to it. This is suggested in the Daemon
+ * Book as a sensible thing to do on systems without real page tables.
+ */
+struct pv_entry {
+ struct pv_entry *pv_next;
+ pmap_t pv_pmap;
+ int pv_ppn;
+ int pv_lpn;
+ u_int32_t pv_activate; /* MEMC command to activate mapping */
+ u_int32_t pv_deactivate;/* MEMC command to deactivate mapping */
+ vm_prot_t pv_prot; /* requested protection */
+ u_int8_t pv_ppl; /* Actual PPL */
+ u_int8_t pv_vflags; /* Per-mapping flags */
+#define PV_WIRED 0x01 /* This is a wired mapping */
+ u_int8_t pv_pflags; /* Per-physical-page flags */
+#define PV_REFERENCED 0x01
+#define PV_MODIFIED 0x02
+};
+
+struct pmap {
+ int pm_count; /* Reference count */
+ int pm_flags;
+#define PM_ACTIVE 0x00000001
+ struct pv_entry *pm_entries[1024];
+};
+
+/*
+ * All physical pages must map to _some_ logical page, even though
+ * they can have all access disabled. This means we need a logical
+ * page reseved for this purpose. We use the last page of kernel VM.
+ */
+#define PMAP_DEAD_PAGE (atop(VM_MAX_KERNEL_ADDRESS) - 1)
+#define PMAP_UNMAP_ENTRY_32K(ppn) \
+ MEMC_TRANS_ENTRY_32K(ppn, PMAP_DEAD_PAGE, MEMC_PPL_NOACCESS)
+#if 0
+{} /* shut up emacs */
+#endif
+
+/*
+ * Global array of pv_entries. Should be dynamically allocated based on
+ * number of physical pages in system, or something.
+ */
+struct pv_entry pv_table[1024];
+
+/* Kernel pmap -- statically allocated to make life slightly less odd. */
+
+struct pmap kernel_pmap_store;
+
+static boolean_t pmap_initialised = FALSE;
+
+static struct pool pmap_pool_store;
+static struct pool *pmap_pool = &pmap_pool_store;
+
+static pmap_t active_pmap;
+
+static void pv_update(struct pv_entry *);
+static struct pv_entry *pv_alloc(void);
+static void pv_free(struct pv_entry *pv);
+static struct pv_entry *pv_get(pmap_t pmap, int ppn, int lpn);
+static void pv_release(pmap_t pmap, int ppn, int lpn);
+
+static caddr_t pmap_find(paddr_t);
+
+static void pmap_update_page(int);
+
+/*
+ * No-one else wanted to take responsibility for the MEMC control register,
+ * so it's ended up here.
+ */
+
+static register_t memc_control = 0;
+
+register_t
+update_memc(register_t mask, register_t value)
+{
+ register_t old;
+ int s;
+
+ s = splhigh();
+ old = memc_control;
+ memc_control &= ~mask;
+ memc_control |= value & mask;
+ MEMC_WRITE(memc_control);
+ splx(s);
+ return old;
+}
+
+/*
+ * pmap_bootstrap: first-stage pmap initialisation
+ *
+ * This is called very early, and has to get the pmap system into a
+ * state where pmap_virtual_space and pmap_kenter_pa at least will
+ * work. If we need memory here, we have to work out how to get it
+ * ourselves.
+ */
+void
+pmap_bootstrap(int npages, paddr_t zp_physaddr)
+{
+ int i;
+ struct pmap *pmap;
+
+ /* Set up the kernel's pmap */
+ pmap = pmap_kernel();
+ bzero(pmap, sizeof(*pmap));
+ pmap->pm_count = 1;
+ pmap->pm_flags = PM_ACTIVE; /* Kernel pmap always is */
+ /* pmap_pinit(pmap); */
+ /* Clear the MEMC's page table */
+ /* XXX Maybe we should leave zero page alone? */
+ for (i=0; i < npages; i++)
+ MEMC_WRITE(PMAP_UNMAP_ENTRY_32K(i));
+ bzero(pv_table, sizeof(pv_table));
+ /* TODO: Set up control register? */
+ update_memc(0xffffffff, MEMC_CONTROL | MEMC_CTL_PGSZ_32K |
+ MEMC_CTL_LROMSPD_4N | MEMC_CTL_HROMSPD_4N |
+#if NARCVIDEO > 0
+ MEMC_CTL_RFRSH_FLYBACK | MEMC_CTL_VIDEODMA
+#else
+ MEMC_CTL_RFRSH_CONTIN
+#endif
+ );
+ /* Manually map zero page (it doesn't appear in pmaps) */
+ MEMC_WRITE(MEMC_TRANS_ENTRY_32K(atop(zp_physaddr), 0,
+ MEMC_PPL_NOACCESS));
+}
+
+/*
+ * pmap_init: second stage pmap initialisation.
+ *
+ * Sets up everything that will be needed for normal running. We can
+ * allocate memory in page-rounded chunks with uvm_km_(z)alloc(), or
+ * use the pool allocator. malloc is still taboo.
+ */
+void
+pmap_init()
+{
+
+ pool_init(pmap_pool, sizeof(struct pmap), 0, 0, 0, "pmappool",
+ 0, NULL, NULL, M_VMPMAP);
+ pmap_initialised = 1;
+}
+
+struct pmap *
+pmap_create()
+{
+ struct pmap *pmap;
+
+ pmap = pool_get(pmap_pool, PR_WAITOK);
+ bzero(pmap, sizeof(*pmap));
+ return pmap;
+}
+
+void
+pmap_destroy(pmap_t pmap)
+{
+#ifdef DIAGNOSTIC
+ int i;
+#endif
+
+ if (--pmap->pm_count > 0)
+ return;
+#ifdef DIAGNOSTIC
+ if (pmap->pm_flags & PM_ACTIVE)
+ panic("pmap_destroy: pmap is active");
+ for (i = 0; i < 1024; i++)
+ if (pmap->pm_entries[i] != NULL)
+ panic("pmap_destroy: pmap isn't empty");
+#endif
+ pool_put(pmap_pool, pmap);
+}
+
+void
+pmap_activate(struct proc *p)
+{
+ pmap_t pmap;
+ int i;
+
+ pmap = p->p_vmspace->vm_map.pmap;
+
+ if (pmap == pmap_kernel())
+ return; /* kernel pmap is always active */
+
+#ifdef DIAGNOSTIC
+ if (active_pmap != NULL || (pmap->pm_flags & PM_ACTIVE) != 0)
+ panic("pmap_activate");
+#endif
+
+ active_pmap = pmap;
+ pmap->pm_flags |= PM_ACTIVE;
+ for (i = 0; i < 1024; i++)
+ if (pmap->pm_entries[i] != NULL)
+ MEMC_WRITE(pmap->pm_entries[i]->pv_activate);
+}
+
+void
+pmap_deactivate(struct proc *p)
+{
+ pmap_t pmap;
+ int i;
+
+ pmap = p->p_vmspace->vm_map.pmap;
+
+ if (pmap == pmap_kernel())
+ return; /* kernel pmap is always active */
+
+#ifdef DIAGNOSTIC
+ if (active_pmap != pmap || (pmap->pm_flags & PM_ACTIVE) == 0)
+ panic("pmap_deactivate");
+#endif
+
+ active_pmap = NULL;
+ pmap->pm_flags &=~ PM_ACTIVE;
+ for (i = 0; i < 1024; i++)
+ if (pmap->pm_entries[i] != NULL)
+ MEMC_WRITE(pmap->pm_entries[i]->pv_deactivate);
+ cpu_cache_flush();
+}
+
+void
+pmap_unwire(pmap_t pmap, vaddr_t va)
+{
+ struct pv_entry *pv;
+
+ if (pmap == NULL) return;
+ pv = pmap->pm_entries[atop(va)];
+ if (pv == NULL) return;
+ pv->pv_vflags &= ~PV_WIRED;
+}
+
+void
+pmap_collect(pmap)
+ pmap_t pmap;
+{
+ /* This is allowed to be a no-op. */
+}
+
+void
+pmap_copy(dst_pmap, src_pmap, dst_addr, len, src_addr)
+ pmap_t dst_pmap, src_pmap;
+ vaddr_t dst_addr, src_addr;
+ vsize_t len;
+{
+ /* This is allowed to be a no-op. */
+}
+
+/*
+ * Update the pv_activate and pv_deactivate fields in a pv_entry to
+ * match the rest.
+ */
+static void
+pv_update(struct pv_entry *pv)
+{
+ int ppl;
+ int pflags;
+
+ pflags = pv_table[pv->pv_ppn].pv_pflags;
+ if (pv->pv_pmap == pmap_kernel()) {
+ if (1) {
+ /* Don't risk faults till everything's happy */
+ ppl = MEMC_PPL_NOACCESS;
+ pv_table[pv->pv_ppn].pv_pflags |=
+ PV_REFERENCED | PV_MODIFIED;
+ } else if ((pflags & PV_REFERENCED) && (pflags & PV_MODIFIED))
+ ppl = MEMC_PPL_NOACCESS;
+ else {
+ /*
+ * To keep SVC mode from seeing a page, we
+ * have to unmap it entirely.
+ */
+ pv->pv_ppl = MEMC_PPL_NOACCESS;
+ pv->pv_activate = pv->pv_deactivate =
+ PMAP_UNMAP_ENTRY_32K(pv->pv_ppn);
+ return;
+ }
+ } else {
+ if ((pv->pv_prot & VM_PROT_WRITE) &&
+ (pflags & PV_REFERENCED) && (pflags & PV_MODIFIED))
+ ppl = MEMC_PPL_RDWR;
+ else if ((pv->pv_prot & (VM_PROT_READ | VM_PROT_EXECUTE)) &&
+ (pflags & PV_REFERENCED))
+ ppl = MEMC_PPL_RDONLY;
+ else
+ ppl = MEMC_PPL_NOACCESS;
+ }
+ pv->pv_ppl = ppl;
+ pv->pv_activate = MEMC_TRANS_ENTRY_32K(pv->pv_ppn, pv->pv_lpn, ppl);
+ pv->pv_deactivate = PMAP_UNMAP_ENTRY_32K(pv->pv_ppn);
+}
+
+
+static struct pv_entry *
+pv_alloc()
+{
+ struct pv_entry *pv;
+
+ MALLOC(pv, struct pv_entry *, sizeof(*pv), M_VMPMAP, M_WAITOK);
+ bzero(pv, sizeof(*pv));
+ return pv;
+}
+
+static void
+pv_free(struct pv_entry *pv)
+{
+
+ FREE(pv, M_VMPMAP);
+}
+
+static struct pv_entry *
+pv_get(pmap_t pmap, int ppn, int lpn)
+{
+ struct pv_entry *pv;
+
+ /* If the head entry's free use that. */
+ pv = &pv_table[ppn];
+ if (pv->pv_pmap == NULL)
+ return pv;
+ /* If this mapping exists already, use that. */
+ for (pv = pv; pv != NULL; pv = pv->pv_next)
+ if (pv->pv_pmap == pmap && pv->pv_lpn == lpn)
+ return pv;
+ /* Otherwise, allocate a new entry and link it in after the head. */
+ pv = pv_alloc();
+ pv->pv_next = pv_table[ppn].pv_next;
+ pv_table[ppn].pv_next = pv;
+ return pv;
+}
+
+/*
+ * Release the pv_entry for a mapping. Code derived from hp300 pmap.
+ */
+static void
+pv_release(pmap_t pmap, int ppn, int lpn)
+{
+ struct pv_entry *pv, *npv;
+
+ pv = &pv_table[ppn];
+ /*
+ * 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 && lpn == pv->pv_lpn) {
+ npv = pv->pv_next;
+ if (npv) {
+ /* Pull up first entry from chain. */
+ npv->pv_pflags = pv->pv_pflags;
+ *pv = *npv;
+ pv->pv_pmap->pm_entries[lpn] = pv;
+ pv_free(npv);
+ } else
+ pv->pv_pmap = NULL;
+ } else {
+ for (npv = pv->pv_next; npv; npv = npv->pv_next) {
+ if (pmap == npv->pv_pmap && lpn == npv->pv_lpn)
+ break;
+ pv = npv;
+ }
+#ifdef DIAGNOSTIC
+ if (npv == NULL)
+ panic("pv_release");
+#endif
+ pv->pv_next = npv->pv_next;
+ pv_free(npv);
+ }
+ pmap->pm_entries[lpn] = NULL;
+}
+
+
+/*
+ * Insert the given physical page (pa) at the specified virtual
+ * address (va) in the target physical map with the protection
+ * requested.
+ *
+ * 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.
+ */
+int
+pmap_enter(pmap_t pmap, vaddr_t va, paddr_t pa, vm_prot_t prot, int flags)
+{
+ int ppn, lpn, s;
+ struct pv_entry *pv;
+
+ ppn = atop(pa); lpn = atop(va);
+
+#if 0
+ printf("pmap_enter: mapping ppn %d at lpn %d in pmap %p\n",
+ ppn, lpn, pmap);
+#endif
+ s = splimp();
+ /* Check if the physical page is mapped already elsewhere. */
+ if (pmap == pmap_kernel()) {
+ for (pv = &pv_table[ppn]; pv != NULL; pv = pv->pv_next)
+ if (pv->pv_pmap != NULL &&
+ (pv->pv_pmap != pmap || pv->pv_lpn != lpn)) {
+ printf("new: pmap = %p, ppn = %d, lpn = %d\n",
+ pmap, ppn, lpn);
+ printf("old: pmap = %p, ppn = %d, lpn = %d\n",
+ pv->pv_pmap, pv->pv_ppn, pv->pv_lpn);
+ panic("Mapping clash not handled");
+ }
+ } else {
+ for (pv = &pv_table[ppn]; pv != NULL; pv = pv->pv_next)
+ if (pv->pv_pmap == pmap_kernel() ||
+ (pv->pv_pmap == pmap && pv->pv_lpn != lpn)) {
+ printf("new: pmap = %p, ppn = %d, lpn = %d\n",
+ pmap, ppn, lpn);
+ printf("old: pmap = %p, ppn = %d, lpn = %d\n",
+ pv->pv_pmap, pv->pv_ppn, pv->pv_lpn);
+ panic("Mapping clash not handled");
+ }
+ }
+
+ /* Remove any existing mapping at this lpn */
+ if (pmap->pm_entries[lpn] != NULL &&
+ pmap->pm_entries[lpn]->pv_ppn != ppn)
+ pmap_remove(pmap, va, va + PAGE_SIZE);
+
+ /* Make a note */
+ pv = pv_get(pmap, ppn, lpn);
+ pv->pv_pmap = pmap;
+ pv->pv_ppn = ppn;
+ pv->pv_lpn = lpn;
+ pv->pv_prot = prot;
+ pv->pv_vflags = 0;
+ pv->pv_pflags = 0;
+ if (flags & PMAP_WIRED)
+ pv->pv_vflags |= PV_WIRED;
+ pv_update(pv);
+ pmap->pm_entries[lpn] = pv;
+ splx(s);
+ /* Poke the MEMC */
+ if (pmap->pm_flags & PM_ACTIVE)
+ MEMC_WRITE(pv->pv_activate);
+
+ return KERN_SUCCESS;
+}
+
+/* Remove a range of virtual mappings from a pmap */
+void
+pmap_remove(pmap_t pmap, vaddr_t sva, vaddr_t eva)
+{
+ int slpn, elpn, lpn, s;
+ struct pv_entry *pv;
+
+ slpn = atop(sva); elpn = atop(eva);
+#if 0
+ printf("pmap_remove: clearing from lpn %d to lpn %d in pmap %p\n",
+ slpn, elpn - 1, pmap);
+#endif
+ s = splimp();
+ for (lpn = slpn; lpn < elpn; lpn++) {
+ pv = pmap->pm_entries[lpn];
+ if (pv != NULL) {
+ if (pmap->pm_flags & PM_ACTIVE) {
+ MEMC_WRITE(pv->pv_deactivate);
+ cpu_cache_flush();
+ }
+ pmap->pm_entries[lpn] = NULL;
+ pv_release(pmap, pv->pv_ppn, lpn);
+ }
+ }
+ splx(s);
+}
+
+boolean_t
+pmap_extract(pmap_t pmap, vaddr_t va, paddr_t *ppa)
+{
+ struct pv_entry *pv;
+
+ pv = pmap->pm_entries[atop(va)];
+ if (pv == NULL)
+ return FALSE;
+ *ppa = ptoa(pv->pv_ppn);
+ return TRUE;
+}
+
+void
+pmap_kenter_pa(vaddr_t va, paddr_t pa, vm_prot_t prot)
+{
+
+ pmap_enter(pmap_kernel(), va, pa, prot, PMAP_WIRED);
+}
+
+void
+pmap_kenter_pgs(vaddr_t va, struct vm_page **pages, int npages)
+{
+
+ while (npages > 0) {
+ pmap_kenter_pa(va, (*pages)->phys_addr, VM_PROT_ALL);
+ va += NBPG;
+ pages++;
+ npages--;
+ }
+}
+
+void
+pmap_kremove(vaddr_t va, vsize_t len)
+{
+
+ pmap_remove(pmap_kernel(), va, va+len);
+}
+
+boolean_t
+pmap_is_modified(page)
+ struct vm_page *page;
+{
+ int ppn;
+
+ ppn = atop(page->phys_addr);
+ return (pv_table[ppn].pv_pflags & PV_MODIFIED) != 0;
+}
+
+boolean_t
+pmap_is_referenced(page)
+ struct vm_page *page;
+{
+ int ppn;
+
+ ppn = atop(page->phys_addr);
+ return (pv_table[ppn].pv_pflags & PV_REFERENCED) != 0;
+}
+
+static void
+pmap_update_page(int ppn)
+{
+ struct pv_entry *pv;
+
+ for (pv = &pv_table[ppn]; pv != NULL; pv = pv->pv_next)
+ if (pv->pv_pmap != NULL) {
+ pv_update(pv);
+ if (pv->pv_pmap->pm_flags & PM_ACTIVE) {
+ if (pv->pv_activate)
+ MEMC_WRITE(pv->pv_activate);
+ else
+ MEMC_WRITE(pv->pv_deactivate);
+ }
+ }
+}
+
+boolean_t
+pmap_clear_modify(struct vm_page *page)
+{
+ int ppn;
+ boolean_t rv;
+
+ ppn = atop(page->phys_addr);
+ rv = pmap_is_modified(page);
+ pv_table[ppn].pv_pflags &= ~PV_MODIFIED;
+ pmap_update_page(ppn);
+ return rv;
+}
+
+boolean_t
+pmap_clear_reference(struct vm_page *page)
+{
+ int ppn;
+ boolean_t rv;
+
+ ppn = atop(page->phys_addr);
+ rv = pmap_is_referenced(page);
+ pv_table[ppn].pv_pflags &= ~PV_REFERENCED;
+ pmap_update_page(ppn);
+ return rv;
+}
+
+/*
+ * Work out if a given page fault was our fault (e.g. through
+ * referenced/modified emulation). If it was, handle it and return
+ * TRUE. Otherwise, return FALSE.
+ */
+boolean_t
+pmap_fault(struct pmap *pmap, vaddr_t va, vm_prot_t atype)
+{
+ int lpn, ppn;
+ struct pv_entry *pv, *ppv;
+
+ lpn = atop(va);
+ pv = pmap->pm_entries[lpn];
+ if (pv == NULL)
+ return FALSE;
+ ppn = pv->pv_ppn;
+ ppv = &pv_table[ppn];
+ if (pmap == pmap_kernel()) {
+ /*
+ * If we allow the kernel to access the page, we can't
+ * stop it writing to it as well, so we have to handle
+ * referenced and modified bits together.
+ */
+ if ((ppv->pv_pflags & PV_REFERENCED) == 0 ||
+ (ppv->pv_pflags & PV_MODIFIED) == 0) {
+ ppv->pv_pflags |= PV_REFERENCED | PV_MODIFIED;
+ pmap_update_page(ppn);
+ return TRUE;
+ }
+ } else {
+ if ((ppv->pv_pflags & PV_REFERENCED) == 0) {
+ ppv->pv_pflags |= PV_REFERENCED;
+ pmap_update_page(ppn);
+ return TRUE;
+ }
+ if ((atype & VM_PROT_WRITE) && (pv->pv_prot & VM_PROT_WRITE) &&
+ (ppv->pv_pflags & PV_MODIFIED) == 0) {
+ ppv->pv_pflags |= PV_MODIFIED;
+ pmap_update_page(ppn);
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+void
+pmap_page_protect(struct vm_page *page, vm_prot_t prot)
+{
+ int ppn;
+ struct pv_entry *pv;
+
+ ppn = atop(page->phys_addr);
+ if (prot == VM_PROT_NONE) {
+#if 0
+ printf("pmap_page_protect: removing ppn %d\n", ppn);
+#endif
+ pv = &pv_table[ppn];
+ while (pv->pv_pmap != NULL) {
+ if (pv->pv_pmap->pm_flags & PM_ACTIVE) {
+ MEMC_WRITE(pv->pv_deactivate);
+ cpu_cache_flush();
+ }
+ pv->pv_pmap->pm_entries[pv->pv_lpn] = NULL;
+ pv_release(pv->pv_pmap, pv->pv_ppn, pv->pv_lpn);
+ }
+ } else if (prot != VM_PROT_ALL) {
+ for (pv = &pv_table[ppn]; pv != NULL; pv = pv->pv_next)
+ if (pv->pv_pmap != NULL) {
+ pv->pv_prot &= prot;
+ pv_update(pv);
+ if (pv->pv_pmap->pm_flags & PM_ACTIVE)
+ MEMC_WRITE(pv->pv_activate);
+ }
+ }
+}
+
+paddr_t
+pmap_phys_address(ppn)
+ int ppn;
+{
+ panic("pmap_phys_address not implemented");
+}
+
+void
+pmap_protect(pmap_t pmap, vaddr_t sva, vaddr_t eva, vm_prot_t prot)
+{
+ struct pv_entry *pv;
+ int s, slpn, elpn, lpn;
+
+ if (prot == VM_PROT_NONE) {
+ pmap_remove(pmap, sva, eva);
+ return;
+ }
+ if (prot & VM_PROT_WRITE)
+ return; /* apparently we're meant to */
+ if (pmap == pmap_kernel())
+ return; /* can't restrict kernel w/o unmapping. */
+
+ slpn = atop(sva); elpn = atop(eva);
+ s = splimp();
+ for (lpn = slpn; lpn < elpn; lpn++) {
+ pv = pmap->pm_entries[lpn];
+ if (pv != NULL) {
+ pv->pv_prot &= prot;
+ pv_update(pv);
+ if (pv->pv_pmap->pm_flags & PM_ACTIVE)
+ MEMC_WRITE(pv->pv_activate);
+ }
+ }
+ splx(s);
+}
+
+void
+pmap_reference(pmap_t pmap)
+{
+
+ pmap->pm_count++;
+}
+
+/*
+ * If there were any actions we could delay committing to hardware,
+ * this would be where they'd be committed. We should perhaps delay
+ * cache flushes till here, but I've heard rumours that pmap_update()
+ * isn't called as often as it should be, so I'll play it safe for
+ * now.
+ */
+void
+pmap_update()
+{
+
+ /* Do nothing */
+}
+
+/*
+ * See if the given physical address has a logical mapping. Return
+ * its address if so, otherwise return the logical address in MEMC
+ * physical space. This means that we can safely write here without
+ * flushing the cache. Only necessary on ARM3.
+ */
+static caddr_t
+pmap_find(paddr_t pa)
+{
+#ifdef CPU_ARM3
+ struct pv_entry *pv;
+
+ for (pv = &pv_table[atop(pa)]; pv != NULL; pv = pv->pv_next)
+ if (pv->pv_pmap != NULL && (pv->pv_pmap->pm_flags & PM_ACTIVE))
+ return (caddr_t)ptoa(pv->pv_lpn);
+#endif
+ return MEMC_PHYS_BASE + pa;
+}
+
+void
+pmap_zero_page(paddr_t pa)
+{
+
+ bzero(pmap_find(pa), PAGE_SIZE);
+ pv_table[atop(pa)].pv_pflags |= PV_MODIFIED | PV_REFERENCED;
+}
+
+void
+pmap_copy_page(paddr_t src, paddr_t dest)
+{
+
+ memcpy(pmap_find(dest), pmap_find(src), PAGE_SIZE);
+ pv_table[atop(src)].pv_pflags |= PV_REFERENCED;
+ pv_table[atop(dest)].pv_pflags |= PV_MODIFIED | PV_REFERENCED;
+}
+
+/*
+ * This is meant to return the range of kernel vm that is available
+ * after loading the kernel. Since NetBSD/arm26 runs the kernel from
+ * physically-mapped space, we just return all of kernel vm. Oh,
+ * except for the single page at the end where we map
+ * otherwise-unmapped pages.
+ */
+void
+pmap_virtual_space(vaddr_t *vstartp, vaddr_t *vendp)
+{
+
+ *vstartp = VM_MIN_KERNEL_ADDRESS;
+ *vendp = VM_MAX_KERNEL_ADDRESS - PAGE_SIZE;
+}
+
+/*
+ * Check if the given access should have aborted. Used in various abort
+ * handlers to work out what happened.
+ */
+boolean_t
+pmap_confess(vaddr_t va, vm_prot_t atype)
+{
+ pmap_t pmap;
+ struct pv_entry *pv;
+
+ /* XXX Assume access was from user mode (or equiv). */
+ pmap = va < VM_MIN_KERNEL_ADDRESS ? active_pmap : pmap_kernel();
+ pv = pmap->pm_entries[atop(va)];
+ if (pv == NULL)
+ return TRUE;
+ if (pv->pv_ppl == MEMC_PPL_NOACCESS)
+ return TRUE;
+ if (pv->pv_ppl == MEMC_PPL_RDONLY && (atype & VM_PROT_WRITE))
+ return TRUE;
+ return FALSE;
+}
+
+#ifdef DDB
+#include <ddb/db_output.h>
+
+void
+pmap_dump(struct pmap *pmap)
+{
+ int i;
+ struct pv_entry *pv;
+ int pflags;
+
+ db_printf("PMAP %p:\n", pmap);
+ db_printf("\tcount = %d, flags = %d\n",
+ pmap->pm_count, pmap->pm_flags);
+ for (i = 0; i < 1024; i++)
+ if ((pv = pmap->pm_entries[i]) != NULL) {
+ db_printf("\t%03d->%p: ", i, pv);
+ if (pv->pv_pmap != pmap)
+ db_printf("pmap=%p!, ", pv->pv_pmap);
+ db_printf("ppn=%d, lpn=%d, ",
+ pv->pv_ppn, pv->pv_lpn);
+ db_printf("act=%08x, deact=%08x,\n",
+ pv->pv_activate, pv->pv_deactivate);
+ db_printf("\t\tprot=%c%c%c, ",
+ pv->pv_prot & VM_PROT_READ ? 'r' : '-',
+ pv->pv_prot & VM_PROT_WRITE ? 'w' : '-',
+ pv->pv_prot & VM_PROT_EXECUTE ? 'x' : '-');
+ db_printf("ppl=");
+ switch(pv->pv_ppl) {
+ case MEMC_PPL_RDWR:
+ db_printf("rw, ");
+ break;
+ case MEMC_PPL_RDONLY:
+ db_printf("r-, ");
+ break;
+ case MEMC_PPL_NOACCESS:
+ db_printf("--, ");
+ break;
+ default:
+ db_printf("0x%x, ", pv->pv_ppl);
+ break;
+ }
+ db_printf("vflags=%c, ",
+ pv->pv_vflags & PV_WIRED ? 'W' : '-');
+ pflags = pv_table[pv->pv_ppn].pv_pflags;
+ db_printf("pflags=%c%c\n",
+ pflags & PV_MODIFIED ? 'M' : '-',
+ pflags & PV_REFERENCED ? 'R' : '-');
+
+ }
+}
+#endif
diff --git a/sys/arch/arm26/arm26/rscons.c b/sys/arch/arm26/arm26/rscons.c
new file mode 100644
index 00000000000..af33f83c22e
--- /dev/null
+++ b/sys/arch/arm26/arm26/rscons.c
@@ -0,0 +1,99 @@
+/* $NetBSD: rscons.c,v 1.1 2000/05/09 21:55:57 bjh21 Exp $ */
+/*-
+ * Copyright (c) 1997, 1998 Ben Harris
+ * 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.
+ */
+/* This file is part of NetBSD/arm26 -- a port of NetBSD to ARM2/3 machines. */
+/*
+ * rscons.c - Really basic routines for the Arc serial port
+ */
+
+#include <sys/param.h>
+#include <sys/conf.h>
+
+#include <dev/cons.h>
+#include <dev/ic/r6551reg.h>
+
+#define RS_BASE 0x033B0000
+
+cons_decl(rs);
+
+void rscnprobe(cp)
+ struct consdev *cp;
+{
+
+ /* Be optimistic! */
+ cp->cn_pri = CN_NORMAL;
+ cp->cn_dev = makedev(13, 0);
+}
+
+void rscninit(cp)
+ struct consdev *cp;
+{
+ volatile char *rs_base = (volatile char *)RS_BASE;
+
+ /* Reset 6551 */
+ rs_base[R6551_RESET<<2] = 1;
+ /* 9600, 8N1 */
+ rs_base[R6551_CONTROL<<2] = R6551_CTL_SBR_9600 |
+ R6551_CTL_WL_8 | R6551_CTL_RCS_INT;
+ /* Enable transmission, disable interrupts, set DTR. */
+ rs_base[R6551_COMMAND<<2] = R6551_CMD_DTR | R6551_CMD_IRD |
+ R6551_CMD_TIC_NOIRQ;
+ /* The 6551 is now sane. Well, as sane as a 6551 can be. */
+}
+
+int rscngetc(dev)
+ dev_t dev;
+{
+ volatile char *rs_base = (volatile char *)RS_BASE;
+ int c;
+
+ /* Wait for reception */
+ while ((rs_base[R6551_STATUS<<2] & R6551_STAT_RDRF) == 0);
+ c = rs_base[R6551_RX_DATA<<2];
+ if (c == '\r')
+ c = '\n';
+ return c;
+}
+
+void rscnputc(dev, c)
+ dev_t dev;
+ int c;
+{
+ volatile char *rs_base = (volatile char *)RS_BASE;
+
+ while (!(rs_base[R6551_STATUS<<2] & R6551_STAT_TDRE));
+ /* And it's now ready to transmit. */
+ rs_base[R6551_TX_DATA<<2] = c;
+ /* Wait for it to finish (me? paranoid?) */
+ while (!(rs_base[R6551_STATUS<<2] & R6551_STAT_TDRE));
+}
+
+void rscnpollc(dev, on)
+ dev_t dev;
+ int on;
+{
+}
diff --git a/sys/arch/arm26/arm26/softintr.c b/sys/arch/arm26/arm26/softintr.c
new file mode 100644
index 00000000000..42122412c54
--- /dev/null
+++ b/sys/arch/arm26/arm26/softintr.c
@@ -0,0 +1,175 @@
+/* $NetBSD: softintr.c,v 1.1 2000/05/09 21:55:57 bjh21 Exp $ */
+
+/*
+ * Copyright (c) 1999 Ben Harris.
+ * Copyright (c) 1994-1998 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
+ * for the NetBSD Project.
+ * 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.
+ *
+ * Soft interrupt and other generic interrupt functions.
+ */
+
+#include <sys/param.h>
+
+__RCSID("$NetBSD: softintr.c,v 1.1 2000/05/09 21:55:57 bjh21 Exp $");
+
+#include <sys/malloc.h>
+#include <sys/queue.h>
+#include <sys/systm.h>
+
+#include <machine/intr.h>
+#include <machine/spl.h>
+
+#include <vm/vm.h>
+#include <uvm/uvm_extern.h>
+
+#include <machine/machdep.h>
+#include <machine/softintr.h>
+
+#include <net/netisr.h>
+
+struct softintr_handler {
+ LIST_ENTRY(softintr_handler) sh_link;
+ int sh_ipl;
+ void (*sh_func)(void *);
+ void *sh_arg;
+ int sh_pending;
+};
+
+LIST_HEAD(sh_head, softintr_handler);
+
+static struct sh_head sh_head;
+
+static struct softintr_handler *sh_softnet;
+static struct softintr_handler *sh_softclock;
+
+static void dosoftnet(void *);
+static void dosoftclock(void *);
+
+extern int hardsplx(int); /* XXX should be in a header somewhere */
+
+void
+softintr_init()
+{
+
+ LIST_INIT(&sh_head);
+ sh_softnet = softintr_establish(IPL_SOFTNET, dosoftnet, NULL);
+ sh_softclock = softintr_establish(IPL_SOFTCLOCK, dosoftclock, NULL);
+}
+
+void
+setsoftclock()
+{
+
+ softintr_schedule(sh_softclock);
+}
+
+void
+setsoftnet()
+{
+
+ softintr_schedule(sh_softnet);
+}
+
+/* Handle software interrupts */
+
+void
+dosoftints(int level)
+{
+ struct softintr_handler *sh;
+
+ for (sh = LIST_FIRST(&sh_head); sh != NULL && sh->sh_ipl > level;
+ sh = LIST_NEXT(sh, sh_link))
+ if (sh->sh_pending) {
+ hardsplx(sh->sh_ipl);
+ uvmexp.softs++;
+ sh->sh_pending = 0;
+ sh->sh_func(sh->sh_arg);
+ }
+}
+
+void *
+softintr_establish(int ipl, void (*func)(void *), void *arg)
+{
+ struct softintr_handler *new, *sh;
+
+ MALLOC(new, struct softintr_handler *, sizeof(*sh),
+ M_DEVBUF, M_WAITOK);
+ new->sh_ipl = ipl;
+ new->sh_func = func;
+ new->sh_arg = arg;
+ if (LIST_FIRST(&sh_head) == NULL ||
+ LIST_FIRST(&sh_head)->sh_ipl <= ipl)
+ /* XXX This shouldn't need to be a special case */
+ LIST_INSERT_HEAD(&sh_head, new, sh_link);
+ else {
+ for (sh = LIST_FIRST(&sh_head);
+ LIST_NEXT(sh, sh_link) != NULL
+ && LIST_NEXT(sh, sh_link)->sh_ipl > ipl;
+ sh = LIST_NEXT(sh, sh_link));
+ LIST_INSERT_AFTER(sh, new, sh_link);
+ }
+ return new;
+}
+
+void
+softintr_disestablish(void *cookie)
+{
+
+ panic("softintr_disestablish not implemented");
+}
+
+void
+softintr_schedule(void *cookie)
+{
+ struct softintr_handler *sh = cookie;
+
+ sh->sh_pending = 1;
+}
+
+static void
+dosoftclock(void *arg)
+{
+
+ softclock();
+}
+
+
+static void
+dosoftnet(void *arg)
+{
+
+#define DONETISR(bit, fn) do { \
+ atomic_clear_bit(&netisr, 1 << (bit)); \
+ fn(); \
+} while (0)
+#include <net/netisr_dispatch.h>
+#undef DONETISR
+}
diff --git a/sys/arch/arm26/arm26/start.c b/sys/arch/arm26/arm26/start.c
new file mode 100644
index 00000000000..699dac8a827
--- /dev/null
+++ b/sys/arch/arm26/arm26/start.c
@@ -0,0 +1,225 @@
+/* $NetBSD: start.c,v 1.1 2000/05/09 21:55:57 bjh21 Exp $ */
+/*-
+ * Copyright (c) 1998, 2000 Ben Harris
+ * 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.
+ */
+/* This file is part of NetBSD/arm26 -- a port of NetBSD to ARM2/3 machines. */
+/*
+ * start.c -- In the beginning...
+ */
+
+#include <sys/param.h>
+
+__KERNEL_RCSID(0, "SId$");
+
+#include <sys/msgbuf.h>
+#include <sys/syslog.h>
+#include <sys/systm.h>
+
+#include <machine/armreg.h>
+#include <machine/boot.h>
+#include <machine/machdep.h>
+#include <machine/memcreg.h>
+
+#include <dev/cons.h>
+
+#include <vm/vm.h>
+
+#include "arcvideo.h"
+#include "ioc.h"
+
+#if NIOC > 0
+#include <arch/arm26/iobus/iocreg.h>
+#endif
+
+extern void main __P((void)); /* XXX Should be in a header file */
+
+struct bootconfig bootconfig;
+
+#define BOOT_SANITY 0x89345846
+static int boot_sanity = BOOT_SANITY;
+
+#ifndef __ELF__
+/* Odd symbols declared by the linker */
+extern char _stext_, _etext, _sdata_, _edata, _bss_start, _end;
+#else /* ELF */
+extern char __bss_start__[], __bss_end__[];
+#endif
+
+/*
+ * This is where it all begins. The bootloader is expected to enter
+ * in an APCS-compliant manner so we don't have to mess around in
+ * assembler to get things going.
+ */
+void
+start(initbootconfig)
+ struct bootconfig *initbootconfig;
+{
+ extern char page0[], page0_end[];
+ size_t size;
+ caddr_t v;
+ char pbuf[9];
+
+ /*
+ * State of the world as of BBBB 0.02:
+ * Registers per APCS
+ * physmem (set up by RISC OS and BBBB):
+ * 0x02000000 -- 0x02080000 == Screen (potentially)
+ * 0x02080000 -- 0x02088000 == Zero page
+ * 0x02088000 -- 0x02090000 == Initial kernel stack
+ * 0x02090000 -- 0x02098000 == Kernel message buffer
+ * 0x02098000 -- freebase == Kernel image
+ * bss is cleared for us
+ */
+
+#define ZP_PHYSADDR ((paddr_t)0x00080000)
+#define MSGBUF_PHYSADDR ((paddr_t)0x00090000)
+
+ /* We can't trust the BSS (at least not with my linker) */
+ bzero(__bss_start__, __bss_end__ - __bss_start__);
+
+ /* Save boot configuration somewhere */
+ memcpy(&bootconfig, initbootconfig, sizeof(struct bootconfig));
+
+ if (bootconfig.magic != BOOT_MAGIC)
+ panic("bootloader is ancient");
+ /* initialise kernel variables */
+ boothowto = bootconfig.boothowto;
+ physmem = bootconfig.npages;
+ uvmexp.pagesize = bootconfig.nbpp;
+ uvm_setpagesize();
+
+ /* Any others? */
+
+ /* Set up kernel message buffer */
+ /* XXX Should be in cpu_startup, yesno? */
+ /* Probably not actually -- the sooner it's run, the better. */
+ initmsgbuf(MEMC_PHYS_BASE + MSGBUF_PHYSADDR, MSGBUFSIZE);
+
+#ifdef DIAGNOSTIC
+ /*
+ * Check that the linker and loader agree about where
+ * everything should be loaded.
+ */
+
+#ifndef __ELF__ /* BBBB doesn't set everything for ELF */
+ if (&_stext_ != (MEMC_PHYS_BASE + bootconfig.txtbase) ||
+ &_etext - &_stext_ != bootconfig.txtsize ||
+ &_sdata_ != (MEMC_PHYS_BASE + bootconfig.database)
+#if 0 /* BBBB gets this wrong, but that's because the a.out header is wrong */
+ ||
+ &_edata - &_sdata_ != bootconfig.datasize ||
+ &_bss_start != (MEMC_PHYS_BASE + bootconfig.bssbase) ||
+ &_end - &_bss_start != bootconfig.bsssize
+#endif
+ ) {
+ printf("text: %p + %08x vs %p + %08x\n",
+ &_stext_, &_etext - &_stext_,
+ MEMC_PHYS_BASE + bootconfig.txtbase,
+ bootconfig.txtsize);
+ printf("data: %p + %08x vs %p + %08x\n",
+ &_sdata_, &_edata - &_sdata_,
+ MEMC_PHYS_BASE + bootconfig.database,
+ bootconfig.datasize);
+ printf("bss: %p + %08x vs %p + %08x\n",
+ &_bss_start, &_end - &_bss_start,
+ MEMC_PHYS_BASE + bootconfig.bssbase,
+ bootconfig.bsssize);
+ panic("bootloader disagreement");
+ }
+#endif
+
+ if (boot_sanity != BOOT_SANITY)
+ panic("Bootloader mislaid the data segment");
+#endif
+
+ /*
+ * Allocate space for system data structures. These data structures
+ * are allocated here instead of cpu_startup() because physical
+ * memory is directly addressable. We don't have to map these into
+ * virtual address space. This trick is stolen from the alpha port.
+ */
+ size = (vsize_t)allocsys(0, NULL);
+ v = MEMC_PHYS_BASE + bootconfig.freebase;
+ bootconfig.freebase += size;
+ if (bootconfig.freebase > ptoa(physmem)) {
+ format_bytes(pbuf, sizeof(pbuf), size);
+ panic("start: out of memory (wanted %s)", pbuf);
+ }
+ bzero(v, size);
+ if ((allocsys(v, NULL) - v) != size)
+ panic("start: table size inconsistency");
+
+ /* Tell UVM about memory */
+#if NARCVIDEO == 0
+ /*
+ * DMA-able space. If the video driver's configured, it'll
+ * register this later once it knows how much it's using.
+ */
+ uvm_page_physload(0, atop(MEMC_DMA_MAX), 0, atop(MEMC_DMA_MAX),
+ VM_FREELIST_LOW);
+#endif
+ /*
+ * Normal memory -- we expect the bootloader to tell us where
+ * the kernel ends.
+ */
+ uvm_page_physload(atop(MEMC_DMA_MAX), bootconfig.npages,
+ atop(round_page(bootconfig.freebase)),
+ bootconfig.npages,
+ VM_FREELIST_DEFAULT);
+
+ /* printf("Memory registered with UVM.\n"); */
+ /* Set up CPU vectors in zero page */
+ memcpy(MEMC_PHYS_BASE + ZP_PHYSADDR, page0, page0_end - page0);
+
+ /* Get the MEMC set up and map zero page */
+ pmap_bootstrap(bootconfig.npages, ZP_PHYSADDR);
+
+ /*
+ * This is a nasty bit. Because the kernel uses a 26-bit APCS
+ * variant, the CPU interrupt disable flags get munged on
+ * every function return. Thus, we need to enable interrupts
+ * at the CPU now since this is the last function we control
+ * that won't return. In order to be able to do this, we need
+ * to ensure we won't get any interrupts before we're ready
+ * for them. For now, I'll assume we've got an IOC doing all
+ * this at the usual location, but it should be done more
+ * elegantly.
+ */
+
+#if NIOC > 0
+ *(volatile u_char *)(0x03200000 + (IOC_IRQMSKA << 2)) = 0;
+ *(volatile u_char *)(0x03200000 + (IOC_IRQMSKB << 2)) = 0;
+ *(volatile u_char *)(0x03200000 + (IOC_FIQMSK << 2)) = 0;
+#endif
+ int_on();
+
+ /* TODO: anything else? */
+
+ main();
+
+ panic("main() returned");
+ /* NOTREACHED */
+}
diff --git a/sys/arch/arm26/arm26/stubs.c b/sys/arch/arm26/arm26/stubs.c
new file mode 100644
index 00000000000..a0b72740b5c
--- /dev/null
+++ b/sys/arch/arm26/arm26/stubs.c
@@ -0,0 +1,205 @@
+/* $NetBSD: stubs.c,v 1.1 2000/05/09 21:55:57 bjh21 Exp $ */
+/*
+ * stubs.c -- functions I haven't written yet
+ */
+
+#include <sys/param.h>
+
+__RCSID("$NetBSD: stubs.c,v 1.1 2000/05/09 21:55:57 bjh21 Exp $");
+
+#include <sys/kernel.h>
+#include <sys/systm.h>
+#include <sys/user.h>
+
+void
+need_proftick(p)
+ struct proc *p;
+{
+ panic("need_proftick not implemented");
+}
+
+void
+resettodr()
+{
+
+ printf("resettodr: not doing anything\n");
+}
+
+int
+suibyte(base, c)
+ void *base;
+ int c;
+{
+ panic("suibyte not implemented");
+}
+
+int
+susword(base, c)
+ void *base;
+ short c;
+{
+ panic("susword not implemented");
+}
+
+int
+suisword(base, c)
+ void *base;
+ short c;
+{
+ panic("suisword not implemented");
+}
+
+int
+suswintr(base, c)
+ void *base;
+ short c;
+{
+ panic("suswintr not implemented");
+}
+
+int
+suiword(base, c)
+ void *base;
+ long c;
+{
+ panic("suiword not implemented");
+}
+
+int
+fuibyte(base)
+ const void *base;
+{
+ panic("fuibyte not implemented");
+}
+
+int
+fusword(base)
+ const void *base;
+{
+ panic("fusword not implemented");
+}
+
+int
+fuisword(base)
+ const void *base;
+{
+ panic("fuisword not implemented");
+}
+
+int
+fuswintr(base)
+ const void *base;
+{
+ panic("fuswintr not implemented");
+}
+
+long
+fuiword(base)
+ const void *base;
+{
+ panic("fuiword not implemented");
+}
+
+int
+cpu_coredump(p, vp, cred, chdr)
+ struct proc *p;
+ struct vnode *vp;
+ struct ucred *cred;
+ struct core *chdr;
+{
+ panic("cpu_coredump not implemented");
+}
+
+int
+cpu_sysctl(name, namelen, oldval, oldlenp, newval, newlen, p)
+ int *name;
+ u_int namelen;
+ void *oldval, *newval;
+ size_t *oldlenp, newlen;
+ struct proc *p;
+{
+ panic("cpu_sysctl not implemented");
+}
+
+void
+vmapbuf(buf, len)
+ struct buf *buf;
+ vsize_t len;
+{
+ panic("vmapbuf not implemented");
+}
+
+void
+vunmapbuf(buf, len)
+ struct buf *buf;
+ vsize_t len;
+{
+ panic("vunmapbuf not implemented");
+}
+
+void
+pagemove(foo, bar, len)
+ caddr_t foo, bar;
+ size_t len;
+{
+ panic("pagemove not implemented");
+}
+
+int sys_sysarch(p, v, retval)
+ struct proc *p;
+ void *v;
+ register_t *retval;
+{
+ panic("sys_sysarch not implemented");
+}
+
+static struct user user0;
+struct user *proc0paddr = &user0;
+
+int
+process_read_fpregs(p, regs)
+ struct proc *p;
+ struct fpreg *regs;
+{
+ panic("process_read_fpregs not implemented");
+}
+
+int
+process_read_regs(p, regs)
+ struct proc *p;
+ struct reg *regs;
+{
+ panic("process_read_regs not implemented");
+}
+
+int
+process_set_pc(p, addr)
+ struct proc *p;
+ caddr_t addr;
+{
+ panic("process_set_pc not implemented");
+}
+
+int
+process_sstep(p, sstep)
+ struct proc *p;
+ int sstep;
+{
+ panic("process_sstep not implemented");
+}
+
+int
+process_write_fpregs(p, regs)
+ struct proc *p;
+ struct fpreg *regs;
+{
+ panic("process_write_fpregs not implemented");
+}
+
+int
+process_write_regs(p, regs)
+ struct proc *p;
+ struct reg *regs;
+{
+ panic("process_write_regs not implemented");
+}
diff --git a/sys/arch/arm26/arm26/vm_machdep.c b/sys/arch/arm26/arm26/vm_machdep.c
new file mode 100644
index 00000000000..df0e559a1b9
--- /dev/null
+++ b/sys/arch/arm26/arm26/vm_machdep.c
@@ -0,0 +1,330 @@
+/* $NetBSD: vm_machdep.c,v 1.1 2000/05/09 21:55:57 bjh21 Exp $ */
+
+/*-
+ * Copyright (c) 2000 Ben Harris
+ * Copyright (c) 1994-1998 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
+ * 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 OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (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 is part of NetBSD/arm26 -- a port of NetBSD to ARM2/3 machines. */
+
+#include <sys/param.h>
+
+__RCSID("$NetBSD: vm_machdep.c,v 1.1 2000/05/09 21:55:57 bjh21 Exp $");
+
+#include <sys/exec.h>
+#include <sys/mount.h> /* XXX syscallargs.h uses fhandle_t and fsid_t */
+#include <sys/proc.h>
+#include <sys/syscallargs.h>
+#include <sys/user.h>
+
+#include <vm/vm.h>
+
+#include <machine/armreg.h>
+#include <machine/frame.h>
+#include <machine/machdep.h>
+
+/*
+ * Finish a fork operation, with process p2 nearly set up.
+ * Copy and update the pcb and trap frame, making the child ready to run.
+ *
+ * p1 is the process being forked; if p1 == &proc0, we are creating
+ * a kernel thread, and the return path will later be changed in cpu_set_kpc.
+ *
+ * If an alternate user-level stack is requested (with non-zero values
+ * in both the stack and stacksize args), set up the user stack pointer
+ * accordingly.
+ */
+
+/*
+ * Note:
+ *
+ * p->p_addr points to a page containing the user structure
+ * (see <sys/user.h>) and the kernel stack. The user structure has to be
+ * at the start of the area -- we start the kernel stack from the end.
+ */
+
+void
+cpu_fork(struct proc *p1, struct proc *p2, void *stack, size_t stacksize)
+{
+ struct pcb *pcb;
+ struct trapframe *tf;
+ struct switchframe *sf;
+ char *stacktop;
+
+#if 0
+ printf("cpu_fork: %p -> %p\n", p1, p2);
+#endif
+ pcb = &p2->p_addr->u_pcb;
+ /* Copy the pcb */
+ *pcb = p1->p_addr->u_pcb;
+
+ /* pmap_activate(p2); XXX Other ports do. Why? */
+
+ /* Set up the kernel stack */
+ stacktop = (char *)p2->p_addr + USPACE;
+ tf = (struct trapframe *)stacktop - 1;
+ sf = (struct switchframe *)tf - 1;
+ /* Duplicate old process's trapframe (if it had one) */
+ if (p1->p_addr->u_pcb.pcb_tf == NULL)
+ bzero(tf, sizeof(*tf));
+ else
+ *tf = *p1->p_addr->u_pcb.pcb_tf;
+ p2->p_addr->u_pcb.pcb_tf = tf;
+ /* Fabricate a new switchframe */
+ bzero(sf, sizeof(*sf));
+ sf->sf_r13 = (register_t)tf; /* Initial stack pointer */
+ sf->sf_r14 = (register_t)proc_trampoline | R15_MODE_SVC;
+
+ pcb->pcb_tf = tf;
+ pcb->pcb_sf = sf;
+ pcb->pcb_onfault = NULL;
+ cpu_set_kpc(p2, child_return, NULL);
+}
+
+/*
+ * Change the initial entry point of a process that's been created by
+ * cpu_fork() but hasn't run yet. It will still start up through
+ * proc_trampoline, but will call pc instead of child_return().
+ */
+void
+cpu_set_kpc(struct proc *p, void (*pc)(void *), void *arg)
+{
+ struct switchframe *sf;
+
+ sf = p->p_addr->u_pcb.pcb_sf;
+#ifdef DIAGNOSTIC
+ if (sf->sf_r14 != ((register_t)proc_trampoline | R15_MODE_SVC))
+ panic("cpu_set_kpc");
+#endif
+ sf->sf_r4 = (register_t)pc;
+ sf->sf_r5 = (register_t)arg;
+}
+
+/*
+ * Set up the registers for a newly-execked image.
+ */
+void
+setregs(struct proc *p, struct exec_package *pack, u_long stack)
+{
+ struct trapframe *tf;
+
+ tf = p->p_addr->u_pcb.pcb_tf;
+ bzero(tf, sizeof(*tf));
+ tf->tf_r0 = (register_t)PS_STRINGS;
+ tf->tf_r13 = stack; /* sp */
+ tf->tf_r15 = pack->ep_entry;
+}
+
+void
+cpu_exit(struct proc *p)
+{
+
+ /* Nothing to do here? */
+ exit2(p); /* I think this is safe on a uniprocessor machine */
+ cpu_switch(p);
+}
+
+/* ARGSUSED */
+void
+cpu_wait(struct proc *p)
+{
+
+ /* Nothing left for us to free... */
+}
+
+
+/*
+ * 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(sig_t catcher, int sig, sigset_t *mask, u_long code)
+{
+ struct proc *p = curproc;
+ struct trapframe *tf;
+ struct sigframe *fp, frame;
+ struct sigacts *psp = p->p_sigacts;
+ int onstack;
+
+ tf = p->p_addr->u_pcb.pcb_tf;
+
+ /* Do we need to jump onto the signal stack? */
+ onstack =
+ (psp->ps_sigstk.ss_flags & (SS_DISABLE | SS_ONSTACK)) == 0 &&
+ (psp->ps_sigact[sig].sa_flags & SA_ONSTACK) != 0;
+
+ /* Allocate space for the signal handler context. */
+ if (onstack)
+ fp = (struct sigframe *)((caddr_t)psp->ps_sigstk.ss_sp +
+ psp->ps_sigstk.ss_size);
+ else
+ fp = (struct sigframe *)tf->tf_r13;
+ fp--;
+
+ /* Build stack frame for signal trampoline. */
+ frame.sf_signum = sig;
+ frame.sf_code = code;
+ frame.sf_scp = &fp->sf_sc;
+ frame.sf_handler = catcher;
+
+ /* Save register context. */
+ 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_r13 = tf->tf_r13;
+ frame.sf_sc.sc_r14 = tf->tf_r14;
+ frame.sf_sc.sc_r15 = tf->tf_r15;
+
+ /* Save signal stack. */
+ frame.sf_sc.sc_onstack = psp->ps_sigstk.ss_flags & SS_ONSTACK;
+
+ /* Save signal mask. */
+ frame.sf_sc.sc_mask = *mask;
+
+ 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 = (int)frame.sf_scp;
+ tf->tf_r3 = (int)frame.sf_handler;
+ tf->tf_r13 = (int)fp;
+ tf->tf_r15 = (int)psp->ps_sigcode;
+
+ /* Remember that we're now on the signal stack. */
+ if (onstack)
+ psp->ps_sigstk.ss_flags |= SS_ONSTACK;
+}
+
+/*
+ * 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___sigreturn14(p, v, retval)
+ struct proc *p;
+ void *v;
+ register_t *retval;
+{
+ struct sys___sigreturn14_args /* {
+ syscallarg(struct sigcontext *) sigcntxp;
+ } */ *uap = v;
+ struct sigcontext *scp, context;
+ struct trapframe *tf;
+
+ /*
+ * 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;
+
+ /* Make sure the processor mode has not been tampered with. */
+ if ((context.sc_r15 & R15_MODE) != R15_MODE_USR ||
+ (context.sc_r15 & (R15_IRQ_DISABLE | R15_FIQ_DISABLE)) != 0)
+ return EINVAL;
+
+ /* Restore register context. */
+ tf = p->p_addr->u_pcb.pcb_tf;
+ 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_r13 = context.sc_r13;
+ tf->tf_r14 = context.sc_r14;
+ tf->tf_r15 = context.sc_r15;
+
+ /* Restore signal stack. */
+ if (context.sc_onstack & SS_ONSTACK)
+ p->p_sigacts->ps_sigstk.ss_flags |= SS_ONSTACK;
+ else
+ p->p_sigacts->ps_sigstk.ss_flags &= ~SS_ONSTACK;
+
+ /* Restore signal mask. */
+ (void) sigprocmask1(p, SIG_SETMASK, &context.sc_mask, 0);
+
+ return EJUSTRETURN;
+}
+
+void
+cpu_swapin(struct proc *p)
+{
+
+ /* Can anyone think of anything I should do here? */
+}
+
+void
+cpu_swapout(struct proc *p)
+{
+
+ /* ... or here, for that matter. */
+}
+
diff --git a/sys/arch/arm26/arm26/zeropage.S b/sys/arch/arm26/arm26/zeropage.S
new file mode 100644
index 00000000000..5424a96bfd0
--- /dev/null
+++ b/sys/arch/arm26/arm26/zeropage.S
@@ -0,0 +1,100 @@
+/* $NetBSD: zeropage.S,v 1.1 2000/05/09 21:55:57 bjh21 Exp $ */
+/*-
+ * Copyright (c) 1999 Ben Harris
+ * 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.
+ */
+/* This file is part of NetBSD/arm26 -- a port of NetBSD to ARM2/3 machines. */
+/*
+ * Data to be copied to zero page at runtime.
+ */
+
+#include <machine/asm.h>
+
+RCSID("$NetBSD: zeropage.S,v 1.1 2000/05/09 21:55:57 bjh21 Exp $")
+
+/*
+ * Now, here we could do with the ability to change the assembler's
+ * idea of where we're assembling to without changing where it puts
+ * the output. Unfortunately, this kind of thing needs the connivance
+ * of the linker, which is asking a bit much. Thus...
+ *
+ * B and BL can be used normally within zero-page, but not between
+ * zero-page and the outside world.
+ *
+ * LDR can safely be used with a label within zero-page, but not to
+ * outside.
+ *
+ * Absolute references only work to outside. Relative references only
+ * work to inside.
+ */
+
+ .text
+ .align 0
+
+/*
+ * Instructions to copy to the bottom of zero page
+ * These are the entry point to the system exception routines
+ *
+ * They go:
+ * Reset
+ * Undefined instruction
+ * SWI
+ * Prefetch abort
+ * Data abort
+ * Address exception
+ * IRQ
+ * FIQ
+ */
+
+ .global _C_LABEL(page0), _C_LABEL(page0_end)
+_C_LABEL(page0):
+ ldr pc, Lreset_target
+ ldr pc, Lundefined_target
+ ldr pc, Lswi_target
+ ldr pc, Lprefetch_abort_target
+ ldr pc, Ldata_abort_target
+ ldr pc, Laddress_exception_target
+ ldr pc, Lirq_target
+Lfiqhandler:
+ .global _C_LABEL(fiqhandler)
+ .set _C_LABEL(fiqhandler), . - _C_LABEL(page0)
+ subs pc, lr, #4
+ .org Lfiqhandler + 0x100
+
+Lreset_target:
+ .word reset_entry
+Lundefined_target:
+ .word undefined_entry
+Lswi_target:
+ .word swi_entry
+Lprefetch_abort_target:
+ .word prefetch_abort_entry
+Ldata_abort_target:
+ .word data_abort_entry
+Laddress_exception_target:
+ .word address_exception_entry
+Lirq_target:
+ .word irq_entry
+_C_LABEL(page0_end):
diff --git a/sys/arch/arm26/boot/BBBB,fd1 b/sys/arch/arm26/boot/BBBB,fd1
new file mode 100644
index 00000000000..70115b453a0
--- /dev/null
+++ b/sys/arch/arm26/boot/BBBB,fd1
@@ -0,0 +1,448 @@
+REM>BBBB
+REM $NetBSD: BBBB,fd1,v 1.1 2000/05/09 21:55:57 bjh21 Exp $
+REM
+REM Copyright (c) 1998, 1999, 2000 Ben Harris
+REM All rights reserved.
+REM
+REM Redistribution and use in source and binary forms, with or without
+REM modification, are permitted provided that the following conditions
+REM are met:
+REM 1. Redistributions of source code must retain the above copyright
+REM notice, this list of conditions and the following disclaimer.
+REM 2. Redistributions in binary form must reproduce the above copyright
+REM notice, this list of conditions and the following disclaimer in the
+REM documentation and/or other materials provided with the distribution.
+REM 3. The name of the author may not be used to endorse or promote products
+REM derived from this software without specific prior written permission.
+REM
+REM THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+REM IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+REM OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+REM IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+REM INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+REM NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+REM DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+REM THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+REM (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+REM THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+REM
+REM This file is part of NetBSD/arm26 -- a port of NetBSD to ARM2/3 machines.
+REM
+REM Ben's BASIC BSD Booter (allegedly)
+debug% = 1
+PRINT ">> BBBB, Revision 0.30"
+SYS "OS_ReadMemMapInfo" TO nbpp%, npages%
+IF debug% THEN
+ PRINT "Machine has ";npages%;" pages of ";nbpp% DIV 1024;"K each. ";
+ PRINT "Total RAM: ";npages% * nbpp% DIV 1024 DIV 1024;"Mb"
+ PRINT "Lowering HIMEM: &";~HIMEM;
+ENDIF
+HIMEM = &10000
+IF debug% THEN PRINT " -> &";~HIMEM
+
+twirl% = 0
+
+DIM vaddr%(npages%-1), access%(npages%-1), pgok%(npages%-1)
+pgok%() = FALSE
+
+PROCget_mem_map
+SYS "OS_GetEnv" TO A$
+IF debug% THEN PRINT A$
+WHILE LEFT$(A$, 1) <> " " AND LEN(A$) > 0 A$ = MID$(A$, 2) : ENDWHILE
+WHILE LEFT$(A$, 1) = " " A$ = MID$(A$, 2) : ENDWHILE
+WHILE RIGHT$(A$,1) = " " A$ = LEFT$(A$) : ENDWHILE
+IF FNtolower(LEFT$(A$, 5)) = "-quit" THEN
+ A$ = MID$(A$, 7)
+ WHILE LEFT$(A$, 1) <> " " AND LEN(A$) > 0 A$ = MID$(A$, 2) : ENDWHILE
+ WHILE LEFT$(A$, 1) = " " A$ = MID$(A$, 2) : ENDWHILE
+ENDIF
+file$ = ""
+howto% = 0
+WHILE LEN(A$) > 0
+ CASE LEFT$(A$, 1) OF
+ WHEN "-"
+ done% = FALSE
+ REPEAT
+ A$ = MID$(A$, 2)
+ CASE FNtolower(LEFT$(A$, 1)) OF
+ WHEN "a" : howto% = howto% OR &01 : REM RB_ASKNAME
+ WHEN "s" : howto% = howto% OR &02 : REM RB_SINGLE
+ WHEN "d" : howto% = howto% OR &40 : REM RB_KDB
+ WHEN " ", "" : done% = TRUE
+ OTHERWISE : ERROR EXT 0, "Bad option: " + LEFT$(A$, 1)
+ ENDCASE
+ UNTIL done%
+ WHEN " "
+ A$ = MID$(A$, 2)
+ OTHERWISE
+ IF file$ <> "" THEN ERROR EXT 0, "Too many files!"
+ WHILE LEFT$(A$, 1) <> " " AND LEN(A$) > 0
+ file$ += LEFT$(A$,1)
+ A$ = MID$(A$, 2)
+ ENDWHILE
+ ENDCASE
+ENDWHILE
+IF file$ = "" AND (howto% AND &01) THEN
+ INPUT "boot: "file$
+ELSE
+ IF file$ = "" THEN file$ = "netbsd"
+ENDIF
+PRINT "Booting "; file$; " (howto = 0x"; ~howto%; ")"
+PROCload_kernel(file$)
+DIM P% 1023
+REM
+[ OPT 2
+ .config%
+ EQUD &942B7DFE ; magic
+ EQUD 0 ; version
+ EQUD howto% ; boothowto
+ EQUD 0 ; bootdev
+ EQUD ssym% ; ssym
+ EQUD esym% ; esym
+ EQUD nbpp% ; nbpp
+ EQUD npages% ; npages
+ EQUD txtbase% ; txtbase
+ EQUD txtsize% ; txtsize
+ EQUD database% ; database
+ EQUD datasize% ; datasize
+ EQUD bssbase% ; bssbase
+ EQUD bsssize% ; bsssize
+ EQUD freebase% ; freebase
+ EQUD FNvdu_var(11) + 1 ; xpixels
+ EQUD FNvdu_var(12) + 1 ; ypixels
+ EQUD 1 << FNvdu_var(9) ; bpp
+ EQUD FNvdu_var(149) + FNvdu_var(150) - &02000000 ; screenbase (XXX?)
+ EQUD FNvdu_var(150) ; screensize
+]
+SYS "OS_Byte", 165 TO ,,crow%
+[ OPT 2
+ EQUD crow% * FNvdu_var(170) ; cpixelrow
+]
+REM };
+PROCstart_kernel(config%, 0, 0, 0, entry%)
+END
+
+DEF PROCget_mem_map
+ LOCAL block%
+ DIM block% (npages%+1)*12
+ FOR page%=0 TO npages%-1
+ block%!(page%*12) = page%
+ NEXT
+ block%!(npages%*12) = -1
+ SYS "OS_ReadMemMapEntries", block%
+ FOR page% = 0 TO npages%-1
+ vaddr%(page%) = block%!(page%*12+4)
+ access%(page%) = block%!(page%*12+8)
+ NEXT
+ IF debug% THEN PRINT "--------/-------/-------/-------"
+ FOR page%=0 TO npages%-1
+ IF access%(page%) = 3 THEN
+ IF debug% THEN PRINT ".";
+ ELSE
+ CASE TRUE OF
+ WHEN vaddr%(page%) < &0008000: IF debug% THEN PRINT "0";
+ WHEN vaddr%(page%) < &0010000: IF debug% THEN PRINT "+";
+ WHEN vaddr%(page%) < &1000000:
+ IF access%(page%) = 0 THEN
+ IF debug% THEN PRINT "*";
+ pgok%(page%) = TRUE
+ ELSE
+ IF debug% THEN PRINT "a";
+ ENDIF
+ WHEN vaddr%(page%) < &1400000: IF debug% THEN PRINT "d";
+ WHEN vaddr%(page%) < &1800000: IF debug% THEN PRINT "s";
+ WHEN vaddr%(page%) < &1C00000: IF debug% THEN PRINT "m";
+ WHEN vaddr%(page%) < &1E00000: IF debug% THEN PRINT "h";
+ WHEN vaddr%(page%) < &1F00000: IF debug% THEN PRINT "f";
+ WHEN vaddr%(page%) < &2000000: IF debug% THEN PRINT "S";
+ ENDCASE
+ ENDIF
+ IF page% MOD 32 = 31 AND debug% THEN PRINT
+ NEXT
+ENDPROC
+
+DEF PROCload_kernel(file$)
+ LOCAL file%, magic%
+ file% = OPENIN(file$)
+ IF file% = 0 THEN ERROR 1, "Can't open kernel"
+ DIM magic% 3
+ SYS "OS_GBPB", 3, file%, magic%, 4, 0
+ IF magic%?0 = 127 AND magic%?1 = ASC("E") AND magic%?2 = ASC("L") AND magic%?3 = ASC("F") THEN
+ PROCload_kernel_elf(file%)
+ ELSE
+ PROCload_kernel_aout(file%)
+ ENDIF
+ CLOSE#file%
+ENDPROC
+
+DEF PROCload_kernel_elf(file%)
+ LOCAL hdr%, phoff%, phentsize%, phnum%, phdrs%, ph%
+ LOCAL offset%, vaddr%, filesz%, memsz%, flags%, first%
+ LOCAL shoff%, shentsize%, shnum%, shdrs%, sh%, havesyms%, mshdrs%
+ DIM hdr% 51
+ SYS "OS_GBPB", 3, file%, hdr%, 52, 0
+ IF hdr%?4 <> 1 THEN ERROR 1, "Not a 32-bit ELF file"
+ IF hdr%?5 <> 1 THEN ERROR 1, "Not an LSB ELF file"
+ IF hdr%?6 <> 1 THEN ERROR 1, "Not a version-1 ELF file"
+ REM hdr%?7 is EI_OSABI. Should it be 255 (ELFOSABI_STANDALONE)?
+ IF (hdr%!16 AND &FFFF) <> 2 THEN ERROR 1, "Not an executable ELF file"
+ IF (hdr%!18 AND &FFFF) <> 40 THEN ERROR 1, "Not an ARM ELF file"
+ entry% = hdr%!24
+ phoff% = hdr%!28
+ shoff% = hdr%!32
+ phentsize% = hdr%!42 AND &FFFF
+ phnum% = hdr%!44 AND &FFFF
+ shentsize% = hdr%!46 AND &FFFF
+ shnum% = hdr%!48 AND &FFFF
+ DIM phdrs% phnum% * phentsize% - 1
+ SYS "OS_GBPB", 3, file%, phdrs%, phnum% * phentsize%, phoff%
+ IF phnum% = 0 THEN ERROR 1, "No program headers"
+ first% = TRUE
+ FOR ph% = phdrs% TO phdrs% + (phnum% - 1) * phentsize% STEP phentsize%
+ IF ph%!0 <> 1 THEN NEXT : REM We only do PT_LOAD
+ IF NOT first% THEN PRINT "+";
+ first% = FALSE
+ offset% = ph%!4
+ vaddr% = ph%!8
+ filesz% = ph%!16
+ memsz% = ph%!20
+ flags% = ph%!24
+ PROCload_chunk(file%, offset%, vaddr%, filesz%, memsz%)
+ freebase% = vaddr% - &02000000 + memsz% : REM XXX
+ NEXT
+ txtbase% = 0
+ txtsize% = 0
+ database% = 0
+ datasize% = 0
+ bssbase% = 0
+ bsssize% = 0
+ ssym% = 0
+ esym% = 0
+ DIM shdrs% shnum% * shentsize% - 1
+ SYS "OS_GBPB", 3, file%, shdrs%, shnum% * shentsize%, shoff%
+ IF shnum% <> 0 THEN
+ havesyms% = FALSE
+ FOR sh% = shdrs% TO shdrs% + (shnum% - 1) * shentsize% STEP shentsize%
+ IF sh%!4 = 2 THEN havesyms% = TRUE
+ NEXT
+ IF havesyms% THEN
+ ssym% = freebase%
+ REM First, we have the munged ELF header
+ PRINT "+[";
+ PROCload_chunk(file%, 0, &02000000 + ssym%, 52, 52)
+ PROCwrite_word(ssym%+32, 52)
+ freebase% += 52
+ REM then, the munged section headers
+ mshdrs% = freebase%
+ PRINT "+";
+ PROCload_chunk(file%, shoff%, &02000000 + mshdrs%, shnum% * shentsize%, shnum% * shentsize%)
+ freebase% += shnum% * shentsize%
+ FOR sh% = shdrs% TO shdrs% + (shnum% - 1) * shentsize% STEP shentsize%
+ IF sh%!4 = 2 OR sh%!4 = 3 THEN
+ PRINT "+";
+ PROCload_chunk(file%, sh%!16, &02000000 + freebase%, sh%!20, sh%!20)
+ PROCwrite_word(mshdrs% + sh% - shdrs% + 16, freebase% - ssym%)
+ freebase% += FNroundup(sh%!20, 4)
+ ENDIF
+ NEXT
+ esym% = freebase%
+ PRINT "]";
+ ENDIF
+ ENDIF
+ PRINT " "
+ REM XXX
+ENDPROC
+
+DEF PROCload_chunk(file%, offset%, vaddr%, filesz%, memsz%)
+ LOCAL paddr%, ppn%, fragaddr%, fragsz%
+ PRINT ;filesz%;
+ WHILE filesz% > 0
+ paddr% = vaddr% - &02000000
+ ppn% = paddr% DIV nbpp%
+ IF NOT pgok%(ppn%) THEN ERROR 1, "Page " + STR$(ppn$) + " not free"
+ fragaddr% = vaddr%(ppn%) + paddr% MOD nbpp%
+ fragsz% = nbpp% - (paddr% MOD nbpp%)
+ IF fragsz% > filesz% THEN fragsz% = filesz%
+ SYS "OS_GBPB", 3, file%, fragaddr%, fragsz%, offset%
+ PROCtwirl
+ offset% += fragsz%
+ vaddr% += fragsz%
+ filesz% -= fragsz%
+ memsz% -= fragsz%
+ ENDWHILE
+ IF memsz% > 0 PRINT "+";memsz%;
+ WHILE memsz% > 0
+ paddr% = vaddr% - &02000000
+ ppn% = paddr% DIV nbpp%
+ IF NOT pgok%(ppn%) THEN ERROR 1, "Page " + STR$(ppn$) + " not free"
+ fragaddr% = vaddr%(ppn%) + paddr% MOD nbpp%
+ fragsz = nbpp% - (paddr% MOD nbpp%)
+ IF fragsz% > memsz% THEN fragsz% = memsz%
+ PROCbzero(fragaddr%, fragsz%)
+ PROCtwirl
+ offset% += fragsz%
+ vaddr% += fragsz%
+ filesz% -= fragsz%
+ memsz% -= fragsz%
+ ENDWHILE
+ENDPROC
+
+DEF PROCwrite_word(paddr%, val%)
+ !(vaddr%(paddr% DIV nbpp%) + paddr% MOD nbpp%) = val%
+ENDPROC
+
+DEF PROCload_kernel_aout(file%)
+ LOCAL hdr%
+ DIM hdr% 32
+ ssym% = 0 : esym% = 0
+ SYS "OS_GBPB", 3, file%, hdr%, 32, 0
+ bemagic% = (hdr%?0 << 24) OR (hdr%?1 <<16) OR (hdr%?2 << 8) OR hdr%?3
+ IF debug% THEN
+ CASE bemagic% AND &0000FFFF OF
+ WHEN &0107
+ PRINT "(OMAGIC)";
+ WHEN &0108
+ PRINT "(NMAGIC)";
+ WHEN &010B
+ PRINT "(ZMAGIC)";
+ WHEN &00CC
+ PRINT "(QMAGIC)";
+ ENDCASE
+ ENDIF
+ REM XXX: Assume ZMAGIC
+
+ REM foooff% is byte offset in file. foobasepage% is base page in RAM.
+ txtoff% = nbpp%
+ txtbase% = &98000
+ txtbasepage% = txtbase% DIV nbpp%
+ txtsize% = hdr%!4
+ IF txtsize% MOD nbpp% <> 0 THEN
+ ERROR EXT 1, "Text size not a multiple of page size"
+ ENDIF
+ txtpages% = txtsize% DIV nbpp%
+ dataoff% = txtoff% + txtsize%
+ databasepage% = txtbasepage% + txtpages%
+ database% = databasepage% * nbpp%
+ datasize% = hdr%!8
+ IF datasize% MOD nbpp% <> 0 THEN
+ ERROR EXT 1, "Data size not a multiple of page size"
+ ENDIF
+ datapages% = datasize% DIV nbpp%
+ bssbasepage% = databasepage% + datapages%
+ bssbase% = bssbasepage% * nbpp%
+ bsssize% = hdr%!12
+ freebase% = bssbase% + bsssize%
+ entry% = hdr%!20
+
+ PRINT ;txtsize%;
+ FOR pg% = 0 TO txtpages%-1
+ IF NOT pgok%(txtbasepage% + pg%) THEN ERROR 0,"Page not mine!"
+ SYS "OS_GBPB", 3, file%, vaddr%(txtbasepage%+pg%), nbpp%, txtoff% + pg%*nbpp%
+ PROCtwirl
+ NEXT
+
+ PRINT "+";datasize%;
+ FOR pg% = 0 TO datapages%-1
+ IF NOT pgok%(databasepage% + pg%) THEN ERROR 0,"Page not mine!"
+ SYS "OS_GBPB", 3, file%, vaddr%(databasepage%+pg%), nbpp%, dataoff% + pg%*nbpp%
+ PROCtwirl
+ NEXT
+
+ PRINT "+";bsssize%;
+ FOR pg% = 0 TO bsssize% DIV nbpp% : REM overshoot is safe
+ IF NOT pgok%(bssbasepage% + pg%) THEN ERROR 0,"Page not mine!"
+ PROCbzero(vaddr%(bssbasepage%+pg%), nbpp%)
+ PROCtwirl
+ NEXT
+
+ PRINT " "
+
+ENDPROC
+
+DEF PROCtwirl
+ PRINT MID$("|/-\", twirl%+1, 1)+CHR$(8);
+ twirl% += 1
+ twirl% = twirl% MOD 4
+ENDPROC
+
+DEF FNtolower(string$)
+ LOCAL ptr%, c%, out$
+ out$ = ""
+ IF string$ = "" THEN =string$
+ FOR ptr% = 1 TO LEN(string$)
+ c% = ASC(MID$(string$, ptr%, 1))
+ IF c% >= ASC("A") AND c% <= ASC("Z") THEN c% += 32
+ out$ += CHR$(c%)
+ NEXT
+=out$
+
+DEF PROCbzero(addr%, len%)
+ LOCAL a%
+ FOR a% = 0 TO len%-4 STEP 4
+ addr%!a% = 0
+ NEXT
+ENDPROC
+
+DEF PROCstart_kernel(A%, B%, C%, D%, E%)
+ REM parameters:
+ REM R0: -> bootconfig structure
+ REM R1: unused
+ REM R2: unused
+ REM R3: unused
+ REM R4: kernel entry point
+ LOCAL asm%, P%
+ DIM asm% 256
+ FOR pass% = 0 TO 2 STEP 2
+ P%=asm%
+ [ OPT pass%
+ STMFD R13!,{R14}
+ STMFD R13!,{R0-R4}
+ ]
+ IF FNswi_valid("Cache_Control") THEN
+ [ OPT pass%
+ MOV R0, 1
+ MVN R1, 1 ; Disable cache
+ SWI "Cache_Control"
+ SWI "Cache_Flush"
+ ]
+ ENDIF
+ [ OPT pass%
+ MOV R0, #1
+ SWI "Sound_Enable"
+ SWI "OS_IntOff"
+ LDMFD R13!, {R0-R4}
+ SWI "OS_EnterOS"
+ ; We now attempt to be APCS compliant on entry to the kernel.
+ ; Kernel APCS is 26bit/explicit/nofpregs/non-reentrant
+ ; Kernel stack is &02090000--&02088000 and coincides with RISC OS's
+ ; system stack page on >=4Mb machines.
+ ADR R5, regs%
+ LDMIA R5, {R10-R14}
+ MOV PC, R4
+ .regs%
+ EQUD &02088000; R10 -- Stack limit
+ EQUD &00000000; R11 -- Frame pointer (NULL in this case)
+ EQUD &00000000; R12 -- Scratch in non-re-entrant APCS
+ EQUD &02090000; R13 -- Stack pointer
+ EQUD &03800003; R14 -- Return address and mode
+ ]
+ NEXT
+ CALL asm%
+ENDPROC
+
+DEF FNswi_valid(swi$)
+ LOCAL flags%
+ SYS "XOS_SWINumberFromString",,swi$ TO ;flags%
+ IF flags% AND 1 THEN =FALSE
+=TRUE
+
+DEF FNvdu_var(var%)
+ LOCAL b%
+ DIM b% 7
+ b%!0 = var%
+ b%!4 = -1
+ SYS "OS_ReadVduVariables", b%, b%
+= b%!0
+
+DEF FNroundup(val%, size%)
+=val% + (size% - 1) AND NOT (size% - 1)
diff --git a/sys/arch/arm26/compile/.keep_me b/sys/arch/arm26/compile/.keep_me
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/sys/arch/arm26/compile/.keep_me
diff --git a/sys/arch/arm26/conf/GENERIC b/sys/arch/arm26/conf/GENERIC
new file mode 100644
index 00000000000..451c46bc328
--- /dev/null
+++ b/sys/arch/arm26/conf/GENERIC
@@ -0,0 +1,178 @@
+# $NetBSD: GENERIC,v 1.1 2000/05/09 21:55:58 bjh21 Exp $
+
+# GENERIC arm26 configuration -- everything I've implemented so far
+
+include "arch/arm26/conf/std.arm26"
+
+maxusers 8
+
+# CPU support
+options CPU_ARM2
+options CPU_ARM250
+options CPU_ARM3
+
+# Diagnostic/debugging support options
+options DIAGNOSTIC # Cheap kernel consistency checks
+options DEBUG # More expensive checks and printfs
+options DDB # kernel debugger
+#options SYSCALL_DEBUG # trace syscall entry/exit
+options SCSIDEBUG
+
+## Compile the kernel with debugging symbols (`netbsd.gdb' is the debug file),
+## such that gdb(1) can be used on a kernel coredump.
+#makeoptions DEBUG="-g"
+
+# File systems
+file-system FFS # Fast file system
+#file-system LFS # log-structured file system
+#file-system MFS # Memory-based file system
+#file-system EXT2FS # second extended file system (linux)
+#file-system CD9660 # ISO-9660 CD-ROM FS (w/RockRidge extensions)
+file-system FILECORE # Acorn filecore file system
+#file-system ADOSFS # AmigaDOS-compatible file system
+#file-system MSDOSFS # MS-DOS-compatible file system
+#file-system NTFS # Windows/NT file system (experimental)
+file-system NFS # Sun NFS-compatible file system client
+#file-system NULLFS # loopback file system
+#file-system OVERLAY # overlay filesystem
+#file-system PORTAL # portal filesystem (still experimental)
+#file-system UMAPFS # NULLFS + uid and gid remapping
+#file-system UNION # union file system
+file-system PROCFS # /proc
+file-system KERNFS # /kern
+file-system FDESC # /dev/fd
+
+# File system options
+#options QUOTA # UFS quotas
+#options NFSSERVER # Sun NFS-compatible file system server
+#options FFS_EI # FFS endianness-independence support
+#options SOFTDEP # FFS soft updates support.
+
+# Pull in config fragments for kernel crypto. This is required for
+# options IPSEC etc. to work. If you want to run with IPSEC, uncomment
+# one of these, based on whether you use crypto-us or crypto-intl, and
+# adjust the prefixes as necessary.
+
+#prefix ../crypto-us/sys
+#cinclude "conf/files.crypto-us"
+#prefix
+
+#prefix ../crypto-intl/sys
+#cinclude "conf/files.crypto-intl"
+#prefix
+
+# Executable format options
+#options EXEC_AOUT
+options EXEC_ELF32
+options EXEC_SCRIPT
+
+# Networking options
+options GATEWAY # packet forwarding
+options INET # Internet protocol suite
+#options INET6 # IPV6
+#options IPSEC # IP security
+#options IPSEC_ESP # IP security (encryption part; define w/IPSEC)
+#options IPSEC_DEBUG # debug for IP security
+#options MROUTING # IP multicast routing
+#options NS # XNS
+#options NSIP # XNS tunneling over IP
+#options ISO,TPIP # OSI
+#options EON # OSI tunneling over IP
+#options CCITT,LLC,HDLC # X.25
+#options NETATALK # AppleTalk networking
+#options PFIL_HOOKS # pfil(9) packet filter hooks
+#options PPP_BSDCOMP # BSD-Compress compression support for PPP
+#options PPP_DEFLATE # Deflate compression support for PPP
+#options PPP_FILTER # Active filter support for PPP (requires bpf)
+#options TCP_COMPAT_42 # TCP bug compatibility with 4.2BSD
+
+# 4.3BSD compatibility.
+#options COMPAT_43
+
+# Binary compatibility with previous versions of NetBSD.
+# None yet, since NetBSD/arm26 hasn't been released.
+
+# System V IPC
+#options SYSVMSG # System V-like message queues
+#options SYSVSEM # System V-like semaphores
+#options SYSVSHM # System V-like shared memory
+#options SHMMAXPGS=1024 # 1024 pages is the default
+
+# Miscellaneous kernel options
+options KTRACE # system call tracing, a la ktrace(1)
+#options IRQSTATS # manage IRQ statistics
+#options LKM # loadable kernel modules
+#options KMEMSTATS # kernel memory statistics
+#options SCSIVERBOSE # Verbose SCSI errors
+
+# Disable kernel security.
+#options INSECURE
+
+# NFS boot options
+options NFS_BOOT_DHCP # superset of BOOTP
+options NFS_BOOT_BOOTPARAM
+
+# WS console uses DUMB, SUN or VT100 terminal emulation
+#options WSEMUL_NODUMB
+#options WSEMUL_SUN
+options WSEMUL_VT100
+options FONT_VT220L8x8 # 8x8 font for console
+
+config netbsd root on ? type ?
+#config netbsd root on sd0 type ffs
+#config netbsd root on ? type nfs
+
+cpu0 at root
+
+iobus0 at root # 16-bit I/O bus
+
+ioc0 at iobus0 base 0x200000 # I/O controller
+
+iic0 at ioc0 # I^2C serial bus
+rtc0 at iic0 addr 0xa0 # Real-time clock
+
+arckbd0 at ioc0 bank 0 offset 0x04 # System keyboard
+arcwskbd0 at arckbd0 # Logical devices...
+wskbd0 at arcwskbd0
+arcwsmouse0 at arckbd0
+wsmouse0 at arcwsmouse0
+
+ioeb0 at ioc0 bank 5 # I/O Extension Block (A5000)
+
+podulebus0 at ioc0 bank 4 # Expansion card bus
+unixbp0 at ioc0 bank 6 # Unix Backplane (interrupt routing)
+
+ei* at podulebus0 slot ? # Acorn AKA25 (Ether1)
+ea* at podulebus0 slot ? # Acorn/Atomwide Ether3
+
+dtide* at podulebus0 slot ? # D.T. Software IDE interface
+wd* at dtide? channel ? drive ?
+
+#asc* at podulebus0 slot ? # Acorn SCSI card (AKA30, AKA31)
+#scsibus* at asc?
+
+arcvideo0 at root # On-board video
+wsdisplay0 at arcvideo0
+
+pseudo-device bpfilter 16
+#pseudo-device ccd 4
+#pseudo-device raid 4 # RAIDframe disk driver
+#options RAID_AUTOCONFIG # auto-configuration of RAID components
+#pseudo-device ipfilter 1
+pseudo-device loop 1
+pseudo-device md 1
+#options MEMORY_DISK_HOOKS
+#options MINIROOTSIZE=
+#pseudo-device ppp 4
+pseudo-device pty 64
+#pseudo-device sl 4
+#pseudo-device vnd 4
+#pseudo-device gre 2 # generic L3 over IP tunnel
+#pseudo-device gif 4 # IPv[46] over IPv[46] tunnel (RFC1933)
+#pseudo-device faith 1 # IPv[46] tcp relay translation i/f
+#pseudo-device sequencer 1 # MIDI sequencer
+#pseudo-device wsmux 2 # keyboard/mouse multiplexor
+
+# rnd is EXPERIMENTAL
+#pseudo-device rnd # /dev/random and in-kernel generator
+
diff --git a/sys/arch/arm26/conf/Makefile.arm26 b/sys/arch/arm26/conf/Makefile.arm26
new file mode 100644
index 00000000000..69cf8a0ec63
--- /dev/null
+++ b/sys/arch/arm26/conf/Makefile.arm26
@@ -0,0 +1,190 @@
+# $NetBSD: Makefile.arm26,v 1.1 2000/05/09 21:55:58 bjh21 Exp $
+
+# Makefile for NetBSD/arm26
+#
+# This makefile is constructed from a machine description:
+# config machineid
+# Most changes should be made in the machine description
+# /sys/arch/arm26/conf/``machineid''
+# after which you should do
+# config machineid
+# Machine generic makefile changes should be made in
+# /sys/arch/arm26/conf/Makefile.arm26
+# 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.
+
+MACHINE=arm26
+MACHINE_ARCH=arm26
+
+AR?= ar
+AS?= as
+CC?= gcc
+CPP?= gcc -E
+LD?= ld
+LORDER?= lorder
+MKDEP?= mkdep
+NM?= nm
+RANLIB?=ranlib
+SIZE?= size
+STRIP?= strip
+TSORT?= tsort -q
+
+COPTS?= -O2
+
+# source tree is located via $S relative to the compilation directory
+.ifndef S
+S!= cd ../../../..; pwd
+.endif
+ARM26= $S/arch/arm26
+
+INCLUDES= -I. -I$S/arch -I$S -nostdinc
+CPPFLAGS= ${INCLUDES} ${IDENT} ${PARAM} -D_KERNEL -Darm26 -Wcomment
+CWARNFLAGS= -Wall -Wstrict-prototypes -Wmissing-prototypes
+CFLAGS= -mcpu=arm2 -ffixed-r14 ${DEBUG} ${COPTS} ${CWARNFLAGS}
+AFLAGS= -x assembler-with-cpp -D_LOCORE
+
+LINKFLAGS= -Ttext 02098000 -e start
+STRIPFLAGS= -d
+
+# Re-arrange for cross-compiling
+HOSTED_CC= cc
+HOSTED_CPPFLAGS=${CPPFLAGS:S/^-nostdinc$//}
+HOSTED_CFLAGS= ${CFLAGS}
+
+### 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} where TYPE is NORMAL or
+# HOSTED}, and SUFFIX is the file suffix, capitalized (e.g. C for a .c file).
+
+NORMAL_C= ${CC} ${CFLAGS} ${CPPFLAGS} ${PROF} -c $<
+NORMAL_S= ${CC} ${AFLAGS} ${CPPFLAGS} -c $<
+
+HOSTED_C= ${HOSTED_CC} ${HOSTED_CFLAGS} ${HOSTED_CPPFLAGS} -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 \
+ 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} ${STRIPFLAGS} $@; ${STRIP} ${STRIPFLAGS} $@
+.else
+#LINKFLAGS+= -S
+LINKFLAGS+= -x
+.endif
+
+%LOAD
+
+assym.h: $S/kern/genassym.sh ${ARM26}/arm26/genassym.cf
+ sh $S/kern/genassym.sh ${CC} ${CFLAGS} ${CPPFLAGS} ${PROF} \
+ < ${ARM26}/arm26/genassym.cf > assym.h.tmp && \
+ mv -f assym.h.tmp assym.h
+
+param.c: $S/conf/param.c
+ rm -f param.c
+ cp $S/conf/param.c .
+
+param.o: param.c Makefile
+ ${NORMAL_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
+
+__CLEANKERNEL: .USE
+ @echo "${.TARGET}ing the kernel objects"
+ rm -f eddep *netbsd netbsd.gdb tags *.[io] [a-z]*.s \
+ [Ee]rrs linterrs makelinks assym.h.tmp assym.h
+
+__CLEANDEPEND: .USE
+ rm -f .depend
+
+clean: __CLEANKERNEL
+
+cleandir: __CLEANKERNEL __CLEANDEPEND
+
+lint:
+ @lint -hbxncez -Dvolatile= ${CPPFLAGS} -UKGDB \
+ ${CFILES} 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= ${ARM26}/arm26/locore.S \
+ param.c ioconf.c ${CFILES} ${SFILES}
+depend: .depend
+.depend: ${SRCS} assym.h
+ ${MKDEP} ${AFLAGS} ${CPPFLAGS} ${ARM26}/arm26/locore.S
+ ${MKDEP} -a ${CFLAGS} ${CPPFLAGS} param.c ioconf.c ${CFILES}
+ ${MKDEP} -a ${AFLAGS} ${CPPFLAGS} ${SFILES}
+# ${MKDEP} -a ${HOSTED_CFLAGS} ${HOSTED_CPPFLAGS} ${ARM26}/arm26/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
+cpufunc.o cpufunc_asm.o cpuswitch.o fault.o machdep.o: Makefile
+
+
+locore.o: ${ARM26}/arm26/locore.S assym.h
+ ${NORMAL_S}
+
+%RULES
diff --git a/sys/arch/arm26/conf/files.arm26 b/sys/arch/arm26/conf/files.arm26
new file mode 100644
index 00000000000..b230c4012b5
--- /dev/null
+++ b/sys/arch/arm26/conf/files.arm26
@@ -0,0 +1,236 @@
+# $NetBSD: files.arm26,v 1.1 2000/05/09 21:55:58 bjh21 Exp $
+
+# Copyright (c) 1997, 1998, 2000 Ben Harris
+# 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.
+
+# This file is part of NetBSD/arm26 -- a port of NetBSD to ARM2/3 machines.
+
+maxpartitions 8
+maxusers 2 8 64
+
+include "dev/wscons/files.wscons"
+include "dev/rasops/files.rasops"
+include "dev/wsfont/files.wsfont"
+
+include "dev/ata/files.ata"
+major { wd = 4 }
+include "dev/scsipi/files.scsipi"
+major {sd = 5}
+major {cd = 6}
+
+# CPU
+device cpu
+attach cpu at root
+defopt opt_cputypes.h CPU_ARM2 CPU_ARM250 CPU_ARM3
+file arch/arm26/arm26/cpu.c cpu
+
+# I/O bus (on the far side of the address and data latches)
+device iobus { base = -1 }
+attach iobus at root
+file arch/arm26/iobus/iobus.c iobus
+
+# 82C710/1 on A5000 etc will be at iobus0 base 0x00010000 (and 0x00012000???)
+
+# I/O controller (Albion) (usually at iobus0 base 0x00200000)
+device ioc { [bank = -1], [offset = 0] }
+attach ioc at iobus
+file arch/arm26/iobus/ioc.c ioc needs-flag
+
+# I^2C bus (bit-banged through IOC control register)
+device iic { addr = -1 }
+attach iic at ioc
+file arch/arm26/ioc/iic.c iic
+
+# PCF8583 I^2C Clock/calendar/RAM
+device rtc
+attach rtc at iic
+file arch/arm26/ioc/rtc.c rtc
+file dev/clock_subr.c rtc
+
+# I/O Extension Block (usually at ioc0 bank 5)
+device ioeb { [offset = -1] }
+attach ioeb at ioc
+file arch/arm26/ioc/ioeb.c ioeb needs-flag
+
+# A3010 joysticks
+device joy
+attach joy at ioeb
+
+# Latches (random internal use) (usually at bank 5 offset 0x18 and 0x40)
+device latch
+attach latch at ioc
+
+# On-board keyboard interface
+device arckbd { }
+attach arckbd at ioc
+device arcwskbd: wskbddev
+attach arcwskbd at arckbd
+device arcwsmouse: wsmousedev
+attach arcwsmouse at arckbd
+file arch/arm26/ioc/arckbd.c arckbd needs-flag
+file arch/arm26/ioc/arckbdmap.c arckbd
+
+# On-board WD 1772 floppy controller (usually at bank 1 irq 12 fiq 0/1)
+# Not to be confused with fdc, which will be the PC-style one on A5k etc.
+device wfdc {drive = -1}
+attach wfdc at ioc
+device wf: disk
+attach wf at wfdc
+# Steal code from arch/atari/dev/fd{.c,reg.h}
+#major {...}
+
+# Econet module (Motorola 6854) (usually at bank 2 fiq 2)
+device ec: ifnet, arp
+attach ec at ioc
+
+# On-board Rockwell 6551 serial (usually at bank 3 irq 10/1)
+device rs: tty
+attach rs at ioc
+file arch/arm26/arm26/rscons.c rs needs-flag
+
+# Podule interface (podules listed later) (usually at bank 4 irq 13 fiq 6)
+# Unix backplanes also use bank 6
+# MEMC podules also use the iobus directly
+# XXX How on Earth do we codify all that?
+device unixbp
+attach unixbp at ioc
+device podulebus { [slot = -1] }
+attach podulebus at ioc
+file arch/arm26/podulebus/podulebus.c podulebus
+file arch/arm26/podulebus/unixbp.c unixbp needs-flag
+
+# Acorn ST506 interface (usually at bank 5 irq 11, or sometimes on a podule)
+device hdc { drive = -1 }
+attach hdc at ioc with hdc_ioc
+attach hdc at podulebus with hdc_podulebus
+device hd: disk
+attach hd at hdc
+#major {hd = ?}
+
+# On-board printer port (usually at bank 5 addr 0x10 irq 0/2)
+device arclpt
+attach arclpt at ioc
+
+# VIDC/MEMC audio/video subsystems.
+# XXX: should be rasops4 as well
+device arcvideo: rasops1, rasops2, rasops8, wsemuldisplaydev
+attach arcvideo at root
+file arch/arm26/vidc/arcvideo.c arcvideo needs-flag
+
+device arcaudio: audio
+attach arcaudio at root
+
+# 82C7xx Universal Peripheral Controller
+device upc { [offset = -1] }
+attach upc at iobus
+
+attach wdc at upc with wdc_upc
+device lpt
+attach lpt at upc with lpt_upc
+attach com at upc with com_upc
+
+device fdc { drive }
+attach fdc at upc with fdc_upc
+device fd: disk
+attach fd at fdc
+
+###
+# Assorted podules
+#
+
+# Acorn Ether1
+device ei: ether, ifnet, arp, i82586
+attach ei at podulebus
+file arch/arm26/podulebus/if_ei.c ei
+
+# Acorn/Atomwide Ether3
+device ea: ether, ifnet, arp
+attach ea at podulebus
+file arch/arm26/podulebus/if_ea.c ea
+
+# D.T. software IDE
+device dtide {[channel = -1]}: wdc_base, ata, atapi
+attach dtide at podulebus
+file arch/arm26/podulebus/dtide.c dtide
+
+# Generic sbic (WD3393) driver
+define sbic
+file arch/arm26/podulebus/sbic.c sbic
+
+# Acorn SCSI I specific layer for sbic
+device asc: scsi, sbic
+attach asc at podulebus
+file arch/arm26/podulebus/asc.c asc needs-flag
+
+
+# Memory disk for installation (or ROM versions?)
+file arch/arm26/arm26/md_root.c memory_disk_hooks
+major { md = 1 }
+
+####
+# Other files
+#
+
+file dev/cons.c
+file dev/cninit.c
+
+file arch/arm32/arm32/in_cksum_arm32.c inet
+file netinet/in4_cksum.c inet
+file netns/ns_cksum.c ns
+
+file arch/arm26/arm26/db_disasm.c ddb
+file arch/arm26/arm26/db_interface.c ddb
+file arch/arm26/arm26/db_machdep.c ddb
+file arch/arm26/arm26/db_trace.c ddb
+
+file arch/arm26/arm26/disksubr.c disk
+file arch/arm26/arm26/disksubr_mbr.c disk
+file arch/arm26/arm26/disksubr_acorn.c disk
+
+file arch/arm26/arm26/aout_machdep.c exec_aout
+
+file arch/arm26/arm26/start.c
+file arch/arm26/arm26/autoconf.c
+file arch/arm26/arm26/bus.c
+file arch/arm26/arm26/conf.c
+file arch/arm26/arm26/cons_machdep.c
+file arch/arm26/arm26/copyinout.S
+file arch/arm26/arm26/copyinoutstr.c
+#file arch/arm26/arm26/copystr.S
+file arch/arm26/arm26/except.c
+file arch/arm26/arm26/irq.c
+file arch/arm26/arm26/intrnames.S
+file arch/arm26/arm26/Locore.c
+file arch/arm26/arm26/machdep.c
+file arch/arm26/arm26/mem.c
+file arch/arm26/arm26/pmap.c
+#file arch/arm26/arm26/rscons.c
+#file arch/arm26/arm26/spl_machdep.c
+file arch/arm26/arm26/softintr.c
+file arch/arm26/arm26/stubs.c
+file arch/arm26/arm26/vm_machdep.c
+file arch/arm26/arm26/zeropage.S
+file arch/arm32/arm32/disassem.c
+
diff --git a/sys/arch/arm26/conf/std.arm26 b/sys/arch/arm26/conf/std.arm26
new file mode 100644
index 00000000000..881bf59e792
--- /dev/null
+++ b/sys/arch/arm26/conf/std.arm26
@@ -0,0 +1,6 @@
+# $NetBSD: std.arm26,v 1.1 2000/05/09 21:55:58 bjh21 Exp $
+
+# Standard NetBSD/arm26 options
+
+machine arm26
+
diff --git a/sys/arch/arm26/include/Makefile b/sys/arch/arm26/include/Makefile
new file mode 100644
index 00000000000..aad8a8ff38e
--- /dev/null
+++ b/sys/arch/arm26/include/Makefile
@@ -0,0 +1,15 @@
+# $NetBSD: Makefile,v 1.1 2000/05/09 21:55:58 bjh21 Exp $
+
+KDIR= /sys/arch/arm26/include
+INCSDIR= /usr/include/arm26
+
+INCS= ansi.h aout_machdep.h armreg.h asm.h boot.h bswap.h bus.h cdefs.h \
+ cpu.h db_machdep.h disklabel.h \
+ disklabel_acorn.h elf_machdep.h endian.h endian_machdep.h float.h \
+ fp.h frame.h ieee.h ieeefp.h intr.h ipkdb.h irq.h \
+ limits.h lock.h math.h \
+ param.h pcb.h pmap.h proc.h profile.h ptrace.h reg.h \
+ setjmp.h signal.h spl.h stdarg.h trap.h types.h undefined.h \
+ varargs.h vmparam.h
+
+.include <bsd.kinc.mk>
diff --git a/sys/arch/arm26/include/ansi.h b/sys/arch/arm26/include/ansi.h
new file mode 100644
index 00000000000..2e90eff8cc4
--- /dev/null
+++ b/sys/arch/arm26/include/ansi.h
@@ -0,0 +1,81 @@
+/* $NetBSD: ansi.h,v 1.1 2000/05/09 21:55:58 bjh21 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 */
+#define _BSD_CLOCKID_T_ int /* clockid_t */
+#define _BSD_TIMER_T_ int /* timer_t */
+#define _BSD_SUSECONDS_T_ int /* suseconds_t */
+#define _BSD_USECONDS_T_ unsigned int /* useconds_t */
+#define _BSD_INTPTR_T_ int /* intptr_t */
+#define _BSD_UINTPTR_T_ unsigned int /* uintptr_t */
+
+/*
+ * 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/arm26/include/aout_machdep.h b/sys/arch/arm26/include/aout_machdep.h
new file mode 100644
index 00000000000..a57dd888346
--- /dev/null
+++ b/sys/arch/arm26/include/aout_machdep.h
@@ -0,0 +1,37 @@
+/* $NetBSD: aout_machdep.h,v 1.1 2000/05/09 21:55:58 bjh21 Exp $ */
+/*-
+ * Copyright (c) 1998 Ben Harris
+ * 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.
+ */
+/* This file is part of NetBSD/arm26 -- a port of NetBSD to ARM2/3 machines. */
+
+#ifndef _ARM26_AOUT_MACHDEP_H
+#define _ARM26_AOUT_MACHDEP_H
+
+#define __LDPGSZ 32768
+
+#define MID_ARM2 170
+
+#endif
diff --git a/sys/arch/arm26/include/armreg.h b/sys/arch/arm26/include/armreg.h
new file mode 100644
index 00000000000..d6f7bf893be
--- /dev/null
+++ b/sys/arch/arm26/include/armreg.h
@@ -0,0 +1,79 @@
+/* $NetBSD: armreg.h,v 1.1 2000/05/09 21:55:58 bjh21 Exp $ */
+/*-
+ * Copyright (c) 1998 Ben Harris
+ * 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.
+ */
+/* This file is part of NetBSD/arm26 -- a port of NetBSD to ARM2/3 machines. */
+
+#ifndef _ARM26_ARMREG_H
+#define _ARM26_ARMREG_H
+
+/* All the junk the old ARMs stuff in R15 */
+
+#define R15_MODE 0x00000003
+#define R15_MODE_USR 0x00000000
+#define R15_MODE_FIQ 0x00000001
+#define R15_MODE_IRQ 0x00000002
+#define R15_MODE_SVC 0x00000003
+
+#define R15_PC 0x03fffffc
+
+#define R15_FIQ_DISABLE 0x04000000
+#define R15_IRQ_DISABLE 0x08000000
+
+#define R15_FLAGS 0xf0000000
+#define R15_FLAG_N 0x80000000
+#define R15_FLAG_Z 0x40000000
+#define R15_FLAG_C 0x20000000
+#define R15_FLAG_V 0x10000000
+
+#define ARM_CP15_CPU_ID 0
+
+/* Not really many CPUs to consider */
+#define CPU_ID_DESIGNER_MASK 0xff000000
+#define CPU_ID_ARM_LTD 0x41000000
+#define CPU_ID_TYPE_MASK 0x00ff0000
+#define CPU_ID_ARM 0x00560000
+#define CPU_ID_CPU_MASK 0x0000fff0
+#define CPU_ID_ARM3 0x00000300
+#define CPU_ID_REVISION_MASK 0x0000000f
+
+/* Fake CPU IDs for older ARMs */
+#define CPU_ID_ARM2 0x00000200
+#define CPU_ID_ARM250 0x00000250
+
+/* ARM3-specific coprocessor 15 register */
+#define ARM3_CP15_FLUSH 1
+#define ARM3_CP15_CONTROL 2
+#define ARM3_CP15_CACHEABLE 3
+#define ARM3_CP15_UPDATEABLE 4
+#define ARM3_CP15_DISRUPTIVE 5
+
+/* Control register bits */
+#define ARM3_CTL_CACHE_ON 1
+#define ARM3_CTL_SHARED 2
+#define ARM3_CTL_MONITOR 4
+
+#endif
diff --git a/sys/arch/arm26/include/asm.h b/sys/arch/arm26/include/asm.h
new file mode 100644
index 00000000000..dd20b261c11
--- /dev/null
+++ b/sys/arch/arm26/include/asm.h
@@ -0,0 +1,117 @@
+/* $NetBSD: asm.h,v 1.1 2000/05/09 21:55:58 bjh21 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_
+
+#define _BEGIN_ENTRY_NP .text; .align 0
+#define _END_ENTRY_NP
+
+#ifdef GPROF
+# define _BEGIN_ENTRY _BEGIN_ENTRY_NP
+# define _END_ENTRY _END_ENTRY_NP
+#else
+# define _BEGIN_ENTRY _BEGIN_ENTRY_NP
+# define _END_ENTRY _END_ENTRY_NP
+#endif
+
+#ifdef __ELF__
+# define _C_FUNC(x) x
+# define _C_LABEL(x) x
+#else
+# ifdef __STDC__
+# define _C_FUNC(x) _ ## x
+# define _C_LABEL(x) _ ## x
+# else
+# define _C_FUNC(x) _/**/x
+# define _C_LABEL(x) _/**/x
+# endif
+#endif
+
+#ifdef __STDC__
+# define __CONCAT(x,y) x ## y
+# define __STRING(x) #x
+#else
+# define __CONCAT(x,y) x/**/y
+# define __STRING(x) "x"
+#endif
+#define _ASM_FUNC(x) x
+
+/*
+ * gas/arm uses @ as a single comment character and thus cannot be used here
+ * Instead it recognised the # instead of an @ symbols in .type directives
+ * We define a couple of macros so that assembly code will not be dependant
+ * on one or the other.
+ */
+#define _ASM_TYPE_FUNCTION #function
+#define _ASM_TYPE_OBJECT #object
+#define _ENTRY(x) .globl x; .type x,_ASM_TYPE_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 ENTRY_NP(y) _BEGIN_ENTRY_NP; _ENTRY(_C_FUNC(y)); _END_ENTRY_NP
+#define ASENTRY_NP(y) _BEGIN_ENTRY_NP; _ENTRY(_ASM_FUNC(y)); _END_ENTRY_NP
+
+#define ASMSTR .asciz
+
+#ifdef __ELF__
+#define RCSID(x) .section ".ident"; .asciz x
+#else
+#define RCSID(x) .text; .asciz x
+#endif
+
+#ifdef __STDC__
+#define WARN_REFERENCES(sym,msg) \
+ .stabs msg ## ,30,0,0,0 ; \
+ .stabs __STRING(_C_LABEL(sym)) ## ,1,0,0,0
+#elif defined(__ELF__)
+#define WARN_REFERENCES(sym,msg) \
+ .stabs msg,30,0,0,0 ; \
+ .stabs __STRING(sym),1,0,0,0
+#else
+#define WARN_REFERENCES(sym,msg) \
+ .stabs msg,30,0,0,0 ; \
+ .stabs __STRING(_/**/sym),1,0,0,0
+#endif /* __STDC__ */
+
+#endif /* !_ARM_ASM_H_ */
diff --git a/sys/arch/arm26/include/boot.h b/sys/arch/arm26/include/boot.h
new file mode 100644
index 00000000000..1da0a0e476b
--- /dev/null
+++ b/sys/arch/arm26/include/boot.h
@@ -0,0 +1,86 @@
+/* $NetBSD: boot.h,v 1.1 2000/05/09 21:55:58 bjh21 Exp $ */
+/*-
+ * Copyright (c) 1998 Ben Harris
+ * 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.
+ */
+/* This file is part of NetBSD/arm26 -- a port of NetBSD to ARM2/3 machines. */
+/*
+ * bootconfig.h -- Stuff to do with starting the kernel
+ */
+
+#ifndef _ARM26_BOOT_H
+#define _ARM26_BOOT_H
+
+#include <sys/types.h>
+
+/*
+ * Bootloader contract 0.2:
+ * + APCS conformant entry.
+ * + SVC mode.
+ * + Interrupts (IRQ and FIQ) disabled on CPU.
+ * + CPU caches disabled.
+ * + Physical memory below 512k is unused except for screen.
+ * + First three 32k blocks above 512k are zero page, stack and msgbuf.
+ * + From there to freebase should be preserved unless you know better.
+ * + From freebase to top of RAM is for general use.
+ * + VIDC is set up as specified (not really bootloader's job).
+ */
+
+#define BOOT_MAGIC 0x942B7DFE
+
+struct bootconfig {
+ u_int32_t magic; /* BOOT_MAGIC */
+ u_int32_t version; /* minor version of structure */
+ /* Standard NetBSD boot parameters */
+ u_int32_t boothowto; /* Reboot flags (single-user etc) */
+ u_int32_t bootdev; /* Boot device */
+ u_int32_t ssym; /* Start of debugging symbols */
+ u_int32_t esym; /* End of debugging symbols */
+ /* Parameters gathered by OS_ReadMemMapInfo */
+ u_int32_t nbpp; /* Machine page size in bytes */
+ u_int32_t npages; /* Number of pages */
+ /* Layout of physical memory. */
+ u_int32_t txtbase; /* Kernel text base */
+ u_int32_t txtsize; /* ... and size */
+ u_int32_t database; /* Ditto for data */
+ u_int32_t datasize; /* and bss */
+ u_int32_t bssbase; /* Note that base addresses are */
+ u_int32_t bsssize; /* "physical" ie bytes above 0x02000000 */
+ u_int32_t freebase; /* Start of free space */
+ /* Framebuffer state -- used to initialise raster console */
+ u_int32_t xpixels; /* Pixels across screen (XWindLimit + 1) */
+ u_int32_t ypixels; /* Pixels down screen (YWindLimit + 1) */
+ u_int32_t bpp; /* Bits per pixel (1 << Log2BPP) */
+ u_int32_t screenbase; /* Physical base of screen */
+ u_int32_t screensize; /* Size of framebuffer (TotalScreenSize) */
+ u_int32_t cpixelrow; /* first free pixel row on screen */
+ /* Version 0 ends here */
+};
+
+void start __P((struct bootconfig *));
+
+extern struct bootconfig bootconfig;
+
+#endif
diff --git a/sys/arch/arm26/include/bswap.h b/sys/arch/arm26/include/bswap.h
new file mode 100644
index 00000000000..b0d71f11f44
--- /dev/null
+++ b/sys/arch/arm26/include/bswap.h
@@ -0,0 +1,9 @@
+/* $NetBSD: bswap.h,v 1.1 2000/05/09 21:55:58 bjh21 Exp $ */
+
+#ifndef _MACHINE_BSWAP_H_
+#define _MACHINE_BSWAP_H_
+
+#define __BSWAP_RENAME
+#include <sys/bswap.h>
+
+#endif /* !_MACHINE_BSWAP_H_ */
diff --git a/sys/arch/arm26/include/bus.h b/sys/arch/arm26/include/bus.h
new file mode 100644
index 00000000000..e8b4c48f28e
--- /dev/null
+++ b/sys/arch/arm26/include/bus.h
@@ -0,0 +1,128 @@
+/* $NetBSD: bus.h,v 1.1 2000/05/09 21:55:58 bjh21 Exp $ */
+
+/*-
+ * Copyright (c) 2000 Ben Harris
+ * 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.
+ */
+/* This file is part of NetBSD/arm26 -- a port of NetBSD to ARM2/3 machines. */
+/*
+ * bus.h - Bus space functions for brivers
+ */
+
+#ifndef _ARM26_BUS_H_
+#define _ARM26_BUS_H_
+
+/*
+ * I believe that there's only one sensible bus space on the Archimedes,
+ * which corresponds to the system I/O bus.
+ *
+ * Some IDE cards have an odd shift applied to their registers. This is
+ * contained in the bus_space_tag_t.
+ */
+
+/* Addresses (in bus space). */
+typedef u_int bus_addr_t;
+typedef u_int bus_size_t;
+
+/* Access methods for bus space. */
+typedef int bus_space_tag_t;
+typedef bus_addr_t bus_space_handle_t;
+
+/* Mapping and unmapping operations. */
+#define BUS_SPACE_MAP_CACHEABLE 0x01
+#define BUS_SPACE_MAP_LINEAR 0x02
+extern int bus_space_map(bus_space_tag_t, bus_addr_t, bus_size_t, int,
+ bus_space_handle_t *);
+#define bus_space_unmap(t,h,s) /* Do nothing */
+extern int bus_space_subregion(bus_space_tag_t, bus_space_handle_t, bus_size_t,
+ bus_size_t, bus_space_handle_t *);
+extern int bus_space_shift(bus_space_tag_t, bus_space_handle_t, int,
+ bus_space_tag_t *, bus_space_handle_t *);
+
+/* Allocating and freeing bus space */
+#define bus_space_alloc(t, rs, re, s, a, b, c, ap, hp) (-1)
+#define bus_space_free(t, h, s) /* Do nothing */
+
+/* Bus barrier operations. */
+#define BUS_SPACE_BARRIER_READ 0
+#define BUS_SPACE_BARRIER_WRITE 0
+#define bus_space_barrier(t, h, o, l, f) /* Do nothing */
+
+/* Bus read (single) operations. */
+#define bus_space_read_1(t, h, o) (*(volatile u_int8_t *)((h) + ((o) << (t))))
+#define bus_space_read_2(t, h, o) (*(volatile u_int16_t *)((h) + ((o) << (t))))
+
+/* Bus write (single) operations. */
+#define bus_space_write_1(t, h, o, v) \
+ (*(volatile u_int8_t *)((h) + ((o) << (t))) = (v))
+#define bus_space_write_2(t, h, o, v) \
+ (*(volatile u_int32_t *)((h) + ((o) << (t))) = (v) | ((v) << 16))
+
+/* Bus read multiple operations. */
+extern void bus_space_read_multi_1(bus_space_tag_t, bus_space_handle_t,
+ bus_size_t, u_int8_t *, bus_size_t);
+extern void bus_space_read_multi_2(bus_space_tag_t, bus_space_handle_t,
+ bus_size_t, u_int16_t *, bus_size_t);
+#define bus_space_read_multi_4(t, h, o, d, s) panic("bus_space_read_multi_4")
+
+/* Bus write multiple operations. */
+extern void bus_space_write_multi_1(bus_space_tag_t, bus_space_handle_t,
+ bus_size_t, u_int8_t const *, bus_size_t);
+extern void bus_space_write_multi_2(bus_space_tag_t, bus_space_handle_t,
+ bus_size_t, u_int16_t const *, bus_size_t);
+#define bus_space_write_multi_4(t, h, o, d, s) panic("bus_space_write_multi_4")
+
+/* Bus set multiple operations. */
+extern void bus_space_set_multi_1(bus_space_tag_t, bus_space_handle_t,
+ bus_size_t, u_int8_t, bus_size_t);
+extern void bus_space_set_multi_2(bus_space_tag_t, bus_space_handle_t,
+ bus_size_t, u_int16_t, bus_size_t);
+
+/* Bus read region operations. */
+extern void bus_space_read_region_1(bus_space_tag_t, bus_space_handle_t,
+ bus_size_t, u_int8_t *, bus_size_t);
+extern void bus_space_read_region_2(bus_space_tag_t, bus_space_handle_t,
+ bus_size_t, u_int16_t *, bus_size_t);
+
+/* Bus write region operations. */
+extern void bus_space_write_region_1(bus_space_tag_t, bus_space_handle_t,
+ bus_size_t, u_int8_t const *, bus_size_t);
+extern void bus_space_write_region_2(bus_space_tag_t, bus_space_handle_t,
+ bus_size_t, u_int16_t const *,
+ bus_size_t);
+
+/* Bus set region operations. */
+extern void bus_space_set_region_1(bus_space_tag_t, bus_space_handle_t,
+ bus_size_t, u_int8_t, bus_size_t);
+extern void bus_space_set_region_2(bus_space_tag_t, bus_space_handle_t,
+ bus_size_t, u_int16_t, bus_size_t);
+
+/* Copy operations. */
+extern void bus_space_copy_1(bus_space_tag_t, bus_space_handle_t, bus_size_t,
+ bus_space_handle_t, bus_size_t, bus_size_t);
+extern void bus_space_copy_2(bus_space_tag_t, bus_space_handle_t, bus_size_t,
+ bus_space_handle_t, bus_size_t, bus_size_t);
+
+#endif /* _ARM26_BUS_H_ */
diff --git a/sys/arch/arm26/include/cdefs.h b/sys/arch/arm26/include/cdefs.h
new file mode 100644
index 00000000000..ef8862a1086
--- /dev/null
+++ b/sys/arch/arm26/include/cdefs.h
@@ -0,0 +1,3 @@
+/* $NetBSD: cdefs.h,v 1.1 2000/05/09 21:55:59 bjh21 Exp $ */
+
+/* Nothing here -- we're ordinary ELF */
diff --git a/sys/arch/arm26/include/cpu.h b/sys/arch/arm26/include/cpu.h
new file mode 100644
index 00000000000..180bacc8f5c
--- /dev/null
+++ b/sys/arch/arm26/include/cpu.h
@@ -0,0 +1,41 @@
+/* $NetBSD: cpu.h,v 1.1 2000/05/09 21:55:59 bjh21 Exp $ */
+/*-
+ * Copyright (c) 1998 Ben Harris
+ * 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.
+ */
+/* This file is part of NetBSD/arm26 -- a port of NetBSD to ARM2/3 machines. */
+
+#ifndef _ARM26_CPU_H
+#define _ARM26_CPU_H
+
+#include <machine/frame.h>
+
+/* Only one CPU */
+
+#define cpu_number() 0
+
+#define INSN_SIZE 4
+
+#endif
diff --git a/sys/arch/arm26/include/db_machdep.h b/sys/arch/arm26/include/db_machdep.h
new file mode 100644
index 00000000000..2f1fcaf06a4
--- /dev/null
+++ b/sys/arch/arm26/include/db_machdep.h
@@ -0,0 +1,90 @@
+/* $NetBSD: db_machdep.h,v 1.1 2000/05/09 21:55:59 bjh21 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 _ARM26_DB_MACHDEP_H_
+#define _ARM26_DB_MACHDEP_H_
+
+/*
+ * Machine-dependent defines for new kernel debugger.
+ */
+
+#include <vm/vm.h>
+#include <machine/armreg.h>
+#include <machine/frame.h>
+
+typedef vm_offset_t db_addr_t; /* address - unsigned */
+typedef long 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_r15 & R15_PC)
+#define PC_ADVANCE(regs) ((regs)->ddb_tf.tf_r15 += 4)
+
+#define BKPT_INST (0xe7ffffff) /* breakpoint instruction */
+#define BKPT_SIZE (INSN_SIZE) /* size of breakpoint inst */
+#define BKPT_SET(inst) (BKPT_INST)
+
+/*#define FIXUP_PC_AFTER_BREAK(regs) ((regs)->ddb_tf.tf_pc -= BKPT_SIZE)*/
+
+#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 inst_unconditional_flow_transfer(ins) (((ins) & 0xf0000000) == 0xe0000000)
+
+#define getreg_val (0)
+#define next_instr_address(pc, bd) (pc + INSN_SIZE)
+
+#define DB_MACHINE_COMMANDS
+
+#define SOFTWARE_SSTEP
+
+u_int branch_taken __P((u_int insn, u_int pc, db_regs_t *db_regs));
+
+/*
+ * We use ELF symbols in DDB.
+ */
+#define DB_ELF_SYMBOLS
+#define DB_ELFSIZE 32
+
+#endif /* _ARM26_DB_MACHDEP_H_ */
diff --git a/sys/arch/arm26/include/disklabel.h b/sys/arch/arm26/include/disklabel.h
new file mode 100644
index 00000000000..41230fd0498
--- /dev/null
+++ b/sys/arch/arm26/include/disklabel.h
@@ -0,0 +1,84 @@
+/* $NetBSD: disklabel.h,v 1.1 2000/05/09 21:55:59 bjh21 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 _MACHINE_DISKLABEL_H_
+#define _MACHINE_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 */
+
+#include <sys/dkbad.h>
+#include <machine/disklabel_acorn.h>
+#include <sys/disklabel_mbr.h>
+
+struct cpu_disklabel {
+#if 0 /* XXX not actually used by anything */
+ u_int pad0;
+ u_int pad1;
+ struct riscbsd_partition partitions[NRISCBSD_PARTITIONS];
+#endif
+ struct mbr_partition mbrparts[NMBRPART];
+ struct dkbad bad;
+};
+
+#ifdef _KERNEL
+struct buf;
+struct disklabel;
+int bounds_check_with_label __P((struct buf *, struct disklabel *, int));
+
+/* for readdisklabel. rv != 0 -> matches, msg == NULL -> success */
+int mbr_label_read __P((dev_t, void (*)(struct buf *), struct disklabel *,
+ struct cpu_disklabel *, char **, int *, int *));
+
+/* for writedisklabel. rv == 0 -> dosen't match, rv > 0 -> success */
+int mbr_label_locate __P((dev_t, void (*)(struct buf *),
+ struct disklabel *, struct cpu_disklabel *, int *, int *));
+#endif /* _KERNEL */
+
+#endif /* _MACHINE_DISKLABEL_H_ */
+
+/* End of disklabel.h */
diff --git a/sys/arch/arm26/include/disklabel_acorn.h b/sys/arch/arm26/include/disklabel_acorn.h
new file mode 100644
index 00000000000..9f6ef6a60ee
--- /dev/null
+++ b/sys/arch/arm26/include/disklabel_acorn.h
@@ -0,0 +1,121 @@
+/* $NetBSD: disklabel_acorn.h,v 1.1 2000/05/09 21:55:59 bjh21 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
+ */
+
+#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];
+};
+
+struct riscbsd_partition {
+ u_int rp_start;
+ u_int rp_length;
+ u_int rp_type;
+ char rp_name[16];
+};
+
+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;
+};
+
+#if defined(_KERNEL) && !defined(__ASSEMBLER__)
+struct buf;
+struct cpu_disklabel;
+struct disklabel;
+
+/* for readdisklabel. rv != 0 -> matches, msg == NULL -> success */
+int filecore_label_read __P((dev_t, void (*)(struct buf *),
+ struct disklabel *, struct cpu_disklabel *, char **, int *,
+ int *));
+/* for writedisklabel. rv == 0 -> dosen't match, rv > 0 -> success */
+int filecore_label_locate __P((dev_t, void (*)(struct buf *),
+ struct disklabel *, struct cpu_disklabel *, int *, int *));
+#endif
diff --git a/sys/arch/arm26/include/elf_machdep.h b/sys/arch/arm26/include/elf_machdep.h
new file mode 100644
index 00000000000..f250a680a0a
--- /dev/null
+++ b/sys/arch/arm26/include/elf_machdep.h
@@ -0,0 +1,44 @@
+/* $NetBSD: elf_machdep.h,v 1.1 2000/05/09 21:55:59 bjh21 Exp $ */
+
+#define ELF32_MACHDEP_ENDIANNESS ELFDATA2LSB
+
+/* Processor specific flags for the ELF header e_flags field. */
+#define EF_ARM_RELEXEC 0x00000001
+#define EF_ARM_HASENTRY 0x00000002
+#define EF_ARM_INTERWORK 0x00000004 /* GNU binutils 000413 */
+#define EF_ARM_SYMSARESORTED 0x00000004 /* ARM ELF A08 */
+#define EF_ARM_APCS_26 0x00000008
+#define EF_ARM_APCS_FLOAT 0x00000010
+#define EF_ARM_PIC 0x00000020
+#define EF_ARM_ALIGN8 0x00000040 /* 8-bit structure alignment. */
+#define EF_ARM_NEW_ABI 0x00000080
+#define EF_ARM_OLD_ABI 0x00000100
+#define EF_ARM_SOFT_FLOAT 0x00000200
+#define EF_ARM_EABIMASK 0xff000000
+
+#define ELF32_MACHDEP_ID_CASES \
+ case EM_ARM: \
+ break;
+
+#define ARCH_ELFSIZE 32 /* MD native binary size */
+
+#define R_ARM_NONE 0
+#define R_ARM_PC24 1
+#define R_ARM_ABS32 2
+#define R_ARM_REL32 3
+#define R_ARM_PC13 4
+#define R_ARM_ABS16 5
+#define R_ARM_ABS12 6
+#define R_ARM_THM_ABS5 7
+#define R_ARM_ABS8 8
+#define R_ARM_SBREL32 9
+#define R_ARM_THM_PC22 10
+#define R_ARM_THM_PC8 11
+#define R_ARM_AMP_VCALL9 12
+#define R_ARM_SWI24 13
+#define R_ARM_THM_SWI8 14
+#define R_ARM_XPC25 15
+#define R_ARM_THM_XPC22 16
+
+#define R_TYPE(name) __CONCAT(R_ARM_,name)
+
diff --git a/sys/arch/arm26/include/endian.h b/sys/arch/arm26/include/endian.h
new file mode 100644
index 00000000000..a6977570e0c
--- /dev/null
+++ b/sys/arch/arm26/include/endian.h
@@ -0,0 +1,3 @@
+/* $NetBSD: endian.h,v 1.1 2000/05/09 21:55:59 bjh21 Exp $ */
+
+#include <sys/endian.h>
diff --git a/sys/arch/arm26/include/endian_machdep.h b/sys/arch/arm26/include/endian_machdep.h
new file mode 100644
index 00000000000..a0a8d999042
--- /dev/null
+++ b/sys/arch/arm26/include/endian_machdep.h
@@ -0,0 +1,3 @@
+/* $NetBSD: endian_machdep.h,v 1.1 2000/05/09 21:55:59 bjh21 Exp $ */
+
+#define _BYTE_ORDER _LITTLE_ENDIAN
diff --git a/sys/arch/arm26/include/float.h b/sys/arch/arm26/include/float.h
new file mode 100644
index 00000000000..70c89e04ff3
--- /dev/null
+++ b/sys/arch/arm26/include/float.h
@@ -0,0 +1,89 @@
+/* $NetBSD: float.h,v 1.1 2000/05/09 21:55:59 bjh21 Exp $ */
+
+/*
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This software was developed by the Computer Systems Engineering group
+ * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
+ * contributed to Berkeley.
+ *
+ * All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Lawrence Berkeley Laboratory.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)float.h 8.1 (Berkeley) 6/11/93
+ */
+
+#ifndef _ARM32_FLOAT_H_
+#define _ARM32_FLOAT_H_
+
+#include <sys/cdefs.h>
+
+__BEGIN_DECLS
+extern int __flt_rounds();
+__END_DECLS
+
+#define FLT_RADIX 2 /* b */
+#define FLT_ROUNDS __flt_rounds()
+
+#define FLT_MANT_DIG 24 /* p */
+#define FLT_EPSILON 1.19209290E-07F /* b**(1-p) */
+#define FLT_DIG 6 /* floor((p-1)*log10(b))+(b == 10) */
+#define FLT_MIN_EXP -125 /* emin */
+#define FLT_MIN 1.17549435E-38F /* b**(emin-1) */
+#define FLT_MIN_10_EXP -37 /* ceil(log10(b**(emin-1))) */
+#define FLT_MAX_EXP 128 /* emax */
+#define FLT_MAX 3.40282347E+38F /* (1-b**(-p))*b**emax */
+#define FLT_MAX_10_EXP 38 /* floor(log10((1-b**(-p))*b**emax)) */
+
+#define DBL_MANT_DIG 53
+#define DBL_EPSILON 2.2204460492503131E-16
+#define DBL_DIG 15
+#define DBL_MIN_EXP -1021
+#define DBL_MIN 2.2250738585072014E-308
+#define DBL_MIN_10_EXP -307
+#define DBL_MAX_EXP 1024
+#define DBL_MAX 1.7976931348623157E+308
+#define DBL_MAX_10_EXP 308
+
+#define LDBL_MANT_DIG DBL_MANT_DIG
+#define LDBL_EPSILON DBL_EPSILON
+#define LDBL_DIG DBL_DIG
+#define LDBL_MIN_EXP DBL_MIN_EXP
+#define LDBL_MIN DBL_MIN
+#define LDBL_MIN_10_EXP DBL_MIN_10_EXP
+#define LDBL_MAX_EXP DBL_MAX_EXP
+#define LDBL_MAX DBL_MAX
+#define LDBL_MAX_10_EXP DBL_MAX_10_EXP
+
+#endif /* _ARM32_FLOAT_H_ */
diff --git a/sys/arch/arm26/include/fp.h b/sys/arch/arm26/include/fp.h
new file mode 100644
index 00000000000..4778bd4c14c
--- /dev/null
+++ b/sys/arch/arm26/include/fp.h
@@ -0,0 +1,86 @@
+/* $NetBSD: fp.h,v 1.1 2000/05/09 21:55:59 bjh21 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
+
+/*
+ * An extended precision floating point number
+ */
+
+typedef struct fp_extended_precision {
+ u_int32_t fp_exponent;
+ u_int32_t fp_mantissa_hi;
+ u_int32_t fp_mantissa_lo;
+} fp_extended_precision_t;
+
+typedef struct fp_extended_precision fp_reg_t;
+
+/*
+ * Information about the FPE-SP state that is stored in the pcb
+ *
+ * This needs to move and be hidden from userland.
+ */
+
+struct fpe_sp_state {
+ unsigned int fp_flags;
+ unsigned int fp_sr;
+ unsigned int fp_cr;
+ fp_reg_t fp_registers[16];
+};
+
+/*
+ * Type for a saved FP context, if we want to translate the context to a
+ * user-readable form
+ */
+
+typedef struct {
+ u_int32_t fpsr;
+ fp_extended_precision_t regs[8];
+} fp_state_t;
+
+#endif
+
+/* End of fp.h */
diff --git a/sys/arch/arm26/include/frame.h b/sys/arch/arm26/include/frame.h
new file mode 100644
index 00000000000..45f777d44b8
--- /dev/null
+++ b/sys/arch/arm26/include/frame.h
@@ -0,0 +1,165 @@
+/* $NetBSD: frame.h,v 1.1 2000/05/09 21:55:59 bjh21 Exp $ */
+/* $NetBSD: frame.h,v 1.1 2000/05/09 21:55:59 bjh21 Exp $ */
+
+/*
+ * Copyright (c) 1999 Ben Harris.
+ * Copyright (c) 1994-1997 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.
+ */
+/*
+ * frame.h - Stack frames structures
+ */
+
+#ifndef _ARM26_FRAME_H_
+#define _ARM26_FRAME_H_
+
+#ifndef _LOCORE
+
+#include <sys/signal.h>
+
+#include <machine/armreg.h>
+
+/*
+ * System stack frames.
+ */
+
+/*
+ * irqframes just contain registers that APCS specifies the callee
+ * need not preserve.
+ */
+typedef struct irqframe {
+ union {
+ struct {
+ register_t if_r0;
+ register_t if_r1;
+ register_t if_r2;
+ register_t if_r3;
+ register_t if_r12;
+ register_t if_r14;
+ } svc;
+ struct {
+ register_t if_r0;
+ register_t if_r1;
+ register_t if_r2;
+ register_t if_r3;
+ register_t if_r11;
+ register_t if_r12;
+ } usr;
+ } if_mode;
+ register_t if_r15; /* Must be fixed so we know which branch to use */
+} irqframe_t;
+
+#define clockframe irqframe
+
+/* All the CLKF_* macros take a struct clockframe * as an argument. */
+
+/* True if we took the interrupt in user mode */
+#define CLKF_USERMODE(frame) ((frame->if_r15 & R15_MODE) == R15_MODE_USR)
+
+/* True if we were at spl0 before the interrupt */
+#define CLKF_BASEPRI(frame) 0 /* FIXME */
+
+/* Extract the program counter from a clockframe */
+#define CLKF_PC(frame) (frame->if_r15 & R15_PC)
+
+/* True if we took the interrupt from inside another interrupt handler. */
+/* Non-trivial to check because we handle interrupts in SVC mode. */
+#define CLKF_INTR(frame) 0 /* FIXME */
+
+typedef struct trapframe {
+ register_t tf_r0;
+ register_t tf_r1;
+ register_t tf_r2;
+ register_t tf_r3;
+ register_t tf_r4;
+ register_t tf_r5;
+ register_t tf_r6;
+ register_t tf_r7;
+ register_t tf_r8;
+ register_t tf_r9;
+ register_t tf_r10;
+ register_t tf_r11;
+ register_t tf_r12;
+ register_t tf_r13;
+ register_t tf_r14;
+ register_t tf_r15;
+} 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 {
+ register_t sf_r4; /* Callee-saved registers */
+ register_t sf_r5;
+ register_t sf_r6;
+ register_t sf_r7;
+ register_t sf_r8;
+ register_t sf_r9;
+ register_t sf_r10;
+ register_t sf_r11; /* Frame pointer */
+ register_t sf_r13; /* Stack pointer */
+ register_t sf_r14; /* Return address */
+};
+
+/*
+ * Stack frame. Used during stack traces (db_trace.c)
+ */
+struct frame {
+ register_t fr_fp;
+ register_t fr_sp;
+ register_t fr_lr;
+ register_t fr_r15;
+};
+
+#ifdef _KERNEL
+void validate_trapframe __P((trapframe_t *, int));
+#endif /* _KERNEL */
+
+#endif _LOCORE
+
+#endif /* _ARM26_FRAME_H_ */
+
+/* End of frame.h */
diff --git a/sys/arch/arm26/include/ieee.h b/sys/arch/arm26/include/ieee.h
new file mode 100644
index 00000000000..d0056fc8a0e
--- /dev/null
+++ b/sys/arch/arm26/include/ieee.h
@@ -0,0 +1,150 @@
+/* $NetBSD: ieee.h,v 1.1 2000/05/09 21:55:59 bjh21 Exp $ */
+
+/*
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This software was developed by the Computer Systems Engineering group
+ * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
+ * contributed to Berkeley.
+ *
+ * All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Lawrence Berkeley Laboratory.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)ieee.h 8.1 (Berkeley) 6/11/93
+ */
+
+/*
+ * ieee.h defines the machine-dependent layout of the machine's IEEE
+ * floating point.
+ */
+
+/*
+ * Define the number of bits in each fraction and exponent.
+ *
+ * k k+1
+ * Note that 1.0 x 2 == 0.1 x 2 and that denorms are represented
+ *
+ * (-exp_bias+1)
+ * as fractions that look like 0.fffff x 2 . This means that
+ *
+ * -126
+ * the number 0.10000 x 2 , for instance, is the same as the normalized
+ *
+ * -127 -128
+ * float 1.0 x 2 . Thus, to represent 2 , we need one leading zero
+ *
+ * -129
+ * in the fraction; to represent 2 , we need two, and so on. This
+ *
+ * (-exp_bias-fracbits+1)
+ * implies that the smallest denormalized number is 2
+ *
+ * for whichever format we are talking about: for single precision, for
+ *
+ * -126 -149
+ * instance, we get .00000000000000000000001 x 2 , or 1.0 x 2 , and
+ *
+ * -149 == -127 - 23 + 1.
+ */
+#define SNG_EXPBITS 8
+#define SNG_FRACBITS 23
+
+#define DBL_EXPBITS 11
+#define DBL_FRACBITS 52
+
+#define E80_EXPBITS 15
+#define E80_FRACBITS 64
+
+#define EXT_EXPBITS 15
+#define EXT_FRACBITS 112
+
+struct ieee_single {
+ u_int sng_frac:23;
+ u_int sng_exponent:8;
+ u_int sng_sign:1;
+};
+
+struct ieee_double {
+ u_int dbl_frach:20;
+ u_int dbl_exp:11;
+ u_int dbl_sign:1;
+ u_int dbl_fracl;
+};
+
+struct ieee_e80 {
+ u_int e80_exp:15;
+ u_int e80_zero:16;
+ u_int e80_sign:1;
+ u_int e80_frach:31;
+ u_int e80_j:1;
+ u_int e80_fracl;
+};
+
+struct ieee_ext {
+ u_int ext_frach:16;
+ u_int ext_exp:15;
+ u_int ext_sign:1;
+ u_int ext_frachm;
+ u_int ext_fraclm;
+ u_int ext_fracl;
+};
+
+/*
+ * Floats whose exponent is in [1..INFNAN) (of whatever type) are
+ * `normal'. Floats whose exponent is INFNAN are either Inf or NaN.
+ * Floats whose exponent is zero are either zero (iff all fraction
+ * bits are zero) or subnormal values.
+ *
+ * A NaN is a `signalling NaN' if its QUIETNAN bit is clear in its
+ * high fraction; if the bit is set, it is a `quiet NaN'.
+ */
+#define SNG_EXP_INFNAN 255
+#define DBL_EXP_INFNAN 2047
+#define E80_EXP_INFNAN 32767
+#define EXT_EXP_INFNAN 32767
+
+#if 0
+#define SNG_QUIETNAN (1 << 22)
+#define DBL_QUIETNAN (1 << 19)
+#define E80_QUIETNAN (1 << 15)
+#define EXT_QUIETNAN (1 << 15)
+#endif
+
+/*
+ * Exponent biases.
+ */
+#define SNG_EXP_BIAS 127
+#define DBL_EXP_BIAS 1023
+#define E80_EXP_BIAS 16383
+#define EXT_EXP_BIAS 16383
diff --git a/sys/arch/arm26/include/ieeefp.h b/sys/arch/arm26/include/ieeefp.h
new file mode 100644
index 00000000000..ed76824723b
--- /dev/null
+++ b/sys/arch/arm26/include/ieeefp.h
@@ -0,0 +1,40 @@
+/* $NetBSD: ieeefp.h,v 1.1 2000/05/09 21:55:59 bjh21 Exp $ */
+
+/*
+ * Based on ieeefp.h written by J.T. Conklin, Apr 28, 1995
+ * Public domain.
+ */
+
+#ifndef _ARM32_IEEEFP_H_
+#define _ARM32_IEEEFP_H_
+
+/* FP exception codes */
+
+#define FP_EXCEPT_INV 0
+#define FP_EXCEPT_DZ 1
+#define FP_EXCEPT_OFL 2
+#define FP_EXCEPT_UFL 3
+#define FP_EXCEPT_IMP 4
+
+/* Exception type (used by fpsetmask() et al.) */
+
+typedef int fp_except;
+
+/* Bit defines for fp_except */
+
+#define FP_X_INV (1 << FP_EXCEPT_INV) /* invalid operation exception */
+#define FP_X_DZ (1 << FP_EXCEPT_DZ) /* divide-by-zero exception */
+#define FP_X_OFL (1 << FP_EXCEPT_OFL) /* overflow exception */
+#define FP_X_UFL (1 << FP_EXCEPT_UFL) /* underflow exception */
+#define FP_X_IMP (1 << FP_EXCEPT_IMP) /* imprecise (loss of precision; "inexact") */
+
+/* Rounding modes */
+
+typedef enum {
+ FP_RN=0, /* round to nearest representable number */
+ FP_RP=1, /* round toward positive infinity */
+ FP_RM=2, /* round toward negative infinity */
+ FP_RZ=3 /* round to zero (truncate) */
+} fp_rnd;
+
+#endif /* _ARM32_IEEEFP_H_ */
diff --git a/sys/arch/arm26/include/intr.h b/sys/arch/arm26/include/intr.h
new file mode 100644
index 00000000000..abb836f2d14
--- /dev/null
+++ b/sys/arch/arm26/include/intr.h
@@ -0,0 +1,53 @@
+/* $NetBSD: intr.h,v 1.1 2000/05/09 21:55:59 bjh21 Exp $ */
+/*-
+ * Copyright (c) 2000 Ben Harris
+ * 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.
+ */
+/* This file is part of NetBSD/arm26 -- a port of NetBSD to ARM2/3 machines. */
+/*
+ * intr.h - Interrupt stuff for the consumption of MI code.
+ *
+ * arm26-specific functions are in irq.h
+ */
+
+#ifndef _ARM26_INTR_H_
+#define _ARM26_INTR_H_
+
+#include <machine/spl.h> /* XXX should be merged into here */
+
+extern int hardsplx(int);
+
+extern void softintr_init(void);
+extern void setsoftclock(void);
+extern void setsoftnet(void);
+extern void dosoftints(int);
+
+#define __GENERIC_SOFT_INTERRUPTS
+
+extern void *softintr_establish(int, void (*)(void *), void *);
+extern void softintr_disestablish(void *);
+extern void softintr_schedule(void *);
+
+#endif
diff --git a/sys/arch/arm26/include/ipkdb.h b/sys/arch/arm26/include/ipkdb.h
new file mode 100644
index 00000000000..c349305477a
--- /dev/null
+++ b/sys/arch/arm26/include/ipkdb.h
@@ -0,0 +1,43 @@
+/* $NetBSD: ipkdb.h,v 1.1 2000/05/09 21:55:59 bjh21 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 NREG 16
+
+extern int ipkdbregs[NREG];
+
+extern int *ipkdb_find_stack();
+extern void ipkdb_free_stack __P((int *));
diff --git a/sys/arch/arm26/include/irq.h b/sys/arch/arm26/include/irq.h
new file mode 100644
index 00000000000..cb86037ce7f
--- /dev/null
+++ b/sys/arch/arm26/include/irq.h
@@ -0,0 +1,46 @@
+/* $NetBSD: irq.h,v 1.1 2000/05/09 21:55:59 bjh21 Exp $ */
+/*-
+ * Copyright (c) 2000 Ben Harris
+ * 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.
+ */
+/* This file is part of NetBSD/arm26 -- a port of NetBSD to ARM2/3 machines. */
+
+/* return values from interrupt handlers */
+/* These are the same as arm32 uses */
+#define IRQ_HANDLED 1
+#define IRQ_NOT_HANDLED 0
+#define IRQ_MAYBE_HANDLED -1
+
+struct irq_handler;
+
+extern void irq_init __P((void));
+/* irq_handler is declared in machdep.h */
+/* splx, raisespl and lowerspl are declared in spl.h */
+extern struct irq_handler *irq_establish __P((int irqnum, int ipl,
+ int func(void *), void *arg));
+extern char const *irq_string __P((struct irq_handler *h));
+extern void irq_enable __P((struct irq_handler *h));
+extern void irq_disable __P((struct irq_handler *h));
+extern void irq_genmasks __P((void));
diff --git a/sys/arch/arm26/include/limits.h b/sys/arch/arm26/include/limits.h
new file mode 100644
index 00000000000..bd2d24341d6
--- /dev/null
+++ b/sys/arch/arm26/include/limits.h
@@ -0,0 +1,97 @@
+/* $NetBSD: limits.h,v 1.1 2000/05/09 21:56:00 bjh21 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 0xff /* max value for a char */
+#define CHAR_MIN 0 /* 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_C_SOURCE) && !defined(_XOPEN_SOURCE) || \
+ defined(_ISOC99_SOURCE) || (__STDC_VERSION__ - 0) >= 199901L
+#define ULLONG_MAX 0xffffffffffffffffULL /* max unsigned long long */
+#define LLONG_MAX 0x7fffffffffffffffLL /* max signed long long */
+#define LLONG_MIN (-0x7fffffffffffffffLL-1) /* min signed long long */
+#endif
+
+#if !defined(_POSIX_C_SOURCE) && !defined(_XOPEN_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_C_SOURCE && !_XOPEN_SOURCE */
+#endif /* !_ANSI_SOURCE */
+
+#if !defined(_ANSI_SOURCE) && !defined(_POSIX_C_SOURCE) || \
+ defined(_XOPEN_SOURCE)
+#define LONG_BIT 32
+#define WORD_BIT 32
+
+#define DBL_DIG 15
+#define DBL_MAX 1.7976931348623157E+308
+#define DBL_MIN 2.2250738585072014E-308
+
+#define FLT_DIG 6
+#define FLT_MAX 3.40282347E+38F
+#define FLT_MIN 1.17549435E-38F
+#endif
+
+#endif /* _ARM32_LIMITS_H_ */
diff --git a/sys/arch/arm26/include/lock.h b/sys/arch/arm26/include/lock.h
new file mode 100644
index 00000000000..72310a6a372
--- /dev/null
+++ b/sys/arch/arm26/include/lock.h
@@ -0,0 +1,51 @@
+/* $NetBSD: lock.h,v 1.1 2000/05/09 21:56:00 bjh21 Exp $ */
+
+/*-
+ * Copyright (c) 2000 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Jason R. Thorpe.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the NetBSD
+ * Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation 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 NETBSD FOUNDATION, INC. 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 FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * Machine-dependent spin lock operations.
+ */
+
+#ifndef _ARM32_LOCK_H_
+#define _ARM32_LOCK_H_
+
+typedef int __cpu_simple_lock_t;
+
+#define __SIMPLELOCK_LOCKED 1
+#define __SIMPLELOCK_UNLOCKED 0
+
+#endif /* _ARM32_LOCK_H_ */
diff --git a/sys/arch/arm26/include/machdep.h b/sys/arch/arm26/include/machdep.h
new file mode 100644
index 00000000000..5d22f0fd9ea
--- /dev/null
+++ b/sys/arch/arm26/include/machdep.h
@@ -0,0 +1,64 @@
+/* $NetBSD: machdep.h,v 1.1 2000/05/09 21:56:00 bjh21 Exp $ */
+/*-
+ * Copyright (c) 1998 Ben Harris
+ * 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.
+ */
+/* This file is part of NetBSD/arm26 -- a port of NetBSD to ARM2/3 machines. */
+/*
+ * machdep.h - random exported functions that have to be declared somewhere.
+ */
+
+#ifndef _ARM26_MACHDEP_H
+#define _ARM26_MACHDEP_H
+
+struct bootconfig;
+
+/* start.c */
+extern void start __P((struct bootconfig *initbootconfig));
+
+/* except.c */
+extern void undefined_handler(struct trapframe *);
+extern void swi_handler(struct trapframe *);
+extern void data_abort_handler(struct trapframe *);
+extern void prefetch_abort_handler(struct trapframe *);
+extern void address_exception_handler(struct trapframe *);
+extern void ast_handler(struct trapframe *);
+
+/* irq.c */
+extern void irq_handler __P((struct irqframe *irqf));
+
+/* locore.S */
+extern void atomic_set_bit __P((u_int *address, u_int setmask));
+extern void atomic_clear_bit __P((u_int *address, u_int clearmask));
+extern register_t set_r13_irq __P((register_t r13_irq));
+extern void int_on __P((void));
+extern void int_off __P((void));
+extern void cpu_loswitch(struct switchframe **, struct switchframe *);
+extern void proc_trampoline(void); /* not quite true */
+extern void child_return(void *);
+
+/* pmap.c */
+extern register_t update_memc __P((register_t, register_t));
+#endif
diff --git a/sys/arch/arm26/include/math.h b/sys/arch/arm26/include/math.h
new file mode 100644
index 00000000000..e1d1b72795c
--- /dev/null
+++ b/sys/arch/arm26/include/math.h
@@ -0,0 +1,11 @@
+/* $NetBSD: math.h,v 1.1 2000/05/09 21:56:00 bjh21 Exp $ */
+
+/*
+ * ISO C99
+ */
+#if !defined(_ANSI_SOURCE) && \
+ (!defined(_POSIX_C_SOURCE) && !defined(_XOPEN_SOURCE) || \
+ defined(_ISOC99_SOURCE) || (__STDC_VERSION__ - 0) >= 199901L)
+extern __const char __nanf[];
+#define NAN (*(__const float *)(__const void *)__nanf)
+#endif
diff --git a/sys/arch/arm26/include/memcreg.h b/sys/arch/arm26/include/memcreg.h
new file mode 100644
index 00000000000..c1ea658c45c
--- /dev/null
+++ b/sys/arch/arm26/include/memcreg.h
@@ -0,0 +1,226 @@
+/* $NetBSD: memcreg.h,v 1.1 2000/05/09 21:56:00 bjh21 Exp $ */
+/*-
+ * Copyright (c) 1997, 1998 Ben Harris
+ * 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.
+ */
+/* This file is part of NetBSD/arm26 -- a port of NetBSD to ARM2/3 machines. */
+/*
+ * memcreg.h - Acorn/ARM MEMC (Anna/VC2304/VL2304/MEMC1A/VL2304A/VL86C110/VY86C110)
+ * registers
+ */
+
+#ifndef _ARM26_MEMCREG_H
+#define _ARM26_MEMCREG_H
+
+/*
+ * Accessing the MEMC is a little odd. It's not connected to the data
+ * bus, so the register and the new value are coded into an address.
+ * Thus, to set a register, OR together the register specifier and the
+ * new value, and write any word to the resultant address.
+ */
+
+#define MEMC_WRITE(value) *(volatile u_int32_t *)value = 0
+
+/*
+ * This information is mostly derived from:
+ * MEMC Datasheet
+ * Published by Acorn Computers Limited.
+ * Part no 0460,019
+ * Issue No 1.0
+ * 30 September 1986
+ * ISBN 1 85250 025 6
+ *
+ * Thanks must go to Jeanette Draper at ARM Ltd
+ * <jeanette.draper@arm.com> for finding it for me.
+ *
+ * Information on master/slave MEMCs came from Tony Duell
+ * <ard@p850ug1.demon.co.uk>, who has a copy of the MEMC1A data
+ * sheet and might photocopy it for me one day.
+ */
+
+/* General memory-map layout provided by MEMC */
+#define MEMC_PHYS_BASE ((caddr_t)0x02000000)
+#define MEMC_IO_BASE ((caddr_t)0x03000000)
+#define MEMC_VIDC_BASE ((caddr_t)0x03400000)
+#define MEMC_ROM_LOW_BASE ((caddr_t)0x03400000)
+#define MEMC_ROM_HIGH_BASE ((caddr_t)0x03800000)
+
+/*
+ * Each MEMC can manage 4Mb in 128 pages. The memory map only has
+ * space for 16Mb of physical RAM.
+ */
+#define MEMC_MAX_PHYSPAGES 512
+
+/*
+ * DMA address generator control registers. Addresses (>>4) go in
+ * bits 2-16, and must thus be in the bottom 512k of physical RAM.
+ */
+#define MEMC_DMA_MAX 0x00080000
+/* Video */
+#define MEMC_VINIT 0x03600000
+#define MEMC_VSTART 0x03620000
+#define MEMC_VEND 0x03640000
+/* Cursor */
+#define MEMC_CINIT 0x03660000
+/* Sound */
+#define MEMC_SSTARTN 0x03680000
+#define MEMC_SENDN 0x036A0000
+#define MEMC_SPTR 0x036C0000
+#define MEMC_SET_PTR(reg,addr) (reg | (addr >> 2))
+
+/* MEMC control register (sec 6.5) */
+#define MEMC_CONTROL 0x036E0000
+
+/* Page size */
+#define MEMC_CTL_PGSZ_MASK 0x0000000C
+#define MEMC_CTL_PGSZ_4K 0x00000000
+#define MEMC_CTL_PGSZ_8K 0x00000004
+#define MEMC_CTL_PGSZ_16K 0x00000008
+#define MEMC_CTL_PGSZ_32K 0x0000000C
+
+/* ROM speeds; low and high banks, relative to RAM speed */
+#define MEMC_CTL_LROMSPD_MASK 0x00000030
+#define MEMC_CTL_LROMSPD_4N 0x00000000
+#define MEMC_CTL_LROMSPD_3N 0x00000010
+#define MEMC_CTL_LROMSPD_2N 0x00000020
+#define MEMC_CTL_LROMSPD_PAGED 0x00000030
+
+#define MEMC_CTL_HROMSPD_MASK 0x000000C0
+#define MEMC_CTL_HROMSPD_4N 0x00000000
+#define MEMC_CTL_HROMSPD_3N 0x00000040
+#define MEMC_CTL_HROMSPD_2N 0x00000080
+#define MEMC_CTL_HROMSPD_PAGED 0x000000C0
+
+/* DRAM refresh control */
+#define MEMC_CTL_RFRSH_MASK 0x00000300
+#define MEMC_CTL_RFRSH_NONE 0x00000000
+#define MEMC_CTL_RFRSH_FLYBACK 0x00000100
+#define MEMC_CTL_RFRSH_CONTIN 0x00000300
+
+/* Enable video DMA */
+#define MEMC_CTL_VIDEODMA 0x00000400
+/* Enable sound DMA */
+#define MEMC_CTL_SOUNDDMA 0x00000800
+/* Operating System Mode Select */
+#define MEMC_CTL_OSMODE 0x00001000
+
+/* Test mode */
+/* This should never be set in a running system */
+#define MEMC_CTL_TESTMODE 0x00002000
+
+/*
+ * Address translation control
+ */
+
+/* Absolute address of translation table */
+#define MEMC_TRANS_BASE 0x03800000
+
+/*
+ * MEMC translation entries are painful, and vary with the page size
+ * in use. Here, ppn is the physical page number, lpn is the logical
+ * page number and ppl is the page protection level.
+ *
+ * This is correct for one or two MEMCs. Where the extra bits of ppn
+ * go with >2 is anyone's guess.
+ *
+ * The list of transformations at the start of each macro is copied
+ * verbatim from the MEMC datasheet (Figure 5). They don't mention
+ * the fact that, in all page sizes, A[7] selects whether to use the
+ * master or slave MEMC in dual-MEMC configurations. This would be
+ * represented here as "PPN[7]->A[7]".
+ */
+
+/* Page protection levels (data sheet section 6.6) */
+/*-
+ * PPL
+ * Mode 00 01 10 11
+ * SVC R/W R/W R/W R/W
+ * OS R/W R/W R R
+ * User R/W R - -
+ */
+
+#define MEMC_PPL_RDWR 0
+#define MEMC_PPL_RDONLY 1
+#define MEMC_PPL_NOACCESS 2
+
+/*-
+ * 4k pages:
+ * PPN[6:0] -> A[6:0]
+ * PPL[1:0] -> A[9:8]
+ * LPN[12:11] -> A[11:10]
+ * LPN[10:0] -> A[22:12]
+ */
+#define MEMC_TRANS_ENTRY_4K(ppn, lpn, ppl) \
+ (MEMC_TRANS_BASE | \
+ ((ppn) & 0xff) | \
+ ((ppl) & 0x3) << 8 | \
+ ((lpn) & 0x7ff) << 12 | ((lpn) & 0x1800) >> 1)
+/*-
+ * 8k pages:
+ * PPN[6] -> A[0]
+ * PPN[5:0] -> A[6:1]
+ * PPL[1:0] -> A[9:8]
+ * LPN[11:10] -> A[11:10]
+ * LPN[9:0] -> A[22:13]
+ */
+#define MEMC_TRANS_ENTRY_8K(ppn, lpn, ppl) \
+ (MEMC_TRANS_BASE | \
+ ((ppn) & 0x3f) << 1 | ((ppn) & 0x40) >> 6 | \
+ ((ppn) & 0x80) | \
+ ((ppl) & 0x3) << 8 | \
+ ((lpn) & 0x3ff) << 13 | ((lpn) & 0xc00))
+/*-
+ * 16k pages:
+ * PPN[6:5] -> A[1:0]
+ * PPN[4:0] -> A[6:2]
+ * PPL[1:0] -> A[9:8]
+ * LPN[10:9] -> A[11:10]
+ * LPN[9:0] -> A[22:14]
+ */
+#define MEMC_TRANS_ENTRY_16K(ppn, lpn, ppl) \
+ (MEMC_TRANS_BASE | \
+ ((ppn) & 0x1f) << 2 | ((ppn) & 0x60) >> 5 | \
+ ((ppn) & 0x80) | \
+ ((ppl) & 0x3) << 8 | \
+ ((lpn) & 0x1ff) << 14 | ((lpn) & 0x600) << 1)
+/*-
+ * 32k pages (here, the MEMC descends into madness...):
+ * PPN[6] -> A[1]
+ * PPN[5] -> A[2]
+ * PPN[4] -> A[0]
+ * PPN[3:0] -> A[6:3]
+ * PPL[1:0] -> A[9:8]
+ * LPN[9:8] -> A[11:10]
+ * LPN[7:0] -> A[22:15]
+ */
+#define MEMC_TRANS_ENTRY_32K(ppn, lpn, ppl) \
+ (MEMC_TRANS_BASE | \
+ ((ppn) & 0x0f) << 3 | ((ppn) & 0x10) >> 4 | \
+ ((ppn) & 0x20) >> 3 | ((ppn) & 0x40) >> 5 | \
+ ((ppn) & 0x80) | \
+ ((ppl) & 0x3) << 8 | \
+ ((lpn) & 0x0ff) << 15 | ((lpn) & 0x300) << 2)
+
+#endif
diff --git a/sys/arch/arm26/include/param.h b/sys/arch/arm26/include/param.h
new file mode 100644
index 00000000000..afacd017500
--- /dev/null
+++ b/sys/arch/arm26/include/param.h
@@ -0,0 +1,144 @@
+/* $NetBSD: param.h,v 1.1 2000/05/09 21:56:00 bjh21 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 _ARM26_PARAM_H_
+#define _ARM26_PARAM_H_
+
+#ifdef _KERNEL
+# include <machine/cpu.h>
+#endif
+
+#include <machine/spl.h>
+
+#define _MACHINE arm26
+#define MACHINE "arm26"
+#define _MACHINE_ARCH arm26
+#define MACHINE_ARCH "arm26"
+#define MID_MACHINE MID_ARM2
+
+/*
+ * 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.
+ *
+ * ALIGNED_POINTER is a boolean macro that checks whether an address
+ * is valid to fetch data elements of type t from on this architecture.
+ * This does not reflect the optimal alignment, just the possibility
+ * (within reasonable limits).
+ *
+ */
+#define ALIGNBYTES (sizeof(int) - 1)
+#define ALIGN(p) (((u_int)(p) + ALIGNBYTES) &~ ALIGNBYTES)
+#define ALIGNED_POINTER(p,t) ((((u_long)(p)) & (sizeof(t)-1)) == 0)
+
+#define PGSHIFT 15 /* LOG2(NBPG) */
+#define NBPG (1 << PGSHIFT) /* bytes/page */
+#define PGOFSET (NBPG-1) /* byte offset into page */
+
+#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 1 /* pages of u-area */
+#define USPACE (UPAGES * NBPG) /* total size of u-area */
+
+#ifndef MSGBUFSIZE
+#define MSGBUFSIZE NBPG /* default message buffer size */
+#endif
+
+/*
+ * 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
+
+/*
+ * Defaults for lower- and upper-bounds for the kmem_map page count.
+ * Can be overridden by kernel config options.
+ */
+#define NKMEMPAGES_MIN_DEFAULT 0
+#define NKMEMPAGES_MAX_DEFAULT 32
+
+/* pages ("clicks") 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) (((x) + PGOFSET) >> PGSHIFT)
+
+#define btodb(bytes) /* calculates (bytes / DEV_BSIZE) */ \
+ ((bytes) >> DEV_BSHIFT)
+#define dbtob(db) /* calculates (db * DEV_BSIZE) */ \
+ ((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))
+
+#ifdef _KERNEL
+#ifndef _LOCORE
+void delay __P((unsigned));
+#define DELAY(x) delay(x)
+#endif
+#endif
+
+#endif /* _ARM_PARAM_H_ */
diff --git a/sys/arch/arm26/include/pcb.h b/sys/arch/arm26/include/pcb.h
new file mode 100644
index 00000000000..310fc2e343e
--- /dev/null
+++ b/sys/arch/arm26/include/pcb.h
@@ -0,0 +1,52 @@
+/* $NetBSD: pcb.h,v 1.1 2000/05/09 21:56:00 bjh21 Exp $ */
+/*-
+ * Copyright (c) 2000 Ben Harris
+ * 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.
+ */
+/* This file is part of NetBSD/arm26 -- a port of NetBSD to ARM2/3 machines. */
+
+#ifndef _ARM26_PCB_H
+#define _ARM26_PCB_H
+
+struct trapframe;
+struct switchframe;
+
+struct pcb {
+ struct trapframe *pcb_tf;
+ struct switchframe *pcb_sf;
+ void *pcb_onfault; /* return here after failed page fault */
+ label_t *pcb_onfault_lj; /* longjmp here ditto */
+ label_t *pcb_onundef_lj; /* longjmp here on undefined instruction */
+};
+
+/*
+ * No additional data for core dumps.
+ */
+
+struct md_coredump {
+};
+
+
+#endif
diff --git a/sys/arch/arm26/include/pmap.h b/sys/arch/arm26/include/pmap.h
new file mode 100644
index 00000000000..d79485f256f
--- /dev/null
+++ b/sys/arch/arm26/include/pmap.h
@@ -0,0 +1,60 @@
+/* $NetBSD: pmap.h,v 1.1 2000/05/09 21:56:00 bjh21 Exp $ */
+/*-
+ * Copyright (c) 1997, 1998 Ben Harris
+ * 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.
+ */
+/* This file is part of NetBSD/arm26 -- a port of NetBSD to ARM2/3 machines. */
+
+/*
+ * machine/pmap.h - Machine-dependent pmap stuff from MEMC1A
+ */
+
+#ifndef _ARM26_PMAP_H
+#define _ARM26_PMAP_H
+
+struct pmap;
+
+typedef struct pmap *pmap_t;
+
+#ifdef _KERNEL
+#include <machine/memcreg.h>
+
+extern void pmap_bootstrap __P((int, paddr_t));
+
+extern struct pmap kernel_pmap_store;
+
+#define pmap_kernel() (&kernel_pmap_store)
+
+extern boolean_t pmap_confess(vaddr_t, vm_prot_t);
+
+extern boolean_t pmap_fault(pmap_t, vaddr_t, vm_prot_t);
+
+/* Save on hassle and kernel VM */
+#define PMAP_MAP_POOLPAGE(pa) ((vaddr_t)MEMC_PHYS_BASE + (pa))
+#define PMAP_UNMAP_POOLPAGE(va) ((va) - (vaddr_t)MEMC_PHYS_BASE)
+
+#endif /* _KERNEL */
+
+#endif
diff --git a/sys/arch/arm26/include/proc.h b/sys/arch/arm26/include/proc.h
new file mode 100644
index 00000000000..5469f673e16
--- /dev/null
+++ b/sys/arch/arm26/include/proc.h
@@ -0,0 +1,38 @@
+/* $NetBSD: proc.h,v 1.1 2000/05/09 21:56:00 bjh21 Exp $ */
+/*-
+ * Copyright (c) 1998 Ben Harris
+ * 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.
+ */
+/* This file is part of NetBSD/arm26 -- a port of NetBSD to ARM2/3 machines. */
+
+#ifndef _ARM26_PROC_H
+#define _ARM26_PROC_H
+
+/* arm26-specific part of struct proc */
+
+struct mdproc {
+};
+
+#endif
diff --git a/sys/arch/arm26/include/profile.h b/sys/arch/arm26/include/profile.h
new file mode 100644
index 00000000000..1216b0c72b1
--- /dev/null
+++ b/sys/arch/arm26/include/profile.h
@@ -0,0 +1,76 @@
+/* $NetBSD: profile.h,v 1.1 2000/05/09 21:56:00 bjh21 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 void _mcount
+
+/*
+ * Cannot implement mcount in C as GCC will trash the ip register when it
+ * pushes a trapframe. Pity we cannot insert assembly before the function
+ * prologue.
+ */
+#define MCOUNT \
+ __asm__(".text"); \
+ __asm__(".align 0"); \
+ __asm__(".type mcount,%function"); \
+ __asm__(".global mcount"); \
+ __asm__("mcount:"); \
+ /* \
+ * Preserve registers that are trashed during mcount \
+ */ \
+ __asm__("stmfd sp!, {r0-r3, lr}"); \
+ /* \
+ * find the return address for mcount, \
+ * and the return address for mcount's caller. \
+ * \
+ * frompcindex = pc pushed by call into self. \
+ */ \
+ __asm__("mov r0, ip"); \
+ /* \
+ * selfpc = pc pushed by mcount call \
+ */ \
+ __asm__("mov r1, lr"); \
+ /* \
+ * Call the real mcount code \
+ */ \
+ __asm__("bl __mcount"); \
+ /* \
+ * Restore registers that were trashed during mcount \
+ */ \
+ __asm__("ldmfd sp!, {r0-r3, pc}^");
+
+#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/arm26/include/pte.h b/sys/arch/arm26/include/pte.h
new file mode 100644
index 00000000000..d513a47b1f5
--- /dev/null
+++ b/sys/arch/arm26/include/pte.h
@@ -0,0 +1,33 @@
+/* $NetBSD: pte.h,v 1.1 2000/05/09 21:56:00 bjh21 Exp $ */
+/*-
+ * Copyright (c) 1998 Ben Harris
+ * 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.
+ */
+/* This file is part of NetBSD/arm26 -- a port of NetBSD to ARM2/3 machines. */
+
+#ifndef _ARM26_PTE_H
+#define _ARM26_PTE_H
+
+#endif
diff --git a/sys/arch/arm26/include/ptrace.h b/sys/arch/arm26/include/ptrace.h
new file mode 100644
index 00000000000..65a3e74e0c2
--- /dev/null
+++ b/sys/arch/arm26/include/ptrace.h
@@ -0,0 +1,41 @@
+/* $NetBSD: ptrace.h,v 1.1 2000/05/09 21:56:00 bjh21 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/arm26/include/reg.h b/sys/arch/arm26/include/reg.h
new file mode 100644
index 00000000000..d31906c1492
--- /dev/null
+++ b/sys/arch/arm26/include/reg.h
@@ -0,0 +1,53 @@
+/* $NetBSD: reg.h,v 1.1 2000/05/09 21:56:00 bjh21 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 _ARM26_REG_H_
+#define _ARM26_REG_H_
+
+#include <machine/fp.h>
+
+struct reg {
+ unsigned int r[13];
+ unsigned int r_sp;
+ unsigned int r_lr;
+ unsigned int r_pc;
+};
+
+struct fpreg {
+ unsigned int fpr_fpsr;
+ fp_reg_t fpr[8];
+};
+
+#endif /* !_ARM26_REG_H_ */
diff --git a/sys/arch/arm26/include/setjmp.h b/sys/arch/arm26/include/setjmp.h
new file mode 100644
index 00000000000..f1f832788b0
--- /dev/null
+++ b/sys/arch/arm26/include/setjmp.h
@@ -0,0 +1,79 @@
+/* $NetBSD: setjmp.h,v 1.1 2000/05/09 21:56:00 bjh21 Exp $ */
+
+/*
+ * machine/setjmp.h: machine dependent setjmp-related information.
+ */
+
+#define _JBLEN 29 /* size, in longs, of a jmp_buf */
+
+/*
+ * NOTE: The internal structure of a jmp_buf is *PRIVATE*
+ * This information is provided as there is software
+ * that fiddles with this with obtain the stack pointer
+ * (yes really ! and its commercial !).
+ *
+ * Description of the setjmp buffer
+ *
+ * word 0 magic number (dependant on creator)
+ * 1 - 3 f4 fp register 4
+ * 4 - 6 f5 fp register 5
+ * 7 - 9 f6 fp register 6
+ * 10 - 12 f7 fp register 7
+ * 13 fpsr fp status register
+ * 14 r4 register 4
+ * 15 r5 register 5
+ * 16 r6 register 6
+ * 17 r7 register 7
+ * 18 r8 register 8
+ * 19 r9 register 9
+ * 20 r10 register 10 (sl)
+ * 21 r11 register 11 (fp)
+ * 22 r12 register 12 (ip)
+ * 23 r13 register 13 (sp)
+ * 24 r14 register 14 (lr)
+ * 25 signal mask (dependant on magic)
+ *
+ * The magic number number identifies the jmp_buf and
+ * how the buffer was created as well as providing
+ * a sanity check
+ *
+ * A side note I should mention - Please do not tamper
+ * with the floating point fields. While they are
+ * always saved and restored at the moment this cannot
+ * be garenteed especially if the compiler happens
+ * to be generating soft-float code so no fp
+ * registers will be used.
+ *
+ * Whilst this can be seen an encouraging people to
+ * use the setjmp buffer in this way I think that it
+ * is for the best then if changes occur compiles will
+ * break rather than just having new builds falling over
+ * mysteriously.
+ */
+
+#define _JB_MAGIC__SETJMP 0x4278f500
+#define _JB_MAGIC_SETJMP 0x4278f501
+
+/* Valid for all jmp_buf's */
+
+#define _JB_MAGIC 0
+#define _JB_REG_F4 1
+#define _JB_REG_F5 4
+#define _JB_REG_F6 7
+#define _JB_REG_F7 10
+#define _JB_REG_FPSR 13
+#define _JB_REG_R4 14
+#define _JB_REG_R5 15
+#define _JB_REG_R6 16
+#define _JB_REG_R7 17
+#define _JB_REG_R8 18
+#define _JB_REG_R9 19
+#define _JB_REG_R10 20
+#define _JB_REG_R11 21
+#define _JB_REG_R12 22
+#define _JB_REG_R13 23
+#define _JB_REG_R14 24
+
+/* Only valid with the _JB_MAGIC_SETJMP magic */
+
+#define _JB_SIGMASK 25
diff --git a/sys/arch/arm26/include/signal.h b/sys/arch/arm26/include/signal.h
new file mode 100644
index 00000000000..5f551e440ed
--- /dev/null
+++ b/sys/arch/arm26/include/signal.h
@@ -0,0 +1,136 @@
+/* $NetBSD: signal.h,v 1.1 2000/05/09 21:56:00 bjh21 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 _ARM26_SIGNAL_H_
+#define _ARM26_SIGNAL_H_
+
+#ifndef _LOCORE
+typedef int sig_atomic_t;
+#endif
+
+#if !defined(_ANSI_SOURCE) && !defined(_POSIX_C_SOURCE) && \
+ !defined(_XOPEN_SOURCE)
+#ifndef _LOCORE
+/*
+ * 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.
+ */
+
+#if defined(__LIBC12_SOURCE__) || defined(_KERNEL)
+struct sigcontext13; /* No COMPAT_13 on arm26. */
+#endif /* __LIBC12_SOURCE__ || _KERNEL */
+
+struct sigcontext {
+ int sc_onstack; /* sigstack state to restore */
+
+ 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_r13;
+ unsigned int sc_r14;
+ unsigned int sc_r15;
+
+ sigset_t sc_mask; /* signal mask to restore */
+};
+
+#endif /* !_LOCORE */
+
+/* Signals codes */
+
+/*
+ * SIGFPE codes
+ *
+ * see ieeefp.h for definition of FP exception codes
+ */
+
+#define SIG_CODE_FPE_CODE_MASK 0x00000f00 /* Mask for exception code */
+#define SIG_CODE_FPE_CODE_SHIFT 8 /* Shift for exception code */
+#define SIG_CODE_FPE_TYPE_MASK 0x000000ff /* Mask for specific code */
+
+/*
+ * SIGILL codes
+ *
+ * the signal code is the instruction that raised the signal
+ */
+
+#if 0
+
+/*
+ * SIGBUS and SIGSEGV codes
+ *
+ * The signal code is combination of the fault address and the fault code.
+ *
+ * The fault code is the coproc #15 fault status code
+ *
+ * The exception to this is a SIGBUS or SIGSEGV from a prefetch abort.
+ * In this case the fault status code is not valid so the TYPE_MASK
+ * should be treated as undefined (in practice it is the bottom 4 bits
+ * of the fault address).
+ */
+
+#define SIG_CODE_BUS_ADDR_MASK 0xfffffff0
+#define SIG_CODE_BUS_TYPE_MASK 0x0000000f
+#define SIG_CODE_SEGV_ADDR_MASK SIG_CODE_BUS_ADDR_MASK
+#define SIG_CODE_SEGV_TYPE_MASK SIG_CODE_BUS_TYPE_MASK
+
+#endif
+
+#endif /* !_ANSI_SOURCE && !_POSIX_C_SOURCE && !_XOPEN_SOURCE */
+#endif /* !_ARM_SIGNAL_H_ */
+
+/* End of signal.h */
diff --git a/sys/arch/arm26/include/softintr.h b/sys/arch/arm26/include/softintr.h
new file mode 100644
index 00000000000..f5ce12e4155
--- /dev/null
+++ b/sys/arch/arm26/include/softintr.h
@@ -0,0 +1,40 @@
+/* $NetBSD: softintr.h,v 1.1 2000/05/09 21:56:00 bjh21 Exp $ */
+/*-
+ * Copyright (c) 1999 Ben Harris
+ * 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.
+ */
+/* This file is part of NetBSD/arm26 -- a port of NetBSD to ARM2/3 machines. */
+/* Software interrupt priority levels */
+
+#ifndef _ARM26_SOFTINTR_H
+#define _ARM26_SOFTINTR_H
+
+#define SOFTIRQ_CLOCK 0
+#define SOFTIRQ_NET 1
+#define SOFTIRQ_SERIAL 2
+
+#define SOFTIRQ_BIT(x) (1 << x)
+
+#endif /* _ARM26_SOFTINTR_H */
diff --git a/sys/arch/arm26/include/spl.h b/sys/arch/arm26/include/spl.h
new file mode 100644
index 00000000000..d2f7705d83e
--- /dev/null
+++ b/sys/arch/arm26/include/spl.h
@@ -0,0 +1,93 @@
+/* $NetBSD: spl.h,v 1.1 2000/05/09 21:56:00 bjh21 Exp $ */
+/*-
+ * Copyright (c) 1998 Ben Harris
+ * 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.
+ */
+/* This file is part of NetBSD/arm26 -- a port of NetBSD to ARM2/3 machines. */
+/*
+ * spl.h -- Software priority levels, I think.
+ */
+
+#ifndef _ARM26_SPL_H
+#define _ARM26_SPL_H
+
+/*
+ * These are the different SPL states
+ *
+ * Each state has an interrupt mask associated with it which
+ * indicate which interrupts are allowed.
+ */
+
+#define IPL_NONE 0
+#define IPL_SOFTCLOCK 1
+#define IPL_SOFTNET 2
+#define IPL_BIO 3
+#define IPL_NET 4
+#define IPL_TTY 5
+#define IPL_IMP 6
+#define IPL_AUDIO 7
+#define IPL_SERIAL 8
+#define IPL_CLOCK 9
+#define IPL_STATCLOCK 10
+#define IPL_SCHED 11
+#define IPL_HIGH 12
+#define NIPL IPL_HIGH + 1
+
+#define spl0() splx(IPL_NONE)
+#define splsoftnet() raisespl(IPL_SOFTNET)
+#define splsoftclock() raisespl(IPL_SOFTCLOCK)
+#define spllowersoftclock() lowerspl(IPL_SOFTCLOCK)
+#define splsoft() splsoftnet()
+#define splbio() raisespl(IPL_BIO)
+#define splnet() raisespl(IPL_NET)
+#define spltty() raisespl(IPL_TTY)
+#define splimp() raisespl(IPL_IMP)
+#define splaudio() raisespl(IPL_AUDIO)
+#define splclock() raisespl(IPL_CLOCK)
+#define splstatclock() raisespl(IPL_STATCLOCK)
+#define splhigh() splx(IPL_HIGH)
+
+#define signotify(p) setsoftast()
+
+#ifdef _KERNEL
+#ifndef ASSEMBLER
+extern int raisespl __P((int));
+extern int lowerspl __P((int));
+extern int splx __P((int));
+
+void setsoftnet __P((void));
+void setsoftast __P((void));
+void setsoftclock __P((void));
+void setsoftintr __P((u_int intrmask));
+
+extern int current_spl_level; /* XXX tautological name */
+
+void need_resched __P((void));
+void need_proftick __P((struct proc *));
+
+#endif /* ASSEMBLER */
+#endif /* _KERNEL */
+
+#endif /* ! _ARM26_SPL_H */
diff --git a/sys/arch/arm26/include/stdarg.h b/sys/arch/arm26/include/stdarg.h
new file mode 100644
index 00000000000..b6449d8bcf9
--- /dev/null
+++ b/sys/arch/arm26/include/stdarg.h
@@ -0,0 +1,60 @@
+/* $NetBSD: stdarg.h,v 1.1 2000/05/09 21:56:01 bjh21 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/arm26/include/trap.h b/sys/arch/arm26/include/trap.h
new file mode 100644
index 00000000000..bbe07e7ffb0
--- /dev/null
+++ b/sys/arch/arm26/include/trap.h
@@ -0,0 +1,58 @@
+/* $NetBSD: trap.h,v 1.1 2000/05/09 21:56:01 bjh21 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
+ *
+ * trap.h
+ *
+ * Various trap definitions
+ */
+
+/*
+ * Instructions used for breakpoints.
+ *
+ * These are an undefined instructions.
+ * Technically the userspace breakpoint could be a SWI
+ * but we want to keep this the same as IPKDB which
+ * needs an undefined instruction as a break point.
+ * Ideally ARM would define several standard instruction
+ * sequences for use as breakpoints.
+ */
+
+#define GDB_BREAKPOINT 0xe6000011 /* Used by GDB */
+#define IPKDB_BREAKPOINT 0xe6000010 /* Used by IPKDB */
+#define KERNEL_BREAKPOINT 0xe7ffffff /* Used by DDB */
+
+#define USER_BREAKPOINT GDB_BREAKPOINT
+
+/* End of trap.h */
diff --git a/sys/arch/arm26/include/types.h b/sys/arch/arm26/include/types.h
new file mode 100644
index 00000000000..cf181f9202d
--- /dev/null
+++ b/sys/arch/arm26/include/types.h
@@ -0,0 +1,88 @@
+/* $NetBSD: types.h,v 1.1 2000/05/09 21:56:01 bjh21 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>
+
+/* NB: This should probably be if defined(_KERNEL) */
+#if !defined(_POSIX_C_SOURCE) && !defined(_XOPEN_SOURCE)
+typedef unsigned long vm_offset_t;
+typedef unsigned long vm_size_t;
+
+typedef vm_offset_t paddr_t;
+typedef vm_size_t psize_t;
+typedef vm_offset_t vaddr_t;
+typedef vm_size_t vsize_t;
+#endif
+
+/*
+ * Basic integral types. Omit the typedef if
+ * not possible for a machine/compiler combination.
+ */
+#define __BIT_TYPES_DEFINED__
+typedef __signed char int8_t;
+typedef unsigned char u_int8_t;
+typedef short int16_t;
+typedef unsigned short u_int16_t;
+typedef int int32_t;
+typedef unsigned int u_int32_t;
+/* LONGLONG */
+typedef long long int64_t;
+/* LONGLONG */
+typedef unsigned long long u_int64_t;
+
+typedef int32_t register_t;
+
+#if !defined(_POSIX_C_SOURCE) && !defined(_XOPEN_SOURCE)
+/* This structure must be kept synchronised with setjmp.S */
+typedef struct label_t { /* Used by setjmp & longjmp */
+ register_t jb_r4;
+ register_t jb_r5;
+ register_t jb_r6;
+ register_t jb_r7;
+ register_t jb_r8;
+ register_t jb_r9;
+ register_t jb_r10;
+ register_t jb_r11;
+ register_t jb_r13;
+ register_t jb_r14;
+} label_t;
+#endif
+
+#endif /* _ARM32_TYPES_H_ */
diff --git a/sys/arch/arm26/include/undefined.h b/sys/arch/arm26/include/undefined.h
new file mode 100644
index 00000000000..4cbd9feba67
--- /dev/null
+++ b/sys/arch/arm26/include/undefined.h
@@ -0,0 +1,63 @@
+/* $NetBSD: undefined.h,v 1.1 2000/05/09 21:56:01 bjh21 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 *, int));
+
+#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/arm26/include/varargs.h b/sys/arch/arm26/include/varargs.h
new file mode 100644
index 00000000000..9fc0a8baab9
--- /dev/null
+++ b/sys/arch/arm26/include/varargs.h
@@ -0,0 +1,64 @@
+/* $NetBSD: varargs.h,v 1.1 2000/05/09 21:56:01 bjh21 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/arm26/include/vmparam.h b/sys/arch/arm26/include/vmparam.h
new file mode 100644
index 00000000000..96b3f4b97d2
--- /dev/null
+++ b/sys/arch/arm26/include/vmparam.h
@@ -0,0 +1,122 @@
+/* $NetBSD: vmparam.h,v 1.1 2000/05/09 21:56:01 bjh21 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.
+ */
+
+#ifndef _ARM32_VMPARAM_H_
+#define _ARM32_VMPARAM_H_
+
+#define USRTEXT VM_MIN_ADDRESS
+#define USRSTACK VM_MAXUSER_ADDRESS
+
+#define MAXTSIZ (0x007f8000) /* max text size */
+#ifndef DFLDSIZ
+#define DFLDSIZ (0x00800000) /* initial data size limit */
+#endif
+#ifndef MAXDSIZ
+#define MAXDSIZ (0x00800000) /* max data size */
+#endif
+#ifndef DFLSSIZ
+#define DFLSSIZ (512*1024) /* initial stack size limit */
+#endif
+#ifndef MAXSSIZ
+#define MAXSSIZ (0x00200000) /* max stack size */
+#endif
+
+/*
+ * 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
+ */
+
+/* Need to link some of these with some in param.h */
+
+/*
+ * These specify the range of virtual pages available to user
+ * processes and to the kernel. This is a bit of a delicate balancing
+ * act, as we've only got 32Mb between them. There should probably be
+ * an option to have separate kernel and user spaces to ease this.
+ */
+
+#define KVM_SIZE 0x00800000 /* 8Mb */
+
+/* User VM range */
+#define VM_MIN_ADDRESS ((vm_offset_t)0x00008000)
+#define VM_MAX_ADDRESS ((vm_offset_t)0x02000000 - KVM_SIZE)
+#define VM_MAXUSER_ADDRESS VM_MAX_ADDRESS
+
+/* Kernel VM range */
+#define VM_MIN_KERNEL_ADDRESS VM_MAX_ADDRESS
+#define VM_MAX_KERNEL_ADDRESS ((vm_offset_t)0x02000000)
+#define VM_MAXKERN_ADDRESS VM_MAX_KERNEL_ADDRESS
+
+/* XXX max. amount of KVM to be used by buffers. */
+#ifndef VM_MAX_KERNEL_BUF
+#define VM_MAX_KERNEL_BUF \
+ ((VM_MAX_KERNEL_ADDRESS - VM_MIN_KERNEL_ADDRESS) / 4)
+#endif
+
+/* Physical memory parameters */
+
+#define VM_PHYSSEG_MAX 2
+
+#define VM_PHYSSEG_STRAT VM_PSTRAT_BIGFIRST
+
+#define VM_PHYSSEG_NOADD /* We won't turn up extra memory during autoconfig */
+
+#define VM_NFREELIST 2
+#define VM_FREELIST_LOW 1 /* DMA-able memory (bottom 512k phys) */
+#define VM_FREELIST_DEFAULT 0 /* The rest */
+
+struct pmap_physseg {
+};
+
+#endif
+
+/* End of vmparam.h */
diff --git a/sys/arch/arm26/iobus/iobus.c b/sys/arch/arm26/iobus/iobus.c
new file mode 100644
index 00000000000..2f20191f291
--- /dev/null
+++ b/sys/arch/arm26/iobus/iobus.c
@@ -0,0 +1,116 @@
+/* $NetBSD: iobus.c,v 1.1 2000/05/09 21:56:01 bjh21 Exp $ */
+/*-
+ * Copyright (c) 1998 Ben Harris
+ * 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.
+ */
+/* This file is part of NetBSD/arm26 -- a port of NetBSD to ARM2/3 machines. */
+/*
+ * iobus.c - when the IORQ* calls...
+ */
+
+#include <sys/param.h>
+
+__RCSID("$NetBSD: iobus.c,v 1.1 2000/05/09 21:56:01 bjh21 Exp $");
+
+#include <sys/device.h>
+#include <sys/systm.h>
+
+#include <machine/bus.h>
+
+#include <arch/arm26/iobus/iobusvar.h>
+
+#include "locators.h"
+
+static int iobus_match __P((struct device *parent, struct cfdata *cf, void *aux));
+static void iobus_attach __P((struct device *parent, struct device *self, void *aux));
+static int iobus_search __P((struct device *parent, struct cfdata *cf, void *aux));
+static int iobus_print __P((void *aux, const char *pnp));
+
+struct iobus_softc {
+ struct device sc_dev;
+};
+
+struct cfattach iobus_ca = {
+ sizeof(struct iobus_softc), iobus_match, iobus_attach
+};
+
+extern struct cfdriver iobus_cd;
+
+static int
+iobus_match(parent, cf, aux)
+ struct device *parent;
+ struct cfdata *cf;
+ void *aux;
+{
+
+ /* There can be only one! */
+ if (cf->cf_unit == 0)
+ return 1;
+ else
+ return 0;
+}
+
+static void
+iobus_attach(parent, self, aux)
+ struct device *parent;
+ struct device *self;
+ void *aux;
+{
+
+ printf("\n");
+
+ config_search(iobus_search, self, NULL);
+}
+
+extern struct bus_space iobus_bs_tag;
+
+static int
+iobus_search(parent, cf, aux)
+ struct device *parent;
+ struct cfdata *cf;
+ void *aux;
+{
+ struct iobus_attach_args ioa;
+
+ ioa.ioa_tag = 2;
+ ioa.ioa_base = cf->cf_loc[IOBUSCF_BASE];
+ if ((cf->cf_attach->ca_match)(parent, cf, &ioa) > 0)
+ config_attach(parent, cf, &ioa, iobus_print);
+
+ return 0;
+}
+
+static int
+iobus_print(aux, pnp)
+ void *aux;
+ const char *pnp;
+{
+ struct iobus_attach_args *ioa = aux;
+
+ if (ioa->ioa_base != IOBUSCF_BASE_DEFAULT)
+ printf(" base 0x%06x", ioa->ioa_base);
+ return UNCONF;
+}
+
diff --git a/sys/arch/arm26/iobus/iobusvar.h b/sys/arch/arm26/iobus/iobusvar.h
new file mode 100644
index 00000000000..e9034c9c07e
--- /dev/null
+++ b/sys/arch/arm26/iobus/iobusvar.h
@@ -0,0 +1,45 @@
+/* $NetBSD: iobusvar.h,v 1.1 2000/05/09 21:56:01 bjh21 Exp $ */
+/*-
+ * Copyright (c) 1998 Ben Harris
+ * 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.
+ */
+/* This file is part of NetBSD/arm26 -- a port of NetBSD to ARM2/3 machines. */
+/*
+ * iobusvar.h - Things other people need to know about iobus.c
+ */
+
+#ifndef _ARM26_IOBUSVAR_H
+#define _ARM26_IOBUSVAR_H
+
+#include <machine/bus.h>
+
+/* Structure passed to children of an iobus */
+
+struct iobus_attach_args {
+ bus_space_tag_t ioa_tag;
+ bus_addr_t ioa_base;
+};
+
+#endif
diff --git a/sys/arch/arm26/iobus/ioc.c b/sys/arch/arm26/iobus/ioc.c
new file mode 100644
index 00000000000..cdbad40105f
--- /dev/null
+++ b/sys/arch/arm26/iobus/ioc.c
@@ -0,0 +1,529 @@
+/* $NetBSD: ioc.c,v 1.1 2000/05/09 21:56:01 bjh21 Exp $ */
+/*-
+ * Copyright (c) 1998, 1999, 2000 Ben Harris
+ * 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.
+ */
+/* This file is part of NetBSD/arm26 -- a port of NetBSD to ARM2/3 machines. */
+/*
+ * ioc.c - Acorn/ARM I/O Controller (Albion/VC2311/VL2311/VY86C410)
+ */
+
+#include <sys/param.h>
+
+__RCSID("$NetBSD: ioc.c,v 1.1 2000/05/09 21:56:01 bjh21 Exp $");
+
+#include <sys/device.h>
+#include <sys/kernel.h>
+#include <sys/queue.h>
+#include <sys/systm.h>
+
+#include <machine/bus.h>
+#include <machine/irq.h>
+#include <machine/spl.h>
+
+#include <arch/arm26/arm26/cpuvar.h>
+#include <arch/arm26/iobus/iobusvar.h>
+#include <arch/arm26/iobus/iocvar.h>
+#include <arch/arm26/iobus/iocreg.h>
+
+#include "locators.h"
+
+static int ioc_match __P((struct device *parent, struct cfdata *cf, void *aux));
+static void ioc_attach __P((struct device *parent, struct device *self, void *aux));
+static int ioc_search __P((struct device *parent, struct cfdata *cf, void *aux));
+static int ioc_print __P((void *aux, const char *pnp));
+static int ioc_irq_clock __P((void *cookie));
+static int ioc_irq_statclock __P((void *cookie));
+
+struct ioc_softc {
+ struct device sc_dev;
+ bus_space_tag_t sc_bst;
+ bus_space_handle_t sc_bsh;
+ struct irq_handler *sc_clkirq;
+ struct irq_handler *sc_sclkirq;
+ u_int8_t sc_ctl;
+};
+
+struct cfattach ioc_ca = {
+ sizeof(struct ioc_softc), ioc_match, ioc_attach
+};
+
+extern struct cfdriver ioc_cd;
+
+/*
+ * Autoconfiguration glue
+ */
+
+static int
+ioc_match(parent, cf, aux)
+ struct device *parent;
+ struct cfdata *cf;
+ void *aux;
+{
+
+ /*
+ * This is tricky. Accessing non-existant devices in iobus
+ * space can hang the machine (MEMC datasheet section 5.3.3),
+ * so probes would have to be very delicate. This isn't
+ * _much_ of a problem with the IOC, since all machines I know
+ * of have exactly one.
+ */
+ if (cf->cf_unit == 0)
+ return 1;
+ else
+ return 0;
+}
+
+static void
+ioc_attach(parent, self, aux)
+ struct device *parent;
+ struct device *self;
+ void *aux;
+{
+ struct ioc_softc *sc = (void *)self;
+ struct iobus_attach_args *ioa = aux;
+ bus_space_tag_t bst;
+ bus_space_handle_t bsh;
+
+ sc->sc_bst = ioa->ioa_tag;
+ if (bus_space_map(ioa->ioa_tag, ioa->ioa_base, 0x00200000,
+ 0, &(sc->sc_bsh)) != 0)
+ panic("%s: couldn't map", sc->sc_dev.dv_xname);
+ bst = sc->sc_bst;
+ bsh = sc->sc_bsh;
+ /* Now we need to set up bits of the IOC */
+ /* Control register: All bits high (input) is probably safe */
+ ioc_ctl_write(self, 0xff, 0xff);
+ /*
+ * IRQ/FIQ: mask out all, leave clearing latched interrupts
+ * till someone asks.
+ *
+ * In fact, the masks will be in this state already. See
+ * start.c for details.
+ */
+ bus_space_write_1(bst, bsh, IOC_IRQMSKA, 0x00);
+ bus_space_write_1(bst, bsh, IOC_IRQMSKB, 0x00);
+ bus_space_write_1(bst, bsh, IOC_FIQMSK, 0x00);
+ /*-
+ * Timers:
+ * Timers 0/1 are set up by ioc_initclocks (called by cpu_initclocks).
+ * XXX What if we need timers before then?
+ * Timer 2 is set up by whatever's connected to BAUD.
+ * Timer 3 is set up by the arckbd driver.
+ */
+ printf("\n");
+
+ config_search(ioc_search, self, NULL);
+}
+
+extern struct bus_space ioc_bs_tag;
+
+static int
+ioc_search(parent, cf, aux)
+ struct device *parent;
+ struct cfdata *cf;
+ void *aux;
+{
+ struct ioc_softc *sc = (void *)parent;
+ struct ioc_attach_args ioc;
+ bus_space_tag_t bst = sc->sc_bst;
+ bus_space_handle_t bsh = sc->sc_bsh;
+
+ ioc.ioc_bank = cf->cf_loc[IOCCF_BANK];
+ ioc.ioc_offset = cf->cf_loc[IOCCF_OFFSET];
+ ioc.ioc_slow_t = bst;
+ bus_space_subregion(bst, bsh, (ioc.ioc_bank << IOC_BANK_SHIFT)
+ + (IOC_TYPE_SLOW << IOC_TYPE_SHIFT)
+ + (ioc.ioc_offset >> 2),
+ 1 << IOC_BANK_SHIFT, &ioc.ioc_slow_h);
+ ioc.ioc_medium_t = bst;
+ bus_space_subregion(bst, bsh, (ioc.ioc_bank << IOC_BANK_SHIFT)
+ + (IOC_TYPE_MEDIUM << IOC_TYPE_SHIFT)
+ + (ioc.ioc_offset >> 2),
+ 1 << IOC_BANK_SHIFT, &ioc.ioc_medium_h);
+ ioc.ioc_fast_t = bst;
+ bus_space_subregion(bst, bsh, (ioc.ioc_bank << IOC_BANK_SHIFT)
+ + (IOC_TYPE_FAST << IOC_TYPE_SHIFT)
+ + (ioc.ioc_offset >> 2),
+ 1 << IOC_BANK_SHIFT, &ioc.ioc_fast_h);
+ ioc.ioc_sync_t = bst;
+ bus_space_subregion(bst, bsh, (ioc.ioc_bank << IOC_BANK_SHIFT)
+ + (IOC_TYPE_SYNC << IOC_TYPE_SHIFT)
+ + (ioc.ioc_offset >> 2),
+ 1 << IOC_BANK_SHIFT, &ioc.ioc_sync_h);
+ if ((cf->cf_attach->ca_match)(parent, cf, &ioc) > 0)
+ config_attach(parent, cf, &ioc, ioc_print);
+
+ return 0;
+}
+
+static int
+ioc_print(aux, pnp)
+ void *aux;
+ const char *pnp;
+{
+ struct ioc_attach_args *ioc = aux;
+
+ if (ioc->ioc_bank != IOCCF_BANK_DEFAULT)
+ printf(" bank %d", ioc->ioc_bank);
+ if (ioc->ioc_offset != IOCCF_OFFSET_DEFAULT)
+ printf(" offset 0x%02x", ioc->ioc_offset);
+ return UNCONF;
+}
+
+/*
+ * Control Register
+ */
+
+/*
+ * ioc_ctl_{read,write}
+ *
+ * Functions to manipulate the IOC control register. The bottom six
+ * bits of the control register map to bidirectional pins on the chip.
+ * The output circuits are open-drain, so a pin is made an input by
+ * writing '1' to it.
+ */
+
+u_int
+ioc_ctl_read(self)
+ struct device *self;
+{
+ struct ioc_softc *sc = (void *)self;
+
+ return bus_space_read_1(sc->sc_bst, sc->sc_bsh, IOC_CTL);
+}
+
+void
+ioc_ctl_write(self, value, mask)
+ struct device *self;
+ u_int value, mask;
+{
+ struct ioc_softc *sc = (void *)self;
+ int s;
+ bus_space_tag_t bst = sc->sc_bst;
+ bus_space_handle_t bsh = sc->sc_bsh;
+
+ s = splhigh();
+ sc->sc_ctl = (sc->sc_ctl & ~mask) | (value & mask);
+ bus_space_barrier(bst, bsh, IOC_CTL, 1, BUS_BARRIER_WRITE);
+ bus_space_write_1(bst, bsh, IOC_CTL, sc->sc_ctl);
+ bus_space_barrier(bst, bsh, IOC_CTL, 1, BUS_BARRIER_WRITE);
+ splx(s);
+}
+
+/*
+ * Interrupt handling
+ */
+
+struct irq_handler *
+ioc_irq_establish(self, irq, level, handler, cookie)
+ struct device *self;
+ int irq, level;
+ int handler __P((void *));
+ void *cookie;
+{
+ /* struct ioc_softc *sc = (void *)self; */
+
+ return irq_establish(irq, level, handler, cookie);
+}
+
+/*
+ * Find out if an interrupt line is currently active
+ */
+
+int
+ioc_irq_status(self, irq)
+ struct device *self;
+ int irq;
+{
+ struct ioc_softc *sc = (void *)self;
+ bus_space_tag_t bst = sc->sc_bst;
+ bus_space_handle_t bsh = sc->sc_bsh;
+
+ if (irq < 8)
+ return (bus_space_read_1(bst, bsh, IOC_IRQSTA) &
+ IOC_IRQA_BIT(irq)) != 0;
+ else
+ return (bus_space_read_1(bst, bsh, IOC_IRQSTB) &
+ IOC_IRQB_BIT(irq)) != 0;
+}
+
+u_int32_t
+ioc_irq_status_full(self)
+ struct device *self;
+{
+ struct ioc_softc *sc = (void *)self;
+ bus_space_tag_t bst = sc->sc_bst;
+ bus_space_handle_t bsh = sc->sc_bsh;
+
+#if 0 /* XXX */
+ printf("IRQ mask: 0x%x\n",
+ bus_space_read_1(bst, bsh, IOC_IRQMSKA) |
+ (bus_space_read_1(bst, bsh, IOC_IRQMSKB) << 8));
+#endif
+ return bus_space_read_1(bst, bsh, IOC_IRQSTA) |
+ (bus_space_read_1(bst, bsh, IOC_IRQSTB) << 8);
+}
+
+void
+ioc_irq_setmask(self, mask)
+ struct device *self;
+ u_int32_t mask;
+{
+ struct ioc_softc *sc = (void *)self;
+ bus_space_tag_t bst = sc->sc_bst;
+ bus_space_handle_t bsh = sc->sc_bsh;
+
+ bus_space_write_1(bst, bsh, IOC_IRQMSKA, mask & 0xff);
+ bus_space_write_1(bst, bsh, IOC_IRQMSKB, (mask >> 8) & 0xff);
+}
+
+void
+ioc_irq_waitfor(self, irq)
+ struct device *self;
+ int irq;
+{
+
+ while (!ioc_irq_status(self, irq));
+}
+
+void
+ioc_irq_clear(self, mask)
+ struct device *self;
+ int mask;
+{
+ struct ioc_softc *sc = (void *)self;
+ bus_space_tag_t bst = sc->sc_bst;
+ bus_space_handle_t bsh = sc->sc_bsh;
+
+ bus_space_write_1(bst, bsh, IOC_IRQRQA, mask);
+}
+
+#if 0
+
+/*
+ * ioc_get_irq_level:
+ *
+ * Find out the current level of an edge-triggered interrupt line.
+ * Useful for the VIDC driver to know if it's in VSYNC if nothing
+ * else.
+ */
+
+int ioc_get_irq_level(self, irq)
+ struct device *self;
+ int irq;
+{
+ struct ioc_softc *sc = (void *)self;
+
+ switch (irq) {
+ case IOC_IRQ_IF:
+ return (bus_space_read_1(sc->sc_bst, sc->sc_bsh, IOC_CTL) &
+ IOC_CTL_NIF) != 0;
+ case IOC_IRQ_IR:
+ return (bus_space_read_1(sc->sc_bst, sc->sc_bsh, IOC_CTL) &
+ IOC_CTL_IR) != 0;
+ }
+ panic("ioc_get_irq_level called for irq %d, which isn't edge-triggered",
+ irq);
+}
+
+#endif /* 0 */
+
+
+/*
+ * Counters
+ */
+
+void ioc_counter_start(self, counter, value)
+ struct device *self;
+ int counter, value;
+{
+ struct ioc_softc *sc = (void *)self;
+ bus_space_tag_t bst = sc->sc_bst;
+ bus_space_handle_t bsh = sc->sc_bsh;
+ int tlow, thigh, tgo;
+
+ switch (counter) {
+ case 0: tlow = IOC_T0LOW; thigh = IOC_T0HIGH; tgo = IOC_T0GO; break;
+ case 1: tlow = IOC_T1LOW; thigh = IOC_T1HIGH; tgo = IOC_T1GO; break;
+ case 2: tlow = IOC_T2LOW; thigh = IOC_T2HIGH; tgo = IOC_T2GO; break;
+ case 3: tlow = IOC_T3LOW; thigh = IOC_T3HIGH; tgo = IOC_T3GO; break;
+ default: panic("%s: ioc_counter_start: bad counter (%d)",
+ self->dv_xname, counter);
+ }
+ bus_space_barrier(bst, bsh, tlow, tgo - tlow + 1, BUS_BARRIER_WRITE);
+ bus_space_write_1(bst, bsh, tlow, value & 0xff);
+ bus_space_write_1(bst, bsh, thigh, value >> 8 & 0xff);
+ bus_space_barrier(bst, bsh, tlow, tgo - tlow + 1, BUS_BARRIER_WRITE);
+ bus_space_write_1(bst, bsh, tgo, 0);
+ bus_space_barrier(bst, bsh, tlow, tgo - tlow, BUS_BARRIER_WRITE);
+}
+
+/* Cache to save microtime recalculating it */
+static int t0_count;
+
+void
+cpu_initclocks()
+{
+ struct device *self;
+ struct ioc_softc *sc;
+
+#ifdef DIAGNOSTIC
+ if (ioc_cd.cd_ndevs <= 0 || ioc_cd.cd_devs[0] == NULL)
+ panic("cpu_initclocks: no ioc0");
+#endif
+ self = ioc_cd.cd_devs[0];
+ sc = (struct ioc_softc *)self;
+ stathz = hz; /* XXX what _should_ it be? */
+
+ if (hz == 0 || IOC_TIMER_RATE % hz != 0 ||
+ (t0_count = IOC_TIMER_RATE / hz) > 65535)
+ panic("ioc_initclocks: Impossible clock rate: %d Hz", hz);
+ ioc_counter_start(self, 0, t0_count);
+ sc->sc_clkirq = ioc_irq_establish(self, IOC_IRQ_TM0, IPL_CLOCK,
+ ioc_irq_clock, NULL);
+ printf("%s: %d Hz clock interrupting at %s\n",
+ self->dv_xname, hz, irq_string(sc->sc_clkirq));
+ irq_enable(sc->sc_clkirq);
+
+ if (stathz) {
+ setstatclockrate(stathz);
+ sc->sc_sclkirq = ioc_irq_establish(self, IOC_IRQ_TM1,
+ IPL_STATCLOCK,
+ ioc_irq_statclock, NULL);
+ printf("%s: %d Hz statclock interrupting at %s\n",
+ self->dv_xname, stathz, irq_string(sc->sc_sclkirq));
+ irq_enable(sc->sc_sclkirq);
+ }
+}
+
+static int
+ioc_irq_clock(cookie)
+ void *cookie;
+{
+
+ hardclock(cookie);
+ return IRQ_HANDLED;
+}
+
+static int
+ioc_irq_statclock(cookie)
+ void *cookie;
+{
+
+ statclock(cookie);
+ return IRQ_HANDLED;
+}
+
+void
+setstatclockrate(hzrate)
+ int hzrate;
+{
+ struct device *self;
+ int count;
+
+#ifdef DIAGNOSTIC
+ if (ioc_cd.cd_ndevs <= 0 || ioc_cd.cd_devs[0] == NULL)
+ panic("setstatclockrate: no ioc0");
+#endif
+ self = ioc_cd.cd_devs[0];
+
+ /* XXX This currently restarts the counter -- should it? */
+ if (hzrate == 0 || IOC_TIMER_RATE % hzrate != 0 ||
+ (count = IOC_TIMER_RATE / hz) > 65535)
+ panic("Impossible statclock rate: %d Hz", hzrate);
+ ioc_counter_start(self, 1, count);
+}
+
+void
+microtime(tv)
+ struct timeval *tv;
+{
+ struct device *self;
+ struct ioc_softc *sc;
+ bus_space_tag_t bst;
+ bus_space_handle_t bsh;
+ int t0, s, intbefore, intafter;
+
+#ifdef DIAGNOSTIC
+ if (ioc_cd.cd_ndevs <= 0 || ioc_cd.cd_devs[0] == NULL)
+ panic("microtime: no ioc0");
+#endif
+ self = ioc_cd.cd_devs[0];
+ sc = (struct ioc_softc *)self;
+
+ bst = sc->sc_bst;
+ bsh = sc->sc_bsh;
+
+ s = splclock();
+
+ *tv = time;
+
+ intbefore = ioc_irq_status(self, IOC_IRQ_TM0);
+ bus_space_write_1(bst, bsh, IOC_T0LATCH, 0);
+ t0 = bus_space_read_1(bst, bsh, IOC_T0LOW);
+ t0 += bus_space_read_1(bst, bsh, IOC_T0HIGH) << 8;
+ intafter = ioc_irq_status(self, IOC_IRQ_TM0);
+
+ splx(s);
+
+ /*
+ * If there's a timer interrupt pending, the counter has
+ * probably wrapped around once since "time" was last updated.
+ * Things are complicated by the fact that this could happen
+ * while we're trying to work out the time. We include some
+ * heuristics to spot this.
+ */
+
+ if (intbefore || (intafter && t0 < t0_count / 2))
+ t0 -= t0_count;
+
+ tv->tv_usec += (t0_count - t0) / (IOC_TIMER_RATE / 1000000);
+
+ while (tv->tv_usec > 1000000) {
+ tv->tv_sec += 1;
+ tv->tv_usec -= 1000000;
+ }
+}
+
+void
+delay(u_int usecs)
+{
+
+ if (usecs <= 10 || cold)
+ cpu_delayloop(usecs * cpu_delay_factor);
+ else {
+ struct timeval start, gap, now, end;
+
+ microtime(&start);
+ gap.tv_sec = usecs / 1000000;
+ gap.tv_usec = usecs % 1000000;
+ timeradd(&start, &gap, &end);
+ do {
+ microtime(&now);
+ } while (timercmp(&now, &end, <));
+ }
+
+}
diff --git a/sys/arch/arm26/iobus/iocreg.h b/sys/arch/arm26/iobus/iocreg.h
new file mode 100644
index 00000000000..c5c3f35144b
--- /dev/null
+++ b/sys/arch/arm26/iobus/iocreg.h
@@ -0,0 +1,153 @@
+/* $NetBSD: iocreg.h,v 1.1 2000/05/09 21:56:01 bjh21 Exp $ */
+
+/*
+ * Copyright (c) 1997 Ben Harris.
+ * 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.
+ */
+
+/*
+ * iocreg.h - Acorn IOC (Albion/VC2311) registers
+ *
+ * Based on arch/arm32/include/iomd.h 1.7:
+ * Created : 18/09/94
+ * Based on kate/display/iomd.h
+ */
+
+#ifndef _ARM26_IOCREG_H
+#define _ARM26_IOCREG_H
+
+/*
+ * These addresses are intended to be inputs to bus_space functions,
+ * and as such bits 0-4 here map to A[2:6] on the IOC.
+ */
+
+/* Read Write */
+#define IOC_CTL 0x00 /* Control Control */
+#define IOC_KBDDAT 0x01 /* Kbd receive Kbd send */
+
+#define IOC_IRQSTA 0x04 /* IRQ status A - */
+#define IOC_IRQRQA 0x05 /* IRQ request A IRQ clear */
+#define IOC_IRQMSKA 0x06 /* IRQ mask A IRQ mask A */
+
+#define IOC_IRQSTB 0x08 /* IRQ status B - */
+#define IOC_IRQRQB 0x09 /* IRQ request B - */
+#define IOC_IRQMSKB 0x0a /* IRQ mask B IRQ mask B */
+
+#define IOC_FIQST 0x0c /* FIQ status - */
+#define IOC_FIQRQ 0x0d /* FIQ request - */
+#define IOC_FIQMSK 0x0e /* FIQ mask FIQ mask */
+
+#define IOC_T0LOW 0x10 /* T0 count low T0 latch low */
+#define IOC_T0HIGH 0x11 /* T0 count high T0 latch high */
+#define IOC_T0GO 0x12 /* - T0 go command */
+#define IOC_T0LATCH 0x13 /* - T0 latch command */
+
+#define IOC_T1LOW 0x14 /* T1 count low T1 latch low */
+#define IOC_T1HIGH 0x15 /* T1 count high T1 latch high */
+#define IOC_T1GO 0x16 /* - T1 go command */
+#define IOC_T1LATCH 0x17 /* - T1 latch command */
+
+#define IOC_T2LOW 0x18 /* T2 count low T2 latch low */
+#define IOC_T2HIGH 0x19 /* T2 count high T2 latch high */
+#define IOC_T2GO 0x1a /* - T2 go command */
+#define IOC_T2LATCH 0x1b /* - T2 latch command */
+
+#define IOC_T3LOW 0x1c /* T3 count low T3 latch low */
+#define IOC_T3HIGH 0x1d /* T3 count high T3 latch high */
+#define IOC_T3GO 0x1e /* - T3 go command */
+#define IOC_T3LATCH 0x1f /* - T3 latch command */
+
+#define IOC_SIZE 0x20 /* Total amount of bus space used by the IOC */
+
+/* Control register bits (should most of these be defined here?) */
+#define IOC_CTL_SDA 0x01 /* IIC serial data */
+#define IOC_CTL_SCL 0x02 /* IIC serial clock */
+#define IOC_CTL_FDREADY 0x04 /* Floppy disc ready */
+#define IOC_CTL_SMUTE 0x20 /* Speaker mute */
+#define IOC_CTL_LPTACK 0x40 /* Printer acknowledge */
+#define IOC_CTL_FLYBACK 0x80 /* Video flyback */
+
+/* Internal control register bits */
+/* These give the current state of the edge-sensitive IRQ lines */
+#define IOC_CTL_NIF 0x04 /* Set if IF* is high (IRQ 2) */
+#define IOC_CTL_IR 0x08 /* Set if IR is high (IRQ 3) */
+
+/* IOC definitions of interrupt sources (independent of machine) */
+/* Hmm Interrupt numbers or masks? Numbers for now. */
+#define IOC_IRQ_IL6 0 /* Active low input */
+#define IOC_IRQ_IL7 1 /* Active low input */
+#define IOC_IRQ_IF 2 /* Falling edge-triggered */
+#define IOC_IRQ_IR 3 /* Rising edge-triggered */
+#define IOC_IRQ_POR 4 /* Power-on reset */
+#define IOC_IRQ_TM0 5 /* Timer 0 reloaded */
+#define IOC_IRQ_TM1 6 /* Timer 1 reloaded */
+#define IOC_IRQ_1 7 /* Always interrupt */
+#define IOC_IRQ_IL0 8 /* Active low input */
+#define IOC_IRQ_IL1 9 /* Active low input */
+#define IOC_IRQ_IL2 10 /* Active low input */
+#define IOC_IRQ_IL3 11 /* Active low input */
+#define IOC_IRQ_IL4 12 /* Active low input */
+#define IOC_IRQ_IL5 13 /* Active low input */
+#define IOC_IRQ_STX 14 /* KART transmit finished */
+#define IOC_IRQ_SRX 15 /* KART receive finished */
+#define IOC_IRQA_BIT(n) ((n) < 8 ? 1 << (n) : 0)
+#define IOC_IRQB_BIT(n) ((n) < 8 ? 0 : 1 << ((n) - 8))
+
+#define IOC_IRQ_CLEARABLE_MASK 0x7c
+
+/* FIQ sources */
+#define IOC_FIQ_FH0 0 /* Active high input */
+#define IOC_FIQ_FH1 1 /* Active high input */
+#define IOC_FIQ_FL 2 /* Active low input */
+#define IOC_FIQ_C3 3 /* Active low input (also ctl reg) */
+#define IOC_FIQ_C4 4 /* Active low input (also ctl reg) */
+#define IOC_FIQ_C5 5 /* Active low input (also ctl reg) */
+#define IOC_FIQ_IL0 6 /* Active low input (also IRQ) */
+#define IOC_FIQ_1 7 /* Always interrupt */
+#define IOC_FIQ_BIT(n) (1 << (n))
+
+/* Cycle types */
+#define IOC_TYPE_SLOW 0
+#define IOC_TYPE_MEDIUM 1
+#define IOC_TYPE_FAST 2
+#define IOC_TYPE_SYNC 3
+
+/* Counter decrement rate */
+#define IOC_TIMER_RATE 2000000 /* 2 MHz */
+
+/* Archimedes-specific defines */
+#define IOC_TYPE_SHIFT (19 - 2) /* A[20:19] -> T[1:0] */
+#define IOC_BANK_SHIFT (16 - 2) /* A[18:16] -> B[2:0] */
+
+#endif
diff --git a/sys/arch/arm26/iobus/iocvar.h b/sys/arch/arm26/iobus/iocvar.h
new file mode 100644
index 00000000000..12ccd7346f5
--- /dev/null
+++ b/sys/arch/arm26/iobus/iocvar.h
@@ -0,0 +1,72 @@
+/* $NetBSD: iocvar.h,v 1.1 2000/05/09 21:56:01 bjh21 Exp $ */
+/*-
+ * Copyright (c) 1998, 1999 Ben Harris
+ * 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.
+ */
+/* This file is part of NetBSD/arm26 -- a port of NetBSD to ARM2/3 machines. */
+/*
+ * iocvar.h - aspects of the IOC driver that are visible to the world.
+ */
+
+#ifndef _ARM26_IOCVAR_H
+#define _ARM26_IOCVAR_H
+
+#include <machine/irq.h>
+
+/* Structure passed to children of an IOC */
+
+struct ioc_attach_args {
+ /* Means of accessing the device at various speeds */
+ bus_space_tag_t ioc_fast_t;
+ bus_space_handle_t ioc_fast_h;
+ bus_space_tag_t ioc_medium_t;
+ bus_space_handle_t ioc_medium_h;
+ bus_space_tag_t ioc_slow_t;
+ bus_space_handle_t ioc_slow_h;
+ bus_space_tag_t ioc_sync_t;
+ bus_space_handle_t ioc_sync_h;
+ int ioc_bank; /* only for ioc_print */
+ int ioc_offset;
+};
+
+/* Public IOC functions */
+
+extern u_int ioc_ctl_read __P((struct device *self));
+extern void ioc_ctl_write __P((struct device *self, u_int value, u_int mask));
+
+extern struct irq_handler *ioc_irq_establish __P((struct device *self, int irq, int level, int handler __P((void *)), void *cookie));
+extern int ioc_irq_status __P((struct device *self, int irq));
+extern void ioc_irq_waitfor __P((struct device *self, int irq));
+extern void ioc_irq_clear __P((struct device *self, int mask));
+extern u_int32_t ioc_irq_status_full __P((struct device *self));
+extern void ioc_irq_setmask __P((struct device *self, u_int32_t mask));
+
+extern void ioc_counter_start __P((struct device *self, int counter, int value));
+
+extern void ioc_initclocks __P((struct device *self));
+extern void ioc_setstatclockrate __P((struct device *self, int hzrate));
+extern void ioc_microtime __P((struct device *self, struct timeval *tv));
+
+#endif
diff --git a/sys/arch/arm26/ioc/arckbd.c b/sys/arch/arm26/ioc/arckbd.c
new file mode 100644
index 00000000000..5823f68fe05
--- /dev/null
+++ b/sys/arch/arm26/ioc/arckbd.c
@@ -0,0 +1,740 @@
+/* $NetBSD: arckbd.c,v 1.1 2000/05/09 21:56:02 bjh21 Exp $ */
+/*-
+ * Copyright (c) 1998, 1999, 2000 Ben Harris
+ * 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.
+ */
+/* This file is part of NetBSD/arm26 -- a port of NetBSD to ARM2/3 machines. */
+/*
+ * arckbd.c - Archimedes keyboard driver
+ */
+
+/*
+ * Most of the information used to write this driver came from the
+ * A3000 Technical Reference Manual (ISBN 1-85250-074-3).
+ *
+ * We keep a queue of one command in the softc for use by the recieve
+ * interrupt handler in case it finds the KART is already transmitting
+ * a command (presumably as a consequence of a user request) when it
+ * wants to. I think this is safe in all cases, and it will never
+ * happen more than once at a time (I hope).
+ */
+
+#include <sys/param.h>
+
+__RCSID("$NetBSD: arckbd.c,v 1.1 2000/05/09 21:56:02 bjh21 Exp $");
+
+#include <sys/device.h>
+#include <sys/errno.h>
+#include <sys/ioctl.h>
+#include <sys/proc.h>
+#include <sys/syslog.h>
+#include <sys/systm.h>
+
+#include <machine/bus.h>
+#include <machine/irq.h>
+#include <machine/spl.h>
+
+#include <dev/wscons/wsconsio.h>
+#include <dev/wscons/wskbdvar.h>
+#include <dev/wscons/wsksymdef.h>
+#include <dev/wscons/wsmousevar.h>
+
+#include <arch/arm26/iobus/iocreg.h>
+#include <arch/arm26/iobus/iocvar.h>
+#include <arch/arm26/ioc/arckbdreg.h>
+#include <arch/arm26/ioc/arckbdvar.h>
+
+#include "locators.h"
+
+/* XXX These should move into sys/dev/wscons/wsconsio.h */
+#define WSKBD_TYPE_ARCHIMEDES 42
+#define WSMOUSE_TYPE_ARCHIMEDES 42
+
+/* #define ARCKBD_DEBUG */
+
+enum arckbd_state {
+ AS_HRST, AS_RAK1, AS_RAK2, /* reset protocol */
+ AS_IDLE, /* idle, waiting for data */
+ AS_KDDA, AS_KUDA, AS_MDAT /* Receiving two-byte message */
+};
+
+static const char *arckbd_statenames[] = {
+ "hrst", "rak1", "rak2", "idle", "kdda", "kuda", "mdat"
+};
+
+static int arckbd_match __P((struct device *parent, struct cfdata *cf, void *aux));
+static void arckbd_attach __P((struct device *parent, struct device *self, void *aux));
+static kbd_t arckbd_pick_layout __P((int kbid));
+static int arcwskbd_match __P((struct device *parent, struct cfdata *cf, void *aux));
+static void arcwskbd_attach __P((struct device *parent, struct device *self, void *aux));
+static int arcwsmouse_match __P((struct device *parent, struct cfdata *cf, void *aux));
+static void arcwsmouse_attach __P((struct device *parent, struct device *self, void *aux));
+
+static int arckbd_rint __P((void *self));
+static int arckbd_xint __P((void *self));
+static void arckbd_mousemoved __P((struct device *self, int byte1, int byte2));
+static void arckbd_keyupdown __P((struct device *self, int byte1, int byte2));
+static int arckbd_send __P((struct device *self, int data, enum arckbd_state newstate, int waitok));
+
+static int arckbd_enable __P((void *cookie, int on));
+static int arckbd_led_encode __P((int));
+static int arckbd_led_decode __P((int));
+static void arckbd_set_leds __P((void *cookie, int new_state));
+static int arckbd_ioctl __P((void *cookie, u_long cmd, caddr_t data, int flag, struct proc *p));
+static void arckbd_getc __P((void *cookie, u_int *typep, int *valuep));
+static void arckbd_pollc __P((void *cookie, int poll));
+static int arcmouse_enable __P((void *cookie));
+static int arcmouse_ioctl __P((void *cookie, u_long cmd, caddr_t data, int flag, struct proc *p));
+static void arcmouse_disable __P((void *cookie));
+
+struct arckbd_softc {
+ struct device sc_dev;
+ bus_space_tag_t sc_bst;
+ bus_space_handle_t sc_bsh;
+ u_int sc_mouse_buttons;
+ enum arckbd_state sc_state;
+ u_char sc_byteone;
+ u_char sc_kbid;
+ struct device *sc_wskbddev;
+ struct device *sc_wsmousedev;
+ struct wskbd_mapdata sc_mapdata;
+ int sc_cmdqueue; /* Single-command queue */
+ enum arckbd_state sc_statequeue;
+ int sc_cmdqueued;
+ int sc_flags;
+ int sc_leds;
+ u_int sc_poll_type;
+ int sc_poll_value;
+ struct irq_handler *sc_xirq;
+ struct irq_handler *sc_rirq;
+};
+
+#define AKF_WANTKBD 0x01
+#define AKF_WANTMOUSE 0x02
+#define AKF_SENTRQID 0x04
+#define AKF_SENTLEDS 0x08
+#define AKF_POLLING 0x10
+
+struct cfattach arckbd_ca = {
+ sizeof(struct arckbd_softc), arckbd_match, arckbd_attach
+};
+
+/*
+ * Internal devices used because arckbd can't be both a wskbddev and a
+ * wsmousedev. I suspect the right way to do this is through an
+ * "attach wskbd at arckbd with wskbd_arckbd" type thing, but we can't
+ * as the size of a wskbd_softc isn't public. Come to think of it,
+ * this isn't very evil -- I just don't like having yet another line
+ * of configuration.
+ */
+
+struct cfattach arcwskbd_ca = {
+ sizeof(struct device), arcwskbd_match, arcwskbd_attach
+};
+
+struct cfattach arcwsmouse_ca = {
+ sizeof(struct device), arcwsmouse_match, arcwsmouse_attach
+};
+
+struct arckbd_attach_args {
+ enum { ARCKBD_KBDDEV, ARCKBD_MOUSEDEV } aka_devtype;
+ struct wskbddev_attach_args aka_wskbdargs;
+ struct wsmousedev_attach_args aka_wsmouseargs;
+};
+
+extern struct cfdriver arckbd_cd, arcwskbd_cd, arcwsmouse_cd;
+
+static struct wskbd_accessops arckbd_accessops = {
+ arckbd_enable, arckbd_set_leds, arckbd_ioctl
+};
+
+static struct wskbd_consops arckbd_consops = {
+ arckbd_getc, arckbd_pollc
+};
+
+static struct wsmouse_accessops arcmouse_accessops = {
+ arcmouse_enable, arcmouse_ioctl, arcmouse_disable
+};
+
+/* ARGSUSED */
+static int
+arckbd_match(parent, cf, aux)
+ struct device *parent;
+ struct cfdata *cf;
+ void *aux;
+{
+
+ /* Assume presence for now */
+ return 1;
+}
+
+static void
+arckbd_attach(parent, self, aux)
+ struct device *parent, *self;
+ void *aux;
+{
+ struct arckbd_softc *sc = (void *)self;
+ struct ioc_attach_args *ioc = aux;
+ bus_space_tag_t bst;
+ bus_space_handle_t bsh;
+ struct arckbd_attach_args aka;
+
+ bst = sc->sc_bst = ioc->ioc_fast_t;
+ bsh = sc->sc_bsh = ioc->ioc_fast_h;
+
+ printf("\n");
+ sc->sc_rirq = ioc_irq_establish(sc->sc_dev.dv_parent, IOC_IRQ_SRX,
+ IPL_TTY, arckbd_rint, self);
+ printf("%s: interrupting at %s (rx)", self->dv_xname,
+ irq_string(sc->sc_rirq));
+ sc->sc_xirq = ioc_irq_establish(sc->sc_dev.dv_parent, IOC_IRQ_STX,
+ IPL_TTY, arckbd_xint, self);
+ printf(" and %s (tx)", irq_string(sc->sc_xirq));
+ irq_enable(sc->sc_rirq);
+
+ /* Initialisation of IOC KART per IOC Data Sheet section 6.2.3. */
+
+ /* Set up IOC counter 3 */
+ /* k_BAUD = 1/((latch+1)*16) MHz */
+ ioc_counter_start(parent, 3, 62500 / ARCKBD_BAUD - 1);
+
+ /* Read from Rx register and discard. */
+ (void)bus_space_read_1(bst, bsh, 0);
+
+ /* Kick the keyboard into life */
+ arckbd_send(self, ARCKBD_HRST, AS_HRST, 0);
+
+ sc->sc_mapdata = arckbd_mapdata_default;
+ sc->sc_mapdata.layout = KB_UK; /* Reasonable default */
+
+ /* XXX set the LEDs to a known state? (or will wskbd do this?) */
+
+ /* Attach the wskbd console */
+ arckbd_cnattach(self);
+
+ printf("\n");
+
+ /* Attach the dummy drivers */
+ aka.aka_wskbdargs.console = 1; /* XXX FIXME */
+ aka.aka_wskbdargs.keymap = &sc->sc_mapdata;
+ aka.aka_wskbdargs.accessops = &arckbd_accessops;
+ aka.aka_wskbdargs.accesscookie = self;
+ aka.aka_wsmouseargs.accessops = &arcmouse_accessops;
+ aka.aka_wsmouseargs.accesscookie = self;
+ aka.aka_devtype = ARCKBD_KBDDEV;
+ config_found(self, &aka, NULL);
+ aka.aka_devtype = ARCKBD_MOUSEDEV;
+ config_found(self, &aka, NULL);
+}
+
+static kbd_t
+arckbd_pick_layout(kbid)
+ int kbid;
+{
+ int i;
+
+ for (i = 0; arckbd_kbidtab[i].kbid != 0; i++) {
+ if (arckbd_kbidtab[i].kbid == kbid)
+ return arckbd_kbidtab[i].layout;
+ }
+ return KB_UK;
+}
+
+
+/* ARGSUSED */
+static int
+arcwskbd_match(parent, cf, aux)
+ struct device *parent;
+ struct cfdata *cf;
+ void *aux;
+{
+ struct arckbd_attach_args *aka = aux;
+
+ if (aka->aka_devtype == ARCKBD_KBDDEV)
+ return 1;
+ return 0;
+}
+
+/* ARGSUSED */
+static int
+arcwsmouse_match(parent, cf, aux)
+ struct device *parent;
+ struct cfdata *cf;
+ void *aux;
+{
+ struct arckbd_attach_args *aka = aux;
+
+ if (aka->aka_devtype == ARCKBD_MOUSEDEV)
+ return 1;
+ return 0;
+}
+
+static void
+arcwskbd_attach(parent, self, aux)
+ struct device *parent, *self;
+ void *aux;
+{
+ struct arckbd_attach_args *aka = aux;
+ struct arckbd_softc *sc = (void *)parent;
+
+ printf("\n");
+
+ sc->sc_wskbddev = config_found(self, &(aka->aka_wskbdargs),
+ wskbddevprint);
+}
+
+static void
+arcwsmouse_attach(parent, self, aux)
+ struct device *parent, *self;
+ void *aux;
+{
+ struct arckbd_attach_args *aka = aux;
+ struct arckbd_softc *sc = (void *)parent;
+
+ printf("\n");
+
+ sc->sc_wsmousedev = config_found(self, &(aka->aka_wsmouseargs),
+ wsmousedevprint);
+}
+
+
+/*
+ * We don't really _need_ a console keyboard before
+ * autoconfiguration's finished, so for now this function's written to
+ * be called from arckbd_attach. The console functions should still
+ * try not to rely on much, and perhaps one day we should make it
+ * happen in consinit instead.
+ */
+
+void
+arckbd_cnattach(self)
+ struct device *self;
+{
+ struct arckbd_softc *sc = (void*)self;
+
+ wskbd_cnattach(&arckbd_consops, sc, &arckbd_mapdata_default);
+}
+
+static void
+arckbd_getc(cookie, typep, valuep)
+ void *cookie;
+ u_int *typep;
+ int *valuep;
+{
+ struct arckbd_softc *sc = cookie;
+ int s;
+
+ if (!(sc->sc_flags & AKF_POLLING))
+ panic("%s: arckbd_getc called with polling disabled",
+ sc->sc_dev.dv_xname);
+ while (sc->sc_poll_type == 0) {
+ if (ioc_irq_status(sc->sc_dev.dv_parent, IOC_IRQ_STX))
+ arckbd_xint(&sc->sc_dev);
+ if (ioc_irq_status(sc->sc_dev.dv_parent, IOC_IRQ_SRX))
+ arckbd_rint(&sc->sc_dev);
+ }
+ s = spltty();
+ *typep = sc->sc_poll_type;
+ *valuep = sc->sc_poll_value;
+ sc->sc_poll_type = 0;
+ sc->sc_poll_value = 0;
+ splx(s);
+}
+
+static void
+arckbd_pollc(cookie, poll)
+ void *cookie;
+ int poll;
+{
+ struct arckbd_softc *sc = cookie;
+ int s;
+
+ s = spltty();
+ if (poll) {
+ sc->sc_flags |= AKF_POLLING;
+ irq_disable(sc->sc_rirq);
+ irq_disable(sc->sc_xirq);
+ } else {
+ sc->sc_flags &= ~AKF_POLLING;
+ irq_enable(sc->sc_rirq);
+ irq_enable(sc->sc_xirq);
+ }
+ splx(s);
+}
+
+static int
+arckbd_send(self, data, newstate, waitok)
+ struct device *self;
+ int data, waitok;
+ enum arckbd_state newstate;
+{
+ struct arckbd_softc *sc = (void *)self;
+ int s, res;
+ bus_space_tag_t bst = sc->sc_bst;
+ bus_space_handle_t bsh = sc->sc_bsh;
+
+ s = spltty();
+ if (waitok) {
+ while (!ioc_irq_status(sc->sc_dev.dv_parent, IOC_IRQ_STX))
+ if ((sc->sc_flags & AKF_POLLING) == 0) {
+ res = tsleep(arckbd_send, PWAIT, "kbdsend", 0);
+ if (res != 0)
+ return res;
+ }
+ } else if (!ioc_irq_status(sc->sc_dev.dv_parent, IOC_IRQ_STX)) {
+ if (sc->sc_cmdqueued)
+ panic("%s: queue overflow", sc->sc_dev.dv_xname);
+ else {
+ sc->sc_cmdqueue = data;
+ sc->sc_statequeue = newstate;
+ sc->sc_cmdqueued = 1;
+ return 0;
+ }
+ }
+ bus_space_barrier(bst, bsh, 0, 1, BUS_BARRIER_WRITE);
+ bus_space_write_1(bst, bsh, 0, data);
+ bus_space_barrier(bst, bsh, 0, 1, BUS_BARRIER_WRITE);
+ sc->sc_state = newstate;
+#ifdef ARCKBD_DEBUG
+ log(LOG_DEBUG, "%s: sent 0x%02x. now in state %s\n",
+ sc->sc_dev.dv_xname, data, arckbd_statenames[newstate]);
+#endif
+ wakeup(&sc->sc_state);
+ splx(s);
+ if ((sc->sc_flags & AKF_POLLING) == 0)
+ irq_enable(sc->sc_xirq);
+ return 0;
+}
+
+static int
+arckbd_xint(cookie)
+ void *cookie;
+{
+ struct arckbd_softc *sc = cookie;
+
+ if (!ioc_irq_status(sc->sc_dev.dv_parent, IOC_IRQ_STX)) {
+ printf("%s: Stray tx interrupt\n", sc->sc_dev.dv_xname);
+ return IRQ_NOT_HANDLED;
+ }
+ irq_disable(sc->sc_xirq);
+ /* First, process queued commands (acks from the last receive) */
+ if (sc->sc_cmdqueued) {
+ sc->sc_cmdqueued = 0;
+ arckbd_send(&sc->sc_dev, sc->sc_cmdqueue, sc->sc_statequeue, 0);
+ } else if (sc->sc_state == AS_IDLE) {
+ /* Do things that need doing after a reset */
+ if (!(sc->sc_flags & AKF_SENTRQID)) {
+ arckbd_send(&sc->sc_dev, ARCKBD_RQID, AS_IDLE, 0);
+ sc->sc_flags |= AKF_SENTRQID;
+ } else if (!(sc->sc_flags & AKF_SENTLEDS)) {
+ arckbd_send(&sc->sc_dev, ARCKBD_LEDS | sc->sc_leds,
+ AS_IDLE, 0);
+ sc->sc_flags |= AKF_SENTLEDS;
+ }
+ } else if ((sc->sc_flags & AKF_POLLING) == 0)
+ wakeup(&arckbd_send);
+ return IRQ_HANDLED;
+}
+
+static int
+arckbd_rint(cookie)
+ void *cookie;
+{
+ struct device *self = cookie;
+ struct arckbd_softc *sc = (void *)self;
+ bus_space_tag_t bst = sc->sc_bst;
+ bus_space_handle_t bsh = sc->sc_bsh;
+ int data;
+
+ if (!ioc_irq_status(sc->sc_dev.dv_parent, IOC_IRQ_SRX)) {
+ printf("%s: Stray rx interrupt\n", sc->sc_dev.dv_xname);
+ return IRQ_NOT_HANDLED;
+ }
+ bus_space_barrier(bst, bsh, 0, 1, BUS_BARRIER_READ);
+ data = bus_space_read_1(bst, bsh, 0);
+ bus_space_barrier(bst, bsh, 0, 1, BUS_BARRIER_READ);
+ /* Reset protocol */
+#ifdef ARCKBD_DEBUG
+ log(LOG_DEBUG, "%s: got 0x%02x in state %s\n", self->dv_xname, data,
+ arckbd_statenames[sc->sc_state]);
+#endif
+ if (data == ARCKBD_HRST && sc->sc_state == AS_HRST)
+ arckbd_send(self, ARCKBD_RAK1, AS_RAK1, 0);
+ else if (data == ARCKBD_RAK1 &&
+ (sc->sc_state == AS_RAK1 || sc->sc_state == AS_HRST))
+ arckbd_send(self, ARCKBD_RAK2, AS_RAK2, 0);
+ else if (data == ARCKBD_RAK2 && sc->sc_state == AS_RAK2)
+ arckbd_send(self, ARCKBD_SMAK, AS_IDLE, 0);
+
+ /*
+ * Note that for data messages, we acknowledge first and
+ * _then_ process the data. This is important because the
+ * processing may end up trying to use the keyboard in polled
+ * mode (e.g. through DDB) and we'd like its state to be
+ * self-consistent.
+ */
+
+ /* Mouse data */
+ else if (ARCKBD_IS_MDAT(data) && sc->sc_state == AS_IDLE) {
+ arckbd_send(self, ARCKBD_BACK, AS_MDAT, 0);
+ sc->sc_byteone = data;
+ } else if (ARCKBD_IS_MDAT(data) && sc->sc_state == AS_MDAT) {
+ arckbd_send(self, ARCKBD_SMAK, AS_IDLE, 0);
+ arckbd_mousemoved(self, sc->sc_byteone, data);
+ }
+
+ /* Key down data */
+ else if (ARCKBD_IS_KDDA(data) && sc->sc_state == AS_IDLE) {
+ arckbd_send(self, ARCKBD_BACK, AS_KDDA, 0);
+ sc->sc_byteone = data;
+ } else if (ARCKBD_IS_KDDA(data) && sc->sc_state == AS_KDDA) {
+ arckbd_send(self, ARCKBD_SMAK, AS_IDLE, 0);
+ arckbd_keyupdown(self, sc->sc_byteone, data);
+ }
+
+ /* Key up data */
+ else if (ARCKBD_IS_KUDA(data) && sc->sc_state == AS_IDLE) {
+ arckbd_send(self, ARCKBD_BACK, AS_KUDA, 0);
+ sc->sc_byteone = data;
+ } else if (ARCKBD_IS_KUDA(data) && sc->sc_state == AS_KUDA) {
+ arckbd_send(self, ARCKBD_SMAK, AS_IDLE, 0);
+ arckbd_keyupdown(self, sc->sc_byteone, data);
+ }
+
+ /* Other cruft */
+ else if (ARCKBD_IS_KBID(data)) {
+ arckbd_send(self, ARCKBD_SMAK, AS_IDLE, 0);
+ if (sc->sc_kbid != data) {
+ printf("%s: layout %d\n",
+ self->dv_xname, data & ~ARCKBD_KBID);
+ sc->sc_kbid = data;
+ }
+ } else if (ARCKBD_IS_PDAT(data))
+ /* unused -- ignore it */;
+ else {
+ /* Protocol error */
+ log(LOG_WARNING, "%s: protocol error: got 0x%02x in state %s\n",
+ self->dv_xname, data, arckbd_statenames[sc->sc_state]);
+ arckbd_send(self, ARCKBD_HRST, AS_HRST, 0);
+ }
+ return IRQ_HANDLED;
+}
+
+static void
+arckbd_mousemoved(self, byte1, byte2)
+ struct device *self;
+ int byte1, byte2;
+{
+ struct arckbd_softc *sc = (void *)self;
+ int dx, dy;
+
+ if (sc->sc_wsmousedev != NULL) {
+ /* deltas are 7-bit signed */
+ dx = byte1 < 0x40 ? byte1 : byte1 - 0x80;
+ dy = byte2 < 0x40 ? byte2 : byte2 - 0x80;
+ wsmouse_input(sc->sc_wsmousedev,
+ sc->sc_mouse_buttons, dx, dy, 0,
+ WSMOUSE_INPUT_DELTA);
+ }
+}
+
+static void
+arckbd_keyupdown(self, byte1, byte2)
+ struct device *self;
+ int byte1, byte2;
+{
+ struct arckbd_softc *sc = (void *)self;
+ u_int type;
+ int value;
+
+ if ((byte1 & 0x0f) == 7) {
+ /* Mouse button event */
+ /*
+ * This is all very silly, as the wsmouse driver then
+ * differentiates the button state to see if there's
+ * an event worth passing to the user.
+ *
+ * Oh well, at least NetBSD and Acorn number their
+ * mouse buttons the same way.
+ */
+ if (ARCKBD_IS_KDDA(byte1))
+ sc->sc_mouse_buttons |= (1 << (byte2 & 0x0f));
+ else
+ sc->sc_mouse_buttons &= ~(1 << (byte2 & 0x0f));
+ if (sc->sc_wsmousedev != NULL)
+ wsmouse_input(sc->sc_wsmousedev, sc->sc_mouse_buttons,
+ 0, 0, 0, WSMOUSE_INPUT_DELTA);
+ } else {
+ type = ARCKBD_IS_KDDA(byte1) ?
+ WSCONS_EVENT_KEY_DOWN : WSCONS_EVENT_KEY_UP;
+ value = ((byte1 & 0x0f) << 4) | (byte2 & 0x0f);
+ if (sc->sc_flags & AKF_POLLING) {
+ sc->sc_poll_type = type;
+ sc->sc_poll_value = value;
+ } else if (sc->sc_wskbddev != NULL)
+ wskbd_input(sc->sc_wskbddev, type, value);
+ }
+}
+
+/*
+ * Keyboard access functions
+ */
+
+static int
+arckbd_enable(cookie, on)
+ void *cookie;
+ int on;
+{
+ struct arckbd_softc *sc = cookie;
+
+ if (on) {
+ sc->sc_flags |= AKF_WANTKBD;
+ /* XXX send RQMP? */
+ } else
+ sc->sc_flags &= ~ AKF_WANTKBD;
+ return 0;
+}
+
+static int
+arckbd_led_encode(wsleds)
+ int wsleds;
+{
+ int arcleds;
+
+ arcleds = 0;
+ if (wsleds & WSKBD_LED_CAPS)
+ arcleds |= ARCKBD_LEDS_CAPSLOCK;
+ if (wsleds & WSKBD_LED_NUM)
+ arcleds |= ARCKBD_LEDS_NUMLOCK;
+ if (wsleds & WSKBD_LED_SCROLL)
+ arcleds |= ARCKBD_LEDS_SCROLLLOCK;
+ /* No "compose" LED */
+ return arcleds;
+}
+
+static int
+arckbd_led_decode(arcleds)
+ int arcleds;
+{
+ int wsleds;
+
+ wsleds = 0;
+ if (arcleds & ARCKBD_LEDS_CAPSLOCK)
+ wsleds |= WSKBD_LED_CAPS;
+ if (arcleds & ARCKBD_LEDS_NUMLOCK)
+ wsleds |= WSKBD_LED_NUM;
+ if (arcleds & ARCKBD_LEDS_SCROLLLOCK)
+ wsleds |= WSKBD_LED_SCROLL;
+ /* No "compose" LED */
+ return wsleds;
+}
+
+/*
+ * Set the LEDs to the requested state.
+ *
+ * Be warned: This function gets called from interrupts.
+ */
+static void
+arckbd_set_leds(cookie, new_state)
+ void *cookie;
+ int new_state;
+{
+ struct arckbd_softc *sc = cookie;
+ int s;
+
+ s = spltty();
+ sc->sc_leds = arckbd_led_encode(new_state);
+ if (arckbd_send(cookie, ARCKBD_LEDS | sc->sc_leds, AS_IDLE, 0) == 0)
+ sc->sc_flags |= AKF_SENTLEDS;
+ splx(s);
+}
+
+/* ARGSUSED */
+static int
+arckbd_ioctl(cookie, cmd, data, flag, p)
+ void *cookie;
+ u_long cmd;
+ caddr_t data;
+ int flag;
+ struct proc *p;
+{
+ struct arckbd_softc *sc = cookie;
+
+ switch (cmd) {
+ case WSKBDIO_GTYPE:
+ *(int *)data = WSKBD_TYPE_ARCHIMEDES;
+ return 0;
+ case WSKBDIO_SETLEDS:
+ arckbd_set_leds(sc, *(int *)data);
+ return 0;
+ case WSKBDIO_GETLEDS:
+ *(int *)data = arckbd_led_decode(sc->sc_leds);
+ return 0;
+ }
+ return -1;
+}
+
+/*
+ * Mouse access functions
+ */
+
+static int
+arcmouse_enable(cookie)
+ void *cookie;
+{
+ struct arckbd_softc *sc = cookie;
+
+ sc->sc_flags |= AKF_WANTMOUSE;
+ /* XXX send RQMP */
+ return 0;
+}
+
+/* ARGSUSED */
+static int
+arcmouse_ioctl(cookie, cmd, data, flag, p)
+ void *cookie;
+ u_long cmd;
+ caddr_t data;
+ int flag;
+ struct proc *p;
+{
+/* struct arckbd_softc *sc = cookie; */
+
+ switch (cmd) {
+ case WSMOUSEIO_GTYPE:
+ *(int *)data = WSMOUSE_TYPE_ARCHIMEDES;
+ return 0;
+ }
+ return -1;
+}
+
+static void
+arcmouse_disable(cookie)
+ void *cookie;
+{
+ struct arckbd_softc *sc = cookie;
+
+ sc->sc_flags &= ~AKF_WANTMOUSE;
+}
diff --git a/sys/arch/arm26/ioc/arckbdmap.c b/sys/arch/arm26/ioc/arckbdmap.c
new file mode 100644
index 00000000000..5be0d83eea9
--- /dev/null
+++ b/sys/arch/arm26/ioc/arckbdmap.c
@@ -0,0 +1,238 @@
+/* $NetBSD: arckbdmap.c,v 1.1 2000/05/09 21:56:02 bjh21 Exp $ */
+/*-
+ * Copyright (c) 1998 Ben Harris
+ * 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.
+ */
+/* This file is part of NetBSD/arm26 -- a port of NetBSD to ARM2/3 machines. */
+/*
+ * arckbdmap.c - Archimedes keyboard maps
+ */
+
+#include <sys/types.h>
+
+__RCSID("$NetBSD: arckbdmap.c,v 1.1 2000/05/09 21:56:02 bjh21 Exp $");
+
+#include <sys/device.h>
+#include <dev/wscons/wsksymdef.h>
+#include <dev/wscons/wsksymvar.h>
+#include <arch/arm26/ioc/arckbdvar.h>
+#include <arch/arm26/ioc/arckbdreg.h>
+
+/* XXX These should be in sys/dev/wscons/wskeysymdef.h */
+#define KB_SE 0x4300
+#define KS_KP_Numbersign 0xf223
+
+#define KC(n) (0xe000 | (n)) /* see wsksymdef.h */
+
+/* Arc keycodes are 0xrc where r and c are the row and column codes */
+
+static const keysym_t arckbd_keydesc_uk[] = {
+/* pos command normal shifted */
+ KC(0x00), KS_Cmd_Debugger,KS_Escape,
+ KC(0x01), KS_Cmd_Screen0, KS_f1,
+ KC(0x02), KS_Cmd_Screen1, KS_f2,
+ KC(0x03), KS_Cmd_Screen2, KS_f3,
+ KC(0x04), KS_Cmd_Screen3, KS_f4,
+ KC(0x05), KS_Cmd_Screen4, KS_f5,
+ KC(0x06), KS_Cmd_Screen5, KS_f6,
+ KC(0x07), KS_Cmd_Screen6, KS_f7,
+ KC(0x08), KS_Cmd_Screen7, KS_f8,
+ KC(0x09), KS_Cmd_Screen8, KS_f9,
+ KC(0x0a), KS_Cmd_Screen9, KS_f10,
+ KC(0x0b), KS_f11,
+ KC(0x0c), KS_f12,
+ KC(0x0d), KS_voidSymbol, /* print: no keysym yet */
+ KC(0x0e), KS_Hold_Screen, /* scroll lock */
+ KC(0x0f), KS_voidSymbol, /* break: no keysym yet */
+
+ KC(0x10), KS_grave, KS_asciitilde,
+ KC(0x11), KS_1, KS_exclam,
+ KC(0x12), KS_2, KS_at,
+ KC(0x13), KS_3, KS_numbersign,
+ KC(0x14), KS_4, KS_dollar,
+ KC(0x15), KS_5, KS_percent,
+ KC(0x16), KS_6, KS_asciicircum,
+ KC(0x17), KS_7, KS_ampersand,
+ KC(0x18), KS_8, KS_asterisk,
+ KC(0x19), KS_9, KS_parenleft,
+ KC(0x1a), KS_0, KS_parenright,
+ KC(0x1b), KS_minus, KS_underscore,
+ KC(0x1c), KS_equal, KS_plus,
+ KC(0x1d), KS_sterling, KS_currency,
+ KC(0x1e), KS_BackSpace,
+ KC(0x1f), KS_Insert,
+ KC(0x20), KS_Home,
+ KC(0x21), KS_Prior,
+ KC(0x22), KS_Num_Lock,
+ KC(0x23), KS_KP_Divide,
+ KC(0x24), KS_KP_Multiply,
+ KC(0x25), KS_KP_Numbersign,
+
+ KC(0x26), KS_Tab,
+ KC(0x27), KS_q,
+ KC(0x28), KS_w,
+ KC(0x29), KS_e,
+ KC(0x2a), KS_r,
+ KC(0x2b), KS_t,
+ KC(0x2c), KS_y,
+ KC(0x2d), KS_u,
+ KC(0x2e), KS_i,
+ KC(0x2f), KS_o,
+ KC(0x30), KS_p,
+ KC(0x31), KS_bracketleft, KS_braceleft,
+ KC(0x32), KS_bracketright,KS_braceright,
+ KC(0x33), KS_backslash, KS_bar,
+ KC(0x34), KS_Delete,
+ KC(0x35), KS_End, /* really Copy */
+ KC(0x36), KS_Next,
+ KC(0x37), KS_KP_7,
+ KC(0x38), KS_KP_8,
+ KC(0x39), KS_KP_9,
+ KC(0x3a), KS_KP_Subtract,
+
+ KC(0x3b), KS_Cmd1, KS_Control_L,
+ KC(0x3c), KS_a,
+ KC(0x3d), KS_s,
+ KC(0x3e), KS_d,
+ KC(0x3f), KS_f,
+ KC(0x40), KS_g,
+ KC(0x41), KS_h,
+ KC(0x42), KS_j,
+ KC(0x43), KS_k,
+ KC(0x44), KS_l,
+ KC(0x45), KS_semicolon, KS_colon,
+ KC(0x46), KS_apostrophe, KS_quotedbl,
+ KC(0x47), KS_Return,
+ KC(0x48), KS_KP_4,
+ KC(0x49), KS_KP_5,
+ KC(0x4a), KS_KP_6,
+ KC(0x4b), KS_KP_Add,
+
+ KC(0x4c), KS_Shift_L,
+ KC(0x4e), KS_z,
+ KC(0x4f), KS_x,
+ KC(0x50), KS_c,
+ KC(0x51), KS_v,
+ KC(0x52), KS_b,
+ KC(0x53), KS_n,
+ KC(0x54), KS_m,
+ KC(0x55), KS_comma, KS_less,
+ KC(0x56), KS_period, KS_greater,
+ KC(0x57), KS_slash, KS_question,
+ KC(0x58), KS_Shift_R,
+ KC(0x59), KS_Up,
+ KC(0x5a), KS_KP_1,
+ KC(0x5b), KS_KP_2,
+ KC(0x5c), KS_KP_3,
+
+ KC(0x5d), KS_Caps_Lock,
+ KC(0x5e), KS_Cmd2, KS_Alt_L,
+ KC(0x5f), KS_space,
+ KC(0x60), KS_Alt_R,
+ KC(0x61), KS_Control_R,
+ KC(0x62), KS_Left,
+ KC(0x63), KS_Down,
+ KC(0x64), KS_Right,
+ KC(0x65), KS_KP_0,
+ KC(0x66), KS_KP_Decimal,
+ KC(0x67), KS_KP_Enter,
+
+ /* Mouse buttons */
+ KC(0x70), KS_voidSymbol, /* left */
+ KC(0x71), KS_voidSymbol, /* middle */
+ KC(0x72), KS_voidSymbol, /* right */
+};
+
+static const keysym_t arckbd_keydesc_no[] = {
+/* Based on uk */
+ KC(0x12), KS_2, KS_quotedbl, KS_apostrophe,
+ KC(0x14), KS_4, KS_dollar, KS_currency,
+ KC(0x16), KS_6, KS_ampersand,
+ KC(0x17), KS_7, KS_slash, KS_braceleft,
+ KC(0x18), KS_8, KS_parenleft, KS_bracketleft,
+ KC(0x19), KS_9, KS_parenright, KS_bracketright,
+ KC(0x1a), KS_0, KS_equal, KS_braceright,
+ KC(0x1b), KS_plus, KS_question,
+ KC(0x1c), KS_less, KS_greater, KS_bar,
+ KC(0x1d), KS_at, KS_sterling,
+ KC(0x31), KS_aring,
+ KC(0x32), KS_asciicircum, KS_asterisk,
+ KC(0x45), KS_oslash,
+ KC(0x46), KS_ae,
+ KC(0x4d), KS_less, KS_greater,
+ KC(0x55), KS_comma, KS_semicolon,
+ KC(0x56), KS_period, KS_colon,
+ KC(0x57), KS_minus, KS_underscore,
+};
+
+static const keysym_t arckbd_keydesc_se[] = {
+/* Based on no */
+/* pos normal shifted altgred */
+ KC(0x32), KS_udiaeresis,
+ KC(0x33), KS_asciicircum, KS_asterisk, KS_backslash,
+ KC(0x45), KS_odiaeresis,
+ KC(0x46), KS_adiaeresis,
+};
+
+static const keysym_t arckbd_keydesc_de[] = {
+/* Based on se */
+/* pos normal shifted altgred */
+ KC(0x10), KS_asciicircum, KS_degree,
+ KC(0x12), KS_2, KS_quotedbl,
+ KC(0x13), KS_3, KS_section,
+ KC(0x14), KS_4, KS_dollar,
+ KC(0x1b), KS_ssharp, KS_question, KS_backslash,
+ KC(0x1c), KS_dead_acute, KS_dead_grave,
+ KC(0x27), KS_q, KS_Q, KS_at,
+ KC(0x2c), KS_z,
+ KC(0x31), KS_udiaeresis,
+ KC(0x32), KS_plus, KS_asterisk, KS_asciitilde,
+ KC(0x33), KS_numbersign, KS_apostrophe,
+ KC(0x4e), KS_y,
+ KC(0x54), KS_m, KS_M, KS_mu,
+};
+
+#define KBD_MAP(name, base, map) \
+ { name, base, sizeof(map)/sizeof(keysym_t), map }
+
+static const struct wscons_keydesc arckbd_keydesctab[] = {
+ KBD_MAP(KB_UK, 0, arckbd_keydesc_uk),
+ KBD_MAP(KB_NO, KB_UK, arckbd_keydesc_no),
+ KBD_MAP(KB_SE, KB_NO, arckbd_keydesc_se),
+ KBD_MAP(KB_DE, KB_SE, arckbd_keydesc_de),
+ {0},
+};
+
+const struct wskbd_mapdata arckbd_mapdata_default = {
+ arckbd_keydesctab, KB_UK
+};
+
+const struct arckbd_kbidtab arckbd_kbidtab[] = {
+ { ARCKBD_KBID_UK, KB_UK },
+ { ARCKBD_KBID_NO, KB_NO },
+ { ARCKBD_KBID_SE, KB_SE },
+ { ARCKBD_KBID_DE, KB_DE },
+ { -1 },
+};
diff --git a/sys/arch/arm26/ioc/arckbdreg.h b/sys/arch/arm26/ioc/arckbdreg.h
new file mode 100644
index 00000000000..025354302fb
--- /dev/null
+++ b/sys/arch/arm26/ioc/arckbdreg.h
@@ -0,0 +1,94 @@
+/* $NetBSD: arckbdreg.h,v 1.1 2000/05/09 21:56:02 bjh21 Exp $ */
+/*-
+ * Copyright (c) 1997, 1998 Ben Harris
+ * 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.
+ */
+/* This file is part of NetBSD/arm26 -- a port of NetBSD to ARM2/3 machines. */
+/*
+ * arckbdreg.h - Archimedes keyboard codes
+ */
+
+#ifndef _ARCKBDREG_H
+#define _ARCKBDREG_H
+
+#define ARCKBD_HRST 0xff /* keyboard reset */
+#define ARCKBD_RAK1 0xfe /* first reset acknowledge */
+#define ARCKBD_RAK2 0xfd /* second reset acknowledge */
+#define ARCKBD_RQPD 0x40 /* reserved */
+#define ARCKBD_PDAT 0xe0 /* response to RQPD */
+#define ARCKBD_IS_PDAT(d) (((d) & 0xf0) == ARCKBD_PDAT)
+#define ARCKBD_RQID 0x20 /* request keyboard ID */
+#define ARCKBD_KBID 0x80 /* keyboard ID (bottom 6 bits) */
+#define ARCKBD_IS_KBID(d) (((d) & 0xc0) == ARCKBD_KBID)
+#define ARCKBD_KDDA 0xc0 /* key down data (bottom 4 bits plus next byte) */
+#define ARCKBD_IS_KDDA(d) (((d) & 0xf0) == ARCKBD_KDDA)
+#define ARCKBD_KUDA 0xd0 /* key up data (bottom 4 bits plus next byte) */
+#define ARCKBD_IS_KUDA(d) (((d) & 0xf0) == ARCKBD_KUDA)
+#define ARCKBD_RQMP 0x22 /* request mouse position */
+#define ARCKBD_MDAT 0x00 /* mouse movement data */
+#define ARCKBD_IS_MDAT(d) (((d) & 0x80) == ARCKBD_MDAT)
+#define ARCKBD_BACK 0x3f /* acknowledge first byte of pair */
+#define ARCKBD_NACK 0x30 /* acknowledge -- send no more */
+#define ARCKBD_SACK 0x31 /* acknowledge -- send only keyup/down */
+#define ARCKBD_MACK 0x32 /* acknowledge -- send only mouse events */
+#define ARCKBD_SMAK 0x33 /* acknowledge -- send mouse or kbd events */
+#define ARCKBD_LEDS 0x00 /* Set LEDs: */
+#define ARCKBD_LEDS_CAPSLOCK 0x01 /* Caps lock */
+#define ARCKBD_LEDS_NUMLOCK 0x02 /* Num lock */
+#define ARCKBD_LEDS_SCROLLLOCK 0x04 /* Scroll lock */
+#define ARCKBD_PRST 0x21 /* reserved */
+
+#define ARCKBD_BAUD 31250 /* Data rate on keyboard serial link */
+
+/* Keyboard ID codes */
+
+/* Inferred from the ARMsi documentation */
+#define ARCKBD_KBID_A500 0x80 /* A500 prototype keyboard */
+/* Determined by experiment */
+#define ARCKBD_KBID_UK 0x81 /* Archimedes UK keyboard */
+/* These are from the RISC OS 2 PRM, page 1666: */
+#define ARCKBD_KBID_MASTER 0x82
+#define ARCKBD_KBID_COMPACT 0x83
+#define ARCKBD_KBID_IT 0x84
+#define ARCKBD_KBID_ES 0x85
+#define ARCKBD_KBID_FR 0x86
+#define ARCKBD_KBID_DE 0x87
+#define ARCKBD_KBID_PT 0x88
+#define ARCKBD_KBID_ESPERANTO 0x89
+#define ARCKBD_KBID_GR 0x8a
+#define ARCKBD_KBID_SE 0x8b
+#define ARCKBD_KBID_FI 0x8c
+#define ARCKBD_KBID_DK 0x8e
+#define ARCKBD_KBID_NO 0x8f
+#define ARCKBD_KBID_IS 0x90
+#define ARCKBD_KBID_CA1 0x91
+#define ARCKBD_KBID_CA2 0x92
+#define ARCKBD_KBID_CA 0x93
+#define ARCKBD_KBID_TR 0x94
+#define ARCKBD_KBID_ARABIC 0x95
+#define ARCKBD_KBID_IE 0x96
+#define ARCKBD_KBID_HK 0x97
+
+#endif /* !_ARCKBDREG_H */
diff --git a/sys/arch/arm26/ioc/arckbdvar.h b/sys/arch/arm26/ioc/arckbdvar.h
new file mode 100644
index 00000000000..fb8ee4e34c8
--- /dev/null
+++ b/sys/arch/arm26/ioc/arckbdvar.h
@@ -0,0 +1,45 @@
+/* $NetBSD: arckbdvar.h,v 1.1 2000/05/09 21:56:02 bjh21 Exp $ */
+/*-
+ * Copyright (c) 1998 Ben Harris
+ * 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.
+ */
+/* This file is part of NetBSD/arm26 -- a port of NetBSD to ARM2/3 machines. */
+
+#ifndef _ARCKBDVAR_H
+#define _ARCKBDVAR_H
+
+#include <dev/wscons/wsksymvar.h>
+
+struct arckbd_kbidtab {
+ int kbid;
+ kbd_t layout;
+};
+
+extern const struct wskbd_mapdata arckbd_mapdata_default;
+extern const struct arckbd_kbidtab arckbd_kbidtab[];
+
+extern void arckbd_cnattach __P((struct device * self));
+
+#endif
diff --git a/sys/arch/arm26/ioc/iic.c b/sys/arch/arm26/ioc/iic.c
new file mode 100644
index 00000000000..22b6eff2ff8
--- /dev/null
+++ b/sys/arch/arm26/ioc/iic.c
@@ -0,0 +1,351 @@
+/* $NetBSD: iic.c,v 1.1 2000/05/09 21:56:02 bjh21 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>
+
+__RCSID("$NetBSD: iic.c,v 1.1 2000/05/09 21:56:02 bjh21 Exp $");
+
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/conf.h>
+#include <sys/malloc.h>
+#include <sys/device.h>
+
+#include <machine/bus.h>
+#include <machine/cpu.h>
+#include <arm26/iobus/iocreg.h>
+#include <arm26/iobus/iocvar.h>
+#include <arm26/ioc/iic.h>
+
+#include "locators.h"
+
+struct iic_softc {
+ struct device sc_dev;
+};
+
+/* Autoconfiguration glue */
+static int iic_match (struct device *, struct cfdata *, void *);
+static void iic_attach(struct device *, struct device *, void *);
+static int iicsearch(struct device *, struct cfdata *, void *);
+
+struct cfattach iic_ca = {
+ sizeof(struct iic_softc), iic_match, iic_attach
+};
+
+/* Local function prototypes */
+
+static int iic_getack(struct device *);
+static void iic_write_bit(struct device *, int);
+static int iic_write_byte(struct device *, int);
+static int iic_read_byte(struct device *);
+static void iic_start_bit(struct device *);
+static void iic_stop_bit(struct device *);
+
+static int iicprint(void *, const char *);
+
+/* Functions that do the bit twiddling */
+static int iic_get_state(struct device *);
+static void iic_set_state_and_ack(struct device *, int, int);
+static void iic_set_state(struct device *, int, int);
+
+extern struct cfdriver iic_cd;
+
+/*
+ * iic device probe function
+ */
+
+/* ARGSUSED */
+static int
+iic_match(struct device *parent, struct cfdata *cf, void *aux)
+{
+
+ return(1);
+}
+
+/*
+ * iic device attach function
+ *
+ * Initialise the softc structure and do a search for children
+ */
+
+static void
+iic_attach(struct device *parent, struct device *self, void *aux)
+{
+
+ printf("\n");
+ config_search(iicsearch, self, NULL);
+}
+
+/*
+ * Main entry to IIC driver.
+ */
+
+int
+iic_control(struct device *self, int address, u_char *buffer, int count)
+{
+ int loop;
+
+ /* Send the start bit */
+
+ iic_start_bit(self);
+
+ /* Send the address */
+
+ if (!iic_write_byte(self, address)) {
+ iic_stop_bit(self);
+ 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(self, buffer[loop])) {
+ iic_stop_bit(self);
+ return -1;
+ }
+ }
+ }
+ else {
+ /* Read bytes */
+ for (loop = 0; loop < count; ++loop) {
+ buffer[loop] = iic_read_byte(self);
+
+ /* Send final acknowledge */
+
+ if (loop == (count - 1))
+ iic_write_bit(self, 1);
+ else
+ iic_write_bit(self, 0);
+ }
+ }
+
+ /* Send stop bit */
+
+ iic_stop_bit(self);
+
+ return 0;
+}
+
+
+static int
+iic_getack(struct device *self)
+{
+ int ack;
+
+ iic_set_state(self, 1, 0);
+ delay(5);
+ iic_set_state_and_ack(self, 1, 1);
+ ack = iic_get_state(self);
+ delay(4);
+ iic_set_state(self, 1, 0);
+
+ return (ack & 1) == 0;
+}
+
+/*
+ * Put the IIC bus lines in the given state (MD)
+ */
+static void
+iic_set_state(struct device *self, int sda, int scl)
+{
+ int bits;
+
+ bits = 0;
+ if (sda) bits |= IOC_CTL_SDA;
+ if (scl) bits |= IOC_CTL_SCL;
+ ioc_ctl_write(self->dv_parent, bits, IOC_CTL_SDA | IOC_CTL_SCL);
+}
+
+/*
+ * Put the IIC bus lines in a given state and wait for the SCL line
+ * to actually do what we asked (so the slave is ready).
+ */
+static void
+iic_set_state_and_ack(struct device *self, int sda, int scl)
+{
+
+ iic_set_state(self, sda, scl);
+ while ((ioc_ctl_read(self->dv_parent) & IOC_CTL_SCL) == 0)
+ continue;
+}
+
+/*
+ * Read state of IIC data line
+ */
+static int
+iic_get_state(struct device *self)
+{
+
+ return (ioc_ctl_read(self->dv_parent) & IOC_CTL_SDA) != 0;
+}
+
+static void
+iic_write_bit(struct device *self, int bit)
+{
+
+ iic_set_state(self, bit, 0);
+ delay(1); /* Data setup time (250 ns) */
+ iic_set_state_and_ack(self, bit, 1);
+ delay(4); /* Clock high time (4.0 us) */
+ iic_set_state(self, bit, 0);
+ delay(5); /* Clock low time (4.7 us) */
+}
+
+
+static int
+iic_write_byte(struct device *self, int value)
+{
+ int loop;
+ int bit;
+
+ for (loop = 0x80; loop != 0; loop = loop >> 1) {
+ bit = ((value & loop) != 0);
+ iic_write_bit(self, bit);
+ }
+
+ return(iic_getack(self));
+}
+
+
+static int
+iic_read_byte(struct device *self)
+{
+ int loop;
+ u_char byte;
+
+ iic_set_state(self, 1, 0);
+
+ byte = 0;
+
+ for (loop = 0; loop < 8; ++loop) {
+ iic_set_state_and_ack(self, 1, 1);
+ delay(4); /* Clock high time (4.0 us) */
+ byte = (byte << 1) + (iic_get_state(self) & 1);
+ iic_set_state(self, 1, 0);
+ delay(5); /* Clock low time (4.7 us) */
+ }
+
+ return(byte);
+}
+
+
+static void
+iic_start_bit(struct device *self)
+{
+
+ iic_set_state(self, 1, 1);
+ delay(5); /* Bus free time (4.7 us) */
+ iic_set_state(self, 0, 1);
+ delay(4); /* Start hold time (4.0 us) */
+ iic_set_state(self, 0, 0);
+ delay(5); /* Clock low time (4.7 us) */
+}
+
+
+static void
+iic_stop_bit(struct device *self)
+{
+
+ iic_set_state(self, 0, 1);
+ delay(4); /* Stop setup time (4.0 us) */
+ iic_set_state(self, 1, 1);
+}
+
+/*
+ * int iicprint(void *aux, const char *name)
+ *
+ * print function for child device configuration
+ */
+
+static int
+iicprint(void *aux, const char *name)
+{
+ struct iicbus_attach_args *iba = aux;
+
+ if (!name) {
+ if (iba->ib_addr)
+ printf(" addr 0x%02x", iba->ib_addr);
+ }
+
+ /* XXXX print flags */
+ return (UNCONF);
+}
+
+/*
+ * iic search function
+ *
+ * search for devices that are children of the iic device
+ * fill out the attach arguments and call the probe and
+ * attach function (as required).
+ *
+ * Note: since the offsets of the devices need to be specified in the
+ * config file we ignore the FSTAT_STAR.
+ */
+
+static int
+iicsearch(struct device *parent, struct cfdata *cf, void *aux)
+{
+ struct iic_softc *sc = (struct iic_softc *)parent;
+ struct iicbus_attach_args iba;
+ int tryagain;
+
+ do {
+ iba.ib_iic_softc = sc;
+ iba.ib_addr = cf->cf_loc[IICCF_ADDR];
+ iba.ib_aux = NULL;
+
+ tryagain = 0;
+ if ((*cf->cf_attach->ca_match)(parent, cf, &iba) > 0) {
+ config_attach(parent, cf, &iba, iicprint);
+/* tryagain = (cf->cf_fstate == FSTATE_STAR);*/
+ }
+ } while (tryagain);
+
+ return (0);
+}
diff --git a/sys/arch/arm26/ioc/iic.h b/sys/arch/arm26/ioc/iic.h
new file mode 100644
index 00000000000..1bea797e0fa
--- /dev/null
+++ b/sys/arch/arm26/ioc/iic.h
@@ -0,0 +1,64 @@
+/* $NetBSD: iic.h,v 1.1 2000/05/09 21:56:02 bjh21 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 {
+ int ib_addr; /* i/o address */
+ void *ib_aux; /* driver specific */
+ void *ib_iic_softc; /* softc of iic parent */
+};
+
+#define IIC_WRITE 0x00
+#define IIC_READ 0x01
+
+/* Prototype for kernel interface to IIC bus */
+
+extern int iic_control(struct device *, int, u_char *, int);
+
+#endif /* _KERNEL */
+
+/* End of iic.h */
diff --git a/sys/arch/arm26/ioc/ioeb.c b/sys/arch/arm26/ioc/ioeb.c
new file mode 100644
index 00000000000..68122585ff8
--- /dev/null
+++ b/sys/arch/arm26/ioc/ioeb.c
@@ -0,0 +1,73 @@
+/* $NetBSD: ioeb.c,v 1.1 2000/05/09 21:56:02 bjh21 Exp $ */
+
+/*-
+ * Copyright (c) 2000 Ben Harris
+ * 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.
+ */
+/* This file is part of NetBSD/arm26 -- a port of NetBSD to ARM2/3 machines. */
+
+#include <sys/param.h>
+
+__KERNEL_RCSID(0, "$NetBSD: ioeb.c,v 1.1 2000/05/09 21:56:02 bjh21 Exp $");
+
+#include <sys/device.h>
+#include <sys/systm.h>
+
+#include <machine/bus.h>
+
+#include <arch/arm26/iobus/iocvar.h>
+#include <arch/arm26/ioc/ioebreg.h>
+
+struct ioeb_softc {
+ struct device sc_dev;
+};
+
+static int ioeb_match(struct device *, struct cfdata *, void *);
+static void ioeb_attach(struct device *, struct device *, void *);
+
+struct cfattach ioeb_ca = {
+ sizeof(struct ioeb_softc), ioeb_match, ioeb_attach
+};
+
+/* IOEB is only four bits wide */
+#define ioeb_read(t, h, o) (bus_space_read_1(t, h, o) & 0xf)
+
+static int
+ioeb_match(struct device *parent, struct cfdata *cf, void *aux)
+{
+ struct ioc_attach_args *ioc = aux;
+
+ if (ioeb_read(ioc->ioc_fast_t, ioc->ioc_fast_h, IOEB_REG_ID) ==
+ IOEB_ID_IOEB)
+ return 1;
+ return 0;
+}
+
+static void
+ioeb_attach(struct device *parent, struct device *self, void *aux)
+{
+
+ printf("\n");
+}
diff --git a/sys/arch/arm26/ioc/ioebreg.h b/sys/arch/arm26/ioc/ioebreg.h
new file mode 100644
index 00000000000..75c29db1313
--- /dev/null
+++ b/sys/arch/arm26/ioc/ioebreg.h
@@ -0,0 +1,40 @@
+/* $NetBSD: ioebreg.h,v 1.1 2000/05/09 21:56:02 bjh21 Exp $ */
+
+/*
+ * This file is in the public domain.
+ *
+ * Derived from:
+ * RISC OS 3 Programmer's Reference Manual
+ * A3010/A3020/A4000 Technical Reference Manual
+ */
+
+/* Acorn IOEB (Input/Output Extension Block) registers */
+
+#ifndef _IOEBREG_H_
+#define _IOEBREG_H_
+
+/*
+ * IOEB starts at a rather high offset because it avoids the ranges
+ * used on older machines.
+ */
+
+#define IOEB_REG_VIDCTL 18 /* Video control latch */
+#define IOEB_REG_ID 20 /* Device ID */
+#define IOEB_REG_SPEED 21 /* Clock speed (A4?) */
+#define IOEB_REG_INTRCLR 22 /* Printer interrupt clear */
+#define IOEB_REG_MONID 28 /* Monitor ID */
+#define IOEB_REG_VGATEST 29 /* VGA test pin/SCART sound ??? */
+#define IOEB_REG_JOY1 30 /* Joystick 1 */
+#define IOEB_REG_JOY2 31 /* Joystick 2 */
+
+/* The IOEB is connected to D[3:0], so its internal registers are 4-bit */
+#define IOEB_VIDCTL_HSINV 0x1 /* Invert horizontal sync */
+#define IOEB_VIDCTL_VSINV 0x2 /* Invert vertical sync */
+#define IOEB_VIDCTL_CLK_MASK 0xc /* VIDCLK select */
+#define IOEB_VIDCTL_CLK_24MHZ 0x0 /* 24 MHz */
+#define IOEB_VIDCTL_CLK_25MHZ 0x4 /* 25.175 MHz */
+#define IOEB_VIDCTL_CLK_36MHZ 0x8 /* 36 MHz */
+
+#define IOEB_ID_IOEB 0x5
+
+#endif
diff --git a/sys/arch/arm26/ioc/latchreg.h b/sys/arch/arm26/ioc/latchreg.h
new file mode 100644
index 00000000000..927ff1460f1
--- /dev/null
+++ b/sys/arch/arm26/ioc/latchreg.h
@@ -0,0 +1,60 @@
+/* $NetBSD: latchreg.h,v 1.1 2000/05/09 21:56:02 bjh21 Exp $ */
+/*-
+ * Copyright (c) 1997, 1998 Ben Harris
+ * 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.
+ */
+/* This file is part of NetBSD/arm26 -- a port of NetBSD to ARM2/3 machines. */
+/*
+ * latchreg.h - Archimedes internal latches
+ */
+
+/* Under NetBSD, Latch A is latch0 and Latch B is latch1. */
+
+#ifndef _LATCHREG_H
+#define _LATCHREG_H
+
+/* Latch A controls some of the floppy disc system */
+
+#define LATCH0_DRIVESEL0 0x01 /* Floppy drive 0 select */
+#define LATCH0_DRIVESEL1 0x02 /* Floppy drive 1 select */
+#define LATCH0_DRIVESEL2 0x04 /* Floppy drive 2 select */
+#define LATCH0_DRIVESEL3 0x08 /* Floppy drive 3 select */
+#define LATCH0_SIDESEL 0x10 /* Floppy side select, inverted. */
+#define LATCH0_SIDE0 0x10
+#define LATCH0_SIDE1 0x00 /* Just to be friendly... */
+#define LATCH0_MOTORONOFF 0x20 /* Motor on/off */
+#define LATCH0_INUSE 0x40 /* 'In Use' */
+
+/* Latch B does all sorts of random stuff */
+
+#define LATCH1_DENSITY 0x02 /* Floppy disc density setting */
+#define LATCH1_DOUBLEDENSITY 0x00 /* Double density */
+#define LATCH1_SINGLEDENSITY 0x02 /* Single density */
+#define LATCH1_NOTFDCRESET 0x08 /* Floppy controller reset (inverted) */
+#define LATCH1_LPTSTROBE 0x10 /* Printer strobe line */
+#define LATCH1_AUX1 0x20 /* Spare (VIDC Enhancer?) */
+#define LATCH1_AUX2 0x40 /* Spare */
+
+#endif /* !_LATCHREG_H */
diff --git a/sys/arch/arm26/ioc/pcf8583reg.h b/sys/arch/arm26/ioc/pcf8583reg.h
new file mode 100644
index 00000000000..552753eba9b
--- /dev/null
+++ b/sys/arch/arm26/ioc/pcf8583reg.h
@@ -0,0 +1,81 @@
+/* $NetBSD: pcf8583reg.h,v 1.1 2000/05/09 21:56:02 bjh21 Exp $ */
+
+/*
+ * Ben Harris, 2000
+ *
+ * This file is in the public domain
+ */
+/*
+ * Philips PCF8583 RTC registers
+ */
+
+/* We only have clock mode registers here */
+
+#ifndef _PCF8583REG_H
+#define _PCF8583REG_H
+
+#define PCF8583_ADDR 0xa0
+#define PCF8583_MASK 0xfc
+
+#define PCF8583_REG_CSR 0x00
+#define PCF8583_REG_CENTI 0x01
+#define PCF8583_REG_SEC 0x02
+#define PCF8583_REG_MIN 0x03
+#define PCF8583_REG_HOUR 0x04
+#define PCF8583_REG_YEARDATE 0x05
+#define PCF8583_REG_WKDYMON 0x06
+#define PCF8583_REG_TIMER 0x07
+#define PCF8583_REG_ALMCTL 0x08
+#define PCF8583_REG_ALMCENTI 0x09
+#define PCF8583_REG_ALMSEC 0x0a
+#define PCF8583_REG_ALMMIN 0x0b
+#define PCF8583_REG_ALMHOUR 0x0c
+#define PCF8583_REG_ALMDAY 0x0d
+#define PCF8583_REG_ALMMON 0x0e
+#define PCF8583_REG_ALMTIMER 0x0f
+
+#define PCF8583_CSR_TIMER 0x01
+#define PCF8583_CSR_SECTICK 0x01
+#define PCF8583_CSR_ALARM 0x02
+#define PCF8583_CSR_MINTICK 0x02
+#define PCF8583_CSR_ALARMENABLE 0x04
+#define PCF8583_CSR_MASK 0x08
+#define PCF8583_CSR_FN_MASK 0x30
+#define PCF8583_CSR_FN_32768HZ 0x00
+#define PCF8583_CSR_FN_50HZ 0x10
+#define PCF8583_CSR_FN_EVENT 0x20
+#define PCF8583_CSR_FN_TEST 0x30
+#define PCF8583_CSR_HOLD 0x40
+#define PCF8583_CSR_STOP 0x80
+
+#define PCF8583_HOUR_MASK 0x3f
+#define PCF8583_HOUR_PM 0x40
+#define PCF8583_HOUR_12H 0x80
+
+#define PCF8583_DATE_MASK 0x3f
+#define PCF8583_YEAR_MASK 0xc0
+#define PCF8583_YEAR_SHIFT 6
+
+#define PCF8583_MON_MASK 0x1f
+#define PCF8583_WKDY_MASK 0xe0
+#define PCF8583_WKDY_SHIFT 5
+
+#define PCF8583_ALMCTL_TIMER_MASK 0x07
+#define PCF8583_ALMCTL_TIMER_OFF 0x00
+#define PCF8583_ALMCTL_TIMER_CENTI 0x01
+#define PCF8583_ALMCTL_TIMER_SEC 0x02
+#define PCF8583_ALMCTL_TIMER_MIN 0x03
+#define PCF8583_ALMCTL_TIMER_HOUR 0x04
+#define PCF8583_ALMCTL_TIMER_DAY 0x05
+#define PCF8583_ALMCTL_TIMER_TEST 0x07
+#define PCF8583_ALMCTL_TIMERINT 0x08
+#define PCF8583_ALMCTL_CLKALM_MASK 0x30
+#define PCF8583_ALMCTL_CLKALM_NONE 0x00
+#define PCF8583_ALMCTL_CLKALM_DAILY 0x10
+#define PCF8583_ALMCTL_CLKALM_WKDY 0x20
+#define PCF8583_ALMCTL_CLKALM_DATED 0x30
+#define PCF8583_ALMCTL_TIMERALM 0x40
+#define PCF8583_ALMCTL_ALMINT 0x80
+
+
+#endif
diff --git a/sys/arch/arm26/ioc/rtc.c b/sys/arch/arm26/ioc/rtc.c
new file mode 100644
index 00000000000..c5219e845b7
--- /dev/null
+++ b/sys/arch/arm26/ioc/rtc.c
@@ -0,0 +1,470 @@
+/* $NetBSD: rtc.c,v 1.1 2000/05/09 21:56:02 bjh21 Exp $ */
+
+/*
+ * Copyright (c) 2000 Ben Harris
+ * 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>
+
+__RCSID("$NetBSD: rtc.c,v 1.1 2000/05/09 21:56:02 bjh21 Exp $");
+
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/conf.h>
+#include <sys/malloc.h>
+#include <sys/device.h>
+#include <dev/clock_subr.h>
+#include <arm26/ioc/iic.h>
+#include <arm26/ioc/pcf8583reg.h>
+
+struct rtc_softc {
+ struct device sc_dev;
+ int sc_flags;
+#define RTC_BROKEN 1
+#define RTC_OPEN 2
+ int sc_addr;
+};
+
+static int rtcmatch(struct device *parent, struct cfdata *cf, void *aux);
+static void rtcattach(struct device *parent, struct device *self, void *aux);
+static int rtc_gettime(struct device *, struct timeval *);
+static int rtc_settime(struct device *, struct timeval *);
+
+#define RTC_ADDR_YEAR 0xc0
+#define RTC_ADDR_CENT 0xc1
+
+extern struct cfdriver rtc_cd;
+
+/* device and attach structures */
+
+struct cfattach rtc_ca = {
+ sizeof(struct rtc_softc), rtcmatch, rtcattach
+};
+
+/*
+ * rtcmatch()
+ *
+ * Validate the IIC address to make sure its an RTC we understand
+ */
+
+int
+rtcmatch(parent, cf, aux)
+ struct device *parent;
+ struct cfdata *cf;
+ void *aux;
+{
+ struct iicbus_attach_args *ib = aux;
+
+ if ((ib->ib_addr & PCF8583_MASK) == PCF8583_ADDR &&
+ iic_control(parent, ib->ib_addr | IIC_READ, NULL, 0) == 0)
+ return 1;
+ return 0;
+}
+
+/*
+ * rtcattach()
+ *
+ * Attach the rtc device
+ */
+
+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;
+ sc->sc_addr = ib->ib_addr;
+ if ((ib->ib_addr & PCF8583_MASK) == PCF8583_ADDR) {
+ printf(": PCF8583");
+
+ /* Read RTC register 0 and report info found */
+
+ buff[0] = PCF8583_REG_CSR;
+
+ if (iic_control(self->dv_parent, sc->sc_addr | IIC_WRITE,
+ buff, 1))
+ return;
+
+ if (iic_control(self->dv_parent, sc->sc_addr | IIC_READ,
+ buff, 1))
+ return;
+
+ switch (buff[0] & PCF8583_CSR_FN_MASK) {
+ case PCF8583_CSR_FN_32768HZ:
+ printf(", 32.768 kHz clock");
+ break;
+ case PCF8583_CSR_FN_50HZ:
+ printf(", 50 Hz clock");
+ break;
+ case PCF8583_CSR_FN_EVENT:
+ printf(", event counter");
+ break;
+ case PCF8583_CSR_FN_TEST:
+ printf(", test mode");
+ break;
+ }
+
+ if (buff[0] & PCF8583_CSR_STOP)
+ printf(", stopped");
+ if (buff[0] & PCF8583_CSR_ALARMENABLE)
+ printf(", alarm enabled");
+ sc->sc_flags &= ~RTC_BROKEN;
+ }
+
+ printf("\n");
+}
+
+/* Read a byte from CMOS RAM */
+
+int
+cmos_read(struct device *self, int location)
+{
+ u_char buff;
+ struct rtc_softc *sc = (struct rtc_softc *)self;
+
+ buff = location;
+
+ if (iic_control(self->dv_parent, sc->sc_addr | IIC_WRITE, &buff, 1))
+ return(-1);
+ if (iic_control(self->dv_parent, sc->sc_addr | IIC_READ, &buff, 1))
+ return(-1);
+
+ return(buff);
+}
+
+
+/* Write a byte to CMOS RAM */
+
+int
+cmos_write(struct device *self, int location, int value)
+{
+ u_char buff[2];
+ struct rtc_softc *sc = (struct rtc_softc *)self;
+
+ buff[0] = location;
+ buff[1] = value;
+
+ if (iic_control(self->dv_parent, sc->sc_addr | IIC_WRITE, buff, 2))
+ return(-1);
+
+ return(0);
+}
+
+static int
+rtc_settime(struct device *self, struct timeval *tv)
+{
+ struct rtc_softc *sc = (struct rtc_softc *)self;
+ u_char buff[8];
+ struct clock_ymdhms ymdhms;
+
+ clock_secs_to_ymdhms(tv->tv_sec, &ymdhms);
+
+ buff[0] = PCF8583_REG_CENTI;
+
+ buff[PCF8583_REG_CENTI] = TOBCD(tv->tv_usec / 10000);
+ buff[PCF8583_REG_SEC] = TOBCD(ymdhms.dt_sec);
+ buff[PCF8583_REG_MIN] = TOBCD(ymdhms.dt_min);
+ buff[PCF8583_REG_HOUR] = TOBCD(ymdhms.dt_hour);
+ buff[PCF8583_REG_YEARDATE] = TOBCD(ymdhms.dt_day) |
+ ((ymdhms.dt_year % 4) << PCF8583_YEAR_SHIFT);
+ buff[PCF8583_REG_WKDYMON] = TOBCD(ymdhms.dt_mon) |
+ ((ymdhms.dt_wday % 4) << PCF8583_WKDY_SHIFT);
+
+ if (iic_control(self->dv_parent, sc->sc_addr | IIC_WRITE, buff, 7))
+ return -1;
+
+ if (cmos_write(self, RTC_ADDR_YEAR, ymdhms.dt_year % 100))
+ return -1;
+ if (cmos_write(self, RTC_ADDR_CENT, ymdhms.dt_year / 100))
+ return -1;
+ return(0);
+}
+
+void
+inittodr(time_t base)
+{
+ int check;
+
+ check = 0;
+ if (rtc_cd.cd_ndevs == 0 || rtc_cd.cd_devs[0] == NULL) {
+ printf("inittodr: rtc0 not present");
+ time.tv_sec = base;
+ time.tv_usec = 0;
+ check = 1;
+ } else {
+ rtc_gettime(rtc_cd.cd_devs[0], &time);
+ if (time.tv_sec > base + 3 * SECDAY) {
+ printf("inittodr: Clock has gained %ld days",
+ (time.tv_sec - base) / SECDAY);
+ check = 1;
+ } else if (time.tv_sec + SECDAY < base) {
+ printf("inittodr: Clock has lost %ld day(s)",
+ (base - time.tv_sec) / SECDAY);
+ check = 1;
+ }
+ }
+ if (check)
+ printf(" - CHECK AND RESET THE DATE.\n");
+}
+
+
+static int
+rtc_gettime(struct device *self, struct timeval *tv)
+{
+ u_char buff[8];
+ int byte, centi;
+ struct rtc_softc *sc = (struct rtc_softc *)self;
+ struct clock_ymdhms ymdhms;
+
+ buff[0] = 0;
+
+ if (iic_control(self->dv_parent, sc->sc_addr | IIC_WRITE, buff, 1))
+ return -1;
+
+ if (iic_control(self->dv_parent, sc->sc_addr | IIC_READ, buff, 8))
+ return -1;
+
+ centi = FROMBCD(buff[PCF8583_REG_CENTI]);
+ ymdhms.dt_sec = FROMBCD(buff[PCF8583_REG_SEC]);
+ ymdhms.dt_min = FROMBCD(buff[PCF8583_REG_MIN]);
+ ymdhms.dt_hour = FROMBCD(buff[PCF8583_REG_HOUR] & PCF8583_HOUR_MASK);
+
+ /* If in 12 hour mode need to look at the AM/PM flag */
+
+ if (buff[PCF8583_REG_HOUR] & PCF8583_HOUR_12H) {
+ ymdhms.dt_hour %= 12; /* 12AM -> 0, 12PM -> 12 */
+ if (buff[PCF8583_REG_HOUR] & PCF8583_HOUR_PM)
+ ymdhms.dt_hour += 12;
+ }
+
+ ymdhms.dt_day = FROMBCD(buff[PCF8583_REG_YEARDATE] &
+ PCF8583_DATE_MASK);
+ ymdhms.dt_mon = FROMBCD(buff[PCF8583_REG_WKDYMON] &
+ PCF8583_MON_MASK);
+
+ byte = cmos_read(self, RTC_ADDR_YEAR);
+ if (byte == -1)
+ return -1;
+ ymdhms.dt_year = byte;
+ byte = cmos_read(self, RTC_ADDR_CENT);
+ if (byte == -1)
+ return -1;
+ ymdhms.dt_year += 100 * byte;
+
+ /* Try to notice if the year's rolled over. */
+ if (buff[PCF8583_REG_CSR] & PCF8583_CSR_MASK)
+ printf("%s: cannot check year in mask mode\n", self->dv_xname);
+ else
+ while (ymdhms.dt_year % 4 !=
+ (buff[PCF8583_REG_YEARDATE] &
+ PCF8583_YEAR_MASK) >> PCF8583_YEAR_SHIFT)
+ ymdhms.dt_year++;
+
+ tv->tv_sec = clock_ymdhms_to_secs(&ymdhms);
+ tv->tv_usec = centi * 10000;
+ return 0;
+}
+
+#if 0
+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_BROKEN) 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;
+{
+ rtc_t rtc;
+ int s;
+ char buffer[32];
+ int length;
+
+ s = splclock();
+ if (rtc_read(NULL, &rtc) == 0) {
+ (void)splx(s);
+ return(ENXIO);
+ }
+
+ (void)splx(s);
+
+ sprintf(buffer, "%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 (uio->uio_offset > strlen(buffer))
+ return 0;
+
+ length = strlen(buffer) - uio->uio_offset;
+ if (length > uio->uio_resid)
+ length = uio->uio_resid;
+
+ return(uiomove((caddr_t)buffer, length, uio));
+}
+
+
+static int
+twodigits(buffer, pos)
+ char *buffer;
+ int pos;
+{
+ int result = 0;
+
+ if (buffer[pos] >= '0' && buffer[pos] <= '9')
+ result = (buffer[pos] - '0') * 10;
+ if (buffer[pos+1] >= '0' && buffer[pos+1] <= '9')
+ result += (buffer[pos+1] - '0');
+ return(result);
+}
+
+int
+rtcwrite(dev, uio, flag)
+ dev_t dev;
+ struct uio *uio;
+ int flag;
+{
+ rtc_t rtc;
+ int s;
+ char buffer[25];
+ int length;
+ int error;
+
+ /*
+ * We require atomic updates!
+ */
+ length = uio->uio_resid;
+ if (uio->uio_offset || (length != sizeof(buffer)
+ && length != sizeof(buffer - 1)))
+ return(EINVAL);
+
+ if ((error = uiomove((caddr_t)buffer, sizeof(buffer), uio)))
+ return(error);
+
+ if (length == sizeof(buffer) && buffer[sizeof(buffer) - 1] != '\n')
+ return(EINVAL);
+
+ printf("rtcwrite: %s\n", buffer);
+
+ rtc.rtc_micro = 0;
+ rtc.rtc_centi = twodigits(buffer, 9);
+ rtc.rtc_sec = twodigits(buffer, 6);
+ rtc.rtc_min = twodigits(buffer, 3);
+ rtc.rtc_hour = twodigits(buffer, 0);
+ rtc.rtc_day = twodigits(buffer, 14);
+ rtc.rtc_mon = twodigits(buffer, 17);
+ rtc.rtc_year = twodigits(buffer, 22);
+ rtc.rtc_cen = twodigits(buffer, 20);
+
+ s = splclock();
+ rtc_write(NULL, &rtc);
+ (void)splx(s);
+
+ return(0);
+}
+
+
+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);
+}
+#endif
+
+/* End of rtc.c */
diff --git a/sys/arch/arm26/mainbus/mainbus.c b/sys/arch/arm26/mainbus/mainbus.c
new file mode 100644
index 00000000000..287002952dc
--- /dev/null
+++ b/sys/arch/arm26/mainbus/mainbus.c
@@ -0,0 +1,104 @@
+/* $NetBSD: mainbus.c,v 1.1 2000/05/09 21:56:02 bjh21 Exp $ */
+/*-
+ * Copyright (c) 1998 Ben Harris
+ * 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.
+ */
+/* This file is part of NetBSD/arm26 -- a port of NetBSD to ARM2/3 machines. */
+/*
+ * mainbus.c - the root device
+ */
+
+#include <sys/param.h>
+
+#include <sys/device.h>
+#include <sys/systm.h>
+
+static int mainbus_match __P((struct device *parent, struct cfdata *cf, void *aux));
+static void mainbus_attach __P((struct device *parent, struct device *self, void *aux));
+static int mainbus_search __P((struct device *parent, struct cfdata *cf, void *aux));
+static int mainbus_print __P((void *aux, const char *pnp));
+
+struct mainbus_softc {
+ struct device sc_dev;
+};
+
+struct cfattach mainbus_ca = {
+ sizeof(struct mainbus_softc), mainbus_match, mainbus_attach
+};
+
+extern struct cfdriver mainbus_cd;
+
+static int
+mainbus_match(parent, cf, aux)
+ struct device *parent;
+ struct cfdata *cf;
+ void *aux;
+{
+
+ /* Only one mainbus */
+ if (cf->cf_unit == 0)
+ return 1;
+ else
+ return 0;
+}
+
+static void
+mainbus_attach(parent, self, aux)
+ struct device *parent;
+ struct device *self;
+ void *aux;
+{
+
+ printf("\n");
+
+ config_search(mainbus_search, self, NULL);
+}
+
+static int
+mainbus_search(parent, cf, aux)
+ struct device *parent;
+ struct cfdata *cf;
+ void *aux;
+{
+
+ /*
+ * Things attached at mainbus are assumed not to need to be
+ * told where they are.
+ */
+
+ if ((cf->cf_attach->ca_match)(parent, cf, NULL) > 0)
+ config_attach(parent, cf, NULL, mainbus_print);
+
+ return 0;
+}
+
+static int
+mainbus_print(aux, pnp)
+ void *aux;
+ const char *pnp;
+{
+
+ return UNCONF;
+}
diff --git a/sys/arch/arm26/podulebus/asc.c b/sys/arch/arm26/podulebus/asc.c
new file mode 100644
index 00000000000..90cdefd81a2
--- /dev/null
+++ b/sys/arch/arm26/podulebus/asc.c
@@ -0,0 +1,469 @@
+/* $NetBSD: asc.c,v 1.1 2000/05/09 21:56:03 bjh21 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
+ */
+
+/*
+ * Driver for the Acorn SCSI card using the SBIC (WD3393) generic driver
+ *
+ * Thanks to Acorn for supplying programming information on this card.
+ */
+
+/*
+ * 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 "opt_ddb.h"
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/device.h>
+#include <sys/buf.h>
+#include <dev/scsipi/scsi_all.h>
+#include <dev/scsipi/scsipi_all.h>
+#include <dev/scsipi/scsiconf.h>
+#include <arm26/podulebus/podulebus.h>
+#include <arm26/podulebus/sbicreg.h>
+#include <arm26/podulebus/sbicvar.h>
+#include <arm26/podulebus/ascreg.h>
+#include <arm26/podulebus/ascvar.h>
+#include <arm32/podulebus/podules.h>
+
+void ascattach __P((struct device *, struct device *, void *));
+int ascmatch __P((struct device *, struct cfdata *, 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 scsipi_xfer *xs));
+int asc_intr __P((void *arg));
+void asc_minphys __P((struct buf *bp));
+
+struct scsipi_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
+};
+
+extern struct cfdriver asc_cd;
+
+u_long scsi_nosync;
+int shift_nosync;
+
+#if ASC_POLL > 0
+int asc_poll = 0;
+
+#endif
+
+int
+ascmatch(pdp, cf, auxp)
+ struct device *pdp;
+ struct cfdata *cf;
+ void *auxp;
+{
+ struct podulebus_attach_args *pa = auxp;
+
+/* Look for the card */
+
+ if (matchpodule(pa, MANUFACTURER_ACORN, PODULE_ACORN_SCSI, -1) == 0)
+ return(0);
+
+ if (strncmp(pa->pa_descr, "MCS", 3) == 0)
+ return(0);
+
+ 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 podulebus_attach_args *pa;
+
+ sc = (struct asc_softc *)dp;
+ pa = auxp;
+
+ sc->sc_podule_number = pa->pa_slotnum;
+
+ 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) (pa->pa_memc_h + ASC_SBIC);
+ sbic->sc_clkfreq = sbic_clock_override ? sbic_clock_override : 143;
+
+ sbic->sc_adapter.scsipi_cmd = asc_scsicmd;
+ sbic->sc_adapter.scsipi_minphys = asc_minphys;
+
+ sbic->sc_link.scsipi_scsi.channel = SCSI_CHANNEL_ONLY_ONE;
+ sbic->sc_link.adapter_softc = sbic;
+ sbic->sc_link.scsipi_scsi.adapter_target = 7;
+ sbic->sc_link.adapter = &sbic->sc_adapter;
+ sbic->sc_link.device = &asc_scsidev;
+ sbic->sc_link.openings = 1; /* was 2 */
+ sbic->sc_link.scsipi_scsi.max_target = 7;
+ sbic->sc_link.scsipi_scsi.max_lun = 7;
+ sbic->sc_link.type = BUS_SCSI;
+
+ printf(": hostid=%d", sbic->sc_link.scsipi_scsi.adapter_target);
+
+#if ASC_POLL > 0
+ if (asc_poll)
+ printf(" polling");
+#endif
+ printf("\n");
+
+ sc->sc_pagereg = pa->pa_fast_h + ASC_PAGEREG;
+ sc->sc_intstat = pa->pa_fast_h + ASC_INTSTATUS;
+
+ /* Reset the card */
+
+ WriteByte(sc->sc_pagereg, 0x80);
+ DELAY(500000);
+ WriteByte(sc->sc_pagereg, 0x00);
+ DELAY(250000);
+
+ sbicinit(sbic);
+
+ if (!asc_poll) {
+ sc->sc_ih =
+ podulebus_irq_establish(sc->sc_softc.sc_dev.dv_parent,
+ pa->pa_slotnum, IPL_BIO, asc_intr, sc);
+ irq_enable(sc->sc_ih);
+ }
+
+ /*
+ * attach all scsi units on us
+ */
+ config_found(dp, &sbic->sc_link, scsiprint);
+}
+
+
+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(addr=%p, count=%d,flags=%d)\n", addr, count, flags);
+ printf("dmago: dc_addr=%p tcnt=%lx\n", dev->sc_cur->dc_addr, dev->sc_tcnt);
+#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
+ return(0);
+}
+
+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
+ return(0);
+}
+
+
+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
+ return(0);
+}
+
+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 scsipi_xfer *xs;
+{
+/* struct scsipi_link *sc_link = xs->sc_link;*/
+
+ /* ensure command is polling for the moment */
+#if ASC_POLL > 0
+ if (asc_poll)
+ xs->xs_control |= XS_CTL_POLL;
+#endif
+
+/* printf("id=%d lun=%dcmdlen=%d datalen=%d opcode=%02x flags=%08x status=%02x blk=%02x %02x\n",
+ sc_link->scsipi_scsi.target, sc_link->scsipi_scsi.lun, xs->cmdlen, xs->datalen, xs->cmd->opcode,
+ xs->xs_control, xs->status, xs->cmd->bytes[0], xs->cmd->bytes[1]);*/
+
+ return(sbic_scsicmd(xs));
+}
+
+
+int
+asc_intr(arg)
+ void *arg;
+{
+ struct asc_softc *sc = arg;
+ int intr;
+
+/* printf("ascintr:");*/
+ intr = ReadByte(sc->sc_intstat);
+/* printf("%02x\n", intr);*/
+
+ if (intr & IS_SBIC_IRQ)
+ return sbicintr((struct sbic_softc *)sc);
+
+ return(0); /* Pass interrupt on down the chain */
+}
+
+
+void alloc_z2mem()
+{
+ panic("allocz2mem");
+}
+
+void isztwomem()
+{
+ panic("isz2mem");
+}
+
+void PREP_DMA_MEM()
+{
+ panic("PREP_DMA_MEM");
+}
+
+/*
+ * limit the transfer as required.
+ */
+void
+asc_minphys(bp)
+ struct buf *bp;
+{
+#if 0
+ /*
+ * We must limit the DMA xfer size
+ */
+ if (bp->b_bcount > MAX_DMA_LEN) {
+ printf("asc: Reducing dma length\n");
+ bp->b_bcount = MAX_DMA_LEN;
+ }
+#endif
+ minphys(bp);
+}
+
diff --git a/sys/arch/arm26/podulebus/ascreg.h b/sys/arch/arm26/podulebus/ascreg.h
new file mode 100644
index 00000000000..af363ea9682
--- /dev/null
+++ b/sys/arch/arm26/podulebus/ascreg.h
@@ -0,0 +1,279 @@
+/* $NetBSD: ascreg.h,v 1.1 2000/05/09 21:56:03 bjh21 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/arm26/podulebus/ascvar.h b/sys/arch/arm26/podulebus/ascvar.h
new file mode 100644
index 00000000000..61a147d085d
--- /dev/null
+++ b/sys/arch/arm26/podulebus/ascvar.h
@@ -0,0 +1,51 @@
+/* $NetBSD: ascvar.h,v 1.1 2000/05/09 21:56:03 bjh21 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 <arm26/podulebus/sbicvar.h>
+#include <arm26/podulebus/ascreg.h>
+
+#define ASC_POLL 1
+
+struct asc_softc {
+ struct sbic_softc sc_softc;
+
+ int sc_podule_number;
+ struct irq_handler *sc_ih;
+
+ vu_int sc_pagereg;
+ vu_int sc_intstat;
+ };
+
+#endif /* _ASCVAR_H_ */
diff --git a/sys/arch/arm26/podulebus/dtide.c b/sys/arch/arm26/podulebus/dtide.c
new file mode 100644
index 00000000000..e988a4e9074
--- /dev/null
+++ b/sys/arch/arm26/podulebus/dtide.c
@@ -0,0 +1,122 @@
+/* $NetBSD: dtide.c,v 1.1 2000/05/09 21:56:03 bjh21 Exp $ */
+
+/*-
+ * Copyright (c) 2000 Ben Harris
+ * 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.
+ */
+/* This file is part of NetBSD/arm26 -- a port of NetBSD to ARM2/3 machines. */
+/*
+ * dtide.c - Driver for the D.T. Software IDE interface.
+ */
+
+#include <sys/param.h>
+
+__RCSID("$NetBSD: dtide.c,v 1.1 2000/05/09 21:56:03 bjh21 Exp $");
+
+#include <sys/device.h>
+#include <sys/systm.h>
+#include <machine/bus.h>
+#include <machine/irq.h>
+
+#include <arch/arm26/podulebus/podulebus.h>
+#include <arch/arm32/podulebus/podules.h>
+#include <arch/arm26/podulebus/dtidereg.h>
+
+#include <dev/ata/atavar.h>
+#include <dev/ic/wdcvar.h>
+
+struct dtide_softc {
+ struct wdc_softc sc_wdc;
+ struct channel_softc *sc_chp[2]; /* pointers to the following */
+ struct channel_softc sc_chan[2];
+ struct irq_handler *sc_ih[2];
+ bus_space_tag_t sc_magict;
+ bus_space_handle_t sc_magich;
+};
+
+static int dtide_match(struct device *, struct cfdata *, void *);
+static void dtide_attach(struct device *, struct device *, void *);
+
+struct cfattach dtide_ca = {
+ sizeof(struct dtide_softc), dtide_match, dtide_attach
+};
+
+static int
+dtide_match(struct device *parent, struct cfdata *cf, void *aux)
+{
+ struct podulebus_attach_args *pa = aux;
+
+ return IS_PODULE(pa, MANUFACTURER_DTSOFT, PODULE_DTSOFT_IDE);
+}
+
+static void
+dtide_attach(struct device *parent, struct device *self, void *aux)
+{
+ struct podulebus_attach_args *pa = aux;
+ struct dtide_softc *sc = (void *)self;
+ int i;
+ bus_space_tag_t bst;
+ bus_space_handle_t bsh;
+
+ sc->sc_wdc.cap = WDC_CAPABILITY_DATA16;
+ sc->sc_wdc.PIO_cap = 0; /* XXX correct? */
+ sc->sc_wdc.DMA_cap = 0; /* XXX correct? */
+ sc->sc_wdc.UDMA_cap = 0;
+ sc->sc_wdc.nchannels = 2;
+ sc->sc_wdc.channels = sc->sc_chp;
+ sc->sc_chp[0] = &sc->sc_chan[0];
+ sc->sc_chp[1] = &sc->sc_chan[1];
+ sc->sc_magict = pa->pa_fast_t;
+ bus_space_subregion(pa->pa_fast_t, pa->pa_fast_h, DTIDE_MAGICBASE >> 2,
+ 1, &sc->sc_magich);
+ bus_space_shift(pa->pa_fast_t, pa->pa_fast_h, DTIDE_REGSHIFT,
+ &bst, &bsh);
+ for (i = 0; i < 2; i++) {
+ sc->sc_chan[i].channel = i;
+ sc->sc_chan[i].wdc = &sc->sc_wdc;
+ sc->sc_chan[i].cmd_iot = bst;
+ sc->sc_chan[i].ctl_iot = bst;
+ }
+ bus_space_subregion(bst, bsh, DTIDE_CMDBASE0 >> 5, 0x100,
+ &sc->sc_chan[0].cmd_ioh);
+ bus_space_subregion(bst, bsh, DTIDE_CTLBASE0 >> 5, 0x100,
+ &sc->sc_chan[0].ctl_ioh);
+ bus_space_subregion(bst, bsh, DTIDE_CMDBASE1 >> 5, 0x100,
+ &sc->sc_chan[1].cmd_ioh);
+ bus_space_subregion(bst, bsh, DTIDE_CTLBASE1 >> 5, 0x100,
+ &sc->sc_chan[1].ctl_ioh);
+ sc->sc_ih[0] =
+ podulebus_irq_establish(self->dv_parent, pa->pa_slotnum,
+ IPL_BIO, wdcintr, &sc->sc_chan[0]);
+ sc->sc_ih[1] =
+ podulebus_irq_establish(self->dv_parent, pa->pa_slotnum,
+ IPL_BIO, wdcintr, &sc->sc_chan[1]);
+ printf(": interrupting at %s\n", irq_string(sc->sc_ih[0]));
+ wdcattach(&sc->sc_chan[0]);
+ irq_enable(sc->sc_ih[0]);
+ wdcattach(&sc->sc_chan[1]);
+ irq_enable(sc->sc_ih[1]);
+/* bus_space_write_1(sc->sc_magict, sc->sc_magich, 0, 1); */
+}
diff --git a/sys/arch/arm26/podulebus/dtidereg.h b/sys/arch/arm26/podulebus/dtidereg.h
new file mode 100644
index 00000000000..cc94a9dcdf3
--- /dev/null
+++ b/sys/arch/arm26/podulebus/dtidereg.h
@@ -0,0 +1,21 @@
+/* $NetBSD: dtidereg.h,v 1.1 2000/05/09 21:56:03 bjh21 Exp $ */
+
+/* This file is in the public domain */
+
+/*
+ * dtidereg.h - hardware-related constants of the D.T. Software IDE interface.
+ */
+
+/*
+ * This is mostly reverse-engineered by Ben Harris from the driver that
+ * comes with the board and the board itself. Treat with caution.
+ */
+
+#define DTIDE_MAGICBASE 0x2000
+
+#define DTIDE_REGSHIFT 5 /* ie DA0 == LA5 */
+#define DTIDE_CMDBASE0 0x2400
+#define DTIDE_CTLBASE0 0x2500
+#define DTIDE_CMDBASE1 0x2600
+#define DTIDE_CTLBASE1 0x2700
+
diff --git a/sys/arch/arm26/podulebus/if_ea.c b/sys/arch/arm26/podulebus/if_ea.c
new file mode 100644
index 00000000000..c254f83c29d
--- /dev/null
+++ b/sys/arch/arm26/podulebus/if_ea.c
@@ -0,0 +1,1537 @@
+/* $NetBSD: if_ea.c,v 1.1 2000/05/09 21:56:03 bjh21 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 "opt_inet.h"
+#include "opt_ns.h"
+
+#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>
+#include <net/if_ether.h>
+
+#ifdef INET
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/in_var.h>
+#include <netinet/ip.h>
+#include <netinet/if_inarp.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/irq.h>
+
+#include <arm26/podulebus/if_eareg.h>
+#include <arm26/podulebus/podulebus.h>
+#include <arm32/podulebus/podules.h>
+
+#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
+
+/*
+ * per-line info and status
+ */
+
+struct ea_softc {
+ struct device sc_dev;
+ struct irq_handler *sc_ih;
+ int sc_podule_number; /* Our podule number */
+ u_int sc_iobase; /* base I/O addr */
+ struct ethercom sc_ethercom; /* 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
+ */
+
+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((struct ifnet *));
+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 *, struct cfdata *, void *));
+void eaattach __P((struct device *, struct device *, void *));
+
+/* driver structure for autoconf */
+
+struct cfattach ea_ca = {
+ sizeof(struct ea_softc), eaprobe, eaattach
+};
+
+#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, struct cfdata *cf, void *aux)
+ *
+ * Probe for the ether3 podule.
+ */
+
+int
+eaprobe(parent, cf, aux)
+ struct device *parent;
+ struct cfdata *cf;
+ void *aux;
+{
+ struct podulebus_attach_args *pa = (void *)aux;
+ u_int iobase;
+
+/* Look for a network slot interface */
+
+ if ((matchpodule(pa, MANUFACTURER_ATOMWIDE, PODULE_ATOMWIDE_ETHER3, -1) == 0)
+ && (matchpodule(pa, MANUFACTURER_ACORN, PODULE_ACORN_ETHER3XXX, -1) == 0)
+ && (matchpodule(pa, MANUFACTURER_ANT, PODULE_ANT_ETHER3, -1) == 0))
+ return(0);
+
+ iobase = pa->pa_memc_h + EA_8005_BASE;
+
+/* Reset it - Why here ? */
+
+ WriteShort(iobase + EA_8005_CONFIG2, EA_CFG2_RESET);
+ delay(100);
+
+ 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 podulebus_attach_args *pa = (void *)aux;
+ struct ifnet *ifp = &sc->sc_ethercom.ec_if;
+ int loop;
+ int sum;
+ u_int8_t myaddr[ETHER_ADDR_LEN];
+
+/* dprintf(("Attaching %s...\n", sc->sc_dev.dv_xname));*/
+
+/* Note the podule number and validate */
+
+ sc->sc_podule_number = pa->pa_slotnum;
+
+/* Set the address of the controller for easy access */
+
+ sc->sc_iobase = pa->pa_memc_h + EA_8005_BASE;
+
+/* 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) {
+ myaddr[loop] =
+ ReadByte(sc->sc_iobase + EA_8005_BUFWIN);
+ sum += myaddr[loop];
+ }
+
+/*
+ * Hard code the ether address if we don't have one.
+ * Need to work out how I get the real address
+ * until then use the one a network slot card
+ * would used, based on the machine id.
+ */
+
+/*
+ * Unfortunately, arm26 machines don't necessarily have a SSN, and I don't
+ * support them yet anyway. Erm, ideas anyone?
+ */
+
+ if (sum == 0) {
+ printf(": Ethernet address not found. Giving up.\n");
+#if 0
+ myaddr[0] = 0x00;
+ myaddr[1] = 0x00;
+ myaddr[2] = bootconfig.machine_id[3];
+ myaddr[3] = bootconfig.machine_id[2];
+ myaddr[4] = bootconfig.machine_id[1];
+ myaddr[5] = bootconfig.machine_id[0];
+#endif
+ }
+
+ /* Print out some information for the user. */
+
+ printf(": SEEQ8005 address %s", ether_sprintf(myaddr));
+
+ sc->sc_irqclaimed = 0;
+
+/* Claim a podule interrupt */
+
+ sc->sc_ih = podulebus_irq_establish(sc->sc_dev.dv_parent,
+ pa->pa_slotnum, IPL_NET, eaintr, sc);
+
+ /* Stop the board. */
+
+ ea_chipreset(sc);
+ ea_stoptx(sc);
+ ea_stoprx(sc);
+
+ /* Initialise ifnet structure. */
+
+ bcopy(sc->sc_dev.dv_xname, ifp->if_xname, IFNAMSIZ);
+ ifp->if_softc = sc;
+ 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, myaddr);
+
+ /* 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 */
+
+ irq_enable(sc->sc_ih);
+
+ sc->sc_irqclaimed = 1;
+}
+
+
+/* Release an irq */
+
+void
+ea_releaseirq(sc)
+ struct ea_softc *sc;
+{
+/* Have we claimed one ? */
+
+ if (!sc->sc_irqclaimed) return;
+
+ irq_disable(sc->sc_ih);
+
+ 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 = splnet();
+ 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_ethercom.ec_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;
+ struct ifnet *ifp = &sc->sc_ethercom.ec_if;
+ 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,
+ LLADDR(ifp->if_sadl)[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_ethercom.ec_if;
+ u_int iobase = sc->sc_iobase;
+ int s;
+
+ dprintf(("ea_init()\n"));
+
+ s = splnet();
+
+/* 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 splnet or
+ * interrupt level!
+ */
+
+static void
+ea_start(ifp)
+ struct ifnet *ifp;
+{
+ struct ea_softc *sc = ifp->if_softc;
+ int s;
+
+ s = splnet();
+#ifdef EA_TX_DEBUG
+ dprintf(("ea_start()...\n"));
+#endif
+
+ /* Don't do anything if output is active. */
+
+ if (ifp->if_flags & IFF_OACTIVE)
+ return;
+
+ /* Mark interface as output active */
+
+ ifp->if_flags |= IFF_OACTIVE;
+
+ /* tx packets */
+
+ eatxpacket(sc);
+ (void)splx(s);
+}
+
+
+/*
+ * Transfer a packet to the interface buffer and start transmission
+ *
+ * Called at splnet()
+ */
+
+void
+eatxpacket(sc)
+ struct ea_softc *sc;
+{
+ u_int iobase = sc->sc_iobase;
+ struct mbuf *m, *m0;
+ struct ifnet *ifp;
+ int len;
+
+ ifp = &sc->sc_ethercom.ec_if;
+
+/* Dequeue the next datagram. */
+
+ IF_DEQUEUE(&ifp->if_snd, m0);
+
+/* If there's nothing to send, return. */
+
+ if (!m0) {
+ ifp->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 (ifp->if_bpf)
+ bpf_mtap(ifp->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 - ETHER_CRC_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;
+ struct ifnet *ifp = &sc->sc_ethercom.ec_if;
+ int status, s, handled;
+ u_int txstatus;
+
+ handled = 0;
+ 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 "));
+ handled = 1;
+
+/* 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) {
+ ifp->if_collisions++;
+ } else if (txstatus & EA_TXHDR_ERROR_MASK) {
+ ifp->if_oerrors++;
+ }
+
+/* if (txstatus & EA_TXHDR_ERROR_MASK) {
+ log(LOG_WARNING, "tx packet error =%02x\n", txstatus);
+ }*/
+
+ if (txstatus & EA_PKTHDR_DONE) {
+ ifp->if_opackets++;
+
+ /* Tx next packet */
+
+ s = splnet();
+ eatxpacket(sc);
+ (void)splx(s);
+ }
+ }
+
+/* Rx interrupt ? */
+
+ if (status & EA_STATUS_RX_INT) {
+ dprintf(("rxint "));
+ handled = 1;
+
+/* 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 */
+
+ ifp->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 handled; /* Pass interrupt on down the chain */
+}
+
+
+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;
+ struct ifnet *ifp;
+
+ ifp = &sc->sc_ethercom.ec_if;
+
+/* 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) {
+ ++ifp->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;
+ }
+
+/* Is the packet too big ? - this will probably be trapped above as a receive error */
+
+ if (len > (ETHER_MAX_LEN - ETHER_CRC_LEN)) {
+ ++ifp->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;
+ }
+
+ 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
+ ifp->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;
+ struct ifnet *ifp;
+
+ ifp = &sc->sc_ethercom.ec_if;
+ eh = (struct ether_header *)buf;
+
+ /* Pull packet off interface. */
+ m = eaget(buf, len, ifp);
+ 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 (ifp->if_bpf) {
+ bpf_mtap(ifp->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 ((ifp->if_flags & IFF_PROMISC) &&
+ (eh->ether_dhost[0] & 1) == 0 && /* !mcast and !bcast */
+ bcmp(eh->ether_dhost, LLADDR(ifp->if_sadl),
+ sizeof(eh->ether_dhost)) != 0) {
+ m_freem(m);
+ return;
+ }
+ }
+#endif
+
+ (*ifp->if_input)(ifp, 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;
+
+ 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 = ifp->if_softc;
+ struct ifaddr *ifa = (struct ifaddr *)data;
+/* struct ifreq *ifr = (struct ifreq *)data;*/
+ int s, error = 0;
+
+ s = splnet();
+
+ 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(ifp, 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 *)LLADDR(ifp->if_sadl);
+ else
+ bcopy(ina->x_host.c_host,
+ LLADDR(ifp->if_sadl), ETHER_ADDR_LEN);
+ /* 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(ifp)
+ struct ifnet *ifp;
+{
+ struct ea_softc *sc = ifp->if_softc;
+
+ log(LOG_ERR, "%s: device timeout\n", sc->sc_dev.dv_xname);
+ ifp->if_oerrors++;
+ dprintf(("ea_watchdog: "));
+ dprintf(("st=%04x\n", ReadShort(sc->sc_iobase + EA_8005_STATUS)));
+
+ /* Kick the interface */
+
+ ea_reinit(sc);
+
+/* ifp->if_timer = EA_TIMEOUT;*/
+ ifp->if_timer = 0;
+}
+
+/* End of if_ea.c */
diff --git a/sys/arch/arm26/podulebus/if_eareg.h b/sys/arch/arm26/podulebus/if_eareg.h
new file mode 100644
index 00000000000..e3c841ad53a
--- /dev/null
+++ b/sys/arch/arm26/podulebus/if_eareg.h
@@ -0,0 +1,168 @@
+/* $NetBSD: if_eareg.h,v 1.1 2000/05/09 21:56:03 bjh21 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/arm26/podulebus/if_ei.c b/sys/arch/arm26/podulebus/if_ei.c
new file mode 100644
index 00000000000..83d5c7a45ca
--- /dev/null
+++ b/sys/arch/arm26/podulebus/if_ei.c
@@ -0,0 +1,371 @@
+/* $NetBSD: if_ei.c,v 1.1 2000/05/09 21:56:03 bjh21 Exp $ */
+
+/*-
+ * Copyright (c) 2000 Ben Harris
+ * 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.
+ */
+/* This file is part of NetBSD/arm26 -- a port of NetBSD to ARM2/3 machines. */
+/*
+ * if_ei.c -- driver for Acorn AKA25 Ether1 card
+ */
+/*
+ * This is not directly based on the arm32 ie driver, as that doesn't
+ * use the MI 82586 driver, and generally looks a mess (not to mention
+ * having dodgy copyright status). Let's try again.
+ */
+
+#include <sys/param.h>
+
+__RCSID("$NetBSD: if_ei.c,v 1.1 2000/05/09 21:56:03 bjh21 Exp $");
+
+#include <sys/device.h>
+#include <sys/malloc.h>
+#include <sys/socket.h>
+#include <sys/syslog.h>
+#include <sys/systm.h>
+#include <net/if.h>
+#include <net/if_ether.h>
+#include <net/if_media.h>
+#include <machine/bus.h>
+#include <machine/irq.h>
+#include <dev/ic/i82586reg.h>
+#include <dev/ic/i82586var.h>
+#include <arch/arm26/podulebus/podulebus.h>
+#include <arch/arm32/podulebus/podules.h>
+#include <arch/arm26/podulebus/if_eireg.h>
+
+/* Callbacks from the MI 82586 driver */
+static void ei_hwreset(struct ie_softc *, int);
+/* static void ei_hwinit(struct ie_softc *); */
+static void ei_attn(struct ie_softc *);
+static int ei_intrhook(struct ie_softc *, int);
+
+static void ei_copyin(struct ie_softc *, void *, int, size_t);
+static void ei_copyout(struct ie_softc *, const void *, int, size_t);
+static u_int16_t ei_read16(struct ie_softc *, int);
+static void ei_write16(struct ie_softc *, int, u_int16_t);
+static void ei_write24(struct ie_softc *, int, int);
+
+/* autoconfiguration glue */
+static int ei_match(struct device *, struct cfdata *, void *);
+static void ei_attach(struct device *, struct device *, void *);
+
+struct ei_softc {
+ struct ie_softc sc_ie;
+ bus_space_tag_t sc_ctl_t;
+ bus_space_handle_t sc_ctl_h;
+ bus_space_tag_t sc_mem_t;
+ bus_space_handle_t sc_mem_h;
+ bus_space_tag_t sc_rom_t;
+ bus_space_handle_t sc_rom_h;
+ u_int8_t sc_idrom[EI_ROMSIZE];
+ struct irq_handler *sc_ih;
+};
+
+struct cfattach ei_ca = {
+ sizeof(struct ei_softc), ei_match, ei_attach
+};
+
+static inline void
+ei_setpage(struct ei_softc *sc, int page)
+{
+
+ bus_space_write_1(sc->sc_ctl_t, sc->sc_ctl_h, EI_PAGE, page);
+}
+
+static inline void
+ei_cli(struct ei_softc *sc)
+{
+
+ bus_space_write_1(sc->sc_ctl_t, sc->sc_ctl_h, EI_CONTROL, EI_CTL_CLI);
+}
+
+static int
+ei_match(struct device *parent, struct cfdata *cf, void *aux)
+{
+ struct podulebus_attach_args *pa = aux;
+
+ return IS_PODULE(pa, MANUFACTURER_ACORN, PODULE_ACORN_ETHER1);
+}
+
+static void
+ei_attach(struct device *parent, struct device *self, void *aux)
+{
+ struct podulebus_attach_args *pa = aux;
+ struct ei_softc *sc = (struct ei_softc *)self;
+ int i;
+ char descr[16];
+
+ /* Set up bus spaces */
+ sc->sc_ctl_t = sc->sc_mem_t = pa->pa_fast_t;
+ bus_space_subregion(sc->sc_ctl_t, pa->pa_fast_h,
+ 0, EI_MEMOFF, &sc->sc_ctl_h);
+ bus_space_subregion(sc->sc_mem_t, pa->pa_fast_h,
+ EI_MEMOFF, EI_PAGESIZE / 2, &sc->sc_mem_h);
+ sc->sc_rom_t = pa->pa_sync_t;
+ sc->sc_rom_h = pa->pa_sync_h;
+
+ /* Set up callbacks */
+ sc->sc_ie.hwinit = NULL;
+ sc->sc_ie.intrhook = ei_intrhook;
+ sc->sc_ie.hwreset = ei_hwreset;
+ sc->sc_ie.chan_attn = ei_attn;
+
+ sc->sc_ie.memcopyin = ei_copyin;
+ sc->sc_ie.memcopyout = ei_copyout;
+ sc->sc_ie.ie_bus_read16 = ei_read16;
+ sc->sc_ie.ie_bus_write16 = ei_write16;
+ sc->sc_ie.ie_bus_write24 = ei_write24;
+
+ sc->sc_ie.do_xmitnopchain = 0; /* Does it listen? */
+
+ sc->sc_ie.sc_mediachange = NULL;
+ sc->sc_ie.sc_mediastatus = NULL;
+
+ sc->sc_ie.bt = sc->sc_mem_t; /* XXX hope it doesn't use them */
+ sc->sc_ie.bh = sc->sc_mem_h;
+
+ printf(":");
+
+ /* All Ether1s are 64k (I believe) */
+ sc->sc_ie.sc_msize = EI_MEMSIZE;
+
+ /* set up pointers to important on-card control structures */
+ sc->sc_ie.iscp = 0;
+ sc->sc_ie.scb = IE_ISCP_SZ;
+ sc->sc_ie.scp = sc->sc_ie.sc_msize + IE_SCP_ADDR - (1 << 24);
+
+ sc->sc_ie.buf_area = sc->sc_ie.scb + IE_SCB_SZ;
+ sc->sc_ie.buf_area_sz =
+ sc->sc_ie.sc_msize - IE_ISCP_SZ - IE_SCB_SZ - IE_SCP_SZ;
+
+ /* Wipe the whole of the card's memory */
+ for (i = 0; i < EI_NPAGES; i++) {
+ ei_setpage(sc, i);
+ bus_space_set_region_2(sc->sc_mem_t, sc->sc_mem_h,
+ 0, 0,EI_PAGESIZE / 2);
+ }
+
+ /* set up pointers to key structures */
+ ei_write24(&sc->sc_ie, IE_SCP_ISCP((u_long)sc->sc_ie.scp),
+ (u_long) sc->sc_ie.iscp);
+ ei_write16(&sc->sc_ie, IE_ISCP_SCB((u_long)sc->sc_ie.iscp),
+ (u_long) sc->sc_ie.scb);
+ ei_write24(&sc->sc_ie, IE_ISCP_BASE((u_long)sc->sc_ie.iscp),
+ (u_long) sc->sc_ie.iscp);
+
+ /* check if chip answers */
+ if (i82586_proberam(&sc->sc_ie) == 0) {
+ printf(" memory probe failed\n");
+ return;
+ }
+
+ /* Read ROM */
+ bus_space_read_region_1(sc->sc_rom_t, sc->sc_rom_h, 0,
+ sc->sc_idrom, EI_ROMSIZE);
+
+ snprintf(descr, 15, "AKA25 iss. %d", sc->sc_idrom[EI_ROM_HWREV]);
+ i82586_attach(&sc->sc_ie, descr, sc->sc_idrom + EI_ROM_EADDR,
+ NULL, 0, 0);
+
+ sc->sc_ih = podulebus_irq_establish(self->dv_parent, pa->pa_slotnum,
+ IPL_NET, i82586_intr, self);
+ printf("%s: interrupting at %s\n",
+ self->dv_xname, irq_string(sc->sc_ih));
+ ei_cli(sc);
+ irq_enable(sc->sc_ih);
+}
+
+static void
+ei_hwreset(struct ie_softc *sc_ie, int why)
+{
+ struct ei_softc *sc = (struct ei_softc *)sc_ie;
+
+ bus_space_write_1(sc->sc_ctl_t, sc->sc_ctl_h,
+ EI_CONTROL, EI_CTL_RESET);
+ DELAY(1000);
+ bus_space_write_1(sc->sc_ctl_t, sc->sc_ctl_h, EI_CONTROL, 0);
+ DELAY(1000);
+ ei_cli(sc);
+}
+
+static int
+ei_intrhook(struct ie_softc *sc_ie, int why)
+{
+ struct ei_softc *sc = (struct ei_softc *)sc_ie;
+
+ switch (why) {
+ case INTR_EXIT:
+ case INTR_ACK:
+ ei_cli(sc);
+ break;
+ }
+ return 0;
+}
+
+static void
+ei_attn(struct ie_softc *sc_ie)
+{
+ struct ei_softc *sc = (void *)sc_ie;
+
+ bus_space_write_1(sc->sc_ctl_t, sc->sc_ctl_h, EI_CONTROL, EI_CTL_ATTN);
+}
+
+/*
+ * Various access functions to allow the MI 82586 driver to get at the
+ * board's memory. All memory accesses must go through these, as
+ * nothing else knows how to manipulate the page register. Note that
+ * all addresses and lengths passed in are in bytes of actual data.
+ * The bus_space functions deal in words, though, so we have to
+ * convert on the way through.
+ */
+
+static void
+ei_copyin(struct ie_softc *sc_ie, void *dest, int src, size_t size)
+{
+ struct ei_softc *sc = (struct ei_softc *)sc_ie;
+ int cnt, s, extra_byte;
+
+#ifdef DIAGNOSTIC
+ if (src % 2 != 0 || !ALIGNED_POINTER(dest, u_int16_t))
+ panic("%s: unaligned copyin", sc_ie->sc_dev.dv_xname);
+#endif
+ extra_byte = size % 2;
+ size -= extra_byte;
+ while (size > 0) {
+ cnt = EI_PAGESIZE - src % EI_PAGESIZE;
+ if (cnt > size)
+ cnt = size;
+ s = splnet();
+ ei_setpage(sc, ei_atop(src));
+ /* bus ops are in words */
+ bus_space_read_region_2(sc->sc_mem_t, sc->sc_mem_h,
+ ei_atopo(src) / 2, dest, cnt / 2);
+ splx(s);
+ src += cnt;
+ dest += cnt;
+ size -= cnt;
+ }
+ if (extra_byte) {
+ /* Do we need to be this careful? */
+ s = splnet();
+ ei_setpage(sc, ei_atop(src));
+ *(u_int8_t *)dest =
+ bus_space_read_2(sc->sc_mem_t, sc->sc_mem_h,
+ ei_atopo(src) / 2) & 0xff;
+ splx(s);
+ }
+
+}
+
+static void
+ei_copyout(struct ie_softc *sc_ie, const void *src, int dest, size_t size)
+{
+ struct ei_softc *sc = (struct ei_softc *)sc_ie;
+ int cnt, s;
+ u_int16_t *bounce = NULL;
+
+#ifdef DIAGNOSTIC
+ if (dest % 2 != 0)
+ panic("%s: unaligned copyout", sc_ie->sc_dev.dv_xname);
+#endif
+ if (!ALIGNED_POINTER(src, u_int16_t)) {
+ MALLOC(bounce, u_int16_t *, size, M_DEVBUF, M_NOWAIT);
+ if (bounce == NULL)
+ panic("%s: no memory to align copyout",
+ sc_ie->sc_dev.dv_xname);
+ memcpy(bounce, src, size);
+ src = bounce;
+ }
+ if (size % 2 != 0)
+ size++; /* This is safe, since the buffer is 16bit aligned */
+ while (size > 0) {
+ cnt = EI_PAGESIZE - dest % EI_PAGESIZE;
+ if (cnt > size)
+ cnt = size;
+ s = splnet();
+ ei_setpage(sc, ei_atop(dest));
+ /* bus ops are in words */
+ bus_space_write_region_2(sc->sc_mem_t, sc->sc_mem_h,
+ ei_atopo(dest) / 2, src, cnt / 2);
+ splx(s);
+ src += cnt;
+ dest += cnt;
+ size -= cnt;
+ }
+ if (bounce != NULL)
+ FREE(bounce, M_DEVBUF);
+}
+
+static u_int16_t
+ei_read16(struct ie_softc *sc_ie, int addr)
+{
+ struct ei_softc *sc = (struct ei_softc *)sc_ie;
+ int result, s;
+
+#ifdef DIAGNOSTIC
+ if (addr % 2 != 0)
+ panic("%s: unaligned read16", sc_ie->sc_dev.dv_xname);
+#endif
+ s = splnet();
+ ei_setpage(sc, ei_atop(addr));
+ result = bus_space_read_2(sc->sc_mem_t, sc->sc_mem_h,
+ ei_atopo(addr) / 2);
+ splx(s);
+ return result;
+}
+
+static void
+ei_write16(struct ie_softc *sc_ie, int addr, u_int16_t value)
+{
+ struct ei_softc *sc = (struct ei_softc *)sc_ie;
+ int s;
+
+#ifdef DIAGNOSTIC
+ if (addr % 2 != 0)
+ panic("%s: unaligned write16", sc_ie->sc_dev.dv_xname);
+#endif
+ s = splnet();
+ ei_setpage(sc, ei_atop(addr));
+ bus_space_write_2(sc->sc_mem_t, sc->sc_mem_h, ei_atopo(addr) / 2,
+ value);
+ splx(s);
+}
+
+static void
+ei_write24(struct ie_softc *sc_ie, int addr, int value)
+{
+ int s;
+
+#ifdef DIAGNOSTIC
+ if (addr % 2 != 0)
+ panic("%s: unaligned write24", sc_ie->sc_dev.dv_xname);
+#endif
+ s = splnet();
+ ei_write16(sc_ie, addr, value & 0xffff);
+ ei_write16(sc_ie, addr + 2, (value >> 16) & 0xff);
+ splx(s);
+}
+
diff --git a/sys/arch/arm26/podulebus/if_eireg.h b/sys/arch/arm26/podulebus/if_eireg.h
new file mode 100644
index 00000000000..63995b5b21e
--- /dev/null
+++ b/sys/arch/arm26/podulebus/if_eireg.h
@@ -0,0 +1,62 @@
+/* $NetBSD: if_eireg.h,v 1.1 2000/05/09 21:56:03 bjh21 Exp $ */
+
+/*
+ * 2000 Ben Harris
+ *
+ * This file is in the public domain.
+ */
+
+/*
+ * if_eireg.h - register definitions etc for the Acorn Ether1 card
+ */
+
+#ifndef _IF_EIREG_H_
+#define _IF_EIREG_H_
+
+/*
+ * My understanding of this card is as follows. Note that this is
+ * mostly derived from reading other people's code, so it may be
+ * hideously inaccurate.
+ *
+ * The card has three address spaces. The ROM is mapped into the
+ * bottom n (16?) bytes of SYNC address space, and contains the
+ * expansion card ID information and the Ethernet address. There is a
+ * (write only?) set of registers at the start of the FAST address
+ * space. One of these performs miscellaneous control functions, and
+ * the other acts as a page selector for the board memory. The board
+ * has 64k of RAM, and 4k pages of this can be mapped at offset 0x2000
+ * in the FAST space by writing the page number to the page register.
+ * The 82586 has access to the whole of this memory and (I believe)
+ * sees it as the top 64k of its address space.
+ */
+
+/* Registers in the board's control space */
+#define EI_PAGE 0
+#define EI_CONTROL 1
+#define EI_CTL_RESET 0x01
+#define EI_CTL_LOOP 0x02
+#define EI_CTL_ATTN 0x04
+#define EI_CTL_CLI 0x08
+
+/* Offset of base of memory in bus_space */
+#define EI_MEMOFF 0x800
+
+/*
+ * All addresses within board RAM are in bytes of actual RAM. RAM is
+ * 16 bis wide, and can only be accessed by word transfers
+ * (bus_space_xxx_2).
+ */
+#define EI_MEMSIZE 0x10000
+#define EI_MEMBASE (0x1000000 - EI_MEMSIZE)
+#define EI_PAGESIZE 0x1000
+#define EI_NPAGES (EI_MEMSIZE / EI_PAGESIZE)
+#define ei_atop(a) (((a) % EI_MEMSIZE) / EI_PAGESIZE)
+#define ei_atopo(a) ((a) % EI_PAGESIZE)
+
+#define EI_SCP_ADDR IE_SCP_ADDR % EI_MEMSIZE
+
+#define EI_ROMSIZE 16
+#define EI_ROM_HWREV 8
+#define EI_ROM_EADDR 9
+
+#endif
diff --git a/sys/arch/arm26/podulebus/podulebus.c b/sys/arch/arm26/podulebus/podulebus.c
new file mode 100644
index 00000000000..2530cd47b82
--- /dev/null
+++ b/sys/arch/arm26/podulebus/podulebus.c
@@ -0,0 +1,251 @@
+/* $NetBSD: podulebus.c,v 1.1 2000/05/09 21:56:03 bjh21 Exp $ */
+
+/*-
+ * Copyright (c) 2000 Ben Harris
+ * 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.
+ */
+/* This file is part of NetBSD/arm26 -- a port of NetBSD to ARM2/3 machines. */
+
+#include <sys/param.h>
+
+__RCSID("$NetBSD: podulebus.c,v 1.1 2000/05/09 21:56:03 bjh21 Exp $");
+
+#include <sys/device.h>
+#include <sys/malloc.h>
+#include <sys/systm.h>
+#include <machine/bus.h>
+#include <machine/irq.h>
+#include <machine/memcreg.h>
+#include <arch/arm26/iobus/iocreg.h>
+#include <arch/arm26/iobus/iocvar.h>
+#include <arch/arm26/podulebus/podulebus.h>
+#include <arch/arm26/podulebus/podulebusreg.h>
+
+#include "locators.h"
+
+static int podulebus_match(struct device *, struct cfdata *, void *);
+static void podulebus_attach(struct device *, struct device *, void *);
+static void podulebus_probe_podule(struct device *, int);
+static int podulebus_print(void *, char const *);
+static int podulebus_submatch(struct device *, struct cfdata *, void *);
+static void podulebus_read_chunks(struct device *,
+ struct podulebus_attach_args *);
+static u_int8_t *podulebus_get_chunk(struct podulebus_attach_args *pa, int type);
+
+struct podulebus_softc {
+ struct device sc_dev;
+ struct ioc_attach_args sc_ioc;
+};
+
+struct cfattach podulebus_ca = {
+ sizeof(struct podulebus_softc), podulebus_match, podulebus_attach
+};
+
+extern struct cfdriver podulebus_cd;
+
+/* ARGSUSED */
+static int
+podulebus_match(struct device *parent, struct cfdata *cf, void *aux)
+{
+
+ /* We can't usefully probe for this */
+ return 1;
+}
+
+static void
+podulebus_attach(struct device *parent, struct device *self, void *aux)
+{
+ int i;
+ struct podulebus_softc *sc = (struct podulebus_softc *)self;
+ struct ioc_attach_args *ioc = aux;
+
+ sc->sc_ioc = *ioc;
+ printf("\n");
+
+ /* Iterate over the podules attaching them */
+ for (i = 0; i < MAX_PODULES; i++)
+ podulebus_probe_podule(self, i);
+}
+
+static void
+podulebus_probe_podule(struct device *self, int slotnum)
+{
+ struct podulebus_softc *sc = (struct podulebus_softc *)self;
+ bus_space_tag_t id_bst;
+ bus_space_handle_t id_bsh;
+ int ecid;
+ u_int8_t extecid[EXTECID_SIZE];
+ struct podulebus_attach_args pa;
+
+ bzero(&pa, sizeof(pa));
+ id_bst = sc->sc_ioc.ioc_sync_t;
+ bus_space_subregion(id_bst, sc->sc_ioc.ioc_sync_h,
+ slotnum * PODULE_GAP, PODULE_GAP, &id_bsh);
+ ecid = bus_space_read_1(id_bst, id_bsh, 0);
+ /* Skip empty or strange slots */
+ if (ecid & (ECID_NOTPRESENT | ECID_NONCONF))
+ return;
+ if ((ecid & ECID_ID_MASK) == ECID_ID_EXTEND) {
+ pa.pa_fast_t = sc->sc_ioc.ioc_fast_t;
+ bus_space_subregion(pa.pa_fast_t, sc->sc_ioc.ioc_fast_h,
+ slotnum * PODULE_GAP, PODULE_GAP,
+ &pa.pa_fast_h);
+ pa.pa_medium_t = sc->sc_ioc.ioc_medium_t;
+ bus_space_subregion(pa.pa_medium_t, sc->sc_ioc.ioc_medium_h,
+ slotnum * PODULE_GAP, PODULE_GAP,
+ &pa.pa_medium_h);
+ pa.pa_slow_t = sc->sc_ioc.ioc_slow_t;
+ bus_space_subregion(pa.pa_slow_t, sc->sc_ioc.ioc_slow_h,
+ slotnum * PODULE_GAP, PODULE_GAP,
+ &pa.pa_slow_h);
+ pa.pa_sync_t = sc->sc_ioc.ioc_sync_t;
+ bus_space_subregion(pa.pa_sync_t, sc->sc_ioc.ioc_sync_h,
+ slotnum * PODULE_GAP, PODULE_GAP,
+ &pa.pa_sync_h);
+ /* XXX This is a hack! */
+ pa.pa_memc_t = 2;
+ bus_space_subregion(pa.pa_memc_t,
+ (bus_space_handle_t)MEMC_IO_BASE, slotnum * PODULE_GAP,
+ PODULE_GAP, &pa.pa_memc_h);
+ bus_space_read_region_1(id_bst, id_bsh, 0,
+ extecid, EXTECID_SIZE);
+ pa.pa_ecid = ecid;
+ pa.pa_flags1 = extecid[EXTECID_F1];
+ pa.pa_manufacturer = (extecid[EXTECID_MLO] |
+ extecid[EXTECID_MHI] << 8);
+ pa.pa_product = (extecid[EXTECID_PLO] |
+ extecid[EXTECID_PHI] << 8);
+ pa.pa_slotnum = slotnum;
+ if (pa.pa_flags1 & EXTECID_F1_CD) {
+ podulebus_read_chunks(self, &pa);
+ pa.pa_descr = podulebus_get_chunk(&pa,
+ CHUNK_DEV_DESCR);
+ }
+ config_found_sm(self, &pa,
+ podulebus_print, podulebus_submatch);
+ if (pa.pa_chunks)
+ FREE(pa.pa_chunks, M_DEVBUF);
+ if (pa.pa_descr)
+ FREE(pa.pa_descr, M_DEVBUF);
+ } else
+ printf("%s:%d: non-extended podule ignored.\n",
+ self->dv_xname, slotnum);
+}
+
+static void
+podulebus_read_chunks(struct device *self, struct podulebus_attach_args *pa)
+{
+ u_int8_t chunk[8];
+ u_int ptr, w, nchunks, type, length, offset;
+
+ nchunks = 0;
+ ptr = EXTECID_SIZE + IRQPTR_SIZE;
+ w = pa->pa_flags1 & EXTECID_F1_W_MASK;
+ if (w != EXTECID_F1_W_8BIT) {
+ /* RISC OS 3 can't handle this either. */
+ printf("%s:%d: ROM is not 8 bits wide; ignoring it\n",
+ self->dv_xname, pa->pa_slotnum);
+ return;
+ }
+ for (;;) {
+ bus_space_read_region_1(pa->pa_sync_t, pa->pa_sync_h,
+ ptr, chunk, 8);
+ ptr += 8;
+ type = chunk[0];
+ length = chunk[1] | chunk[2] << 8 | chunk[3] << 16;
+ if (length == 0)
+ break;
+ offset = chunk[4] | chunk[5] << 8 |
+ chunk[6] << 16 | chunk[7] << 24;
+ if ((offset + length) > PODULE_GAP)
+ continue;
+ nchunks++;
+ pa->pa_chunks = realloc(pa->pa_chunks,
+ nchunks * sizeof(*pa->pa_chunks),
+ M_DEVBUF, M_WAITOK);
+ pa->pa_chunks[nchunks-1].pc_type = type;
+ pa->pa_chunks[nchunks-1].pc_length = length;
+ pa->pa_chunks[nchunks-1].pc_offset = offset;
+ }
+ pa->pa_nchunks = nchunks;
+}
+
+static u_int8_t *
+podulebus_get_chunk(struct podulebus_attach_args *pa, int type)
+{
+ int i;
+ u_int8_t *chunk;
+
+ for (i = 0; i < pa->pa_nchunks; i++)
+ if (pa->pa_chunks[i].pc_type == type) {
+ MALLOC(chunk, u_int8_t *,
+ pa->pa_chunks[i].pc_length + 1,
+ M_DEVBUF, M_WAITOK);
+ bus_space_read_region_1(pa->pa_sync_t, pa->pa_sync_h,
+ pa->pa_chunks[i].pc_offset,
+ chunk,
+ pa->pa_chunks[i].pc_length);
+ chunk[pa->pa_chunks[i].pc_length] = 0;
+ return chunk;
+ }
+ return NULL;
+}
+
+static int
+podulebus_print(void *aux, char const *pnp)
+{
+ struct podulebus_attach_args *pa = aux;
+
+ if (pnp) {
+ if (pa->pa_descr)
+ printf("%s", pa->pa_descr);
+ else
+ printf("podule");
+ printf(" <%04x:%04x> at %s",
+ pa->pa_manufacturer, pa->pa_product, pnp);
+ }
+ printf(" slot %d", pa->pa_slotnum);
+ return UNCONF;
+}
+
+static int
+podulebus_submatch(struct device *parent, struct cfdata *cf, void *aux)
+{
+ struct podulebus_attach_args *pa = aux;
+
+ if (cf->cf_loc[PODULEBUSCF_SLOT] == PODULEBUSCF_SLOT_DEFAULT ||
+ cf->cf_loc[PODULEBUSCF_SLOT] == pa->pa_slotnum)
+ return (*cf->cf_attach->ca_match)(parent, cf, aux);
+ return 0;
+}
+
+struct irq_handler *
+podulebus_irq_establish(struct device *self, int slot, int ipl,
+ int (*func)(void *), void *arg)
+{
+
+ /* XXX: support for checking IRQ bit on podule? */
+ return ioc_irq_establish(self->dv_parent, IOC_IRQ_IL5, ipl, func, arg);
+}
diff --git a/sys/arch/arm26/podulebus/podulebus.h b/sys/arch/arm26/podulebus/podulebus.h
new file mode 100644
index 00000000000..661e0de8570
--- /dev/null
+++ b/sys/arch/arm26/podulebus/podulebus.h
@@ -0,0 +1,98 @@
+/* $NetBSD: podulebus.h,v 1.1 2000/05/09 21:56:03 bjh21 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>
+#include <machine/bus.h>
+
+struct podulebus_chunk {
+ int pc_type;
+ int pc_length;
+ int pc_offset;
+};
+
+struct podulebus_attach_args {
+ bus_space_tag_t pa_memc_t;
+ bus_space_handle_t pa_memc_h;
+ bus_space_tag_t pa_fast_t;
+ bus_space_handle_t pa_fast_h;
+ bus_space_tag_t pa_medium_t;
+ bus_space_handle_t pa_medium_h;
+ bus_space_tag_t pa_slow_t;
+ bus_space_handle_t pa_slow_h;
+ bus_space_tag_t pa_sync_t;
+ bus_space_handle_t pa_sync_h;
+ int pa_slotnum;
+ int pa_ecid;
+ int pa_flags1;
+ int pa_manufacturer;
+ int pa_product;
+ struct podulebus_chunk *pa_chunks;
+ int pa_nchunks;
+ char *pa_descr;
+};
+
+#define IS_PODULE(pa, man, prod) \
+ ((pa)->pa_manufacturer == (man) && (pa)->pa_product == (prod))
+
+#ifdef _KERNEL
+
+extern struct irq_handler *podulebus_irq_establish(struct device *, int, int,
+ int (*)(void *), void *);
+
+#endif
+
+/* arm32 compatibility */
+
+#define WriteByte(a, v) bus_space_write_1(2, (a), 0, (v))
+#define WriteShort(a, v) bus_space_write_2(2, (a), 0, (v))
+#define ReadByte(a) bus_space_read_1(2, (a), 0)
+#define ReadShort(a) bus_space_read_2(2, (a), 0)
+
+/* XXX The arm32 version ignores "slot" too. */
+#define matchpodule(pa, man, prod, slot) IS_PODULE(pa, man, prod)
+
+#define mod_base
+
+/* end arm32 compatibility */
+
+/* End of podulebus.h */
diff --git a/sys/arch/arm26/podulebus/podulebusreg.h b/sys/arch/arm26/podulebus/podulebusreg.h
new file mode 100644
index 00000000000..834293930ef
--- /dev/null
+++ b/sys/arch/arm26/podulebus/podulebusreg.h
@@ -0,0 +1,62 @@
+/* $NetBSD: podulebusreg.h,v 1.1 2000/05/09 21:56:03 bjh21 Exp $ */
+
+/*
+ * 2000 Ben Harris
+ *
+ * This file is in the public domain.
+ */
+
+#ifndef _PODULEBUSREG_H_
+#define _PODULEBUSREG_H_
+
+#define MAX_PODULES 4
+#define PODULE_GAP 0x4000 >> 2
+
+/* Podule identity byte (ECId) flags */
+#define ECID_IRQING 0x01
+#define ECID_NOTPRESENT 0x02
+#define ECID_FIQING 0x04
+#define ECID_ID_MASK 0x78
+#define ECID_ID_SHIFT 3
+#define ECID_ID_EXTEND 0x00
+#define ECID_NONCONF 0x80
+
+/* Extended ECId bytes */
+#define EXTECID_F1 1
+#define EXTECID_F1_CD 0x01
+#define EXTECID_F1_IS 0x02
+#define EXTECID_F1_W_MASK 0xc0
+#define EXTECID_F1_W_8BIT 0x00
+#define EXTECID_F1_W_16BIT 0x40
+#define EXTECID_F1_W_32BIT 0x80
+
+#define EXTECID_PLO 3
+#define EXTECID_PHI 4
+#define EXTECID_MLO 5
+#define EXTECID_MHI 6
+
+#define EXTECID_SIZE 8
+
+/* Extended interrupt pointers */
+#define IRQPTR_SIZE 8
+
+/* Chunk types */
+#define CHUNK_RISCOS_LOADER 0x80
+#define CHUNK_RISCOS_MODULE 0x81
+#define CHUNK_RISCOS_BBCROM 0x82
+#define CHUNK_RISCOS_SPRITE 0x83
+#define CHUNK_OS1_LOADER 0x90
+#define CHUNK_RISCIX_LOADER 0xa0
+#define CHUNK_HELIOS 0xa3
+#define CHUNK_DEV_LINK 0xf0
+#define CHUNK_DEV_SERIAL 0xf1
+#define CHUNK_DEV_DATE 0xf2
+#define CHUNK_DEV_MODS 0xf3
+#define CHUNK_DEV_PLACE 0xf4
+#define CHUNK_DEV_DESCR 0xf5
+#define CHUNK_DEV_PARTNO 0xf6
+#define CHUNK_DEV_EADDR 0xf7
+#define CHUNK_DEV_HWREV 0xf8
+#define CHUNK_DEV_ROMCRC 0xf9
+
+#endif
diff --git a/sys/arch/arm26/podulebus/sbic.c b/sys/arch/arm26/podulebus/sbic.c
new file mode 100644
index 00000000000..05bdbcefa99
--- /dev/null
+++ b/sys/arch/arm26/podulebus/sbic.c
@@ -0,0 +1,3011 @@
+/* $NetBSD: sbic.c,v 1.1 2000/05/09 21:56:03 bjh21 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 UNPROTECTED_CSR
+/*#define SBIC_DEBUG*/
+/*
+ * WD 33C93 scsi adaptor driver
+ */
+
+#include "opt_ddb.h"
+
+#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 <dev/scsipi/scsi_all.h>
+#include <dev/scsipi/scsipi_all.h>
+#include <dev/scsipi/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 <arm26/podulebus/podulebus.h>
+#include <arm26/podulebus/sbicreg.h>
+#include <arm26/podulebus/sbicvar.h>
+#include <arm26/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 SBIC_WAIT(regs, until, timeo) sbicwait(regs, until, timeo, __LINE__)
+
+int sbicicmd __P((struct sbic_softc *, int, int, void *, int, void *, int));
+int sbicgo __P((struct sbic_softc *, struct scsipi_xfer *));
+int sbicdmaok __P((struct sbic_softc *, struct scsipi_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));
+u_int kvtop(void *);
+
+u_int kvtop(void *va) {
+ panic("kvtop not implemented");
+}
+
+/*
+ * 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(dev)
+#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, s;
+/* int csr; */
+/* 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 (%p,%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 (%p,%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 s, count;
+/* int i, asr;*/
+ char* vaddr;
+/* char* 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(%p,%x)pa(%p,%lx)\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 (%p,%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 scsipi_xfer *xs;
+{
+ struct sbic_acb *acb;
+ struct sbic_softc *dev;
+ struct scsipi_link *slp;
+ int flags, s, stat;
+
+ slp = xs->sc_link;
+ dev = slp->adapter_softc;
+ SBIC_TRACE(dev);
+ flags = xs->xs_control;
+
+ if (flags & XS_CTL_DATA_UIO)
+ panic("sbic: scsi data uio requested");
+
+ if (dev->sc_nexus && flags & XS_CTL_POLL)
+ panic("sbic_scsicmd: busy");
+
+ if (slp->scsipi_scsi.target == slp->scsipi_scsi.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->scsipi_scsi.target);
+#ifdef DDB
+ Debugger();
+#endif
+#endif
+ xs->error = XS_DRIVER_STUFFUP;
+ SBIC_TRACE(dev);
+ return(TRY_AGAIN_LATER);
+ }
+
+ acb->flags = ACB_ACTIVE;
+ if (flags & XS_CTL_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 & XS_CTL_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->scsipi_scsi.target;
+ dev->lun = slp->scsipi_scsi.lun;
+ stat = sbicicmd(dev, slp->scsipi_scsi.target, slp->scsipi_scsi.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 XS_CTL_POLL operations */
+#if 0
+ if (flags & XS_CTL_POLL)
+ return(COMPLETE);
+#endif
+ return(SUCCESSFULLY_QUEUED);
+}
+
+/*
+ * attempt to start the next available command
+ */
+void
+sbic_sched(dev)
+ struct sbic_softc *dev;
+{
+ struct scsipi_xfer *xs;
+ struct scsipi_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->scsipi_scsi.target;
+ if (!(dev->sc_tinfo[i].lubusy & (1 << slp->scsipi_scsi.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->scsipi_scsi.target];
+ ti->lubusy |= (1 << slp->scsipi_scsi.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->xs_control;
+
+ if (flags & XS_CTL_RESET)
+ sbicreset(dev);
+
+#ifdef DEBUG
+ if( data_pointer_debug > 1 )
+ printf("sbic_sched(%d,%d)\n",slp->scsipi_scsi.target,slp->scsipi_scsi.lun);
+#endif
+ dev->sc_stat[0] = -1;
+ dev->target = slp->scsipi_scsi.target;
+ dev->lun = slp->scsipi_scsi.lun;
+ if ( flags & XS_CTL_POLL || ( !sbic_parallel_operations
+ && (/*phase == STATUS_PHASE ||*/
+ sbicdmaok(dev, xs) == 0) ) )
+ stat = sbicicmd(dev, slp->scsipi_scsi.target, slp->scsipi_scsi.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 scsipi_xfer *xs;
+ struct scsipi_link *slp;
+ struct sbic_softc *dev;
+/* int s;*/
+ int 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 scsipi_xfer\n",
+ dev->target, dev->lun);
+#ifdef DDB
+ Debugger();
+#endif
+ return;
+ }
+#endif
+ /*
+ * is this right?
+ */
+ xs->status = stat;
+
+#ifdef DEBUG
+ if( data_pointer_debug > 1 )
+ printf("scsidone: (%d,%d)->(%d,%d)%02x\n",
+ slp->scsipi_scsi.target, slp->scsipi_scsi.lun,
+ dev->target, dev->lun, stat);
+ if( xs->sc_link->scsipi_scsi.target == dev->sc_link.scsipi_scsi.adapter_target )
+ panic("target == hostid");
+#endif
+
+ if (xs->error == XS_NOERROR && !(acb->flags & ACB_CHKSENSE)) {
+ if (stat == SCSI_CHECK) {
+ /* Schedule a REQUEST SENSE */
+ struct scsipi_sense *ss = (void *)&acb->cmd;
+#ifdef DEBUG
+ if (report_sense)
+ printf("sbic_scsidone: autosense %02x targ %d lun %d",
+ acb->cmd.opcode, slp->scsipi_scsi.target, slp->scsipi_scsi.lun);
+#endif
+ bzero(ss, sizeof(*ss));
+ ss->opcode = REQUEST_SENSE;
+ ss->byte2 = slp->scsipi_scsi.lun << 5;
+ ss->length = sizeof(struct scsipi_sense_data);
+ acb->clen = sizeof(*ss);
+ acb->sc_kv.dc_addr = (char *)&xs->sense.scsi_sense;
+ acb->sc_kv.dc_count = sizeof(struct scsipi_sense_data);
+#if 0
+ acb->pa_addr = (char *)kvtop(&xs->sense.scsi_sense); /* XXX check */
+#endif
+ acb->flags = ACB_ACTIVE | ACB_CHKSENSE | ACB_DATAIN;
+ bzero(acb->sc_kv.dc_addr, acb->clen);
+ TAILQ_INSERT_HEAD(&dev->ready_list, acb, chain);
+ dev->sc_tinfo[slp->scsipi_scsi.target].lubusy &=
+ ~(1 << slp->scsipi_scsi.lun);
+ dev->sc_tinfo[slp->scsipi_scsi.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)) {
+ QPRINTF(("status = %0x\n", stat));
+ if (xs->sense.scsi_sense.error_code == 0)
+ {
+ struct scsipi_sense *ss = (void *)&acb->cmd;
+
+ QPRINTF(("Retrying sense.\n"));
+ bzero(ss, sizeof(*ss));
+ ss->opcode = REQUEST_SENSE;
+ ss->byte2 = slp->scsipi_scsi.lun << 5;
+ ss->length = sizeof(struct scsipi_sense_data);
+ acb->clen = sizeof(*ss);
+ acb->sc_kv.dc_addr = (char *)&xs->sense.scsi_sense;
+ acb->sc_kv.dc_count = sizeof(struct scsipi_sense_data);
+
+ acb->flags = ACB_ACTIVE | ACB_CHKSENSE | ACB_DATAIN;
+ bzero(acb->sc_kv.dc_addr, acb->clen);
+ TAILQ_INSERT_HEAD(&dev->ready_list, acb, chain);
+ dev->sc_tinfo[slp->scsipi_scsi.target].lubusy &=
+ ~(1 << slp->scsipi_scsi.lun);
+ dev->sc_tinfo[slp->scsipi_scsi.target].senses++;
+ if (dev->sc_nexus == acb) {
+ dev->sc_nexus = NULL;
+ dev->sc_xs = NULL;
+ sbic_sched(dev);
+ }
+ SBIC_TRACE(dev);
+ return;
+ }
+ xs->error = XS_SENSE;
+#ifdef DEBUG
+ if (report_sense)
+ printf(" => %02x %02x %02x\n", xs->sense.scsi_sense.error_code,
+ xs->sense.scsi_sense.flags,
+ xs->sense.scsi_sense.extra_bytes[3]);
+#endif
+ } else {
+ xs->resid = 0; /* XXXX */
+ }
+#if whataboutthisone
+ case SCSI_BUSY:
+ xs->error = XS_BUSY;
+ break;
+#endif
+ xs->xs_status |= XS_STS_DONE;
+
+ /*
+ * 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->scsipi_scsi.target].lubusy &= ~(1<<slp->scsipi_scsi.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->scsipi_scsi.target].lubusy
+ &= ~(1<<slp->scsipi_scsi.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->scsipi_scsi.target].cmds++;
+
+ scsipi_done(xs);
+
+ if (dosched)
+ sbic_sched(dev);
+ SBIC_TRACE(dev);
+}
+
+int
+sbicdmaok(dev, xs)
+ struct sbic_softc *dev;
+ struct scsipi_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->scsipi_scsi.target].bounce)
+ return(1);
+ /*
+ * try to get one
+ */
+ else
+ panic("sbic: cannot do DMA\n");
+#if 0
+ else if (dev->sc_tinfo[xs->sc_link->scsipi_scsi.target].bounce
+ = (char *)alloc_z2mem(MAXPHYS)) {
+ if (isztwomem(dev->sc_tinfo[xs->sc_link->scsipi_scsi.target].bounce))
+ printf("alloc ZII target %d bounce pa 0x%x\n",
+ xs->sc_link->scsipi_scsi.target,
+ kvtop(dev->sc_tinfo[xs->sc_link->scsipi_scsi.target].bounce));
+ else if (dev->sc_tinfo[xs->sc_link->scsipi_scsi.target].bounce)
+ printf("alloc CHIP target %d bounce pa 0x%x\n",
+ xs->sc_link->scsipi_scsi.target,
+ PREP_DMA_MEM(dev->sc_tinfo[xs->sc_link->scsipi_scsi.target].bounce));
+ return(1);
+ }
+#endif
+ 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 i;
+/* u_int my_id, 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);
+ callout_init(&dev->sc_timo_ch);
+ 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 */
+ callout_reset(&dev->sc_timo_ch, 30 * hz,
+ (void *)sbictimeout, dev);
+#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, s;
+/* u_int i;*/
+ 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.scsipi_scsi.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 scsipi_xfer *xs;
+
+ xs = dev->sc_xs;
+
+#ifdef DIAGNOSTIC
+ if (xs == NULL)
+ panic("sbicerror");
+#endif
+ if (xs->xs_control & XS_CTL_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->xs_control & XS_CTL_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, asr, *buf;
+/* u_char csr;*/
+ 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]));
+
+#ifdef UNPROTECTED_CSR
+ GET_SBIC_csr (regs, orig_csr);
+ CSR_TRACE('>',orig_csr,0,0);
+#endif
+
+ /*
+ * 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;
+/* int read;*/
+ u_char *obp, *buf;
+ u_char orig_csr, csr, asr;
+
+ wait = sbic_data_wait;
+ obp = bp;
+ buf = bp;
+
+#ifdef UNPROTECTED_CSR
+ GET_SBIC_csr (regs, orig_csr);
+ CSR_TRACE('<',orig_csr,0,0);
+
+ QPRINTF(("sbicxfin %d, csr=%02x\n", len, orig_csr));
+#endif
+
+ 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;
+ }
+
+#ifdef UNPROTECTED_CSR
+ if( ! asr & SBIC_ASR_BSY ) {
+ GET_SBIC_csr(regs, csr);
+ CSR_TRACE('<',csr,asr,len);
+ QPRINTF(("[CSR%02xASR%02x]", csr, asr));
+ }
+#endif
+
+/* 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;
+/* int 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 scsipi_xfer *xs;
+{
+ int i, dmaflags, count, usedma;
+/* int wait;*/
+/* u_char cmd;*/
+ u_char *addr, asr = 0, csr = 0;
+ sbic_regmap_p regs;
+ struct sbic_acb *acb;
+
+ SBIC_TRACE(dev);
+ dev->target = xs->sc_link->scsipi_scsi.target;
+ dev->lun = xs->sc_link->scsipi_scsi.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 (usedma)
+ panic("sbic: Cannot use DMA\n");
+#if 0
+ 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: (%p->%p,%lx)\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->scsipi_scsi.target].bounce));
+ else if (dev->sc_tinfo[xs->sc_link->scsipi_scsi.target].bounce)
+ printf("alloc CHIP target %d bounce pa 0x%x\n",
+ xs->sc_link->scsipi_scsi.target,
+ PREP_DMA_MEM(dev->sc_tinfo[xs->sc_link->scsipi_scsi.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
+ }
+#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);
+
+#if 0
+ /* XXX - This code was used on the 68040. This is left as a
+ * reminder that consideration needs to be given to this when
+ * DMA support is implemented
+ */
+ /*
+ * push the data cache ( I think this won't work (EH))
+ */
+ if (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(%p:%lx)\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;
+/* u_char *tmpaddr;*/
+/* struct sbic_acb *acb;*/
+ int i;
+/* int 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;*/
+ int 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
+ */
+#if 0
+ if (dev->sc_flags & SBICF_DCFLUSH) {
+ /* XXX - This check was used on the 68040. This is
+ * left as a reminder that consideration needs to
+ * be given to this when DMA support is implemented
+ */
+ }
+#endif
+#ifdef DEBUG
+ if( data_pointer_debug > 1 )
+ printf("next dmastop: %d(%p:%lx)\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 %p->%x\n",
+ dev->sc_dev.dv_xname, acb->sc_usrbufpa,
+ kvtop(acb->sc_dmausrbuf));
+#ifdef DEBUG
+ if(data_pointer_debug)
+ printf("sbicgo:copying %lx 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:
+ {
+ int i = 0;
+
+ if( dev->sc_xs->xs_control & XS_CTL_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(%p:%lx)\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->xs_control & XS_CTL_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->scsipi_scsi.target != newtarget ||
+ acb->xs->sc_link->scsipi_scsi.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 %p\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(%p:%lx)\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
+ */
+#if 0
+ if (dev->sc_flags & SBICF_DCFLUSH) {
+ /* XXX - This check was used on the 68040.
+ * This is left as a reminder that
+ * consideration needs to be given to this
+ * when DMA support is implemented
+ */
+ }
+#endif
+ dev->sc_flags &=
+ ~(SBICF_INDMA | SBICF_DCFLUSH);
+#ifdef DEBUG
+ if( data_pointer_debug > 1 )
+ printf("next dmastop: %d(%p:%lx)\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);
+ callout_reset(&dev->sc_timo_ch, 30 * hz,
+ (void *)sbictimeout, dev);
+}
+
+void
+sbic_dump_acb(acb)
+ struct sbic_acb *acb;
+{
+ u_char *b = (u_char *) &acb->cmd;
+ int i;
+
+ printf("acb@%p ", acb);
+ if (acb->xs == NULL) {
+ printf("<unused>\n");
+ return;
+ }
+ printf("(%d:%d) flags %2x clen %2d cmd ", acb->xs->sc_link->scsipi_scsi.target,
+ acb->xs->sc_link->scsipi_scsi.lun, acb->flags, acb->clen);
+ for (i = acb->clen; i; --i)
+ printf(" %02x", *b++);
+ printf("\n");
+ printf(" xs: %8p data %8p:%04x ", acb->xs, acb->xs->data,
+ acb->xs->datalen);
+ printf("va %8p:%04x ", acb->sc_kv.dc_addr, acb->sc_kv.dc_count);
+ printf("pa %8p:%04x tcnt %lx\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@%p regs %p 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 %p targ %d lun %d flags %x tcnt %lx dmacmd %x mask %lx\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/arm26/podulebus/sbicreg.h b/sys/arch/arm26/podulebus/sbicreg.h
new file mode 100644
index 00000000000..939c2556381
--- /dev/null
+++ b/sys/arch/arm26/podulebus/sbicreg.h
@@ -0,0 +1,426 @@
+/* $NetBSD: sbicreg.h,v 1.1 2000/05/09 21:56:03 bjh21 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/arm26/podulebus/sbicvar.h b/sys/arch/arm26/podulebus/sbicvar.h
new file mode 100644
index 00000000000..3f7d9f3a610
--- /dev/null
+++ b/sys/arch/arm26/podulebus/sbicvar.h
@@ -0,0 +1,236 @@
+/* $NetBSD: sbicvar.h,v 1.1 2000/05/09 21:56:04 bjh21 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>
+#include <sys/callout.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 scsipi_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 callout sc_timo_ch;
+ 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 scsipi_link sc_link; /* proto for sub devices */
+ struct scsipi_adapter sc_adapter;
+ 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 scsipi_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 scsipi_xfer;
+
+void sbic_minphys __P((struct buf *bp));
+int sbic_scsicmd __P((struct scsipi_xfer *));
+void sbicinit __P((struct sbic_softc *dev));
+int sbicintr __P((struct sbic_softc *));
+void sbic_dump __P((struct sbic_softc *dev));
+
+#endif /* _SBICVAR_H_ */
diff --git a/sys/arch/arm26/podulebus/unixbp.c b/sys/arch/arm26/podulebus/unixbp.c
new file mode 100644
index 00000000000..21785ac9bee
--- /dev/null
+++ b/sys/arch/arm26/podulebus/unixbp.c
@@ -0,0 +1,85 @@
+/* $NetBSD: unixbp.c,v 1.1 2000/05/09 21:56:04 bjh21 Exp $ */
+
+/*-
+ * Copyright (c) 2000 Ben Harris
+ * 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.
+ */
+/* This file is part of NetBSD/arm26 -- a port of NetBSD to ARM2/3 machines. */
+/*
+ * unixbp.c - driver for the Unix Backplane, found in the R140 etc
+ */
+
+#include <sys/param.h>
+
+__KERNEL_RCSID(0, "$NetBSD: unixbp.c,v 1.1 2000/05/09 21:56:04 bjh21 Exp $");
+
+#include <sys/device.h>
+#include <sys/systm.h>
+#include <machine/bus.h>
+#include <arch/arm26/iobus/iocvar.h>
+#include <arch/arm26/podulebus/unixbpreg.h>
+
+struct unixbp_softc {
+ struct device sc_dev;
+ bus_space_tag_t sc_iot;
+ bus_space_handle_t sc_ioh;
+};
+
+static int unixbp_match(struct device *, struct cfdata *, void *);
+static void unixbp_attach(struct device *, struct device *, void *);
+
+struct cfattach unixbp_ca = {
+ sizeof(struct unixbp_softc), unixbp_match, unixbp_attach
+};
+
+static int
+unixbp_match(struct device *parent, struct cfdata *cf, void *aux)
+{
+ struct ioc_attach_args *ioc = aux;
+ bus_space_tag_t bst = ioc->ioc_fast_t;
+ bus_space_handle_t bsh = ioc->ioc_fast_h;
+
+ /* Ask to disable all interrupts and check the request lines go low. */
+ bus_space_write_1(bst, bsh, UNIXBP_REG_MASK, 0);
+ if ((bus_space_read_1(bst, bsh, UNIXBP_REG_REQUEST) & 0xf) != 0)
+ return 0;
+ /* Re-enable interrupts. */
+ bus_space_write_1(bst, bsh, UNIXBP_REG_MASK, 0xf);
+ return 1;
+}
+
+static void
+unixbp_attach(struct device *parent, struct device *self, void *aux)
+
+{
+ struct ioc_attach_args *ioc = aux;
+ struct unixbp_softc *sc = (void *)self;
+
+ sc->sc_iot = ioc->ioc_fast_t;
+ sc->sc_ioh = ioc->ioc_fast_h;
+
+ printf(": not yet used\n");
+}
+
diff --git a/sys/arch/arm26/podulebus/unixbpreg.h b/sys/arch/arm26/podulebus/unixbpreg.h
new file mode 100644
index 00000000000..16c077eae13
--- /dev/null
+++ b/sys/arch/arm26/podulebus/unixbpreg.h
@@ -0,0 +1,15 @@
+/* $NetBSD: unixbpreg.h,v 1.1 2000/05/09 21:56:04 bjh21 Exp $ */
+
+/*
+ * This file is in the public domain.
+ */
+
+/* Acorn "Unix Backplane" registers */
+
+#ifndef _UNIXBPREG_H_
+#define _UNIXBPREG_H_
+
+#define UNIXBP_REG_REQUEST 0 /* Enabled _and_ active */
+#define UNIXBP_REG_MASK 1
+
+#endif
diff --git a/sys/arch/arm26/vidc/arcvideo.c b/sys/arch/arm26/vidc/arcvideo.c
new file mode 100644
index 00000000000..c40650116ae
--- /dev/null
+++ b/sys/arch/arm26/vidc/arcvideo.c
@@ -0,0 +1,501 @@
+/* $NetBSD: arcvideo.c,v 1.1 2000/05/09 21:56:04 bjh21 Exp $ */
+/*-
+ * Copyright (c) 1998, 2000 Ben Harris
+ * 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.
+ */
+/* This file is part of NetBSD/arm26 -- a port of NetBSD to ARM2/3 machines. */
+/*
+ * arcvideo.c - Archimedes video system driver.
+ */
+
+/*
+ * The Arc video system is rather closely tied into the heart of the
+ * machine, being partly controlled by the MEMC. Similarly, this
+ * driver will probably end up with its tentacles throughout the
+ * kernel, though in theory it should be posible to leave it out.
+ */
+
+#include <sys/param.h>
+
+__RCSID("$NetBSD: arcvideo.c,v 1.1 2000/05/09 21:56:04 bjh21 Exp $");
+
+#include <sys/device.h>
+#include <sys/errno.h>
+#include <sys/systm.h>
+
+#include <vm/vm.h>
+
+#include <dev/wscons/wsconsio.h>
+#define WSDISPLAY_TYPE_ARCHIMEDES 42 /* XXX Should be in wsconsio.h */
+#include <dev/wscons/wscons_raster.h>
+#include <dev/wscons/wsdisplayvar.h>
+#include <dev/rasops/rasops.h>
+
+#include <machine/boot.h>
+#include <machine/bus.h>
+#include <machine/irq.h>
+#include <machine/memcreg.h>
+#include <machine/spl.h>
+
+#include <arch/arm26/iobus/iocreg.h>
+#include <arch/arm26/iobus/iocvar.h>
+#include <arch/arm26/vidc/vidcreg.h>
+#include <arch/arm26/vidc/arcvideovar.h>
+
+#include "ioc.h"
+
+static int arcvideo_match __P((struct device *parent, struct cfdata *cf,
+ void *aux));
+static void arcvideo_attach __P((struct device *parent, struct device *self,
+ void *aux));
+#if 0
+static int arcvideo_setmode __P((struct device *self,
+ struct arcvideo_mode *mode));
+static void arcvideo_await_vsync __P((struct device *self));
+#endif
+static int arcvideo_intr __P((void *cookie));
+static int arcvideo_ioctl __P((void *cookie, u_long cmd, caddr_t data,
+ int flag, struct proc *p));
+static int arcvideo_mmap __P((void *cookie, off_t off, int prot));
+static int arcvideo_alloc_screen __P((void *cookie,
+ const struct wsscreen_descr *scr,
+ void **scookiep, int *curxp, int *curyp,
+ long *defattrp));
+static void arcvideo_free_screen __P((void *cookie, void *scookie));
+static void arcvideo_show_screen __P((void *cookie, void *scookie, int waitok,
+ void (*cb)(void *, int, int),
+ void *cbarg));
+static int arcvideo_load_font __P((void *cookie, void *scookie,
+ struct wsdisplay_font *));
+static void arccons_8bpp_hack __P((struct rasops_info *ri));
+
+struct arcvideo_softc {
+ struct device sc_dev;
+ paddr_t sc_screenmem_base;
+ struct arcvideo_mode sc_current_mode;
+ u_int32_t sc_vidc_ctl;
+ struct device *sc_ioc;
+ struct irq_handler *sc_irq;
+ int sc_flags;
+#define AV_VIDEO_ON 0x01
+};
+
+struct cfattach arcvideo_ca = {
+ sizeof(struct arcvideo_softc), arcvideo_match, arcvideo_attach
+};
+
+extern struct cfdriver arcvideo_cd;
+#if NIOC > 0
+extern struct cfdriver ioc_cd;
+#endif
+
+static struct rasops_info arccons_ri;
+
+static struct wsscreen_descr arcscreen;
+
+static struct wsdisplay_accessops arcvideo_accessops = {
+ arcvideo_ioctl, arcvideo_mmap, arcvideo_alloc_screen,
+ arcvideo_free_screen, arcvideo_show_screen, arcvideo_load_font
+};
+
+static int arcvideo_isconsole = 0;
+
+static int
+arcvideo_match(parent, cf, aux)
+ struct device *parent;
+ struct cfdata *cf;
+ void *aux;
+{
+
+ /* A system can't sensibly have more than one VIDC. */
+ if (cf->cf_unit == 0)
+ return 1;
+ else
+ return 0;
+}
+
+static void
+arcvideo_attach(parent, self, aux)
+ struct device *parent;
+ struct device *self;
+ void *aux;
+{
+ struct wsemuldisplaydev_attach_args da;
+ struct wsscreen_list scrdata;
+ const struct wsscreen_descr *screenp;
+ struct arcvideo_softc *sc = (void *)self;
+
+ printf(": ");
+
+ if (!arcvideo_isconsole) {
+ printf("Not console -- I can't cope with this!\n");
+ return;
+ }
+
+ sc->sc_flags = AV_VIDEO_ON;
+ /* Detect monitor type? */
+ /* Reset VIDC */
+
+ /* Find IRQ */
+#if NIOC > 0
+ /*
+ * We could probe, but until someone comes up with a machine
+ * that's different from all the others, why bother?
+ */
+ if (ioc_cd.cd_ndevs > 0 && ioc_cd.cd_devs[0] != NULL) {
+ /* ioc0 exists */
+ sc->sc_ioc = ioc_cd.cd_devs[0];
+ sc->sc_irq = ioc_irq_establish(sc->sc_ioc, IOC_IRQ_IR, IPL_TTY,
+ arcvideo_intr, self);
+ printf("VSYNC interrupts at %s", irq_string(sc->sc_irq));
+ } else
+#endif /* NIOC > 0 */
+ printf("no VSYNC sensing");
+
+ printf("\n");
+
+ scrdata.nscreens = 1;
+ scrdata.screens = &screenp;
+ screenp = &arcscreen;
+
+ da.console = arcvideo_isconsole;
+ da.scrdata = &scrdata;
+ da.accessops = &arcvideo_accessops;
+ da.accesscookie = sc;
+
+ config_found(self, &da, wsemuldisplaydevprint);
+}
+
+#if 0
+static int
+arcvideo_setmode(self, mode)
+ struct device *self;
+ struct arcvideo_mode *mode;
+{
+ struct arcvideo_softc *sc = (void *)self;
+ u_int32_t newctl, ctlmask;
+ u_int32_t newhswr, newhbsr, newhdsr, newhder, newhber, newhcr, newhir;
+ u_int32_t newvswr, newvbsr, newvdsr, newvder, newvber, newvcr;
+
+ newctl = 0;
+ /* Dot clock */
+ /* XXX: should this be abstracted a little to allow for
+ variable VIDCLKs? */
+ switch (mode->timings.pixelrate) {
+ case 8000000:
+ newctl |= VIDC_CTL_DOTCLOCK_8MHZ;
+ break;
+ case 12000000:
+ newctl |= VIDC_CTL_DOTCLOCK_12MHZ;
+ break;
+ case 16000000:
+ newctl |= VIDC_CTL_DOTCLOCK_16MHZ;
+ break;
+ case 24000000:
+ newctl |= VIDC_CTL_DOTCLOCK_24MHZ;
+ break;
+ default:
+ return ENXIO;
+ };
+ /* Bits per pixel */
+ switch (mode->bpp) {
+ case 1:
+ newctl |= VIDC_CTL_BPP_ONE;
+ break;
+ case 2:
+ newctl |= VIDC_CTL_BPP_TWO;
+ break;
+ case 4:
+ newctl |= VIDC_CTL_BPP_FOUR;
+ break;
+ case 8:
+ newctl |= VIDC_CTL_BPP_EIGHT;
+ break;
+ default:
+ return EINVAL;
+ }
+ /* DMA timings */
+ /* XXX: should work this out from pixelrate, bpp and MCLK rate. */
+ newctl |= VIDC_CTL_DMARQ_37;
+
+ ctlmask = ~(VIDC_CTL_DOTCLOCK_MASK
+ | VIDC_CTL_BPP_MASK
+ | VIDC_CTL_DMARQ_MASK);
+
+ newhswr = (mode->timings.hsw - 2) / 2 << 14;
+ newhbsr = (mode->timings.hbs - 1) / 2 << 14;
+ switch (mode->bpp) {
+ case 8:
+ newhdsr = (mode->timings.hds - 5) / 2 << 14;
+ newhder = (mode->timings.hde - 5) / 2 << 14;
+ break;
+ case 4:
+ newhdsr = (mode->timings.hds - 7) / 2 << 14;
+ newhder = (mode->timings.hde - 7) / 2 << 14;
+ break;
+ case 2:
+ newhdsr = (mode->timings.hds - 11) / 2 << 14;
+ newhder = (mode->timings.hde - 11) / 2 << 14;
+ break;
+ case 1:
+ newhdsr = (mode->timings.hds - 19) / 2 << 14;
+ newhder = (mode->timings.hde - 19) / 2 << 14;
+ break;
+ }
+ newhber = (mode->timings.hbe - 1) / 2 << 14;
+ newhcr = (mode->timings.hc - 2) / 2 << 14;
+ newhir = mode->timings.hc / 4 << 14;
+ newvswr = (mode->timings.vsw - 1) << 14;
+ newvbsr = (mode->timings.vbs - 1) << 14;
+ newvdsr = (mode->timings.vds - 1) << 14;
+ newvder = (mode->timings.vde - 1) << 14;
+ newvber = (mode->timings.vbe - 1) << 14;
+ newvcr = (mode->timings.vc - 1) << 14;
+ arcvideo_await_vsync(self);
+ spltty(); /* XXX audio? */
+ newctl |= sc->sc_vidc_ctl & ctlmask;
+ VIDC_WRITE(VIDC_CONTROL | newctl);
+ sc->sc_vidc_ctl = newctl;
+ VIDC_WRITE(VIDC_VCR | newvcr);
+ VIDC_WRITE(VIDC_VSWR | newvswr);
+ VIDC_WRITE(VIDC_VBSR | newvbsr);
+ VIDC_WRITE(VIDC_VDSR | newvdsr);
+ VIDC_WRITE(VIDC_VDER | newvder);
+ VIDC_WRITE(VIDC_VBER | newvber);
+ VIDC_WRITE(VIDC_HCR | newhcr);
+ VIDC_WRITE(VIDC_HIR | newhir);
+ VIDC_WRITE(VIDC_HSWR | newhswr);
+ VIDC_WRITE(VIDC_HBSR | newhbsr);
+ VIDC_WRITE(VIDC_HDSR | newhdsr);
+ VIDC_WRITE(VIDC_HDER | newhder);
+ VIDC_WRITE(VIDC_HBER | newhber);
+ return 0;
+}
+
+static void
+arcvideo_await_vsync(self)
+ struct device *self;
+{
+
+ panic("arcvideo_await_vsync not implemented");
+}
+#endif
+
+static int
+arcvideo_intr(cookie)
+ void *cookie;
+{
+/* struct arcvideo_softc *sc = cookie; */
+
+ return IRQ_HANDLED;
+}
+
+/*
+ * In the standard RISC OS 8-bit palette (which we use), the bits go
+ * BGgRbrTt, feeding RrTt, GgTt and BbTt to the DACs. The top four of
+ * these bits are fixed in hardware.
+ *
+ * The following table is the closest match I can get to the colours
+ * at the top of rasops.c.
+ */
+
+static u_int8_t rasops_cmap_8bpp[] = {
+ 0x00, 0x10, 0x40, 0x50, 0x80, 0x90, 0xc0, 0xfc,
+ 0xd0, 0x17, 0x63, 0x77, 0x8b, 0x9f, 0xeb, 0xff,
+};
+
+void
+arccons_init()
+{
+ long defattr;
+ int clear = 0;
+ int crow;
+ struct rasops_info *ri = &arccons_ri;
+
+ /* Force the screen to be at a known location */
+ if (bootconfig.screenbase != 0)
+ clear = 1;
+ MEMC_WRITE(MEMC_SET_PTR(MEMC_VSTART, 0));
+ MEMC_WRITE(MEMC_SET_PTR(MEMC_VINIT, 0));
+ MEMC_WRITE(MEMC_SET_PTR(MEMC_VEND, 0x00080000));
+
+ /* Register video memory with UVM now we know how much we're using. */
+ uvm_page_physload(0, atop(MEMC_DMA_MAX),
+ atop(round_page(bootconfig.screensize)),
+ atop(MEMC_DMA_MAX), VM_FREELIST_LOW);
+
+ /* TODO: We should really set up the VIDC ourselves here. */
+
+ /* Set up arccons_ri */
+ memset(ri, 0, sizeof(*ri));
+ ri->ri_depth = bootconfig.bpp;
+ ri->ri_bits = (u_char *)(MEMC_PHYS_BASE + 0);
+ ri->ri_width = bootconfig.xpixels;
+ ri->ri_height = bootconfig.ypixels;
+ ri->ri_stride = ((bootconfig.xpixels * bootconfig.bpp + 31) >> 5) << 2;
+ ri->ri_flg = RI_CENTER | (clear ? RI_CLEAR : 0);
+
+ if (rasops_init(ri, 1000, 1000) < 0)
+ panic("rasops_init failed");
+
+ if (ri->ri_depth == 8)
+ arccons_8bpp_hack(&arccons_ri);
+
+ /* Take rcons stuff and put it in arcscreen */
+ /* XXX shouldn't this kind of thing be done by rcons_init? */
+ arcscreen.name = "arccons";
+ arcscreen.ncols = ri->ri_cols;
+ arcscreen.nrows = ri->ri_rows;
+ arcscreen.textops = &ri->ri_ops;
+ arcscreen.fontwidth = ri->ri_font->fontwidth;
+ arcscreen.fontheight = ri->ri_font->fontheight;
+ arcscreen.capabilities = ri->ri_caps;
+
+ /* work out cursor row */
+ if (clear)
+ crow = 0;
+ else
+ /* +/-1 is to round up */
+ crow = (bootconfig.cpixelrow - ri->ri_yorigin - 1) /
+ ri->ri_font->fontheight + 1;
+ if (crow < 0) crow = 0;
+ if (crow > ri->ri_rows) crow = ri->ri_rows;
+
+ if ((arccons_ri.ri_ops.alloc_attr)(&arccons_ri, 0, 0, 0, &defattr) !=
+ 0)
+ panic("alloc_attr failed");
+ wsdisplay_cnattach(&arcscreen, &arccons_ri, 0, crow, defattr);
+
+ /* That should be all */
+ arcvideo_isconsole = 1;
+}
+
+/*
+ * The following is a gross hack because the rasops code has no way
+ * for us to specify the devcmap if we don't want the default. I think
+ * it assumes that all 8-bit displays are PseudoColor.
+ */
+
+static void
+arccons_8bpp_hack(ri)
+ struct rasops_info *ri;
+{
+ int i, c;
+
+ for (i = 0; i < 16; i++) {
+ c = rasops_cmap_8bpp[i];
+ ri->ri_devcmap[i] = c | (c<<8) | (c<<16) | (c<<24);
+ }
+}
+
+
+/* wsdisplay access functions */
+
+static int
+arcvideo_ioctl(cookie, cmd, data, flag, p)
+ void *cookie;
+ u_long cmd;
+ caddr_t data;
+ int flag;
+ struct proc *p;
+{
+ struct arcvideo_softc *sc = cookie;
+
+ switch (cmd) {
+ case WSDISPLAYIO_GTYPE:
+ *(u_int *)data = WSDISPLAY_TYPE_ARCHIMEDES;
+ return 0;
+ case WSDISPLAYIO_GVIDEO:
+ if (sc->sc_flags & AV_VIDEO_ON)
+ *(u_int *)data = WSDISPLAYIO_VIDEO_ON;
+ else
+ *(u_int *)data = WSDISPLAYIO_VIDEO_OFF;
+ return 0;
+ case WSDISPLAYIO_SVIDEO:
+ switch (*(u_int *)data) {
+ case WSDISPLAYIO_VIDEO_OFF:
+ sc->sc_flags &= ~AV_VIDEO_ON;
+ update_memc(MEMC_CTL_VIDEODMA | MEMC_CTL_RFRSH_MASK,
+ MEMC_CTL_RFRSH_CONTIN);
+ return 0;
+ case WSDISPLAYIO_VIDEO_ON:
+ sc->sc_flags |= AV_VIDEO_ON;
+ update_memc(MEMC_CTL_VIDEODMA | MEMC_CTL_RFRSH_MASK,
+ MEMC_CTL_VIDEODMA |
+ MEMC_CTL_RFRSH_FLYBACK);
+ return 0;
+ }
+ }
+ return -1;
+}
+
+static int
+arcvideo_mmap(cookie, off, prot)
+ void *cookie;
+ off_t off;
+ int prot;
+{
+
+ return ENODEV;
+}
+
+static int
+arcvideo_alloc_screen(cookie, scr, scookiep, curxp, curyp, defattrp)
+ void *cookie, **scookiep;
+ const struct wsscreen_descr *scr;
+ int *curxp, *curyp;
+ long *defattrp;
+{
+
+ return ENODEV;
+}
+
+static void
+arcvideo_free_screen(cookie, scookie)
+ void *cookie, *scookie;
+{
+
+ panic("arcvideo_free_screen not implemented");
+}
+
+static void
+arcvideo_show_screen(cookie, scookie, waitok, cb, cbarg)
+ void *cookie, *scookie;
+ int waitok;
+ void (*cb) __P((void *cbarg, int error, int waitok));
+ void *cbarg;
+{
+
+ panic("arcvideo_show_screen not implemented");
+}
+
+static int
+arcvideo_load_font(cookie, emulcookie, font)
+ void *cookie, *emulcookie;
+ struct wsdisplay_font *font;
+{
+
+ return ENODEV;
+}
diff --git a/sys/arch/arm26/vidc/arcvideovar.h b/sys/arch/arm26/vidc/arcvideovar.h
new file mode 100644
index 00000000000..f970a08dfa2
--- /dev/null
+++ b/sys/arch/arm26/vidc/arcvideovar.h
@@ -0,0 +1,47 @@
+/* $NetBSD: arcvideovar.h,v 1.1 2000/05/09 21:56:04 bjh21 Exp $ */
+/*-
+ * Copyright (c) 1998 Ben Harris
+ * 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.
+ */
+/* This file is part of NetBSD/arm26 -- a port of NetBSD to ARM2/3 machines. */
+
+#ifndef _ARM26_ARCVIDEOVAR_H
+#define _ARM26_ARCVIDEOVAR_H
+
+struct arcvideo_timings {
+ int pixelrate; /* in Hz */
+ int hsw, hbs, hds, hde, hbe, hc; /* In pixels */
+ int vsw, vbs, vds, vde, vbe, vc; /* In rasters */
+};
+
+struct arcvideo_mode {
+ struct arcvideo_timings timings;
+ int bpp;
+ int sync_pol;
+};
+
+extern void arccons_init __P((void));
+
+#endif
diff --git a/sys/arch/arm26/vidc/vidcreg.h b/sys/arch/arm26/vidc/vidcreg.h
new file mode 100644
index 00000000000..7b7bb7a74c7
--- /dev/null
+++ b/sys/arch/arm26/vidc/vidcreg.h
@@ -0,0 +1,131 @@
+/* $NetBSD: vidcreg.h,v 1.1 2000/05/09 21:56:04 bjh21 Exp $ */
+/*-
+ * Copyright (c) 1998 Ben Harris
+ * 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.
+ */
+/* This file is part of NetBSD/arm26 -- a port of NetBSD to ARM2/3 machines. */
+/*
+ * vidcreg.h - Acorn/ARM VIDC (Arabella) registers
+ */
+
+#ifndef _ARM26_VIDCREG_H
+#define _ARM26_VIDCREG_H
+
+/*
+ * The VIDC is accessed by writing words to addresses starting at
+ * MEMC_VIDC_BASE definied in memcreg.h.
+ *
+ * As with the MEMC, the value is the logical OR of the register
+ * specifier and the new value.
+ */
+
+/* Palette entries */
+
+#define VIDC_PALETTE 0x00000000
+#define VIDC_PALETTE_LCOL(n) (n << 26)
+#define VIDC_PALETTE_BCOL 0x40000000
+#define VIDC_PALETTE_CCOL(n) (0x40000000 + (n << 26))
+
+#define VIDC_PALETTE_ENTRY(r, g, b, s) ((s != 0) << 12 | b << 8 | g << 4 | r)
+
+/* Stereo image registers */
+/* They're in the order 70123456 */
+#define VIDC_SIR(n) (0x60000000 + ((n + 1) % 8 << 26))
+#define VIDC_STEREO_L100 1
+#define VIDC_STEREO_L83 2
+#define VIDC_STEREO_L67 3
+#define VIDC_STEREO_C 4
+#define VIDC_STEREO_R67 5
+#define VIDC_STEREO_R83 6
+#define VIDC_STEREO_R100 7
+
+/* Video timing register */
+#define VIDC_HCR 0x80000000
+#define VIDC_HSWR 0x84000000
+#define VIDC_HBSR 0x88000000
+#define VIDC_HDSR 0x8c000000
+#define VIDC_HDER 0x90000000
+#define VIDC_HBER 0x94000000
+#define VIDC_HCSR 0x98000000
+#define VIDC_HIR 0x9c000000
+
+#define VIDC_VCR 0xa0000000
+#define VIDC_VSWR 0xa4000000
+#define VIDC_VBSR 0xa8000000
+#define VIDC_VDSR 0xac000000
+#define VIDC_VDER 0xb0000000
+#define VIDC_VBER 0xb4000000
+#define VIDC_VCSR 0xb8000000
+#define VIDC_VCER 0xbc000000
+
+/*
+ * Horizontal timings have units of two pixels (except HCSR).
+ * Vertical timings have units of a raster. Most have to have one or
+ * two subtracted from them.
+ */
+#define VIDC_VIDTIMING(x) (x << 14)
+#define VIDC_HCS(x) (x << 13)
+#define VIDC_HCS_HIRES(x) (x << 11)
+
+/* Sound frequency register */
+#define VIDC_SFR 0xc0000000
+/* Units are us */
+#define VIDC_SF(x) (x & 0x100)
+
+/* Control register */
+#define VIDC_CONTROL 0xe0000000
+
+#define VIDC_CTL_DOTCLOCK_MASK 0x00000003
+#define VIDC_CTL_DOTCLOCK_8MHZ 0x00000000
+#define VIDC_CTL_DOTCLOCK_12MHZ 0x00000001
+#define VIDC_CTL_DOTCLOCK_16MHZ 0x00000002
+#define VIDC_CTL_DOTCLOCK_24MHZ 0x00000003
+
+#define VIDC_CTL_BPP_MASK 0x0000000c
+#define VIDC_CTL_BPP_ONE 0x00000000
+#define VIDC_CTL_BPP_TWO 0x00000004
+#define VIDC_CTL_BPP_FOUR 0x00000008
+#define VIDC_CTL_BPP_EIGHT 0x0000000c
+
+#define VIDC_CTL_DMARQ_MASK 0x00000030
+#define VIDC_CTL_DMARQ_04 0x00000000
+#define VIDC_CTL_DMARQ_15 0x00000010
+#define VIDC_CTL_DMARQ_26 0x00000020
+#define VIDC_CTL_DMARQ_37 0x00000030
+
+#define VIDC_CTL_INTERLACE 0x00000040
+
+#define VIDC_CTL_CSYNC 0x00000080
+
+#define VIDC_CTL_TEST_MASK 0x0000c100
+#define VIDC_CTL_TEST_OFF 0x00000000
+#define VIDC_CTL_TEST_MODE0 0x00004000
+#define VIDC_CTL_TEST_MODE1 0x00008000
+#define VIDC_CTL_TEST_MODE2 0x0000c000
+#define VIDC_CTL_TEST_MODE3 0x00000100
+
+#define VIDC_WRITE(value) *(volatile u_int32_t *)MEMC_VIDC_BASE = value
+
+#endif
diff --git a/sys/arch/arm26/vidc/vidmodes.c b/sys/arch/arm26/vidc/vidmodes.c
new file mode 100644
index 00000000000..99e8edfcb13
--- /dev/null
+++ b/sys/arch/arm26/vidc/vidmodes.c
@@ -0,0 +1,48 @@
+/*
+ * XFree86 modes are:
+ * Modeline "name" dotclock hdisp hsyncstart hsyncend htotal \
+ * vdisp vsyncstart vsyncend vtotal flags
+ *
+ * hswr = hsyncend - hsyncstart
+ * hdsr = htotal - hsyncstart
+ * hder = hdsr + hdisp
+ * hcr = htotal
+ * Same for vertical. XFree doesn't do borders.
+ */
+
+/* RISC OS Mode 0 etc (I think) 640x256 @ 50Hz, 15.6kHz hsync */
+struct arcvideo_timings timing_std640x256 = {
+ 16000000,
+ 72, 217, 265, 905, 953, 1024,
+ 3, 21, 39, 295, 312, 312
+};
+
+/*
+ * # 640x400 @ 70 Hz, 31.5 kHz hsync
+ * Modeline "640x400" 25.175 640 664 760 800 400 409 411 450
+ */
+struct arcvideo_timings timing_vga640x400 = {
+ 25175000,
+ 96, 136, 136, 776, 776, 800,
+ 2, 41, 41, 441, 441, 450
+};
+
+/*
+ * # 640x480 @ 60 Hz, 31.5 kHz hsync
+ * Modeline "640x480" 25.175 640 664 760 800 480 491 493 525
+ */
+struct arcvideo_timings timing_vga640x480 = {
+ 25175000,
+ 96, 136, 136, 776, 776, 800,
+ 2, 34, 34, 514, 514, 525
+};
+
+/*
+ * # 800x600 @ 56 Hz, 35.15 kHz hsync
+ * ModeLine "800x600" 36 800 824 896 1024 600 601 603 625
+ */
+struct arcvideo_timings timing_svga800x600 = {
+ 36000000,
+ 72, 200, 200, 1000, 1000, 1024,
+ 2, 24, 24, 624, 624, 625
+};
diff --git a/sys/arch/arm32/podulebus/podule_data.h b/sys/arch/arm32/podulebus/podule_data.h
index e37a471a05b..4c3106a8bd1 100644
--- a/sys/arch/arm32/podulebus/podule_data.h
+++ b/sys/arch/arm32/podulebus/podule_data.h
@@ -1,4 +1,4 @@
-/* $NetBSD: podule_data.h,v 1.13 1999/11/12 07:38:51 mark Exp $ */
+/* $NetBSD: podule_data.h,v 1.14 2000/05/09 21:56:04 bjh21 Exp $ */
/*
* THIS FILE AUTOMATICALLY GENERATED. DO NOT EDIT.
@@ -178,6 +178,11 @@ static struct podule_description podules_castle[] = {
{ 0x0000, NULL }
};
+static struct podule_description podules_dtsoft[] = {
+ { PODULE_DTSOFT_IDE, "IDE interface" },
+ { 0x0000, NULL }
+};
+
static struct podule_description podules_alsystems[] = {
{ PODULE_ALSYSTEMS_SCSI, "SCSI II host adapter" },
{ 0x0000, NULL }
@@ -228,6 +233,7 @@ struct podule_list known_podules[] = {
{ MANUFACTURER_BRINI, "Brini", podules_brini },
{ MANUFACTURER_ANT, "ANT", podules_ant },
{ MANUFACTURER_CASTLE, "Castle Technology", podules_castle },
+ { MANUFACTURER_DTSOFT, "D.T. Software", podules_dtsoft },
{ MANUFACTURER_ALSYSTEMS, "Alsystems", podules_alsystems },
{ MANUFACTURER_SIMTEC, "Simtec Electronics", podules_simtec },
{ MANUFACTURER_YES, "Yellowstone Educational Solutions", podules_yes },
diff --git a/sys/arch/arm32/podulebus/podules b/sys/arch/arm32/podulebus/podules
index 15598de0b2e..cd2f00a6657 100644
--- a/sys/arch/arm32/podulebus/podules
+++ b/sys/arch/arm32/podulebus/podules
@@ -1,4 +1,4 @@
-$NetBSD: podules,v 1.10 1999/11/12 07:37:21 mark Exp $
+$NetBSD: podules,v 1.11 2000/05/09 21:56:04 bjh21 Exp $
/*
* Copyright (c) 1996 Mark Brinicombe
@@ -57,6 +57,7 @@ manufacturer ICUBED 0x0046 I-Cubed
manufacturer BRINI 0x0050 Brini
manufacturer ANT 0x0053 ANT
manufacturer CASTLE 0x0055 Castle Technology
+manufacturer DTSOFT 0x0037 D.T. Software
manufacturer ALSYSTEMS 0x005b Alsystems
manufacturer SIMTEC 0x005f Simtec Electronics
manufacturer YES 0x0060 Yellowstone Educational Solutions
@@ -105,6 +106,8 @@ podule MORLEY SCSI 0x0067 SCSI interface
podule VTI SCSI 0x008d SCSI interface
+podule DTSOFT IDE 0x00ae IDE interface
+
podule CUMANA SCSI2 0x003a SCSI II interface
podule CUMANA SCSI1 0x00a0 SCSI I interface
podule CUMANA SLCD 0x00dd CDFS & SLCD expansion card
diff --git a/sys/arch/arm32/podulebus/podules.h b/sys/arch/arm32/podulebus/podules.h
index 0a7ba9c695c..18a22fec6ac 100644
--- a/sys/arch/arm32/podulebus/podules.h
+++ b/sys/arch/arm32/podulebus/podules.h
@@ -1,4 +1,4 @@
-/* $NetBSD: podules.h,v 1.13 1999/11/12 07:38:51 mark Exp $ */
+/* $NetBSD: podules.h,v 1.14 2000/05/09 21:56:04 bjh21 Exp $ */
/*
* THIS FILE AUTOMATICALLY GENERATED. DO NOT EDIT.
@@ -64,6 +64,7 @@
#define MANUFACTURER_BRINI 0x0050 /* Brini */
#define MANUFACTURER_ANT 0x0053 /* ANT */
#define MANUFACTURER_CASTLE 0x0055 /* Castle Technology */
+#define MANUFACTURER_DTSOFT 0x0037 /* D.T. Software */
#define MANUFACTURER_ALSYSTEMS 0x005b /* Alsystems */
#define MANUFACTURER_SIMTEC 0x005f /* Simtec Electronics */
#define MANUFACTURER_YES 0x0060 /* Yellowstone Educational Solutions */
@@ -112,6 +113,8 @@
#define PODULE_VTI_SCSI 0x008d /* SCSI interface */
+#define PODULE_DTSOFT_IDE 0x00ae /* IDE interface */
+
#define PODULE_CUMANA_SCSI2 0x003a /* SCSI II interface */
#define PODULE_CUMANA_SCSI1 0x00a0 /* SCSI I interface */
#define PODULE_CUMANA_SLCD 0x00dd /* CDFS & SLCD expansion card */
diff --git a/sys/lib/libkern/arch/arm26/Makefile.inc b/sys/lib/libkern/arch/arm26/Makefile.inc
new file mode 100644
index 00000000000..0bb37876769
--- /dev/null
+++ b/sys/lib/libkern/arch/arm26/Makefile.inc
@@ -0,0 +1,9 @@
+# $NetBSD: Makefile.inc,v 1.1 2000/05/09 21:56:05 bjh21 Exp $
+
+SRCS+= __main.c imax.c imin.c lmax.c lmin.c max.c min.c ulmax.c ulmin.c \
+ byte_swap_2.S byte_swap_4.S bswap64.c bcmp.c ffs.c strcat.c strcmp.c \
+ strcpy.c strlen.c strncmp.c strncpy.c scanc.c skpc.c random.c \
+ strncasecmp.c __assert.c
+SRCS+= divsi3.S
+SRCS+= memchr.c memcmp.c _memcpy.S memcpy.S memmove.S memset.S
+SRCS+= bcopy.S bzero.S
diff --git a/sys/lib/libkern/arch/arm26/_memcpy.S b/sys/lib/libkern/arch/arm26/_memcpy.S
new file mode 100644
index 00000000000..d217837947c
--- /dev/null
+++ b/sys/lib/libkern/arch/arm26/_memcpy.S
@@ -0,0 +1,463 @@
+/* $Id: _memcpy.S,v 1.1 2000/05/09 21:56:05 bjh21 Exp $ */
+/* $NetBSD: _memcpy.S,v 1.1 2000/05/09 21:56:05 bjh21 Exp $ */
+
+/*
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Neil A. Carson and Mark Brinicombe
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. 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 FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (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 <machine/asm.h>
+
+/*
+ * This is one fun bit of code ...
+ * Some easy listening music is suggested while trying to understand this
+ * code e.g. Iron Maiden
+ *
+ * For anyone attempting to understand it :
+ *
+ * The core code is implemented here with simple stubs for memcpy()
+ * memmove() and bcopy().
+ *
+ * All local labels are prefixed with Lmemcpy_
+ * Following the prefix a label starting f is used in the forward copy code
+ * while a label using b is used in the backwards copy code
+ * The source and destination addresses determine whether a forward or
+ * backward copy is performed.
+ * Separate bits of code are used to deal with the following situations
+ * for both the forward and backwards copy.
+ * unaligned source address
+ * unaligned destination address
+ * Separate copy routines are used to produce an optimised result for each
+ * of these cases.
+ * The copy code will use LDM/STM instructions to copy up to 32 bytes at
+ * a time where possible.
+ *
+ * Note: r12 (aka ip) can be trashed during the function along with
+ * r0-r3 although r0-r2 have defined uses i.e. src, dest, len through out.
+ * Additional registers are preserved prior to use i.e. r4, r5 & lr
+ *
+ * Apologies for the state of the comments ;-)
+ */
+
+ENTRY(_memcpy)
+ /* Determine copy direction */
+ cmp r1, r0
+ bcc Lmemcpy_backwards
+
+ moveq r0, #0 /* Quick abort for len=0 */
+#ifdef __APCS_26__
+ moveqs pc, lr
+#else
+ moveq pc, lr
+#endif
+
+ stmdb sp!, {r0, lr} /* memcpy() returns dest addr */
+ subs r2, r2, #4
+ blt Lmemcpy_fl4 /* less than 4 bytes */
+ ands r12, r0, #3
+ bne Lmemcpy_fdestul /* oh unaligned destination addr */
+ ands r12, r1, #3
+ bne Lmemcpy_fsrcul /* oh unaligned source addr */
+
+Lmemcpy_ft8:
+ /* We have aligned source and destination */
+ subs r2, r2, #8
+ blt Lmemcpy_fl12 /* less than 12 bytes (4 from above) */
+ subs r2, r2, #0x14
+ blt Lmemcpy_fl32 /* less than 32 bytes (12 from above) */
+ stmdb sp!, {r4} /* borrow r4 */
+
+ /* blat 32 bytes at a time */
+ /* XXX for really big copies perhaps we should use more registers */
+Lmemcpy_floop32:
+ ldmia r1!, {r3, r4, r12, lr}
+ stmia r0!, {r3, r4, r12, lr}
+ ldmia r1!, {r3, r4, r12, lr}
+ stmia r0!, {r3, r4, r12, lr}
+ subs r2, r2, #0x20
+ bge Lmemcpy_floop32
+
+ cmn r2, #0x10
+ ldmgeia r1!, {r3, r4, r12, lr} /* blat a remaining 16 bytes */
+ stmgeia r0!, {r3, r4, r12, lr}
+ subge r2, r2, #0x10
+ ldmia sp!, {r4} /* return r4 */
+
+Lmemcpy_fl32:
+ adds r2, r2, #0x14
+
+ /* blat 12 bytes at a time */
+Lmemcpy_floop12:
+ ldmgeia r1!, {r3, r12, lr}
+ stmgeia r0!, {r3, r12, lr}
+ subges r2, r2, #0x0c
+ bge Lmemcpy_floop12
+
+Lmemcpy_fl12:
+ adds r2, r2, #8
+ blt Lmemcpy_fl4
+
+ subs r2, r2, #4
+ ldrlt r3, [r1], #4
+ strlt r3, [r0], #4
+ ldmgeia r1!, {r3, r12}
+ stmgeia r0!, {r3, r12}
+ subge r2, r2, #4
+
+Lmemcpy_fl4:
+ /* less than 4 bytes to go */
+ adds r2, r2, #4
+ ldmeqia sp!, {r0, pc} /* done */
+
+ /* copy the crud byte at a time */
+ cmp r2, #2
+ ldrb r3, [r1], #1
+ strb r3, [r0], #1
+ ldrgeb r3, [r1], #1
+ strgeb r3, [r0], #1
+ ldrgtb r3, [r1], #1
+ strgtb r3, [r0], #1
+#ifdef __APCS_26__
+ ldmia sp!, {r0, pc}^
+#else
+ ldmia sp!, {r0, pc}
+#endif
+
+ /* erg - unaligned destination */
+Lmemcpy_fdestul:
+ rsb r12, r12, #4
+ cmp r12, #2
+
+ /* align destination with byte copies */
+ ldrb r3, [r1], #1
+ strb r3, [r0], #1
+ ldrgeb r3, [r1], #1
+ strgeb r3, [r0], #1
+ ldrgtb r3, [r1], #1
+ strgtb r3, [r0], #1
+ subs r2, r2, r12
+ blt Lmemcpy_fl4 /* less the 4 bytes */
+
+ ands r12, r1, #3
+ beq Lmemcpy_ft8 /* we have an aligned source */
+
+ /* erg - unaligned source */
+ /* This is where it gets nasty ... */
+Lmemcpy_fsrcul:
+ bic r1, r1, #3
+ ldr lr, [r1], #4
+ cmp r12, #2
+ bgt Lmemcpy_fsrcul3
+ beq Lmemcpy_fsrcul2
+ cmp r2, #0x0c
+ blt Lmemcpy_fsrcul1loop4
+ sub r2, r2, #0x0c
+ stmdb sp!, {r4, r5}
+
+Lmemcpy_fsrcul1loop16:
+ mov r3, lr, lsr #8
+ ldmia r1!, {r4, r5, r12, lr}
+ orr r3, r3, r4, lsl #24
+ mov r4, r4, lsr #8
+ orr r4, r4, r5, lsl #24
+ mov r5, r5, lsr #8
+ orr r5, r5, r12, lsl #24
+ mov r12, r12, lsr #8
+ orr r12, r12, lr, lsl #24
+ stmia r0!, {r3-r5, r12}
+ subs r2, r2, #0x10
+ bge Lmemcpy_fsrcul1loop16
+ ldmia sp!, {r4, r5}
+ adds r2, r2, #0x0c
+ blt Lmemcpy_fsrcul1l4
+
+Lmemcpy_fsrcul1loop4:
+ mov r12, lr, lsr #8
+ ldr lr, [r1], #4
+ orr r12, r12, lr, lsl #24
+ str r12, [r0], #4
+ subs r2, r2, #4
+ bge Lmemcpy_fsrcul1loop4
+
+Lmemcpy_fsrcul1l4:
+ sub r1, r1, #3
+ b Lmemcpy_fl4
+
+Lmemcpy_fsrcul2:
+ cmp r2, #0x0c
+ blt Lmemcpy_fsrcul2loop4
+ sub r2, r2, #0x0c
+ stmdb sp!, {r4, r5}
+
+Lmemcpy_fsrcul2loop16:
+ mov r3, lr, lsr #16
+ ldmia r1!, {r4, r5, r12, lr}
+ orr r3, r3, r4, lsl #16
+ mov r4, r4, lsr #16
+ orr r4, r4, r5, lsl #16
+ mov r5, r5, lsr #16
+ orr r5, r5, r12, lsl #16
+ mov r12, r12, lsr #16
+ orr r12, r12, lr, lsl #16
+ stmia r0!, {r3-r5, r12}
+ subs r2, r2, #0x10
+ bge Lmemcpy_fsrcul2loop16
+ ldmia sp!, {r4, r5}
+ adds r2, r2, #0x0c
+ blt Lmemcpy_fsrcul2l4
+
+Lmemcpy_fsrcul2loop4:
+ mov r12, lr, lsr #16
+ ldr lr, [r1], #4
+ orr r12, r12, lr, lsl #16
+ str r12, [r0], #4
+ subs r2, r2, #4
+ bge Lmemcpy_fsrcul2loop4
+
+Lmemcpy_fsrcul2l4:
+ sub r1, r1, #2
+ b Lmemcpy_fl4
+
+Lmemcpy_fsrcul3:
+ cmp r2, #0x0c
+ blt Lmemcpy_fsrcul3loop4
+ sub r2, r2, #0x0c
+ stmdb sp!, {r4, r5}
+
+Lmemcpy_fsrcul3loop16:
+ mov r3, lr, lsr #24
+ ldmia r1!, {r4, r5, r12, lr}
+ orr r3, r3, r4, lsl #8
+ mov r4, r4, lsr #24
+ orr r4, r4, r5, lsl #8
+ mov r5, r5, lsr #24
+ orr r5, r5, r12, lsl #8
+ mov r12, r12, lsr #24
+ orr r12, r12, lr, lsl #8
+ stmia r0!, {r3-r5, r12}
+ subs r2, r2, #0x10
+ bge Lmemcpy_fsrcul3loop16
+ ldmia sp!, {r4, r5}
+ adds r2, r2, #0x0c
+ blt Lmemcpy_fsrcul3l4
+
+Lmemcpy_fsrcul3loop4:
+ mov r12, lr, lsr #24
+ ldr lr, [r1], #4
+ orr r12, r12, lr, lsl #8
+ str r12, [r0], #4
+ subs r2, r2, #4
+ bge Lmemcpy_fsrcul3loop4
+
+Lmemcpy_fsrcul3l4:
+ sub r1, r1, #1
+ b Lmemcpy_fl4
+
+Lmemcpy_backwards:
+ add r1, r1, r2
+ add r0, r0, r2
+ subs r2, r2, #4
+ blt Lmemcpy_bl4 /* less than 4 bytes */
+ ands r12, r0, #3
+ bne Lmemcpy_bdestul /* oh unaligned destination addr */
+ ands r12, r1, #3
+ bne Lmemcpy_bsrcul /* oh unaligned source addr */
+
+Lmemcpy_bt8:
+ /* We have aligned source and destination */
+ subs r2, r2, #8
+ blt Lmemcpy_bl12 /* less than 12 bytes (4 from above) */
+ stmdb sp!, {r4, lr}
+ subs r2, r2, #0x14 /* less than 32 bytes (12 from above) */
+ blt Lmemcpy_bl32
+
+ /* blat 32 bytes at a time */
+ /* XXX for really big copies perhaps we should use more registers */
+Lmemcpy_bloop32:
+ ldmdb r1!, {r3, r4, r12, lr}
+ stmdb r0!, {r3, r4, r12, lr}
+ ldmdb r1!, {r3, r4, r12, lr}
+ stmdb r0!, {r3, r4, r12, lr}
+ subs r2, r2, #0x20
+ bge Lmemcpy_bloop32
+
+Lmemcpy_bl32:
+ cmn r2, #0x10
+ ldmgedb r1!, {r3, r4, r12, lr} /* blat a remaining 16 bytes */
+ stmgedb r0!, {r3, r4, r12, lr}
+ subge r2, r2, #0x10
+ adds r2, r2, #0x14
+ ldmgedb r1!, {r3, r12, lr} /* blat a remaining 12 bytes */
+ stmgedb r0!, {r3, r12, lr}
+ subge r2, r2, #0x0c
+ ldmia sp!, {r4, lr}
+
+Lmemcpy_bl12:
+ adds r2, r2, #8
+ blt Lmemcpy_bl4
+ subs r2, r2, #4
+ ldrlt r3, [r1, #-4]!
+ strlt r3, [r0, #-4]!
+ ldmgedb r1!, {r3, r12}
+ stmgedb r0!, {r3, r12}
+ subge r2, r2, #4
+
+Lmemcpy_bl4:
+ /* less than 4 bytes to go */
+ adds r2, r2, #4
+ moveq pc, lr /* done */
+
+ /* copy the crud byte at a time */
+ cmp r2, #2
+ ldrb r3, [r1, #-1]!
+ strb r3, [r0, #-1]!
+ ldrgeb r3, [r1, #-1]!
+ strgeb r3, [r0, #-1]!
+ ldrgtb r3, [r1, #-1]!
+ strgtb r3, [r0, #-1]!
+#ifdef __APCS_26__
+ movs pc, lr
+#else
+ mov pc, lr
+#endif
+
+ /* erg - unaligned destination */
+Lmemcpy_bdestul:
+ cmp r12, #2
+
+ /* align destination with byte copies */
+ ldrb r3, [r1, #-1]!
+ strb r3, [r0, #-1]!
+ ldrgeb r3, [r1, #-1]!
+ strgeb r3, [r0, #-1]!
+ ldrgtb r3, [r1, #-1]!
+ strgtb r3, [r0, #-1]!
+ subs r2, r2, r12
+ blt Lmemcpy_bl4 /* less than 4 bytes to go */
+ ands r12, r1, #3
+ beq Lmemcpy_bt8 /* we have an aligned source */
+
+ /* erg - unaligned source */
+ /* This is where it gets nasty ... */
+Lmemcpy_bsrcul:
+ bic r1, r1, #3
+ ldr r3, [r1, #0]
+ cmp r12, #2
+ blt Lmemcpy_bsrcul1
+ beq Lmemcpy_bsrcul2
+ cmp r2, #0x0c
+ blt Lmemcpy_bsrcul3loop4
+ sub r2, r2, #0x0c
+ stmdb sp!, {r4, r5, lr}
+
+Lmemcpy_bsrcul3loop16:
+ mov lr, r3, lsl #8
+ ldmdb r1!, {r3-r5, r12}
+ orr lr, lr, r12, lsr #24
+ mov r12, r12, lsl #8
+ orr r12, r12, r5, lsr #24
+ mov r5, r5, lsl #8
+ orr r5, r5, r4, lsr #24
+ mov r4, r4, lsl #8
+ orr r4, r4, r3, lsr #24
+ stmdb r0!, {r4, r5, r12, lr}
+ subs r2, r2, #0x10
+ bge Lmemcpy_bsrcul3loop16
+ ldmia sp!, {r4, r5, lr}
+ adds r2, r2, #0x0c
+ blt Lmemcpy_bsrcul3l4
+
+Lmemcpy_bsrcul3loop4:
+ mov r12, r3, lsl #8
+ ldr r3, [r1, #-4]!
+ orr r12, r12, r3, lsr #24
+ str r12, [r0, #-4]!
+ subs r2, r2, #4
+ bge Lmemcpy_bsrcul3loop4
+
+Lmemcpy_bsrcul3l4:
+ add r1, r1, #3
+ b Lmemcpy_bl4
+
+Lmemcpy_bsrcul2:
+ cmp r2, #0x0c
+ blt Lmemcpy_bsrcul2loop4
+ sub r2, r2, #0x0c
+ stmdb sp!, {r4, r5, lr}
+
+Lmemcpy_bsrcul2loop16:
+ mov lr, r3, lsl #16
+ ldmdb r1!, {r3-r5, r12}
+ orr lr, lr, r12, lsr #16
+ mov r12, r12, lsl #16
+ orr r12, r12, r5, lsr #16
+ mov r5, r5, lsl #16
+ orr r5, r5, r4, lsr #16
+ mov r4, r4, lsl #16
+ orr r4, r4, r3, lsr #16
+ stmdb r0!, {r4, r5, r12, lr}
+ subs r2, r2, #0x10
+ bge Lmemcpy_bsrcul2loop16
+ ldmia sp!, {r4, r5, lr}
+ adds r2, r2, #0x0c
+ blt Lmemcpy_bsrcul2l4
+
+Lmemcpy_bsrcul2loop4:
+ mov r12, r3, lsl #16
+ ldr r3, [r1, #-4]!
+ orr r12, r12, r3, lsr #16
+ str r12, [r0, #-4]!
+ subs r2, r2, #4
+ bge Lmemcpy_bsrcul2loop4
+
+Lmemcpy_bsrcul2l4:
+ add r1, r1, #2
+ b Lmemcpy_bl4
+
+Lmemcpy_bsrcul1:
+ cmp r2, #0x0c
+ blt Lmemcpy_bsrcul1loop4
+ sub r2, r2, #0x0c
+ stmdb sp!, {r4, r5, lr}
+
+Lmemcpy_bsrcul1loop32:
+ mov lr, r3, lsl #24
+ ldmdb r1!, {r3-r5, r12}
+ orr lr, lr, r12, lsr #8
+ mov r12, r12, lsl #24
+ orr r12, r12, r5, lsr #8
+ mov r5, r5, lsl #24
+ orr r5, r5, r4, lsr #8
+ mov r4, r4, lsl #24
+ orr r4, r4, r3, lsr #8
+ stmdb r0!, {r4, r5, r12, lr}
+ subs r2, r2, #0x10
+ bge Lmemcpy_bsrcul1loop32
+ ldmia sp!, {r4, r5, lr}
+ adds r2, r2, #0x0c
+ blt Lmemcpy_bsrcul1l4
+
+Lmemcpy_bsrcul1loop4:
+ mov r12, r3, lsl #24
+ ldr r3, [r1, #-4]!
+ orr r12, r12, r3, lsr #8
+ str r12, [r0, #-4]!
+ subs r2, r2, #4
+ bge Lmemcpy_bsrcul1loop4
+
+Lmemcpy_bsrcul1l4:
+ add r1, r1, #1
+ b Lmemcpy_bl4
+
diff --git a/sys/lib/libkern/arch/arm26/bcopy.S b/sys/lib/libkern/arch/arm26/bcopy.S
new file mode 100644
index 00000000000..cebada98b57
--- /dev/null
+++ b/sys/lib/libkern/arch/arm26/bcopy.S
@@ -0,0 +1,48 @@
+/* $NetBSD: bcopy.S,v 1.1 2000/05/09 21:56:05 bjh21 Exp $ */
+
+/*-
+ * Copyright (c) 1997 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Neil A. Carson and 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 NetBSD
+ * Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation 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 NETBSD FOUNDATION, INC. 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 FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (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 <machine/asm.h>
+
+/* bcopy = memcpy/memmove with arguments reversed. */
+
+TWOENTRY(bcopy,ovbcopy)
+ /* switch the source and destination registers */
+ eor r0, r1, r0
+ eor r1, r0, r1
+ eor r0, r1, r0
+ b __memcpy
diff --git a/sys/lib/libkern/arch/arm26/byte_swap_2.S b/sys/lib/libkern/arch/arm26/byte_swap_2.S
new file mode 100644
index 00000000000..a7a9da236aa
--- /dev/null
+++ b/sys/lib/libkern/arch/arm26/byte_swap_2.S
@@ -0,0 +1,53 @@
+/* $NetBSD: byte_swap_2.S,v 1.1 2000/05/09 21:56:05 bjh21 Exp $ */
+
+/*-
+ * Copyright (c) 1999 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Charles M. Hannum.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the NetBSD
+ * Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation 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 NETBSD FOUNDATION, INC. 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 FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (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 <machine/asm.h>
+
+_BEGIN_ENTRY;
+_ENTRY(_C_FUNC(bswap16));
+_ENTRY(_C_FUNC(ntohs));
+_ENTRY(_C_FUNC(htons));
+_END_ENTRY
+ and r1, r0, #0xFF00
+ mov r0, r0, lsl #8
+ orr r0, r0, r1, lsr #8
+#ifdef __APCS_26__
+ movs pc, lr
+#else
+ mov pc, lr
+#endif \ No newline at end of file
diff --git a/sys/lib/libkern/arch/arm26/byte_swap_4.S b/sys/lib/libkern/arch/arm26/byte_swap_4.S
new file mode 100644
index 00000000000..1b1878090b8
--- /dev/null
+++ b/sys/lib/libkern/arch/arm26/byte_swap_4.S
@@ -0,0 +1,54 @@
+/* $NetBSD: byte_swap_4.S,v 1.1 2000/05/09 21:56:05 bjh21 Exp $ */
+
+/*-
+ * Copyright (c) 1997 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Neil A. Carson
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the NetBSD
+ * Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation 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 NETBSD FOUNDATION, INC. 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 FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (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 <machine/asm.h>
+
+_BEGIN_ENTRY;
+_ENTRY(_C_FUNC(bswap32));
+_ENTRY(_C_FUNC(ntohl));
+_ENTRY(_C_FUNC(htonl));
+_END_ENTRY
+ eor r1, r0, r0, ror #16
+ bic r1, r1, #0x00FF0000
+ mov r0, r0, ror #8
+ eor r0, r0, r1, lsr #8
+#ifdef __APCS_26__
+ movs pc,lr
+#else
+ mov pc, lr
+#endif \ No newline at end of file
diff --git a/sys/lib/libkern/arch/arm26/bzero.S b/sys/lib/libkern/arch/arm26/bzero.S
new file mode 100644
index 00000000000..5e0fc5654c3
--- /dev/null
+++ b/sys/lib/libkern/arch/arm26/bzero.S
@@ -0,0 +1,44 @@
+/* $NetBSD: bzero.S,v 1.1 2000/05/09 21:56:05 bjh21 Exp $ */
+
+/*-
+ * Copyright (c) 1997 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Neil A. Carson and 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 NetBSD
+ * Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation 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 NETBSD FOUNDATION, INC. 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 FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (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 <machine/asm.h>
+
+ENTRY(bzero)
+ mov r2, r1
+ mov r1, #0
+ b _memset
diff --git a/sys/lib/libkern/arch/arm26/divsi3.S b/sys/lib/libkern/arch/arm26/divsi3.S
new file mode 100644
index 00000000000..9c28b7157cd
--- /dev/null
+++ b/sys/lib/libkern/arch/arm26/divsi3.S
@@ -0,0 +1,398 @@
+/* $NetBSD: divsi3.S,v 1.1 2000/05/09 21:56:05 bjh21 Exp $ */
+
+/*
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 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 <machine/asm.h>
+
+ENTRY(__umodsi3)
+ stmfd sp!, {lr}
+ bl L_udivide
+ mov r0, r1
+#ifdef __APCS_26__
+ ldmfd sp!, {pc}^
+#else /* APCS-32 */
+ ldmfd sp!, {pc}
+#endif
+
+ENTRY(__modsi3)
+ stmfd sp!, {lr}
+ bl L_divide
+ mov r0, r1
+#ifdef __APCS_26__
+ ldmfd sp!, {pc}^
+#else
+ ldmfd sp!, {pc}
+#endif
+
+L_overflow:
+#if 0 /* FIXME */
+ mov r0, #8 /* SIGFPE */
+ bl _C_FUNC(raise) /* raise it */
+#endif
+ mov r0, #0
+#ifdef __APCS_26__
+ movs pc, lr
+#else
+ mov pc, lr
+#endif
+
+ENTRY(__udivsi3)
+L_udivide: /* r0 = r0 / r1; r1 = r0 % r1 */
+ eor r0, r1, r0
+ eor r1, r0, r1
+ eor r0, r1, r0
+ /* r0 = r1 / r0; r1 = r1 % r0 */
+ cmp r0, #1
+ bcc L_overflow
+ beq L_divide_l0
+ mov ip, #0
+ movs r1, r1
+ bpl L_divide_l1
+ orr ip, ip, #0x20000000 /* ip bit 0x20000000 = -ve r1 */
+ movs r1, r1, lsr #1
+ orrcs ip, ip, #0x10000000 /* ip bit 0x10000000 = bit 0 of r1 */
+ b L_divide_l1
+
+L_divide_l0: /* r0 == 1 */
+ mov r0, r1
+ mov r1, #0
+#ifdef __APCS_26__
+ movs pc, lr
+#else
+ mov pc, lr
+#endif
+
+ENTRY(__divsi3)
+L_divide: /* r0 = r0 / r1; r1 = r0 % r1 */
+ eor r0, r1, r0
+ eor r1, r0, r1
+ eor r0, r1, r0
+ /* r0 = r1 / r0; r1 = r1 % r0 */
+ cmp r0, #1
+ bcc L_overflow
+ beq L_divide_l0
+ ands ip, r0, #0x80000000
+ rsbmi r0, r0, #0
+ ands r2, r1, #0x80000000
+ eor ip, ip, r2
+ rsbmi r1, r1, #0
+ orr ip, r2, ip, lsr #1 /* ip bit 0x40000000 = -ve division */
+ /* ip bit 0x80000000 = -ve remainder */
+
+L_divide_l1:
+ mov r2, #1
+ mov r3, #0
+
+ /*
+ * If the highest bit of the dividend is set, we have to be
+ * careful when shifting the divisor. Test this.
+ */
+ movs r1,r1
+ bpl L_old_code
+
+ /*
+ * At this point, the highest bit of r1 is known to be set.
+ * We abuse this below in the tst instructions.
+ */
+ tst r1, r0 /*, lsl #0 */
+ bmi L_divide_b1
+ tst r1, r0, lsl #1
+ bmi L_divide_b2
+ tst r1, r0, lsl #2
+ bmi L_divide_b3
+ tst r1, r0, lsl #3
+ bmi L_divide_b4
+ tst r1, r0, lsl #4
+ bmi L_divide_b5
+ tst r1, r0, lsl #5
+ bmi L_divide_b6
+ tst r1, r0, lsl #6
+ bmi L_divide_b7
+ tst r1, r0, lsl #7
+ bmi L_divide_b8
+ tst r1, r0, lsl #8
+ bmi L_divide_b9
+ tst r1, r0, lsl #9
+ bmi L_divide_b10
+ tst r1, r0, lsl #10
+ bmi L_divide_b11
+ tst r1, r0, lsl #11
+ bmi L_divide_b12
+ tst r1, r0, lsl #12
+ bmi L_divide_b13
+ tst r1, r0, lsl #13
+ bmi L_divide_b14
+ tst r1, r0, lsl #14
+ bmi L_divide_b15
+ tst r1, r0, lsl #15
+ bmi L_divide_b16
+ tst r1, r0, lsl #16
+ bmi L_divide_b17
+ tst r1, r0, lsl #17
+ bmi L_divide_b18
+ tst r1, r0, lsl #18
+ bmi L_divide_b19
+ tst r1, r0, lsl #19
+ bmi L_divide_b20
+ tst r1, r0, lsl #20
+ bmi L_divide_b21
+ tst r1, r0, lsl #21
+ bmi L_divide_b22
+ tst r1, r0, lsl #22
+ bmi L_divide_b23
+ tst r1, r0, lsl #23
+ bmi L_divide_b24
+ tst r1, r0, lsl #24
+ bmi L_divide_b25
+ tst r1, r0, lsl #25
+ bmi L_divide_b26
+ tst r1, r0, lsl #26
+ bmi L_divide_b27
+ tst r1, r0, lsl #27
+ bmi L_divide_b28
+ tst r1, r0, lsl #28
+ bmi L_divide_b29
+ tst r1, r0, lsl #29
+ bmi L_divide_b30
+ tst r1, r0, lsl #30
+ bmi L_divide_b31
+/*
+ * instead of:
+ * tst r1, r0, lsl #31
+ * bmi L_divide_b32
+ */
+ b L_divide_b32
+
+L_old_code:
+ cmp r1, r0
+ bcc L_divide_b0
+ cmp r1, r0, lsl #1
+ bcc L_divide_b1
+ cmp r1, r0, lsl #2
+ bcc L_divide_b2
+ cmp r1, r0, lsl #3
+ bcc L_divide_b3
+ cmp r1, r0, lsl #4
+ bcc L_divide_b4
+ cmp r1, r0, lsl #5
+ bcc L_divide_b5
+ cmp r1, r0, lsl #6
+ bcc L_divide_b6
+ cmp r1, r0, lsl #7
+ bcc L_divide_b7
+ cmp r1, r0, lsl #8
+ bcc L_divide_b8
+ cmp r1, r0, lsl #9
+ bcc L_divide_b9
+ cmp r1, r0, lsl #10
+ bcc L_divide_b10
+ cmp r1, r0, lsl #11
+ bcc L_divide_b11
+ cmp r1, r0, lsl #12
+ bcc L_divide_b12
+ cmp r1, r0, lsl #13
+ bcc L_divide_b13
+ cmp r1, r0, lsl #14
+ bcc L_divide_b14
+ cmp r1, r0, lsl #15
+ bcc L_divide_b15
+ cmp r1, r0, lsl #16
+ bcc L_divide_b16
+ cmp r1, r0, lsl #17
+ bcc L_divide_b17
+ cmp r1, r0, lsl #18
+ bcc L_divide_b18
+ cmp r1, r0, lsl #19
+ bcc L_divide_b19
+ cmp r1, r0, lsl #20
+ bcc L_divide_b20
+ cmp r1, r0, lsl #21
+ bcc L_divide_b21
+ cmp r1, r0, lsl #22
+ bcc L_divide_b22
+ cmp r1, r0, lsl #23
+ bcc L_divide_b23
+ cmp r1, r0, lsl #24
+ bcc L_divide_b24
+ cmp r1, r0, lsl #25
+ bcc L_divide_b25
+ cmp r1, r0, lsl #26
+ bcc L_divide_b26
+ cmp r1, r0, lsl #27
+ bcc L_divide_b27
+ cmp r1, r0, lsl #28
+ bcc L_divide_b28
+ cmp r1, r0, lsl #29
+ bcc L_divide_b29
+ cmp r1, r0, lsl #30
+ bcc L_divide_b30
+L_divide_b32:
+ cmp r1, r0, lsl #31
+ subhs r1, r1,r0, lsl #31
+ addhs r3, r3,r2, lsl #31
+L_divide_b31:
+ cmp r1, r0, lsl #30
+ subhs r1, r1,r0, lsl #30
+ addhs r3, r3,r2, lsl #30
+L_divide_b30:
+ cmp r1, r0, lsl #29
+ subhs r1, r1,r0, lsl #29
+ addhs r3, r3,r2, lsl #29
+L_divide_b29:
+ cmp r1, r0, lsl #28
+ subhs r1, r1,r0, lsl #28
+ addhs r3, r3,r2, lsl #28
+L_divide_b28:
+ cmp r1, r0, lsl #27
+ subhs r1, r1,r0, lsl #27
+ addhs r3, r3,r2, lsl #27
+L_divide_b27:
+ cmp r1, r0, lsl #26
+ subhs r1, r1,r0, lsl #26
+ addhs r3, r3,r2, lsl #26
+L_divide_b26:
+ cmp r1, r0, lsl #25
+ subhs r1, r1,r0, lsl #25
+ addhs r3, r3,r2, lsl #25
+L_divide_b25:
+ cmp r1, r0, lsl #24
+ subhs r1, r1,r0, lsl #24
+ addhs r3, r3,r2, lsl #24
+L_divide_b24:
+ cmp r1, r0, lsl #23
+ subhs r1, r1,r0, lsl #23
+ addhs r3, r3,r2, lsl #23
+L_divide_b23:
+ cmp r1, r0, lsl #22
+ subhs r1, r1,r0, lsl #22
+ addhs r3, r3,r2, lsl #22
+L_divide_b22:
+ cmp r1, r0, lsl #21
+ subhs r1, r1,r0, lsl #21
+ addhs r3, r3,r2, lsl #21
+L_divide_b21:
+ cmp r1, r0, lsl #20
+ subhs r1, r1,r0, lsl #20
+ addhs r3, r3,r2, lsl #20
+L_divide_b20:
+ cmp r1, r0, lsl #19
+ subhs r1, r1,r0, lsl #19
+ addhs r3, r3,r2, lsl #19
+L_divide_b19:
+ cmp r1, r0, lsl #18
+ subhs r1, r1,r0, lsl #18
+ addhs r3, r3,r2, lsl #18
+L_divide_b18:
+ cmp r1, r0, lsl #17
+ subhs r1, r1,r0, lsl #17
+ addhs r3, r3,r2, lsl #17
+L_divide_b17:
+ cmp r1, r0, lsl #16
+ subhs r1, r1,r0, lsl #16
+ addhs r3, r3,r2, lsl #16
+L_divide_b16:
+ cmp r1, r0, lsl #15
+ subhs r1, r1,r0, lsl #15
+ addhs r3, r3,r2, lsl #15
+L_divide_b15:
+ cmp r1, r0, lsl #14
+ subhs r1, r1,r0, lsl #14
+ addhs r3, r3,r2, lsl #14
+L_divide_b14:
+ cmp r1, r0, lsl #13
+ subhs r1, r1,r0, lsl #13
+ addhs r3, r3,r2, lsl #13
+L_divide_b13:
+ cmp r1, r0, lsl #12
+ subhs r1, r1,r0, lsl #12
+ addhs r3, r3,r2, lsl #12
+L_divide_b12:
+ cmp r1, r0, lsl #11
+ subhs r1, r1,r0, lsl #11
+ addhs r3, r3,r2, lsl #11
+L_divide_b11:
+ cmp r1, r0, lsl #10
+ subhs r1, r1,r0, lsl #10
+ addhs r3, r3,r2, lsl #10
+L_divide_b10:
+ cmp r1, r0, lsl #9
+ subhs r1, r1,r0, lsl #9
+ addhs r3, r3,r2, lsl #9
+L_divide_b9:
+ cmp r1, r0, lsl #8
+ subhs r1, r1,r0, lsl #8
+ addhs r3, r3,r2, lsl #8
+L_divide_b8:
+ cmp r1, r0, lsl #7
+ subhs r1, r1,r0, lsl #7
+ addhs r3, r3,r2, lsl #7
+L_divide_b7:
+ cmp r1, r0, lsl #6
+ subhs r1, r1,r0, lsl #6
+ addhs r3, r3,r2, lsl #6
+L_divide_b6:
+ cmp r1, r0, lsl #5
+ subhs r1, r1,r0, lsl #5
+ addhs r3, r3,r2, lsl #5
+L_divide_b5:
+ cmp r1, r0, lsl #4
+ subhs r1, r1,r0, lsl #4
+ addhs r3, r3,r2, lsl #4
+L_divide_b4:
+ cmp r1, r0, lsl #3
+ subhs r1, r1,r0, lsl #3
+ addhs r3, r3,r2, lsl #3
+L_divide_b3:
+ cmp r1, r0, lsl #2
+ subhs r1, r1,r0, lsl #2
+ addhs r3, r3,r2, lsl #2
+L_divide_b2:
+ cmp r1, r0, lsl #1
+ subhs r1, r1,r0, lsl #1
+ addhs r3, r3,r2, lsl #1
+L_divide_b1:
+ cmp r1, r0
+ subhs r1, r1, r0
+ addhs r3, r3, r2
+L_divide_b0:
+
+ tst ip, #0x20000000
+ bne L_udivide_l1
+ mov r0, r3
+ cmp ip, #0
+ rsbmi r1, r1, #0
+ movs ip, ip, lsl #1
+ bicmi r0, r0, #0x80000000 /* Fix incase we divided 0x80000000 */
+ rsbmi r0, r0, #0
+#ifdef __APCS_26__
+ movs pc, lr
+#else
+ mov pc, lr
+#endif
+
+L_udivide_l1:
+ tst ip, #0x10000000
+ mov r1, r1, lsl #1
+ orrne r1, r1, #1
+ mov r3, r3, lsl #1
+ cmp r1, r0
+ subhs r1, r1, r0
+ addhs r3, r3, r2
+ mov r0, r3
+#ifdef __APCS_26__
+ movs pc, lr
+#else
+ mov pc, lr
+#endif
diff --git a/sys/lib/libkern/arch/arm26/memcpy.S b/sys/lib/libkern/arch/arm26/memcpy.S
new file mode 100644
index 00000000000..27edaf15ee7
--- /dev/null
+++ b/sys/lib/libkern/arch/arm26/memcpy.S
@@ -0,0 +1,48 @@
+/* $NetBSD: memcpy.S,v 1.1 2000/05/09 21:56:05 bjh21 Exp $ */
+
+/*-
+ * Copyright (c) 1997 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Neil A. Carson and 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 NetBSD
+ * Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation 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 NETBSD FOUNDATION, INC. 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 FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (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 <machine/asm.h>
+
+ENTRY(memcpy)
+ stmfd sp!, {r0, lr}
+ bl _C_FUNC(_memcpy)
+#ifdef __APCS_26__
+ ldmfd sp!, {r0, pc}^
+#else
+ ldmfd sp!, {r0, pc}
+#endif
diff --git a/sys/lib/libkern/arch/arm26/memmove.S b/sys/lib/libkern/arch/arm26/memmove.S
new file mode 100644
index 00000000000..b67a40f15bc
--- /dev/null
+++ b/sys/lib/libkern/arch/arm26/memmove.S
@@ -0,0 +1,48 @@
+/* $NetBSD: memmove.S,v 1.1 2000/05/09 21:56:05 bjh21 Exp $ */
+
+/*-
+ * Copyright (c) 1997 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Neil A. Carson and 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 NetBSD
+ * Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation 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 NETBSD FOUNDATION, INC. 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 FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (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 <machine/asm.h>
+
+ENTRY(memmove)
+ stmfd sp!, {r0, lr}
+ bl _C_FUNC(_memcpy)
+#ifdef __APCS_26__
+ ldmfd sp!, {r0, pc}^
+#else
+ ldmfd sp!, {r0, pc}
+#endif
diff --git a/sys/lib/libkern/arch/arm26/memset.S b/sys/lib/libkern/arch/arm26/memset.S
new file mode 100644
index 00000000000..3f62aed5563
--- /dev/null
+++ b/sys/lib/libkern/arch/arm26/memset.S
@@ -0,0 +1,134 @@
+/* $NetBSD: memset.S,v 1.1 2000/05/09 21:56:05 bjh21 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.
+ */
+
+#include <machine/asm.h>
+
+/*
+ * Sets a block of memory to the specified value
+ *
+ * On entry:
+ * r0 - dest address
+ * r1 - byte to write
+ * r2 - number of bytes to write
+ *
+ * On exit:
+ * r0 - dest address
+ */
+
+ENTRY(memset)
+ stmfd sp!, {r0} /* Remember address for return value */
+ and r1, r1, #0x000000ff /* We write bytes */
+
+ cmp r2, #0x00000004 /* Do we have less than 4 bytes */
+ blt Lmemset_lessthanfour
+
+ /* Ok first we will word align the address */
+
+ ands r3, r0, #0x00000003 /* Get the bottom two bits */
+ beq Lmemset_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 Lmemset_lessthanfour
+
+ /* Now we must be word aligned */
+
+Lmemset_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 Lmemset_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
+
+Lmemset_loop16:
+ stmia r0!, {r3-r6} /* Store 16 bytes */
+ sub r2, r2, #0x00000010 /* Adjust count */
+ cmp r2, #0x00000010 /* Still got at least 16 bytes ? */
+ bgt Lmemset_loop16
+
+ ldmfd sp!, {r4-r6} /* Restore registers */
+
+ /* Do we need to set some words as well ? */
+
+ cmp r2, #0x00000004
+ blt Lmemset_lessthanfour
+
+ /* Have either less than 16 or less than 32 depending on route taken */
+
+Lmemset_lessthan32:
+
+ /* We have at least 4 bytes so copy as words */
+
+Lmemset_loop4:
+ str r3, [r0], #0x0004
+ sub r2, r2, #0x0004
+ cmp r2, #0x00000004
+ bge Lmemset_loop4
+
+Lmemset_lessthanfour:
+ cmp r2, #0x00000000
+ ldmeqfd sp!, {r0}
+#ifdef __APCS_26__
+ moveqs pc, lr /* Zero length so exit */
+#else
+ moveq pc, lr /* Zero length so exit */
+#endif
+
+ cmp r2, #0x00000002
+ strb r1, [r0], #0x0001 /* Set 1 byte */
+ strgeb r1, [r0], #0x0001 /* Set another byte */
+ strgtb r1, [r0], #0x0001 /* and a third */
+
+ ldmfd sp!, {r0}
+#ifdef __APCS_26__
+ movs pc, lr /* Exit */
+#else
+ mov pc, lr /* Exit */
+#endif